[Jython-checkins] jython: Moved getJarFileName() to public API and solved Issue 2386.

stefan.richthofer jython-checkins at python.org
Thu Sep 3 14:43:24 CEST 2015


https://hg.python.org/jython/rev/9bb29fb686d2
changeset:   7719:9bb29fb686d2
user:        Stefan Richthofer <stefan.richthofer at gmx.de>
date:        Thu Sep 03 14:42:46 2015 +0200
summary:
  Moved getJarFileName() to public API and solved Issue 2386.

files:
  Lib/distutils/sysconfig.py                        |   16 +-
  lib-python/2.7/distutils/command/build.py         |    6 +-
  src/org/python/core/Py.java                       |  155 +++++++++-
  src/org/python/core/PySystemState.java            |   66 +----
  tests/java/org/python/core/PySystemStateTest.java |   20 +-
  5 files changed, 181 insertions(+), 82 deletions(-)


diff --git a/Lib/distutils/sysconfig.py b/Lib/distutils/sysconfig.py
--- a/Lib/distutils/sysconfig.py
+++ b/Lib/distutils/sysconfig.py
@@ -15,6 +15,7 @@
 import re
 import string
 import sys
+from org.python.core import Py
 
 from distutils.errors import DistutilsPlatformError
 
@@ -25,7 +26,14 @@
 # Path to the base directory of the project. On Windows the binary may
 # live in project/PCBuild9.  If we're dealing with an x64 Windows build,
 # it'll live in project/PCbuild/amd64.
-project_base = os.path.dirname(os.path.realpath(sys.executable))
+
+def getJythonBinDir():
+    if not sys.executable is None:
+        return os.path.dirname(os.path.realpath(sys.executable))
+    else:
+        return Py.getDefaultBinDir()
+
+project_base = getJythonBinDir()
 if os.name == "nt" and "pcbuild" in project_base[-8:].lower():
     project_base = os.path.abspath(os.path.join(project_base, os.path.pardir))
 # PC/VS7.1
@@ -74,7 +82,7 @@
 
     if os.name == "posix":
         if python_build:
-            buildir = os.path.dirname(os.path.realpath(sys.executable))
+            buildir = getJythonBinDir()
             if plat_specific:
                 # python.h is located in the buildir
                 inc_dir = buildir
@@ -222,7 +230,7 @@
 def get_makefile_filename():
     """Return full pathname of installed Makefile from the Python build."""
     if python_build:
-        return os.path.join(os.path.dirname(os.path.realpath(sys.executable)),
+        return os.path.join(getJythonBinDir(),
                             "Makefile")
     lib_dir = get_python_lib(plat_specific=1, standard_lib=1)
     return os.path.join(lib_dir, "config", "Makefile")
@@ -460,7 +468,7 @@
     g['SO'] = '.pyd'
     g['EXE'] = ".exe"
     g['VERSION'] = get_python_version().replace(".", "")
-    g['BINDIR'] = os.path.dirname(os.path.realpath(sys.executable))
+    g['BINDIR'] = getJythonBinDir()
 
     global _config_vars
     _config_vars = g
diff --git a/lib-python/2.7/distutils/command/build.py b/lib-python/2.7/distutils/command/build.py
--- a/lib-python/2.7/distutils/command/build.py
+++ b/lib-python/2.7/distutils/command/build.py
@@ -115,7 +115,11 @@
                                               'scripts-' + sys.version[0:3])
 
         if self.executable is None:
-            self.executable = os.path.normpath(sys.executable)
+            if not sys.executable is None:
+                self.executable = os.path.normpath(sys.executable)
+            else:
+                from org.python.core import Py
+                self.executable = Py.getDefaultExecutableName()
 
     def run(self):
         # Run all relevant sub-commands.  This will be some subset of:
diff --git a/src/org/python/core/Py.java b/src/org/python/core/Py.java
--- a/src/org/python/core/Py.java
+++ b/src/org/python/core/Py.java
@@ -15,6 +15,8 @@
 import java.io.StreamCorruptedException;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
+import java.net.URL;
+import java.net.URLDecoder;
 import java.sql.Date;
 import java.sql.Time;
 import java.sql.Timestamp;
@@ -29,8 +31,8 @@
 import jnr.constants.platform.Errno;
 import jnr.posix.POSIX;
 import jnr.posix.POSIXFactory;
+import jnr.posix.util.Platform;
 
-import jnr.posix.util.Platform;
 import org.python.antlr.base.mod;
 import org.python.core.adapter.ClassicPyObjectAdapter;
 import org.python.core.adapter.ExtensiblePyObjectAdapter;
@@ -2301,6 +2303,155 @@
         }
         return objs.toArray(Py.EmptyObjects);
     }
+
+    /**
+     * Infers the usual Jython executable name from the position of the
+     * jar-file returned by {@link #getJarFileName()} by replacing the
+     * file name with "bin/jython". This is intended as an easy fallback
+     * for cases where {@code sys.executable} is {@code None} due to
+     * direct launching via the java executable.<br>
+     * Note that this does not necessarily return the actual executable,
+     * but instead infers the place where it is usually expected to be.
+     * Use {@code sys.executable} to get the actual executable (may be
+     * {@code None}.
+     *
+     * In contrast to {@link #getJarFileName()} and
+     * {@link #getJarFileNameFromURL(java.net.URL)} this method returns
+     * the path using system-specific separator characters.
+     *
+     * @return usual Jython-executable as absolute path
+     */
+    public static String getDefaultExecutableName() {
+        return getDefaultBinDir()+File.separator+(
+                Platform.IS_WINDOWS ? "jython.exe" : "jython");
+    }
+
+    /**
+     * Infers the usual Jython bin-dir from the position of the jar-file
+     * returned by {@link #getJarFileName()} byr replacing the file name
+     * with "bin". This is intended as an easy fallback for cases where
+     * {@code sys.executable} is {@code null} due to direct launching via
+     * the java executable.<br>
+     * Note that this does not necessarily return the actual bin-directory,
+     * but instead infers the place where it is usually expected to be.
+     *
+     * In contrast to {@link #getJarFileName()} and
+     * {@link #getJarFileNameFromURL(java.net.URL)} this method returns
+     * the path using system-specific separator characters.
+     *
+     * @return usual Jython bin-dir as absolute path
+     */
+    public static String getDefaultBinDir() {
+        String jar = _getJarFileName();
+        if (File.separatorChar != '/') {
+            jar = jar.replace('/', File.separatorChar);
+        }
+        int start = 0;
+        if (Platform.IS_WINDOWS && jar.startsWith(File.separator)) {
+            ++start;
+        }
+        return jar.substring(start, jar.lastIndexOf(File.separatorChar)+1)+"bin";
+    }
+
+    /**
+     * Utility-method to obtain the name (including absolute path) of the currently used
+     * jython-jar-file. Usually this is jython.jar, but can also be jython-dev.jar or
+     * jython-standalone.jar or something custom.
+     *
+     * @return the full name of the jar file containing this class, <code>null</code>
+     *         if not available.
+     */
+    public static String getJarFileName() {
+        String jar = _getJarFileName();
+        if (File.separatorChar != '/') {
+            jar = jar.replace('/', File.separatorChar);
+        }
+        int start = 0;
+        if (Platform.IS_WINDOWS && jar.startsWith(File.separator)) {
+            ++start;
+        }
+        return jar.substring(start);
+    }
+
+    /**
+     * Utility-method to obtain the name (including absolute path) of the currently used
+     * jython-jar-file. Usually this is jython.jar, but can also be jython-dev.jar or
+     * jython-standalone.jar or something custom.
+     * 
+     * Note that it does not use system-specific seperator-chars, but always
+     * '/'. Also, on windows it might prepend a '/' before the drive-letter. (Is this a bug?)
+     *
+     * @return the full name of the jar file containing this class, <code>null</code>
+     *         if not available.
+     */
+    protected static String _getJarFileName() {
+        Class<Py> thisClass = Py.class;
+        String fullClassName = thisClass.getName();
+        String className = fullClassName.substring(fullClassName.lastIndexOf(".") + 1);
+        URL url = thisClass.getResource(className + ".class");
+        return getJarFileNameFromURL(url);
+    }
+
+    /**exclusively used by {@link #getJarFileNameFromURL(java.net.URL)}.*/
+    private static final String JAR_URL_PREFIX = "jar:file:";
+    /**exclusively used by {@link #getJarFileNameFromURL(java.net.URL)}.*/
+    private static final String JAR_SEPARATOR = "!";
+    /**exclusively used by {@link #getJarFileNameFromURL(java.net.URL)}.*/
+    private static final String VFSZIP_PREFIX = "vfszip:";
+    /**exclusively used by {@link #getJarFileNameFromURL(java.net.URL)}.*/
+    private static final String VFS_PREFIX = "vfs:";
+
+    /**
+     * Converts a url that points to a jar-file to the actual jar-file name.
+     * Note that it does not use system-specific seperator-chars, but always
+     * '/'. Also, on windows it might prepend a '/' before the drive-letter.
+     */
+    public static String getJarFileNameFromURL(URL url) {
+        String jarFileName = null;
+        if (url != null) {
+            try {
+                // escape plus signs, since the URLDecoder would turn them into spaces
+                final String plus = "\\+";
+                final String escapedPlus = "__ppluss__";
+                String rawUrl = url.toString();
+                rawUrl = rawUrl.replaceAll(plus, escapedPlus);
+                String urlString = URLDecoder.decode(rawUrl, "UTF-8");
+                urlString = urlString.replaceAll(escapedPlus, plus);
+                int jarSeparatorIndex = urlString.lastIndexOf(JAR_SEPARATOR);
+                if (urlString.startsWith(JAR_URL_PREFIX) && jarSeparatorIndex > 0) {
+                    // jar:file:/install_dir/jython.jar!/org/python/core/PySystemState.class
+                    jarFileName = urlString.substring(JAR_URL_PREFIX.length(), jarSeparatorIndex);
+                } else if (urlString.startsWith(VFSZIP_PREFIX)) {
+                    // vfszip:/some/path/jython.jar/org/python/core/PySystemState.class
+                    final String path = Py.class.getName().replace('.', '/');
+                    int jarIndex = urlString.indexOf(".jar/".concat(path));
+                    if (jarIndex > 0) {
+                        jarIndex += 4;
+                        int start = VFSZIP_PREFIX.length();
+                        if (Platform.IS_WINDOWS) {
+                            // vfszip:/C:/some/path/jython.jar/org/python/core/PySystemState.class
+                            start++;
+                        }
+                        jarFileName = urlString.substring(start, jarIndex);
+                    }
+                } else if (urlString.startsWith(VFS_PREFIX)) {
+                    // vfs:/some/path/jython.jar/org/python/core/PySystemState.class
+                    final String path = Py.class.getName().replace('.', '/');
+                    int jarIndex = urlString.indexOf(".jar/".concat(path));
+                    if (jarIndex > 0) {
+                        jarIndex += 4;
+                        int start = VFS_PREFIX.length();
+                        if (Platform.IS_WINDOWS) {
+                            // vfs:/C:/some/path/jython.jar/org/python/core/PySystemState.class
+                            start++;
+                        }
+                        jarFileName = urlString.substring(start, jarIndex);
+                    }
+                }
+            } catch (Exception e) {}
+        }
+        return jarFileName;
+    }
 }
 
 class FixedFileWrapper extends StdoutWrapper {
@@ -2407,7 +2558,7 @@
 }
 
 /**
- * A function object wrapper for a java method which comply with the
+ * A function object wrapper for a java method that complies with the
  * PyArgsKeywordsCall standard.
  */
 @Untraversable
diff --git a/src/org/python/core/PySystemState.java b/src/org/python/core/PySystemState.java
--- a/src/org/python/core/PySystemState.java
+++ b/src/org/python/core/PySystemState.java
@@ -64,11 +64,6 @@
     public static final String JYTHON_JAR = "jython.jar";
     public static final String JYTHON_DEV_JAR = "jython-dev.jar";
 
-    private static final String JAR_URL_PREFIX = "jar:file:";
-    private static final String JAR_SEPARATOR = "!";
-    private static final String VFSZIP_PREFIX = "vfszip:";
-    private static final String VFS_PREFIX = "vfs:";
-
     public static final PyString version = new PyString(Version.getVersion());
 
     public static final PyTuple subversion = new PyTuple(new PyString("Jython"), Py.newString(""),
@@ -1036,7 +1031,7 @@
         initialized = true;
         Py.setAdapter(adapter);
         boolean standalone = false;
-        String jarFileName = getJarFileName();
+        String jarFileName = Py._getJarFileName();
         if (jarFileName != null) {
             standalone = isStandalone(jarFileName);
         }
@@ -1343,65 +1338,6 @@
         return standalone;
     }
 
-    /**
-     * @return the full name of the jar file containing this class, <code>null</code> if not
-     *         available.
-     */
-    private static String getJarFileName() {
-        Class<PySystemState> thisClass = PySystemState.class;
-        String fullClassName = thisClass.getName();
-        String className = fullClassName.substring(fullClassName.lastIndexOf(".") + 1);
-        URL url = thisClass.getResource(className + ".class");
-        return getJarFileNameFromURL(url);
-    }
-
-    protected static String getJarFileNameFromURL(URL url) {
-        String jarFileName = null;
-        if (url != null) {
-            try {
-                // escape plus signs, since the URLDecoder would turn them into spaces
-                final String plus = "\\+";
-                final String escapedPlus = "__ppluss__";
-                String rawUrl = url.toString();
-                rawUrl = rawUrl.replaceAll(plus, escapedPlus);
-                String urlString = URLDecoder.decode(rawUrl, "UTF-8");
-                urlString = urlString.replaceAll(escapedPlus, plus);
-                int jarSeparatorIndex = urlString.lastIndexOf(JAR_SEPARATOR);
-                if (urlString.startsWith(JAR_URL_PREFIX) && jarSeparatorIndex > 0) {
-                    // jar:file:/install_dir/jython.jar!/org/python/core/PySystemState.class
-                    jarFileName = urlString.substring(JAR_URL_PREFIX.length(), jarSeparatorIndex);
-                } else if (urlString.startsWith(VFSZIP_PREFIX)) {
-                    // vfszip:/some/path/jython.jar/org/python/core/PySystemState.class
-                    final String path = PySystemState.class.getName().replace('.', '/');
-                    int jarIndex = urlString.indexOf(".jar/".concat(path));
-                    if (jarIndex > 0) {
-                        jarIndex += 4;
-                        int start = VFSZIP_PREFIX.length();
-                        if (Platform.IS_WINDOWS) {
-                            // vfszip:/C:/some/path/jython.jar/org/python/core/PySystemState.class
-                            start++;
-                        }
-                        jarFileName = urlString.substring(start, jarIndex);
-                    }
-                } else if (urlString.startsWith(VFS_PREFIX)) {
-                    // vfs:/some/path/jython.jar/org/python/core/PySystemState.class
-                    final String path = PySystemState.class.getName().replace('.', '/');
-                    int jarIndex = urlString.indexOf(".jar/".concat(path));
-                    if (jarIndex > 0) {
-                        jarIndex += 4;
-                        int start = VFS_PREFIX.length();
-                        if (Platform.IS_WINDOWS) {
-                            // vfs:/C:/some/path/jython.jar/org/python/core/PySystemState.class
-                            start++;
-                        }
-                        jarFileName = urlString.substring(start, jarIndex);
-                    }
-                }
-            } catch (Exception e) {}
-        }
-        return jarFileName;
-    }
-
     private static void addPaths(PyList path, String pypath) {
         StringTokenizer tok = new StringTokenizer(pypath, java.io.File.pathSeparator);
         while (tok.hasMoreTokens()) {
diff --git a/tests/java/org/python/core/PySystemStateTest.java b/tests/java/org/python/core/PySystemStateTest.java
--- a/tests/java/org/python/core/PySystemStateTest.java
+++ b/tests/java/org/python/core/PySystemStateTest.java
@@ -13,19 +13,19 @@
 
     public void testGetJarFileNameFromURL() throws Exception {
         // null
-        assertNull(PySystemState.getJarFileNameFromURL(null));
+        assertNull(Py.getJarFileNameFromURL(null));
         // plain jar url
         String urlString = "jar:file:/some_dir/some.jar!/a/package/with/A.class";
         URL url = new URL(urlString);
-        assertEquals("/some_dir/some.jar", PySystemState.getJarFileNameFromURL(url));
+        assertEquals("/some_dir/some.jar", Py.getJarFileNameFromURL(url));
         // jar url to decode
         urlString = "jar:file:/some%20dir/some.jar!/a/package/with/A.class";
         url = new URL(urlString);
-        assertEquals("/some dir/some.jar", PySystemState.getJarFileNameFromURL(url));
+        assertEquals("/some dir/some.jar", Py.getJarFileNameFromURL(url));
         // jar url with + signs to escape
         urlString = "jar:file:/some+dir/some.jar!/a/package/with/A.class";
         url = new URL(urlString);
-        assertEquals("/some+dir/some.jar", PySystemState.getJarFileNameFromURL(url));
+        assertEquals("/some+dir/some.jar", Py.getJarFileNameFromURL(url));
     }
 
     public void testGetJarFileNameFromURL_jboss() throws Exception {
@@ -41,33 +41,33 @@
             url = new URL(protocol, host, port, file, handler);
             // tests with jboss on windows gave URL's like this:
             assertEquals("vfszip:/C:/some_dir/some.jar/org/python/core/PySystemState.class", url.toString());
-            assertEquals("C:/some_dir/some.jar", PySystemState.getJarFileNameFromURL(url));
+            assertEquals("C:/some_dir/some.jar", Py.getJarFileNameFromURL(url));
             // jboss url to decode
             file = "/C:/some%20dir/some.jar/org/python/core/PySystemState.class";
             url = new URL(protocol, host, port, file, handler);
             assertEquals("vfszip:/C:/some%20dir/some.jar/org/python/core/PySystemState.class", url.toString());
-            assertEquals("C:/some dir/some.jar", PySystemState.getJarFileNameFromURL(url));
+            assertEquals("C:/some dir/some.jar", Py.getJarFileNameFromURL(url));
             // jboss url with + to escape
             file = "/C:/some+dir/some.jar/org/python/core/PySystemState.class";
             url = new URL(protocol, host, port, file, handler);
             assertEquals("vfszip:/C:/some+dir/some.jar/org/python/core/PySystemState.class", url.toString());
-            assertEquals("C:/some+dir/some.jar", PySystemState.getJarFileNameFromURL(url));
+            assertEquals("C:/some+dir/some.jar", Py.getJarFileNameFromURL(url));
         } else {
             // plain jboss url
             file = "/some_dir/some.jar/org/python/core/PySystemState.class";
             url = new URL(protocol, host, port, file, handler);
             assertEquals("vfszip:/some_dir/some.jar/org/python/core/PySystemState.class", url.toString());
-            assertEquals("/some_dir/some.jar", PySystemState.getJarFileNameFromURL(url));
+            assertEquals("/some_dir/some.jar", Py.getJarFileNameFromURL(url));
             // jboss url to decode
             file = "/some%20dir/some.jar/org/python/core/PySystemState.class";
             url = new URL(protocol, host, port, file, handler);
             assertEquals("vfszip:/some%20dir/some.jar/org/python/core/PySystemState.class", url.toString());
-            assertEquals("/some dir/some.jar", PySystemState.getJarFileNameFromURL(url));
+            assertEquals("/some dir/some.jar", Py.getJarFileNameFromURL(url));
             // jboss url with + to escape
             file = "/some+dir/some.jar/org/python/core/PySystemState.class";
             url = new URL(protocol, host, port, file, handler);
             assertEquals("vfszip:/some+dir/some.jar/org/python/core/PySystemState.class", url.toString());
-            assertEquals("/some+dir/some.jar", PySystemState.getJarFileNameFromURL(url));
+            assertEquals("/some+dir/some.jar", Py.getJarFileNameFromURL(url));
         }
     }
 

-- 
Repository URL: https://hg.python.org/jython


More information about the Jython-checkins mailing list