run ensurepip if selected
*
- *
+ *
* @param targetDirectory
* @param installationType
*/
@@ -102,8 +102,9 @@ public void inflate(final File targetDirectory, InstallationType installationTyp
}
}
// exclude build.xml when not installing source
- if (!installationType.installSources() && zipEntryName.equals("build.xml"))
+ if (!installationType.installSources() && zipEntryName.equals("build.xml")) {
exclude = true;
+ }
// handle exclusion of core Lib files
if (!exclude) {
exclude = shouldExcludeFile(installationType,
@@ -182,12 +183,14 @@ private int ensurepip(Path bindir) {
try {
String command[];
if (Installation.isWindows()) {
- command = new String[]{ bindir.resolve("jython.exe").toString(), "-m", "ensurepip" };
+ command = new String[] {bindir.resolve("jython.exe").toString(), "-m", "ensurepip"};
} else {
- command = new String[]{ Paths.get(".", "jython").toString(), "-m", "ensurepip"};
+ command = new String[] {Paths.get(".", "jython").toString(), "-m", "ensurepip"};
}
ChildProcess childProcess = new ChildProcess(command);
childProcess.setCWD(bindir);
+ // JYTHON_HOME will be wrong if set: see https://bugs.jython.org/issue2345
+ childProcess.putEnvironment("JYTHON_HOME", null);
errorCode = childProcess.run();
} catch (Throwable t) {
errorCode = 1;
diff --git a/installer/src/java/org/python/util/install/StartScriptGenerator.java b/installer/src/java/org/python/util/install/StartScriptGenerator.java
index 3165e6b40..fe0a4c9ea 100644
--- a/installer/src/java/org/python/util/install/StartScriptGenerator.java
+++ b/installer/src/java/org/python/util/install/StartScriptGenerator.java
@@ -81,7 +81,6 @@ protected final void generateStartScripts() throws IOException {
}
Files.delete(bindir.resolve("jython.py"));
Files.delete(bindir.resolve("jython.exe"));
- Files.delete(bindir.resolve("python27.dll"));
Files.setPosixFilePermissions(bindir.resolve("jython"),
PosixFilePermissions.fromString("rwxr-xr-x")); // 0755
}
diff --git a/lib-python/2.7/httplib.py b/lib-python/2.7/httplib.py
index 7223ba151..f3bb22c2b 100644
--- a/lib-python/2.7/httplib.py
+++ b/lib-python/2.7/httplib.py
@@ -242,7 +242,7 @@
#
# VCHAR defined in http://tools.ietf.org/html/rfc5234#appendix-B.1
-# the patterns for both name and value are more leniant than RFC
+# the patterns for both name and value are more lenient than RFC
# definitions to allow for backwards compatibility
_is_legal_header_name = re.compile(r'\A[^:\s][^:\r\n]*\Z').match
_is_illegal_header_value = re.compile(r'\n(?![ \t])|\r(?![ \t\n])').search
@@ -273,9 +273,8 @@ def readheaders(self):
Read header lines up to the entirely blank line that terminates them.
The (normally blank) line that ends the headers is skipped, but not
- included in the returned list. If a non-header line ends the headers,
- (which is an error), an attempt is made to backspace over it; it is
- never included in the returned list.
+ included in the returned list. If an invalid line is found in the
+ header section, it is skipped, and further lines are processed.
The variable self.status is set to the empty string if all went well,
otherwise it is an error message. The variable self.headers is a
@@ -302,19 +301,17 @@ def readheaders(self):
self.status = ''
headerseen = ""
firstline = 1
- startofline = unread = tell = None
- if hasattr(self.fp, 'unread'):
- unread = self.fp.unread
- elif self.seekable:
+ tell = None
+ if not hasattr(self.fp, 'unread') and self.seekable:
tell = self.fp.tell
while True:
if len(hlist) > _MAXHEADERS:
raise HTTPException("got more than %d headers" % _MAXHEADERS)
if tell:
try:
- startofline = tell()
+ tell()
except IOError:
- startofline = tell = None
+ tell = None
self.seekable = 0
line = self.fp.readline(_MAXLINE + 1)
if len(line) > _MAXLINE:
@@ -345,26 +342,14 @@ def readheaders(self):
# It's a legal header line, save it.
hlist.append(line)
self.addheader(headerseen, line[len(headerseen)+1:].strip())
- continue
elif headerseen is not None:
# An empty header name. These aren't allowed in HTTP, but it's
# probably a benign mistake. Don't add the header, just keep
# going.
- continue
+ pass
else:
- # It's not a header line; throw it back and stop here.
- if not self.dict:
- self.status = 'No headers'
- else:
- self.status = 'Non-header line where header expected'
- # Try to undo the read.
- if unread:
- unread(line)
- elif tell:
- self.fp.seek(startofline)
- else:
- self.status = self.status + '; bad seek'
- break
+ # It's not a header line; skip it and try the next line.
+ self.status = 'Non-header line where header expected'
class HTTPResponse:
diff --git a/lib-python/2.7/test/selfsigned_pythontestdotnet.pem b/lib-python/2.7/test/selfsigned_pythontestdotnet.pem
new file mode 100644
index 000000000..2b1760747
--- /dev/null
+++ b/lib-python/2.7/test/selfsigned_pythontestdotnet.pem
@@ -0,0 +1,34 @@
+-----BEGIN CERTIFICATE-----
+MIIF9zCCA9+gAwIBAgIUH98b4Fw/DyugC9cV7VK7ZODzHsIwDQYJKoZIhvcNAQEL
+BQAwgYoxCzAJBgNVBAYTAlhZMRcwFQYDVQQIDA5DYXN0bGUgQW50aHJheDEYMBYG
+A1UEBwwPQXJndW1lbnQgQ2xpbmljMSMwIQYDVQQKDBpQeXRob24gU29mdHdhcmUg
+Rm91bmRhdGlvbjEjMCEGA1UEAwwac2VsZi1zaWduZWQucHl0aG9udGVzdC5uZXQw
+HhcNMTkwNTA4MDEwMjQzWhcNMjcwNzI0MDEwMjQzWjCBijELMAkGA1UEBhMCWFkx
+FzAVBgNVBAgMDkNhc3RsZSBBbnRocmF4MRgwFgYDVQQHDA9Bcmd1bWVudCBDbGlu
+aWMxIzAhBgNVBAoMGlB5dGhvbiBTb2Z0d2FyZSBGb3VuZGF0aW9uMSMwIQYDVQQD
+DBpzZWxmLXNpZ25lZC5weXRob250ZXN0Lm5ldDCCAiIwDQYJKoZIhvcNAQEBBQAD
+ggIPADCCAgoCggIBAMKdJlyCThkahwoBb7pl5q64Pe9Fn5jrIvzsveHTc97TpjV2
+RLfICnXKrltPk/ohkVl6K5SUZQZwMVzFubkyxE0nZPHYHlpiKWQxbsYVkYv01rix
+IFdLvaxxbGYke2jwQao31s4o61AdlsfK1SdpHQUynBBMssqI3SB4XPmcA7e+wEEx
+jxjVish4ixA1vuIZOx8yibu+CFCf/geEjoBMF3QPdzULzlrCSw8k/45iZCSoNbvK
+DoL4TVV07PHOxpheDh8ZQmepGvU6pVqhb9m4lgmV0OGWHgozd5Ur9CbTVDmxIEz3
+TSoRtNJK7qtyZdGNqwjksQxgZTjM/d/Lm/BJG99AiOmYOjsl9gbQMZgvQmMAtUsI
+aMJnQuZ6R+KEpW/TR5qSKLWZSG45z/op+tzI2m+cE6HwTRVAWbcuJxcAA55MZjqU
+OOOu3BBYMjS5nf2sQ9uoXsVBFH7i0mQqoW1SLzr9opI8KsWwFxQmO2vBxWYaN+lH
+OmwBZBwyODIsmI1YGXmTp09NxRYz3Qe5GCgFzYowpMrcxUC24iduIdMwwhRM7rKg
+7GtIWMSrFfuI1XCLRmSlhDbhNN6fVg2f8Bo9PdH9ihiIyxSrc+FOUasUYCCJvlSZ
+8hFUlLvcmrZlWuazohm0lsXuMK1JflmQr/DA/uXxP9xzFfRy+RU3jDyxJbRHAgMB
+AAGjUzBRMB0GA1UdDgQWBBSQJyxiPMRK01i+0BsV9zUwDiBaHzAfBgNVHSMEGDAW
+gBSQJyxiPMRK01i+0BsV9zUwDiBaHzAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3
+DQEBCwUAA4ICAQCR+7a7N/m+WLkxPPIA/CB4MOr2Uf8ixTv435Nyv6rXOun0+lTP
+ExSZ0uYQ+L0WylItI3cQHULldDueD+s8TGzxf5woaLKf6tqyr0NYhKs+UeNEzDnN
+9PHQIhX0SZw3XyXGUgPNBfRCg2ZDdtMMdOU4XlQN/IN/9hbYTrueyY7eXq9hmtI9
+1srftAMqr9SR1JP7aHI6DVgrEsZVMTDnfT8WmLSGLlY1HmGfdEn1Ip5sbo9uSkiH
+AEPgPfjYIvR5LqTOMn4KsrlZyBbFIDh9Sl99M1kZzgH6zUGVLCDg1y6Cms69fx/e
+W1HoIeVkY4b4TY7Bk7JsqyNhIuqu7ARaxkdaZWhYaA2YyknwANdFfNpfH+elCLIk
+BUt5S3f4i7DaUePTvKukCZiCq4Oyln7RcOn5If73wCeLB/ZM9Ei1HforyLWP1CN8
+XLfpHaoeoPSWIveI0XHUl65LsPN2UbMbul/F23hwl+h8+BLmyAS680Yhn4zEN6Ku
+B7Po90HoFa1Du3bmx4jsN73UkT/dwMTi6K072FbipnC1904oGlWmLwvAHvrtxxmL
+Pl3pvEaZIu8wa/PNF6Y7J7VIewikIJq6Ta6FrWeFfzMWOj2qA1ZZi6fUaDSNYvuV
+J5quYKCc/O+I/yDDf8wyBbZ/gvUXzUHTMYGG+bFrn1p7XDbYYeEJ6R/xEg==
+-----END CERTIFICATE-----
diff --git a/lib-python/2.7/test/test_httplib.py b/lib-python/2.7/test/test_httplib.py
index d3bac0f91..7e8b058e8 100644
--- a/lib-python/2.7/test/test_httplib.py
+++ b/lib-python/2.7/test/test_httplib.py
@@ -241,6 +241,120 @@ def test_malformed_headers_coped_with(self):
self.assertEqual(resp.getheader('First'), 'val')
self.assertEqual(resp.getheader('Second'), 'val')
+ def test_malformed_truncation(self):
+ # Other malformed header lines, especially without colons, used to
+ # cause the rest of the header section to be truncated
+ resp = (
+ b'HTTP/1.1 200 OK\r\n'
+ b'Public-Key-Pins: \n'
+ b'pin-sha256="xxx=";\n'
+ b'report-uri="https://..."\r\n'
+ b'Transfer-Encoding: chunked\r\n'
+ b'\r\n'
+ b'4\r\nbody\r\n0\r\n\r\n'
+ )
+ resp = httplib.HTTPResponse(FakeSocket(resp))
+ resp.begin()
+ self.assertIsNotNone(resp.getheader('Public-Key-Pins'))
+ self.assertEqual(resp.getheader('Transfer-Encoding'), 'chunked')
+ self.assertEqual(resp.read(), b'body')
+
+ def test_blank_line_forms(self):
+ # Test that both CRLF and LF blank lines can terminate the header
+ # section and start the body
+ for blank in (b'\r\n', b'\n'):
+ resp = b'HTTP/1.1 200 OK\r\n' b'Transfer-Encoding: chunked\r\n'
+ resp += blank
+ resp += b'4\r\nbody\r\n0\r\n\r\n'
+ resp = httplib.HTTPResponse(FakeSocket(resp))
+ resp.begin()
+ self.assertEqual(resp.getheader('Transfer-Encoding'), 'chunked')
+ self.assertEqual(resp.read(), b'body')
+
+ resp = b'HTTP/1.0 200 OK\r\n' + blank + b'body'
+ resp = httplib.HTTPResponse(FakeSocket(resp))
+ resp.begin()
+ self.assertEqual(resp.read(), b'body')
+
+ # A blank line ending in CR is not treated as the end of the HTTP
+ # header section, therefore header fields following it should be
+ # parsed if possible
+ resp = (
+ b'HTTP/1.1 200 OK\r\n'
+ b'\r'
+ b'Name: value\r\n'
+ b'Transfer-Encoding: chunked\r\n'
+ b'\r\n'
+ b'4\r\nbody\r\n0\r\n\r\n'
+ )
+ resp = httplib.HTTPResponse(FakeSocket(resp))
+ resp.begin()
+ self.assertEqual(resp.getheader('Transfer-Encoding'), 'chunked')
+ self.assertEqual(resp.read(), b'body')
+
+ # No header fields nor blank line
+ resp = b'HTTP/1.0 200 OK\r\n'
+ resp = httplib.HTTPResponse(FakeSocket(resp))
+ resp.begin()
+ self.assertEqual(resp.read(), b'')
+
+ def test_from_line(self):
+ # The parser handles "From" lines specially, so test this does not
+ # affect parsing the rest of the header section
+ resp = (
+ b'HTTP/1.1 200 OK\r\n'
+ b'From start\r\n'
+ b' continued\r\n'
+ b'Name: value\r\n'
+ b'From middle\r\n'
+ b' continued\r\n'
+ b'Transfer-Encoding: chunked\r\n'
+ b'From end\r\n'
+ b'\r\n'
+ b'4\r\nbody\r\n0\r\n\r\n'
+ )
+ resp = httplib.HTTPResponse(FakeSocket(resp))
+ resp.begin()
+ self.assertIsNotNone(resp.getheader('Name'))
+ self.assertEqual(resp.getheader('Transfer-Encoding'), 'chunked')
+ self.assertEqual(resp.read(), b'body')
+
+ resp = (
+ b'HTTP/1.0 200 OK\r\n'
+ b'From alone\r\n'
+ b'\r\n'
+ b'body'
+ )
+ resp = httplib.HTTPResponse(FakeSocket(resp))
+ resp.begin()
+ self.assertEqual(resp.read(), b'body')
+
+ def test_parse_all_octets(self):
+ # Ensure no valid header field octet breaks the parser
+ body = (
+ b'HTTP/1.1 200 OK\r\n'
+ b"!#$%&'*+-.^_`|~: value\r\n" # Special token characters
+ b'VCHAR: ' + bytearray(range(0x21, 0x7E + 1)) + b'\r\n'
+ b'obs-text: ' + bytearray(range(0x80, 0xFF + 1)) + b'\r\n'
+ b'obs-fold: text\r\n'
+ b' folded with space\r\n'
+ b'\tfolded with tab\r\n'
+ b'Content-Length: 0\r\n'
+ b'\r\n'
+ )
+ sock = FakeSocket(body)
+ resp = httplib.HTTPResponse(sock)
+ resp.begin()
+ self.assertEqual(resp.getheader('Content-Length'), '0')
+ self.assertEqual(resp.getheader("!#$%&'*+-.^_`|~"), 'value')
+ vchar = ''.join(map(chr, range(0x21, 0x7E + 1)))
+ self.assertEqual(resp.getheader('VCHAR'), vchar)
+ self.assertIsNotNone(resp.getheader('obs-text'))
+ folded = resp.getheader('obs-fold')
+ self.assertTrue(folded.startswith('text'))
+ self.assertIn(' folded with space', folded)
+ self.assertTrue(folded.endswith('folded with tab'))
+
def test_invalid_headers(self):
conn = httplib.HTTPConnection('example.com')
conn.sock = FakeSocket('')
@@ -525,7 +639,7 @@ def test_filenoattr(self):
self.assertTrue(hasattr(resp,'fileno'),
'HTTPResponse should expose a fileno attribute')
- # Test lines overflowing the max line size (_MAXLINE in http.client)
+ # Test lines overflowing the max line size (_MAXLINE in httplib)
def test_overflowing_status_line(self):
self.skipTest("disabled for HTTP 0.9 support")
@@ -624,7 +738,7 @@ def testHTTPConnectionSourceAddress(self):
def testHTTPSConnectionSourceAddress(self):
self.conn = httplib.HTTPSConnection(HOST, self.port,
source_address=('', self.source_port))
- # We don't test anything here other the constructor not barfing as
+ # We don't test anything here other than the constructor not barfing as
# this code doesn't deal with setting up an active running SSL server
# for an ssl_wrapped connect() to actually return from.
diff --git a/lib-python/2.7/urllib.py b/lib-python/2.7/urllib.py
index c3ba2c94c..7f70496b6 100644
--- a/lib-python/2.7/urllib.py
+++ b/lib-python/2.7/urllib.py
@@ -138,7 +138,7 @@ def __init__(self, proxies=None, context=None, **x509):
self.key_file = x509.get('key_file')
self.cert_file = x509.get('cert_file')
self.context = context
- self.addheaders = [('User-Agent', self.version)]
+ self.addheaders = [('User-Agent', self.version), ('Accept', '*/*')]
self.__tempfiles = []
self.__unlink = os.unlink # See cleanup()
self.tempcache = None
diff --git a/lib-python/LICENSE.txt b/lib-python/LICENSE.txt
new file mode 100644
index 000000000..bd13df28c
--- /dev/null
+++ b/lib-python/LICENSE.txt
@@ -0,0 +1,748 @@
+A. HISTORY OF THE SOFTWARE
+==========================
+
+Python was created in the early 1990s by Guido van Rossum at Stichting
+Mathematisch Centrum (CWI, see http://www.cwi.nl) in the Netherlands
+as a successor of a language called ABC. Guido remains Python's
+principal author, although it includes many contributions from others.
+
+In 1995, Guido continued his work on Python at the Corporation for
+National Research Initiatives (CNRI, see http://www.cnri.reston.va.us)
+in Reston, Virginia where he released several versions of the
+software.
+
+In May 2000, Guido and the Python core development team moved to
+BeOpen.com to form the BeOpen PythonLabs team. In October of the same
+year, the PythonLabs team moved to Digital Creations, which became
+Zope Corporation. In 2001, the Python Software Foundation (PSF, see
+https://www.python.org/psf/) was formed, a non-profit organization
+created specifically to own Python-related Intellectual Property.
+Zope Corporation was a sponsoring member of the PSF.
+
+All Python releases are Open Source (see http://www.opensource.org for
+the Open Source Definition). Historically, most, but not all, Python
+releases have also been GPL-compatible; the table below summarizes
+the various releases.
+
+ Release Derived Year Owner GPL-
+ from compatible? (1)
+
+ 0.9.0 thru 1.2 1991-1995 CWI yes
+ 1.3 thru 1.5.2 1.2 1995-1999 CNRI yes
+ 1.6 1.5.2 2000 CNRI no
+ 2.0 1.6 2000 BeOpen.com no
+ 1.6.1 1.6 2001 CNRI yes (2)
+ 2.1 2.0+1.6.1 2001 PSF no
+ 2.0.1 2.0+1.6.1 2001 PSF yes
+ 2.1.1 2.1+2.0.1 2001 PSF yes
+ 2.1.2 2.1.1 2002 PSF yes
+ 2.1.3 2.1.2 2002 PSF yes
+ 2.2 and above 2.1.1 2001-now PSF yes
+
+Footnotes:
+
+(1) GPL-compatible doesn't mean that we're distributing Python under
+ the GPL. All Python licenses, unlike the GPL, let you distribute
+ a modified version without making your changes open source. The
+ GPL-compatible licenses make it possible to combine Python with
+ other software that is released under the GPL; the others don't.
+
+(2) According to Richard Stallman, 1.6.1 is not GPL-compatible,
+ because its license has a choice of law clause. According to
+ CNRI, however, Stallman's lawyer has told CNRI's lawyer that 1.6.1
+ is "not incompatible" with the GPL.
+
+Thanks to the many outside volunteers who have worked under Guido's
+direction to make these releases possible.
+
+
+B. TERMS AND CONDITIONS FOR ACCESSING OR OTHERWISE USING PYTHON
+===============================================================
+
+PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
+--------------------------------------------
+
+1. This LICENSE AGREEMENT is between the Python Software Foundation
+("PSF"), and the Individual or Organization ("Licensee") accessing and
+otherwise using this software ("Python") in source or binary form and
+its associated documentation.
+
+2. Subject to the terms and conditions of this License Agreement, PSF hereby
+grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce,
+analyze, test, perform and/or display publicly, prepare derivative works,
+distribute, and otherwise use Python alone or in any derivative version,
+provided, however, that PSF's License Agreement and PSF's notice of copyright,
+i.e., "Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
+2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019 Python Software Foundation;
+All Rights Reserved" are retained in Python alone or in any derivative version
+prepared by Licensee.
+
+3. In the event Licensee prepares a derivative work that is based on
+or incorporates Python or any part thereof, and wants to make
+the derivative work available to others as provided herein, then
+Licensee hereby agrees to include in any such work a brief summary of
+the changes made to Python.
+
+4. PSF is making Python available to Licensee on an "AS IS"
+basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
+IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND
+DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
+FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT
+INFRINGE ANY THIRD PARTY RIGHTS.
+
+5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON
+FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS
+A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON,
+OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
+
+6. This License Agreement will automatically terminate upon a material
+breach of its terms and conditions.
+
+7. Nothing in this License Agreement shall be deemed to create any
+relationship of agency, partnership, or joint venture between PSF and
+Licensee. This License Agreement does not grant permission to use PSF
+trademarks or trade name in a trademark sense to endorse or promote
+products or services of Licensee, or any third party.
+
+8. By copying, installing or otherwise using Python, Licensee
+agrees to be bound by the terms and conditions of this License
+Agreement.
+
+
+BEOPEN.COM LICENSE AGREEMENT FOR PYTHON 2.0
+-------------------------------------------
+
+BEOPEN PYTHON OPEN SOURCE LICENSE AGREEMENT VERSION 1
+
+1. This LICENSE AGREEMENT is between BeOpen.com ("BeOpen"), having an
+office at 160 Saratoga Avenue, Santa Clara, CA 95051, and the
+Individual or Organization ("Licensee") accessing and otherwise using
+this software in source or binary form and its associated
+documentation ("the Software").
+
+2. Subject to the terms and conditions of this BeOpen Python License
+Agreement, BeOpen hereby grants Licensee a non-exclusive,
+royalty-free, world-wide license to reproduce, analyze, test, perform
+and/or display publicly, prepare derivative works, distribute, and
+otherwise use the Software alone or in any derivative version,
+provided, however, that the BeOpen Python License is retained in the
+Software, alone or in any derivative version prepared by Licensee.
+
+3. BeOpen is making the Software available to Licensee on an "AS IS"
+basis. BEOPEN MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
+IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, BEOPEN MAKES NO AND
+DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
+FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE WILL NOT
+INFRINGE ANY THIRD PARTY RIGHTS.
+
+4. BEOPEN SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF THE
+SOFTWARE FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS
+AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THE SOFTWARE, OR ANY
+DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
+
+5. This License Agreement will automatically terminate upon a material
+breach of its terms and conditions.
+
+6. This License Agreement shall be governed by and interpreted in all
+respects by the law of the State of California, excluding conflict of
+law provisions. Nothing in this License Agreement shall be deemed to
+create any relationship of agency, partnership, or joint venture
+between BeOpen and Licensee. This License Agreement does not grant
+permission to use BeOpen trademarks or trade names in a trademark
+sense to endorse or promote products or services of Licensee, or any
+third party. As an exception, the "BeOpen Python" logos available at
+http://www.pythonlabs.com/logos.html may be used according to the
+permissions granted on that web page.
+
+7. By copying, installing or otherwise using the software, Licensee
+agrees to be bound by the terms and conditions of this License
+Agreement.
+
+
+CNRI LICENSE AGREEMENT FOR PYTHON 1.6.1
+---------------------------------------
+
+1. This LICENSE AGREEMENT is between the Corporation for National
+Research Initiatives, having an office at 1895 Preston White Drive,
+Reston, VA 20191 ("CNRI"), and the Individual or Organization
+("Licensee") accessing and otherwise using Python 1.6.1 software in
+source or binary form and its associated documentation.
+
+2. Subject to the terms and conditions of this License Agreement, CNRI
+hereby grants Licensee a nonexclusive, royalty-free, world-wide
+license to reproduce, analyze, test, perform and/or display publicly,
+prepare derivative works, distribute, and otherwise use Python 1.6.1
+alone or in any derivative version, provided, however, that CNRI's
+License Agreement and CNRI's notice of copyright, i.e., "Copyright (c)
+1995-2001 Corporation for National Research Initiatives; All Rights
+Reserved" are retained in Python 1.6.1 alone or in any derivative
+version prepared by Licensee. Alternately, in lieu of CNRI's License
+Agreement, Licensee may substitute the following text (omitting the
+quotes): "Python 1.6.1 is made available subject to the terms and
+conditions in CNRI's License Agreement. This Agreement together with
+Python 1.6.1 may be located on the Internet using the following
+unique, persistent identifier (known as a handle): 1895.22/1013. This
+Agreement may also be obtained from a proxy server on the Internet
+using the following URL: http://hdl.handle.net/1895.22/1013".
+
+3. In the event Licensee prepares a derivative work that is based on
+or incorporates Python 1.6.1 or any part thereof, and wants to make
+the derivative work available to others as provided herein, then
+Licensee hereby agrees to include in any such work a brief summary of
+the changes made to Python 1.6.1.
+
+4. CNRI is making Python 1.6.1 available to Licensee on an "AS IS"
+basis. CNRI MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
+IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, CNRI MAKES NO AND
+DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
+FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 1.6.1 WILL NOT
+INFRINGE ANY THIRD PARTY RIGHTS.
+
+5. CNRI SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON
+1.6.1 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS
+A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 1.6.1,
+OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
+
+6. This License Agreement will automatically terminate upon a material
+breach of its terms and conditions.
+
+7. This License Agreement shall be governed by the federal
+intellectual property law of the United States, including without
+limitation the federal copyright law, and, to the extent such
+U.S. federal law does not apply, by the law of the Commonwealth of
+Virginia, excluding Virginia's conflict of law provisions.
+Notwithstanding the foregoing, with regard to derivative works based
+on Python 1.6.1 that incorporate non-separable material that was
+previously distributed under the GNU General Public License (GPL), the
+law of the Commonwealth of Virginia shall govern this License
+Agreement only as to issues arising under or with respect to
+Paragraphs 4, 5, and 7 of this License Agreement. Nothing in this
+License Agreement shall be deemed to create any relationship of
+agency, partnership, or joint venture between CNRI and Licensee. This
+License Agreement does not grant permission to use CNRI trademarks or
+trade name in a trademark sense to endorse or promote products or
+services of Licensee, or any third party.
+
+8. By clicking on the "ACCEPT" button where indicated, or by copying,
+installing or otherwise using Python 1.6.1, Licensee agrees to be
+bound by the terms and conditions of this License Agreement.
+
+ ACCEPT
+
+
+CWI LICENSE AGREEMENT FOR PYTHON 0.9.0 THROUGH 1.2
+--------------------------------------------------
+
+Copyright (c) 1991 - 1995, Stichting Mathematisch Centrum Amsterdam,
+The Netherlands. All rights reserved.
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+
+Additional Conditions for this Windows binary build
+---------------------------------------------------
+
+This program is linked with and uses Microsoft Distributable Code,
+copyrighted by Microsoft Corporation. The Microsoft Distributable Code
+includes the following files:
+
+msvcr90.dll
+msvcp90.dll
+msvcm90.dll
+
+If you further distribute programs that include the Microsoft
+Distributable Code, you must comply with the restrictions on
+distribution specified by Microsoft. In particular, you must require
+distributors and external end users to agree to terms that protect the
+Microsoft Distributable Code at least as much as Microsoft's own
+requirements for the Distributable Code. See Microsoft's documentation
+(included in its developer tools and on its website at microsoft.com)
+for specific details.
+
+Redistribution of the Windows binary build of the Python interpreter
+complies with this agreement, provided that you do not:
+
+- alter any copyright, trademark or patent notice in Microsoft's
+Distributable Code;
+
+- use Microsoft's trademarks in your programs' names or in a way that
+suggests your programs come from or are endorsed by Microsoft;
+
+- distribute Microsoft's Distributable Code to run on a platform other
+than Microsoft operating systems, run-time technologies or application
+platforms; or
+
+- include Microsoft Distributable Code in malicious, deceptive or
+unlawful programs.
+
+These restrictions apply only to the Microsoft Distributable Code as
+defined above, not to Python itself or any programs running on the
+Python interpreter. The redistribution of the Python interpreter and
+libraries is governed by the Python Software License included with this
+file, or by other licenses as marked.
+
+
+This copy of Python includes a copy of bzip2, which is licensed under the following terms:
+
+
+--------------------------------------------------------------------------
+
+This program, "bzip2", the associated library "libbzip2", and all
+documentation, are copyright (C) 1996-2010 Julian R Seward. All
+rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+2. The origin of this software must not be misrepresented; you must
+ not claim that you wrote the original software. If you use this
+ software in a product, an acknowledgment in the product
+ documentation would be appreciated but is not required.
+
+3. Altered source versions must be plainly marked as such, and must
+ not be misrepresented as being the original software.
+
+4. The name of the author may not be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Julian Seward, jseward@bzip.org
+bzip2/libbzip2 version 1.0.6 of 6 September 2010
+
+--------------------------------------------------------------------------
+
+This copy of Python includes a copy of Berkeley DB, which is licensed under the following terms:
+
+/*-
+ * $Id: LICENSE,v 12.9 2008/02/07 17:12:17 mark Exp $
+ */
+
+The following is the license that applies to this copy of the Berkeley DB
+software. For a license to use the Berkeley DB software under conditions
+other than those described here, or to purchase support for this software,
+please contact Oracle at berkeleydb-info_us@oracle.com.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+/*
+ * Copyright (c) 1990,2008 Oracle. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Redistributions in any form must be accompanied by information on
+ * how to obtain complete source code for the DB software and any
+ * accompanying software that uses the DB software. The source code
+ * must either be included in the distribution or be available for no
+ * more than the cost of distribution plus a nominal fee, and must be
+ * freely redistributable under reasonable conditions. For an
+ * executable file, complete source code means the source code for all
+ * modules it contains. It does not include source code for modules or
+ * files that typically accompany the major components of the operating
+ * system on which the executable file runs.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ORACLE ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL ORACLE BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * Copyright (c) 1990, 1993, 1994, 1995
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/*
+ * Copyright (c) 1995, 1996
+ * The President and Fellows of Harvard University. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY HARVARD AND ITS CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL HARVARD OR ITS CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2005 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+This copy of Python includes a copy of openssl, which is licensed under the following terms:
+
+
+ LICENSE ISSUES
+ ==============
+
+ The OpenSSL toolkit stays under a double license, i.e. both the conditions of
+ the OpenSSL License and the original SSLeay license apply to the toolkit.
+ See below for the actual license texts. Actually both licenses are BSD-style
+ Open Source licenses. In case of any license issues related to OpenSSL
+ please contact openssl-core@openssl.org.
+
+ OpenSSL License
+ ---------------
+
+/* ====================================================================
+ * Copyright (c) 1998-2018 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+ Original SSLeay License
+ -----------------------
+
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+
+This copy of Python includes a copy of Tcl, which is licensed under the following terms:
+
+This software is copyrighted by the Regents of the University of
+California, Sun Microsystems, Inc., Scriptics Corporation, ActiveState
+Corporation and other parties. The following terms apply to all files
+associated with the software unless explicitly disclaimed in
+individual files.
+
+The authors hereby grant permission to use, copy, modify, distribute,
+and license this software and its documentation for any purpose, provided
+that existing copyright notices are retained in all copies and that this
+notice is included verbatim in any distributions. No written agreement,
+license, or royalty fee is required for any of the authorized uses.
+Modifications to this software may be copyrighted by their authors
+and need not follow the licensing terms described here, provided that
+the new terms are clearly indicated on the first page of each file where
+they apply.
+
+IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
+FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
+DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE
+IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
+NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
+MODIFICATIONS.
+
+GOVERNMENT USE: If you are acquiring this software on behalf of the
+U.S. government, the Government shall have only "Restricted Rights"
+in the software and related documentation as defined in the Federal
+Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you
+are acquiring the software on behalf of the Department of Defense, the
+software shall be classified as "Commercial Computer Software" and the
+Government shall have only "Restricted Rights" as defined in Clause
+252.227-7013 (b) (3) of DFARs. Notwithstanding the foregoing, the
+authors grant the U.S. Government and others acting in its behalf
+permission to use and distribute the software in accordance with the
+terms specified in this license.
+
+This copy of Python includes a copy of Tk, which is licensed under the following terms:
+
+This software is copyrighted by the Regents of the University of
+California, Sun Microsystems, Inc., and other parties. The following
+terms apply to all files associated with the software unless explicitly
+disclaimed in individual files.
+
+The authors hereby grant permission to use, copy, modify, distribute,
+and license this software and its documentation for any purpose, provided
+that existing copyright notices are retained in all copies and that this
+notice is included verbatim in any distributions. No written agreement,
+license, or royalty fee is required for any of the authorized uses.
+Modifications to this software may be copyrighted by their authors
+and need not follow the licensing terms described here, provided that
+the new terms are clearly indicated on the first page of each file where
+they apply.
+
+IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
+FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
+DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE
+IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
+NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
+MODIFICATIONS.
+
+GOVERNMENT USE: If you are acquiring this software on behalf of the
+U.S. government, the Government shall have only "Restricted Rights"
+in the software and related documentation as defined in the Federal
+Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you
+are acquiring the software on behalf of the Department of Defense, the
+software shall be classified as "Commercial Computer Software" and the
+Government shall have only "Restricted Rights" as defined in Clause
+252.227-7013 (b) (3) of DFARs. Notwithstanding the foregoing, the
+authors grant the U.S. Government and others acting in its behalf
+permission to use and distribute the software in accordance with the
+terms specified in this license.
+
+This copy of Python includes a copy of Tix, which is licensed under the following terms:
+
+Copyright (c) 1993-1999 Ioi Kim Lam.
+Copyright (c) 2000-2001 Tix Project Group.
+Copyright (c) 2004 ActiveState
+
+This software is copyrighted by the above entities
+and other parties. The following terms apply to all files associated
+with the software unless explicitly disclaimed in individual files.
+
+The authors hereby grant permission to use, copy, modify, distribute,
+and license this software and its documentation for any purpose, provided
+that existing copyright notices are retained in all copies and that this
+notice is included verbatim in any distributions. No written agreement,
+license, or royalty fee is required for any of the authorized uses.
+Modifications to this software may be copyrighted by their authors
+and need not follow the licensing terms described here, provided that
+the new terms are clearly indicated on the first page of each file where
+they apply.
+
+IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
+FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
+DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE
+IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
+NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
+MODIFICATIONS.
+
+GOVERNMENT USE: If you are acquiring this software on behalf of the
+U.S. government, the Government shall have only "Restricted Rights"
+in the software and related documentation as defined in the Federal
+Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you
+are acquiring the software on behalf of the Department of Defense, the
+software shall be classified as "Commercial Computer Software" and the
+Government shall have only "Restricted Rights" as defined in Clause
+252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the
+authors grant the U.S. Government and others acting in its behalf
+permission to use and distribute the software in accordance with the
+terms specified in this license.
+
+----------------------------------------------------------------------
+
+Parts of this software are based on the Tcl/Tk software copyrighted by
+the Regents of the University of California, Sun Microsystems, Inc.,
+and other parties. The original license terms of the Tcl/Tk software
+distribution is included in the file docs/license.tcltk.
+
+Parts of this software are based on the HTML Library software
+copyrighted by Sun Microsystems, Inc. The original license terms of
+the HTML Library software distribution is included in the file
+docs/license.html_lib.
diff --git a/maven/build.xml b/maven/build.xml
index e33640485..eea24cd06 100644
--- a/maven/build.xml
+++ b/maven/build.xml
@@ -8,7 +8,7 @@
to you 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,
@@ -29,184 +29,221 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/maven/pom-template.xml b/maven/pom-template.xml
index a427eaca4..ca981b9b7 100644
--- a/maven/pom-template.xml
+++ b/maven/pom-template.xml
@@ -9,29 +9,33 @@
jarJython@PROJECT-VERSION@
- http://www.jython.org/
+ https://www.jython.org/
+
Jython is an implementation of the high-level, dynamic, object-oriented
language Python written in 100% Pure Java, and seamlessly integrated with
the Java platform. It thus allows you to run Python on any Java platform.
+
Jython Software License
- http://www.jython.org/Project/license.html
+ https://www.jython.org/Project/license.htmlrepo
+
- scm:hg:http://hg.python.org/jython
+ scm:hg:https://hg.python.org/jythonscm:hg:ssh://hg@hg.python.org/jython
- http://hg.python.org/jython
+ https://hg.python.org/jython
-
+
- fwierzbicki
- Frank Wierzbicki
+ jython
+ Jython Developers
+ jython-dev@lists.sourceforge.net
diff --git a/registry b/registry
index b7b54cbe0..8024bfefc 100644
--- a/registry
+++ b/registry
@@ -1,6 +1,10 @@
# Python Registry -*- sh -*-
# This default registry sets many common options to their default values
# All of these settings could be erased with no change in behavior
+#
+# Definitive descriptions of supported keys and values is in the javadoc
+# for org.python.core.RegistryKey
+#
# This is how Jim sets his path on his Windows development machine
#python.path=.;c:\\Jython\\Lib;d:\\Python-1.5.2\\Lib
@@ -10,29 +14,34 @@
#python.path = d:\\python20\\lib
# Set the directory to use for caches (currently just package information)
-# This directory should be writable by the user
-# If this is an absolute path it is used as given
-# Otherwise it is interpreted relative to sys.prefix
-# (typically the directory of this file)
-python.cachedir = cachedir
+# This directory should be writable by the user. If this is an absolute path it is used as given,
+# otherwise it is interpreted relative to the current working directory (at initialisation).
+#python.cachedir = .jython_cache
# Setting this property to true disables the package scan for the cachedir.
# Please be aware that disabling this will break importing * from java packages
#python.cachedir.skip = false
# Properties to check for initializing and updating the package cache
-# Hopefully you won't have any need to change these
-python.packages.paths = java.class.path, sun.boot.class.path
-python.packages.directories = java.ext.dirs
+# Values shown here are those hard-coded in Jython's cache manager.
+
+# Treat JARs on the classpath and (up to Java 8) in the JRE as a source of Python packages.
+#python.packages.paths = java.class.path, sun.boot.class.path # up to Java 8
+#python.packages.paths = java.class.path # from Java 9
+# Treat installed optional (Java) packages as source of Python packages (before Java 9)
+#python.packages.directories = java.ext.dirs # up to Java 8
+#python.packages.directories # undefined from Java 9
-# Set verbosity to error, warning, message, comment, or debug
-# for varying levels of informative messages from Jython. Normally
-# this option is set from the command line.
+
+# DEPRECATED way to set the verbosity of messages output by Jython. If
+# specified, "python.verbose" will set logging level for "org.python" when
+# the runtime is initialised. It is better to use java.util.logging
+# preferences (and the -v option) which work from the start of execution.
#python.verbose = message
# Jython ships with a JLine console (http://jline.sourceforge.net/) out of the
# box. This is selected by default in the Jython command-line application
-# (org.python.util,jython) if you do not define python.console to be another
+# (org.python.util.jython) if you do not define python.console to be another
# class on the command line. Alternatively, you could set python.console here,
# 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.
@@ -58,6 +67,14 @@ python.security.respectJavaAccessibility = true
# behaviour.
python.options.caseok = false
+# Setting this non-empty will drop the interpreter into an interactive session at the end of
+# execution, like adding the -i flag (roughly) or setting the environment variable PYTHONINSPECT
+# during execution.
+#python.inspect = true
+
+# Setting this to a file name will cause that file to be run at the start of each interactive
+# session (but not when dropping in with the -i flag in after a script has run).
+#python.startup = jython-startup.py
# Use this registry entry to control the list of builtin modules; you
# can add, remove, or override builtin modules. The value for this
diff --git a/settings.gradle b/settings.gradle
new file mode 100644
index 000000000..69e01717d
--- /dev/null
+++ b/settings.gradle
@@ -0,0 +1,5 @@
+/*
+ * Gradle settings for Jython. See also build.gradle.
+ */
+
+rootProject.name = 'jython-slim'
diff --git a/src/com/ziclix/python/sql/DataHandler.java b/src/com/ziclix/python/sql/DataHandler.java
index c9172a3a3..62efb0fe3 100644
--- a/src/com/ziclix/python/sql/DataHandler.java
+++ b/src/com/ziclix/python/sql/DataHandler.java
@@ -331,14 +331,14 @@ public PyObject getPyObject(ResultSet set, int col, int type) throws SQLExceptio
throw createUnsupportedTypeSQLException("STRUCT", col);
default :
- throw createUnsupportedTypeSQLException(new Integer(type), col);
+ throw createUnsupportedTypeSQLException(Integer.valueOf(type), col);
}
return set.wasNull() || obj == null ? Py.None : obj;
}
protected final SQLException createUnsupportedTypeSQLException(Object type, int col) {
- Object[] vals = {type, new Integer(col)};
+ Object[] vals = {type, Integer.valueOf(col)};
String msg = zxJDBC.getString("unsupportedTypeForColumn", vals);
return new SQLException(msg);
}
diff --git a/src/com/ziclix/python/sql/DateFactory.java b/src/com/ziclix/python/sql/DateFactory.java
index 5a4f03d28..186159fd5 100644
--- a/src/com/ziclix/python/sql/DateFactory.java
+++ b/src/com/ziclix/python/sql/DateFactory.java
@@ -19,33 +19,33 @@ public interface DateFactory {
/**
* 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);
@@ -53,7 +53,7 @@ public interface DateFactory {
* 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 @@ public interface DateFactory {
* 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 @@ public interface DateFactory {
* 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
index 6610f48bd..b6ea69289 100644
--- 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 @@ abstract public class Fetch implements Traverseproc {
/**
* 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 @@ abstract public void add(CallableStatement callableStatement, Procedure procedur
/**
* 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 @@ public PyObject fetchone() {
* 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 @@ public PyObject fetchone() {
* 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 @@ public PyObject fetchone() {
/**
* 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 @@ public void close() throws SQLException {
/**
* Builds a tuple containing the meta-information about each column.
- *
* precision and scale are only available for numeric types
*/
protected PyObject createDescription(ResultSetMetaData meta) throws SQLException {
@@ -293,9 +293,9 @@ protected PyObject createDescription(ResultSetMetaData meta) throws SQLException
/**
* Builds a tuple containing the meta-information about each column.
- *
* precision and scale are only available for numeric types
*/
protected PyObject createDescription(Procedure procedure) throws SQLException {
@@ -617,7 +617,7 @@ public void add(CallableStatement callableStatement, Procedure procedure, PyObje
* 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 @@ public PyObject fetchall() {
* 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
index a89341824..dfce74121 100644
--- 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 @@ public class JavaDateFactory implements DateFactory {
/**
* 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 @@ 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
*/
+ @Override
public PyObject Time(int hour, int minute, int second) {
Calendar c = Calendar.getInstance();
@@ -62,14 +63,15 @@ 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
*/
+ @Override
public PyObject Timestamp(int year, int month, int day, int hour, int minute, int second) {
Calendar c = Calendar.getInstance();
@@ -89,7 +91,7 @@ public PyObject Timestamp(int year, int month, int day, int hour, int minute, in
* 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
@@ -98,6 +100,7 @@ public PyObject Timestamp(int year, int month, int day, int hour, int minute, in
* @param ticks number of seconds since the epoch
* @return PyObject
*/
+ @Override
public PyObject DateFromTicks(long ticks) {
Calendar c = Calendar.getInstance();
@@ -115,7 +118,7 @@ public PyObject DateFromTicks(long ticks) {
* 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
@@ -124,6 +127,7 @@ public PyObject DateFromTicks(long ticks) {
* @param ticks number of seconds since the epoch
* @return PyObject
*/
+ @Override
public PyObject TimeFromTicks(long ticks) {
return Py.java2py(new Time(ticks * 1000));
}
@@ -132,7 +136,7 @@ public PyObject TimeFromTicks(long ticks) {
* 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
@@ -141,6 +145,7 @@ public PyObject TimeFromTicks(long ticks) {
* @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/Jython22DataHandler.java b/src/com/ziclix/python/sql/Jython22DataHandler.java
index 4fb6aaa5c..79a86743f 100644
--- a/src/com/ziclix/python/sql/Jython22DataHandler.java
+++ b/src/com/ziclix/python/sql/Jython22DataHandler.java
@@ -313,7 +313,7 @@ public PyObject getPyObject(ResultSet set, int col, int type) throws SQLExceptio
break;
default :
- throw createUnsupportedTypeSQLException(new Integer(type), col);
+ throw createUnsupportedTypeSQLException(Integer.valueOf(type), col);
}
return (set.wasNull() || (obj == null)) ? Py.None : obj;
@@ -401,7 +401,7 @@ public PyObject getPyObject(CallableStatement stmt, int col, int type) throws SQ
break;
default :
- throw createUnsupportedTypeSQLException(new Integer(type), col);
+ throw createUnsupportedTypeSQLException(Integer.valueOf(type), col);
}
return (stmt.wasNull() || (obj == null)) ? Py.None : obj;
diff --git a/src/com/ziclix/python/sql/Procedure.java b/src/com/ziclix/python/sql/Procedure.java
index 789ca3da4..793199fe9 100644
--- a/src/com/ziclix/python/sql/Procedure.java
+++ b/src/com/ziclix/python/sql/Procedure.java
@@ -235,13 +235,13 @@ public boolean isInput(int index) throws SQLException {
}
/**
- * 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
index fd9e5d6b8..514362d8d 100644
--- a/src/com/ziclix/python/sql/PyConnection.java
+++ b/src/com/ziclix/python/sql/PyConnection.java
@@ -273,7 +273,7 @@ public void close() {
* 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 @@ public void commit() {
/**
* 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/connect/Connectx.java b/src/com/ziclix/python/sql/connect/Connectx.java
index ebcd22941..d7d42ea27 100644
--- a/src/com/ziclix/python/sql/connect/Connectx.java
+++ b/src/com/ziclix/python/sql/connect/Connectx.java
@@ -58,7 +58,7 @@ public PyObject __call__(PyObject[] args, String[] keywords) {
try {
String klass = (String) parser.arg(0).__tojava__(String.class);
- datasource = Class.forName(klass).newInstance();
+ datasource = Class.forName(klass).getDeclaredConstructor().newInstance();
} catch (Exception e) {
throw zxJDBC.makeException(zxJDBC.DatabaseError, "unable to instantiate datasource");
}
@@ -113,11 +113,6 @@ public PyObject __call__(PyObject[] args, String[] keywords) {
return pc;
}
- /**
- * Method toString
- *
- * @return String
- */
@Override
public String toString() {
return String.format("", Py.id(this));
@@ -126,9 +121,9 @@ public String toString() {
/**
* Method invoke
*
- * @param Object src
- * @param String methodName
- * @param Object value
+ * @param src
+ * @param methodName
+ * @param value
*/
protected void invoke(Object src, String methodName, Object value) {
Method method = null;
diff --git a/src/com/ziclix/python/sql/handler/RowIdHandler.java b/src/com/ziclix/python/sql/handler/RowIdHandler.java
index 74f8211e8..324dda272 100644
--- a/src/com/ziclix/python/sql/handler/RowIdHandler.java
+++ b/src/com/ziclix/python/sql/handler/RowIdHandler.java
@@ -37,7 +37,7 @@ public RowIdHandler(DataHandler handler) {
* Return the name of the method that returns the last row id. The
* method can take no arguments but the return type is flexible and
* will be figured out by the Jython runtime system.
- * @return
+ * @return name of the method that returns the last row id
*/
protected abstract String getRowIdMethodName();
@@ -47,7 +47,8 @@ public RowIdHandler(DataHandler handler) {
* @return an object representing the last row id
* @throws SQLException
*/
- public PyObject getRowId(Statement stmt) throws SQLException {
+ @Override
+public PyObject getRowId(Statement stmt) throws SQLException {
Class> c = stmt.getClass();
Object o = ROWIDS.get(c);
diff --git a/src/com/ziclix/python/sql/handler/SQLServerDataHandler.java b/src/com/ziclix/python/sql/handler/SQLServerDataHandler.java
index b990f16e5..06db6895a 100644
--- a/src/com/ziclix/python/sql/handler/SQLServerDataHandler.java
+++ b/src/com/ziclix/python/sql/handler/SQLServerDataHandler.java
@@ -47,7 +47,7 @@ public Procedure getProcedure(PyCursor cursor, PyObject name) throws SQLExceptio
/**
* 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
index 12a623d70..f6f4c65b1 100644
--- 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/Pipe.java b/src/com/ziclix/python/sql/pipe/Pipe.java
index a9dc81c49..6bb95cfe3 100644
--- a/src/com/ziclix/python/sql/pipe/Pipe.java
+++ b/src/com/ziclix/python/sql/pipe/Pipe.java
@@ -30,7 +30,7 @@ public Pipe() {
}
/**
- * 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
@@ -87,8 +87,8 @@ public PyObject pipe(Source source, Sink sink) {
// the purpose of the assert, but there's no need to create the buffer if I don't need it and I still
// want to throw the AssertionError if required
if ((sourceRunner.getCount() - sinkRunner.getCount()) != 0) {
- Integer[] counts = {new Integer(sourceRunner.getCount()),
- new Integer(sinkRunner.getCount())};
+ Integer[] counts = {Integer.valueOf(sourceRunner.getCount()),
+ Integer.valueOf(sinkRunner.getCount())};
String msg = zxJDBC.getString("inconsistentRowCount", counts);
Py.assert_(Py.Zero, Py.newString(msg));
@@ -144,6 +144,7 @@ public int getCount() {
/**
* Method run
*/
+ @Override
public void run() {
try {
@@ -216,6 +217,7 @@ public SourceRunner(Queue queue, Source source) {
*
* @throws InterruptedException
*/
+ @Override
protected void pipe() throws InterruptedException {
PyObject row = Py.None;
@@ -270,6 +272,7 @@ public SinkRunner(Queue queue, Sink sink) {
*
* @throws InterruptedException
*/
+ @Override
protected void pipe() throws InterruptedException {
PyObject row = Py.None;
diff --git a/src/com/ziclix/python/sql/pipe/Sink.java b/src/com/ziclix/python/sql/pipe/Sink.java
index c0ec6e9d5..322e66455 100644
--- a/src/com/ziclix/python/sql/pipe/Sink.java
+++ b/src/com/ziclix/python/sql/pipe/Sink.java
@@ -24,9 +24,9 @@ public interface Sink {
/**
* 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
index 7a11ccffb..8664280e6 100644
--- a/src/com/ziclix/python/sql/pipe/Source.java
+++ b/src/com/ziclix/python/sql/pipe/Source.java
@@ -28,7 +28,7 @@ public interface Source {
* 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/pipe/csv/CSVString.java b/src/com/ziclix/python/sql/pipe/csv/CSVString.java
index 1eae3967f..69b0f5098 100644
--- a/src/com/ziclix/python/sql/pipe/csv/CSVString.java
+++ b/src/com/ziclix/python/sql/pipe/csv/CSVString.java
@@ -44,17 +44,16 @@ public static String toCSV(String string, String delimiter) {
}
/**
- * Returns a new string resulting from replacing the first occurrence, or all occurrences,
- * of search string in this string with replace string.
- * If the string search does not occur in the character sequence represented by this object,
- * then this string is returned.
+ * Returns a new string resulting from replacing the first occurrence, or all occurrences, of
+ * search string in this string with replace string. If the string search does not occur in the
+ * character sequence represented by this object, then this string is returned.
*
- * @param search the old string
- * @param replace the new string
- * @param all=true all occurrences of the search string are replaced
- * @param all=false only the first occurrence of the search string is replaced
- * @return a string derived from this string by replacing the first occurrence,
- * or every occurrence of search with replace.
+ * @param search the old string
+ * @param replace the new string
+ * @param all if {@code true} all occurrences of the search string are replaced; if
+ * {@code false} only the first occurrence
+ * @return a string derived from this string by replacing the first occurrence, or every
+ * occurrence, of {@code search} with {@code replace}.
*/
public static String replace(String original, String search, String replace, boolean all) {
diff --git a/src/com/ziclix/python/sql/util/BCP.java b/src/com/ziclix/python/sql/util/BCP.java
index 01a5b9ed3..6df774281 100644
--- 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 @@ public BCP(PyConnection source, PyConnection destination, int batchsize) {
this.batchsize = batchsize;
this.queuesize = 0;
}
-
+
/**
* Field __methods__
*/
@@ -99,6 +98,7 @@ public BCP(PyConnection source, PyConnection destination, int batchsize) {
*
* @return a string representation of the object.
*/
+ @Override
public String toString() {
return "";
}
@@ -109,6 +109,7 @@ public String toString() {
* @param name
* @param value
*/
+ @Override
public void __setattr__(String name, PyObject value) {
if ("destinationDataHandler".equals(name)) {
@@ -130,6 +131,7 @@ public void __setattr__(String name, PyObject value) {
* @param name
* @return the attribute for the given name
*/
+ @Override
public PyObject __findattr_ex__(String name) {
if ("destinationDataHandler".equals(name)) {
@@ -206,7 +208,7 @@ public boolean refersDirectlyTo(PyObject ob) {
}
/**
- * @copyright 2001 brian zimmer
+ * Copyright 2001 brian zimmer
*/
class BCPFunc extends PyBuiltinMethodSet {
@@ -224,6 +226,7 @@ class BCPFunc extends PyBuiltinMethodSet {
* @param arg
* @return PyObject
*/
+ @Override
public PyObject __call__(PyObject arg) {
BCP bcp = (BCP) __self__;
@@ -246,6 +249,7 @@ public PyObject __call__(PyObject arg) {
}
}
+ @Override
public PyObject __call__(PyObject arga, PyObject argb) {
BCP bcp = (BCP) __self__;
@@ -269,6 +273,7 @@ public PyObject __call__(PyObject arga, PyObject argb) {
}
}
+ @Override
public PyObject __call__(PyObject arga, PyObject argb, PyObject argc) {
BCP bcp = (BCP) __self__;
@@ -292,6 +297,7 @@ public PyObject __call__(PyObject arga, PyObject argb, PyObject argc) {
}
}
+ @Override
public PyObject __call__(PyObject[] args, String[] keywords) {
BCP bcp = (BCP) __self__;
diff --git a/src/com/ziclix/python/sql/zxJDBC.java b/src/com/ziclix/python/sql/zxJDBC.java
index 3b1a8b3ae..25cd60cec 100644
--- 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")
@@ -223,7 +223,8 @@ protected static void _addConnectors(PyObject dict) throws PyException {
String className = props.getProperty(name).trim();
try {
- connector = (PyObject) Class.forName(className).newInstance();
+ connector =
+ (PyObject) Class.forName(className).getDeclaredConstructor().newInstance();
dict.__setitem__(name, connector);
Py.writeComment("zxJDBC", "loaded connector [" + className + "] as [" + name
+ "]");
@@ -326,7 +327,7 @@ public static PyException makeException(String msg) {
* @return PyException
*/
public static PyException makeException(PyObject type, String msg) {
- return Py.makeException(type, msg == null ? Py.EmptyString : Py.newString(msg));
+ return Py.makeException(type, msg == null ? Py.EmptyString : Py.newStringOrUnicode(msg));
}
/**
@@ -419,7 +420,6 @@ public static PyException makeException(PyObject type, Throwable t, int rowIndex
*
* @param classname
* @param superclass
- * @param classCodeName
* @return PyObject
*/
protected static PyObject buildClass(String classname, PyObject superclass) {
diff --git a/src/org/python/Version.java b/src/org/python/Version.java
index e06e16224..e16b0628b 100644
--- a/src/org/python/Version.java
+++ b/src/org/python/Version.java
@@ -121,7 +121,7 @@ public static String getBuildInfo() {
* Describe the current Java VM.
*/
public static String getVM() {
- return String.format("\n[%s (%s)]", System.getProperty("java.vm.name"),
+ return String.format("[%s (%s)]", System.getProperty("java.vm.name"),
System.getProperty("java.vm.vendor"));
}
@@ -130,7 +130,7 @@ public static String getVM() {
* the Java VM).
*/
public static String getVersion() {
- return String.format("%.80s (%.80s) %.80s", PY_VERSION, getBuildInfo(), getVM());
+ return String.format("%.80s (%.80s)\n%.80s", PY_VERSION, getBuildInfo(), getVM());
}
public static Set getDefaultCodeFlags() {
diff --git a/src/org/python/antlr/ASTDerived.java b/src/org/python/antlr/ASTDerived.java
new file mode 100644
index 000000000..f6b2e37a0
--- /dev/null
+++ b/src/org/python/antlr/ASTDerived.java
@@ -0,0 +1,1175 @@
+/* Generated file, do not modify. See jython/src/templates/gderived.py. */
+package org.python.antlr;
+
+import java.io.Serializable;
+import org.python.core.*;
+import org.python.core.finalization.FinalizeTrigger;
+import org.python.core.finalization.FinalizablePyObjectDerived;
+
+public class ASTDerived extends AST implements Slotted,FinalizablePyObjectDerived,TraverseprocDerived {
+
+ public PyObject getSlot(int index) {
+ return slots[index];
+ }
+
+ public void setSlot(int index,PyObject value) {
+ slots[index]=value;
+ }
+
+ private PyObject[]slots;
+
+ public void __del_derived__() {
+ PyType self_type=getType();
+ PyObject impl=self_type.lookup("__del__");
+ if (impl!=null) {
+ impl.__get__(this,self_type).__call__();
+ }
+ }
+
+ public void __ensure_finalizer__() {
+ FinalizeTrigger.ensureFinalizer(this);
+ }
+
+ /* TraverseprocDerived implementation */
+ public int traverseDerived(Visitproc visit,Object arg) {
+ int retVal;
+ for(int i=0;i0?1:0;
+ }
+
+ public boolean __nonzero__() {
+ PyType self_type=getType();
+ PyObject impl=self_type.lookup("__nonzero__");
+ if (impl==null) {
+ impl=self_type.lookup("__len__");
+ if (impl==null)
+ return super.__nonzero__();
+ }
+ PyObject o=impl.__get__(this,self_type).__call__();
+ Class c=o.getClass();
+ if (c!=PyInteger.class&&c!=PyBoolean.class) {
+ throw Py.TypeError(String.format("__nonzero__ should return bool or int, returned %s",self_type.getName()));
+ }
+ return o.__nonzero__();
+ }
+
+ public boolean __contains__(PyObject o) {
+ PyType self_type=getType();
+ PyObject impl=self_type.lookup("__contains__");
+ if (impl==null)
+ return super.__contains__(o);
+ return impl.__get__(this,self_type).__call__(o).__nonzero__();
+ }
+
+ public int __len__() {
+ PyType self_type=getType();
+ PyObject impl=self_type.lookup("__len__");
+ if (impl!=null) {
+ PyObject res=impl.__get__(this,self_type).__call__();
+ return res.asInt();
+ }
+ return super.__len__();
+ }
+
+ public PyObject __iter__() {
+ PyType self_type=getType();
+ PyObject impl=self_type.lookup("__iter__");
+ if (impl!=null)
+ return impl.__get__(this,self_type).__call__();
+ impl=self_type.lookup("__getitem__");
+ if (impl==null)
+ return super.__iter__();
+ return new PySequenceIter(this);
+ }
+
+ public PyObject __iternext__() {
+ PyType self_type=getType();
+ PyObject impl=self_type.lookup("next");
+ if (impl!=null) {
+ try {
+ return impl.__get__(this,self_type).__call__();
+ } catch (PyException exc) {
+ if (exc.match(Py.StopIteration))
+ return null;
+ throw exc;
+ }
+ }
+ return super.__iternext__(); // ???
+ }
+
+ public PyObject __finditem__(PyObject key) { // ???
+ PyType self_type=getType();
+ PyObject impl=self_type.lookup("__getitem__");
+ if (impl!=null)
+ try {
+ return impl.__get__(this,self_type).__call__(key);
+ } catch (PyException exc) {
+ if (exc.match(Py.LookupError))
+ return null;
+ throw exc;
+ }
+ return super.__finditem__(key);
+ }
+
+ public PyObject __finditem__(int key) {
+ PyType self_type=getType();
+ PyObject impl=self_type.lookup("__getitem__");
+ if (impl!=null)
+ try {
+ return impl.__get__(this,self_type).__call__(new PyInteger(key));
+ } catch (PyException exc) {
+ if (exc.match(Py.LookupError))
+ return null;
+ throw exc;
+ }
+ return super.__finditem__(key);
+ }
+
+ public PyObject __getitem__(PyObject key) {
+ // Same as __finditem__, without swallowing LookupErrors. This allows
+ // __getitem__ implementations written in Python to raise custom
+ // exceptions (such as subclasses of KeyError).
+ //
+ // We are forced to duplicate the code, instead of defining __finditem__
+ // in terms of __getitem__. That's because PyObject defines __getitem__
+ // in terms of __finditem__. Therefore, we would end with an infinite
+ // loop when self_type.lookup("__getitem__") returns null:
+ //
+ // __getitem__ -> super.__getitem__ -> __finditem__ -> __getitem__
+ //
+ // By duplicating the (short) lookup and call code, we are safe, because
+ // the call chains will be:
+ //
+ // __finditem__ -> super.__finditem__
+ //
+ // __getitem__ -> super.__getitem__ -> __finditem__ -> super.__finditem__
+
+ PyType self_type=getType();
+ PyObject impl=self_type.lookup("__getitem__");
+ if (impl!=null)
+ return impl.__get__(this,self_type).__call__(key);
+ return super.__getitem__(key);
+ }
+
+ public void __setitem__(PyObject key,PyObject value) { // ???
+ PyType self_type=getType();
+ PyObject impl=self_type.lookup("__setitem__");
+ if (impl!=null) {
+ impl.__get__(this,self_type).__call__(key,value);
+ return;
+ }
+ super.__setitem__(key,value);
+ }
+
+ public PyObject __getslice__(PyObject start,PyObject stop,PyObject step) { // ???
+ if (step!=null) {
+ return __getitem__(new PySlice(start,stop,step));
+ }
+ PyType self_type=getType();
+ PyObject impl=self_type.lookup("__getslice__");
+ if (impl!=null) {
+ PyObject[]indices=PySlice.indices2(this,start,stop);
+ return impl.__get__(this,self_type).__call__(indices[0],indices[1]);
+ }
+ return super.__getslice__(start,stop,step);
+ }
+
+ public void __setslice__(PyObject start,PyObject stop,PyObject step,PyObject value) {
+ if (step!=null) {
+ __setitem__(new PySlice(start,stop,step),value);
+ return;
+ }
+ PyType self_type=getType();
+ PyObject impl=self_type.lookup("__setslice__");
+ if (impl!=null) {
+ PyObject[]indices=PySlice.indices2(this,start,stop);
+ impl.__get__(this,self_type).__call__(indices[0],indices[1],value);
+ return;
+ }
+ super.__setslice__(start,stop,step,value);
+ }
+
+ public void __delslice__(PyObject start,PyObject stop,PyObject step) {
+ if (step!=null) {
+ __delitem__(new PySlice(start,stop,step));
+ return;
+ }
+ PyType self_type=getType();
+ PyObject impl=self_type.lookup("__delslice__");
+ if (impl!=null) {
+ PyObject[]indices=PySlice.indices2(this,start,stop);
+ impl.__get__(this,self_type).__call__(indices[0],indices[1]);
+ return;
+ }
+ super.__delslice__(start,stop,step);
+ }
+
+ public void __delitem__(PyObject key) { // ???
+ PyType self_type=getType();
+ PyObject impl=self_type.lookup("__delitem__");
+ if (impl!=null) {
+ impl.__get__(this,self_type).__call__(key);
+ return;
+ }
+ super.__delitem__(key);
+ }
+
+ public PyObject __call__(PyObject args[],String keywords[]) {
+ PyType self_type=getType();
+ PyObject impl=self_type.lookup("__call__");
+ if (impl!=null) {
+ return impl.__get__(this,self_type).__call__(args,keywords);
+ }
+ return super.__call__(args,keywords);
+ }
+
+ public PyObject __findattr_ex__(String name) {
+ return Deriveds.__findattr_ex__(this,name);
+ }
+
+ public void __setattr__(String name,PyObject value) {
+ PyType self_type=getType();
+ PyObject impl=self_type.lookup("__setattr__");
+ if (impl!=null) {
+ impl.__get__(this,self_type).__call__(PyString.fromInterned(name),value);
+ //CPython does not support instance-acquired finalizers.
+ //So we don't check for __del__ here.
+ return;
+ }
+ super.__setattr__(name,value);
+ }
+
+ public void __delattr__(String name) {
+ PyType self_type=getType();
+ PyObject impl=self_type.lookup("__delattr__");
+ if (impl!=null) {
+ impl.__get__(this,self_type).__call__(PyString.fromInterned(name));
+ return;
+ }
+ super.__delattr__(name);
+ }
+
+ public PyObject __get__(PyObject obj,PyObject type) {
+ PyType self_type=getType();
+ PyObject impl=self_type.lookup("__get__");
+ if (impl!=null) {
+ if (obj==null)
+ obj=Py.None;
+ if (type==null)
+ type=Py.None;
+ return impl.__get__(this,self_type).__call__(obj,type);
+ }
+ return super.__get__(obj,type);
+ }
+
+ public void __set__(PyObject obj,PyObject value) {
+ PyType self_type=getType();
+ PyObject impl=self_type.lookup("__set__");
+ if (impl!=null) {
+ impl.__get__(this,self_type).__call__(obj,value);
+ return;
+ }
+ super.__set__(obj,value);
+ }
+
+ public void __delete__(PyObject obj) {
+ PyType self_type=getType();
+ PyObject impl=self_type.lookup("__delete__");
+ if (impl!=null) {
+ impl.__get__(this,self_type).__call__(obj);
+ return;
+ }
+ super.__delete__(obj);
+ }
+
+ public PyObject __pow__(PyObject other,PyObject modulo) {
+ PyType self_type=getType();
+ PyObject impl=self_type.lookup("__pow__");
+ if (impl!=null) {
+ PyObject res;
+ if (modulo==null) {
+ res=impl.__get__(this,self_type).__call__(other);
+ } else {
+ res=impl.__get__(this,self_type).__call__(other,modulo);
+ }
+ if (res==Py.NotImplemented)
+ return null;
+ return res;
+ }
+ return super.__pow__(other,modulo);
+ }
+
+ public void dispatch__init__(PyObject[]args,String[]keywords) {
+ Deriveds.dispatch__init__(this,args,keywords);
+ }
+
+ public PyObject __index__() {
+ PyType self_type=getType();
+ PyObject impl=self_type.lookup("__index__");
+ if (impl!=null) {
+ PyObject res=impl.__get__(this,self_type).__call__();
+ if (res instanceof PyInteger||res instanceof PyLong) {
+ return res;
+ }
+ throw Py.TypeError(String.format("__index__ returned non-(int,long) (type %s)",res.getType().fastGetName()));
+ }
+ return super.__index__();
+ }
+
+ public Object __tojava__(Class c) {
+ // If we are not being asked by the "default" conversion to java, then
+ // we can provide this as the result, as long as it is a instance of the
+ // specified class. Without this, derived.__tojava__(PyObject.class)
+ // would broke. (And that's not pure speculation: PyReflectedFunction's
+ // ReflectedArgs asks for things like that).
+ if ((c!=Object.class)&&(c!=Serializable.class)&&(c.isInstance(this))) {
+ return this;
+ }
+ // Otherwise, we call the derived __tojava__, if it exists:
+ PyType self_type=getType();
+ PyObject impl=self_type.lookup("__tojava__");
+ if (impl!=null) {
+ PyObject delegate=impl.__get__(this,self_type).__call__(Py.java2py(c));
+ if (delegate!=this)
+ return delegate.__tojava__(Object.class);
+ }
+ return super.__tojava__(c);
+ }
+
+ public Object __coerce_ex__(PyObject o) {
+ PyType self_type=getType();
+ PyObject impl=self_type.lookup("__coerce__");
+ if (impl!=null) {
+ PyObject res=impl.__get__(this,self_type).__call__(o);
+ if (res==Py.NotImplemented)
+ return Py.None;
+ if (!(res instanceof PyTuple))
+ throw Py.TypeError("__coerce__ didn't return a 2-tuple");
+ return((PyTuple)res).getArray();
+ }
+ return super.__coerce_ex__(o);
+ }
+
+ public String toString() {
+ PyType self_type=getType();
+ PyObject impl=self_type.lookup("__repr__");
+ if (impl!=null) {
+ PyObject res=impl.__get__(this,self_type).__call__();
+ if (!(res instanceof PyString))
+ throw Py.TypeError("__repr__ returned non-string (type "+res.getType().fastGetName()+")");
+ return((PyString)res).toString();
+ }
+ return super.toString();
+ }
+
+}
diff --git a/src/org/python/antlr/BaseParser.java b/src/org/python/antlr/BaseParser.java
index a1c82a3ca..8fd5847c6 100644
--- a/src/org/python/antlr/BaseParser.java
+++ b/src/org/python/antlr/BaseParser.java
@@ -3,7 +3,6 @@
import org.antlr.runtime.CharStream;
import org.antlr.runtime.CommonTokenStream;
import org.antlr.runtime.RecognitionException;
-import org.antlr.runtime.Token;
import org.python.antlr.base.mod;
public class BaseParser {
diff --git a/src/org/python/antlr/GrammarActions.java b/src/org/python/antlr/GrammarActions.java
index a5c42ce72..14d56c2d3 100644
--- a/src/org/python/antlr/GrammarActions.java
+++ b/src/org/python/antlr/GrammarActions.java
@@ -129,10 +129,10 @@ List makeBases(expr etype) {
return result;
}
- List makeNames(List names) {
+ List makeNames(List names) {
List s = new ArrayList();
- for(int i=0;i makeNameNodes(List names) {
List s = new ArrayList();
- for (int i=0; i{@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 ...
-
+
+ * While Java String objects are limited only by the address range of arrays, the class file
+ * standard only supports literals representable in at most 65535 bytes of modified UTF-8. This
+ * method us used only with base64 Strings (therefore ASCII without nulls) and so each character
+ * occupies exactly 1 byte in the class file after encoding to UTF-8.
+ *
+ * To work within the 65535 byte limitation, the {@code code_str} is split into several literals
+ * with the following naming-scheme:
+ *
+ *
The marker-interface 'ContainsPyBytecode' indicates that a class contains (static final)
+ * literals of the following scheme:
+ *
a prefix of '___' indicates a bytecode-containing string literal
+ *
a number indicating the number of parts follows
+ *
'0_' indicates that no splitting occurred
+ *
otherwise another number follows, naming the index of the literal
+ *
indexing starts at 0
+ *
+ * Examples:
+ *
+ *
{@code ___0_method1} contains bytecode for method1
+ *
{@code ___2_0_method2} contains first part of method2's bytecode
+ *
{@code ___2_1_method2} contains second part of method2's bytecode
+ *
+ * Note that this approach is provisional. In future, Jython might contain the bytecode directly
+ * as bytecode-objects. The current approach was feasible with far less complicated JVM
+ * bytecode-manipulation, but needs special treatment after class-loading.
+ *
+ * @param name of the method or function being generated
+ * @param code_str Base64 encoded CPython byte code
+ * @param module currently being defined as a class file
+ * @throws java.io.IOException
+ */
+ private static void insert_code_str_to_classfile(String name, String code_str, Module module)
+ throws java.io.IOException {
+ if (code_str.length() <= maxLiteral) {
+ // This can go as a single literal
+ module.classfile.addFinalStringLiteral("___0_" + name, code_str);
+ } else {
+ // We need to split the code into several literals.
+ int splits = code_str.length() / maxLiteral;
+ if (code_str.length() % maxLiteral > 0) {
+ ++splits;
+ }
+ int pos = 0, i = 0;
+ for (; pos + maxLiteral <= code_str.length(); ++i) {
+ module.classfile.addFinalStringLiteral("___" + splits + "_" + i + "_" + name,
+ code_str.substring(pos, pos + maxLiteral));
+ pos += maxLiteral;
+ }
+ if (i < splits) {
+ module.classfile.addFinalStringLiteral("___" + splits + "_" + i + "_" + name,
+ code_str.substring(pos));
+ }
+ }
+ }
+
+ /**
+ * Create and write a Python module as a Java class file.
+ *
+ * @param node AST of the module to write
+ * @param ostream stream onto which to write it
+ * @param name
+ * @param filename
+ * @param linenumbers
+ * @param printResults
+ * @param cflags
+ * @param mtime
+ * @throws Exception
+ */
+ public static void compile(mod node, OutputStream ostream, String name, String filename,
+ boolean linenumbers, boolean printResults, CompilerFlags cflags, long mtime)
+ throws Exception {
+
+ try {
+ Module module = new Module(name, filename, linenumbers, mtime);
+ _module_init(node, module, printResults, cflags);
+ module.write(ostream);
+
+ } catch (MethodTooLargeException re) {
+ PyBytecode btcode = loadPyBytecode(filename, true);
+ int thresh = 22000;
+ /*
+ * No idea, how to determine at this point if a method is oversized, so we just try a
+ * threshold regarding Python code-length, while JVM restriction is actually about Java
+ * bytecode length. Anyway; given that code-lengths are strongly related, this should
+ * work well enough.
+ */
+ while (true) { // Always enjoy to write a line like this :)
+ try {
+ List largest_m_codes = new ArrayList<>();
+ Stack buffer = new Stack<>();
+ // HashSet allCodes = new HashSet<>();
+ buffer.push(btcode);
+ // allCodes.add(btcode);
+
+ while (!buffer.isEmpty()) {
+ /*
+ * Probably this cannot yield cycles, so cycle-proof stuff is out-commented
+ * for now. (everything regarding 'allCodes')
+ */
+ PyBytecode bcode = buffer.pop();
+ if (bcode.co_code.length > thresh) {
+ largest_m_codes.add(bcode);
+ } else {
+ /*
+ * If a function needs to be represented as CPython bytecode, we create
+ * all inner PyCode-items (classes, functions, methods) also as CPython
+ * bytecode implicitly, so no need to look at them individually. Maybe
+ * we can later optimize this such that inner methods can be
+ * JVM-bytecode as well (if not oversized themselves).
+ */
+ for (PyObject item : bcode.co_consts) {
+ if (item instanceof PyBytecode /* && !allCodes.contains(item) */) {
+ PyBytecode mpbc = (PyBytecode) item;
+ buffer.push(mpbc);
+ // allCodes.add(mpbc);
+ }
+ }
+ }
+ }
+
+ Module module = new Module(name, filename, linenumbers, mtime);
+
+ module.oversized_methods = new Hashtable<>(largest_m_codes.size());
+ int ov_id = 0;
+ String name_id;
+
+ for (PyBytecode largest_m_code : largest_m_codes) {
+ if (!PyCodeConstant.isJavaIdentifier(largest_m_code.co_name)) {
+ name_id = "f$_" + ov_id++;
+ } else {
+ name_id = largest_m_code.co_name + "$_" + ov_id++;
+ }
+ if (largest_m_code.co_name.equals("")) {
+ /*
+ * In Jython's opinion module begins at line 0 (while CPython reports
+ * line 1)
+ */
+ module.oversized_methods.put(largest_m_code.co_name + 0, name_id);
+ } else {
+ module.oversized_methods.put(
+ largest_m_code.co_name + largest_m_code.co_firstlineno,
+ name_id);
+ }
+
+ String code_str = serializePyBytecode(largest_m_code);
+ insert_code_str_to_classfile(name_id, code_str, module);
+ }
+
+ module.classfile.addInterface(p(org.python.core.ContainsPyBytecode.class));
+
+ _module_init(node, module, printResults, cflags);
+ module.write(ostream);
+
+ break;
+
+ } catch (MethodTooLargeException e) {
+ thresh -= 1000;
+ }
+ if (thresh < 10000) {
+ /*
+ * This value should be well feasible by JVM-bytecode, so something else must be
+ * wrong.
+ */
+ throw new RuntimeException(
+ "For unknown reason, too large method code couldn't be resolved"
+ + "\nby PyBytecode-approach:\n" + filename);
+ }
+ }
+ }
}
public void emitNum(Num node, Code code) throws Exception {
@@ -720,7 +1135,7 @@ public boolean emitPrimitiveArraySetters(java.util.List extends PythonTree> no
code.iconst(n);
code.anewarray(p(PyObject.class));
for (int i = 0; i < num_setters; i++) {
- Code setter = this.classfile.addMethod("set$$" + setter_count, //
+ Code setter = this.classfile.addMethod("set$$" + setter_count,
sig(Void.TYPE, PyObject[].class), ACC_STATIC | ACC_PRIVATE);
for (int j = 0; (j < MAX_SETTINGS_PER_SETTER)
diff --git a/src/org/python/compiler/ProxyMaker.java b/src/org/python/compiler/ProxyMaker.java
index 5fac4256b..10acf6c8d 100644
--- a/src/org/python/compiler/ProxyMaker.java
+++ b/src/org/python/compiler/ProxyMaker.java
@@ -16,7 +16,6 @@
import static org.python.util.CodegenUtils.p;
import static org.python.util.CodegenUtils.sig;
-
public class ProxyMaker extends ProxyCodeHelpers implements ClassConstants, Opcodes
{
protected final Class> superclass;
@@ -33,8 +32,7 @@ public class ProxyMaker extends ProxyCodeHelpers implements ClassConstants, Opco
* org.python.proxies.(superclassName) with superclass as an
* implemented interface or extended class, depending on the its type.
*
- * @deprecated - Use {@link ProxyMaker#ProxyMaker(String, Class, Class[])
-
+ * @deprecated - Use {@link ProxyMaker#ProxyMaker(String, Class, Class[])}
*/
@Deprecated
public ProxyMaker(String superclassName, Class> superclass) {
@@ -265,8 +263,9 @@ public void callMethod(Code code,
doNullReturn(code, ret);
code.freeLocal(excLocal);
- if (exception == Throwable.class)
+ if (exception == Throwable.class) {
throwableFound = true;
+ }
}
if (!throwableFound) {
@@ -293,7 +292,7 @@ public void addMethod(Method method, int access) throws Exception {
addMethod(method.getName(), method.getReturnType(), method.getParameterTypes(),
method.getExceptionTypes(), access, method.getDeclaringClass());
}
-
+
/**
* Adds a method of the given name to the class being implemented. If
* declaringClass is null, the generated method will expect to find an object of
@@ -310,21 +309,20 @@ public void addMethod(String name,
addMethod(name, name, ret, parameters, exceptions, access, declaringClass, null, null);
}
-
+
/**
* Generates and adds a proxy method to the proxy class
- *
- * @param name: name of the java method
- * @param pyName: name of the python method to which the java method
- * proxies (useful for clamped objects)
- *
- * @param ret: return type
- * @param parameters: parameter types
- * @param exceptions: throwable exception types
+ *
+ * @param name of the java method
+ * @param pyName name of the python method to which the java method proxies (useful for clamped
+ * objects)
+ * @param ret return type
+ * @param parameters parameter types
+ * @param exceptions throwable exception types
* @param access
* @param declaringClass
- * @param methodAnnotations: method annotations
- * @param parameterAnnotations: parameter annotations
+ * @param methodAnnotations method annotations
+ * @param parameterAnnotations parameter annotations
* @throws Exception
*/
public void addMethod(String name,
@@ -337,7 +335,7 @@ public void addMethod(String name,
AnnotationDescr[] methodAnnotations,
AnnotationDescr[][]parameterAnnotations) throws Exception {
boolean isAbstract = false;
-
+
if (Modifier.isAbstract(access)) {
access = access & ~Modifier.ABSTRACT;
isAbstract = true;
@@ -400,7 +398,7 @@ public void addMethod(String name,
doNullReturn(code, ret);
}
}
-
+
/**
* A constructor that is also a method (!)
*/
@@ -412,7 +410,7 @@ public void addConstructorMethodCode(String pyName,
Code code) throws Exception {
code.aload(0);
code.ldc(pyName);
-
+
int tmp = code.getLocal("org/python/core/PyObject");
code.invokestatic("org/python/compiler/ProxyMaker", "findPython",
makeSig($pyObj, $pyProxy, $str));
@@ -421,7 +419,7 @@ public void addConstructorMethodCode(String pyName,
callMethod(code, "", parameters, Void.TYPE, exceptions);
}
-
+
private String methodString(Method m) {
StringBuffer buf = new StringBuffer(m.getName());
buf.append(":");
@@ -500,7 +498,7 @@ public void addConstructors(Class> c) throws Exception {
addConstructor(name, parameters, Void.TYPE, makeSig(Void.TYPE, parameters), access);
}
}
-
+
protected void addClassAnnotation(AnnotationDescr annotation) {
classfile.addClassAnnotation(annotation);
}
@@ -635,21 +633,21 @@ public void build() throws Exception {
addProxy();
visitConstructors();
classfile.addInterface("org/python/core/PyProxy");
-
+
visitClassAnnotations();
visitMethods();
doConstants();
addClassDictInit();
}
-
+
/**
* Visits all methods declared on the given class and classes in its inheritance hierarchy.
* Methods visible to subclasses are added to seen.
*/
protected void visitMethods(Class> klass) throws Exception {
for (Method method : klass.getDeclaredMethods()) {
-
-
+
+
// make sure we have only one name + signature pair available per method
if (!namesAndSigs.add(methodString(method))) {
continue;
@@ -689,9 +687,10 @@ protected void visitMethods(Class> klass) throws Exception {
}
/**
- * Called for every method on the proxy's superclass and interfaces that can be overriden by the
- * proxy class. If the proxy wants to perform Python lookup and calling for the method,
- * {@link #addMethod(Method)} should be called. For abstract methods, addMethod must be called.
+ * Called for every method on the proxy's superclass and interfaces that can be overridden by
+ * the proxy class. If the proxy wants to perform Python lookup and calling,
+ * {@link #addMethod(Method, int)} or one of its more complex forms should be called. For
+ * abstract methods, {@code addMethod} must be called.
*/
protected void visitMethod(Method method) throws Exception {
addMethod(method, method.getModifiers());
@@ -708,14 +707,14 @@ protected void visitMethods() throws Exception {
visitMethods(iface);
}
}
-
+
/** Adds a constructor that calls through to superclass. */
protected void addConstructor(Class>[] parameters, int access) throws Exception {
String sig = makeSig(Void.TYPE, parameters);
Code code = classfile.addMethod("", sig, access);
callSuper(code, "", mapClass(superclass), parameters, Void.TYPE, true);
}
-
+
/**
* Called for every constructor on the proxy's superclass that can be overridden by
* the proxy class.
@@ -747,16 +746,15 @@ protected void callInitProxy(Class>[] parameters, Code code) throws Exception
code.visitMethodInsn(INVOKEVIRTUAL, classfile.name, "__initProxy__", makeSig("V", $objArr), false);
code.visitInsn(RETURN);
}
-
+
/**
* Visits constructors from this proxy's superclass.
*/
protected void visitConstructors() throws Exception {
addConstructors(superclass);
}
-
+
protected void visitClassAnnotations() throws Exception {
// ProxyMaker itself does nothing with class annotations for now
}
-
}
diff --git a/src/org/python/compiler/ScopeInfo.java b/src/org/python/compiler/ScopeInfo.java
index 863f5bf9e..381d12b3e 100644
--- a/src/org/python/compiler/ScopeInfo.java
+++ b/src/org/python/compiler/ScopeInfo.java
@@ -1,12 +1,16 @@
+// (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 java.util.logging.Level;
+import java.util.logging.Logger;
import org.python.antlr.ParseException;
import org.python.antlr.PythonTree;
@@ -15,38 +19,53 @@
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 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");
- System.err.print(" ");
+ if (LOGGER.isLoggable(Level.FINE)) {
+ StringBuilder m = new StringBuilder(100);
+ for (int i = 0; i < level; i++) {
+ m.append(' ');
+ }
+ 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(' ');
+ }
+ LOGGER.fine(m.toString());
}
- 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 +92,22 @@ public ScopeInfo(String name, PythonTree node, int level, int kind,
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 +135,7 @@ public void addUsed(String name) {
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 +147,11 @@ public void addUsed(String name) {
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 +159,26 @@ public void cook(ScopeInfo up, int distance, CompilationContext ctxt) throws Exc
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 +192,11 @@ public void cook(ScopeInfo up, int distance, CompilationContext ctxt) throws Exc
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 +204,9 @@ public void cook(ScopeInfo up, int distance, CompilationContext ctxt) throws Exc
}
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 +222,11 @@ public void cook(ScopeInfo up, int distance, CompilationContext ctxt) throws Exc
// 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 +234,10 @@ else if(func_level > 1 && some_free)
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 +253,18 @@ private void dynastuff_trouble(boolean inner_free, CompilationContext ctxt) thro
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 +272,19 @@ public void setup_closure(ScopeInfo up){
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 +296,19 @@ public void setup_closure(ScopeInfo up){
@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;
}
diff --git a/src/org/python/compiler/ScopesCompiler.java b/src/org/python/compiler/ScopesCompiler.java
index ff51cdeb9..6dd474bdd 100644
--- a/src/org/python/compiler/ScopesCompiler.java
+++ b/src/org/python/compiler/ScopesCompiler.java
@@ -285,7 +285,7 @@ public Object visitName(Name node) throws Exception {
@Override
public Object visitListComp(ListComp node) throws Exception {
- String tmp = "_[" + node.getLine() + "_" + node.getCharPositionInLine()
+ String tmp = "_[" + node.getLineno() + "_" + node.getCol_offset()
+ "]";
cur.addBound(tmp);
traverse(node);
@@ -328,7 +328,7 @@ private Object visitInternalGenerators(expr node, expr elt, java.util.List
+ * Since AbstractArray can support a clone method, this facilitates subclasses that want to
+ * implement clone (poor man's cloning). Subclasses can then do this:
+ *
+ *
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 @@ public void clear() {
this.modCountIncr = 0;
if (this.size != 0) {
this.modCountIncr = 1;
- clearRange(0, this.size);
+ clearRange(0, this.size);
setSize(0);
}
@@ -400,43 +400,43 @@ public void replaceSubArray(Object array, int atIndex) {
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 @@ public void replaceSubArray(int thisStart, int thisStop, Object srcArray,
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 @@ public void replaceSubArray(int thisStart, int thisStop, Object srcArray,
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 @@ public void setSize(int count) {
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 @@ public int getSize() {
*
* @see java.lang.Object#toString()
*/
+ @Override
public String toString() {
StringBuilder buf = new StringBuilder();
buf.append("[");
@@ -543,7 +544,9 @@ public String toString() {
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 @@ protected void trimToSize() {
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/AbstractDict.java b/src/org/python/core/AbstractDict.java
index 84f6ec7c8..ad600cf20 100644
--- a/src/org/python/core/AbstractDict.java
+++ b/src/org/python/core/AbstractDict.java
@@ -6,6 +6,7 @@
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
+import java.util.Map.Entry;
import java.util.Set;
public abstract class AbstractDict extends PyObject {
@@ -65,23 +66,80 @@ static Object tojava(Object val) {
return val == null ? null : ((PyObject)val).__tojava__(Object.class);
}
- static class ValuesIter extends PyIterator {
-
- private final Iterator iterator;
+ /**
+ * Only valid for T=PyObject.
+ * Subclasses can use a different T, but then have to
+ * override __iternext__() accordingly.
+ */
+ static abstract class AbstractDictIter extends PyIterator {
- private final int size;
+ protected final Iterator iterator;
+ protected final int size;
- public ValuesIter(Collection values) {
+ public AbstractDictIter(Collection values) {
iterator = values.iterator();
size = values.size();
}
+ /**
+ * For use by subclasses.
+ */
+ protected void check(int size) {
+ if (size != this.size) {
+ throw Py.RuntimeError("dictionary changed size during iteration");
+ }
+ }
+
+ /**
+ * Warning: This default implementation is only
+ * valid for T=PyObject.
+ */
+ @Override
+ public PyObject __iternext__() {
+ if (!iterator.hasNext()) {
+ return null;
+ }
+ return (PyObject) iterator.next();
+ }
+ }
+
+ static class ValuesIter extends AbstractDictIter
+ {
+ public ValuesIter(Collection values) {
+ super(values);
+ }
+ }
+
+ /**
+ * Only valid for T=PyObject.
+ * Subclasses can use a different T, but then have to
+ * override __iternext__() accordingly.
+ */
+ static class KeysIter extends AbstractDictIter
+ {
+ public KeysIter(Collection keys) {
+ super(keys);
+ }
+ }
+
+ /**
+ * Only valid for T=PyObject.
+ * Subclasses can use a different T, but then have to
+ * override __iternext__() accordingly.
+ */
+ static class ItemsIter extends AbstractDictIter> {
+
+ public ItemsIter(Set> items) {
+ super(items);
+ }
+
@Override
public PyObject __iternext__() {
if (!iterator.hasNext()) {
return null;
}
- return iterator.next();
+ Entry entry = iterator.next();
+ return new PyTuple((PyObject) entry.getKey(), entry.getValue());
}
}
}
diff --git a/src/org/python/core/AnnotationReader.java b/src/org/python/core/AnnotationReader.java
index 9a5f0e4c9..1dfe9763c 100644
--- a/src/org/python/core/AnnotationReader.java
+++ b/src/org/python/core/AnnotationReader.java
@@ -36,7 +36,7 @@ public class AnnotationReader extends ClassVisitor {
* @throws IOException - if the classfile is malformed.
*/
public AnnotationReader(byte[] data) throws IOException {
- super(Opcodes.ASM5);
+ super(Opcodes.ASM7);
ClassReader r;
try {
r = new ClassReader(data);
@@ -52,7 +52,7 @@ public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
nextVisitIsVersion = desc.equals("Lorg/python/compiler/APIVersion;");
nextVisitIsMTime = desc.equals("Lorg/python/compiler/MTime;");
nextVisitIsFilename = desc.equals("Lorg/python/compiler/Filename;");
- return new AnnotationVisitor(Opcodes.ASM5) {
+ return new AnnotationVisitor(Opcodes.ASM7) {
public void visit(String name, Object value) {
if (nextVisitIsVersion) {
diff --git a/src/org/python/core/BaseBytes.java b/src/org/python/core/BaseBytes.java
index dd1495444..8889babff 100644
--- 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 #getBuilder(int)} to return instances of its own type. See the documentation of 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 @@ public BaseBytes(PyType type, int[] value) {
*
* @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,10 +115,11 @@ protected BaseBytes(PyType type, String value) throws PyException {
* @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 {
+ protected void setStorage(byte[] storage, int size, int offset)
+ throws IllegalArgumentException {
if (size < 0 || offset < 0 || offset + size > storage.length) {
throw new IllegalArgumentException();
} else {
@@ -136,8 +135,8 @@ protected void setStorage(byte[] storage, int size, int offset) throws IllegalAr
*
* @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) {
@@ -172,64 +171,49 @@ protected void setStorage(byte[] storage) {
*/
/**
- * 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.ByteArray#bytearray___init__(PyObject[], String[])
- * @see org.python.core.ByteArray#ByteArray(PyObject)
+ * @see org.python.core.PyByteArray#bytearray___init__(PyObject[], String[])
+ * @see org.python.core.PyByteArray#PyByteArray(PyObject)
* @param arg primary argument from which value is taken
- * @param encoding name of optional encoding (must be a string type)
- * @param errors name of optional errors policy (must be a string type)
*/
protected void init(PyObject arg) {
if (arg == null) {
- /*
- * bytearray() Construct a zero-length bytearray.
- */
+ // bytearray() Construct a zero-length bytearray.
setStorage(emptyStorage);
- } else if (arg instanceof PyString) {
+ } else if (arg instanceof PyString) { // or PyUnicode
/*
* bytearray(string) Construct from a text string by default encoding and error policy.
* Cases where encoding and error policy are specified explicitly are dealt with
* elsewhere.
*/
- init((PyString)arg, (String)null, (String)null); // Casts select right init()
+ init((PyString) arg, (String) null, (String) null); // Casts select right init()
} else if (arg.isIndex()) {
- /*
- * bytearray(int) Construct a zero-initialised bytearray of the given length.
- */
+ // bytearray(int) Construct a zero-initialised bytearray of the given length.
init(arg.asIndex(Py.OverflowError)); // overflow if too big to be Java int
} else if (arg instanceof BaseBytes) {
- /*
- * bytearray copy of bytearray (or bytes) -- do efficiently
- */
- init((BaseBytes)arg);
+ // bytearray copy of bytearray (or bytes) -- do efficiently
+ init((BaseBytes) arg);
- } else if (arg instanceof BufferProtocol) {
- /*
- * bytearray copy of object supporting Jython implementation of PEP 3118
- */
- init((BufferProtocol)arg);
+ } else if (initFromBuffer(arg)) {
+ // arg supports Jython implementation of PEP 3118. (We're done.)
} else {
- /*
- * The remaining alternative is an iterable returning (hopefully) right-sized ints. If
- * it isn't one, we get an exception about not being iterable, or about the values.
- */
+ // The remaining alternative is an iterable returning (we hope) right-sized ints.
init(arg.asIterable());
-
}
}
/**
- * 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 #bytearray___init__(PyObject[], String[])
+ * @see PyByteArray#bytearray___init__(PyObject[], String[])
* @see PyByteArray#PyByteArray(PyString, String, String)
* @param arg primary argument from which value is taken
* @param encoding name of optional encoding (must be a string type)
@@ -242,10 +226,10 @@ protected void init(PyString arg, PyObject encoding, PyObject errors) {
}
/**
- * 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 #bytearray___init__(PyObject[], String[])
+ * @see PyByteArray#bytearray___init__(PyObject[], String[])
* @see PyByteArray#PyByteArray(PyString, String, String)
* @param arg primary argument from which value is taken
* @param encoding name of optional encoding
@@ -259,20 +243,21 @@ protected void init(PyString arg, String encoding, String errors) {
}
/**
- * 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 #ByteArray(PyString, String, String)
+ * @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 {
+ protected static String encode(PyString arg, String encoding, String errors)
+ throws PyException {
// Jython encode emits a String (not byte[])
String encoded;
@@ -298,7 +283,7 @@ protected static String encode(PyString arg, String encoding, String errors) thr
*
* @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 {@code value[i] > 255}
*/
protected void setBytes(int start, String value) throws PyException {
int n = value.length();
@@ -314,7 +299,7 @@ protected void setBytes(int start, String value) throws PyException {
*
* @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 {@code value[i] > 255}
*/
protected void setBytes(int start, int step, String value) throws PyException {
int n = value.length();
@@ -326,8 +311,8 @@ protected void setBytes(int start, int step, String value) throws PyException {
}
/**
- * 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
*/
@@ -339,14 +324,14 @@ protected void init(int n) {
}
/**
- * 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
*/
- protected void init(BufferProtocol value) throws PyException {
+ protected void init(BufferProtocol value) throws PyException, ClassCastException {
// Get the buffer view
- try (PyBuffer view = value.getBuffer(PyBUF.FULL_RO)) {
+ try (PyBuffer view = value.getBuffer(PyBUF.SIMPLE)) {
// Create storage for the bytes and have the view drop them in
newStorage(view.getLen());
view.copyTo(storage, offset);
@@ -354,10 +339,27 @@ protected void init(BufferProtocol value) throws PyException {
}
/**
- * Helper for __new__ and __init__ and the Java API constructor from
- * bytearray or bytes in subclasses.
+ * Helper for {@code __new__} and {@code __init__} from objects that might support the
+ * Jython Buffer API.
*
- * @param source bytearray (or bytes) to copy
+ * @param value an object possibly bearing the Buffer API
+ * @return {@code true} iff {@code value} allows the {@code getBuffer}
+ */
+ private boolean initFromBuffer(PyObject value) throws PyException {
+ if (value instanceof BufferProtocol) {
+ try {
+ init((BufferProtocol) value);
+ return true;
+ } catch (ClassCastException e) { /* fall through to false */ }
+ }
+ return false;
+ }
+
+ /**
+ * Helper for {@code __new__} and {@code __init__} and the Java API constructor from
+ * {@code bytearray} or {@code bytes} in subclasses.
+ *
+ * @param source {@code bytearray} (or {@code bytes}) to copy
*/
protected void init(BaseBytes source) {
newStorage(source.size);
@@ -365,8 +367,8 @@ protected void init(BaseBytes source) {
}
/**
- * 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
*/
@@ -437,8 +439,9 @@ protected static class FragmentList extends LinkedList {
* 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 extends PyObject> iter) throws PyException {
@@ -543,7 +546,7 @@ void emptyInto(byte[] target, int start, int step) {
* 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) {
@@ -577,13 +580,13 @@ protected void newStorage(int needed) {
* 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) {
throw Py.ValueError("byte must be in range(0, 256)");
}
- return (byte)value;
+ return (byte) value;
}
/**
@@ -592,7 +595,7 @@ protected static final byte byteCheck(int value) throws PyException {
* 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());
@@ -610,8 +613,8 @@ protected static final byte byteCheck(PyInteger value) throws PyException {
*
*
* @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()) {
@@ -619,7 +622,7 @@ protected static final byte byteCheck(PyObject value) throws PyException {
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");
}
@@ -630,12 +633,12 @@ protected static final byte byteCheck(PyObject value) throws PyException {
}
/**
- * 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) {
@@ -651,7 +654,7 @@ protected static PyBuffer getView(PyObject b) {
return null;
} else if (b instanceof BufferProtocol) {
- return ((BufferProtocol)b).getBuffer(PyBUF.FULL_RO);
+ return ((BufferProtocol) b).getBuffer(PyBUF.FULL_RO);
} else {
return null;
@@ -661,7 +664,7 @@ protected static PyBuffer getView(PyObject b) {
/**
* 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
@@ -707,9 +710,9 @@ protected PyInteger pyget(int index) {
*
* @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.
@@ -719,8 +722,8 @@ public void pyinsert(int index, PyObject element) {
/**
* 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.
@@ -731,8 +734,8 @@ protected BaseBytes getslice(int start, int stop) {
}
/**
- * 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 {
@@ -770,11 +773,11 @@ public int __len__() {
/**
* 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
@@ -848,8 +851,8 @@ private synchronized int basebytes_cmp(PyObject b) {
/**
* 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
@@ -884,10 +887,10 @@ private synchronized int basebytes_cmpeq(PyObject b) {
/**
* 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);
@@ -902,10 +905,10 @@ final PyObject basebytes___eq__(PyObject other) {
/**
* 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);
@@ -920,10 +923,10 @@ final PyObject basebytes___ne__(PyObject other) {
/**
* 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);
@@ -938,10 +941,10 @@ final PyObject basebytes___lt__(PyObject other) {
/**
* 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);
@@ -956,10 +959,10 @@ final PyObject basebytes___le__(PyObject other) {
/**
* 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);
@@ -974,10 +977,10 @@ final PyObject basebytes___ge__(PyObject other) {
/**
* 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);
@@ -1015,17 +1018,17 @@ protected final synchronized boolean basebytes___contains__(PyObject target) {
/**
* 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) {
@@ -1037,7 +1040,7 @@ protected final synchronized boolean basebytes_starts_or_endswith(PyObject targe
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;
}
@@ -1050,17 +1053,16 @@ protected final synchronized boolean basebytes_starts_or_endswith(PyObject targe
}
/**
- * 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) {
@@ -1119,14 +1121,14 @@ public synchronized String asString() {
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);
}
/**
* 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
*/
@@ -1136,10 +1138,10 @@ public PyObject decode() {
/**
* 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) {
@@ -1148,18 +1150,18 @@ public PyObject decode(String encoding) {
/**
* 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);
@@ -1170,7 +1172,7 @@ public PyObject decode(String encoding, String errors) {
*
* @param args Python argument list
* @param keywords Assocaited keywords
- * @return
+ * @return object containing the decoded characters
*/
protected final PyObject basebytes_decode(PyObject[] args, String[] keywords) {
ArgParser ap = new ArgParser("decode", args, keywords, "encoding", "errors");
@@ -1180,8 +1182,8 @@ protected final PyObject basebytes_decode(PyObject[] args, String[] keywords) {
}
/**
- * 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
@@ -1258,11 +1260,11 @@ protected int index(byte b) {
}
/**
- * 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
@@ -1272,7 +1274,7 @@ protected int index(byte b) {
*
*
* 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.
*/
@@ -1290,13 +1292,12 @@ public Finder(PyBuffer pattern) {
/**
* 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;
@@ -1322,8 +1323,8 @@ protected int[] calculateSkipTable() {
}
/**
- * 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
*/
@@ -1332,8 +1333,8 @@ public void setText(byte[] text) {
}
/**
- * 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
*/
@@ -1342,9 +1343,8 @@ public void setText(BaseBytes text) {
}
/**
- * 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
@@ -1374,8 +1374,8 @@ public void setText(byte[] text, int start, int size) {
/**
* 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:
*
@@ -1394,8 +1394,8 @@ public int currIndex() {
/**
* 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
*/
@@ -1476,8 +1476,7 @@ public int count(byte[] text) {
/**
* 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
@@ -1490,7 +1489,7 @@ public int count(byte[] text, int start, int size) {
/**
* 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
@@ -1527,11 +1526,11 @@ public ReverseFinder(PyBuffer pattern) {
/**
* 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.MASKcalculateSkipTable() 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;
@@ -1569,7 +1568,7 @@ public int currIndex() {
/**
* 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
@@ -1682,7 +1681,7 @@ public boolean contains(byte b) {
*
* @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;
@@ -1709,8 +1708,8 @@ protected final static int checkForEmptySeparator(PyBuffer separator) throws PyE
}
/**
- * 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
@@ -1730,8 +1729,8 @@ protected int lstripIndex(ByteSet byteSet) {
}
/**
- * 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
*/
@@ -1749,8 +1748,8 @@ protected int lstripIndex() {
/**
* 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
@@ -1770,7 +1769,7 @@ protected int rstripIndex(ByteSet byteSet) {
/**
* 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
*/
@@ -1786,10 +1785,10 @@ protected int rstripIndex() {
}
/**
- * 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
@@ -1809,12 +1808,11 @@ final int basebytes_count(PyObject sub, PyObject ostart, PyObject oend) {
}
/**
- * 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
@@ -1829,10 +1827,10 @@ final int basebytes_find(PyObject sub, PyObject ostart, PyObject oend) {
}
/**
- * 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:
*
*
@@ -1841,7 +1839,8 @@ final int basebytes_find(PyObject sub, PyObject ostart, PyObject oend) {
*
* @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 {
@@ -1867,7 +1866,7 @@ static void basebytes_fromhex(BaseBytes result, String hex) throws PyException {
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) {
@@ -1903,7 +1902,7 @@ private static int hexDigit(char c) throws IllegalArgumentException {
}
/**
- * 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
@@ -1922,8 +1921,8 @@ final synchronized PyByteArray basebytes_join(Iterable extends PyObject> iter)
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();
@@ -1941,7 +1940,7 @@ final synchronized PyByteArray basebytes_join(Iterable extends PyObject> iter)
}
// 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;
@@ -1961,7 +1960,7 @@ final synchronized PyByteArray basebytes_join(Iterable extends PyObject> iter)
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();
}
@@ -1969,16 +1968,16 @@ final synchronized PyByteArray basebytes_join(Iterable extends PyObject> iter)
}
/**
- * 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)
@@ -1988,10 +1987,10 @@ public PyTuple partition(PyObject sep) {
}
/**
- * 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)
@@ -2018,11 +2017,11 @@ final synchronized PyTuple basebytes_partition(PyObject sep) {
}
/**
- * 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
@@ -2036,12 +2035,11 @@ private PyTuple partition(int p, int q) {
}
/**
- * 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
@@ -2056,10 +2054,10 @@ final int basebytes_rfind(PyObject sub, PyObject ostart, PyObject oend) {
}
/**
- * 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
@@ -2080,11 +2078,10 @@ private final int find(Finder finder, PyObject ostart, PyObject oend) {
}
/**
- * 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
@@ -2187,7 +2184,7 @@ private PyByteArray replace_substring(PyBuffer from, PyBuffer to, int maxcount)
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");
}
@@ -2250,11 +2247,11 @@ private PyByteArray replace_interleave(PyBuffer to, int maxcount) {
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");
}
@@ -2311,7 +2308,7 @@ private PyByteArray replace_delete_substring(PyBuffer from, int maxcount) {
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");
}
@@ -2399,16 +2396,16 @@ private PyByteArray replace_substring_in_place(PyBuffer from, PyBuffer to, int m
}
/**
- * 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)
@@ -2418,10 +2415,10 @@ public PyTuple rpartition(PyObject sep) {
}
/**
- * 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)
@@ -2448,11 +2445,11 @@ final synchronized PyTuple basebytes_rpartition(PyObject sep) {
}
/**
- * 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
*/
@@ -2461,14 +2458,14 @@ public PyList rsplit() {
}
/**
- * 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) {
@@ -2476,27 +2473,27 @@ public PyList rsplit(PyObject sep) {
}
/**
- * 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,
*
- * 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
*/
@@ -2505,14 +2502,14 @@ public PyList rsplit(PyObject sep, int maxsplit) {
}
/**
- * 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
*/
@@ -2525,16 +2522,16 @@ final PyList basebytes_rsplit(PyObject sep, int maxsplit) {
}
/**
- * 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
*/
@@ -2580,19 +2577,19 @@ final synchronized PyList basebytes_rsplit_explicit(PyObject sep, int maxsplit)
}
/**
- * 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
@@ -2641,11 +2638,11 @@ final synchronized PyList basebytes_rsplit_whitespace(int maxsplit) {
}
/**
- * 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
*/
@@ -2654,14 +2651,14 @@ public PyList split() {
}
/**
- * 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) {
@@ -2669,34 +2666,34 @@ public PyList split(PyObject sep) {
}
/**
- * 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,
*
- * 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
*/
@@ -2705,14 +2702,14 @@ public PyList split(PyObject sep, int maxsplit) {
}
/**
- * 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
*/
@@ -2725,16 +2722,16 @@ final PyList basebytes_split(PyObject sep, int maxsplit) {
}
/**
- * 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
*/
@@ -2771,19 +2768,19 @@ final synchronized PyList basebytes_split_explicit(PyObject sep, int maxsplit) {
}
/**
- * 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
@@ -2826,11 +2823,11 @@ final synchronized PyList basebytes_split_whitespace(int maxsplit) {
}
/**
- * 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
*/
@@ -2839,12 +2836,12 @@ public PyList splitlines() {
}
/**
- * 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
@@ -2854,12 +2851,12 @@ public PyList splitlines(boolean keepends) {
}
/**
- * 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
@@ -2905,19 +2902,19 @@ protected final synchronized PyList basebytes_splitlines(boolean keepends) {
//
/**
- * Helper to check the fill byte for {@link #rjust(String)}, {@link #ljust(String)} and
- * {@link #center(String)}, which is required to be a single character string, treated as a
- * byte.
+ * Helper to check the fill byte for {@link #basebytes_rjust(int, String)},
+ * {@link #basebytes_ljust(int, String)} and {@link #basebytes_center(int, String)}, which is
+ * required to be a single character string, treated as a byte.
*
* @param function name
- * @param fillchar or null
- * @return
+ * @param fillchar or {@code null}
+ * @return the (checked) single fill byte
*/
protected static byte fillByteCheck(String function, String fillchar) {
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");
}
@@ -2927,8 +2924,8 @@ protected static byte fillByteCheck(String function, String fillchar) {
* 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
@@ -2944,22 +2941,22 @@ private BaseBytes padHelper(byte pad, int left, int right) {
}
// 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);
}
/**
- * 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) {
@@ -2973,14 +2970,14 @@ final BaseBytes basebytes_center(int width, String fillchar) {
}
/**
- * 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) {
@@ -2992,14 +2989,14 @@ final BaseBytes basebytes_ljust(int width, String fillchar) {
}
/**
- * 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) {
@@ -3011,13 +3008,13 @@ final BaseBytes basebytes_rjust(int width, String fillchar) {
}
/**
- * 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.
*
- * 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
@@ -3025,8 +3022,8 @@ final BaseBytes basebytes_rjust(int width, String fillchar) {
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;
@@ -3036,7 +3033,7 @@ final BaseBytes basebytes_expandtabs(int tabsize) {
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
@@ -3045,13 +3042,13 @@ final BaseBytes basebytes_expandtabs(int tabsize) {
}
}
- return builder.getResult();
+ return getResult(builder);
}
/**
- * 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
@@ -3060,7 +3057,7 @@ final BaseBytes basebytes_expandtabs(int tabsize) {
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
@@ -3076,20 +3073,19 @@ final BaseBytes basebytes_zfill(int width) {
}
}
// 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;
@@ -3147,8 +3143,8 @@ static final boolean isspace(byte b) {
}
/**
- * 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.
@@ -3158,7 +3154,7 @@ public boolean isalnum() {
}
/**
- * 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.
@@ -3180,8 +3176,8 @@ final boolean basebytes_isalnum() {
}
/**
- * 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
@@ -3191,7 +3187,7 @@ public boolean isalpha() {
}
/**
- * 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
@@ -3213,8 +3209,8 @@ final boolean basebytes_isalpha() {
}
/**
- * 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.
@@ -3224,7 +3220,7 @@ public boolean isdigit() {
}
/**
- * 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.
@@ -3246,8 +3242,8 @@ final boolean basebytes_isdigit() {
}
/**
- * 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.
@@ -3257,7 +3253,7 @@ public boolean islower() {
}
/**
- * 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.
@@ -3295,8 +3291,8 @@ final boolean basebytes_islower() {
}
/**
- * 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.
@@ -3306,7 +3302,7 @@ public boolean isspace() {
}
/**
- * 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.
@@ -3328,8 +3324,8 @@ final boolean basebytes_isspace() {
}
/**
- * 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
@@ -3340,7 +3336,7 @@ public boolean istitle() {
}
/**
- * 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
@@ -3354,7 +3350,7 @@ final boolean basebytes_istitle() {
// 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
@@ -3380,8 +3376,8 @@ final boolean basebytes_istitle() {
}
/**
- * 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.
@@ -3391,7 +3387,7 @@ public boolean isupper() {
}
/**
- * 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.
@@ -3433,9 +3429,9 @@ final boolean basebytes_isupper() {
//
/**
- * 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.
*/
@@ -3444,15 +3440,14 @@ public BaseBytes capitalize() {
}
/**
- * 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.
*/
final BaseBytes basebytes_capitalize() {
- Builder builder = getBuilder(size);
+ Builder builder = new Builder(size);
if (size > 0) {
// Treat first character
@@ -3465,7 +3460,7 @@ final BaseBytes basebytes_capitalize() {
// 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.
}
@@ -3474,13 +3469,13 @@ final BaseBytes basebytes_capitalize() {
}
}
- return builder.getResult();
+ return getResult(builder);
}
/**
- * 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.
*/
@@ -3489,17 +3484,17 @@ public BaseBytes lower() {
}
/**
- * 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.
*/
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.
}
@@ -3507,13 +3502,13 @@ final BaseBytes basebytes_lower() {
builder.append(c);
}
- return builder.getResult();
+ return getResult(builder);
}
/**
- * 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.
*/
@@ -3522,17 +3517,17 @@ public BaseBytes swapcase() {
}
/**
- * 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.
*/
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.
}
@@ -3540,15 +3535,15 @@ final BaseBytes basebytes_swapcase() {
builder.append(c);
}
- return builder.getResult();
+ return getResult(builder);
}
/**
- * 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.
@@ -3558,19 +3553,19 @@ public BaseBytes title() {
}
/**
- * 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.
*/
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 ...
@@ -3592,14 +3587,13 @@ final BaseBytes basebytes_title() {
// Put the adjusted character in the output as a byte
builder.append(c);
}
- return builder.getResult();
+ return getResult(builder);
}
/**
- * 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.
*/
@@ -3608,17 +3602,17 @@ public BaseBytes upper() {
}
/**
- * 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.
*/
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.
}
@@ -3626,7 +3620,7 @@ final BaseBytes basebytes_upper() {
builder.append(c);
}
- return builder.getResult();
+ return getResult(builder);
}
/*
@@ -3652,48 +3646,13 @@ private final synchronized byte byteAt(int index) {
*
* @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);
return 0xff & byteAt(index);
}
- /**
- * Helper to implement {@link #repeat(int)}. Use something like:
- *
- *
- *
- * @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)
//
@@ -3710,10 +3669,10 @@ private static final void appendHexEscape(StringBuilder buf, int c) {
}
/**
- * 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!')
@@ -3723,7 +3682,7 @@ private static final void appendHexEscape(StringBuilder buf, int c) {
*
* @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) {
@@ -3750,7 +3709,7 @@ final synchronized String basebytes_repr(String before, String after) {
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') {
@@ -3796,9 +3755,9 @@ public int size() {
* 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 {
@@ -3814,9 +3773,9 @@ public PyInteger set(int index, PyInteger element) throws PyException {
* 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 {
@@ -3831,7 +3790,7 @@ public void add(int index, PyInteger element) throws PyException {
* 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) {
@@ -3844,11 +3803,11 @@ public PyInteger remove(int index) {
};
/**
- * 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.
- * */
+ */
@Override
public int size() {
return size;
@@ -3960,17 +3919,15 @@ public void clear() {
}
/**
- * 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) {
@@ -4070,55 +4027,50 @@ public List subList(int fromIndex, int toIndex) {
*/
/**
- * A Builder holds a buffer of bytes to which new bytes may be appended while
+ * 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
+ */
+ protected abstract BaseBytes getResult(Builder b);
+
+ /**
+ * 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.
- *
- * 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
*/
@@ -4129,8 +4081,8 @@ byte[] getStorage() {
}
/**
- * 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
*/
@@ -4149,7 +4101,7 @@ void append(byte b) {
}
/**
- * 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)
@@ -4157,7 +4109,7 @@ void append(byte b) {
void repeat(byte b, int n) {
if (n > 0) {
makeRoomFor(n);
- while (n-- > 0) {
+ while (--n >= 0) {
storage[size++] = b;
}
}
@@ -4172,18 +4124,45 @@ void append(BaseBytes b) {
append(b, 0, b.size);
}
+ /**
+ * 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;
+ }
}
/**
@@ -4198,34 +4177,43 @@ void append(PyBuffer v) {
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 {@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;
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());
}
}
}
@@ -4233,11 +4221,11 @@ void makeRoomFor(int n) throws PyException {
/**
* 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
+ * @return n ≥ size a recommended storage array size
*/
protected static final int roundUp(int size) {
/*
@@ -4257,16 +4245,4 @@ protected static final int roundUp(int size) {
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/* extends BaseBytes> */getBuilder(int capacity);
-
}
diff --git a/src/org/python/core/BaseSet.java b/src/org/python/core/BaseSet.java
index 55fbeb0b8..1c603a2d1 100644
--- a/src/org/python/core/BaseSet.java
+++ b/src/org/python/core/BaseSet.java
@@ -31,7 +31,7 @@ protected void _update(PyObject data) {
protected void _update(PyObject [] args) {
_update(_set, args);
}
-
+
/**
* Update the underlying set with the contents of the iterable.
*/
@@ -64,12 +64,13 @@ protected static Set _update(Set set, PyObject[] data) {
}
/**
- * 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.
* @return The union of the two sets as a new set.
*/
+ @Override
public PyObject __or__(PyObject other) {
return baseset___or__(other);
}
@@ -83,13 +84,14 @@ final PyObject baseset___or__(PyObject other) {
/**
* The intersection of the this with other.
- *
- *
+ *
+ *
* (I.e. all elements that are in both sets)
*
* @param other A BaseSet instance.
* @return The intersection of the two sets as a new set.
*/
+ @Override
public PyObject __and__(PyObject other) {
return baseset___and__(other);
}
@@ -103,13 +105,14 @@ final PyObject baseset___and__(PyObject other) {
/**
* 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.
* @return The difference of the two sets as a new set.
*/
+ @Override
public PyObject __sub__(PyObject other) {
return baseset___sub__(other);
}
@@ -124,16 +127,16 @@ final PyObject baseset___sub__(PyObject other) {
public PyObject difference(PyObject other) {
return baseset_difference(other);
}
-
+
final PyObject baseset_difference(PyObject other) {
return baseset_difference(new PyObject[] {other});
}
-
+
final PyObject baseset_difference(PyObject [] args) {
if (args.length == 0) {
return BaseSet.makeNewSet(getType(), this);
}
-
+
BaseSet o = BaseSet.makeNewSet(getType(), this);
for (PyObject item: args) {
BaseSet bs = args[0] instanceof BaseSet ? (BaseSet)item : new PySet(item);
@@ -150,13 +153,14 @@ final PyObject baseset_difference(PyObject [] args) {
/**
* 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.
* @return The symmetric difference of the two sets as a new set.
*/
+ @Override
public PyObject __xor__(PyObject other) {
return baseset___xor__(other);
}
@@ -193,6 +197,7 @@ final PyObject baseset_symmetric_difference(PyObject other) {
*
* @return The hashCode of the set.
*/
+ @Override
public abstract int hashCode();
/**
@@ -200,6 +205,7 @@ final PyObject baseset_symmetric_difference(PyObject other) {
*
* @return The length of the set.
*/
+ @Override
public int __len__() {
return baseset___len__();
}
@@ -214,6 +220,7 @@ final int baseset___len__() {
*
* @return true if the set is not empty, false otherwise
*/
+ @Override
public boolean __nonzero__() {
return !_set.isEmpty();
}
@@ -223,6 +230,7 @@ public boolean __nonzero__() {
*
* @return An iteration of the set.
*/
+ @Override
public PyObject __iter__() {
return baseset___iter__();
}
@@ -243,6 +251,7 @@ public PyObject __iternext__() {
};
}
+ @Override
public boolean __contains__(PyObject other) {
return baseset___contains__(other);
}
@@ -256,6 +265,7 @@ final boolean baseset___contains__(PyObject other) {
}
}
+ @Override
public int __cmp__(PyObject other) {
return baseset___cmp__(other);
}
@@ -264,28 +274,61 @@ final int baseset___cmp__(PyObject other) {
throw Py.TypeError("cannot compare sets using cmp()");
}
+ @Override
public PyObject __eq__(PyObject other) {
return baseset___eq__(other);
}
final PyObject baseset___eq__(PyObject other) {
- if (other instanceof BaseSet) {
- return Py.newBoolean(_set.equals(((BaseSet)other)._set));
+ // jobj might be Py.NoConversion if other is not a Set
+ Object jobj = other.__tojava__(Set.class);
+ if (jobj instanceof Set) {
+ final Set jSet = (Set) jobj;
+ // If the sizes differ must be not equal
+ if (jSet.size() != size()) {
+ return Py.False;
+ }
+ // Now need to perform element comparison
+ for (Object otherItem : jSet) {
+ if (!contains(otherItem)) {
+ return Py.False; // If any item is not contained then they are not equal
+ }
+ }
+ // All items are contained and the lentgh is the same so we are equal
+ return Py.True;
}
+ // other wasn't a set so not equal
return Py.False;
}
+ @Override
public PyObject __ne__(PyObject other) {
return baseset___ne__(other);
}
final PyObject baseset___ne__(PyObject other) {
- if (other instanceof BaseSet) {
- return Py.newBoolean(!_set.equals(((BaseSet)other)._set));
+ // jobj might be Py.NoConversion if other is not a Set
+ Object jobj = other.__tojava__(Set.class);
+ if (jobj instanceof Set) {
+ final Set jSet = (Set) jobj;
+ // If the sizes differ must be not equal
+ if (jSet.size() != size()) {
+ return Py.True;
+ }
+ // Now need to perform element comparison
+ for (Object otherItem : jSet) {
+ if (!contains(otherItem)) {
+ return Py.True; // If any item is not contained then they are not equal
+ }
+ }
+ // All items are contained and the lentgh is the same so we are equal
+ return Py.False;
}
+ // other wasn't a set so not equal
return Py.True;
}
+ @Override
public PyObject __le__(PyObject other) {
return baseset___le__(other);
}
@@ -294,6 +337,7 @@ final PyObject baseset___le__(PyObject other) {
return baseset_issubset(asBaseSet(other));
}
+ @Override
public PyObject __ge__(PyObject other) {
return baseset___ge__(other);
}
@@ -302,6 +346,7 @@ final PyObject baseset___ge__(PyObject other) {
return baseset_issuperset(asBaseSet(other));
}
+ @Override
public PyObject __lt__(PyObject other) {
return baseset___lt__(other);
}
@@ -311,6 +356,7 @@ final PyObject baseset___lt__(PyObject other) {
return Py.newBoolean(size() < bs.size() && baseset_issubset(other).__nonzero__());
}
+ @Override
public PyObject __gt__(PyObject other) {
return baseset___gt__(other);
}
@@ -321,11 +367,12 @@ final PyObject baseset___gt__(PyObject other) {
}
/**
- * 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))
*/
+ @Override
public PyObject __reduce__() {
return baseset___reduce__();
}
@@ -344,7 +391,7 @@ final PyObject baseset_union(PyObject other) {
result._update(other);
return result;
}
-
+
final PyObject baseset_union(PyObject [] args) {
BaseSet result = BaseSet.makeNewSet(getType(), this);
for (PyObject item: args) {
@@ -370,13 +417,13 @@ final PyObject baseset_intersection(PyObject other) {
PyObject common = __builtin__.filter(big.__getattr__("__contains__"), little);
return BaseSet.makeNewSet(getType(), common);
}
-
+
final PyObject baseset_intersection(PyObject [] args) {
BaseSet result = BaseSet.makeNewSet(getType(), this);
if (args.length == 0) {
return result;
}
-
+
for (PyObject other: args) {
result = (BaseSet)result.baseset_intersection(other);
}
@@ -405,12 +452,13 @@ final PyObject baseset_issuperset(PyObject other) {
BaseSet bs = other instanceof BaseSet ? (BaseSet)other : new PySet(other);
return bs.baseset_issubset(this);
}
-
+
final PyObject baseset_isdisjoint(PyObject other) {
BaseSet bs = other instanceof BaseSet ? (BaseSet)other : new PySet(other);
return Collections.disjoint(_set, bs._set) ? Py.True : Py.False;
}
+ @Override
public String toString() {
return baseset_toString();
}
@@ -502,30 +550,37 @@ protected static BaseSet makeNewSet(PyType type, PyObject iterable) {
return so;
}
+ @Override
public int size() {
return _set.size();
}
+ @Override
public void clear() {
_set.clear();
}
+ @Override
public boolean isEmpty() {
return _set.isEmpty();
}
+ @Override
public boolean add(Object o) {
return _set.add(Py.java2py(o));
}
+ @Override
public boolean contains(Object o) {
return _set.contains(Py.java2py(o));
}
+ @Override
public boolean remove(Object o) {
return _set.remove(Py.java2py(o));
}
+ @Override
public boolean addAll(Collection c) {
boolean added = false;
for (Object object : c) {
@@ -534,6 +589,7 @@ public boolean addAll(Collection c) {
return added;
}
+ @Override
public boolean containsAll(Collection c) {
for (Object object : c) {
if (!_set.contains(Py.java2py(object))) {
@@ -543,6 +599,7 @@ public boolean containsAll(Collection c) {
return true;
}
+ @Override
public boolean removeAll(Collection c) {
boolean removed = false;
for (Object object : c) {
@@ -551,6 +608,7 @@ public boolean removeAll(Collection c) {
return removed;
}
+ @Override
public boolean retainAll(Collection c) {
boolean modified = false;
Iterator e = iterator();
@@ -563,28 +621,34 @@ public boolean retainAll(Collection c) {
return modified;
}
+ @Override
public Iterator iterator() {
return new Iterator() {
Iterator real = _set.iterator();
+ @Override
public boolean hasNext() {
return real.hasNext();
}
+ @Override
public Object next() {
return Py.tojava(real.next(), Object.class);
}
+ @Override
public void remove() {
real.remove();
}
};
}
+ @Override
public Object[] toArray() {
return toArray(new Object[size()]);
}
+ @Override
public Object[] toArray(Object a[]) {
int size = size();
if (a.length < size) {
diff --git a/src/org/python/core/BufferProtocol.java b/src/org/python/core/BufferProtocol.java
index 4d5a0d318..701b5d3ff 100644
--- a/src/org/python/core/BufferProtocol.java
+++ b/src/org/python/core/BufferProtocol.java
@@ -2,19 +2,32 @@
/**
* Interface marking an object as capable of exposing its internal state as a {@link PyBuffer}.
+ *
+ * A few objects implement {@code BufferProtocol} (e.g. by inheritance) but cannot actually provide
+ * their value as a {@link PyBuffer}. These should throw {@code ClassCastException}, permitting the
+ * idiom:
+ * try (PyBuffer buf = ((BufferProtocol) obj).getBuffer(PyBUF.SIMPLE)) {
+ * ... // Do something with buf
+ * } catch (ClassCastException e) {
+ * ... // expected bytes object or buffer not obj.getType()
+ * }
+ *
The {@code catch} is executed identically whether the cause is the explicit cast of
+ * {@code obj} or {@code getBuffer}, and the try-with-resources releases the buffer if one was
+ * obtained.
*/
public interface BufferProtocol {
/**
* Method by which the consumer requests the buffer from the exporter. The consumer provides
- * information on its intended method of navigation and the features the buffer object is asked
- * (or assumed) to provide. Each consumer requesting a buffer in this way, when it has finished
- * using it, should make a corresponding call to {@link PyBuffer#release()} on the buffer it
- * obtained, since some objects alter their behaviour while buffers are exported.
- *
+ * information on its ability to understand buffer navigation. Each consumer requesting a buffer
+ * in this way, when it has finished using it, should make a corresponding call to
+ * {@link PyBuffer#release()} on the buffer it obtained, or {@link PyBuffer#close()} using
+ * try-with-resources, since some objects alter their behaviour while buffers are exported.
+ *
* @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;
+ PyBuffer getBuffer(int flags) throws PyException, ClassCastException;
}
diff --git a/src/org/python/core/BytecodeLoader.java b/src/org/python/core/BytecodeLoader.java
index 07f482e3e..82e7fc658 100644
--- a/src/org/python/core/BytecodeLoader.java
+++ b/src/org/python/core/BytecodeLoader.java
@@ -1,53 +1,58 @@
// Copyright (c) Corporation for National Research Initiatives
package org.python.core;
+import org.objectweb.asm.ClassReader;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
import java.net.URL;
import java.net.URLClassLoader;
+import java.util.LinkedList;
import java.util.List;
-import org.objectweb.asm.ClassReader;
-import org.python.util.Generic;
-
/**
- * Utility class for loading compiled python modules and java classes defined in python modules.
+ * Utility class for loading compiled Python modules and Java classes defined in Python modules.
*/
public class BytecodeLoader {
/**
- * Turn the java byte code in data into a java class.
+ * Turn the Java class file data into a Java class.
*
- * @param name
- * the name of the class
- * @param data
- * the java byte code.
- * @param referents
- * superclasses and interfaces that the new class will reference.
+ * @param name fully-qualified binary name of the class
+ * @param data a class file as a byte array
+ * @param referents super-classes and interfaces that the new class will reference.
*/
+ @SuppressWarnings("unchecked")
public static Class> makeClass(String name, byte[] data, Class>... referents) {
+ @SuppressWarnings("resource")
Loader loader = new Loader();
for (Class> referent : referents) {
try {
- ClassLoader cur = referent.getClassLoader();
- if (cur != null) {
- loader.addParent(cur);
- }
- } catch (SecurityException e) {
- }
+ loader.addParent(referent.getClassLoader());
+ } catch (SecurityException e) {}
}
Class> c = loader.loadClassFromBytes(name, data);
+ if (ContainsPyBytecode.class.isAssignableFrom(c)) {
+ try {
+ fixPyBytecode((Class extends ContainsPyBytecode>) c);
+ } catch (IllegalAccessException | NoSuchFieldException | ClassNotFoundException
+ | IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
BytecodeNotification.notify(name, data, c);
return c;
}
/**
- * Turn the java byte code in data into a java class.
+ * Turn the Java class file data into a Java class.
*
- * @param name
- * the name of the class
- * @param referents
- * superclasses and interfaces that the new class will reference.
- * @param data
- * the java byte code.
+ * @param name the name of the class
+ * @param referents super-classes and interfaces that the new class will reference.
+ * @param data a class file as a byte array
*/
public static Class> makeClass(String name, List> referents, byte[] data) {
if (referents != null) {
@@ -56,20 +61,197 @@ public static Class> makeClass(String name, List> referents, byte[] d
return makeClass(name, data);
}
+ private static PyCode parseSerializedCode(String code_str)
+ throws IOException, ClassNotFoundException {
+ // From Java 8 use: byte[] b = Base64.getDecoder().decode(code_str);
+ byte[] b = base64decode(code_str);
+ ByteArrayInputStream bi = new ByteArrayInputStream(b);
+ ObjectInputStream si = new ObjectInputStream(bi);
+ PyBytecode meth_code = (PyBytecode) si.readObject();
+ si.close();
+ bi.close();
+ return meth_code;
+ }
+
+ /**
+ * Implement a restricted form of base64 decoding compatible with the encoding in Module. This
+ * decoder treats characters outside the set of 64 necessary to encode data as errors, including
+ * the pad "=". As a result, the length of the argument exactly determines the size of array
+ * returned.
+ *
+ * @param src to decode
+ * @return a new byte array
+ * @throws IllegalArgumentException if src has an invalid character or impossible length.
+ */
+ private static byte[] base64decode(String src) throws IllegalArgumentException {
+
+ // Length L is a multiple of 4 plus 0, 2 or 3 tail characters (bearing 0, 8, or 16 bits)
+ final int L = src.length();
+ final int tail = L % 4; // 0 to 3 where 1 (an extra 6 bits) is invalid.
+ if (tail == 1) {
+ throw new IllegalArgumentException("Input length invalid (4n+1)");
+ }
+
+ // src encodes exactly this many bytes:
+ final int N = (L / 4) * 3 + (tail > 0 ? tail - 1 : 0);
+ byte[] data = new byte[N];
+
+ // Work through src in blocks of 4
+ int s = 0, b = 0, quantum;
+ while (s <= L - 4) {
+ // Process src[s:s+4]
+ quantum = (base64CharToBits(src.charAt(s++)) << 18)
+ + (base64CharToBits(src.charAt(s++)) << 12)
+ + (base64CharToBits(src.charAt(s++)) << 6) + base64CharToBits(src.charAt(s++));
+ data[b++] = (byte) (quantum >> 16);
+ data[b++] = (byte) (quantum >> 8);
+ data[b++] = (byte) quantum;
+ }
+
+ // Now deal with 2 or 3 tail characters, generating one or two bytes.
+ if (tail >= 2) {
+ // Repeat the loop body, but everything is 8 bits to the right.
+ quantum = (base64CharToBits(src.charAt(s++)) << 10)
+ + (base64CharToBits(src.charAt(s++)) << 4);
+ data[b++] = (byte) (quantum >> 8);
+ if (tail == 3) {
+ quantum += (base64CharToBits(src.charAt(s++)) >> 2);
+ data[b++] = (byte) quantum;
+ }
+ }
+
+ return data;
+ }
+
+ /**
+ * Helper for {@link #base64decode(String)}, converting one character.
+ *
+ * @param c to convert
+ * @return value 0..63
+ * @throws IllegalArgumentException if not a base64 character
+ */
+ private static int base64CharToBits(char c) throws IllegalArgumentException {
+ if (c >= 'a') {
+ if (c <= 'z') {
+ return c - 71; // c - 'a' + 26
+ }
+ } else if (c >= 'A') {
+ if (c <= 'Z') {
+ return c - 'A';
+ }
+ } else if (c >= '0') {
+ if (c <= '9') {
+ return c + 4; // c - '0' + 52
+ }
+ } else if (c == '+') {
+ return 62;
+ } else if (c == '/') {
+ return 63;
+ }
+ throw new IllegalArgumentException("Invalid character " + c);
+ }
+
+ /**
+ * This method looks for Python-Bytecode stored in String literals.
+ * While Java supports rather long strings, constrained only by
+ * int-addressing of arrays, it supports only up to 65535 characters
+ * in literals (not sure how escape-sequences are counted).
+ * To circumvent this limitation, the code is automatically splitted
+ * into several literals with the following naming-scheme.
+ *
+ * - The marker-interface 'ContainsPyBytecode' indicates that a class
+ * contains (static final) literals of the following scheme:
+ * - a prefix of '___' indicates a bytecode-containing string literal
+ * - a number indicating the number of parts follows
+ * - '0_' indicates that no splitting occurred
+ * - otherwise another number follows, naming the index of the literal
+ * - indexing starts at 0
+ *
+ * Examples:
+ * ___0_method1 contains bytecode for method1
+ * ___2_0_method2 contains first part of method2's bytecode
+ * ___2_1_method2 contains second part of method2's bytecode
+ *
+ * Note that this approach is provisional. In future, Jython might contain
+ * the bytecode directly as bytecode-objects. The current approach was
+ * feasible with much less complicated JVM bytecode-manipulation, but needs
+ * special treatment after class-loading.
+ */
+ public static void fixPyBytecode(Class extends ContainsPyBytecode> c)
+ throws IllegalAccessException, NoSuchFieldException, java.io.IOException,
+ ClassNotFoundException {
+ Field[] fields = c.getDeclaredFields();
+ for (Field fld: fields) {
+ String fldName = fld.getName();
+ if (fldName.startsWith("___")) {
+ fldName = fldName.substring(3);
+
+ String[] splt = fldName.split("_");
+ if (splt[0].equals("0")) {
+ fldName = fldName.substring(2);
+ Field codeField = c.getDeclaredField(fldName);
+ if (codeField.get(null) == null) {
+ codeField.set(null, parseSerializedCode((String) fld.get(null)));
+ }
+ } else {
+ if (splt[1].equals("0")) {
+ fldName = fldName.substring(splt[0].length()+splt[1].length()+2);
+ Field codeField = c.getDeclaredField(fldName);
+ if (codeField.get(null) == null) {
+ // assemble original code-string:
+ int len = Integer.parseInt(splt[0]);
+ StringBuilder blt = new StringBuilder((String) fld.get(null));
+ int pos = 1, pos0;
+ String partName;
+ while (pos < len) {
+ pos0 = pos;
+ for (Field fldPart: fields) {
+ partName = fldPart.getName();
+ if (partName.length() != fldName.length() &&
+ partName.startsWith("___") &&
+ partName.endsWith(fldName)) {
+ String[] splt2 = partName.substring(3).split("_");
+ if (Integer.parseInt(splt2[1]) == pos) {
+ blt.append((String) fldPart.get(null));
+ pos += 1;
+ if (pos == len) {
+ break;
+ }
+ }
+ }
+ }
+ if (pos0 == pos) {
+ throw new RuntimeException(
+ "Invalid PyBytecode splitting in " + c.getName()
+ + ":\nSplit-index " + pos + " wasn't found.");
+ }
+ }
+ codeField.set(null, parseSerializedCode(blt.toString()));
+ }
+ }
+ }
+ }
+ }
+ }
+
/**
- * Turn the java byte code for a compiled python module into a java class.
+ * Turn the Java class file data for a compiled Python module into a {@code PyCode} object, by
+ * constructing an instance of the named class and calling the instance's
+ * {@link PyRunnable#getMain()}.
*
- * @param name
- * the name of the class
- * @param data
- * the java byte code.
+ * @param name fully-qualified binary name of the class
+ * @param data a class file as a byte array
+ * @param filename to provide to the constructor of the named class
+ * @return the {@code PyCode} object produced by the named class' {@code getMain}
*/
public static PyCode makeCode(String name, byte[] data, String filename) {
try {
Class> c = makeClass(name, data);
- Object o = c.getConstructor(new Class[] {String.class})
- .newInstance(new Object[] {filename});
- return ((PyRunnable)o).getMain();
+ // A compiled module has a constructor taking a String filename argument.
+ Constructor> cons = c.getConstructor(new Class>[] {String.class});
+ Object instance = cons.newInstance(new Object[] {filename});
+ PyCode result = ((PyRunnable) instance).getMain();
+ return result;
} catch (Exception e) {
throw Py.JavaError(e);
}
@@ -77,16 +259,17 @@ public static PyCode makeCode(String name, byte[] data, String filename) {
public static class Loader extends URLClassLoader {
- private List parents = Generic.list();
+ private LinkedList parents = new LinkedList<>();
public Loader() {
super(new URL[0]);
parents.add(imp.getSyspathJavaLoader());
}
+ /** Add given loader at the front of the list of the parent list (if not {@code null}). */
public void addParent(ClassLoader referent) {
- if (!parents.contains(referent)) {
- parents.add(0, referent);
+ if (referent != null && !parents.contains(referent)) {
+ parents.addFirst(referent);
}
}
@@ -105,6 +288,15 @@ protected Class> loadClass(String name, boolean resolve) throws ClassNotFoundE
throw new ClassNotFoundException(name);
}
+ /**
+ * Define the named class using the class file data provided, and resolve it. (See JVM
+ * specification.) For class names ending "$py", this method may adjust that name to that
+ * found in the class file itself.
+ *
+ * @param name fully-qualified binary name of the class
+ * @param data a class file as a byte array
+ * @return the defined and resolved class
+ */
public Class> loadClassFromBytes(String name, byte[] data) {
if (name.endsWith("$py")) {
try {
diff --git a/src/org/python/core/BytecodeNotification.java b/src/org/python/core/BytecodeNotification.java
index d70893322..aaa157d4c 100644
--- a/src/org/python/core/BytecodeNotification.java
+++ b/src/org/python/core/BytecodeNotification.java
@@ -1,17 +1,16 @@
package org.python.core;
+import java.io.ByteArrayOutputStream;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
-import java.util.Collections;
-import java.io.ByteArrayOutputStream;
/**
* Notifies registered callbacks if new bytecode is loaded.
*/
public class BytecodeNotification {
/**
- * Interface for callbacks.
- * Notifies the name of the loaded class, raw bytes of the class,
+ * Interface for callbacks.
+ * Notifies the name of the loaded class, raw bytes of the class,
* and the Java class object.
*/
public interface Callback {
@@ -19,8 +18,8 @@ public interface Callback {
}
/**
- * The following list stores register callback objects.
- * The list is shared among the PySystemState objects
+ * The following list stores register callback objects.
+ * The list is shared among the PySystemState objects
* if there are multiple instances.
*/
private static List callbacks = new CopyOnWriteArrayList();
@@ -28,6 +27,7 @@ public interface Callback {
static {
// Maintain legacy behavior
register(new Callback() {
+ @Override
public void notify(String name, byte[] bytes, Class c) {
if (Options.proxyDebugDirectory == null ||
(!name.startsWith("org.python.pycode.") &&
@@ -52,11 +52,11 @@ public void notify(String name, byte[] bytes, Class c) {
* Unregisters the callback object
*
* @param n the callback object
- * @return true if successfully removed and
+ * @return true if successfully removed and
* false if the callback object was not registered
*/
public static boolean unregister(Callback n) { return callbacks.remove(n); }
-
+
/**
* Clears all the registered callbacks
*/
@@ -67,14 +67,14 @@ public void notify(String name, byte[] bytes, Class c) {
*
* @param name the name of the class of the new bytecode
* @param data raw byte data of the class
- * @param class Java class object of the new bytecode
+ * @param klass Java class object of the new bytecode
*/
public static void notify(String name, byte[] data, Class klass) {
- for (Callback c:callbacks) {
+ for (Callback c : callbacks) {
try {
c.notify(name, data, klass);
} catch (Exception e) {
- Py.writeWarning("BytecodeNotification", "Exception from callback:"+e);
+ Py.writeWarning("BytecodeNotification", "Exception from callback:" + e);
}
}
}
diff --git a/src/org/python/core/ClasspathPyImporter.java b/src/org/python/core/ClasspathPyImporter.java
index 34032a74f..04b23ead6 100644
--- a/src/org/python/core/ClasspathPyImporter.java
+++ b/src/org/python/core/ClasspathPyImporter.java
@@ -5,6 +5,7 @@
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
+import java.util.logging.Level;
import org.python.core.util.FileUtil;
import org.python.core.util.StringUtil;
@@ -213,9 +214,10 @@ protected String makeEntry(String filename) {
return null;
}
- private InputStream tryClassLoader(String fullFilename, ClassLoader loader, String name) {
+ private InputStream tryClassLoader(String fullFilename, ClassLoader loader, String place) {
if (loader != null) {
- Py.writeDebug("import", "trying " + fullFilename + " in " + name + " class loader");
+ logger.log(Level.FINE, "# trying {0} in {1} class loader",
+ new Object[] {fullFilename, place});
return loader.getResourceAsStream(fullFilename);
}
return null;
diff --git a/src/org/python/core/Console.java b/src/org/python/core/Console.java
index 88d274029..dfa7a87fa 100644
--- a/src/org/python/core/Console.java
+++ b/src/org/python/core/Console.java
@@ -11,6 +11,8 @@
* use on the console. Such a class may provide line editing and history recall to an interactive
* console. A default implementation (that does not provide any such facilities) is available as
* {@link PlainConsole}.
+ *
+ * @see org.python.core.RegistryKey#PYTHON_CONSOLE
*/
public interface Console {
diff --git a/src/org/python/core/ContainsPyBytecode.java b/src/org/python/core/ContainsPyBytecode.java
new file mode 100644
index 000000000..379862a43
--- /dev/null
+++ b/src/org/python/core/ContainsPyBytecode.java
@@ -0,0 +1,34 @@
+package org.python.core;
+
+/**
+ * Jython stores Python-Bytecode of methods and functions that exceed
+ * JVM method-size restrictions in String literals.
+ * While Java supports rather long strings, constrained only by
+ * int-addressing of arrays, it supports only up to 65535 characters
+ * in literals (not sure how escape-sequences are counted).
+ * To circumvent this limitation, the code is automatically splitted
+ * into several literals with the following naming-scheme.
+ *
+ * - The marker-interface 'ContainsPyBytecode' indicates that a class
+ * contains (static final) literals of the following scheme:
+ * - a prefix of '___' indicates a bytecode-containing string literal
+ * - a number indicating the number of parts follows
+ * - '0_' indicates that no splitting occurred
+ * - otherwise another number follows, naming the index of the literal
+ * - indexing starts at 0
+ *
+ * Examples:
+ * ___0_method1 contains bytecode for method1
+ * ___2_0_method2 contains first part of method2's bytecode
+ * ___2_1_method2 contains second part of method2's bytecode
+ *
+ * Note that this approach is provisional. In future, Jython might contain
+ * the bytecode directly as bytecode-objects. The current approach was
+ * feasible with much less complicated JVM bytecode-manipulation, but needs
+ * special treatment after class-loading.
+ *
+ * In a future approach this interface might be removed.
+ */
+public interface ContainsPyBytecode {
+ // For now this is a pure marker-interface.
+}
diff --git a/src/org/python/core/Deriveds.java b/src/org/python/core/Deriveds.java
index d6a90b038..ebf65666a 100644
--- a/src/org/python/core/Deriveds.java
+++ b/src/org/python/core/Deriveds.java
@@ -1,4 +1,5 @@
-/* Copyright (c) Jython Developers */
+// Copyright (c)2019 Jython Developers.
+// Licensed to PSF under a Contributor Agreement.
package org.python.core;
/**
@@ -46,19 +47,10 @@ public static PyObject __findattr_ex__(PyObject self, String name) {
// pass through to __getattr__
} else {
PyObject getattribute = type.lookup("__getattribute__");
- // This is a horrible hack for eventual consistency of the cache. We hope that the cached version
- // becomes available, but don't wait forever.
- for (int i = 0; i < 100000; i++) {
- if (getattribute != null) {
- break;
- }
- getattribute = type.lookup("__getattribute__");
- }
if (getattribute == null) {
- // This shouldn't happen
- throw Py.SystemError(String.format(
- "__getattribute__ not found on type %s. See http://bugs.jython.org/issue2487 for details.",
- type.getName()));
+ // This shouldn't happen (and isn't always to do with bjo #2487 when it does).
+ throw Py.SystemError(
+ String.format("__getattribute__ not found on type %s", type.getName()));
}
if (getattribute == objectGetattribute) {
type.setUsesObjectGetattribute(true);
diff --git a/src/org/python/core/FunctionThread.java b/src/org/python/core/FunctionThread.java
index 500210772..ea3935991 100644
--- a/src/org/python/core/FunctionThread.java
+++ b/src/org/python/core/FunctionThread.java
@@ -2,8 +2,6 @@
import java.util.concurrent.atomic.AtomicInteger;
-import org.python.modules._systemrestart;
-
public class FunctionThread extends Thread
{
private final PyObject func;
@@ -24,7 +22,7 @@ public void run() {
try {
func.__call__(args);
} catch (PyException exc) {
- if (exc.match(Py.SystemExit) || exc.match(_systemrestart.SystemRestart)) {
+ if (exc.match(Py.SystemExit)) {
return;
}
Py.stderr.println("Unhandled exception in thread started by " + func);
diff --git a/src/org/python/core/JavaImportHelper.java b/src/org/python/core/JavaImportHelper.java
index 633c4b4a1..10d944e49 100644
--- a/src/org/python/core/JavaImportHelper.java
+++ b/src/org/python/core/JavaImportHelper.java
@@ -1,220 +1,220 @@
-package org.python.core;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.TreeMap;
-
-/**
- * Helper class handling the VM specific java package detection.
- */
-public class JavaImportHelper {
-
- private static final String DOT = ".";
-
- /**
- * Try to add the java package.
- *
- * This is handy in cases where the package scan cannot run, or when the initial classpath does not contain all .jar
- * files (such as in J2EE containers).
- *
- * There is some self-healing in the sense that a correct, explicit import of a java class will succeed even if
- * sys.modules already contains a Py.None entry for the corresponding java package.
- *
- * @param packageName The dotted name of the java package
- * @param fromlist A tuple with the from names to import. Can be null or empty.
- *
- * @return true if a java package was doubtlessly identified and added, false
- * otherwise.
- */
- protected static boolean tryAddPackage(final String packageName, PyObject fromlist) {
- // make sure we do not turn off the added flag, once it is set
- boolean packageAdded = false;
-
- if (packageName != null) {
- // check explicit imports first (performance optimization)
-
- // handle 'from java.net import URL' like explicit imports
- List stringFromlist = getFromListAsStrings(fromlist);
- for (String fromName : stringFromlist) {
- if (isJavaClass(packageName, fromName)) {
- packageAdded = addPackage(packageName, packageAdded);
-
- }
- }
-
- // handle 'import java.net.URL' style explicit imports
- int dotPos = packageName.lastIndexOf(DOT);
- if (dotPos > 0) {
- String lastDottedName = packageName.substring(dotPos + 1);
- String packageCand = packageName.substring(0, dotPos);
- if (isJavaClass(packageCand, lastDottedName)) {
- packageAdded = addPackage(packageCand, packageAdded);
- }
- }
-
- // if all else fails, check already loaded packages
- if (!packageAdded) {
- // build the actual map with the packages known to the VM
- Map packages = buildLoadedPackages();
-
- // add known packages
- String parentPackageName = packageName;
- if (isLoadedPackage(packageName, packages)) {
- packageAdded = addPackage(packageName, packageAdded);
- }
- dotPos = 0;
- do {
- dotPos = parentPackageName.lastIndexOf(DOT);
- if (dotPos > 0) {
- parentPackageName = parentPackageName.substring(0, dotPos);
- if (isLoadedPackage(parentPackageName, packages)) {
- packageAdded = addPackage(parentPackageName, packageAdded);
- }
- }
- } while (dotPos > 0);
-
- // handle package imports like 'from java import math'
- for (String fromName : stringFromlist) {
- String fromPackageName = packageName + DOT + fromName;
- if (isLoadedPackage(fromPackageName, packages)) {
- packageAdded = addPackage(fromPackageName, packageAdded);
- }
- }
- }
- }
- return packageAdded;
- }
-
- /**
- * Check if a java package is already known to the VM.
- *
- * May return false even if the given package name is a valid java package !
- *
- * @param packageName
- *
- * @return true if the package with the given name is already loaded by the VM, false
- * otherwise.
- */
- protected static boolean isLoadedPackage(String packageName) {
- return isLoadedPackage(packageName, buildLoadedPackages());
- }
-
- /**
- * Convert the fromlist into a java.lang.String based list.
- *
- * Do some sanity checks: filter out '*' and empty tuples, as well as non tuples.
- *
- * @param fromlist
- * @return a list containing java.lang.String entries
- */
- private static final List getFromListAsStrings(PyObject fromlist) {
- List stringFromlist = new ArrayList();
-
- if (fromlist != null && fromlist != Py.EmptyTuple && fromlist instanceof PyTuple) {
- Iterator iterator = ((PyTuple) fromlist).iterator();
- while (iterator.hasNext()) {
- Object obj = iterator.next();
- if (obj instanceof PyString) {
- obj = ((PyString) obj).getString();
- }
- if (obj instanceof String) {
- String fromName = (String) obj;
- if (!"*".equals(fromName)) {
- stringFromlist.add(fromName);
- }
- }
- }
- }
- return stringFromlist;
- }
-
- /**
- * Faster way to check if a java package is already known to the VM.
- *
- * May return false even if the given package name is a valid java package !
- *
- * @param packageName
- * @param packages A Map containing all packages actually known to the VM. Such a Map can be obtained using
- * {@link JavaImportHelper.buildLoadedPackagesTree()}
- *
- * @return true if the package with the given name is already loaded by the VM, false
- * otherwise.
- */
- private static boolean isLoadedPackage(String javaPackageName, Map packages) {
- boolean isLoaded = false;
- if (javaPackageName != null) {
- isLoaded = packages.containsKey(javaPackageName);
- }
- return isLoaded;
- }
-
- /**
- * Build a Map of the currently known packages to the VM.
- *
- * All parent packages appear as single entries like python modules, e.g. java,
- * java.lang, java.lang.reflect,
- */
- private static Map buildLoadedPackages() {
- TreeMap packageMap = new TreeMap();
- Package[] packages = Package.getPackages();
- for (int i = 0; i < packages.length; i++) {
- String packageName = packages[i].getName();
- packageMap.put(packageName, "");
- int dotPos = 0;
- do {
- dotPos = packageName.lastIndexOf(DOT);
- if (dotPos > 0) {
- packageName = packageName.substring(0, dotPos);
- packageMap.put(packageName, "");
- }
- } while (dotPos > 0);
- }
- return packageMap;
- }
-
- /**
- * @return true if the java class can be found by the current
- * Py classloader setup
- */
- private static boolean isJavaClass(String packageName, String className) {
- return className != null && className.length() > 0
- && Py.findClass(packageName + "." + className) != null;
- }
-
- /**
- * Add a java package to sys.modules, if not already done
- *
- * @return true if something was really added, false otherwise
- */
- private static boolean addPackage(String packageName, boolean packageAdded) {
- PyObject modules = Py.getSystemState().modules;
- String internedPackageName = packageName.intern();
- PyObject module = modules.__finditem__(internedPackageName);
- // a previously failed import could have created a Py.None entry in sys.modules
- if (module == null || module == Py.None) {
- int dotPos = 0;
- do {
- PyJavaPackage p = PySystemState.add_package(packageName);
- if(dotPos == 0) {
- modules.__setitem__(internedPackageName, p);
- } else {
- module = modules.__finditem__(internedPackageName);
- if (module == null || module == Py.None) {
- modules.__setitem__(internedPackageName, p);
- }
- }
- dotPos = packageName.lastIndexOf(DOT);
- if (dotPos > 0) {
- packageName = packageName.substring(0, dotPos);
- internedPackageName = packageName.intern();
- }
- } while(dotPos > 0);
- // make sure not to turn off the packageAdded flag
- packageAdded = true;
- }
- return packageAdded;
- }
-
-}
+package org.python.core;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+/**
+ * Helper class handling the VM specific java package detection.
+ */
+public class JavaImportHelper {
+
+ private static final String DOT = ".";
+
+ /**
+ * Try to add the java package.
+ *
+ * This is handy in cases where the package scan cannot run, or when the initial classpath does
+ * not contain all .jar files (such as in J2EE containers).
+ *
+ * There is some self-healing in the sense that a correct, explicit import of a java class will
+ * succeed even if sys.modules already contains a Py.None entry for the corresponding java
+ * package.
+ *
+ * @param packageName The dotted name of the java package
+ * @param fromlist A tuple with the from names to import. Can be null or empty.
+ *
+ * @return true if a java package was doubtlessly identified and added,
+ * false otherwise.
+ */
+ protected static boolean tryAddPackage(final String packageName, PyObject fromlist) {
+ // make sure we do not turn off the added flag, once it is set
+ boolean packageAdded = false;
+
+ if (packageName != null) {
+ // check explicit imports first (performance optimization)
+
+ // handle 'from java.net import URL' like explicit imports
+ List stringFromlist = getFromListAsStrings(fromlist);
+ for (String fromName : stringFromlist) {
+ if (isJavaClass(packageName, fromName)) {
+ packageAdded = addPackage(packageName, packageAdded);
+ }
+ }
+
+ // handle 'import java.net.URL' style explicit imports
+ int dotPos = packageName.lastIndexOf(DOT);
+ if (dotPos > 0) {
+ String lastDottedName = packageName.substring(dotPos + 1);
+ String packageCand = packageName.substring(0, dotPos);
+ if (isJavaClass(packageCand, lastDottedName)) {
+ packageAdded = addPackage(packageCand, packageAdded);
+ }
+ }
+
+ // if all else fails, check already loaded packages
+ if (!packageAdded) {
+ // build the actual map with the packages known to the VM
+ Map packages = buildLoadedPackages();
+
+ // add known packages
+ String parentPackageName = packageName;
+ if (isLoadedPackage(packageName, packages)) {
+ packageAdded = addPackage(packageName, packageAdded);
+ }
+ dotPos = 0;
+ do {
+ dotPos = parentPackageName.lastIndexOf(DOT);
+ if (dotPos > 0) {
+ parentPackageName = parentPackageName.substring(0, dotPos);
+ if (isLoadedPackage(parentPackageName, packages)) {
+ packageAdded = addPackage(parentPackageName, packageAdded);
+ }
+ }
+ } while (dotPos > 0);
+
+ // handle package imports like 'from java import math'
+ for (String fromName : stringFromlist) {
+ String fromPackageName = packageName + DOT + fromName;
+ if (isLoadedPackage(fromPackageName, packages)) {
+ packageAdded = addPackage(fromPackageName, packageAdded);
+ }
+ }
+ }
+ }
+ return packageAdded;
+ }
+
+ /**
+ * Check if a java package is already known to the VM.
+ *
+ * May return false even if the given package name is a valid java package !
+ *
+ * @param packageName
+ *
+ * @return true if the package with the given name is already loaded by the VM,
+ * false otherwise.
+ */
+ protected static boolean isLoadedPackage(String packageName) {
+ return isLoadedPackage(packageName, buildLoadedPackages());
+ }
+
+ /**
+ * Convert the fromlist into a java.lang.String based list.
+ *
+ * Do some sanity checks: filter out '*' and empty tuples, as well as non tuples.
+ *
+ * @param fromlist
+ * @return a list containing java.lang.String entries
+ */
+ private static final List getFromListAsStrings(PyObject fromlist) {
+ List stringFromlist = new ArrayList();
+
+ if (fromlist != null && fromlist != Py.EmptyTuple && fromlist instanceof PyTuple) {
+ Iterator iterator = ((PyTuple) fromlist).iterator();
+ while (iterator.hasNext()) {
+ Object obj = iterator.next();
+ if (obj instanceof PyString) {
+ obj = ((PyString) obj).getString();
+ }
+ if (obj instanceof String) {
+ String fromName = (String) obj;
+ if (!"*".equals(fromName)) {
+ stringFromlist.add(fromName);
+ }
+ }
+ }
+ }
+ return stringFromlist;
+ }
+
+ /**
+ * Faster way to check if a java package is already known to the VM.
+ *
+ * May return false even if the given package name is a valid java package !
+ *
+ * @param packageName
+ * @param packages A Map containing all packages actually known to the VM. Such a Map can be
+ * obtained using {@link JavaImportHelper.buildLoadedPackagesTree()}
+ *
+ * @return true if the package with the given name is already loaded by the VM,
+ * false otherwise.
+ */
+ private static boolean isLoadedPackage(String javaPackageName, Map packages) {
+ boolean isLoaded = false;
+ if (javaPackageName != null) {
+ isLoaded = packages.containsKey(javaPackageName);
+ }
+ return isLoaded;
+ }
+
+ /**
+ * Build a Map of the currently known packages to the VM.
+ *
+ * All parent packages appear as single entries like python modules, e.g. java,
+ * java.lang, java.lang.reflect,
+ */
+ private static Map buildLoadedPackages() {
+ TreeMap packageMap = new TreeMap();
+ Package[] packages = Package.getPackages();
+ for (int i = 0; i < packages.length; i++) {
+ String packageName = packages[i].getName();
+ packageMap.put(packageName, "");
+ int dotPos = 0;
+ do {
+ dotPos = packageName.lastIndexOf(DOT);
+ if (dotPos > 0) {
+ packageName = packageName.substring(0, dotPos);
+ packageMap.put(packageName, "");
+ }
+ } while (dotPos > 0);
+ }
+ return packageMap;
+ }
+
+ /**
+ * Try to load packageName.className and return {@code true} if successful.
+ *
+ * @return true if the java class can be found by the current Py classloader setup
+ */
+ private static boolean isJavaClass(String packageName, String className) {
+ return className != null && className.length() > 0
+ && Py.findClass(packageName + "." + className) != null;
+ }
+
+ /**
+ * Add a java package to sys.modules, if not already done.
+ *
+ * @return true if something was really added, false otherwise
+ */
+ private static boolean addPackage(String packageName, boolean packageAdded) {
+ PyObject modules = Py.getSystemState().modules;
+ String internedPackageName = packageName.intern();
+ PyObject module = modules.__finditem__(internedPackageName);
+ // a previously failed import could have created a Py.None entry in sys.modules
+ if (module == null || module == Py.None) {
+ int dotPos = 0;
+ do {
+ PyJavaPackage p = PySystemState.add_package(packageName);
+ if(dotPos == 0) {
+ modules.__setitem__(internedPackageName, p);
+ } else {
+ module = modules.__finditem__(internedPackageName);
+ if (module == null || module == Py.None) {
+ modules.__setitem__(internedPackageName, p);
+ }
+ }
+ dotPos = packageName.lastIndexOf(DOT);
+ if (dotPos > 0) {
+ packageName = packageName.substring(0, dotPos);
+ internedPackageName = packageName.intern();
+ }
+ } while(dotPos > 0);
+ // make sure not to turn off the packageAdded flag
+ packageAdded = true;
+ }
+ return packageAdded;
+ }
+}
diff --git a/src/org/python/core/JavaImporter.java b/src/org/python/core/JavaImporter.java
index 6ea381684..b8377ef68 100644
--- a/src/org/python/core/JavaImporter.java
+++ b/src/org/python/core/JavaImporter.java
@@ -1,5 +1,8 @@
package org.python.core;
+import java.util.logging.Logger;
+import java.util.logging.Level;
+
/**
* Load Java classes.
*/
@@ -7,7 +10,9 @@
public class JavaImporter extends PyObject {
public static final String JAVA_IMPORT_PATH_ENTRY = "__classpath__";
+ private static Logger log = Logger.getLogger("org.python.import");
+ @Override
public PyObject __call__(PyObject args[], String keywords[]) {
if(args[0].toString().endsWith(JAVA_IMPORT_PATH_ENTRY)){
return this;
@@ -35,11 +40,11 @@ public PyObject find_module(String name) {
* otherwise
*/
public PyObject find_module(String name, PyObject path) {
- Py.writeDebug("import", "trying " + name
- + " in packagemanager for path " + path);
+ log.log(Level.FINE, "# trying {0} in package manager for path {1}",
+ new Object[] {name, path});
PyObject ret = PySystemState.packageManager.lookupName(name.intern());
if (ret != null) {
- Py.writeComment("import", "'" + name + "' as java package");
+ log.log(Level.CONFIG, "import {0} # as java package", name);
return this;
}
return Py.None;
@@ -54,6 +59,7 @@ public PyObject load_module(String name) {
*
* @return a string representation of the object.
*/
+ @Override
public String toString() {
return this.getType().toString();
}
diff --git a/src/org/python/core/JavaProxyList.java b/src/org/python/core/JavaProxyList.java
index fdf624e9a..0ca502eed 100644
--- a/src/org/python/core/JavaProxyList.java
+++ b/src/org/python/core/JavaProxyList.java
@@ -1,12 +1,5 @@
package org.python.core;
-/**
- * Proxy Java objects implementing java.util.List with Python methods
- * corresponding to the standard list type
- */
-
-import org.python.util.Generic;
-
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -16,7 +9,12 @@
import java.util.List;
import java.util.ListIterator;
+import org.python.util.Generic;
+/**
+ * Proxy Java objects implementing java.util.List with Python methods corresponding to the standard
+ * list type
+ */
class JavaProxyList {
@Untraversable
@@ -35,13 +33,73 @@ protected List asList() {
protected List newList() {
try {
- return (List) asList().getClass().newInstance();
- } catch (IllegalAccessException e) {
- throw Py.JavaError(e);
- } catch (InstantiationException e) {
+ return (List) asList().getClass().getDeclaredConstructor().newInstance();
+ } catch (ReflectiveOperationException | SecurityException
+ | IllegalArgumentException e) {
throw Py.JavaError(e);
}
}
+
+ /**
+ * Compares this object with other to check for equality. Used to implement __eq __ and
+ * __ne__. May return null if the other object cannot be compared i.e. is not a Python list
+ * or Java List.
+ *
+ * @param other The object to compare to this
+ * @return true is equal, false if not equal and null if we can't compare
+ */
+ protected PyBoolean isEqual(PyObject other) {
+ if (isPyList(other)) {
+ // Being compared to a Python list
+ PyList oList = (PyList) other;
+ List jList = asList();
+ if (jList.size() != oList.size()) {
+ // Size mismatched so not equal
+ return Py.False;
+ }
+ for (int i = 0; i < jList.size(); i++) {
+ // Do element by element comparison, if any elements are not equal return false
+ if (!Py.java2py(jList.get(i))._eq(oList.pyget(i)).__nonzero__()) {
+ return Py.False;
+ }
+ }
+ // All elements are equal so the lists are equal
+ return Py.True;
+ } else {
+ // Being compared to something that is not a Python list
+ Object oj = other.getJavaProxy();
+ if (oj instanceof List) {
+ // Being compared to a Java List
+ List oList = (List) oj;
+ List jList = asList();
+ if (jList.size() != oList.size()) {
+ // Size mismatched so not equal
+ return Py.False;
+ }
+ for (int i = 0; i < jList.size(); i++) {
+ /*
+ * Do element by element comparison, if any elements are not equal return
+ * false.
+ */
+ if (!Py.java2py(jList.get(i))._eq(Py.java2py(oList.get(i))).__nonzero__()) {
+ return Py.False;
+ }
+ }
+ // All elements are equal so the lists are equal
+ return Py.True;
+ } else {
+ /*
+ * other is not a Python or Java list, so we don't know if were equal therefore
+ * return null.
+ */
+ return null;
+ }
+ }
+ }
+
+ private boolean isPyList(PyObject object) {
+ return object.getType().isSubType(PyList.TYPE);
+ }
}
protected static class ListIndexDelegate extends SequenceIndexDelegate {
@@ -70,8 +128,9 @@ public PyObject getSlice(int start, int stop, int step) {
int n = PySequence.sliceLength(start, stop, step);
List newList;
try {
- newList = list.getClass().newInstance();
- } catch (Exception e) {
+ newList = list.getClass().getDeclaredConstructor().newInstance();
+ } catch (ReflectiveOperationException | SecurityException
+ | IllegalArgumentException e) {
throw Py.JavaError(e);
}
int j = 0;
@@ -257,6 +316,7 @@ private static class KVComparator implements Comparator {
this.cmp = cmp;
}
+ @Override
public int compare(KV o1, KV o2) {
int result;
if (cmp != null && cmp != Py.None) {
@@ -274,6 +334,7 @@ public int compare(KV o1, KV o2) {
return result;
}
+ @Override
public boolean equals(Object o) {
if (o == this) {
return true;
@@ -339,38 +400,23 @@ public PyObject __call__(PyObject key) {
private static final PyBuiltinMethodNarrow listEqProxy = new ListMethod("__eq__", 1) {
@Override
public PyObject __call__(PyObject other) {
- List jList = asList();
- if (other.getType().isSubType(PyList.TYPE)) {
- PyList oList = (PyList) other;
- if (jList.size() != oList.size()) {
- return Py.False;
- }
- for (int i = 0; i < jList.size(); i++) {
- if (!Py.java2py(jList.get(i))._eq(oList.pyget(i)).__nonzero__()) {
- return Py.False;
- }
- }
- return Py.True;
- } else {
- Object oj = other.getJavaProxy();
- if (oj instanceof List) {
- List oList = (List) oj;
- if (jList.size() != oList.size()) {
- return Py.False;
- }
- for (int i = 0; i < jList.size(); i++) {
- if (!Py.java2py(jList.get(i))._eq(
- Py.java2py(oList.get(i))).__nonzero__()) {
- return Py.False;
- }
- }
- return Py.True;
- } else {
- return null;
- }
+ return isEqual(other);
+ }
+ };
+
+ private static final PyBuiltinMethodNarrow listNeProxy = new ListMethod("__ne__", 1) {
+ @Override
+ public PyObject __call__(PyObject other) {
+ // isEqual may return null if we don't know how to compare to other.
+ PyBoolean equal = isEqual(other);
+ if (equal != null) {
+ // implement NOT equal by the inverse of equal
+ return equal.__not__();
}
+ return null;
}
};
+
private static final PyBuiltinMethodNarrow listAppendProxy = new ListMethod("append", 1) {
@Override
public PyObject __call__(PyObject value) {
@@ -508,10 +554,9 @@ public PyObject __call__(PyObject obj) {
List jList = asList();
List jClone;
try {
- jClone = (List) jList.getClass().newInstance();
- } catch (IllegalAccessException e) {
- throw Py.JavaError(e);
- } catch (InstantiationException e) {
+ jClone = (List) jList.getClass().getDeclaredConstructor().newInstance();
+ } catch (ReflectiveOperationException | SecurityException
+ | IllegalArgumentException e) {
throw Py.JavaError(e);
}
for (Object entry : jList) {
@@ -618,6 +663,7 @@ static PyBuiltinMethod[] getProxyMethods() {
listGetProxy,
listSetProxy,
listEqProxy,
+ listNeProxy,
listRemoveProxy,
listAppendProxy,
listExtendProxy,
@@ -630,13 +676,13 @@ static PyBuiltinMethod[] getProxyMethods() {
listIAddProxy,
new ListMulProxyClass("__mul__", 1),
new ListMulProxyClass("__rmul__", 1),
- listIMulProxy,
- listSortProxy,
+ listIMulProxy
};
}
static PyBuiltinMethod[] getPostProxyMethods() {
return new PyBuiltinMethod[]{
+ listSortProxy,
listRemoveOverrideProxy
};
}
diff --git a/src/org/python/core/JavaProxyMap.java b/src/org/python/core/JavaProxyMap.java
index c0c0a4b75..efbcd2d84 100644
--- a/src/org/python/core/JavaProxyMap.java
+++ b/src/org/python/core/JavaProxyMap.java
@@ -1,17 +1,21 @@
package org.python.core;
+import java.lang.reflect.Constructor;
+import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
+import java.util.Map.Entry;
import java.util.Set;
/**
- * Proxy Java objects implementing java.util.List with Python methods
- * corresponding to the standard list type
+ * Proxy Java objects implementing java.util.List with Python methods corresponding to the standard
+ * list type
*/
class JavaProxyMap {
@Untraversable
private static class MapMethod extends PyBuiltinMethodNarrow {
+
protected MapMethod(String name, int numArgs) {
super(name, numArgs);
}
@@ -27,6 +31,7 @@ protected Map