diff options
Diffstat (limited to 'Lib')
-rw-r--r-- | Lib/plat-mac/gensuitemodule.py | 512 |
1 files changed, 258 insertions, 254 deletions
diff --git a/Lib/plat-mac/gensuitemodule.py b/Lib/plat-mac/gensuitemodule.py index bc8619e..1e604fc 100644 --- a/Lib/plat-mac/gensuitemodule.py +++ b/Lib/plat-mac/gensuitemodule.py @@ -467,17 +467,16 @@ def compileaete(aete, resinfo, fname, output=None, basepkgname=None, allprecompinfo = [] allsuites = [] for suite in suites: - code, suite, pathname, modname, precompinfo = precompilesuite(suite, basepackage, - output=output, edit_modnames=edit_modnames, verbose=verbose) + compiler = SuiteCompiler(suite, basepackage, output, edit_modnames, verbose) + code, modname, precompinfo = compiler.precompilesuite() if not code: continue allprecompinfo = allprecompinfo + precompinfo suiteinfo = suite, pathname, modname suitelist.append((code, modname)) - allsuites.append(suiteinfo) - for suiteinfo in allsuites: - compilesuite(suiteinfo, major, minor, language, script, fname, basepackage, - allprecompinfo, interact=(edit_modnames is None), verbose=verbose) + allsuites.append(compiler) + for compiler in allsuites: + compiler.compilesuite(major, minor, language, script, fname, allprecompinfo) initfilename = os.path.join(output, '__init__.py') fp = open(initfilename, 'w') MacOS.SetCreatorAndType(initfilename, 'Pyth', 'TEXT') @@ -540,268 +539,273 @@ def compileaete(aete, resinfo, fname, output=None, basepkgname=None, fp.write("\t_signature = %s\n\n"%`creatorsignature`) fp.write("\t_moduleName = '%s'\n\n"%packagename) fp.close() - -def precompilesuite(suite, basepackage=None, edit_modnames=None, output=None, - verbose=None): - """Parse a single suite without generating the output. This step is needed - so we can resolve recursive references by suites to enums/comps/etc declared - in other suites""" - [name, desc, code, level, version, events, classes, comps, enums] = suite - - modname = identify(name) - if len(modname) > 28: - modname = modname[:27] - if edit_modnames is None: - pathname = EasyDialogs.AskFileForSave(message='Python output file', - savedFileName=modname+'.py') - else: - for old, new in edit_modnames: - if old == modname: - modname = new - if modname: - pathname = os.path.join(output, modname + '.py') - else: - pathname = None - if not pathname: - return None, None, None, None, None - - modname = os.path.splitext(os.path.split(pathname)[1])[0] - - if basepackage and basepackage._code_to_module.has_key(code): - # We are an extension of a baseclass (usually an application extending - # Standard_Suite or so). Import everything from our base module - basemodule = basepackage._code_to_module[code] - else: - # We are not an extension. - basemodule = None - - enumsneeded = {} - for event in events: - findenumsinevent(event, enumsneeded) - objc = ObjectCompiler(None, basemodule, interact=(edit_modnames is None), - verbose=verbose) - for cls in classes: - objc.compileclass(cls) - for cls in classes: - objc.fillclasspropsandelems(cls) - for comp in comps: - objc.compilecomparison(comp) - for enum in enums: - objc.compileenumeration(enum) - - for enum in enumsneeded.keys(): - objc.checkforenum(enum) +class SuiteCompiler: + def __init__(self, suite, basepackage, output, edit_modnames, verbose): + self.suite = suite + self.basepackage = basepackage + self.edit_modnames = edit_modnames + self.output = output + self.verbose = verbose - objc.dumpindex() - - precompinfo = objc.getprecompinfo(modname) - - return code, suite, pathname, modname, precompinfo - -def compilesuite((suite, pathname, modname), major, minor, language, script, - fname, basepackage, precompinfo, interact=1, verbose=None): - """Generate code for a single suite""" - [name, desc, code, level, version, events, classes, comps, enums] = suite - # Sort various lists, so re-generated source is easier compared - def class_sorter(k1, k2): - """Sort classes by code, and make sure main class sorts before synonyms""" - # [name, code, desc, properties, elements] = cls - if k1[1] < k2[1]: return -1 - if k1[1] > k2[1]: return 1 - if not k2[3] or k2[3][0][1] == 'c@#!': - # This is a synonym, the other one is better - return -1 - if not k1[3] or k1[3][0][1] == 'c@#!': - # This is a synonym, the other one is better - return 1 - return 0 + # Set by precompilesuite + self.pathname = None + self.modname = None - events.sort() - classes.sort(class_sorter) - comps.sort() - enums.sort() - - fp = open(pathname, 'w') - MacOS.SetCreatorAndType(pathname, 'Pyth', 'TEXT') + # Set by compilesuite + self.fp = None + self.basemodule = None + self.enumsneeded = {} + + def precompilesuite(self): + """Parse a single suite without generating the output. This step is needed + so we can resolve recursive references by suites to enums/comps/etc declared + in other suites""" + [name, desc, code, level, version, events, classes, comps, enums] = self.suite + + modname = identify(name) + if len(modname) > 28: + modname = modname[:27] + if self.edit_modnames is None: + self.pathname = EasyDialogs.AskFileForSave(message='Python output file', + savedFileName=modname+'.py') + else: + for old, new in self.edit_modnames: + if old == modname: + modname = new + if modname: + self.pathname = os.path.join(self.output, modname + '.py') + else: + self.pathname = None + if not self.pathname: + return None, None, None - fp.write('"""Suite %s: %s\n' % (ascii(name), ascii(desc))) - fp.write("Level %d, version %d\n\n" % (level, version)) - fp.write("Generated from %s\n"%ascii(fname)) - fp.write("AETE/AEUT resource version %d/%d, language %d, script %d\n" % \ - (major, minor, language, script)) - fp.write('"""\n\n') + self.modname = os.path.splitext(os.path.split(self.pathname)[1])[0] + + if self.basepackage and self.basepackage._code_to_module.has_key(code): + # We are an extension of a baseclass (usually an application extending + # Standard_Suite or so). Import everything from our base module + basemodule = self.basepackage._code_to_module[code] + else: + # We are not an extension. + basemodule = None - fp.write('import aetools\n') - fp.write('import MacOS\n\n') - fp.write("_code = %s\n\n"% `code`) - if basepackage and basepackage._code_to_module.has_key(code): - # We are an extension of a baseclass (usually an application extending - # Standard_Suite or so). Import everything from our base module - fp.write('from %s import *\n'%basepackage._code_to_fullname[code][0]) - basemodule = basepackage._code_to_module[code] - elif basepackage and basepackage._code_to_module.has_key(code.lower()): - # This is needed by CodeWarrior and some others. - fp.write('from %s import *\n'%basepackage._code_to_fullname[code.lower()][0]) - basemodule = basepackage._code_to_module[code.lower()] - else: - # We are not an extension. - basemodule = None - compileclassheader(fp, modname, basemodule) - - enumsneeded = {} - if events: + self.enumsneeded = {} for event in events: - compileevent(fp, event, enumsneeded) - else: - fp.write("\tpass\n\n") - - objc = ObjectCompiler(fp, basemodule, precompinfo, interact=interact, - verbose=verbose) - for cls in classes: - objc.compileclass(cls) - for cls in classes: - objc.fillclasspropsandelems(cls) - for comp in comps: - objc.compilecomparison(comp) - for enum in enums: - objc.compileenumeration(enum) + self.findenumsinevent(event) - for enum in enumsneeded.keys(): - objc.checkforenum(enum) + objc = ObjectCompiler(None, basemodule, interact=(self.edit_modnames is None), + verbose=self.verbose) + for cls in classes: + objc.compileclass(cls) + for cls in classes: + objc.fillclasspropsandelems(cls) + for comp in comps: + objc.compilecomparison(comp) + for enum in enums: + objc.compileenumeration(enum) + + for enum in self.enumsneeded.keys(): + objc.checkforenum(enum) + + objc.dumpindex() - objc.dumpindex() + precompinfo = objc.getprecompinfo(self.modname) + + return code, self.modname, precompinfo - return code, modname + def compilesuite(self, major, minor, language, script, fname, precompinfo): + """Generate code for a single suite""" + [name, desc, code, level, version, events, classes, comps, enums] = self.suite + # Sort various lists, so re-generated source is easier compared + def class_sorter(k1, k2): + """Sort classes by code, and make sure main class sorts before synonyms""" + # [name, code, desc, properties, elements] = cls + if k1[1] < k2[1]: return -1 + if k1[1] > k2[1]: return 1 + if not k2[3] or k2[3][0][1] == 'c@#!': + # This is a synonym, the other one is better + return -1 + if not k1[3] or k1[3][0][1] == 'c@#!': + # This is a synonym, the other one is better + return 1 + return 0 + + events.sort() + classes.sort(class_sorter) + comps.sort() + enums.sort() + + self.fp = fp = open(self.pathname, 'w') + MacOS.SetCreatorAndType(self.pathname, 'Pyth', 'TEXT') + + fp.write('"""Suite %s: %s\n' % (ascii(name), ascii(desc))) + fp.write("Level %d, version %d\n\n" % (level, version)) + fp.write("Generated from %s\n"%ascii(fname)) + fp.write("AETE/AEUT resource version %d/%d, language %d, script %d\n" % \ + (major, minor, language, script)) + fp.write('"""\n\n') + + fp.write('import aetools\n') + fp.write('import MacOS\n\n') + fp.write("_code = %s\n\n"% `code`) + if self.basepackage and self.basepackage._code_to_module.has_key(code): + # We are an extension of a baseclass (usually an application extending + # Standard_Suite or so). Import everything from our base module + fp.write('from %s import *\n'%self.basepackage._code_to_fullname[code][0]) + basemodule = self.basepackage._code_to_module[code] + elif self.basepackage and self.basepackage._code_to_module.has_key(code.lower()): + # This is needed by CodeWarrior and some others. + fp.write('from %s import *\n'%self.basepackage._code_to_fullname[code.lower()][0]) + basemodule = self.basepackage._code_to_module[code.lower()] + else: + # We are not an extension. + basemodule = None + self.basemodule = basemodule + self.compileclassheader() -def compileclassheader(fp, name, module=None): - """Generate class boilerplate""" - classname = '%s_Events'%name - if module: - modshortname = string.split(module.__name__, '.')[-1] - baseclassname = '%s_Events'%modshortname - fp.write("class %s(%s):\n\n"%(classname, baseclassname)) - else: - fp.write("class %s:\n\n"%classname) + self.enumsneeded = {} + if events: + for event in events: + self.compileevent(event) + else: + fp.write("\tpass\n\n") -def compileevent(fp, event, enumsneeded): - """Generate code for a single event""" - [name, desc, code, subcode, returns, accepts, arguments] = event - funcname = identify(name) - # - # generate name->keyword map - # - if arguments: - fp.write("\t_argmap_%s = {\n"%funcname) - for a in arguments: - fp.write("\t\t%s : %s,\n"%(`identify(a[0])`, `a[1]`)) - fp.write("\t}\n\n") + objc = ObjectCompiler(fp, basemodule, precompinfo, interact=(self.edit_modnames is None), + verbose=self.verbose) + for cls in classes: + objc.compileclass(cls) + for cls in classes: + objc.fillclasspropsandelems(cls) + for comp in comps: + objc.compilecomparison(comp) + for enum in enums: + objc.compileenumeration(enum) - # - # Generate function header - # - has_arg = (not is_null(accepts)) - opt_arg = (has_arg and is_optional(accepts)) - - fp.write("\tdef %s(self, "%funcname) - if has_arg: - if not opt_arg: - fp.write("_object, ") # Include direct object, if it has one + for enum in self.enumsneeded.keys(): + objc.checkforenum(enum) + + objc.dumpindex() + + def compileclassheader(self): + """Generate class boilerplate""" + classname = '%s_Events'%self.modname + if self.basemodule: + modshortname = string.split(self.basemodule.__name__, '.')[-1] + baseclassname = '%s_Events'%modshortname + self.fp.write("class %s(%s):\n\n"%(classname, baseclassname)) else: - fp.write("_object=None, ") # Also include if it is optional - else: - fp.write("_no_object=None, ") # For argument checking - fp.write("_attributes={}, **_arguments):\n") # include attribute dict and args - # - # Generate doc string (important, since it may be the only - # available documentation, due to our name-remaping) - # - fp.write('\t\t"""%s: %s\n'%(ascii(name), ascii(desc))) - if has_arg: - fp.write("\t\tRequired argument: %s\n"%getdatadoc(accepts)) - elif opt_arg: - fp.write("\t\tOptional argument: %s\n"%getdatadoc(accepts)) - for arg in arguments: - fp.write("\t\tKeyword argument %s: %s\n"%(identify(arg[0]), - getdatadoc(arg[2]))) - fp.write("\t\tKeyword argument _attributes: AppleEvent attribute dictionary\n") - if not is_null(returns): - fp.write("\t\tReturns: %s\n"%getdatadoc(returns)) - fp.write('\t\t"""\n') - # - # Fiddle the args so everything ends up in 'arguments' dictionary - # - fp.write("\t\t_code = %s\n"% `code`) - fp.write("\t\t_subcode = %s\n\n"% `subcode`) - # - # Do keyword name substitution - # - if arguments: - fp.write("\t\taetools.keysubst(_arguments, self._argmap_%s)\n"%funcname) - else: - fp.write("\t\tif _arguments: raise TypeError, 'No optional args expected'\n") - # - # Stuff required arg (if there is one) into arguments - # - if has_arg: - fp.write("\t\t_arguments['----'] = _object\n") - elif opt_arg: - fp.write("\t\tif _object:\n") - fp.write("\t\t\t_arguments['----'] = _object\n") - else: - fp.write("\t\tif _no_object != None: raise TypeError, 'No direct arg expected'\n") - fp.write("\n") - # - # Do enum-name substitution - # - for a in arguments: - if is_enum(a[2]): - kname = a[1] - ename = a[2][0] - if ename <> '****': - fp.write("\t\taetools.enumsubst(_arguments, %s, _Enum_%s)\n" % - (`kname`, identify(ename))) - enumsneeded[ename] = 1 - fp.write("\n") - # - # Do the transaction - # - fp.write("\t\t_reply, _arguments, _attributes = self.send(_code, _subcode,\n") - fp.write("\t\t\t\t_arguments, _attributes)\n") - # - # Error handling - # - fp.write("\t\tif _arguments.get('errn', 0):\n") - fp.write("\t\t\traise aetools.Error, aetools.decodeerror(_arguments)\n") - fp.write("\t\t# XXXX Optionally decode result\n") - # - # Decode result - # - fp.write("\t\tif _arguments.has_key('----'):\n") - if is_enum(returns): - fp.write("\t\t\t# XXXX Should do enum remapping here...\n") - fp.write("\t\t\treturn _arguments['----']\n") - fp.write("\n") + self.fp.write("class %s:\n\n"%classname) + + def compileevent(self, event): + """Generate code for a single event""" + [name, desc, code, subcode, returns, accepts, arguments] = event + fp = self.fp + funcname = identify(name) + # + # generate name->keyword map + # + if arguments: + fp.write("\t_argmap_%s = {\n"%funcname) + for a in arguments: + fp.write("\t\t%s : %s,\n"%(`identify(a[0])`, `a[1]`)) + fp.write("\t}\n\n") + + # + # Generate function header + # + has_arg = (not is_null(accepts)) + opt_arg = (has_arg and is_optional(accepts)) + + fp.write("\tdef %s(self, "%funcname) + if has_arg: + if not opt_arg: + fp.write("_object, ") # Include direct object, if it has one + else: + fp.write("_object=None, ") # Also include if it is optional + else: + fp.write("_no_object=None, ") # For argument checking + fp.write("_attributes={}, **_arguments):\n") # include attribute dict and args + # + # Generate doc string (important, since it may be the only + # available documentation, due to our name-remaping) + # + fp.write('\t\t"""%s: %s\n'%(ascii(name), ascii(desc))) + if has_arg: + fp.write("\t\tRequired argument: %s\n"%getdatadoc(accepts)) + elif opt_arg: + fp.write("\t\tOptional argument: %s\n"%getdatadoc(accepts)) + for arg in arguments: + fp.write("\t\tKeyword argument %s: %s\n"%(identify(arg[0]), + getdatadoc(arg[2]))) + fp.write("\t\tKeyword argument _attributes: AppleEvent attribute dictionary\n") + if not is_null(returns): + fp.write("\t\tReturns: %s\n"%getdatadoc(returns)) + fp.write('\t\t"""\n') + # + # Fiddle the args so everything ends up in 'arguments' dictionary + # + fp.write("\t\t_code = %s\n"% `code`) + fp.write("\t\t_subcode = %s\n\n"% `subcode`) + # + # Do keyword name substitution + # + if arguments: + fp.write("\t\taetools.keysubst(_arguments, self._argmap_%s)\n"%funcname) + else: + fp.write("\t\tif _arguments: raise TypeError, 'No optional args expected'\n") + # + # Stuff required arg (if there is one) into arguments + # + if has_arg: + fp.write("\t\t_arguments['----'] = _object\n") + elif opt_arg: + fp.write("\t\tif _object:\n") + fp.write("\t\t\t_arguments['----'] = _object\n") + else: + fp.write("\t\tif _no_object != None: raise TypeError, 'No direct arg expected'\n") + fp.write("\n") + # + # Do enum-name substitution + # + for a in arguments: + if is_enum(a[2]): + kname = a[1] + ename = a[2][0] + if ename <> '****': + fp.write("\t\taetools.enumsubst(_arguments, %s, _Enum_%s)\n" % + (`kname`, identify(ename))) + self.enumsneeded[ename] = 1 + fp.write("\n") + # + # Do the transaction + # + fp.write("\t\t_reply, _arguments, _attributes = self.send(_code, _subcode,\n") + fp.write("\t\t\t\t_arguments, _attributes)\n") + # + # Error handling + # + fp.write("\t\tif _arguments.get('errn', 0):\n") + fp.write("\t\t\traise aetools.Error, aetools.decodeerror(_arguments)\n") + fp.write("\t\t# XXXX Optionally decode result\n") + # + # Decode result + # + fp.write("\t\tif _arguments.has_key('----'):\n") + if is_enum(returns): + fp.write("\t\t\t# XXXX Should do enum remapping here...\n") + fp.write("\t\t\treturn _arguments['----']\n") + fp.write("\n") + + def findenumsinevent(self, event): + """Find all enums for a single event""" + [name, desc, code, subcode, returns, accepts, arguments] = event + for a in arguments: + if is_enum(a[2]): + ename = a[2][0] + if ename <> '****': + self.enumsneeded[ename] = 1 -# print "\n# Command %s -- %s (%s, %s)" % (`name`, `desc`, `code`, `subcode`) -# print "# returns", compiledata(returns) -# print "# accepts", compiledata(accepts) -# for arg in arguments: -# compileargument(arg) - -def compileargument(arg): - [name, keyword, what] = arg - print "# %s (%s)" % (name, `keyword`), compiledata(what) - -def findenumsinevent(event, enumsneeded): - """Find all enums for a single event""" - [name, desc, code, subcode, returns, accepts, arguments] = event - for a in arguments: - if is_enum(a[2]): - ename = a[2][0] - if ename <> '****': - enumsneeded[ename] = 1 - # # This class stores the code<->name translations for a single module. It is used # to keep the information while we're compiling the module, but we also keep these objects |