Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-serpent for openSUSE:Factory 
checked in at 2026-06-28 21:10:43
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-serpent (Old)
 and      /work/SRC/openSUSE:Factory/.python-serpent.new.11887 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-serpent"

Sun Jun 28 21:10:43 2026 rev:11 rq:1362156 version:1.43

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-serpent/python-serpent.changes    
2025-11-10 19:19:11.589003795 +0100
+++ /work/SRC/openSUSE:Factory/.python-serpent.new.11887/python-serpent.changes 
2026-06-28 21:12:16.949720927 +0200
@@ -1,0 +2,8 @@
+Sun Jun 28 11:17:11 UTC 2026 - Dirk Müller <[email protected]>
+
+- update to serpent-1.43:
+  * Fixed multiple bugs in serialization and parsing (complex
+    number edge cases, custom types etc)
+  * Changed java maven publishing method
+
+-------------------------------------------------------------------

Old:
----
  serpent-1.42.tar.gz

New:
----
  serpent-1.43.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-serpent.spec ++++++
--- /var/tmp/diff_new_pack.Q5L1cZ/_old  2026-06-28 21:12:17.521740270 +0200
+++ /var/tmp/diff_new_pack.Q5L1cZ/_new  2026-06-28 21:12:17.521740270 +0200
@@ -1,7 +1,7 @@
 #
 # spec file for package python-serpent
 #
-# Copyright (c) 2025 SUSE LLC and contributors
+# Copyright (c) 2026 SUSE LLC and contributors
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -18,7 +18,7 @@
 
 %{?sle15_python_module_pythons}
 Name:           python-serpent
-Version:        1.42
+Version:        1.43
 Release:        0
 Summary:        Serialization based on astliteral_eval
 License:        MIT

++++++ serpent-1.42.tar.gz -> serpent-1.43.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/serpent-1.42/PKG-INFO new/serpent-1.43/PKG-INFO
--- old/serpent-1.42/PKG-INFO   2025-10-26 22:58:11.738168200 +0100
+++ new/serpent-1.43/PKG-INFO   2026-05-30 18:30:10.791089300 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 2.4
 Name: serpent
-Version: 1.42
+Version: 1.43
 Summary: Serialization based on ast.literal_eval
 Home-page: https://github.com/irmen/Serpent
 Author: Irmen de Jong
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/serpent-1.42/dotnet/Serpent/Razorvine.Serpent/ComplexNumber.cs 
new/serpent-1.43/dotnet/Serpent/Razorvine.Serpent/ComplexNumber.cs
--- old/serpent-1.42/dotnet/Serpent/Razorvine.Serpent/ComplexNumber.cs  
2025-04-25 12:28:43.000000000 +0200
+++ new/serpent-1.43/dotnet/Serpent/Razorvine.Serpent/ComplexNumber.cs  
2026-05-30 16:56:04.000000000 +0200
@@ -22,7 +22,7 @@
        {
                var sb=new StringBuilder();
                sb.Append(Real);
-               if(Imaginary>0)
+               if(Imaginary>=0 && BitConverter.DoubleToInt64Bits(Imaginary) >= 
0)
                        sb.Append('+');
                return sb.Append(Imaginary).Append('i').ToString();
        }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/serpent-1.42/dotnet/Serpent/Razorvine.Serpent/Parser.cs 
new/serpent-1.43/dotnet/Serpent/Razorvine.Serpent/Parser.cs
--- old/serpent-1.42/dotnet/Serpent/Razorvine.Serpent/Parser.cs 2025-04-25 
12:28:22.000000000 +0200
+++ new/serpent-1.43/dotnet/Serpent/Razorvine.Serpent/Parser.cs 2026-05-30 
16:42:41.000000000 +0200
@@ -93,9 +93,15 @@
                                        // if the last character before the 
closing parenthesis is a 'j', it is a complex number
                                        {
                                                int bm = sr.Bookmark();
-                                               string betweenparens = 
sr.ReadUntil(')', '\n').TrimEnd();
+                                               string betweenparens = 
sr.ReadUntil(')', '\n');
                                                sr.FlipBack(bm);
-                                               return 
betweenparens.EndsWith("j") ? ParseComplex(sr) : ParseTuple(sr);
+                                               string trimmed = 
betweenparens.Trim();
+                                               if(trimmed.EndsWith("j") && 
trimmed.IndexOf(',')<0 && (trimmed.IndexOf('(')<0 || 
trimmed.LastIndexOf('(')==0))
+                                               {
+                                                       // complex number
+                                                       return ParseComplex(sr);
+                                               }
+                                               return ParseTuple(sr);
                                        }
                                default:
                                        throw new ParseException("invalid 
sequencetype char");
@@ -650,23 +656,17 @@
                private Ast.PrimitiveNode<bool> ParseBool(SeekableStringReader 
sr)
                {
                        // True,False
-                       string b = sr.ReadUntil('e');
-                       switch (b)
-                       {
-                               case "Tru":
-                                       return new Ast.BooleanNode(true);
-                               case "Fals":
-                                       return new Ast.BooleanNode(false);
-                       }
-
+                       string b = sr.Peek() == 'T' ? sr.Read(4) : sr.Read(5);
+                       if(b == "True" || b == "False")
+                               return new Ast.BooleanNode(b == "True");
                        throw new ParseException("expected bool, True or 
False");
                }
 
                private Ast.NoneNode ParseNone(SeekableStringReader sr)
                {
                        // None
-                       string n = sr.ReadUntil('e');
-                       if(n=="Non")
+                       string n = sr.Read(4);
+                       if(n == "None")
                                return Ast.NoneNode.Instance;
                        throw new ParseException("expected None");
                }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/serpent-1.42/dotnet/Serpent/Razorvine.Serpent/SeekableStringReader.cs 
new/serpent-1.43/dotnet/Serpent/Razorvine.Serpent/SeekableStringReader.cs
--- old/serpent-1.42/dotnet/Serpent/Razorvine.Serpent/SeekableStringReader.cs   
2024-03-07 01:16:23.000000000 +0100
+++ new/serpent-1.43/dotnet/Serpent/Razorvine.Serpent/SeekableStringReader.cs   
2026-05-30 16:42:25.000000000 +0200
@@ -117,8 +117,13 @@
                                char c=Read();
                                if(c=='#')
                                {
-                                       ReadUntil('\n');
-                                       return;
+                                       try {
+                                               ReadUntil('\n');
+                                       } catch (ParseException) {
+                                               // terminator not found, this 
is fine (comment until end of string)
+                                               _cursor = _str.Length;
+                                       }
+                                       continue;
                                }
 
                                if (char.IsWhiteSpace(c)) 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/serpent-1.42/dotnet/Serpent/Razorvine.Serpent/Serializer.cs 
new/serpent-1.43/dotnet/Serpent/Razorvine.Serpent/Serializer.cs
--- old/serpent-1.42/dotnet/Serpent/Razorvine.Serpent/Serializer.cs     
2025-05-05 22:53:45.000000000 +0200
+++ new/serpent-1.43/dotnet/Serpent/Razorvine.Serpent/Serializer.cs     
2026-05-30 16:56:11.000000000 +0200
@@ -524,9 +524,19 @@
 
                protected void Serialize_complex(ComplexNumber cplx, TextWriter 
tw, int level)
                {
+                       if(double.IsNaN(cplx.Real) || 
double.IsNaN(cplx.Imaginary))
+                       {
+                               tw.Write("{'__class__':'complex','real':");
+                               Serialize_primitive(cplx.Real, tw, level);
+                               tw.Write(",'imag':");
+                               Serialize_primitive(cplx.Imaginary, tw, level);
+                               tw.Write("}");
+                               return;
+                       }
+
                        tw.Write("(");
                        Serialize_primitive(cplx.Real, tw, level);
-                       if(cplx.Imaginary>=0)
+                       if(cplx.Imaginary>=0 && 
BitConverter.DoubleToInt64Bits(cplx.Imaginary) >= 0)
                                tw.Write("+");
                        Serialize_primitive(cplx.Imaginary, tw, level);
                        tw.Write("j)");
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/serpent-1.42/dotnet/Serpent/Tests/ParserTest.cs 
new/serpent-1.43/dotnet/Serpent/Tests/ParserTest.cs
--- old/serpent-1.42/dotnet/Serpent/Tests/ParserTest.cs 2025-04-25 
12:23:51.000000000 +0200
+++ new/serpent-1.43/dotnet/Serpent/Tests/ParserTest.cs 2026-05-30 
16:57:35.000000000 +0200
@@ -73,6 +73,14 @@
         }
 
         [Fact]
+        public void TestNestedComplex()
+        {
+            var p = new Parser();
+            p.Parse("((1, 2j), 3)");
+            p.Parse("(1, (2, 3j))");
+        }
+
+        [Fact]
         public void TestWeirdFloats()
         {
             var p = new Parser();
@@ -480,6 +488,11 @@
             cplx.Real = -3.2e-32;
             cplx.Imaginary = -9.9e-44;
             Assert.Equal(cplx, p.Parse("(-3.2e-32-9.9e-44j)").Root);
+
+            // new cases
+            cplx.Real = 1.0;
+            cplx.Imaginary = -0.0;
+            Assert.Equal(cplx, p.Parse("(1.0-0.0j)").Root);
         }
 
         [Fact]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/serpent-1.42/dotnet/Serpent/Tests/SerializeTest.cs 
new/serpent-1.43/dotnet/Serpent/Tests/SerializeTest.cs
--- old/serpent-1.42/dotnet/Serpent/Tests/SerializeTest.cs      2025-04-25 
12:26:42.000000000 +0200
+++ new/serpent-1.43/dotnet/Serpent/Tests/SerializeTest.cs      2026-05-30 
16:58:06.000000000 +0200
@@ -191,6 +191,10 @@
                ser = serpent.Serialize(cplx);
                data = strip_header(ser);
                Assert.Equal(B("(-2-3j)"), data);
+               cplx = new ComplexNumber(1.0, -0.0);
+               ser = serpent.Serialize(cplx);
+               data = strip_header(ser);
+               Assert.Equal(B("(1-0j)"), data);
                }
                                
                [Fact]
@@ -199,10 +203,11 @@
                        var serpent = new Serializer();
                        var doubles = new object[] {double.PositiveInfinity, 
double.NegativeInfinity, double.NaN,
                                float.PositiveInfinity, float.NegativeInfinity, 
float.NaN,
-                               new ComplexNumber(double.PositiveInfinity, 
3.4)};
+                               new ComplexNumber(double.PositiveInfinity, 3.4),
+                               new ComplexNumber(1.0, double.NaN)};
                        var ser = serpent.Serialize(doubles);
                        var data = strip_header(ser);
-                       
Assert.Equal("(1e30000,-1e30000,{'__class__':'float','value':'nan'},1e30000,-1e30000,{'__class__':'float','value':'nan'},(1e30000+3.4j))",
 S(data));
+                       
Assert.Equal("(1e30000,-1e30000,{'__class__':'float','value':'nan'},1e30000,-1e30000,{'__class__':'float','value':'nan'},(1e30000+3.4j),{'__class__':'complex','real':1,'imag':{'__class__':'float','value':'nan'}})",
 S(data));
                }
 
                [Fact]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/serpent-1.42/dotnet/Serpent/Tests/StringreaderTest.cs 
new/serpent-1.43/dotnet/Serpent/Tests/StringreaderTest.cs
--- old/serpent-1.42/dotnet/Serpent/Tests/StringreaderTest.cs   2025-04-25 
12:26:42.000000000 +0200
+++ new/serpent-1.43/dotnet/Serpent/Tests/StringreaderTest.cs   2026-05-30 
16:31:50.000000000 +0200
@@ -32,6 +32,16 @@
                }
                
                [Fact]
+               public void TestSkipMultipleComments()
+               {
+                       using(var s = new SeekableStringReader("# comment 1\n# 
comment 2\n# comment 3\n[1,2,3]"))
+                       {
+                               s.SkipWhitespace();
+                               Assert.Equal('[', s.Peek());
+                       }
+               }
+
+               [Fact]
                public void TestRead()
                {
                        var s = new SeekableStringReader("hello");
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/serpent-1.42/dotnet/Serpent/Tests/Tests.csproj 
new/serpent-1.43/dotnet/Serpent/Tests/Tests.csproj
--- old/serpent-1.42/dotnet/Serpent/Tests/Tests.csproj  2025-04-25 
12:31:13.000000000 +0200
+++ new/serpent-1.43/dotnet/Serpent/Tests/Tests.csproj  2026-05-30 
16:33:39.000000000 +0200
@@ -1,6 +1,6 @@
 <Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
-    <TargetFramework>net9.0</TargetFramework>
+    <TargetFramework>net10.0</TargetFramework>
     <IsPackable>false</IsPackable>
     <LangVersion>latestmajor</LangVersion>
     <RootNamespace>UnitTests</RootNamespace>
@@ -8,9 +8,9 @@
     <OutputType>Library</OutputType>
   </PropertyGroup>
   <ItemGroup>
-    <PackageReference Include="Microsoft.NET.Test.Sdk" 
Version="17.14.0-preview-25107-01" />
+    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.0.0" />
     <PackageReference Include="xunit" Version="2.9.3" />
-    <PackageReference Include="xunit.runner.visualstudio" Version="3.0.2">
+    <PackageReference Include="xunit.runner.visualstudio" Version="3.1.5">
       <PrivateAssets>all</PrivateAssets>
       <IncludeAssets>runtime; build; native; contentfiles; analyzers; 
buildtransitive</IncludeAssets>
     </PackageReference>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/serpent-1.42/java/.idea/libraries/Maven__org_hamcrest_hamcrest_core_1_3.xml 
new/serpent-1.43/java/.idea/libraries/Maven__org_hamcrest_hamcrest_core_1_3.xml
--- 
old/serpent-1.42/java/.idea/libraries/Maven__org_hamcrest_hamcrest_core_1_3.xml 
    2020-10-06 19:31:54.000000000 +0200
+++ 
new/serpent-1.43/java/.idea/libraries/Maven__org_hamcrest_hamcrest_core_1_3.xml 
    1970-01-01 01:00:00.000000000 +0100
@@ -1,13 +0,0 @@
-<component name="libraryTable">
-  <library name="Maven: org.hamcrest:hamcrest-core:1.3">
-    <CLASSES>
-      <root 
url="jar://$MAVEN_REPOSITORY$/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar!/"
 />
-    </CLASSES>
-    <JAVADOC>
-      <root 
url="jar://$MAVEN_REPOSITORY$/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3-javadoc.jar!/"
 />
-    </JAVADOC>
-    <SOURCES>
-      <root 
url="jar://$MAVEN_REPOSITORY$/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3-sources.jar!/"
 />
-    </SOURCES>
-  </library>
-</component>
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/serpent-1.42/java/mvn-release-readme.txt 
new/serpent-1.43/java/mvn-release-readme.txt
--- old/serpent-1.42/java/mvn-release-readme.txt        2020-10-06 
19:31:54.000000000 +0200
+++ new/serpent-1.43/java/mvn-release-readme.txt        2026-05-30 
18:07:11.000000000 +0200
@@ -1,14 +1,18 @@
-Making a release to Sonatype Nexus/maven central:
+Making a release to Maven Central (Central Publishing Portal):
 
 
-$ mvn release:clean release:prepare release:perform
+First make sure that JAVA_HOME is set (needed for the javadoc tool)
+For example:  export JAVA_HOME=/usr/lib/jvm/java-21-openjdk/
 
 
-Requires version number in the pom.xml to be "x.y-SNAPSHOT".
+Ensure your ~/.m2/settings.xml has a <server> entry for 'central' with your 
User Token.
 
-Finalise and publish the release via 
https://oss.sonatype.org/#stagingRepositories
+$ mvn clean deploy -Prelease
+
+
+Monitor progress and finalise via https://central.sonatype.com
 
 
 See also:
-http://java.dzone.com/articles/deploy-maven-central
-http://central.sonatype.org/pages/apache-maven.html#performing-a-release-deployment
+https://central.sonatype.com
+https://central.sonatype.org/publish/publish-portal/
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/serpent-1.42/java/pom.xml 
new/serpent-1.43/java/pom.xml
--- old/serpent-1.42/java/pom.xml       2021-05-15 00:01:51.000000000 +0200
+++ new/serpent-1.43/java/pom.xml       2026-05-30 18:10:11.000000000 +0200
@@ -1,15 +1,9 @@
 <project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
        <modelVersion>4.0.0</modelVersion>
 
-       <parent>
-               <groupId>org.sonatype.oss</groupId>
-               <artifactId>oss-parent</artifactId>
-               <version>9</version>
-       </parent>
-
        <groupId>net.razorvine</groupId>
        <artifactId>serpent</artifactId>
-       <version>1.41-SNAPSHOT</version>
+       <version>1.43</version>
        <packaging>jar</packaging>
 
        <name>serpent</name>
@@ -19,12 +13,74 @@
                
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        </properties>
        <build>
+               <plugins>
+                       <plugin>
+                               <groupId>org.sonatype.central</groupId>
+                               
<artifactId>central-publishing-maven-plugin</artifactId>
+                               <version>0.7.0</version>
+                               <extensions>true</extensions>
+                               <configuration>
+                                       
<publishingServerId>central</publishingServerId>
+                                       <autoPublish>true</autoPublish>
+                                       <waitUntil>published</waitUntil>
+                               </configuration>
+                       </plugin>
+                       <plugin>
+                               <groupId>org.apache.maven.plugins</groupId>
+                               <artifactId>maven-source-plugin</artifactId>
+                               <version>3.3.1</version>
+                               <executions>
+                                       <execution>
+                                               <id>attach-sources</id>
+                                               <goals>
+                                                       <goal>jar-no-fork</goal>
+                                               </goals>
+                                       </execution>
+                               </executions>
+                       </plugin>
+                       <plugin>
+                               <groupId>org.apache.maven.plugins</groupId>
+                               <artifactId>maven-javadoc-plugin</artifactId>
+                               <version>3.12.0</version>
+                               <configuration>
+                                       <doclint>none</doclint>
+                               </configuration>
+                               <executions>
+                                       <execution>
+                                               <id>attach-javadocs</id>
+                                               <goals>
+                                                       <goal>jar</goal>
+                                               </goals>
+                                       </execution>
+                               </executions>
+                       </plugin>
+                       <plugin>
+                               <groupId>org.apache.maven.plugins</groupId>
+                               <artifactId>maven-enforcer-plugin</artifactId>
+                               <version>3.5.0</version>
+                               <executions>
+                                       <execution>
+                                               <id>enforce-maven</id>
+                                               <goals>
+                                                       <goal>enforce</goal>
+                                               </goals>
+                                               <configuration>
+                                                       <rules>
+                                                               
<requireMavenVersion>
+                                                                       
<version>3.6.3</version>
+                                                               
</requireMavenVersion>
+                                                       </rules>
+                                               </configuration>
+                                       </execution>
+                               </executions>
+                       </plugin>
+               </plugins>
                <pluginManagement>
                        <plugins>
                                <plugin>
                                        
<groupId>org.apache.maven.plugins</groupId>
                                        
<artifactId>maven-compiler-plugin</artifactId>
-                                       <version>3.8.0</version>
+                                       <version>3.15.0</version>
                                        <configuration>
                                                <compilerArgs>
                                                        <arg>-Xlint:all</arg>
@@ -36,19 +92,12 @@
                                <plugin>
                                        
<groupId>org.apache.maven.plugins</groupId>
                                        
<artifactId>maven-gpg-plugin</artifactId>
-                                       <version>1.5</version>
+                                       <version>3.2.8</version>
                                </plugin>
                                <plugin>
                                        
<groupId>org.apache.maven.plugins</groupId>
                                        
<artifactId>maven-release-plugin</artifactId>
-                                       <version>2.5.2</version>
-                               </plugin>
-                               <plugin>
-                                       
<groupId>org.apache.maven.plugins</groupId>
-                                       
<artifactId>maven-javadoc-plugin</artifactId>
-                                       <configuration>
-                                               <doclint>none</doclint>
-                                       </configuration>
+                                       <version>3.3.1</version>
                                </plugin>
                        </plugins>
                </pluginManagement>
@@ -57,7 +106,7 @@
                <dependency>
                        <groupId>junit</groupId>
                        <artifactId>junit</artifactId>
-                       <version>4.13.1</version>
+                       <version>4.13.2</version>
                        <scope>test</scope>
                </dependency>
        </dependencies>
@@ -69,7 +118,7 @@
        <scm>
                <url>https://github.com/irmen/Serpent</url>
                
<connection>scm:git:https://github.com/irmen/Serpent.git</connection>
-               
<developerConnection>scm:git:https://github.com/irmen/Serpent.git</developerConnection>
+        
<developerConnection>scm:git:[email protected]:irmen/Serpent.git</developerConnection>
                <tag>HEAD</tag>
        </scm>
        <issueManagement>
@@ -92,4 +141,27 @@
                        
<url>http://www.opensource.org/licenses/mit-license.php</url>
                </license>
        </licenses>
+       <profiles>
+               <profile>
+                       <id>release</id>
+                       <build>
+                               <plugins>
+                                       <plugin>
+                                               
<groupId>org.apache.maven.plugins</groupId>
+                                               
<artifactId>maven-gpg-plugin</artifactId>
+                                               <version>3.2.8</version>
+                                               <executions>
+                                                       <execution>
+                                                               
<id>sign-artifacts</id>
+                                                               
<phase>verify</phase>
+                                                               <goals>
+                                                                       
<goal>sign</goal>
+                                                               </goals>
+                                                       </execution>
+                                               </executions>
+                                       </plugin>
+                               </plugins>
+                       </build>
+               </profile>
+       </profiles>
 </project>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/serpent-1.42/java/src/main/java/net/razorvine/serpent/ComplexNumber.java 
new/serpent-1.43/java/src/main/java/net/razorvine/serpent/ComplexNumber.java
--- 
old/serpent-1.42/java/src/main/java/net/razorvine/serpent/ComplexNumber.java    
    2020-10-06 19:31:54.000000000 +0200
+++ 
new/serpent-1.43/java/src/main/java/net/razorvine/serpent/ComplexNumber.java    
    2026-05-30 16:52:37.000000000 +0200
@@ -29,7 +29,7 @@
        {
                StringBuilder sb=new StringBuilder();
                sb.append(real);
-               if(imaginary>0)
+               if(imaginary>=0 && Math.copySign(1.0, imaginary) > 0)
                        sb.append('+');
                return sb.append(imaginary).append('i').toString();
        }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/serpent-1.42/java/src/main/java/net/razorvine/serpent/Parser.java 
new/serpent-1.43/java/src/main/java/net/razorvine/serpent/Parser.java
--- old/serpent-1.42/java/src/main/java/net/razorvine/serpent/Parser.java       
2021-05-10 22:30:25.000000000 +0200
+++ new/serpent-1.43/java/src/main/java/net/razorvine/serpent/Parser.java       
2026-05-30 16:40:53.000000000 +0200
@@ -107,9 +107,15 @@
                                // if the last character before the closing 
parenthesis is a 'j', it is a complex number
                                {
                                        int bm = sr.bookmark();
-                                       String betweenparens = 
sr.readUntil(")\n").trim();
+                                       String betweenparens = 
sr.readUntil(")\n");
                                        sr.flipBack(bm);
-                                       return betweenparens.endsWith("j") ? 
parseComplex(sr) : parseTuple(sr);
+                                       String trimmed = betweenparens.trim();
+                                       if(trimmed.endsWith("j") && 
trimmed.indexOf(',')<0 && (trimmed.indexOf('(')<0 || 
trimmed.lastIndexOf('(')==0))
+                                       {
+                                               // complex number
+                                               return parseComplex(sr);
+                                       }
+                                       return parseTuple(sr);
                                }
                        default:
                                throw new ParseException("invalid sequencetype 
char");
@@ -644,19 +650,17 @@
        PrimitiveNode<Boolean> parseBool(SeekableStringReader sr)
        {
                // True,False
-               String b = sr.readUntil('e');
-               if(b.equals("Tru"))
-                       return new BooleanNode(true);
-               if(b.equals("Fals"))
-                       return new BooleanNode(false);
+               String b = sr.peek()=='T'? sr.read(4) : sr.read(5);
+               if(b.equals("True") || b.equals("False"))
+                       return new BooleanNode(b.equals("True"));
                throw new ParseException("expected bool, True or False");
        }
 
        NoneNode parseNone(SeekableStringReader sr)
        {
                // None
-               String n = sr.readUntil('e');
-               if(n.equals("Non"))
+               String n = sr.read(4);
+               if(n.equals("None"))
                        return NoneNode.Instance;
                throw new ParseException("expected None");
        }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/serpent-1.42/java/src/main/java/net/razorvine/serpent/SeekableStringReader.java
 
new/serpent-1.43/java/src/main/java/net/razorvine/serpent/SeekableStringReader.java
--- 
old/serpent-1.42/java/src/main/java/net/razorvine/serpent/SeekableStringReader.java
 2020-10-06 19:31:54.000000000 +0200
+++ 
new/serpent-1.43/java/src/main/java/net/razorvine/serpent/SeekableStringReader.java
 2026-05-30 16:36:06.000000000 +0200
@@ -149,8 +149,13 @@
                        char c=read();
                        if(c=='#')
                        {
-                               readUntil('\n');
-                               return;
+                               try {
+                                       readUntil('\n');
+                               } catch (ParseException x) {
+                                       // terminator not found, this is fine 
(comment until end of string)
+                                       cursor = str.length();
+                               }
+                               continue;
                        }
                        if(!Character.isWhitespace(c))
                        {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/serpent-1.42/java/src/main/java/net/razorvine/serpent/Serializer.java 
new/serpent-1.43/java/src/main/java/net/razorvine/serpent/Serializer.java
--- old/serpent-1.42/java/src/main/java/net/razorvine/serpent/Serializer.java   
2021-05-10 22:02:49.000000000 +0200
+++ new/serpent-1.43/java/src/main/java/net/razorvine/serpent/Serializer.java   
2026-05-30 16:53:38.000000000 +0200
@@ -504,9 +504,19 @@
 
        protected void serialize_complex(ComplexNumber cplx, StringWriter sw, 
int level)
        {
+               if(Double.isNaN(cplx.real) || Double.isNaN(cplx.imaginary))
+               {
+                       sw.write("{'__class__':'complex','real':");
+                       serialize_primitive(cplx.real, sw, level);
+                       sw.write(",'imag':");
+                       serialize_primitive(cplx.imaginary, sw, level);
+                       sw.write("}");
+                       return;
+               }
+
                sw.write("(");
                serialize_primitive(cplx.real, sw, level);
-               if(cplx.imaginary>=0)
+               if(cplx.imaginary>=0 && Math.copySign(1.0, cplx.imaginary) > 0)
                        sw.write("+");
                serialize_primitive(cplx.imaginary, sw, level);
                sw.write("j)");
@@ -588,7 +598,7 @@
        }
 
        protected IClassSerializer getCustomConverter(Class<?> type) {
-               IClassSerializer converter = 
classToDictRegistry.get(type.getClass());
+               IClassSerializer converter = classToDictRegistry.get(type);
                if(converter!=null) {
                        return converter; // exact match
                }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/serpent-1.42/java/src/test/java/net/razorvine/serpent/test/ParserTest.java 
new/serpent-1.43/java/src/test/java/net/razorvine/serpent/test/ParserTest.java
--- 
old/serpent-1.42/java/src/test/java/net/razorvine/serpent/test/ParserTest.java  
    2020-10-06 19:31:54.000000000 +0200
+++ 
new/serpent-1.43/java/src/test/java/net/razorvine/serpent/test/ParserTest.java  
    2026-05-30 16:57:03.000000000 +0200
@@ -102,6 +102,14 @@
        }
        
        @Test
+       public void TestNestedComplex()
+       {
+               Parser p = new Parser();
+               p.parse("((1, 2j), 3)");
+               p.parse("(1, (2, 3j))");
+       }
+
+       @Test
        public void TestWeirdFloats()
        {
                Parser p = new Parser();
@@ -478,6 +486,11 @@
                cplx.real = -3.2e-32;
                cplx.imaginary = -9.9e-44;
                assertEquals(cplx, p.parse("(-3.2e-32-9.9e-44j)").root);        
        
+               
+               // new cases
+               cplx.real = 1.0;
+               cplx.imaginary = -0.0;
+               assertEquals(cplx, p.parse("(1.0-0.0j)").root);
        }
 
        @Test
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/serpent-1.42/java/src/test/java/net/razorvine/serpent/test/SerializeTest.java
 
new/serpent-1.43/java/src/test/java/net/razorvine/serpent/test/SerializeTest.java
--- 
old/serpent-1.42/java/src/test/java/net/razorvine/serpent/test/SerializeTest.java
   2021-05-10 22:43:58.000000000 +0200
+++ 
new/serpent-1.43/java/src/test/java/net/razorvine/serpent/test/SerializeTest.java
   2026-05-30 16:57:30.000000000 +0200
@@ -81,6 +81,38 @@
 
 
        @Test
+       public void testCustomConverter()
+       {
+               class MyClass implements Serializable {
+                       public String name = "test";
+               }
+               
+               class MyConverter implements IClassSerializer {
+                       public Map<String, Object> convert(Object obj) {
+                               Map<String, Object> result = new HashMap<>();
+                               result.put("__class__", "ConvertedMyClass");
+                               return result;
+                       }
+               }
+
+               class ObjectConverter implements IClassSerializer {
+                       public Map<String, Object> convert(Object obj) {
+                               Map<String, Object> result = new HashMap<>();
+                               result.put("__class__", "ConvertedObject");
+                               return result;
+                       }
+               }
+
+               Serializer.registerClass(MyClass.class, new MyConverter());
+               
+               Serializer ser = new Serializer();
+               byte[] data = ser.serialize(new MyClass());
+               String result = S(data);
+               
+               assertTrue(result.contains("ConvertedMyClass"));
+       }
+
+       @Test
        public void testException()
        {
                Serializer.registerClass(IllegalArgumentException.class, null);
@@ -404,6 +436,10 @@
         ser = serpent.serialize(cplx);
         data = strip_header(ser);
         assertEquals("(-2.5-3.9j)", S(data));
+        cplx = new ComplexNumber(1.0, -0.0);
+        ser = serpent.serialize(cplx);
+        data = strip_header(ser);
+        assertEquals("(1.0-0.0j)", S(data));
        }
 
        @Test
@@ -412,10 +448,11 @@
                Serializer serpent = new Serializer();
                Object[] doubles = new Object[] {Double.POSITIVE_INFINITY, 
Double.NEGATIVE_INFINITY, Double.NaN,
                                Float.POSITIVE_INFINITY, 
Float.NEGATIVE_INFINITY, Float.NaN,
-                       new ComplexNumber(Double.POSITIVE_INFINITY, 3.3)};
+                       new ComplexNumber(Double.POSITIVE_INFINITY, 3.3),
+                       new ComplexNumber(1.0, Double.NaN)};
                byte[] ser = serpent.serialize(doubles);
                byte[] data = strip_header(ser);
-               
assertEquals("(1e30000,-1e30000,{'__class__':'float','value':'nan'},1e30000,-1e30000,{'__class__':'float','value':'nan'},(1e30000+3.3j))",
 S(data));
+               
assertEquals("(1e30000,-1e30000,{'__class__':'float','value':'nan'},1e30000,-1e30000,{'__class__':'float','value':'nan'},(1e30000+3.3j),{'__class__':'complex','real':1.0,'imag':{'__class__':'float','value':'nan'}})",
 S(data));
        }
 
        @Test
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/serpent-1.42/java/src/test/java/net/razorvine/serpent/test/StringreaderTest.java
 
new/serpent-1.43/java/src/test/java/net/razorvine/serpent/test/StringreaderTest.java
--- 
old/serpent-1.42/java/src/test/java/net/razorvine/serpent/test/StringreaderTest.java
        2020-10-06 19:31:54.000000000 +0200
+++ 
new/serpent-1.43/java/src/test/java/net/razorvine/serpent/test/StringreaderTest.java
        2026-05-30 16:31:42.000000000 +0200
@@ -46,6 +46,14 @@
        }
        
        @Test
+       public void testSkipMultipleComments()
+       {
+               SeekableStringReader s = new SeekableStringReader("# comment 
1\n# comment 2\n# comment 3\n[1,2,3]");
+               s.skipWhitespace();
+               assertEquals('[', s.peek());
+       }
+
+       @Test
        public void testRanges()
        {
                SeekableStringReader s = new SeekableStringReader("hello");
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/serpent-1.42/serpent.egg-info/PKG-INFO 
new/serpent-1.43/serpent.egg-info/PKG-INFO
--- old/serpent-1.42/serpent.egg-info/PKG-INFO  2025-10-26 22:58:11.000000000 
+0100
+++ new/serpent-1.43/serpent.egg-info/PKG-INFO  2026-05-30 18:30:10.000000000 
+0200
@@ -1,6 +1,6 @@
 Metadata-Version: 2.4
 Name: serpent
-Version: 1.42
+Version: 1.43
 Summary: Serialization based on ast.literal_eval
 Home-page: https://github.com/irmen/Serpent
 Author: Irmen de Jong
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/serpent-1.42/serpent.egg-info/SOURCES.txt 
new/serpent-1.43/serpent.egg-info/SOURCES.txt
--- old/serpent-1.42/serpent.egg-info/SOURCES.txt       2025-10-26 
22:58:11.000000000 +0100
+++ new/serpent-1.43/serpent.egg-info/SOURCES.txt       2026-05-30 
18:30:10.000000000 +0200
@@ -35,7 +35,6 @@
 java/mvn-release-readme.txt
 java/pom.xml
 java/serpent.iml
-java/.idea/libraries/Maven__org_hamcrest_hamcrest_core_1_3.xml
 java/src/main/java/net/razorvine/serpent/ComplexNumber.java
 java/src/main/java/net/razorvine/serpent/DebugVisitor.java
 java/src/main/java/net/razorvine/serpent/IClassSerializer.java
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/serpent-1.42/serpent.py new/serpent-1.43/serpent.py
--- old/serpent-1.42/serpent.py 2025-10-26 22:57:18.000000000 +0100
+++ new/serpent-1.43/serpent.py 2026-05-30 17:06:34.000000000 +0200
@@ -55,7 +55,7 @@
 import enum
 from collections.abc import KeysView, ValuesView, ItemsView
 
-__version__ = "1.42"
+__version__ = "1.43"
 __all__ = ["dump", "dumps", "load", "loads", "register_class", 
"unregister_class", "tobytes"]
 
 
@@ -99,11 +99,17 @@
 
 
 def _ser_OrderedDict(obj, serializer, outputstream, indentlevel):
-    obj = {
-        "__class__": "collections.OrderedDict" if 
serializer.module_in_classname else "OrderedDict",
-        "items": list(obj.items())
-    }
-    serializer._serialize(obj, outputstream, indentlevel)
+    if id(obj) in serializer.serialized_obj_ids:
+        raise ValueError("Circular reference detected (OrderedDict)")
+    serializer.serialized_obj_ids.add(id(obj))
+    try:
+        obj = {
+            "__class__": "collections.OrderedDict" if 
serializer.module_in_classname else "OrderedDict",
+            "items": list(obj.items())
+        }
+        serializer._serialize(obj, outputstream, indentlevel)
+    finally:
+        serializer.serialized_obj_ids.discard(id(obj))
 
 
 def _ser_DictView(obj, serializer, outputstream, indentlevel):
@@ -289,9 +295,16 @@
     dispatch[float] = ser_builtins_float
 
     def ser_builtins_complex(self, complex_obj, out, level):
+        if math.isnan(complex_obj.real) or math.isnan(complex_obj.imag):
+            out.append("{'__class__':'complex','real':")
+            self.ser_builtins_float(complex_obj.real, out, level)
+            out.append(",'imag':")
+            self.ser_builtins_float(complex_obj.imag, out, level)
+            out.append("}")
+            return
         out.append("(")
         self.ser_builtins_float(complex_obj.real, out, level)
-        if complex_obj.imag >= 0:
+        if complex_obj.imag >= 0 and math.copysign(1.0, complex_obj.imag) > 0:
             out.append("+")
         self.ser_builtins_float(complex_obj.imag, out, level)
         out.append("j)")
@@ -499,6 +512,9 @@
             if has_own_getstate:
                 value = obj.__getstate__()
                 if isinstance(value, dict):
+                    if "__class__" not in value:
+                        value = value.copy()
+                        value["__class__"] = self.get_class_name(obj)
                     self.ser_builtins_dict(value, out, level)
                     return
             else:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/serpent-1.42/tests/test_serpent.py 
new/serpent-1.43/tests/test_serpent.py
--- old/serpent-1.42/tests/test_serpent.py      2022-06-26 15:30:37.000000000 
+0200
+++ new/serpent-1.43/tests/test_serpent.py      2026-05-30 16:56:43.000000000 
+0200
@@ -299,6 +299,12 @@
         ser = serpent.dumps(2 - 3j)
         data = strip_header(ser)
         self.assertEqual(b"(2.0-3.0j)", data)
+        ser = serpent.dumps(complex(1.0, -0.0))
+        data = strip_header(ser)
+        self.assertEqual(b"(1.0-0.0j)", data)
+        ser = serpent.dumps(complex(float('nan'), 1.0))
+        data = strip_header(ser)
+        self.assertIn(b"'__class__':'complex'", data)
 
     def test_bool(self):
         ser = serpent.dumps(True)
@@ -495,7 +501,18 @@
         c = Class2()
         ser = serpent.dumps(c)
         data = serpent.loads(ser)
-        self.assertEqual({'attr': 42}, data)
+        self.assertEqual({'__class__': 'Class2', 'attr': 42}, data)
+
+    def test_class_getstate_dict(self):
+        class MyObj:
+            def __init__(self, val):
+                self.val = val
+            def __getstate__(self):
+                return {"val": self.val}
+        obj = MyObj(42)
+        ser = serpent.dumps(obj).decode('utf-8')
+        self.assertIn("'__class__':'MyObj'", ser)
+        self.assertIn("'val':42", ser)
 
     def test_class_slots(self):
         c = SlotsClass()
@@ -972,6 +989,13 @@
             serpent.dumps(d)
         self.assertEqual("Circular reference detected (class)", 
str(e.exception))
 
+    def testOrderedDictCycle(self):
+        od = collections.OrderedDict()
+        od['self'] = od
+        with self.assertRaises(ValueError) as e:
+            serpent.dumps(od)
+        self.assertEqual("Circular reference detected (OrderedDict)", 
str(e.exception))
+
     # noinspection PyUnreachableCode
     def testMaxLevel(self):
         ser = serpent.Serializer()

Reply via email to