2 gensuitemodule - Generate an AE suite module from an aete/aeut resource
6 Reading and understanding this code is left as an exercise to the reader.
19 import distutils
.sysconfig
21 from Carbon
.Res
import *
24 _MAC_LIB_FOLDER
=os
.path
.dirname(aetools
.__file
__)
25 DEFAULT_STANDARD_PACKAGEFOLDER
=os
.path
.join(_MAC_LIB_FOLDER
, 'lib-scriptpackages')
26 DEFAULT_USER_PACKAGEFOLDER
=distutils
.sysconfig
.get_python_lib()
30 for filename
in sys
.argv
[1:]:
33 # The dialogOptionFlags below allows selection of .app bundles.
34 filename
= EasyDialogs
.AskFileForOpen(
35 message
='Select scriptable application',
36 dialogOptionFlags
=0x1056)
41 except MacOS
.Error
, arg
:
42 print "Error getting terminology:", arg
43 print "Retry, manually parsing resources"
44 processfile_fromresource(filename
)
46 def processfile_fromresource(fullname
):
47 """Process all resources in a single file"""
49 print "Processing", fullname
50 rf
= macresource
.open_pathname(fullname
)
54 for i
in range(Count1Resources('aete')):
55 res
= Get1IndResource('aete', 1+i
)
57 for i
in range(Count1Resources('aeut')):
58 res
= Get1IndResource('aeut', 1+i
)
60 print "\nLISTING aete+aeut RESOURCES IN", `fullname`
63 print "decoding", res
.GetResInfo(), "..."
66 aetelist
.append((aete
, res
.GetResInfo()))
71 # switch back (needed for dialogs in Python)
73 compileaetelist(aetelist
, fullname
)
75 def processfile(fullname
):
76 """Ask an application for its terminology and process that"""
77 aedescobj
, launched
= OSATerminology
.GetSysTerminology(fullname
)
79 print "Launched", fullname
80 raw
= aetools
.unpack(aedescobj
)
82 print 'Unpack returned empty value:', raw
85 print 'Unpack returned value without data:', raw
88 aete
= decode(aedata
.data
)
89 compileaete(aete
, None, fullname
)
91 def compileaetelist(aetelist
, fullname
):
92 for aete
, resinfo
in aetelist
:
93 compileaete(aete
, resinfo
, fullname
)
96 """Decode a resource into a python data structure"""
97 f
= StringIO
.StringIO(data
)
98 aete
= generic(getaete
, f
)
101 unprocessed
= len(f
.read())
104 sys
.stderr
.write("%d processed + %d unprocessed = %d total\n" %
105 (processed
, unprocessed
, total
))
109 """Recursively replace singleton tuples by their constituent item"""
110 if type(item
) is types
.ListType
:
111 return map(simplify
, item
)
112 elif type(item
) == types
.TupleType
and len(item
) == 2:
113 return simplify(item
[1])
118 # Here follows the aete resource decoder.
119 # It is presented bottom-up instead of top-down because there are direct
120 # references to the lower-level part-decoders from the high-level part-decoders.
122 def getbyte(f
, *args
):
125 raise EOFError, 'in getbyte' + str(args
)
128 def getword(f
, *args
):
132 raise EOFError, 'in getword' + str(args
)
133 return (ord(s
[0])<<8) |
ord(s
[1])
135 def getlong(f
, *args
):
139 raise EOFError, 'in getlong' + str(args
)
140 return (ord(s
[0])<<24) |
(ord(s
[1])<<16) |
(ord(s
[2])<<8) |
ord(s
[3])
142 def getostype(f
, *args
):
146 raise EOFError, 'in getostype' + str(args
)
149 def getpstr(f
, *args
):
152 raise EOFError, 'in getpstr[1]' + str(args
)
154 if nbytes
== 0: return ''
157 raise EOFError, 'in getpstr[2]' + str(args
)
164 ## print 'align:', `c`
166 def getlist(f
, description
, getitem
):
169 for i
in range(count
):
170 list.append(generic(getitem
, f
))
174 def alt_generic(what
, f
, *args
):
175 print "generic", `what`
, args
176 res
= vageneric(what
, f
, args
)
180 def generic(what
, f
, *args
):
181 if type(what
) == types
.FunctionType
:
182 return apply(what
, (f
,) + args
)
183 if type(what
) == types
.ListType
:
186 item
= apply(generic
, thing
[:1] + (f
,) + thing
[1:])
187 record
.append((thing
[1], item
))
189 return "BAD GENERIC ARGS: %s" % `what`
193 (getpstr
, "description"),
198 (getostype
, "keyword"),
203 (getpstr
, "description"),
204 (getostype
, "suite code"),
205 (getostype
, "event code"),
206 (getdata
, "returns"),
207 (getdata
, "accepts"),
208 (getlist
, "optional arguments", getargument
)
217 (getlist
, "keyform", getostype
)
221 (getostype
, "class code"),
222 (getpstr
, "description"),
223 (getlist
, "properties", getproperty
),
224 (getlist
, "elements", getelement
)
227 (getpstr
, "operator name"),
228 (getostype
, "operator ID"),
229 (getpstr
, "operator comment"),
232 (getpstr
, "enumerator name"),
233 (getostype
, "enumerator ID"),
234 (getpstr
, "enumerator comment")
237 (getostype
, "enumeration ID"),
238 (getlist
, "enumerator", getenumerator
)
241 (getpstr
, "suite name"),
242 (getpstr
, "suite description"),
243 (getostype
, "suite ID"),
244 (getword
, "suite level"),
245 (getword
, "suite version"),
246 (getlist
, "events", getevent
),
247 (getlist
, "classes", getclass
),
248 (getlist
, "comparisons", getcomparison
),
249 (getlist
, "enumerations", getenumeration
)
252 (getword
, "major/minor version in BCD"),
253 (getword
, "language code"),
254 (getword
, "script code"),
255 (getlist
, "suites", getsuite
)
258 def compileaete(aete
, resinfo
, fname
):
259 """Generate code for a full aete resource. fname passed for doc purposes"""
260 [version
, language
, script
, suites
] = aete
261 major
, minor
= divmod(version
, 256)
262 creatorsignature
, dummy
= MacOS
.GetCreatorAndType(fname
)
263 packagename
= identify(os
.path
.splitext(os
.path
.basename(fname
))[0])
265 packagename
= packagename
+'_lang%d'%language
267 packagename
= packagename
+'_script%d'%script
268 if len(packagename
) > 27:
269 packagename
= packagename
[:27]
270 pathname
= EasyDialogs
.AskFolder(message
='Create and select package folder for %s'%packagename
,
271 defaultLocation
=DEFAULT_USER_PACKAGEFOLDER
)
274 packagename
= os
.path
.split(os
.path
.normpath(pathname
))[1]
275 basepkgname
= EasyDialogs
.AskFolder(message
='Package folder for base suite (usually StdSuites)',
276 defaultLocation
=DEFAULT_STANDARD_PACKAGEFOLDER
)
278 dirname
, basepkgname
= os
.path
.split(os
.path
.normpath(basepkgname
))
279 if not dirname
in sys
.path
:
280 sys
.path
.insert(0, dirname
)
281 basepackage
= __import__(basepkgname
)
288 code
, suite
, pathname
, modname
, precompinfo
= precompilesuite(suite
, basepackage
)
291 allprecompinfo
= allprecompinfo
+ precompinfo
292 suiteinfo
= suite
, pathname
, modname
293 suitelist
.append((code
, modname
))
294 allsuites
.append(suiteinfo
)
295 for suiteinfo
in allsuites
:
296 compilesuite(suiteinfo
, major
, minor
, language
, script
, fname
, basepackage
, allprecompinfo
)
297 initfilename
= EasyDialogs
.AskFileForSave(message
='Package module',
298 savedFileName
='__init__.py')
301 fp
= open(initfilename
, 'w')
302 MacOS
.SetCreatorAndType(initfilename
, 'Pyth', 'TEXT')
304 fp
.write("Package generated from %s\n"%fname
)
306 fp
.write("Resource %s resid %d %s\n"%(ascii(resinfo
[1]), resinfo
[0], ascii(resinfo
[2])))
308 fp
.write('import aetools\n')
309 fp
.write('Error = aetools.Error\n')
310 for code
, modname
in suitelist
:
311 fp
.write("import %s\n" % modname
)
312 fp
.write("\n\n_code_to_module = {\n")
313 for code
, modname
in suitelist
:
314 fp
.write("\t'%s' : %s,\n"%(ascii(code
), modname
))
316 fp
.write("\n\n_code_to_fullname = {\n")
317 for code
, modname
in suitelist
:
318 fp
.write("\t'%s' : ('%s.%s', '%s'),\n"%(ascii(code
), packagename
, modname
, modname
))
320 for code
, modname
in suitelist
:
321 fp
.write("from %s import *\n"%modname
)
323 # Generate property dicts and element dicts for all types declared in this module
324 fp
.write("def getbaseclasses(v):\n")
325 fp
.write("\tif hasattr(v, '_superclassnames') and not hasattr(v, '_propdict'):\n")
326 fp
.write("\t\tv._propdict = {}\n")
327 fp
.write("\t\tv._elemdict = {}\n")
328 fp
.write("\t\tfor superclass in v._superclassnames:\n")
329 ## fp.write("\t\t\tgetbaseclasses(superclass)\n")
330 fp
.write("\t\t\tv._propdict.update(getattr(eval(superclass), '_privpropdict', {}))\n")
331 fp
.write("\t\t\tv._elemdict.update(getattr(eval(superclass), '_privelemdict', {}))\n")
332 fp
.write("\t\tv._propdict.update(v._privpropdict)\n")
333 fp
.write("\t\tv._elemdict.update(v._privelemdict)\n")
335 fp
.write("import StdSuites\n")
337 fp
.write("\n#\n# Set property and element dictionaries now that all classes have been defined\n#\n")
338 for codenamemapper
in allprecompinfo
:
339 for k
, v
in codenamemapper
.getall('class'):
340 fp
.write("getbaseclasses(%s)\n" % v
)
342 # Generate a code-to-name mapper for all of the types (classes) declared in this module
344 fp
.write("\n#\n# Indices of types declared in this module\n#\n")
345 fp
.write("_classdeclarations = {\n")
346 for codenamemapper
in allprecompinfo
:
347 for k
, v
in codenamemapper
.getall('class'):
348 fp
.write("\t%s : %s,\n" % (`k`
, v
))
352 fp
.write("\n\nclass %s(%s_Events"%(packagename
, suitelist
[0][1]))
353 for code
, modname
in suitelist
[1:]:
354 fp
.write(",\n\t\t%s_Events"%modname
)
355 fp
.write(",\n\t\taetools.TalkTo):\n")
356 fp
.write("\t_signature = %s\n\n"%`creatorsignature`
)
357 fp
.write("\t_moduleName = '%s'\n\n"%packagename
)
360 def precompilesuite(suite
, basepackage
=None):
361 """Parse a single suite without generating the output. This step is needed
362 so we can resolve recursive references by suites to enums/comps/etc declared
364 [name
, desc
, code
, level
, version
, events
, classes
, comps
, enums
] = suite
366 modname
= identify(name
)
367 if len(modname
) > 28:
368 modname
= modname
[:27]
369 pathname
= EasyDialogs
.AskFileForSave(message
='Python output file',
370 savedFileName
=modname
+'.py')
372 return None, None, None, None, None
374 modname
= os
.path
.splitext(os
.path
.split(pathname
)[1])[0]
376 if basepackage
and basepackage
._code
_to
_module
.has_key(code
):
377 # We are an extension of a baseclass (usually an application extending
378 # Standard_Suite or so). Import everything from our base module
379 basemodule
= basepackage
._code
_to
_module
[code
]
381 # We are not an extension.
386 findenumsinevent(event
, enumsneeded
)
388 objc
= ObjectCompiler(None, basemodule
)
390 objc
.compileclass(cls
)
392 objc
.fillclasspropsandelems(cls
)
394 objc
.compilecomparison(comp
)
396 objc
.compileenumeration(enum
)
398 for enum
in enumsneeded
.keys():
399 objc
.checkforenum(enum
)
403 precompinfo
= objc
.getprecompinfo(modname
)
405 return code
, suite
, pathname
, modname
, precompinfo
407 def compilesuite((suite
, pathname
, modname
), major
, minor
, language
, script
, fname
, basepackage
, precompinfo
):
408 """Generate code for a single suite"""
409 [name
, desc
, code
, level
, version
, events
, classes
, comps
, enums
] = suite
411 fp
= open(pathname
, 'w')
412 MacOS
.SetCreatorAndType(pathname
, 'Pyth', 'TEXT')
414 fp
.write('"""Suite %s: %s\n' % (ascii(name
), ascii(desc
)))
415 fp
.write("Level %d, version %d\n\n" % (level
, version
))
416 fp
.write("Generated from %s\n"%ascii(fname
))
417 fp
.write("AETE/AEUT resource version %d/%d, language %d, script %d\n" % \
418 (major
, minor
, language
, script
))
421 fp
.write('import aetools\n')
422 fp
.write('import MacOS\n\n')
423 fp
.write("_code = %s\n\n"% `code`
)
424 if basepackage
and basepackage
._code
_to
_module
.has_key(code
):
425 # We are an extension of a baseclass (usually an application extending
426 # Standard_Suite or so). Import everything from our base module
427 fp
.write('from %s import *\n'%basepackage
._code
_to
_fullname
[code
][0])
428 basemodule
= basepackage
._code
_to
_module
[code
]
429 elif basepackage
and basepackage
._code
_to
_module
.has_key(code
.lower()):
430 # This is needed by CodeWarrior and some others.
431 fp
.write('from %s import *\n'%basepackage
._code
_to
_fullname
[code
.lower()][0])
432 basemodule
= basepackage
._code
_to
_module
[code
.lower()]
434 # We are not an extension.
436 compileclassheader(fp
, modname
, basemodule
)
441 compileevent(fp
, event
, enumsneeded
)
443 fp
.write("\tpass\n\n")
445 objc
= ObjectCompiler(fp
, basemodule
, precompinfo
)
447 objc
.compileclass(cls
)
449 objc
.fillclasspropsandelems(cls
)
451 objc
.compilecomparison(comp
)
453 objc
.compileenumeration(enum
)
455 for enum
in enumsneeded
.keys():
456 objc
.checkforenum(enum
)
462 def compileclassheader(fp
, name
, module
=None):
463 """Generate class boilerplate"""
464 classname
= '%s_Events'%name
466 modshortname
= string
.split(module
.__name
__, '.')[-1]
467 baseclassname
= '%s_Events'%modshortname
468 fp
.write("class %s(%s):\n\n"%(classname
, baseclassname
))
470 fp
.write("class %s:\n\n"%classname
)
472 def compileevent(fp
, event
, enumsneeded
):
473 """Generate code for a single event"""
474 [name
, desc
, code
, subcode
, returns
, accepts
, arguments
] = event
475 funcname
= identify(name
)
477 # generate name->keyword map
480 fp
.write("\t_argmap_%s = {\n"%funcname
)
482 fp
.write("\t\t%s : %s,\n"%(`
identify(a
[0])`
, `a
[1]`
))
486 # Generate function header
488 has_arg
= (not is_null(accepts
))
489 opt_arg
= (has_arg
and is_optional(accepts
))
491 fp
.write("\tdef %s(self, "%funcname
)
494 fp
.write("_object, ") # Include direct object, if it has one
496 fp
.write("_object=None, ") # Also include if it is optional
498 fp
.write("_no_object=None, ") # For argument checking
499 fp
.write("_attributes={}, **_arguments):\n") # include attribute dict and args
501 # Generate doc string (important, since it may be the only
502 # available documentation, due to our name-remaping)
504 fp
.write('\t\t"""%s: %s\n'%(ascii(name
), ascii(desc
)))
506 fp
.write("\t\tRequired argument: %s\n"%getdatadoc
(accepts
))
508 fp
.write("\t\tOptional argument: %s\n"%getdatadoc
(accepts
))
509 for arg
in arguments
:
510 fp
.write("\t\tKeyword argument %s: %s\n"%(identify(arg
[0]),
512 fp
.write("\t\tKeyword argument _attributes: AppleEvent attribute dictionary\n")
513 if not is_null(returns
):
514 fp
.write("\t\tReturns: %s\n"%getdatadoc
(returns
))
515 fp
.write('\t\t"""\n')
517 # Fiddle the args so everything ends up in 'arguments' dictionary
519 fp
.write("\t\t_code = %s\n"% `code`
)
520 fp
.write("\t\t_subcode = %s\n\n"% `subcode`
)
522 # Do keyword name substitution
525 fp
.write("\t\taetools.keysubst(_arguments, self._argmap_%s)\n"%funcname
)
527 fp
.write("\t\tif _arguments: raise TypeError, 'No optional args expected'\n")
529 # Stuff required arg (if there is one) into arguments
532 fp
.write("\t\t_arguments['----'] = _object\n")
534 fp
.write("\t\tif _object:\n")
535 fp
.write("\t\t\t_arguments['----'] = _object\n")
537 fp
.write("\t\tif _no_object != None: raise TypeError, 'No direct arg expected'\n")
540 # Do enum-name substitution
547 fp
.write("\t\taetools.enumsubst(_arguments, %s, _Enum_%s)\n" %
548 (`kname`
, identify(ename
)))
549 enumsneeded
[ename
] = 1
554 fp
.write("\t\t_reply, _arguments, _attributes = self.send(_code, _subcode,\n")
555 fp
.write("\t\t\t\t_arguments, _attributes)\n")
559 fp
.write("\t\tif _arguments.get('errn', 0):\n")
560 fp
.write("\t\t\traise aetools.Error, aetools.decodeerror(_arguments)\n")
561 fp
.write("\t\t# XXXX Optionally decode result\n")
565 fp
.write("\t\tif _arguments.has_key('----'):\n")
567 fp
.write("\t\t\t# XXXX Should do enum remapping here...\n")
568 fp
.write("\t\t\treturn _arguments['----']\n")
571 # print "\n# Command %s -- %s (%s, %s)" % (`name`, `desc`, `code`, `subcode`)
572 # print "# returns", compiledata(returns)
573 # print "# accepts", compiledata(accepts)
574 # for arg in arguments:
575 # compileargument(arg)
577 def compileargument(arg
):
578 [name
, keyword
, what
] = arg
579 print "# %s (%s)" % (name
, `keyword`
), compiledata(what
)
581 def findenumsinevent(event
, enumsneeded
):
582 """Find all enums for a single event"""
583 [name
, desc
, code
, subcode
, returns
, accepts
, arguments
] = event
588 enumsneeded
[ename
] = 1
591 # This class stores the code<->name translations for a single module. It is used
592 # to keep the information while we're compiling the module, but we also keep these objects
593 # around so if one suite refers to, say, an enum in another suite we know where to
594 # find it. Finally, if we really can't find a code, the user can add modules by
597 class CodeNameMapper
:
612 self
.modulename
= None
613 self
.star_imported
= 0
615 def addnamecode(self
, type, name
, code
):
616 self
.name2code
[type][name
] = code
617 if not self
.code2name
[type].has_key(code
):
618 self
.code2name
[type][code
] = name
620 def hasname(self
, type, name
):
621 return self
.name2code
[type].has_key(name
)
623 def hascode(self
, type, code
):
624 return self
.code2name
[type].has_key(code
)
626 def findcodename(self
, type, code
):
627 if not self
.hascode(type, code
):
628 return None, None, None
629 name
= self
.code2name
[type][code
]
630 if self
.modulename
and not self
.star_imported
:
631 qualname
= '%s.%s'%(self
.modulename
, name
)
634 return name
, qualname
, self
.modulename
636 def getall(self
, type):
637 return self
.code2name
[type].items()
639 def addmodule(self
, module
, name
, star_imported
):
640 self
.modulename
= name
641 self
.star_imported
= star_imported
642 for code
, name
in module
._propdeclarations
.items():
643 self
.addnamecode('property', name
, code
)
644 for code
, name
in module
._classdeclarations
.items():
645 self
.addnamecode('class', name
, code
)
646 for code
in module
._enumdeclarations
.keys():
647 self
.addnamecode('enum', '_Enum_'+identify(code
), code
)
648 for code
, name
in module
._compdeclarations
.items():
649 self
.addnamecode('comparison', name
, code
)
651 def prepareforexport(self
, name
=None):
652 if not self
.modulename
:
653 self
.modulename
= name
656 class ObjectCompiler
:
657 def __init__(self
, fp
, basesuite
=None, othernamemappers
=None):
659 self
.basesuite
= basesuite
660 self
.namemappers
= [CodeNameMapper()]
662 self
.othernamemappers
= othernamemappers
[:]
664 self
.othernamemappers
= []
666 basemapper
= CodeNameMapper()
667 basemapper
.addmodule(basesuite
, '', 1)
668 self
.namemappers
.append(basemapper
)
670 def getprecompinfo(self
, modname
):
672 for mapper
in self
.namemappers
:
673 emapper
= mapper
.prepareforexport(modname
)
678 def findcodename(self
, type, code
):
680 # First try: check whether we already know about this code.
681 for mapper
in self
.namemappers
:
682 if mapper
.hascode(type, code
):
683 return mapper
.findcodename(type, code
)
684 # Second try: maybe one of the other modules knows about it.
685 for mapper
in self
.othernamemappers
:
686 if mapper
.hascode(type, code
):
687 self
.othernamemappers
.remove(mapper
)
688 self
.namemappers
.append(mapper
)
690 self
.fp
.write("import %s\n"%mapper
.modulename
)
693 # If all this has failed we ask the user for a guess on where it could
696 m
= self
.askdefinitionmodule(type, code
)
699 if not m
: return None, None, None
700 mapper
= CodeNameMapper()
701 mapper
.addmodule(m
, m
.__name
__, 0)
702 self
.namemappers
.append(mapper
)
704 def askdefinitionmodule(self
, type, code
):
705 path
= EasyDialogs
.AskFileForSave(message
='Where is %s %s declared?'%(type, code
))
707 path
, file = os
.path
.split(path
)
708 modname
= os
.path
.splitext(file)[0]
709 if not path
in sys
.path
:
710 sys
.path
.insert(0, path
)
711 m
= __import__(modname
)
712 self
.fp
.write("import %s\n"%modname
)
715 def compileclass(self
, cls
):
716 [name
, code
, desc
, properties
, elements
] = cls
717 pname
= identify(name
)
718 if self
.namemappers
[0].hascode('class', code
):
719 # plural forms and such
720 othername
, dummy
, dummy
= self
.namemappers
[0].findcodename('class', code
)
722 self
.fp
.write("\n%s = %s\n"%(pname
, othername
))
725 self
.fp
.write('\nclass %s(aetools.ComponentItem):\n' % pname
)
726 self
.fp
.write('\t"""%s - %s """\n' % (ascii(name
), ascii(desc
)))
727 self
.fp
.write('\twant = %s\n' % `code`
)
728 self
.namemappers
[0].addnamecode('class', pname
, code
)
729 for prop
in properties
:
730 self
.compileproperty(prop
)
731 for elem
in elements
:
732 self
.compileelement(elem
)
734 def compileproperty(self
, prop
):
735 [name
, code
, what
] = prop
737 # Something silly with plurals. Skip it.
739 pname
= identify(name
)
740 if self
.namemappers
[0].hascode('property', code
):
741 # plural forms and such
742 othername
, dummy
, dummy
= self
.namemappers
[0].findcodename('property', code
)
743 if pname
== othername
:
746 self
.fp
.write("\n%s = %s\n"%(pname
, othername
))
749 self
.fp
.write("class %s(aetools.NProperty):\n" % pname
)
750 self
.fp
.write('\t"""%s - %s """\n' % (ascii(name
), ascii(what
[1])))
751 self
.fp
.write("\twhich = %s\n" % `code`
)
752 self
.fp
.write("\twant = %s\n" % `what
[0]`
)
753 self
.namemappers
[0].addnamecode('property', pname
, code
)
755 def compileelement(self
, elem
):
756 [code
, keyform
] = elem
758 self
.fp
.write("# element %s as %s\n" % (`code`
, keyform
))
760 def fillclasspropsandelems(self
, cls
):
761 [name
, code
, desc
, properties
, elements
] = cls
762 cname
= identify(name
)
763 if self
.namemappers
[0].hascode('class', code
) and \
764 self
.namemappers
[0].findcodename('class', code
)[0] != cname
:
765 # This is an other name (plural or so) for something else. Skip.
770 for prop
in properties
:
771 [pname
, pcode
, what
] = prop
773 superclasses
.append(what
)
776 pname
= identify(pname
)
780 for superclass
in superclasses
:
781 superId
, superDesc
, dummy
= superclass
782 superclassname
, fullyqualifiedname
, module
= self
.findcodename("class", superId
)
783 superclassnames
.append(superclassname
)
786 self
.fp
.write("%s._superclassnames = %s\n"%(cname
, `superclassnames`
))
788 for elem
in elements
:
789 [ecode
, keyform
] = elem
792 name
, ename
, module
= self
.findcodename('class', ecode
)
795 self
.fp
.write("# XXXX %s element %s not found!!\n"%(cname
, `ecode`
))
797 elist
.append((name
, ename
))
800 self
.fp
.write("%s._privpropdict = {\n"%cname
)
802 self
.fp
.write("\t'%s' : %s,\n"%(n
, n
))
804 self
.fp
.write("%s._privelemdict = {\n"%cname
)
805 for n
, fulln
in elist
:
806 self
.fp
.write("\t'%s' : %s,\n"%(n
, fulln
))
809 def compilecomparison(self
, comp
):
810 [name
, code
, comment
] = comp
811 iname
= identify(name
)
812 self
.namemappers
[0].addnamecode('comparison', iname
, code
)
814 self
.fp
.write("class %s(aetools.NComparison):\n" % iname
)
815 self
.fp
.write('\t"""%s - %s """\n' % (ascii(name
), ascii(comment
)))
817 def compileenumeration(self
, enum
):
819 name
= "_Enum_%s" % identify(code
)
821 self
.fp
.write("%s = {\n" % name
)
823 self
.compileenumerator(item
)
824 self
.fp
.write("}\n\n")
825 self
.namemappers
[0].addnamecode('enum', name
, code
)
828 def compileenumerator(self
, item
):
829 [name
, code
, desc
] = item
830 self
.fp
.write("\t%s : %s,\t# %s\n" % (`
identify(name
)`
, `code`
, ascii(desc
)))
832 def checkforenum(self
, enum
):
833 """This enum code is used by an event. Make sure it's available"""
834 name
, fullname
, module
= self
.findcodename('enum', enum
)
837 self
.fp
.write("_Enum_%s = None # XXXX enum %s not found!!\n"%(identify(enum
), ascii(enum
)))
841 self
.fp
.write("from %s import %s\n"%(module
, name
))
846 self
.fp
.write("\n#\n# Indices of types declared in this module\n#\n")
847 self
.fp
.write("_classdeclarations = {\n")
848 for k
, v
in self
.namemappers
[0].getall('class'):
849 self
.fp
.write("\t%s : %s,\n" % (`k`
, v
))
851 self
.fp
.write("\n_propdeclarations = {\n")
852 for k
, v
in self
.namemappers
[0].getall('property'):
853 self
.fp
.write("\t%s : %s,\n" % (`k`
, v
))
855 self
.fp
.write("\n_compdeclarations = {\n")
856 for k
, v
in self
.namemappers
[0].getall('comparison'):
857 self
.fp
.write("\t%s : %s,\n" % (`k`
, v
))
859 self
.fp
.write("\n_enumdeclarations = {\n")
860 for k
, v
in self
.namemappers
[0].getall('enum'):
861 self
.fp
.write("\t%s : %s,\n" % (`k`
, v
))
864 def compiledata(data
):
865 [type, description
, flags
] = data
866 return "%s -- %s %s" % (`
type`
, `description`
, compiledataflags(flags
))
869 return data
[0] == 'null'
871 def is_optional(data
):
872 return (data
[2] & 0x8000)
875 return (data
[2] & 0x2000)
877 def getdatadoc(data
):
878 [type, descr
, flags
] = data
884 return 'an AE object reference'
885 return "undocumented, typecode %s"%`
type`
887 dataflagdict
= {15: "optional", 14: "list", 13: "enum", 12: "mutable"}
888 def compiledataflags(flags
):
892 if i
in dataflagdict
.keys():
893 bits
.append(dataflagdict
[i
])
896 return '[%s]' % string
.join(bits
)
899 """Return a string with all non-ascii characters hex-encoded"""
900 if type(str) != type(''):
901 return map(ascii
, str)
904 if c
in ('\t', '\n', '\r') or ' ' <= c
< chr(0x7f):
907 rv
= rv
+ '\\' + 'x%02.2x' % ord(c
)
911 """Turn any string into an identifier:
913 - replace other illegal chars by _xx_ (hex code)
914 - prepend _ if the result is a python keyword
917 return "empty_ae_name_"
919 ok
= string
.ascii_letters
+ '_'
920 ok2
= ok
+ string
.digits
927 rv
= rv
+ '_%02.2x_'%ord(c
)
929 if keyword
.iskeyword(rv
):
933 # Call the main program
935 if __name__
== '__main__':