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)