[Jython-checkins] jython: Refactoring around os.uname() to extract common code.
jeff.allen
jython-checkins at python.org
Tue Jan 1 18:58:22 EST 2019
https://hg.python.org/jython/rev/4bbacf481833
changeset: 8212:4bbacf481833
user: Jeff Allen <ja.py at farowl.co.uk>
date: Tue Jan 01 23:14:03 2019 +0000
summary:
Refactoring around os.uname() to extract common code.
Use Py.getCommandResult and Py.getenv, the latter so that os.environ is
consulted to pick up changes. Also a slight tweak to the logic allows us to pass
test_uname_win32_ARCHITEW6432 in test_platform, if that test is enabled and
uname_cache disabled (temporarily).
Top-level classes hiding in Hider.java are made nested to placate IDE linters.
files:
Lib/test/test_platform.py | 1 +
src/org/python/core/PrePy.java | 33 +
src/org/python/core/PySystemState.java | 34 +-
src/org/python/modules/posix/Hider.java | 37 +-
src/org/python/modules/posix/PosixModule.java | 227 +++------
5 files changed, 137 insertions(+), 195 deletions(-)
diff --git a/Lib/test/test_platform.py b/Lib/test/test_platform.py
--- a/Lib/test/test_platform.py
+++ b/Lib/test/test_platform.py
@@ -136,6 +136,7 @@
self.assertTrue(any(res))
@unittest.skipUnless(sys.platform.startswith('win'), "windows only test")
+ # One may enable this for Jython, but must disable the cache in os.uname() to pass.
def test_uname_win32_ARCHITEW6432(self):
# Issue 7860: make sure we get architecture from the correct variable
# on 64 bit Windows: if PROCESSOR_ARCHITEW6432 exists we should be
diff --git a/src/org/python/core/PrePy.java b/src/org/python/core/PrePy.java
--- a/src/org/python/core/PrePy.java
+++ b/src/org/python/core/PrePy.java
@@ -264,4 +264,37 @@
}
return url;
}
+
+ /**
+ * Run a command as a sub-process and return as the result the first line of output that
+ * consists of more than white space. It returns "" on any kind of error.
+ *
+ * @param command as strings (as for <code>ProcessBuilder</code>)
+ * @return the first line with content, or ""
+ */
+ public static String getCommandResult(String... command) {
+ String result = "", line = null;
+ ProcessBuilder pb = new ProcessBuilder(command);
+ try {
+ Process p = pb.start();
+ java.io.BufferedReader br =
+ new java.io.BufferedReader(new java.io.InputStreamReader(p.getInputStream()));
+ // We read to the end-of-stream in case the sub-process cannot end cleanly without.
+ while ((line = br.readLine()) != null) {
+ if (line.length() > 0 && result.length() == 0) {
+ // This is the first line with content (maybe).
+ result = line.trim();
+ }
+ }
+ br.close();
+ // Now we wait for the sub-process to terminate nicely.
+ if (p.waitFor() != 0) {
+ // Bad exit status: don't take the result.
+ result = "";
+ }
+ } catch (IOException | InterruptedException | SecurityException e) {
+ result = "";
+ }
+ return result;
+ }
}
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
@@ -996,7 +996,7 @@
} else if (os != null && os.startsWith("Windows")) {
// Go via the Windows code page built-in command "chcp".
- String output = getCommandResult("cmd", "/c", "chcp");
+ String output = Py.getCommandResult("cmd", "/c", "chcp");
/*
* The output will be like "Active code page: 850" or maybe "Aktive Codepage: 1252." or
* "활성 코드 페이지: 949". Assume the first number with 2 or more digits is the code page.
@@ -1009,7 +1009,7 @@
} else {
// Try a Unix-like "locale charmap".
- String output = getCommandResult("locale", "charmap");
+ String output = Py.getCommandResult("locale", "charmap");
// The result of "locale charmap" is just the charmap name ~ Charset or codec name.
if (output.length() > 0) {
return output;
@@ -1782,10 +1782,10 @@
// "Microsoft Windows [版本 10.0.17134.472]"
// We match the dots and digits within square brackets.
Pattern p = Pattern.compile("\\[.* ([\\d.]+)\\]");
- Matcher m = p.matcher(getCommandResult("cmd.exe", "/c", "ver"));
+ Matcher m = p.matcher(Py.getCommandResult("cmd.exe", "/c", "ver"));
return m.find() ? m.group(1) : "";
} else {
- return getCommandResult("uname", "-v");
+ return Py.getCommandResult("uname", "-v");
}
}
@@ -1795,31 +1795,11 @@
*
* @param command as strings (as for <code>ProcessBuilder</code>)
* @return the first line with content, or ""
+ * @deprecated Use {@link Py#getCommandResult(String...)} instead
*/
+ @Deprecated
private static String getCommandResult(String... command) {
- String result = "", line = null;
- ProcessBuilder pb = new ProcessBuilder(command);
- try {
- Process p = pb.start();
- java.io.BufferedReader br =
- new java.io.BufferedReader(new java.io.InputStreamReader(p.getInputStream()));
- // We read to the end-of-stream in case the sub-process cannot end cleanly without.
- while ((line = br.readLine()) != null) {
- if (line.length() > 0 && result.length() == 0) {
- // This is the first line with content (maybe).
- result = line.trim();
- }
- }
- br.close();
- // Now we wait for the sub-process to terminate nicely.
- if (p.waitFor() != 0) {
- // Bad exit status: don't take the result.
- result = "";
- }
- } catch (IOException | InterruptedException | SecurityException e) {
- result = "";
- }
- return result;
+ return PrePy.getCommandResult(command);
}
/* Traverseproc implementation */
diff --git a/src/org/python/modules/posix/Hider.java b/src/org/python/modules/posix/Hider.java
--- a/src/org/python/modules/posix/Hider.java
+++ b/src/org/python/modules/posix/Hider.java
@@ -50,27 +50,24 @@
}
return false;
}
-}
-/**
- * Tags PosixModule methods as hidden on the specified OS or PosixImpl.
- */
- at Retention(RetentionPolicy.RUNTIME)
- at Target(ElementType.METHOD)
- at interface Hide {
+ /** Tags PosixModule methods as hidden on the specified OS or PosixImpl. */
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target(ElementType.METHOD)
+ @interface Hide {
- /** Hide method on these OSes. */
- OS[] value() default {};
+ /** Hide method on these OSes. */
+ OS[] value() default {};
- /**
- * @Hide(posixImpl = PosixImpl.JAVA) hides the method from Python when the POSIX
- * library isn't native. The default NOT_APPLICABLE means the POSIX implementation
- * doesn't matter.
- */
- PosixImpl posixImpl() default PosixImpl.NOT_APPLICABLE;
+ /**
+ * @Hide(posixImpl = PosixImpl.JAVA) hides the method from Python when the POSIX
+ * library isn't native. The default NOT_APPLICABLE means the POSIX implementation
+ * doesn't matter.
+ */
+ PosixImpl posixImpl() default PosixImpl.NOT_APPLICABLE;
+ }
+
+ /** The type of underlying POSIX library implementation (native or not). */
+ enum PosixImpl {NOT_APPLICABLE, NATIVE, JAVA};
+
}
-
-/**
- * The type of underlying POSIX library implementation (native or not).
- */
-enum PosixImpl {NOT_APPLICABLE, NATIVE, JAVA};
diff --git a/src/org/python/modules/posix/PosixModule.java b/src/org/python/modules/posix/PosixModule.java
--- a/src/org/python/modules/posix/PosixModule.java
+++ b/src/org/python/modules/posix/PosixModule.java
@@ -343,7 +343,7 @@
public static PyString __doc__chown = new PyString(
"chown(path, uid, gid)\n\n" +
"Change the owner and group id of path to the numeric uid and gid.");
- @Hide(OS.NT)
+ @Hider.Hide(OS.NT)
public static void chown(PyObject path, int uid, int gid) {
if (posix.chown(absolutePath(path).toString(), uid, gid) < 0) {
throw errorFromErrno(path);
@@ -362,7 +362,7 @@
}
}
- @Hide(OS.NT)
+ @Hider.Hide(OS.NT)
public static void closerange(PyObject fd_lowObj, PyObject fd_highObj) {
int fd_low = getFD(fd_lowObj).getIntFD(false);
int fd_high = getFD(fd_highObj).getIntFD(false);
@@ -424,7 +424,7 @@
"fdatasync(fildes)\n\n" +
"force write of file with filedescriptor to disk.\n" +
"does not force update of metadata.");
- @Hide(OS.NT)
+ @Hider.Hide(OS.NT)
public static void fdatasync(PyObject fd) {
Object javaobj = fd.__tojava__(RawIOBase.class);
if (javaobj != Py.NoConversion) {
@@ -501,7 +501,7 @@
public static PyString __doc__getegid = new PyString(
"getegid() -> egid\n\n" +
"Return the current process's effective group id.");
- @Hide(OS.NT)
+ @Hider.Hide(OS.NT)
public static int getegid() {
return posix.getegid();
}
@@ -509,7 +509,7 @@
public static PyString __doc__geteuid = new PyString(
"geteuid() -> euid\n\n" +
"Return the current process's effective user id.");
- @Hide(OS.NT)
+ @Hider.Hide(OS.NT)
public static int geteuid() {
return posix.geteuid();
}
@@ -517,7 +517,7 @@
public static PyString __doc__getgid = new PyString(
"getgid() -> gid\n\n" +
"Return the current process's group id.");
- @Hide(value=OS.NT, posixImpl = PosixImpl.JAVA)
+ @Hider.Hide(value=OS.NT, posixImpl = Hider.PosixImpl.JAVA)
public static int getgid() {
return posix.getgid();
}
@@ -525,7 +525,7 @@
public static PyString __doc__getlogin = new PyString(
"getlogin() -> string\n\n" +
"Return the actual login name.");
- @Hide(value=OS.NT, posixImpl = PosixImpl.JAVA)
+ @Hider.Hide(value=OS.NT, posixImpl = Hider.PosixImpl.JAVA)
public static PyObject getlogin() {
String login = posix.getlogin();
if (login == null) {
@@ -539,7 +539,7 @@
public static PyString __doc__getppid = new PyString(
"getppid() -> ppid\n\n" +
"Return the parent's process id.");
- @Hide(value=OS.NT, posixImpl = PosixImpl.JAVA)
+ @Hider.Hide(value=OS.NT, posixImpl = Hider.PosixImpl.JAVA)
public static int getppid() {
return posix.getppid();
}
@@ -547,7 +547,7 @@
public static PyString __doc__getuid = new PyString(
"getuid() -> uid\n\n" +
"Return the current process's user id.");
- @Hide(value=OS.NT, posixImpl = PosixImpl.JAVA)
+ @Hider.Hide(value=OS.NT, posixImpl = Hider.PosixImpl.JAVA)
public static int getuid() {
return posix.getuid();
}
@@ -556,7 +556,7 @@
"getpid() -> pid\n\n" +
"Return the current process id");
- @Hide(posixImpl = PosixImpl.JAVA)
+ @Hider.Hide(posixImpl = Hider.PosixImpl.JAVA)
public static int getpid() {
return posix.getpid();
}
@@ -564,7 +564,7 @@
public static PyString __doc__getpgrp = new PyString(
"getpgrp() -> pgrp\n\n" +
"Return the current process group id.");
- @Hide(value=OS.NT, posixImpl = PosixImpl.JAVA)
+ @Hider.Hide(value=OS.NT, posixImpl = Hider.PosixImpl.JAVA)
public static int getpgrp() {
return posix.getpgrp();
}
@@ -575,7 +575,7 @@
"isatty(fd) -> bool\n\n" +
"Return True if the file descriptor 'fd' is an open file descriptor\n" +
"connected to the slave end of a terminal.");
- @Hide(posixImpl = PosixImpl.JAVA)
+ @Hider.Hide(posixImpl = Hider.PosixImpl.JAVA)
public static boolean isatty(PyObject fdObj) {
Object tojava = fdObj.__tojava__(IOBase.class);
if (tojava != Py.NoConversion) {
@@ -609,7 +609,7 @@
public static PyString __doc__kill = new PyString(
"kill(pid, sig)\n\n" +
"Kill a process with a signal.");
- @Hide(value=OS.NT, posixImpl = PosixImpl.JAVA)
+ @Hider.Hide(value=OS.NT, posixImpl = Hider.PosixImpl.JAVA)
public static void kill(int pid, int sig) {
if (posix.kill(pid, sig) < 0) {
throw errorFromErrno();
@@ -620,7 +620,7 @@
"lchmod(path, mode)\n\n" +
"Change the access permissions of a file. If path is a symlink, this\n" +
"affects the link itself rather than the target.");
- @Hide(value=OS.NT, posixImpl = PosixImpl.JAVA)
+ @Hider.Hide(value=OS.NT, posixImpl = Hider.PosixImpl.JAVA)
public static void lchmod(PyObject path, int mode) {
if (posix.lchmod(absolutePath(path).toString(), mode) < 0) {
throw errorFromErrno(path);
@@ -631,7 +631,7 @@
"lchown(path, uid, gid)\n\n" +
"Change the owner and group id of path to the numeric uid and gid.\n" +
"This function will not follow symbolic links.");
- @Hide(value=OS.NT, posixImpl = PosixImpl.JAVA)
+ @Hider.Hide(value=OS.NT, posixImpl = Hider.PosixImpl.JAVA)
public static void lchown(PyObject path, int uid, int gid) {
if (posix.lchown(absolutePath(path).toString(), uid, gid) < 0) {
throw errorFromErrno(path);
@@ -642,7 +642,7 @@
"link(src, dst)\n\n" +
"Create a hard link to a file.");
- @Hide(OS.NT)
+ @Hider.Hide(OS.NT)
public static void link(PyObject src, PyObject dst) {
try {
Files.createLink(Paths.get(asPath(dst)), Paths.get(asPath(src)));
@@ -857,7 +857,7 @@
public static PyString __doc__readlink = new PyString(
"readlink(path) -> path\n\n" +
"Return a string representing the path to which the symbolic link points.");
- @Hide(OS.NT)
+ @Hider.Hide(OS.NT)
public static PyString readlink(PyObject path) {
try {
return Py.newStringOrUnicode(path, Files.readSymbolicLink(absolutePath(path)).toString());
@@ -908,7 +908,7 @@
public static PyString __doc__setpgrp = new PyString(
"setpgrp()\n\n" +
"Make this process a session leader.");
- @Hide(value=OS.NT, posixImpl = PosixImpl.JAVA)
+ @Hider.Hide(value=OS.NT, posixImpl = Hider.PosixImpl.JAVA)
public static void setpgrp() {
if (posix.setpgrp(0, 0) < 0) {
throw errorFromErrno();
@@ -918,7 +918,7 @@
public static PyString __doc__setsid = new PyString(
"setsid()\n\n" +
"Call the system call setsid().");
- @Hide(value=OS.NT, posixImpl = PosixImpl.JAVA)
+ @Hider.Hide(value=OS.NT, posixImpl = Hider.PosixImpl.JAVA)
public static void setsid() {
if (posix.setsid() < 0) {
throw errorFromErrno();
@@ -946,7 +946,7 @@
"symlink(src, dst)\n\n" +
"Create a symbolic link pointing to src named dst.");
- @Hide(OS.NT)
+ @Hider.Hide(OS.NT)
public static void symlink(PyObject src, PyObject dst) {
try {
Files.createSymbolicLink(Paths.get(asPath(dst)), Paths.get(asPath(src)));
@@ -967,7 +967,7 @@
"times() -> (utime, stime, cutime, cstime, elapsed_time)\n\n" +
"Return a tuple of floating point numbers indicating process times.");
- @Hide(posixImpl = PosixImpl.JAVA)
+ @Hider.Hide(posixImpl = Hider.PosixImpl.JAVA)
public static PyTuple times() {
Times times = posix.times();
long CLK_TCK = Sysconf._SC_CLK_TCK.longValue();
@@ -983,7 +983,7 @@
public static PyString __doc__umask = new PyString(
"umask(new_mask) -> old_mask\n\n" +
"Set the current numeric umask and return the previous umask.");
- @Hide(posixImpl = PosixImpl.JAVA)
+ @Hider.Hide(posixImpl = Hider.PosixImpl.JAVA)
public static int umask(int mask) {
return posix.umask(mask);
}
@@ -1042,138 +1042,69 @@
* @return PyTuple containing sysname, nodename, release, version, machine
*/
public static PyTuple uname() {
- if (uname_cache != null) {
- return uname_cache;
- }
- String sysname = System.getProperty("os.name");
- String sysrelease;
- boolean win;
- if (sysname.equals("Mac OS X")) {
- sysname = "Darwin";
- win = false;
- try {
- Process p = Runtime.getRuntime().exec("uname -r");
- java.io.BufferedReader br = new java.io.BufferedReader(
- new java.io.InputStreamReader(p.getInputStream()));
- sysrelease = br.readLine();
- // to end the process sanely in case we deal with some
- // implementation that emits additional new-lines:
- while (br.readLine() != null) {
- ;
- }
- br.close();
- if (p.waitFor() != 0) {
- sysrelease = "";
- }
- } catch (Exception e) {
- sysrelease = "";
+ if (uname_cache == null) {
+ // First call: have to construct the result.
+ String sysname = System.getProperty("os.name");
+ String sysrelease, nodename, machine;
+ boolean win = false;
+
+ if (sysname.equals("Mac OS X")) {
+ sysname = "Darwin";
+ sysrelease = Py.getCommandResult("uname", "-r");
+ } else if (sysname.startsWith("Windows")) {
+ sysrelease = sysname.length() > 7 ? sysname.substring(8)
+ : System.getProperty("os.version", "");
+ sysname = "Windows";
+ win = true;
+ } else {
+ sysrelease = System.getProperty("os.version", "");
}
- } else {
- win = sysname.startsWith("Windows");
- if (win) {
- sysrelease = sysname.length() > 7 ? sysname.substring(8) :
- System.getProperty("os.version");
- sysname = "Windows";
- } else {
- sysrelease = System.getProperty("os.version");
- }
- }
- String uname_nodename;
- try {
- uname_nodename = java.net.InetAddress.getLocalHost().getHostName();
- } catch (Exception e) {
- // Do nothing to leverage fallback
- uname_nodename = null;
- }
- if (uname_nodename == null && win) {
- uname_nodename = System.getenv("USERDOMAIN");
- }
- if (uname_nodename == null) {
try {
- Process p = Runtime.getRuntime().exec(
- win ? "hostname" : "uname -n");
- java.io.BufferedReader br = new java.io.BufferedReader(
- new java.io.InputStreamReader(p.getInputStream()));
- uname_nodename = br.readLine();
- // to end the process sanely in case we deal with some
- // implementation that emits additional new-lines:
- while (br.readLine() != null) {
- ;
- }
- br.close();
- if (p.waitFor() != 0) {
- uname_nodename = "";
- }
+ nodename = java.net.InetAddress.getLocalHost().getHostName();
} catch (Exception e) {
- uname_nodename = "";
- }
- }
-
- String uname_sysver = PySystemState.getSystemVersionString();
-
- String uname_machine;
- try {
- if (win) {
- String machine = System.getenv("PROCESSOR_ARCHITECTURE");
- if (machine.equals("x86")) {
- // maybe 32-bit process running on 64 bit machine
- machine = System.getenv("PROCESSOR_ARCHITEW6432");
- }
- // if machine == null it's actually a 32-bit machine
- uname_machine = machine == null ? "x86" : machine;
-// We refrain from this normalization in order to match platform.uname behavior on Windows:
-/* if (machine == null) {
- uname_machine = "i686";
- } else if (machine.equals("AMD64") || machine.equals("EM64T")) {
- uname_machine = "x86_64";
- } else if (machine.equals("IA64")) {
- uname_machine = "ia64";
+ // If that fails, try the shell.
+ if (win) {
+ nodename = Py.getenv("USERDOMAIN", "");
+ if (nodename.isEmpty()) {
+ nodename = Py.getCommandResult("hostname");
+ }
} else {
- uname_machine = machine.toLowerCase();
- } */
- } else {
- Process p = Runtime.getRuntime().exec("uname -m");
- java.io.BufferedReader br = new java.io.BufferedReader(
- new java.io.InputStreamReader(p.getInputStream()));
- uname_machine = br.readLine();
- // to end the process sanely in case we deal with some
- // implementation that emits additional new-lines:
- while (br.readLine() != null) {
- ;
- }
- br.close();
- if (p.waitFor() != 0) {
- // To leverage os.arch-fallback:
- uname_machine = null;
+ nodename = Py.getCommandResult("uname", "-n");
}
}
- } catch (Exception e) {
- // To leverage os.arch-fallback:
- uname_machine = null;
+
+ String sysver = PySystemState.getSystemVersionString();
+
+ if (win) {
+ // Check if 32-bit process on a 64 bit machine (compare platform.py)
+ machine = Py.getenv("PROCESSOR_ARCHITEW6432", "");
+ if (machine.isEmpty()) {
+ // Otherwise, this contains the value (or we default to null)
+ machine = Py.getenv("PROCESSOR_ARCHITECTURE", "");
+ }
+ } else {
+ machine = Py.getCommandResult("uname", "-m");
+ }
+
+ if (machine.isEmpty()) {
+ machine = System.getProperty("os.arch", "");
+ if (machine.equals("amd64")) {
+ // 64-bit processor presents as x86_64 on Linux and AMD64 on Windows.
+ machine = win ? "AMD64" : "x86_64";
+ } else if (machine.equals("x86")) {
+ machine = "i686";
+ }
+ }
+
+ uname_cache = new PyTuple(new PyObject[] {
+ Py.fileSystemEncode(sysname),
+ Py.fileSystemEncode(nodename),
+ Py.fileSystemEncode(sysrelease),
+ Py.fileSystemEncode(sysver),
+ Py.fileSystemEncode(machine)},
+ false);
}
- if (uname_machine == null) {
- String machine = System.getProperty("os.arch");
- if (machine == null) {
- uname_machine = "";
- } else if (machine.equals("amd64")) {
- // Normalize the common amd64-case to x86_64:
- uname_machine = "x86_64";
- } else if (machine.equals("x86")) {
- uname_machine = "i686";
- } else {
- uname_machine = machine;
- }
- }
-
- PyObject[] vals = {
- Py.fileSystemEncode(sysname),
- Py.fileSystemEncode(uname_nodename),
- Py.fileSystemEncode(sysrelease),
- Py.fileSystemEncode(uname_sysver),
- Py.fileSystemEncode(uname_machine)
- };
- uname_cache = new PyTuple(vals, false);
return uname_cache;
}
@@ -1251,7 +1182,7 @@
public static PyString __doc__wait = new PyString(
"wait() -> (pid, status)\n\n" +
"Wait for completion of a child process.");
- @Hide(value=OS.NT, posixImpl = PosixImpl.JAVA)
+ @Hider.Hide(value=OS.NT, posixImpl = Hider.PosixImpl.JAVA)
public static PyObject wait$() {
int[] status = new int[1];
int pid = posix.wait(status);
@@ -1264,7 +1195,7 @@
public static PyString __doc__waitpid = new PyString(
"wait() -> (pid, status)\n\n" +
"Wait for completion of a child process.");
- @Hide(posixImpl = PosixImpl.JAVA)
+ @Hider.Hide(posixImpl = Hider.PosixImpl.JAVA)
public static PyObject waitpid(int pid, int options) {
int[] status = new int[1];
pid = posix.waitpid(pid, status, options);
--
Repository URL: https://hg.python.org/jython
More information about the Jython-checkins
mailing list