def _makeTypeTable(classes, enums, properties): # Used for constructing k.keywords # Each argument is of format [[name, code], ...] typebycode = _typebycode.copy() typebyname = _typebyname.copy() # TO DO: testing indicates that where name+code clashes occur, classes have highest priority, followed by properties, with enums last; currently this code gives higher priority to enums: for klass, table in [ (AEType, properties), (AEEnum, enums), (AEType, classes) ]: # note: packing properties as AEProp causes problems when the same name is used for both a class and a property, and the property's definition masks the class's one (e.g. Finder's 'file'); if an AEProp is passed where an AEType is expected, it can cause an error as it's not what the receiving app expects. (Whereas they may be more tolerant of an AEType being passed where an AEProp is expected.) Also, note that AppleScript always seems to pack property names as typeType, so we should be ok following its lead here. for i, (name, code) in enumerate(table): # TO DO: decide where best to apply AE keyword escaping, language keyword escaping # TO DO: make sure same collision avoidance is done in help terminology (i.e. need to centralise all this stuff in a single osaterminology module) # If an application-defined name overlaps an existing type name but has a different code, append '_' to avoid collision: if _typebyname.has_key(name) and _typebyname[name].code != code: name += '_' typebycode[code] = Keyword( name ) # to handle synonyms, if same code appears more than once then use name from last definition in list name, code = table[-i - 1] if _typebyname.has_key(name) and _typebyname[name].code != code: name += '_' typebyname[name] = klass( code ) # to handle synonyms, if same name appears more than once then use code from first definition in list return typebycode, typebyname
def _makeTypeTable(classes, enums, properties): # Used for constructing k.keywords # Each parameter is of format [[name, code], ...] typebycode = _typebycode.copy() typebyname = _typebyname.copy() for klass, table in [ (AEType, classes), (AEEnum, enums), (AEType, properties) ]: # note: packing properties as AEProp causes problems when the same name is used for both a class and a property, and the property's definition masks the class's one (e.g. Finder's 'file'); if an AEProp is passed where an AEType is expected, it can cause an error as it's not what the receiving app expects. (Whereas they may be more tolerant of an AEType being passed where an AEProp is expected.) Also, note that AppleScript always seems to pack property names as typeType, so we should be ok following its lead here. for name, code in table: # TO DO: decide where best to apply AE keyword escaping, language keyword escaping # TO DO: make sure same collision avoidance is done in help terminology (i.e. need to centralise all this stuff in a single osaterminology module) # If an application-defined name overlaps an existing type name but has a different code, append '_' to avoid collision: if _typebyname.has_key(name) and _typebyname[name].code != code: name += '_' typebycode[code] = Keyword(name) typebyname[name] = klass(code) return typebycode, typebyname
def _maketypetable(classes, enums, properties): # Used for constructing k.keywords # Each argument is of format [[name, code], ...] typebycode = _defaulttypebycode.copy() typebyname = _defaulttypebyname.copy() # note: testing indicates that where name+code clashes occur, classes have highest priority, followed by properties, with enums last (prior to 0.19.0 this code gave higher priority to enums): for klass, table in [ (AEEnum, enums), (AEType, properties), (AEType, classes) ]: # note: packing properties as AEProp causes problems when the same name is used for both a class and a property, and the property's definition masks the class's one (e.g. Finder's 'file'); if an AEProp is passed where an AEType is expected, it can cause an error as it's not what the receiving app expects. (Whereas they may be more tolerant of an AEType being passed where an AEProp is expected.) Also, note that AppleScript always seems to pack property names as typeType, so we should be ok following its lead here. for i, (name, code) in enumerate(table): # If an application-defined name overlaps an existing type name but has a different code, append '_' to avoid collision: if _defaulttypecodebyname.get(name, code) != code: name += '_' typebycode[code] = Keyword( name ) # to handle synonyms, if same code appears more than once then use name from last definition in list name, code = table[-i - 1] if _defaulttypecodebyname.get(name, code) != code: name += '_' typebyname[name] = klass( code ) # to handle synonyms, if same name appears more than once then use code from first definition in list return typebycode, typebyname
###################################################################### # Default terminology tables for converting between human-readable identifiers and Apple event codes; used by all apps. # Includes default entries for Required Suite, get/set and miscellaneous other commands; application may override some or all of these definitions. # Type tables; used to translate constants # e.g. k.document <-> AEType('docu') # e.g. k.ask <-> AEEnum('ask ') _typebyname = {} # used to encode class and enumerator keywords _typebycode = { } # used to decode class (typeType) and enumerator (typeEnum) descriptors for _, enumerators in appscripttypedefs.enumerations: for name, code in enumerators: _typebyname[name] = AEEnum(code) _typebycode[code] = Keyword(name) for defs in [ appscripttypedefs.alltypes, appscripttypedefs.commontypes, appscripttypedefs.properties ]: for name, code in defs: _typebyname[name] = AEType(code) _typebycode[code] = Keyword(name) # Reference tables; used to translate references and commands # e.g. app(...).documents.text <-> app.elements('docu').property('ctxt') # e.g. app(...).quit(saving=k.ask) <-> Application(...).event('aevtquit', {'savo': AEEnum('ask ')}) _defaultcommands = { # 'run', 'open', 'print' and 'quit' are Required Suite commands so should always be available. 'run': (kCommand, ('aevtoapp', {})),
# Default terminology tables for converting between human-readable identifiers and Apple event codes; used by all apps. # Includes default entries for Required Suite, get/set and miscellaneous other commands; application may override some or all of these definitions. # Type tables; used to translate constants # e.g. k.document <-> AEType('docu') # e.g. k.ask <-> AEEnum('ask ') _defaulttypebyname = {} # used to encode class and enumerator keywords _defaulttypebycode = { } # used to decode class (typeType) and enumerator (typeEnum) descriptors _defaulttypecodebyname = {} # used to check for name collisions for _, enumerators in defaultterminology.enumerations: for name, code in enumerators: _defaulttypebyname[name] = AEEnum(code) _defaulttypebycode[code] = Keyword(name) _defaulttypecodebyname[name] = code for defs in [defaultterminology.types, defaultterminology.properties]: for name, code in defs: _defaulttypebyname[name] = AEType(code) _defaulttypebycode[code] = Keyword(name) _defaulttypecodebyname[name] = code # Reference tables; used to translate references and commands # e.g. app(...).documents.text <-> app.elements('docu').property('ctxt') # e.g. app(...).quit(saving=k.ask) <-> Application(...).event('aevtquit', {'savo': AEEnum('ask ')}) _defaultreferencebycode = {} # used to decode property and element specifiers _defaultreferencebyname = { } # used to encode property and element specifiers and Apple events _defaultcommandcodebyname = {} # used to check for name collisions
class AppData(aem.Codecs): """Provides application-specific: - aem.Application instance - name-code terminology translation tables - pack/unpack methods - help system """ ####### # constants, etc. keyAECompOperator = aem.AEType(kae.keyAECompOperator) keyAEObject1 = aem.AEType(kae.keyAEObject1) keyAEObject2 = aem.AEType(kae.keyAEObject2) kAppscriptTypeCompDescriptorOperators = { kae.kAEGreaterThan: 'AS__gt__', kae.kAEGreaterThanEquals: 'AS__ge__', kae.kAEEquals: 'AS__eq__', kae.kAELessThan: 'AS__lt__', kae.kAELessThanEquals: 'AS__le__', kae.kAEBeginsWith: 'beginswith', kae.kAEEndsWith: 'endswith', kae.kAEContains: 'contains' } kClassKeyword = Keyword('class_') kClassType = aem.AEType('pcls') kHelpAgentBundleID = 'net.sourceforge.appscript.asdictionary' ####### # initialiser def __init__(self, aemapplicationclass, constructor, identifier, terms): """ aemapplicationclass : class -- aem.Application or equivalent constructor : str -- indicates how to construct the aem.Application instance ('path', 'pid', 'url', 'aemapp', 'current') identifier : any -- value identifying the target application (its type is dependent on constructor parameter) terms : bool | module | tuple """ # initialise codecs aem.Codecs.__init__(self) self.decoders.update({ kae.typeType: self.unpackkeyword, kae.typeEnumerated: self.unpackkeyword, kae.typeProperty: self.unpackkeyword, kae.typeObjectSpecifier: self.unpackreference, kae.typeInsertionLoc: self.unpackreference, # AEAddressDesc types kae.typeApplicationBundleID: self.unpackapplicationbyid, kae.typeApplicationURL: self.unpackapplicationbyurl, kae.typeApplSignature: self.unpackapplicationbysignature, kae.typeKernelProcessID: self.unpackapplicationbypid, kae.typeMachPort: self.unpackapplicationbydesc, kae.typeProcessSerialNumber: self.unpackapplicationbydesc, }) # store parameters for later use self._aemapplicationclass = aemapplicationclass self.constructor, self.identifier = constructor, identifier self._relaunchmode = 'limited' self._terms = terms self._helpagent = None ####### # Terminology-aware pack/unpack functions. # These replace the default aem pack/unpack functions, which don't understand appscript Keyword and Reference objects. def packdict(self, val): # Pack dictionary whose keys are strings (e.g. 'foo'), Keywords (e.g. k.name) or AETypes (e.g. AEType('pnam'). record = newrecord() if self.kClassKeyword in val or self.kClassType in val: # if hash contains a 'class' property containing a class name, coerce the AEDesc to that class newval = val.copy() if self.kClassKeyword in newval: value = newval.pop(self.kClassKeyword) else: value = newval.pop(self.kClassType) if isinstance( value, Keyword ): # get the corresponding AEType (assuming there is one) value = self.typebyname().get(value.name, value) if isinstance(value, aem.AEType): # coerce the record to the desired type record = record.coerce(value.code) val = newval usrf = None for key, value in val.items(): if isinstance(key, Keyword): try: keyCode = self.typebyname()[key.AS_name].code except KeyError: raise KeyError("Unknown Keyword: k.%s" % key.AS_name) record.setparam(keyCode, self.pack(value)) elif isinstance( key, aem.AETypeBase ): # AEType/AEProp (AEType is normally used in practice) record.setparam(key.code, self.pack(value)) else: # user-defined key (normally a string) if not usrf: usrf = newlist() usrf.setitem(0, self.pack(key)) usrf.setitem(0, self.pack(value)) if usrf: record.setparam('usrf', usrf) return record def unpackaerecord(self, desc): # Unpack typeAERecord, converting record keys to Keyword objects (not AETypes) where possible. dct = {} for i in range(desc.count()): key, value = desc.getitem(i + 1, kae.typeWildCard) if key == 'usrf': lst = self.unpack(value) for i in range(0, len(lst), 2): dct[lst[i]] = lst[i + 1] elif key in self.typebycode(): dct[self.typebycode()[key]] = self.unpack(value) else: dct[aem.AEType(key)] = self.unpack(value) return dct ## def unpackkeyword(self, desc): # Unpack typeType, typeEnum, typeProperty; replaces default aem decoders to convert types, enums, etc. # to Keyword objects instead of AETypes, AEEnums, etc. aemValue = _lowlevelcodecs.unpack(desc) return self.typebycode().get(aemValue.code, aemValue) def unpackreference(self, desc): return Reference(self, _lowlevelcodecs.unpack(desc)) def unpackcompdescriptor(self, desc): # need to do some typechecking when unpacking 'contains' comparisons, so have to override the low-level unpacker rec = self.unpack(desc.coerce(kae.typeAERecord)) operator = self.kAppscriptTypeCompDescriptorOperators[rec[ self.keyAECompOperator].code] op1 = rec[self.keyAEObject1] op2 = rec[self.keyAEObject2] if operator == 'contains': if isinstance( op1, Reference) and op1.AS_aemreference.AEM_root() == aem.its: return op1.contains(op2) elif isinstance( op2, Reference) and op2.AS_aemreference.AEM_root() == aem.its: return op2.isin(op1) else: return _lowlevelcodecs.unpack(desc) else: return getattr(op1, operator)(op2) ## def unpackapplicationbyid(self, desc): return app(id=desc.data) def unpackapplicationbyurl(self, desc): if desc.data.startswith( 'file' ): # workaround for converting AEAddressDescs containing file:// URLs to application paths, since AEAddressDescs containing file URLs don't seem to work correctly return app(mactypes.File.makewithurl(desc.data).path) else: # presumably contains an eppc:// URL return app(url=desc.data) def unpackapplicationbysignature(self, desc): return app(creator=struct.pack('>I', struct.unpack('I', desc.data)[0])) def unpackapplicationbypid(self, desc): return app(pid=struct.unpack('I', desc.data)[0]) def unpackapplicationbydesc(self, desc): return app(aemapp=aem.Application(desc=desc)) ####### def connect(self): """Initialises application target and terminology lookup tables. Called automatically the first time clients retrieve target, typebycode, typebyname, referencebycode, referencebyname; clients should not need to call it themselves. """ # initialise target (by default an aem.Application instance) if self.constructor == 'aemapp': t = self._target = self.identifier elif self.constructor == 'current': t = self._target = self._aemapplicationclass() else: t = self._target = self._aemapplicationclass( **{self.constructor: self.identifier}) # initialise translation tables if self._terms == True: # obtain terminology from application self._terms = terminology.tablesforapp(t) elif self._terms == False: # use built-in terminology only (e.g. use this when running AppleScript applets) self._terms = terminology.defaulttables elif not isinstance(self._terms, tuple): # use user-supplied terminology module self._terms = terminology.tablesformodule(self._terms) d1, d2, d3, d4 = self._typebycode, self._typebyname, \ self._referencebycode, self._referencebyname = self._terms self.target = lambda: t self.typebycode = lambda: d1 self.typebyname = lambda: d2 self.referencebycode = lambda: d3 self.referencebyname = lambda: d4 def target(self): self.connect() return self._target def typebycode(self): self.connect() return self._typebycode def typebyname(self): self.connect() return self._typebyname def referencebycode(self): self.connect() return self._referencebycode def referencebyname(self): self.connect() return self._referencebyname ## def pack(self, data): if isinstance(data, GenericReference): data = data.AS_resolve(Reference, self) if isinstance(data, Reference): data = data.AS_aemreference elif isinstance(data, Keyword): try: data = self.typebyname()[data.AS_name] except KeyError: raise KeyError("Unknown Keyword: k.%s" % data.AS_name) return aem.Codecs.pack(self, data) # Relaunch mode def _setrelaunchmode(self, mode): if mode not in ['never', 'limited', 'always']: raise ValueError('Unknown relaunch mode: %r' % mode) self._relaunchmode = mode relaunchmode = property(lambda self: self._relaunchmode, _setrelaunchmode) # Help system def _write(self, s): if isinstance(s, unicode): s = s.encode('utf8') print >> sys.stderr, s def _inithelpagent(self): try: apppath = aem.findapp.byid(self.kHelpAgentBundleID) asdictionaryisrunning = aem.Application.processexistsforpath( apppath) self._helpagent = aem.Application(apppath) if not asdictionaryisrunning: # tell System Events hide ASDictionary after it's launched (kludgy, but does the job) aem.Application( aem.findapp.byid('com.apple.systemevents')).event( 'coresetd', { '----': aem.app.elements('prcs').byname( 'ASDictionary').property('pvis'), 'data': False }).send() self._helpagent.event( 'AppSHelp', { 'Cons': self.constructor, 'Iden': self.identifier, 'Styl': 'py-appscript', 'Flag': '-h', 'aRef': None, 'CNam': '' }).send() return True except aem.findapp.ApplicationNotFoundError: self._write( "No help available: ASDictionary application not found.") except aem.CantLaunchApplicationError: self._write( "No help available: can't launch ASDictionary application.") return False def _displayhelp(self, flags, ref): if isinstance(ref, Command): commandname = ref.AS_name ref = ref.AS_aemreference else: commandname = '' try: self._write( self._helpagent.event( 'AppSHelp', { 'Cons': self.constructor, 'Iden': self.identifier, 'Styl': 'py-appscript', 'Flag': flags, 'aRef': self.pack(ref), 'CNam': commandname }).send()) return None except aem.EventError, e: return e
print_exc() return ref ###################################################################### # Considering/ignoring constants def _packuint32(n): # used to pack csig attributes return newdesc(kae.typeUInt32, struct.pack('I', n)) # 'csig' attribute flags (see ASRegistry.h; note: there's no option for 'numeric strings' in 10.4) _ignoreenums = [ (Keyword('case'), kae.kAECaseConsiderMask, kae.kAECaseIgnoreMask), (Keyword('diacriticals'), kae.kAEDiacriticConsiderMask, kae.kAEDiacriticIgnoreMask), (Keyword('whitespace'), kae.kAEWhiteSpaceConsiderMask, kae.kAEWhiteSpaceIgnoreMask), (Keyword('hyphens'), kae.kAEHyphensConsiderMask, kae.kAEHyphensIgnoreMask), (Keyword('expansion'), kae.kAEExpansionConsiderMask, kae.kAEExpansionIgnoreMask), (Keyword('punctuation'), kae.kAEPunctuationConsiderMask, kae.kAEPunctuationIgnoreMask), ] # default cons, csig attributes _defaultconsiderations = _lowlevelcodecs.pack([aem.AEEnum(kae.kAECase)]) _defaultconsidsandignores = _packuint32(kae.kAECaseIgnoreMask)
class AppData(aem.Codecs): """Provides application-specific: - aem.Application instance - name-code terminology translation tables - pack/unpack methods - help system """ ####### # constants, etc. keyAECompOperator = aem.AEType(kae.keyAECompOperator) keyAEObject1 = aem.AEType(kae.keyAEObject1) keyAEObject2 = aem.AEType(kae.keyAEObject2) kAppscriptTypeCompDescriptorOperators = { kae. kAEGreaterThan: 'AS__gt__', kae.kAEGreaterThanEquals: 'AS__ge__', kae.kAEEquals: 'AS__eq__', kae.kAELessThan: 'AS__lt__', kae.kAELessThanEquals: 'AS__le__', kae.kAEBeginsWith: 'beginswith', kae.kAEEndsWith: 'endswith', kae.kAEContains: 'contains' } kClassKeyword = Keyword('class_') kClassType = aem.AEType('pcls') kHelpAgentBundleID = 'net.sourceforge.appscript.asdictionary' ####### # initialiser def __init__(self, aemapplicationclass, constructor, identifier, terms, aemconstructoroptions={}): """ aemapplicationclass : class -- aem.Application or equivalent constructor : str -- indicates how to construct the aem.Application instance ('path', 'pid', 'url', 'aemapp', 'current') identifier : any -- value identifying the target application (its type is dependent on constructor parameter) terms : bool | module | tuple -- if True, retrieve terminology from target application dynamically; if false, use only default terminology; if static glue module or tuple, use terminology from that aemconstructoroptions -- any additional keyword arguments to pass to aemapplicationclass constructor (e.g. newinstance, hide) """ # initialise codecs aem.Codecs.__init__(self) self.decoders.update({ kae.typeType: self.unpackkeyword, kae.typeEnumerated: self.unpackkeyword, kae.typeProperty: self.unpackkeyword, kae.typeObjectSpecifier: self.unpackreference, kae.typeInsertionLoc: self.unpackreference, # AEAddressDesc types kae.typeApplicationBundleID: self.unpackapplicationbyid, kae.typeApplicationURL: self.unpackapplicationbyurl, kae.typeApplSignature: self.unpackapplicationbysignature, kae.typeKernelProcessID: self.unpackapplicationbypid, kae.typeMachPort: self.unpackapplicationbydesc, kae.typeProcessSerialNumber: self.unpackapplicationbydesc, }) # store parameters for later use self._aemapplicationclass = aemapplicationclass self.constructor, self.identifier = constructor, identifier self.aemconstructoroptions = aemconstructoroptions self._relaunchmode = 'limited' self._terms = terms self._helpagent = None self._isconnected = False ####### # Terminology-aware pack/unpack functions. # These replace the default aem pack/unpack functions, which don't understand appscript Keyword and Reference objects. def packdict(self, val): # Pack dictionary whose keys are strings (e.g. 'foo'), Keywords (e.g. k.name) or AETypes (e.g. AEType('pnam'). record = newrecord() if self.kClassKeyword in val or self.kClassType in val: # if hash contains a 'class' property containing a class name, coerce the AEDesc to that class newval = val.copy() if self.kClassKeyword in newval: value = newval.pop(self.kClassKeyword) else: value = newval.pop(self.kClassType) if isinstance(value, Keyword): # get the corresponding AEType (assuming there is one) value = self.typebyname().get(value.name, value) if isinstance(value, aem.AEType): # coerce the record to the desired type record = record.coerce(value.code) val = newval usrf = None for key, value in val.items(): if isinstance(key, Keyword): try: keyCode = self.typebyname()[key.AS_name].code except KeyError: raise ValueError("Unknown Keyword: k.%s" % key.AS_name) record.setparam(keyCode, self.pack(value)) elif isinstance(key, aem.AETypeBase): # AEType/AEProp (AEType is normally used in practice) record.setparam(key.code, self.pack(value)) else: # user-defined key (normally a string) if not usrf: usrf = newlist() usrf.setitem(0, self.pack(key)) usrf.setitem(0, self.pack(value)) if usrf: record.setparam('usrf', usrf) return record def unpackaerecord(self, desc): # Unpack typeAERecord, converting record keys to Keyword objects (not AETypes) where possible. dct = {} for i in range(desc.count()): key, value = desc.getitem(i + 1, kae.typeWildCard) if key == 'usrf': lst = self.unpack(value) for i in range(0, len(lst), 2): dct[lst[i]] = lst[i+1] elif key in self.typebycode(): dct[self.typebycode()[key]] = self.unpack(value) else: dct[aem.AEType(key)] = self.unpack(value) return dct ## def unpackkeyword(self, desc): # Unpack typeType, typeEnum, typeProperty; replaces default aem decoders to convert types, enums, etc. # to Keyword objects instead of AETypes, AEEnums, etc. aemValue = _lowlevelcodecs.unpack(desc) return self.typebycode().get(aemValue.code, aemValue) def unpackreference(self, desc): return Reference(self, _lowlevelcodecs.unpack(desc)) def unpackcompdescriptor(self, desc): # need to do some typechecking when unpacking 'contains' comparisons, so have to override the low-level unpacker rec = self.unpack(desc.coerce(kae.typeAERecord)) operator = self.kAppscriptTypeCompDescriptorOperators[rec[self.keyAECompOperator].code] op1 = rec[self.keyAEObject1] op2 = rec[self.keyAEObject2] if operator == 'contains': if isinstance(op1, Reference) and op1.AS_aemreference.AEM_root() == aem.its: return op1.contains(op2) elif isinstance(op2, Reference) and op2.AS_aemreference.AEM_root() == aem.its: return op2.isin(op1) else: return _lowlevelcodecs.unpack(desc) else: return getattr(op1, operator)(op2) ## def unpackapplicationbyid(self, desc): return app(id=desc.data) def unpackapplicationbyurl(self, desc): if desc.data.startswith('file'): # workaround for converting AEAddressDescs containing file:// URLs to application paths, since AEAddressDescs containing file URLs don't seem to work correctly return app(mactypes.File.makewithurl(desc.data).path) else: # presumably contains an eppc:// URL return app(url=desc.data) def unpackapplicationbysignature(self, desc): return app(creator=struct.pack('>I', struct.unpack('I', desc.data)[0])) def unpackapplicationbypid(self, desc): return app(pid=struct.unpack('I', desc.data)[0]) def unpackapplicationbydesc(self, desc): return app(aemapp=aem.Application(desc=desc)) ####### isconnected = property(lambda self: self._isconnected) def connect(self): """Initialises application target and terminology lookup tables. Called automatically the first time clients retrieve target, typebycode, typebyname, referencebycode, referencebyname; clients should not need to call it themselves. """ # initialise target (by default an aem.Application instance) if self.constructor == 'aemapp': t = self._target = self.identifier elif self.constructor == 'current': t = self._target = self._aemapplicationclass() else: kargs = {self.constructor: self.identifier} kargs.update(self.aemconstructoroptions) t = self._target = self._aemapplicationclass(**kargs) # initialise translation tables if self._terms == True: # obtain terminology from application self._terms = terminology.tablesforapp(t) elif self._terms == False: # use built-in terminology only (e.g. use this when running AppleScript applets) self._terms = terminology.defaulttables elif not isinstance(self._terms, tuple): # use user-supplied terminology module self._terms = terminology.tablesformodule(self._terms) d1, d2, d3, d4 = self._typebycode, self._typebyname, \ self._referencebycode, self._referencebyname = self._terms self.target = lambda: t self.typebycode = lambda: d1 self.typebyname = lambda: d2 self.referencebycode = lambda: d3 self.referencebyname = lambda: d4 self._isconnected = True def target(self): self.connect() return self._target def typebycode(self): self.connect() return self._typebycode def typebyname(self): self.connect() return self._typebyname def referencebycode(self): self.connect() return self._referencebycode def referencebyname(self): self.connect() return self._referencebyname _kYes = Keyword('yes') _kNo = Keyword('no') _kAsk = Keyword('ask') def permissiontoautomate(self, code=kae.typeWildCard*2): try: self.target().permissiontoautomate(code[:4], code[4:], True) except MacOSError, e: if e.args[0] == -1744: # errAEEventWouldRequireUserConsent return self._kAsk # unknown (i.e. user has yet to allow/forbid access) elif e.args[0] == -1743: # errAEEventNotPermitted (broken in 10.14.x; see <rdar://44049802>) return self._kNo else: # e.g. -600 (process not found) raise except NotImplementedError: # always True if OS version < 10.14 pass
flags, ref ) # call real help. Note that help system is responsible for providing a return value (usually the same reference it was called upon, but it may modify this). ###################################################################### # Considering/ignoring constants def _packUInt64(n): # used to pack csig attributes return AECreateDesc(kAE.typeUInt32, struct.pack('L', n)) # 'csig' attribute flags (see ASRegistry.h; note: there's no option for 'numeric strings' in 10.4) _ignoreEnums = [ (Keyword('case'), aem.k.CaseConsider, aem.k.CaseIgnore), (Keyword('diacriticals'), aem.k.DiacriticConsider, aem.k.DiacriticIgnore), (Keyword('whitespace'), aem.k.WhiteSpaceConsider, aem.k.WhiteSpaceIgnore), (Keyword('hyphens'), aem.k.HyphensConsider, aem.k.HyphensIgnore), (Keyword('expansion'), aem.k.ExpansionConsider, aem.k.ExpansionIgnore), (Keyword('punctuation'), aem.k.PunctuationConsider, aem.k.PunctuationIgnore), ] # default cons, csig attributes _defaultConsiderations = _lowLevelCodecs.pack([aem.AEType('case')]) _defaultConsidsAndIgnores = _packUInt64(aem.k.CaseIgnore) ###################################################################### # Base class for references and commands