def packlong(self, val): if (-2**31) <= val < (2**31): # pack as typeSInt32 if possible (non-lossy) return newdesc(kae.typeSInt32, struct.pack('i', val)) elif (-2**63) <= val < (2**63): # else pack as typeSInt64 if possible (non-lossy) return newdesc(kae.typeSInt64, struct.pack('q', val)) else: # else pack as typeFloat (lossy) return self.pack(float(val))
def makewithurl(klass, url): """Make File object from file URL.""" obj = klass(_kNoPath) obj._desc = newdesc(kae.typeFileURL, url) obj._url = url obj._path = converturltopath(url, kCFURLPOSIXPathStyle) return obj
def processexistsforurl(url): """Does an application process specified by the given eppc:// URL exist? Note: this will send a 'launch' Apple event to the target application. """ if ':' not in url: # workaround: process will crash if no colon in URL (OS bug) raise ValueError("Invalid url: %r" % url) return processexistsfordesc(ae.newdesc(kae.typeApplicationURL, url))
def remoteapp(url): """Make an AEAddressDesc identifying a running application on another machine. url : string -- URL for remote application, e.g. 'eppc://*****:*****@0.0.0.1/TextEdit' Result : AEAddressDesc """ if ':' not in url: # workaround: process will crash if no colon in URL (OS bug) raise ValueError("Invalid url: %r" % url) return ae.newdesc(kae.typeApplicationURL, url)
def __init__(self, path): """Make File object from POSIX path.""" if path is not _kNoPath: if not isinstance(path, unicode): path = unicode(path) self._path = abspath(path) self._url = convertpathtourl(self._path, kCFURLPOSIXPathStyle) self._desc = newdesc(kae.typeFileURL, self._url)
def packunicodetext(self, val): # Note: optional BOM is omitted as this causes problems with stupid apps like iTunes 7 that don't # handle BOMs correctly; note: while typeUnicodeText is not recommended as of OS 10.4, it's still # being used rather than typeUTF8Text or typeUTF16ExternalRepresentation to provide compatibility #with not-so-well-designed applications that may have problems with these newer types. data = val.encode(nativeutf16encoding) if data.startswith(BOM_UTF16_LE) or data.startswith(BOM_UTF16_BE): data = data[2:] return newdesc(kae.typeUnicodeText, data)
def __init__(self, path): """Make Alias object from POSIX path.""" if path is _kNoPath: self._desc = None else: urldesc = newdesc(kae.typeFileURL, convertpathtourl(abspath(path), kCFURLPOSIXPathStyle)) try: self._desc = urldesc.coerce(kae.typeAlias) except MacOSError, err: if err.args[0] == -1700: raise ValueError("Can't make mactypes.Alias as file doesn't exist: %r" % path) else: raise
def __init__(self, path): """Make Alias object from POSIX path.""" if path is _kNoPath: self._desc = None else: urldesc = newdesc( kae.typeFileURL, convertpathtourl(abspath(path), kCFURLPOSIXPathStyle)) try: self._desc = urldesc.coerce(kae.typeAlias) except MacOSError, err: if err.args[0] == -1700: raise ValueError( "Can't make mactypes.Alias as file doesn't exist: %r" % path) else: raise
def localappbypid(pid): """Make an AEAddressDesc identifying a local process. pid : integer -- Unix process id Result : AEAddressDesc """ return ae.newdesc(kae.typeKernelProcessID, struct.pack('i', pid))
kLSLaunchDontAddToRecents = 0x00000100 kLSLaunchDontSwitch = 0x00000200 kLSLaunchNoParams = 0x00000800 kLSLaunchAsync = 0x00010000 kLSLaunchStartClassic = 0x00020000 kLSLaunchInClassic = 0x00040000 kLSLaunchNewInstance = 0x00080000 kLSLaunchAndHide = 0x00100000 kLSLaunchAndHideOthers = 0x00200000 kLSLaunchHasUntrustedContents = 0x00400000 _kNoProcess = 0 _kCurrentProcess = 2 _nulladdressdesc = ae.newdesc(kae.typeProcessSerialNumber, struct.pack('II', 0, _kNoProcess)) # ae.newappleevent complains if you pass None as address, so we give it one to throw away _launchevent = Event(_nulladdressdesc, 'ascrnoop').AEM_event _runevent = Event(_nulladdressdesc, 'aevtoapp').AEM_event ####### def _launchapplication(path, event, newinstance=False, hide=False): flags = kLSLaunchNoParams | kLSLaunchStartClassic | kLSLaunchDontSwitch if newinstance: flags |= kLSLaunchNewInstance if hide: flags |= kLSLaunchAndHide try: return ae.launchapplication(path, event, flags) except ae.MacOSError, err:
def packkey(self, val): return newdesc(kae.typeKeyword, fourcharcode(val.code))
def packfloat(self, val): return newdesc(kae.typeFloat, struct.pack('d', val))
def _defaultpacker(self, units, code): return newdesc(code, struct.pack('d', units.value))
def packprop(self, val): return newdesc(kae.typeProperty, fourcharcode(val.code))
def makewithurl(klass, url): """Make File object from file URL.""" obj = klass(_kNoPath) obj._desc = newdesc(kae.typeFileURL, url).coerce(kae.typeAlias) return obj
def desc(self): if self._desc is None: self._desc = newdesc(kae.typeFileURL, self.url) return self._desc
def packabsoluteordinal(code): return ae.newdesc(kae.typeAbsoluteOrdinal, code[::-1])
class ObjectBeingExamined(ReferenceRoot): """Form: its Reference base; represents an element to be tested. Used to construct by-filter references. """ _kName = 'its' _kType = ae.newdesc(kae.typeObjectBeingExamined, '')
'remoteapp', 'CantLaunchApplicationError' ] ###################################################################### # PRIVATE ###################################################################### _kLaunchContinue = 0x4000 _kLaunchNoFileFlags = 0x0800 _kLaunchDontSwitch = 0x0200 _kNoProcess = 0 _kCurrentProcess = 2 _nulladdressdesc = ae.newdesc( kae.typeProcessSerialNumber, struct.pack('LL', 0, _kNoProcess) ) # ae.newappleevent complains if you pass None as address, so we give it one to throw away _launchevent = Event(_nulladdressdesc, 'ascrnoop').AEM_event _runevent = Event(_nulladdressdesc, 'aevtoapp').AEM_event ####### def _launchapplication(path, event): try: return ae.launchapplication( path, event, _kLaunchContinue + _kLaunchNoFileFlags + _kLaunchDontSwitch) except ae.MacOSError, err: raise CantLaunchApplicationError(err.args[0], path)
class CurrentContainer(ReferenceRoot): """Form: con Reference base; represents elements' container object. Used to construct by-range references. """ _kName = 'con' _kType = ae.newdesc(kae.typeCurrentContainer, '')
def packenum(self, val): return newdesc(kae.typeEnumeration, fourcharcode(val.code))
class Codecs(object): """Convert between Python and Apple event data types. Clients may add additional encoders/decoders and/or subclass to suit their needs. """ # Constants kNullDesc = newdesc(kae.typeNull, '') kMacEpoch = datetime.datetime(1904, 1, 1) # used in packing datetime objects as AEDesc typeLongDateTime kMacEpochT = time.mktime(kMacEpoch.timetuple()) kShortMacEpoch = kMacEpoch.date() # used in packing date objects as AEDesc typeLongDateTime kTrueDesc = newdesc(kae.typeTrue, '') kFalseDesc = newdesc(kae.typeFalse, '') ####### # tables to map AE codes to aem method names kInsertionLocSelectors = { fourcharcode(kae.kAEBefore): 'before', fourcharcode(kae.kAEAfter): 'after', fourcharcode(kae.kAEBeginning): 'beginning', fourcharcode(kae.kAEEnd): 'end' } kTypeCompDescriptorOperators = { fourcharcode(kae.kAEGreaterThan): 'gt', fourcharcode(kae.kAEGreaterThanEquals): 'ge', fourcharcode(kae.kAEEquals): 'eq', fourcharcode(kae.kAELessThan): 'lt', fourcharcode(kae.kAELessThanEquals): 'le', fourcharcode(kae.kAEBeginsWith): 'beginswith', fourcharcode(kae.kAEEndsWith): 'endswith', fourcharcode(kae.kAEContains): 'contains' } kTypeLogicalDescriptorOperators = { fourcharcode(kae.kAEAND): 'AND', fourcharcode(kae.kAEOR): 'OR', fourcharcode(kae.kAENOT): 'NOT' } ################################### def __init__(self): # Clients may add/remove/replace encoder and decoder items: self.encoders = { AEDesc: self.packdesc, type(None): self.packnone, bool: self.packbool, int: self.packint, long: self.packlong, float: self.packfloat, str: self.packstr, unicode: self.packunicodetext, list: self.packlist, tuple: self.packlist, dict: self.packdict, datetime.date: self.packdate, datetime.datetime: self.packdatetime, datetime.time: self.packtime, time.struct_time: self.packstructtime, mactypes.Alias: self.packalias, mactypes.File: self.packfile, AEType: self.packtype, AEEnum: self.packenum, AEProp: self.packprop, AEKey: self.packkey, } self. decoders = { kae.typeNull: self.unpacknull, kae.typeBoolean: self.unpackboolean, kae.typeFalse: self.unpackfalse, kae.typeTrue: self.unpacktrue, kae.typeSInt16: self.unpacksint16, kae.typeUInt16: self.unpackuint16, kae.typeSInt32: self.unpacksint32, kae.typeUInt32: self.unpackuint32, kae.typeSInt64: self.unpacksint64, kae.typeUInt64: self.unpackuint64, kae.typeIEEE32BitFloatingPoint: self.unpackfloat32, kae.typeIEEE64BitFloatingPoint: self.unpackfloat64, kae.type128BitFloatingPoint: self.unpackfloat128, kae.typeChar: self.unpackchar, kae.typeIntlText: self.unpackintltext, kae.typeUTF8Text: self.unpackutf8text, kae.typeUTF16ExternalRepresentation: self.unpackutf16externalrepresentation, kae.typeStyledText: self.unpackstyledtext, kae.typeUnicodeText: self.unpackunicodetext, kae.typeLongDateTime: self.unpacklongdatetime, kae.typeAEList: self.unpackaelist, kae.typeAERecord: self.unpackaerecord, kae.typeVersion: self.unpackversion, kae.typeAlias: self.unpackalias, kae.typeFSS: self.unpackfss, kae.typeFSRef: self.unpackfsref, kae.typeFileURL: self.unpackfileurl, kae.typeQDPoint: self.unpackqdpoint, kae.typeQDRectangle: self.unpackqdrect, kae.typeRGBColor: self.unpackrgbcolor, kae.typeType: self.unpacktype, kae.typeEnumeration: self.unpackenumeration, kae.typeProperty: self.unpackproperty, kae.typeKeyword: self.unpackkeyword, kae.typeInsertionLoc: self.unpackinsertionloc, kae.typeObjectSpecifier: self.unpackobjectspecifier, kae.typeAbsoluteOrdinal: self.unpackabsoluteordinal, kae.typeCompDescriptor: self.unpackcompdescriptor, kae.typeLogicalDescriptor: self.unpacklogicaldescriptor, kae.typeRangeDescriptor: self.unpackrangedescriptor, kae.typeCurrentContainer: lambda desc: self.con, kae.typeObjectBeingExamined: lambda desc: self.its, } self._unittypecodecs = UnitTypeCodecs() ################################### # compatibility options def addunittypes(self, typedefs): """Register custom unit type definitions with this Codecs instance e.g. Adobe apps define additional unit types (ciceros, pixels, etc.) """ self._unittypecodecs.addtypes(typedefs) def dontcacheunpackedspecifiers(self): """ When unpacking object specifiers, unlike AppleScript, appscript caches the original AEDesc for efficiency, allowing the resulting reference to be re-packed much more quickly. Occasionally this causes compatibility problems with applications that returned subtly malformed specifiers. To force a Codecs object to fully unpack and repack object specifiers, call its dontcacheunpackedspecifiers method. """ self.unpackobjectspecifier = self.fullyunpackobjectspecifier ################################### def packunknown(self, data): """Clients may override this to provide additional packers.""" raise TypeError("Can't pack data into an AEDesc (unsupported type): %r" % data) def unpackunknown(self, desc): """Clients may override this to provide additional unpackers.""" if desc.isrecord(): rec = desc.coerce('reco') rec.setparam('pcls', self.pack(AEType(desc.type))) decoder = self.decoders.get('reco') if decoder: return decoder(rec) else: return rec else: return desc ## def pack(self, data): """Pack Python data. data : anything -- a Python value Result : aem.ae.AEDesc -- an Apple event descriptor, or error if no encoder exists for this type of data """ if isinstance(data, aemreference.Query): return data.AEM_packself(self) else: try: return self.encoders[data.__class__](data) # quick lookup by type/class except (KeyError, AttributeError): for type, encoder in self.encoders.items(): # slower but more thorough lookup that can handle subtypes/subclasses if isinstance(data, type): return encoder(data) didpack, desc = self._unittypecodecs.pack(data) if didpack: return desc else: self.packunknown(data) def unpack(self, desc): """Unpack an Apple event descriptor. desc : aem.ae.AEDesc -- an Apple event descriptor Result : anything -- a Python value, or the AEDesc object if no decoder is found """ decoder = self.decoders.get(desc.type) if decoder: return decoder(desc) else: didunpack, val = self._unittypecodecs.unpack(desc) if didunpack: return val else: return self.unpackunknown(desc) ################################### def packdesc(self, val): return val def packnone(self, val): return self.kNullDesc def packbool(self, val): return val and self.kTrueDesc or self.kFalseDesc def packlong(self, val): if (-2**31) <= val < (2**31): # pack as typeSInt32 if possible (non-lossy) return newdesc(kae.typeSInt32, struct.pack('i', val)) elif (-2**63) <= val < (2**63): # else pack as typeSInt64 if possible (non-lossy) return newdesc(kae.typeSInt64, struct.pack('q', val)) else: # else pack as typeFloat (lossy) return self.pack(float(val)) packint = packlong # note: Python int = C long, so may need to pack as typeSInt64 on 64-bit def packfloat(self, val): return newdesc(kae.typeFloat, struct.pack('d', val)) ## def packunicodetext(self, val): # Note: optional BOM is omitted as this causes problems with stupid apps like iTunes 7 that don't # handle BOMs correctly; note: while typeUnicodeText is not recommended as of OS 10.4, it's still # being used rather than typeUTF8Text or typeUTF16ExternalRepresentation to provide compatibility #with not-so-well-designed applications that may have problems with these newer types. data = val.encode(nativeutf16encoding) if data.startswith(BOM_UTF16_LE) or data.startswith(BOM_UTF16_BE): data = data[2:] return newdesc(kae.typeUnicodeText, data) def packstr(self, val): return newdesc(kae.typeChar, val) ## def packdate(self, val): delta = val - self.kShortMacEpoch sec = delta.days * 3600 * 24 + delta.seconds return newdesc(kae.typeLongDateTime, struct.pack('q', sec)) def packdatetime(self, val): delta = val - self.kMacEpoch sec = delta.days * 3600 * 24 + delta.seconds return newdesc(kae.typeLongDateTime, struct.pack('q', sec)) def packtime(self, val): return self.packdatetime(datetime.datetime.combine(datetime.date.today(), val)) def packstructtime(self, val): sec = int(time.mktime(val) - self.kMacEpochT) return newdesc(kae.typeLongDateTime, struct.pack('q', sec)) def packalias(self, val): return val.desc packfile = packalias ## def packlist(self, val): lst = newlist() for item in val: lst.setitem(0, self.pack(item)) return lst def packdict(self, val): record = newrecord() usrf = None for key, value in val.items(): if isinstance(key, (AEType, AEProp)): if key.code == 'pcls': # AS packs records that contain a 'class' property by coercing the packed record to that type at the end try: record = record.coerce(value.code) except: record.setparam(key.code, self.pack(value)) else: record.setparam(key.code, self.pack(value)) else: 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 packtype(self, val): return newdesc(kae.typeType, fourcharcode(val.code)) def packenum(self, val): return newdesc(kae.typeEnumeration, fourcharcode(val.code)) def packprop(self, val): return newdesc(kae.typeProperty, fourcharcode(val.code)) def packkey(self, val): return newdesc(kae.typeKeyword, fourcharcode(val.code)) ################################### # unpack def unpacknull(self, desc): return None def unpackboolean(self, desc): return desc.data != '\x00' def unpacktrue(self, desc): return True def unpackfalse(self, desc): return False def unpacksint16(self, desc): return struct.unpack('h', desc.data)[0] def unpackuint16(self, desc): return struct.unpack('H', desc.data)[0] def unpacksint32(self, desc): return struct.unpack('i', desc.data)[0] def unpackuint32(self, desc): return struct.unpack('I', desc.data)[0] def unpacksint64(self, desc): return struct.unpack('q', desc.data)[0] def unpackuint64(self, desc): return struct.unpack('Q', desc.data)[0] def unpackfloat32(self, desc): return struct.unpack('f', desc.data)[0] def unpackfloat64(self, desc): return struct.unpack('d', desc.data)[0] def unpackfloat128(self, desc): return struct.unpack('d', desc.coerce(kae.typeIEEE64BitFloatingPoint).data)[0] ## def unpackchar(self, desc): return desc.data def unpackintltext(self, desc): return self.unpackunicodetext(desc.coerce(kae.typeUnicodeText)) def unpackutf8text(self, desc): return unicode(desc.data, 'utf8') def unpackstyledtext(self, desc): return self.unpackunicodetext(desc.coerce(kae.typeUnicodeText)) def unpackunicodetext(self, desc): # typeUnicodeText = native endian UTF16 with optional BOM data = desc.data if data.startswith(BOM_UTF16_BE): return unicode(data, 'UTF-16BE') elif data.startswith(BOM_UTF16_LE): return unicode(data, 'UTF-16LE') else: return unicode(data, nativeutf16encoding) def unpackutf16externalrepresentation(self, desc): # type UTF16ExternalRepresentation = big-endian UTF16 with optional byte-order-mark # OR little-endian UTF16 with required byte-order-mark if desc.data.startswith(BOM_UTF16_LE): return unicode(desc.data, 'UTF-16LE') else: return unicode(desc.data, 'UTF-16BE') ## def unpacklongdatetime(self, desc): return self.kMacEpoch + datetime.timedelta(seconds=struct.unpack('q', desc.data)[0]) def unpackqdpoint(self, desc): x, y = struct.unpack('hh', desc.data) return (y, x) def unpackqdrect(self, desc): x1, y1, x2, y2 = struct.unpack('hhhh', desc.data) return (y1, x1, y2, x2) def unpackrgbcolor(self, desc): return struct.unpack('HHH', desc.data) def unpackversion(self, desc): # Cocoa apps use unicode strings for version numbers, so return as string for consistency try: return self.unpack(desc.coerce(kae.typeUnicodeText)) # supported in 10.4+ except: return '%i.%i.%i' % ((ord(desc.data[0]),) + divmod(ord(desc.data[1]), 16)) # note: always big-endian ## def unpackalias(self, desc): return mactypes.Alias.makewithdesc(desc) def unpackfileurl(self, desc): return mactypes.File.makewithdesc(desc) unpackfsref = unpackfss = unpackfileurl ## def unpackaelist(self, desc): # Unpack list and its values. return [self.unpack(desc.getitem(i + 1, kae.typeWildCard)[1]) for i in range(desc.count())] def unpackaerecord(self, desc): # Unpack record to dict, converting keys from 4-letter codes to AEType instances and unpacking values. dct = {} for i in range(desc.count()): key, value = desc.getitem(i + 1, kae.typeWildCard) if key == 'usrf': lst = self.unpackaelist(value) for i in range(0, len(lst), 2): dct[lst[i]] = lst[i+1] else: dct[AEType(key)] = self.unpack(value) return dct ## def unpacktype(self, desc): return AEType(fourcharcode(desc.data)) def unpackenumeration(self, desc): return AEEnum(fourcharcode(desc.data)) def unpackproperty(self, desc): return AEProp(fourcharcode(desc.data)) def unpackkeyword(self, desc): return AEKey(fourcharcode(desc.data)) ## def fullyunpackobjectspecifier(self, desc): # This function performs a full recursive unpacking of object specifiers, reconstructing an 'app'/'con'/'its' based aem reference from the ground up. want = self.unpack(desc.getparam(kae.keyAEDesiredClass, kae.typeType)).code # 4-letter code indicating element class keyform = self.unpack(desc.getparam(kae.keyAEKeyForm, kae.typeEnumeration)).code # 4-letter code indicating Specifier type key = self.unpack(desc.getparam(kae.keyAEKeyData, kae.typeWildCard)) # value indicating which object(s) to select ref = self.unpack(desc.getparam(kae.keyAEContainer, kae.typeWildCard)) # recursively unpack container structure if not isinstance(ref, aemreference.Query): if ref is None: ref = self.app else: ref = self.customroot(ref) # print(want, keyform, key, ref) # DEBUG if keyform == kae.formPropertyID: # property specifier return ref.property(key.code) elif keyform == 'usrp': # user-defined property specifier return ref.userproperty(key) elif keyform == kae.formRelativePosition: # relative element specifier if key.code == kae.kAEPrevious: return ref.previous(want) elif key.code == kae.kAENext: return ref.next(want) else: raise ValueError("Bad relative position selector: %r" % want) else: # other element(s) specifier ref = ref.elements(want) if keyform == kae.formName: return ref.byname(key) elif keyform == kae.formAbsolutePosition: if isinstance(key, _Ordinal): if key.code == kae.kAEAll: return ref else: return getattr(ref, {kae.kAEFirst: 'first', kae.kAELast: 'last', kae.kAEMiddle: 'middle', kae.kAEAny: 'any'}[key.code]) else: return ref.byindex(key) elif keyform == kae.formUniqueID: return ref.byid(key) elif keyform == kae.formRange: return ref.byrange(*key.range) elif keyform == kae.formTest: return ref.byfilter(key) raise TypeError def unpackobjectspecifier(self, desc): # This function performance-optimises the unpacking of some object specifiers by only doing a shallow unpack where only the topmost descriptor is unpacked. # The container AEDesc is retained as-is, allowing a full recursive unpack to be performed later on only if needed (e.g. if the __repr__ method is called). # For simplicity, only the commonly encountered forms are optimised this way; forms that are rarely returned by applications (e.g. typeRange) are always fully unpacked. keyform = self.unpack(desc.getparam(kae.keyAEKeyForm, kae.typeEnumeration)).code if keyform in [kae.formPropertyID, kae.formAbsolutePosition, kae.formName, kae.formUniqueID]: want = self.unpack(desc.getparam(kae.keyAEDesiredClass, kae.typeType)).code # 4-letter code indicating element class key = self.unpack(desc.getparam(kae.keyAEKeyData, kae.typeWildCard)) # value indicating which object(s) to select container = aemreference.DeferredSpecifier(desc.getparam(kae.keyAEContainer, kae.typeWildCard), self) if keyform == kae.formPropertyID: ref = aemreference.Property(want, container, key.code) elif keyform == kae.formAbsolutePosition: if isinstance(key, _Ordinal): if key.code == kae.kAEAll: ref = aemreference.AllElements(want, container) else: keyname = {kae.kAEFirst: 'first', kae.kAELast: 'last', kae.kAEMiddle: 'middle', kae.kAEAny: 'any'}[key.code] ref = aemreference.ElementByOrdinal(want, aemreference.UnkeyedElements(want, container), key, keyname) else: ref = aemreference.ElementByIndex(want, aemreference.UnkeyedElements(want, container), key) elif keyform == kae.formName: ref = aemreference.ElementByName(want, aemreference.UnkeyedElements(want, container), key) elif keyform == kae.formUniqueID: ref = aemreference.ElementByID(want, aemreference.UnkeyedElements(want, container), key) ref.AEM_packself = lambda codecs:desc return ref else: # do full unpack of more complex, rarely returned reference forms return self.fullyunpackobjectspecifier(desc) def unpackinsertionloc(self, desc): return getattr(self.fullyunpackobjectspecifier(desc.getparam(kae.keyAEObject, kae.typeWildCard)), self.kInsertionLocSelectors[desc.getparam(kae.keyAEPosition, kae.typeEnumeration).data]) def unpackcompdescriptor(self, desc): operator = self.kTypeCompDescriptorOperators[desc.getparam(kae.keyAECompOperator, kae.typeEnumeration).data] op1 = self.unpack(desc.getparam(kae.keyAEObject1, kae.typeWildCard)) op2 = self.unpack(desc.getparam(kae.keyAEObject2, kae.typeWildCard)) if operator == 'contains': if isinstance(op1, aemreference.Query) and op1.AEM_root() == aemreference.its: return op1.contains(op2) else: return op2.isin(op1) return getattr(op1, operator)(op2) def unpacklogicaldescriptor(self, desc): operator = self.kTypeLogicalDescriptorOperators[desc.getparam(kae.keyAELogicalOperator, kae.typeEnumeration).data] operands = self.unpack(desc.getparam(kae.keyAELogicalTerms, kae.typeAEList)) return operator == 'NOT' and operands[0].NOT or getattr(operands[0], operator)(*operands[1:]) def unpackrangedescriptor(self, desc): return _Range([self.unpack(desc.getparam(kae.keyAERangeStart, kae.typeWildCard)), self.unpack(desc.getparam(kae.keyAERangeStop, kae.typeWildCard))]) def unpackabsoluteordinal(self, desc): return _Ordinal(fourcharcode(desc.data)) ## app = aemreference.app con = aemreference.con its = aemreference.its customroot = aemreference.customroot
def packstr(self, val): return newdesc(kae.typeChar, val)
def packstructtime(self, val): sec = int(time.mktime(val) - self.kMacEpochT) return newdesc(kae.typeLongDateTime, struct.pack('q', sec))
def packtype(code): return ae.newdesc(kae.typeType, code[::-1])
def packenum(code): return ae.newdesc(kae.typeEnumeration, code[::-1])
def packdatetime(self, val): delta = val - self.kMacEpoch sec = delta.days * 3600 * 24 + delta.seconds return newdesc(kae.typeLongDateTime, struct.pack('q', sec))
def packtype(self, val): return newdesc(kae.typeType, fourcharcode(val.code))
class ApplicationRoot(ReferenceRoot): """Form: app Reference base; represents an application's application object. Used to construct full references. """ _kName = 'app' _kType = ae.newdesc(kae.typeNull, '')