SMJobBlessUtil.py and python 3 on Apple Silicon

My build process depends on SMJobBlessUtil.py. With the removal of python 2 from Monterey 12.3 beta, is there a replacement script available in any sample code.

I am not very interested in patching my current version as python is way beyond my skill set.

Answered by mikeyh in 703002022

Try something like this (not a python expert so expecting comments):

1c1
< #! /usr/bin/python 
---
> #! /usr/bin/python3
96c96
<   except subprocess.CalledProcessError, e:
---
>   except subprocess.CalledProcessError as e:
110,111c110,111
<     req = subprocess.check_output(args, stderr=open("/dev/null"))
<   except subprocess.CalledProcessError, e:
---
>     req = subprocess.check_output(args, stderr=open("/dev/null"), encoding="utf-8")
>   except subprocess.CalledProcessError as e:
122c122,123
<     info = plistlib.readPlist(infoPath)
---
>     with open(infoPath, 'rb') as fp:
>       info = plistlib.load(fp)
143,144c144,145
<     plistDump = subprocess.check_output(args)
<   except subprocess.CalledProcessError, e:
---
>     plistDump = subprocess.check_output(args, encoding="utf-8")
>   except subprocess.CalledProcessError as e:
149a151
> 
155c157
<     bytes = []
---
>     data = []
163,164c165,167
<         bytes.append(int(hexStr, 16))
<     plist = plistlib.readPlistFromString(bytearray(bytes))
---
>         data.append(int(hexStr, 16))
> 
>     plist = plistlib.loads(bytes(data))
223c226
<   if not info.has_key("SMPrivilegedExecutables"):
---
>   if "SMPrivilegedExecutables" not in info:
263c266
<     if not info.has_key("CFBundleInfoDictionaryVersion") or info["CFBundleInfoDictionaryVersion"] != "6.0":
---
>     if "CFBundleInfoDictionaryVersion" not in info or info["CFBundleInfoDictionaryVersion"] != "6.0":
266c269
<     if not info.has_key("CFBundleIdentifier") or info["CFBundleIdentifier"] != os.path.basename(toolPath):
---
>     if "CFBundleIdentifier" not in info or info["CFBundleIdentifier"] != os.path.basename(toolPath):
269c272
<     if not info.has_key("SMAuthorizedClients"):
---
>     if "SMAuthorizedClients" not in info:
289c292
<     if not launchd.has_key("Label") or launchd["Label"] != os.path.basename(toolPath):
---
>     if "Label" not in launchd or launchd["Label"] != os.path.basename(toolPath):
355c358
<     if not toolInfo.has_key("CFBundleIdentifier"):
---
>     if "CFBundleIdentifier" not in toolInfo:
358c361
<     if not isinstance(bundleID, basestring):
---
>     if not isinstance(bundleID, str):
365c368
<   needsUpdate = not appInfo.has_key("SMPrivilegedExecutables")
---
>   needsUpdate = "SMPrivilegedExecutables" not in appInfo
370,371c373,374
<     appToolDictSorted = sorted(appToolDict.iteritems(), key=operator.itemgetter(0))
<     oldAppToolDictSorted = sorted(oldAppToolDict.iteritems(), key=operator.itemgetter(0))
---
>     appToolDictSorted = sorted(appToolDict.items(), key=operator.itemgetter(0))
>     oldAppToolDictSorted = sorted(oldAppToolDict.items(), key=operator.itemgetter(0))
376,377c379,381
<     plistlib.writePlist(appInfo, appInfoPlistPath)
<     print >> sys.stdout, "%s: updated" % appInfoPlistPath
---
>     with open(appInfoPlistPath, 'wb') as fp:
>       plistlib.dump(appInfo, fp)
>     print ("%s: updated" % appInfoPlistPath, file = sys.stdout)
385c389
<     needsUpdate = not toolInfo.has_key("SMAuthorizedClients")
---
>     needsUpdate = "SMAuthorizedClients" not in toolInfo
396c400
<       print >> sys.stdout, "%s: updated" % toolInfoPlistPath
---
>       print("%s: updated" % toolInfoPlistPath, file = sys.stdout)
425c429
<   except CheckException, e:
---
>   except CheckException as e:
427c431
<       print >> sys.stderr, "%s: %s" % (os.path.basename(sys.argv[0]), e.message)
---
>       print("%s: %s" % (os.path.basename(sys.argv[0]), e.message), file = sys.stderr)
432c436
<       print >> sys.stderr, "%s: %s" % (path, e.message)
---
>       print("%s: %s" % (path, e.message), file = sys.stderr)
434,436c438,440
<   except UsageException, e:
<     print >> sys.stderr, "usage: %s check /path/to/app" % os.path.basename(sys.argv[0])
<     print >> sys.stderr, "    %s setreq /path/to/app /path/to/app/Info.plist /path/to/tool/Info.plist..." % os.path.basename(sys.argv[0])
---
>   except UsageException as e:
>     print("usage: %s check /path/to/app" % os.path.basename(sys.argv[0]), file = sys.stderr)
>     print("    %s setreq /path/to/app /path/to/app/Info.plist /path/to/tool/Info.plist..." % os.path.basename(sys.argv[0]), file = sys.stderr)

Accepted Answer

Try something like this (not a python expert so expecting comments):

1c1
< #! /usr/bin/python 
---
> #! /usr/bin/python3
96c96
<   except subprocess.CalledProcessError, e:
---
>   except subprocess.CalledProcessError as e:
110,111c110,111
<     req = subprocess.check_output(args, stderr=open("/dev/null"))
<   except subprocess.CalledProcessError, e:
---
>     req = subprocess.check_output(args, stderr=open("/dev/null"), encoding="utf-8")
>   except subprocess.CalledProcessError as e:
122c122,123
<     info = plistlib.readPlist(infoPath)
---
>     with open(infoPath, 'rb') as fp:
>       info = plistlib.load(fp)
143,144c144,145
<     plistDump = subprocess.check_output(args)
<   except subprocess.CalledProcessError, e:
---
>     plistDump = subprocess.check_output(args, encoding="utf-8")
>   except subprocess.CalledProcessError as e:
149a151
> 
155c157
<     bytes = []
---
>     data = []
163,164c165,167
<         bytes.append(int(hexStr, 16))
<     plist = plistlib.readPlistFromString(bytearray(bytes))
---
>         data.append(int(hexStr, 16))
> 
>     plist = plistlib.loads(bytes(data))
223c226
<   if not info.has_key("SMPrivilegedExecutables"):
---
>   if "SMPrivilegedExecutables" not in info:
263c266
<     if not info.has_key("CFBundleInfoDictionaryVersion") or info["CFBundleInfoDictionaryVersion"] != "6.0":
---
>     if "CFBundleInfoDictionaryVersion" not in info or info["CFBundleInfoDictionaryVersion"] != "6.0":
266c269
<     if not info.has_key("CFBundleIdentifier") or info["CFBundleIdentifier"] != os.path.basename(toolPath):
---
>     if "CFBundleIdentifier" not in info or info["CFBundleIdentifier"] != os.path.basename(toolPath):
269c272
<     if not info.has_key("SMAuthorizedClients"):
---
>     if "SMAuthorizedClients" not in info:
289c292
<     if not launchd.has_key("Label") or launchd["Label"] != os.path.basename(toolPath):
---
>     if "Label" not in launchd or launchd["Label"] != os.path.basename(toolPath):
355c358
<     if not toolInfo.has_key("CFBundleIdentifier"):
---
>     if "CFBundleIdentifier" not in toolInfo:
358c361
<     if not isinstance(bundleID, basestring):
---
>     if not isinstance(bundleID, str):
365c368
<   needsUpdate = not appInfo.has_key("SMPrivilegedExecutables")
---
>   needsUpdate = "SMPrivilegedExecutables" not in appInfo
370,371c373,374
<     appToolDictSorted = sorted(appToolDict.iteritems(), key=operator.itemgetter(0))
<     oldAppToolDictSorted = sorted(oldAppToolDict.iteritems(), key=operator.itemgetter(0))
---
>     appToolDictSorted = sorted(appToolDict.items(), key=operator.itemgetter(0))
>     oldAppToolDictSorted = sorted(oldAppToolDict.items(), key=operator.itemgetter(0))
376,377c379,381
<     plistlib.writePlist(appInfo, appInfoPlistPath)
<     print >> sys.stdout, "%s: updated" % appInfoPlistPath
---
>     with open(appInfoPlistPath, 'wb') as fp:
>       plistlib.dump(appInfo, fp)
>     print ("%s: updated" % appInfoPlistPath, file = sys.stdout)
385c389
<     needsUpdate = not toolInfo.has_key("SMAuthorizedClients")
---
>     needsUpdate = "SMAuthorizedClients" not in toolInfo
396c400
<       print >> sys.stdout, "%s: updated" % toolInfoPlistPath
---
>       print("%s: updated" % toolInfoPlistPath, file = sys.stdout)
425c429
<   except CheckException, e:
---
>   except CheckException as e:
427c431
<       print >> sys.stderr, "%s: %s" % (os.path.basename(sys.argv[0]), e.message)
---
>       print("%s: %s" % (os.path.basename(sys.argv[0]), e.message), file = sys.stderr)
432c436
<       print >> sys.stderr, "%s: %s" % (path, e.message)
---
>       print("%s: %s" % (path, e.message), file = sys.stderr)
434,436c438,440
<   except UsageException, e:
<     print >> sys.stderr, "usage: %s check /path/to/app" % os.path.basename(sys.argv[0])
<     print >> sys.stderr, "    %s setreq /path/to/app /path/to/app/Info.plist /path/to/tool/Info.plist..." % os.path.basename(sys.argv[0])
---
>   except UsageException as e:
>     print("usage: %s check /path/to/app" % os.path.basename(sys.argv[0]), file = sys.stderr)
>     print("    %s setreq /path/to/app /path/to/app/Info.plist /path/to/tool/Info.plist..." % os.path.basename(sys.argv[0]), file = sys.stderr)

@mikeyh Thank you so much for this. I have just tried your patched code and it is working in my build process.

I'll refrain from marking your solution as accepted for now, just in case there are more comments/improvements from others, but it seems to be working fine.

Updated version with workaround for otool arm64 weirdness: https://gist.github.com/mikeyh/89a1e2ecc6849ff6056b7391c5216799

SMJobBlessUtil.py and python 3 on Apple Silicon
 
 
Q