]> granicus.if.org Git - python/commitdiff
Turned the suite compiler into an object.
authorJack Jansen <jack.jansen@cwi.nl>
Tue, 1 Apr 2003 14:25:49 +0000 (14:25 +0000)
committerJack Jansen <jack.jansen@cwi.nl>
Tue, 1 Apr 2003 14:25:49 +0000 (14:25 +0000)
Lib/plat-mac/gensuitemodule.py

index bc8619ec7e47d93e70df1490a79144730a337e9d..1e604fcbab1b8dc4e6eb218284e4307a0861e07b 100644 (file)
@@ -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