ยปCore Development>Code coverage>Lib/plat-mac/aepack.py

Python code coverage for Lib/plat-mac/aepack.py

#countcontent
1n/a"""Tools for use in AppleEvent clients and servers:
2n/aconversion between AE types and python types
3n/a
4n/apack(x) converts a Python object to an AEDesc object
5n/aunpack(desc) does the reverse
6n/acoerce(x, wanted_sample) coerces a python object to another python object
7n/a"""
8n/a
9n/a#
10n/a# This code was originally written by Guido, and modified/extended by Jack
11n/a# to include the various types that were missing. The reference used is
12n/a# Apple Event Registry, chapter 9.
13n/a#
14n/a
15n/afrom warnings import warnpy3k
16n/awarnpy3k("In 3.x, the aepack module is removed.", stacklevel=2)
17n/a
18n/aimport struct
19n/aimport types
20n/afrom types import *
21n/afrom Carbon import AE
22n/afrom Carbon.AppleEvents import *
23n/aimport MacOS
24n/aimport Carbon.File
25n/aimport aetypes
26n/afrom aetypes import mkenum, ObjectSpecifier
27n/a
28n/a# These ones seem to be missing from AppleEvents
29n/a# (they're in AERegistry.h)
30n/a
31n/a#typeColorTable = 'clrt'
32n/a#typeDrawingArea = 'cdrw'
33n/a#typePixelMap = 'cpix'
34n/a#typePixelMapMinus = 'tpmm'
35n/a#typeRotation = 'trot'
36n/a#typeTextStyles = 'tsty'
37n/a#typeStyledText = 'STXT'
38n/a#typeAEText = 'tTXT'
39n/a#typeEnumeration = 'enum'
40n/a
41n/a#
42n/a# Some AE types are immedeately coerced into something
43n/a# we like better (and which is equivalent)
44n/a#
45n/aunpacker_coercions = {
46n/a typeComp : typeFloat,
47n/a typeColorTable : typeAEList,
48n/a typeDrawingArea : typeAERecord,
49n/a typeFixed : typeFloat,
50n/a typeExtended : typeFloat,
51n/a typePixelMap : typeAERecord,
52n/a typeRotation : typeAERecord,
53n/a typeStyledText : typeAERecord,
54n/a typeTextStyles : typeAERecord,
55n/a};
56n/a
57n/a#
58n/a# Some python types we need in the packer:
59n/a#
60n/aAEDescType = AE.AEDescType
61n/atry:
62n/a FSSType = Carbon.File.FSSpecType
63n/aexcept AttributeError:
64n/a class FSSType:
65n/a pass
66n/aFSRefType = Carbon.File.FSRefType
67n/aAliasType = Carbon.File.AliasType
68n/a
69n/adef packkey(ae, key, value):
70n/a if hasattr(key, 'which'):
71n/a keystr = key.which
72n/a elif hasattr(key, 'want'):
73n/a keystr = key.want
74n/a else:
75n/a keystr = key
76n/a ae.AEPutParamDesc(keystr, pack(value))
77n/a
78n/adef pack(x, forcetype = None):
79n/a """Pack a python object into an AE descriptor"""
80n/a
81n/a if forcetype:
82n/a if type(x) is StringType:
83n/a return AE.AECreateDesc(forcetype, x)
84n/a else:
85n/a return pack(x).AECoerceDesc(forcetype)
86n/a
87n/a if x is None:
88n/a return AE.AECreateDesc('null', '')
89n/a
90n/a if isinstance(x, AEDescType):
91n/a return x
92n/a if isinstance(x, FSSType):
93n/a return AE.AECreateDesc('fss ', x.data)
94n/a if isinstance(x, FSRefType):
95n/a return AE.AECreateDesc('fsrf', x.data)
96n/a if isinstance(x, AliasType):
97n/a return AE.AECreateDesc('alis', x.data)
98n/a if isinstance(x, IntType):
99n/a return AE.AECreateDesc('long', struct.pack('l', x))
100n/a if isinstance(x, FloatType):
101n/a return AE.AECreateDesc('doub', struct.pack('d', x))
102n/a if isinstance(x, StringType):
103n/a return AE.AECreateDesc('TEXT', x)
104n/a if isinstance(x, UnicodeType):
105n/a data = x.encode('utf16')
106n/a if data[:2] == '\xfe\xff':
107n/a data = data[2:]
108n/a return AE.AECreateDesc('utxt', data)
109n/a if isinstance(x, ListType):
110n/a list = AE.AECreateList('', 0)
111n/a for item in x:
112n/a list.AEPutDesc(0, pack(item))
113n/a return list
114n/a if isinstance(x, DictionaryType):
115n/a record = AE.AECreateList('', 1)
116n/a for key, value in x.items():
117n/a packkey(record, key, value)
118n/a #record.AEPutParamDesc(key, pack(value))
119n/a return record
120n/a if type(x) == types.ClassType and issubclass(x, ObjectSpecifier):
121n/a # Note: we are getting a class object here, not an instance
122n/a return AE.AECreateDesc('type', x.want)
123n/a if hasattr(x, '__aepack__'):
124n/a return x.__aepack__()
125n/a if hasattr(x, 'which'):
126n/a return AE.AECreateDesc('TEXT', x.which)
127n/a if hasattr(x, 'want'):
128n/a return AE.AECreateDesc('TEXT', x.want)
129n/a return AE.AECreateDesc('TEXT', repr(x)) # Copout
130n/a
131n/adef unpack(desc, formodulename=""):
132n/a """Unpack an AE descriptor to a python object"""
133n/a t = desc.type
134n/a
135n/a if t in unpacker_coercions:
136n/a desc = desc.AECoerceDesc(unpacker_coercions[t])
137n/a t = desc.type # This is a guess by Jack....
138n/a
139n/a if t == typeAEList:
140n/a l = []
141n/a for i in range(desc.AECountItems()):
142n/a keyword, item = desc.AEGetNthDesc(i+1, '****')
143n/a l.append(unpack(item, formodulename))
144n/a return l
145n/a if t == typeAERecord:
146n/a d = {}
147n/a for i in range(desc.AECountItems()):
148n/a keyword, item = desc.AEGetNthDesc(i+1, '****')
149n/a d[keyword] = unpack(item, formodulename)
150n/a return d
151n/a if t == typeAEText:
152n/a record = desc.AECoerceDesc('reco')
153n/a return mkaetext(unpack(record, formodulename))
154n/a if t == typeAlias:
155n/a return Carbon.File.Alias(rawdata=desc.data)
156n/a # typeAppleEvent returned as unknown
157n/a if t == typeBoolean:
158n/a return struct.unpack('b', desc.data)[0]
159n/a if t == typeChar:
160n/a return desc.data
161n/a if t == typeUnicodeText:
162n/a return unicode(desc.data, 'utf16')
163n/a # typeColorTable coerced to typeAEList
164n/a # typeComp coerced to extended
165n/a # typeData returned as unknown
166n/a # typeDrawingArea coerced to typeAERecord
167n/a if t == typeEnumeration:
168n/a return mkenum(desc.data)
169n/a # typeEPS returned as unknown
170n/a if t == typeFalse:
171n/a return 0
172n/a if t == typeFloat:
173n/a data = desc.data
174n/a return struct.unpack('d', data)[0]
175n/a if t == typeFSS:
176n/a return Carbon.File.FSSpec(rawdata=desc.data)
177n/a if t == typeFSRef:
178n/a return Carbon.File.FSRef(rawdata=desc.data)
179n/a if t == typeInsertionLoc:
180n/a record = desc.AECoerceDesc('reco')
181n/a return mkinsertionloc(unpack(record, formodulename))
182n/a # typeInteger equal to typeLongInteger
183n/a if t == typeIntlText:
184n/a script, language = struct.unpack('hh', desc.data[:4])
185n/a return aetypes.IntlText(script, language, desc.data[4:])
186n/a if t == typeIntlWritingCode:
187n/a script, language = struct.unpack('hh', desc.data)
188n/a return aetypes.IntlWritingCode(script, language)
189n/a if t == typeKeyword:
190n/a return mkkeyword(desc.data)
191n/a if t == typeLongInteger:
192n/a return struct.unpack('l', desc.data)[0]
193n/a if t == typeLongDateTime:
194n/a a, b = struct.unpack('lL', desc.data)
195n/a return (long(a) << 32) + b
196n/a if t == typeNull:
197n/a return None
198n/a if t == typeMagnitude:
199n/a v = struct.unpack('l', desc.data)
200n/a if v < 0:
201n/a v = 0x100000000L + v
202n/a return v
203n/a if t == typeObjectSpecifier:
204n/a record = desc.AECoerceDesc('reco')
205n/a # If we have been told the name of the module we are unpacking aedescs for,
206n/a # we can attempt to create the right type of python object from that module.
207n/a if formodulename:
208n/a return mkobjectfrommodule(unpack(record, formodulename), formodulename)
209n/a return mkobject(unpack(record, formodulename))
210n/a # typePict returned as unknown
211n/a # typePixelMap coerced to typeAERecord
212n/a # typePixelMapMinus returned as unknown
213n/a # typeProcessSerialNumber returned as unknown
214n/a if t == typeQDPoint:
215n/a v, h = struct.unpack('hh', desc.data)
216n/a return aetypes.QDPoint(v, h)
217n/a if t == typeQDRectangle:
218n/a v0, h0, v1, h1 = struct.unpack('hhhh', desc.data)
219n/a return aetypes.QDRectangle(v0, h0, v1, h1)
220n/a if t == typeRGBColor:
221n/a r, g, b = struct.unpack('hhh', desc.data)
222n/a return aetypes.RGBColor(r, g, b)
223n/a # typeRotation coerced to typeAERecord
224n/a # typeScrapStyles returned as unknown
225n/a # typeSessionID returned as unknown
226n/a if t == typeShortFloat:
227n/a return struct.unpack('f', desc.data)[0]
228n/a if t == typeShortInteger:
229n/a return struct.unpack('h', desc.data)[0]
230n/a # typeSMFloat identical to typeShortFloat
231n/a # typeSMInt indetical to typeShortInt
232n/a # typeStyledText coerced to typeAERecord
233n/a if t == typeTargetID:
234n/a return mktargetid(desc.data)
235n/a # typeTextStyles coerced to typeAERecord
236n/a # typeTIFF returned as unknown
237n/a if t == typeTrue:
238n/a return 1
239n/a if t == typeType:
240n/a return mktype(desc.data, formodulename)
241n/a #
242n/a # The following are special
243n/a #
244n/a if t == 'rang':
245n/a record = desc.AECoerceDesc('reco')
246n/a return mkrange(unpack(record, formodulename))
247n/a if t == 'cmpd':
248n/a record = desc.AECoerceDesc('reco')
249n/a return mkcomparison(unpack(record, formodulename))
250n/a if t == 'logi':
251n/a record = desc.AECoerceDesc('reco')
252n/a return mklogical(unpack(record, formodulename))
253n/a return mkunknown(desc.type, desc.data)
254n/a
255n/adef coerce(data, egdata):
256n/a """Coerce a python object to another type using the AE coercers"""
257n/a pdata = pack(data)
258n/a pegdata = pack(egdata)
259n/a pdata = pdata.AECoerceDesc(pegdata.type)
260n/a return unpack(pdata)
261n/a
262n/a#
263n/a# Helper routines for unpack
264n/a#
265n/adef mktargetid(data):
266n/a sessionID = getlong(data[:4])
267n/a name = mkppcportrec(data[4:4+72])
268n/a location = mklocationnamerec(data[76:76+36])
269n/a rcvrName = mkppcportrec(data[112:112+72])
270n/a return sessionID, name, location, rcvrName
271n/a
272n/adef mkppcportrec(rec):
273n/a namescript = getword(rec[:2])
274n/a name = getpstr(rec[2:2+33])
275n/a portkind = getword(rec[36:38])
276n/a if portkind == 1:
277n/a ctor = rec[38:42]
278n/a type = rec[42:46]
279n/a identity = (ctor, type)
280n/a else:
281n/a identity = getpstr(rec[38:38+33])
282n/a return namescript, name, portkind, identity
283n/a
284n/adef mklocationnamerec(rec):
285n/a kind = getword(rec[:2])
286n/a stuff = rec[2:]
287n/a if kind == 0: stuff = None
288n/a if kind == 2: stuff = getpstr(stuff)
289n/a return kind, stuff
290n/a
291n/adef mkunknown(type, data):
292n/a return aetypes.Unknown(type, data)
293n/a
294n/adef getpstr(s):
295n/a return s[1:1+ord(s[0])]
296n/a
297n/adef getlong(s):
298n/a return (ord(s[0])<<24) | (ord(s[1])<<16) | (ord(s[2])<<8) | ord(s[3])
299n/a
300n/adef getword(s):
301n/a return (ord(s[0])<<8) | (ord(s[1])<<0)
302n/a
303n/adef mkkeyword(keyword):
304n/a return aetypes.Keyword(keyword)
305n/a
306n/adef mkrange(dict):
307n/a return aetypes.Range(dict['star'], dict['stop'])
308n/a
309n/adef mkcomparison(dict):
310n/a return aetypes.Comparison(dict['obj1'], dict['relo'].enum, dict['obj2'])
311n/a
312n/adef mklogical(dict):
313n/a return aetypes.Logical(dict['logc'], dict['term'])
314n/a
315n/adef mkstyledtext(dict):
316n/a return aetypes.StyledText(dict['ksty'], dict['ktxt'])
317n/a
318n/adef mkaetext(dict):
319n/a return aetypes.AEText(dict[keyAEScriptTag], dict[keyAEStyles], dict[keyAEText])
320n/a
321n/adef mkinsertionloc(dict):
322n/a return aetypes.InsertionLoc(dict[keyAEObject], dict[keyAEPosition])
323n/a
324n/adef mkobject(dict):
325n/a want = dict['want'].type
326n/a form = dict['form'].enum
327n/a seld = dict['seld']
328n/a fr = dict['from']
329n/a if form in ('name', 'indx', 'rang', 'test'):
330n/a if want == 'text': return aetypes.Text(seld, fr)
331n/a if want == 'cha ': return aetypes.Character(seld, fr)
332n/a if want == 'cwor': return aetypes.Word(seld, fr)
333n/a if want == 'clin': return aetypes.Line(seld, fr)
334n/a if want == 'cpar': return aetypes.Paragraph(seld, fr)
335n/a if want == 'cwin': return aetypes.Window(seld, fr)
336n/a if want == 'docu': return aetypes.Document(seld, fr)
337n/a if want == 'file': return aetypes.File(seld, fr)
338n/a if want == 'cins': return aetypes.InsertionPoint(seld, fr)
339n/a if want == 'prop' and form == 'prop' and aetypes.IsType(seld):
340n/a return aetypes.Property(seld.type, fr)
341n/a return aetypes.ObjectSpecifier(want, form, seld, fr)
342n/a
343n/a# Note by Jack: I'm not 100% sure of the following code. This was
344n/a# provided by Donovan Preston, but I wonder whether the assignment
345n/a# to __class__ is safe. Moreover, shouldn't there be a better
346n/a# initializer for the classes in the suites?
347n/adef mkobjectfrommodule(dict, modulename):
348n/a if type(dict['want']) == types.ClassType and issubclass(dict['want'], ObjectSpecifier):
349n/a # The type has already been converted to Python. Convert back:-(
350n/a classtype = dict['want']
351n/a dict['want'] = aetypes.mktype(classtype.want)
352n/a want = dict['want'].type
353n/a module = __import__(modulename)
354n/a codenamemapper = module._classdeclarations
355n/a classtype = codenamemapper.get(want, None)
356n/a newobj = mkobject(dict)
357n/a if classtype:
358n/a assert issubclass(classtype, ObjectSpecifier)
359n/a newobj.__class__ = classtype
360n/a return newobj
361n/a
362n/adef mktype(typecode, modulename=None):
363n/a if modulename:
364n/a module = __import__(modulename)
365n/a codenamemapper = module._classdeclarations
366n/a classtype = codenamemapper.get(typecode, None)
367n/a if classtype:
368n/a return classtype
369n/a return aetypes.mktype(typecode)