From 8c0914de52ab370861bf651c6bd51b1cd1bcf2cc Mon Sep 17 00:00:00 2001 From: Eric Atkin Date: Wed, 1 May 2024 16:12:51 -0600 Subject: [PATCH 1/2] Fix tests for python 3.12 and sqlalchemy >=2 --- spyne/client/twisted/__init__.py | 3 +- spyne/protocol/http.py | 2 +- spyne/protocol/json.py | 2 +- spyne/store/relational/_base.py | 12 ++- spyne/test/interop/test_pyramid.py | 2 +- spyne/test/multipython/model/test_complex.py | 6 +- spyne/test/protocol/_test_dictdoc.py | 4 +- spyne/test/test_sqlalchemy.py | 102 ++++++++++--------- spyne/util/invregexp.py | 2 +- 9 files changed, 73 insertions(+), 62 deletions(-) diff --git a/spyne/client/twisted/__init__.py b/spyne/client/twisted/__init__.py index 6609e82c8..aaf65e9c4 100644 --- a/spyne/client/twisted/__init__.py +++ b/spyne/client/twisted/__init__.py @@ -26,8 +26,6 @@ from spyne.client import RemoteProcedureBase from spyne.client import ClientBase -from zope.interface import implements - from twisted.internet import reactor from twisted.internet.defer import Deferred from twisted.internet.protocol import Protocol @@ -42,6 +40,7 @@ class _Producer(object): if six.PY2: + from zope.interface import implements implements(IBodyProducer) _deferred = None diff --git a/spyne/protocol/http.py b/spyne/protocol/http.py index b351d8169..1db705e38 100644 --- a/spyne/protocol/http.py +++ b/spyne/protocol/http.py @@ -435,7 +435,7 @@ def _compile_host_pattern(cls, pattern): pattern = _full_pattern_re.sub(r'(?P<\1>.*)', pattern) pattern_b = pattern.encode(cls.HOST_ENCODING) - pattern_b = _fragment_pattern_b_re.sub(b'(?P<\\1>[^\.]*)', pattern_b) + pattern_b = _fragment_pattern_b_re.sub(rb'(?P<\\1>[^\.]*)', pattern_b) pattern_b = _full_pattern_b_re.sub(b'(?P<\\1>.*)', pattern_b) return re.compile(pattern), re.compile(pattern_b) diff --git a/spyne/protocol/json.py b/spyne/protocol/json.py index 16acb11f3..fa569a32c 100644 --- a/spyne/protocol/json.py +++ b/spyne/protocol/json.py @@ -17,7 +17,7 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 # -"""The ``spyne.protocol.json`` package contains the Json-related protocols. +r"""The ``spyne.protocol.json`` package contains the Json-related protocols. Currently, only :class:`spyne.protocol.json.JsonDocument` is supported. Initially released in 2.8.0-rc. diff --git a/spyne/store/relational/_base.py b/spyne/store/relational/_base.py index 66fca3219..715162622 100644 --- a/spyne/store/relational/_base.py +++ b/spyne/store/relational/_base.py @@ -44,7 +44,6 @@ from sqlalchemy.dialects.postgresql.base import PGUuid, PGInet from sqlalchemy.orm import relationship -from sqlalchemy.orm import mapper from sqlalchemy.ext.associationproxy import association_proxy # TODO: find the latest way of checking whether a class is already mapped @@ -87,6 +86,11 @@ from spyne.util import sanitize_args +if int(sqlalchemy.__version__.split('.')[0]) < 2: + from sqlalchemy.orm import mapper +else: + from sqlalchemy.orm import registry + mapper = registry().map_imperatively # Inheritance type constants. class _SINGLE: @@ -582,10 +586,11 @@ def _gen_array_m2m(cls, props, subname, arrser, storage): rel_kwargs = dict( lazy=storage.lazy, backref=storage.backref, - cascade=storage.cascade, order_by=storage.order_by, back_populates=storage.back_populates, ) + if storage.cascade: # sqla >=2 doesn't accept False + rel_kwargs['cascade'] = cascade if storage.explicit_join: # Specify primaryjoin and secondaryjoin when requested. @@ -753,11 +758,12 @@ def _gen_array_o2m(cls, props, subname, arrser, arrser_cust, storage): rel_kwargs = dict( lazy=storage.lazy, backref=storage.backref, - cascade=storage.cascade, order_by=storage.order_by, foreign_keys=[col], back_populates=storage.back_populates, ) + if storage.cascade: # sqla >=2 doesn't accept False + rel_kwargs['cascade'] = cascade if storage.single_parent is not None: rel_kwargs['single_parent'] = storage.single_parent diff --git a/spyne/test/interop/test_pyramid.py b/spyne/test/interop/test_pyramid.py index 2dd3b044c..f0fd12be4 100755 --- a/spyne/test/interop/test_pyramid.py +++ b/spyne/test/interop/test_pyramid.py @@ -71,6 +71,6 @@ def testGetWsdl(self): request = Request(env) resp = request.get_response(wsgi_app) - self.assert_(resp.status.startswith("200 ")) + self.assertTrue(resp.status.startswith("200 ")) node = etree.XML(resp.body) # will throw exception if non well formed diff --git a/spyne/test/multipython/model/test_complex.py b/spyne/test/multipython/model/test_complex.py index 9aa8d1cb2..0cd5b001f 100644 --- a/spyne/test/multipython/model/test_complex.py +++ b/spyne/test/multipython/model/test_complex.py @@ -140,7 +140,7 @@ class Attributes(ComplexModel.Attributes): Base2 = Base.customize(prop1=4) - self.assertNotEquals(Base.Attributes.prop1, Base2.Attributes.prop1) + self.assertNotEqual(Base.Attributes.prop1, Base2.Attributes.prop1) self.assertEqual(Base.Attributes.prop2, Base2.Attributes.prop2) class Derived(Base): @@ -156,7 +156,7 @@ class Attributes(Base.Attributes): self.assertEqual(Derived.Attributes.prop1, 3) self.assertEqual(Derived2.Attributes.prop1, 5) - self.assertNotEquals(Derived.Attributes.prop3, Derived2.Attributes.prop3) + self.assertNotEqual(Derived.Attributes.prop3, Derived2.Attributes.prop3) self.assertEqual(Derived.Attributes.prop4, Derived2.Attributes.prop4) Derived3 = Derived.customize(prop3=12) @@ -164,7 +164,7 @@ class Attributes(Base.Attributes): # changes made to bases propagate, unless overridden self.assertEqual(Derived.Attributes.prop1, Base.Attributes.prop1) - self.assertNotEquals(Derived2.Attributes.prop1, Base.Attributes.prop1) + self.assertNotEqual(Derived2.Attributes.prop1, Base.Attributes.prop1) self.assertEqual(Derived3.Attributes.prop1, Base.Attributes.prop1) def test_declare_order(self): diff --git a/spyne/test/protocol/_test_dictdoc.py b/spyne/test/protocol/_test_dictdoc.py index 7e4af3dfa..ba5e6b5cc 100644 --- a/spyne/test/protocol/_test_dictdoc.py +++ b/spyne/test/protocol/_test_dictdoc.py @@ -1234,7 +1234,7 @@ def some_call(p): print(ctx.out_document) d = convert_dict({"some_callResponse": {"some_callResult": inner}}) - self.assertEquals(ctx.out_document[0], d) + self.assertEqual(ctx.out_document[0], d) def test_validation_freq_parent(self): class C(ComplexModel): @@ -1308,7 +1308,7 @@ def some_call(sc): doc = [{"C": {"s1": "s1","s2": "s2"}}] ctx = _dry_me([SomeService], {"some_call": doc}) - self.assertEquals(ctx.out_document[0], convert_dict( + self.assertEqual(ctx.out_document[0], convert_dict( {'some_callResponse': {'some_callResult': {'C': {'s2': 's2'}}}}) ) diff --git a/spyne/test/test_sqlalchemy.py b/spyne/test/test_sqlalchemy.py index 9d7af0df3..6a137a9eb 100755 --- a/spyne/test/test_sqlalchemy.py +++ b/spyne/test/test_sqlalchemy.py @@ -30,9 +30,9 @@ from sqlalchemy import MetaData from sqlalchemy import Column from sqlalchemy import Table +from sqlalchemy import text from sqlalchemy.exc import IntegrityError -from sqlalchemy.orm import mapper from sqlalchemy.orm import sessionmaker from spyne import M, Any, Double @@ -142,7 +142,6 @@ def setUp(self): self.engine = create_engine('sqlite:///:memory:') self.session = sessionmaker(bind=self.engine)() self.metadata = TableModel.Attributes.sqla_metadata = MetaData() - self.metadata.bind = self.engine logging.info('Testing against sqlalchemy-%s', sqlalchemy.__version__) def test_obj_json_dirty(self): @@ -159,7 +158,7 @@ class SomeClass1(TableModel): ('a', SomeClass.store_as('jsonb')), ] - self.metadata.create_all() + self.metadata.create_all(self.engine) sc1 = SomeClass1(i=5, a=SomeClass(s="s", d=42.0)) self.session.add(sc1) @@ -191,7 +190,7 @@ class SomeClass(TableModel): i = Integer32(64, index=True) t = SomeClass.__table__ - self.metadata.create_all() # not needed, just nice to see. + self.metadata.create_all(self.engine) # not needed, just nice to see. assert t.c.id.primary_key == True assert t.c.id.autoincrement == False @@ -211,7 +210,7 @@ class SomeClass(TableModel): s = Unicode(64, sqla_column_args=dict(name='ss')) t = SomeClass.__table__ - self.metadata.create_all() # not needed, just nice to see. + self.metadata.create_all(self.engine) # not needed, just nice to see. assert 'ss' in t.c @@ -234,7 +233,7 @@ class SomeClass(TableModel): sqla_column_args=dict(name='oo')) t = SomeClass.__table__ - self.metadata.create_all() # not needed, just nice to see. + self.metadata.create_all(self.engine) # not needed, just nice to see. assert 'oo_id' in t.c @@ -257,7 +256,7 @@ class SomeClass(TableModel): sqla_column_args=dict(name='oo')) t = SomeClass.__table__ - self.metadata.create_all() # not needed, just nice to see. + self.metadata.create_all(self.engine) # not needed, just nice to see. assert 'oo' in t.c @@ -278,7 +277,7 @@ class SomeClass(TableModel): id = Integer32(primary_key=True) o = SomeOtherClass.customize(store_as='table') - self.metadata.create_all() + self.metadata.create_all(self.engine) soc = SomeOtherClass(s='ehe') sc = SomeClass(o=soc) @@ -315,7 +314,7 @@ class SomeClass(TableModel): id = Integer32(primary_key=True) others = Array(SomeOtherClass, store_as='table') - self.metadata.create_all() + self.metadata.create_all(self.engine) soc1 = SomeOtherClass(s='ehe1') soc2 = SomeOtherClass(s='ehe2') @@ -347,7 +346,7 @@ class SomeClass(TableModel): id = Integer32(primary_key=True) others = Array(SomeOtherClass, store_as=table(multi=True)) - self.metadata.create_all() + self.metadata.create_all(self.engine) soc1 = SomeOtherClass(s='ehe1') soc2 = SomeOtherClass(s='ehe2') @@ -380,7 +379,7 @@ class SomeClass(TableModel): others = Array(SomeOtherClass, store_as=table(multi=True, backref='some_classes')) - self.metadata.create_all() + self.metadata.create_all(self.engine) soc1 = SomeOtherClass(s='ehe1') soc2 = SomeOtherClass(s='ehe2') @@ -409,7 +408,7 @@ class SomeClass(TableModel): id = Integer32(primary_key=True) others = Array(SomeOtherClass, store_as='xml') - self.metadata.create_all() + self.metadata.create_all(self.engine) soc1 = SomeOtherClass(s='ehe1') soc2 = SomeOtherClass(s='ehe2') @@ -438,7 +437,7 @@ class SomeClass(TableModel): id = Integer32(primary_key=True) others = Array(SomeOtherClass, store_as=xml(no_ns=True)) - self.metadata.create_all() + self.metadata.create_all(self.engine) soc1 = SomeOtherClass(s='ehe1') soc2 = SomeOtherClass(s='ehe2') @@ -449,7 +448,8 @@ class SomeClass(TableModel): self.session.close() sc_xml = self.session.connection() \ - .execute("select others from some_class") .fetchall()[0][0] + .execute(text("select others from some_class")) \ + .fetchall()[0][0] from lxml import etree assert etree.fromstring(sc_xml).tag == 'SomeOtherClassArray' @@ -467,7 +467,7 @@ class SomeOtherClass(TableModel): class SomeClass(SomeOtherClass): numbers = Array(Integer32).store_as(xml(no_ns=True, root_tag='a')) - self.metadata.create_all() + self.metadata.create_all(self.engine) sc = SomeClass(id=5, s='s', numbers=[1, 2, 3, 4]) @@ -614,26 +614,34 @@ def __repr__(self): Column('type', sqlalchemy.String(20), nullable=False), ) - employee_mapper = mapper(Employee, employees_table, - polymorphic_on=employees_table.c.type, - polymorphic_identity='employee') + if int(sqlalchemy.__version__.split('.')[0]) < 2: + from sqlalchemy.orm import mapper + else: + from sqlalchemy.orm import registry + mapper = registry().map_imperatively + + employee_mapper = mapper(Employee, + employees_table, + polymorphic_on=employees_table.c.type, + polymorphic_identity='employee') - manager_mapper = mapper(Manager, inherits=employee_mapper, - polymorphic_identity='manager') + manager_mapper = mapper(Manager, + inherits=employee_mapper, + polymorphic_identity='manager') - engineer_mapper = mapper(Engineer, inherits=employee_mapper, - polymorphic_identity='engineer') + engineer_mapper = mapper(Engineer, + inherits=employee_mapper, + polymorphic_identity='engineer') - self.metadata.create_all() + self.metadata.create_all(self.engine) manager = Manager('name', 'data') self.session.add(manager) self.session.commit() self.session.close() - assert self.session.query(Employee).with_polymorphic('*') \ - .filter_by(employee_id=1) \ - .one().type == 'manager' + assert self.session.query(Employee).filter_by(employee_id=1) \ + .one().type == 'manager' def test_inheritance_polymorphic_with_non_nullables_in_subclasses(self): class SomeOtherClass(TableModel): @@ -653,7 +661,7 @@ class SomeClass(SomeOtherClass): i = Integer(nillable=False) - self.metadata.create_all() + self.metadata.create_all(self.engine) assert SomeOtherClass.__table__.c.s.nullable == False @@ -683,8 +691,8 @@ class SomeClass(SomeOtherClass): self.session.expunge_all() - assert self.session.query(SomeOtherClass).with_polymorphic('*') \ - .filter_by(id=soc_id).one().t == 1 + assert self.session.query(SomeOtherClass).filter_by(id=soc_id) \ + .one().t == 1 self.session.close() @@ -702,7 +710,7 @@ class SomeClass(SomeOtherClass): __mapper_args__ = {'polymorphic_identity': 2} numbers = Array(Integer32).store_as(xml(no_ns=True, root_tag='a')) - self.metadata.create_all() + self.metadata.create_all(self.engine) sc = SomeClass(id=5, s='s', numbers=[1, 2, 3, 4]) @@ -710,8 +718,7 @@ class SomeClass(SomeOtherClass): self.session.commit() self.session.close() - assert self.session.query(SomeOtherClass).with_polymorphic('*') \ - .filter_by(id=5).one().t == 2 + assert self.session.query(SomeOtherClass).filter_by(id=5).one().t == 2 self.session.close() def test_nested_sql_array_as_json(self): @@ -726,7 +733,7 @@ class SomeClass(TableModel): id = Integer32(primary_key=True) others = Array(SomeOtherClass, store_as='json') - self.metadata.create_all() + self.metadata.create_all(self.engine) soc1 = SomeOtherClass(s='ehe1') soc2 = SomeOtherClass(s='ehe2') @@ -751,7 +758,7 @@ class SomeClass(TableModel): i = XmlAttribute(Integer32(pk=True)) s = XmlData(Unicode(64)) - self.metadata.create_all() + self.metadata.create_all(self.engine) self.session.add(SomeClass(s='s')) self.session.commit() self.session.expunge_all() @@ -773,7 +780,7 @@ class SomeClass(TableModel): others = Array(SomeOtherClass, store_as='json') f = Unicode(32, default='uuu') - self.metadata.create_all() + self.metadata.create_all(self.engine) self.session.add(SomeClass()) self.session.commit() self.session.expunge_all() @@ -788,7 +795,7 @@ class SomeClass(TableModel): id = Integer32(primary_key=True) f = Unicode(32, db_default=u'uuu') - self.metadata.create_all() + self.metadata.create_all(self.engine) val = SomeClass() assert val.f is None @@ -814,7 +821,7 @@ class SomeClass(TableModel): id = Integer32(primary_key=True) o = SomeOtherClass.customize(store_as='table') - self.metadata.create_all() + self.metadata.create_all(self.engine) self.session.add(SomeClass()) self.session.commit() @@ -833,7 +840,7 @@ class SomeClass(TableModel): id = Integer32(primary_key=True) o = SomeOtherClass.customize(store_as='table', index='btree') - self.metadata.create_all() + self.metadata.create_all(self.engine) idx, = SomeClass.__table__.indexes assert 'o_id' in idx.columns @@ -844,7 +851,7 @@ class SomeClass(TableModel): id = Integer32(primary_key=True) values = Array(Unicode).store_as('table') - self.metadata.create_all() + self.metadata.create_all(self.engine) self.session.add(SomeClass(id=1, values=['a', 'b', 'c'])) self.session.commit() @@ -881,7 +888,7 @@ class SomeClass(TableModel): children = Array(SomeChildClass).store_as('table') mirror = SomeChildClass.store_as('table') - self.metadata.create_all() + self.metadata.create_all(self.engine) children = [ SomeChildClass(s='p', i=600), @@ -973,14 +980,13 @@ class SomeClass(TableModel): id = Integer32(primary_key=True) s = Unicode(32) - TableModel.Attributes.sqla_metadata.create_all() + TableModel.Attributes.sqla_metadata.create_all(self.engine) # create a new table model with empty metadata TM2 = TTableModel() - TM2.Attributes.sqla_metadata.bind = self.engine # fill it with information from the db - TM2.Attributes.sqla_metadata.reflect() + TM2.Attributes.sqla_metadata.reflect(self.engine) # convert sqla info to spyne info class Reflected(TM2): @@ -1037,7 +1043,7 @@ class C(TableModel): id = Integer32(pk=True) f = File(store_as=HybridFileStore('test_file_storage', 'json')) - self.metadata.create_all() + self.metadata.create_all(self.engine) c = C(f=File.Value(name=u"name", type=u"type", data=[b"data"])) self.session.add(c) self.session.flush() @@ -1100,7 +1106,7 @@ class D(TableModel): c = Array(C).customize(store_as=table(right='dd_id')) C.append_field('d', D.customize(store_as=table(left='dd_id'))) - self.metadata.create_all() + self.metadata.create_all(self.engine) c1, c2 = C(id=1), C(id=2) d = D(id=1, c=[c1, c2]) @@ -1179,7 +1185,7 @@ class C(TableModel): C() - self.metadata.create_all() + self.metadata.create_all(self.engine) assert "s" in C2._type_info assert "s" in C2.Attributes.sqla_mapper.columns @@ -1233,7 +1239,7 @@ class C(B): B.append_field('i', Integer32) - self.metadata.create_all() + self.metadata.create_all(self.engine) self.session.add(C(s="foo", i=42)) self.session.commit() @@ -1268,7 +1274,7 @@ class D(TableModel): B.append_field('d', D.store_as('table')) - self.metadata.create_all() + self.metadata.create_all(self.engine) self.session.add(C(d=D(i=42))) self.session.commit() diff --git a/spyne/util/invregexp.py b/spyne/util/invregexp.py index 1e7f1e52b..8d35a2662 100644 --- a/spyne/util/invregexp.py +++ b/spyne/util/invregexp.py @@ -256,7 +256,7 @@ def count(gen): def invregexp(regex): - """Call this routine as a generator to return all the strings that + r"""Call this routine as a generator to return all the strings that match the input regular expression. for s in invregexp("[A-Z]{3}\d{3}"): print s From 734fdb1018c2b41cfebad8fbea1ce4b029b1d5a4 Mon Sep 17 00:00:00 2001 From: Eric Atkin Date: Wed, 1 May 2024 17:31:50 -0600 Subject: [PATCH 2/2] Use classImplements() instead of deprecated implements() --- spyne/client/twisted/__init__.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/spyne/client/twisted/__init__.py b/spyne/client/twisted/__init__.py index aaf65e9c4..70a79594e 100644 --- a/spyne/client/twisted/__init__.py +++ b/spyne/client/twisted/__init__.py @@ -26,6 +26,8 @@ from spyne.client import RemoteProcedureBase from spyne.client import ClientBase +from zope.interface import classImplements + from twisted.internet import reactor from twisted.internet.defer import Deferred from twisted.internet.protocol import Protocol @@ -39,10 +41,6 @@ class _Producer(object): - if six.PY2: - from zope.interface import implements - implements(IBodyProducer) - _deferred = None def __init__(self, body): @@ -84,6 +82,10 @@ def stopProducing(self): self.__paused = True +if six.PY2: + classImplements(_Producer, IBodyProducer) + + class _Protocol(Protocol): def __init__(self, ctx): self.ctx = ctx