Jump to content

Newbie question - Workflows relying on Python 2


Recommended Posts

@xilopaint The ship is sailing. I agree that ideally the library would be updated officially, and that the second best option would be for a forum regular (such as yourself) to coordinate a community-approved successor. But we can’t force either of those; the community of Python Workflow developers at large will decide, and right now they’re looking for something.

 

So if you have a fork which you believe to be more solid than the ones being shared, I urge you to make it public and your intentions known in that GitHub thread. The longer you wait, the harder it will be for your alternative to gain traction. It doesn’t have to be perfect now, but it should be available. I’ll eventually have to update the libraries thread and I can only recommend what is public.

Link to comment
On 3/20/2022 at 11:11 AM, vitor said:

@xilopaint The ship is sailing. I agree that ideally the library would be updated officially, and that the second best option would be for a forum regular (such as yourself) to coordinate a community-approved successor. But we can’t force either of those; the community of Python Workflow developers at large will decide, and right now they’re looking for something.

 

So if you have a fork which you believe to be more solid than the ones being shared, I urge you to make it public and your intentions known in that GitHub thread. The longer you wait, the harder it will be for your alternative to gain traction. It doesn’t have to be perfect now, but it should be available. I’ll eventually have to update the libraries thread and I can only recommend what is public.

 

Hey @vitor, I’m finishing the work with Alfredeanishe (the name I gave to the community port of Alfred Workflow in honor of our hero 😄).


Alfred-Workflow library has a class named Workflow and its instance (the Workflow object) is the main interface to the library, which “provides APIs for accessing the Alfred/workflow environment, storing & caching data, using Keychain, and generating Script Filter feedback” according the docs. The point is the Workflow object "is targeted at Alfred 2" and Workflow3, a subclass of Workflow, should be used for Alfred 3+ features. This choice was understandable for some time but I think now we should drop Alfred 2 support and moving forward. That’s what I did removing the Workflow3 module and putting everything together. It makes the codebase way cleaner. I still can’t be sure I haven’t committed some mistake but in my tests everything seems to be working fine.


One of the last issues I’m still facing is regarding the notify module. As you can see in the original code an AppKit module should be imported but it’s not part of Python standard library but part of the PyObjC bridge. I suspect PyObjC was embedded with Python 2 in macOS versions earlier than 12.3 (unfortunately I can’t check this on my up-to-date macOS). This StackOverflow answer mentions a /System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/PyObjC path (was that installed by default?).


Well, at this moment I’m searching for the best solution for this issue but first of all I would like to be sure it’s not only a problem on my machine and AppKit cannot really be imported through Python in macOS 12.3. If it's the case, one solution would be embedding the Library with some PyObjC modules and other solution would be using something like Notificator.

Edited by xilopaint
Link to comment

@vitor After a few days of receiving the first issues with missing Python 2.7 I attempted to fix my pyenv python installation and some older workflows, but I decided to give it up and switch to Python 3 completely. I found it easier instead of maintaining an old python. 

 

A goblin gave me the magic script some time ago ;). I received it via Pull request in one of my workflow, but I don't know avatar in Alfred forum: https://github.com/Acidham/chromium-hist-bookmarks/pull/6

 

The script helps a bit to handle different python3 installations, and I decide to add it to most of my workflows. Finally, all my py3 workflows didn't fail after upgrading to macOS 12.3 ;) 

Link to comment
22 hours ago, xilopaint said:

I’m finishing the work with Alfredeanishe

 

That’s a nice gesture, but do make sure he’s OK with it. What we know is an homage can be perceived by others as an endorsement. I have no idea what Dean’s thoughts are on the matter, but I know mine. Sometimes people really want to show their appreciation and that is touching, but to me it is important that I don’t seem to be involved with something I’m not.

 

23 hours ago, xilopaint said:

I think now we should drop Alfred 2 support and moving forward.

 

Definitely!

 

23 hours ago, xilopaint said:

One of the last issues I’m still facing is regarding the notify module.

 

In the meantime, you can just show a Notification via AppleScript. It won’t have a custom icon, but everything else will work.

 

23 hours ago, xilopaint said:

I suspect PyObjC was embedded with Python 2 in macOS versions earlier than12.3

 

Yep.

 

23 hours ago, xilopaint said:

other solution would be using something like Notificator.

 

Notificator needs to be built in advance, for the icon. Though I could change it so it’s built on-demand and cached. I’ll have a thought about that.

 

8 hours ago, Acidham said:

but I decided to give it up and switch to Python 3 completely.

 

That’s the right choice and what I expected you’d do. I frequently mention you when pointing to developers who were already making Python3 Workflows before the removal.

 

8 hours ago, Acidham said:

A goblin gave me the magic script some time ago

 

That is needlessly complex. All you need is export PATH="/opt/homebrew/bin:/usr/local/bin:${PATH}". That single line will make calls to python3 use a Homebrew-installed Python if it exists, or /usr/bin/python3 if it doesn’t. If the user doesn’t have the latter either, macOS will take care of it by showing users a GUI to install it in two clicks.


It’s not that env isn’t working, it’s that env checks PATH, and Alfred uses the default. That’s why that single line solves it all.

Link to comment
1 hour ago, vitor said:
On 3/26/2022 at 1:30 PM, xilopaint said:

other solution would be using something like Notificator.

 

Notificator needs to be built in advance, for the icon. Though I could change it so it’s built on-demand and cached. I’ll have a thought about that.

 

This is not different from Alfred-Workflow. If the user invokes the notify function to fire a notification it first checks for the presence of Notify.app in the data folder. If Notify.app is not present the install_notifier function is invoked and Notify.app is extracted from the library folder and moved to data folder where the icon is changed and the bundle id set.

 

def install_notifier():
    """Extract ``Notify.app`` from the workflow to data directory.
    Changes the bundle ID of the installed app and gives it the
    workflow's icon.
    """
    archive = os.path.join(os.path.dirname(__file__), 'Notify.tgz')
    destdir = wf().datadir
    app_path = os.path.join(destdir, 'Notify.app')
    n = notifier_program()
    log().debug('installing Notify.app to %r ...', destdir)
    # z = zipfile.ZipFile(archive, 'r')
    # z.extractall(destdir)
    tgz = tarfile.open(archive, 'r:gz')
    tgz.extractall(destdir)
    if not os.path.exists(n):  # pragma: nocover
        raise RuntimeError('Notify.app could not be installed in ' + destdir)

    # Replace applet icon
    icon = notifier_icon_path()
    workflow_icon = wf().workflowfile('icon.png')
    if os.path.exists(icon):
        os.unlink(icon)

    png_to_icns(workflow_icon, icon)

    # Set file icon
    # PyObjC isn't available for 2.6, so this is 2.7 only. Actually,
    # none of this code will "work" on pre-10.8 systems. Let it run
    # until I figure out a better way of excluding this module
    # from coverage in py2.6.
    if sys.version_info >= (2, 7):  # pragma: no cover
        from AppKit import NSWorkspace, NSImage

        ws = NSWorkspace.sharedWorkspace()
        img = NSImage.alloc().init()
        img.initWithContentsOfFile_(icon)
        ws.setIcon_forFile_options_(img, app_path, 0)

    # Change bundle ID of installed app
    ip_path = os.path.join(app_path, 'Contents/Info.plist')
    bundle_id = '{0}.{1}'.format(wf().bundleid, uuid.uuid4().hex)
    data = plistlib.readPlist(ip_path)
    log().debug('changing bundle ID to %r', bundle_id)
    data['CFBundleIdentifier'] = bundle_id
    plistlib.writePlist(data, ip_path)

 

Link to comment
2 minutes ago, xilopaint said:

This is not different from Alfred-Workflow.

 

It’s the same thing conceptually, which is why I mentioned it. What I’m having a think about is the implementation, because if I do it it will be a single script you call and does everything, it won’t use extra files.

Link to comment
11 minutes ago, vitor said:

 

It’s the same thing conceptually, which is why I mentioned it. What I’m having a think about is the implementation, because if I do it it will be a single script you call and does everything, it won’t use extra files.

 

It would be great. I just tried to point out that PyObjC would not be required in a possible integration of Notificator even in its current implementation. My main issue with Alfred-Workflow is the need of PyObjC. If I embedded the library with a minimal part of PyObjC needed to the job it would still add 4.8MB to the library. Not a great choice.

 

In any case I'm gonna wait for your decision about a new implementation for Notificator.

Edited by xilopaint
Link to comment
  • Vero changed the title to Newbie question - Workflows relying on Python 2

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...