diff --git a/osxphotos/_applescript/__init__.py b/osxphotos/_applescript/__init__.py new file mode 100644 index 00000000..8883faa2 --- /dev/null +++ b/osxphotos/_applescript/__init__.py @@ -0,0 +1,162 @@ +""" applescript -- Easy-to-use Python wrapper for NSAppleScript """ + +import sys + +from Foundation import NSAppleScript, NSAppleEventDescriptor, NSURL, \ + NSAppleScriptErrorMessage, NSAppleScriptErrorBriefMessage, \ + NSAppleScriptErrorNumber, NSAppleScriptErrorAppName, NSAppleScriptErrorRange + +from .aecodecs import Codecs, fourcharcode, AEType, AEEnum +from . import kae + +__all__ = ['AppleScript', 'ScriptError', 'AEType', 'AEEnum', 'kMissingValue', 'kae'] + + +###################################################################### + + +class AppleScript: + """ Represents a compiled AppleScript. The script object is persistent; its handlers may be called multiple times and its top-level properties will retain current state until the script object's disposal. + + + """ + + _codecs = Codecs() + + def __init__(self, source=None, path=None): + """ + source : str | None -- AppleScript source code + path : str | None -- full path to .scpt/.applescript file + + Notes: + + - Either the path or the source argument must be provided. + + - If the script cannot be read/compiled, a ScriptError is raised. + """ + if path: + url = NSURL.fileURLWithPath_(path) + self._script, errorinfo = NSAppleScript.alloc().initWithContentsOfURL_error_(url, None) + if errorinfo: + raise ScriptError(errorinfo) + elif source: + self._script = NSAppleScript.alloc().initWithSource_(source) + else: + raise ValueError("Missing source or path argument.") + if not self._script.isCompiled(): + errorinfo = self._script.compileAndReturnError_(None)[1] + if errorinfo: + raise ScriptError(errorinfo) + + def __repr__(self): + s = self.source + return 'AppleScript({})'.format(repr(s) if len(s) < 100 else '{}...{}'.format(repr(s)[:80], repr(s)[-17:])) + + ## + + def _newevent(self, suite, code, args): + evt = NSAppleEventDescriptor.appleEventWithEventClass_eventID_targetDescriptor_returnID_transactionID_( + fourcharcode(suite), fourcharcode(code), NSAppleEventDescriptor.nullDescriptor(), 0, 0) + evt.setDescriptor_forKeyword_(self._codecs.pack(args), fourcharcode(kae.keyDirectObject)) + return evt + + def _unpackresult(self, result, errorinfo): + if not result: + raise ScriptError(errorinfo) + return self._codecs.unpack(result) + + ## + + source = property(lambda self: str(self._script.source()), doc="str -- the script's source code") + + def run(self, *args): + """ Run the script, optionally passing arguments to its run handler. + + args : anything -- arguments to pass to script, if any; see also supported type mappings documentation + Result : anything | None -- the script's return value, if any + + Notes: + + - The run handler must be explicitly declared in order to pass arguments. + + - AppleScript will ignore excess arguments. Passing insufficient arguments will result in an error. + + - If execution fails, a ScriptError is raised. + """ + if args: + evt = self._newevent(kae.kCoreEventClass, kae.kAEOpenApplication, args) + return self._unpackresult(*self._script.executeAppleEvent_error_(evt, None)) + else: + return self._unpackresult(*self._script.executeAndReturnError_(None)) + + def call(self, name, *args): + """ Call the specified user-defined handler. + + name : str -- the handler's name (case-sensitive) + args : anything -- arguments to pass to script, if any; see documentation for supported types + Result : anything | None -- the script's return value, if any + + Notes: + + - The handler's name must be a user-defined identifier, not an AppleScript keyword; e.g. 'myCount' is acceptable; 'count' is not. + + - AppleScript will ignore excess arguments. Passing insufficient arguments will result in an error. + + - If execution fails, a ScriptError is raised. + """ + evt = self._newevent(kae.kASAppleScriptSuite, kae.kASPrepositionalSubroutine, args) + evt.setDescriptor_forKeyword_(NSAppleEventDescriptor.descriptorWithString_(name), + fourcharcode(kae.keyASSubroutineName)) + return self._unpackresult(*self._script.executeAppleEvent_error_(evt, None)) + + +## + + +class ScriptError(Exception): + """ Indicates an AppleScript compilation/execution error. """ + + def __init__(self, errorinfo): + self._errorinfo = dict(errorinfo) + + def __repr__(self): + return 'ScriptError({})'.format(self._errorinfo) + + @property + def message(self): + """ str -- the error message """ + msg = self._errorinfo.get(NSAppleScriptErrorMessage) + if not msg: + msg = self._errorinfo.get(NSAppleScriptErrorBriefMessage, 'Script Error') + return msg + + number = property(lambda self: self._errorinfo.get(NSAppleScriptErrorNumber), + doc="int | None -- the error number, if given") + + appname = property(lambda self: self._errorinfo.get(NSAppleScriptErrorAppName), + doc="str | None -- the name of the application that reported the error, where relevant") + + @property + def range(self): + """ (int, int) -- the start and end points (1-indexed) within the source code where the error occurred """ + range = self._errorinfo.get(NSAppleScriptErrorRange) + if range: + start = range.rangeValue().location + end = start + range.rangeValue().length + return (start, end) + else: + return None + + def __str__(self): + msg = self.message + for s, v in [(' ({})', self.number), (' app={!r}', self.appname), (' range={0[0]}-{0[1]}', self.range)]: + if v is not None: + msg += s.format(v) + return msg.encode('ascii', 'replace') if sys.version_info.major < 3 else msg # 2.7 compatibility + + +## + + +kMissingValue = AEType(kae.cMissingValue) # convenience constant + diff --git a/osxphotos/_applescript/aecodecs.py b/osxphotos/_applescript/aecodecs.py new file mode 100644 index 00000000..2fbde773 --- /dev/null +++ b/osxphotos/_applescript/aecodecs.py @@ -0,0 +1,269 @@ +""" aecodecs -- Convert from common Python types to Apple Event Manager types and vice-versa. """ + +import datetime, struct, sys + +from Foundation import NSAppleEventDescriptor, NSURL + +from . import kae + + +__all__ = ['Codecs', 'AEType', 'AEEnum'] + + +###################################################################### + + +def fourcharcode(code): + """ Convert four-char code for use in NSAppleEventDescriptor methods. + + code : bytes -- four-char code, e.g. b'utxt' + Result : int -- OSType, e.g. 1970567284 + """ + return struct.unpack('>I', code)[0] + + +####### + + +class Codecs: + """ Implements mappings for common Python types with direct AppleScript equivalents. Used by AppleScript class. """ + + kMacEpoch = datetime.datetime(1904, 1, 1) + kUSRF = fourcharcode(kae.keyASUserRecordFields) + + def __init__(self): + # Clients may add/remove/replace encoder and decoder items: + self.encoders = { + NSAppleEventDescriptor.class__(): self.packdesc, + type(None): self.packnone, + bool: self.packbool, + int: self.packint, + float: self.packfloat, + bytes: self.packbytes, + str: self.packstr, + list: self.packlist, + tuple: self.packlist, + dict: self.packdict, + datetime.datetime: self.packdatetime, + AEType: self.packtype, + AEEnum: self.packenum, + } + if sys.version_info.major < 3: # 2.7 compatibility + self.encoders[unicode] = self.packstr + + self.decoders = {fourcharcode(k): v for k, v in { + kae.typeNull: self.unpacknull, + kae.typeBoolean: self.unpackboolean, + kae.typeFalse: self.unpackboolean, + kae.typeTrue: self.unpackboolean, + kae.typeSInt32: self.unpacksint32, + kae.typeIEEE64BitFloatingPoint: self.unpackfloat64, + kae.typeUTF8Text: self.unpackunicodetext, + kae.typeUTF16ExternalRepresentation: self.unpackunicodetext, + kae.typeUnicodeText: self.unpackunicodetext, + kae.typeLongDateTime: self.unpacklongdatetime, + kae.typeAEList: self.unpackaelist, + kae.typeAERecord: self.unpackaerecord, + kae.typeAlias: self.unpackfile, + kae.typeFSS: self.unpackfile, + kae.typeFSRef: self.unpackfile, + kae.typeFileURL: self.unpackfile, + kae.typeType: self.unpacktype, + kae.typeEnumeration: self.unpackenumeration, + }.items()} + + def pack(self, data): + """Pack Python data. + data : anything -- a Python value + Result : NSAppleEventDescriptor -- an AE descriptor, or error if no encoder exists for this type of data + """ + try: + return self.encoders[data.__class__](data) # quick lookup by type/class + except (KeyError, AttributeError) as e: + for type, encoder in self.encoders.items(): # slower but more thorough lookup that can handle subtypes/subclasses + if isinstance(data, type): + return encoder(data) + raise TypeError("Can't pack data into an AEDesc (unsupported type): {!r}".format(data)) + + def unpack(self, desc): + """Unpack an Apple event descriptor. + desc : NSAppleEventDescriptor + Result : anything -- a Python value, or the original NSAppleEventDescriptor if no decoder is found + """ + decoder = self.decoders.get(desc.descriptorType()) + # unpack known type + if decoder: + return decoder(desc) + # if it's a record-like desc, unpack as dict with an extra AEType(b'pcls') key containing the desc type + rec = desc.coerceToDescriptorType_(fourcharcode(kae.typeAERecord)) + if rec: + rec = self.unpackaerecord(rec) + rec[AEType(kae.pClass)] = AEType(struct.pack('>I', desc.descriptorType())) + return rec + # return as-is + return desc + + ## + + def _packbytes(self, desctype, data): + return NSAppleEventDescriptor.descriptorWithDescriptorType_bytes_length_( + fourcharcode(desctype), data, len(data)) + + def packdesc(self, val): + return val + + def packnone(self, val): + return NSAppleEventDescriptor.nullDescriptor() + + def packbool(self, val): + return NSAppleEventDescriptor.descriptorWithBoolean_(int(val)) + + def packint(self, val): + if (-2**31) <= val < (2**31): + return NSAppleEventDescriptor.descriptorWithInt32_(val) + else: + return self.pack(float(val)) + + def packfloat(self, val): + return self._packbytes(kae.typeFloat, struct.pack('d', val)) + + def packbytes(self, val): + return self._packbytes(kae.typeData, val) + + def packstr(self, val): + return NSAppleEventDescriptor.descriptorWithString_(val) + + def packdatetime(self, val): + delta = val - self.kMacEpoch + sec = delta.days * 3600 * 24 + delta.seconds + return self._packbytes(kae.typeLongDateTime, struct.pack('q', sec)) + + def packlist(self, val): + lst = NSAppleEventDescriptor.listDescriptor() + for item in val: + lst.insertDescriptor_atIndex_(self.pack(item), 0) + return lst + + def packdict(self, val): + record = NSAppleEventDescriptor.recordDescriptor() + usrf = desctype = None + for key, value in val.items(): + if isinstance(key, AEType): + if key.code == kae.pClass and isinstance(value, AEType): # AS packs records that contain a 'class' property by coercing the packed record to the descriptor type specified by the property's value (assuming it's an AEType) + desctype = value + else: + record.setDescriptor_forKeyword_(self.pack(value), fourcharcode(key.code)) + else: + if not usrf: + usrf = NSAppleEventDescriptor.listDescriptor() + usrf.insertDescriptor_atIndex_(self.pack(key), 0) + usrf.insertDescriptor_atIndex_(self.pack(value), 0) + if usrf: + record.setDescriptor_forKeyword_(usrf, self.kUSRF) + if desctype: + newrecord = record.coerceToDescriptorType_(fourcharcode(desctype.code)) + if newrecord: + record = newrecord + else: # coercion failed for some reason, so pack as normal key-value pair + record.setDescriptor_forKeyword_(self.pack(desctype), fourcharcode(key.code)) + return record + + def packtype(self, val): + return NSAppleEventDescriptor.descriptorWithTypeCode_(fourcharcode(val.code)) + + def packenum(self, val): + return NSAppleEventDescriptor.descriptorWithEnumCode_(fourcharcode(val.code)) + + ####### + + def unpacknull(self, desc): + return None + + def unpackboolean(self, desc): + return desc.booleanValue() + + def unpacksint32(self, desc): + return desc.int32Value() + + def unpackfloat64(self, desc): + return struct.unpack('d', bytes(desc.data()))[0] + + def unpackunicodetext(self, desc): + return desc.stringValue() + + def unpacklongdatetime(self, desc): + return self.kMacEpoch + datetime.timedelta(seconds=struct.unpack('q', bytes(desc.data()))[0]) + + def unpackaelist(self, desc): + return [self.unpack(desc.descriptorAtIndex_(i + 1)) for i in range(desc.numberOfItems())] + + def unpackaerecord(self, desc): + dct = {} + for i in range(desc.numberOfItems()): + key = desc.keywordForDescriptorAtIndex_(i + 1) + value = desc.descriptorForKeyword_(key) + if key == self.kUSRF: + lst = self.unpackaelist(value) + for i in range(0, len(lst), 2): + dct[lst[i]] = lst[i+1] + else: + dct[AEType(struct.pack('>I', key))] = self.unpack(value) + return dct + + def unpacktype(self, desc): + return AEType(struct.pack('>I', desc.typeCodeValue())) + + def unpackenumeration(self, desc): + return AEEnum(struct.pack('>I', desc.enumCodeValue())) + + def unpackfile(self, desc): + url = bytes(desc.coerceToDescriptorType_(fourcharcode(kae.typeFileURL)).data()).decode('utf8') + return NSURL.URLWithString_(url).path() + + +####### + + +class AETypeBase: + """ Base class for AEType and AEEnum. + + Notes: + + - Hashable and comparable, so may be used as keys in dictionaries that map to AE records. + """ + + def __init__(self, code): + """ + code : bytes -- four-char code, e.g. b'utxt' + """ + if not isinstance(code, bytes): + raise TypeError('invalid code (not a bytes object): {!r}'.format(code)) + elif len(code) != 4: + raise ValueError('invalid code (not four bytes long): {!r}'.format(code)) + self._code = code + + code = property(lambda self:self._code, doc="bytes -- four-char code, e.g. b'utxt'") + + def __hash__(self): + return hash(self._code) + + def __eq__(self, val): + return val.__class__ == self.__class__ and val.code == self._code + + def __ne__(self, val): + return not self == val + + def __repr__(self): + return "{}({!r})".format(self.__class__.__name__, self._code) + + +## + + +class AEType(AETypeBase): + """An AE type. Maps to an AppleScript type class, e.g. AEType(b'utxt') <=> 'unicode text'.""" + + +class AEEnum(AETypeBase): + """An AE enumeration. Maps to an AppleScript constant, e.g. AEEnum(b'yes ') <=> 'yes'.""" + diff --git a/osxphotos/_applescript/kae.py b/osxphotos/_applescript/kae.py new file mode 100644 index 00000000..42d56e68 --- /dev/null +++ b/osxphotos/_applescript/kae.py @@ -0,0 +1,1720 @@ +# kae.py +# +# Generated on Sun Dec 30 17:39:53 +0000 2007 + + +# AEDataModel.h + +typeBoolean = b'bool' +typeChar = b'TEXT' + +typeStyledUnicodeText = b'sutx' +typeEncodedString = b'encs' +typeUnicodeText = b'utxt' +typeCString = b'cstr' +typePString = b'pstr' + +typeUTF16ExternalRepresentation = b'ut16' +typeUTF8Text = b'utf8' + +typeSInt16 = b'shor' +typeUInt16 = b'ushr' +typeSInt32 = b'long' +typeUInt32 = b'magn' +typeSInt64 = b'comp' +typeUInt64 = b'ucom' +typeIEEE32BitFloatingPoint = b'sing' +typeIEEE64BitFloatingPoint = b'doub' +type128BitFloatingPoint = b'ldbl' +typeDecimalStruct = b'decm' + +typeSMInt = typeSInt16 +typeShortInteger = typeSInt16 +typeInteger = typeSInt32 +typeLongInteger = typeSInt32 +typeMagnitude = typeUInt32 +typeComp = typeSInt64 +typeSMFloat = typeIEEE32BitFloatingPoint +typeShortFloat = typeIEEE32BitFloatingPoint +typeFloat = typeIEEE64BitFloatingPoint +typeLongFloat = typeIEEE64BitFloatingPoint +typeExtended = b'exte' + +typeAEList = b'list' +typeAERecord = b'reco' +typeAppleEvent = b'aevt' +typeEventRecord = b'evrc' +typeTrue = b'true' +typeFalse = b'fals' +typeAlias = b'alis' +typeEnumerated = b'enum' +typeType = b'type' +typeAppParameters = b'appa' +typeProperty = b'prop' +typeFSRef = b'fsrf' +typeFileURL = b'furl' +typeKeyword = b'keyw' +typeSectionH = b'sect' +typeWildCard = b'****' +typeApplSignature = b'sign' +typeQDRectangle = b'qdrt' +typeFixed = b'fixd' +typeProcessSerialNumber = b'psn ' +typeApplicationURL = b'aprl' +typeNull = b'null' + +typeFSS = b'fss ' + +typeCFAttributedStringRef = b'cfas' +typeCFMutableAttributedStringRef = b'cfaa' +typeCFStringRef = b'cfst' +typeCFMutableStringRef = b'cfms' +typeCFArrayRef = b'cfar' +typeCFMutableArrayRef = b'cfma' +typeCFDictionaryRef = b'cfdc' +typeCFMutableDictionaryRef = b'cfmd' +typeCFNumberRef = b'cfnb' +typeCFBooleanRef = b'cftf' +typeCFTypeRef = b'cfty' + +typeKernelProcessID = b'kpid' +typeMachPort = b'port' + +typeApplicationBundleID = b'bund' + +keyTransactionIDAttr = b'tran' +keyReturnIDAttr = b'rtid' +keyEventClassAttr = b'evcl' +keyEventIDAttr = b'evid' +keyAddressAttr = b'addr' +keyOptionalKeywordAttr = b'optk' +keyTimeoutAttr = b'timo' +keyInteractLevelAttr = b'inte' +keyEventSourceAttr = b'esrc' +keyMissedKeywordAttr = b'miss' +keyOriginalAddressAttr = b'from' +keyAcceptTimeoutAttr = b'actm' +keyReplyRequestedAttr = b'repq' + +kAEDebugPOSTHeader = (1 << 0) +kAEDebugReplyHeader = (1 << 1) +kAEDebugXMLRequest = (1 << 2) +kAEDebugXMLResponse = (1 << 3) +kAEDebugXMLDebugAll = 0xFFFFFFFF + +kSOAP1999Schema = b'ss99' +kSOAP2001Schema = b'ss01' + +keyUserNameAttr = b'unam' +keyUserPasswordAttr = b'pass' +keyDisableAuthenticationAttr = b'auth' +keyXMLDebuggingAttr = b'xdbg' +kAERPCClass = b'rpc ' +kAEXMLRPCScheme = b'RPC2' +kAESOAPScheme = b'SOAP' +kAESharedScriptHandler = b'wscp' +keyRPCMethodName = b'meth' +keyRPCMethodParam = b'parm' +keyRPCMethodParamOrder = b'/ord' +keyAEPOSTHeaderData = b'phed' +keyAEReplyHeaderData = b'rhed' +keyAEXMLRequestData = b'xreq' +keyAEXMLReplyData = b'xrep' +keyAdditionalHTTPHeaders = b'ahed' +keySOAPAction = b'sact' +keySOAPMethodNameSpace = b'mspc' +keySOAPMethodNameSpaceURI = b'mspu' +keySOAPSchemaVersion = b'ssch' + +keySOAPStructureMetaData = b'/smd' +keySOAPSMDNamespace = b'ssns' +keySOAPSMDNamespaceURI = b'ssnu' +keySOAPSMDType = b'sstp' + +kAEUseHTTPProxyAttr = b'xupr' +kAEHTTPProxyPortAttr = b'xhtp' +kAEHTTPProxyHostAttr = b'xhth' + +kAESocks4Protocol = 4 +kAESocks5Protocol = 5 + +kAEUseSocksAttr = b'xscs' +kAESocksProxyAttr = b'xsok' +kAESocksHostAttr = b'xshs' +kAESocksPortAttr = b'xshp' +kAESocksUserAttr = b'xshu' +kAESocksPasswordAttr = b'xshw' + +kAEDescListFactorNone = 0 +kAEDescListFactorType = 4 +kAEDescListFactorTypeAndSize = 8 + +kAutoGenerateReturnID = -1 +kAnyTransactionID = 0 + +kAEDataArray = 0 +kAEPackedArray = 1 +kAEDescArray = 3 +kAEKeyDescArray = 4 + +kAEHandleArray = 2 + +kAENormalPriority = 0x00000000 +kAEHighPriority = 0x00000001 + +kAENoReply = 0x00000001 +kAEQueueReply = 0x00000002 +kAEWaitReply = 0x00000003 +kAEDontReconnect = 0x00000080 +kAEWantReceipt = 0x00000200 +kAENeverInteract = 0x00000010 +kAECanInteract = 0x00000020 +kAEAlwaysInteract = 0x00000030 +kAECanSwitchLayer = 0x00000040 +kAEDontRecord = 0x00001000 +kAEDontExecute = 0x00002000 +kAEProcessNonReplyEvents = 0x00008000 + +kAEDefaultTimeout = -1 +kNoTimeOut = -2 + + + +# AEHelpers.h + +aeBuildSyntaxNoErr = 0 +aeBuildSyntaxBadToken = 1 +aeBuildSyntaxBadEOF = 2 +aeBuildSyntaxNoEOF = 3 +aeBuildSyntaxBadNegative = 4 +aeBuildSyntaxMissingQuote = 5 +aeBuildSyntaxBadHex = 6 +aeBuildSyntaxOddHex = 7 +aeBuildSyntaxNoCloseHex = 8 +aeBuildSyntaxUncoercedHex = 9 +aeBuildSyntaxNoCloseString = 10 +aeBuildSyntaxBadDesc = 11 +aeBuildSyntaxBadData = 12 +aeBuildSyntaxNoCloseParen = 13 +aeBuildSyntaxNoCloseBracket = 14 +aeBuildSyntaxNoCloseBrace = 15 +aeBuildSyntaxNoKey = 16 +aeBuildSyntaxNoColon = 17 +aeBuildSyntaxCoercedList = 18 +aeBuildSyntaxUncoercedDoubleAt = 19 + + + +# AEMach.h + +keyReplyPortAttr = b'repp' + +typeReplyPortAttr = keyReplyPortAttr + + + +# AEObjects.h + +kAEAND = b'AND ' +kAEOR = b'OR ' +kAENOT = b'NOT ' +kAEFirst = b'firs' +kAELast = b'last' +kAEMiddle = b'midd' +kAEAny = b'any ' +kAEAll = b'all ' +kAENext = b'next' +kAEPrevious = b'prev' +keyAECompOperator = b'relo' +keyAELogicalTerms = b'term' +keyAELogicalOperator = b'logc' +keyAEObject1 = b'obj1' +keyAEObject2 = b'obj2' +keyAEDesiredClass = b'want' +keyAEContainer = b'from' +keyAEKeyForm = b'form' +keyAEKeyData = b'seld' + +keyAERangeStart = b'star' +keyAERangeStop = b'stop' +keyDisposeTokenProc = b'xtok' +keyAECompareProc = b'cmpr' +keyAECountProc = b'cont' +keyAEMarkTokenProc = b'mkid' +keyAEMarkProc = b'mark' +keyAEAdjustMarksProc = b'adjm' +keyAEGetErrDescProc = b'indc' + +formAbsolutePosition = b'indx' +formRelativePosition = b'rele' +formTest = b'test' +formRange = b'rang' +formPropertyID = b'prop' +formName = b'name' +formUniqueID = b'ID ' +typeObjectSpecifier = b'obj ' +typeObjectBeingExamined = b'exmn' +typeCurrentContainer = b'ccnt' +typeToken = b'toke' +typeRelativeDescriptor = b'rel ' +typeAbsoluteOrdinal = b'abso' +typeIndexDescriptor = b'inde' +typeRangeDescriptor = b'rang' +typeLogicalDescriptor = b'logi' +typeCompDescriptor = b'cmpd' +typeOSLTokenList = b'ostl' + +kAEIDoMinimum = 0x0000 +kAEIDoWhose = 0x0001 +kAEIDoMarking = 0x0004 +kAEPassSubDescs = 0x0008 +kAEResolveNestedLists = 0x0010 +kAEHandleSimpleRanges = 0x0020 +kAEUseRelativeIterators = 0x0040 + +typeWhoseDescriptor = b'whos' +formWhose = b'whos' +typeWhoseRange = b'wrng' +keyAEWhoseRangeStart = b'wstr' +keyAEWhoseRangeStop = b'wstp' +keyAEIndex = b'kidx' +keyAETest = b'ktst' + + + +# AEPackObject.h + + + +# AERegistry.h + +cAEList = b'list' +cApplication = b'capp' +cArc = b'carc' +cBoolean = b'bool' +cCell = b'ccel' +cChar = b'cha ' +cColorTable = b'clrt' +cColumn = b'ccol' +cDocument = b'docu' +cDrawingArea = b'cdrw' +cEnumeration = b'enum' +cFile = b'file' +cFixed = b'fixd' +cFixedPoint = b'fpnt' +cFixedRectangle = b'frct' +cGraphicLine = b'glin' +cGraphicObject = b'cgob' +cGraphicShape = b'cgsh' +cGraphicText = b'cgtx' +cGroupedGraphic = b'cpic' + +cInsertionLoc = b'insl' +cInsertionPoint = b'cins' +cIntlText = b'itxt' +cIntlWritingCode = b'intl' +cItem = b'citm' +cLine = b'clin' +cLongDateTime = b'ldt ' +cLongFixed = b'lfxd' +cLongFixedPoint = b'lfpt' +cLongFixedRectangle = b'lfrc' +cLongInteger = b'long' +cLongPoint = b'lpnt' +cLongRectangle = b'lrct' +cMachineLoc = b'mLoc' +cMenu = b'cmnu' +cMenuItem = b'cmen' +cObject = b'cobj' +cObjectSpecifier = b'obj ' +cOpenableObject = b'coob' +cOval = b'covl' + +cParagraph = b'cpar' +cPICT = b'PICT' +cPixel = b'cpxl' +cPixelMap = b'cpix' +cPolygon = b'cpgn' +cProperty = b'prop' +cQDPoint = b'QDpt' +cQDRectangle = b'qdrt' +cRectangle = b'crec' +cRGBColor = b'cRGB' +cRotation = b'trot' +cRoundedRectangle = b'crrc' +cRow = b'crow' +cSelection = b'csel' +cShortInteger = b'shor' +cTable = b'ctbl' +cText = b'ctxt' +cTextFlow = b'cflo' +cTextStyles = b'tsty' +cType = b'type' + +cVersion = b'vers' +cWindow = b'cwin' +cWord = b'cwor' +enumArrows = b'arro' +enumJustification = b'just' +enumKeyForm = b'kfrm' +enumPosition = b'posi' +enumProtection = b'prtn' +enumQuality = b'qual' +enumSaveOptions = b'savo' +enumStyle = b'styl' +enumTransferMode = b'tran' +kAEAbout = b'abou' +kAEAfter = b'afte' +kAEAliasSelection = b'sali' +kAEAllCaps = b'alcp' +kAEArrowAtEnd = b'aren' +kAEArrowAtStart = b'arst' +kAEArrowBothEnds = b'arbo' + +kAEAsk = b'ask ' +kAEBefore = b'befo' +kAEBeginning = b'bgng' +kAEBeginsWith = b'bgwt' +kAEBeginTransaction = b'begi' +kAEBold = b'bold' +kAECaseSensEquals = b'cseq' +kAECentered = b'cent' +kAEChangeView = b'view' +kAEClone = b'clon' +kAEClose = b'clos' +kAECondensed = b'cond' +kAEContains = b'cont' +kAECopy = b'copy' +kAECoreSuite = b'core' +kAECountElements = b'cnte' +kAECreateElement = b'crel' +kAECreatePublisher = b'cpub' +kAECut = b'cut ' +kAEDelete = b'delo' + +kAEDoObjectsExist = b'doex' +kAEDoScript = b'dosc' +kAEDrag = b'drag' +kAEDuplicateSelection = b'sdup' +kAEEditGraphic = b'edit' +kAEEmptyTrash = b'empt' +kAEEnd = b'end ' +kAEEndsWith = b'ends' +kAEEndTransaction = b'endt' +kAEEquals = b'= ' +kAEExpanded = b'pexp' +kAEFast = b'fast' +kAEFinderEvents = b'FNDR' +kAEFormulaProtect = b'fpro' +kAEFullyJustified = b'full' +kAEGetClassInfo = b'qobj' +kAEGetData = b'getd' +kAEGetDataSize = b'dsiz' +kAEGetEventInfo = b'gtei' +kAEGetInfoSelection = b'sinf' + +kAEGetPrivilegeSelection = b'sprv' +kAEGetSuiteInfo = b'gtsi' +kAEGreaterThan = b'> ' +kAEGreaterThanEquals = b'>= ' +kAEGrow = b'grow' +kAEHidden = b'hidn' +kAEHiQuality = b'hiqu' +kAEImageGraphic = b'imgr' +kAEIsUniform = b'isun' +kAEItalic = b'ital' +kAELeftJustified = b'left' +kAELessThan = b'< ' +kAELessThanEquals = b'<= ' +kAELowercase = b'lowc' +kAEMakeObjectsVisible = b'mvis' +kAEMiscStandards = b'misc' +kAEModifiable = b'modf' +kAEMove = b'move' +kAENo = b'no ' +kAENoArrow = b'arno' + +kAENonmodifiable = b'nmod' +kAEOpen = b'odoc' +kAEOpenSelection = b'sope' +kAEOutline = b'outl' +kAEPageSetup = b'pgsu' +kAEPaste = b'past' +kAEPlain = b'plan' +kAEPrint = b'pdoc' +kAEPrintSelection = b'spri' +kAEPrintWindow = b'pwin' +kAEPutAwaySelection = b'sput' +kAEQDAddOver = b'addo' +kAEQDAddPin = b'addp' +kAEQDAdMax = b'admx' +kAEQDAdMin = b'admn' +kAEQDBic = b'bic ' +kAEQDBlend = b'blnd' +kAEQDCopy = b'cpy ' +kAEQDNotBic = b'nbic' +kAEQDNotCopy = b'ncpy' + +kAEQDNotOr = b'ntor' +kAEQDNotXor = b'nxor' +kAEQDOr = b'or ' +kAEQDSubOver = b'subo' +kAEQDSubPin = b'subp' +kAEQDSupplementalSuite = b'qdsp' +kAEQDXor = b'xor ' +kAEQuickdrawSuite = b'qdrw' +kAEQuitAll = b'quia' +kAERedo = b'redo' +kAERegular = b'regl' +kAEReopenApplication = b'rapp' +kAEReplace = b'rplc' +kAERequiredSuite = b'reqd' +kAERestart = b'rest' +kAERevealSelection = b'srev' +kAERevert = b'rvrt' +kAERightJustified = b'rght' +kAESave = b'save' +kAESelect = b'slct' +kAESetData = b'setd' + +kAESetPosition = b'posn' +kAEShadow = b'shad' +kAEShowClipboard = b'shcl' +kAEShutDown = b'shut' +kAESleep = b'slep' +kAESmallCaps = b'smcp' +kAESpecialClassProperties = b'c@#!' +kAEStrikethrough = b'strk' +kAESubscript = b'sbsc' +kAESuperscript = b'spsc' +kAETableSuite = b'tbls' +kAETextSuite = b'TEXT' +kAETransactionTerminated = b'ttrm' +kAEUnderline = b'undl' +kAEUndo = b'undo' +kAEWholeWordEquals = b'wweq' +kAEYes = b'yes ' +kAEZoom = b'zoom' + +kAELogOut = b'logo' +kAEReallyLogOut = b'rlgo' +kAEShowRestartDialog = b'rrst' +kAEShowShutdownDialog = b'rsdn' + +kAEMouseClass = b'mous' +kAEDown = b'down' +kAEUp = b'up ' +kAEMoved = b'move' +kAEStoppedMoving = b'stop' +kAEWindowClass = b'wind' +kAEUpdate = b'updt' +kAEActivate = b'actv' +kAEDeactivate = b'dact' +kAECommandClass = b'cmnd' +kAEKeyClass = b'keyc' +kAERawKey = b'rkey' +kAEVirtualKey = b'keyc' +kAENavigationKey = b'nave' +kAEAutoDown = b'auto' +kAEApplicationClass = b'appl' +kAESuspend = b'susp' +kAEResume = b'rsme' +kAEDiskEvent = b'disk' +kAENullEvent = b'null' +kAEWakeUpEvent = b'wake' +kAEScrapEvent = b'scrp' +kAEHighLevel = b'high' + +keyAEAngle = b'kang' +keyAEArcAngle = b'parc' + +keyAEBaseAddr = b'badd' +keyAEBestType = b'pbst' +keyAEBgndColor = b'kbcl' +keyAEBgndPattern = b'kbpt' +keyAEBounds = b'pbnd' +keyAECellList = b'kclt' +keyAEClassID = b'clID' +keyAEColor = b'colr' +keyAEColorTable = b'cltb' +keyAECurveHeight = b'kchd' +keyAECurveWidth = b'kcwd' +keyAEDashStyle = b'pdst' +keyAEData = b'data' +keyAEDefaultType = b'deft' +keyAEDefinitionRect = b'pdrt' +keyAEDescType = b'dstp' +keyAEDestination = b'dest' +keyAEDoAntiAlias = b'anta' +keyAEDoDithered = b'gdit' +keyAEDoRotate = b'kdrt' + +keyAEDoScale = b'ksca' +keyAEDoTranslate = b'ktra' +keyAEEditionFileLoc = b'eloc' +keyAEElements = b'elms' +keyAEEndPoint = b'pend' +keyAEEventClass = b'evcl' +keyAEEventID = b'evti' +keyAEFile = b'kfil' +keyAEFileType = b'fltp' +keyAEFillColor = b'flcl' +keyAEFillPattern = b'flpt' +keyAEFlipHorizontal = b'kfho' +keyAEFlipVertical = b'kfvt' +keyAEFont = b'font' +keyAEFormula = b'pfor' +keyAEGraphicObjects = b'gobs' +keyAEID = b'ID ' +keyAEImageQuality = b'gqua' +keyAEInsertHere = b'insh' +keyAEKeyForms = b'keyf' + +keyAEKeyword = b'kywd' +keyAELevel = b'levl' +keyAELineArrow = b'arro' +keyAEName = b'pnam' +keyAENewElementLoc = b'pnel' +keyAEObject = b'kobj' +keyAEObjectClass = b'kocl' +keyAEOffStyles = b'ofst' +keyAEOnStyles = b'onst' +keyAEParameters = b'prms' +keyAEParamFlags = b'pmfg' +keyAEPenColor = b'ppcl' +keyAEPenPattern = b'pppa' +keyAEPenWidth = b'ppwd' +keyAEPixelDepth = b'pdpt' +keyAEPixMapMinus = b'kpmm' +keyAEPMTable = b'kpmt' +keyAEPointList = b'ptlt' +keyAEPointSize = b'ptsz' +keyAEPosition = b'kpos' + +keyAEPropData = b'prdt' +keyAEProperties = b'qpro' +keyAEProperty = b'kprp' +keyAEPropFlags = b'prfg' +keyAEPropID = b'prop' +keyAEProtection = b'ppro' +keyAERenderAs = b'kren' +keyAERequestedType = b'rtyp' +keyAEResult = b'----' +keyAEResultInfo = b'rsin' +keyAERotation = b'prot' +keyAERotPoint = b'krtp' +keyAERowList = b'krls' +keyAESaveOptions = b'savo' +keyAEScale = b'pscl' +keyAEScriptTag = b'psct' +keyAESearchText = b'stxt' +keyAEShowWhere = b'show' +keyAEStartAngle = b'pang' +keyAEStartPoint = b'pstp' +keyAEStyles = b'ksty' + +keyAESuiteID = b'suit' +keyAEText = b'ktxt' +keyAETextColor = b'ptxc' +keyAETextFont = b'ptxf' +keyAETextPointSize = b'ptps' +keyAETextStyles = b'txst' +keyAETextLineHeight = b'ktlh' +keyAETextLineAscent = b'ktas' +keyAETheText = b'thtx' +keyAETransferMode = b'pptm' +keyAETranslation = b'ptrs' +keyAETryAsStructGraf = b'toog' +keyAEUniformStyles = b'ustl' +keyAEUpdateOn = b'pupd' +keyAEUserTerm = b'utrm' +keyAEWindow = b'wndw' +keyAEWritingCode = b'wrcd' + +keyMiscellaneous = b'fmsc' +keySelection = b'fsel' +keyWindow = b'kwnd' +keyWhen = b'when' +keyWhere = b'wher' +keyModifiers = b'mods' +keyKey = b'key ' +keyKeyCode = b'code' +keyKeyboard = b'keyb' +keyDriveNumber = b'drv#' +keyErrorCode = b'err#' +keyHighLevelClass = b'hcls' +keyHighLevelID = b'hid ' + +pArcAngle = b'parc' +pBackgroundColor = b'pbcl' +pBackgroundPattern = b'pbpt' +pBestType = b'pbst' +pBounds = b'pbnd' +pClass = b'pcls' +pClipboard = b'pcli' +pColor = b'colr' +pColorTable = b'cltb' +pContents = b'pcnt' +pCornerCurveHeight = b'pchd' +pCornerCurveWidth = b'pcwd' +pDashStyle = b'pdst' +pDefaultType = b'deft' +pDefinitionRect = b'pdrt' +pEnabled = b'enbl' +pEndPoint = b'pend' +pFillColor = b'flcl' +pFillPattern = b'flpt' +pFont = b'font' + +pFormula = b'pfor' +pGraphicObjects = b'gobs' +pHasCloseBox = b'hclb' +pHasTitleBar = b'ptit' +pID = b'ID ' +pIndex = b'pidx' +pInsertionLoc = b'pins' +pIsFloating = b'isfl' +pIsFrontProcess = b'pisf' +pIsModal = b'pmod' +pIsModified = b'imod' +pIsResizable = b'prsz' +pIsStationeryPad = b'pspd' +pIsZoomable = b'iszm' +pIsZoomed = b'pzum' +pItemNumber = b'itmn' +pJustification = b'pjst' +pLineArrow = b'arro' +pMenuID = b'mnid' +pName = b'pnam' + +pNewElementLoc = b'pnel' +pPenColor = b'ppcl' +pPenPattern = b'pppa' +pPenWidth = b'ppwd' +pPixelDepth = b'pdpt' +pPointList = b'ptlt' +pPointSize = b'ptsz' +pProtection = b'ppro' +pRotation = b'prot' +pScale = b'pscl' +pScript = b'scpt' +pScriptTag = b'psct' +pSelected = b'selc' +pSelection = b'sele' +pStartAngle = b'pang' +pStartPoint = b'pstp' +pTextColor = b'ptxc' +pTextFont = b'ptxf' +pTextItemDelimiters = b'txdl' +pTextPointSize = b'ptps' + +pTextStyles = b'txst' +pTransferMode = b'pptm' +pTranslation = b'ptrs' +pUniformStyles = b'ustl' +pUpdateOn = b'pupd' +pUserSelection = b'pusl' +pVersion = b'vers' +pVisible = b'pvis' + +typeAEText = b'tTXT' +typeArc = b'carc' +typeBest = b'best' +typeCell = b'ccel' +typeClassInfo = b'gcli' +typeColorTable = b'clrt' +typeColumn = b'ccol' +typeDashStyle = b'tdas' +typeData = b'tdta' +typeDrawingArea = b'cdrw' +typeElemInfo = b'elin' +typeEnumeration = b'enum' +typeEPS = b'EPS ' +typeEventInfo = b'evin' + +typeFinderWindow = b'fwin' +typeFixedPoint = b'fpnt' +typeFixedRectangle = b'frct' +typeGraphicLine = b'glin' +typeGraphicText = b'cgtx' +typeGroupedGraphic = b'cpic' +typeInsertionLoc = b'insl' +typeIntlText = b'itxt' +typeIntlWritingCode = b'intl' +typeLongDateTime = b'ldt ' +typeCFAbsoluteTime = b'cfat' +typeISO8601DateTime = b'isot' +typeLongFixed = b'lfxd' +typeLongFixedPoint = b'lfpt' +typeLongFixedRectangle = b'lfrc' +typeLongPoint = b'lpnt' +typeLongRectangle = b'lrct' +typeMachineLoc = b'mLoc' +typeOval = b'covl' +typeParamInfo = b'pmin' +typePict = b'PICT' + +typePixelMap = b'cpix' +typePixMapMinus = b'tpmm' +typePolygon = b'cpgn' +typePropInfo = b'pinf' +typePtr = b'ptr ' +typeQDPoint = b'QDpt' +typeQDRegion = b'Qrgn' +typeRectangle = b'crec' +typeRGB16 = b'tr16' +typeRGB96 = b'tr96' +typeRGBColor = b'cRGB' +typeRotation = b'trot' +typeRoundedRectangle = b'crrc' +typeRow = b'crow' +typeScrapStyles = b'styl' +typeScript = b'scpt' +typeStyledText = b'STXT' +typeSuiteInfo = b'suin' +typeTable = b'ctbl' +typeTextStyles = b'tsty' + +typeTIFF = b'TIFF' +typeJPEG = b'JPEG' +typeGIF = b'GIFf' +typeVersion = b'vers' + +kAEMenuClass = b'menu' +kAEMenuSelect = b'mhit' +kAEMouseDown = b'mdwn' +kAEMouseDownInBack = b'mdbk' +kAEKeyDown = b'kdwn' +kAEResized = b'rsiz' +kAEPromise = b'prom' + +keyMenuID = b'mid ' +keyMenuItem = b'mitm' +keyCloseAllWindows = b'caw ' +keyOriginalBounds = b'obnd' +keyNewBounds = b'nbnd' +keyLocalWhere = b'lwhr' + +typeHIMenu = b'mobj' +typeHIWindow = b'wobj' + +kBySmallIcon = 0 +kByIconView = 1 +kByNameView = 2 +kByDateView = 3 +kBySizeView = 4 +kByKindView = 5 +kByCommentView = 6 +kByLabelView = 7 +kByVersionView = 8 + +kAEInfo = 11 +kAEMain = 0 +kAESharing = 13 + +kAEZoomIn = 7 +kAEZoomOut = 8 + +kTextServiceClass = b'tsvc' +kUpdateActiveInputArea = b'updt' +kShowHideInputWindow = b'shiw' +kPos2Offset = b'p2st' +kOffset2Pos = b'st2p' +kUnicodeNotFromInputMethod = b'unim' +kGetSelectedText = b'gtxt' +keyAETSMDocumentRefcon = b'refc' +keyAEServerInstance = b'srvi' +keyAETheData = b'kdat' +keyAEFixLength = b'fixl' +keyAEUpdateRange = b'udng' +keyAECurrentPoint = b'cpos' +keyAEBufferSize = b'buff' +keyAEMoveView = b'mvvw' +keyAENextBody = b'nxbd' +keyAETSMScriptTag = b'sclg' +keyAETSMTextFont = b'ktxf' +keyAETSMTextFMFont = b'ktxm' +keyAETSMTextPointSize = b'ktps' +keyAETSMEventRecord = b'tevt' +keyAETSMEventRef = b'tevr' +keyAETextServiceEncoding = b'tsen' +keyAETextServiceMacEncoding = b'tmen' +keyAETSMGlyphInfoArray = b'tgia' +typeTextRange = b'txrn' +typeComponentInstance = b'cmpi' +typeOffsetArray = b'ofay' +typeTextRangeArray = b'tray' +typeLowLevelEventRecord = b'evtr' +typeGlyphInfoArray = b'glia' +typeEventRef = b'evrf' +typeText = typeChar + +kTSMOutsideOfBody = 1 +kTSMInsideOfBody = 2 +kTSMInsideOfActiveInputArea = 3 + +kNextBody = 1 +kPreviousBody = 2 + +kTSMHiliteCaretPosition = 1 +kTSMHiliteRawText = 2 +kTSMHiliteSelectedRawText = 3 +kTSMHiliteConvertedText = 4 +kTSMHiliteSelectedConvertedText = 5 +kTSMHiliteBlockFillText = 6 +kTSMHiliteOutlineText = 7 +kTSMHiliteSelectedText = 8 +kTSMHiliteNoHilite = 9 + +kCaretPosition = kTSMHiliteCaretPosition +kRawText = kTSMHiliteRawText +kSelectedRawText = kTSMHiliteSelectedRawText +kConvertedText = kTSMHiliteConvertedText +kSelectedConvertedText = kTSMHiliteSelectedConvertedText +kBlockFillText = kTSMHiliteBlockFillText +kOutlineText = kTSMHiliteOutlineText +kSelectedText = kTSMHiliteSelectedText + +keyAEHiliteRange = b'hrng' +keyAEPinRange = b'pnrg' +keyAEClauseOffsets = b'clau' +keyAEOffset = b'ofst' +keyAEPoint = b'gpos' +keyAELeftSide = b'klef' +keyAERegionClass = b'rgnc' +keyAEDragging = b'bool' + +keyAELeadingEdge = keyAELeftSide + +typeMeters = b'metr' +typeInches = b'inch' +typeFeet = b'feet' +typeYards = b'yard' +typeMiles = b'mile' +typeKilometers = b'kmtr' +typeCentimeters = b'cmtr' +typeSquareMeters = b'sqrm' +typeSquareFeet = b'sqft' +typeSquareYards = b'sqyd' +typeSquareMiles = b'sqmi' +typeSquareKilometers = b'sqkm' +typeLiters = b'litr' +typeQuarts = b'qrts' +typeGallons = b'galn' +typeCubicMeters = b'cmet' +typeCubicFeet = b'cfet' +typeCubicInches = b'cuin' +typeCubicCentimeter = b'ccmt' +typeCubicYards = b'cyrd' +typeKilograms = b'kgrm' +typeGrams = b'gram' +typeOunces = b'ozs ' +typePounds = b'lbs ' +typeDegreesC = b'degc' +typeDegreesF = b'degf' +typeDegreesK = b'degk' + +kFAServerApp = b'ssrv' +kDoFolderActionEvent = b'fola' +kFolderActionCode = b'actn' +kFolderOpenedEvent = b'fopn' +kFolderClosedEvent = b'fclo' +kFolderWindowMovedEvent = b'fsiz' +kFolderItemsAddedEvent = b'fget' +kFolderItemsRemovedEvent = b'flos' +kItemList = b'flst' +kNewSizeParameter = b'fnsz' +kFASuiteCode = b'faco' +kFAAttachCommand = b'atfa' +kFARemoveCommand = b'rmfa' +kFAEditCommand = b'edfa' +kFAFileParam = b'faal' +kFAIndexParam = b'indx' + +kAEInternetSuite = b'gurl' +kAEISWebStarSuite = b'WWW\xBD' + +kAEISGetURL = b'gurl' +KAEISHandleCGI = b'sdoc' + +cURL = b'url ' +cInternetAddress = b'IPAD' +cHTML = b'html' +cFTPItem = b'ftp ' + +kAEISHTTPSearchArgs = b'kfor' +kAEISPostArgs = b'post' +kAEISMethod = b'meth' +kAEISClientAddress = b'addr' +kAEISUserName = b'user' +kAEISPassword = b'pass' +kAEISFromUser = b'frmu' +kAEISServerName = b'svnm' +kAEISServerPort = b'svpt' +kAEISScriptName = b'scnm' +kAEISContentType = b'ctyp' +kAEISReferrer = b'refr' +kAEISUserAgent = b'Agnt' +kAEISAction = b'Kact' +kAEISActionPath = b'Kapt' +kAEISClientIP = b'Kcip' +kAEISFullRequest = b'Kfrq' + +pScheme = b'pusc' +pHost = b'HOST' +pPath = b'FTPc' +pUserName = b'RAun' +pUserPassword = b'RApw' +pDNSForm = b'pDNS' +pURL = b'pURL' +pTextEncoding = b'ptxe' +pFTPKind = b'kind' + +eScheme = b'esch' +eurlHTTP = b'http' +eurlHTTPS = b'htps' +eurlFTP = b'ftp ' +eurlMail = b'mail' +eurlFile = b'file' +eurlGopher = b'gphr' +eurlTelnet = b'tlnt' +eurlNews = b'news' +eurlSNews = b'snws' +eurlNNTP = b'nntp' +eurlMessage = b'mess' +eurlMailbox = b'mbox' +eurlMulti = b'mult' +eurlLaunch = b'laun' +eurlAFP = b'afp ' +eurlAT = b'at ' +eurlEPPC = b'eppc' +eurlRTSP = b'rtsp' +eurlIMAP = b'imap' +eurlNFS = b'unfs' +eurlPOP = b'upop' +eurlLDAP = b'uldp' +eurlUnknown = b'url?' + +kConnSuite = b'macc' +cDevSpec = b'cdev' +cAddressSpec = b'cadr' +cADBAddress = b'cadb' +cAppleTalkAddress = b'cat ' +cBusAddress = b'cbus' +cEthernetAddress = b'cen ' +cFireWireAddress = b'cfw ' +cIPAddress = b'cip ' +cLocalTalkAddress = b'clt ' +cSCSIAddress = b'cscs' +cTokenRingAddress = b'ctok' +cUSBAddress = b'cusb' +pDeviceType = b'pdvt' +pDeviceAddress = b'pdva' +pConduit = b'pcon' +pProtocol = b'pprt' +pATMachine = b'patm' +pATZone = b'patz' +pATType = b'patt' +pDottedDecimal = b'pipd' +pDNS = b'pdns' +pPort = b'ppor' +pNetwork = b'pnet' +pNode = b'pnod' +pSocket = b'psoc' +pSCSIBus = b'pscb' +pSCSILUN = b'pslu' +eDeviceType = b'edvt' +eAddressSpec = b'eads' +eConduit = b'econ' +eProtocol = b'epro' +eADB = b'eadb' +eAnalogAudio = b'epau' +eAppleTalk = b'epat' +eAudioLineIn = b'ecai' +eAudioLineOut = b'ecal' +eAudioOut = b'ecao' +eBus = b'ebus' +eCDROM = b'ecd ' +eCommSlot = b'eccm' +eDigitalAudio = b'epda' +eDisplay = b'edds' +eDVD = b'edvd' +eEthernet = b'ecen' +eFireWire = b'ecfw' +eFloppy = b'efd ' +eHD = b'ehd ' +eInfrared = b'ecir' +eIP = b'epip' +eIrDA = b'epir' +eIRTalk = b'epit' +eKeyboard = b'ekbd' +eLCD = b'edlc' +eLocalTalk = b'eclt' +eMacIP = b'epmi' +eMacVideo = b'epmv' +eMicrophone = b'ecmi' +eModemPort = b'ecmp' +eModemPrinterPort = b'empp' +eModem = b'edmm' +eMonitorOut = b'ecmn' +eMouse = b'emou' +eNuBusCard = b'ednb' +eNuBus = b'enub' +ePCcard = b'ecpc' +ePCIbus = b'ecpi' +ePCIcard = b'edpi' +ePDSslot = b'ecpd' +ePDScard = b'epds' +ePointingDevice = b'edpd' +ePostScript = b'epps' +ePPP = b'eppp' +ePrinterPort = b'ecpp' +ePrinter = b'edpr' +eSvideo = b'epsv' +eSCSI = b'ecsc' +eSerial = b'epsr' +eSpeakers = b'edsp' +eStorageDevice = b'edst' +eSVGA = b'epsg' +eTokenRing = b'etok' +eTrackball = b'etrk' +eTrackpad = b'edtp' +eUSB = b'ecus' +eVideoIn = b'ecvi' +eVideoMonitor = b'edvm' +eVideoOut = b'ecvo' + +cKeystroke = b'kprs' +pKeystrokeKey = b'kMsg' +pModifiers = b'kMod' +pKeyKind = b'kknd' +eModifiers = b'eMds' +eOptionDown = b'Kopt' +eCommandDown = b'Kcmd' +eControlDown = b'Kctl' +eShiftDown = b'Ksft' +eCapsLockDown = b'Kclk' +eKeyKind = b'ekst' +eEscapeKey = b'ks5\x00' +eDeleteKey = b'ks3\x00' +eTabKey = b'ks0\x00' +eReturnKey = b'ks\x24\x00' +eClearKey = b'ksG\x00' +eEnterKey = b'ksL\x00' +eUpArrowKey = b'ks\x7E\x00' +eDownArrowKey = b'ks\x7D\x00' +eLeftArrowKey = b'ks\x7B\x00' +eRightArrowKey = b'ks\x7C\x00' +eHelpKey = b'ksr\x00' +eHomeKey = b'kss\x00' +ePageUpKey = b'kst\x00' +ePageDownKey = b'ksy\x00' +eForwardDelKey = b'ksu\x00' +eEndKey = b'ksw\x00' +eF1Key = b'ksz\x00' +eF2Key = b'ksx\x00' +eF3Key = b'ksc\x00' +eF4Key = b'ksv\x00' +eF5Key = b'ks\x60\x00' +eF6Key = b'ksa\x00' +eF7Key = b'ksb\x00' +eF8Key = b'ksd\x00' +eF9Key = b'kse\x00' +eF10Key = b'ksm\x00' +eF11Key = b'ksg\x00' +eF12Key = b'kso\x00' +eF13Key = b'ksi\x00' +eF14Key = b'ksk\x00' +eF15Key = b'ksq\x00' + +keyAELaunchedAsLogInItem = b'lgit' +keyAELaunchedAsServiceItem = b'svit' + + + +# AEUserTermTypes.h + +kAEUserTerminology = b'aeut' +kAETerminologyExtension = b'aete' +kAEScriptingSizeResource = b'scsz' +kAEOSAXSizeResource = b'osiz' + +kAEUTHasReturningParam = 31 +kAEUTOptional = 15 +kAEUTlistOfItems = 14 +kAEUTEnumerated = 13 +kAEUTReadWrite = 12 +kAEUTChangesState = 12 +kAEUTTightBindingFunction = 12 +kAEUTEnumsAreTypes = 11 +kAEUTEnumListIsExclusive = 10 +kAEUTReplyIsReference = 9 +kAEUTDirectParamIsReference = 9 +kAEUTParamIsReference = 9 +kAEUTPropertyIsReference = 9 +kAEUTNotDirectParamIsTarget = 8 +kAEUTParamIsTarget = 8 +kAEUTApostrophe = 3 +kAEUTFeminine = 2 +kAEUTMasculine = 1 +kAEUTPlural = 0 + +kLaunchToGetTerminology = (1 << 15) +kDontFindAppBySignature = (1 << 14) +kAlwaysSendSubject = (1 << 13) + +kReadExtensionTermsMask = (1 << 15) + +kOSIZDontOpenResourceFile = 15 +kOSIZdontAcceptRemoteEvents = 14 +kOSIZOpenWithReadPermission = 13 +kOSIZCodeInSharedLibraries = 11 + + + +# AppleEvents.h + +keyDirectObject = b'----' +keyErrorNumber = b'errn' +keyErrorString = b'errs' +keyProcessSerialNumber = b'psn ' +keyPreDispatch = b'phac' +keySelectProc = b'selh' +keyAERecorderCount = b'recr' +keyAEVersion = b'vers' + +kCoreEventClass = b'aevt' + +kAEOpenApplication = b'oapp' +kAEOpenDocuments = b'odoc' +kAEPrintDocuments = b'pdoc' +kAEOpenContents = b'ocon' +kAEQuitApplication = b'quit' +kAEAnswer = b'ansr' +kAEApplicationDied = b'obit' +kAEShowPreferences = b'pref' + +kAEStartRecording = b'reca' +kAEStopRecording = b'recc' +kAENotifyStartRecording = b'rec1' +kAENotifyStopRecording = b'rec0' +kAENotifyRecording = b'recr' + +kAEUnknownSource = 0 +kAEDirectCall = 1 +kAESameProcess = 2 +kAELocalProcess = 3 +kAERemoteProcess = 4 + + + +# AEInteraction.h + +kAEInteractWithSelf = 0 +kAEInteractWithLocal = 1 +kAEInteractWithAll = 2 + +kAEDoNotIgnoreHandler = 0x00000000 +kAEIgnoreAppPhacHandler = 0x00000001 +kAEIgnoreAppEventHandler = 0x00000002 +kAEIgnoreSysPhacHandler = 0x00000004 +kAEIgnoreSysEventHandler = 0x00000008 +kAEIngoreBuiltInEventHandler = 0x00000010 +kAEDontDisposeOnResume = 0x80000000 + +kAENoDispatch = 0 +kAEUseStandardDispatch = 0xFFFFFFFF + + + +# AppleScript.h + +typeAppleScript = b'ascr' +kAppleScriptSubtype = typeAppleScript +typeASStorage = typeAppleScript + +kASSelectInit = 0x1001 +kASSelectSetSourceStyles = 0x1002 +kASSelectGetSourceStyles = 0x1003 +kASSelectGetSourceStyleNames = 0x1004 +kASSelectCopySourceAttributes = 0x1005 +kASSelectSetSourceAttributes = 0x1006 + +kASHasOpenHandler = b'hsod' + +kASDefaultMinStackSize = 4 +kASDefaultPreferredStackSize = 16 +kASDefaultMaxStackSize = 16 +kASDefaultMinHeapSize = 4 +kASDefaultPreferredHeapSize = 16 +kASDefaultMaxHeapSize = 32 + +kASSourceStyleUncompiledText = 0 +kASSourceStyleNormalText = 1 +kASSourceStyleLanguageKeyword = 2 +kASSourceStyleApplicationKeyword = 3 +kASSourceStyleComment = 4 +kASSourceStyleLiteral = 5 +kASSourceStyleUserSymbol = 6 +kASSourceStyleObjectSpecifier = 7 +kASNumberOfSourceStyles = 8 + + + +# ASDebugging.h + +kOSAModeDontDefine = 0x0001 + +kASSelectSetPropertyObsolete = 0x1101 +kASSelectGetPropertyObsolete = 0x1102 +kASSelectSetHandlerObsolete = 0x1103 +kASSelectGetHandlerObsolete = 0x1104 +kASSelectGetAppTerminologyObsolete = 0x1105 +kASSelectSetProperty = 0x1106 +kASSelectGetProperty = 0x1107 +kASSelectSetHandler = 0x1108 +kASSelectGetHandler = 0x1109 +kASSelectGetAppTerminology = 0x110A +kASSelectGetSysTerminology = 0x110B +kASSelectGetPropertyNames = 0x110C +kASSelectGetHandlerNames = 0x110D + + + +# ASRegistry.h + +keyAETarget = b'targ' +keySubjectAttr = b'subj' +keyASReturning = b'Krtn' +kASAppleScriptSuite = b'ascr' +kASScriptEditorSuite = b'ToyS' +kASTypeNamesSuite = b'tpnm' +typeAETE = b'aete' +typeAEUT = b'aeut' +kGetAETE = b'gdte' +kGetAEUT = b'gdut' +kUpdateAEUT = b'udut' +kUpdateAETE = b'udte' +kCleanUpAEUT = b'cdut' +kASComment = b'cmnt' +kASLaunchEvent = b'noop' +keyScszResource = b'scsz' +typeScszResource = b'scsz' +kASSubroutineEvent = b'psbr' +keyASSubroutineName = b'snam' +kASPrepositionalSubroutine = b'psbr' +keyASPositionalArgs = b'parg' + +keyAppHandledCoercion = b'idas' + +kASStartLogEvent = b'log1' +kASStopLogEvent = b'log0' +kASCommentEvent = b'cmnt' + +kASAdd = b'+ ' +kASSubtract = b'- ' +kASMultiply = b'* ' +kASDivide = b'/ ' +kASQuotient = b'div ' +kASRemainder = b'mod ' +kASPower = b'^ ' +kASEqual = kAEEquals +kASNotEqual = 0xAD202020 +kASGreaterThan = kAEGreaterThan +kASGreaterThanOrEqual = kAEGreaterThanEquals +kASLessThan = kAELessThan +kASLessThanOrEqual = kAELessThanEquals +kASComesBefore = b'cbfr' +kASComesAfter = b'cafr' +kASConcatenate = b'ccat' +kASStartsWith = kAEBeginsWith +kASEndsWith = kAEEndsWith +kASContains = kAEContains + +kASAnd = kAEAND +kASOr = kAEOR +kASNot = kAENOT +kASNegate = b'neg ' +keyASArg = b'arg ' + +kASErrorEventCode = b'err ' +kOSAErrorArgs = b'erra' +keyAEErrorObject = b'erob' +pLength = b'leng' +pReverse = b'rvse' +pRest = b'rest' +pInherits = b'c@#^' +pProperties = b'pALL' +keyASUserRecordFields = b'usrf' +typeUserRecordFields = typeAEList + +keyASPrepositionAt = b'at ' +keyASPrepositionIn = b'in ' +keyASPrepositionFrom = b'from' +keyASPrepositionFor = b'for ' +keyASPrepositionTo = b'to ' +keyASPrepositionThru = b'thru' +keyASPrepositionThrough = b'thgh' +keyASPrepositionBy = b'by ' +keyASPrepositionOn = b'on ' +keyASPrepositionInto = b'into' +keyASPrepositionOnto = b'onto' +keyASPrepositionBetween = b'btwn' +keyASPrepositionAgainst = b'agst' +keyASPrepositionOutOf = b'outo' +keyASPrepositionInsteadOf = b'isto' +keyASPrepositionAsideFrom = b'asdf' +keyASPrepositionAround = b'arnd' +keyASPrepositionBeside = b'bsid' +keyASPrepositionBeneath = b'bnth' +keyASPrepositionUnder = b'undr' + +keyASPrepositionOver = b'over' +keyASPrepositionAbove = b'abve' +keyASPrepositionBelow = b'belw' +keyASPrepositionApartFrom = b'aprt' +keyASPrepositionGiven = b'givn' +keyASPrepositionWith = b'with' +keyASPrepositionWithout = b'wout' +keyASPrepositionAbout = b'abou' +keyASPrepositionSince = b'snce' +keyASPrepositionUntil = b'till' + +kDialectBundleResType = b'Dbdl' +cConstant = typeEnumerated +cClassIdentifier = pClass +cObjectBeingExamined = typeObjectBeingExamined +cList = typeAEList +cSmallReal = typeIEEE32BitFloatingPoint +cReal = typeIEEE64BitFloatingPoint +cRecord = typeAERecord +cReference = cObjectSpecifier +cUndefined = b'undf' +cMissingValue = b'msng' +cSymbol = b'symb' +cLinkedList = b'llst' +cVector = b'vect' +cEventIdentifier = b'evnt' +cKeyIdentifier = b'kyid' +cUserIdentifier = b'uid ' +cPreposition = b'prep' +cKeyForm = enumKeyForm +cScript = b'scpt' +cHandler = b'hand' +cProcedure = b'proc' + +cHandleBreakpoint = b'brak' + +cClosure = b'clsr' +cRawData = b'rdat' +cStringClass = typeChar +cNumber = b'nmbr' +cListElement = b'celm' +cListOrRecord = b'lr ' +cListOrString = b'ls ' +cListRecordOrString = b'lrs ' +cNumberOrString = b'ns ' +cNumberOrDateTime = b'nd ' +cNumberDateTimeOrString = b'nds ' +cAliasOrString = b'sf ' +cSeconds = b'scnd' +typeSound = b'snd ' +enumBooleanValues = b'boov' +kAETrue = typeTrue +kAEFalse = typeFalse +enumMiscValues = b'misc' +kASCurrentApplication = b'cura' +formUserPropertyID = b'usrp' + +cString = cStringClass + +pASIt = b'it ' +pASMe = b'me ' +pASResult = b'rslt' +pASSpace = b'spac' +pASReturn = b'ret ' +pASTab = b'tab ' +pASPi = b'pi ' +pASParent = b'pare' +kASInitializeEventCode = b'init' +pASPrintLength = b'prln' +pASPrintDepth = b'prdp' +pASTopLevelScript = b'ascr' + +kAECase = b'case' +kAEDiacritic = b'diac' +kAEWhiteSpace = b'whit' +kAEHyphens = b'hyph' +kAEExpansion = b'expa' +kAEPunctuation = b'punc' +kAEZenkakuHankaku = b'zkhk' +kAESmallKana = b'skna' +kAEKataHiragana = b'hika' +kASConsiderReplies = b'rmte' +kASNumericStrings = b'nume' +enumConsiderations = b'cons' + +kAECaseConsiderMask = 0x00000001 +kAEDiacriticConsiderMask = 0x00000002 +kAEWhiteSpaceConsiderMask = 0x00000004 +kAEHyphensConsiderMask = 0x00000008 +kAEExpansionConsiderMask = 0x00000010 +kAEPunctuationConsiderMask = 0x00000020 +kASConsiderRepliesConsiderMask = 0x00000040 +kASNumericStringsConsiderMask = 0x00000080 +kAECaseIgnoreMask = 0x00010000 +kAEDiacriticIgnoreMask = 0x00020000 +kAEWhiteSpaceIgnoreMask = 0x00040000 +kAEHyphensIgnoreMask = 0x00080000 +kAEExpansionIgnoreMask = 0x00100000 +kAEPunctuationIgnoreMask = 0x00200000 +kASConsiderRepliesIgnoreMask = 0x00400000 +kASNumericStringsIgnoreMask = 0x00800000 +enumConsidsAndIgnores = b'csig' + +cCoercion = b'coec' +cCoerceUpperCase = b'txup' +cCoerceLowerCase = b'txlo' +cCoerceRemoveDiacriticals = b'txdc' +cCoerceRemovePunctuation = b'txpc' +cCoerceRemoveHyphens = b'txhy' +cCoerceOneByteToTwoByte = b'txex' +cCoerceRemoveWhiteSpace = b'txws' +cCoerceSmallKana = b'txsk' +cCoerceZenkakuhankaku = b'txze' +cCoerceKataHiragana = b'txkh' +cZone = b'zone' +cMachine = b'mach' +cAddress = b'addr' +cRunningAddress = b'radd' +cStorage = b'stor' + +pASWeekday = b'wkdy' +pASMonth = b'mnth' +pASDay = b'day ' +pASYear = b'year' +pASTime = b'time' +pASDateString = b'dstr' +pASTimeString = b'tstr' +cMonth = pASMonth +cJanuary = b'jan ' +cFebruary = b'feb ' +cMarch = b'mar ' +cApril = b'apr ' +cMay = b'may ' +cJune = b'jun ' +cJuly = b'jul ' +cAugust = b'aug ' +cSeptember = b'sep ' +cOctober = b'oct ' +cNovember = b'nov ' +cDecember = b'dec ' + +cWeekday = pASWeekday +cSunday = b'sun ' +cMonday = b'mon ' +cTuesday = b'tue ' +cWednesday = b'wed ' +cThursday = b'thu ' +cFriday = b'fri ' +cSaturday = b'sat ' +pASQuote = b'quot' +pASSeconds = b'secs' +pASMinutes = b'min ' +pASHours = b'hour' +pASDays = b'days' +pASWeeks = b'week' +cWritingCodeInfo = b'citl' +pScriptCode = b'pscd' +pLangCode = b'plcd' +kASMagicTellEvent = b'tell' +kASMagicEndTellEvent = b'tend' + + + +# DigitalHubRegistry.h + +kDigiHubEventClass = b'dhub' + +kDigiHubMusicCD = b'aucd' +kDigiHubPictureCD = b'picd' +kDigiHubVideoDVD = b'vdvd' +kDigiHubBlankCD = b'bcd ' +kDigiHubBlankDVD = b'bdvd' + + + +# OSA.h + +kOSAComponentType = b'osa ' + +kOSAGenericScriptingComponentSubtype = b'scpt' + +kOSAFileType = b'osas' + +kOSASuite = b'ascr' + +kOSARecordedText = b'recd' + +kOSAScriptIsModified = b'modi' + +kOSAScriptIsTypeCompiledScript = b'cscr' + +kOSAScriptIsTypeScriptValue = b'valu' + +kOSAScriptIsTypeScriptContext = b'cntx' + +kOSAScriptBestType = b'best' + +kOSACanGetSource = b'gsrc' + +typeOSADialectInfo = b'difo' +keyOSADialectName = b'dnam' +keyOSADialectCode = b'dcod' +keyOSADialectLangCode = b'dlcd' +keyOSADialectScriptCode = b'dscd' + +kOSANullScript = 0 + +kOSANullMode = 0 +kOSAModeNull = 0 + +kOSASupportsCompiling = 0x0002 +kOSASupportsGetSource = 0x0004 +kOSASupportsAECoercion = 0x0008 +kOSASupportsAESending = 0x0010 +kOSASupportsRecording = 0x0020 +kOSASupportsConvenience = 0x0040 +kOSASupportsDialects = 0x0080 +kOSASupportsEventHandling = 0x0100 + +kOSASelectLoad = 0x0001 +kOSASelectStore = 0x0002 +kOSASelectExecute = 0x0003 +kOSASelectDisplay = 0x0004 +kOSASelectScriptError = 0x0005 +kOSASelectDispose = 0x0006 +kOSASelectSetScriptInfo = 0x0007 +kOSASelectGetScriptInfo = 0x0008 +kOSASelectSetActiveProc = 0x0009 +kOSASelectGetActiveProc = 0x000A +kOSASelectCopyDisplayString = 0x000B + +kOSASelectScriptingComponentName = 0x0102 +kOSASelectCompile = 0x0103 +kOSASelectCopyID = 0x0104 + +kOSASelectCopyScript = 0x0105 + +kOSASelectGetSource = 0x0201 +kOSASelectCopySourceString = 0x0202 + +kOSASelectCoerceFromDesc = 0x0301 +kOSASelectCoerceToDesc = 0x0302 + +kOSASelectSetSendProc = 0x0401 +kOSASelectGetSendProc = 0x0402 +kOSASelectSetCreateProc = 0x0403 +kOSASelectGetCreateProc = 0x0404 +kOSASelectSetDefaultTarget = 0x0405 + +kOSASelectStartRecording = 0x0501 +kOSASelectStopRecording = 0x0502 + +kOSASelectLoadExecute = 0x0601 +kOSASelectCompileExecute = 0x0602 +kOSASelectDoScript = 0x0603 + +kOSASelectSetCurrentDialect = 0x0701 +kOSASelectGetCurrentDialect = 0x0702 +kOSASelectAvailableDialects = 0x0703 +kOSASelectGetDialectInfo = 0x0704 +kOSASelectAvailableDialectCodeList = 0x0705 + +kOSASelectSetResumeDispatchProc = 0x0801 +kOSASelectGetResumeDispatchProc = 0x0802 +kOSASelectExecuteEvent = 0x0803 +kOSASelectDoEvent = 0x0804 +kOSASelectMakeContext = 0x0805 + +kOSASelectComponentSpecificStart = 0x1001 + +kOSAModePreventGetSource = 0x00000001 + +kOSAModeNeverInteract = kAENeverInteract +kOSAModeCanInteract = kAECanInteract +kOSAModeAlwaysInteract = kAEAlwaysInteract +kOSAModeDontReconnect = kAEDontReconnect + +kOSAModeCantSwitchLayer = 0x00000040 + +kOSAModeDoRecord = 0x00001000 + +kOSAModeCompileIntoContext = 0x00000002 + +kOSAModeAugmentContext = 0x00000004 + +kOSAModeDisplayForHumans = 0x00000008 + +kOSAModeDontStoreParent = 0x00010000 + +kOSAModeDispatchToDirectObject = 0x00020000 + +kOSAModeDontGetDataForArguments = 0x00040000 + +kOSAModeFullyQualifyDescriptors = 0x00080000 + +kOSAScriptResourceType = kOSAGenericScriptingComponentSubtype + +typeOSAGenericStorage = kOSAScriptResourceType + +kOSAErrorNumber = keyErrorNumber + +kOSAErrorMessage = keyErrorString + +kOSAErrorBriefMessage = b'errb' + +kOSAErrorApp = b'erap' + +kOSAErrorPartialResult = b'ptlr' + +kOSAErrorOffendingObject = b'erob' + +kOSAErrorExpectedType = b'errt' + +kOSAErrorRange = b'erng' + +typeOSAErrorRange = b'erng' + +keyOSASourceStart = b'srcs' + +keyOSASourceEnd = b'srce' + +kOSAUseStandardDispatch = kAEUseStandardDispatch + +kOSANoDispatch = kAENoDispatch + +kOSADontUsePhac = 0x0001 + + + +# OSAComp.h + + + +# OSAGeneric.h + +kGenericComponentVersion = 0x0100 + +kGSSSelectGetDefaultScriptingComponent = 0x1001 +kGSSSelectSetDefaultScriptingComponent = 0x1002 +kGSSSelectGetScriptingComponent = 0x1003 +kGSSSelectGetScriptingComponentFromStored = 0x1004 +kGSSSelectGenericToRealID = 0x1005 +kGSSSelectRealToGenericID = 0x1006 +kGSSSelectOutOfRange = 0x1007 + + + +# Miscellaneous + diff --git a/osxphotos/photoinfo.py b/osxphotos/photoinfo.py index 3bb2157f..63a405f5 100644 --- a/osxphotos/photoinfo.py +++ b/osxphotos/photoinfo.py @@ -16,13 +16,9 @@ from pprint import pformat import yaml -from ._constants import ( - _MOVIE_TYPE, - _PHOTO_TYPE, - _PHOTOS_5_SHARED_PHOTO_PATH, - _PHOTOS_5_VERSION, -) -from .utils import _get_resource_loc, dd_to_dms_str, _copy_file +from ._constants import (_MOVIE_TYPE, _PHOTO_TYPE, _PHOTOS_5_SHARED_PHOTO_PATH, + _PHOTOS_5_VERSION) +from .utils import _copy_file, _get_resource_loc, dd_to_dms_str # TODO: check pylint output @@ -140,6 +136,9 @@ class PhotoInfo: logging.debug(f"WARNING: unknown type {self._info['type']}") return None + # photopath appears to usually be in "00" subfolder but + # could be elsewhere--I haven't figured out this logic yet + # first see if it's in 00 photopath = os.path.join( library, "resources", @@ -149,6 +148,21 @@ class PhotoInfo: "00", filename, ) + + if not os.path.isfile(photopath): + rootdir = os.path.join( + library, + "resources", + "media", + "version", + folder_id) + + for dirname, _, filelist in os.walk(rootdir): + if filename in filelist: + photopath = os.path.join(dirname, filename) + break + + # check again to see if we found a valid file if not os.path.isfile(photopath): logging.warning( f"MISSING PATH: edited file for UUID {self._uuid} should be at {photopath} but does not appear to exist" @@ -424,17 +438,22 @@ class PhotoInfo: overwrite=False, increment=True, sidecar=False, + use_photos_export=False, + timeout=120, ): - """ export photo """ - """ first argument must be valid destination path (or exception raised) """ - """ second argument (optional): name of picture; if not provided, will use current filename """ - """ if edited=True (default=False), will export the edited version of the photo (or raise exception if no edited version) """ - """ if overwrite=True (default=False), will overwrite files if they alreay exist """ - """ if increment=True (default=True), will increment file name until a non-existant name is found """ - """ if overwrite=False and increment=False, export will fail if destination file already exists """ - """ if sidecar=True, will also write a json sidecar with EXIF data in format readable by exiftool """ - """ sidecar filename will be dest/filename.ext.json where ext is suffix of the image file (e.g. jpeg or jpg) """ - """ returns the full path to the exported file """ + """ export photo + dest: must be valid destination path (or exception raised) + filename: (optional): name of picture; if not provided, will use current filename + edited: (boolean, default=False); if True will export the edited version of the photo + (or raise exception if no edited version) + overwrite: (boolean, default=False); if True will overwrite files if they alreay exist + increment: (boolean, default=True); if True, will increment file name until a non-existant name is found + if overwrite=False and increment=False, export will fail if destination file already exists + sidecar: (boolean, default = False); if True will also write a json sidecar with EXIF data in format readable by exiftool + sidecar filename will be dest/filename.ext.json where ext is suffix of the image file (e.g. jpeg or jpg) + use_photos_export: (boolean, default=False); if True will attempt to export photo via applescript interaction with Photos + timeout: (int, default=120) timeout in seconds used with use_photos_export + returns the full path to the exported file """ # TODO: add this docs: # ( for jpeg in *.jpeg; do exiftool -v -json=$jpeg.json $jpeg; done ) diff --git a/osxphotos/utils.py b/osxphotos/utils.py index 2c201ad3..ff12ae27 100644 --- a/osxphotos/utils.py +++ b/osxphotos/utils.py @@ -3,6 +3,7 @@ import logging import os.path import platform import subprocess +import tempfile import urllib.parse from pathlib import Path from plistlib import load as plistload @@ -11,6 +12,8 @@ import CoreFoundation import objc from Foundation import * +from osxphotos._applescript import AppleScript + _DEBUG = False @@ -284,3 +287,70 @@ def create_path_by_date(dest, dt): if not os.path.isdir(new_dest): os.makedirs(new_dest) return new_dest + + +def _export_photo_uuid_applescript( + uuid, dest, original=True, edited=False, timeout=120 +): + """ Export photo to dest path using applescript to control Photos + uuid: UUID of photo to export + dest: destination path to export to; may be either a directory or a filename + if filename provided and file exists, exiting file will be overwritten + original: (boolean) if True, export original image; default = True + edited: (boolean) if True, export edited photo; default = False + will produce an error if image does not have edits/adjustments + timeout: timeout value in seconds; export will fail if applescript run time exceeds timeout + """ + + # setup the applescript to do the export + export_scpt = AppleScript( + """ + on export_by_uuid(theUUID, thePath, original, edited, theTimeOut) + tell application "Photos" + activate + set thePath to thePath + set theItem to media item id theUUID + set theFilename to filename of theItem + set itemList to {theItem} + + if original then + with timeout of theTimeOut seconds + export itemList to POSIX file thePath with using originals + end timeout + end if + + if edited then + with timeout of theTimeOut seconds + export itemList to POSIX file thePath + end timeout + end if + + return theFilename + end tell + + end export_by_uuid + """ + ) + + tmpdir = tempfile.TemporaryDirectory(prefix="osxphotos_") + + # export original + filename = None + try: + filename = export_scpt.call( + "export_by_uuid", uuid, tmpdir.name, original, edited, timeout + ) + except Exception as e: + logging.warning("Error exporting uuid %s: %s" % (uuid, str(e))) + return None + + if filename is not None: + path = os.path.join(tmpdir.name, filename) + _copy_file(path, dest) + if os.path.isdir(dest): + new_path = os.path.join(dest, filename) + else: + new_path = dest + return new_path + else: + return None diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/Masters/2019/07/27/20190727-131650/Pumkins1.jpg b/tests/Test-10.14.6-path_edited.photoslibrary/Masters/2019/07/27/20190727-131650/Pumkins1.jpg new file mode 100644 index 00000000..3748a6b4 Binary files /dev/null and b/tests/Test-10.14.6-path_edited.photoslibrary/Masters/2019/07/27/20190727-131650/Pumkins1.jpg differ diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/Masters/2019/07/27/20190727-131650/Pumkins2.jpg b/tests/Test-10.14.6-path_edited.photoslibrary/Masters/2019/07/27/20190727-131650/Pumkins2.jpg new file mode 100644 index 00000000..4d88368a Binary files /dev/null and b/tests/Test-10.14.6-path_edited.photoslibrary/Masters/2019/07/27/20190727-131650/Pumkins2.jpg differ diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/Masters/2019/07/27/20190727-131650/Pumpkins3.jpg b/tests/Test-10.14.6-path_edited.photoslibrary/Masters/2019/07/27/20190727-131650/Pumpkins3.jpg new file mode 100644 index 00000000..775207c8 Binary files /dev/null and b/tests/Test-10.14.6-path_edited.photoslibrary/Masters/2019/07/27/20190727-131650/Pumpkins3.jpg differ diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/Masters/2019/07/27/20190727-131650/St James Park.jpg b/tests/Test-10.14.6-path_edited.photoslibrary/Masters/2019/07/27/20190727-131650/St James Park.jpg new file mode 100644 index 00000000..494d60de Binary files /dev/null and b/tests/Test-10.14.6-path_edited.photoslibrary/Masters/2019/07/27/20190727-131650/St James Park.jpg differ diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/Masters/2019/07/27/20190727-131650/Tulips.jpg b/tests/Test-10.14.6-path_edited.photoslibrary/Masters/2019/07/27/20190727-131650/Tulips.jpg new file mode 100644 index 00000000..3f09e25b Binary files /dev/null and b/tests/Test-10.14.6-path_edited.photoslibrary/Masters/2019/07/27/20190727-131650/Tulips.jpg differ diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/Masters/2019/07/27/20190727-131650/wedding.jpg b/tests/Test-10.14.6-path_edited.photoslibrary/Masters/2019/07/27/20190727-131650/wedding.jpg new file mode 100644 index 00000000..5f29bd3f Binary files /dev/null and b/tests/Test-10.14.6-path_edited.photoslibrary/Masters/2019/07/27/20190727-131650/wedding.jpg differ diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/database/DataModelVersion.plist b/tests/Test-10.14.6-path_edited.photoslibrary/database/DataModelVersion.plist new file mode 100644 index 00000000..8b86b773 --- /dev/null +++ b/tests/Test-10.14.6-path_edited.photoslibrary/database/DataModelVersion.plist @@ -0,0 +1,18 @@ + + + + + DatabaseMinorVersion + 1 + DatabaseVersion + 112 + LastOpenMode + 2 + LibrarySchemaVersion + 4025 + MetaSchemaVersion + 2 + createDate + 2019-07-27T13:16:43Z + + diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/database/RKAlbum_name.skindex b/tests/Test-10.14.6-path_edited.photoslibrary/database/RKAlbum_name.skindex new file mode 100644 index 00000000..005f905f Binary files /dev/null and b/tests/Test-10.14.6-path_edited.photoslibrary/database/RKAlbum_name.skindex differ diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/database/RKMemory_title.skindex b/tests/Test-10.14.6-path_edited.photoslibrary/database/RKMemory_title.skindex new file mode 100644 index 00000000..e407c663 Binary files /dev/null and b/tests/Test-10.14.6-path_edited.photoslibrary/database/RKMemory_title.skindex differ diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/database/RKVersion_searchIndexText.skindex b/tests/Test-10.14.6-path_edited.photoslibrary/database/RKVersion_searchIndexText.skindex new file mode 100644 index 00000000..7de13426 Binary files /dev/null and b/tests/Test-10.14.6-path_edited.photoslibrary/database/RKVersion_searchIndexText.skindex differ diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/database/metaSchema.db b/tests/Test-10.14.6-path_edited.photoslibrary/database/metaSchema.db new file mode 100644 index 00000000..a69a92eb Binary files /dev/null and b/tests/Test-10.14.6-path_edited.photoslibrary/database/metaSchema.db differ diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/database/photos (Rhets-MacBook-Pro.local's conflicted copy 2019-12-07).db-wal b/tests/Test-10.14.6-path_edited.photoslibrary/database/photos (Rhets-MacBook-Pro.local's conflicted copy 2019-12-07).db-wal new file mode 100644 index 00000000..e69de29b diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/database/photos.db b/tests/Test-10.14.6-path_edited.photoslibrary/database/photos.db new file mode 100644 index 00000000..83637f49 Binary files /dev/null and b/tests/Test-10.14.6-path_edited.photoslibrary/database/photos.db differ diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/database/photos.db-wal b/tests/Test-10.14.6-path_edited.photoslibrary/database/photos.db-wal new file mode 100644 index 00000000..e69de29b diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/private/.metadata_never_index b/tests/Test-10.14.6-path_edited.photoslibrary/private/.metadata_never_index new file mode 100644 index 00000000..e69de29b diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/private/com.apple.Photos/appPrivateData.plist b/tests/Test-10.14.6-path_edited.photoslibrary/private/com.apple.Photos/appPrivateData.plist new file mode 100644 index 00000000..a5cdd9c2 --- /dev/null +++ b/tests/Test-10.14.6-path_edited.photoslibrary/private/com.apple.Photos/appPrivateData.plist @@ -0,0 +1,43 @@ + + + + + Photos + + CollapsedSidebarSectionIdentifiers + + ExpandedSidebarItemIdentifiers + + TopLevelAlbums + TopLevelSlideshows + + IPXWorkspaceControllerZoomLevelsKey + + kZoomLevelIdentifierAlbums + 10 + kZoomLevelIdentifierVersions + 7 + + lastAddToDestination + + key + 1 + lastKnownDisplayName + Test Album (1) + type + album + uuid + Uq6qsKihRRSjMHTiD+0Azg + + lastKnownItemCounts + + other + 0 + photos + 6 + videos + 0 + + + + diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/private/com.apple.photoanalysisd/GraphService/PhotoAnalysisServicePreferences.plist b/tests/Test-10.14.6-path_edited.photoslibrary/private/com.apple.photoanalysisd/GraphService/PhotoAnalysisServicePreferences.plist new file mode 100644 index 00000000..152956d7 --- /dev/null +++ b/tests/Test-10.14.6-path_edited.photoslibrary/private/com.apple.photoanalysisd/GraphService/PhotoAnalysisServicePreferences.plist @@ -0,0 +1,10 @@ + + + + + PhotoAnalysisGraphLastBackgroundGraphRebuildJobDate + 2020-01-11T16:41:00Z + PhotoAnalysisGraphLastBackgroundMemoryGenerationJobDate + 2020-01-12T06:02:45Z + + diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/private/com.apple.photoanalysisd/GraphService/PhotosGraph/construction-photosgraph.graphdb b/tests/Test-10.14.6-path_edited.photoslibrary/private/com.apple.photoanalysisd/GraphService/PhotosGraph/construction-photosgraph.graphdb new file mode 100644 index 00000000..96fee1ce Binary files /dev/null and b/tests/Test-10.14.6-path_edited.photoslibrary/private/com.apple.photoanalysisd/GraphService/PhotosGraph/construction-photosgraph.graphdb differ diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/private/com.apple.photoanalysisd/GraphService/PhotosGraph/construction-photosgraph.graphdb-shm b/tests/Test-10.14.6-path_edited.photoslibrary/private/com.apple.photoanalysisd/GraphService/PhotosGraph/construction-photosgraph.graphdb-shm new file mode 100644 index 00000000..fe9ac284 Binary files /dev/null and b/tests/Test-10.14.6-path_edited.photoslibrary/private/com.apple.photoanalysisd/GraphService/PhotosGraph/construction-photosgraph.graphdb-shm differ diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/private/com.apple.photoanalysisd/GraphService/PhotosGraph/construction-photosgraph.graphdb-wal b/tests/Test-10.14.6-path_edited.photoslibrary/private/com.apple.photoanalysisd/GraphService/PhotosGraph/construction-photosgraph.graphdb-wal new file mode 100644 index 00000000..e69de29b diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/private/com.apple.photoanalysisd/GraphService/PhotosGraph/liveupdate-photosgraph.graphdb b/tests/Test-10.14.6-path_edited.photoslibrary/private/com.apple.photoanalysisd/GraphService/PhotosGraph/liveupdate-photosgraph.graphdb new file mode 100644 index 00000000..68b388ea Binary files /dev/null and b/tests/Test-10.14.6-path_edited.photoslibrary/private/com.apple.photoanalysisd/GraphService/PhotosGraph/liveupdate-photosgraph.graphdb differ diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/private/com.apple.photoanalysisd/GraphService/PhotosGraph/liveupdate-photosgraph.graphdb-shm b/tests/Test-10.14.6-path_edited.photoslibrary/private/com.apple.photoanalysisd/GraphService/PhotosGraph/liveupdate-photosgraph.graphdb-shm new file mode 100644 index 00000000..fe9ac284 Binary files /dev/null and b/tests/Test-10.14.6-path_edited.photoslibrary/private/com.apple.photoanalysisd/GraphService/PhotosGraph/liveupdate-photosgraph.graphdb-shm differ diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/private/com.apple.photoanalysisd/GraphService/PhotosGraph/liveupdate-photosgraph.graphdb-wal b/tests/Test-10.14.6-path_edited.photoslibrary/private/com.apple.photoanalysisd/GraphService/PhotosGraph/liveupdate-photosgraph.graphdb-wal new file mode 100644 index 00000000..e69de29b diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/private/com.apple.photoanalysisd/GraphService/PhotosGraph/photosgraph-tmp.graphdb b/tests/Test-10.14.6-path_edited.photoslibrary/private/com.apple.photoanalysisd/GraphService/PhotosGraph/photosgraph-tmp.graphdb new file mode 100644 index 00000000..96fee1ce Binary files /dev/null and b/tests/Test-10.14.6-path_edited.photoslibrary/private/com.apple.photoanalysisd/GraphService/PhotosGraph/photosgraph-tmp.graphdb differ diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/private/com.apple.photoanalysisd/GraphService/PhotosGraph/photosgraph-tmp.graphdb-shm b/tests/Test-10.14.6-path_edited.photoslibrary/private/com.apple.photoanalysisd/GraphService/PhotosGraph/photosgraph-tmp.graphdb-shm new file mode 100644 index 00000000..fe9ac284 Binary files /dev/null and b/tests/Test-10.14.6-path_edited.photoslibrary/private/com.apple.photoanalysisd/GraphService/PhotosGraph/photosgraph-tmp.graphdb-shm differ diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/private/com.apple.photoanalysisd/GraphService/PhotosGraph/photosgraph-tmp.graphdb-wal b/tests/Test-10.14.6-path_edited.photoslibrary/private/com.apple.photoanalysisd/GraphService/PhotosGraph/photosgraph-tmp.graphdb-wal new file mode 100644 index 00000000..e69de29b diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/private/com.apple.photoanalysisd/GraphService/PhotosGraph/photosgraph.graphdb b/tests/Test-10.14.6-path_edited.photoslibrary/private/com.apple.photoanalysisd/GraphService/PhotosGraph/photosgraph.graphdb new file mode 100644 index 00000000..5dadb7c8 Binary files /dev/null and b/tests/Test-10.14.6-path_edited.photoslibrary/private/com.apple.photoanalysisd/GraphService/PhotosGraph/photosgraph.graphdb differ diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/private/com.apple.photoanalysisd/GraphService/PhotosGraph/photosgraph.graphdb-shm b/tests/Test-10.14.6-path_edited.photoslibrary/private/com.apple.photoanalysisd/GraphService/PhotosGraph/photosgraph.graphdb-shm new file mode 100644 index 00000000..fe9ac284 Binary files /dev/null and b/tests/Test-10.14.6-path_edited.photoslibrary/private/com.apple.photoanalysisd/GraphService/PhotosGraph/photosgraph.graphdb-shm differ diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/private/com.apple.photoanalysisd/GraphService/PhotosGraph/photosgraph.graphdb-wal b/tests/Test-10.14.6-path_edited.photoslibrary/private/com.apple.photoanalysisd/GraphService/PhotosGraph/photosgraph.graphdb-wal new file mode 100644 index 00000000..e69de29b diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/private/com.apple.photoanalysisd/VisionService/2E578BF2-718A-43E1-81BA-80AC61004DCF.cmap b/tests/Test-10.14.6-path_edited.photoslibrary/private/com.apple.photoanalysisd/VisionService/2E578BF2-718A-43E1-81BA-80AC61004DCF.cmap new file mode 100644 index 00000000..4aaf1638 Binary files /dev/null and b/tests/Test-10.14.6-path_edited.photoslibrary/private/com.apple.photoanalysisd/VisionService/2E578BF2-718A-43E1-81BA-80AC61004DCF.cmap differ diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/private/com.apple.photoanalysisd/VisionService/AlgoFaceClusterCache.data b/tests/Test-10.14.6-path_edited.photoslibrary/private/com.apple.photoanalysisd/VisionService/AlgoFaceClusterCache.data new file mode 100644 index 00000000..1f14d535 Binary files /dev/null and b/tests/Test-10.14.6-path_edited.photoslibrary/private/com.apple.photoanalysisd/VisionService/AlgoFaceClusterCache.data differ diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/private/com.apple.photoanalysisd/VisionService/C7589FFF-A378-4059-ABDC-19C4316A8B69.cmap b/tests/Test-10.14.6-path_edited.photoslibrary/private/com.apple.photoanalysisd/VisionService/C7589FFF-A378-4059-ABDC-19C4316A8B69.cmap new file mode 100644 index 00000000..1d6b6446 Binary files /dev/null and b/tests/Test-10.14.6-path_edited.photoslibrary/private/com.apple.photoanalysisd/VisionService/C7589FFF-A378-4059-ABDC-19C4316A8B69.cmap differ diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/private/com.apple.photoanalysisd/VisionService/PersonPromoter b/tests/Test-10.14.6-path_edited.photoslibrary/private/com.apple.photoanalysisd/VisionService/PersonPromoter new file mode 100644 index 00000000..4fdc85b4 --- /dev/null +++ b/tests/Test-10.14.6-path_edited.photoslibrary/private/com.apple.photoanalysisd/VisionService/PersonPromoter @@ -0,0 +1,12 @@ + + + + + ProcessedInQuiescentState + + SuggestedMeIdentifier + + Version + 3 + + diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/private/com.apple.photoanalysisd/VisionService/clustererState.plist b/tests/Test-10.14.6-path_edited.photoslibrary/private/com.apple.photoanalysisd/VisionService/clustererState.plist new file mode 100644 index 00000000..cb4560b6 --- /dev/null +++ b/tests/Test-10.14.6-path_edited.photoslibrary/private/com.apple.photoanalysisd/VisionService/clustererState.plist @@ -0,0 +1,8 @@ + + + + + PVClustererBringUpState + 50 + + diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/private/com.apple.photoanalysisd/VisionService/faceWorkerState.plist b/tests/Test-10.14.6-path_edited.photoslibrary/private/com.apple.photoanalysisd/VisionService/faceWorkerState.plist new file mode 100644 index 00000000..736db69d --- /dev/null +++ b/tests/Test-10.14.6-path_edited.photoslibrary/private/com.apple.photoanalysisd/VisionService/faceWorkerState.plist @@ -0,0 +1,12 @@ + + + + + IncrementalPersonProcessingStage + 0 + PersonBuilderLastMinimumFaceGroupSizeForCreatingMergeCandidates + 15 + PersonBuilderMergeCandidatesEnabled + + + diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/private/com.apple.photomodel/appPrivateData.plist b/tests/Test-10.14.6-path_edited.photoslibrary/private/com.apple.photomodel/appPrivateData.plist new file mode 100644 index 00000000..808541b5 --- /dev/null +++ b/tests/Test-10.14.6-path_edited.photoslibrary/private/com.apple.photomodel/appPrivateData.plist @@ -0,0 +1,11 @@ + + + + + LithiumMessageTracer + + LastReportedDate + 2020-01-04T18:29:59Z + + + diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/resources/.metadata_never_index b/tests/Test-10.14.6-path_edited.photoslibrary/resources/.metadata_never_index new file mode 100644 index 00000000..e69de29b diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/resources/media/face/00/00/facetile_1.jpeg b/tests/Test-10.14.6-path_edited.photoslibrary/resources/media/face/00/00/facetile_1.jpeg new file mode 100644 index 00000000..f39a1ec8 Binary files /dev/null and b/tests/Test-10.14.6-path_edited.photoslibrary/resources/media/face/00/00/facetile_1.jpeg differ diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/resources/media/face/00/00/facetile_2.jpeg b/tests/Test-10.14.6-path_edited.photoslibrary/resources/media/face/00/00/facetile_2.jpeg new file mode 100644 index 00000000..4ac5f4ed Binary files /dev/null and b/tests/Test-10.14.6-path_edited.photoslibrary/resources/media/face/00/00/facetile_2.jpeg differ diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/resources/media/face/00/00/facetile_3.jpeg b/tests/Test-10.14.6-path_edited.photoslibrary/resources/media/face/00/00/facetile_3.jpeg new file mode 100644 index 00000000..78bc1973 Binary files /dev/null and b/tests/Test-10.14.6-path_edited.photoslibrary/resources/media/face/00/00/facetile_3.jpeg differ diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/resources/media/face/00/00/facetile_4.jpeg b/tests/Test-10.14.6-path_edited.photoslibrary/resources/media/face/00/00/facetile_4.jpeg new file mode 100644 index 00000000..44d120e7 Binary files /dev/null and b/tests/Test-10.14.6-path_edited.photoslibrary/resources/media/face/00/00/facetile_4.jpeg differ diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/resources/media/face/00/00/facetile_5.jpeg b/tests/Test-10.14.6-path_edited.photoslibrary/resources/media/face/00/00/facetile_5.jpeg new file mode 100644 index 00000000..908ac7f3 Binary files /dev/null and b/tests/Test-10.14.6-path_edited.photoslibrary/resources/media/face/00/00/facetile_5.jpeg differ diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/resources/media/face/00/00/facetile_7.jpeg b/tests/Test-10.14.6-path_edited.photoslibrary/resources/media/face/00/00/facetile_7.jpeg new file mode 100644 index 00000000..4a892442 Binary files /dev/null and b/tests/Test-10.14.6-path_edited.photoslibrary/resources/media/face/00/00/facetile_7.jpeg differ diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/resources/media/face/00/00/facetile_a.jpeg b/tests/Test-10.14.6-path_edited.photoslibrary/resources/media/face/00/00/facetile_a.jpeg new file mode 100644 index 00000000..75bd69d7 Binary files /dev/null and b/tests/Test-10.14.6-path_edited.photoslibrary/resources/media/face/00/00/facetile_a.jpeg differ diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/resources/media/version/00/00/fullsizeinput_c.jpeg b/tests/Test-10.14.6-path_edited.photoslibrary/resources/media/version/00/00/fullsizeinput_c.jpeg new file mode 100644 index 00000000..30704a41 Binary files /dev/null and b/tests/Test-10.14.6-path_edited.photoslibrary/resources/media/version/00/00/fullsizeinput_c.jpeg differ diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/resources/media/version/00/00/fullsizeoutput_d.jpeg b/tests/Test-10.14.6-path_edited.photoslibrary/resources/media/version/00/00/fullsizeoutput_d.jpeg new file mode 100644 index 00000000..088893a9 Binary files /dev/null and b/tests/Test-10.14.6-path_edited.photoslibrary/resources/media/version/00/00/fullsizeoutput_d.jpeg differ diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/resources/media/version/00/02/fullsizeoutput_9.jpeg b/tests/Test-10.14.6-path_edited.photoslibrary/resources/media/version/00/02/fullsizeoutput_9.jpeg new file mode 100644 index 00000000..88caa537 Binary files /dev/null and b/tests/Test-10.14.6-path_edited.photoslibrary/resources/media/version/00/02/fullsizeoutput_9.jpeg differ diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/resources/moments/analysismetadata.plist b/tests/Test-10.14.6-path_edited.photoslibrary/resources/moments/analysismetadata.plist new file mode 100644 index 00000000..6253636a --- /dev/null +++ b/tests/Test-10.14.6-path_edited.photoslibrary/resources/moments/analysismetadata.plist @@ -0,0 +1,16 @@ + + + + + PLLanguageAndLocaleKey + en-US:en_US + PLLastGeoProviderIdKey + 7618 + PLLastLocationInfoFormatVer + 12 + PLLastRevGeoForcedProviderOutOfDateCheckVersionKey + 1 + PLLastRevGeoVerFileFetchDateKey + 2020-01-11T16:40:56Z + + diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/resources/moments/historicalmarker.plist b/tests/Test-10.14.6-path_edited.photoslibrary/resources/moments/historicalmarker.plist new file mode 100644 index 00000000..89349855 --- /dev/null +++ b/tests/Test-10.14.6-path_edited.photoslibrary/resources/moments/historicalmarker.plist @@ -0,0 +1,12 @@ + + + + + LastHistoryRowId + 575 + LibraryBuildTag + D8C4AAA1-3AB6-4A65-BEBD-99CC3E5D433E + LibrarySchemaVersion + 4025 + + diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/resources/moments/needsanalysis b/tests/Test-10.14.6-path_edited.photoslibrary/resources/moments/needsanalysis new file mode 100644 index 00000000..e69de29b diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/resources/moments/serverinfo.plist b/tests/Test-10.14.6-path_edited.photoslibrary/resources/moments/serverinfo.plist new file mode 100644 index 00000000..ce9edee3 --- /dev/null +++ b/tests/Test-10.14.6-path_edited.photoslibrary/resources/moments/serverinfo.plist @@ -0,0 +1,47 @@ + + + + + FileVersion + 11 + Source + + 35230 + + CountryMinVersions + + OTHER + 1 + + CurrentVersion + 1 + NoResultErrorIsSuccess + + + 57879 + + CountryMinVersions + + OTHER + 1 + + CurrentVersion + 1 + NoResultErrorIsSuccess + + + 7618 + + AddCountyIfNeeded + + CountryMinVersions + + OTHER + 10 + + CurrentVersion + 10 + + + + diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/resources/proxies/derivatives/00/00/1/Y6OofYkbR96spbS6XgwOQw_mini_1.jpg b/tests/Test-10.14.6-path_edited.photoslibrary/resources/proxies/derivatives/00/00/1/Y6OofYkbR96spbS6XgwOQw_mini_1.jpg new file mode 100644 index 00000000..30e71540 Binary files /dev/null and b/tests/Test-10.14.6-path_edited.photoslibrary/resources/proxies/derivatives/00/00/1/Y6OofYkbR96spbS6XgwOQw_mini_1.jpg differ diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/resources/proxies/derivatives/00/00/1/Y6OofYkbR96spbS6XgwOQw_thumb_1.jpg b/tests/Test-10.14.6-path_edited.photoslibrary/resources/proxies/derivatives/00/00/1/Y6OofYkbR96spbS6XgwOQw_thumb_1.jpg new file mode 100644 index 00000000..db88ba04 Binary files /dev/null and b/tests/Test-10.14.6-path_edited.photoslibrary/resources/proxies/derivatives/00/00/1/Y6OofYkbR96spbS6XgwOQw_thumb_1.jpg differ diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/resources/proxies/derivatives/00/00/2/UNADJUSTEDNONRAW_mini_2.jpg b/tests/Test-10.14.6-path_edited.photoslibrary/resources/proxies/derivatives/00/00/2/UNADJUSTEDNONRAW_mini_2.jpg new file mode 100644 index 00000000..8c8e178d Binary files /dev/null and b/tests/Test-10.14.6-path_edited.photoslibrary/resources/proxies/derivatives/00/00/2/UNADJUSTEDNONRAW_mini_2.jpg differ diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/resources/proxies/derivatives/00/00/2/UNADJUSTEDNONRAW_thumb_2.jpg b/tests/Test-10.14.6-path_edited.photoslibrary/resources/proxies/derivatives/00/00/2/UNADJUSTEDNONRAW_thumb_2.jpg new file mode 100644 index 00000000..8a612cdc Binary files /dev/null and b/tests/Test-10.14.6-path_edited.photoslibrary/resources/proxies/derivatives/00/00/2/UNADJUSTEDNONRAW_thumb_2.jpg differ diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/resources/proxies/derivatives/00/00/3/UNADJUSTEDNONRAW_mini_3.jpg b/tests/Test-10.14.6-path_edited.photoslibrary/resources/proxies/derivatives/00/00/3/UNADJUSTEDNONRAW_mini_3.jpg new file mode 100644 index 00000000..0549fb7f Binary files /dev/null and b/tests/Test-10.14.6-path_edited.photoslibrary/resources/proxies/derivatives/00/00/3/UNADJUSTEDNONRAW_mini_3.jpg differ diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/resources/proxies/derivatives/00/00/3/UNADJUSTEDNONRAW_thumb_3.jpg b/tests/Test-10.14.6-path_edited.photoslibrary/resources/proxies/derivatives/00/00/3/UNADJUSTEDNONRAW_thumb_3.jpg new file mode 100644 index 00000000..4f0c1479 Binary files /dev/null and b/tests/Test-10.14.6-path_edited.photoslibrary/resources/proxies/derivatives/00/00/3/UNADJUSTEDNONRAW_thumb_3.jpg differ diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/resources/proxies/derivatives/00/00/4/UNADJUSTEDNONRAW_mini_4.jpg b/tests/Test-10.14.6-path_edited.photoslibrary/resources/proxies/derivatives/00/00/4/UNADJUSTEDNONRAW_mini_4.jpg new file mode 100644 index 00000000..095ef4d1 Binary files /dev/null and b/tests/Test-10.14.6-path_edited.photoslibrary/resources/proxies/derivatives/00/00/4/UNADJUSTEDNONRAW_mini_4.jpg differ diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/resources/proxies/derivatives/00/00/4/UNADJUSTEDNONRAW_thumb_4.jpg b/tests/Test-10.14.6-path_edited.photoslibrary/resources/proxies/derivatives/00/00/4/UNADJUSTEDNONRAW_thumb_4.jpg new file mode 100644 index 00000000..6881aa31 Binary files /dev/null and b/tests/Test-10.14.6-path_edited.photoslibrary/resources/proxies/derivatives/00/00/4/UNADJUSTEDNONRAW_thumb_4.jpg differ diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/resources/proxies/derivatives/00/00/5/UNADJUSTEDNONRAW_mini_5.jpg b/tests/Test-10.14.6-path_edited.photoslibrary/resources/proxies/derivatives/00/00/5/UNADJUSTEDNONRAW_mini_5.jpg new file mode 100644 index 00000000..7929d77d Binary files /dev/null and b/tests/Test-10.14.6-path_edited.photoslibrary/resources/proxies/derivatives/00/00/5/UNADJUSTEDNONRAW_mini_5.jpg differ diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/resources/proxies/derivatives/00/00/5/UNADJUSTEDNONRAW_thumb_5.jpg b/tests/Test-10.14.6-path_edited.photoslibrary/resources/proxies/derivatives/00/00/5/UNADJUSTEDNONRAW_thumb_5.jpg new file mode 100644 index 00000000..df6e6345 Binary files /dev/null and b/tests/Test-10.14.6-path_edited.photoslibrary/resources/proxies/derivatives/00/00/5/UNADJUSTEDNONRAW_thumb_5.jpg differ diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/resources/proxies/derivatives/00/00/6/yd1KuwTpRaSh3At8YfJ7OQ_mini_6.jpg b/tests/Test-10.14.6-path_edited.photoslibrary/resources/proxies/derivatives/00/00/6/yd1KuwTpRaSh3At8YfJ7OQ_mini_6.jpg new file mode 100644 index 00000000..226d337d Binary files /dev/null and b/tests/Test-10.14.6-path_edited.photoslibrary/resources/proxies/derivatives/00/00/6/yd1KuwTpRaSh3At8YfJ7OQ_mini_6.jpg differ diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/resources/proxies/derivatives/00/00/6/yd1KuwTpRaSh3At8YfJ7OQ_thumb_6.jpg b/tests/Test-10.14.6-path_edited.photoslibrary/resources/proxies/derivatives/00/00/6/yd1KuwTpRaSh3At8YfJ7OQ_thumb_6.jpg new file mode 100644 index 00000000..85c0fbd5 Binary files /dev/null and b/tests/Test-10.14.6-path_edited.photoslibrary/resources/proxies/derivatives/00/00/6/yd1KuwTpRaSh3At8YfJ7OQ_thumb_6.jpg differ diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/resources/proxies/derivatives/00/00/7/UNADJUSTEDNONRAW_mini_7.jpg b/tests/Test-10.14.6-path_edited.photoslibrary/resources/proxies/derivatives/00/00/7/UNADJUSTEDNONRAW_mini_7.jpg new file mode 100644 index 00000000..15403b4d Binary files /dev/null and b/tests/Test-10.14.6-path_edited.photoslibrary/resources/proxies/derivatives/00/00/7/UNADJUSTEDNONRAW_mini_7.jpg differ diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/resources/proxies/derivatives/00/00/7/UNADJUSTEDNONRAW_thumb_7.jpg b/tests/Test-10.14.6-path_edited.photoslibrary/resources/proxies/derivatives/00/00/7/UNADJUSTEDNONRAW_thumb_7.jpg new file mode 100644 index 00000000..f8943c5c Binary files /dev/null and b/tests/Test-10.14.6-path_edited.photoslibrary/resources/proxies/derivatives/00/00/7/UNADJUSTEDNONRAW_thumb_7.jpg differ diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/resources/recovery/Info.plist b/tests/Test-10.14.6-path_edited.photoslibrary/resources/recovery/Info.plist new file mode 100644 index 00000000..8cac64ba --- /dev/null +++ b/tests/Test-10.14.6-path_edited.photoslibrary/resources/recovery/Info.plist @@ -0,0 +1,31 @@ + + + + + DatabaseMinorVersion + 1 + DatabaseVersion + 112 + HistoricalMarker + + LastHistoryRowId + 575 + LibraryBuildTag + D8C4AAA1-3AB6-4A65-BEBD-99CC3E5D433E + LibrarySchemaVersion + 4025 + + LibrarySchemaVersion + 4025 + MetaSchemaVersion + 2 + SnapshotComplete + + SnapshotCompletedDate + 2019-07-27T13:16:43Z + SnapshotLastValidated + 2020-01-12T06:04:41Z + SnapshotTables + + + diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/resources/recovery/RKAdjustmentData/0000000000.lij b/tests/Test-10.14.6-path_edited.photoslibrary/resources/recovery/RKAdjustmentData/0000000000.lij new file mode 100644 index 00000000..64aa5fb3 Binary files /dev/null and b/tests/Test-10.14.6-path_edited.photoslibrary/resources/recovery/RKAdjustmentData/0000000000.lij differ diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/resources/recovery/RKAdminData/0000000000.lij b/tests/Test-10.14.6-path_edited.photoslibrary/resources/recovery/RKAdminData/0000000000.lij new file mode 100644 index 00000000..65290a1f Binary files /dev/null and b/tests/Test-10.14.6-path_edited.photoslibrary/resources/recovery/RKAdminData/0000000000.lij differ diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/resources/recovery/RKAlbum/0000000000.lij b/tests/Test-10.14.6-path_edited.photoslibrary/resources/recovery/RKAlbum/0000000000.lij new file mode 100644 index 00000000..709d4fd4 Binary files /dev/null and b/tests/Test-10.14.6-path_edited.photoslibrary/resources/recovery/RKAlbum/0000000000.lij differ diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/resources/recovery/RKAlbumVersion/0000000000.lij b/tests/Test-10.14.6-path_edited.photoslibrary/resources/recovery/RKAlbumVersion/0000000000.lij new file mode 100644 index 00000000..90d13f94 Binary files /dev/null and b/tests/Test-10.14.6-path_edited.photoslibrary/resources/recovery/RKAlbumVersion/0000000000.lij differ diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/resources/recovery/RKBookmark/0000000000.lij b/tests/Test-10.14.6-path_edited.photoslibrary/resources/recovery/RKBookmark/0000000000.lij new file mode 100644 index 00000000..88d7f509 Binary files /dev/null and b/tests/Test-10.14.6-path_edited.photoslibrary/resources/recovery/RKBookmark/0000000000.lij differ diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/resources/recovery/RKCustomSortOrder/0000000000.lij b/tests/Test-10.14.6-path_edited.photoslibrary/resources/recovery/RKCustomSortOrder/0000000000.lij new file mode 100644 index 00000000..c0641fd7 Binary files /dev/null and b/tests/Test-10.14.6-path_edited.photoslibrary/resources/recovery/RKCustomSortOrder/0000000000.lij differ diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/resources/recovery/RKFace/0000000000.lij b/tests/Test-10.14.6-path_edited.photoslibrary/resources/recovery/RKFace/0000000000.lij new file mode 100644 index 00000000..bfc7e6ea Binary files /dev/null and b/tests/Test-10.14.6-path_edited.photoslibrary/resources/recovery/RKFace/0000000000.lij differ diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/resources/recovery/RKFaceGroup/0000000000.lij b/tests/Test-10.14.6-path_edited.photoslibrary/resources/recovery/RKFaceGroup/0000000000.lij new file mode 100644 index 00000000..ea33f762 Binary files /dev/null and b/tests/Test-10.14.6-path_edited.photoslibrary/resources/recovery/RKFaceGroup/0000000000.lij differ diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/resources/recovery/RKFacePrint/0000000000.lij b/tests/Test-10.14.6-path_edited.photoslibrary/resources/recovery/RKFacePrint/0000000000.lij new file mode 100644 index 00000000..fca406bf Binary files /dev/null and b/tests/Test-10.14.6-path_edited.photoslibrary/resources/recovery/RKFacePrint/0000000000.lij differ diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/resources/recovery/RKFolder/0000000000.lij b/tests/Test-10.14.6-path_edited.photoslibrary/resources/recovery/RKFolder/0000000000.lij new file mode 100644 index 00000000..8141ed17 Binary files /dev/null and b/tests/Test-10.14.6-path_edited.photoslibrary/resources/recovery/RKFolder/0000000000.lij differ diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/resources/recovery/RKImageProxyState/0000000000.lij b/tests/Test-10.14.6-path_edited.photoslibrary/resources/recovery/RKImageProxyState/0000000000.lij new file mode 100644 index 00000000..08305e5c Binary files /dev/null and b/tests/Test-10.14.6-path_edited.photoslibrary/resources/recovery/RKImageProxyState/0000000000.lij differ diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/resources/recovery/RKImportGroup/0000000000.lij b/tests/Test-10.14.6-path_edited.photoslibrary/resources/recovery/RKImportGroup/0000000000.lij new file mode 100644 index 00000000..f9e21589 Binary files /dev/null and b/tests/Test-10.14.6-path_edited.photoslibrary/resources/recovery/RKImportGroup/0000000000.lij differ diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/resources/recovery/RKKeyword/0000000000.lij b/tests/Test-10.14.6-path_edited.photoslibrary/resources/recovery/RKKeyword/0000000000.lij new file mode 100644 index 00000000..ae599bfe Binary files /dev/null and b/tests/Test-10.14.6-path_edited.photoslibrary/resources/recovery/RKKeyword/0000000000.lij differ diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/resources/recovery/RKKeywordForVersion/0000000000.lij b/tests/Test-10.14.6-path_edited.photoslibrary/resources/recovery/RKKeywordForVersion/0000000000.lij new file mode 100644 index 00000000..869f9778 Binary files /dev/null and b/tests/Test-10.14.6-path_edited.photoslibrary/resources/recovery/RKKeywordForVersion/0000000000.lij differ diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/resources/recovery/RKMaster/0000000000.lij b/tests/Test-10.14.6-path_edited.photoslibrary/resources/recovery/RKMaster/0000000000.lij new file mode 100644 index 00000000..4a6854d7 Binary files /dev/null and b/tests/Test-10.14.6-path_edited.photoslibrary/resources/recovery/RKMaster/0000000000.lij differ diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/resources/recovery/RKModelResource/0000000000.lij b/tests/Test-10.14.6-path_edited.photoslibrary/resources/recovery/RKModelResource/0000000000.lij new file mode 100644 index 00000000..2b43df90 Binary files /dev/null and b/tests/Test-10.14.6-path_edited.photoslibrary/resources/recovery/RKModelResource/0000000000.lij differ diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/resources/recovery/RKPerson/0000000000.lij b/tests/Test-10.14.6-path_edited.photoslibrary/resources/recovery/RKPerson/0000000000.lij new file mode 100644 index 00000000..29ce3a59 Binary files /dev/null and b/tests/Test-10.14.6-path_edited.photoslibrary/resources/recovery/RKPerson/0000000000.lij differ diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/resources/recovery/RKPersonMergeCandidatePerson/0000000000.lij b/tests/Test-10.14.6-path_edited.photoslibrary/resources/recovery/RKPersonMergeCandidatePerson/0000000000.lij new file mode 100644 index 00000000..94ff1216 Binary files /dev/null and b/tests/Test-10.14.6-path_edited.photoslibrary/resources/recovery/RKPersonMergeCandidatePerson/0000000000.lij differ diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/resources/recovery/RKPlace/0000000000.lij b/tests/Test-10.14.6-path_edited.photoslibrary/resources/recovery/RKPlace/0000000000.lij new file mode 100644 index 00000000..1698aaef Binary files /dev/null and b/tests/Test-10.14.6-path_edited.photoslibrary/resources/recovery/RKPlace/0000000000.lij differ diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/resources/recovery/RKPlaceForVersion/0000000000.lij b/tests/Test-10.14.6-path_edited.photoslibrary/resources/recovery/RKPlaceForVersion/0000000000.lij new file mode 100644 index 00000000..991ca93c Binary files /dev/null and b/tests/Test-10.14.6-path_edited.photoslibrary/resources/recovery/RKPlaceForVersion/0000000000.lij differ diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/resources/recovery/RKSceneInVersion/0000000000.lij b/tests/Test-10.14.6-path_edited.photoslibrary/resources/recovery/RKSceneInVersion/0000000000.lij new file mode 100644 index 00000000..fa462206 Binary files /dev/null and b/tests/Test-10.14.6-path_edited.photoslibrary/resources/recovery/RKSceneInVersion/0000000000.lij differ diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/resources/recovery/RKVersion/0000000000.lij b/tests/Test-10.14.6-path_edited.photoslibrary/resources/recovery/RKVersion/0000000000.lij new file mode 100644 index 00000000..6182489a Binary files /dev/null and b/tests/Test-10.14.6-path_edited.photoslibrary/resources/recovery/RKVersion/0000000000.lij differ diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/resources/recovery/RKVersionAnalysisState/0000000000.lij b/tests/Test-10.14.6-path_edited.photoslibrary/resources/recovery/RKVersionAnalysisState/0000000000.lij new file mode 100644 index 00000000..ff004d0a Binary files /dev/null and b/tests/Test-10.14.6-path_edited.photoslibrary/resources/recovery/RKVersionAnalysisState/0000000000.lij differ diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/resources/recovery/RKVolume/0000000000.lij b/tests/Test-10.14.6-path_edited.photoslibrary/resources/recovery/RKVolume/0000000000.lij new file mode 100644 index 00000000..bc990544 Binary files /dev/null and b/tests/Test-10.14.6-path_edited.photoslibrary/resources/recovery/RKVolume/0000000000.lij differ diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/resources/segments/Thumb64Segment_0.data b/tests/Test-10.14.6-path_edited.photoslibrary/resources/segments/Thumb64Segment_0.data new file mode 100644 index 00000000..d62e8211 Binary files /dev/null and b/tests/Test-10.14.6-path_edited.photoslibrary/resources/segments/Thumb64Segment_0.data differ diff --git a/tests/Test-10.14.6-path_edited.photoslibrary/resources/segments/ThumbJPGSegment_0.data b/tests/Test-10.14.6-path_edited.photoslibrary/resources/segments/ThumbJPGSegment_0.data new file mode 100644 index 00000000..b661d2db Binary files /dev/null and b/tests/Test-10.14.6-path_edited.photoslibrary/resources/segments/ThumbJPGSegment_0.data differ diff --git a/tests/test_mojave_10_14_6_path_edited.py b/tests/test_mojave_10_14_6_path_edited.py new file mode 100644 index 00000000..4acbb687 --- /dev/null +++ b/tests/test_mojave_10_14_6_path_edited.py @@ -0,0 +1,40 @@ +import pytest + +# test ability to search for edited files + +PHOTOS_DB = "./tests/Test-10.14.6-path_edited.photoslibrary/database/photos.db" +PHOTOS_DB_PATH = "/Test-10.14.6-path_edited.photoslibrary/database/photos.db" +PHOTOS_LIBRARY_PATH = "/Test-10.14.6-path_edited.photoslibrary" + +UUID_DICT = { + "non_00_path": "6bxcNnzRQKGnK4uPrCJ9UQ", + "standard_00_path": "3Jn73XpSQQCluzRBMWRsMA", +} + + +def test_path_edited1(): + # test a valid edited path + import os.path + import osxphotos + + photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) + photos = photosdb.photos(uuid=[UUID_DICT["standard_00_path"]]) + assert len(photos) == 1 + p = photos[0] + path = p.path_edited + assert path.endswith("resources/media/version/00/00/fullsizeoutput_d.jpeg") + assert os.path.exists(path) + + +def test_path_edited2(): + # test a non-standard (not 00) edited path + import os.path + import osxphotos + + photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) + photos = photosdb.photos(uuid=[UUID_DICT["non_00_path"]]) + assert len(photos) == 1 + p = photos[0] + path = p.path_edited + assert path.endswith("resources/media/version/00/02/fullsizeoutput_9.jpeg") + assert os.path.exists(path)