SimpleService

Shows how to implement entries for the Services menu.

Sources

ServiceTest.py

import Cocoa
import objc

def serviceSelector(fn):
    # this is the signature of service selectors
    return objc.selector(fn, signature=b"v@:@@o^@")

def ERROR(s):
    #NSLog(u"ERROR: %s", s)
    return s

class ServiceTest(Cocoa.NSObject):

    @serviceSelector
    def doOpenFileService_userData_error_(self, pboard, data, error):
        try:
            types = pboard.types()
            pboardString = None
            if Cocoa.NSStringPboardType in types:
                pboardString = pboard.stringForType_(Cocoa.NSStringPboardType)
            if pboardString is None:
                return ERROR(Cocoa.NSLocalizedString(
                    "Error: Pasteboard doesn't contain a string.",
                    "Pasteboard couldn't give string."
                ))

            if not Cocoa.NSWorkspace.sharedWorkspace().openFile_(pboardString):
                return ERROR(Cocoa.NSLocalizedString(
                    "Error: Couldn't open file %s.",
                    "Couldn't perform service operation for file %s."
                ) % pboardString)

            return ERROR(None)
        except:
            import traceback
            traceback.print_exc()
            return ERROR(u'Exception, see traceback')


    @serviceSelector
    def doCapitalizeService_userData_error_(self, pboard, data, err):
        #NSLog(u"doCapitalizeService_userData_error_(%s, %s)", pboard, data)
        try:
            types = pboard.types()
            pboardString = None
            if Cocoa.NSStringPboardType in types:
                pboardString = pboard.stringForType_(Cocoa.NSStringPboardType)
            if pboardString is None:
                return ERROR(Cocoa.NSLocalizedString(
                    "Error: Pasteboard doesn't contain a string.",
                    "Pasteboard couldn't give string."
                ))

            newString = Cocoa.NSString.capitalizedString(pboardString)

            if not newString:
                return ERROR(Cocoa.NSLocalizedString(
                    "Error: Couldn't capitalize string %s.",
                    "Couldn't perform service operation for string %s."
                ) % pboardString)

            types = [Cocoa.NSStringPboardType]
            pboard.declareTypes_owner_([Cocoa.NSStringPboardType], None)
            pboard.setString_forType_(newString, Cocoa.NSStringPboardType)
            return ERROR(None)
        except:
            import traceback
            traceback.print_exc()
            return ERROR(u'Exception, see traceback')

SimpleService_main.py

from AppKit import *
from Foundation import *
from ServiceTest import *
from PyObjCTools import AppHelper

def main():
    #NSLog(u"main()")
    serviceProvider = ServiceTest.alloc().init()
    #NSLog(u"serviceProvider = %s", serviceProvider)
    NSRegisterServicesProvider(serviceProvider, u"PyObjCSimpleService")
    #NSLog(u"registered as PyObjCSimpleService")
    AppHelper.runConsoleEventLoop()

if __name__ == '__main__':
    main()

rebuild.py

#!/usr/bin/env python
"""
Quickie script to update the services
"""
import AppKit
AppKit.NSUpdateDynamicServices()

setup.py

"""
Script for building the example.

Usage:
    python3 setup.py py2app
"""
from setuptools import setup

plist = dict(
    CFBundleIdentifier = "net.sf.pyobjc.PyObjCSimpleService",
    CFBundleName = "PyObjCSimpleService",
    LSBackgroundOnly = 1,
    NSServices = [
        dict(
            NSKeyEquivalent=dict(
                default="F",
            ),
            NSMenuItem=dict(
                default="Open File",
            ),
            NSMessage="doOpenFileService",
            NSPortName="PyObjCSimpleService",
            NSSendTypes=[
                "NSStringPboardType",
            ],
        ),
        dict(
            NSMenuItem=dict(
                default="Capitalize String",
            ),
            NSMessage="doCapitalizeService",
            NSPortName="PyObjCSimpleService",
            NSReturnTypes=[
                "NSStringPboardType",
            ],
            NSSendTypes=[
                "NSStringPboardType",
            ],
        ),
    ],
)


setup(
    name="Simple Service",
    app=["SimpleService_main.py"],
    options=dict(
        py2app=dict(
            plist=plist
        )
    ),
    setup_requires=[
        "py2app",
        "pyobjc-framework-Cocoa",
    ]
)

Resources