Browse Source

python_dev mode

David Rose 16 years ago
parent
commit
93e7352476

+ 1 - 1
direct/src/p3d/HostInfo.py

@@ -127,7 +127,7 @@ class HostInfo:
         platform, if one is provided by this host, or None if not. """
 
         assert self.hasContentsFile
-        platforms = self.packages.get((name, version), {})
+        platforms = self.packages.get((name, version or None), {})
 
         if platform is not None:
             # In this case, we are looking for a specific platform

+ 10 - 3
direct/src/p3d/PackageInfo.py

@@ -1,4 +1,4 @@
-from pandac.PandaModules import Filename, URLSpec, DocumentSpec, Ramfile, TiXmlDocument, Multifile, Decompressor, EUOk, EUSuccess, VirtualFileSystem, Thread
+from pandac.PandaModules import Filename, URLSpec, DocumentSpec, Ramfile, TiXmlDocument, Multifile, Decompressor, EUOk, EUSuccess, VirtualFileSystem, Thread, getModelPath
 from direct.p3d.FileSpec import FileSpec
 from direct.showbase import VFSImporter
 import os
@@ -16,7 +16,9 @@ class PackageInfo:
         self.packageVersion = packageVersion
         self.platform = platform
 
-        self.packageDir = Filename(host.hostDir, '%s/%s' % (self.packageName, self.packageVersion))
+        self.packageDir = Filename(host.hostDir, self.packageName)
+        if self.packageVersion:
+            self.packageDir = Filename(self.packageDir, self.packageVersion)
 
         # These will be filled in by HostInfo when the package is read
         # from contents.xml.
@@ -362,7 +364,12 @@ class PackageInfo:
 
         if not foundOnPath:
             # Not already here; add it.
-            sys.path.append(root)
+            sys.path.insert(0, root)
+
+        # Put it on the model-path, too.  We do this indiscriminantly,
+        # because the Panda3D runtime won't be adding things to the
+        # model-path, so it shouldn't be already there.
+        getModelPath().prependDirectory(self.packageDir)
 
         # Also, find any toplevel Python packages, and add these as
         # shared packages.  This will allow different packages

+ 40 - 26
direct/src/p3d/Packager.py

@@ -306,6 +306,12 @@ class Packager:
             else:
                 self.installMultifile()
 
+            if self.p3dApplication:
+                allowPythonDev = self.configs.get('allow_python_dev', 0)
+                if int(allowPythonDev):
+                    print "\n*** Generating %s.p3d with allow_python_dev enabled ***\n" % (self.packageName)
+
+
         def considerPlatform(self):
             # Check to see if any of the files are platform-specific,
             # making the overall package platform-specific.
@@ -1866,38 +1872,43 @@ class Packager:
         selected.
         """
 
-        packageDir = Filename(rootDir, packageName)
-        basename = packageName
+        packages = []
 
         if version:
             # A specific version package.
-            packageDir = Filename(packageDir, version)
-            basename += '.%s' % (version)
+            versionList = [version]
         else:
-            # Scan all versions.
-            packageDir = Filename(packageDir, '*')
-            basename += '.%s' % ('*')
-
-        if platform:
-            packageDir = Filename(packageDir, platform)
-            basename += '.%s' % (platform)
-
-        # Actually, the host means little for this search, since we're
-        # only looking in a local directory at this point.
-
-        basename += '.import.xml'
-        filename = Filename(packageDir, basename)
-        filelist = glob.glob(filename.toOsSpecific())
-        if not filelist:
-            # It doesn't exist in the nested directory; try the root
-            # directory.
-            filename = Filename(rootDir, basename)
+            # An unversioned package, or any old version.
+            versionList = [None, '*']
+
+        for version in versionList:
+            packageDir = Filename(rootDir, packageName)
+            basename = packageName
+
+            if version:
+                # A specific or nonspecific version package.
+                packageDir = Filename(packageDir, version)
+                basename += '.%s' % (version)
+
+            if platform:
+                packageDir = Filename(packageDir, platform)
+                basename += '.%s' % (platform)
+
+            # Actually, the host means little for this search, since we're
+            # only looking in a local directory at this point.
+
+            basename += '.import.xml'
+            filename = Filename(packageDir, basename)
             filelist = glob.glob(filename.toOsSpecific())
+            if not filelist:
+                # It doesn't exist in the nested directory; try the root
+                # directory.
+                filename = Filename(rootDir, basename)
+                filelist = glob.glob(filename.toOsSpecific())
 
-        packages = []
-        for file in filelist:
-            package = self.__readPackageImportDescFile(Filename.fromOsSpecific(file))
-            packages.append(package)
+            for file in filelist:
+                package = self.__readPackageImportDescFile(Filename.fromOsSpecific(file))
+                packages.append(package)
 
         self.__sortImportPackages(packages)
         for package in packages:
@@ -1952,6 +1963,9 @@ class Packager:
         separating out numbers into separate numeric fields, so that
         version numbers sort numerically where appropriate. """
 
+        if not version:
+            return ('',)
+
         words = []
         p = 0
         while p < len(version):

+ 16 - 1
direct/src/p3d/packp3d.py

@@ -40,6 +40,15 @@ Options:
      This option may be repeated as necessary.  These directories may
      also be specified with the pdef-path Config.prc variable.
 
+  -D
+     Allow the application to be run with -D on the panda3d command
+     line, or equivalently, "python_dev=1" in the web tokens.  If this
+     is allowed, then it will preserve the PYTHONPATH environment
+     variable from the user's environment, allowing Python files on
+     disk to shadow the same-named Python files within the p3d file,
+     for rapid iteration on the Python code.  If the appliation is not
+     built with -D here, this option does nothing at runtime.
+
 """
 
 import sys
@@ -57,13 +66,14 @@ class ArgumentError(StandardError):
     pass
 
 def makePackedApp(args):
-    opts, args = getopt.getopt(args, 'd:m:r:s:h')
+    opts, args = getopt.getopt(args, 'd:m:r:s:Dh')
 
     packager = Packager.Packager()
 
     root = Filename('.')
     main = None
     requires = []
+    allowPythonDev = False
     
     for option, value in opts:
         if option == '-d':
@@ -74,6 +84,8 @@ def makePackedApp(args):
             requires.append(value)
         elif option == '-s':
             packager.installSearch.appendDirectory(Filename.fromOsSpecific(value))
+        elif option == '-D':
+            allowPythonDev = True
         elif option == '-h':
             print __doc__ % (os.path.split(sys.argv[0])[1])
             sys.exit(1)
@@ -120,6 +132,9 @@ def makePackedApp(args):
         for requireName in requires:
             packager.do_require(requireName)
 
+        if allowPythonDev:
+            packager.do_config(allow_python_dev = True)
+
         packager.do_dir(root)
         packager.do_mainModule(mainModule)
 

+ 7 - 2
direct/src/plugin/p3dInstance.cxx

@@ -72,6 +72,7 @@ P3DInstance(P3D_request_ready_func *func,
   P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
   _instance_id = inst_mgr->get_unique_id();
   _hidden = false;
+  _allow_python_dev = false;
   _session = NULL;
   _panda3d = NULL;
   _splash_window = NULL;
@@ -881,13 +882,17 @@ scan_app_desc_file(TiXmlDocument *doc) {
     _log_basename = log_basename;
   }
 
-  int hidden = 0;
-
   TiXmlElement *xconfig = xpackage->FirstChildElement("config");
   if (xconfig != NULL) {
+    int hidden = 0;
     if (xconfig->QueryIntAttribute("hidden", &hidden) == TIXML_SUCCESS) {
       _hidden = (hidden != 0);
     }
+
+    int allow_python_dev = 0;
+    if (xconfig->QueryIntAttribute("allow_python_dev", &allow_python_dev) == TIXML_SUCCESS) {
+      _allow_python_dev = (allow_python_dev != 0);
+    }
   }
 
   if (_hidden && _got_wparams) {

+ 1 - 0
direct/src/plugin/p3dInstance.h

@@ -161,6 +161,7 @@ private:
   string _python_version;
   string _log_basename;
   bool _hidden;
+  bool _allow_python_dev;
 
   P3DSession *_session;
 

+ 4 - 1
direct/src/plugin/p3dPythonRun.cxx

@@ -1048,9 +1048,12 @@ add_package_info(P3DCInstance *inst, TiXmlElement *xpackage) {
   const char *platform = xpackage->Attribute("platform");
   const char *version = xpackage->Attribute("version");
   const char *host = xpackage->Attribute("host");
-  if (name == NULL || version == NULL || host == NULL) {
+  if (name == NULL || host == NULL) {
     return;
   }
+  if (version == NULL) {
+    version = "";
+  }
   if (platform == NULL) {
     platform = "";
   }

+ 50 - 9
direct/src/plugin/p3dSession.cxx

@@ -663,6 +663,12 @@ start_p3dpython(P3DInstance *inst) {
     mkdir_complete(start_dir, nout);
   }
 
+#ifdef _WIN32
+  char sep = ';';
+#else
+  char sep = ':';
+#endif  // _WIN32
+
   // Build up a search path that includes all of the required packages
   // that have already been installed.  We build this in reverse
   // order, so that the higher-order packages come first in the list;
@@ -673,17 +679,52 @@ start_p3dpython(P3DInstance *inst) {
   search_path = inst->_packages[pi]->get_package_dir();
   while (pi > 0) {
     --pi;
-#ifdef _WIN32
-    search_path += ';';
-#else
-    search_path += ':';
-#endif  // _WIN32
-
+    search_path += sep;
     search_path += inst->_packages[pi]->get_package_dir();
   }
 
   nout << "Search path is " << search_path << "\n";
 
+  bool python_dev = false;
+  if (inst->_allow_python_dev) {
+    // If "allow_python_dev" is set in the instance's p3d_info.xml,
+    // *and* we have python_dev in the tokens, then we set python_dev
+    // true.
+    python_dev = (inst->get_fparams().lookup_token_int("python_dev") != 0);
+  }
+
+  string python_path = search_path;
+  string prc_path = search_path;
+
+  if (python_dev) {
+    // With python_dev true, we preserve the PYTHONPATH setting from
+    // the caller's environment; in fact, we put it in the front.
+    // This allows the caller's on-disk Python files to shadow the
+    // similar-named files in the p3d file, allowing easy iteration on
+    // the code in the p3d file.
+    const char *pypath = getenv("PYTHONPATH");
+    if (pypath != (char *)NULL) {
+      python_path = pypath;
+      python_path += sep;
+      python_path += search_path;
+    }
+
+    // We also preserve PRC_PATH.
+    const char *prcpath = getenv("PRC_PATH");
+    if (prcpath == NULL) {
+      prcpath = getenv("PANDA_PRC_PATH");
+    }
+    if (prcpath != (char *)NULL) {
+      prc_path = prcpath;
+      prc_path += sep;
+      prc_path += search_path;
+    }
+
+    nout << "python_dev is true\n"
+         << "PYTHONPATH set to: " << python_path << "\n"
+         << "PRC_PATH set to: " << prc_path << "\n";
+  }
+
   string p3dpython = P3D_PLUGIN_P3DPYTHON;
   if (p3dpython.empty()) {
     p3dpython = _python_root_dir + "/p3dpython";
@@ -728,7 +769,7 @@ start_p3dpython(P3DInstance *inst) {
   env += '\0';
 
   env += "PYTHONPATH=";
-  env += search_path;
+  env += python_path;
   env += '\0';
 
   env += "PYTHONHOME=";
@@ -736,11 +777,11 @@ start_p3dpython(P3DInstance *inst) {
   env += '\0';
 
   env += "PRC_PATH=";
-  env += search_path;
+  env += prc_path;
   env += '\0';
 
   env += "PANDA_PRC_PATH=";
-  env += search_path;
+  env += prc_path;
   env += '\0';
     
   // Define each package's root directory in an environment variable

+ 18 - 1
direct/src/plugin_standalone/panda3d.cxx

@@ -64,7 +64,7 @@ run(int argc, char *argv[]) {
   // We prefix a "+" sign to tell gnu getopt not to parse options
   // following the first not-option parameter.  (These will be passed
   // into the sub-process.)
-  const char *optstr = "+mu:p:fw:t:s:o:l:h";
+  const char *optstr = "+mu:p:fw:t:s:o:l:Dh";
 
   bool allow_multiple = false;
   string download_url = PANDA_PACKAGE_HOST_URL;
@@ -136,6 +136,15 @@ run(int argc, char *argv[]) {
       _log_basename = "panda3d";
       break;
 
+    case 'D':
+      {
+        P3D_token token;
+        token._keyword = "python_dev";
+        token._value = "1";
+        _tokens.push_back(token);
+      }
+      break;
+
     case 'h':
     case '?':
     case '+':
@@ -780,6 +789,14 @@ usage() {
     << "    if a new version is available.  Normally, this is done only\n"
     << "    if contents.xml cannot be read.\n\n"
 
+    << "  -D\n"
+    << "    Request python_dev mode.  This requires that the application was\n"
+    << "    also built with -D on the packp3d command line.  If so, this will\n"
+    << "    preserve the PYTHONPATH environment variable from the user's\n"
+    << "    environment, allowing Python files on disk to shadow the same-named\n"
+    << "    Python files within the p3d file, for rapid iteration on the Python\n"
+    << "    code.\n\n"
+
     << "  -u url\n"
     << "    Specify the URL of the Panda3D download server.  The default is\n"
     << "    \"" << PANDA_PACKAGE_HOST_URL << "\" .\n\n"