David Rose 16 anni fa
parent
commit
5b84a46753
2 ha cambiato i file con 158 aggiunte e 44 eliminazioni
  1. 23 6
      direct/src/showutil/FreezeTool.py
  2. 135 38
      direct/src/showutil/Packager.py

+ 23 - 6
direct/src/showutil/FreezeTool.py

@@ -422,7 +422,7 @@ class Freezer:
         constructor, but it may be called at any point during
         processing. """
 
-        for key, value in freezer.modules:
+        for key, value in freezer.modules.items():
             self.previousModules[key] = value
             self.modules[key] = value
 
@@ -686,9 +686,26 @@ class Freezer:
     def mangleName(self, moduleName):
         return 'M_' + moduleName.replace('.', '__').replace('-', '_')
 
-    def __getModuleDefs(self):
-        # Collect a list of all of the modules we will be explicitly
-        # referencing.
+    def getAllModuleNames(self):
+        """ Return a list of all module names that have been included
+        or forbidden, either in this current pass or in a previous
+        pass.  Module names that have been excluded are not included
+        in this list. """
+
+        moduleNames = []
+
+        for newName, mdef in self.modules.items():
+            if mdef.token != self.MTExclude:
+                moduleNames.append(newName)
+
+        moduleNames.sort()
+        return moduleNames
+
+    def getModuleDefs(self):
+        """ Return a list of all of the modules we will be explicitly
+        or implicitly including.  The return value is actually a list
+        of tuples: (moduleName, moduleDef)."""
+        
         moduleDefs = []
 
         for newName, mdef in self.modules.items():
@@ -831,7 +848,7 @@ class Freezer:
         python code into the indicated Multifile. """
 
         moduleDirs = {}
-        for moduleName, mdef in self.__getModuleDefs():
+        for moduleName, mdef in self.getModuleDefs():
             if mdef.token != self.MTForbid:
                 self.__addPythonFile(multifile, moduleDirs, moduleName, mdef)
     
@@ -874,7 +891,7 @@ class Freezer:
         moduleDefs = []
         moduleList = []
         
-        for moduleName, mdef in self.__getModuleDefs():
+        for moduleName, mdef in self.getModuleDefs():
             token = mdef.token
             origName = mdef.moduleName
             if token == self.MTForbid:

+ 135 - 38
direct/src/showutil/Packager.py

@@ -29,6 +29,7 @@ class Packager:
 
     class PackFile:
         def __init__(self, filename, newName = None, deleteTemp = False):
+            assert isinstance(filename, Filename)
             self.filename = filename
             self.newName = newName
             self.deleteTemp = deleteTemp
@@ -37,37 +38,66 @@ class Packager:
         def __init__(self, packageName, packager):
             self.packageName = packageName
             self.packager = packager
-            self.version = 'dev'
+            self.version = None
+            self.platform = None
+            self.p3dApplication = False
             self.files = []
             self.compressionLevel = 0
             self.importedMapsDir = 'imported_maps'
 
+            # This is the set of files and modules, already included
+            # by required packages, that we can skip.
+            self.skipFilenames = {}
+            self.skipModules = {}
+
             # This records the current list of modules we have added so
             # far.
             self.freezer = FreezeTool.Freezer()
 
+            # Set this true to parse and build up the internal
+            # filelist, but not generate any output.
+            self.dryRun = False
+
         def close(self):
             """ Writes out the contents of the current package. """
 
             packageFilename = self.packageName
-            packageFilename += '_' + self.version
-            packageFilename += '.mf'
+            if self.platform:
+                packageFilename += '_' + self.platform
+            if self.version:
+                packageFilename += '_' + self.version
+
+            if self.p3dApplication:
+                packageFilename += '.p3d'
+            else:
+                packageFilename += '.mf'
             
             try:
                 os.unlink(packageFilename)
             except OSError:
                 pass
-            
-            self.multifile = Multifile()
-            self.multifile.openReadWrite(packageFilename)
+
+            if self.dryRun:
+                self.multifile = None
+            else:
+                self.multifile = Multifile()
+                self.multifile.openReadWrite(packageFilename)
+
+            # Exclude modules already imported in a required package.
+            for moduleName in self.skipModules.keys():
+                self.freezer.excludeModule(moduleName)
 
             # Build up a cross-reference of files we've already
             # discovered.
             self.sourceFilenames = {}
             self.targetFilenames = {}
+            processFiles = []
             for file in self.files:
                 if not file.newName:
                     file.newName = file.filename
+                if file.newName in self.skipFilenames:
+                    # Skip this file.
+                    continue
 
                 # Convert the source filename to an unambiguous
                 # filename for searching.
@@ -76,12 +106,13 @@ class Packager:
                 
                 self.sourceFilenames[filename] = file
                 self.targetFilenames[file.newName] = file
+                processFiles.append(file)
 
-            for file in self.files:
+            for file in processFiles:
                 ext = file.filename.getExtension()
                 if ext == 'py':
                     self.addPyFile(file)
-                else:
+                elif not self.dryRun:
                     if ext == 'pz':
                         # Strip off an implicit .pz extension.
                         filename = Filename(file.filename)
@@ -100,22 +131,31 @@ class Packager:
                         self.addBamFile(file)
                     elif ext in self.packager.imageExtensions:
                         self.addTexture(file)
+                    elif ext in self.packager.uncompressibleExtensions:
+                        # An uncompressible file.
+                        self.multifile.addSubfile(file.newName, file.filename, 0)
                     else:
-                        # An ordinary file.
+                        # Any other file.
                         self.multifile.addSubfile(file.newName, file.filename, self.compressionLevel)
 
             # Pick up any unfrozen Python files.
             self.freezer.done()
-            self.freezer.addToMultifile(self.multifile)
 
-            self.multifile.repack()
-            self.multifile.close()
+            # Add known module names.
+            self.moduleNames = {}
+            for moduleName in self.freezer.getAllModuleNames():
+                self.moduleNames[moduleName] = True
+
+            if not self.dryRun:
+                self.freezer.addToMultifile(self.multifile)
+                self.multifile.repack()
+                self.multifile.close()
 
             # Now that all the files have been packed, we can delete
             # the temporary files.
             for file in self.files:
                 if file.deleteTemp:
-                    os.unlink(file.filename)
+                    file.filename.unlink()
 
         def addPyFile(self, file):
             """ Adds the indicated python file, identified by filename
@@ -319,15 +359,21 @@ class Packager:
         self.sfxManagerList = None
         self.musicManager = None
 
+        # This is filled in during readPackageDef().
+        self.packageList = None
+
+        # A table of all known packages by name.
+        self.packages = {}
+
+        self.dryRun = False
+
+
     def setup(self):
         """ Call this method to initialize the class after filling in
         some of the values in the constructor. """
 
         self.knownExtensions = self.imageExtensions + self.modelExtensions + self.textExtensions + self.binaryExtensions + self.uncompressibleExtensions
 
-        # We need a stack of packages for managing begin_package
-        # .. end_package.
-        self.packageStack = []
         self.currentPackage = None
 
         # The persist dir is the directory in which the results from
@@ -353,10 +399,13 @@ class Packager:
         # created there
         os.chdir(self.persistDir.toOsSpecific())
 
-
     def readPackageDef(self, packageDef):
-        """ Reads the lines in packageDef and dispatches to the
-        appropriate handler method for each line. """
+        """ Reads the lines in the .pdef file named by packageDef and
+        dispatches to the appropriate handler method for each
+        line.  Returns the list of package files."""
+
+        assert self.packageList is None
+        self.packageList = []
 
         self.notify.info('Reading %s' % (packageDef))
         file = open(packageDef.toOsSpecific())
@@ -418,6 +467,11 @@ class Packager:
             inst.args = (inst.args[0] + ' on line %s of %s' % (lineNum[0], packageDef),)
             raise
 
+        packageList = self.packageList
+        self.packageList = None
+
+        return packageList
+
     def parse_setenv(self, lineList):
         """
         setenv variable value
@@ -430,7 +484,7 @@ class Packager:
 
         value = ExecutionEnvironment.expandString(value)
         ExecutionEnvironment.setEnvironmentVariable(variable, value)
-            
+
     def parse_begin_package(self, lineList):
         """
         begin_package packageName
@@ -455,6 +509,23 @@ class Packager:
 
         self.endPackage(packageName)
 
+    def parse_require(self, lineList):
+        """
+        require packageName
+        """
+
+        try:
+            command, packageName = lineList
+        except ValueError:
+            raise ArgumentError
+
+        package = self.findPackage(packageName)
+        if not package:
+            message = "Unknown package %s" % (packageName)
+            raise PackagerError, message
+
+        self.require(package)
+
     def parse_module(self, lineList):
         """
         module moduleName [newName]
@@ -533,12 +604,13 @@ class Packager:
         """ Begins a new package specification.  packageName is the
         basename of the package.  Follow this with a number of calls
         to file() etc., and close the package with endPackage(). """
-        
-        package = self.Package(packageName, self)
+
         if self.currentPackage:
-            package.freezer.excludeFrom(self.currentPackage.freezer)
-            
-        self.packageStack.append(package)
+            raise PackagerError, 'unmatched end_package %s' % (self.currentPackage.packageName)
+
+        package = self.Package(packageName, self)
+        package.dryRun = self.dryRun
+        
         self.currentPackage = package
 
     def endPackage(self, packageName):
@@ -555,12 +627,36 @@ class Packager:
         package = self.currentPackage
         package.close()
 
-        del self.packageStack[-1]
-        if self.packageStack:
-            self.currentPackage = self.packageStack[-1]
-            self.currentPackage.freezer.excludeFrom(package.freezer)
-        else:
-            self.currentPackage = None
+        self.packageList.append(package)
+        self.packages[package.packageName] = package
+        self.currentPackage = None
+
+    def findPackage(self, packageName, searchUrl = None):
+        """ Searches for the named package from a previous publish
+        operation, either at the indicated URL or along the default
+        search path.
+
+        Returns the Package object, or None if the package cannot be
+        located. """
+
+        # Is it a package we already have resident?
+        package = self.packages.get(packageName, None)
+        if package:
+            return package
+
+        return None
+
+    def require(self, package):
+        """ Indicates a dependency on the indicated package.
+
+        Attempts to install this package will implicitly install the
+        named package also.  Files already included in the named
+        package will be omitted from this one. """
+
+        for filename in package.targetFilenames.keys():
+            self.currentPackage.skipFilenames[filename] = True
+        for moduleName in package.moduleNames.keys():
+            self.currentPackage.skipModules[moduleName] = True
 
     def module(self, moduleName, newName = None):
         """ Adds the indicated Python module to the current package. """
@@ -584,14 +680,15 @@ class Packager:
         freezer = package.freezer
         freezer.done()
 
-        dirname = ''
-        basename = filename
-        if '/' in basename:
-            dirname, basename = filename.rsplit('/', 1)
-            dirname += '/'
-        basename = freezer.generateCode(basename, compileToExe = compileToExe)
+        if not package.dryRun:
+            dirname = ''
+            basename = filename
+            if '/' in basename:
+                dirname, basename = filename.rsplit('/', 1)
+                dirname += '/'
+            basename = freezer.generateCode(basename, compileToExe = compileToExe)
 
-        package.files.append(self.PackFile(basename, newName = dirname + basename, deleteTemp = True))
+            package.files.append(self.PackFile(Filename(basename), newName = dirname + basename, deleteTemp = True))
 
         # Reset the freezer for more Python files.
         freezer.reset()