From d5ee5d9869b8aafab8cb813a83340c757d6c33a9 Mon Sep 17 00:00:00 2001 From: Thomas Calmant Date: Mon, 1 Jun 2026 01:16:14 +0200 Subject: [PATCH 1/6] Fixed bugs found by Copilot review Signed-off-by: Thomas Calmant --- javaobj/v1/beans.py | 2 +- javaobj/v1/transformers.py | 2 +- javaobj/v1/unmarshaller.py | 10 ++++++---- javaobj/v2/transformers.py | 2 +- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/javaobj/v1/beans.py b/javaobj/v1/beans.py index bf867bb..6c41409 100644 --- a/javaobj/v1/beans.py +++ b/javaobj/v1/beans.py @@ -199,7 +199,7 @@ def __init__(self, classdesc=None): self.classdesc = classdesc def __hash__(self): - return list.__hash__(self) + return object.__hash__(self) class JavaByteArray(JavaObject): diff --git a/javaobj/v1/transformers.py b/javaobj/v1/transformers.py index c581125..2a28f1a 100644 --- a/javaobj/v1/transformers.py +++ b/javaobj/v1/transformers.py @@ -136,7 +136,7 @@ def __extra_loading__(self, unmarshaller, ident=0): """ # Ignore the blockdata opid (opid,) = unmarshaller._readStruct(">B") - if opid != ClassDescFlags.SC_BLOCK_DATA: + if opid != TerminalCode.TC_BLOCKDATA: raise ValueError("Start of block data not found") # Read HashMap fields diff --git a/javaobj/v1/unmarshaller.py b/javaobj/v1/unmarshaller.py index 17c9343..47c6cc1 100644 --- a/javaobj/v1/unmarshaller.py +++ b/javaobj/v1/unmarshaller.py @@ -83,7 +83,7 @@ # Convertion of a Java type char to its NumPy equivalent NUMPY_TYPE_MAP = { TypeCode.TYPE_BYTE: "B", - TypeCode.TYPE_CHAR: "b", + TypeCode.TYPE_CHAR: ">u2", TypeCode.TYPE_DOUBLE: ">d", TypeCode.TYPE_FLOAT: ">f", TypeCode.TYPE_INTEGER: ">i", @@ -508,7 +508,8 @@ def do_object(self, parent=None, ident=0): # classdata[] if ( - classdesc.flags & ClassDescFlags.SC_EXTERNALIZABLE + classdesc is not None + and classdesc.flags & ClassDescFlags.SC_EXTERNALIZABLE and not classdesc.flags & ClassDescFlags.SC_BLOCK_DATA ): # TODO: @@ -831,8 +832,9 @@ def _oops_dump_state(self, ignore_remaining_data=False): "(2nd line is an actual position!):" ) - # Do not use a keyword argument - self.object_stream.seek(-16, os.SEEK_CUR) + # Do not use a keyword argument; clamp to avoid seeking before start + current_pos = self.object_stream.tell() + self.object_stream.seek(max(0, current_pos - 16)) position = self.object_stream.tell() the_rest = self.object_stream.read() diff --git a/javaobj/v2/transformers.py b/javaobj/v2/transformers.py index 087eea9..82bfd96 100644 --- a/javaobj/v2/transformers.py +++ b/javaobj/v2/transformers.py @@ -506,7 +506,7 @@ class NumpyArrayTransformer(ObjectTransformer): # Convertion of a Java type char to its NumPy equivalent NUMPY_TYPE_MAP = { TypeCode.TYPE_BYTE: "B", - TypeCode.TYPE_CHAR: "b", + TypeCode.TYPE_CHAR: ">u2", TypeCode.TYPE_DOUBLE: ">d", TypeCode.TYPE_FLOAT: ">f", TypeCode.TYPE_INTEGER: ">i", From 06514f2a989c875086f8ad29684fcec820497c6c Mon Sep 17 00:00:00 2001 From: Thomas Calmant Date: Mon, 1 Jun 2026 01:18:16 +0200 Subject: [PATCH 2/6] Fixed pyproject.toml Signed-off-by: Thomas Calmant --- pyproject.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index c380172..a564a3e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -38,8 +38,8 @@ classifiers = [ ] dependencies = [ - "enum34; python_version<='3.4'", - "typing; python_version<='3.4'" + "enum34; python_version<'3.4'", + "typing; python_version<'3.5'" ] [project.optional-dependencies] From 2e4bf5d7fde9c3b3af2e278526ce4d5a814d2290 Mon Sep 17 00:00:00 2001 From: Thomas Calmant Date: Mon, 1 Jun 2026 01:20:56 +0200 Subject: [PATCH 3/6] Fixed setup.py Signed-off-by: Thomas Calmant --- setup.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index cf93fb8..5e2b29c 100644 --- a/setup.py +++ b/setup.py @@ -72,8 +72,8 @@ def read(fname): packages=["javaobj", "javaobj.v1", "javaobj.v2"], test_suite="tests", install_requires=[ - 'enum34;python_version<="3.4"', - 'typing;python_version<="3.4"', + "enum34; python_version<'3.4'", + "typing; python_version<'3.5'" ], long_description=read("README.md"), long_description_content_type="text/markdown", @@ -91,6 +91,8 @@ def read(fname): "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.14", "Topic :: Software Development :: Libraries :: Python Modules", ], ) From 73c10c6fcc39adc9260bdc89678960f5b86b7eca Mon Sep 17 00:00:00 2001 From: Thomas Calmant Date: Mon, 1 Jun 2026 01:31:33 +0200 Subject: [PATCH 4/6] Quiet down a log in v2 Signed-off-by: Thomas Calmant --- javaobj/v2/core.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javaobj/v2/core.py b/javaobj/v2/core.py index 8e018a6..880be3c 100644 --- a/javaobj/v2/core.py +++ b/javaobj/v2/core.py @@ -146,7 +146,7 @@ def run(self): # Read content contents = [] # type: List[ParsedJavaContent] while True: - self._log.info("Reading next content") + self._log.debug("Reading next content") start = self.__fd.tell() try: type_code = self.__reader.read_byte() From dbdf7eca4bf664f2d7a0f8383e9443dbccff7a4b Mon Sep 17 00:00:00 2001 From: Thomas Calmant Date: Mon, 1 Jun 2026 01:32:03 +0200 Subject: [PATCH 5/6] Support str/unicode comparison in JavaString Adds back Python 2.7 support Signed-off-by: Thomas Calmant --- javaobj/v1/beans.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/javaobj/v1/beans.py b/javaobj/v1/beans.py index 6c41409..03a0f26 100644 --- a/javaobj/v1/beans.py +++ b/javaobj/v1/beans.py @@ -173,9 +173,14 @@ def __hash__(self): return UNICODE_TYPE.__hash__(self) def __eq__(self, other): - if not isinstance(other, UNICODE_TYPE): + # Accept both UNICODE_TYPE and plain str. + # In Python 2, UNICODE_TYPE is unicode while str literals are bytes; + # including str here lets assertEqual(java_string, "literal") work + # in Python 2 as well as Python 3 (where str == UNICODE_TYPE). + if not isinstance(other, (UNICODE_TYPE, str)): return False - return UNICODE_TYPE.__eq__(self, other) + result = UNICODE_TYPE.__eq__(self, other) + return False if result is NotImplemented else result class JavaEnum(JavaObject): From c899f9979cc687baff16689223db174c85d0c1c1 Mon Sep 17 00:00:00 2001 From: Thomas Calmant Date: Mon, 1 Jun 2026 01:32:37 +0200 Subject: [PATCH 6/6] Fixed tests to work on Python 2.7 ... and without having ruff messing with test values Signed-off-by: Thomas Calmant --- tests/test_v1.py | 18 ++++++------------ tests/test_v2.py | 18 ++++++------------ 2 files changed, 12 insertions(+), 24 deletions(-) diff --git a/tests/test_v1.py b/tests/test_v1.py index e22ebc0..65fcd5f 100644 --- a/tests/test_v1.py +++ b/tests/test_v1.py @@ -337,18 +337,12 @@ def test_char_array(self): jobj = self.read_file("testCharArray.ser") pobj = javaobj.loads(jobj) _logger.debug(pobj) - self.assertEqual( - pobj, - [ - "\u0000", - "\ud800", - "\u0001", - "\udc00", - "\u0002", - "\uffff", - "\u0003", - ], - ) + # Compare by code points to avoid Python 2/3 string literal ambiguity + # (ruff strips u"" prefixes; \u-escapes in plain str are literal in Py2) + expected_codepoints = [0x0000, 0xD800, 0x0001, 0xDC00, 0x0002, 0xFFFF, 0x0003] + self.assertEqual(len(pobj), len(expected_codepoints)) + for actual, cp in zip(pobj, expected_codepoints): + self.assertEqual(ord(actual), cp) self._try_marshalling(jobj, pobj) def test_2d_array(self): diff --git a/tests/test_v2.py b/tests/test_v2.py index fbabbda..b4b8503 100644 --- a/tests/test_v2.py +++ b/tests/test_v2.py @@ -417,18 +417,12 @@ def test_char_array(self): jobj = self.read_file("testCharArray.ser") pobj = javaobj.loads(jobj) _logger.debug(pobj) - self.assertEqual( - pobj, - [ - "\u0000", - "\ud800", - "\u0001", - "\udc00", - "\u0002", - "\uffff", - "\u0003", - ], - ) + # Compare by code points to avoid Python 2/3 string literal ambiguity + # (ruff strips u"" prefixes; \u-escapes in plain str are literal in Py2) + expected_codepoints = [0x0000, 0xD800, 0x0001, 0xDC00, 0x0002, 0xFFFF, 0x0003] + self.assertEqual(len(pobj), len(expected_codepoints)) + for actual, cp in zip(pobj, expected_codepoints): + self.assertEqual(ord(actual), cp) def test_2d_array(self): """