Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-pony for openSUSE:Factory 
checked in at 2026-07-07 21:06:17
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-pony (Old)
 and      /work/SRC/openSUSE:Factory/.python-pony.new.1982 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-pony"

Tue Jul  7 21:06:17 2026 rev:17 rq:1364309 version:0.7.19

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-pony/python-pony.changes  2025-10-29 
21:07:31.984836012 +0100
+++ /work/SRC/openSUSE:Factory/.python-pony.new.1982/python-pony.changes        
2026-07-07 21:08:52.234056098 +0200
@@ -1,0 +2,7 @@
+Tue Jul  7 10:41:32 UTC 2026 - Nico Krapp <[email protected]>
+
+- Add py313.patch and py314.patch to support Python 3.13 and Python 3.14
+- remove skip for Python 3.13 and Python 3.14
+- add skip for Python 3.15
+
+-------------------------------------------------------------------

New:
----
  py313.patch
  py314.patch

----------(New B)----------
  New:
- Add py313.patch and py314.patch to support Python 3.13 and Python 3.14
- remove skip for Python 3.13 and Python 3.14
  New:
- Add py313.patch and py314.patch to support Python 3.13 and Python 3.14
- remove skip for Python 3.13 and Python 3.14
----------(New E)----------

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

Other differences:
------------------
++++++ python-pony.spec ++++++
--- /var/tmp/diff_new_pack.YoV6Fa/_old  2026-07-07 21:08:52.922079877 +0200
+++ /var/tmp/diff_new_pack.YoV6Fa/_new  2026-07-07 21:08:52.926080016 +0200
@@ -1,7 +1,7 @@
 #
 # spec file for package python-pony
 #
-# 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
@@ -17,8 +17,7 @@
 
 
 # not compatible: https://github.com/ponyorm/pony/blob/v0.7.17/setup.py#L112
-%define skip_python313 1
-%define skip_python314 1
+%define skip_python315 1
 Name:           python-pony
 Version:        0.7.19
 Release:        0
@@ -26,6 +25,10 @@
 License:        Apache-2.0
 URL:            https://ponyorm.com
 Source:         
https://files.pythonhosted.org/packages/source/p/pony/pony-%{version}.tar.gz
+# PATCH-FIX-UPSTREAM py313.patch to support Python 3.13 gh#ponyorm/pony@179cb05
+Patch0:         py313.patch
+# PATCH-FIX-UPSTREAM py314.patch to support Python 3.14 gh#ponyorm/pony#754
+Patch1:         py314.patch
 BuildRequires:  %{python_module base}
 BuildRequires:  %{python_module pip}
 BuildRequires:  %{python_module setuptools}

++++++ py313.patch ++++++
>From a52bdba67123e2f7be78e04bb67339411c46df8e Mon Sep 17 00:00:00 2001
From: black-sliver <[email protected]>
Date: Thu, 21 Aug 2025 00:29:59 +0200
Subject: [PATCH 1/6] Py3.13: add missing iter to ResultIterator

---
 pony/orm/core.py | 2 ++
 1 file changed, 2 insertions(+)

Index: pony-0.7.19/pony/orm/core.py
===================================================================
--- pony-0.7.19.orig/pony/orm/core.py
+++ pony-0.7.19/pony/orm/core.py
@@ -6282,6 +6282,8 @@ class QueryResultIterator(object):
         self._position += 1
         return item
     __next__ = next
+    def __iter__(self):
+        return self 
     def __length_hint__(self):
         return len(self._query_result) - self._position
 
Index: pony-0.7.19/pony/orm/decompiling.py
===================================================================
--- pony-0.7.19.orig/pony/orm/decompiling.py
+++ pony-0.7.19/pony/orm/decompiling.py
@@ -1,5 +1,5 @@
 from __future__ import absolute_import, print_function, division
-from pony.py23compat import PY36, PY37, PY38, PY39, PY310, PY311, PY312, PYPY
+from pony.py23compat import PY36, PY37, PY38, PY39, PY310, PY311, PY312, 
PY313, PYPY
 
 import sys, types, inspect
 from opcode import opname as opnames, HAVE_ARGUMENT, EXTENDED_ARG, cmp_op
@@ -194,6 +194,10 @@ class Decompiler(object):
                         oparg = co_code[i] + co_code[i + 1] * 256 + oparg * 
65536
                         i += 2
 
+            # CACHE bytes have inconvenient placement in py3.13, so we need to 
skip them
+            while i < len(code.co_code) and opnames[code.co_code[i]] == 
'CACHE':
+                i += 2
+
             opname = opnames[op].replace('+', '_')
             if op >= HAVE_ARGUMENT:
                 if op in hasconst:
@@ -217,9 +221,18 @@ class Decompiler(object):
                     arg = [i + oparg * (2 if PY310 else 1)
                            * (-1 if 'BACKWARD' in opname else 1)]
                 elif op in haslocal:
-                    arg = [code.co_varnames[oparg]]
+                    if opname in {'LOAD_FAST_LOAD_FAST', 
'STORE_FAST_LOAD_FAST', 'STORE_FAST_STORE_FAST'}:
+                        # py3.13: 2 4bit args
+                        arg = [code._varname_from_oparg(oparg >> 4), 
code._varname_from_oparg(oparg & 0x0f)]
+                    elif PY313:
+                        # co_varnames is incomplete now
+                        arg = [code._varname_from_oparg(oparg)]
+                    else:
+                        arg = [code.co_varnames[oparg]]
                 elif op in hascompare:
-                    if PY312:
+                    if PY313:
+                        oparg >>= 5
+                    elif PY312:
                         oparg >>= 4
                     arg = [cmp_op[oparg]]
                 elif op in hasfree:
@@ -230,6 +243,10 @@ class Decompiler(object):
                     arg = [oparg * (2 if PY310 else 1)]
                 else:
                     arg = [oparg]
+            elif PY313 and opname == 'MAKE_FUNCTION' and 
opnames[code.co_code[i]] == 'SET_FUNCTION_ATTRIBUTE':
+                # pull attributes from next instruction
+                arg = [code.co_code[i+1]]
+                i += 2
             else: arg = []
             if opname == 'FOR_ITER':
                 decompiler.for_iter_pos = decompiler.pos
@@ -390,6 +407,11 @@ class Decompiler(object):
         end = decompiler.stack.pop()
         start = decompiler.stack.pop()
         node1 = decompiler.stack.pop()
+        if PY313:
+            if isinstance(end, ast.Constant) and end.value is None:
+                end = None
+            if isinstance(start, ast.Constant) and start.value is None:
+                start = None
         node2 = ast.Slice(start, end, ctx=ast.Load())
         return ast.Subscript(value=node1, slice=node2, ctx=ast.Load())
 
@@ -502,12 +524,19 @@ class Decompiler(object):
             args = values[:-len(keys)]
             keywords = [ast.keyword(k, v) for k, v in zip(keys, 
values[-len(keys):])]
 
-        self = decompiler.stack.pop()
-        callable_ = decompiler.stack.pop()
-        if callable_ is None:
-            callable_ = self
+        if PY313:
+            # self/NULL and callable are swapped
+            self_ = decompiler.stack.pop()
+            callable_ = decompiler.stack.pop()
+            if self_ is not None:
+                args.insert(0, self_)
         else:
-            args.insert(0, self)
+            self_ = decompiler.stack.pop()
+            callable_ = decompiler.stack.pop()
+            if callable_ is None:
+                callable_ = self_
+            else:
+                args.insert(0, self_)
         decompiler.stack.append(callable_)
         return decompiler._call_function(args, keywords)
 
@@ -545,6 +574,12 @@ class Decompiler(object):
         star = decompiler.stack.pop()
         args = [ast.Starred(value=star)] if star else None
         keywords = [ast.keyword(value=star2)] if star2 else None
+        if PY313:
+            # self/NULL and callable are swapped; FIXME: this leaves NULL on 
the stack?
+            self_ = decompiler.stack.pop()
+            callable_ = decompiler.stack.pop()
+            decompiler.stack.append(self_)
+            decompiler.stack.append(callable_)
         return decompiler._call_function(args, keywords)
 
     def CALL_METHOD(decompiler, argc):
@@ -566,12 +601,24 @@ class Decompiler(object):
         method = pop()
         return ast.Call(method, args, keywords)
 
+    def CALL_KW(decompiler, argc):
+        names = decompiler.stack.pop()
+        if isinstance(names, ast.Constant):
+            decompiler.kw_names = names.value
+        else:
+            raise NotImplementedError(f"CALL_KW for {names.__class__.__name__} 
not implemented")
+        return decompiler.CALL(argc)
+
     def COMPARE_OP(decompiler, op):
         oper2 = decompiler.stack.pop()
         oper1 = decompiler.stack.pop()
         op = operator_mapping[op]()
         return ast.Compare(oper1, [op], [oper2])
 
+    def CONVERT_VALUE(decompiler, conversion):
+        value = decompiler.stack.pop()
+        return value, [-1, ord('s'), ord('r'), ord('a')][conversion]
+
     def COPY(decompiler, _):
         pass  # this is not great, but stack is not the same as during runtime
         # actual queries are hopefully covered by tests
@@ -609,6 +656,25 @@ class Decompiler(object):
             value = decompiler.stack.pop()
         return ast.FormattedValue(value=value, conversion=conversion, 
format_spec=format_spec)
 
+    def FORMAT_SIMPLE(decompiler):
+        # see CONVERT_VALUE
+        args = decompiler.stack.pop()
+        if isinstance(args, tuple):
+            value, conversion = args
+        else:
+            value, conversion = args, -1
+        return ast.FormattedValue(value=value, conversion=conversion)
+
+    def FORMAT_WITH_SPEC(decompiler):
+        spec = decompiler.stack.pop()
+        args = decompiler.stack.pop()
+        if isinstance(args, tuple):
+            # FIXME: is this correct here? should we look for 
ast.FormattedValue instead?
+            value, conversion = args
+        else:
+            value, conversion = args, -1
+        return ast.FormattedValue(value=value, conversion=conversion, 
format_spec=spec)
+
     def GEN_START(decompiler, kind):
         assert kind == 0  # only support sync
 
@@ -791,7 +857,12 @@ class Decompiler(object):
 
     def LOAD_ATTR(decompiler, attr_name, push_null):
         res = ast.Attribute(decompiler.stack.pop(), attr_name, ast.Load())
-        if push_null:
+        if push_null and PY313:
+            # NULL and attr swapped
+            decompiler.stack.append(res)
+            decompiler.stack.append(None)
+            return None
+        elif push_null:
             decompiler.stack.append(None)
         return res
 
@@ -810,13 +881,24 @@ class Decompiler(object):
         decompiler.names.add(varname)
         return ast.Name(varname, ast.Load())
 
+    def LOAD_FAST_LOAD_FAST(decompiler, varname1, varname2):
+        decompiler.names.add(varname1)
+        decompiler.stack.append(ast.Name(varname1, ast.Load()))
+        return decompiler.LOAD_FAST(varname2)
+
     LOAD_FAST_AND_CLEAR = LOAD_FAST
 
     def LOAD_GLOBAL(decompiler, varname, push_null):
-        if push_null:
-            decompiler.stack.append(None)
+        res = ast.Name(varname, ast.Load())
         decompiler.names.add(varname)
-        return ast.Name(varname, ast.Load())
+        if push_null and PY313:
+            # NULL and global swapped
+            decompiler.stack.append(res)
+            decompiler.stack.append(None)
+            return None
+        elif push_null and not PY313:
+            decompiler.stack.append(None)
+        return res
 
     def LOAD_METHOD(decompiler, methname):
         return decompiler.LOAD_ATTR(methname, PY311)
@@ -834,7 +916,7 @@ class Decompiler(object):
         decompiler.stack[-3:-2] = []  # ignore freevars
         return decompiler.MAKE_FUNCTION(argc)
 
-    def MAKE_FUNCTION(decompiler, argc):
+    def MAKE_FUNCTION(decompiler, argc=0):
         defaults = []
         if sys.version_info >= (3, 6):
             if not PY311:
@@ -923,6 +1005,12 @@ class Decompiler(object):
         decompiler.stack.append(tos2)
         decompiler.stack.append(tos1)
 
+    def SET_FUNCTION_ATTRIBUTE(decompiler, flag):
+        """This replaces the argument to MAKE_FUNCTION in py 3.13"""
+        # This actually needs special handling in get_instructions because
+        # the func will not be at the top of the stack when we get here.
+        throw(NotImplementedError)
+
     def SETUP_LOOP(decompiler, endpos):
         pass
 
@@ -940,6 +1028,14 @@ class Decompiler(object):
         decompiler.assnames.add(varname)
         decompiler.store(ast.Name(varname, ast.Store()))
 
+    def STORE_FAST_STORE_FAST(decompiler, varname1, varname2):
+        decompiler.STORE_FAST(varname1)
+        decompiler.STORE_FAST(varname2)
+
+    def STORE_FAST_LOAD_FAST(decompiler, varname1, varname2):
+        decompiler.STORE_FAST(varname1)
+        return decompiler.LOAD_FAST(varname2)
+
     def STORE_MAP(decompiler):
         tos = decompiler.stack.pop()
         tos1 = decompiler.stack.pop()
@@ -964,6 +1060,9 @@ class Decompiler(object):
         pass  # this is not great, but stack is not the same as during runtime
         # actual queries are hopefully covered by tests
 
+    def TO_BOOL(decompiler):
+        pass
+
     def UNARY_POSITIVE(decompiler):
         return ast.UnaryOp(op=ast.UAdd(), operand=decompiler.stack.pop())
 
Index: pony-0.7.19/pony/py23compat.py
===================================================================
--- pony-0.7.19.orig/pony/py23compat.py
+++ pony-0.7.19/pony/py23compat.py
@@ -8,6 +8,7 @@ PY39 = sys.version_info[:2] >= (3, 9)
 PY310 = sys.version_info[:2] >= (3, 10)
 PY311 = sys.version_info[:2] >= (3, 11)
 PY312 = sys.version_info[:2] >= (3, 12)
+PY313 = sys.version_info[:2] >= (3, 13)
 
 unicode = str
 buffer = bytes
Index: pony-0.7.19/pony/utils/tests/test_utils.py
===================================================================
--- /dev/null
+++ pony-0.7.19/pony/utils/tests/test_utils.py
@@ -0,0 +1,17 @@
+import ast
+import unittest
+from pony.py23compat import PY36
+from pony.utils import pickle_ast, unpickle_ast
+
+
+class PickleTest(unittest.TestCase):
+    @unittest.skipUnless(PY36, "requires Python 3")
+    def test_persistent_id(self):
+        src = ast.literal_eval("...")
+        res = unpickle_ast(pickle_ast(src))
+        self.assertEqual(res, src)
+
+    def test_simple_ast(self):
+        src = ast.parse("(x for x in [])")
+        res = unpickle_ast(pickle_ast(src))
+        self.assertEqual(ast.dump(res), ast.dump(src))
Index: pony-0.7.19/pony/utils/utils.py
===================================================================
--- pony-0.7.19.orig/pony/utils/utils.py
+++ pony-0.7.19/pony/utils/utils.py
@@ -368,26 +368,30 @@ def between(x, a, b):
 def is_utf8(encoding):
     return encoding.upper().replace('_', '').replace('-', '') in ('UTF8', 
'UTF', 'U8')
 
-def _persistent_id(obj):
-    if obj is Ellipsis:
-        return "Ellipsis"
-
-def _persistent_load(persid):
-    if persid == "Ellipsis":
-        return Ellipsis
-    raise pickle.UnpicklingError("unsupported persistent object")
+
+class PersistentPickler(pickle.Pickler):
+    def persistent_id(self, obj):
+        if obj is Ellipsis:
+            return "Ellipsis"
+        return None
+
+
+class PersistentUnpickler(pickle.Unpickler):
+    def persistent_load(self, persid):
+        if persid == "Ellipsis":
+            return Ellipsis
+        raise pickle.UnpicklingError("unsupported persistent object")
+
 
 def pickle_ast(val):
     pickled = io.BytesIO()
-    pickler = pickle.Pickler(pickled)
-    pickler.persistent_id = _persistent_id
+    pickler = PersistentPickler(pickled)
     pickler.dump(val)
     return pickled
 
 def unpickle_ast(pickled):
     pickled.seek(0)
-    unpickler = pickle.Unpickler(pickled)
-    unpickler.persistent_load = _persistent_load
+    unpickler = PersistentUnpickler(pickled)
     return unpickler.load()
 
 def copy_ast(tree):
Index: pony-0.7.19/setup.py
===================================================================
--- pony-0.7.19.orig/setup.py
+++ pony-0.7.19/setup.py
@@ -70,6 +70,7 @@ classifiers = [
     'Programming Language :: Python :: 3.10',
     'Programming Language :: Python :: 3.11',
     'Programming Language :: Python :: 3.12',
+    'Programming Language :: Python :: 3.13',
     'Programming Language :: Python :: Implementation :: PyPy',
     'Topic :: Software Development :: Libraries',
     'Topic :: Database'
@@ -110,8 +111,8 @@ download_url = "http://pypi.python.org/p
 
 if __name__ == "__main__":
     pv = sys.version_info[:2]
-    if pv < (3, 8) or pv > (3, 12):
-        s = "Sorry, but %s %s requires Python of one of the following 
versions: 3.8-3.12." \
+    if pv < (3, 8) or pv > (3, 13):
+        s = "Sorry, but %s %s requires Python of one of the following 
versions: 3.8-3.13." \
             " You have version %s"
         print(s % (name, version, sys.version.split(' ', 1)[0]))
         sys.exit(1)

++++++ py314.patch ++++++
Index: pony-0.7.19/pony/orm/core.py
===================================================================
--- pony-0.7.19.orig/pony/orm/core.py
+++ pony-0.7.19/pony/orm/core.py
@@ -3871,7 +3871,8 @@ class EntityMeta(type):
         comprehension = ast.comprehension(
             target=ast.Name(iter_name, ast.Store()),
             iter=ast.Name('.0', ast.Load()),
-            ifs=[]
+            ifs=[],
+            is_async=False
         )
         entity._default_genexpr_ = ast.GeneratorExp(ast.Name(iter_name, 
ast.Load()), [comprehension])
 
@@ -4393,7 +4394,11 @@ class EntityMeta(type):
         name = names[0]
 
         for_expr = ast.comprehension(
-            target=ast.Name(name, ast.Store()), iter=ast.Name('.0', 
ast.Load()), ifs=[cond_expr])
+            target=ast.Name(name, ast.Store()),
+            iter=ast.Name('.0', ast.Load()),
+            ifs=[cond_expr],
+            is_async = False
+        )
         inner_expr = ast.GeneratorExp(elt=ast.Name(name, ast.Load()), 
generators=[for_expr])
 
         locals = locals.copy() if locals is not None else {}
Index: pony-0.7.19/pony/orm/decompiling.py
===================================================================
--- pony-0.7.19.orig/pony/orm/decompiling.py
+++ pony-0.7.19/pony/orm/decompiling.py
@@ -1,5 +1,5 @@
 from __future__ import absolute_import, print_function, division
-from pony.py23compat import PY36, PY37, PY38, PY39, PY310, PY311, PY312, 
PY313, PYPY
+from pony.py23compat import PY36, PY37, PY38, PY39, PY310, PY311, PY312, 
PY313, PY314, PYPY
 
 import sys, types, inspect
 from opcode import opname as opnames, HAVE_ARGUMENT, EXTENDED_ARG, cmp_op
@@ -89,6 +89,12 @@ operator_mapping = {
     'not in': ast.NotIn
 }
 
+double_load_store_ops = {
+    'LOAD_FAST_LOAD_FAST',
+    'STORE_FAST_LOAD_FAST',
+    'STORE_FAST_STORE_FAST',
+    'LOAD_FAST_BORROW_LOAD_FAST_BORROW',
+}
 
 def clean_assign(node):
     if isinstance(node, ast.Assign):
@@ -99,6 +105,9 @@ def clean_assign(node):
 def make_const(value):
     if is_const(value):
         return value
+    if PY314:
+        if isinstance(value, slice):
+            return slice_to_ast(value)
     if PY39:
         return ast.Constant(value)
     elif PY38:
@@ -140,6 +149,13 @@ def unwrap_str(key):
     return key.s
 
 
+def slice_to_ast(value):
+    start = ast.Constant(value.start) if value.start is not None else None
+    stop = ast.Constant(value.stop) if value.stop is not None else None
+    step = ast.Constant(value.step) if value.step is not None else None
+    return ast.Slice(start, stop, step)
+
+
 class Decompiler(object):
     def __init__(decompiler, code, start=0, end=None):
         decompiler.code = code
@@ -221,7 +237,7 @@ class Decompiler(object):
                     arg = [i + oparg * (2 if PY310 else 1)
                            * (-1 if 'BACKWARD' in opname else 1)]
                 elif op in haslocal:
-                    if opname in {'LOAD_FAST_LOAD_FAST', 
'STORE_FAST_LOAD_FAST', 'STORE_FAST_STORE_FAST'}:
+                    if opname in double_load_store_ops:
                         # py3.13: 2 4bit args
                         arg = [code._varname_from_oparg(oparg >> 4), 
code._varname_from_oparg(oparg & 0x0f)]
                     elif PY313:
@@ -254,6 +270,10 @@ class Decompiler(object):
                     and arg[0] == decompiler.for_iter_pos):
                 decompiler.abs_jump_to_top = decompiler.pos
 
+            # NOT_TAKEN has a similar problem as CACHE, but does not change 
rel jump addresses, so needs to be here
+            while i < len(code.co_code) and opnames[code.co_code[i]] == 
'NOT_TAKEN':
+                i += 2
+
             if before_yield:
                 merge = False
                 if opname == 'JUMP_BACKWARD':
@@ -379,6 +399,9 @@ class Decompiler(object):
         inplace = opname.startswith('NB_INPLACE_')
         opname = opname.split('_', 2 if inplace else 1)[-1]
 
+        if opname == "SUBSCR":
+            return decompiler.BINARY_SUBSCR()
+
         op = {
             "ADD": ast.Add,
             "AND": ast.BitAnd,
@@ -412,7 +435,7 @@ class Decompiler(object):
                 end = None
             if isinstance(start, ast.Constant) and start.value is None:
                 start = None
-        node2 = ast.Slice(start, end, ctx=ast.Load())
+        node2 = ast.Slice(start, end)
         return ast.Subscript(value=node1, slice=node2, ctx=ast.Load())
 
     def BINARY_SUBSCR(decompiler):
@@ -423,6 +446,13 @@ class Decompiler(object):
                 node2.lower = None
             if isinstance(node2.upper, ast.Constant) and node2.upper.value is 
None:
                 node2.upper = None
+        elif (
+            isinstance(node2, ast.Constant)
+            and isinstance(node2.value, tuple)
+            and any(isinstance(value, slice) for value in node2.value)
+        ):
+            # py3.14 has a different format for constant tuple of slices
+            node2 = ast.Tuple(elts=[slice_to_ast(value) for value in 
node2.value])
         elif not PY38:
             if isinstance(node2, ast.Tuple) and any(isinstance(item, 
ast.Slice) for item in node2.elts):
                 node2 = ast.ExtSlice(node2.elts)
@@ -565,7 +595,7 @@ class Decompiler(object):
         star = decompiler.stack.pop()
         return decompiler.CALL_FUNCTION(argc, star, star2)
 
-    def CALL_FUNCTION_EX(decompiler, argc):
+    def CALL_FUNCTION_EX(decompiler, argc=1):
         star2 = None
         if argc:
             if argc != 1:
@@ -881,12 +911,15 @@ class Decompiler(object):
         decompiler.names.add(varname)
         return ast.Name(varname, ast.Load())
 
+    LOAD_FAST_AND_CLEAR = LOAD_FAST
+    LOAD_FAST_BORROW = LOAD_FAST
+
     def LOAD_FAST_LOAD_FAST(decompiler, varname1, varname2):
         decompiler.names.add(varname1)
         decompiler.stack.append(ast.Name(varname1, ast.Load()))
         return decompiler.LOAD_FAST(varname2)
 
-    LOAD_FAST_AND_CLEAR = LOAD_FAST
+    LOAD_FAST_BORROW_LOAD_FAST_BORROW = LOAD_FAST_LOAD_FAST
 
     def LOAD_GLOBAL(decompiler, varname, push_null):
         res = ast.Name(varname, ast.Load())
@@ -909,6 +942,9 @@ class Decompiler(object):
         decompiler.names.add(varname)
         return ast.Name(varname, ast.Load())
 
+    def LOAD_SMALL_INT(decompiler, value):
+        return make_const(value)
+
     def MAKE_CELL(decompiler, freevar):
         pass
 
Index: pony-0.7.19/pony/orm/sqltranslation.py
===================================================================
--- pony-0.7.19.orig/pony/orm/sqltranslation.py
+++ pony-0.7.19/pony/orm/sqltranslation.py
@@ -10,7 +10,7 @@ from functools import update_wrapper
 from uuid import UUID
 
 from pony import options, utils
-from pony.utils import localbase, is_ident, throw, reraise, copy_ast, between, 
concat, coalesce
+from pony.utils import localbase, is_ident, throw, reraise, copy_ast, between, 
concat, coalesce, IntegerGenerator
 from pony.orm.asttranslation import ASTTranslator, ast2src, TranslationError, 
create_extractors, get_child_nodes
 from pony.orm.decompiling import decompile, DecompileError, operator_mapping
 from pony.orm.ormtypes import \
@@ -1241,7 +1241,7 @@ class SqlQuery(object):
         sqlquery.tablerefs = {}
         if parent_sqlquery is None:
             sqlquery.alias_counters = {}
-            sqlquery.expr_counter = itertools.count(1)
+            sqlquery.expr_counter = IntegerGenerator(1)
         else:
             sqlquery.alias_counters = parent_sqlquery.alias_counters.copy()
             sqlquery.expr_counter = parent_sqlquery.expr_counter
Index: pony-0.7.19/pony/orm/tests/test_declarative_exceptions.py
===================================================================
--- pony-0.7.19.orig/pony/orm/tests/test_declarative_exceptions.py
+++ pony-0.7.19/pony/orm/tests/test_declarative_exceptions.py
@@ -1,5 +1,5 @@
 from __future__ import absolute_import, print_function, division
-from pony.py23compat import PYPY
+from pony.py23compat import PY314, PYPY
 
 import sys, unittest
 from datetime import date
@@ -77,7 +77,8 @@ class TestSQLTranslatorExceptions(unitte
         def test5(self):
             select(s for s in Student if s.name.upper(**{'a':'b', 'c':'d'}))
 
-    @raises_exception(ExprEvalError, "`1 in 2` raises TypeError: argument of 
type 'int' is not iterable" if not PYPY else
+    @raises_exception(ExprEvalError, "`1 in 2` raises TypeError: argument of 
type 'int' is not a container or iterable" if PY314 else
+                                     "`1 in 2` raises TypeError: argument of 
type 'int' is not iterable" if not PYPY else
                                      "`1 in 2` raises TypeError: 'int' object 
is not iterable")
     def test6(self):
         select(s for s in Student if 1 in 2)
Index: pony-0.7.19/pony/py23compat.py
===================================================================
--- pony-0.7.19.orig/pony/py23compat.py
+++ pony-0.7.19/pony/py23compat.py
@@ -9,6 +9,7 @@ PY310 = sys.version_info[:2] >= (3, 10)
 PY311 = sys.version_info[:2] >= (3, 11)
 PY312 = sys.version_info[:2] >= (3, 12)
 PY313 = sys.version_info[:2] >= (3, 13)
+PY314 = sys.version_info[:2] >= (3, 14)
 
 unicode = str
 buffer = bytes
Index: pony-0.7.19/pony/utils/tests/test_utils.py
===================================================================
--- pony-0.7.19.orig/pony/utils/tests/test_utils.py
+++ pony-0.7.19/pony/utils/tests/test_utils.py
@@ -1,7 +1,9 @@
 import ast
 import unittest
+from copy import deepcopy
+
 from pony.py23compat import PY36
-from pony.utils import pickle_ast, unpickle_ast
+from pony.utils import pickle_ast, unpickle_asti, IntegerGenerator
 
 
 class PickleTest(unittest.TestCase):
@@ -15,3 +17,21 @@ class PickleTest(unittest.TestCase):
         src = ast.parse("(x for x in [])")
         res = unpickle_ast(pickle_ast(src))
         self.assertEqual(ast.dump(res), ast.dump(src))
+
+
+class IntegerGeneratorTest(unittest.TestCase):
+    def test_from_zero(self):
+        c = IntegerGenerator()
+        self.assertEqual(next(c), 0)
+        self.assertEqual(next(c), 1)
+
+    def test_from_start(self):
+        c = IntegerGenerator(42)
+        self.assertEqual(next(c), 42)
+        self.assertEqual(next(c), 43)
+
+    def test_copy(self):
+        c = IntegerGenerator(42)
+        self.assertEqual(next(c), 42)
+        d = deepcopy(c)
+        self.assertEqual(next(c), next(d))
Index: pony-0.7.19/pony/utils/utils.py
===================================================================
--- pony-0.7.19.orig/pony/utils/utils.py
+++ pony-0.7.19/pony/utils/utils.py
@@ -445,3 +445,17 @@ def deduplicate(value, deduplication_cac
         return deduplication_cache[t].setdefault(value, value)
     except:
         return value
+
+
+class IntegerGenerator:
+    """pickleable version of itertools.count() with fixed step=1"""
+    def __init__(self, firstval=0):
+        self.val = firstval
+
+    def __iter__(self):
+        return self
+
+    def __next__(self):
+        res = self.val
+        self.val += 1
+        return res
Index: pony-0.7.19/setup.py
===================================================================
--- pony-0.7.19.orig/setup.py
+++ pony-0.7.19/setup.py
@@ -71,6 +71,7 @@ classifiers = [
     'Programming Language :: Python :: 3.11',
     'Programming Language :: Python :: 3.12',
     'Programming Language :: Python :: 3.13',
+    'Programming Language :: Python :: 3.14',
     'Programming Language :: Python :: Implementation :: PyPy',
     'Topic :: Software Development :: Libraries',
     'Topic :: Database'
@@ -111,8 +112,8 @@ download_url = "http://pypi.python.org/p
 
 if __name__ == "__main__":
     pv = sys.version_info[:2]
-    if pv < (3, 8) or pv > (3, 13):
-        s = "Sorry, but %s %s requires Python of one of the following 
versions: 3.8-3.13." \
+    if pv < (3, 8) or pv > (3, 14):
+        s = "Sorry, but %s %s requires Python of one of the following 
versions: 3.8-3.14." \
             " You have version %s"
         print(s % (name, version, sys.version.split(' ', 1)[0]))
         sys.exit(1)

Reply via email to