[Jython-checkins] jython: Route console messages into Java logging (addresses #2778).
jeff.allen
jython-checkins at python.org
Thu Aug 8 02:45:47 EDT 2019
https://hg.python.org/jython/rev/5e3bd2044a51
changeset: 8272:5e3bd2044a51
user: Jeff Allen <ja.py at farowl.co.uk>
date: Wed Aug 07 22:45:47 2019 +0100
summary:
Route console messages into Java logging (addresses #2778).
With this change, console messages generated with Py.writeDebug etc.
are converted to java.util.logging messages of corresponding severity,
and so may be controlled or routed using a logging.properties file.
In particular, the path now is open to obtain timestamped messages.
Direct use of Options.verbose is deprecated, but clients that modify it,
then call the classic Py.write* methods end up adjusting the console
logging level and so the effect what they expect (nearly).
files:
NEWS | 10 +
registry | 7 +-
src/org/python/core/Options.java | 137 +++++++++++-------
src/org/python/core/PrePy.java | 141 ++++++++++++++++++-
src/org/python/util/jython.java | 119 ++++++++++++++-
5 files changed, 343 insertions(+), 71 deletions(-)
diff --git a/NEWS b/NEWS
--- a/NEWS
+++ b/NEWS
@@ -76,6 +76,16 @@
- Experimentally, we use Gradle to build a JAR and POM that may be cited as a dependency by
other projects. The Jython project would like to know if this is being done suitably
for downstream use.
+ - The registry setting (or Java property) "python.verbose", and direct use of the global
+ org.python.core.Options.verbose are DEPRECATED: use a Java logging properties file instead.
+ Console messages are now produced via java.util.logging (JUL), and the logger "org.python"
+ or its descendants. The jython command configures a ConsoleLogger for "org.python" and by
+ default a format for messages generally similar to that in v2.7.1, preceded by the logger
+ name and JUL severity. The volume of messages is controlled by your logging preferences, but
+ by default is unchanged from v2.7.1. Each -v option on the command line makes the logging
+ one step finer on the JUL scale. Error messages from Python and stack traces are unaffected.
+ When embedded in your application, Jython makes no logging configuration changes: messages
+ from the "org.python" name space merge with those of your application.
Jython 2.7.2a1
Bugs fixed
diff --git a/registry b/registry
--- a/registry
+++ b/registry
@@ -31,9 +31,10 @@
#python.packages.directories = java.ext.dirs # up to Java 8
#python.packages.directories # undefined from Java 9
-# Set verbosity to error, warning, message, comment, or debug
-# for varying levels of informative messages from Jython. Normally
-# this option is set from the command line.
+# DEPRECATED way to set the verbosity of messages output by Jython. If
+# specified, "python.verbose" will set logging level for "org.python" when
+# the runtime is initialised. It is better to use java.util.logging
+# preferences (and the -v option) which work from the start of execution.
#python.verbose = message
# Jython ships with a JLine console (http://jline.sourceforge.net/) out of the
diff --git a/src/org/python/core/Options.java b/src/org/python/core/Options.java
--- a/src/org/python/core/Options.java
+++ b/src/org/python/core/Options.java
@@ -3,35 +3,34 @@
import static org.python.core.RegistryKey.*;
+import java.util.logging.Level;
+
/**
- * A class with static fields for each of the settable options. The options from
- * registry and command line is copied into the fields here and the rest of
- * Jython checks these fields.
+ * A class with static fields for each of the settable options. The options from registry and
+ * command line is copied into the fields here and the rest of Jython checks these fields.
*/
public class Options {
// Jython options. Some of these can be set from the command line
// options, but all can be controlled through the Jython registry
/**
- * when an exception occurs in Java code, and it is not caught, should the
- * interpreter print out the Java exception in the traceback?
+ * when an exception occurs in Java code, and it is not caught, should the interpreter print out
+ * the Java exception in the traceback?
*/
public static boolean showJavaExceptions = false;
/**
- * If true, exceptions raised from Python code will include a Java stack
- * trace in addition to the Python traceback. This can slow raising
- * considerably.
+ * If true, exceptions raised from Python code will include a Java stack trace in addition to
+ * the Python traceback. This can slow raising considerably.
*
* @see org.python.core.RegistryKey#PYTHON_OPTIONS_INCLUDE_JAVA_STACK_IN_EXCEPTIONS
*/
public static boolean includeJavaStackInExceptions = true;
/**
- * When true, python exception raised in overridden methods will be shown on
- * stderr. This option is remarkably useful when python is used for
- * implementing CORBA server. Some CORBA servers will turn python exception
- * (say a NameError) into an anonymous user exception without any
+ * When true, python exception raised in overridden methods will be shown on stderr. This option
+ * is remarkably useful when python is used for implementing CORBA server. Some CORBA servers
+ * will turn python exception (say a NameError) into an anonymous user exception without any
* stacktrace. Setting this option will show the stacktrace.
*
* @see org.python.core.RegistryKey#PYTHON_OPTIONS_SHOW_PYTHON_PROXY_EXCEPTIONS
@@ -39,10 +38,9 @@
public static boolean showPythonProxyExceptions = false;
/**
- * If true, Jython respects Java the accessibility flag for fields,
- * methods, and constructors. This means you can only access public members.
- * Set this to false to access all members by toggling the accessible flag
- * on the member.
+ * If true, Jython respects Java the accessibility flag for fields, methods, and constructors.
+ * This means you can only access public members. Set this to false to access all members by
+ * toggling the accessible flag on the member.
*
* @see org.python.core.RegistryKey#PYTHON_SECURITY_RESPECT_JAVA_ACCESSIBILITY
*/
@@ -73,11 +71,16 @@
public static boolean no_site = false;
/**
- * Set verbosity to Py.ERROR, Py.WARNING, Py.MESSAGE, Py.COMMENT, or
- * Py.DEBUG for varying levels of informative messages from Jython. Normally
- * this option is set from the command line.
+ * Verbosity of informative messages from Jython, retained as a field for reasons of
+ * backward-compatibility. Normally this option should be allowed to find its value indirectly
+ * through {@code java.util.logging}, as adjusted by the command line {@code -v} option.
+ *
+ * @deprecated Use {@link Py#getLoggingLevel()},
+ * {@link Py#setLoggingLevel(java.util.logging.Level)}, or {@code java.util.logging}
+ * preferences to configure logging levels.
*/
- public static int verbose = PrePy.MESSAGE;
+ @Deprecated
+ public static int verbose = PrePy.verbosityFromLevel(PrePy.getLoggingLevel());
/**
* Set by the {@code -i} option to the interpreter command, to ask for an interactive session to
@@ -95,16 +98,15 @@
public static boolean inspect = false;
/**
- * A directory where the dynamically generated classes are written. Nothing is
- * ever read from here, it is only for debugging purposes.
+ * A directory where the dynamically generated classes are written. Nothing is ever read from
+ * here, it is only for debugging purposes.
*/
public static String proxyDebugDirectory;
/**
- * If true, Jython will use the first module found on sys.path where java
- * File.isFile() returns true. Setting this to true have no effect on
- * unix-type filesystems. On Windows/HFS+ systems setting it to true will
- * enable Jython-2.0 behaviour.
+ * If true, Jython will use the first module found on sys.path where java File.isFile() returns
+ * true. Setting this to true have no effect on unix-type filesystems. On Windows/HFS+ systems
+ * setting it to true will enable Jython-2.0 behaviour.
*
* @see org.python.core.RegistryKey#PYTHON_OPTIONS_CASE_OK
*/
@@ -117,8 +119,7 @@
*/
public static boolean Qnew = false;
- /** Force stdin, stdout and stderr to be unbuffered, and opened in
- * binary mode */
+ /** Force stdin, stdout and stderr to be unbuffered, and opened in binary mode */
public static boolean unbuffered = false;
/** Whether -3 (py3k warnings) was enabled via the command line. */
@@ -136,7 +137,7 @@
*/
public static boolean no_user_site = false;
- //XXX: place holder
+ // XXX: place holder
public static int bytes_warning = 0;
/**
@@ -157,9 +158,8 @@
public static int division_warning = 0;
/**
- * Cache spec for the SRE_STATE code point cache. The value maps to the
- * CacheBuilderSpec string and affects how the SRE_STATE cache will behave/evict
- * cached PyString -> int[] code points.
+ * Cache spec for the SRE_STATE code point cache. The value maps to the CacheBuilderSpec string
+ * and affects how the SRE_STATE cache will behave/evict cached PyString -> int[] code points.
*/
public static final String sreCacheSpecDefault =
"weakKeys,concurrencyLevel=4,maximumWeight=2621440,expireAfterAccess=30s";
@@ -189,45 +189,82 @@
/** Initialize the static fields from the registry options. */
public static void setFromRegistry() {
- // Set the more unusual options
+
showJavaExceptions =
getBooleanOption(PYTHON_OPTIONS_SHOW_JAVA_EXCEPTIONS, showJavaExceptions);
includeJavaStackInExceptions = getBooleanOption(
PYTHON_OPTIONS_INCLUDE_JAVA_STACK_IN_EXCEPTIONS, includeJavaStackInExceptions);
- showPythonProxyExceptions = getBooleanOption(
- PYTHON_OPTIONS_SHOW_PYTHON_PROXY_EXCEPTIONS, showPythonProxyExceptions);
- respectJavaAccessibility = getBooleanOption(
- PYTHON_SECURITY_RESPECT_JAVA_ACCESSIBILITY, respectJavaAccessibility);
+ showPythonProxyExceptions = getBooleanOption(PYTHON_OPTIONS_SHOW_PYTHON_PROXY_EXCEPTIONS,
+ showPythonProxyExceptions);
+ respectJavaAccessibility = getBooleanOption(PYTHON_SECURITY_RESPECT_JAVA_ACCESSIBILITY,
+ respectJavaAccessibility);
proxyDebugDirectory =
getStringOption(PYTHON_OPTIONS_PROXY_DEBUG_DIRECTORY, proxyDebugDirectory);
- // verbosity is more complicated:
+ // Legacy python.verbose if used may countermand logging.properties::org.python.level
+ setLoggingFromRegistry();
+
+ caseok = getBooleanOption(PYTHON_OPTIONS_CASE_OK, caseok);
+ Qnew = getBooleanOption(PYTHON_OPTIONS_Q_NEW, Qnew);
+
+ setDivisionWarningFromRegistry();
+
+ sreCacheSpec = getStringOption(PYTHON_SRE_CACHESPEC, sreCacheSpec);
+ inspect |= getStringOption(PYTHON_INSPECT, "").length() > 0;
+ importSite = getBooleanOption(PYTHON_IMPORT_SITE, importSite);
+ no_site = !importSite;
+ }
+
+ /**
+ * Set the logging level from {@link RegistryKey#PYTHON_VERBOSE}. We recognise the traditional
+ * Jython names and those used by {@code java.util.logging}. If that key is present in the
+ * Jython registry it will determine the level or the logger named "org.python".
+ */
+ private static void setLoggingFromRegistry() {
String prop;
switch ((prop = getStringOption(PYTHON_VERBOSE, "")).toLowerCase()) {
- case "":
+ case "": // Leave it as it is.
+ break;
+ case "off":
+ PrePy.setLoggingLevel(Level.OFF);
break;
case "error":
- verbose = PrePy.ERROR;
+ case "severe":
+ PrePy.setLoggingLevel(Level.SEVERE);
break;
case "warning":
- verbose = PrePy.WARNING;
+ case "warn":
+ PrePy.setLoggingLevel(Level.WARNING);
break;
case "message":
- verbose = PrePy.MESSAGE;
+ case "info":
+ PrePy.setLoggingLevel(Level.INFO);
break;
case "comment":
- verbose = PrePy.COMMENT;
+ case "config":
+ PrePy.setLoggingLevel(Level.CONFIG);
break;
case "debug":
- verbose = PrePy.DEBUG;
+ case "fine":
+ PrePy.setLoggingLevel(Level.FINE);
+ break;
+ case "finer":
+ PrePy.setLoggingLevel(Level.FINER);
+ break;
+ case "finest":
+ PrePy.setLoggingLevel(Level.FINEST);
+ break;
+ case "all":
+ PrePy.setLoggingLevel(Level.ALL);
break;
default:
throw new IllegalArgumentException("Invalid verbose option: '" + prop + "'");
}
+ }
- caseok = getBooleanOption(PYTHON_OPTIONS_CASE_OK, caseok);
- Qnew = getBooleanOption(PYTHON_OPTIONS_Q_NEW, Qnew);
-
+ /** Set {@link division_warning} from {@link RegistryKey#PYTHON_DIVISION_WARNING}. */
+ private static void setDivisionWarningFromRegistry() {
+ String prop;
switch ((prop = getStringOption(PYTHON_DIVISION_WARNING, "")).toLowerCase()) {
case "":
break;
@@ -244,10 +281,6 @@
throw new IllegalArgumentException(
"Invalid division_warning option: '" + prop + "'");
}
+ }
- sreCacheSpec = getStringOption(PYTHON_SRE_CACHESPEC, sreCacheSpec);
- inspect |= getStringOption(PYTHON_INSPECT, "").length() > 0;
- importSite = getBooleanOption(PYTHON_IMPORT_SITE, importSite);
- no_site = !importSite;
- }
}
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
@@ -11,6 +11,8 @@
import java.net.URLConnection;
import java.security.AccessControlException;
import java.util.Properties;
+import java.util.logging.Level;
+import java.util.logging.Logger;
import jnr.posix.util.Platform;
@@ -30,7 +32,10 @@
// Do not refer to any PyObject, Py export or PySystemState in this class.
public class PrePy {
- // Logging convenience functions are here so they may work before the Jython runtime starts.
+ // Logging functions are here so they may be used without starting the Jython runtime.
+
+ /** Our name-spaced root logger is "org.python". */
+ protected static final Logger logger = Logger.getLogger("org.python");
/** {@link Options#verbose} level indicating an error that prevents correct results. */
public static final int ERROR = -1;
@@ -43,10 +48,136 @@
/** {@link Options#verbose} level providing detail in support of debugging or tracing. */
public static final int DEBUG = 3;
- /** Log a message at a specified level (if that level be not below the threshold). */
- public static void maybeWrite(String type, String msg, int level) {
- if (level <= Options.verbose) {
- System.err.println(type + ": " + msg);
+ static final Level[] LEVELS = {//
+ Level.OFF, //
+ Level.SEVERE, // Legacy: ERROR
+ Level.WARNING, // Legacy: WARNING
+ Level.INFO, // Legacy: MESSAGE
+ Level.CONFIG, // Legacy: COMMENT
+ Level.FINE, // Legacy: DEBUG
+ Level.FINER, Level.FINEST, Level.ALL};
+
+ /**
+ * Translate from the traditional "verbosity" system to JUL Level. We allow Jython verbosity
+ * values beyond the conventional range, treating values <{@link #ERROR} as {@code ERROR}
+ * (that is {@code Level.SEVERE}) and values >{@link #DEBUG} (that is {@code Level.FINE}) as
+ * {@code FINER}, {@code FINEST} and {@code ALL}.
+ *
+ * @param verbosity any integer verbosity, where the runtime default {@link #MESSAGE} = 1
+ * @return a corresponding level where the default {@link #MESSAGE} produces {@code Level.INFO}.
+ */
+ public static Level levelFromVerbosity(int verbosity) {
+ if (verbosity < ERROR) {
+ return Level.OFF;
+ } else if (verbosity >= LEVELS.length + (ERROR - 1)) {
+ return Level.ALL;
+ } else {
+ // Bound the index to the LEVELS array.
+ int index = verbosity - (ERROR - 1);
+ return LEVELS[index];
+ }
+ }
+
+ /**
+ * Translate from JUL Level to equivalent in the traditional "verbosity" system. We return
+ * Jython verbosity values beyond the conventional range, enough to enumerate the Java standard
+ * levels (e.g {@code FINER} returns 4 and {@code ALL} returns 6 ).
+ *
+ * @param level {@code java.util.logging.Level} to translate.
+ * @return integer verbosity, where the runtime default {@code INFO} = 1
+ */
+ public static int verbosityFromLevel(Level level) {
+ /*
+ * Find the least verbose setting v such that events at the given level or above will be
+ * logged by Jython, that is, v such that levelFromVerbosity(v) is a threshold no higher
+ * than the given level. We allow Jython verbosity values beyond the conventional range (e.g
+ * level==FINER), according to the range of values in the LEVELS array.
+ */
+ int intLevel = level.intValue();
+ int index = 0, v = ERROR - 1; // = OFF
+ while (index < LEVELS.length && LEVELS[index].intValue() > intLevel) {
+ assert LEVELS[index] == levelFromVerbosity(v);
+ index += 1;
+ v += 1;
+ }
+ return v;
+ }
+
+ /**
+ * Convenience function to get the effective level of a given Logger, looking up the parent
+ * chain.
+ */
+ private static Level getEffectiveLoggingLevel(Logger logger) {
+ Level level;
+ while ((level = logger.getLevel()) == null) {
+ logger = logger.getParent();
+ }
+ return level;
+ }
+
+ /** Convenience function to get the effective level of Logger "org.python". */
+ public static Level getLoggingLevel() {
+ return getEffectiveLoggingLevel(logger);
+ }
+
+ /**
+ * Used by {@link #maybeWrite(Level, String)}, the terminus of all verbosity-based logging
+ * calls, to detect changes made directly to {@link Options#verbose}.
+ */
+ private static int savedVerbosity = Py.MESSAGE;
+
+ /**
+ * Set the level of the Jython logger "org.python" using the standard {@code java.util.logging}
+ * scale. For backward compatibility with the traditional "verbosity" system, make a
+ * corresponding setting of {@link Options#verbose}.
+ */
+ @SuppressWarnings("deprecation")
+ public static void setLoggingLevel(Level newLevel) {
+ Level currentLevel = getLoggingLevel();
+ if (newLevel != currentLevel) {
+ try {
+ logger.setLevel(newLevel);
+ currentLevel = newLevel;
+ } catch (SecurityException se) {
+ logger.warning("A security manager prevented a change to the logging level.");
+ }
+ }
+ savedVerbosity = Options.verbose = verbosityFromLevel(currentLevel);
+ }
+
+ /**
+ * Adjust the level of the Jython logger "org.python" using the traditional "verbosity" system:
+ * the bigger the number, the lower the logging threshold. This is primarily for the
+ * command-line Jython, where each "-v" increases the verbosity by one, on the
+ * {@code java.util.logging} scale.
+ *
+ * @param n increment on the scale {@code 1=INFO, 2=CONFIG, 3=FINE, ... }
+ */
+ public static void increaseLoggingLevel(int n) {
+ int v = verbosityFromLevel(getLoggingLevel());
+ setLoggingLevel(levelFromVerbosity(v + n));
+ }
+
+ /**
+ * Ensure that the logging system threshold is adjusted to match the legacy
+ * {@link Options#verbose} in the event that that has changed since we last looked.
+ */
+ @SuppressWarnings("deprecation")
+ private static void syncLoggingLevel() {
+ if (Options.verbose != savedVerbosity) {
+ Level level = levelFromVerbosity(savedVerbosity = Options.verbose);
+ setLoggingLevel(level);
+ }
+ }
+
+ /** Log a message at a specified level (if that level is not below the threshold). */
+ @SuppressWarnings("deprecation")
+ public static void maybeWrite(String type, String msg, int verbosity) {
+ // If the caller is using the legacy logging system they may have changed Options.verbose.
+ syncLoggingLevel();
+ if (verbosity <= Options.verbose) {
+ // Formulate the message in legacy style, then as a log message
+ logger.log(levelFromVerbosity(verbosity), "{0}: {1}", new Object[] {type, msg});
}
}
diff --git a/src/org/python/util/jython.java b/src/org/python/util/jython.java
--- a/src/org/python/util/jython.java
+++ b/src/org/python/util/jython.java
@@ -10,6 +10,10 @@
import java.util.LinkedList;
import java.util.List;
import java.util.Properties;
+import java.util.logging.ConsoleHandler;
+import java.util.logging.Handler;
+import java.util.logging.Level;
+import java.util.logging.Logger;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
@@ -38,6 +42,54 @@
OK, ERROR, NOT_RUN, NO_FILE
}
+ /** The root of the Jython Logger hierarchy, named "org.python". */
+ public static final Logger logger;// = Logger.getLogger("org.python");
+
+ /**
+ * The default format for console log messages in the command-line Jython. See
+ * {@code java.util.logging.SimpleFormatter} for an explanation of the syntax.
+ * <p>
+ * This format is used in the absence of other logging preferences. Jython tests for definitions
+ * in the system properties of {@code java.util.logging.config.class},
+ * {@code java.util.logging.config.file}, and {@code java.util.logging.SimpleFormatter.format}
+ * and if none of these is defined, it sets the last of them to this value.
+ * <p>
+ * You can choose something else, for example to log with millisecond time stamps, launch Jython
+ * as: <pre>
+ * jython -vv -J-Djava.util.logging.SimpleFormatter.format="[%1$tT.%1$tL] %3$s: (%4$s) %5$s%n"
+ * </pre> Depending on your shell, the argument may need quoting or escaping.
+ */
+ public static final String CONSOLE_LOG_FORMAT = "%3$s %4$s %5$s%n";
+
+ static {
+ SecurityException exception = null;
+ try {
+ // Jython console messages (-v option) are emitted using SimpleFormatter
+ configureSimpleFormatter(CONSOLE_LOG_FORMAT);
+ } catch (SecurityException se) {
+ // Unable to access the necessary system properties. Give up on custom logging.
+ exception = se;
+ }
+
+ // Whether we can configure it or not, we can still _use_ logging.
+ logger = Logger.getLogger("org.python");
+
+ if (exception == null) {
+ try {
+ // Make our "org.python" logger do its own output and not propagate to root.
+ setConsoleHandler(logger);
+ } catch (SecurityException se) {
+ // This probably means no logging finer than INFO (so none enabled by -v)
+ exception = se;
+ }
+ }
+
+ if (exception != null) {
+ logger.log(Level.WARNING, "Unable to format console messages: {0}",
+ exception.getMessage());
+ }
+ }
+
// An instance of this class will provide the console (python.console) by default.
private static final String PYTHON_CONSOLE_CLASS = "org.python.util.JLineConsole";
@@ -75,7 +127,7 @@
+ "-u : unbuffered binary stdout and stderr\n"
// + "(also PYTHONUNBUFFERED=x)\n"
// + " see man page for details on internal buffering relating to '-u'\n"
- + "-v : verbose (trace import statements)\n"
+ + "-v : verbose (emit more \"org.python\" log messages)\n"
// + "(also PYTHONVERBOSE=x)\n"
+ " can be supplied multiple times to increase verbosity\n"
+ "-V : print the Python version number and exit (also --version)\n"
@@ -113,6 +165,45 @@
}
/**
+ * Try to set the format for SimpleFormatter if no other mechanism has been provided, and
+ * security allows it.
+ *
+ * @param format to set for {@code java.util.logging.SimpleFormatter}
+ * @throws SecurityException if not allowed to read or set necessary properties.
+ */
+ private static void configureSimpleFormatter(String format) throws SecurityException {
+ final String CLASS_KEY = "java.util.logging.config.class";
+ String className = System.getProperty(CLASS_KEY);
+ if (className == null) {
+ final String FILE_KEY = "java.util.logging.config.file";
+ String fileName = System.getProperty(FILE_KEY);
+ if (fileName == null) {
+ final String FORMAT_KEY = "java.util.logging.SimpleFormatter.format";
+ String currentFormat = System.getProperty(FORMAT_KEY);
+ if (currentFormat == null) {
+ // Note that this sets the format for _all_ console logging
+ System.setProperty(FORMAT_KEY, format);
+ }
+ }
+ }
+ }
+
+ /**
+ * Customise the logger so that it does not propagate to its parent and has its own
+ * {@code Handler} accepting all messages. The level set on the logger alone therefore controls
+ * whether messages are emitted to the console.
+ *
+ * @param logger to adjust (always "python.org")
+ * @throws SecurityException if no permission to adjust logging
+ */
+ private static void setConsoleHandler(Logger logger) throws SecurityException {
+ logger.setUseParentHandlers(false);
+ Handler handler = new ConsoleHandler();
+ handler.setLevel(Level.ALL);
+ logger.addHandler(handler);
+ }
+
+ /**
* Runs a JAR file, by executing the code found in the file __run__.py, which should be in the
* root of the JAR archive. Note that {@code __name__} is set to the base name of the JAR file
* and not to "__main__" (for historical reasons). This method does <b>not</b> handle
@@ -384,6 +475,8 @@
public static void main(String[] args) {
// Parse the command line options
CommandLineOptions opts = CommandLineOptions.parse(args);
+
+ // Choose the basic action
switch (opts.action) {
case VERSION:
System.err.printf("Jython %s\n", Version.PY_VERSION);
@@ -397,6 +490,9 @@
// Let's run some Python! ...
}
+ // Adjust relative to the level set by java.util.logging.
+ PrePy.increaseLoggingLevel(opts.verbosity);
+
// Get system properties (or empty set if we're prevented from accessing them)
Properties preProperties = PrePy.getSystemProperties();
addDefaultsFromEnvironment(preProperties);
@@ -417,8 +513,7 @@
// We'll be going interactive eventually. condition an interactive console.
if (PrePy.haveConsole()) {
// Set the default console type if nothing else has
- addDefault(preProperties, RegistryKey.PYTHON_CONSOLE,
- PYTHON_CONSOLE_CLASS);
+ addDefault(preProperties, RegistryKey.PYTHON_CONSOLE, PYTHON_CONSOLE_CLASS);
}
}
@@ -455,7 +550,7 @@
*/
InteractiveConsole interp = new InteractiveConsole();
- if (Options.verbose > Py.MESSAGE || (!haveScript && stdinIsInteractive)) {
+ if (opts.verbosity > 0 || (!haveScript && stdinIsInteractive)) {
// Verbose or going interactive immediately: produce sign on messages.
System.err.println(InteractiveConsole.getDefaultBanner());
if (Options.importSite) {
@@ -721,6 +816,8 @@
boolean version = false;
/** -jar option. */
boolean jar = false;
+ /** Count of -v options. */
+ int verbosity = 0;
/** Collects definitions made with the -D option directly to Jython (not java -D). */
Properties properties = new Properties();
@@ -736,12 +833,12 @@
/** Valid long-name options. */
static final char JAR_OPTION = '\u2615';
- static final OptionScanner.LongSpec[] PROGRAM_LONG_OPTS = {
- new OptionScanner.LongSpec("--", OptionScanner.DONE),
- new OptionScanner.LongSpec("--help", 'h'),
- new OptionScanner.LongSpec("--version", 'V'),
- new OptionScanner.LongSpec("-jar", JAR_OPTION, true), // Yes, just one dash.
- };
+ static final OptionScanner.LongSpec[] PROGRAM_LONG_OPTS =
+ {new OptionScanner.LongSpec("--", OptionScanner.DONE),
+ new OptionScanner.LongSpec("--help", 'h'),
+ new OptionScanner.LongSpec("--version", 'V'),
+ new OptionScanner.LongSpec("-jar", JAR_OPTION, true), // Yes, just one dash.
+ };
/**
* Parse the arguments into the static {@link Options} and a returned instance of this
@@ -892,7 +989,7 @@
break;
case 'v':
- Options.verbose++;
+ verbosity++;
break;
case 'x':
--
Repository URL: https://hg.python.org/jython
More information about the Jython-checkins
mailing list