From jython-checkins at python.org Sun Sep 1 08:36:56 2019 From: jython-checkins at python.org (jeff.allen) Date: Sun, 01 Sep 2019 12:36:56 +0000 Subject: [Jython-checkins] =?utf-8?q?jython=3A_Fix_bugtests/support=2Epy_?= =?utf-8?q?to_work_on_Windows=2E?= Message-ID: <20190901123656.1.63F4734CB260F81A@mg.python.org> https://hg.python.org/jython/rev/8e8c93e73f21 changeset: 8285:8e8c93e73f21 user: Jeff Allen date: Thu Aug 29 21:32:11 2019 +0100 summary: Fix bugtests/support.py to work on Windows. We also eliminate a couple of broken tests. However, the ant bugtest target cannot be recommended (fails), and is likely to be removed. files: bugtests/README.txt | 8 ++++++ bugtests/support.py | 22 ++++++++-------- bugtests/test236.py | 23 ------------------ bugtests/test401.py | 18 -------------- bugtests/test401/to_be_executed.py | 4 --- build.xml | 7 ++++- 6 files changed, 25 insertions(+), 57 deletions(-) diff --git a/bugtests/README.txt b/bugtests/README.txt --- a/bugtests/README.txt +++ b/bugtests/README.txt @@ -2,6 +2,14 @@ This directory contains small tests that attempt to ensure that old fixed bugs do not reappear. +These tests are not actively maintained and while many pass, others have been +broken by changes in the main codebase and now fail for what might be spurious +reasons. + +As the regression tests have grown, the need for these has largely ceased. +It is likely these tests will be removed eventually. + + Running ======= diff --git a/bugtests/support.py b/bugtests/support.py --- a/bugtests/support.py +++ b/bugtests/support.py @@ -84,7 +84,7 @@ cmd = "%s/bin/javac -classpath %s %s" % (cfg.java_home, classpath, src) elif WIN: src = src.replace("/", "\\") - cmd = 'cmd /C "%s/bin/javac.exe -classpath %s %s"' % (cfg.java_home, classpath, src) + cmd = 'cmd /C "%s/bin/javac.exe" -classpath %s %s' % (cfg.java_home, classpath, src) return execCmd(cmd, kw) def runJava(cls, **kw): @@ -98,7 +98,7 @@ if UNIX: cmd = ['/bin/sh', '-c', "%s/bin/java -classpath %s %s %s" % (cfg.java_home, classpath, defs, cls)] elif WIN: - cmd = 'cmd /C "%s/bin/java.exe -classpath %s %s %s"' % (cfg.java_home, classpath, defs, cls) + cmd = 'cmd /C "%s/bin/java.exe" -classpath %s %s %s' % (cfg.java_home, classpath, defs, cls) return execCmd(cmd, kw) def runJavaJar(jar, *args, **kw): @@ -106,7 +106,7 @@ if UNIX: cmd = ['/bin/sh', '-c', "%s/bin/java -jar %s %s" % (cfg.java_home, jar, argString)] elif WIN: - cmd = 'cmd /C "%s/bin/java.exe -jar %s %s"' % (cfg.java_home, jar, argString) + cmd = 'cmd /C "%s/bin/java.exe" -jar %s %s' % (cfg.java_home, jar, argString) return execCmd(cmd, kw) def runJython(cls, **kw): @@ -119,7 +119,7 @@ if UNIX: cmd = "%s/bin/java -classpath %s %s -Dpython.home=%s org.python.util.jython %s" % (cfg.java_home, classpath, javaargs, cfg.jython_home, cls) elif WIN: - cmd = 'cmd /C "%s/bin/java.exe -classpath %s %s -Dpython.home=%s org.python.util.jython %s"' % (cfg.java_home, classpath, javaargs, cfg.jython_home, cls) + cmd = 'cmd /C "%s/bin/java.exe" -classpath %s %s -Dpython.home=%s org.python.util.jython %s' % (cfg.java_home, classpath, javaargs, cfg.jython_home, cls) return execCmd(cmd, kw) def compileJPythonc(*files, **kw): @@ -148,12 +148,12 @@ classpath = cfg.classpath if "classpath" in kw: classpath = os.pathsep.join([cfg.classpath, kw["classpath"]]) - + jythonc = "%s/Tools/jythonc/jythonc.py %s" % (cfg.jython_home, cmd) if UNIX: cmd = "%s/bin/java -classpath %s -Dpython.home=%s org.python.util.jython %s" % (cfg.java_home, classpath, cfg.jython_home, jythonc) elif WIN: - cmd = 'cmd /C "%s/bin/java.exe -classpath \"%s\" -Dpython.home=%s org.python.util.jython %s"' % (cfg.java_home, classpath, cfg.jython_home, jythonc) + cmd = 'cmd /C "%s/bin/java.exe" -classpath "%s" -Dpython.home=%s org.python.util.jython %s' % (cfg.java_home, classpath, cfg.jython_home, jythonc) return execCmd(cmd, kw) def grep(file, text, count=0): @@ -173,7 +173,7 @@ class JarPacker: __doc__ = """helper class to pack stuff into a jar file - the terms 'file' and 'dir' mean java.io.File here """ - + def __init__(self, jarFile, bufsize=1024): self._jarFile = jarFile self._bufsize = bufsize @@ -186,11 +186,11 @@ def addManifestFile(self, manifestFile): __doc__ = """only one manifest file can be added""" self.addManifest(Manifest(FileInputStream(manifestFile))) - + def addManifest(self, manifest): if not self._manifest: self._manifest = manifest - + def addFile(self, file, parentDirName=None): buffer = jarray.zeros(self._bufsize, 'b') inputStream = FileInputStream(file) @@ -204,7 +204,7 @@ read = inputStream.read(buffer) self.getJarOutputStream().closeEntry() inputStream.close() - + def addDirectory(self, dir, parentDirName=None): if not dir.isDirectory(): return @@ -221,7 +221,7 @@ else: newParentDirName = dir.getName() self.addDirectory(currentFile, newParentDirName) - + def addJarFile(self, jarFile): __doc__ = """if you want to add a .jar file with a MANIFEST, add it first""" jarJarFile = JarFile(jarFile) diff --git a/bugtests/test236.py b/bugtests/test236.py deleted file mode 100644 --- a/bugtests/test236.py +++ /dev/null @@ -1,23 +0,0 @@ - -import support, os - -support.compileJava("classes/test236j1.java", force=1) -os.remove("classes/test236j2.class") - -onimport = 1 - -import java -try: - import test236j1 - onimport = 0 - test236j1() -except ImportError: - raise support.TestError, "Should not raise a simple ImportError" -except java.lang.NoClassDefFoundError: - if not onimport: - raise support.TestWarning, "import itself does not imply class initialization" -else: - raise support.TestError, "Should raise some exception" - - - diff --git a/bugtests/test401.py b/bugtests/test401.py deleted file mode 100644 --- a/bugtests/test401.py +++ /dev/null @@ -1,18 +0,0 @@ -# -# Test for bug 1758838 -# -# execfile() should not throw a NullPointerException -# -# The error only shows up in interactive interpretation (type "single" for the compilation). -# But we cannot use InteractiveInterpreter here since it catches all Exceptions, -# therefore we do the compilation 'by hand'. -# - -from org.python.core import Py -from org.python.core import PySystemState -from org.python.util import PythonInterpreter - -PySystemState.initialize() -interp = PythonInterpreter() -code = Py.compile_command_flags("execfile('test401/to_be_executed.py')", "", "single", None, 1) -interp.exec(code) diff --git a/bugtests/test401/to_be_executed.py b/bugtests/test401/to_be_executed.py deleted file mode 100644 --- a/bugtests/test401/to_be_executed.py +++ /dev/null @@ -1,4 +0,0 @@ -# the contents of this file are not important for bug 1758838 - -class TestBug1758838: - pass diff --git a/build.xml b/build.xml --- a/build.xml +++ b/build.xml @@ -1493,6 +1493,11 @@ or set jdk.home explicitly --> + + + + + creating ${bugtests.dir}/support_config.py @@ -1500,7 +1505,7 @@ # safe to edit by hand (won't be overwritten) java_home="${jdk.home}" jython_home="${dist.dir}" -classpath="${dist.dir}/${jython.dev.jar}${path.separator}classes" +classpath="${ant.refid:bugtest.classpath}" -- Repository URL: https://hg.python.org/jython From jython-checkins at python.org Sun Sep 1 08:36:57 2019 From: jython-checkins at python.org (jeff.allen) Date: Sun, 01 Sep 2019 12:36:57 +0000 Subject: [Jython-checkins] =?utf-8?q?jython=3A_Opt-in_setlocale=28=29_sup?= =?utf-8?q?port_=28issue_=232730_and_others=29=2E?= Message-ID: <20190901123657.1.114353275B6667AA@mg.python.org> https://hg.python.org/jython/rev/d60fce7f6c37 changeset: 8286:d60fce7f6c37 user: Adam Burke date: Sat Aug 31 19:55:19 2019 +0100 summary: Opt-in setlocale() support (issue #2730 and others). This is a patch to add improved locale support, allowing use of setlocale() as a beta feature. It also fixes some regrtest failures on Windows and possibly elsewhere when developers use different locales. When the user opts in by defining python.locale.control=settable, default locale setlocale(LC_ALL,'') is supported and C locale used on startup. files: Lib/test/regrtest.py | 14 +- Lib/test/test_calendar_jy.py | 24 + Lib/test/test_email.py | 7 +- Lib/test/test_email_jy.py | 12 + Lib/test/test_strptime_jy.py | 24 +- Lib/test/test_support.py | 29 + NEWS | 4 + src/org/python/core/PyObject.java | 2 +- src/org/python/core/PySystemState.java | 1 - src/org/python/core/RegistryKey.java | 23 + src/org/python/core/exceptions.java | 13 +- src/org/python/modules/Setup.java | 1 + src/org/python/modules/_locale/CEmulationLocale.java | 131 ++ src/org/python/modules/_locale/DateSymbolJyLocale.java | 53 + src/org/python/modules/_locale/DateSymbolLocale.java | 20 + src/org/python/modules/_locale/JyLocale.java | 223 +++ src/org/python/modules/_locale/PyLocale.java | 28 + src/org/python/modules/_locale/_locale.java | 377 ++++++ src/org/python/modules/time/Time.java | 39 +- src/org/python/util/PythonInterpreter.java | 9 +- tests/java/org/python/modules/_locale/_localeTest.java | 626 ++++++++++ 21 files changed, 1620 insertions(+), 40 deletions(-) diff --git a/Lib/test/regrtest.py b/Lib/test/regrtest.py --- a/Lib/test/regrtest.py +++ b/Lib/test/regrtest.py @@ -1371,11 +1371,15 @@ 'java.nt': # Expected to fail on Windows """ - test_mailbox # fails miserably and ruins other tests - # test_os_jy # Locale tests fail on Cygwin (but not Windows) - # test_popen # Passes, but see http://bugs.python.org/issue1559298 - test_select_new # Hangs (Windows), though ok run singly - test_urllib2 # file not on local host (likely Windows only) + test_calendar # Same, covered by test_calendar_jy + test_email # test_email_jy overrides for correct locale handling + test_mailbox # fails miserably and ruins other tests + # test_popen # Passes, but see http://bugs.python.org/issue1559298 + test_select_new # Hangs (Windows), though ok run singly + test_strptime # Fails on JDK 9+ due to locale strings change + # Covered by test_strptime_jy until the beta locale + # behaviour becomes the default + test_urllib2 # file not on local host (likely Windows only) """, 'java.posix': # Expected to fail on Linux diff --git a/Lib/test/test_calendar_jy.py b/Lib/test/test_calendar_jy.py new file mode 100644 --- /dev/null +++ b/Lib/test/test_calendar_jy.py @@ -0,0 +1,24 @@ +# Java locale differences from JDK 9 onwards, and locale variation on +# developer machines, break test_calendar tests. This manifests more on Windows. +# Rather than diverge from the Python source, this overrides with extra locale +# setup. + +from test.test_calendar import * +from test import test_support + + +def test_main(initialize=True): + test_support.force_reset_locale(initialize) + test_support.run_unittest( + OutputTestCase, + CalendarTestCase, + MondayTestCase, + SundayTestCase, + MonthRangeTestCase, + LeapdaysTestCase, + ) + + +if __name__ == '__main__': + test_main(initialize=False) + diff --git a/Lib/test/test_email.py b/Lib/test/test_email.py --- a/Lib/test/test_email.py +++ b/Lib/test/test_email.py @@ -3,14 +3,13 @@ # The specific tests now live in Lib/email/test from email.test.test_email import TestEncoders, suite +from email.test.test_email_renamed import suite as suite2 from test import test_support def test_main(): - #This one doesn't work on Jython - del TestEncoders.test_encode7or8bit - - s = suite() test_support.run_unittest(suite()) + test_support.run_unittest(suite2()) if __name__ == '__main__': test_main() + diff --git a/Lib/test/test_email_jy.py b/Lib/test/test_email_jy.py new file mode 100644 --- /dev/null +++ b/Lib/test/test_email_jy.py @@ -0,0 +1,12 @@ +# Copyright (C) 2001,2002 Python Software Foundation +# Jython override to enforce C locale during locale beta +from test import test_email +from test import test_support + +def test_main(initialize=True): + test_support.force_reset_locale(initialize) + test_email.test_main() + +if __name__ == '__main__': + test_main(False) + diff --git a/Lib/test/test_strptime_jy.py b/Lib/test/test_strptime_jy.py --- a/Lib/test/test_strptime_jy.py +++ b/Lib/test/test_strptime_jy.py @@ -1,8 +1,14 @@ -# merge into upstream test_strptime.py at some point +# Java locale differences from JDK 9 onwards, and locale variation on +# developer machines, break test_strptime tests. This manifests more on Windows. +# Rather than diverge from the Python source, this overrides with extra locale +# setup. +# Merging back into CPython is desirable, but is a bigger discussion around +# library merging generally. import unittest from datetime import datetime from time import strptime +from test.test_strptime import * from test import test_support @@ -26,11 +32,23 @@ d = strptime('1', '%d') self.assertEqual(1900, d.tm_year) -def test_main(): + +def test_main(initialize=True): + test_support.force_reset_locale(initialize) + test_support.run_unittest( + getlang_Tests, + LocaleTime_Tests, + TimeRETests, + StrptimeTests, + Strptime12AMPMTests, + JulianTests, + CalculationTests, + CacheTests, ParsingTests ) if __name__ == '__main__': - test_main() + test_main(initialize=False) + diff --git a/Lib/test/test_support.py b/Lib/test/test_support.py --- a/Lib/test/test_support.py +++ b/Lib/test/test_support.py @@ -1129,6 +1129,35 @@ return decorator #======================================================================= +# Reset locale to C / POSIX locale. In Jython to date the default locale +# has been Locale.getDefaultLocale(), ie OS determined +# The new locale.setlocale() support is in beta and off by default, +# but some tests need the changes it introduces to pass. +# It requires certain "startup" initialization corresponding to +# -J-Dpython.locale.control=settable which is hard to simulate in a unit +# test. To see the calling test pass without the reload throat-clearing, +# invoke Jython with python.locale.control=settable on the command line, +# in either direct or regrtest flavours. +# Use of this function can be removed from most tests once +# locale.setlocale() support is on by default +def force_reset_locale(initialize=True): + import locale + if initialize: + from datetime import datetime + import time + from java.lang import System + System.setProperty('python.locale.control','settable') + import _locale + reload(_locale) + reload(locale) + # Trigger date format cache reload - need lang change + import _strptime + locale.setlocale(locale.LC_ALL,'de_DE') + _strptime._strptime('16', '%d') # numbers more portable hopefully + locale.setlocale(locale.LC_ALL,'C') + + +#======================================================================= # Big-memory-test support. Separate from 'resources' because memory use should be configurable. # Some handy shorthands. Note that these are used for byte-limits as well diff --git a/NEWS b/NEWS --- a/NEWS +++ b/NEWS @@ -5,6 +5,7 @@ Development tip Bugs fixed + - [ 2730 ] datetime.strptime('%b') behaviour inconsistent with CPython on Windows JDK 9+ - [ 2613 ] MANIFEST.MF contains unfilled placeholders - [ 2330 ] full-build fails to copy CPython License - [ 2651 ] Travis builds failing with *** buffer overflow detected *** @@ -88,6 +89,9 @@ 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. + - There is much improved support for locale, but as a backward-incompatible change, it is + provided as an opt-in. Define property python.locale.control=settable on the command line + or via the Jython registry, to enable. This may become the default in a later version. Jython 2.7.2a1 Bugs fixed diff --git a/src/org/python/core/PyObject.java b/src/org/python/core/PyObject.java --- a/src/org/python/core/PyObject.java +++ b/src/org/python/core/PyObject.java @@ -828,7 +828,7 @@ * When iterating over a python sequence from java code, it should be done with code like * this:
      * for (PyObject item : seq.asIterable()) {
-     *     // Do somting with item
+     *     // Do something with item
      * }
      * 
* 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 @@ -15,7 +15,6 @@ import java.lang.reflect.InvocationTargetException; import java.nio.charset.Charset; import java.nio.charset.UnsupportedCharsetException; -import java.security.AccessControlException; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; diff --git a/src/org/python/core/RegistryKey.java b/src/org/python/core/RegistryKey.java --- a/src/org/python/core/RegistryKey.java +++ b/src/org/python/core/RegistryKey.java @@ -100,6 +100,29 @@ public static final String PYTHON_IO_ERRORS = "python.io.errors"; /** + * {@code python.locale.control} determines locale module behaviour, including enabling locale + * module support, currently in beta. + *

+ * Values: + * + * + * + * + * + * + * + * + * + *
{@code settable}Python locale module is available and supports {@code setlocale()} and other standard + * functions. This will be the default in a future Jython version.
{@code jython2_legacy} (default)Mix of implicit Java locale and emulated 'C' locale behaviour, consistent with behaviour + * in Jython 2.7.1 and earlier. Will be deprecated in a future Jython version.
+ *

+ * More detail can be found in the documentation for the {@code locale} module and the + * underlying platform services exposed in {@link org.python.modules._locale._locale}. + */ + public static final String PYTHON_LOCALE_CONTROL = "python.locale.control"; + + /** * {@code python.modules.builtin} controls the list of builtin modules; you can add, remove, or * override builtin modules. The value for this registry key is a comma separated list of module * entries, each entry of which has the following allowable forms: diff --git a/src/org/python/core/exceptions.java b/src/org/python/core/exceptions.java --- a/src/org/python/core/exceptions.java +++ b/src/org/python/core/exceptions.java @@ -4,6 +4,7 @@ import java.io.File; import java.lang.reflect.Method; +import org.python.modules._locale._locale; import org.python.modules.zipimport.zipimport; /** @@ -174,11 +175,15 @@ "Base class for warnings about bytes and buffer related problems, mostly\n" + "related to conversion from str or comparing to str."); - // Initialize ZipImportError here, where it's safe to; it's - // needed immediately + buildModuleExceptions(dict); + ts.frame = ts.frame.f_back; + } + + // Native modules exposing errors as part of their public interface + private static void buildModuleExceptions(PyObject dict) { + // Initialize ZipImportError here, where it's safe to; it's needed immediately zipimport.initClassExceptions(dict); - - ts.frame = ts.frame.f_back; + _locale.initClassExceptions(dict); } public static PyObject SyntaxError() { diff --git a/src/org/python/modules/Setup.java b/src/org/python/modules/Setup.java --- a/src/org/python/modules/Setup.java +++ b/src/org/python/modules/Setup.java @@ -56,6 +56,7 @@ "itertools:org.python.modules.itertools.itertools", "jarray", "jffi:org.python.modules.jffi.jffi", + "_locale:org.python.modules._locale._locale", "math", "operator", "struct", diff --git a/src/org/python/modules/_locale/CEmulationLocale.java b/src/org/python/modules/_locale/CEmulationLocale.java new file mode 100644 --- /dev/null +++ b/src/org/python/modules/_locale/CEmulationLocale.java @@ -0,0 +1,131 @@ +// (c) 2019 Jython Developers +// Licensed to PSF under a contributor agreement + +package org.python.modules._locale; + +import org.python.core.Py; +import org.python.core.PyDictionary; +import org.python.core.PyList; +import org.python.core.PyString; + +/** + * Emulates the Python (ie POSIX) 'C' locale. + * + * The C emulation locale uses only ANSI characters in non-unicode strings, in keeping with it being + * the locale of last resort and maximum compatibility. + * + * Used by the _locale module. Callers would not usually interact with this class directly unless + * working with _locale internals. + * + * @Immutable + * + * @since Jython 2.7.2 + */ +public class CEmulationLocale implements PyLocale { + /* + * A number of these structures are repeated from Time.java and elsewhere They can be removed + * from those other classes and pointed here once jython2_legacy behaviour is deprecated or + * removed. + */ + private static final String[] EN_SHORT_DAYS = + new String[] {"", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; + + private static final String[] EN_DAYS = new String[] {"", "Sunday", "Monday", "Tuesday", + "Wednesday", "Thursday", "Friday", "Saturday"}; + + private static final String[] EN_SHORT_MONTHS = new String[] {"Jan", "Feb", "Mar", "Apr", "May", + "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; + + private static final String[] EN_MONTHS = new String[] {"January", "February", "March", "April", + "May", "June", "July", "August", "September", "October", "November", "December"}; + + private static final String[] EN_AM_PM = new String[] {"am", "pm"}; + + private static final PyDictionary EMULATION_CONV; + + private static void putEmpty(PyDictionary dict, String key) { + dict.put(new PyString(key), Py.EmptyString); + } + + private static void putCharMax(PyDictionary dict, String key) { + dict.put(new PyString(key), _locale.CHAR_MAX_PY_INT); + } + + static { + EMULATION_CONV = new PyDictionary(); + /* + * This is a repetition of the locale emulation in the locale module to allow resetting the + * locale back to C emulation. + */ + _locale.putConvEntry(EMULATION_CONV, "decimal_point", "."); + putEmpty(EMULATION_CONV, "thousands_sep"); + putEmpty(EMULATION_CONV, "currency_symbol"); + putEmpty(EMULATION_CONV, "int_curr_symbol"); + putEmpty(EMULATION_CONV, "negative_sign"); + putEmpty(EMULATION_CONV, "positive_sign"); + putCharMax(EMULATION_CONV, "p_sign_posn"); + PyList groupingList = new PyList(); + _locale.putConvEntry(EMULATION_CONV, "grouping", groupingList); + putEmpty(EMULATION_CONV, "mon_decimal_point"); + putEmpty(EMULATION_CONV, "mon_thousands_sep"); + putCharMax(EMULATION_CONV, "frac_digits"); + putCharMax(EMULATION_CONV, "int_frac_digits"); + _locale.putConvEntry(EMULATION_CONV, "mon_grouping", groupingList); + putCharMax(EMULATION_CONV, "n_sign_posn"); + putCharMax(EMULATION_CONV, "p_cs_precedes"); + putCharMax(EMULATION_CONV, "n_cs_precedes"); + putCharMax(EMULATION_CONV, "p_sep_by_space"); + putCharMax(EMULATION_CONV, "n_sep_by_space"); + } + + @Override + public PyDictionary localeconv() { + return EMULATION_CONV; + } + + @Override + public PyString getLocaleString() { + return _locale.C_LOCALE_PY_STRING; + } + + @Override + public PyString getUnderlyingLocale() { + return _locale.C_LOCALE_PY_STRING; + } + + @Override + public int strcoll(PyString str1, PyString str2) { + return str1.__cmp__(str2); + } + + @Override + public PyString strxfrm(PyString str1) { + return str1; + } + + @Override + public String[] getShortWeekdays() { + return EN_SHORT_DAYS; + } + + @Override + public String[] getWeekdays() { + return EN_DAYS; + } + + @Override + public String[] getShortMonths() { + return EN_SHORT_MONTHS; + } + + @Override + public String[] getMonths() { + return EN_MONTHS; + } + + @Override + public String[] getAmPmStrings() { + return EN_AM_PM; + } + +} \ No newline at end of file diff --git a/src/org/python/modules/_locale/DateSymbolJyLocale.java b/src/org/python/modules/_locale/DateSymbolJyLocale.java new file mode 100644 --- /dev/null +++ b/src/org/python/modules/_locale/DateSymbolJyLocale.java @@ -0,0 +1,53 @@ +package org.python.modules._locale; + +import java.text.DateFormatSymbols; +import java.util.Locale; + +/** + * Separating these largely constant values from Python encoding conversions allows for safer + * initialization even if modules are loaded in different orders. The Python {@code locale} and + * {@code codecs} modules have interdependencies, as well as {@org.python.modules.time.Time} and + * {@code org.python.modules._locale._locale}. The latter in particular depends on + * {@code java.util.Locale} and this class, but only uses the date symbol aspect. + * + * @Immutable + * + * @since Jython 2.7.2 + */ +public class DateSymbolJyLocale implements DateSymbolLocale { + + protected final Locale locale; + protected final DateFormatSymbols dfSymbols; + + public DateSymbolJyLocale(Locale locale) { + super(); + this.locale = locale; + this.dfSymbols = DateFormatSymbols.getInstance(locale); + } + + @Override + public String[] getShortWeekdays() { + return dfSymbols.getShortWeekdays(); + } + + @Override + public String[] getWeekdays() { + return dfSymbols.getWeekdays(); + } + + @Override + public String[] getShortMonths() { + return dfSymbols.getShortMonths(); + } + + @Override + public String[] getMonths() { + return dfSymbols.getMonths(); + } + + @Override + public String[] getAmPmStrings() { + return dfSymbols.getAmPmStrings(); + } + +} \ No newline at end of file diff --git a/src/org/python/modules/_locale/DateSymbolLocale.java b/src/org/python/modules/_locale/DateSymbolLocale.java new file mode 100644 --- /dev/null +++ b/src/org/python/modules/_locale/DateSymbolLocale.java @@ -0,0 +1,20 @@ +package org.python.modules._locale; + +/** + * Date related string values. + * + * @since Jython 2.7.2 + */ +public interface DateSymbolLocale { + + public String[] getShortWeekdays(); + + public String[] getShortMonths(); + + public String[] getMonths(); + + public String[] getAmPmStrings(); + + public String[] getWeekdays(); + +} \ No newline at end of file diff --git a/src/org/python/modules/_locale/JyLocale.java b/src/org/python/modules/_locale/JyLocale.java new file mode 100644 --- /dev/null +++ b/src/org/python/modules/_locale/JyLocale.java @@ -0,0 +1,223 @@ +// (c) 2019 Jython Developers +// Licensed to PSF under a contributor agreement + +package org.python.modules._locale; + +import java.text.Collator; +import java.text.DecimalFormat; +import java.text.DecimalFormatSymbols; +import java.text.NumberFormat; +import java.util.Locale; + +import org.python.core.Py; +import org.python.core.PyDictionary; +import org.python.core.PyException; +import org.python.core.PyInteger; +import org.python.core.PyList; +import org.python.core.PyString; +import org.python.core.PyUnicode; + +/** + * Sources locale information from standard Java API functions, such as that in + * {@link java.util.Locale} and {@link java.text.DecimalFormat}. + * + * Used by the _locale module. Callers would not usually interact with this class directly unless + * working with _locale internals. + * + * @Immutable + * + * @since Jython 2.7.2 + */ +public class JyLocale extends DateSymbolJyLocale implements PyLocale { + + private final String encoding; + private final PyDictionary conv; + private final Collator collator; + + public JyLocale(Locale locale, String encoding) { + super(locale); + this.encoding = encoding; + this.conv = initLocaleConv(); + this.collator = Collator.getInstance(locale); + } + + @Override + public PyDictionary localeconv() { + return conv; + } + + private PyDictionary initLocaleConv() { + DecimalFormat df = (DecimalFormat) NumberFormat.getInstance(locale); + DecimalFormat cf = (DecimalFormat) NumberFormat.getCurrencyInstance(locale); + return localeConvForFormat(df, cf, getEncoding()); + } + + /** + * Fallbacks provided for charset conversion failures in this method match either the C locale, + * or plausible lower-risk substitutes, like ISO currency code for currency symbol. + */ + static PyDictionary localeConvForFormat(DecimalFormat decimalFormat, + DecimalFormat currencyFormat, String encoding) { + PyDictionary result = new PyDictionary(); + DecimalFormatSymbols dfs = decimalFormat.getDecimalFormatSymbols(); + DecimalFormatSymbols cfs = currencyFormat.getDecimalFormatSymbols(); + putConvUnicodeEntry(result, "decimal_point", dfs.getDecimalSeparator(), ".", encoding); + putConvUnicodeEntry(result, "thousands_sep", dfs.getGroupingSeparator(), "", encoding); + putConvUnicodeEntry(result, "currency_symbol", cfs.getCurrencySymbol(), + dfs.getInternationalCurrencySymbol(), encoding); + _locale.putConvEntry(result, "int_curr_symbol", cfs.getInternationalCurrencySymbol()); + putConvUnicodeEntry(result, "negative_sign", cfs.getMinusSign(), "-", encoding); + // No positive sign concept in Java locale + _locale.putConvEntry(result, "positive_sign", new PyString("")); + _locale.putConvEntry(result, "p_sign_posn", new PyInteger(3)); + PyList groupingList = new PyList(); + groupingList.add(new PyInteger(decimalFormat.getGroupingSize())); + groupingList.add(new PyInteger(0)); + _locale.putConvEntry(result, "grouping", groupingList); + _locale.putConvEntry(result, "mon_decimal_point", cfs.getMonetaryDecimalSeparator()); + putConvUnicodeEntry(result, "mon_thousands_sep", cfs.getGroupingSeparator(), "", encoding); + _locale.putConvEntry(result, "frac_digits", + new PyInteger(currencyFormat.getMaximumFractionDigits())); + _locale.putConvEntry(result, "int_frac_digits", + new PyInteger(currencyFormat.getMaximumFractionDigits())); + PyList monGroupingList = new PyList(); + monGroupingList.add(new PyInteger(currencyFormat.getGroupingSize())); + monGroupingList.add(new PyInteger(0)); + _locale.putConvEntry(result, "mon_grouping", monGroupingList); + _locale.putConvEntry(result, "n_sign_posn", + new PyInteger(negativeSignPosition(currencyFormat))); + _locale.putConvEntry(result, "p_cs_precedes", + new PyInteger(positiveCurrencyPrecedesValue(currencyFormat))); + _locale.putConvEntry(result, "n_cs_precedes", + new PyInteger(negativeCurrencyPrecedesValue(currencyFormat))); + _locale.putConvEntry(result, "p_sep_by_space", + new PyInteger(positiveSeparatedBySpace(currencyFormat))); + _locale.putConvEntry(result, "n_sep_by_space", + new PyInteger(negativeSeparatedBySpace(currencyFormat))); + return result; + } + + private static void putConvUnicodeEntry(PyDictionary result, String key, String value, + String fallback, String encoding) { + try { + result.put(new PyString(key), new PyString(new PyUnicode(value).encode(encoding))); + } catch (PyException pye) { + encodingFallback(result, key, fallback, pye); + } + } + + private static void putConvUnicodeEntry(PyDictionary result, String key, char value, + String fallback, String encoding) { + try { + result.put(new PyString(key), new PyString(new PyUnicode(value).encode(encoding))); + } catch (PyException pye) { + encodingFallback(result, key, fallback, pye); + } + } + + private static void encodingFallback(PyDictionary result, String key, String fallback, + PyException pye) { + Py.writeComment("_locale", + "Could not encode value for key " + key + " " + pye.getMessage()); + result.put(new PyString(key), new PyString(fallback)); + } + + @Override + public PyString getLocaleString() { + return new PyString(locale.toString() + "." + encoding); + } + + @Override + public PyString getUnderlyingLocale() { + return new PyString(locale.toString()); + } + + @Override + public int strcoll(PyString str1, PyString str2) { + return collator.compare(unicoder(str1), unicoder(str2)); + } + + private String unicoder(PyString str) { + return strxfrm(str).toString(); + } + + @Override + public PyString strxfrm(PyString str) { + if (str instanceof PyUnicode) { + return str; + } + return (PyString) str.decode(encoding); + } + + public String getEncoding() { + return encoding; + } + + static int negativeSignPosition(DecimalFormat df) { + String prefix = df.getNegativePrefix(); + String suffix = df.getNegativeSuffix(); + if ("".equals(suffix)) { + if ("".equals(prefix)) { + // Nothing is specified in this locale. + return _locale.CHAR_MAX; + } + } + if (prefix.startsWith("(") && suffix.endsWith(")")) { + // Currency and value are surrounded by parentheses. + return 0; + } + final String MINUS = String.valueOf(df.getDecimalFormatSymbols().getMinusSign()); + if (prefix.startsWith(MINUS)) { + // The sign should precede the value and currency symbol. + return 1; + } else if (prefix.endsWith(MINUS)) { + // The sign should immediately precede the value. + return 3; + } else if (suffix.startsWith(MINUS)) { + // The sign should immediately follow the value. + return 4; + } + // The sign should follow the value and currency symbol. + return 2; + } + + static int positiveCurrencyPrecedesValue(DecimalFormat df) { + return currencyPrecedesValue(df, df.getPositivePrefix()); + } + + static int negativeCurrencyPrecedesValue(DecimalFormat df) { + return currencyPrecedesValue(df, df.getNegativePrefix()); + } + + private static int currencyPrecedesValue(DecimalFormat df, String prefix) { + if (prefix.contains(df.getDecimalFormatSymbols().getCurrencySymbol())) { + return 1; + } + return 0; + } + + static int positiveSeparatedBySpace(DecimalFormat df) { + return separatedBySpace(df.getPositivePrefix(), df.getPositiveSuffix()); + } + + static int negativeSeparatedBySpace(DecimalFormat df) { + return separatedBySpace(df.getNegativePrefix(), df.getNegativeSuffix()); + } + + private static int separatedBySpace(String prefix, String suffix) { + if ((!prefix.isEmpty() && isExtendedWhitespace(prefix.charAt(prefix.length() - 1)))) { + return 1; + } else if ((!suffix.isEmpty() && isExtendedWhitespace(suffix.charAt(0)))) { + return 1; + } + return 0; + } + + /** + * Includes non-breaking space, but not extended codepoints + */ + public static boolean isExtendedWhitespace(char c) { + return Character.isWhitespace(c) || '\u00A0' == c; + } + +} \ No newline at end of file diff --git a/src/org/python/modules/_locale/PyLocale.java b/src/org/python/modules/_locale/PyLocale.java new file mode 100644 --- /dev/null +++ b/src/org/python/modules/_locale/PyLocale.java @@ -0,0 +1,28 @@ +// (c) 2019 Jython Developers +// Licensed to PSF under a contributor agreement + +package org.python.modules._locale; + +import org.python.core.PyDictionary; +import org.python.core.PyString; + +/** + * Definition of a Python native locale implementation. Based on Python locale module behaviour and + * implicit dependencies, and the {@code _localemodule.c} implementation in CPython. + * + * It is recommended classes implementing this interface are made immutable. + * + * @since Jython 2.7.2 + */ +public interface PyLocale extends DateSymbolLocale { + + public PyDictionary localeconv(); + + public PyString getLocaleString(); + + public PyString getUnderlyingLocale(); + + public int strcoll(PyString str1, PyString str2); + + public PyString strxfrm(PyString str1); +} diff --git a/src/org/python/modules/_locale/_locale.java b/src/org/python/modules/_locale/_locale.java new file mode 100644 --- /dev/null +++ b/src/org/python/modules/_locale/_locale.java @@ -0,0 +1,377 @@ +// (c) 2019 Jython Developers +// Licensed to PSF under a contributor agreement + +package org.python.modules._locale; + +import java.nio.charset.Charset; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.Locale; +import java.util.Set; + +import org.python.core.ClassDictInit; +import org.python.core.Py; +import org.python.core.PyDictionary; +import org.python.core.PyException; +import org.python.core.PyInteger; +import org.python.core.PyObject; +import org.python.core.PyString; +import org.python.core.PyStringMap; +import org.python.core.PySystemState; + +import static org.python.core.RegistryKey.PYTHON_LOCALE_CONTROL; + +/** + * Java native implementation of underlying locale functions, fitting the interface defined or + * implied by the Python locale module. + * + * Functional documentation can be found in the Python module docstring. This class depends on + * registry key {@link org.python.core.RegistryKey.PYTHON.LOCALE_CONTROL}. Additional implementation + * details for users of this class are captured below. + *

+ * Unicode. In general, Java and its locale settings are quite unicode heavy, making rich use of + * different symbols for eg currencies. This solution allows some of that to leak through by + * encoding the Java locale value with the current character encoding. The Python locale module is + * quite conservative and tends to keep things as solely strings. Python 2.x usually supports only + * string / ascii by default in many cases, and only unicode when asked. This is a little less + * conservative while only allowing values consistent with the current encoding. + *

+ * An example of this is some Python implementations using EUR rather than the Euro symbol ? / + * {@code 'u20ac'}, probably because ? is only available in Unicode. In the Java implementation, if + * UTF-8 encoding is set, the resulting entry in {@code localeconv()['currency_code']} is + * {@code '\xe2\x82\xac'}. This can be used by {@code print()} and related functions directly. + * Encoding failures for {@code currency_symbol} fall back to {@code int_curr_symbol} (eg EUR). + * Encoding failures for {@code negative_sign}, which are sometimes unicode, fall back to an ANSI + * hyphen ('-'). Other encoding failures fallback to the 'C' locale values, where possible. + *

+ * The C emulation locale uses only ANSI characters in non-unicode strings, in keeping with it being + * the locale of last resort and maximum compatibility. + *

+ * Positive sign position ({@code p_sign_posn}) is not a distinguished concept in Java and so this + * is hardcoded to 3. + *

+ * This class ensures read/write consistency, when changing locales via + * {@link #setlocale(PyInteger,PyString)}, by declaring private variable {@code currentLocale} as + * volatile, and only assigning it immutable objects. It does not lock to guarantee sequencing of + * {@code setLocale()} calls from separate threads. In the rare cases where that would be needed, it + * is the responsibility of the calling code. + * + * @since Jython 2.7.2 + * + */ +public class _locale implements ClassDictInit { + + /** + * The {@code locale} module exposes {@code _locale.Error} as {@code locale.Error}. Some Python + * functions, including {@code strptime()}, depend on {@code locale.Error}, making it part of + * the public API for native locale implementations. + */ + public static PyObject Error; + + public static PyException LocaleException(String message) { + return new PyException(Error, message); + } + + // @formatter:off + public static final PyString __doc__ = new PyString( + "The _locale module exposes locale functions in the underlying " + + "operating system or platform in a consistent way, for use by " + + "the Python locale module. It is a native Java implementation, " + + "paralleling libmodule.c in CPython and its dependence on C " + + "libraries provided by the OS.\n" + + "This module is currently in beta, and is enabled with the " + + "registry property ``python.locale.control``. It is " + + "disabled by default, resulting in jython 2.7.1 (and previous) " + + "locale behaviour.\n" + + "\n" + + "+-------------------+-----------------------------------------+\n" + + "+ Property Value + Behaviour |\n" + + "+===================+=========================================+\n" + + "| jython2_legacy | Mix of implicit Java locale and |\n" + + "| | emulated 'C'. Text and date formatting |\n" + + "| | mostly Java locale (eg ``%b``). |\n" + + "| | ``asctime()`` matches C emulation |\n" + + "| | ``setlocale()`` always errors by design.|\n" + + "| | This matches version 2.7.1 and previous |\n" + + "| | behaviour. Will be deprecated in future |\n" + + "| | versions. |\n" + + "+-------------------+-----------------------------------------+\n" + + "| settable | Java platform locale services made |\n" + + "| | available via locale module. |\n" + + "| | ``setlocale()`` works, using Java locale|\n" + + "| | identifiers and LC_ALL (only). C locale |\n" + + "| | available via ``setlocale()``. Initial |\n" + + "| | locale and encoding per Java defaults. |\n" + + "+-------------------+-----------------------------------------+\n" + + "| '' or unset | As per ``jython2_legacy``. |\n" + + "| | In future versions, per ``settable``. |\n" + + "+-------------------+-----------------------------------------+\n"); + // @formatter:on + + public static final String LOCALE_CONTROL_SETTABLE = "settable"; + public static final String LOCALE_CONTROL_JYTHON2_LEGACY = "jython2_legacy"; + + // These values are the same as glibc locale/bits/locale.h + // Specific integer constants are not mandated by the POSIX locale spec, so an existing + // standard seemed as good an arbitrary set of values as any + private static final int __LC_CTYPE = 0; + private static final int __LC_NUMERIC = 1; + private static final int __LC_TIME = 2; + private static final int __LC_COLLATE = 3; + private static final int __LC_MONETARY = 4; + private static final int __LC_MESSAGES = 5; + private static final int __LC_ALL = 6; + @SuppressWarnings("unused") + private static final int __LC_PAPER = 7; + @SuppressWarnings("unused") + private static final int __LC_NAME = 8; + @SuppressWarnings("unused") + private static final int __LC_ADDRESS = 9; + @SuppressWarnings("unused") + private static final int __LC_TELEPHONE = 10; + @SuppressWarnings("unused") + private static final int __LC_MEASUREMENT = 11; + @SuppressWarnings("unused") + private static final int __LC_IDENTIFICATION = 12; + + public static final PyInteger LC_CTYPE = new PyInteger(__LC_CTYPE); + public static final PyInteger LC_NUMERIC = new PyInteger(__LC_NUMERIC); + public static final PyInteger LC_TIME = new PyInteger(__LC_TIME); + public static final PyInteger LC_COLLATE = new PyInteger(__LC_COLLATE); + public static final PyInteger LC_MONETARY = new PyInteger(__LC_MONETARY); + public static final PyInteger LC_MESSAGES = new PyInteger(__LC_MESSAGES); + public static final PyInteger LC_ALL = new PyInteger(__LC_ALL); + // Remaining constants not used by locale.py so are not exposed here + + // 127 chosen as consistent with hardcoded default in locale.py for C locale + public static final int CHAR_MAX = 127; + public static final PyInteger CHAR_MAX_PY_INT = new PyInteger(127); + public static final PyString C_LOCALE_PY_STRING = new PyString("C"); + private static final Set AVAILABLE_LOCALES; + + // Failsafe for date symbols only. Insufficient for full locale module behaviour. + private static final DateSymbolLocale DEFAULT_LOCALE = + new DateSymbolJyLocale(Locale.getDefault()); + + // This has a subtle initialization dependency on the codecs module due to the initialization + // in JyLocale(). Let the interpreter initialize via classDictInit(). + private static volatile PyLocale currentLocale = null; + + static { + final Set set = new HashSet<>(Arrays.asList(Locale.getAvailableLocales())); + AVAILABLE_LOCALES = Collections.unmodifiableSet(set); + } + + @SuppressWarnings("serial") + public static void initClassExceptions(PyObject exceptions) { + PyObject baseException = exceptions.__finditem__("BaseException"); + Error = Py.makeClass("locale.Error", baseException, new PyStringMap() { + + { + __setitem__("__module__", Py.newString("locale")); + } + }); + } + + // This is used when the module is first initialized, or when simulating re-initialization from + // tests + public static void classDictInit(PyObject dict) { + dict.__setitem__("Error", Error); + try { + changeCurrentLocaleToDefault(); + } catch (Throwable t) { + throw Py.ImportError( + "Jython failed to load default Java locale, falling back. " + t.getMessage()); + } + final String localeControl = PySystemState.registry.getProperty(PYTHON_LOCALE_CONTROL, ""); + if ("".equals(localeControl) || LOCALE_CONTROL_JYTHON2_LEGACY.equals(localeControl)) { + throw Py.ImportError( + "Jython locale support not enabled with python.locale.control, falling back"); + } + if (!LOCALE_CONTROL_SETTABLE.equals(localeControl)) { + throw Py.ImportError( + "Jython locale support python.locale.control unrecognized value, falling back"); + } + changeCurrentLocaleToC(); + } + + private static void changeCurrentLocaleToDefault() { + currentLocale = new JyLocale(Locale.getDefault(), Charset.defaultCharset().name()); + } + + /** + * Put {@code key} mapping to {@code value} into {@code result}, converting to {@code PyString}s + * as needed + */ + protected static void putConvEntry(PyDictionary result, String key, String value) { + try { + result.put(new PyString(key), new PyString(value)); + } catch (IllegalArgumentException iae) { + throw new IllegalArgumentException(iae.getMessage() + " for key " + key); + } + } + + /** + * Put {@code key} mapping to {@code value} into {@code result}, converting to {@code PyString}s + * as needed + */ + protected static void putConvEntry(PyDictionary result, String key, char value) { + try { + result.put(new PyString(key), new PyString(value)); + } catch (IllegalArgumentException iae) { + throw new IllegalArgumentException(iae.getMessage() + " for key " + key); + } + } + + /** + * Put {@code key} mapping to {@code value} into {@code result}, converting {@code key} to + * {@code PyString}. + */ + protected static void putConvEntry(PyDictionary result, String key, PyObject value) { + try { + result.put(new PyString(key), value); + } catch (IllegalArgumentException iae) { + throw new IllegalArgumentException(iae.getMessage() + " for key " + key); + } + } + + public static PyString __doc___localeconv = + new PyString("Database of local conventions, mapped from Java.\n" + + "Note that Java locale information is relatively unicode-rich, " + + "particularly for currency symbols. Where that is not supported " + + "by the current encoding, the international currency symbol is "// + + "used.\n"// + + "C locale emulation matches CPython C locale emulation."); + + public static PyDictionary localeconv() { + return currentLocale.localeconv(); + } + + public static PyString __doc___strcoll = + new PyString("Compare Java (unicode) strings using the Java collator for the " + + "current locale, and the encoding normalization provided by strxfrm\n." + + "In the 'C' locale, this simply calls str.__cmp__() "); + + public static int strcoll(PyString str1, PyString str2) { + return currentLocale.strcoll(str1, str2); + } + + public static PyString __doc___strxfrm = + new PyString("Normalize a string to unicode, for common comparison, using the " + + "locale encoding.\n" + + "In the 'C' locale, this is a no-op, returning the parameter."); + + public static PyString strxfrm(PyString str1) { + return currentLocale.strxfrm(str1); + } + + public static PyString __doc___setlocale = + new PyString("Sets the locale given a category and normalized locale string.\n" + + "Only category LC_ALL is supported. Other categories such as " + + "LC_TIME or LC_NUMERIC result in a locale.Error." + "\n"// + + "Normalized format is per RFC 1766, but using underscores instead " + + "of dashes, eg zh_CH.UTF-8. Briefly, the format is " + + "[language]_[locality].[encoding], where [language] is a two " + + "character language identifer, locality is a regional indicator, " + + "and encoding is a character encoding. Other examples are " + + "en_AU.ISO8859-1 and de_DE.ISO8859-15.\n" + + "If this is an empty locale, the same language tag will be tried " + + "with dashes instead of underscores, ie [lanuage]-[locality].\n" + + "Normalization would usually be done by the enclosing locale module.\n" + + "This function treats a missing encoding as using UTF-8.\n"); + + public static PyString setlocale(PyInteger category) { + return currentLocale.getLocaleString(); + } + + /** + * Java Locale loading behaviour is quite forgiving, or uninformative, depending on your + * perspective. It will return a dummy locale for any language tag that fits the syntax, or make + * various attempts to approximate a locale. This solution instead follows the stricter Python + * behaviour of requiring a particular locale to be installed. + */ + public static PyString setlocale(PyInteger category, PyString locale) { + Py.writeDebug("_locale", "setlocale(category,locale==" + locale + ")"); + if (locale == null || locale.equals(Py.None) + || locale.equals(currentLocale.getLocaleString())) { + return setlocale(category); + } + if (!category.equals(LC_ALL)) { + // Py.NotImplementedError not used as dependencies exist on + // locale.Error + throw LocaleException("Only LC_ALL is supported in this version of Jython"); + } + if (locale.equals(C_LOCALE_PY_STRING)) { + changeCurrentLocaleToC(); + return C_LOCALE_PY_STRING; + } + if (locale.equals(new PyString(""))) { + changeCurrentLocaleToDefault(); + } else { + changeLocaleFromLocaleString(locale); + } + return currentLocale.getLocaleString(); + } + + private static void changeLocaleFromLocaleString(PyString locale) { + String localeStr = locale.toString(); + String[] localeParts = localeStr.split("\\."); + String language; + String encoding = "UTF-8"; + if (localeParts.length >= 3) { + throw LocaleException("Does not conform to [language]_[locality].[encoding] format: " + + locale.toString()); + } + if (localeParts.length == 1) { + language = localeStr; + } else { + // == 2 + language = localeParts[0]; + encoding = localeParts[1]; + } + Locale newLocale = loadLocale(language); + if (!isAvailableLocale(newLocale)) { + String underscoreAlias = language.replace('_', '-'); + // Not only are these often switched in Java, Locale.toLanguageTag() uses "-" and + // Locale.toString() uses "_" + newLocale = loadLocale(underscoreAlias); + if (!isAvailableLocale(newLocale)) { + throw LocaleException("unsupported locale setting: " + locale.toString()); + } + } + changeCurrentLocale(new JyLocale(newLocale, encoding)); + } + + private static void changeCurrentLocaleToC() { + changeCurrentLocale(new CEmulationLocale()); + } + + private static boolean isAvailableLocale(Locale locale) { + return locale != null && !locale.toString().isEmpty() && AVAILABLE_LOCALES.contains(locale); + } + + private static Locale loadLocale(String language) { + Locale newLocale = Locale.forLanguageTag(language); + Py.writeDebug("_locale", "Current: " + currentLocale.getUnderlyingLocale()); + Py.writeDebug("_locale", "New: " + newLocale + " loaded with tag: " + language); + return newLocale; + } + + private static void changeCurrentLocale(PyLocale pyLocale) { + Py.writeDebug("_locale", "Locale changed to: " + pyLocale.getLocaleString()); + currentLocale = pyLocale; + } + + /** + * Current {@code DateSymbolLocale} used by the Python interpreter. This object will no longer + * reflect the current state after subsequent calls to {@code setlocale}. + */ + public static DateSymbolLocale getDateSymbolLocale() { + if (currentLocale == null) { + return DEFAULT_LOCALE; + } + return currentLocale; + } + +} diff --git a/src/org/python/modules/time/Time.java b/src/org/python/modules/time/Time.java --- a/src/org/python/modules/time/Time.java +++ b/src/org/python/modules/time/Time.java @@ -12,12 +12,10 @@ // see org/python/modules/time.java for previous history. package org.python.modules.time; -import java.text.DateFormatSymbols; import java.util.Arrays; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; -import java.util.Locale; import java.util.TimeZone; import org.python.core.ClassDictInit; @@ -28,8 +26,11 @@ import org.python.core.PyObject; import org.python.core.PyString; import org.python.core.PyTuple; +import org.python.core.Untraversable; import org.python.core.__builtin__; -import org.python.core.Untraversable; +import org.python.modules._locale.DateSymbolLocale; +import org.python.modules._locale._locale; + @Untraversable class TimeFunctions extends PyBuiltinFunctionSet @@ -329,11 +330,11 @@ } // Python's time module specifies use of current locale - protected static Locale currentLocale = null; - protected static DateFormatSymbols datesyms = new DateFormatSymbols(); + protected static DateSymbolLocale datesyms = _locale.getDateSymbolLocale(); protected static String[] shortdays = null; protected static String[] shortmonths = null; + // Consider moving to CEmulationLocale, where there is another copy private static String[] enshortdays = new String[] {"Mon", "Tue", "Wed", @@ -375,7 +376,7 @@ } private synchronized static String _shortmonth(int month0to11) { - // getShortWeekdays() returns a 13 element array with the last item + // getShortMonths() returns a 13 element array with the last item // being the empty string. This is also undocumented ;-/ if (shortmonths == null) { shortmonths = new String[12]; @@ -633,13 +634,16 @@ // locale is set by user.language and user.region // properties and is "en_US" by default, at least around // here! Locale "en_US" differs from locale "C" in the way - // it represents dates and times. Eventually we might want - // to craft a "C" locale for Java and set Jython to use - // this by default, but that's too much work right now. + // it represents dates and times. Beta support for a "C" + // locale is in org.python.modules._locale.CEmulationLocale // - // For now, we hard code %x and %X to return values - // formatted in the "C" locale, i.e. the default way - // CPython does it. E.g.: + // For now, we continue the historically hard coded pre-2.7.1 + // %x and %X behaviour to return values formatted in the + // "C" locale, i.e. the default way CPython does it. This + // can be unified and simplified using CEmulationLocale once + // native _locale support becomes the default in a future + // version. + // E.g.: // %x == mm/dd/yy // %X == HH:mm:SS // @@ -698,9 +702,9 @@ private static void checkLocale() { - if (!Locale.getDefault().equals(currentLocale)) { - currentLocale = Locale.getDefault(); - datesyms = new DateFormatSymbols(currentLocale); + DateSymbolLocale latestLocale = _locale.getDateSymbolLocale(); + if (!latestLocale.equals(datesyms)) { + datesyms = latestLocale; shortdays = null; shortmonths = null; } @@ -710,10 +714,6 @@ return strptime(data_string, DEFAULT_FORMAT_PY); } - /** - * Calls _strptime.strptime(), for cases that our SimpleDateFormat backed - * strptime can't handle. - */ private static PyTuple pystrptime(String data_string, String format) { return (PyTuple) __builtin__.__import__("_strptime") .invoke("_strptime_time", @@ -728,3 +728,4 @@ private static final String DEFAULT_FORMAT_PY = "%a %b %d %H:%M:%S %Y"; } + diff --git a/src/org/python/util/PythonInterpreter.java b/src/org/python/util/PythonInterpreter.java --- a/src/org/python/util/PythonInterpreter.java +++ b/src/org/python/util/PythonInterpreter.java @@ -9,21 +9,19 @@ import org.python.core.CodeFlag; import org.python.core.CompileMode; import org.python.core.CompilerFlags; -import org.python.core.imp; import org.python.core.Options; import org.python.core.ParserFacade; import org.python.core.Py; import org.python.core.PyCode; import org.python.core.PyException; import org.python.core.PyFile; +import org.python.core.PyFileReader; import org.python.core.PyFileWriter; import org.python.core.PyModule; import org.python.core.PyObject; import org.python.core.PyString; -import org.python.core.PyStringMap; import org.python.core.PySystemState; import org.python.core.__builtin__; -import org.python.core.PyFileReader; /** * The PythonInterpreter class is a standard wrapper for a Jython interpreter for embedding in a @@ -260,6 +258,11 @@ /** * Executes a string of Python source in the local namespace. + * + * In some environments, such as Windows, Unicode characters in the script will be converted + * into ascii question marks (?). This can be avoided by first compiling the fragment using + * PythonInterpreter.compile(), and using the overridden form of this method which takes a + * PyCode object. Code page declarations are not supported. */ public void exec(String s) { setSystemState(); diff --git a/tests/java/org/python/modules/_locale/_localeTest.java b/tests/java/org/python/modules/_locale/_localeTest.java new file mode 100644 --- /dev/null +++ b/tests/java/org/python/modules/_locale/_localeTest.java @@ -0,0 +1,626 @@ +// (c) 2019 Jython Developers +// Licensed to PSF under a contributor agreement + +package org.python.modules._locale; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.python.core.RegistryKey.PYTHON_LOCALE_CONTROL; + +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.text.DecimalFormat; +import java.text.DecimalFormatSymbols; +import java.text.NumberFormat; +import java.util.Locale; + +import org.junit.Before; +import org.junit.Test; +import org.python.core.Py; +import org.python.core.PyCode; +import org.python.core.PyDictionary; +import org.python.core.PyException; +import org.python.core.PyInteger; +import org.python.core.PyObject; +import org.python.core.PySet; +import org.python.core.PyString; +import org.python.core.PyStringMap; +import org.python.core.PySystemState; +import org.python.core.PyUnicode; +import org.python.util.PythonInterpreter; + +public class _localeTest { + + private PySystemState systemState; + private PythonInterpreter interp; + + @Before + public void setUp() throws Exception { + // Initialise a Jython interpreter + systemState = Py.getSystemState(); + interp = new PythonInterpreter(new PyStringMap(), systemState); + } + + @SuppressWarnings("static-access") + private void setLocaleProperty(String value) { + systemState.registry.setProperty(PYTHON_LOCALE_CONTROL, value); + } + + private void defaultState() { + setLocaleProperty(""); + } + + private void jython2LegacyState() { + setLocaleProperty("jython2_legacy"); + } + + private void settableState() { + setLocaleProperty("settable"); + } + + private void importAndInit() { + interp.exec("import _locale"); + /* + * Following line is a hacky workaround, because interpreter and PySystemState can't be + * fully reinitialized. classDictInit() is called implicitly on first module import only. + */ + interp.exec("_locale.classDictInit({})"); + } + + private void settableInit() { + settableState(); + importAndInit(); + } + + private void assertPyTrue(String variableName) { + PyObject result = interp.get(variableName); + assertEquals(Py.True, result); + } + + private void assertPyEquals(int expected, String valueName) { + PyObject result = interp.get(valueName); + assertEquals(new PyInteger(expected), result); + } + + private void assertPyEquals(String expected, String valueName) { + PyObject result = interp.get(valueName); + assertEquals(new PyString(expected), result); + } + + private void assertInterpEquals(String expected, String value) { + PyObject result1 = interp.get(expected); + PyObject result2 = interp.get(value); + assertEquals(result1, result2); + } + + @Test + public void moduleImportSettable() { + settableInit(); + PyObject _localeModule = interp.get("_locale"); + assertNotNull(_localeModule); + } + + @Test(expected = PyException.class) + public void moduleImportLegacy() { + jython2LegacyState(); + importAndInit(); + } + + @Test(expected = PyException.class) + public void moduleImportDefault() { + defaultState(); + importAndInit(); + } + + private static int javaMajorVersion() { + String versionString = System.getProperty("java.runtime.version"); + String[] javaVersionElements = versionString.split("\\.|_|-b"); + int major = Integer.valueOf(javaVersionElements[0]); + int minor = Integer.valueOf(javaVersionElements[1]); + if (major == 1) { + return minor; + } + return major; + } + + public void setLocaleEN_US(String tag) { + // Anchor test to a popular locale to prove alignment + settableInit(); + /* + * Java 8 and Python use en-US negative currency formatting ($123). This changes to -$123 + * from 9 onwards. + */ + int nSignPosition = 0; + if (javaMajorVersion() >= 9) { + nSignPosition = 1; + } + // @formatter:off + String script = + "from _locale import setlocale, localeconv\n" + + "setlocale(_locale.LC_ALL, '" + tag + "' ) \n" + + "expected = " + + "{'mon_decimal_point': '.', 'int_frac_digits': 2, " + + " 'p_sep_by_space': 0, 'frac_digits': 2, " + + " 'thousands_sep': ',', " + + " 'n_sign_posn': " + String.valueOf(nSignPosition) + " , " + + "'decimal_point': '.', 'int_curr_symbol': 'USD', " + + "'n_cs_precedes': 1, 'p_sign_posn': 3, " + + "'mon_thousands_sep': ',', 'negative_sign': '-', " + + "'currency_symbol': '$', 'n_sep_by_space': 0 , " + + "'positive_sign': '', 'p_cs_precedes': 1 } \n" + + "actual = localeconv() \n" + + "grouping = actual.pop('grouping',None) \n" + + "mon_grouping = actual.pop('mon_grouping',None) \n" + + "result = set( actual.items() ) ^ set(expected.items()) \n" + + "resultGrouping = (grouping == [3,0] ) \n" + + "resultMonGrouping = (mon_grouping == [3,0] ) \n"; + // @formatter:on + interp.exec(script); + PyObject result = interp.get("result"); + assertEquals(new PySet(), result); + assertPyTrue("resultGrouping"); + assertPyTrue("resultMonGrouping"); + } + + @Test + public void setLocaleEN_US_Underscore() { + /* + * Locales are aliased to underscore equivalents, due to that being a common convention in + * Python and Java itself. + */ + setLocaleEN_US("en_US.ISO8859-1"); + } + + @Test + public void setLocaleEN_US_Dash() { + setLocaleEN_US("en-US"); + } + + @Test + public void setLocaleEN_US_Tuple() { + settableInit(); + // @formatter:off + String script = + "from locale import setlocale, getlocale, LC_ALL \n" + + "setlocale(LC_ALL,('en-US','ISO8859-1') ) \n" + + "actual = getlocale() \n" + + "expected = ('en_US', 'ISO8859-1') \n"; + // @formatter:on + PyCode code = interp.compile(script); + interp.exec(code); + assertInterpEquals("expected", "actual"); + } + + @Test + public void setLocaleNotLCALL() { + settableInit(); + String script = "import locale \n" + "caught = False \n" + "try: \n" + + " locale.setlocale(locale.LC_MONETARY,'zh-CN') \n" + + "except locale.Error as e: \n" + " caught = True \n"; + // @formatter:on + interp.exec(script); + assertPyTrue("caught"); + } + + @Test + public void setLocaleEmpty() { + settableInit(); + // @formatter:off + String script = + "from _locale import setlocale \n" + + "setlocale(_locale.LC_ALL,'zh_CN.UTF-8') \n" + + "result1 = setlocale(_locale.LC_ALL) \n" + + "result2 = setlocale(_locale.LC_MONETARY,None) \n" + + "result3 = setlocale(_locale.LC_MONETARY,'zh_CN.UTF-8') \n"; + interp.exec(script); + assertPyEquals("zh_CN.UTF-8", "result1"); + assertPyEquals("zh_CN.UTF-8", "result2"); + assertPyEquals("zh_CN.UTF-8", "result3"); + } + + @Test + public void setLocaleDefault() { + settableInit(); + // @formatter:off + String script = + "from locale import setlocale \n" + + "result1 = setlocale(_locale.LC_ALL,'zh_CN.UTF-8') \n" + + "result2 = setlocale(_locale.LC_ALL,'') "; + // @formatter:on + interp.exec(script); + assertPyEquals("zh_CN.UTF-8", "result1"); + assertPyEquals(Locale.getDefault().toString() + "." + Charset.defaultCharset().name(), + "result2"); + } + + @Test(expected = PyException.class) + public void setLocaleInvalid() { + settableInit(); + // @formatter:off + String script = + "from _locale import setlocale \n" + + "result = setlocale(_locale.LC_ALL,'green_midget_cafe_nosuch') \n"; + // @formatter:on + interp.exec(script); + } + + @Test + public void setLocaleGerman() { + settableInit(); + // @formatter:off + String script = + "from _locale import setlocale, localeconv\n" + + "setlocale(_locale.LC_ALL,'de_DE.ISO8859-15') \n" + + "expected = " + + "{'mon_decimal_point': ',', 'int_frac_digits': 2, " + + " 'p_sep_by_space': 1, 'frac_digits': 2, " + + "'thousands_sep': '.', 'n_sign_posn': 1, " + + "'decimal_point': ',', 'int_curr_symbol': 'EUR', " + + "'n_cs_precedes': 0, 'p_sign_posn': 3, " + + "'mon_thousands_sep': '.', 'negative_sign': '-', " + + "'currency_symbol': '\\xa4' , 'n_sep_by_space': 1, " + + "'p_cs_precedes': 0, 'positive_sign': ''} \n" + + "actual = localeconv() \n" + + "grouping = actual.pop('grouping',None) \n" + + "mon_grouping = actual.pop('mon_grouping',None) \n" + + "result = set( actual.items() ) ^ set(expected.items()) \n" + + "resultGrouping = (grouping == [3,0] ) \n" + + "resultMonGrouping = (mon_grouping == [3,0] ) \n"; + // @formatter:on + PyCode code = interp.compile(script); + interp.exec(code); + PyObject result = interp.get("result"); + assertEquals(new PySet(), result); + assertPyTrue("resultGrouping"); + assertPyTrue("resultMonGrouping"); + } + + @Test + public void setLocaleChinaMainland() { + settableInit(); + /* + * Java has ? \uffe5 rather than ? \u5143 for zh-CN Java has negative sign preceding, Python + * following. + */ + // @formatter:off + String script = + "from _locale import setlocale, localeconv\n" + + "setlocale(_locale.LC_ALL,'zh_CN.UTF-8') \n" + + "expected = " + + "{'mon_decimal_point': '.', 'int_frac_digits': 2, " + + " 'p_sep_by_space': 0, 'frac_digits': 2, " + + "'thousands_sep': ',', 'n_sign_posn': 1, " + + "'decimal_point': '.', 'int_curr_symbol': 'CNY', " + + "'n_cs_precedes': 1, 'p_sign_posn': 3, " + + "'mon_thousands_sep': ',', 'negative_sign': '-', " + + "'currency_symbol': '\\xef\\xbf\\xa5' , " + + "'n_sep_by_space': 0, " + + "'p_cs_precedes': 1, 'positive_sign': ''} \n" + + "actual = localeconv() \n" + + "grouping = actual.pop('grouping',None) \n" + + "mon_grouping = actual.pop('mon_grouping',None) \n" + + "result = set( actual.items() ) ^ set(expected.items()) \n" + + "resultGrouping = (grouping == [3,0] ) \n" + + "resultMonGrouping = (mon_grouping == [3,0] ) \n"; + // @formatter:on + PyCode code = interp.compile(script); + interp.exec(code); + PyObject result = interp.get("result"); + assertEquals(new PySet(), result); + assertPyTrue("resultGrouping"); + assertPyTrue("resultMonGrouping"); + } + + @Test + public void setlocaleJPEncodingCurrencyFallback() { + settableInit(); + /* + * Deliberately set a Japanese locale with an ANSI US codepage lacking the ? \uffe5 + * character. Which is a bit weird, but shows fallback. + */ + // @formatter:off + String script = + "from _locale import setlocale, localeconv\n" + + "setlocale(_locale.LC_ALL,'ja_JP.ISO8859-1') \n" + + "result = localeconv()['currency_symbol'] \n"; + // @formatter:on + interp.exec(script); + PyObject result = interp.get("result"); + assertEquals(new PyString("JPY"), result); + } + + /** + * We use the unconventional "~h" as a byte marker, rather than say \x, to show the conversion + * happens in this unit test, when troubleshooting. + */ + private String byteStr(byte[] bytes, boolean lePadding) { + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < bytes.length; i++) { + sb.append("~h"); + sb.append(Integer.toHexString(bytes[i])); + if (lePadding) { + sb.append("~h0"); + } + } + return sb.toString(); + } + + private String utf16LEByteStr(String in, boolean lePadding) { + return byteStr(in.getBytes(StandardCharsets.UTF_16LE), lePadding); + } + + private void assertDictValueEquals(PyDictionary dict, String expectedValue, String key) { + assertEquals(new PyUnicode(expectedValue), dict.__getitem__(new PyString(key))); + } + + /** + * Assert byte transcription equality for the PyString found in {@code}dict{code} using + * {@code}key{code} under encoding utf-16le + */ + private void assertDictUTF16LEEquals(PyDictionary dict, String expectedStr, String key) { + PyString value = (PyString) dict.__getitem__(new PyString(key)); + // PyString applies zero padding, we need to add it to Java String to compare + assertEquals(utf16LEByteStr(expectedStr, true), utf16LEByteStr(value.getString(), false)); + } + + @Test + public void utf16EncodingAndFallback() { + /* + * Chinese Finland is not usually found in locale databases, so this lets us create our own + * locale with unusual symbols. + */ + Locale unicodeMockLocale = new Locale.Builder().setLanguage("zh").setRegion("FI").build(); + DecimalFormat df = (DecimalFormat) DecimalFormat.getInstance(unicodeMockLocale); + DecimalFormatSymbols dfs = df.getDecimalFormatSymbols(); + // no locale uses these, it is to trigger fallbacks + dfs.setMinusSign('\u2212'); + dfs.setGroupingSeparator('\u65E0'); + dfs.setDecimalSeparator('\u70B9'); + df.setDecimalFormatSymbols(dfs); + // Fallback case + PyDictionary dict = JyLocale.localeConvForFormat(df, df, "ISO8859-1"); + assertDictValueEquals(dict, "-", "negative_sign"); + assertDictValueEquals(dict, ".", "decimal_point"); + assertDictValueEquals(dict, "", "thousands_sep"); + assertDictValueEquals(dict, "", "mon_thousands_sep"); + // Check happy path where values are compatible with the encoding + dict = JyLocale.localeConvForFormat(df, df, "utf-16le"); + assertDictUTF16LEEquals(dict, "\u2212", "negative_sign"); + assertDictUTF16LEEquals(dict, "\u70B9", "decimal_point"); + assertDictUTF16LEEquals(dict, "\u65E0", "thousands_sep"); + assertDictUTF16LEEquals(dict, "\u65E0", "mon_thousands_sep"); + } + + @Test + public void negativeSignPosition() { + // per documentation for Python locale module + Locale locale = Locale.forLanguageTag("en-US"); + DecimalFormat df = (DecimalFormat) NumberFormat.getCurrencyInstance(locale); + df.setNegativePrefix("($"); // ($123) as in en-US Java 8 + df.setNegativeSuffix(")"); + assertEquals(0, JyLocale.negativeSignPosition(df)); + df.setNegativePrefix("-"); // -123 EUR as in es_ES Spanish + df.setNegativeSuffix("EUR"); + assertEquals(1, JyLocale.negativeSignPosition(df)); + df.setNegativePrefix(""); // No clear example of this + df.setNegativeSuffix("SPAM-"); // that is distinguishable from 4 + // fy Western Frisian doesn't qualify (see below) so this is a synthetic one. + assertEquals(2, JyLocale.negativeSignPosition(df)); + df.setNegativePrefix("FCFA-"); // FCFA-123 as in sg-CF Sango (CAR) + df.setNegativeSuffix(""); + assertEquals(3, JyLocale.negativeSignPosition(df)); + df.setNegativePrefix("CHF"); // CHF123- as in German Swiss Francs + df.setNegativeSuffix("-"); // Python de_CH.ISO8859-1 + assertEquals(4, JyLocale.negativeSignPosition(df)); + df.setNegativePrefix("? "); // U0164 fy Western Frisian is the only Python + df.setNegativeSuffix("-"); // example of 2, and appears identical to 4 + assertEquals(4, JyLocale.negativeSignPosition(df)); + df.setNegativePrefix(""); // 123 as in empty locales + df.setNegativeSuffix(""); + assertEquals(_locale.CHAR_MAX, JyLocale.negativeSignPosition(df)); + } + + @Test + public void positiveCurrencyPrecedesValue() { + Locale locale = Locale.forLanguageTag("en-US"); + DecimalFormat df = (DecimalFormat) NumberFormat.getCurrencyInstance(locale); + df.setPositivePrefix("$"); // $123 as in en-US Java 8 + df.setPositiveSuffix(""); + assertEquals(1, JyLocale.positiveCurrencyPrecedesValue(df)); + df.setPositivePrefix(""); // 123$ (similar to 123 CHF) + df.setPositiveSuffix(" $"); + assertEquals(0, JyLocale.positiveCurrencyPrecedesValue(df)); + } + + @Test + public void negativeCurrencyPrecedesValue() { + Locale locale = Locale.forLanguageTag("en-US"); + DecimalFormat df = (DecimalFormat) NumberFormat.getCurrencyInstance(locale); + df.setNegativePrefix("($"); // ($123) as in en-US Java 8 + df.setNegativeSuffix(")"); + assertEquals(1, JyLocale.negativeCurrencyPrecedesValue(df)); + df.setNegativePrefix(""); // 123$ (similar to 123 CHF) + df.setNegativeSuffix(" $"); + assertEquals(0, JyLocale.negativeCurrencyPrecedesValue(df)); + } + + @Test + public void positiveSeparatedBySpace() { + Locale locale = Locale.forLanguageTag("en-US"); + DecimalFormat df = (DecimalFormat) NumberFormat.getCurrencyInstance(locale); + df.setPositivePrefix("$"); // $123 as in en-US Java 8 + df.setPositiveSuffix(""); + assertEquals(0, JyLocale.positiveSeparatedBySpace(df)); + df.setPositivePrefix(""); // 123 CHF + df.setPositiveSuffix(" CHF"); + assertEquals(1, JyLocale.positiveSeparatedBySpace(df)); + } + + @Test + public void negativeSeparatedBySpace() { + Locale locale = Locale.forLanguageTag("de-DE"); + DecimalFormat df = (DecimalFormat) NumberFormat.getCurrencyInstance(locale); + // Many Java locales use U+00A0, non-breaking space, for spacing, rather than " ". + assertEquals(1, JyLocale.negativeSeparatedBySpace(df)); + df.setNegativePrefix(""); // -123 ? + df.setNegativeSuffix("\u00A0" + "?"); + assertEquals(1, JyLocale.negativeSeparatedBySpace(df)); + df.setNegativePrefix(""); // 123 EUR/ + df.setNegativeSuffix(" EUR"); + assertEquals(1, JyLocale.negativeSeparatedBySpace(df)); + // Many Java locales use + df.setNegativePrefix("-$"); // -$123 + df.setNegativeSuffix(""); + assertEquals(0, JyLocale.negativeSeparatedBySpace(df)); + } + + @Test + public void extendedWhitespace() { + assertTrue(JyLocale.isExtendedWhitespace(' ')); + assertFalse(JyLocale.isExtendedWhitespace('a')); + assertTrue(JyLocale.isExtendedWhitespace('\u00A0')); + assertFalse(JyLocale.isExtendedWhitespace('?')); + } + + @Test + public void getlocale() { + settableInit(); + // @formatter:off + String script = + "from locale import normalize, setlocale, getlocale, LC_ALL, LC_NUMERIC\n" + + "norm = normalize('zh_CN') \n" + + "setlocale(LC_ALL,('zh_CN',None)) \n" + + "actual = getlocale() \n" + "expected = ('zh_CN', 'gb2312') \n"; + // @formatter:on + PyCode code = interp.compile(script); + interp.exec(code); + PyObject norm = interp.get("norm"); + assertEquals(new PyString("zh_CN.gb2312"), norm); + PyObject actual = interp.get("actual"); + PyObject expected = interp.get("expected"); + assertEquals(expected, actual); + script = "actual = getlocale(LC_NUMERIC) \n"; + interp.exec(script); + actual = interp.get("actual"); + assertEquals(expected, actual); + } + + @Test + public void setlocaleC() { + settableInit(); + // @formatter:off + String script = + "from locale import setlocale, getlocale, localeconv, LC_ALL\n" + + "setlocale(LC_ALL,'C') \n" + + "actualLocale = getlocale() \n" + + "actual = localeconv() \n" + + "expected = { " + + " 'mon_decimal_point': '', 'int_frac_digits': 127, " + + " 'p_sep_by_space': 127, 'frac_digits': 127, " + + " 'thousands_sep': '', 'n_sign_posn': 127, " + + " 'decimal_point': '.', 'int_curr_symbol': '', " + + " 'n_cs_precedes': 127, 'p_sign_posn': 127, " + + " 'mon_thousands_sep': '', 'negative_sign': '', " + + " 'currency_symbol': '', 'n_sep_by_space': 127, " + + " 'p_cs_precedes': 127, 'positive_sign': '' } \n" + + "expectedLocale = (None,None) \n" + + "grouping = actual.pop('grouping',None) \n" + + "mon_grouping = actual.pop('mon_grouping',None) \n" + + "result = set( actual.items() ) ^ set(expected.items()) \n" + + "resultGrouping = (grouping == [] ) \n" + + "resultMonGrouping = (mon_grouping == [] ) \n"; + // @formatter:on + interp.exec(script); + assertInterpEquals("expectedLocale", "actualLocale"); + PyObject result = interp.get("result"); + assertEquals(new PySet(), result); + assertPyTrue("resultGrouping"); + assertPyTrue("resultMonGrouping"); + } + + @Test + public void strCompareUS() { + settableInit(); + _locale.setlocale(_locale.LC_ALL, new PyString("en_US")); + assertEquals(-1, _locale.strcoll(new PyString("aaa"), new PyString("baa"))); + assertEquals(1, _locale.strcoll(new PyString("baa"), new PyString("aaa"))); + assertEquals(0, _locale.strcoll(new PyString("knight"), new PyString("knight"))); + } + + @Test + public void strCompareChineseMainlandInterp() { + Py.writeDebug("_localeTest", "strCompareCMI()"); + // also test exposure through locale itself here + settableInit(); + // @formatter:off + String script = "from _locale import setlocale, LC_ALL, strcoll \n" + + "setlocale(LC_ALL, 'zh_CN.UTF-8' ) \n" + + "resultSame = strcoll( u'\\u4e00', u'\\u4e00' ) \n" // yi / yi + + "resultLvsU = strcoll( '\\xe4\\xb8\\x80', u'\\u4e00' ) \n" + + "resultAscii = strcoll( 'b', 'a' ) \n" + + "resultUltU1 = strcoll( u'\\u4e00', u'\\u5f00' ) \n" // yi / kai + + "resultUltU2 = strcoll( u'\\u597d', u'\\u4e00' ) \n"; // hao / yi + // @formatter:on + interp.exec(script); + assertPyEquals(0, "resultSame"); + assertPyEquals(0, "resultLvsU"); + assertPyEquals(1, "resultAscii"); + assertPyEquals(1, "resultUltU1"); + assertPyEquals(-1, "resultUltU2"); + } + + @Test + public void strCompareC() { + Py.writeDebug("_localeTest", "strCompareC()"); + // also test exposure through locale itself here + settableInit(); + // @formatter:off + String script = + "from locale import setlocale, LC_ALL, strcoll \n" + + "setlocale(LC_ALL, 'C' ) \n" + + "result1 = strcoll( 'a', 'b' ) \n" + + "result2 = strcoll( 'b', 'a' ) \n"; + // @formatter:on + interp.exec(script); + assertPyEquals(-1, "result1"); + assertPyEquals(1, "result2"); + } + + @Test + public void strxfrm() { + Py.writeDebug("_localeTest", "strxfrm()"); + settableInit(); + // @formatter:off + String script = + "from _locale import setlocale, LC_ALL, strxfrm \n" + + "setlocale(LC_ALL, 'zh_CN.UTF-8' ) \n" + + "resultU = strxfrm( u'\\u4e00') \n" + + "resultL = strxfrm( '\\xe4\\xb8\\x80' ) \n" + + "result1 = (resultU == u'\\u4e00') \n" + + "result2 = (resultU == resultL) \n" ; + // @formatter:on + interp.exec(script); + assertPyTrue("result1"); + assertPyTrue("result2"); + } + + @Test + public void dateSymbols() { + settableInit(); + // @formatter:off + String script = + "from locale import setlocale, LC_ALL \n" + + "from datetime import datetime \n" + + "setlocale(LC_ALL, 'C' ) \n" + + "resultC = datetime(2019,04,15,15, 56, 44).strftime('%c') \n" + + "setlocale(LC_ALL, 'de_DE' ) \n" + + "resultD = datetime(1919,05,16,15, 56, 44).strftime('%A %Y') \n" ; + // @formatter:on + interp.exec(script); + assertPyEquals("Mon Apr 15 15:56:44 2019", "resultC"); + assertPyEquals("Freitag 1919", "resultD"); + } + +} -- Repository URL: https://hg.python.org/jython From jython-checkins at python.org Sun Sep 8 08:24:00 2019 From: jython-checkins at python.org (jeff.allen) Date: Sun, 08 Sep 2019 12:24:00 +0000 Subject: [Jython-checkins] =?utf-8?q?jython=3A_Take_the_maven_version_fro?= =?utf-8?q?m_version=2Eproperties?= Message-ID: <20190908122400.1.BCA8AE19F789D13A@mg.python.org> https://hg.python.org/jython/rev/54ed8d276773 changeset: 8287:54ed8d276773 user: Jeff Allen date: Mon Sep 02 21:00:23 2019 +0100 summary: Take the maven version from version.properties Move the version from hard-coded 2.7.0-SNAPSHOT to property read in. The use of gpg is disabled because it does not work on all platforms. files: maven/build.xml | 70 ++++++++++++++++++++---------------- 1 files changed, 38 insertions(+), 32 deletions(-) diff --git a/maven/build.xml b/maven/build.xml --- a/maven/build.xml +++ b/maven/build.xml @@ -32,48 +32,52 @@ - - + + - - + + - - + + - - + + - - + + - - + + + + + + - + @@ -89,18 +93,19 @@ + + default="${m2.repo}/${m2.groupDir}/@{artifactId}/@{version}"/> + default="@{artifactId}-@{version}"/> - + - + @@ -125,10 +130,11 @@ --> + - + - + @@ -139,13 +145,14 @@ --> + + tofile="${build.dir}/@{artifactId}-@{version}.pom"> - + @@ -157,33 +164,32 @@ --> + tofile="${build.dir}/@{artifactId}-@{version}.jar"/> - - + + - + @@ -208,5 +214,5 @@ - + -- Repository URL: https://hg.python.org/jython From jython-checkins at python.org Sun Sep 8 08:24:00 2019 From: jython-checkins at python.org (jeff.allen) Date: Sun, 08 Sep 2019 12:24:00 +0000 Subject: [Jython-checkins] =?utf-8?q?jython=3A_Check_for_oversize_array_a?= =?utf-8?q?llocation_in_BaseBytes_=28fixes_=232796=29=2E?= Message-ID: <20190908122400.1.1D49212514A2C2B8@mg.python.org> https://hg.python.org/jython/rev/4bbc6d13f9af changeset: 8288:4bbc6d13f9af user: Jeff Allen date: Sat Sep 07 22:57:04 2019 +0100 summary: Check for oversize array allocation in BaseBytes (fixes #2796). In bytearray.repeat, integer rounding of the new computed size results in a negative size. This change set re-works the logic using Java long and an explicit test against sys.maxsize. At the same time, other logic around Builder and repeat() is improved. files: NEWS | 1 + src/org/python/core/BaseBytes.java | 315 ++++----- src/org/python/core/PyByteArray.java | 20 +- tests/java/org/python/core/BaseBytesTest.java | 27 +- 4 files changed, 164 insertions(+), 199 deletions(-) diff --git a/NEWS b/NEWS --- a/NEWS +++ b/NEWS @@ -5,6 +5,7 @@ Development tip Bugs fixed + - [ 2796 ] Request for oversize arrays not handled in BaseBytes and PyByteArray - [ 2730 ] datetime.strptime('%b') behaviour inconsistent with CPython on Windows JDK 9+ - [ 2613 ] MANIFEST.MF contains unfilled placeholders - [ 2330 ] full-build fails to copy CPython License diff --git a/src/org/python/core/BaseBytes.java b/src/org/python/core/BaseBytes.java --- a/src/org/python/core/BaseBytes.java +++ b/src/org/python/core/BaseBytes.java @@ -45,8 +45,8 @@ * when applied to a bytearray. Or it may be that the method returns a * PyList of instances of the target type, for example {@link #rpartition(PyObject)}. * This is achieved by the sub-class defining {@link #getslice(int, int, int)} and - * {@link #getBuilder(int)} to return instances of its own type. See the documentation of particular - * methods for more information. + * {@link #getResult(Builder)} to return instances of its own type. See the documentation of the + * particular methods for more information. */ @Untraversable public abstract class BaseBytes extends PySequence implements List { @@ -120,7 +120,8 @@ * @throws IllegalArgumentException if the range [offset:offset+size] is not within the array * bounds of storage or size<0. */ - protected void setStorage(byte[] storage, int size, int offset) throws IllegalArgumentException { + protected void setStorage(byte[] storage, int size, int offset) + throws IllegalArgumentException { if (size < 0 || offset < 0 || offset + size > storage.length) { throw new IllegalArgumentException(); } else { @@ -257,7 +258,8 @@ * @throws PyException (TypeError) if the PyString is actually a {@link PyUnicode} * and encoding is null */ - protected static String encode(PyString arg, String encoding, String errors) throws PyException { + protected static String encode(PyString arg, String encoding, String errors) + throws PyException { // Jython encode emits a String (not byte[]) String encoded; @@ -585,7 +587,7 @@ if (value < 0 || value > 255) { throw Py.ValueError("byte must be in range(0, 256)"); } - return (byte)value; + return (byte) value; } /** @@ -621,7 +623,7 @@ return byteCheck(value.asIndex()); } else if (value.getType() == PyString.TYPE) { // Exactly PyString (not PyUnicode) - String strValue = ((PyString)value).getString(); + String strValue = ((PyString) value).getString(); if (strValue.length() != 1) { throw Py.ValueError("string must be of size 1"); } @@ -653,7 +655,7 @@ return null; } else if (b instanceof BufferProtocol) { - return ((BufferProtocol)b).getBuffer(PyBUF.FULL_RO); + return ((BufferProtocol) b).getBuffer(PyBUF.FULL_RO); } else { return null; @@ -1039,7 +1041,7 @@ if (target instanceof PyTuple) { // target is a tuple of suffixes/prefixes and only one need match - for (PyObject t : ((PyTuple)target).getList()) { + for (PyObject t : ((PyTuple) target).getList()) { if (match(t, index[0], index[3], endswith)) { return true; } @@ -1121,7 +1123,7 @@ char[] buf = new char[size]; int j = offset + size; for (int i = size; --i >= 0;) { - buf[i] = (char)(0xff & storage[--j]); + buf[i] = (char) (0xff & storage[--j]); } return new String(buf); } @@ -1182,8 +1184,8 @@ } /** - * Convenience method to create a TypeError PyException with the message - * "can't concat {type} to {toType}" + * Convenience method to create a TypeError PyException with the message "can't + * concat {type} to {toType}" * * @param type * @param toType @@ -1260,11 +1262,11 @@ } /** - * This class implements the Boyer-Moore-Horspool Algorithm for find a pattern in text, applied - * to byte arrays. The BMH algorithm uses a table of bad-character skips derived from the - * pattern. The bad-character skips table tells us how far from the end of the pattern is a byte - * that might match the text byte currently aligned with the end of the pattern. For example, - * suppose the pattern ("panama") is at position 6: + * This class implements the Boyer-Moore-Horspool Algorithm for finding a pattern in text, + * applied to byte arrays. The BMH algorithm uses a table of bad-character skips derived from + * the pattern. The bad-character skips table tells us how far from the end of the pattern is a + * byte that might match the text byte currently aligned with the end of the pattern. For + * example, suppose the pattern ("panama") is at position 6: * *

      *                    1         2         3
@@ -1274,7 +1276,7 @@
      * 
* * This puts the 'p' of 'map' against the last byte 'a' of the pattern. Rather than testing the - * pattern, we will look up 'p' in the skip table. There is an 'p' just 5 steps from the end of + * pattern, we will look up 'p' in the skip table. There is a 'p' just 5 steps from the end of * the pattern, so we will move the pattern 5 places to the right before trying to match it. * This allows us to move in large strides through the text. */ @@ -1869,7 +1871,7 @@ int value = hexDigit(c); c = hex.charAt(i++); // Throw IndexOutOfBoundsException if no second digit value = (value << 4) + hexDigit(c); - r[p++] = (byte)value; + r[p++] = (byte) value; } catch (IllegalArgumentException e) { throw Py.ValueError(String.format(fmt, i - 1)); } catch (IndexOutOfBoundsException e) { @@ -1924,8 +1926,8 @@ if (v == null) { // Unsuitable object to be in this join String fmt = "can only join an iterable of bytes (item %d has type '%.80s')"; - throw Py.TypeError(String.format(fmt, iterList.size(), o.getType() - .fastGetName())); + throw Py.TypeError( + String.format(fmt, iterList.size(), o.getType().fastGetName())); } iterList.add(v); totalSize += v.getLen(); @@ -1943,7 +1945,7 @@ } // Load the Views from the iterator into a new PyByteArray - PyByteArray result = new PyByteArray((int)totalSize); + PyByteArray result = new PyByteArray((int) totalSize); int p = result.offset; // Copy-to pointer first = true; @@ -1963,7 +1965,7 @@ return result; } finally { - // All the buffers we acquired have to be realeased + // All the buffers we acquired have to be released for (PyBuffer v : iterList) { v.release(); } @@ -2189,7 +2191,7 @@ byte[] r; // Build result here try { // Good to go. As we know the ultimate size, we can do all our allocation in one - r = new byte[(int)result_len]; + r = new byte[(int) result_len]; } catch (OutOfMemoryError e) { throw Py.OverflowError("replace bytes is too long"); } @@ -2252,11 +2254,11 @@ int to_len = to.getLen(); // Calculate length of result and check for too big - long result_len = ((long)count) * to_len + size; + long result_len = ((long) count) * to_len + size; byte[] r; // Build result here try { // Good to go. As we know the ultimate size, we can do all our allocation in one - r = new byte[(int)result_len]; + r = new byte[(int) result_len]; } catch (OutOfMemoryError e) { throw Py.OverflowError("replace bytes is too long"); } @@ -2313,7 +2315,7 @@ byte[] r; // Build result here try { // Good to go. As we know the ultimate size, we can do all our allocation in one - r = new byte[(int)result_len]; + r = new byte[(int) result_len]; } catch (OutOfMemoryError e) { throw Py.OverflowError("replace bytes is too long"); } @@ -2919,7 +2921,7 @@ if (fillchar == null) { return ' '; } else if (fillchar.length() == 1) { - return (byte)fillchar.charAt(0); + return (byte) fillchar.charAt(0); } else { throw Py.TypeError(function + "() argument 2 must be char, not str"); } @@ -2946,11 +2948,11 @@ } // Construct the result in a Builder of the desired width - Builder builder = getBuilder(left + size + right); + Builder builder = new Builder(left + size + right); builder.repeat(pad, left); builder.append(this); builder.repeat(pad, right); - return builder.getResult(); + return getResult(builder); } /** @@ -3019,7 +3021,7 @@ * occurring in the array. This treats other non-printing characters or escape sequences as * regular characters. *

- * The actual class of the returned object is determined by {@link #getBuilder(int)}. + * The actual class of the returned object is determined by {@link #getResult(Builder)}. * * @param tabsize number of character positions between tab stops * @return copy of this byte array with tabs expanded @@ -3027,8 +3029,8 @@ final BaseBytes basebytes_expandtabs(int tabsize) { // We could only work out the true size by doing the work twice, // so make a guess and let the Builder re-size if it's not enough. - int estimatedSize = size + size / 8; - Builder builder = getBuilder(estimatedSize); + long estimatedSize = (long) size + size / 8; + Builder builder = new Builder(estimatedSize); int carriagePosition = 0; int limit = offset + size; @@ -3038,7 +3040,7 @@ if (c == '\t') { // Number of spaces is 1..tabsize int spaces = tabsize - carriagePosition % tabsize; - builder.repeat((byte)' ', spaces); + builder.repeat((byte) ' ', spaces); carriagePosition += spaces; } else { // Transfer the character, but if it is a line break, reset the carriage @@ -3047,7 +3049,7 @@ } } - return builder.getResult(); + return getResult(builder); } /** @@ -3062,7 +3064,7 @@ final BaseBytes basebytes_zfill(int width) { // How many zeros will I need? int fill = width - size; - Builder builder = getBuilder((fill > 0) ? width : size); + Builder builder = new Builder((fill > 0) ? width : size); if (fill <= 0) { // width <= size so result is just a copy of this array @@ -3078,20 +3080,19 @@ } } // Now insert enough zeros - builder.repeat((byte)'0', fill); + builder.repeat((byte) '0', fill); // And finally the numeric part. Note possibility of no text eg. ''.zfill(6). if (size > p) { builder.append(this, p, size); } } - return builder.getResult(); + return getResult(builder); } // // Character class operations // - // Bit to twiddle (XOR) for lowercase letter to uppercase and vice-versa. private static final int SWAP_CASE = 0x20; @@ -3356,7 +3357,7 @@ // 2 = in a word (hence have have seen cased character) for (int i = 0; i < size; i++) { - byte c = storage[offset+i]; + byte c = storage[offset + i]; if (isupper(c)) { if (state == 2) { // Violation: can't continue a word in upper case @@ -3454,7 +3455,7 @@ */ final BaseBytes basebytes_capitalize() { - Builder builder = getBuilder(size); + Builder builder = new Builder(size); if (size > 0) { // Treat first character @@ -3467,7 +3468,7 @@ // Treat the rest for (int i = 1; i < size; i++) { - c = storage[offset+i]; + c = storage[offset + i]; if (isupper(c)) { c ^= SWAP_CASE; // 'A' -> 'a', etc. } @@ -3476,7 +3477,7 @@ } } - return builder.getResult(); + return getResult(builder); } /** @@ -3498,10 +3499,10 @@ */ final BaseBytes basebytes_lower() { - Builder builder = getBuilder(size); + Builder builder = new Builder(size); for (int i = 0; i < size; i++) { - byte c = storage[offset+i]; + byte c = storage[offset + i]; if (isupper(c)) { c ^= SWAP_CASE; // 'A' -> 'a', etc. } @@ -3509,7 +3510,7 @@ builder.append(c); } - return builder.getResult(); + return getResult(builder); } /** @@ -3531,10 +3532,10 @@ */ final BaseBytes basebytes_swapcase() { - Builder builder = getBuilder(size); + Builder builder = new Builder(size); for (int i = 0; i < size; i++) { - byte c = storage[offset+i]; + byte c = storage[offset + i]; if (isalpha(c)) { c ^= SWAP_CASE; // 'a' -> 'A', 'A' -> 'a', etc. } @@ -3542,7 +3543,7 @@ builder.append(c); } - return builder.getResult(); + return getResult(builder); } /** @@ -3568,11 +3569,11 @@ */ final BaseBytes basebytes_title() { - Builder builder = getBuilder(size); + Builder builder = new Builder(size); boolean inWord = false; // We begin, not in a word (sequence of cased characters) for (int i = 0; i < size; i++) { - byte c = storage[offset+i]; + byte c = storage[offset + i]; if (!inWord) { // When we are not in a word ... @@ -3594,7 +3595,7 @@ // Put the adjusted character in the output as a byte builder.append(c); } - return builder.getResult(); + return getResult(builder); } /** @@ -3617,10 +3618,10 @@ */ final BaseBytes basebytes_upper() { - Builder builder = getBuilder(size); + Builder builder = new Builder(size); for (int i = 0; i < size; i++) { - byte c = storage[offset+i]; + byte c = storage[offset + i]; if (islower(c)) { c ^= SWAP_CASE; // 'a' -> 'A' etc. } @@ -3628,7 +3629,7 @@ builder.append(c); } - return builder.getResult(); + return getResult(builder); } /* @@ -3661,41 +3662,6 @@ return 0xff & byteAt(index); } - /** - * Helper to implement {@link #repeat(int)}. Use something like: - * - *

-     * @Override
-     * protected PyByteArray repeat(int count) {
-     *     PyByteArray ret = new PyByteArray();
-     *     ret.setStorage(repeatImpl(count));
-     *     return ret;
-     * }
-     * 
- * - * @param count the number of times to repeat this. - * @return this byte array repeated count times. - */ - protected synchronized byte[] repeatImpl(int count) { - if (count <= 0) { - return emptyStorage; - } else { - // Allocate new storage, in a guarded way - long newSize = ((long)count) * size; - byte[] dst; - try { - dst = new byte[(int)newSize]; - } catch (OutOfMemoryError e) { - throw Py.MemoryError(e.getMessage()); - } - // Now fill with the repetitions needed - for (int i = 0, p = 0; i < count; i++, p += size) { - System.arraycopy(storage, offset, dst, p, size); - } - return dst; - } - } - // // str() and repr() have different behaviour (despite PEP 3137) // @@ -3752,7 +3718,7 @@ if (c == '\\' || c == '\'') { // Special cases buf.append('\\'); } - buf.append((char)c); + buf.append((char) c); } else if (c == '\t') { // Special cases in the low 32 buf.append("\\t"); } else if (c == '\n') { @@ -3850,7 +3816,7 @@ * * @see java.util.List#size() * @return Number of bytes in byte array. - * */ + */ @Override public int size() { return size; @@ -4072,55 +4038,50 @@ */ /** + * Every sub-class of BaseBytes overrides this method to access a Builder and + * return that class' particular type, possibly without copying. Although the instance of which + * this is a method is not used, the class of that instance determines which overridden + * implementation is chosen, and hence both the action and the return type. + * + * @param b containing the result + * @return a new object of the correct sub-class + */ + protected abstract BaseBytes getResult(Builder b); + + /** * A Builder holds a buffer of bytes to which new bytes may be appended while * constructing the value of byte array, even when the type ultimately constructed is immutable. * The value it builds may be transferred (normally without copying) to a new instance of the * type being built. - *

- * Builder is an abstract class. The each sub-class of BaseBytes may - * define its own concrete implementation in which {@link Builder#getResult()} returns an object - * of its own type, taking its value from the Builder contents using - * {@link #getStorage()} and {@link #getSize()}. Methods in BaseBytes obtain a - * Builder by calling the abstract method {@link BaseBytes#getBuilder(int)}, which - * the sub-class also defines, to return an isnstance of its characteristic Builder - * sub-class. The subclass that uses a method from BaseBytes returning a - * BaseBytes has to cast a returned from a BaseBytes method to its proper type. - * which it can do without error, since it was responsible for its actual type. - *

- * Implementation note: This can be done in a type-safe way but, in the present design, - * only by making BaseBytes parameterised class. - * */ - protected static abstract class Builder /* */{ - - /** - * Return an object of type B extends BaseBytes whose content is what we built. - */ - abstract BaseBytes getResult(); + protected static class Builder { // Internal state private byte[] storage = emptyStorage; private int size = 0; /** - * Construct a builder with specified initial capacity. + * Construct a builder with specified initial capacity. The use of a {@code long} argument + * allows the caller to delegate overflow checks to this constructor in certain cases. One + * cannot allocate more bytes than the JVM-allows for an array. * * @param capacity */ - Builder(int capacity) { + Builder(long capacity) { makeRoomFor(capacity); } /** - * Get an array of bytes containing the accumulated value, and clear the existing contents - * of the Builder. {@link #getCount()} returns the number of valid bytes in this array, - * which may be longer than the valid data. + * Destructively get the array of bytes containing the accumulated value, leaving the + * Builder empty. The array may be longer than the valid data if {@link #makeRoomFor(long)} + * chose so. {@link #getSize()}, continues to return the number of valid bytes in the array + * last returned, until an append next occurs. This ensures the idiom + * {@code func(getStorage(), getSize())} works as expected. *

* It is intended the client call this method only once to get the result of a series of - * append operations. A second call to {@link #getCount()}, before any further appending, + * append operations. A second call to {@link #getStorage()}, before any further appending, * returns a zero-length array. This is to ensure that the same array is not given out - * twice. However, {@link #getCount()} continues to return the number bytes accumulated - * until an append next occurs. + * twice. * * @return an array containing the accumulated result */ @@ -4131,8 +4092,8 @@ } /** - * Number of bytes accumulated. In conjunctin with {@link #getStorage()}, this provides the - * result. Unlike {@link #getStorage()}, it does not affect the contents. + * Number of bytes accumulated. In conjunction with {@link #getStorage()}, this provides the + * result. Unlike {@link #getStorage()}, it does not affect the contents of the builder. * * @return number of bytes accumulated */ @@ -4151,7 +4112,7 @@ } /** - * Append a number of repeats of a single byte to the value, fo example in padding. + * Append a number of repeats of a single byte to the value, for example in padding. * * @param b byte to repeat * @param n number of repeats (none if n<=0) @@ -4159,7 +4120,7 @@ void repeat(byte b, int n) { if (n > 0) { makeRoomFor(n); - while (n-- > 0) { + while (--n >= 0) { storage[size++] = b; } } @@ -4175,17 +4136,44 @@ } /** + * Repeat the contents of the given byte array. + * + * @param b + */ + void repeat(BaseBytes b, int n) { + repeat(b, 0, b.size, n); + } + + /** * Append the contents of a slice of the given byte array. * * @param b * @param start index of first byte copied - * @param end index of fisrt byte not copied + * @param end index of first byte not copied */ void append(BaseBytes b, int start, int end) { - int n = end - start; - makeRoomFor(n); - System.arraycopy(b.storage, b.offset + start, storage, size, n); - size += n; + int len = end - start; + makeRoomFor(len); + System.arraycopy(b.storage, b.offset + start, storage, size, len); + size += len; + } + + /** + * Repeat the contents of a slice of the given byte array. + * + * @param b + * @param start index of first byte copied + * @param end index of first byte not copied + * @param n number of repetitions + */ + void repeat(BaseBytes b, int start, int end, int n) { + int len = end - start; + makeRoomFor(len * (long) n); + start += b.offset; + while (--n >= 0) { + System.arraycopy(b.storage, start, storage, size, len); + size += len; + } } /** @@ -4200,34 +4188,43 @@ size += n; } - // Ensure there is enough free space for n bytes (or allocate some) - void makeRoomFor(int n) throws PyException { - int needed = size + n; + /** + * Ensure there is room for an additional {@code n} bytes, if necessary allocating a new + * {@code byte[]} and copying the contents. Trap and convert to {@code PyException} any + * overflow. + * + * @param n additional capacity requested ({@code long} so we can recognise overflow). + * @throws PyException(OverflowError) when {@code sys.maxsize} is exceeded. + * @throws PyException(MemoryError) when free heap or JVM limitation is exceeded. + */ + final void makeRoomFor(long n) throws PyException { + long needed = size + n; if (needed > storage.length) { - try { - if (storage == emptyStorage) { - /* - * After getStorage(): size deliberately retains its prior value, even - * though storage is set to emptyStorage. However, the first (non-empty) - * append() operation after that lands us here, because storage.length==0. - */ - size = 0; - if (n > 0) { - // When previously empty (incluing the constructor) allocate exactly n. - storage = new byte[n]; + if (size > 0 && storage == emptyStorage) { + // Special case where append comes after a getStorage(). + size = 0; + needed = n; + } + // Guardedly allocate the needed amount (or a rounded-up amount) + if (needed > PySystemState.maxsize) { + throw Py.OverflowError("max bytes len is " + PySystemState.maxsize); + } else if (needed <= 0) { + storage = emptyStorage; + } else { + try { + if (size == 0) { + // Just a new array + storage = new byte[(int) needed]; + } else { + // New array preserving existing contents + byte[] existing = storage; + storage = new byte[roundUp((int) needed)]; + System.arraycopy(existing, 0, storage, 0, size); } - } else { - // We are expanding an existing allocation: be imaginative - byte[] old = storage; - storage = new byte[roundUp(needed)]; - System.arraycopy(old, 0, storage, 0, size); + } catch (OutOfMemoryError e) { + // Exceeded the available heap or the limits of this JVM. + throw Py.MemoryError(e.getMessage()); } - } catch (OutOfMemoryError e) { - /* - * MemoryError is right for most clients. Some (e.g. bytearray.replace()) should - * convert it to an overflow, with a customised message. - */ - throw Py.MemoryError(e.getMessage()); } } } @@ -4259,16 +4256,4 @@ return 0; } } - - /** - * Every sub-class of BaseBytes overrides this method to return a Builder<B> - * where B is (normally) that class's particular type, and it extends - * Builder<B> so that {@link Builder#getResult()} produces an instance of - * B from the contents. - * - * @param capacity of the Builder<B> returned - * @return a Builder<B> for the correct sub-class - */ - protected abstract Builder/* */getBuilder(int capacity); - } diff --git a/src/org/python/core/PyByteArray.java b/src/org/python/core/PyByteArray.java --- a/src/org/python/core/PyByteArray.java +++ b/src/org/python/core/PyByteArray.java @@ -341,9 +341,9 @@ */ @Override protected synchronized PyByteArray repeat(int count) { - PyByteArray ret = new PyByteArray(); - ret.setStorage(repeatImpl(count)); - return ret; + Builder builder = new Builder(size * (long) count); + builder.repeat(this, count); + return getResult(builder); } /** @@ -831,21 +831,11 @@ * Support for Builder * ============================================================================================ * - * Extend BaseBytes.Builder so that it can return a PyByteArray and give the superclass a hook - * for it. */ @Override - protected Builder getBuilder(int capacity) { - // Return a Builder specialised for my class - return new Builder(capacity) { - - @Override - PyByteArray getResult() { - // Create a PyByteArray from the storage that the builder holds - return new PyByteArray(getStorage(), getSize()); - } - }; + protected PyByteArray getResult(Builder b) { + return new PyByteArray(b.getStorage(), b.getSize()); } /* diff --git a/tests/java/org/python/core/BaseBytesTest.java b/tests/java/org/python/core/BaseBytesTest.java --- a/tests/java/org/python/core/BaseBytesTest.java +++ b/tests/java/org/python/core/BaseBytesTest.java @@ -6,6 +6,7 @@ import junit.framework.TestCase; +import org.python.core.BaseBytes.Builder; import org.python.core.buffer.SimpleBuffer; import org.python.util.PythonInterpreter; @@ -685,7 +686,7 @@ } /** - * Returns a PyByteArray that repeats this sequence the given number of times, as in the + * Returns a MyBytes that repeats this sequence the given number of times, as in the * implementation of __mul__ for strings. * * @param count the number of times to repeat this. @@ -693,9 +694,9 @@ */ @Override protected MyBytes repeat(int count) { - MyBytes ret = new MyBytes(); - ret.setStorage(repeatImpl(count)); - return ret; + Builder builder = new Builder(size * (long) count); + builder.repeat(this, count); + return getResult(builder); } /** @@ -743,23 +744,11 @@ setStorage(builder.getStorage(), builder.getSize()); } - /* - * (non-Javadoc) - * - * @see org.python.core.BaseBytes#getBuilder(int) - */ @Override - protected Builder getBuilder(int capacity) { - // Return a Builder specialised for my class - return new Builder(capacity) { + protected MyBytes getResult(Builder b) { + return new MyBytes(b); + } - @Override - MyBytes getResult() { - // Create a MyBytes from the storage that the builder holds - return new MyBytes(this); - } - }; - } } /** -- Repository URL: https://hg.python.org/jython From jython-checkins at python.org Sun Sep 8 08:24:00 2019 From: jython-checkins at python.org (jeff.allen) Date: Sun, 08 Sep 2019 12:24:00 +0000 Subject: [Jython-checkins] =?utf-8?q?jython=3A_Fix_warnings_from_=27ant_j?= =?utf-8?q?avadoc=27=2E?= Message-ID: <20190908122400.1.03BA7916C2D4E4A9@mg.python.org> https://hg.python.org/jython/rev/2c1e08463533 changeset: 8289:2c1e08463533 user: Jeff Allen date: Sun Sep 08 08:36:45 2019 +0100 summary: Fix warnings from 'ant javadoc'. files: src/org/python/core/Console.java | 2 +- src/org/python/core/Options.java | 6 ++-- src/org/python/core/PrePy.java | 2 +- src/org/python/core/RegistryKey.java | 8 +++--- src/org/python/core/imp.java | 2 +- src/org/python/modules/_locale/CEmulationLocale.java | 2 - src/org/python/modules/_locale/DateSymbolJyLocale.java | 6 +--- src/org/python/modules/_locale/JyLocale.java | 2 - src/org/python/modules/_locale/_locale.java | 11 ++++----- 9 files changed, 17 insertions(+), 24 deletions(-) diff --git a/src/org/python/core/Console.java b/src/org/python/core/Console.java --- a/src/org/python/core/Console.java +++ b/src/org/python/core/Console.java @@ -12,7 +12,7 @@ * console. A default implementation (that does not provide any such facilities) is available as * {@link PlainConsole}. * - * @see org.python.core.RegistryKey.PYTHON_CONSOLE + * @see org.python.core.RegistryKey#PYTHON_CONSOLE */ public interface Console { 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 @@ -113,13 +113,13 @@ public static boolean caseok = false; /** - * If true, enable truedivision for the '/' operator. + * If true, enable true division for the '/' operator. * - * @see org.python.core.RegistryKey#PYTHON_OPTIONS_Q_NEW; + * @see org.python.core.RegistryKey#PYTHON_OPTIONS_Q_NEW */ 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. */ 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 @@ -280,7 +280,7 @@ *

    *
  1. it is {@code System.in} and {@link #isInteractive()} is {@code true}, or
  2. *
  3. the {@code -i} flag was given ({@link Options#interactive}={@code true}), and the - * filename associated with it is {@code null} or {@code""} or {@code "???"}.
  4. + * filename associated with it is {@code null} or {@code ""} or {@code "???"}. *
* * @param fp stream (tested only for {@code System.in}) diff --git a/src/org/python/core/RegistryKey.java b/src/org/python/core/RegistryKey.java --- a/src/org/python/core/RegistryKey.java +++ b/src/org/python/core/RegistryKey.java @@ -89,8 +89,8 @@ public static final String PYTHON_INSPECT = "python.inspect"; /** - * {@code python.io.encoding} controls the encoding of {@code sys.stdin}, {@codesys.stdout}, and - * {@code sys.stderr}. The encoding must name a Python codec, as in {@code codecs.encode()}. + * {@code python.io.encoding} controls the encoding of {@code sys.stdin}, {@code sys.stdout}, + * and {@code sys.stderr}. The encoding must name a Python codec, as in {@code codecs.encode()}. */ public static final String PYTHON_IO_ENCODING = "python.io.encoding"; @@ -200,12 +200,12 @@ /** * {@code python.os} defines the string used to report the underlying operating system. Used as - * prefix when resolving which operating system, impacting * some OS-specific behaviour. + * prefix when resolving which operating system, impacting some OS-specific behaviour. */ public static final String PYTHON_OS = "python.os"; /** - * {@code python.packages.fakepath} defines a sequence of directories and JARs * that are to be + * {@code python.packages.fakepath} defines a sequence of directories and JARs that are to be * sources of Python packages. */ public static final String PYTHON_PACKAGES_FAKEPATH = "python.packages.fakepath"; diff --git a/src/org/python/core/imp.java b/src/org/python/core/imp.java --- a/src/org/python/core/imp.java +++ b/src/org/python/core/imp.java @@ -772,7 +772,7 @@ * {@code __builtin__}. * * @param fully-qualified name of module - * @return + * @return the module named */ private static PyObject loadBuiltin(String name) { final String MSG = "import {0} # builtin"; diff --git a/src/org/python/modules/_locale/CEmulationLocale.java b/src/org/python/modules/_locale/CEmulationLocale.java --- a/src/org/python/modules/_locale/CEmulationLocale.java +++ b/src/org/python/modules/_locale/CEmulationLocale.java @@ -17,8 +17,6 @@ * Used by the _locale module. Callers would not usually interact with this class directly unless * working with _locale internals. * - * @Immutable - * * @since Jython 2.7.2 */ public class CEmulationLocale implements PyLocale { diff --git a/src/org/python/modules/_locale/DateSymbolJyLocale.java b/src/org/python/modules/_locale/DateSymbolJyLocale.java --- a/src/org/python/modules/_locale/DateSymbolJyLocale.java +++ b/src/org/python/modules/_locale/DateSymbolJyLocale.java @@ -6,12 +6,10 @@ /** * Separating these largely constant values from Python encoding conversions allows for safer * initialization even if modules are loaded in different orders. The Python {@code locale} and - * {@code codecs} modules have interdependencies, as well as {@org.python.modules.time.Time} and - * {@code org.python.modules._locale._locale}. The latter in particular depends on + * {@code codecs} modules have interdependencies, as well as {@link org.python.modules.time.Time} + * and {@link org.python.modules._locale._locale}. The latter in particular depends on * {@code java.util.Locale} and this class, but only uses the date symbol aspect. * - * @Immutable - * * @since Jython 2.7.2 */ public class DateSymbolJyLocale implements DateSymbolLocale { diff --git a/src/org/python/modules/_locale/JyLocale.java b/src/org/python/modules/_locale/JyLocale.java --- a/src/org/python/modules/_locale/JyLocale.java +++ b/src/org/python/modules/_locale/JyLocale.java @@ -24,8 +24,6 @@ * Used by the _locale module. Callers would not usually interact with this class directly unless * working with _locale internals. * - * @Immutable - * * @since Jython 2.7.2 */ public class JyLocale extends DateSymbolJyLocale implements PyLocale { diff --git a/src/org/python/modules/_locale/_locale.java b/src/org/python/modules/_locale/_locale.java --- a/src/org/python/modules/_locale/_locale.java +++ b/src/org/python/modules/_locale/_locale.java @@ -27,19 +27,19 @@ * implied by the Python locale module. * * Functional documentation can be found in the Python module docstring. This class depends on - * registry key {@link org.python.core.RegistryKey.PYTHON.LOCALE_CONTROL}. Additional implementation + * registry key {@link org.python.core.RegistryKey#PYTHON_LOCALE_CONTROL}. Additional implementation * details for users of this class are captured below. *

* Unicode. In general, Java and its locale settings are quite unicode heavy, making rich use of - * different symbols for eg currencies. This solution allows some of that to leak through by + * different symbols for e.g. currencies. This solution allows some of that to leak through by * encoding the Java locale value with the current character encoding. The Python locale module is * quite conservative and tends to keep things as solely strings. Python 2.x usually supports only * string / ascii by default in many cases, and only unicode when asked. This is a little less * conservative while only allowing values consistent with the current encoding. *

- * An example of this is some Python implementations using EUR rather than the Euro symbol ? / - * {@code 'u20ac'}, probably because ? is only available in Unicode. In the Java implementation, if - * UTF-8 encoding is set, the resulting entry in {@code localeconv()['currency_code']} is + * An example of this is some Python implementations using EUR rather than the Euro symbol ? + * ({@code 'u20ac'}), probably because ? is only available in Unicode. In the Java implementation, + * if UTF-8 encoding is set, the resulting entry in {@code localeconv()['currency_code']} is * {@code '\xe2\x82\xac'}. This can be used by {@code print()} and related functions directly. * Encoding failures for {@code currency_symbol} fall back to {@code int_curr_symbol} (eg EUR). * Encoding failures for {@code negative_sign}, which are sometimes unicode, fall back to an ANSI @@ -58,7 +58,6 @@ * is the responsibility of the calling code. * * @since Jython 2.7.2 - * */ public class _locale implements ClassDictInit { -- Repository URL: https://hg.python.org/jython From jython-checkins at python.org Sat Sep 21 06:58:50 2019 From: jython-checkins at python.org (jeff.allen) Date: Sat, 21 Sep 2019 10:58:50 +0000 Subject: [Jython-checkins] =?utf-8?q?jython=3A_Make_the_Gradle-built_JAR_?= =?utf-8?q?a_published_artefact=2E?= Message-ID: <20190921105850.1.5292674AB6EDA7A3@mg.python.org> https://hg.python.org/jython/rev/cdf832cb2e82 changeset: 8291:cdf832cb2e82 user: Jeff Allen date: Tue Sep 17 22:43:11 2019 +0100 summary: Make the Gradle-built JAR a published artefact. Introduces a ~/publications directory and places the bundles there, adding "jython-slim" built by Gradle. Names in maven/build.xml are made more consistent with build.xml. There are fixes to the Gradle build and additions to manipulate the version comparably with the Ant build. files: .hgignore | 2 + build.gradle | 144 +++++++++++++++++------------------ build.xml | 7 +- maven/build.xml | 109 +++++++++++++------------- settings.gradle | 2 +- 5 files changed, 132 insertions(+), 132 deletions(-) diff --git a/.hgignore b/.hgignore --- a/.hgignore +++ b/.hgignore @@ -30,11 +30,13 @@ __pycache__ bin +# Jython specific ant.properties build build2 cachedir dist +publications reports profile.txt diff --git a/build.gradle b/build.gradle --- a/build.gradle +++ b/build.gradle @@ -36,13 +36,19 @@ * application. It should be all you have to edit to version a release built * here. But of course you have to do it the hard way too (see build.xml) as * long as Ant is also used. + * + * The convention here is that you specify the version of the next release. If + * there are files not checked in, extra files (not of types hg ignores), or the + * changeset is not tagged correspondingly, the build will add "-SNAPSHOT" to + * the effective version. */ // Versions are specified in this grammar: -// . ( . )? ( )? ([-+] ? )? +// . ( . )? ( )? ( + | - )? version = '2.7.2a1+' // Valid examples (please preserve in comments): +//version = '2.7.2a1+' //version = '2.7.2a2' //version = '2.7.2b1-SNAPSHOT' //version = '2.7.2b1' @@ -306,9 +312,7 @@ // Create the properties when the task runs. But do it before the write! doFirst { - /* - * Query Mercurial for version and tagging. - */ + // Query Mercurial for version and tagging. String hgOutput = 'hg identify -ibt'.execute().text hgOutput = hgOutput.split('\n', 2)[0] @@ -328,8 +332,8 @@ * properties. (The Ant build.xml requires them to be set in parts, but * we can work it out from project.version.) */ - // .(.)()?([-+])? - def versionRegex = /(\d+)\.(\d+)(\.(\d+))?((a|b|rc)(\d+))?([-+]\w*)?/ + // .(.)()?(+|-)? + def versionRegex = /(\d+)\.(\d+)(\.(\d+))?((a|b|rc)(\d+))?(\+|-(\w+))?/ def versionMatcher = project.version =~ versionRegex if (versionMatcher.count != 1) { throw new IllegalArgumentException( @@ -344,7 +348,6 @@ String micro = versionResult[3] ? versionResult[4] : '0' // Convert the optional to numbers - int SNAPSHOT = 0xaa int level = 0, serial = 0 if (versionResult[5]) { // This is some kind of pre-final release (unless snapshot) @@ -359,12 +362,49 @@ level = 0xf } - // Except, if there was something after the version we decoded ... - if (versionResult[8]) { - level = SNAPSHOT // it's snapshot or dev version of some kind - serial = 0 + // Convert optional +|- to -DEV or -SNAPSHOT suffix or empty string + String snapshotSuffix = versionResult[8]; + if (snapshotSuffix == '+') { + snapshotSuffix = "-SNAPSHOT" } + /* + * Work out if it looks like a release, or adjust project.version. This logic prevents us + * releasing from a polluted repo (similar to logic in the Ant build.xml). + */ + def L = [0:'', 10:'a', 11:'b', 12:'rc', 15:''] + String release = "$major.$minor.$micro${L[level]}${serial?:''}" + + if (snapshotSuffix == null) { + // The version is named correctly for a release. Make safety checks on the repo. + String expectTag = "v$release" + String message = null; + if (ident.endsWith('+')) { + message = 'Version-controlled files have been edited since the last commit' + } else if (tag != expectTag) { + message = "Change set $ident is not tagged $expectTag." + } else { + // Query Mercurial for status: non-empty if uncontrolled (unignored) files. + String hgStatus = 'hg status'.execute().text + if (hgStatus.trim().length() > 0) { + message = 'Workspace contains uncontrolled files' + } + } + // If a message was set for any reason, fall back to a snapshot. + if (message == null) { + // Repository state is good for a full build. + snapshotSuffix = '' + } else { + // Some reason found not to build the release. + println "$message - build is a snapshot." + snapshotSuffix = '-SNAPSHOT' + } + } + + // Rebuild the version with the snapshot suffix, even if not given originally. + project.version = release + snapshotSuffix + println "This build is for v${project.version}." + property('jython.version', project.version) property('jython.major_version', major) property('jython.minor_version', minor) @@ -382,22 +422,6 @@ property('jython.build.date', (new SimpleDateFormat('MMM d yyyy')) .format(project.ext.buildDate)) - - /* - * Remind the developer about tagging it if it looks like a release, - * or to adjust project.version if we're moving on from the release. - */ - if (level != SNAPSHOT) { - def L = [0:'', 10:'a', 11:'b', 12:'rc', 15:''] - String release = "$major.$minor.$micro${L[level]}${serial?:''}" - println "This build is versioned for distribution as $release" - if (tag == 'tip' || ident.endsWith('+')) { - println "If this really is distributable, " + - "don't forget to tag it in the repository.\n" + - "Alternatively, add a suffix to version = " + - "'${project.version}' in build.gradle to shut this up." - } - } } } @@ -678,16 +702,15 @@ * distribute. * * Maybe have a second JAR that contains the additional material necessary to - * run integration tests (regression tests and others). Python tests are - * (incorrectly) in the main JAR at present. + * run integration tests (regression tests and others). */ -task sourcesJar(type: Jar) { +task sourcesJar(type: Jar, dependsOn: classes) { classifier = 'sources' from sourceSets.main.allJava } -task javadocJar(type: Jar) { +task javadocJar(type: Jar, dependsOn: javadoc) { classifier = 'javadoc' from javadoc.destinationDir } @@ -708,14 +731,24 @@ } repositories { - // Dummy one for test: need sonatype here and credentials from user + // Staging area where ant -f maven/build.xml will look. maven { - name = 'myRepo' - url = "file://${buildDir}/repo" + name = 'stagingRepo' + url = "file://${buildDir}/stagingRepo" } } } +// Ensure version computation/branding precedes any publication we use. +publish.dependsOn(generateVersionInfo) + +/* FIXME: Depending on publishMainPublicationToMavenLocal does not work, + because it does not exist when evaluating this line. Is this the deferred + configuration removed in Gradle 5.0? Failsd on POM version mismatch if main + publish task not run before publishMainPublicationToMavenLocal. +*/ +//publishMainPublicationToMavenLocal.dependsOn(generateVersionInfo) + // ---------------- Java unit tests -------------------------------------------- @@ -755,6 +788,8 @@ systemProperty 'python.test.source.dir', project.ext.testSourceDir // Place cache outside the targets for jar task systemProperty 'python.cachedir', "${project.buildDir}/cachedir" + // Logging level: default is message=INFO + //systemProperty 'python.verbose', 'CONFIG' include '**/*Test*' @@ -784,47 +819,6 @@ println "systemProperties = $systemProperties" } - /* A reminder of how this is addressed in build.xml, for comparison: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ } diff --git a/build.xml b/build.xml --- a/build.xml +++ b/build.xml @@ -168,6 +168,9 @@ + + + @@ -261,8 +264,6 @@ - - @@ -407,6 +408,8 @@ + + diff --git a/maven/build.xml b/maven/build.xml --- a/maven/build.xml +++ b/maven/build.xml @@ -32,21 +32,28 @@ + + + + + + - + - + + - - + + @@ -75,22 +82,28 @@ + + + + + + + + + - + - - + - + - - + @@ -110,9 +123,9 @@ - - @@ -125,32 +138,32 @@ - + - - - + + - + + - - + + + + + + + tofile="${build.maven}/@{artifactId}-@{version}.pom"> @@ -159,37 +172,17 @@ - - - - - - + - - - - + + + - - - - - - - - - - --> @@ -214,5 +207,13 @@ - + + + + + + + + diff --git a/settings.gradle b/settings.gradle --- a/settings.gradle +++ b/settings.gradle @@ -2,4 +2,4 @@ * Gradle settings for Jython. See also build.gradle. */ -rootProject.name = 'jython' +rootProject.name = 'jython-slim' -- Repository URL: https://hg.python.org/jython From jython-checkins at python.org Sat Sep 21 06:58:50 2019 From: jython-checkins at python.org (jeff.allen) Date: Sat, 21 Sep 2019 10:58:50 +0000 Subject: [Jython-checkins] =?utf-8?q?jython=3A_Insubstantial_change=3A_fo?= =?utf-8?q?rmatting_and_coding_standard_only=2E?= Message-ID: <20190921105850.1.FE2B653B62A75A26@mg.python.org> https://hg.python.org/jython/rev/f29c1c3bf757 changeset: 8293:f29c1c3bf757 user: Jeff Allen date: Sat Sep 21 08:47:02 2019 +0100 summary: Insubstantial change: formatting and coding standard only. files: src/org/python/compiler/ScopeInfo.java | 130 +++++++----- 1 files changed, 75 insertions(+), 55 deletions(-) diff --git a/src/org/python/compiler/ScopeInfo.java b/src/org/python/compiler/ScopeInfo.java --- a/src/org/python/compiler/ScopeInfo.java +++ b/src/org/python/compiler/ScopeInfo.java @@ -1,11 +1,13 @@ +// (C) Copyright 2019 Jython Developers // (C) Copyright 2001 Samuele Pedroni +// Licensed to the PSF under a Contributor Agreement package org.python.compiler; import java.util.Enumeration; +import java.util.Hashtable; import java.util.LinkedHashMap; import java.util.Map; -import java.util.Hashtable; import java.util.Vector; import org.python.antlr.ParseException; @@ -21,32 +23,45 @@ public int func_level; public void dump() { // for debugging - if (org.python.core.Options.verbose < org.python.core.Py.DEBUG) + if (org.python.core.Options.verbose < org.python.core.Py.DEBUG) { return; - for(int i=0; i entry : tbl.entrySet()) { String name = entry.getKey(); SymInfo info = entry.getValue(); int flags = info.flags; System.err.print(name); - if ((flags&BOUND) != 0) System.err.print('='); - // func scope global (affect nested scopes) - // vs. class scope global - if ((flags&NGLOBAL) != 0) System.err.print('G'); - else if ((flags&CLASS_GLOBAL) != 0) System.err.print('g'); - if ((flags&PARAM) != 0) System.err.print('P'); - else if ((flags&FROM_PARAM) != 0) System.err.print('p'); - if ((flags&CELL) != 0) System.err.print('!'); - if ((flags&FREE) != 0) System.err.print(",f"); + if ((flags & BOUND) != 0) { + System.err.print('='); + } + // func scope global (affect nested scopes) vs. class scope global + if ((flags & NGLOBAL) != 0) { + System.err.print('G'); + } else if ((flags & CLASS_GLOBAL) != 0) { + System.err.print('g'); + } + if ((flags & PARAM) != 0) { + System.err.print('P'); + } else if ((flags & FROM_PARAM) != 0) { + System.err.print('p'); + } + if ((flags & CELL) != 0) { + System.err.print('!'); + } + if ((flags & FREE) != 0) { + System.err.print(",f"); + } System.err.print(" "); } System.err.println(); } - public ScopeInfo(String name, PythonTree node, int level, int kind, - int func_level, ArgListCompiler ac) { + public ScopeInfo(String name, PythonTree node, int level, int kind, int func_level, + ArgListCompiler ac) { scope_name = name; scope_node = node; this.level = level; @@ -73,22 +88,22 @@ public int addGlobal(String name) { // global kind = func vs. class - int global = kind==CLASSSCOPE?CLASS_GLOBAL:NGLOBAL; + int global = kind == CLASSSCOPE ? CLASS_GLOBAL : NGLOBAL; SymInfo info = tbl.get(name); if (info == null) { - tbl.put(name,new SymInfo(global|BOUND)); + tbl.put(name, new SymInfo(global | BOUND)); return -1; } int prev = info.flags; - info.flags |= global|BOUND; + info.flags |= global | BOUND; return prev; } public int local = 0; public void addParam(String name) { -//System.out.println("addParam " + name); - tbl.put(name, new SymInfo(PARAM|BOUND,local++)); + // System.out.println("addParam " + name); + tbl.put(name, new SymInfo(PARAM | BOUND, local++)); names.addElement(name); } @@ -116,7 +131,7 @@ private final static Object PRESENT = new Object(); - public Hashtable inner_free = new Hashtable(); + public Hashtable inner_free = new Hashtable(); public Vector cellvars = new Vector(); @@ -128,10 +143,11 @@ public ScopeInfo up; - //Resolve the names used in the given scope, and mark any freevars used in the up scope + // Resolve the names used in the given scope, and mark any freevars used in the up scope public void cook(ScopeInfo up, int distance, CompilationContext ctxt) throws Exception { - if(up == null) + if (up == null) { return; // top level => nop + } this.up = up; this.distance = distance; boolean func = kind == FUNCSCOPE; @@ -139,23 +155,26 @@ cell = 0; boolean some_inner_free = inner_free.size() > 0; - for (Enumeration e = inner_free.keys(); e.hasMoreElements(); ) { - String name = (String)e.nextElement(); + for (Enumeration e = inner_free.keys(); e.hasMoreElements();) { + String name = (String) e.nextElement(); SymInfo info = tbl.get(name); if (info == null) { - tbl.put(name,new SymInfo(FREE)); + tbl.put(name, new SymInfo(FREE)); continue; } int flags = info.flags; if (func) { // not func global and bound ? - if ((flags&NGLOBAL) == 0 && (flags&BOUND) != 0) { + if ((flags & NGLOBAL) == 0 && (flags & BOUND) != 0) { info.flags |= CELL; - if ((info.flags&PARAM) != 0) + if ((info.flags & PARAM) != 0) { jy_paramcells.addElement(name); + } cellvars.addElement(name); info.env_index = cell++; - if ((flags&PARAM) == 0) purecells.addElement(name); + if ((flags & PARAM) == 0) { + purecells.addElement(name); + } continue; } } else { @@ -169,9 +188,11 @@ String name = entry.getKey(); SymInfo info = entry.getValue(); int flags = info.flags; - if (nested && (flags&FREE) != 0) up.inner_free.put(name,PRESENT); - if ((flags&(GLOBAL|PARAM|CELL)) == 0) { - if ((flags&BOUND) != 0) { // ?? only func + if (nested && (flags & FREE) != 0) { + up.inner_free.put(name, PRESENT); + } + if ((flags & (GLOBAL | PARAM | CELL)) == 0) { + if ((flags & BOUND) != 0) { // ?? only func // System.err.println("local: "+name); names.addElement(name); info.locals_index = local++; @@ -179,7 +200,9 @@ } info.flags |= FREE; some_free = true; - if (nested) up.inner_free.put(name,PRESENT); + if (nested) { + up.inner_free.put(name, PRESENT); + } } } if ((jy_npurecell = purecells.size()) > 0) { @@ -195,9 +218,11 @@ // XXX - this doesn't catch all cases - may depend subtly // on how visiting NOW works with antlr compared to javacc if ((unqual_exec || from_import_star)) { - if(some_inner_free) dynastuff_trouble(true, ctxt); - else if(func_level > 1 && some_free) + if (some_inner_free) { + dynastuff_trouble(true, ctxt); + } else if (func_level > 1 && some_free) { dynastuff_trouble(false, ctxt); + } } } @@ -205,12 +230,10 @@ private void dynastuff_trouble(boolean inner_free, CompilationContext ctxt) throws Exception { StringBuilder illegal = new StringBuilder(); if (unqual_exec && from_import_star) { - illegal.append("function '") - .append(scope_name) + illegal.append("function '").append(scope_name) .append("' uses import * and bare exec, which are illegal"); } else if (unqual_exec) { - illegal.append("unqualified exec is not allowed in function '") - .append(scope_name) + illegal.append("unqualified exec is not allowed in function '").append(scope_name) .append("'"); } else { illegal.append("import * is not allowed in function '").append(scope_name).append("'"); @@ -226,18 +249,18 @@ public Vector freevars = new Vector(); /** - * setup the closure on this scope using the scope passed into cook as up as - * the containing scope + * setup the closure on this scope using the scope passed into cook as up as the containing + * scope */ public void setup_closure() { setup_closure(up); } /** - * setup the closure on this scope using the passed in scope. This is used - * by jythonc to setup its closures. + * setup the closure on this scope using the passed in scope. This is used by jythonc to setup + * its closures. */ - public void setup_closure(ScopeInfo up){ + public void setup_closure(ScopeInfo up) { int free = cell; // env = cell...,free... Map up_tbl = up.tbl; boolean nested = up.kind != TOPSCOPE; @@ -245,19 +268,19 @@ String name = entry.getKey(); SymInfo info = entry.getValue(); int flags = info.flags; - if ((flags&FREE) != 0) { + if ((flags & FREE) != 0) { SymInfo up_info = up_tbl.get(name); // ?? differs from CPython -- what is the intended behaviour? if (up_info != null) { int up_flags = up_info.flags; - if ((up_flags&(CELL|FREE)) != 0) { + if ((up_flags & (CELL | FREE)) != 0) { info.env_index = free++; freevars.addElement(name); continue; } // ! func global affect nested scopes - if (nested && (up_flags&NGLOBAL) != 0) { - info.flags = NGLOBAL|BOUND; + if (nested && (up_flags & NGLOBAL) != 0) { + info.flags = NGLOBAL | BOUND; continue; } } @@ -269,22 +292,19 @@ @Override public String toString() { - return "ScopeInfo[" + scope_name + " " + kind + "]@" + - System.identityHashCode(this); + return "ScopeInfo[" + scope_name + " " + kind + "]@" + System.identityHashCode(this); } public void defineAsGenerator(expr node) { generator = true; if (hasReturnWithValue) { - throw new ParseException("'return' with argument " + - "inside generator", node); + throw new ParseException("'return' with argument " + "inside generator", node); } } public void noteReturnValue(Return node) { if (generator) { - throw new ParseException("'return' with argument " + - "inside generator", node); + throw new ParseException("'return' with argument " + "inside generator", node); } hasReturnWithValue = true; } -- Repository URL: https://hg.python.org/jython From jython-checkins at python.org Sat Sep 21 06:58:50 2019 From: jython-checkins at python.org (jeff.allen) Date: Sat, 21 Sep 2019 10:58:50 +0000 Subject: [Jython-checkins] =?utf-8?q?jython=3A_Upgrade_commons-compress_J?= =?utf-8?q?AR_to_1=2E19?= Message-ID: <20190921105850.1.260797A1B08D79D0@mg.python.org> https://hg.python.org/jython/rev/76c929fbb7e8 changeset: 8292:76c929fbb7e8 user: Jeff Allen date: Wed Sep 18 22:49:55 2019 +0100 summary: Upgrade commons-compress JAR to 1.19 files: build.gradle | 2 +- build.xml | 2 +- extlibs/commons-compress-1.18.jar | Bin extlibs/commons-compress-1.19.jar | Bin 4 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle --- a/build.gradle +++ b/build.gradle @@ -156,7 +156,7 @@ antlr 'org.antlr:antlr:3.5.2' implementation 'org.antlr:antlr-runtime:3.5.2' - implementation 'org.apache.commons:commons-compress:1.18' + implementation 'org.apache.commons:commons-compress:1.19' implementation 'org.bouncycastle:bcpkix-jdk15on:1.62' implementation 'org.bouncycastle:bcprov-jdk15on:1.62' diff --git a/build.xml b/build.xml --- a/build.xml +++ b/build.xml @@ -241,7 +241,7 @@ - + diff --git a/extlibs/commons-compress-1.18.jar b/extlibs/commons-compress-1.18.jar deleted file mode 100644 index e401046b5a6e5b1779fa8f50cc39dcd51a7da137..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 GIT binary patch [stripped] diff --git a/extlibs/commons-compress-1.19.jar b/extlibs/commons-compress-1.19.jar new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..5c9f52a2903d826c5f69ab8e342eac00d33264aa GIT binary patch [stripped] -- Repository URL: https://hg.python.org/jython From jython-checkins at python.org Sat Sep 21 06:58:50 2019 From: jython-checkins at python.org (jeff.allen) Date: Sat, 21 Sep 2019 10:58:50 +0000 Subject: [Jython-checkins] =?utf-8?q?jython=3A_Use_logging_instead_of_Sys?= =?utf-8?q?tem=2Eerr_in_the_compiler=2E?= Message-ID: <20190921105850.1.CBCD8AD13B1EB616@mg.python.org> https://hg.python.org/jython/rev/443426bd426c changeset: 8294:443426bd426c user: Jeff Allen date: Sat Sep 21 09:02:53 2019 +0100 summary: Use logging instead of System.err in the compiler. Otherwise, the pycompile phase of the Gradle build is very chatty, following changes to the way Options.verbose is determined. files: src/org/python/compiler/ScopeInfo.java | 68 +++++++------ 1 files changed, 36 insertions(+), 32 deletions(-) diff --git a/src/org/python/compiler/ScopeInfo.java b/src/org/python/compiler/ScopeInfo.java --- a/src/org/python/compiler/ScopeInfo.java +++ b/src/org/python/compiler/ScopeInfo.java @@ -9,6 +9,8 @@ import java.util.LinkedHashMap; import java.util.Map; import java.util.Vector; +import java.util.logging.Level; +import java.util.logging.Logger; import org.python.antlr.ParseException; import org.python.antlr.PythonTree; @@ -17,47 +19,49 @@ public class ScopeInfo extends Object implements ScopeConstants { + static final Logger LOGGER = Logger.getLogger("org.python.compiler"); + public PythonTree scope_node; public String scope_name; public int level; public int func_level; public void dump() { // for debugging - if (org.python.core.Options.verbose < org.python.core.Py.DEBUG) { - return; - } - for (int i = 0; i < level; i++) { - System.err.print(' '); - } - System.err.print(((kind != CLASSSCOPE) ? scope_name : "class " + scope_name) + ": "); - for (Map.Entry entry : tbl.entrySet()) { - String name = entry.getKey(); - SymInfo info = entry.getValue(); - int flags = info.flags; - System.err.print(name); - if ((flags & BOUND) != 0) { - System.err.print('='); + if (LOGGER.isLoggable(Level.FINE)) { + StringBuilder m = new StringBuilder(100); + for (int i = 0; i < level; i++) { + m.append(' '); } - // func scope global (affect nested scopes) vs. class scope global - if ((flags & NGLOBAL) != 0) { - System.err.print('G'); - } else if ((flags & CLASS_GLOBAL) != 0) { - System.err.print('g'); + m.append(((kind != CLASSSCOPE) ? scope_name : "class " + scope_name) + ": "); + for (Map.Entry entry : tbl.entrySet()) { + String name = entry.getKey(); + SymInfo info = entry.getValue(); + int flags = info.flags; + m.append(name); + if ((flags & BOUND) != 0) { + m.append('='); + } + // func scope global (affect nested scopes) vs. class scope global + if ((flags & NGLOBAL) != 0) { + m.append('G'); + } else if ((flags & CLASS_GLOBAL) != 0) { + m.append('g'); + } + if ((flags & PARAM) != 0) { + m.append('P'); + } else if ((flags & FROM_PARAM) != 0) { + m.append('p'); + } + if ((flags & CELL) != 0) { + m.append('!'); + } + if ((flags & FREE) != 0) { + m.append(",f"); + } + m.append(' '); } - if ((flags & PARAM) != 0) { - System.err.print('P'); - } else if ((flags & FROM_PARAM) != 0) { - System.err.print('p'); - } - if ((flags & CELL) != 0) { - System.err.print('!'); - } - if ((flags & FREE) != 0) { - System.err.print(",f"); - } - System.err.print(" "); + LOGGER.fine(m.toString()); } - System.err.println(); } public ScopeInfo(String name, PythonTree node, int level, int kind, int func_level, -- Repository URL: https://hg.python.org/jython From jython-checkins at python.org Sat Sep 21 06:58:50 2019 From: jython-checkins at python.org (jeff.allen) Date: Sat, 21 Sep 2019 10:58:50 +0000 Subject: [Jython-checkins] =?utf-8?q?jython=3A_Default_sys=2Eprefix_to_?= =?utf-8?b?Ii4iIHJhdGhlciB0aGFuIG51bGwu?= Message-ID: <20190921105850.1.F5553C194892A585@mg.python.org> https://hg.python.org/jython/rev/05f61ba4d447 changeset: 8290:05f61ba4d447 user: Jeff Allen date: Sun Sep 08 21:27:21 2019 +0100 summary: Default sys.prefix to "." rather than null. Noticed in Java tests, when python.home not set and there is no clue from locating a JAR, sys.prefix would be null, leading to an NPE. files: src/org/python/core/PySystemState.java | 68 +++++++------- 1 files changed, 34 insertions(+), 34 deletions(-) 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 @@ -30,6 +30,7 @@ import java.util.concurrent.locks.ReentrantLock; import java.util.jar.JarEntry; import java.util.jar.JarFile; +import java.util.logging.Logger; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -58,6 +59,8 @@ public class PySystemState extends PyObject implements AutoCloseable, ClassDictInit, Closeable, Traverseproc { + protected static final Logger logger = Logger.getLogger("org.python"); + protected static final String CACHEDIR_DEFAULT_NAME = "cachedir"; public static final String JYTHON_JAR = "jython.jar"; @@ -130,7 +133,7 @@ * contain bytes in the file system encoding for consistency with use in the standard library * (see sysconfig.py). */ - public static PyObject exec_prefix = Py.EmptyString; + public static PyObject exec_prefix; public static final PyString byteorder = new PyString("big"); public static final int maxint = Integer.MAX_VALUE; @@ -927,32 +930,36 @@ Py.writeError("systemState", "trying to reinitialize registry"); return; } + registry = preProperties; - registry = preProperties; + // Work out sys.prefix String prefix = findRoot(preProperties, postProperties, jarFileName); + + if (prefix == null || prefix.length() == 0) { + /* + * All strategies in find_root failed (can happen in embedded use), but sys.prefix is + * generally assumed not to be null (or even None). Go for current directory. + */ + prefix = "."; + logger.config("No property 'jython.home' or other clue. sys.prefix defaulting to ''."); + } + + // sys.exec_prefix is the same initially String exec_prefix = prefix; // Load the default registry - if (prefix != null) { - if (prefix.length() == 0) { - prefix = exec_prefix = "."; - } - try { - // user registry has precedence over installed registry - File homeFile = new File(registry.getProperty(USER_HOME), - ".jython"); - addRegistryFile(homeFile); - addRegistryFile(new File(prefix, "registry")); - } catch (Exception exc) { - // Continue - } + try { + // user registry has precedence over installed registry + File homeFile = new File(registry.getProperty(USER_HOME), ".jython"); + addRegistryFile(homeFile); + addRegistryFile(new File(prefix, "registry")); + } catch (Exception exc) { + // Continue: addRegistryFile does its own logging. } - if (prefix != null) { - PySystemState.prefix = Py.fileSystemEncode(prefix); - } - if (exec_prefix != null) { - PySystemState.exec_prefix = Py.fileSystemEncode(exec_prefix); - } + + // Exposed values have to be properly-encoded objects + PySystemState.prefix = Py.fileSystemEncode(prefix); + PySystemState.exec_prefix = Py.fileSystemEncode(exec_prefix); // Now the post properties (possibly set by custom JythonInitializer). registry.putAll(postProperties); @@ -1261,7 +1268,7 @@ } cachedir = new File(props.getProperty(PYTHON_CACHEDIR, CACHEDIR_DEFAULT_NAME)); if (!cachedir.isAbsolute()) { - String prefixString = prefix == null ? null : Py.fileSystemDecode(prefix); + String prefixString = Py.fileSystemDecode(prefix); cachedir = new File(prefixString, cachedir.getPath()); } } @@ -1304,13 +1311,9 @@ // The executable from the registry is a Unicode String path executableFile = new File(executable); } else { - if (prefix == null) { - return Py.None; - } else { - // The prefix is a unicode or encoded bytes object - executableFile = new File(Py.fileSystemDecode(prefix), - Platform.IS_WINDOWS ? "bin\\jython.exe" : "bin/jython"); - } + // The prefix is a unicode or encoded bytes object + executableFile = new File(Py.fileSystemDecode(prefix), + Platform.IS_WINDOWS ? "bin\\jython.exe" : "bin/jython"); } try { @@ -1461,15 +1464,12 @@ private static PyList initPath(Properties props, boolean standalone, String jarFileName) { PyList path = new PyList(); addPaths(path, props.getProperty(PYTHON_PATH, "")); - if (prefix != null) { - String libpath = new File(Py.fileSystemDecode(prefix), "Lib").toString(); - path.append(Py.fileSystemEncode(libpath)); // XXX or newUnicode? - } + String libpath = new File(Py.fileSystemDecode(prefix), "Lib").toString(); + path.append(Py.fileSystemEncode(libpath)); // XXX or newUnicode? if (standalone) { // standalone jython: add the /Lib directory inside JYTHON_JAR to the path addPaths(path, jarFileName + "/Lib"); } - return path; } -- Repository URL: https://hg.python.org/jython From jython-checkins at python.org Sun Sep 22 16:37:15 2019 From: jython-checkins at python.org (jeff.allen) Date: Sun, 22 Sep 2019 20:37:15 +0000 Subject: [Jython-checkins] =?utf-8?q?jython=3A_Delete_circle=2Eyml?= Message-ID: <20190922203715.1.2178A0B53ED72BAF@mg.python.org> https://hg.python.org/jython/rev/8e4fbaa393b6 changeset: 8296:8e4fbaa393b6 user: Christian Clauss date: Sat Sep 21 15:30:57 2019 +0100 summary: Delete circle.yml files: ACKNOWLEDGMENTS | 1 + circle.yml | 17 ----------------- 2 files changed, 1 insertions(+), 17 deletions(-) diff --git a/ACKNOWLEDGMENTS b/ACKNOWLEDGMENTS --- a/ACKNOWLEDGMENTS +++ b/ACKNOWLEDGMENTS @@ -185,6 +185,7 @@ yishenggudou (??) Andrew Kuchling Jim Peterson + Christian Clauss Local Variables: mode: indented-text diff --git a/circle.yml b/circle.yml deleted file mode 100644 --- a/circle.yml +++ /dev/null @@ -1,17 +0,0 @@ -machine: - java: - version: openjdk7 - -# refactor into a script some time -test: - override: - - case $CIRCLE_NODE_INDEX in 0) sudo update-alternatives --set java /usr/lib/jvm/java-7-openjdk-amd64/jre/bin/java; java -version ;; 1) sudo update-alternatives --set java /usr/lib/jvm/jdk1.7.0/bin/java; java -version ;; esac: - parallel: true - timeout: 2400 - - if [ $CIRCLE_NODE_INDEX -lt 2 ]; then ant developer-build regrtest-travis; elif [ $CIRCLE_NODE_INDEX -eq 2 ]; then ant developer-build; sudo update-alternatives --set java /usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java; ant regrtest-travis; fi: - parallel: true - timeout: 2400 - - post: - - mkdir -p $CIRCLE_TEST_REPORTS/junit/; cp -a dist/testreports/* $CIRCLE_TEST_REPORTS/junit/: - parallel: true -- Repository URL: https://hg.python.org/jython From jython-checkins at python.org Sun Sep 22 16:37:15 2019 From: jython-checkins at python.org (jeff.allen) Date: Sun, 22 Sep 2019 20:37:15 +0000 Subject: [Jython-checkins] =?utf-8?q?jython=3A_Fixed_issues_we_forgot_to_?= =?utf-8?q?add_to_NEWS=2E?= Message-ID: <20190922203715.1.1484529966AF30BB@mg.python.org> https://hg.python.org/jython/rev/109932ae93b6 changeset: 8297:109932ae93b6 user: Jeff Allen date: Sat Sep 21 17:03:31 2019 +0100 summary: Fixed issues we forgot to add to NEWS. ... going back to 2.7.1. (Not that many, actually.) files: NEWS | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-) diff --git a/NEWS b/NEWS --- a/NEWS +++ b/NEWS @@ -5,6 +5,11 @@ Development tip Bugs fixed + - [ 2666 ] Oracle JDK 7 out of support so no longer available on Travis + - [ 2294 ] Importation of modules from directories with non-ASCII characters fails + - [ 2055 ] isinstance() and issubclass() fail with abc.ABCMeta + - [ 2569 ] jython launcher fails on Windows if JAVA_HOME is set + - [ 2505 ] PySystemState is lost - [ 2796 ] Request for oversize arrays not handled in BaseBytes and PyByteArray - [ 2730 ] datetime.strptime('%b') behaviour inconsistent with CPython on Windows JDK 9+ - [ 2613 ] MANIFEST.MF contains unfilled placeholders -- Repository URL: https://hg.python.org/jython From jython-checkins at python.org Sun Sep 22 16:37:16 2019 From: jython-checkins at python.org (jeff.allen) Date: Sun, 22 Sep 2019 20:37:16 +0000 Subject: [Jython-checkins] =?utf-8?q?jython=3A_Tweaks_to_README?= Message-ID: <20190922203716.1.358FAAA665D97C30@mg.python.org> https://hg.python.org/jython/rev/8bae3f72712d changeset: 8299:8bae3f72712d user: Jeff Allen date: Sat Sep 21 20:39:18 2019 +0100 summary: Tweaks to README files: README.txt | 36 ++++++++++++++++++++---------------- 1 files changed, 20 insertions(+), 16 deletions(-) diff --git a/README.txt b/README.txt --- a/README.txt +++ b/README.txt @@ -1,8 +1,9 @@ Jython: Python for the Java Platform +------------------------------------ Welcome to Jython @jython.version at . @snapshot.banner@ -This is @readme.release@ release of the @jython.version.short@ version of Jython. +This is @readme.release@ release of version @jython.version.short@ of Jython. Along with language and runtime compatibility with CPython 2.7, Jython 2.7 provides substantial support of the Python ecosystem. This includes built-in @@ -15,24 +16,27 @@ This release was compiled on @os.name@ using @java.vendor@ Java version @java.version@ and requires a minimum of Java @jdk.target.version@ to run. -You can test your installation of Jython (not the standalone jar) by -running the regression tests, with the command: - -jython -m test.regrtest -e - -The regression tests can take about forty minutes. At the time of writing, -these tests are known to fail: - test___all__ - test_java_visibility - test_jy_internals - test_pep277 - test_ssl_jy -Please report other bugs at http://bugs.jython.org . - See ACKNOWLEDGMENTS for details about Jython's copyright, license, contributors, and mailing lists; and NEWS for detailed release notes, including bugs fixed, backwards breaking changes, and new features. The developers extend their thanks to all who contributed to this release of Jython, through bug reports, patches, pull requests, documentation -changes, email and conversation in any media. +changes, email and conversation in any media. We are grateful to the PSF for +continuing practical help and support to the project. + +Testing +------- +You can test your installation of Jython (not the standalone jar) by +running the regression tests, with the command: + +jython -m test.regrtest -e + +The regression tests can take about fifty minutes. At the time of writing, +these tests are known to fail (spuriously) on an installed Jython: + test___all__ + test_java_visibility + test_jy_internals + test_ssl_jy +Please report reproducible failures at http://bugs.jython.org . + -- Repository URL: https://hg.python.org/jython From jython-checkins at python.org Sun Sep 22 16:37:16 2019 From: jython-checkins at python.org (jeff.allen) Date: Sun, 22 Sep 2019 20:37:16 +0000 Subject: [Jython-checkins] =?utf-8?q?jython=3A_Fix_javadoc_errors_newly-d?= =?utf-8?q?etected_in_Java_8?= Message-ID: <20190922203716.1.9D8DE9D9D576D408@mg.python.org> https://hg.python.org/jython/rev/b180cce20e85 changeset: 8300:b180cce20e85 user: Jeff Allen date: Sun Sep 22 19:58:17 2019 +0100 summary: Fix javadoc errors newly-detected in Java 8 There's a lot of this, but it's confined to comments and mostly trivial. A lot of lint can build up in 20 years. Not treating warnings for now. files: src/com/ziclix/python/sql/DateFactory.java | 6 +- src/com/ziclix/python/sql/Fetch.java | 38 +- src/com/ziclix/python/sql/JavaDateFactory.java | 6 +- src/com/ziclix/python/sql/Procedure.java | 10 +- src/com/ziclix/python/sql/PyConnection.java | 4 +- src/com/ziclix/python/sql/handler/SQLServerDataHandler.java | 2 +- src/com/ziclix/python/sql/handler/UpdateCountDataHandler.java | 2 +- src/com/ziclix/python/sql/pipe/Sink.java | 4 +- src/com/ziclix/python/sql/pipe/Source.java | 2 +- src/com/ziclix/python/sql/zxJDBC.java | 2 +- src/org/python/core/AbstractArray.java | 71 +- src/org/python/core/BaseBytes.java | 811 ++++----- src/org/python/core/BaseSet.java | 16 +- src/org/python/core/BufferProtocol.java | 2 +- src/org/python/core/Options.java | 3 +- src/org/python/core/Py.java | 4 +- src/org/python/core/Py2kBuffer.java | 4 +- src/org/python/core/PyArray.java | 10 +- src/org/python/core/PyBUF.java | 169 +- src/org/python/core/PyBuffer.java | 20 +- src/org/python/core/PyByteArray.java | 45 +- src/org/python/core/PyComplex.java | 2 +- src/org/python/core/PyFloat.java | 2 +- src/org/python/core/PyInteger.java | 6 +- src/org/python/core/PyMemoryView.java | 6 +- src/org/python/core/PyObject.java | 383 ++-- src/org/python/core/PyString.java | 18 +- src/org/python/core/PySystemState.java | 17 +- src/org/python/core/PyUnicode.java | 2 +- src/org/python/core/RegistryKey.java | 9 +- src/org/python/core/Traverseproc.java | 5 +- src/org/python/core/__builtin__.java | 2 +- src/org/python/core/buffer/BaseArrayBuffer.java | 2 +- src/org/python/core/buffer/BaseBuffer.java | 12 +- src/org/python/core/buffer/BaseNIOBuffer.java | 2 +- src/org/python/core/buffer/SimpleBuffer.java | 4 +- src/org/python/core/buffer/SimpleNIOBuffer.java | 4 +- src/org/python/core/buffer/SimpleWritableBuffer.java | 4 +- src/org/python/core/buffer/Strided1DBuffer.java | 4 +- src/org/python/core/buffer/Strided1DNIOBuffer.java | 4 +- src/org/python/core/buffer/Strided1DWritableBuffer.java | 6 +- src/org/python/core/buffer/ZeroByteBuffer.java | 3 +- src/org/python/core/codecs.java | 1 + src/org/python/core/finalization/FinalizablePyObject.java | 124 +- src/org/python/core/imp.java | 20 +- src/org/python/core/io/IOBase.java | 31 +- src/org/python/core/stringlib/FloatFormatter.java | 5 +- src/org/python/core/stringlib/InternalFormat.java | 35 +- src/org/python/core/util/ByteSwapper.java | 20 +- src/org/python/core/util/ExtraMath.java | 5 +- src/org/python/core/util/FileUtil.java | 2 +- src/org/python/core/util/StringUtil.java | 3 +- src/org/python/modules/_bytecodetools.java | 2 +- src/org/python/modules/_io/OpenMode.java | 10 +- src/org/python/modules/_io/PyIOBase.java | 50 +- src/org/python/modules/binascii.java | 137 +- src/org/python/modules/cPickle.java | 192 +- src/org/python/modules/cmath.java | 2 +- src/org/python/modules/gc.java | 273 +- src/org/python/modules/math.java | 6 +- src/org/python/modules/struct.java | 89 +- src/org/python/util/InteractiveConsole.java | 7 +- src/org/python/util/InteractiveInterpreter.java | 19 +- src/org/python/util/PyServlet.java | 39 +- src/org/python/util/PythonInterpreter.java | 1 + 65 files changed, 1426 insertions(+), 1375 deletions(-) diff --git a/src/com/ziclix/python/sql/DateFactory.java b/src/com/ziclix/python/sql/DateFactory.java --- a/src/com/ziclix/python/sql/DateFactory.java +++ b/src/com/ziclix/python/sql/DateFactory.java @@ -53,7 +53,7 @@ * This function constructs an object holding a date value from the * given ticks value (number of seconds since the epoch; see the * documentation of the standard Python time module for details). - *

+ *

* Note: The DB API 2.0 spec calls for time in seconds since the epoch * while the Java Date object returns time in milliseconds since the epoch. * This module adheres to the python API and will therefore use time in @@ -68,7 +68,7 @@ * This function constructs an object holding a time value from the * given ticks value (number of seconds since the epoch; see the * documentation of the standard Python time module for details). - *

+ *

* Note: The DB API 2.0 spec calls for time in seconds since the epoch * while the Java Date object returns time in milliseconds since the epoch. * This module adheres to the python API and will therefore use time in @@ -83,7 +83,7 @@ * This function constructs an object holding a time stamp value from * the given ticks value (number of seconds since the epoch; see the * documentation of the standard Python time module for details). - *

+ *

* Note: The DB API 2.0 spec calls for time in seconds since the epoch * while the Java Date object returns time in milliseconds since the epoch. * This module adheres to the python API and will therefore use time in diff --git a/src/com/ziclix/python/sql/Fetch.java b/src/com/ziclix/python/sql/Fetch.java --- a/src/com/ziclix/python/sql/Fetch.java +++ b/src/com/ziclix/python/sql/Fetch.java @@ -31,14 +31,14 @@ /** *

The responsibility of a Fetch instance is to manage the iteration of a * ResultSet. Two different alogorithms are available: static or dynamic.

- *

+ * *

Static The static variety iterates the entire set immediately, * creating the necessary Jython objects and storing them. It is able to * immediately close the ResultSet so a call to close() is essentially a no-op * from a database resource perspective (it does clear the results list however). * This approach also allows for the correct rowcount to be determined since * the entire result set has been iterated.

- *

+ * *

Dynamic The dynamic variety iterates the result set only as requested. * This holds a bit truer to the intent of the API as the fetch*() methods actually * fetch when instructed. This is especially useful for managing exeedingly large @@ -54,7 +54,7 @@ /** * The total number of rows in the result set. - *

+ *

* Note: since JDBC provides no means to get this information without iterating * the entire result set, only those fetches which build the result statically * will have an accurate row count. @@ -157,7 +157,7 @@ /** * Fetch the next row of a query result set, returning a single sequence, * or None when no more data is available. - *

+ *

* An Error (or subclass) exception is raised if the previous call to * executeXXX() did not produce any result set or no call was issued yet. * @@ -178,7 +178,7 @@ * Fetch all (remaining) rows of a query result, returning them as a sequence * of sequences (e.g. a list of tuples). Note that the cursor's arraysize attribute * can affect the performance of this operation. - *

+ *

* An Error (or subclass) exception is raised if the previous call to executeXXX() * did not produce any result set or no call was issued yet. * @@ -190,16 +190,16 @@ * Fetch the next set of rows of a query result, returning a sequence of * sequences (e.g. a list of tuples). An empty sequence is returned when * no more rows are available. - *

+ *

* The number of rows to fetch per call is specified by the parameter. If * it is not given, the cursor's arraysize determines the number of rows * to be fetched. The method should try to fetch as many rows as indicated * by the size parameter. If this is not possible due to the specified number * of rows not being available, fewer rows may be returned. - *

+ *

* An Error (or subclass) exception is raised if the previous call to executeXXX() * did not produce any result set or no call was issued yet. - *

+ *

* Note there are performance considerations involved with the size parameter. * For optimal performance, it is usually best to use the arraysize attribute. * If the size parameter is used, then it is best for it to retain the same value @@ -219,15 +219,15 @@ /** * Scroll the cursor in the result set to a new position according * to mode. - *

+ *

* If mode is 'relative' (default), value is taken as offset to * the current position in the result set, if set to 'absolute', * value states an absolute target position. - *

+ *

* An IndexError should be raised in case a scroll operation would * leave the result set. In this case, the cursor position is left * undefined (ideal would be to not move the cursor at all). - *

+ *

* Note: This method should use native scrollable cursors, if * available, or revert to an emulation for forward-only * scrollable cursors. The method may raise NotSupportedErrors to @@ -248,9 +248,9 @@ /** * Builds a tuple containing the meta-information about each column. - *

+ *

* (name, type_code, display_size, internal_size, precision, scale, null_ok) - *

+ *

* precision and scale are only available for numeric types */ protected PyObject createDescription(ResultSetMetaData meta) throws SQLException { @@ -293,9 +293,9 @@ /** * Builds a tuple containing the meta-information about each column. - *

+ *

* (name, type_code, display_size, internal_size, precision, scale, null_ok) - *

+ *

* precision and scale are only available for numeric types */ protected PyObject createDescription(Procedure procedure) throws SQLException { @@ -617,7 +617,7 @@ * Fetch all (remaining) rows of a query result, returning them as a sequence * of sequences (e.g. a list of tuples). Note that the cursor's arraysize attribute * can affect the performance of this operation. - *

+ *

* An Error (or subclass) exception is raised if the previous call to executeXXX() * did not produce any result set or no call was issued yet. * @@ -633,16 +633,16 @@ * Fetch the next set of rows of a query result, returning a sequence of * sequences (e.g. a list of tuples). An empty sequence is returned when * no more rows are available. - *

+ *

* The number of rows to fetch per call is specified by the parameter. If * it is not given, the cursor's arraysize determines the number of rows * to be fetched. The method should try to fetch as many rows as indicated * by the size parameter. If this is not possible due to the specified number * of rows not being available, fewer rows may be returned. - *

+ *

* An Error (or subclass) exception is raised if the previous call to executeXXX() * did not produce any result set or no call was issued yet. - *

+ *

* Note there are performance considerations involved with the size parameter. * For optimal performance, it is usually best to use the arraysize attribute. * If the size parameter is used, then it is best for it to retain the same value diff --git a/src/com/ziclix/python/sql/JavaDateFactory.java b/src/com/ziclix/python/sql/JavaDateFactory.java --- a/src/com/ziclix/python/sql/JavaDateFactory.java +++ b/src/com/ziclix/python/sql/JavaDateFactory.java @@ -89,7 +89,7 @@ * This function constructs an object holding a date value from the * given ticks value (number of seconds since the epoch; see the * documentation of the standard Python time module for details). - *

+ *

* Note: The DB API 2.0 spec calls for time in seconds since the epoch * while the Java Date object returns time in milliseconds since the epoch. * This module adheres to the python API and will therefore use time in @@ -115,7 +115,7 @@ * This function constructs an object holding a time value from the * given ticks value (number of seconds since the epoch; see the * documentation of the standard Python time module for details). - *

+ *

* Note: The DB API 2.0 spec calls for time in seconds since the epoch * while the Java Date object returns time in milliseconds since the epoch. * This module adheres to the python API and will therefore use time in @@ -132,7 +132,7 @@ * This function constructs an object holding a time stamp value from * the given ticks value (number of seconds since the epoch; see the * documentation of the standard Python time module for details). - *

+ *

* Note: The DB API 2.0 spec calls for time in seconds since the epoch * while the Java Date object returns time in milliseconds since the epoch. * This module adheres to the python API and will therefore use time in diff --git a/src/com/ziclix/python/sql/Procedure.java b/src/com/ziclix/python/sql/Procedure.java --- a/src/com/ziclix/python/sql/Procedure.java +++ b/src/com/ziclix/python/sql/Procedure.java @@ -235,13 +235,13 @@ } /** - * Returns the call in the syntax: - *

+ * Returns the call in the syntax:

{@literal
      * {? = call (?, ?, ...)}
      * {call (?, ?, ...)}
-     * 

- * As of now, all parameters variables are created and no support for named variable - * calling is supported. + * }

+ * + * As of now, all parameters variables are created and no support for named variable calling is + * supported. * * @return String */ diff --git a/src/com/ziclix/python/sql/PyConnection.java b/src/com/ziclix/python/sql/PyConnection.java --- a/src/com/ziclix/python/sql/PyConnection.java +++ b/src/com/ziclix/python/sql/PyConnection.java @@ -273,7 +273,7 @@ * Commit any pending transaction to the database. Note that if the database supports * an auto-commit feature, this must be initially off. An interface method may be * provided to turn it back on. - *

+ *

* Database modules that do not support transactions should implement this method with * void functionality. */ @@ -295,7 +295,7 @@ /** * This method is optional since not all databases provide transaction support. - *

+ *

* In case a database does provide transactions this method causes the database to * roll back to the start of any pending transaction. Closing a connection without * committing the changes first will cause an implicit rollback to be performed. diff --git a/src/com/ziclix/python/sql/handler/SQLServerDataHandler.java b/src/com/ziclix/python/sql/handler/SQLServerDataHandler.java --- a/src/com/ziclix/python/sql/handler/SQLServerDataHandler.java +++ b/src/com/ziclix/python/sql/handler/SQLServerDataHandler.java @@ -47,7 +47,7 @@ /** * Given a ResultSet, column and type, return the appropriate * Jython object. - *

+ * *

Note: DO NOT iterate the ResultSet. * * @param set the current ResultSet set to the current row diff --git a/src/com/ziclix/python/sql/handler/UpdateCountDataHandler.java b/src/com/ziclix/python/sql/handler/UpdateCountDataHandler.java --- a/src/com/ziclix/python/sql/handler/UpdateCountDataHandler.java +++ b/src/com/ziclix/python/sql/handler/UpdateCountDataHandler.java @@ -18,7 +18,7 @@ /** * A data handler that keeps track of the update count for each execution of a * Statement. - *

+ * *

Note: MySql does not return the correct count for a * delete statement that has * no where clause. Therefore, to assure the correct update count is returned, diff --git a/src/com/ziclix/python/sql/pipe/Sink.java b/src/com/ziclix/python/sql/pipe/Sink.java --- a/src/com/ziclix/python/sql/pipe/Sink.java +++ b/src/com/ziclix/python/sql/pipe/Sink.java @@ -24,9 +24,9 @@ /** * Invoked for each row of data. In general, the first row of data will - * consist of header information in the format:
+ * consist of header information in the format:
*   [(colName, colType), ...] - * and in the format:
+ * and in the format:
*   (colData, colData, ...) * for all other data. */ diff --git a/src/com/ziclix/python/sql/pipe/Source.java b/src/com/ziclix/python/sql/pipe/Source.java --- a/src/com/ziclix/python/sql/pipe/Source.java +++ b/src/com/ziclix/python/sql/pipe/Source.java @@ -28,7 +28,7 @@ * Return the next row from the source. * The following format:
*   [(colName, colType), (colName, colType), ...] - * for headers and:
+ * for headers and:
*   [(col), (colName, colType), ...] * for all other data must be used. */ diff --git a/src/com/ziclix/python/sql/zxJDBC.java b/src/com/ziclix/python/sql/zxJDBC.java --- a/src/com/ziclix/python/sql/zxJDBC.java +++ b/src/com/ziclix/python/sql/zxJDBC.java @@ -34,7 +34,7 @@ /** * Creates database connections. - *

+ *

*

  * from com.ziclix.python.sql import zxJDBC
  * db = zxJDBC.connect("jdbc:mysql://localhost:3306/MySql", None, None, "org.gjt.mm.mysql.Driver")
diff --git a/src/org/python/core/AbstractArray.java b/src/org/python/core/AbstractArray.java
--- a/src/org/python/core/AbstractArray.java
+++ b/src/org/python/core/AbstractArray.java
@@ -69,21 +69,21 @@
     protected int modCountIncr;
 
     /**
-     * Since AbstractArray can support a clone method, this facilitates
-     * sublcasses that want to implement clone (poor man's cloning).
-     * Sublclasses can then do this:
-     * 
+     * Since AbstractArray can support a clone method, this facilitates subclasses that want to
+     * implement clone (poor man's cloning). Subclasses can then do this:
+     *
+     * 
{@literal
      * public MyManagedArray(MyManagedArray toCopy) {
-     * super(this);
-     * this.baseArray = ()toCopy.copyArray();
-     * this.someProp = toCopy.someProp;
-     * 
+     *     super(this);
+     *     this.baseArray = () toCopy.copyArray();
+     *     this.someProp = toCopy.someProp;
+     *     
      * }
-     * 

+ * * public Object clone() { - * return new MyManagedArray(this); + * return new MyManagedArray(this); * } - *

+ * }
* * @param toCopy */ @@ -161,7 +161,7 @@ *

Note: This method does not set modCountIncr to * 1 even though java.util.ArrayList * would. - *

+ * *

AbstractList subclasses should update their * modCount after calling this method. */ @@ -169,7 +169,7 @@ this.modCountIncr = 0; if (this.size != 0) { this.modCountIncr = 1; - clearRange(0, this.size); + clearRange(0, this.size); setSize(0); } @@ -400,43 +400,43 @@ int arrayLen = Array.getLength(array); replaceSubArray(atIndex, Math.min(this.size, atIndex + arrayLen), array, 0, arrayLen); } - + /** * Replace a range of this array with another subarray. - * @param thisStart the start index (inclusive) of the subarray in this + * @param thisStart the start index (inclusive) of the subarray in this * array to be replaced - * @param thisStop the stop index (exclusive) of the subarray in this + * @param thisStop the stop index (exclusive) of the subarray in this * array to be replaced * @param srcArray the source array from which to copy * @param srcStart the start index (inclusive) of the replacement subarray * @param srcStop the stop index (exclusive) of the replacement subarray */ - public void replaceSubArray(int thisStart, int thisStop, Object srcArray, + public void replaceSubArray(int thisStart, int thisStop, Object srcArray, int srcStart, int srcStop) { - + this.modCountIncr = 0; if (!srcArray.getClass().isArray()) { throw new IllegalArgumentException("'array' must be an array type"); } - + int replacedLen = thisStop - thisStart; if (thisStart < 0 || replacedLen < 0 || thisStop > this.size) { String message = null; if (thisStart < 0) { message = "thisStart < 0 (thisStart = " + thisStart + ")"; } else if (replacedLen < 0) { - message = "thisStart > thistStop (thisStart = " + thisStart + + message = "thisStart > thistStop (thisStart = " + thisStart + ", thisStop = " + thisStop + ")"; } else if (thisStop > this.size) { - message = "thisStop > size (thisStop = " + thisStop + + message = "thisStop > size (thisStop = " + thisStop + ", size = " + this.size + ")"; } else { throw new InternalError("Incorrect validation logic"); } - + throw new ArrayIndexOutOfBoundsException(message); } - + int srcLen = Array.getLength(srcArray); int replacementLen = srcStop - srcStart; if (srcStart < 0 || replacementLen < 0 || srcStop > srcLen) { @@ -444,29 +444,29 @@ if (srcStart < 0) { message = "srcStart < 0 (srcStart = " + srcStart +")"; } else if (replacementLen < 0) { - message = "srcStart > srcStop (srcStart = " + srcStart + + message = "srcStart > srcStop (srcStart = " + srcStart + ", srcStop = " + srcStop + ")"; } else if (srcStop > srcLen) { - message = "srcStop > srcArray length (srcStop = " + srcStop + + message = "srcStop > srcArray length (srcStop = " + srcStop + ", srcArray length = " +srcLen + ")"; } else { throw new InternalError("Incorrect validation logic"); } - + throw new IllegalArgumentException("start, stop and array must follow:\n\t" + "0 <= start <= stop <= array length\nBut found\n\t" + message); } - + int lengthChange = replacementLen - replacedLen; - + // Adjust array size if needed. if (lengthChange < 0) { remove(thisStop + lengthChange, thisStop); } else if (lengthChange > 0) { makeInsertSpace(thisStop, lengthChange); } - + try { this.modCountIncr = 1; System.arraycopy(srcArray, srcStart, getArray(), thisStart, replacementLen); @@ -475,7 +475,7 @@ getArray().getClass().getName() + "\tsee java.lang.Class.getName()."); } } - + /** * Set the backing array. This method is used by the type-agnostic base * class code to set the array used for type-specific storage by the @@ -513,7 +513,7 @@ if (count > this.capacity) { ensureCapacity(count); } else if (count < this.size) { - clearRange(count, this.size); + clearRange(count, this.size); } this.size = count; } @@ -532,6 +532,7 @@ * * @see java.lang.Object#toString() */ + @Override public String toString() { StringBuilder buf = new StringBuilder(); buf.append("["); @@ -543,7 +544,9 @@ for (int i = 0; i < n; i++) { buf.append(Array.get(base, i)).append(", "); } - if (n >= 0) buf.append(Array.get(base, n)); + if (n >= 0) { + buf.append(Array.get(base, n)); + } } else { Object[] objects = (Object[]) base; for (int i = 0; i < n; i++) { @@ -585,9 +588,9 @@ public int getModCountIncr() { return this.modCountIncr; } - + /** * @return an array of the given size for the type used by this abstract array. - */ + */ protected abstract Object createArray(int size); } diff --git a/src/org/python/core/BaseBytes.java b/src/org/python/core/BaseBytes.java --- a/src/org/python/core/BaseBytes.java +++ b/src/org/python/core/BaseBytes.java @@ -9,12 +9,11 @@ import java.util.ListIterator; /** - * Base class for Jython bytearray (and bytes in due course) that provides - * most of the Java API, including Java {@link List} behaviour. Attempts to modify the contents - * through this API will throw a TypeError if the actual type of the object is not - * mutable. It is possible for a Java client to treat this class as a - * List<PyInteger>, obtaining equivalent functionality to the Python interface in a - * Java paradigm. + * Base class for Jython {@code bytearray} (and {@code bytes} in due course) that provides most of + * the Java API, including Java {@link List} behaviour. Attempts to modify the contents through this + * API will throw a {@code TypeError} if the actual type of the object is not mutable. It is + * possible for a Java client to treat this class as a {@code List}, obtaining equivalent + * functionality to the Python interface in a Java paradigm. *

* Subclasses must define (from {@link PySequence}): *

    @@ -32,27 +31,26 @@ *

    * Many of the methods implemented here are inherited or thinly wrapped by {@link PyByteArray}, * which offers them as Java API, or exposes them as Python methods. These prototype Python methods - * mostly accept a {@link PyObject} as argument, where you might have expected a byte[] - * or BaseBytes, in order to accommodate the full range of types accepted by the Python - * equivalent: usually, any PyObject that implements {@link BufferProtocol}, providing - * a one-dimensional array of bytes, is an acceptable argument. In the documentation, the reader - * will often see the terms "byte array" or "object viewable as bytes" instead of - * BaseBytes when this broader scope is intended. + * mostly accept a {@link PyObject} as argument, where you might have expected a {@code byte[]} or + * {@code BaseBytes}, in order to accommodate the full range of types accepted by the Python + * equivalent: usually, any {@code PyObject} that implements {@link BufferProtocol}, providing a + * one-dimensional array of bytes, is an acceptable argument. In the documentation, the reader will + * often see the terms "byte array" or "object viewable as bytes" instead of {@code BaseBytes} when + * this broader scope is intended. *

    - * Where the methods return a BaseBytes, this is will normally be an instance of the - * class of the object on which the method was actually called. For example {@link #capitalize()}, - * defined in BaseBytes to return a BaseBytes, actually returns a {@link PyByteArray} - * when applied to a bytearray. Or it may be that the method returns a - * PyList of instances of the target type, for example {@link #rpartition(PyObject)}. - * This is achieved by the sub-class defining {@link #getslice(int, int, int)} and - * {@link #getResult(Builder)} to return instances of its own type. See the documentation of the - * particular methods for more information. + * Where the methods return a {@code BaseBytes}, this is will normally be an instance of the class + * of the object on which the method was actually called. For example {@link #capitalize()}, defined + * in {@code BaseBytes} to return a BaseBytes, actually returns a {@link PyByteArray} when applied + * to a {@code bytearray}. Or it may be that the method returns a {@code PyList} of instances of the + * target type, for example {@link #rpartition(PyObject)}. This is achieved by the sub-class + * defining {@link #getslice(int, int, int)} and {@link #getResult(Builder)} to return instances of + * its own type. See the documentation of the particular methods for more information. */ @Untraversable public abstract class BaseBytes extends PySequence implements List { /** - * Constructs a zero-length BaseBytes of explicitly-specified sub-type. + * Constructs a zero-length {@code BaseBytes} of explicitly-specified sub-type. * * @param type explicit Jython type */ @@ -96,7 +94,7 @@ * * @param type explicit Jython type * @param value source of characters - * @throws PyException if any value[i] > 255 + * @throws PyException {@code ValueError} if any {@code value[i] > 255} */ protected BaseBytes(PyType type, String value) throws PyException { super(type, null); @@ -117,8 +115,8 @@ * @param storage byte array allocated by client * @param size number of bytes actually used * @param offset index of first byte used - * @throws IllegalArgumentException if the range [offset:offset+size] is not within the array - * bounds of storage or size<0. + * @throws IllegalArgumentException if the range {@code [offset:offset+size]} is not within the + * array bounds of storage or {@code size<0}. */ protected void setStorage(byte[] storage, int size, int offset) throws IllegalArgumentException { @@ -137,8 +135,8 @@ * * @param storage byte array allocated by client * @param size number of bytes actually used - * @throws IllegalArgumentException if the range [0:size] is not within the array bounds of - * storage. + * @throws IllegalArgumentException if the range {@code [0:size]} is not within the array bounds + * of storage. */ protected void setStorage(byte[] storage, int size) throws IllegalArgumentException { if (size < 0 || size > storage.length) { @@ -173,8 +171,8 @@ */ /** - * Helper for __new__ and __init__ and the Java API constructor from - * PyObject in subclasses. + * Helper for {@code __new__} and {@code __init__} and the Java API constructor from PyObject in + * subclasses. * * @see org.python.core.PyByteArray#bytearray___init__(PyObject[], String[]) * @see org.python.core.PyByteArray#PyByteArray(PyObject) @@ -212,8 +210,8 @@ } /** - * Helper for __new__ and __init__ and the Java API constructor from a - * text string with the specified encoding in subclasses. + * Helper for {@code __new__} and {@code __init__} and the Java API constructor from a text + * string with the specified encoding in subclasses. * * @see PyByteArray#bytearray___init__(PyObject[], String[]) * @see PyByteArray#PyByteArray(PyString, String, String) @@ -228,8 +226,8 @@ } /** - * Helper for __new__ and __init__ and the Java API constructor from a - * text string with the specified encoding in subclasses. + * Helper for {@code __new__} and {@code __init__} and the Java API constructor from a text + * string with the specified encoding in subclasses. * * @see PyByteArray#bytearray___init__(PyObject[], String[]) * @see PyByteArray#PyByteArray(PyString, String, String) @@ -245,18 +243,18 @@ } /** - * Helper for {@link #setslice(int, int, int, PyObject)}, for __new__ and - * __init__ and the Java API constructor from a text string with the specified - * encoding in subclasses. This method thinly wraps a call to the codecs module and deals with - * checking for PyUnicode (where the encoding argument is mandatory). + * Helper for {@link #setslice(int, int, int, PyObject)}, for {@code __new__} and + * {@code __init__} and the Java API constructor from a text string with the specified encoding + * in subclasses. This method thinly wraps a call to the codecs module and deals with checking + * for PyUnicode (where the encoding argument is mandatory). * * @see PyByteArray#PyByteArray(PyString, String, String) * @param arg primary argument from which value is taken * @param encoding name of optional encoding * @param errors name of optional errors policy * @return encoded string - * @throws PyException (TypeError) if the PyString is actually a {@link PyUnicode} - * and encoding is null + * @throws PyException {@code TypeError} if the {@code PyString} is actually a {@link PyUnicode} + * and encoding is {@code null} */ protected static String encode(PyString arg, String encoding, String errors) throws PyException { @@ -285,7 +283,7 @@ * * @param start index in this byte array at which the first character code lands * @param value source of characters - * @throws PyException (ValueError) if any value[i] > 255 + * @throws PyException {@code ValueError} if any value[i] > 255 */ protected void setBytes(int start, String value) throws PyException { int n = value.length(); @@ -301,7 +299,7 @@ * * @param start index in this byte array at which the first character code lands * @param value source of characters - * @throws PyException (ValueError) if any value[i] > 255 + * @throws PyException {@code ValueError} if any value[i] > 255 */ protected void setBytes(int start, int step, String value) throws PyException { int n = value.length(); @@ -313,8 +311,8 @@ } /** - * Helper for __new__ and __init__ and the Java API constructor from - * int in subclasses. Construct zero-filled byte array of specified size. + * Helper for {@code __new__} and {@code __init__} and the Java API constructor from int in + * subclasses. Construct zero-filled byte array of specified size. * * @param n size of zero-filled array */ @@ -326,8 +324,8 @@ } /** - * Helper for __new__ and __init__ and the Java API constructor from - * objects supporting the Jython implementation of PEP 3118 (Buffer API) in subclasses. + * Helper for {@code __new__} and {@code __init__} and the Java API constructor from objects + * supporting the Jython implementation of PEP 3118 (Buffer API) in subclasses. * * @param value an object bearing the Buffer API and consistent with the slice assignment */ @@ -341,8 +339,8 @@ } /** - * Helper for __new__ and __init__ from objects that might - * support the Jython Buffer API. + * Helper for {@code __new__} and {@code __init__} from objects that might support the + * Jython Buffer API. * * @param value an object possibly bearing the Buffer API * @return {@code true} iff {@code value} allows the {@code getBuffer} @@ -358,10 +356,10 @@ } /** - * Helper for __new__ and __init__ and the Java API constructor from - * bytearray or bytes in subclasses. + * Helper for {@code __new__} and {@code __init__} and the Java API constructor from + * {@code bytearray} or {@code bytes} in subclasses. * - * @param source bytearray (or bytes) to copy + * @param source {@code bytearray} (or {@code bytes}) to copy */ protected void init(BaseBytes source) { newStorage(source.size); @@ -369,8 +367,8 @@ } /** - * Helper for __new__ and __init__ and the Java API constructor from - * an arbitrary iterable Python type in subclasses. This will include generators and lists. + * Helper for {@code __new__} and {@code __init__} and the Java API constructor from an + * arbitrary iterable Python type in subclasses. This will include generators and lists. * * @param iter iterable source of values to enter in the array */ @@ -441,8 +439,9 @@ * Load bytes into the container from the given iterable * * @param iter iterable source of values to enter into the container - * @throws PyException (TypeError) if any value not acceptable type - * @throws PyException (ValueError) if any value<0 or value>255 or string length!=1 + * @throws PyException {@code TypeError} if any value not acceptable type + * @throws PyException {@code ValueError} if any value<0 or value>255 or string + * length!=1 */ void loadFrom(Iterable iter) throws PyException { @@ -547,7 +546,7 @@ * Check that an index is within the range of the array, that is 0<=index<size. * * @param index to check - * @throws PyException (IndexError) if the index is outside the array bounds + * @throws PyException {@code IndexError} if the index is outside the array bounds */ protected final void indexCheck(int index) throws PyException { if (index < 0 || index >= size) { @@ -581,7 +580,7 @@ * 0..255.) * * @param value to convert. - * @throws PyException (ValueError) if value<0 or value>255 + * @throws PyException {@code ValueError} if value<0 or value>255 */ protected static final byte byteCheck(int value) throws PyException { if (value < 0 || value > 255) { @@ -596,7 +595,7 @@ * Python bytes run 0..255.) * * @param value to convert. - * @throws PyException (ValueError) if value<0 or value>255 + * @throws PyException {@code ValueError} if value<0 or value>255 */ protected static final byte byteCheck(PyInteger value) throws PyException { return byteCheck(value.asInt()); @@ -614,8 +613,8 @@ *

* * @param value to convert. - * @throws PyException (TypeError) if not acceptable type - * @throws PyException (ValueError) if value<0 or value>255 or string length!=1 + * @throws PyException {@code TypeError} if not acceptable type + * @throws PyException {@code ValueError} if value<0 or value>255 or string length!=1 */ protected static final byte byteCheck(PyObject value) throws PyException { if (value.isIndex()) { @@ -634,12 +633,12 @@ } /** - * Return a buffer exported by the argument, or return null if it does not bear the + * Return a buffer exported by the argument, or return {@code null} if it does not bear the * buffer API. The caller is responsible for calling {@link PyBuffer#release()} on the buffer, - * if the return value is not null. + * if the return value is not {@code null}. * * @param b object to wrap - * @return byte-oriented view or null + * @return byte-oriented view or {@code null} */ protected static PyBuffer getView(PyObject b) { @@ -665,7 +664,7 @@ /** * Return a buffer exported by the argument or raise an exception if it does not bear the buffer * API. The caller is responsible for calling {@link PyBuffer#release()} on the buffer. The - * return value is never null. + * return value is never {@code null}. * * @param b object to wrap * @return byte-oriented view @@ -711,9 +710,9 @@ * * @param index to insert at * @param element to insert (by value) - * @throws PyException (IndexError) if the index is outside the array bounds - * @throws PyException (ValueError) if element<0 or element>255 - * @throws PyException (TypeError) if the subclass is immutable + * @throws PyException {@code IndexError} if the index is outside the array bounds + * @throws PyException {@code ValueError} if element<0 or element>255 + * @throws PyException {@code TypeError} if the subclass is immutable */ public void pyinsert(int index, PyObject element) { // This won't succeed: it just produces the right error. @@ -723,8 +722,8 @@ /** * Specialisation of {@link #getslice(int, int, int)} to contiguous slices (of step size 1) for - * brevity and efficiency. The default implementation is getslice(start, stop, 1) - * but it is worth overriding. + * brevity and efficiency. The default implementation is {@code getslice(start, stop, 1)} but it + * is worth overriding. * * @param start the position of the first element. * @param stop one more than the position of the last element. @@ -735,8 +734,8 @@ } /** - * Class defining the behaviour of bytearray with respect to slice assignment, - * etc., which differs from the default (list) behaviour in small ways. + * Class defining the behaviour of {@code bytearray} with respect to slice assignment, etc., + * which differs from the default (list) behaviour in small ways. */ private class IndexDelegate extends PySequence.DefaultIndexDelegate { @@ -774,11 +773,11 @@ /** * Comparison function between a byte array and a buffer of bytes exported by some other object, - * such as a String, presented as a PyBuffer, returning 1, 0 or -1 as a>b, a==b, or + * such as a String, presented as a {@code PyBuffer}, returning 1, 0 or -1 as a>b, a==b, or * a<b respectively. The comparison is by value, using Python unsigned byte conventions, * left-to-right (low to high index). Zero bytes are significant, even at the end of the array: - * [65,66,67]<"ABC\u0000", for example and [] is less than every - * non-empty b, while []=="". + * {@code [65,66,67]<"ABC\u0000"}, for example and {@code []} is less than every non-empty b, + * while {@code []==""}. * * @param a left-hand array in the comparison * @param b right-hand wrapped object in the comparison @@ -852,8 +851,8 @@ /** * Fail-fast comparison function between byte array types and any other object, for when the - * test is only for equality. The "rich comparison" operators __eq__ and - * __ne__ are based on this. + * test is only for equality. The "rich comparison" operators {@code __eq__} and {@code __ne__} + * are based on this. * * @param b * @return 0 if this==b, or +1 or -1 if this!=b, or -2 if the comparison is not implemented @@ -888,10 +887,10 @@ /** * Implementation of __eq__ (equality) operator, capable of comparison with another byte array. - * Comparison with an invalid type returns null. + * Comparison with an invalid type returns {@code null}. * * @param other Python object to compare with - * @return Python boolean result or null if not implemented for the other type. + * @return Python boolean result or {@code null} if not implemented for the other type. */ final PyObject basebytes___eq__(PyObject other) { int cmp = basebytes_cmpeq(other); @@ -906,10 +905,10 @@ /** * Implementation of __ne__ (not equals) operator, capable of comparison with another byte - * array. Comparison with an invalid type returns null. + * array. Comparison with an invalid type returns {@code null}. * * @param other Python object to compare with - * @return Python boolean result or null if not implemented for the other type. + * @return Python boolean result or {@code null} if not implemented for the other type. */ final PyObject basebytes___ne__(PyObject other) { int cmp = basebytes_cmpeq(other); @@ -924,10 +923,10 @@ /** * Implementation of __lt__ (less than) operator, capable of comparison with another byte array. - * Comparison with an invalid type returns null. + * Comparison with an invalid type returns {@code null}. * * @param other Python object to compare with - * @return Python boolean result or null if not implemented for the other type. + * @return Python boolean result or {@code null} if not implemented for the other type. */ final PyObject basebytes___lt__(PyObject other) { int cmp = basebytes_cmp(other); @@ -942,10 +941,10 @@ /** * Implementation of __le__ (less than or equal to) operator, capable of comparison with another - * byte array. Comparison with an invalid type returns null. + * byte array. Comparison with an invalid type returns {@code null}. * * @param other Python object to compare with - * @return Python boolean result or null if not implemented for the other type. + * @return Python boolean result or {@code null} if not implemented for the other type. */ final PyObject basebytes___le__(PyObject other) { int cmp = basebytes_cmp(other); @@ -960,10 +959,10 @@ /** * Implementation of __ge__ (greater than or equal to) operator, capable of comparison with - * another byte array. Comparison with an invalid type returns null. + * another byte array. Comparison with an invalid type returns {@code null}. * * @param other Python object to compare with - * @return Python boolean result or null if not implemented for the other type. + * @return Python boolean result or {@code null} if not implemented for the other type. */ final PyObject basebytes___ge__(PyObject other) { int cmp = basebytes_cmp(other); @@ -978,10 +977,10 @@ /** * Implementation of __gt__ (greater than) operator, capable of comparison with another byte - * array. Comparison with an invalid type returns null. + * array. Comparison with an invalid type returns {@code null}. * * @param other Python object to compare with - * @return Python boolean result or null if not implemented for the other type. + * @return Python boolean result or {@code null} if not implemented for the other type. */ final PyObject basebytes___gt__(PyObject other) { int cmp = basebytes_cmp(other); @@ -1019,17 +1018,17 @@ /** * Almost ready-to-expose implementation serving both Python - * startswith( prefix [, start [, end ]] ) and - * endswith( suffix [, start [, end ]] ). An extra boolean argument specifies which - * to implement on a given call, that is, whether the target is a suffix or prefix. The target - * may also be a tuple of targets. + * {@code startswith( prefix [, start [, end ]] )} and + * {@code endswith( suffix [, start [, end ]] )}. An extra boolean argument specifies which to + * implement on a given call, that is, whether the target is a suffix or prefix. The target may + * also be a tuple of targets. * * @param target prefix or suffix sequence to find (of a type viewable as a byte sequence) or a * tuple of those. * @param ostart of slice to search. * @param oend of slice to search. * @param endswith true if we are doing endswith, false if startswith. - * @return true if and only if this byte array ends with (one of) target. + * @return true if and only if this byte array ends with (one of) {@code target}. */ protected final synchronized boolean basebytes_starts_or_endswith(PyObject target, PyObject ostart, PyObject oend, boolean endswith) { @@ -1054,17 +1053,16 @@ } /** - * Test whether the slice [pos:pos+n] of this byte array matches the given target - * object (accessed as a {@link PyBuffer}) at one end or the orher. That is, if - * endswith==false test whether the bytes from index pos match all the - * bytes of the target; if endswith==false test whether the bytes up to index - * pos+n-1 match all the bytes of the target. By implication, the test returns - * false if the target is bigger than n. The caller guarantees that the slice - * [pos:pos+n] is within the byte array. + * Test whether the slice {@code [pos:pos+n]} of this byte array matches the given target object + * (accessed as a {@link PyBuffer}) at one end or the other. That is, if {@code endswith==false} + * test whether the bytes from index {@code pos} match all the bytes of the target; if + * {@code endswith==false} test whether the bytes up to index {@code pos+n-1} match all the + * bytes of the target. By implication, the test returns false if the target is bigger than n. + * The caller guarantees that the slice {@code [pos:pos+n]} is within the byte array. * * @param target pattern to match * @param pos at which to start the comparison - * @return true if and only if the slice [offset:] matches the given target + * @return true if and only if the slice {@code this[pos:pos+n]} matches the given target */ private boolean match(PyObject target, int pos, int n, boolean endswith) { @@ -1130,7 +1128,7 @@ /** * Decode the byte array to a Unicode string according to the default encoding. The returned - * PyObject should be a PyUnicode, since the default codec is well-behaved. + * PyObject should be a {@code PyUnicode}, since the default codec is well-behaved. * * @return object containing the decoded characters */ @@ -1140,10 +1138,10 @@ /** * Decode the byte array to a Unicode string according to the specified encoding and default - * error policy. The returned PyObject will usually be a PyUnicode, but in practice - * it is whatever the decode method of the codec decides. + * error policy. The returned PyObject will usually be a {@code PyUnicode}, but in practice it + * is whatever the {@code decode} method of the codec decides. * - * @param encoding the name of the codec (uses default codec if null) + * @param encoding the name of the codec (uses default codec if {@code null}) * @return object containing the decoded characters */ public PyObject decode(String encoding) { @@ -1152,18 +1150,18 @@ /** * Decode the byte array to a Unicode string according to the specified encoding and error - * policy. The returned PyObject will usually be a PyUnicode, but in practice it is - * whatever the decode method of the codec decides. + * policy. The returned PyObject will usually be a {@code PyUnicode}, but in practice it is + * whatever the {@code decode} method of the codec decides. * - * @param encoding the name of the codec (uses default codec if null) - * @param errors the name of the error policy (uses 'strict' if null) + * @param encoding the name of the codec (uses default codec if {@code null}) + * @param errors the name of the error policy (uses 'strict' if {@code null}) * @return object containing the decoded characters */ public PyObject decode(String encoding, String errors) { /* - * Provide a Python str input to the decode method of a codec, which in v2.7 - * expects a PyString. (In Python 3k the codecs decode from the bytes type, so - * we can pass this directly.) + * Provide a Python {@code str} input to the decode method of a codec, which in v2.7 expects + * a PyString. (In Python 3k the codecs decode from the {@code bytes} type, so we can pass + * this directly.) */ PyString this_ = new PyString(this.asString()); return codecs.decode(this_, encoding, errors); @@ -1184,8 +1182,8 @@ } /** - * Convenience method to create a TypeError PyException with the message "can't - * concat {type} to {toType}" + * Convenience method to create a {@code TypeError} PyException with the message "can't concat + * {type} to {toType}" * * @param type * @param toType @@ -1294,13 +1292,12 @@ /** * Mask defining how many of the bits of each byte are used when looking up the skip, used - * like: skip = skipTable[MASK & currentByte]. + * like: {@code skip = skipTable[MASK & currentByte]}. */ private static final byte MASK = 0x1f; /** - * Table for looking up the skip, used like: - * skip = skipTable[MASK & currentByte]. + * Table for looking up the skip, used like: {@code skip = skipTable[MASK & currentByte]}. */ protected int[] skipTable = null; @@ -1326,8 +1323,8 @@ } /** - * Set the text to be searched in successive calls to nextIndex(), where the - * text is the entire array text[]. + * Set the text to be searched in successive calls to {@code nextIndex()}, where the text is + * the entire array {@code text[]}. * * @param text to search */ @@ -1336,8 +1333,8 @@ } /** - * Set the text to be searched in successive calls to nextIndex(), where the - * text is the entire byte array text. + * Set the text to be searched in successive calls to {@code nextIndex()}, where the text is + * the entire byte array {@code text}. * * @param text to search */ @@ -1346,9 +1343,8 @@ } /** - * Set the text to be searched in successive calls to nextIndex(), where the - * text is effectively only the bytes text[start] to - * text[start+size-1] inclusive. + * Set the text to be searched in successive calls to {@code nextIndex()}, where the text is + * effectively only the bytes {@code text[start]} to {@code text[start+size-1]} inclusive. * * @param text to search * @param start first position to consider @@ -1378,8 +1374,8 @@ /** * Return the index in the text array where the preceding pattern match ends (one beyond the * last character matched), which may also be one beyond the effective end ofthe text. - * Between a call to setText() and the first call to nextIndex() return the - * start position. + * Between a call to setText() and the first call to {@code nextIndex()} return the start + * position. *

* The following idiom may be used: * @@ -1398,8 +1394,8 @@ /** * Find the next index in the text array where the pattern starts. Successive calls to - * nextIndex() return the successive (non-overlapping) occurrences of the - * pattern in the text. + * {@code nextIndex()} return the successive (non-overlapping) occurrences of the pattern in + * the text. * * @return matching index or -1 if no (further) occurrences found */ @@ -1480,8 +1476,7 @@ /** * Count the non-overlapping occurrences of the pattern in the text, where the text is - * effectively only the bytes text[start] to text[start+size-1] - * inclusive. + * effectively only the bytes {@code text[start]} to {@code text[start+size-1]} inclusive. * * @param text to search * @param start first position to consider @@ -1494,7 +1489,7 @@ /** * Count the non-overlapping occurrences of the pattern in the text, where the text is - * effectively only the bytes text[start] to text[start+size-1]. + * effectively only the bytes {@code text[start]} to {@code text[start+size-1]}. * * @param text to search * @param start first position to consider @@ -1531,11 +1526,11 @@ /** * Mask defining how many of the bits of each byte are used when looking up the skip, used - * like: skip = skipTable[MASK & currentByte]. + * like: {@code skip = skipTable[MASK & currentByte]}. *

- * Note that the way this is written at the moment, if MASK is different from - * super.MASK calculateSkipTable() and nextIndex() - * must both be overridden consistently to use the local definition. + * Note that the way this is written at the moment, if {@code MASK} is different from + * {@code super.MASK} {@code calculateSkipTable()} and {@code nextIndex()} must both be + * overridden consistently to use the local definition. */ private static final byte MASK = 0x1f; @@ -1573,7 +1568,7 @@ /** * Find the next index in the text array where the pattern starts, but working backwards. - * Successive calls to nextIndex() return the successive (non-overlapping) + * Successive calls to {@code nextIndex()} return the successive (non-overlapping) * occurrences of the pattern in the text. * * @return matching index or -1 if no (further) occurrences found @@ -1686,7 +1681,7 @@ * * @param b integer value of the byte * @return true iff b is in the set - * @throws ArrayIndexOutOfBoundsException if b>255 or b<0 + * @throws ArrayIndexOutOfBoundsException if b%gt;255 or b<0 */ public boolean contains(int b) { int word = b >> 6; @@ -1713,8 +1708,8 @@ } /** - * Return the index [0..size-1] of the leftmost byte not matching any in byteSet, - * or size if they are all strippable. + * Return the index [0..size-1] of the leftmost byte not matching any in {@code byteSet}, or + * {@code size} if they are all strippable. * * @param byteSet set of byte values to skip over * @return index of first unstrippable byte @@ -1734,8 +1729,8 @@ } /** - * Return the index [0..size-1] of the leftmost non-whitespace byte, or size if - * they are all whitespace. + * Return the index [0..size-1] of the leftmost non-whitespace byte, or {@code size} if they are + * all whitespace. * * @return index of first non-whitespace byte */ @@ -1753,8 +1748,8 @@ /** * Return the index [0..size-1] such that all bytes from here to the right match one in - * byteSet, that is, the index of the matching tail, or size if there - * is no matching tail byte. + * {@code byteSet}, that is, the index of the matching tail, or {@code size} if there is no + * matching tail byte. * * @param byteSet set of byte values to strip * @return index of strippable tail @@ -1774,7 +1769,7 @@ /** * Return the index [0..size-1] such that all bytes from here to the right are whitespace, that - * is, the index of the whitespace tail, or size if there is no whitespace tail. + * is, the index of the whitespace tail, or {@code size} if there is no whitespace tail. * * @return index of strippable tail */ @@ -1790,10 +1785,10 @@ } /** - * Ready-to-expose implementation of Python count( sub [, start [, end ]] ). Return - * the number of non-overlapping occurrences of sub in the range [start, end]. - * Optional arguments start and end (which may be null or - * Py.None ) are interpreted as in slice notation. + * Ready-to-expose implementation of Python {@code count( sub [, start [, end ]] )}. Return the + * number of non-overlapping occurrences of {@code sub} in the range [start, end]. Optional + * arguments {@code start} and {@code end} (which may be {@code null} or {@code Py.None}) are + * interpreted as in slice notation. * * @param sub bytes to find * @param ostart of slice to search @@ -1813,12 +1808,11 @@ } /** - * Ready-to-expose implementation of Python find( sub [, start [, end ]] ). Return - * the lowest index in the byte array where byte sequence sub is found, such that - * sub is contained in the slice [start:end]. Arguments - * start and end (which may be null or - * Py.None ) are interpreted as in slice notation. Return -1 if sub is - * not found. + * Ready-to-expose implementation of Python {@code find( sub [, start [, end ]] )}. Return the + * lowest index in the byte array where byte sequence {@code sub} is found, such that + * {@code sub} is contained in the slice {@code [start:end]}. Arguments {@code start} and + * {@code end} (which may be {@code null} or {@code Py.None} ) are interpreted as in slice + * notation. Return -1 if {@code sub} is not found. * * @param sub bytes to find * @param ostart of slice to search @@ -1833,10 +1827,10 @@ } /** - * Almost ready-to-expose implementation of Python class method fromhex(string). - * This assigns a value to the passed byte array object from a string of two-digit hexadecimal + * Almost ready-to-expose implementation of Python class method {@code fromhex(string)}. This + * assigns a value to the passed byte array object from a string of two-digit hexadecimal * numbers. Spaces (but not whitespace in general) are acceptable around the numbers, not - * within. Non-hexadecimal characters or un-paired hex digits raise a ValueError. + * within. Non-hexadecimal characters or un-paired hex digits raise a {@code ValueError}. * Example: * *

@@ -1845,7 +1839,8 @@
      *
      * @param result to receive the decoded values
      * @param hex specification of the bytes
-     * @throws PyException (ValueError) if non-hex characters, or isolated ones, are encountered
+     * @throws PyException {@code ValueError} if non-hex characters, or isolated ones, are
+     *             encountered
      */
     static void basebytes_fromhex(BaseBytes result, String hex) throws PyException {
 
@@ -1907,7 +1902,7 @@
     }
 
     /**
-     * Almost ready-to-expose implementation of Python join(iterable).
+     * Almost ready-to-expose implementation of Python {@code join(iterable)}.
      *
      * @param iter iterable of objects capable of being regarded as byte arrays
      * @return the byte array that is their join
@@ -1973,16 +1968,16 @@
     }
 
     /**
-     * Implementation of Python partition(sep), returning a 3-tuple of byte arrays (of
-     * the same type as this).
+     * Implementation of Python {@code partition(sep)}, returning a 3-tuple of byte arrays (of the
+     * same type as {@code this}).
      *
-     * Split the string at the first occurrence of sep, and return a 3-tuple containing
-     * the part before the separator, the separator itself, and the part after the separator. If the
+     * Split the string at the first occurrence of {@code sep}, and return a 3-tuple containing the
+     * part before the separator, the separator itself, and the part after the separator. If the
      * separator is not found, return a 3-tuple containing the string itself, followed by two empty
      * byte arrays.
      * 

- * The elements of the PyTuple returned by this method are instances of the same - * actual type as this. + * The elements of the {@code PyTuple} returned by this method are instances of the same actual + * type as {@code this}. * * @param sep the separator on which to partition this byte array * @return a tuple of (head, separator, tail) @@ -1992,10 +1987,10 @@ } /** - * Ready-to-expose implementation of Python partition(sep). + * Ready-to-expose implementation of Python {@code partition(sep)}. *

- * The elements of the PyTuple returned by this method are instances of the same - * actual type as this. + * The elements of the {@code PyTuple} returned by this method are instances of the same actual + * type as {@code this}. * * @param sep the separator on which to partition this byte array * @return a tuple of (head, separator, tail) @@ -2022,11 +2017,11 @@ } /** - * Construct return value for implementation of Python partition(sep) or - * rpartition(sep), returns [0:p], [p:q], [q:] + * Construct return value for implementation of Python {@code partition(sep)} or + * {@code rpartition(sep)}, returns {@code [0:p], [p:q], [q:]} *

- * The elements of the PyTuple returned by this method are instances of the same - * actual type as this. + * The elements of the {@code PyTuple} returned by this method are instances of the same actual + * type as {@code this}. * * @param p start of separator * @param q start of tail @@ -2040,12 +2035,11 @@ } /** - * Ready-to-expose implementation of Python rfind( sub [, start [, end ]] ). Return - * the highest index in the byte array where byte sequence sub is found, such that - * sub is contained in the slice [start:end]. Arguments - * start and end (which may be null or - * Py.None) are interpreted as in slice notation. Return -1 if sub is - * not found. + * Ready-to-expose implementation of Python {@code rfind( sub [, start [, end ]] )}. Return the + * highest index in the byte array where byte sequence {@code sub} is found, such that + * {@code sub} is contained in the slice {@code [start:end]}. Arguments {@code start} and + * {@code end} (which may be {@code null} or {@code Py.None}) are interpreted as in slice + * notation. Return -1 if {@code sub} is not found. * * @param sub bytes to find * @param ostart of slice to search @@ -2060,10 +2054,10 @@ } /** - * Common code for Python find( sub [, start [, end ]] ) and - * rfind( sub [, start [, end ]] ). Return the lowest or highest index in the byte - * array where byte sequence used to construct finder is found. The particular type - * (plain Finder or ReverseFinder) determines the direction. + * Common code for Python {@code find( sub [, start [, end ]] )} and + * {@code rfind( sub [, start [, end ]] )}. Return the lowest or highest index in the byte array + * where byte sequence used to construct {@code finder} is found. The particular type (plain + * {@code Finder} or {@code ReverseFinder}) determines the direction. * * @param finder for the bytes to find, sometime forwards, sometime backwards * @param ostart of slice to search @@ -2084,11 +2078,10 @@ } /** - * An almost ready-to-expose implementation of Python - * replace( old, new [, count ] ), returning a PyByteArray with all - * occurrences of sequence oldB replaced by newB. If the optional - * argument count is given, only the first count occurrences are - * replaced. + * An almost ready-to-expose implementation of Python {@code replace( old, new [, count ] )}, + * returning a {@code PyByteArray} with all occurrences of sequence {@code oldB} replaced by + * {@code newB}. If the optional argument {@code count} is given, only the first {@code count} + * occurrences are replaced. * * @param oldB sequence to find * @param newB relacement sequence @@ -2403,16 +2396,16 @@ } /** - * Implementation of Python rpartition(sep), returning a 3-tuple of byte arrays (of - * the same type as this). + * Implementation of Python {@code rpartition(sep)}, returning a 3-tuple of byte arrays (of the + * same type as {@code this}). * - * Split the string at the rightmost occurrence of sep, and return a 3-tuple - * containing the part before the separator, the separator itself, and the part after the - * separator. If the separator is not found, return a 3-tuple containing two empty byte arrays, - * followed by the byte array itself. + * Split the string at the rightmost occurrence of {@code sep}, and return a 3-tuple containing + * the part before the separator, the separator itself, and the part after the separator. If the + * separator is not found, return a 3-tuple containing two empty byte arrays, followed by the + * byte array itself. *

- * The elements of the PyTuple returned by this method are instances of the same - * actual type as this. + * The elements of the {@code PyTuple} returned by this method are instances of the same actual + * type as {@code this}. * * @param sep the separator on which to partition this byte array * @return a tuple of (head, separator, tail) @@ -2422,10 +2415,10 @@ } /** - * Ready-to-expose implementation of Python rpartition(sep). + * Ready-to-expose implementation of Python {@code rpartition(sep)}. *

- * The elements of the PyTuple returned by this method are instances of the same - * actual type as this. + * The elements of the {@code PyTuple} returned by this method are instances of the same actual + * type as {@code this}. * * @param sep the separator on which to partition this byte array * @return a tuple of (head, separator, tail) @@ -2452,11 +2445,11 @@ } /** - * Implementation of Python rsplit(), that returns a list of the words in the byte + * Implementation of Python {@code rsplit()}, that returns a list of the words in the byte * array, using whitespace as the delimiter. See {@link #rsplit(PyObject, int)}. *

- * The elements of the PyList returned by this method are instances of the same - * actual type as this. + * The elements of the {@code PyList} returned by this method are instances of the same actual + * type as {@code this}. * * @return PyList of byte arrays that result from the split */ @@ -2465,14 +2458,14 @@ } /** - * Implementation of Python rsplit(sep), that returns a list of the words in the - * byte array, using sep as the delimiter. See {@link #rsplit(PyObject, int)} for - * the semantics of the separator. + * Implementation of Python {@code rsplit(sep)}, that returns a list of the words in the byte + * array, using {@code sep} as the delimiter. See {@link #rsplit(PyObject, int)} for the + * semantics of the separator. *

- * The elements of the PyList returned by this method are instances of the same - * actual type as this. + * The elements of the {@code PyList} returned by this method are instances of the same actual + * type as {@code this}. * - * @param sep bytes, or object viewable as bytes, defining the separator + * @param sep {@code bytes}, or object viewable as bytes, defining the separator * @return PyList of byte arrays that result from the split */ public PyList rsplit(PyObject sep) { @@ -2480,27 +2473,27 @@ } /** - * Implementation of Python rsplit(sep, maxsplit), that returns a list of the words - * in the byte array, using sep as the delimiter. If maxsplit is - * given, at most maxsplit splits are done (thus, the list will have at most - * maxsplit+1 elements). If maxsplit is not specified, then there is - * no limit on the number of splits (all possible splits are made). + * Implementation of Python {@code rsplit(sep, maxsplit)}, that returns a list of the words in + * the byte array, using {@code sep} as the delimiter. If {@code maxsplit} is given, at most + * {@code maxsplit} splits are done (thus, the list will have at most {@code maxsplit+1} + * elements). If {@code maxsplit} is not specified, then there is no limit on the number of + * splits (all possible splits are made). *

- * The semantics of sep and maxcount are identical to those of - * split(sep, maxsplit) , except that splits are generated from the right (and - * pushed onto the front of the result list). The result is only different from that of - * split if maxcount limits the number of splits. For example, + * The semantics of {@code sep} and maxcount are identical to those of + * {@code split(sep, maxsplit)} , except that splits are generated from the right (and pushed + * onto the front of the result list). The result is only different from that of {@code split} + * if {@code maxcount} limits the number of splits. For example, *

    - *
  • bytearray(b' 1 2 3 ').rsplit() returns - * [bytearray(b'1'), bytearray(b'2'), bytearray(b'3')], and
  • - *
  • bytearray(b' 1 2 3 ').rsplit(None, 1) returns - * [bytearray(b' 1 2'), bytearray(b'3')]
  • . + *
  • {@code bytearray(b' 1 2 3 ').rsplit()} returns + * {@code [bytearray(b'1'), bytearray(b'2'), bytearray(b'3')]}, and
  • + *
  • {@code bytearray(b' 1 2 3 ').rsplit(None, 1)} returns + * {@code [bytearray(b' 1 2'), bytearray(b'3')]}.
  • *
*

- * The elements of the PyList returned by this method are instances of the same - * actual type as this. + * The elements of the {@code PyList} returned by this method are instances of the same actual + * type as {@code this}. * - * @param sep bytes, or object viewable as bytes, defining the separator + * @param sep {@code bytes}, or object viewable as bytes, defining the separator * @param maxsplit maximum number of splits * @return PyList of byte arrays that result from the split */ @@ -2509,14 +2502,14 @@ } /** - * Ready-to-expose implementation of Python rsplit(sep, maxsplit), that returns a - * list of the words in the byte array, using sep as the delimiter. Use the defines - * whitespace semantics if sep is null. + * Ready-to-expose implementation of Python {@code rsplit(sep, maxsplit)}, that returns a list + * of the words in the byte array, using {@code sep} as the delimiter. Use the defines + * whitespace semantics if {@code sep} is {@code null}. *

- * The elements of the PyList returned by this method are instances of the same - * actual type as this. + * The elements of the {@code PyList} returned by this method are instances of the same actual + * type as {@code this}. * - * @param sep bytes, or object viewable as bytes, defining the separator + * @param sep {@code bytes}, or object viewable as bytes, defining the separator * @param maxsplit maximum number of splits * @return PyList of byte arrays that result from the split */ @@ -2529,16 +2522,16 @@ } /** - * Implementation of Python rsplit(sep, maxsplit), that returns a list of the words - * in the byte array, using sep (which is not null) as the delimiter. - * If maxsplit>=0, at most maxsplit splits are done (thus, the list - * will have at most maxsplit+1 elements). If maxsplit<0, then - * there is no limit on the number of splits (all possible splits are made). + * Implementation of Python {@code rsplit(sep, maxsplit)}, that returns a list of the words in + * the byte array, using {@code sep} (which is not {@code null}) as the delimiter. If + * {@code maxsplit>=0}, at most {@code maxsplit} splits are done (thus, the list will have at + * most {@code maxsplit+1} elements). If {@code maxsplit<0}, then there is no limit on the + * number of splits (all possible splits are made). *

- * The elements of the PyList returned by this method are instances of the same - * actual type as this. + * The elements of the {@code PyList} returned by this method are instances of the same actual + * type as {@code this}. * - * @param sep bytes, or object viewable as bytes, defining the separator + * @param sep {@code bytes}, or object viewable as bytes, defining the separator * @param maxsplit maximum number of splits * @return PyList of byte arrays that result from the split */ @@ -2584,19 +2577,19 @@ } /** - * Implementation of Python rsplit(None, maxsplit), that returns a list of the - * words in the byte array, using whitespace as the delimiter. If maxsplit is - * given, at most maxsplit splits are done (thus, the list will have at most - * maxsplit+1 elements). If maxsplit is not specified, then there is no limit on - * the number of splits (all possible splits are made). + * Implementation of Python {@code rsplit(None, maxsplit)}, that returns a list of the words in + * the byte array, using whitespace as the delimiter. If {@code maxsplit} is given, at most + * {@code maxsplit} splits are done (thus, the list will have at most {@code maxsplit+1} + * elements). If maxsplit is not specified, then there is no limit on the number of splits (all + * possible splits are made). *

* Runs of consecutive whitespace are regarded as a single separator, and the result will * contain no empty strings at the start or end if the string has leading or trailing * whitespace. Consequently, splitting an empty string or a string consisting of just whitespace - * with a None separator returns []. + * with a {@code None} separator returns []. *

- * The elements of the PyList returned by this method are instances of the same - * actual type as this/self. + * The elements of the {@code PyList} returned by this method are instances of the same actual + * type as {@code this/self}. * * @param maxsplit maximum number of splits * @return PyList of byte arrays that result from the split @@ -2645,11 +2638,11 @@ } /** - * Implementation of Python split(), that returns a list of the words in the byte - * array, using whitespace as the delimiter. See {@link #split(PyObject, int)}. + * Implementation of Python {@code split()}, that returns a list of the words in the byte array, + * using whitespace as the delimiter. See {@link #split(PyObject, int)}. *

- * The elements of the PyList returned by this method are instances of the same - * actual type as this. + * The elements of the {@code PyList} returned by this method are instances of the same actual + * type as {@code this}. * * @return PyList of byte arrays that result from the split */ @@ -2658,14 +2651,14 @@ } /** - * Implementation of Python split(sep), that returns a list of the words in the - * byte array, using sep as the delimiter. See {@link #split(PyObject, int)} for - * the semantics of the separator. + * Implementation of Python {@code split(sep)}, that returns a list of the words in the byte + * array, using {@code sep} as the delimiter. See {@link #split(PyObject, int)} for the + * semantics of the separator. *

- * The elements of the PyList returned by this method are instances of the same - * actual type as this. + * The elements of the {@code PyList} returned by this method are instances of the same actual + * type as {@code this}. * - * @param sep bytes, or object viewable as bytes, defining the separator + * @param sep {@code bytes}, or object viewable as bytes, defining the separator * @return PyList of byte arrays that result from the split */ public PyList split(PyObject sep) { @@ -2673,34 +2666,34 @@ } /** - * Implementation of Python split(sep, maxsplit), that returns a list of the words - * in the byte array, using sep as the delimiter. If maxsplit is - * given, at most maxsplit splits are done. (Thus, the list will have at most - * maxsplit+1 elements). If maxsplit is not specified, then there is - * no limit on the number of splits (all possible splits are made). + * Implementation of Python {@code split(sep, maxsplit)}, that returns a list of the words in + * the byte array, using {@code sep} as the delimiter. If {@code maxsplit} is given, at most + * {@code maxsplit} splits are done. (Thus, the list will have at most {@code maxsplit+1} + * elements). If {@code maxsplit} is not specified, then there is no limit on the number of + * splits (all possible splits are made). *

- * If sep is given, consecutive delimiters are not grouped together and are deemed - * to delimit empty strings (for example, '1,,2'.split(',') returns - * ['1', '', '2']). The sep argument may consist of multiple - * characters (for example, '1<>2<>3'.split('<>') returns ['1', - * '2', '3']). Splitting an empty string with a specified separator ['']. + * If {@code sep} is given, consecutive delimiters are not grouped together and are deemed to + * delimit empty strings (for example, {@code '1,,2'.split(',')} returns + * {@code ['1', '', '2']}). The {@code sep} argument may consist of multiple characters (for + * example, {@code '1<>2<>3'.split('<>')} returns {@code ['1', '2', '3']}). Splitting an empty + * string with a specified separator {@code ['']}. *

- * If sep is not specified or is None, a different splitting algorithm - * is applied: runs of consecutive whitespace are regarded as a single separator, and the result + * If {@code sep} is not specified or is {@code None}, a different splitting algorithm is + * applied: runs of consecutive whitespace are regarded as a single separator, and the result * will contain no empty strings at the start or end if the string has leading or trailing * whitespace. Consequently, splitting an empty string or a string consisting of just whitespace - * with a None separator returns []. For example, + * with a {@code None} separator returns {@code []}. For example, *

    - *
  • bytearray(b' 1 2 3 ').split() returns - * [bytearray(b'1'), bytearray(b'2'), bytearray(b'3')], and
  • - *
  • bytearray(b' 1 2 3 ').split(None, 1) returns - * [bytearray(b'1'), bytearray(b'2 3 ')].
  • + *
  • {@code bytearray(b' 1 2 3 ').split()} returns + * {@code [bytearray(b'1'), bytearray(b'2'), bytearray(b'3')]}, and
  • + *
  • {@code bytearray(b' 1 2 3 ').split(None, 1)} returns + * {@code [bytearray(b'1'), bytearray(b'2 3 ')]}.
  • *
*

- * The elements of the PyList returned by this method are instances of the same - * actual type as this. + * The elements of the {@code PyList} returned by this method are instances of the same actual + * type as {@code this}. * - * @param sep bytes, or object viewable as bytes, defining the separator + * @param sep {@code bytes}, or object viewable as bytes, defining the separator * @param maxsplit maximum number of splits * @return PyList of byte arrays that result from the split */ @@ -2709,14 +2702,14 @@ } /** - * Ready-to-expose implementation of Python split(sep, maxsplit), that returns a - * list of the words in the byte array, using sep as the delimiter. Use the defines - * whitespace semantics if sep is null. + * Ready-to-expose implementation of Python {@code split(sep, maxsplit)}, that returns a list of + * the words in the byte array, using {@code sep} as the delimiter. Use the defines whitespace + * semantics if {@code sep} is {@code null}. *

- * The elements of the PyList returned by this method are instances of the same - * actual type as this. + * The elements of the {@code PyList} returned by this method are instances of the same actual + * type as {@code this}. * - * @param sep bytes, or object viewable as bytes, defining the separator + * @param sep {@code bytes}, or object viewable as bytes, defining the separator * @param maxsplit maximum number of splits * @return PyList of byte arrays that result from the split */ @@ -2729,16 +2722,16 @@ } /** - * Implementation of Python split(sep, maxsplit), that returns a list of the words - * in the byte array, using sep (which is not null) as the delimiter. - * If maxsplit>=0, at most maxsplit splits are done (thus, the list - * will have at most maxsplit+1 elements). If maxsplit<0, then - * there is no limit on the number of splits (all possible splits are made). + * Implementation of Python {@code split(sep, maxsplit)}, that returns a list of the words in + * the byte array, using {@code sep} (which is not {@code null}) as the delimiter. If + * {@code maxsplit>=0}, at most {@code maxsplit} splits are done (thus, the list will have at + * most {@code maxsplit+1} elements). If {@code maxsplit<0}, then there is no limit on the + * number of splits (all possible splits are made). *

- * The elements of the PyList returned by this method are instances of the same - * actual type as this. + * The elements of the {@code PyList} returned by this method are instances of the same actual + * type as {@code this}. * - * @param sep bytes, or object viewable as bytes, defining the separator + * @param sep {@code bytes}, or object viewable as bytes, defining the separator * @param maxsplit maximum number of splits * @return PyList of byte arrays that result from the split */ @@ -2775,19 +2768,19 @@ } /** - * Implementation of Python split(None, maxsplit), that returns a list of the words - * in the byte array, using whitespace as the delimiter. If maxsplit is given, at - * most maxsplit splits are done (thus, the list will have at most maxsplit+1 - * elements). If maxsplit is not specified, then there is no limit on the number of - * splits (all possible splits are made). + * Implementation of Python {@code split(None, maxsplit)}, that returns a list of the words in + * the byte array, using whitespace as the delimiter. If {@code maxsplit} is given, at most + * maxsplit splits are done (thus, the list will have at most {@code maxsplit+1} elements). If + * {@code maxsplit} is not specified, then there is no limit on the number of splits (all + * possible splits are made). *

* Runs of consecutive whitespace are regarded as a single separator, and the result will * contain no empty strings at the start or end if the string has leading or trailing * whitespace. Consequently, splitting an empty string or a string consisting of just whitespace - * with a None separator returns []. + * with a {@code None} separator returns []. *

- * The elements of the PyList returned by this method are instances of the same - * actual type as this. + * The elements of the {@code PyList} returned by this method are instances of the same actual + * type as {@code this}. * * @param maxsplit maximum number of splits * @return PyList of byte arrays that result from the split @@ -2830,11 +2823,11 @@ } /** - * Implementation of Python splitlines(), returning a list of the lines in the byte + * Implementation of Python {@code splitlines()}, returning a list of the lines in the byte * array, breaking at line boundaries. Line breaks are not included in the resulting segments. *

- * The elements of the PyList returned by this method are instances of the same - * actual type as this. + * The elements of the {@code PyList} returned by this method are instances of the same actual + * type as {@code this}. * * @return List of segments */ @@ -2843,12 +2836,12 @@ } /** - * Implementation of Python splitlines(keepends), returning a list of the lines in - * the string, breaking at line boundaries. Line breaks are not included in the resulting list - * unless keepends is true. + * Implementation of Python {@code splitlines(keepends)}, returning a list of the lines in the + * string, breaking at line boundaries. Line breaks are not included in the resulting list + * unless {@code keepends} is true. *

- * The elements of the PyList returned by this method are instances of the same - * actual type as this. + * The elements of the {@code PyList} returned by this method are instances of the same actual + * type as {@code this}. * * @param keepends if true, include the end of line bytes(s) * @return PyList of segments @@ -2858,12 +2851,12 @@ } /** - * Ready-to-expose implementation of Python splitlines(keepends), returning a list - * of the lines in the array, breaking at line boundaries. Line breaks are not included in the - * resulting list unless keepends is given and true. + * Ready-to-expose implementation of Python {@code splitlines(keepends)}, returning a list of + * the lines in the array, breaking at line boundaries. Line breaks are not included in the + * resulting list unless {@code keepends} is given and true. *

- * The elements of the PyList returned by this method are instances of the same - * actual type as this. + * The elements of the {@code PyList} returned by this method are instances of the same actual + * type as {@code this}. * * @param keepends if true, include the end of line bytes(s) * @return List of segments @@ -2914,7 +2907,7 @@ * required to be a single character string, treated as a byte. * * @param function name - * @param fillchar or null + * @param fillchar or {@code null} * @return the (checked) single fill byte */ protected static byte fillByteCheck(String function, String fillchar) { @@ -2931,8 +2924,8 @@ * Helper function to construct the return value for {@link #rjust(String)}, * {@link #ljust(String)} and {@link #center(String)}. Clients calculate the left and right fill * values according to their nature, and ignoring the possibility that the desired - * width=left+size+right may be less than this.size. This method does - * all the work, and deals with that exceptional case by returning self[:]. + * {@code width=left+size+right} may be less than {@code this.size}. This method does all the + * work, and deals with that exceptional case by returning {@code self[:]}. * * @param pad byte to fill with * @param left padding requested @@ -2956,14 +2949,14 @@ } /** - * A ready-to-expose implementation of Python center(width [, fillchar]): return - * the bytes centered in an array of length width. Padding is done using the - * specified fillchar (default is a space). A copy of the original byte array is returned if - * width is less than this.size(). (Immutable subclasses may return - * exactly the original object.) + * A ready-to-expose implementation of Python {@code center(width [, fillchar])}: return the + * bytes centered in an array of length {@code width}. Padding is done using the specified + * fillchar (default is a space). A copy of the original byte array is returned if {@code width} + * is less than {@code this.size()}. (Immutable subclasses may return exactly the original + * object.) * * @param width desired - * @param fillchar one-byte String to fill with, or null implying space + * @param fillchar one-byte String to fill with, or {@code null} implying space * @return (possibly new) byte array containing the result */ final BaseBytes basebytes_center(int width, String fillchar) { @@ -2977,14 +2970,14 @@ } /** - * A ready-to-expose implementation of Python ljust(width [, fillchar]): return the - * bytes left-justified in an array of length width. Padding is done using the - * specified fillchar (default is a space). A copy of the original byte array is returned if - * width is less than this.size(). (Immutable subclasses may return - * exactly the original object.) + * A ready-to-expose implementation of Python {@code ljust(width [, fillchar])}: return the + * bytes left-justified in an array of length {@code width}. Padding is done using the specified + * fillchar (default is a space). A copy of the original byte array is returned if {@code width} + * is less than {@code this.size()}. (Immutable subclasses may return exactly the original + * object.) * * @param width desired - * @param fillchar one-byte String to fill with, or null implying space + * @param fillchar one-byte String to fill with, or {@code null} implying space * @return (possibly new) byte array containing the result */ final BaseBytes basebytes_ljust(int width, String fillchar) { @@ -2996,14 +2989,14 @@ } /** - * A ready-to-expose implementation of Python rjust(width [, fillchar]): return the - * bytes right-justified in an array of length width. Padding is done using the + * A ready-to-expose implementation of Python {@code rjust(width [, fillchar])}: return the + * bytes right-justified in an array of length {@code width}. Padding is done using the * specified fillchar (default is a space). A copy of the original byte array is returned if - * width is less than this.size(). (Immutable subclasses may return - * exactly the original object.) + * {@code width} is less than {@code this.size()}. (Immutable subclasses may return exactly the + * original object.) * * @param width desired - * @param fillchar one-byte String to fill with, or null implying space + * @param fillchar one-byte String to fill with, or {@code null} implying space * @return (possibly new) byte array containing the result */ final BaseBytes basebytes_rjust(int width, String fillchar) { @@ -3015,8 +3008,8 @@ } /** - * Ready-to-expose implementation of Python expandtabs([tabsize]): return a copy of - * the byte array where all tab characters are replaced by one or more spaces, depending on the + * Ready-to-expose implementation of Python {@code expandtabs([tabsize])}: return a copy of the + * byte array where all tab characters are replaced by one or more spaces, depending on the * current column and the given tab size. The column number is reset to zero after each newline * occurring in the array. This treats other non-printing characters or escape sequences as * regular characters. @@ -3053,9 +3046,9 @@ } /** - * Ready-to-expose implementation of Python zfill(width): return the numeric string - * left filled with zeros in a byte array of length width. A sign prefix is handled correctly if - * it is in the first byte. A copy of the original is returned if width is less than the current + * Ready-to-expose implementation of Python {@code zfill(width):} return the numeric string left + * filled with zeros in a byte array of length width. A sign prefix is handled correctly if it + * is in the first byte. A copy of the original is returned if width is less than the current * size of the array. * * @param width desired @@ -3150,8 +3143,8 @@ } /** - * Java API equivalent of Python isalnum(). This method treats the bytes as - * US-ASCII code points. + * Java API equivalent of Python {@code isalnum()}. This method treats the bytes as US-ASCII + * code points. * * @return true if all bytes in the array are code points for alphanumerics and there is at * least one byte, false otherwise. @@ -3161,7 +3154,7 @@ } /** - * Ready-to-expose implementation of Python isalnum(). + * Ready-to-expose implementation of Python {@code isalnum()}. * * @return true if all bytes in the array are code points for alphanumerics and there is at * least one byte, false otherwise. @@ -3183,8 +3176,8 @@ } /** - * Java API equivalent of Python isalpha(). This method treats the bytes as - * US-ASCII code points. + * Java API equivalent of Python {@code isalpha()}. This method treats the bytes as US-ASCII + * code points. * * @return true if all bytes in the array are alphabetic and there is at least one byte, false * otherwise @@ -3194,7 +3187,7 @@ } /** - * Ready-to-expose implementation of Python isalpha(). + * Ready-to-expose implementation of Python {@code isalpha()}. * * @return true if all bytes in the array are alphabetic and there is at least one byte, false * otherwise @@ -3216,8 +3209,8 @@ } /** - * Java API equivalent of Python isdigit(). This method treats the bytes as - * US-ASCII code points. + * Java API equivalent of Python {@code isdigit()}. This method treats the bytes as US-ASCII + * code points. * * @return true if all bytes in the array are code points for digits and there is at least one * byte, false otherwise. @@ -3227,7 +3220,7 @@ } /** - * Ready-to-expose implementation of Python isdigit(). + * Ready-to-expose implementation of Python {@code isdigit()}. * * @return true if all bytes in the array are code points for digits and there is at least one * byte, false otherwise. @@ -3249,8 +3242,8 @@ } /** - * Java API equivalent of Python islower(). This method treats the bytes as - * US-ASCII code points. + * Java API equivalent of Python {@code islower()}. This method treats the bytes as US-ASCII + * code points. * * @return true if all cased bytes in the array are code points for lowercase characters and * there is at least one cased byte, false otherwise. @@ -3260,7 +3253,7 @@ } /** - * Ready-to-expose implementation of Python islower(). + * Ready-to-expose implementation of Python {@code islower()}. * * @return true if all cased bytes in the array are code points for lowercase characters and * there is at least one cased byte, false otherwise. @@ -3298,8 +3291,8 @@ } /** - * Java API equivalent of Python isspace(). This method treats the bytes as - * US-ASCII code points. + * Java API equivalent of Python {@code isspace()}. This method treats the bytes as US-ASCII + * code points. * * @return true if all the bytes in the array are code points for whitespace characters and * there is at least one byte, false otherwise. @@ -3309,7 +3302,7 @@ } /** - * Ready-to-expose implementation of Python isspace(). + * Ready-to-expose implementation of Python {@code isspace()}. * * @return true if all the bytes in the array are code points for whitespace characters and * there is at least one byte, false otherwise. @@ -3331,8 +3324,8 @@ } /** - * Java API equivalent of Python istitle(). This method treats the bytes as - * US-ASCII code points. + * Java API equivalent of Python {@code istitle()}. This method treats the bytes as US-ASCII + * code points. * * @return true if the string is a titlecased string and there is at least one cased byte, for * example uppercase characters may only follow uncased bytes and lowercase characters @@ -3343,7 +3336,7 @@ } /** - * Ready-to-expose implementation of Python istitle(). + * Ready-to-expose implementation of Python {@code istitle()}. * * @return true if the string is a titlecased string and there is at least one cased byte, for * example uppercase characters may only follow uncased bytes and lowercase characters @@ -3383,8 +3376,8 @@ } /** - * Java API equivalent of Python isupper(). This method treats the bytes as - * US-ASCII code points. + * Java API equivalent of Python {@code isupper()}. This method treats the bytes as US-ASCII + * code points. * * @return true if all cased bytes in the array are code points for uppercase characters and * there is at least one cased byte, false otherwise. @@ -3394,7 +3387,7 @@ } /** - * Ready-to-expose implementation of Python isupper(). + * Ready-to-expose implementation of Python {@code isupper()}. * * @return true if all cased bytes in the array are code points for uppercase characters and * there is at least one cased byte, false otherwise. @@ -3436,9 +3429,9 @@ // /** - * Java API equivalent of Python capitalize(). This method treats the bytes as - * US-ASCII code points. The BaseBytes returned by this method has the same actual - * type as this/self. + * Java API equivalent of Python {@code capitalize()}. This method treats the bytes as US-ASCII + * code points. The {@code BaseBytes} returned by this method has the same actual type as + * {@code this/self}. * * @return a copy of the array with its first character capitalized and the rest lowercased. */ @@ -3447,9 +3440,8 @@ } /** - * Ready-to-expose implementation of Python capitalize(). The - * BaseBytes returned by this method has the same actual type as - * this/self. + * Ready-to-expose implementation of Python {@code capitalize()}. The {@code BaseBytes} returned + * by this method has the same actual type as {@code this/self}. * * @return a copy of the array with its first character capitalized and the rest lowercased. */ @@ -3481,9 +3473,9 @@ } /** - * Java API equivalent of Python lower(). This method treats the bytes as US-ASCII - * code points. The BaseBytes returned by this method has the same actual type as - * this/self. + * Java API equivalent of Python {@code lower()}. This method treats the bytes as US-ASCII code + * points. The {@code BaseBytes} returned by this method has the same actual type as + * {@code this/self}. * * @return a copy of the array with all the cased characters converted to lowercase. */ @@ -3492,8 +3484,8 @@ } /** - * Ready-to-expose implementation of Python lower(). The BaseBytes - * returned by this method has the same actual type as this/self. + * Ready-to-expose implementation of Python {@code lower()}. The {@code BaseBytes} returned by + * this method has the same actual type as {@code this/self}. * * @return a copy of the array with all the cased characters converted to lowercase. */ @@ -3514,9 +3506,9 @@ } /** - * Java API equivalent of Python swapcase(). This method treats the bytes as - * US-ASCII code points. The BaseBytes returned by this method has the same actual - * type as this/self. + * Java API equivalent of Python {@code swapcase()}. This method treats the bytes as US-ASCII + * code points. The {@code BaseBytes} returned by this method has the same actual type as + * {@code this/self}. * * @return a copy of the array with uppercase characters converted to lowercase and vice versa. */ @@ -3525,8 +3517,8 @@ } /** - * Ready-to-expose implementation of Python swapcase(). The BaseBytes - * returned by this method has the same actual type as this/self. + * Ready-to-expose implementation of Python {@code swapcase()}. The {@code BaseBytes} returned + * by this method has the same actual type as {@code this/self}. * * @return a copy of the array with uppercase characters converted to lowercase and vice versa. */ @@ -3547,11 +3539,11 @@ } /** - * Java API equivalent of Python title(). The algorithm uses a simple + * Java API equivalent of Python {@code title()}. The algorithm uses a simple * language-independent definition of a word as groups of consecutive letters. The definition * works in many contexts but it means that apostrophes in contractions and possessives form - * word boundaries, which may not be the desired result. The BaseBytes returned by - * this method has the same actual type as this/self. + * word boundaries, which may not be the desired result. The {@code BaseBytes} returned by this + * method has the same actual type as {@code this/self}. * * @return a titlecased version of the array where words start with an uppercase character and * the remaining characters are lowercase. @@ -3561,8 +3553,8 @@ } /** - * Ready-to-expose implementation of Python title(). The BaseBytes - * returned by this method has the same actual type as this/self. + * Ready-to-expose implementation of Python {@code title()}. The {@code BaseBytes} returned by + * this method has the same actual type as {@code this/self}. * * @return a titlecased version of the array where words start with an uppercase character and * the remaining characters are lowercase. @@ -3599,10 +3591,9 @@ } /** - * Java API equivalent of Python upper(). Note that - * x.upper().isupper() might be false if the array contains uncased - * characters. The BaseBytes returned by this method has the same actual type as - * this/self. + * Java API equivalent of Python {@code upper()}. Note that {@code x.upper().isupper()} might be + * {@code false} if the array contains uncased characters. The {@code BaseBytes} returned by + * this method has the same actual type as {@code this/self}. * * @return a copy of the array with all the cased characters converted to uppercase. */ @@ -3611,8 +3602,8 @@ } /** - * Ready-to-expose implementation of Python upper(). The BaseBytes - * returned by this method has the same actual type as this/self. + * Ready-to-expose implementation of Python {@code upper()}. The {@code BaseBytes} returned by + * this method has the same actual type as {@code this/self}. * * @return a copy of the array with all the cased characters converted to uppercase. */ @@ -3655,7 +3646,7 @@ * * @param index of value in byte array * @return the integer value at the index - * @throws PyException (IndexError) if the index is outside the array bounds + * @throws PyException {@code IndexError} if the index is outside the array bounds */ public synchronized int intAt(int index) throws PyException { indexCheck(index); @@ -3678,10 +3669,10 @@ } /** - * Almost ready-to-expose Python __repr__(), based on treating the bytes as point - * codes. The value added by this method is conversion of non-printing code points to - * hexadecimal escapes in printable ASCII, and bracketed by the given before and after strings. - * These are used to get the required presentation: + * Almost ready-to-expose Python {@code __repr__()}, based on treating the bytes as point codes. + * The value added by this method is conversion of non-printing code points to hexadecimal + * escapes in printable ASCII, and bracketed by the given before and after strings. These are + * used to get the required presentation: * *

      * bytearray(b'Hello world!')
@@ -3691,7 +3682,7 @@
      *
      * @param before String to insert before the quoted text
      * @param after String to insert after the quoted text
-     * @return string representation: before + "'" + String(this) + "'" + after
+     * @return string representation: {@code before + "'" + String(this) + "'" + after}
      */
     final synchronized String basebytes_repr(String before, String after) {
 
@@ -3764,9 +3755,9 @@
          * Replaces the element at the specified position in this list with the specified element.
          *
          * @see java.util.AbstractList#set(int, java.lang.Object)
-         * @throws PyException (TypeError) if actual class is immutable
-         * @throws PyException (IndexError) if the index is outside the array bounds
-         * @throws PyException (ValueError) if element<0 or element>255
+         * @throws PyException {@code TypeError} if actual class is immutable
+         * @throws PyException {@code IndexError} if the index is outside the array bounds
+         * @throws PyException {@code ValueError} if element<0 or element>255
          */
         @Override
         public PyInteger set(int index, PyInteger element) throws PyException {
@@ -3782,9 +3773,9 @@
          * currently at that position and any subsequent elements to the right.
          *
          * @see java.util.AbstractList#add(int, java.lang.Object)
-         * @throws PyException (IndexError) if the index is outside the array bounds
-         * @throws PyException (ValueError) if element<0 or element>255
-         * @throws PyException (TypeError) if the owning concrete subclass is immutable
+         * @throws PyException {@code IndexError} if the index is outside the array bounds
+         * @throws PyException {@code ValueError} if element<0 or element>255
+         * @throws PyException {@code TypeError} if the owning concrete subclass is immutable
          */
         @Override
         public void add(int index, PyInteger element) throws PyException {
@@ -3799,7 +3790,7 @@
          * removed from the list.
          *
          * @see java.util.AbstractList#remove(int)
-         * @throws PyException (IndexError) if the index is outside the array bounds
+         * @throws PyException {@code IndexError} if the index is outside the array bounds
          */
         @Override
         public PyInteger remove(int index) {
@@ -3812,7 +3803,7 @@
     };
 
     /**
-     * Number of bytes in bytearray (or bytes) object.
+     * Number of bytes in {@code bytearray} (or {@code bytes}) object.
      *
      * @see java.util.List#size()
      * @return Number of bytes in byte array.
@@ -3928,17 +3919,15 @@
     }
 
     /**
-     * Test for the equality of (the value of) this byte array to the object other. In
-     * the case where other is a PyObject, the comparison used is the
-     * standard Python == operation through PyObject. When
-     * other is not a PyObject, this object acts as a
-     * List<PyInteger>.
+     * Test for the equality of (the value of) this byte array to the object {@code other}. In the
+     * case where {@code other} is a {@code PyObject}, the comparison used is the standard Python
+     * {@code ==} operation through {@code PyObject}. When {@code other} is not a {@code PyObject},
+     * this object acts as a {@code List}.
      *
      * @see java.util.List#equals(java.lang.Object)
      *
      * @param other object to compare this byte array to
-     * @return true if and only if this byte array is equal (in value) to
-     *         other
+     * @return {@code true} if and only if this byte array is equal (in value) to {@code other}
      */
     @Override
     public boolean equals(Object other) {
@@ -4038,10 +4027,10 @@
      */
 
     /**
-     * Every sub-class of BaseBytes overrides this method to access a Builder and
-     * return that class' particular type, possibly without copying. Although the instance of which
-     * this is a method is not used, the class of that instance determines which overridden
-     * implementation is chosen, and hence both the action and the return type.
+     * Every sub-class of BaseBytes overrides this method to access a {@code Builder} and return
+     * that class' particular type, possibly without copying. Although the instance of which this is
+     * a method is not used, the class of that instance determines which overridden implementation
+     * is chosen, and hence both the action and the return type.
      *
      * @param b containing the result
      * @return a new object of the correct sub-class
@@ -4049,7 +4038,7 @@
     protected abstract BaseBytes getResult(Builder b);
 
     /**
-     * A Builder holds a buffer of bytes to which new bytes may be appended while
+     * A {@code Builder} holds a buffer of bytes to which new bytes may be appended while
      * constructing the value of byte array, even when the type ultimately constructed is immutable.
      * The value it builds may be transferred (normally without copying) to a new instance of the
      * type being built.
@@ -4194,8 +4183,8 @@
          * overflow.
          *
          * @param n additional capacity requested ({@code long} so we can recognise overflow).
-         * @throws PyException(OverflowError) when {@code sys.maxsize} is exceeded.
-         * @throws PyException(MemoryError) when free heap or JVM limitation is exceeded.
+         * @throws PyException {@code OverflowError} when {@code sys.maxsize} is exceeded.
+         * @throws PyException {@code MemoryError} when free heap or JVM limitation is exceeded.
          */
         final void makeRoomFor(long n) throws PyException {
             long needed = size + n;
@@ -4232,8 +4221,8 @@
 
     /**
      * Choose a size appropriate to store the given number of bytes, with some room for growth, when
-     * allocating storage for mutable types or Builder. We'll be more generous than
-     * CPython for small array sizes to avoid needless reallocation.
+     * allocating storage for mutable types or {@code Builder}. We'll be more generous than CPython
+     * for small array sizes to avoid needless reallocation.
      *
      * @param size of storage actually needed
      * @return n >= size a recommended storage array size
diff --git a/src/org/python/core/BaseSet.java b/src/org/python/core/BaseSet.java
--- a/src/org/python/core/BaseSet.java
+++ b/src/org/python/core/BaseSet.java
@@ -64,7 +64,7 @@
     }
 
     /**
-     * The union of this with other. 


(I.e. all elements + * The union of this with other.

(I.e. all elements * that are in either set) * * @param other A BaseSet instance. @@ -84,8 +84,8 @@ /** * The intersection of the this with other. - *

- *
+ *

+ * * (I.e. all elements that are in both sets) * * @param other A BaseSet instance. @@ -105,8 +105,8 @@ /** * The difference of the this with other. - *

- *
+ *

+ * * (I.e. all elements that are in this set and not in the other) * * @param other A BaseSet instance. @@ -153,8 +153,8 @@ /** * The symmetric difference of the this with other. - *

- *
+ *

+ * * (I.e. all elements that are in exactly one of the sets) * * @param other A BaseSet instance. @@ -367,7 +367,7 @@ } /** - * Used for pickling. Uses the module setsfactory to + * Used for pickling. Uses the module setsfactory to * export safe constructors. * * @return a tuple of (constructor, (elements)) diff --git a/src/org/python/core/BufferProtocol.java b/src/org/python/core/BufferProtocol.java --- a/src/org/python/core/BufferProtocol.java +++ b/src/org/python/core/BufferProtocol.java @@ -26,7 +26,7 @@ * * @param flags specifying features demanded and the navigational capabilities of the consumer * @return exported buffer - * @throws PyException (BufferError) when expectations do not correspond with the buffer + * @throws PyException {@code BufferError} when expectations do not correspond with the buffer * @throws ClassCastException when the object only formally implements {@code BufferProtocol} */ PyBuffer getBuffer(int flags) throws PyException, ClassCastException; 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 @@ -159,7 +159,8 @@ /** * 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. + * and affects how the SRE_STATE cache will behave/evict cached {@code PyString -> int[]} code + * points. */ public static final String sreCacheSpecDefault = "weakKeys,concurrencyLevel=4,maximumWeight=2621440,expireAfterAccess=30s"; 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 @@ -1139,8 +1139,8 @@ * @param name Name of the Java class. * @param reason for finding the class. Used in debugging messages. * @return the class, or {@code null} if it simply wasn't found - * @throws PyException (JavaError) wrapping errors occurring when the class is found but cannot - * be loaded. + * @throws PyException {@code JavaError} wrapping errors occurring when the class is found but + * cannot be loaded. */ public static Class findClassEx(String name, String reason) throws PyException { try { diff --git a/src/org/python/core/Py2kBuffer.java b/src/org/python/core/Py2kBuffer.java --- a/src/org/python/core/Py2kBuffer.java +++ b/src/org/python/core/Py2kBuffer.java @@ -561,8 +561,8 @@ * * @param index index of the element to set. * @param value to set this element to, regarded as a buffer of length one unit. - * @throws PyException(AttributeError) if value cannot be converted to an integer - * @throws PyException(ValueError) if value<0 or value>255 + * @throws PyException {@code AttributeError} if value cannot be converted to an integer + * @throws PyException {@code ValueError} if value<0 or value%gt;255 */ @Override public synchronized void pyset(int index, PyObject value) throws PyException { diff --git a/src/org/python/core/PyArray.java b/src/org/python/core/PyArray.java --- a/src/org/python/core/PyArray.java +++ b/src/org/python/core/PyArray.java @@ -600,9 +600,8 @@ /** * Converts a character code for the array type to a Java Class. - *

- * The following character codes and their native types are supported:
* + * * * * @@ -1285,9 +1284,8 @@ * memory this value is the minimum number of bytes required to store the type. *

* This method is used by other methods to define read/write quanta from strings and streams. - *

- * Values returned are:
*

Supported character codes and their native types
Type codenative type
+ * * * * @@ -2105,7 +2103,7 @@ /** * Try to re-use an existing exported buffer, or return null if we can't. * - * @throws PyException (BufferError) if the the flags are incompatible with the buffer + * @throws PyException {@code BufferError} if the the flags are incompatible with the buffer */ private BaseBuffer getExistingBuffer(int flags) throws PyException { BaseBuffer pybuf = null; @@ -2129,7 +2127,7 @@ * Test to see if the array may be resized and raise a BufferError if not. This must be called * by the implementation of any operation that changes the number of elements in the array. * - * @throws PyException (BufferError) if there are buffer exports preventing a resize + * @throws PyException {@code BufferError} if there are buffer exports preventing a resize */ private void resizeCheck() throws PyException { if (export != null) { diff --git a/src/org/python/core/PyBUF.java b/src/org/python/core/PyBUF.java --- a/src/org/python/core/PyBUF.java +++ b/src/org/python/core/PyBUF.java @@ -2,22 +2,22 @@ /** * This interface provides a base for the key interface of the buffer API, {@link PyBuffer}, - * including symbolic constants used by the consumer of a PyBuffer to specify its + * including symbolic constants used by the consumer of a {@code PyBuffer} to specify its * requirements and assumptions. The Jython buffer API emulates the CPython buffer API. There are - * two reasons for separating parts of PyBuffer into this interface: + * two reasons for separating parts of {@code PyBuffer} into this interface: *
    - *
  • The constants defined in CPython have the names PyBUF_SIMPLE, - * PyBUF_WRITABLE, etc., and the trick of defining ours here means we can write - * PyBUF.SIMPLE, PyBUF.WRITABLE, etc. so source code looks similar.
  • - *
  • It is not so easy in Java as it is in C to treat a byte array as storing - * anything other than byte, and we prepare for the possibility of buffers with a - * series of different primitive types by defining here those methods that would be in common - * between (Byte)Buffer and an assumed future FloatBuffer or - * TypedBuffer<T>. (Compare java.nio.Buffer.)
  • + *
  • The constants defined in CPython have the names {@code PyBUF_SIMPLE}, {@code PyBUF_WRITABLE}, + * etc., and the trick of defining ours here means we can write {@code PyBUF.SIMPLE}, + * {@code PyBUF.WRITABLE}, etc. so source code looks similar.
  • + *
  • It is not so easy in Java as it is in C to treat a {@code byte} array as storing anything + * other than {@code byte}, and we prepare for the possibility of buffers with a series of different + * primitive types by defining here those methods that would be in common between + * (Byte){@code Buffer} and an assumed future {@code FloatBuffer} or {@code TypedBuffer}. + * (Compare {@code java.nio.Buffer}.)
  • *
- * It is unlikely any classes would implement PyBUF, except indirectly through other + * It is unlikely any classes would implement {@code PyBUF}, except indirectly through other * interfaces. Users of the Jython buffer API can mostly overlook the distinction and just use - * PyBuffer. + * {@code PyBuffer}. */ public interface PyBUF { @@ -29,8 +29,8 @@ boolean isReadonly(); /** - * The number of dimensions to the buffer. This number is the length of the shape - * array. The actual storage may be a linear array, but this is the number of dimensions in the + * The number of dimensions to the buffer. This number is the length of the {@code shape} array. + * The actual storage may be a linear array, but this is the number of dimensions in the * interpretation that the exporting object gives the data. * * @return number of dimensions @@ -43,8 +43,8 @@ * size in "items". An item is the amount of buffer content addressed by one index or set of * indices. In the simplest case an item is a single unit (byte), and there is one dimension. In * complex cases, the array is multi-dimensional, and the item at each location is multi-unit - * (multi-byte). The consumer must not modify this array. A valid shape array is - * always returned (difference from CPython). + * (multi-byte). The consumer must not modify this array. A valid {@code shape} array is always + * returned (difference from CPython). * * @return the dimensions of the buffer as an array */ @@ -58,20 +58,20 @@ int getItemsize(); /** - * The total number of bytes represented by the view, which will be the product of the elements of the - * shape array, and the item size in bytes. + * The total number of bytes represented by the view, which will be the product of the elements + * of the {@code shape} array, and the item size in bytes. * * @return the total number of bytes represented. */ int getLen(); /** - * The strides array gives the distance in the storage array between adjacent items - * (in each dimension). In the rawest parts of the buffer API, the consumer of the buffer is - * able to navigate the exported storage. The "strides" array is part of the support for - * interpreting the buffer as an n-dimensional array of items. It provides the coefficients of - * the "addressing polynomial". (More on this in the CPython documentation.) The consumer must - * not modify this array. A valid strides array is always returned (difference from + * The {@code strides} array gives the distance in the storage array between adjacent items (in + * each dimension). In the rawest parts of the buffer API, the consumer of the buffer is able to + * navigate the exported storage. The "strides" array is part of the support for interpreting + * the buffer as an n-dimensional array of items. It provides the coefficients of the + * "addressing polynomial". (More on this in the CPython documentation.) The consumer must not + * modify this array. A valid {@code strides} array is always returned (difference from * CPython). * * @return the distance in the storage array between adjacent items (in each dimension) @@ -79,15 +79,15 @@ int[] getStrides(); /** - * The suboffsets array is a further part of the support for interpreting the - * buffer as an n-dimensional array of items, where the array potentially uses indirect - * addressing (like a real Java array of arrays, in fact). This is only applicable when there is - * more than 1 dimension, and it works in conjunction with the strides array. (More - * on this in the CPython documentation.) When used, suboffsets[k] is an integer - * index, not a byte offset as in CPython. The consumer must not modify this array. When not - * needed for navigation null is returned (as in CPython). + * The {@code suboffsets} array is a further part of the support for interpreting the buffer as + * an n-dimensional array of items, where the array potentially uses indirect addressing (like a + * real Java array of arrays, in fact). This is only applicable when there is more than 1 + * dimension, and it works in conjunction with the {@code strides} array. (More on this in the + * CPython documentation.) When used, {@code suboffsets[k]} is an integer index, not a byte + * offset as in CPython. The consumer must not modify this array. When not needed for navigation + * {@code null} is returned (as in CPython). * - * @return suboffsets array or null if not necessary for navigation + * @return suboffsets array or {@code null} if not necessary for navigation */ int[] getSuboffsets(); @@ -108,53 +108,53 @@ static final int MAX_NDIM = 64; /** * A constant used by the consumer in its call to {@link BufferProtocol#getBuffer(int)} to - * specify that it expects to write to the buffer contents. getBuffer will raise an + * specify that it expects to write to the buffer contents. {@code getBuffer} will raise an * exception if the exporter's buffer cannot meet this requirement. */ static final int WRITABLE = 0x0001; /** * A constant used by the consumer in its call to {@link BufferProtocol#getBuffer(int)} to * specify that it assumes a simple one-dimensional organisation of the exported storage with - * item size of one. getBuffer will raise an exception if the consumer sets this - * flag and the exporter cannot represent itself as byte array data. + * item size of one. {@code getBuffer} will raise an exception if the consumer sets this flag + * and the exporter cannot represent itself as byte array data. */ static final int SIMPLE = 0; /** * A constant used by the consumer in its call to {@link BufferProtocol#getBuffer(int)} to - * specify that it requires {@link PyBuffer#getFormat()} to return a String - * indicating the type of the unit. This exists for compatibility with CPython, as in Jython the - * format is always provided by getFormat(). + * specify that it requires {@link PyBuffer#getFormat()} to return a {@code String} indicating + * the type of the unit. This exists for compatibility with CPython, as in Jython the format is + * always provided by {@code getFormat()}. */ static final int FORMAT = 0x0004; /** * A constant used by the consumer in its call to {@link BufferProtocol#getBuffer(int)} to * specify that it is prepared to navigate the buffer as multi-dimensional using the - * shape array. getBuffer will raise an exception if consumer does not - * specify the flag but the exporter's buffer cannot be navigated without taking into account - * its multiple dimensions. + * {@code shape} array. {@code getBuffer} will raise an exception if consumer does not specify + * the flag but the exporter's buffer cannot be navigated without taking into account its + * multiple dimensions. */ static final int ND = 0x0008; /** * A constant used by the consumer in its call to {@link BufferProtocol#getBuffer(int)} to - * specify that it expects to use the strides array. getBuffer will - * raise an exception if consumer does not specify the flag but the exporter's buffer cannot be - * navigated without using the strides array. + * specify that it expects to use the {@code strides} array. {@code getBuffer} will raise an + * exception if consumer does not specify the flag but the exporter's buffer cannot be navigated + * without using the {@code strides} array. */ static final int STRIDES = 0x0010 | ND; /** * A constant used by the consumer in its call to {@link BufferProtocol#getBuffer(int)} to - * specify that it will assume C-order organisation of the items. getBuffer will - * raise an exception if the exporter's buffer is not C-ordered. C_CONTIGUOUS - * implies STRIDES. + * specify that it will assume C-order organisation of the items. {@code getBuffer} will raise + * an exception if the exporter's buffer is not C-ordered. {@code C_CONTIGUOUS} implies + * {@code STRIDES}. */ // It is possible this should have been (0x20|ND) expressing the idea that C-order addressing // will be assumed *instead of* using a strides array. static final int C_CONTIGUOUS = 0x0020 | STRIDES; /** * A constant used by the consumer in its call to {@link BufferProtocol#getBuffer(int)} to - * specify that it will assume Fortran-order organisation of the items. getBuffer - * will raise an exception if the exporter's buffer is not Fortran-ordered. - * F_CONTIGUOUS implies STRIDES. + * specify that it will assume Fortran-order organisation of the items. {@code getBuffer} will + * raise an exception if the exporter's buffer is not Fortran-ordered. {@code F_CONTIGUOUS} + * implies {@code STRIDES}. */ static final int F_CONTIGUOUS = 0x0040 | STRIDES; /** @@ -162,55 +162,53 @@ * specify that it will assume a contiguous organisation of the items, but will enquire which * organisation it actually is. * - * getBuffer will raise an exception if the exporter's buffer is not contiguous. - * ANY_CONTIGUOUS implies STRIDES. + * {@code getBuffer} will raise an exception if the exporter's buffer is not contiguous. + * {@code ANY_CONTIGUOUS} implies {@code STRIDES}. */ // Further CPython strangeness since it uses the strides array to answer the enquiry. static final int ANY_CONTIGUOUS = 0x0080 | STRIDES; /** * A constant used by the consumer in its call to {@link BufferProtocol#getBuffer(int)} to - * specify that it understands the suboffsets array. getBuffer will - * raise an exception if consumer does not specify the flag but the exporter's buffer cannot be - * navigated without understanding the suboffsets array. INDIRECT - * implies STRIDES. + * specify that it understands the {@code suboffsets} array. {@code getBuffer} will raise an + * exception if consumer does not specify the flag but the exporter's buffer cannot be navigated + * without understanding the {@code suboffsets} array. {@code INDIRECT} implies {@code STRIDES}. */ static final int INDIRECT = 0x0100 | STRIDES; /** - * Equivalent to (ND | WRITABLE) + * Equivalent to {@code (ND | WRITABLE)} */ static final int CONTIG = ND | WRITABLE; /** - * Equivalent to ND + * Equivalent to {@code ND} */ static final int CONTIG_RO = ND; /** - * Equivalent to (STRIDES | WRITABLE) + * Equivalent to {@code (STRIDES | WRITABLE)} */ static final int STRIDED = STRIDES | WRITABLE; /** - * Equivalent to STRIDES + * Equivalent to {@code STRIDES} */ static final int STRIDED_RO = STRIDES; /** - * Equivalent to (STRIDES | WRITABLE | FORMAT) + * Equivalent to {@code (STRIDES | WRITABLE | FORMAT)} */ static final int RECORDS = STRIDES | WRITABLE | FORMAT; /** - * Equivalent to (STRIDES | FORMAT) + * Equivalent to {@code (STRIDES | FORMAT)} */ static final int RECORDS_RO = STRIDES | FORMAT; /** - * Equivalent to (INDIRECT | WRITABLE | FORMAT). Also use this in the request if - * you plan only to use the fully-encapsulated API (byteAt, storeAt, - * copyTo, copyFrom, etc.), without ever calling - * {@link PyBuffer#getNIOByteBuffer()} or using {@link PyBuffer.Pointer}. + * Equivalent to {@code (INDIRECT | WRITABLE | FORMAT)}. Also use this in the request if you + * plan only to use the fully-encapsulated API ({@code byteAt}, {@code storeAt}, {@code copyTo}, + * {@code copyFrom}, etc.), without ever calling {@link PyBuffer#getNIOByteBuffer()} or using + * {@link PyBuffer.Pointer}. */ static final int FULL = INDIRECT | WRITABLE | FORMAT; /** - * Equivalent to (INDIRECT | FORMAT). Also use this in the request if you plan only - * to use the fully-encapsulated API (byteAt, copyTo, etc.), read - * only, without ever calling {@link PyBuffer#getNIOByteBuffer()} or using - * {@link PyBuffer.Pointer}. + * Equivalent to {@code (INDIRECT | FORMAT)}. Also use this in the request if you plan only to + * use the fully-encapsulated API ({@code byteAt}, {@code copyTo}, etc.), read only, without + * ever calling {@link PyBuffer#getNIOByteBuffer()} or using {@link PyBuffer.Pointer}. */ static final int FULL_RO = INDIRECT | FORMAT; @@ -219,43 +217,42 @@ /** * A constant used by the consumer in its call to {@link BufferProtocol#getBuffer(int)} to * specify that it expects to access the buffer contents directly as an array (rather than - * through the purely abstract part of the API). getBuffer will raise an exception - * if the exporter cannot expose its storage as Java array. + * through the purely abstract part of the API). {@code getBuffer} will raise an exception if + * the exporter cannot expose its storage as Java array. */ // XXX Pending: @Deprecated - static final int AS_ARRAY = 0x10000000; + static final int AS_ARRAY = 0x10000000; /* Constants for readability, not standard for CPython */ /** - * Field mask, used as in if ((flags&NAVIGATION) == STRIDES) .... The importance of - * the subset of flags defined by this mask is not so much in their "navigational" character as - * in the way they are treated in a buffer request. + * Field mask, used as in {@code if ((flags&NAVIGATION) == STRIDES) ...}. The importance of the + * subset of flags defined by this mask is not so much in their "navigational" character as in + * the way they are treated in a buffer request. *

- * The NAVIGATION set are used to specify which navigation arrays the consumer will - * use, and therefore the consumer must ask for all those necessary to use the buffer - * successfully (which is a function of the buffer's actual type). Asking for extra ones is not - * an error, since all are supplied (in Jython): asking for too few is an error. + * The {@code NAVIGATION} set are used to specify which navigation arrays the consumer will use, + * and therefore the consumer must ask for all those necessary to use the buffer successfully + * (which is a function of the buffer's actual type). Asking for extra ones is not an error, + * since all are supplied (in Jython): asking for too few is an error. *

- * Flags outside the NAVIGATION set, work the other way round. Asking for one the - * buffer cannot match is an error: not asking for a feature the buffer does not have is an - * error. + * Flags outside the {@code NAVIGATION} set, work the other way round. Asking for one the buffer + * cannot match is an error: not asking for a feature the buffer does not have is an error. */ static final int NAVIGATION = SIMPLE | ND | STRIDES | INDIRECT; /** * A constant used by the exporter in processing {@link BufferProtocol#getBuffer(int)} to check * for assumed C-order organisation of the items. - * C_CONTIGUOUS = IS_C_CONTIGUOUS | STRIDES. + * {@code C_CONTIGUOUS = IS_C_CONTIGUOUS | STRIDES}. */ static final int IS_C_CONTIGUOUS = C_CONTIGUOUS & ~STRIDES; /** * A constant used by the exporter in processing {@link BufferProtocol#getBuffer(int)} to check * for assumed C-order Fortran-order organisation of the items. - * F_CONTIGUOUS = IS_F_CONTIGUOUS | STRIDES. + * {@code F_CONTIGUOUS = IS_F_CONTIGUOUS | STRIDES}. */ static final int IS_F_CONTIGUOUS = F_CONTIGUOUS & ~STRIDES; /** - * Field mask, used as in if ((flags&CONTIGUITY)== ... ) .... + * Field mask, used as in if {@code ((flags&CONTIGUITY)== ... ) ...}. */ static final int CONTIGUITY = (C_CONTIGUOUS | F_CONTIGUOUS | ANY_CONTIGUOUS) & ~STRIDES; } diff --git a/src/org/python/core/PyBuffer.java b/src/org/python/core/PyBuffer.java --- a/src/org/python/core/PyBuffer.java +++ b/src/org/python/core/PyBuffer.java @@ -41,7 +41,7 @@ * Return the byte indexed from a one-dimensional buffer with item size one. This is part of the * fully-encapsulated API: the buffer implementation exported takes care of navigating the * structure of the buffer. Results are undefined where the number of dimensions is not one or - * if itemsize>1. + * if itemsize>1. * * @param index to retrieve from * @return the item at index, which is a byte @@ -52,10 +52,10 @@ * Return the unsigned byte value indexed from a one-dimensional buffer with item size one. This * is part of the fully-encapsulated API: the exporter takes care of navigating the structure of * the buffer. Results are undefined where the number of dimensions is not one or if - * itemsize>1. + * itemsize>1. * * @param index to retrieve from - * @return the item at index, treated as an unsigned byte, =0xff & byteAt(index) + * @return the item at index, treated as an unsigned byte, {@code =0xff & byteAt(index)} */ int intAt(int index) throws IndexOutOfBoundsException; @@ -63,7 +63,7 @@ * Store the given byte at the indexed location in of a one-dimensional buffer with item size * one. This is part of the fully-encapsulated API: the buffer implementation exported takes * care of navigating the structure of the buffer. Results are undefined where the number of - * dimensions is not one or if itemsize>1. + * dimensions is not one or if itemsize>1. * * @param value to store * @param index to location @@ -76,7 +76,7 @@ * Return the byte indexed from an N-dimensional buffer with item size one. This is part of the * fully-encapsulated API: the buffer implementation exported takes care of navigating the * structure of the buffer. The indices must be correct in number and range for the array shape. - * Results are undefined where itemsize>1. + * Results are undefined where itemsize>1. * * @param indices specifying location to retrieve from * @return the item at location, which is a byte @@ -87,10 +87,10 @@ * Return the unsigned byte value indexed from an N-dimensional buffer with item size one. This * is part of the fully-encapsulated API: the buffer implementation exported takes care of * navigating the structure of the buffer. The indices must be correct in number and range for - * the array shape. Results are undefined where itemsize>1. + * the array shape. Results are undefined where itemsize>1. * * @param indices specifying location to retrieve from - * @return the item at location, treated as an unsigned byte, =0xff & byteAt(index) + * @return the item at location, treated as an unsigned byte, {@code =0xff & byteAt(index)} */ int intAt(int... indices) throws IndexOutOfBoundsException; @@ -98,7 +98,7 @@ * Store the given byte at the indexed location in of an N-dimensional buffer with item size * one. This is part of the fully-encapsulated API: the exporter takes care of navigating the * structure of the buffer. The indices must be correct in number and range for the array shape. - * Results are undefined where itemsize>1. + * Results are undefined where itemsize>1. * * @param value to store * @param indices specifying location to store at @@ -145,7 +145,7 @@ * @param destIndex starting item-index in the destination (i.e. this) * @param count number of items to copy in * @throws IndexOutOfBoundsException if access out of bounds in source or destination - * @throws PyException (TypeError) if read-only buffer + * @throws PyException {@code TypeError} if read-only buffer */ void copyFrom(byte[] src, int srcPos, int destIndex, int count) // mimic arraycopy args throws IndexOutOfBoundsException, PyException; @@ -157,7 +157,7 @@ * * @param src source buffer * @throws IndexOutOfBoundsException if access out of bounds in source or destination - * @throws PyException (TypeError) if read-only buffer + * @throws PyException {@code TypeError} if read-only buffer */ void copyFrom(PyBuffer src) throws IndexOutOfBoundsException, PyException; diff --git a/src/org/python/core/PyByteArray.java b/src/org/python/core/PyByteArray.java --- a/src/org/python/core/PyByteArray.java +++ b/src/org/python/core/PyByteArray.java @@ -190,8 +190,8 @@ * an exception about that. * * @param arg primary argument from which value is taken (may be null) - * @throws PyException (TypeError) for non-iterable, - * @throws PyException (ValueError) if iterables do not yield byte [0..255] values. + * @throws PyException {@code TypeError} for non-iterable, + * @throws PyException {@code ValueError} if iterables do not yield byte [0..255] values. */ public PyByteArray(PyObject arg) throws PyException { super(TYPE); @@ -239,7 +239,7 @@ /** * Try to re-use an existing exported buffer, or return null if we can't. * - * @throws PyException (BufferError) if the the flags are incompatible with the buffer + * @throws PyException {@code BufferError} if the the flags are incompatible with the buffer */ private BaseBuffer getExistingBuffer(int flags) throws PyException { BaseBuffer pybuf = null; @@ -264,7 +264,7 @@ * called by the implementation of any append or insert that changes the number of bytes in the * array. * - * @throws PyException (BufferError) if there are buffer exports preventing a resize + * @throws PyException {@code BufferError} if there are buffer exports preventing a resize */ protected void resizeCheck() throws PyException { if (export != null) { @@ -390,8 +390,8 @@ * * @param index index of the element to set. * @param value the value to set this element to. - * @throws PyException (AttributeError) if value cannot be converted to an integer - * @throws PyException (ValueError) if value<0 or value>255 + * @throws PyException {@code AttributeError} if value cannot be converted to an integer + * @throws PyException {@code ValueError} if value<0 or value>255 */ @Override public synchronized void pyset(int index, PyObject value) throws PyException { @@ -404,9 +404,9 @@ * * @param index to insert at * @param element to insert (by value) - * @throws PyException (IndexError) if the index is outside the array bounds - * @throws PyException (ValueError) if element<0 or element>255 - * @throws PyException (TypeError) if the subclass is immutable + * @throws PyException {@code IndexError} if the index is outside the array bounds + * @throws PyException {@code ValueError} if element<0 or element>255 + * @throws PyException {@code TypeError} if the subclass is immutable */ @Override public synchronized void pyinsert(int index, PyObject element) { @@ -503,7 +503,7 @@ * @param stop one more than the position of the last element. * @param step the step size. * @param len number of zeros to insert consistent with the slice assignment - * @throws PyException (SliceSizeError) if the value size is inconsistent with an extended slice + * @throws PyException {@code SliceSizeError} if the value size is inconsistent with an extended slice */ private void setslice(int start, int stop, int step, int len) throws PyException { if (step == 1) { @@ -532,8 +532,8 @@ * @param stop one more than the position of the last element. * @param step the step size. * @param value a PyString object consistent with the slice assignment - * @throws PyException (SliceSizeError) if the value size is inconsistent with an extended slice - * @throws PyException (ValueError) if the value is a PyUnicode + * @throws PyException {@code SliceSizeError} if the value size is inconsistent with an extended slice + * @throws PyException {@code ValueError} if the value is a PyUnicode */ private void setslice(int start, int stop, int step, PyString value) throws PyException { if (value instanceof PyUnicode) { @@ -567,7 +567,7 @@ * @param stop one more than the position of the last element. * @param step the step size. * @param value an object supporting the buffer API consistent with the slice assignment - * @throws PyException (SliceSizeError) if the value size is inconsistent with an extended slice + * @throws PyException {@code SliceSizeError} if the value size is inconsistent with an extended slice */ private void setslice(int start, int stop, int step, BufferProtocol value) throws PyException, ClassCastException { @@ -603,7 +603,7 @@ * @param step the step size. * @param value an object possibly bearing the Buffer API * @return true if the slice was set successfully, false otherwise - * @throws PyException (SliceSizeError) if the value size is inconsistent with an extended slice + * @throws PyException {@code SliceSizeError} if the value size is inconsistent with an extended slice */ private boolean setsliceFromBuffer(int start, int stop, int step, PyObject value) throws PyException { @@ -626,7 +626,7 @@ * @param stop one more than the position of the last element. * @param step the step size. * @param value a bytearray (or bytes) object consistent with the slice assignment - * @throws PyException (SliceSizeError) if the value size is inconsistent with an extended slice + * @throws PyException {@code SliceSizeError} if the value size is inconsistent with an extended slice */ private void setslice(int start, int stop, int step, BaseBytes value) throws PyException { @@ -665,8 +665,8 @@ * @param stop one more than the position of the last element. * @param step the step size. * @param iter iterable source of values to enter in the array - * @throws PyException (SliceSizeError) if the iterable size is inconsistent with an extended - * slice + * @throws PyException {@code SliceSizeError} if the iterable size is inconsistent with an + * extended slice */ private void setslice(int start, int stop, int step, Iterable iter) { /* @@ -788,8 +788,8 @@ * * @param args argument array according to Jython conventions * @param kwds Keywords according to Jython conventions - * @throws PyException (TypeError) for non-iterable, - * @throws PyException (ValueError) if iterables do not yield byte [0..255] values. + * @throws PyException {@code TypeError} for non-iterable, + * @throws PyException {@code ValueError} if iterables do not yield byte [0..255] values. */ @ExposedNew @ExposedMethod(doc = BuiltinDocs.bytearray___init___doc) @@ -1007,7 +1007,7 @@ * length 1. * * @param element the item to append. - * @throws PyException (ValueError) if element<0 or element>255 + * @throws PyException {@code ValueError} if element<0 or element>255 */ public void append(PyObject element) { bytearray_append(element); @@ -1279,7 +1279,8 @@ * * * @param hex specification of the bytes - * @throws PyException (ValueError) if non-hex characters, or isolated ones, are encountered + * @throws PyException {@code ValueError} if non-hex characters, or isolated ones, are + * encountered */ static PyByteArray fromhex(String hex) throws PyException { return bytearray_fromhex(TYPE, hex); @@ -1352,7 +1353,7 @@ /** * This type is not hashable. * - * @throws PyException (TypeError) as this type is not hashable. + * @throws PyException {@code TypeError} as this type is not hashable. */ @Override public int hashCode() throws PyException { diff --git a/src/org/python/core/PyComplex.java b/src/org/python/core/PyComplex.java --- a/src/org/python/core/PyComplex.java +++ b/src/org/python/core/PyComplex.java @@ -924,7 +924,7 @@ * * @param spec a parsed PEP-3101 format specification. * @return 0, 1, or other value for none-format, a float format, or incorrect type. - * @throws PyException(ValueError) if the specification is faulty. + * @throws PyException {@code ValueError} if the specification is faulty. */ @SuppressWarnings("fallthrough") private static int checkSpecification(Spec spec) { diff --git a/src/org/python/core/PyFloat.java b/src/org/python/core/PyFloat.java --- a/src/org/python/core/PyFloat.java +++ b/src/org/python/core/PyFloat.java @@ -979,7 +979,7 @@ * * @param spec a parsed PEP-3101 format specification. * @return a formatter ready to use, or null if the type is not a floating point format type. - * @throws PyException(ValueError) if the specification is faulty. + * @throws PyException {@code ValueError} if the specification is faulty. */ @SuppressWarnings("fallthrough") static FloatFormatter prepareFormatter(Spec spec) { diff --git a/src/org/python/core/PyInteger.java b/src/org/python/core/PyInteger.java --- a/src/org/python/core/PyInteger.java +++ b/src/org/python/core/PyInteger.java @@ -117,8 +117,8 @@ * * @param x to convert to an int * @return int or long result. - * @throws PyException (TypeError) if no method of conversion can be found - * @throws PyException (AttributeError) if neither __int__ nor __trunc__ found (?) + * @throws PyException {@code TypeError} if no method of conversion can be found + * @throws PyException {@code AttributeError} if neither __int__ nor __trunc__ found (?) */ private static PyObject asPyInteger(PyObject x) throws PyException { // XXX: Not sure that this perfectly matches CPython semantics. @@ -1062,7 +1062,7 @@ * * @param spec a parsed PEP-3101 format specification. * @return a formatter ready to use, or null if the type is not an integer format type. - * @throws PyException(ValueError) if the specification is faulty. + * @throws PyException {@code ValueError} if the specification is faulty. */ @SuppressWarnings("fallthrough") static IntegerFormatter prepareFormatter(Spec spec) throws PyException { diff --git a/src/org/python/core/PyMemoryView.java b/src/org/python/core/PyMemoryView.java --- a/src/org/python/core/PyMemoryView.java +++ b/src/org/python/core/PyMemoryView.java @@ -736,7 +736,7 @@ * * @param count the number of times to repeat this. * @return never - * @throws PyException(NotImlemented) always + * @throws PyException {@code NotImplemented} always */ @Override protected synchronized PyMemoryView repeat(int count) throws PyException { @@ -754,8 +754,8 @@ * * @param index index of the element to set. * @param value to set this element to, regarded as a buffer of length one unit. - * @throws PyException(AttributeError) if value cannot be converted to an integer - * @throws PyException(ValueError) if value<0 or value>255 + * @throws PyException {@code AttributeError} if value cannot be converted to an integer + * @throws PyException {@code ValueError} if value<0 or value>255 */ @Override public synchronized void pyset(int index, PyObject value) throws PyException { diff --git a/src/org/python/core/PyObject.java b/src/org/python/core/PyObject.java --- a/src/org/python/core/PyObject.java +++ b/src/org/python/core/PyObject.java @@ -692,7 +692,7 @@ * * @param key the key to lookup in this container. * @return the value corresponding to that key. - * @exception Py.KeyError if the key is not found. + * @throws PyException {@code KeyError} if the key is not found. * * @see #__finditem__(int) **/ @@ -710,7 +710,7 @@ * * @param key the key to lookup in this container. * @return the value corresponding to that key. - * @exception Py.KeyError if the key is not found. + * @throws PyException {@code KeyError} if the key is not found. * * @see #__finditem__(PyObject) **/ @@ -766,7 +766,7 @@ * Equivalent to the standard Python __delitem__ method. * * @param key the key to be removed from the container - * @exception Py.KeyError if the key is not found in the container + * @throws PyException {@code KeyError} if the key is not found in the container **/ public void __delitem__(PyObject key) { throw Py.TypeError(String.format("'%.200s' object doesn't support item deletion", @@ -779,7 +779,7 @@ * appropriate args. The only reason to override this method is for performance. * * @param key the key who will be removed - must be an interned string . - * @exception Py.KeyError if the key is not found in the container + * @throws PyException {@code KeyError} if the key is not found in the container * * @see #__delitem__(PyObject) **/ @@ -918,9 +918,9 @@ * methods have a clear policy for failed lookups. * * @return The looked up value. May return null if the attribute is not found - * @throws PyException(AttributeError) if the attribute is not found. This is not mandatory, - * null can be returned if it fits the implementation better, or for performance - * reasons. + * @throws PyException {@code AttributeError} if the attribute is not found. This is not + * mandatory, null can be returned if it fits the implementation better, or for + * performance reasons. */ public PyObject __findattr_ex__(String name) { return object___findattr__(name); @@ -934,7 +934,7 @@ * * @param name the name to lookup in this namespace * @return the value corresponding to name - * @exception Py.AttributeError if the name is not found. + * @throws PyException {@code AttributeError} if the name is not found. * * @see #__findattr_ex__(String) **/ @@ -950,7 +950,7 @@ * * @param name the name to lookup in this namespace must be an interned string . * @return the value corresponding to name - * @exception Py.AttributeError if the name is not found. + * @throws PyException {@code AttributeError} if the name is not found. * * @see #__findattr__(java.lang.String) **/ @@ -978,7 +978,7 @@ * Equivalent to the standard Python __setattr__ method. This method can not be overridden. * * @param name the name to lookup in this namespace - * @exception Py.AttributeError if the name is not found. + * @throws PyException {@code AttributeError} if the name is not found. * * @see #__setattr__(java.lang.String, PyObject) **/ @@ -1003,7 +1003,7 @@ * Equivalent to the standard Python __delattr__ method. This method can not be overridden. * * @param name the name to which will be removed - * @exception Py.AttributeError if the name doesn't exist + * @throws PyException {@code AttributeError} if the name doesn't exist * * @see #__delattr__(java.lang.String) **/ @@ -1017,7 +1017,7 @@ * appropriate args. The only reason to override this method is for performance. * * @param name the name which will be removed - must be an interned string . - * @exception Py.AttributeError if the name doesn't exist + * @throws PyException {@code AttributeError} if the name doesn't exist * * @see #__delattr__(PyString) **/ @@ -1026,8 +1026,8 @@ } /** - * This is a hook called during the import mechanism when the target module is (or may be) - * a sub-module of this object. + * This is a hook called during the import mechanism when the target module is (or may be) a + * sub-module of this object. * * @param name relative to this object must be an interned string. * @return corresponding value (a module or package) or {@code null} if not found @@ -1208,7 +1208,8 @@ * Equivalent to the standard Python __cmp__ method. * * @param other the object to compare this with. - * @return -1 if this < o; 0 if this == o; +1 if this > o; -2 if no comparison is implemented + * @return -1 if {@code thiso}; -2 if no comparison + * is implemented **/ public int __cmp__(PyObject other) { return -2; @@ -1278,7 +1279,7 @@ * Implements cmp(this, other) * * @param o the object to compare this with. - * @return -1 if this < 0; 0 if this == o; +1 if this > o + * @return -1 if {@code this<0}; 0 if {@code this==o}; +1 if {@code this>o} **/ public final int _cmp(PyObject o) { if (this == o) { @@ -1452,7 +1453,7 @@ } /** - * Implements the Python expression this == other. + * Implements the Python expression {@code this == other}. * * @param o the object to compare this with. * @return the result of the comparison @@ -1489,7 +1490,7 @@ } /** - * Implements the Python expression this != other. + * Implements the Python expression {@code this != other}. * * @param o the object to compare this with. * @return the result of the comparison @@ -1526,7 +1527,7 @@ } /** - * Implements the Python expression this <= other. + * Implements the Python expression {@code this <= other}. * * @param o the object to compare this with. * @return the result of the comparison @@ -1563,7 +1564,7 @@ } /** - * Implements the Python expression this < other. + * Implements the Python expression {@code this < other}. * * @param o the object to compare this with. * @return the result of the comparison @@ -1600,7 +1601,7 @@ } /** - * Implements the Python expression this >= other. + * Implements the Python expression {@code this >= other}. * * @param o the object to compare this with. * @return the result of the comparison @@ -1637,7 +1638,7 @@ } /** - * Implements the Python expression this > other. + * Implements the Python expression {@code this > other}. * * @param o the object to compare this with. * @return the result of the comparison @@ -1900,7 +1901,7 @@ * Equivalent to the standard Python __index__ method. * * @return a PyInteger or PyLong - * @throws a Py.TypeError if not supported + * @throws PyException {@code TypeError} if not supported **/ public PyObject __index__() { throw Py.TypeError(String.format("'%.200s' object cannot be interpreted as an index", @@ -2054,11 +2055,12 @@ } /** - * Implements the Python expression this + o2. + * Implements the Python expression {@code this + o2}. * * @param o2 the object to perform this binary operation with. * @return the result of the add. - * @exception Py.TypeError if this operation can't be performed with these operands. + * @throws PyException {@code TypeError} if this operation can't be performed with these + * operands. **/ public final PyObject _add(PyObject o2) { PyType t1 = this.getType(); @@ -2070,12 +2072,13 @@ } /** - * Implements the Python expression this + o2 when this and o2 have the same type - * or are builtin types. + * Implements the Python expression {@code this + o2} when this and o2 have the same type or are + * builtin types. * * @param o2 the object to perform this binary operation with. * @return the result of the add. - * @exception Py.TypeError if this operation can't be performed with these operands. + * @throws PyException {@code TypeError} if this operation can't be performed with these + * operands. **/ final PyObject _basic_add(PyObject o2) { PyObject x = __add__(o2); @@ -2090,11 +2093,12 @@ } /** - * Implements the Python expression this += o2. + * Implements the Python expression {@code this += o2}. * * @param o2 the object to perform this inplace binary operation with. * @return the result of the iadd. - * @exception Py.TypeError if this operation can't be performed with these operands. + * @throws PyException {@code TypeError} if this operation can't be performed with these + * operands. **/ public final PyObject _iadd(PyObject o2) { PyType t1 = this.getType(); @@ -2113,12 +2117,13 @@ } /** - * Implements the Python expression this += o2 when this and o2 have the same type - * or are builtin types. + * Implements the Python expression {@code this += o2} when this and o2 have the same type or + * are builtin types. * * @param o2 the object to perform this inplace binary operation with. * @return the result of the iadd. - * @exception Py.TypeError if this operation can't be performed with these operands. + * @throws PyException {@code TypeError} if this operation can't be performed with these + * operands. **/ final PyObject _basic_iadd(PyObject o2) { PyObject x = __iadd__(o2); @@ -2159,11 +2164,12 @@ } /** - * Implements the Python expression this - o2 + * Implements the Python expression {@code this - o2} * * @param o2 the object to perform this binary operation with. * @return the result of the sub. - * @exception Py.TypeError if this operation can't be performed with these operands. + * @throws PyException {@code TypeError} if this operation can't be performed with these + * operands. **/ public final PyObject _sub(PyObject o2) { PyType t1 = this.getType(); @@ -2175,12 +2181,13 @@ } /** - * Implements the Python expression this - o2 when this and o2 have the same type - * or are builtin types. + * Implements the Python expression {@code this - o2} when this and o2 have the same type or are + * builtin types. * * @param o2 the object to perform this binary operation with. * @return the result of the sub. - * @exception Py.TypeError if this operation can't be performed with these operands. + * @throws PyException {@code TypeError} if this operation can't be performed with these + * operands. **/ final PyObject _basic_sub(PyObject o2) { PyObject x = __sub__(o2); @@ -2195,11 +2202,12 @@ } /** - * Implements the Python expression this -= o2 + * Implements the Python expression {@code this -= o2} * * @param o2 the object to perform this inplace binary operation with. * @return the result of the isub. - * @exception Py.TypeError if this operation can't be performed with these operands. + * @throws PyException {@code TypeError} if this operation can't be performed with these + * operands. **/ public final PyObject _isub(PyObject o2) { PyType t1 = this.getType(); @@ -2218,12 +2226,13 @@ } /** - * Implements the Python expression this -= o2 when this and o2 have the same type - * or are builtin types. + * Implements the Python expression {@code this -= o2} when this and o2 have the same type or + * are builtin types. * * @param o2 the object to perform this inplace binary operation with. * @return the result of the isub. - * @exception Py.TypeError if this operation can't be performed with these operands. + * @throws PyException {@code TypeError} if this operation can't be performed with these + * operands. **/ final PyObject _basic_isub(PyObject o2) { PyObject x = __isub__(o2); @@ -2264,11 +2273,12 @@ } /** - * Implements the Python expression this * o2. + * Implements the Python expression {@code this * o2}. * * @param o2 the object to perform this binary operation with. * @return the result of the mul. - * @exception Py.TypeError if this operation can't be performed with these operands. + * @throws PyException {@code TypeError} if this operation can't be performed with these + * operands. **/ public final PyObject _mul(PyObject o2) { PyType t1 = this.getType(); @@ -2280,12 +2290,13 @@ } /** - * Implements the Python expression this * o2 when this and o2 have the same type - * or are builtin types. + * Implements the Python expression {@code this * o2} when this and o2 have the same type or are + * builtin types. * * @param o2 the object to perform this binary operation with. * @return the result of the mul. - * @exception Py.TypeError if this operation can't be performed with these operands. + * @throws PyException {@code TypeError} if this operation can't be performed with these + * operands. **/ final PyObject _basic_mul(PyObject o2) { PyObject x = __mul__(o2); @@ -2300,11 +2311,12 @@ } /** - * Implements the Python expression this *= o2. + * Implements the Python expression {@code this *= o2}. * * @param o2 the object to perform this inplace binary operation with. * @return the result of the imul. - * @exception Py.TypeError if this operation can't be performed with these operands. + * @throws PyException {@code TypeError} if this operation can't be performed with these + * operands. **/ public final PyObject _imul(PyObject o2) { PyType t1 = this.getType(); @@ -2323,12 +2335,13 @@ } /** - * Implements the Python expression this *= o2 when this and o2 have the same type - * or are builtin types. + * Implements the Python expression {@code this *= o2} when this and o2 have the same type or + * are builtin types. * * @param o2 the object to perform this inplace binary operation with. * @return the result of the imul. - * @exception Py.TypeError if this operation can't be performed with these operands. + * @throws PyException {@code TypeError} if this operation can't be performed with these + * operands. **/ final PyObject _basic_imul(PyObject o2) { PyObject x = __imul__(o2); @@ -2369,11 +2382,12 @@ } /** - * Implements the Python expression this / o2 + * Implements the Python expression {@code this / o2} * * @param o2 the object to perform this binary operation with. * @return the result of the div. - * @exception Py.TypeError if this operation can't be performed with these operands. + * @throws PyException {@code TypeError} if this operation can't be performed with these + * operands. **/ public final PyObject _div(PyObject o2) { if (Options.Qnew) { @@ -2388,12 +2402,13 @@ } /** - * Implements the Python expression this / o2 when this and o2 have the same type - * or are builtin types. + * Implements the Python expression {@code this / o2} when this and o2 have the same type or are + * builtin types. * * @param o2 the object to perform this binary operation with. * @return the result of the div. - * @exception Py.TypeError if this operation can't be performed with these operands. + * @throws PyException {@code TypeError} if this operation can't be performed with these + * operands. **/ final PyObject _basic_div(PyObject o2) { PyObject x = __div__(o2); @@ -2408,11 +2423,12 @@ } /** - * Implements the Python expression this /= o2 + * Implements the Python expression {@code this /= o2} * * @param o2 the object to perform this inplace binary operation with. * @return the result of the idiv. - * @exception Py.TypeError if this operation can't be performed with these operands. + * @throws PyException {@code TypeError} if this operation can't be performed with these + * operands. **/ public final PyObject _idiv(PyObject o2) { if (Options.Qnew) { @@ -2434,12 +2450,13 @@ } /** - * Implements the Python expression this /= o2 when this and o2 have the same type - * or are builtin types. + * Implements the Python expression {@code this /= o2} when this and o2 have the same type or + * are builtin types. * * @param o2 the object to perform this inplace binary operation with. * @return the result of the idiv. - * @exception Py.TypeError if this operation can't be performed with these operands. + * @throws PyException {@code TypeError} if this operation can't be performed with these + * operands. **/ final PyObject _basic_idiv(PyObject o2) { PyObject x = __idiv__(o2); @@ -2480,11 +2497,12 @@ } /** - * Implements the Python expression this // o2 + * Implements the Python expression {@code this // o2} * * @param o2 the object to perform this binary operation with. * @return the result of the floordiv. - * @exception Py.TypeError if this operation can't be performed with these operands. + * @throws PyException {@code TypeError} if this operation can't be performed with these + * operands. **/ public final PyObject _floordiv(PyObject o2) { PyType t1 = this.getType(); @@ -2496,12 +2514,13 @@ } /** - * Implements the Python expression this // o2 when this and o2 have the same type - * or are builtin types. + * Implements the Python expression {@code this // o2} when this and o2 have the same type or + * are builtin types. * * @param o2 the object to perform this binary operation with. * @return the result of the floordiv. - * @exception Py.TypeError if this operation can't be performed with these operands. + * @throws PyException {@code TypeError} if this operation can't be performed with these + * operands. **/ final PyObject _basic_floordiv(PyObject o2) { PyObject x = __floordiv__(o2); @@ -2516,11 +2535,12 @@ } /** - * Implements the Python expression this //= o2 + * Implements the Python expression {@code this //= o2} * * @param o2 the object to perform this inplace binary operation with. * @return the result of the ifloordiv. - * @exception Py.TypeError if this operation can't be performed with these operands. + * @throws PyException {@code TypeError} if this operation can't be performed with these + * operands. **/ public final PyObject _ifloordiv(PyObject o2) { PyType t1 = this.getType(); @@ -2539,12 +2559,13 @@ } /** - * Implements the Python expression this //= o2 when this and o2 have the same type - * or are builtin types. + * Implements the Python expression {@code this //= o2} when this and o2 have the same type or + * are builtin types. * * @param o2 the object to perform this inplace binary operation with. * @return the result of the ifloordiv. - * @exception Py.TypeError if this operation can't be performed with these operands. + * @throws PyException {@code TypeError} if this operation can't be performed with these + * operands. **/ final PyObject _basic_ifloordiv(PyObject o2) { PyObject x = __ifloordiv__(o2); @@ -2585,11 +2606,12 @@ } /** - * Implements the Python expression this / o2 + * Implements the Python expression {@code this / o2} * * @param o2 the object to perform this binary operation with. * @return the result of the truediv. - * @exception Py.TypeError if this operation can't be performed with these operands. + * @throws PyException {@code TypeError} if this operation can't be performed with these + * operands. **/ public final PyObject _truediv(PyObject o2) { PyType t1 = this.getType(); @@ -2601,12 +2623,13 @@ } /** - * Implements the Python expression this / o2 when this and o2 have the same type - * or are builtin types. + * Implements the Python expression {@code this / o2} when this and o2 have the same type or are + * builtin types. * * @param o2 the object to perform this binary operation with. * @return the result of the truediv. - * @exception Py.TypeError if this operation can't be performed with these operands. + * @throws PyException {@code TypeError} if this operation can't be performed with these + * operands. **/ final PyObject _basic_truediv(PyObject o2) { PyObject x = __truediv__(o2); @@ -2621,11 +2644,12 @@ } /** - * Implements the Python expression this /= o2 + * Implements the Python expression {@code this /= o2} * * @param o2 the object to perform this inplace binary operation with. * @return the result of the itruediv. - * @exception Py.TypeError if this operation can't be performed with these operands. + * @throws PyException {@code TypeError} if this operation can't be performed with these + * operands. **/ public final PyObject _itruediv(PyObject o2) { PyType t1 = this.getType(); @@ -2644,12 +2668,13 @@ } /** - * Implements the Python expression this /= o2 when this and o2 have the same type - * or are builtin types. + * Implements the Python expression {@code this /= o2} when this and o2 have the same type or + * are builtin types. * * @param o2 the object to perform this inplace binary operation with. * @return the result of the itruediv. - * @exception Py.TypeError if this operation can't be performed with these operands. + * @throws PyException {@code TypeError} if this operation can't be performed with these + * operands. **/ final PyObject _basic_itruediv(PyObject o2) { PyObject x = __itruediv__(o2); @@ -2690,11 +2715,12 @@ } /** - * Implements the Python expression this % o2 + * Implements the Python expression {@code this % o2} * * @param o2 the object to perform this binary operation with. * @return the result of the mod. - * @exception Py.TypeError if this operation can't be performed with these operands. + * @throws PyException {@code TypeError} if this operation can't be performed with these + * operands. **/ public final PyObject _mod(PyObject o2) { PyType t1 = this.getType(); @@ -2706,12 +2732,13 @@ } /** - * Implements the Python expression this % o2 when this and o2 have the same type - * or are builtin types. + * Implements the Python expression {@code this % o2} when this and o2 have the same type or are + * builtin types. * * @param o2 the object to perform this binary operation with. * @return the result of the mod. - * @exception Py.TypeError if this operation can't be performed with these operands. + * @throws PyException {@code TypeError} if this operation can't be performed with these + * operands. **/ final PyObject _basic_mod(PyObject o2) { PyObject x = __mod__(o2); @@ -2726,11 +2753,12 @@ } /** - * Implements the Python expression this %= o2 + * Implements the Python expression {@code this %= o2} * * @param o2 the object to perform this inplace binary operation with. * @return the result of the imod. - * @exception Py.TypeError if this operation can't be performed with these operands. + * @throws PyException {@code TypeError} if this operation can't be performed with these + * operands. **/ public final PyObject _imod(PyObject o2) { PyType t1 = this.getType(); @@ -2749,12 +2777,13 @@ } /** - * Implements the Python expression this %= o2 when this and o2 have the same type - * or are builtin types. + * Implements the Python expression {@code this %= o2} when this and o2 have the same type or + * are builtin types. * * @param o2 the object to perform this inplace binary operation with. * @return the result of the imod. - * @exception Py.TypeError if this operation can't be performed with these operands. + * @throws PyException {@code TypeError} if this operation can't be performed with these + * operands. **/ final PyObject _basic_imod(PyObject o2) { PyObject x = __imod__(o2); @@ -2795,11 +2824,12 @@ } /** - * Implements the Python expression this divmod o2 + * Implements the Python expression {@code this divmod o2} * * @param o2 the object to perform this binary operation with. * @return the result of the divmod. - * @exception Py.TypeError if this operation can't be performed with these operands. + * @throws PyException {@code TypeError} if this operation can't be performed with these + * operands. **/ public final PyObject _divmod(PyObject o2) { PyType t1 = this.getType(); @@ -2811,12 +2841,13 @@ } /** - * Implements the Python expression this divmod o2 when this and o2 have the same - * type or are builtin types. + * Implements the Python expression {@code this divmod o2} when this and o2 have the same type + * or are builtin types. * * @param o2 the object to perform this binary operation with. * @return the result of the divmod. - * @exception Py.TypeError if this operation can't be performed with these operands. + * @throws PyException {@code TypeError} if this operation can't be performed with these + * operands. **/ final PyObject _basic_divmod(PyObject o2) { PyObject x = __divmod__(o2); @@ -2831,11 +2862,12 @@ } /** - * Implements the Python expression this divmod= o2 + * Implements the Python expression {@code this divmod= o2} * * @param o2 the object to perform this inplace binary operation with. * @return the result of the idivmod. - * @exception Py.TypeError if this operation can't be performed with these operands. + * @throws PyException {@code TypeError} if this operation can't be performed with these + * operands. **/ public final PyObject _idivmod(PyObject o2) { PyType t1 = this.getType(); @@ -2854,12 +2886,13 @@ } /** - * Implements the Python expression this divmod= o2 when this and o2 have the same - * type or are builtin types. + * Implements the Python expression {@code this divmod= o2} when this and o2 have the same type + * or are builtin types. * * @param o2 the object to perform this inplace binary operation with. * @return the result of the idivmod. - * @exception Py.TypeError if this operation can't be performed with these operands. + * @throws PyException {@code TypeError} if this operation can't be performed with these + * operands. **/ final PyObject _basic_idivmod(PyObject o2) { PyObject x = __idivmod__(o2); @@ -2900,11 +2933,12 @@ } /** - * Implements the Python expression this ** o2 + * Implements the Python expression {@code this ** o2} * * @param o2 the object to perform this binary operation with. * @return the result of the pow. - * @exception Py.TypeError if this operation can't be performed with these operands. + * @throws PyException {@code TypeError} if this operation can't be performed with these + * operands. **/ public final PyObject _pow(PyObject o2) { PyType t1 = this.getType(); @@ -2916,12 +2950,13 @@ } /** - * Implements the Python expression this ** o2 when this and o2 have the same type - * or are builtin types. + * Implements the Python expression {@code this ** o2} when this and o2 have the same type or + * are builtin types. * * @param o2 the object to perform this binary operation with. * @return the result of the pow. - * @exception Py.TypeError if this operation can't be performed with these operands. + * @throws PyException {@code TypeError} if this operation can't be performed with these + * operands. **/ final PyObject _basic_pow(PyObject o2) { PyObject x = __pow__(o2); @@ -2936,11 +2971,12 @@ } /** - * Implements the Python expression this **= o2 + * Implements the Python expression {@code this **= o2} * * @param o2 the object to perform this inplace binary operation with. * @return the result of the ipow. - * @exception Py.TypeError if this operation can't be performed with these operands. + * @throws PyException {@code TypeError} if this operation can't be performed with these + * operands. **/ public final PyObject _ipow(PyObject o2) { PyType t1 = this.getType(); @@ -2959,12 +2995,13 @@ } /** - * Implements the Python expression this **= o2 when this and o2 have the same type - * or are builtin types. + * Implements the Python expression {@code this **= o2} when this and o2 have the same type or + * are builtin types. * * @param o2 the object to perform this inplace binary operation with. * @return the result of the ipow. - * @exception Py.TypeError if this operation can't be performed with these operands. + * @throws PyException {@code TypeError} if this operation can't be performed with these + * operands. **/ final PyObject _basic_ipow(PyObject o2) { PyObject x = __ipow__(o2); @@ -3005,11 +3042,12 @@ } /** - * Implements the Python expression this << o2 + * Implements the Python expression {@code this << o2} * * @param o2 the object to perform this binary operation with. * @return the result of the lshift. - * @exception Py.TypeError if this operation can't be performed with these operands. + * @throws PyException {@code TypeError} if this operation can't be performed with these + * operands. **/ public final PyObject _lshift(PyObject o2) { PyType t1 = this.getType(); @@ -3021,12 +3059,13 @@ } /** - * Implements the Python expression this << o2 when this and o2 have the same type - * or are builtin types. + * Implements the Python expression {@code this << o2} when this and o2 have the same type or + * are builtin types. * * @param o2 the object to perform this binary operation with. * @return the result of the lshift. - * @exception Py.TypeError if this operation can't be performed with these operands. + * @throws PyException {@code TypeError} if this operation can't be performed with these + * operands. **/ final PyObject _basic_lshift(PyObject o2) { PyObject x = __lshift__(o2); @@ -3041,11 +3080,12 @@ } /** - * Implements the Python expression this <<= o2 + * Implements the Python expression {@code this <<= o2} * * @param o2 the object to perform this inplace binary operation with. * @return the result of the ilshift. - * @exception Py.TypeError if this operation can't be performed with these operands. + * @throws PyException {@code TypeError} if this operation can't be performed with these + * operands. **/ public final PyObject _ilshift(PyObject o2) { PyType t1 = this.getType(); @@ -3064,12 +3104,13 @@ } /** - * Implements the Python expression this <<= o2 when this and o2 have the same type - * or are builtin types. + * Implements the Python expression {@code this <<= o2} when this and o2 have the same type or + * are builtin types. * * @param o2 the object to perform this inplace binary operation with. * @return the result of the ilshift. - * @exception Py.TypeError if this operation can't be performed with these operands. + * @throws PyException {@code TypeError} if this operation can't be performed with these + * operands. **/ final PyObject _basic_ilshift(PyObject o2) { PyObject x = __ilshift__(o2); @@ -3110,11 +3151,12 @@ } /** - * Implements the Python expression this >> o2 + * Implements the Python expression {@code this >> o2} * * @param o2 the object to perform this binary operation with. * @return the result of the rshift. - * @exception Py.TypeError if this operation can't be performed with these operands. + * @throws PyException {@code TypeError} if this operation can't be performed with these + * operands. **/ public final PyObject _rshift(PyObject o2) { PyType t1 = this.getType(); @@ -3126,12 +3168,13 @@ } /** - * Implements the Python expression this >> o2 when this and o2 have the same type - * or are builtin types. + * Implements the Python expression {@code this >> o2} when this and o2 have the same type or + * are builtin types. * * @param o2 the object to perform this binary operation with. * @return the result of the rshift. - * @exception Py.TypeError if this operation can't be performed with these operands. + * @throws PyException {@code TypeError} if this operation can't be performed with these + * operands. **/ final PyObject _basic_rshift(PyObject o2) { PyObject x = __rshift__(o2); @@ -3146,11 +3189,12 @@ } /** - * Implements the Python expression this >>= o2 + * Implements the Python expression {@code this >>= o2} * * @param o2 the object to perform this inplace binary operation with. * @return the result of the irshift. - * @exception Py.TypeError if this operation can't be performed with these operands. + * @throws PyException {@code TypeError} if this operation can't be performed with these + * operands. **/ public final PyObject _irshift(PyObject o2) { PyType t1 = this.getType(); @@ -3169,12 +3213,13 @@ } /** - * Implements the Python expression this >>= o2 when this and o2 have the same type - * or are builtin types. + * Implements the Python expression {@code this >>= o2} when this and o2 have the same type or + * are builtin types. * * @param o2 the object to perform this inplace binary operation with. * @return the result of the irshift. - * @exception Py.TypeError if this operation can't be performed with these operands. + * @throws PyException {@code TypeError} if this operation can't be performed with these + * operands. **/ final PyObject _basic_irshift(PyObject o2) { PyObject x = __irshift__(o2); @@ -3215,11 +3260,12 @@ } /** - * Implements the Python expression this & o2 + * Implements the Python expression {@code this & o2} * * @param o2 the object to perform this binary operation with. * @return the result of the and. - * @exception Py.TypeError if this operation can't be performed with these operands. + * @throws PyException {@code TypeError} if this operation can't be performed with these + * operands. **/ public final PyObject _and(PyObject o2) { PyType t1 = this.getType(); @@ -3231,12 +3277,13 @@ } /** - * Implements the Python expression this & o2 when this and o2 have the same type - * or are builtin types. + * Implements the Python expression {@code this & o2} when this and o2 have the same type or are + * builtin types. * * @param o2 the object to perform this binary operation with. * @return the result of the and. - * @exception Py.TypeError if this operation can't be performed with these operands. + * @throws PyException {@code TypeError} if this operation can't be performed with these + * operands. **/ final PyObject _basic_and(PyObject o2) { PyObject x = __and__(o2); @@ -3251,11 +3298,12 @@ } /** - * Implements the Python expression this &= o2 + * Implements the Python expression {@code this &= o2} * * @param o2 the object to perform this inplace binary operation with. * @return the result of the iand. - * @exception Py.TypeError if this operation can't be performed with these operands. + * @throws PyException {@code TypeError} if this operation can't be performed with these + * operands. **/ public final PyObject _iand(PyObject o2) { PyType t1 = this.getType(); @@ -3274,12 +3322,13 @@ } /** - * Implements the Python expression this &= o2 when this and o2 have the same type - * or are builtin types. + * Implements the Python expression {@code this &= o2} when this and o2 have the same type or + * are builtin types. * * @param o2 the object to perform this inplace binary operation with. * @return the result of the iand. - * @exception Py.TypeError if this operation can't be performed with these operands. + * @throws PyException {@code TypeError} if this operation can't be performed with these + * operands. **/ final PyObject _basic_iand(PyObject o2) { PyObject x = __iand__(o2); @@ -3320,11 +3369,12 @@ } /** - * Implements the Python expression this | o2 + * Implements the Python expression {@code this | o2} * * @param o2 the object to perform this binary operation with. * @return the result of the or. - * @exception Py.TypeError if this operation can't be performed with these operands. + * @throws PyException {@code TypeError} if this operation can't be performed with these + * operands. **/ public final PyObject _or(PyObject o2) { PyType t1 = this.getType(); @@ -3336,12 +3386,13 @@ } /** - * Implements the Python expression this | o2 when this and o2 have the same type - * or are builtin types. + * Implements the Python expression {@code this | o2} when this and o2 have the same type or are + * builtin types. * * @param o2 the object to perform this binary operation with. * @return the result of the or. - * @exception Py.TypeError if this operation can't be performed with these operands. + * @throws PyException {@code TypeError} if this operation can't be performed with these + * operands. **/ final PyObject _basic_or(PyObject o2) { PyObject x = __or__(o2); @@ -3356,11 +3407,12 @@ } /** - * Implements the Python expression this |= o2 + * Implements the Python expression {@code this |= o2} * * @param o2 the object to perform this inplace binary operation with. * @return the result of the ior. - * @exception Py.TypeError if this operation can't be performed with these operands. + * @throws PyException {@code TypeError} if this operation can't be performed with these + * operands. **/ public final PyObject _ior(PyObject o2) { PyType t1 = this.getType(); @@ -3379,12 +3431,13 @@ } /** - * Implements the Python expression this |= o2 when this and o2 have the same type - * or are builtin types. + * Implements the Python expression {@code this |= o2} when this and o2 have the same type or + * are builtin types. * * @param o2 the object to perform this inplace binary operation with. * @return the result of the ior. - * @exception Py.TypeError if this operation can't be performed with these operands. + * @throws PyException {@code TypeError} if this operation can't be performed with these + * operands. **/ final PyObject _basic_ior(PyObject o2) { PyObject x = __ior__(o2); @@ -3425,11 +3478,12 @@ } /** - * Implements the Python expression this ^ o2 + * Implements the Python expression {@code this ^ o2} * * @param o2 the object to perform this binary operation with. * @return the result of the xor. - * @exception Py.TypeError if this operation can't be performed with these operands. + * @throws PyException {@code TypeError} if this operation can't be performed with these + * operands. **/ public final PyObject _xor(PyObject o2) { PyType t1 = this.getType(); @@ -3441,12 +3495,13 @@ } /** - * Implements the Python expression this ^ o2 when this and o2 have the same type - * or are builtin types. + * Implements the Python expression {@code this ^ o2} when this and o2 have the same type or are + * builtin types. * * @param o2 the object to perform this binary operation with. * @return the result of the xor. - * @exception Py.TypeError if this operation can't be performed with these operands. + * @throws PyException {@code TypeError} if this operation can't be performed with these + * operands. **/ final PyObject _basic_xor(PyObject o2) { PyObject x = __xor__(o2); @@ -3461,11 +3516,12 @@ } /** - * Implements the Python expression this ^= o2 + * Implements the Python expression {@code this ^= o2} * * @param o2 the object to perform this inplace binary operation with. * @return the result of the ixor. - * @exception Py.TypeError if this operation can't be performed with these operands. + * @throws PyException {@code TypeError} if this operation can't be performed with these + * operands. **/ public final PyObject _ixor(PyObject o2) { PyType t1 = this.getType(); @@ -3484,12 +3540,13 @@ } /** - * Implements the Python expression this ^= o2 when this and o2 have the same type - * or are builtin types. + * Implements the Python expression {@code this ^= o2} when this and o2 have the same type or + * are builtin types. * * @param o2 the object to perform this inplace binary operation with. * @return the result of the ixor. - * @exception Py.TypeError if this operation can't be performed with these operands. + * @throws PyException {@code TypeError} if this operation can't be performed with these + * operands. **/ final PyObject _basic_ixor(PyObject o2) { PyObject x = __ixor__(o2); diff --git a/src/org/python/core/PyString.java b/src/org/python/core/PyString.java --- a/src/org/python/core/PyString.java +++ b/src/org/python/core/PyString.java @@ -875,7 +875,7 @@ * * @param obj to coerce to a String * @return coerced value - * @throws PyException if the coercion fails (including unicode) + * @throws PyException {@code TypeError} if the coercion fails (including unicode) */ protected static String asU16BytesOrError(PyObject obj) throws PyException { String ret = asU16BytesOrNull(obj); @@ -2190,7 +2190,7 @@ * * @param sub substring to find. * @return index of sub in this object. - * @throws PyException(ValueError) if not found. + * @throws PyException {@code ValueError} if not found. */ public int index(PyObject sub) { return str_index(sub, null, null); @@ -2204,7 +2204,7 @@ * @param sub substring to find. * @param start start of slice. * @return index of sub in this object. - * @throws PyException(ValueError) if not found. + * @throws PyException {@code ValueError} if not found. */ public int index(PyObject sub, PyObject start) throws PyException { return str_index(sub, start, null); @@ -2221,7 +2221,7 @@ * @param start start of slice. * @param end end of slice. * @return index of sub in this object. - * @throws PyException(ValueError) if not found. + * @throws PyException {@code ValueError} if not found. */ public int index(PyObject sub, PyObject start, PyObject end) throws PyException { return checkIndex(str_index(sub, start, end)); @@ -2256,7 +2256,7 @@ * * @param sub substring to find. * @return index of sub in this object. - * @throws PyException(ValueError) if not found. + * @throws PyException {@code ValueError} if not found. */ public int rindex(PyObject sub) { return str_rindex(sub, null, null); @@ -2270,7 +2270,7 @@ * @param sub substring to find. * @param start start of slice. * @return index of sub in this object. - * @throws PyException(ValueError) if not found. + * @throws PyException {@code ValueError} if not found. */ public int rindex(PyObject sub, PyObject start) throws PyException { return str_rindex(sub, start, null); @@ -2287,7 +2287,7 @@ * @param start start of slice. * @param end end of slice. * @return index of sub in this object. - * @throws PyException(ValueError) if not found. + * @throws PyException {@code ValueError} if not found. */ public int rindex(PyObject sub, PyObject start, PyObject end) throws PyException { return checkIndex(str_rindex(sub, start, end)); @@ -2323,7 +2323,7 @@ * * @param index to check * @return index if non-negative - * @throws PyException(ValueError) if not found + * @throws PyException {@code ValueError} if not found */ protected final int checkIndex(int index) throws PyException { if (index >= 0) { @@ -4237,7 +4237,7 @@ * * @param spec a parsed PEP-3101 format specification. * @return a formatter ready to use, or null if the type is not a string format type. - * @throws PyException(ValueError) if the specification is faulty. + * @throws PyException {@code ValueError} if the specification is faulty. */ @SuppressWarnings("fallthrough") static TextFormatter prepareFormatter(Spec spec) throws PyException { 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 @@ -822,6 +822,7 @@ * Emulates CPython's way to name sys.platform. Works according to this table: * *

Values returned
TypeSize
+ * * * * @@ -883,6 +884,7 @@ * argument is the {@code System.getProperties()}, if were allowed to access it, and therefore * represents definitions made on the command-line. The net precedence order is: *
Platform names
SystemValue
+ * * * * @@ -1525,16 +1527,17 @@ * Note. Classes found in directory and sub-directory are not made available to jython by * this call. It only makes the java package found in the directory available. This call is * mostly useful if jython is embedded in an application that deals with its own class loaders. - * A servlet container is a very good example. Calling add_classdir("/WEB-INF/classes") - * makes the java packages in WEB-INF classes available to jython import. However the actual - * classloading is completely handled by the servlet container's context classloader. + * A servlet container is a very good example. Calling + * {@code add_classdir("/WEB-INF/classes")} makes the java packages in WEB-INF classes + * available to jython import. However the actual class loading is completely handled by the + * servlet container's context classloader. */ public static void add_classdir(String directoryPath) { packageManager.addDirectory(new File(directoryPath)); } /** - * Add a .jar & .zip directory to the list of places that are searched for java .jar and .zip + * Add a .jar and .zip directory to the list of places that are searched for java .jar and .zip * files. The .jar and .zip files found will not be cached. *

* Note. Classes in .jar and .zip files found in the directory are not made available to @@ -1549,7 +1552,7 @@ } /** - * Add a .jar & .zip directory to the list of places that are searched for java .jar and .zip + * Add a .jar and .zip directory to the list of places that are searched for java .jar and .zip * files. *

* Note. Classes in .jar and .zip files found in the directory are not made available to @@ -1589,8 +1592,8 @@ * Exit a Python program with the given status. * * @param status the value to exit with - * @exception Py.SystemExit always throws this exception. When caught at top level the program - * will exit. + * @throws PyException {@code SystemExit} always throws this exception. When caught at top level + * the program will exit. */ public static void exit(PyObject status) { throw new PyException(Py.SystemExit, status); diff --git a/src/org/python/core/PyUnicode.java b/src/org/python/core/PyUnicode.java --- a/src/org/python/core/PyUnicode.java +++ b/src/org/python/core/PyUnicode.java @@ -480,7 +480,7 @@ * @param string of UTF-16 code units * @param p index into that string * @return 2 if a surrogate pair stands at p, 1 if not - * @throws PyException(ValueError) if a lone surrogate stands at p. + * @throws PyException {@code ValueError} if a lone surrogate stands at p. */ private static int calcAdvance(String string, int p) throws PyException { diff --git a/src/org/python/core/RegistryKey.java b/src/org/python/core/RegistryKey.java --- a/src/org/python/core/RegistryKey.java +++ b/src/org/python/core/RegistryKey.java @@ -48,11 +48,10 @@ * console (http://jline.sourceforge.net/) out of the box. This is selected by default in the * Jython command-line application ({@link org.python.util.jython}) if you do not define * {@code python.console} to be another class on the command line. Alternatively, you can set - * python.console in the registry, but be aware that this will also affect the console in - * applications that embed a PythonInterpreter, or use Jython as a JSR-223 script engine. - *

- * Values: + * {@code python.console} in the registry, but be aware that this will also affect the console + * in applications that embed a PythonInterpreter, or use Jython as a JSR-223 script engine. *

Precedence order of registry sources
SourceFilled by
+ * * * * @@ -105,6 +104,7 @@ *

* Values: *

Values for {@code python.console}
{@link org.python.util.JLineConsole} (default)
+ * * * *
Values for {@code python.locale.control}
{@code settable}Python locale module is available and supports {@code setlocale()} and other standard @@ -128,6 +128,7 @@ * entries, each entry of which has the following allowable forms: *

* + * * * *
Values for {@code python.modules.builtin}
{@code name}The module name is {@code name} and the class name is diff --git a/src/org/python/core/Traverseproc.java b/src/org/python/core/Traverseproc.java --- a/src/org/python/core/Traverseproc.java +++ b/src/org/python/core/Traverseproc.java @@ -147,7 +147,7 @@ *
  *  {@literal @}Override
  *  public boolean refersDirectlyTo(PyObject ob) {
- *      return ob != null && (ob == im_class || ob == __func__ || ob == __self__);
+ *      return ob != null {@literal &&} (ob == im_class || ob == __func__ || ob == __self__);
  *  }
  * 
* If there is a Java-set or other iterable that it is not a {@code PyObject}, @@ -177,7 +177,7 @@ *
  *  {@literal @}Override
  *  public boolean refersDirectlyTo(PyObject ob) {
- *      return ob != null && _set.contains(ob);
+ *      return ob != null {@literal &&} _set.contains(ob);
  *  }
  * 
* If a class extends a {@code Traverseproc}-implementing class and adds @@ -256,7 +256,6 @@ * throw new UnsupportedOperationException(); * } * - *

*

*
* List of {@code PyObject}-subclasses

diff --git a/src/org/python/core/__builtin__.java b/src/org/python/core/__builtin__.java --- a/src/org/python/core/__builtin__.java +++ b/src/org/python/core/__builtin__.java @@ -785,7 +785,7 @@ * * @param c string-like object of length 1 * @return ordinal value of character or byte value in - * @throws PyException (TypeError) if not a string-like type + * @throws PyException {@code TypeError} if not a string-like type */ public static final int ord(PyObject c) throws PyException { final int length; diff --git a/src/org/python/core/buffer/BaseArrayBuffer.java b/src/org/python/core/buffer/BaseArrayBuffer.java --- a/src/org/python/core/buffer/BaseArrayBuffer.java +++ b/src/org/python/core/buffer/BaseArrayBuffer.java @@ -126,7 +126,7 @@ * @param destIndex starting item-index in the destination (i.e. this) * @param count number of items to copy in * @throws IndexOutOfBoundsException if access out of bounds in source or destination - * @throws PyException (TypeError) if read-only buffer + * @throws PyException {@code TypeError} if read-only buffer */ protected void copyFrom(byte[] src, int srcPos, int srcStride, int destIndex, int count) throws IndexOutOfBoundsException, PyException { diff --git a/src/org/python/core/buffer/BaseBuffer.java b/src/org/python/core/buffer/BaseBuffer.java --- a/src/org/python/core/buffer/BaseBuffer.java +++ b/src/org/python/core/buffer/BaseBuffer.java @@ -211,7 +211,7 @@ * corresponding to an array that the buffer deems necessary. * * @param flags capabilities of and navigation assumed by the consumer - * @throws PyException (BufferError) when expectations do not correspond with the buffer + * @throws PyException {@code BufferError} when expectations do not correspond with the buffer */ protected void checkRequestFlags(int flags) throws PyException { /* @@ -291,7 +291,7 @@ * * @param value to store * @param byteIndex byte-index of location to retrieve - * @throws PyException(BufferError) if this object is read-only. + * @throws PyException {@code BufferError} if this object is read-only. */ abstract protected void storeAtImpl(byte value, int byteIndex) throws IndexOutOfBoundsException, PyException; @@ -820,7 +820,7 @@ * * @param indices into the buffer (to test) * @return number of dimensions - * @throws PyException (BufferError) if wrong number of indices + * @throws PyException {@code BufferError} if wrong number of indices */ int checkDimension(int[] indices) throws PyException { int n = indices.length; @@ -834,7 +834,7 @@ * N-dimensional arrays. * * @param n number of dimensions being assumed by caller - * @throws PyException (BufferError) if wrong number of indices + * @throws PyException {@code BufferError} if wrong number of indices */ void checkDimension(int n) throws PyException { int ndim = getNdim(); @@ -848,7 +848,7 @@ /** * Check that the buffer is writable. * - * @throws PyException (TypeError) if not + * @throws PyException {@code TypeError} if not */ protected void checkWritable() throws PyException { if (isReadonly()) { @@ -859,7 +859,7 @@ /** * Check that the buffer is backed by an array the client can access as byte[]. * - * @throws PyException (BufferError) if not + * @throws PyException {@code BufferError} if not */ protected void checkHasArray() throws PyException { if (!hasArray()) { diff --git a/src/org/python/core/buffer/BaseNIOBuffer.java b/src/org/python/core/buffer/BaseNIOBuffer.java --- a/src/org/python/core/buffer/BaseNIOBuffer.java +++ b/src/org/python/core/buffer/BaseNIOBuffer.java @@ -182,7 +182,7 @@ * @param destIndex starting item-index in the destination (i.e. this) * @param count number of items to copy in * @throws IndexOutOfBoundsException if access out of bounds in source or destination - * @throws PyException (TypeError) if read-only buffer + * @throws PyException {@code TypeError} if read-only buffer */ // XXX Should this become part of the PyBUffer interface? protected void copyFrom(ByteBuffer src, int destIndex, int count) diff --git a/src/org/python/core/buffer/SimpleBuffer.java b/src/org/python/core/buffer/SimpleBuffer.java --- a/src/org/python/core/buffer/SimpleBuffer.java +++ b/src/org/python/core/buffer/SimpleBuffer.java @@ -48,7 +48,7 @@ * @throws NullPointerException if storage is null * @throws ArrayIndexOutOfBoundsException if index0 and size are * inconsistent with storage.length - * @throws PyException (BufferError) when expectations do not correspond with the type + * @throws PyException {@code BufferError} when expectations do not correspond with the type */ public SimpleBuffer(int flags, BufferProtocol obj, byte[] storage, int index0, int size) throws PyException, ArrayIndexOutOfBoundsException, NullPointerException { @@ -83,7 +83,7 @@ * @param obj exporting object (or null) * @param storage the array of bytes storing the implementation of the exporting object * @throws NullPointerException if storage is null - * @throws PyException (BufferError) when expectations do not correspond with the type + * @throws PyException {@code BufferError} when expectations do not correspond with the type */ public SimpleBuffer(int flags, BufferProtocol obj, byte[] storage) throws PyException, NullPointerException { diff --git a/src/org/python/core/buffer/SimpleNIOBuffer.java b/src/org/python/core/buffer/SimpleNIOBuffer.java --- a/src/org/python/core/buffer/SimpleNIOBuffer.java +++ b/src/org/python/core/buffer/SimpleNIOBuffer.java @@ -58,7 +58,7 @@ * @throws NullPointerException if storage is null * @throws ArrayIndexOutOfBoundsException if index0 and size are * inconsistent with storage.length - * @throws PyException (BufferError) when expectations do not correspond with the type + * @throws PyException {@code BufferError} when expectations do not correspond with the type */ public SimpleNIOBuffer(int flags, BufferProtocol obj, ByteBuffer storage, int index0, int size) throws PyException, ArrayIndexOutOfBoundsException, NullPointerException { @@ -92,7 +92,7 @@ * @param obj exporting object (or null) * @param storage the ByteBuffer wrapping the exported object state * @throws NullPointerException if storage is null - * @throws PyException (BufferError) when expectations do not correspond with the type + * @throws PyException {@code BufferError} when expectations do not correspond with the type */ public SimpleNIOBuffer(int flags, BufferProtocol obj, ByteBuffer storage) throws PyException, NullPointerException { diff --git a/src/org/python/core/buffer/SimpleWritableBuffer.java b/src/org/python/core/buffer/SimpleWritableBuffer.java --- a/src/org/python/core/buffer/SimpleWritableBuffer.java +++ b/src/org/python/core/buffer/SimpleWritableBuffer.java @@ -19,7 +19,7 @@ * @param storage the array of bytes storing the implementation of the exporting object * @param index0 offset where the data starts in that array (item[0]) * @param size the number of bytes occupied - * @throws PyException (BufferError) when expectations do not correspond with the type + * @throws PyException {@code BufferError} when expectations do not correspond with the type */ public SimpleWritableBuffer(int flags, BufferProtocol obj, byte[] storage, int index0, int size) throws PyException, NullPointerException { @@ -36,7 +36,7 @@ * @param flags consumer requirements * @param obj exporting object (or null) * @param storage the array of bytes storing the implementation of the exporting object - * @throws PyException (BufferError) when expectations do not correspond with the type + * @throws PyException {@code BufferError} when expectations do not correspond with the type */ public SimpleWritableBuffer(int flags, BufferProtocol obj, byte[] storage) throws PyException, NullPointerException { diff --git a/src/org/python/core/buffer/Strided1DBuffer.java b/src/org/python/core/buffer/Strided1DBuffer.java --- a/src/org/python/core/buffer/Strided1DBuffer.java +++ b/src/org/python/core/buffer/Strided1DBuffer.java @@ -117,7 +117,7 @@ * @throws NullPointerException if storage is null * @throws ArrayIndexOutOfBoundsException if index0, count and * stride are inconsistent with storage.length - * @throws PyException (BufferError) when expectations do not correspond with the type + * @throws PyException {@code BufferError} when expectations do not correspond with the type */ public Strided1DBuffer(int flags, BufferProtocol obj, byte[] storage, int index0, int count, int stride) throws ArrayIndexOutOfBoundsException, NullPointerException, PyException { @@ -197,7 +197,7 @@ * @param index0 index into storage of item[0] * @param count number of items in the sliced view * @param stride in between successive elements of the new PyBuffer - * @throws PyException (BufferError) when expectations do not correspond with the type + * @throws PyException {@code BufferError} when expectations do not correspond with the type */ public SlicedView(PyBuffer root, int flags, byte[] storage, int index0, int count, int stride) throws PyException { diff --git a/src/org/python/core/buffer/Strided1DNIOBuffer.java b/src/org/python/core/buffer/Strided1DNIOBuffer.java --- a/src/org/python/core/buffer/Strided1DNIOBuffer.java +++ b/src/org/python/core/buffer/Strided1DNIOBuffer.java @@ -131,7 +131,7 @@ * @throws NullPointerException if storage is null * @throws ArrayIndexOutOfBoundsException if index0, count and * stride are inconsistent with storage.length - * @throws PyException (BufferError) when expectations do not correspond with the type + * @throws PyException {@code BufferError} when expectations do not correspond with the type */ public Strided1DNIOBuffer(int flags, BufferProtocol obj, ByteBuffer storage, int index0, int count, int stride) throws ArrayIndexOutOfBoundsException, NullPointerException, @@ -190,7 +190,7 @@ * @param index0 index into storage of item[0] * @param count the number of items in the sliced view * @param stride in between successive elements of the new PyBuffer - * @throws PyException (BufferError) when expectations do not correspond with the type + * @throws PyException {@code BufferError} when expectations do not correspond with the type */ public SlicedView(PyBuffer root, int flags, ByteBuffer storage, int index0, int count, int stride) throws PyException { diff --git a/src/org/python/core/buffer/Strided1DWritableBuffer.java b/src/org/python/core/buffer/Strided1DWritableBuffer.java --- a/src/org/python/core/buffer/Strided1DWritableBuffer.java +++ b/src/org/python/core/buffer/Strided1DWritableBuffer.java @@ -15,7 +15,7 @@ * Provide an instance of Strided1DWritableBuffer on a particular array of bytes * specifying a starting index, the number of items in the result, and a byte-indexing stride. * The result of byteAt(i) will be equal to storage[index0+stride*i] - * (whatever the sign of stride>0), valid for 0<=i<count. + * (whatever the sign of {@code stride}), valid for 0≤{@code i}<{@code count}. *

* The constructed PyBuffer meets the consumer's expectations as expressed in the * flags argument, or an exception will be thrown if these are incompatible with @@ -34,7 +34,7 @@ * @throws NullPointerException if storage is null * @throws ArrayIndexOutOfBoundsException if index0, count and * stride are inconsistent with storage.length - * @throws PyException (BufferError) when expectations do not correspond with the type + * @throws PyException {@code BufferError} when expectations do not correspond with the type */ public Strided1DWritableBuffer(int flags, BufferProtocol obj, byte[] storage, int index0, int count, int stride) throws ArrayIndexOutOfBoundsException, NullPointerException, @@ -105,7 +105,7 @@ * @param index0 index into storage of item[0] * @param count number of items in the sliced view * @param stride in between successive elements of the new PyBuffer - * @throws PyException (BufferError) when expectations do not correspond with the type + * @throws PyException {@code BufferError} when expectations do not correspond with the type */ public SlicedView(PyBuffer root, int flags, byte[] storage, int index0, int count, int stride) throws PyException { diff --git a/src/org/python/core/buffer/ZeroByteBuffer.java b/src/org/python/core/buffer/ZeroByteBuffer.java --- a/src/org/python/core/buffer/ZeroByteBuffer.java +++ b/src/org/python/core/buffer/ZeroByteBuffer.java @@ -29,7 +29,8 @@ * @param obj exporting object (or null) * @param readonly set true if not to be considered writable * @param hasArray set true if to be considered as backed by an array - * @throws PyException (BufferError) when client expectations do not correspond with the type + * @throws PyException {@code BufferError} when client expectations do not correspond with the + * type */ public ZeroByteBuffer(int flags, BufferProtocol obj, boolean readonly, boolean hasArray) throws PyException { diff --git a/src/org/python/core/codecs.java b/src/org/python/core/codecs.java --- a/src/org/python/core/codecs.java +++ b/src/org/python/core/codecs.java @@ -723,6 +723,7 @@ * decoder, where partial output characters are an error. For 32 bits or more, It duplicates * some logic, but is called only during abnormal processing. The return is: * + * * * * diff --git a/src/org/python/core/finalization/FinalizablePyObject.java b/src/org/python/core/finalization/FinalizablePyObject.java --- a/src/org/python/core/finalization/FinalizablePyObject.java +++ b/src/org/python/core/finalization/FinalizablePyObject.java @@ -1,97 +1,69 @@ package org.python.core.finalization; /** - *

- * This interface allows {@code PyObject}s to have finalizers. - * Alternatively one can use + * This interface allows {@code PyObject}s to have finalizers. Alternatively one can use * {@link org.python.core.finalization.FinalizableBuiltin}. - *

*

- * The difference is that {@link #__del__()} can be overridden by a - * new-style subclass's {@code __del__}-method on Python-side, while - * {@link FinalizableBuiltin#__del_builtin__()} is always called. - * If a Python-side finalizer exists, - * {@link FinalizableBuiltin#__del_builtin__()} will be called after the - * Python-side finalizer has been processed. - *

+ * The difference is that {@link #__del__()} can be overridden by a new-style subclass's + * {@code __del__}-method on Python-side, while {@link FinalizableBuiltin#__del_builtin__()} is + * always called. If a Python-side finalizer exists, {@link FinalizableBuiltin#__del_builtin__()} + * will be called after the Python-side finalizer has been processed. *

- * One can even implement both interfaces. - * If both interfaces are implemented, the {@link FinalizeTrigger} will - * call {@link #__del__()} first and then - * {@link FinalizableBuiltin#__del_builtin__()}. If a - * new-style subclass has an own, Python-side {@code __del__}-method, this - * overrides the Java-implemented {@link #__del__()}, but not - * {@link FinalizableBuiltin#__del_builtin__()}, which will be called after - * the Python-side finalizer. - *

+ * One can even implement both interfaces. If both interfaces are implemented, the + * {@link FinalizeTrigger} will call {@link #__del__()} first and then + * {@link FinalizableBuiltin#__del_builtin__()}. If a new-style subclass has an own, Python-side + * {@code __del__}-method, this overrides the Java-implemented {@link #__del__()}, but not + * {@link FinalizableBuiltin#__del_builtin__()}, which will be called after the Python-side + * finalizer. *

- * If you are writing a custom built-in that shall directly - * extend {@link org.python.core.PyObject} or some other not-yet-finalizable - * builtin and have a finalizer, follow the instructions below. - *

+ * If you are writing a custom built-in that shall directly extend {@link org.python.core.PyObject} + * or some other not-yet-finalizable builtin and have a finalizer, follow the instructions below. *

*

    - *
  1. - * Let your subclass implement {@link FinalizablePyObject} - * (or {@link FinalizableBuiltin}). - *
  2. - *
  3. - * In every constructor call
    - * {@code FinalizeTrigger.ensureFinalizer(this);}
    - *
  4. - *
  5. - * Write your {@link #__del__()}-method however you intend it. - * (or {@link FinalizableBuiltin#__del_builtin__()} if - * {@link FinalizableBuiltin} was used) + *
  6. Let your subclass implement {@link FinalizablePyObject} (or {@link FinalizableBuiltin}).
  7. + *
  8. In every constructor call
    + * {@code FinalizeTrigger.ensureFinalizer(this);}
    *
  9. - *
  10. - * (optional)
    - * If your finalizer resurrects the object (Python allows this) and you wish the - * finalizer to run again on next collection of the object:
    - * In the block where the resurrection occurs, let your {@link #__del__()}- or - * {@link FinalizableBuiltin#__del_builtin__()}-method call
    - * {@code FinalizeTrigger.ensureFinalizer(this);}. - * If you implement {@code __del__} in Python and need this functionality, you can - * simply call {@code someObject.__ensure_finalizer__()}
    - * Note that this is Jython-specific and should be surrounded by a - * {@code try/except}-block to ensure compatibility with other Python implementations. - *
  11. + *
  12. Write your {@link #__del__()}-method however you intend it. (or + * {@link FinalizableBuiltin#__del_builtin__()} if {@link FinalizableBuiltin} was used)
  13. + *
  14. (optional)
    + * If your finalizer resurrects the object (Python allows this) and you wish the finalizer to run + * again on next collection of the object:
    + * In the block where the resurrection occurs, let your {@link #__del__()}- or + * {@link FinalizableBuiltin#__del_builtin__()}-method call
    + * {@code FinalizeTrigger.ensureFinalizer(this);}. If you implement {@code __del__} in Python and + * need this functionality, you can simply call {@code someObject.__ensure_finalizer__()}
    + * Note that this is Jython-specific and should be surrounded by a {@code try/except}-block to + * ensure compatibility with other Python implementations.
  15. *
- *

*

- * Note: Regarding to object resurrection, Jython currently behaves like CPython >= 3.4. - * That means the finalizer {@link #__del__()} or {@link FinalizableBuiltin#__del_builtin__()} - * is called only the first time an object gets gc'ed. If pre-3.4.-behavior is required for - * some reason (i.e. have the finalizer called repeatedly on every collection after a - * resurrection), one can achieve this manually via step 5). - *

+ * Note: Regarding to object resurrection, Jython currently behaves like CPython ≥ 3.4. That means + * the finalizer {@link #__del__()} or {@link FinalizableBuiltin#__del_builtin__()} is called only + * the first time an object gets gc'ed. If pre-3.4.-behavior is required for some reason (i.e. have + * the finalizer called repeatedly on every collection after a resurrection), one can achieve this + * manually via step 5). *

- * The built-in function {@code __ensure_finalizer__} is also useful if a class acquires a - * finalizer after instances have already been created. Usually only those instances that were - * created after their class acquired the finalizer will actually be finalized (in contrast to - * CPython). - * However, one can manually tell earlier created instances to become finalizable by - * calling {@code __ensure_finalizer__()} on them. As mentioned above, it is recommended to - * surround this with a {@code try/except}-block to ensure compatibility with other Python - * implementations. - *

+ * The built-in function {@code __ensure_finalizer__} is also useful if a class acquires a finalizer + * after instances have already been created. Usually only those instances that were created after + * their class acquired the finalizer will actually be finalized (in contrast to CPython). However, + * one can manually tell earlier created instances to become finalizable by calling + * {@code __ensure_finalizer__()} on them. As mentioned above, it is recommended to surround this + * with a {@code try/except}-block to ensure compatibility with other Python implementations. *

- * Note that it is not possible to override {@code __ensure_finalizer__} on Python side. - * If one overrides {@code __ensure_finalizer__} on Python side, Jython will ignore the + * Note that it is not possible to override {@code __ensure_finalizer__} on Python side. If one + * overrides {@code __ensure_finalizer__} on Python side, Jython will ignore the * override-implementation and still call the original one. - *

*

- * It is possible to switch finalization on and off at any desired time for a certain object. - * This can be helpful if it is only necessary to have {@link #__del__()} or + * It is possible to switch finalization on and off at any desired time for a certain object. This + * can be helpful if it is only necessary to have {@link #__del__()} or * {@link FinalizableBuiltin#__del_builtin__()} called for certain configurations of an object. - *

*

- * To turn off the finalizer, call
- * {@code ((FinalizeTrigger) JyAttribute.getAttr(this, JyAttribute.FINALIZE_TRIGGER_ATTR)).clear();}
- * To turn it on again, call
- * {@code ((FinalizeTrigger) JyAttribute.getAttr(this, JyAttribute.FINALIZE_TRIGGER_ATTR)).trigger(this);} - *

- * + * To turn off the finalizer, call:
{@literal
+ * ((FinalizeTrigger) JyAttribute.getAttr(this, JyAttribute.FINALIZE_TRIGGER_ATTR)).clear();
+ * }
To turn it on again, call
{@literal
+ * ((FinalizeTrigger) JyAttribute.getAttr(this, JyAttribute.FINALIZE_TRIGGER_ATTR)).trigger(this);
+ * }
+ * * @see org.python.core.JyAttribute#FINALIZE_TRIGGER_ATTR * @see FinalizableBuiltin#__del_builtin__() */ diff --git a/src/org/python/core/imp.java b/src/org/python/core/imp.java --- a/src/org/python/core/imp.java +++ b/src/org/python/core/imp.java @@ -229,7 +229,7 @@ * @param sourceName used for identification in messages and the constructor of the named class. * @param compiledName used for identification in messages and {@code __file__}. * @return the module or {@code null} on failure (if {@code testing}). - * @throws PyException (ImportError) on API mismatch or i/o error. + * @throws PyException {@code ImportError} on API mismatch or i/o error. */ static PyObject createFromPyClass(String name, InputStream fp, boolean testing, String sourceName, String compiledName) { @@ -247,7 +247,7 @@ * @param compiledName used for identification in messages and {@code __file__}. * @param sourceLastModified time expected to match {@code MTime} annotation in the class file * @return the module or {@code null} on failure (if {@code testing}). - * @throws PyException (ImportError) on API or last-modified time mismatch or i/o error. + * @throws PyException {@code ImportError} on API or last-modified time mismatch or i/o error. */ static PyObject createFromPyClass(String name, InputStream fp, boolean testing, String sourceName, String compiledName, long sourceLastModified) { @@ -272,7 +272,7 @@ * @param sourceLastModified time expected to match {@code MTime} annotation in the class file * @param source choose what to use as the file name when initialising the class * @return the module or {@code null} on failure (if {@code testing}). - * @throws PyException (ImportError) on API or last-modified time mismatch or i/o error. + * @throws PyException {@code ImportError} on API or last-modified time mismatch or i/o error. */ static PyObject createFromPyClass(String name, InputStream fp, boolean testing, String sourceName, String compiledName, long sourceLastModified, CodeImport source) { @@ -319,7 +319,7 @@ * @param fp stream from which to read class file (closed when read) * @param testing if {@code true}, failures are signalled by a {@code null} not an exception * @return the class file bytes as an array or {@code null} on failure (if {@code testing}). - * @throws PyException (ImportError) on API or last-modified time mismatch + * @throws PyException {@code ImportError} on API or last-modified time mismatch * @throws IOException from read failures */ public static byte[] readCode(String name, InputStream fp, boolean testing) throws IOException { @@ -335,7 +335,7 @@ * @param testing if {@code true}, failures are signalled by a {@code null} not an exception * @param sourceLastModified time expected to match {@code MTime} annotation in the class file * @return the class file bytes as an array or {@code null} on failure (if {@code testing}). - * @throws PyException (ImportError) on API or last-modified time mismatch + * @throws PyException {@code ImportError} on API or last-modified time mismatch * @throws IOException from read failures */ public static byte[] readCode(String name, InputStream fp, boolean testing, @@ -356,7 +356,7 @@ * @param fp stream from which to read class file (closed when read) * @param testing if {@code true}, failures are signalled by a {@code null} not an exception * @return the {@code CodeData} bundle or {@code null} on failure (if {@code testing}). - * @throws PyException (ImportError) on API mismatch + * @throws PyException {@code ImportError} on API mismatch * @throws IOException from read failures */ public static CodeData readCodeData(String name, InputStream fp, boolean testing) @@ -376,7 +376,7 @@ * @param testing if {@code true}, failures are signalled by a {@code null} not an exception * @param sourceLastModified time expected to match {@code MTime} annotation in the class file * @return the {@code CodeData} bundle or {@code null} on failure (if {@code testing}). - * @throws PyException (ImportError) on API or last-modified time mismatch + * @throws PyException {@code ImportError} on API or last-modified time mismatch * @throws IOException from read failures */ public static CodeData readCodeData(String name, InputStream fp, boolean testing, @@ -1181,7 +1181,7 @@ * @param name fully-qualified name of module to import {@code import a.b.c.m} * @param parentName used as a workspace as the search descends the package hierarchy * @return the named module (never {@code null} or {@code None}) - * @throws PyException (ImportError) if not found + * @throws PyException {@code ImportError} if not found */ private static PyObject import_first(String name, StringBuilder parentName) throws PyException { PyObject ret = import_next(null, parentName, name, null, null); @@ -1199,7 +1199,7 @@ * @param fullName the "outer" name by which the module is known {@code a.b.c.m}. * @param fromlist names to import from the module {@code n1, n2, n3}. * @return the named module (never returns {@code null} or {@code None}) - * @throws PyException (ImportError) if not found + * @throws PyException {@code ImportError} if not found */ private static PyObject import_first(String name, StringBuilder parentName, String fullName, PyObject fromlist) throws PyException { @@ -1239,7 +1239,7 @@ * @param fullName {@code a.b.c.m} * @param fromlist names to import from the module {@code n1, n2, n3}. * @return the last named module (never {@code null} or {@code None}) - * @throws PyException (ImportError) if not found + * @throws PyException {@code ImportError} if not found */ // ??pending: check if result is really a module/jpkg/jclass? private static PyObject import_logic(PyObject mod, StringBuilder parentName, String restOfName, diff --git a/src/org/python/core/io/IOBase.java b/src/org/python/core/io/IOBase.java --- a/src/org/python/core/io/IOBase.java +++ b/src/org/python/core/io/IOBase.java @@ -44,16 +44,31 @@ } /** - * Seek to byte offset pos relative to position indicated by whence: 0 Start of stream (the - * default). pos should be >= 0; 1 Current position - whence may be negative; 2 End of stream - - * whence usually negative. - * + * Seek to byte offset {@code pos} relative to position indicated by {@code whence}. + *
Values returned
NONENo error
+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Semantics
{@code whence}Seek to{@code pos}
0Start of stream (the default).Should be ≥0.
1Current position + {@code pos} Either sign.
2End of stream + {@code pos} Usually ≤0.
* Returns the new absolute position. * - * @param pos - * a long position value - * @param whence - * an int whence value + * @param pos a long position value + * @param whence an int whence value * @return a long position value seeked to */ public long seek(long pos, int whence) { diff --git a/src/org/python/core/stringlib/FloatFormatter.java b/src/org/python/core/stringlib/FloatFormatter.java --- a/src/org/python/core/stringlib/FloatFormatter.java +++ b/src/org/python/core/stringlib/FloatFormatter.java @@ -30,7 +30,7 @@ private int lenMarker; /** The length of the exponent sign and digits or zero if there isn't one. */ private int lenExponent; - /** if >=0, minimum digits to follow decimal point (where consulted) */ + /** if ≥0, minimum digits to follow decimal point (where consulted) */ private int minFracDigits; /** @@ -85,7 +85,7 @@ * formats remove trailing zero digits, trimming to zero or one. Set member * minFracDigits, to modify this behaviour. * - * @param minFracDigits if <0 prevent truncation; if >=0 the minimum number of fractional + * @param minFracDigits if <0 prevent truncation; if ≥0 the minimum number of fractional * digits; when this is zero, and all fractional digits are zero, the decimal point * will also be removed. */ @@ -436,6 +436,7 @@ * these recommended values: * * + * * * * diff --git a/src/org/python/core/stringlib/InternalFormat.java b/src/org/python/core/stringlib/InternalFormat.java --- a/src/org/python/core/stringlib/InternalFormat.java +++ b/src/org/python/core/stringlib/InternalFormat.java @@ -316,6 +316,7 @@ * When the padding method has decided that that it needs to add n padding characters, it * will affect {@link #start} or {@link #lenWhole} as follows. *
Recommended values for formatting arguments
typeprecision
+ * * * * @@ -324,28 +325,28 @@ * * * - * + * * * * * * * - * + * * * * * * * - * + * * * * * * * - * + * * * * @@ -655,7 +656,7 @@ * * A typical idiom is: * - *
+     * 
{@literal
      *     private static final InternalFormatSpec FLOAT_DEFAULTS = InternalFormatSpec.from(">");
      *     ...
      *         InternalFormat.Spec spec = InternalFormat.fromText(specString);
@@ -663,17 +664,13 @@
      *         ... // Validation of spec.type, and other attributes, for this type.
      *         FloatFormatter f = new FloatFormatter(spec);
      *         String result = f.format(value).getResult();
-     *
-     * 
+ * }
*/ public static class Spec { /** The fill character specified, or U+FFFF if unspecified. */ public final char fill; - /** - * Alignment indicator is one of {'<', '^', '>', '=', or U+FFFF if - * unspecified. - */ + /** Alignment indicator is one of {'<', '^', '>', '=', or U+FFFF if unspecified. */ public final char align; /** * Sign-handling flag, one of '+', '-', or ' ', or @@ -710,7 +707,7 @@ * Test to see if an attribute has been specified. * * @param value of attribute - * @return true only if the attribute is >=0 (meaning that it has been specified). + * @return true only if the attribute is ≥0 (meaning that it has been specified). */ public static final boolean specified(int value) { return value >= 0; @@ -724,7 +721,7 @@ * * * @param fill fill character (or {@link #NONE} - * @param align alignment indicator, one of {'<', '^', '>', '=' + * @param align alignment indicator, one of {'<', '^', '>', '='} * @param sign policy, one of '+', '-', or ' '. * @param alternate true to request alternate formatting mode ('#' flag). * @param width of field after padding or -1 to default @@ -785,8 +782,8 @@ * defaults may also be unspecified.) The use of this method is to allow a Spec * constructed from text to record exactly, and only, what was in the textual specification, * while the __format__ method of a client object supplies its type-specific defaults. Thus - * "20" means "<20s" to a str, ">20.12" to a float and ">20.12g" - * to a complex. + * "20" means "<20s" to a str, ">20.12" to a float and + * ">20.12g" to a complex. * * @param other defaults to merge where this object does not specify the attribute. * @return a new Spec object. @@ -804,15 +801,11 @@ ); } - /** - * Defaults applicable to most numeric types. Equivalent to " >" - */ + /** Defaults applicable to most numeric types. Equivalent to " >" */ public static final Spec NUMERIC = new Spec(' ', '>', Spec.NONE, false, Spec.UNSPECIFIED, false, Spec.UNSPECIFIED, Spec.NONE); - /** - * Defaults applicable to string types. Equivalent to " <" - */ + /** Defaults applicable to string types. Equivalent to " <" */ public static final Spec STRING = new Spec(' ', '<', Spec.NONE, false, Spec.UNSPECIFIED, false, Spec.UNSPECIFIED, Spec.NONE); diff --git a/src/org/python/core/util/ByteSwapper.java b/src/org/python/core/util/ByteSwapper.java --- a/src/org/python/core/util/ByteSwapper.java +++ b/src/org/python/core/util/ByteSwapper.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -28,9 +28,9 @@ *
  • float
  • *
  • double
  • * - *

    + * * Note this functionality is provided in the base types since 1.5. - * + * * @author Andrew Howard */ public class ByteSwapper { @@ -38,7 +38,7 @@ /** * Reverses the byte order of all elements in the supplied array, converting * between little and big endian byte order. - * + * * @param array the input array for type sensitive byte swapping. */ public static void swap(Object array) { @@ -68,7 +68,7 @@ /** * Byte order reverses an Array of doubles - * + * * @param array input array */ private static void swapDoubleArray(Object array) { @@ -99,7 +99,7 @@ /** * Byte order reverses an Array of floats - * + * * @param array input array */ private static void swapFloatArray(Object array) { @@ -125,7 +125,7 @@ /** * Byte order reverses an Array of ints - * + * * @param array input array */ private static void swapIntegerArray(Object array) { @@ -148,7 +148,7 @@ /** * Byte order reverses an Array of longs - * + * * @param array input array */ private static void swapLongArray(Object array) { @@ -176,7 +176,7 @@ /** * Byte order reverses an Array of shorts - * + * * @param array input array */ private static void swapShortArray(Object array) { diff --git a/src/org/python/core/util/ExtraMath.java b/src/org/python/core/util/ExtraMath.java --- a/src/org/python/core/util/ExtraMath.java +++ b/src/org/python/core/util/ExtraMath.java @@ -43,13 +43,14 @@ *

    * For sufficiently small x*10n, the rounding is to zero, and the return value * is a signed zero (same sign as x). Suppose x = a*2b, where the significand - * we must have a<2. Sufficiently small means such that n log210 < + * we must have a<2. Sufficiently small means such that n log210 < * -(b+2). *

    * For sufficiently large x*10n, the adjustment of rounding is too small to * affect the least significant bit. That is a*2b represents an amount greater * than one, and rounding no longer affects the value, and the return is x. Since the matissa - * has 52 fractional bits, sufficiently large means such that n log210 > 52-b. + * has 52 fractional bits, sufficiently large means such that n log210 > + * 52-b. * * @param x to round * @param n decimal places diff --git a/src/org/python/core/util/FileUtil.java b/src/org/python/core/util/FileUtil.java --- a/src/org/python/core/util/FileUtil.java +++ b/src/org/python/core/util/FileUtil.java @@ -72,7 +72,7 @@ } /** - * Read all bytes from the input stream.

    Note that using this method to + * Read all bytes from the input stream.

    Note that using this method to * read very large streams could cause out-of-memory exceptions and/or block * for large periods of time. */ diff --git a/src/org/python/core/util/StringUtil.java b/src/org/python/core/util/StringUtil.java --- a/src/org/python/core/util/StringUtil.java +++ b/src/org/python/core/util/StringUtil.java @@ -95,7 +95,8 @@ } /** - * Decapitalize a String if it begins with a capital letter, e.g.: FooBar -> fooBar + * Decapitalize a String if it begins with a capital letter, e.g.: + * {@code decapitalize("FooBar") == "fooBar"} * * @param string a String * @return a decapitalized String diff --git a/src/org/python/modules/_bytecodetools.java b/src/org/python/modules/_bytecodetools.java --- a/src/org/python/modules/_bytecodetools.java +++ b/src/org/python/modules/_bytecodetools.java @@ -6,7 +6,7 @@ /** * BytecodeTools provides tools for generated JVM bytecode. - *

    + *

    * This module supports registering a python callback function * to be notified when new bytecode is loaded. * see also core/BytecodeNotification.java diff --git a/src/org/python/modules/_io/OpenMode.java b/src/org/python/modules/_io/OpenMode.java --- a/src/org/python/modules/_io/OpenMode.java +++ b/src/org/python/modules/_io/OpenMode.java @@ -120,10 +120,10 @@ *

    * The invalid combinations enforced here are those for the "raw" (ie non-text) file types: *

      - *
    • universal & (writing | appending)),
    • - *
    • text & binary
    • , - *
    • reading & writing,
    • - *
    • appending & (reading | writing)
    • + *
    • {@code universal & (writing | appending)},
    • + *
    • {@code text & binary},
    • + *
    • {@code reading & writing},
    • + *
    • {@code appending & (reading | writing)}
    • *
    * See also {@link #validate(String, String, String)} for additional checks relevant to text * files. @@ -191,7 +191,7 @@ * by either {@link #invalid} or {@link #other} being true after that call. If no * more specific message has been assigned in {@link #message}, report the original mode string. * - * @throws PyException (ValueError) if the mode string was invalid. + * @throws PyException {@code ValueError} if the mode string was invalid. */ public void checkValid() throws PyException { diff --git a/src/org/python/modules/_io/PyIOBase.java b/src/org/python/modules/_io/PyIOBase.java --- a/src/org/python/modules/_io/PyIOBase.java +++ b/src/org/python/modules/_io/PyIOBase.java @@ -244,7 +244,7 @@ * Is the stream capable of positioning the read/write pointer? * * @return True if may be positioned - * @throws PyException(ValueError) if the object is closed to client operations + * @throws PyException {@code ValueError} if the object is closed to client operations */ public boolean seekable() throws PyException { return _IOBase_seekable(); @@ -260,8 +260,8 @@ * positioned. * * @param msg optional custom message - * @throws PyException(ValueError) if the object is closed to client operations - * @throws PyException(IOError) if the stream is not capable of being positioned. + * @throws PyException {@code ValueError} if the object is closed to client operations + * @throws PyException {@code IOError} if the stream is not capable of being positioned. */ public void _checkSeekable(String msg) { _IOBase__checkSeekable(msg); @@ -271,8 +271,8 @@ * Raise an error if the pointer of underlying IO stream is not capable of being * positioned. * - * @throws PyException(ValueError) if the object is closed to client operations - * @throws PyException(IOError) if the stream is not capable of being positioned. + * @throws PyException {@code ValueError} if the object is closed to client operations + * @throws PyException {@code IOError} if the stream is not capable of being positioned. */ public final void _checkSeekable() { _checkSeekable(null); @@ -289,7 +289,7 @@ * Is the stream readable? * * @return true if readable - * @throws PyException(ValueError) if the object is closed to client operations + * @throws PyException {@code ValueError} if the object is closed to client operations */ public boolean readable() throws PyException { return _IOBase_readable(); @@ -304,8 +304,8 @@ * Raise an error if the underlying IO stream is not readable. * * @param msg optional custom message - * @throws PyException(ValueError) if the object is closed to client operations - * @throws PyException(IOError) if the stream is not readable. + * @throws PyException {@code ValueError} if the object is closed to client operations + * @throws PyException {@code IOError} if the stream is not readable. */ public void _checkReadable(String msg) { _IOBase__checkReadable(msg); @@ -314,8 +314,8 @@ /** * Raise an error if the underlying IO stream is not readable. * - * @throws PyException(ValueError) if the object is closed to client operations - * @throws PyException(IOError) if the stream is not readable. + * @throws PyException {@code ValueError} if the object is closed to client operations + * @throws PyException {@code IOError} if the stream is not readable. */ public final void _checkReadable() { _checkReadable(null); @@ -332,7 +332,7 @@ * Is the stream writable? * * @return true if writable - * @throws PyException(ValueError) if the object is closed to client operations + * @throws PyException {@code ValueError} if the object is closed to client operations */ public boolean writable() throws PyException { return _IOBase_writable(); @@ -347,8 +347,8 @@ * Raise an error if the underlying IO stream is not writable. * * @param msg optional custom message - * @throws PyException(ValueError) if the object is closed to client operations - * @throws PyException(IOError) if the stream is not writable. + * @throws PyException {@code ValueError} if the object is closed to client operations + * @throws PyException {@code IOError} if the stream is not writable. */ public void _checkWritable(String msg) throws PyException { _IOBase__checkWritable(msg); @@ -357,8 +357,8 @@ /** * Raise an error if the underlying IO stream is not writable. * - * @throws PyException(ValueError) if the object is closed to client operations - * @throws PyException(IOError) if the stream is not writable. + * @throws PyException {@code ValueError} if the object is closed to client operations + * @throws PyException {@code IOError} if the stream is not writable. */ public final void _checkWritable() throws PyException { _checkWritable(null); @@ -385,7 +385,7 @@ * {@link #_checkSeekable}, etc.. * * @param msg optional custom message - * @throws PyException(ValueError) if the object is closed to client operations + * @throws PyException {@code ValueError} if the object is closed to client operations */ public void _checkClosed(String msg) throws PyException { _IOBase__checkClosed(msg); @@ -471,7 +471,7 @@ * Return one line of text (bytes terminates by '\n'), or the specified number of * bytes, or the whole stream, whichever is shortest. * - * @param limit maximum number of bytes (<0 means no limit) + * @param limit maximum number of bytes (<0 means no limit) * @return the line (or fragment) */ public PyObject readline(int limit) { @@ -648,9 +648,9 @@ * May be called repeatedly to produce (usually) lines from this stream or file. * * @return next line from the stream or file - * @throws PyException(StopIteration) when iteration has reached a natural conclusion - * @throws PyException(ValueError) if the file or stream is closed - * @throws PyException(IOError) reflecting an I/O error in during the read + * @throws PyException {@code StopIteration} when iteration has reached a natural conclusion + * @throws PyException {@code ValueError} if the file or stream is closed + * @throws PyException {@code IOError} reflecting an I/O error in during the read */ public PyObject next() throws PyException { return _IOBase_next(); @@ -746,8 +746,9 @@ * * @param obj to be wrapped and presented as a buffer * @return a 1D contiguous PyBuffer of bytes - * @throws PyException (BufferError) if object has buffer API, but is not 1D contiguous bytes - * @throws PyException (TypeError) if object not convertible to a byte array + * @throws PyException {@code BufferError} if object has buffer API, but is not 1D contiguous + * bytes + * @throws PyException {@code TypeError} if object not convertible to a byte array */ protected static PyBuffer readablePyBuffer(PyObject obj) throws PyException { @@ -781,8 +782,9 @@ * * @param obj to be wrapped and presented as a buffer * @return a 1D contiguous PyBuffer of bytes - * @throws PyException (BufferError) if object has buffer API, but is not 1D contiguous bytes - * @throws PyException (TypeError) if object not convertible to a byte array + * @throws PyException {@code BufferError} if object has buffer API, but is not 1D contiguous + * bytes + * @throws PyException {@code TypeError} if object not convertible to a byte array */ protected static PyBuffer writablePyBuffer(PyObject obj) throws PyException { try { diff --git a/src/org/python/modules/binascii.java b/src/org/python/modules/binascii.java --- a/src/org/python/modules/binascii.java +++ b/src/org/python/modules/binascii.java @@ -29,56 +29,52 @@ * The binascii.java module contains a number of methods to convert * between binary and various ASCII-encoded binary * representations. Normally, you will not use these modules directly but - * use wrapper modules like uu or - * hexbin instead, this module solely - * exists because bit-manipuation of large amounts of data is slow in + * use wrapper modules like uu or + * hexbin instead, this module solely + * exists because bit-manipulation of large amounts of data is slow in * Python. * *

    * The binascii.java module defines the following functions: - *

    - *

    a2b_uu (string) + * + *
    + *
    a2b_uu (string)
    *
    * Convert a single line of uuencoded data back to binary and return the * binary data. Lines normally contain 45 (binary) bytes, except for the * last line. Line data may be followed by whitespace. - *
    + * * - *

    - *

    b2a_uu (data) + *
    b2a_uu (data)
    *
    * Convert binary data to a line of ASCII characters, the return value * is the converted line, including a newline char. The length of * data should be at most 45. - *
    + * * - *

    - *

    a2b_base64 (string) + *
    a2b_base64 (string)
    *
    * Convert a block of base64 data back to binary and return the * binary data. More than one line may be passed at a time. - *
    + * * - *

    - *

    b2a_base64 (data) + *
    b2a_base64 (data)
    *
    * Convert binary data to a line of ASCII characters in base64 coding. * The return value is the converted line, including a newline char. * The length of data should be at most 57 to adhere to the base64 * standard. - *
    + * * - *

    - *

    a2b_hqx (string) + *
    a2b_hqx (string)
    *
    * Convert binhex4 formatted ASCII data to binary, without doing * RLE-decompression. The string should contain a complete number of * binary bytes, or (in case of the last portion of the binhex4 data) * have the remaining bits zero. - *
    + * * - *

    - *

    rledecode_hqx (data) + *
    rledecode_hqx (data)
    *
    * Perform RLE-decompression on the data, as per the binhex4 * standard. The algorithm uses 0x90 after a byte as a repeat @@ -86,46 +82,43 @@ * value of 0x90. The routine returns the decompressed data, * unless data input data ends in an orphaned repeat indicator, in which * case the Incomplete exception is raised. - *
    + * * - *

    - *

    rlecode_hqx (data) + *
    rlecode_hqx (data)
    *
    * Perform binhex4 style RLE-compression on data and return the * result. - *
    + * * - *

    - *

    b2a_hqx (data) + *
    b2a_hqx (data)
    *
    * Perform hexbin4 binary-to-ASCII translation and return the * resulting string. The argument should already be RLE-coded, and have a * length divisible by 3 (except possibly the last fragment). - *
    + * * - *

    - *

    crc_hqx (data, crc) + *
    crc_hqx (data, crc)
    *
    * Compute the binhex4 crc value of data, starting with an initial * crc and returning the result. - *
    + * * - *
    Error + *
    Error
    *
    * Exception raised on errors. These are usually programming errors. - *
    + * * - *

    - *

    Incomplete + *
    Incomplete
    *
    * Exception raised on incomplete data. These are usually not programming * errors, but may be handled by reading a little more data and trying * again. + *
    *
    * * The module is a line-by-line conversion of the original binasciimodule.c * written by Jack Jansen, except that all mistakes and errors are my own. - *

    + * * @author Finn Bock, bckfnn at pipmail.dknet.dk * @version binascii.java,v 1.6 1999/02/20 11:37:07 fb Exp @@ -284,8 +277,9 @@ StringBuilder bin_data = new StringBuilder(); try (PyBuffer ascii_data = getTextBuffer(bp)) { - if (ascii_data.getLen() == 0) + if (ascii_data.getLen() == 0) { return new PyString(""); + } char this_ch; int i; @@ -334,8 +328,9 @@ } // finally, if we haven't decoded enough stuff, fill it up with zeros - for (; i < bin_len; i++) + for (; i < bin_len; i++) { bin_data.append((char) 0); + } return new PyString(bin_data.toString()); @@ -374,10 +369,11 @@ for (int i = 0; bin_len > 0 || leftbits != 0; i++, bin_len--) { // Shift the data (or padding) into our buffer - if (bin_len > 0) // Data + if (bin_len > 0) { leftchar = (leftchar << 8) | (char) bin_data.intAt(i); - else // Padding + } else { leftchar <<= 8; + } leftbits += 8; // See if there are 6-bit groups ready @@ -409,8 +405,9 @@ int c = b.intAt(offset); short b64val = table_a2b_base64[c & 0x7f]; if (((c <= 0x7f) && (b64val != -1)) ) { - if (num == 0) - ret = c; + if (num == 0) { + ret = c; + } num--; } @@ -445,14 +442,15 @@ for (int i = 0; ascii_len > 0; ascii_len--, i++) { // Skip some punctuation this_ch = (char) ascii_data.intAt(i); - if (this_ch > 0x7F || this_ch == '\r' || this_ch == '\n' || this_ch == ' ') + if (this_ch > 0x7F || this_ch == '\r' || this_ch == '\n' || this_ch == ' ') { continue; + } if (this_ch == BASE64_PAD) { if (quad_pos < 2 || (quad_pos == 2 - && binascii_find_valid(ascii_data, i, 1) != BASE64_PAD)) + && binascii_find_valid(ascii_data, i, 1) != BASE64_PAD)) { continue; - else { + } else { // A pad sequence means no more input. // We've already interpreted the data // from the quad at this point. @@ -462,8 +460,9 @@ } short this_v = table_a2b_base64[this_ch]; - if (this_v == -1) + if (this_v == -1) { continue; + } // Shift it in on the low end, and see if there's // a byte ready for output. @@ -566,8 +565,9 @@ for (int i = 0; len > 0; len--, i++) { // Get the byte and look it up this_ch = (char) table_a2b_hqx[ascii_data.intAt(i)]; - if (this_ch == SKIP) + if (this_ch == SKIP) { continue; + } if (this_ch == FAIL) { throw new PyException(Error, "Illegal char"); } @@ -624,8 +624,9 @@ int inend; for (inend=in+1; inend < len && (char) in_data.intAt(inend) == ch && - inend < in+255; inend++) + inend < in+255; inend++) { ; + } if (inend - in > 3) { // More than 3 in a row. Output RLE. out_data.append(ch); @@ -711,17 +712,22 @@ StringBuilder out_data = new StringBuilder(); try { // Empty string is a special case - if (in_len == 0) + if (in_len == 0) { return Py.EmptyString; + } // Handle first byte separately (since we have to get angry // in case of an orphaned RLE code). - if (--in_len < 0) throw new PyException(Incomplete); + if (--in_len < 0) { + throw new PyException(Incomplete); + } in_byte = (char) in_data.intAt(i++); if (in_byte == RUNCHAR) { - if (--in_len < 0) throw new PyException(Incomplete); + if (--in_len < 0) { + throw new PyException(Incomplete); + } in_repeat = (char) in_data.intAt(i++); if (in_repeat != 0) { @@ -735,11 +741,15 @@ } while (in_len > 0) { - if (--in_len < 0) throw new PyException(Incomplete); + if (--in_len < 0) { + throw new PyException(Incomplete); + } in_byte = (char) in_data.intAt(i++); if (in_byte == RUNCHAR) { - if (--in_len < 0) throw new PyException(Incomplete); + if (--in_len < 0) { + throw new PyException(Incomplete); + } in_repeat = (char) in_data.intAt(i++); if (in_repeat == 0) { @@ -748,8 +758,9 @@ } else { // Pick up value and output a sequence of it in_byte = out_data.charAt(out_data.length()-1); - while (--in_repeat > 0) + while (--in_repeat > 0) { out_data.append(in_byte); + } } } else { // Normal byte @@ -868,10 +879,11 @@ } finally { bin_data.release(); } - if (crc >= 0x80000000) + if (crc >= 0x80000000) { return -(int)(crc+1 & 0xFFFFFFFF); - else + } else { return (int)(crc & 0xFFFFFFFF); + } } @@ -927,14 +939,16 @@ * XXX What should we do about strings with an odd length? Should we add an implicit * leading zero, or a trailing zero? For now, raise an exception. */ - if (arglen % 2 != 0) + if (arglen % 2 != 0) { throw Py.TypeError("Odd-length string"); + } for (int i = 0; i < arglen; i += 2) { int top = Character.digit(argbuf.intAt(i), 16); int bot = Character.digit(argbuf.intAt(i + 1), 16); - if (top == -1 || bot == -1) + if (top == -1 || bot == -1) { throw Py.TypeError("Non-hexadecimal digit found"); + } retbuf.append((char) ((top << 4) + bot)); } @@ -968,8 +982,9 @@ try { val = ap.getInt(index, dflt) != 0; } catch (PyException e) { - if (e.match(Py.AttributeError) || e.match(Py.ValueError)) - throw Py.TypeError(errMsg); + if (e.match(Py.AttributeError) || e.match(Py.ValueError)) { + throw Py.TypeError(errMsg); + } throw e; } return val; @@ -1027,7 +1042,7 @@ final private static Pattern RN_TO_N = Pattern.compile("\r\n"); final private static Pattern N_TO_RN = Pattern.compile("(? s;\n" + "Encode a string using quoted-printable encoding.\n\n" + "On encoding, when istext is set, newlines are not encoded, and white\n" @@ -1146,7 +1161,7 @@ * it is byte-like, the bytes are used unchanged, assumed in the "intended" character set. It * may be a {@code PyUnicode}, in which case the it will be decoded to bytes using the default * encoding ({@code sys.getdefaultencoding()}. - * + * * @param text an object with the buffer protocol * @return a byte-buffer view of the ASCII text * @throws ClassCastException where the text object does not implement the buffer protocol diff --git a/src/org/python/modules/cPickle.java b/src/org/python/modules/cPickle.java --- a/src/org/python/modules/cPickle.java +++ b/src/org/python/modules/cPickle.java @@ -1,3 +1,4 @@ +// Copyright (c)2019 Jython Developers /* * Copyright 1998 Finn Bock. * @@ -5,6 +6,7 @@ * Copyright (c) 1991-1995 by Stichting Mathematisch Centrum, Amsterdam, * The Netherlands. */ +// Licensed to the PSF under a Contributor Agreement /* note about impl: instanceof vs. CPython type(.) is . @@ -289,10 +291,8 @@ *

    * Apart from the Pickler and Unpickler classes, the * module defines the following functions, and an exception: - * - *

    - *

    dump (object, file[, - * bin]) + *
    + *
    dump (object, file[, bin])
    *
    * Write a pickled representation of obect to the open file object * file. This is equivalent to @@ -300,41 +300,35 @@ * If the optional bin argument is present and nonzero, the binary * pickle format is used; if it is zero or absent, the (less efficient) * text pickle format is used. - *
    + * * - *

    - *

    load (file) + *
    load (file)
    *
    * Read a pickled object from the open file object file. This is * equivalent to "Unpickler(file).load()". - *
    + * * - *

    - *

    dumps (object[, - * bin]) + *
    dumps (object[, bin])
    *
    * Return the pickled representation of the object as a string, instead * of writing it to a file. If the optional bin argument is * present and nonzero, the binary pickle format is used; if it is zero * or absent, the (less efficient) text pickle format is used. - *
    + * * - *

    - *

    loads (string) + *
    loads (string)
    *
    * Read a pickled object from a string instead of a file. Characters in * the string past the pickled object's representation are ignored. - *
    + * * - *

    - *

    PicklingError + *
    PicklingError
    *
    * This exception is raised when an unpicklable object is passed to * Pickler.dump(). + *
    *
    * - * - *

    * For the complete documentation on the pickle module, please see the * "Python Library Reference" *


    @@ -781,10 +775,11 @@ PyType t = object.getType(); if (t == TupleType && object.__len__() == 0) { - if (protocol > 0) + if (protocol > 0) { save_empty_tuple(object); - else + } else { save_tuple(object); + } return; } @@ -794,8 +789,9 @@ return; } - if (save_type(object, t)) + if (save_type(object, t)) { return; + } if (!pers_save && inst_persistent_id != null && save_pers(object, inst_persistent_id)) { return; @@ -814,8 +810,9 @@ tup = reduce.__call__(Py.newInteger(protocol)); } else { reduce = object.__findattr__("__reduce__"); - if (reduce == null) + if (reduce == null) { throw new PyException(UnpickleableError, object); + } tup = reduce.__call__(); } } else { @@ -883,9 +880,10 @@ if(protocol >= 2 && callableName != null && "__newobj__".equals(callableName.toString())) { PyObject cls = arg_tup.__finditem__(0); - if(cls.__findattr__("__new__") == null) + if(cls.__findattr__("__new__") == null) { throw new PyException(PicklingError, "args[0] from __newobj__ args has no __new__"); + } // TODO: check class save(cls); save(arg_tup.__getslice__(Py.One, Py.None)); @@ -915,40 +913,41 @@ final private boolean save_type(PyObject object, PyType type) { //System.out.println("save_type " + object + " " + cls); - if (type == NoneType) + if (type == NoneType) { save_none(object); - else if (type == StringType) + } else if (type == StringType) { save_string(object); - else if (type == UnicodeType) + } else if (type == UnicodeType) { save_unicode(object); - else if (type == IntType) + } else if (type == IntType) { save_int(object); - else if (type == LongType) + } else if (type == LongType) { save_long(object); - else if (type == FloatType) + } else if (type == FloatType) { save_float(object); - else if (type == TupleType) + } else if (type == TupleType) { save_tuple(object); - else if (type == ListType) + } else if (type == ListType) { save_list(object); - else if (type == DictionaryType || type == StringMapType) + } else if (type == DictionaryType || type == StringMapType) { save_dict(object); - else if (type == InstanceType) + } else if (type == InstanceType) { save_inst((PyInstance)object); - else if (type == ClassType) + } else if (type == ClassType) { save_global(object); - else if (type == TypeType) + } else if (type == TypeType) { + save_global(object); + } else if (type == FunctionType) { save_global(object); - else if (type == FunctionType) + } else if (type == BuiltinCallableType) { save_global(object); - else if (type == BuiltinCallableType) + } else if (type == ReflectedFunctionType) { save_global(object); - else if (type == ReflectedFunctionType) - save_global(object); - else if (type == BoolType) + } else if (type == BoolType) { save_bool(object); - else + } else { return false; + } return true; } @@ -1113,12 +1112,14 @@ int len = object.__len__(); if (len > 0 && len <= 3 && protocol >= 2) { - for (int i = 0; i < len; i++) + for (int i = 0; i < len; i++) { save(object.__finditem__(i)); + } int m = getMemoPosition(d, object); if (m >= 0) { - for (int i = 0; i < len; i++) + for (int i = 0; i < len; i++) { file.write(POP); + } get(m); } else { @@ -1131,8 +1132,9 @@ file.write(MARK); - for (int i = 0; i < len; i++) + for (int i = 0; i < len; i++) { save(object.__finditem__(i)); + } if (len > 0) { int m = getMemoPosition(d, object); @@ -1142,8 +1144,9 @@ get(m); return; } - for (int i = 0; i < len+1; i++) + for (int i = 0; i < len+1; i++) { file.write(POP); + } get(m); return; } @@ -1158,9 +1161,9 @@ } private void save_list(PyObject object) { - if (protocol > 0) + if (protocol > 0) { file.write(EMPTY_LIST); - else { + } else { file.write(MARK); file.write(LIST); } @@ -1188,15 +1191,16 @@ } } } - if (countInBatch > 0) + if (countInBatch > 0) { file.write(APPENDS); + } } private void save_dict(PyObject object) { - if (protocol > 0) + if (protocol > 0) { file.write(EMPTY_DICT); - else { + } else { file.write(MARK); file.write(DICT); } @@ -1264,13 +1268,15 @@ } file.write(MARK); - if (protocol > 0) + if (protocol > 0) { save(cls); + } if (args != null) { int len = args.__len__(); - for (int i = 0; i < len; i++) + for (int i = 0; i < len; i++) { save(args.__finditem__(i)); + } } int mid = putMemo(get_id(object), object); @@ -1305,12 +1311,14 @@ final private void save_global(PyObject object, PyObject name) { - if (name == null) + if (name == null) { name = object.__findattr__("__name__"); + } PyObject module = object.__findattr__("__module__"); - if (module == null || module == Py.None) + if (module == null || module == Py.None) { module = whichmodule(object, name); + } if(protocol >= 2) { PyTuple extKey = new PyTuple(module, name); @@ -1380,8 +1388,9 @@ PyObject clsname) { PyObject name = classmap.get(cls); - if (name != null) + if (name != null) { return name; + } name = new PyString("__main__"); @@ -1465,21 +1474,27 @@ if (tkey == key && value == values[index]) { return index; } - if (values[index] == null) return -1; + if (values[index] == null) { + return -1; + } index = (index+stepsize) % maxindex; } } public int findPosition(int key, Object value) { int idx = findIndex(key, value); - if (idx < 0) return -1; + if (idx < 0) { + return -1; + } return position[idx]; } public Object findValue(int key, Object value) { int idx = findIndex(key, value); - if (idx < 0) return null; + if (idx < 0) { + return null; + } return values[idx]; } @@ -1514,7 +1529,9 @@ private final void resize(int capacity) { int p = prime; for(; p= capacity) break; + if (primes[p] >= capacity) { + break; + } } if (primes[p] < capacity) { throw Py.ValueError("can't make hashtable of size: " + @@ -1538,14 +1555,18 @@ for(int i=0; i keys.length) resize(keys.length+1); + if (2*filled > keys.length) { + resize(keys.length+1); + } insertkey(key, pos, value); } } @@ -1603,8 +1624,9 @@ // System.out.println("load:" + s); // for (int i = 0; i < stackTop; i++) // System.out.println(" " + stack[i]); - if (s.length() < 1) + if (s.length() < 1) { load_eof(); + } char key = s.charAt(0); switch (key) { case PERSID: load_persid(); break; @@ -1670,9 +1692,11 @@ final private int marker() { - for (int k = stackTop-1; k >= 0; k--) - if (stack[k] == mark) + for (int k = stackTop-1; k >= 0; k--) { + if (stack[k] == mark) { return stackTop-k-1; + } + } throw new PyException(UnpicklingError, "Inputstream corrupt, marker not found"); } @@ -1684,8 +1708,9 @@ private void load_proto() { int proto = file.read(1).charAt(0); - if (proto < 0 || proto > 2) + if (proto < 0 || proto > 2) { throw Py.ValueError("unsupported pickle protocol: " + proto); + } } @@ -1807,12 +1832,13 @@ } private int read_binint(int length) { - if (length == 1) + if (length == 1) { return file.read(1).charAt(0); - else if (length == 2) + } else if (length == 2) { return read_binint2(); - else + } else { return read_binint(); + } } final private void load_float() { @@ -1838,8 +1864,9 @@ String value; char quote = line.charAt(0); - if (quote != '"' && quote != '\'') + if (quote != '"' && quote != '\'') { throw Py.ValueError("insecure string pickle"); + } int nslash = 0; int i; @@ -1847,19 +1874,23 @@ int n = line.length(); for (i = 1; i < n; i++) { ch = line.charAt(i); - if (ch == quote && nslash % 2 == 0) + if (ch == quote && nslash % 2 == 0) { break; - if (ch == '\\') + } + if (ch == '\\') { nslash++; - else + } else { nslash = 0; + } } - if (ch != quote) + if (ch != quote) { throw Py.ValueError("insecure string pickle"); + } for (i++ ; i < line.length(); i++) { - if (line.charAt(i) > ' ') + if (line.charAt(i) > ' ') { throw Py.ValueError("insecure string pickle " + i); + } } value = PyString.decode_UnicodeEscape(line, 1, n-1, "strict", false); @@ -1988,9 +2019,10 @@ final private PyObject find_class(String module, String name) { if (find_global != null) { - if (find_global == Py.None) - throw new PyException(UnpicklingError, + if (find_global == Py.None) { + throw new PyException(UnpicklingError, "Global and instance pickles are not supported."); + } return find_global.__call__(new PyString(module), new PyString(name)); } @@ -2049,8 +2081,9 @@ int n = seq.__len__(); PyObject[] objs= new PyObject[n]; - for(int i=0; iarg was NaN or result was not * NaN - * @throws PyException (ValueError) if result was NaN and + * @throws PyException {@code ValueError} if result was NaN and * arg was not NaN */ private static PyComplex exceptNaN(PyComplex result, PyComplex arg) throws PyException { diff --git a/src/org/python/modules/gc.java b/src/org/python/modules/gc.java --- a/src/org/python/modules/gc.java +++ b/src/org/python/modules/gc.java @@ -15,6 +15,7 @@ import org.python.core.JyAttribute; import org.python.core.Py; +import org.python.core.PyException; import org.python.core.PyList; import org.python.core.PyObject; import org.python.core.PyInstance; @@ -35,140 +36,121 @@ //import javax.management.openmbean.*; /** - *

    - * In Jython, the gc module notably differs from that in CPython. - * This comes from the different ways Jython and CPython perform - * garbage collection. While CPython's garbage collection is based on - * - * reference counting, Jython is backed by Java's gc, which is - * based on a - * - * mark-and-sweep approach. - *

    + * In Jython, the gc module notably differs from that in CPython. This comes from the different ways + * Jython and CPython perform garbage collection. While CPython's garbage collection is based on + * reference + * counting, Jython is backed by Java's gc, which is based on a + * mark-and-sweep + * approach. *

    - * This difference becomes most notable if finalizers are involved that perform resurrection. - * While the resurrected object itself behaves rather similar between Jython and CPython, - * things are more delicate with objects that are reachable (i.e. strongly referenced) - * via the resurrected object exclusively. - * While in CPython such objects do not get their finalizers called, Jython/Java would - * call all their finalizers. That is because Java detects the whole unreachable subgraph - * as garbage and thus calls all their finalizers without any chance of direct intervention. - * CPython instead detects the unreachable object and calls its finalizer, which makes the - * object reachable again. Then all other objects are reachable from it and CPython does not - * treat them as garbage and does not call their finalizers at all. - * This further means that in Jython weak references to such indirectly resurrected objects - * break, while these persist in CPython. - *

    + * This difference becomes most notable if finalizers are involved that perform resurrection. While + * the resurrected object itself behaves rather similar between Jython and CPython, things are more + * delicate with objects that are reachable (i.e. strongly referenced) via the resurrected object + * exclusively. While in CPython such objects do not get their finalizers called, Jython/Java would + * call all their finalizers. That is because Java detects the whole unreachable subgraph as garbage + * and thus calls all their finalizers without any chance of direct intervention. CPython instead + * detects the unreachable object and calls its finalizer, which makes the object reachable again. + * Then all other objects are reachable from it and CPython does not treat them as garbage and does + * not call their finalizers at all. This further means that in Jython weak references to such + * indirectly resurrected objects break, while these persist in CPython. + *

    + * As of Jython 2.7, the gc module offers some options to emulate CPython behavior. Especially see + * the flags {@link #PRESERVE_WEAKREFS_ON_RESURRECTION}, {@link #DONT_FINALIZE_RESURRECTED_OBJECTS} + * and {@link #DONT_FINALIZE_CYCLIC_GARBAGE} for this. *

    - * As of Jython 2.7, the gc module offers some options to emulate CPython behavior. - * Especially see the flags {@link #PRESERVE_WEAKREFS_ON_RESURRECTION}, - * {@link #DONT_FINALIZE_RESURRECTED_OBJECTS} and {@link #DONT_FINALIZE_CYCLIC_GARBAGE} - * for this. - *

    + * Another difference is that CPython's gc module offers some debug features like counting of + * collected cyclic trash, which are hard to support by Jython. As of Jython 2.7 the introduction of + * a traverseproc mechanism (c.f. {@link org.python.core.Traverseproc}) made support of these + * features feasible. As support of these features comes with a significant emulation cost, one must + * explicitly tell gc to perform this. To make objects subject to cyclic trash counting, these + * objects must be gc-monitored in Jython. See {@link #monitorObject(PyObject)}, + * {@link #unmonitorObject(PyObject)}, {@link #MONITOR_GLOBAL} and {@link #stopMonitoring()} for + * this. *

    - * Another difference is that CPython's gc module offers some debug features like counting - * of collected cyclic trash, which are hard to support by Jython. As of Jython 2.7 the - * introduction of a traverseproc mechanism (c.f. {@link org.python.core.Traverseproc}) - * made support of these features feasible. As support of these features comes - * with a significant emulation cost, one must explicitly tell gc to perform this. - * To make objects subject to cyclic trash counting, these objects must be gc-monitored in - * Jython. See {@link #monitorObject(PyObject)}, {@link #unmonitorObject(PyObject)}, - * {@link #MONITOR_GLOBAL} and {@link #stopMonitoring()} for this.
    - * If at least one object is gc-monitored, {@link #collect()} works synchronously in the - * sense that it blocks until all gc-monitored objects that are garbage actually have been - * collected and had their finalizers called and completed. {@link #collect()} will report - * the number of collected objects in the same manner as in CPython, i.e. counts only those - * that participate in reference cycles. This allows a unified test implementation across - * Jython and CPython (which applies to most tests in test_gc.py). If not any object is - * gc-monitored, {@link #collect()} just delegates to {@link java.lang.System#gc()}, runs - * asynchronously (i.e. non-blocking) and returns {@link #UNKNOWN_COUNT}. - * See also {@link #DEBUG_SAVEALL} for a useful gc debugging feature that is supported by - * Jython from version 2.7 onwards. - *

    + * If at least one object is gc-monitored, {@link #collect()} works synchronously in the sense that + * it blocks until all gc-monitored objects that are garbage actually have been collected and had + * their finalizers called and completed. {@link #collect()} will report the number of collected + * objects in the same manner as in CPython, i.e. counts only those that participate in reference + * cycles. This allows a unified test implementation across Jython and CPython (which applies to + * most tests in test_gc.py). If not any object is gc-monitored, {@link #collect()} just delegates + * to {@link java.lang.System#gc()}, runs asynchronously (i.e. non-blocking) and returns + * {@link #UNKNOWN_COUNT}. See also {@link #DEBUG_SAVEALL} for a useful gc debugging feature that is + * supported by Jython from version 2.7 onwards. *

    - * Implementing all these features in Jython involved a lot of synchronization logic. - * While care was taken to implement this without using timeouts as far as possible and - * rely on locks, states and system/hardware independent synchronization techniques, - * this was not entirely feasible.
    - * The aspects that were only feasible using a timeout are waiting for gc to enqueue all - * collected objects (i.e. weak references to monitored objects that were gc'ed) to the - * reference queue and waiting for gc to run all PyObject finalizers. - *

    + * Implementing all these features in Jython involved a lot of synchronization logic. While care was + * taken to implement this without using timeouts as far as possible and rely on locks, states and + * system/hardware independent synchronization techniques, this was not entirely feasible.
    + * The aspects that were only feasible using a timeout are waiting for gc to enqueue all collected + * objects (i.e. weak references to monitored objects that were gc'ed) to the reference queue and + * waiting for gc to run all PyObject finalizers. *

    * Waiting for trash could in theory be strictly synchronized by using {@code MXBean}s, i.e. - * GarbageCollectionNotificationInfo and related API. - * However, experiments showed that the arising gc notifications do not reliably indicate - * when enqueuing was done for a specific gc run. We kept the experimental implementation - * in source code comments to allow easy reproducibility of this issue. (Note that out commented - * code contradicts Jython styleguide, but this one - however - is needed to document this - * infeasible approach and is explicitly declared accordingly).
    - * But how is sync done now? - * We insert a sentinel before running gc and wait until this sentinel was collected. - * Timestamps are taken to give us an idea at which time scales the gc of the current JVM - * performs. We then wait until twice the measured time (i.e. duration from call to - * {@link java.lang.System#gc()} until the sentinel reference was enqueued) has passed after - * the last reference was enqueued by gc. While this approach is not entirely safe in theory, - * it passes all tests on various systems and machines we had available for testing so far. - * We consider it more robust than a fixed-length timeout and regard it the best known feasible - * compromise to emulate synchronous gc runs in Java. - *

    + * GarbageCollectionNotificationInfo and related API. However, experiments + * showed that the arising gc notifications do not reliably indicate when enqueuing was done for a + * specific gc run. We kept the experimental implementation in source code comments to allow easy + * reproducibility of this issue. (Note that out commented code contradicts Jython styleguide, but + * this one - however - is needed to document this infeasible approach and is explicitly declared + * accordingly). + *

    + * But how is sync done now? We insert a sentinel before running gc and wait until this + * sentinel was collected. Timestamps are taken to give us an idea at which time scales the gc of + * the current JVM performs. We then wait until twice the measured time (i.e. duration from call to + * {@link java.lang.System#gc()} until the sentinel reference was enqueued) has passed after the + * last reference was enqueued by gc. While this approach is not entirely safe in theory, it passes + * all tests on various systems and machines we had available for testing so far. We consider it + * more robust than a fixed-length timeout and regard it the best known feasible compromise to + * emulate synchronous gc runs in Java. *

    * The other timing-based synchronization issue - waiting for finalizers to run - is solved as * follows. Since PyObject finalizers are based on - * {@link org.python.core.finalization.FinalizeTrigger}s, Jython has full control about - * these finalization process from a central point. Before such a finalizer runs, it calls - * {@link #notifyPreFinalization()} and when it is done, it calls - * {@link #notifyPostFinalization()}. While processing of a finalizer can be of arbitrary - * duration, it widely holds that Java's gc thread calls the next finalizer almost - * instantaneously after the former. That means that a timestamp taken in - * {@link #notifyPreFinalization()} is usually delayed only few milliseconds - * - often even reported as 0 milliseconds - after the last taken timestamp in - * {@link #notifyPostFinalization()} (i.e. that was called by the previous finalizer). - * Jython's gc module assumes the end of Java's finalization process if - * {@link #postFinalizationTimeOut} milliseconds passed after a call of - * {@link #notifyPostFinalization()} without another call to + * {@link org.python.core.finalization.FinalizeTrigger}s, Jython has full control about these + * finalization process from a central point. Before such a finalizer runs, it calls + * {@link #notifyPreFinalization()} and when it is done, it calls {@link #notifyPostFinalization()}. + * While processing of a finalizer can be of arbitrary duration, it widely holds that Java's gc + * thread calls the next finalizer almost instantaneously after the former. That means that a + * timestamp taken in {@link #notifyPreFinalization()} is usually delayed only few milliseconds - + * often even reported as 0 milliseconds - after the last taken timestamp in + * {@link #notifyPostFinalization()} (i.e. that was called by the previous finalizer). Jython's gc + * module assumes the end of Java's finalization process if {@link #postFinalizationTimeOut} + * milliseconds passed after a call of {@link #notifyPostFinalization()} without another call to * {@link #notifyPreFinalization()} in that time. The default value of - * {@link #postFinalizationTimeOut} is {@code 100}, which is far larger than the - * usual almost-zero duration between finalizer calls.
    - * This process can be disturbed by third-party finalizers of non-PyObjects brought - * into the process by external libraries. If these finalizers are of short duration - * (which applies to typical finalizers), one can deal with this by adjusting - * {@link #postFinalizationTimeOut}, which was declared {@code public} for exactly this - * purpose. However if the external framework causing the issue is Jython aware, a - * cleaner solution would be to let its finalizers call {@link #notifyPreFinalization()} - * and {@link #notifyPostFinalization()} appropriately. In that case these finalizers - * must not terminate by throwing an exception before {@link #notifyPostFinalization()} - * was called. This is a strict requirement, since a deadlock can be caused otherwise.
    - *
    - * Note that the management API - * (c.f. - * com.sun.management.GarbageCollectionNotificationInfo) does not emit any - * notifications that allow to detect the end of the finalization phase. So this API - * provides no alternative to the described technique. - *

    + * notifications that allow to detect the end of the finalization phase. So this API provides no + * alternative to the described technique. *

    - * Usually Java's gc provides hardly any guarantee about its collection and finalization - * process. It not even guarantees that finalizers are called at all (c.f. - * http://howtodoinjava.com/2012/10/31/why-not-to-use-finalize-method-in-java). - * While at least the most common JVM implementations usually do call finalizers - * reliably under normal conditions, there still is no specific finalization order guaranteed - * (one might reasonably expect that this would be related to reference connection graph - * topology, but this appears not to be the case). - * However Jython now offers some functionality to compensate this - * situation. Via {@link #registerPreFinalizationProcess(Runnable)} and - * {@link #registerPostFinalizationProcess(Runnable)} and related methods one can now - * listen to beginning and end of the finalization process. Note that this functionality - * relies on the technique described in the former paragraph (i.e. based on calls to - * {@link #notifyPreFinalization()} and {@link #notifyPostFinalization()}) and thus - * underlies its unsafety, if third-party finalizers are involved. Such finalizers can - * cause false-positive runs of registered (pre/post) finalization processes, so this - * feature should be used with some care. It is recommended to use it only in such a way - * that false-positive runs would not cause serious harm, but only some loss in - * performance or so. - *

    + * Usually Java's gc provides hardly any guarantee about its collection and finalization process. It + * not even guarantees that finalizers are called at all (c.f. + * http://howtodoinjava.com/2012/10/31/why-not-to-use-finalize-method-in-java). While + * at least the most common JVM implementations usually do call finalizers reliably under + * normal conditions, there still is no specific finalization order guaranteed (one might reasonably + * expect that this would be related to reference connection graph topology, but this appears not to + * be the case). However Jython now offers some functionality to compensate this situation. Via + * {@link #registerPreFinalizationProcess(Runnable)} and + * {@link #registerPostFinalizationProcess(Runnable)} and related methods one can now listen to + * beginning and end of the finalization process. Note that this functionality relies on the + * technique described in the former paragraph (i.e. based on calls to + * {@link #notifyPreFinalization()} and {@link #notifyPostFinalization()}) and thus underlies its + * unsafety, if third-party finalizers are involved. Such finalizers can cause false-positive runs + * of registered (pre/post) finalization processes, so this feature should be used with some care. + * It is recommended to use it only in such a way that false-positive runs would not cause serious + * harm, but only some loss in performance or so. */ public class gc { /** @@ -195,7 +177,7 @@ /** * CPython prior to 3.4 does not finalize cyclic garbage * PyObjects, while Jython does this by default. This flag - * tells Jython's gc to mimic CPython <3.4 behavior (i.e. + * tells Jython's gc to mimic CPython <3.4 behavior (i.e. * add such objects to {@code gc.garbage} list instead). * * @see #setJythonGCFlags(short) @@ -253,7 +235,7 @@ /** *

    - * Reflection-based traversion is an inefficient fallback method to + * Reflection-based traversal is an inefficient fallback method to * traverse PyObject subtypes that don't implement * {@link org.python.core.Traverseproc} and * are not marked as {@link org.python.core.Untraversable}. @@ -262,19 +244,19 @@ * compensate this. *

    *

    - * This flag allows to inhibit reflection-based traversion. If it is + * This flag allows to inhibit reflection-based traversal. If it is * activated, objects that don't implement * {@link org.python.core.Traverseproc} * are always treated as if they were marked as * {@link org.python.core.Untraversable}. *

    *

    - * Note that reflection-based traversion fallback is performed by + * Note that reflection-based traversal fallback is performed by * default. Further note that Jython emits warning messages if - * reflection-based traversion occurs or if an object is encountered + * reflection-based traversal occurs or if an object is encountered * that neither implements {@link org.python.core.Traverseproc} * nor is marked as {@link org.python.core.Untraversable} (even if - * reflection-based traversion is inhibited). See + * reflection-based traversal is inhibited). See * {@link #SUPPRESS_TRAVERSE_BY_REFLECTION_WARNING} and * {@link #INSTANCE_TRAVERSE_BY_REFLECTION_WARNING} to control * these warning messages. @@ -292,9 +274,9 @@ /** *

    * If this flag is not set, gc warns whenever an object would be subject to - * reflection-based traversion. + * reflection-based traversal. * Note that if this flag is not set, the warning will occur even if - * reflection-based traversion is not active. The purpose of this behavior is + * reflection-based traversal is not active. The purpose of this behavior is * to identify objects that don't properly support the traverseproc mechanism, * i.e. instances of PyObject subclasses that neither implement * {@link org.python.core.Traverseproc}, @@ -304,7 +286,7 @@ * A SUPPRESS flag was chosen rather than a WARN flag, so that warning is the * default behavior - the user must actively set this flag in order to not to * be warned. - * This is because in an ideal implementation reflection-based traversion never + * This is because in an ideal implementation reflection-based traversal never * occurs; it is only an inefficient fallback. *

    * @@ -317,9 +299,9 @@ public static final short SUPPRESS_TRAVERSE_BY_REFLECTION_WARNING = (1<<7); /** - * Makes gc emit reflection-based traversion warning for every traversed + * Makes gc emit reflection-based traversal warning for every traversed * object instead of only once per class. - * A potential reflection-based traversion occurs whenever an object is + * A potential reflection-based traversal occurs whenever an object is * traversed that neither implements {@link org.python.core.Traverseproc}, * nor is annotated with the {@link org.python.core.Untraversable} annotation. * @@ -1618,7 +1600,7 @@ * {@link #PRESERVE_WEAKREFS_ON_RESURRECTION} - Keeps weak references alive if the referent is resurrected.
    * {@link #DONT_FINALIZE_RESURRECTED_OBJECTS} - * Emulates CPython behavior regarding resurrected objects and finalization.
    - * {@link #DONT_TRAVERSE_BY_REFLECTION} - Inhibits reflection-based traversion.
    + * {@link #DONT_TRAVERSE_BY_REFLECTION} - Inhibits reflection-based traversal.
    * {@link #SUPPRESS_TRAVERSE_BY_REFLECTION_WARNING} - * Suppress warnings for PyObjects that neither implement {@link org.python.core.Traverseproc} nor * are marked as {@link org.python.core.Untraversable}.
    @@ -1736,9 +1718,8 @@ /** * Not supported by Jython. - * Throws {@link org.python.core.Py#NotImplementedError}. * - * @throws org.python.core.Py.NotImplementedError + * @throws PyException {@code NotImplementedError} */ public static void disable() { throw Py.NotImplementedError("can't disable Java GC"); @@ -2401,9 +2382,8 @@ /** * Not supported by Jython. - * Throws {@link org.python.core.Py#NotImplementedError}. * - * @throws org.python.core.Py.NotImplementedError + * @throws PyException {@code NotImplementedError} */ public static PyObject get_count() { throw Py.NotImplementedError("not applicable to Java GC"); @@ -2448,9 +2428,8 @@ /** * Not supported by Jython. - * Throws {@link org.python.core.Py#NotImplementedError}. * - * @throws org.python.core.Py.NotImplementedError + * @throws PyException {@code NotImplementedError} */ public static void set_threshold(PyObject[] args, String[] kwargs) { throw Py.NotImplementedError("not applicable to Java GC"); @@ -2458,9 +2437,8 @@ /** * Not supported by Jython. - * Throws {@link org.python.core.Py#NotImplementedError}. * - * @throws org.python.core.Py.NotImplementedError + * @throws PyException {@code NotImplementedError} */ public static PyObject get_threshold() { throw Py.NotImplementedError("not applicable to Java GC"); @@ -2470,10 +2448,9 @@ * Only works reliably if {@code monitorGlobal} is active, as it depends on * monitored objects to search for referrers. It only finds referrers that * properly implement the traverseproc mechanism (unless reflection-based - * traversion is activated and works stable). - * Throws {@link org.python.core.Py#NotImplementedError}. + * traversal is activated and works stable). * - * @throws org.python.core.Py.NotImplementedError + * @throws PyException {@code NotImplementedError} */ public static PyObject get_objects() { if (!isMonitoring()) { @@ -2497,7 +2474,7 @@ * Only works reliably if {@code monitorGlobal} is active, as it depends on * monitored objects to search for referrers. It only finds referrers that * properly implement the traverseproc mechanism (unless reflection-based - * traversion is activated and works stable). + * traversal is activated and works stable). * Further note that the resulting list will contain referrers in no specific * order and may even include duplicates. */ @@ -2537,7 +2514,7 @@ /** * Only works reliably if all objects in args properly - * implement the Traverseproc mechanism (unless reflection-based traversion + * implement the Traverseproc mechanism (unless reflection-based traversal * is activated and works stable). * Further note that the resulting list will contain referents in no * specific order and may even include duplicates. @@ -2874,7 +2851,7 @@ * {@link org.python.core.TraverseprocDerived#traverseDerived(Visitproc, Object)}. * If {@code ob} neither implements {@link org.python.core.Traverseproc} nor * {@link org.python.core.Traverseproc} and is not annotated with - * {@link org.python.core.Untraversable}, reflection-based traversion via + * {@link org.python.core.Untraversable}, reflection-based traversal via * {@link #traverseByReflection(Object, Visitproc, Object)} may be attempted * according to {@link #DONT_TRAVERSE_BY_REFLECTION}. * diff --git a/src/org/python/modules/math.java b/src/org/python/modules/math.java --- a/src/org/python/modules/math.java +++ b/src/org/python/modules/math.java @@ -544,7 +544,7 @@ * @param arg to include in check * @return result if arg was NaN or result was not * NaN - * @throws PyException (ValueError) if result was NaN and + * @throws PyException {@code ValueError} if result was NaN and * arg was not NaN */ private static double exceptNaN(double result, double arg) throws PyException { @@ -570,8 +570,8 @@ * @param result to return (if we return) * @param arg to include in check * @return result if arg was infinite or result was not infinite - * @throws PyException (ValueError) if result was infinite and arg was - * not infinite + * @throws PyException {@code ValueError} if result was infinite and + * arg was not infinite */ private static double exceptInf(double result, double arg) { if (Double.isInfinite(result) && !Double.isInfinite(arg)) { diff --git a/src/org/python/modules/struct.java b/src/org/python/modules/struct.java --- a/src/org/python/modules/struct.java +++ b/src/org/python/modules/struct.java @@ -31,89 +31,81 @@ * *

    * The module defines the following exception and functions: - * - *

    - *

    error + *
    + *
    error
    *
    * Exception raised on various occasions; argument is a string * describing what is wrong. - *
    - * - *

    - *

    pack (fmt, v1, v2, ...) + * + *
    pack (fmt, v1, v2, ...)
    *
    * Return a string containing the values * v1, v2, ... packed according to the given * format. The arguments must match the values required by the format * exactly. - *
    - * - *

    - *

    unpack> (fmt, string) + * + *
    unpack (fmt, string)
    *
    * Unpack the string (presumably packed by pack(fmt, * ...)) according to the given format. The result is a * tuple even if it contains exactly one item. The string must contain * exactly the amount of data required by the format (i.e. * len(string) must equal calcsize(fmt)). - *
    - * - *

    - *

    calcsize (fmt) + * + *
    calcsize (fmt)
    *
    * Return the size of the struct (and hence of the string) * corresponding to the given format. *
    * - *

    * Format characters have the following meaning; the conversion between * C and Python values should be obvious given their types: - * - *

    - *

    Effect of padding on {@link #start} or {@link #lenWhole}
    alignmeaningresult.length()
    <{@code <}left-aligned+0+0+n
    >{@code >}right-aligned+n+0+n
    ^{@code ^}centred+(n/2)+0+n
    ={@code =}pad after sign+0+n
    + + *
    + * * * * - * + * * * - * + * * * - * + * * * - * + * * * - * + * * * - * + * * * - * + * * * - * + * * * - * + * * * - * + * * * - * + * * * - * + * * * - * + * * * - * + * * * *
    Format characters
    FormatC TypePython
    x
    {@code x}pad byteno value
    c
    {@code c}charstring of length 1
    b
    {@code b}signed charinteger
    B
    {@code B}unsigned charinteger
    h
    {@code h}shortinteger
    H
    {@code H}unsigned shortinteger
    i
    {@code i}intinteger
    I
    {@code I}unsigned intinteger
    size
    {@code size}longinteger
    L
    {@code L}unsigned longinteger
    f
    {@code f}floatfloat
    d
    {@code d}doublefloat
    s
    {@code s}char[]string
    p
    {@code p}char[]string
    @@ -161,24 +153,24 @@ * according to the following table: * *

    - * - * + *
    + * * * * - * + * * * - * + * * * - * + * * * - * + * * * - * + * * * * @@ -222,19 +214,16 @@ * *

    * Examples (all using native byte order, size and alignment, on a - * big-endian machine): - * - *

    - *

    - * >>> from struct import *
    - * >>> pack('hhl', 1, 2, 3)
    + * big-endian machine): 
    {@literal
    + * >>> from struct import *
    + * >>> pack('hhl', 1, 2, 3)
      * '\000\001\000\002\000\000\000\003'
    - * >>> unpack('hhl', '\000\001\000\002\000\000\000\003')
    + * >>> unpack('hhl', '\000\001\000\002\000\000\000\003')
      * (1, 2, 3)
    - * >>> calcsize('hhl')
    + * >>> calcsize('hhl')
      * 8
    - * >>>
    - * 
    + * >>> + * } * *

    * Hint: to align the end of a structure to the alignment requirement of diff --git a/src/org/python/util/InteractiveConsole.java b/src/org/python/util/InteractiveConsole.java --- a/src/org/python/util/InteractiveConsole.java +++ b/src/org/python/util/InteractiveConsole.java @@ -101,13 +101,14 @@ } /** - * Returns the banner to print before the first interaction: "Jython on ". + * Returns the banner to print before the first interaction: + * "{@code Jython on }". * * @return the banner. */ public static String getDefaultBanner() { - return String - .format("Jython %s on %s", PySystemState.version, Py.getSystemState().platform); + return String.format("Jython %s on %s", PySystemState.version, + Py.getSystemState().platform); } /** diff --git a/src/org/python/util/InteractiveInterpreter.java b/src/org/python/util/InteractiveInterpreter.java --- a/src/org/python/util/InteractiveInterpreter.java +++ b/src/org/python/util/InteractiveInterpreter.java @@ -41,7 +41,7 @@ /** * Compile and run some source in the interpreter, in the mode {@link CompileMode#single} which - * is used for incremental compilation at the interactive console, known as "". + * is used for incremental compilation at the interactive console, known as {@code }. * * @param source Python code * @return true to indicate a partial statement was entered @@ -65,31 +65,30 @@ /** * Compile and run some source in the interpreter, according to the {@link CompileMode} given. * This method supports incremental compilation and interpretation through the return value, - * where true signifies that more input is expected in order to complete the Python - * statement. An interpreter can use this to decide whether to use sys.ps1 (" - * >>> ") or sys.ps2 ("... ") to prompt the next line. - * The arguments are the same as the mandatory ones in the Python compile() - * command. + * where {@code true} signifies that more input is expected in order to complete the Python + * statement. An interpreter can use this to decide whether to use {@code sys.ps1} + * ("{@code >>> }") or {@code sys.ps2} ("{@code ... }") to prompt the next line. The arguments + * are the same as the mandatory ones in the Python {@code compile()} command. *

    * One the following can happen: *

      *
    1. The input is incorrect; compilation raised an exception (SyntaxError or OverflowError). A * syntax traceback will be printed by calling {@link #showexception(PyException)}. Return is - * false.
    2. + * {@code false}. * *
    3. The input is incomplete, and more input is required; compilation returned no code. - * Nothing happens. Return is true.
    4. + * Nothing happens. Return is {@code true}. * *
    5. The input is complete; compilation returned a code object. The code is executed by * calling {@link #runcode(PyObject)} (which also handles run-time exceptions, except for - * SystemExit). Return is false.
    6. + * SystemExit). Return is {@code false}. *
    * * @param source Python code * @param filename name with which to label this console input (e.g. in error messages). * @param kind of compilation required: {@link CompileMode#eval}, {@link CompileMode#exec} or * {@link CompileMode#single} - * @return true to indicate a partial statement was provided + * @return {@code true} to indicate a partial statement was provided */ public boolean runsource(String source, String filename, CompileMode kind) { PyObject code; diff --git a/src/org/python/util/PyServlet.java b/src/org/python/util/PyServlet.java --- a/src/org/python/util/PyServlet.java +++ b/src/org/python/util/PyServlet.java @@ -27,8 +27,8 @@ * This servlet is used to re-serve Jython servlets. It stores bytecode for Jython servlets and * re-uses it if the underlying .py file has not changed. *

    - * e.g. http://localhost:8080/test/hello.py - *

    + * e.g. {@code http://localhost:8080/test/hello.py}
    + * 
    {@literal
      *
      * from javax.servlet.http import HttpServlet
      * class hello(HttpServlet):
    @@ -41,26 +41,25 @@
      *         print >>out, ""
      *         print >>out, ""
      *         out.close()
    - * 
    + * }
    * * in web.xml for the PyServlet context: - *
    - * <web-app>
    - *     <servlet>
    - *         <servlet-name>PyServlet</servlet-name>
    - *         <servlet-class>org.python.util.PyServlet</servlet-class>
    - *         <init-param>
    - *             <param-name>python.home</param-name>
    - *             <param-value>/usr/home/jython-2.5</param-value>
    - *         </init-param>
    - *     </servlet>
    - *     <servlet-mapping>
    - *         <servlet-name>PyServlet</servlet-name>
    - *         <url-pattern>*.py</url-pattern>
    - *     </servlet-mapping>
    - * </web-app>
    - *
    - * 
    + *
    {@literal
    + * 
    + *     
    + *         PyServlet
    + *         org.python.util.PyServlet
    + *         
    + *             python.home
    + *             /usr/home/jython-2.5
    + *         
    + *     
    + *     
    + *         PyServlet
    + *         *.py
    + *     
    + * 
    + * }
    */ public class PyServlet extends HttpServlet { diff --git a/src/org/python/util/PythonInterpreter.java b/src/org/python/util/PythonInterpreter.java --- a/src/org/python/util/PythonInterpreter.java +++ b/src/org/python/util/PythonInterpreter.java @@ -158,6 +158,7 @@ * stream is used in a byte-oriented way (mostly) that depends on the type of file-like object. * The behaviour as implemented is: *
    Byte order and alignment characters
    CharacterByte orderSize and alignment
    @
    {@code @}nativenative
    =
    {@code =}nativestandard
    <
    {@code <}little-endianstandard
    >
    {@code >}big-endianstandard
    !
    {@code !}network (= big-endian)standard
    + * * * * -- Repository URL: https://hg.python.org/jython From jython-checkins at python.org Sun Sep 22 16:37:15 2019 From: jython-checkins at python.org (jeff.allen) Date: Sun, 22 Sep 2019 20:37:15 +0000 Subject: [Jython-checkins] =?utf-8?q?jython=3A_Update_JARs_for_JFFI_=281?= =?utf-8?b?LjIuMjApIGFuZCBBU00gNy4xLg==?= Message-ID: <20190922203715.1.26EAC92715D36E89@mg.python.org> https://hg.python.org/jython/rev/dd91eabd8988 changeset: 8298:dd91eabd8988 user: Jeff Allen date: Sat Sep 21 20:26:42 2019 +0100 summary: Update JARs for JFFI (1.2.20) and ASM 7.1. Attempted update of JUnit to 4.12 caused a failure in complation of tests (missing hamcrest classes), so pinning for now to 4.10. files: build.gradle | 9 +++++---- build.xml | 19 ++++++++++--------- extlibs/asm-7.0.jar | Bin extlibs/asm-7.1.jar | Bin extlibs/asm-commons-7.0.jar | Bin extlibs/asm-commons-7.1.jar | Bin extlibs/asm-util-7.0.jar | Bin extlibs/asm-util-7.1.jar | Bin extlibs/jffi-1.2.19.jar | Bin extlibs/jffi-1.2.20.jar | Bin 10 files changed, 15 insertions(+), 13 deletions(-) diff --git a/build.gradle b/build.gradle --- a/build.gradle +++ b/build.gradle @@ -162,9 +162,9 @@ implementation 'org.bouncycastle:bcpkix-jdk15on:1.62' implementation 'org.bouncycastle:bcprov-jdk15on:1.62' - implementation 'org.ow2.asm:asm:7.0' - implementation 'org.ow2.asm:asm-commons:7.0' - implementation 'org.ow2.asm:asm-util:7.0' + implementation 'org.ow2.asm:asm:7.1' + implementation 'org.ow2.asm:asm-commons:7.1' + implementation 'org.ow2.asm:asm-util:7.1' // The Android Guava and "failureaccess" are necessary to support Java 7. implementation 'com.google.guava:guava:28.0-android' @@ -175,7 +175,7 @@ implementation 'com.carrotsearch:java-sizeof:0.0.5' - implementation 'com.github.jnr:jffi:1.2.19' + implementation 'com.github.jnr:jffi:1.2.20' implementation 'com.github.jnr:jnr-netdb:1.1.6' implementation 'com.github.jnr:jnr-ffi:2.1.10' implementation 'com.github.jnr:jnr-posix:3.0.50' @@ -193,6 +193,7 @@ // Used implicitly in the Ant build, must be explicit here implementation 'org.apache.ant:ant:1.9.7' + // Pin to 4.10 until dependency on hamcrest classes resolved. testImplementation 'junit:junit:4.10' } diff --git a/build.xml b/build.xml --- a/build.xml +++ b/build.xml @@ -246,14 +246,14 @@ - - - + + + - + @@ -272,6 +272,7 @@ + @@ -824,15 +825,15 @@ - - - + + + - + @@ -876,7 +877,7 @@ - + diff --git a/extlibs/asm-7.0.jar b/extlibs/asm-7.0.jar deleted file mode 100644 index 2cf38f46167192e6d65c4906c77cd7e3dce5598d..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 GIT binary patch [stripped] diff --git a/extlibs/asm-7.1.jar b/extlibs/asm-7.1.jar new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..355eb08db9df7112a17def5a2a6efa6ae2b9c975 GIT binary patch [stripped] diff --git a/extlibs/asm-commons-7.0.jar b/extlibs/asm-commons-7.0.jar deleted file mode 100644 index ba0de6cd49dc34cb2ea5423b1a16f1122a44bdca..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 GIT binary patch [stripped] diff --git a/extlibs/asm-commons-7.1.jar b/extlibs/asm-commons-7.1.jar new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..31ffb987d5ee19917f7895a04b75cb1784a81567 GIT binary patch [stripped] diff --git a/extlibs/asm-util-7.0.jar b/extlibs/asm-util-7.0.jar deleted file mode 100644 index 47717e5d18f9b3a6df1300c9872541b3c895d2bc..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 GIT binary patch [stripped] diff --git a/extlibs/asm-util-7.1.jar b/extlibs/asm-util-7.1.jar new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..5e61f2c10465a1a6c32f5a325dcd9ea017173bba GIT binary patch [stripped] diff --git a/extlibs/jffi-1.2.19.jar b/extlibs/jffi-1.2.19.jar deleted file mode 100644 index b92013e1ca14f2785a9a44a41190d905c0d5d1fc..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 GIT binary patch [stripped] diff --git a/extlibs/jffi-1.2.20.jar b/extlibs/jffi-1.2.20.jar new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..011e3afa864a1f80d25eddd0c7f623c2b9f19588 GIT binary patch [stripped] -- Repository URL: https://hg.python.org/jython From jython-checkins at python.org Sun Sep 22 16:37:15 2019 From: jython-checkins at python.org (jeff.allen) Date: Sun, 22 Sep 2019 20:37:15 +0000 Subject: [Jython-checkins] =?utf-8?q?jython=3A_Target_Java_8_in_Jython_v2?= =?utf-8?q?=2E7=2E2_=28source_compatible_with_7=29=2E?= Message-ID: <20190922203715.1.FB4452639E2D43EE@mg.python.org> https://hg.python.org/jython/rev/1a6a5516d6e3 changeset: 8295:1a6a5516d6e3 user: Jeff Allen date: Sat Sep 21 10:33:05 2019 +0100 summary: Target Java 8 in Jython v2.7.2 (source compatible with 7). files: .travis.yml | 8 ++++++-- build.gradle | 15 ++++++++------- build.xml | 10 +++++++++- 3 files changed, 23 insertions(+), 10 deletions(-) diff --git a/.travis.yml b/.travis.yml --- a/.travis.yml +++ b/.travis.yml @@ -12,8 +12,12 @@ matrix: include: - os: linux - dist: precise - jdk: oraclejdk7 + dist: xenial + addons: + apt: + packages: + - ant + jdk: openjdk8 - os: linux dist: xenial diff --git a/build.gradle b/build.gradle --- a/build.gradle +++ b/build.gradle @@ -60,9 +60,13 @@ // ---------------- Miscellaneous configuration -------------------------------- -// Support Java 7 onwards -sourceCompatibility = '1.7' -targetCompatibility = '1.7' +/* + * We support Java 8 onwards officially, up to v2.7.2, but retain the option of + * compiling for Java 7 (in v2.7.2) by maintaining compatibility in the code + * base and in the choice of JARs. + */ +sourceCompatibility = '1.7' // Make both 1.8 after 2.7.2 released +targetCompatibility = '1.8' project.compileJava.options.debug = true @@ -90,10 +94,7 @@ repositories { - /* - * Jython is distributed through Maven Central. Get our dependencies there - * too. - */ + // Jython is distributed through Maven Central. Get our dependencies there too. mavenCentral() } diff --git a/build.xml b/build.xml --- a/build.xml +++ b/build.xml @@ -88,9 +88,16 @@ + - + + + + + -- Repository URL: https://hg.python.org/jython From jython-checkins at python.org Sat Sep 28 04:47:32 2019 From: jython-checkins at python.org (jeff.allen) Date: Sat, 28 Sep 2019 08:47:32 +0000 Subject: [Jython-checkins] =?utf-8?q?jython=3A_Fix_more_javadoc_8_errors?= =?utf-8?q?=2E?= Message-ID: <20190928084732.1.48ADB40E0D68DD46@mg.python.org> https://hg.python.org/jython/rev/bd853a8783a5 changeset: 8301:bd853a8783a5 user: Jeff Allen date: Mon Sep 23 22:42:47 2019 +0100 summary: Fix more javadoc 8 errors. Not sure why these escaped the first attempt at a clean-up. files: build.gradle | 2 +- src/com/ziclix/python/sql/DateFactory.java | 30 +++--- src/com/ziclix/python/sql/JavaDateFactory.java | 43 +++++---- src/com/ziclix/python/sql/pipe/Pipe.java | 5 +- src/com/ziclix/python/sql/util/BCP.java | 16 ++- src/org/python/antlr/PythonTokenSource.java | 18 ++- src/org/python/core/BaseBytes.java | 6 +- src/org/python/core/PyBuiltinMethodNarrow.java | 9 +- src/org/python/core/PyObject.java | 7 +- src/org/python/core/PySequence.java | 9 +- src/org/python/core/buffer/BaseBuffer.java | 2 +- 11 files changed, 85 insertions(+), 62 deletions(-) diff --git a/build.gradle b/build.gradle --- a/build.gradle +++ b/build.gradle @@ -688,9 +688,9 @@ /* * The JavaDoc, anyway. */ - javadoc { options.encoding = 'UTF-8' + source = fileTree(dir: 'src', include: '**/*.java') } // ---------------- Publication ------------------------------------------------ diff --git a/src/com/ziclix/python/sql/DateFactory.java b/src/com/ziclix/python/sql/DateFactory.java --- a/src/com/ziclix/python/sql/DateFactory.java +++ b/src/com/ziclix/python/sql/DateFactory.java @@ -19,33 +19,33 @@ /** * This function constructs an object holding a date value. * - * @param year - * @param month - * @param day - * @return PyObject + * @param year to set + * @param month to set + * @param day to set + * @return date as PyObject */ public PyObject Date(int year, int month, int day); /** * This function constructs an object holding a time value. * - * @param hour - * @param minute - * @param second - * @return PyObject + * @param hour to set + * @param minute to set + * @param second to set + * @return time as PyObject */ public PyObject Time(int hour, int minute, int second); /** * This function constructs an object holding a time stamp value. * - * @param year - * @param month - * @param day - * @param hour - * @param minute - * @param second - * @return PyObject + * @param year to set + * @param month to set + * @param day to set + * @param hour to set + * @param minute to set + * @param second to set + * @return time stamp as PyObject */ public PyObject Timestamp(int year, int month, int day, int hour, int minute, int second); diff --git a/src/com/ziclix/python/sql/JavaDateFactory.java b/src/com/ziclix/python/sql/JavaDateFactory.java --- a/src/com/ziclix/python/sql/JavaDateFactory.java +++ b/src/com/ziclix/python/sql/JavaDateFactory.java @@ -1,10 +1,9 @@ +// Copyright (c)2019 Jython Developers /* * Jython Database Specification API 2.0 - * - * - * Copyright (c) 2003 brian zimmer - * + * Copyright (c) 2001 brian zimmer */ +// Licensed to the PSF under a Contributor Agreement package com.ziclix.python.sql; import org.python.core.Py; @@ -24,11 +23,12 @@ /** * This function constructs an object holding a date value. * - * @param year - * @param month - * @param day - * @return PyObject + * @param year to set + * @param month to set + * @param day to set + * @return date as PyObject */ + @Override public PyObject Date(int year, int month, int day) { Calendar c = Calendar.getInstance(); @@ -43,11 +43,12 @@ /** * This function constructs an object holding a time value. * - * @param hour - * @param minute - * @param second - * @return PyObject + * @param hour to set + * @param minute to set + * @param second to set + * @return time as PyObject */ + @Override public PyObject Time(int hour, int minute, int second) { Calendar c = Calendar.getInstance(); @@ -62,14 +63,15 @@ /** * This function constructs an object holding a time stamp value. * - * @param year - * @param month - * @param day - * @param hour - * @param minute - * @param second - * @return PyObject + * @param year to set + * @param month to set + * @param day to set + * @param hour to set + * @param minute to set + * @param second to set + * @return time stamp as PyObject */ + @Override public PyObject Timestamp(int year, int month, int day, int hour, int minute, int second) { Calendar c = Calendar.getInstance(); @@ -98,6 +100,7 @@ * @param ticks number of seconds since the epoch * @return PyObject */ + @Override public PyObject DateFromTicks(long ticks) { Calendar c = Calendar.getInstance(); @@ -124,6 +127,7 @@ * @param ticks number of seconds since the epoch * @return PyObject */ + @Override public PyObject TimeFromTicks(long ticks) { return Py.java2py(new Time(ticks * 1000)); } @@ -141,6 +145,7 @@ * @param ticks number of seconds since the epoch * @return PyObject */ + @Override public PyObject TimestampFromTicks(long ticks) { return Py.java2py(new Timestamp(ticks * 1000)); } diff --git a/src/com/ziclix/python/sql/pipe/Pipe.java b/src/com/ziclix/python/sql/pipe/Pipe.java --- a/src/com/ziclix/python/sql/pipe/Pipe.java +++ b/src/com/ziclix/python/sql/pipe/Pipe.java @@ -30,7 +30,7 @@ } /** - * Start the processing of the Source->Sink. + * Start the processing of the Source to the Sink. * * @param source the data generator * @param sink the consumer of the data @@ -144,6 +144,7 @@ /** * Method run */ + @Override public void run() { try { @@ -216,6 +217,7 @@ * * @throws InterruptedException */ + @Override protected void pipe() throws InterruptedException { PyObject row = Py.None; @@ -270,6 +272,7 @@ * * @throws InterruptedException */ + @Override protected void pipe() throws InterruptedException { PyObject row = Py.None; diff --git a/src/com/ziclix/python/sql/util/BCP.java b/src/com/ziclix/python/sql/util/BCP.java --- a/src/com/ziclix/python/sql/util/BCP.java +++ b/src/com/ziclix/python/sql/util/BCP.java @@ -1,10 +1,9 @@ +// Copyright (c)2019 Jython Developers /* * Jython Database Specification API 2.0 - * - * * Copyright (c) 2001 brian zimmer - * */ +// Licensed to the PSF under a Contributor Agreement package com.ziclix.python.sql.util; import org.python.core.ClassDictInit; @@ -68,7 +67,7 @@ this.batchsize = batchsize; this.queuesize = 0; } - + /** * Field __methods__ */ @@ -99,6 +98,7 @@ * * @return a string representation of the object. */ + @Override public String toString() { return ""; } @@ -109,6 +109,7 @@ * @param name * @param value */ + @Override public void __setattr__(String name, PyObject value) { if ("destinationDataHandler".equals(name)) { @@ -130,6 +131,7 @@ * @param name * @return the attribute for the given name */ + @Override public PyObject __findattr_ex__(String name) { if ("destinationDataHandler".equals(name)) { @@ -206,7 +208,7 @@ } /** - * @copyright 2001 brian zimmer + * Copyright 2001 brian zimmer */ class BCPFunc extends PyBuiltinMethodSet { @@ -224,6 +226,7 @@ * @param arg * @return PyObject */ + @Override public PyObject __call__(PyObject arg) { BCP bcp = (BCP) __self__; @@ -246,6 +249,7 @@ } } + @Override public PyObject __call__(PyObject arga, PyObject argb) { BCP bcp = (BCP) __self__; @@ -269,6 +273,7 @@ } } + @Override public PyObject __call__(PyObject arga, PyObject argb, PyObject argc) { BCP bcp = (BCP) __self__; @@ -292,6 +297,7 @@ } } + @Override public PyObject __call__(PyObject[] args, String[] keywords) { BCP bcp = (BCP) __self__; diff --git a/src/org/python/antlr/PythonTokenSource.java b/src/org/python/antlr/PythonTokenSource.java --- a/src/org/python/antlr/PythonTokenSource.java +++ b/src/org/python/antlr/PythonTokenSource.java @@ -38,17 +38,17 @@ This is an interesting lexical problem because multiple DEDENT tokens should be sent to the parser sometimes without a corresponding input symbol! Consider the following example: - +
    {@literal
      a=1
      if a>1:
          print a
      b=3
    -
    +}
    Here the "b" token on the left edge signals that a DEDENT is needed after the "print a \n" and before the "b". The sequence should be - +
      ... 1 COLON NEWLINE INDENT PRINT a NEWLINE DEDENT b ASSIGN 3 ...
    -
    +
    For more examples, see the big comment at the bottom of this file. This TokenStream normally just passes tokens through to the parser. @@ -131,6 +131,7 @@ EOF to have char pos 0 even though with UNIX it's hard to get EOF at a non left edge. */ + @Override public Token nextToken() { // if something in queue, just remove and return it if (tokens.size() > 0) { @@ -366,6 +367,7 @@ return buf.toString(); } + @Override public String getSourceName() { return filename; } @@ -383,13 +385,13 @@ a c b c -a c \n INDENT b \n DEDENT c \n EOF +a c \n INDENT b \n DEDENT c \n EOF ------- t3 ------- a b c d -a \n INDENT b \n INDENT c \n DEDENT DEDENT d \n EOF +a \n INDENT b \n INDENT c \n DEDENT DEDENT d \n EOF ------- t4 ------- a c @@ -401,12 +403,12 @@ i j k -a \n INDENT c \n INDENT d \n DEDENT e \n f \n INDENT g \n h \n i \n INDENT j \n DEDENT DEDENT k \n DEDENT EOF +a \n INDENT c \n INDENT d \n DEDENT e \n f \n INDENT g \n h \n i \n INDENT j \n DEDENT DEDENT k \n DEDENT EOF ------- t5 ------- a b c d e -a \n INDENT b \n c \n INDENT d \n e \n DEDENT DEDENT EOF +a \n INDENT b \n c \n INDENT d \n e \n DEDENT DEDENT EOF */ diff --git a/src/org/python/core/BaseBytes.java b/src/org/python/core/BaseBytes.java --- a/src/org/python/core/BaseBytes.java +++ b/src/org/python/core/BaseBytes.java @@ -283,7 +283,7 @@ * * @param start index in this byte array at which the first character code lands * @param value source of characters - * @throws PyException {@code ValueError} if any value[i] > 255 + * @throws PyException {@code ValueError} if any {@code value[i] > 255} */ protected void setBytes(int start, String value) throws PyException { int n = value.length(); @@ -299,7 +299,7 @@ * * @param start index in this byte array at which the first character code lands * @param value source of characters - * @throws PyException {@code ValueError} if any value[i] > 255 + * @throws PyException {@code ValueError} if any {@code value[i] > 255} */ protected void setBytes(int start, int step, String value) throws PyException { int n = value.length(); @@ -4225,7 +4225,7 @@ * for small array sizes to avoid needless reallocation. * * @param size of storage actually needed - * @return n >= size a recommended storage array size + * @return n ≥ size a recommended storage array size */ protected static final int roundUp(int size) { /* diff --git a/src/org/python/core/PyBuiltinMethodNarrow.java b/src/org/python/core/PyBuiltinMethodNarrow.java --- a/src/org/python/core/PyBuiltinMethodNarrow.java +++ b/src/org/python/core/PyBuiltinMethodNarrow.java @@ -9,7 +9,7 @@ } /** - * Creates a method for the name that takes exactly numArgs arguments. + * Creates a method for the name that takes exactly numArgs arguments. */ protected PyBuiltinMethodNarrow(String name, int numArgs) { this(name, numArgs, numArgs); @@ -31,6 +31,7 @@ super(type, self, info); } + @Override public PyObject __call__(PyObject[] args, String[] keywords) { if(keywords.length != 0) { throw info.unexpectedCall(args.length, true); @@ -38,6 +39,7 @@ return __call__(args); } + @Override public PyObject __call__(PyObject[] args) { switch(args.length){ case 0: @@ -55,22 +57,27 @@ } } + @Override public PyObject __call__() { throw info.unexpectedCall(0, false); } + @Override public PyObject __call__(PyObject arg0) { throw info.unexpectedCall(1, false); } + @Override public PyObject __call__(PyObject arg0, PyObject arg1) { throw info.unexpectedCall(2, false); } + @Override public PyObject __call__(PyObject arg0, PyObject arg1, PyObject arg2) { throw info.unexpectedCall(3, false); } + @Override public PyObject __call__(PyObject arg0, PyObject arg1, PyObject arg2, diff --git a/src/org/python/core/PyObject.java b/src/org/python/core/PyObject.java --- a/src/org/python/core/PyObject.java +++ b/src/org/python/core/PyObject.java @@ -128,10 +128,9 @@ * {@link org.python.core.finalization.FinalizablePyObject}. *

    * Note that this empty finalizer implementation is optimized away by the JVM. (See Discovering Objects with - * Non-trivial Finalizers). So {@code PyObject}s are not expensively treated as finalizable - * objects by the Java-GC. Its single intention is to prevent subclasses from having Java-style - * finalizers. + * href=http://www.javaspecialists.eu/archive/Issue170.html>Discovering Objects with Non-trivial + * Finalizers). So {@code PyObject}s are not expensively treated as finalizable objects by + * the Java-GC. Its single intention is to prevent subclasses from having Java-style finalizers. */ @SuppressWarnings("deprecation") // See the Javadoc @Override diff --git a/src/org/python/core/PySequence.java b/src/org/python/core/PySequence.java --- a/src/org/python/core/PySequence.java +++ b/src/org/python/core/PySequence.java @@ -280,8 +280,8 @@ /** * Compare the specified object/length pairs. * - * @return value >= 0 is the index where the sequences differs. -1: reached the end of o1 - * without a difference -2: reached the end of both seqeunces without a difference -3: + * @return value ≥ 0 is the index where the sequences differs. -1: reached the end of o1 + * without a difference -2: reached the end of both sequences without a difference -3: * reached the end of o2 without a difference */ protected static int cmp(PyObject o1, int ol1, PyObject o2, int ol2) { @@ -334,8 +334,9 @@ } /** - * Adjusts index such that it's >= 0 and <= __len__. If index starts - * off negative, it's treated as an index from the end of the sequence going back to the start. + * Adjusts index such that it's ≥0 and ≤ __len__. If index + * starts off negative, it's treated as an index from the end of the sequence going back to the + * start. */ protected int boundToSequence(int index) { int length = __len__(); diff --git a/src/org/python/core/buffer/BaseBuffer.java b/src/org/python/core/buffer/BaseBuffer.java --- a/src/org/python/core/buffer/BaseBuffer.java +++ b/src/org/python/core/buffer/BaseBuffer.java @@ -182,7 +182,7 @@ /** * Remove features from this buffer expressed using the constants defined in {@link PyBUF}, * clearing individual flags specified while leaving others already set. Equivalent to - * setFeatureFlags(~flags & getFeatureFlags()). + * {@code setFeatureFlags(~flags & getFeatureFlags())}. * * @param flags to clear within the feature flags */ -- Repository URL: https://hg.python.org/jython

    Stream behaviour for various object types
    Python type of object o written