Skip to content

Commit

Permalink
Merge pull request #3951 from camptocamp/association_proxy_nullable
Browse files Browse the repository at this point in the history
Correctly return nillable for relations in md.xsd
  • Loading branch information
arnaud-morvan committed Aug 14, 2018
2 parents 0116e53 + 9e831b2 commit 852388e
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 9 deletions.
17 changes: 12 additions & 5 deletions c2cgeoportal/lib/dbreflection.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,17 +70,18 @@ class an engine, required for the reflection.
class _AssociationProxy(object):
# A specific "association proxy" implementation

def __init__(self, target, value_attr):
def __init__(self, target, value_attr, nullable=True):
self.target = target
self.value_attr = value_attr
self.nullable = nullable

def __get__(self, obj, type_=None):
if obj is None:
# For "hybrid" descriptors that work both at the instance
# and class levels we could return an SQL expression here.
# The code of hybrid_property in SQLAlchemy illustrates
# how to do that.
raise AttributeError # pragma: no cover
return self
target = getattr(obj, self.target)
return getattr(target, self.value_attr) if target else None

Expand Down Expand Up @@ -109,8 +110,9 @@ def xsd_sequence_callback(tb, cls):
target_cls = relationship_property.argument
query = DBSession.query(getattr(target_cls, p.value_attr))
attrs = {}
attrs["minOccurs"] = str(0)
attrs["nillable"] = "true"
if p.nullable:
attrs["minOccurs"] = str(0)
attrs["nillable"] = "true"
attrs["name"] = k
with tag(tb, "xsd:element", attrs) as tb:
with tag(tb, "xsd:simpleType") as tb:
Expand Down Expand Up @@ -247,7 +249,12 @@ def _add_association_proxy(cls, col):
lazy="immediate")
setattr(cls, rel, relationship_)

setattr(cls, proxy, _AssociationProxy(rel, "name"))
nullable = True
cls_column_property = getattr(cls, col.name).property
for column in cls_column_property.columns:
nullable = nullable and column.nullable

setattr(cls, proxy, _AssociationProxy(rel, "name", nullable=nullable))

if cls.__add_properties__ is None:
cls.__add_properties__ = [proxy]
Expand Down
14 changes: 10 additions & 4 deletions c2cgeoportal/tests/functional/test_dbreflection.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,8 @@ def _create_table(self, tablename):
),
Column(
"child2_id", types.Integer,
ForeignKey("public.{0!s}_child.id".format(tablename))
ForeignKey("public.{0!s}_child.id".format(tablename)),
nullable=False
),
Column("point", Geometry("POINT")),
Column("linestring", Geometry("LINESTRING")),
Expand All @@ -122,7 +123,7 @@ def test_get_class_nonexisting_table(self):
def test_get_class(self):
from geoalchemy2 import Geometry
import c2cgeoportal.lib.dbreflection
from c2cgeoportal.lib.dbreflection import get_class
from c2cgeoportal.lib.dbreflection import get_class, _AssociationProxy

self._create_table("table_a")
modelclass = get_class("table_a")
Expand All @@ -139,6 +140,11 @@ def test_get_class(self):
self.assertTrue(isinstance(modelclass.multilinestring.type, Geometry))
self.assertTrue(isinstance(modelclass.multipolygon.type, Geometry))

self.assertTrue(isinstance(modelclass.child1, _AssociationProxy))
self.assertTrue(modelclass.child1.nullable)
self.assertTrue(isinstance(modelclass.child2, _AssociationProxy))
self.assertFalse(modelclass.child2.nullable)

# test the Table object
table = modelclass.__table__
self.assertTrue("id" in table.c)
Expand Down Expand Up @@ -257,7 +263,7 @@ class Parent(Base):
child1_ = relationship(Child, primaryjoin=(child1_id == Child.id))
child1 = _AssociationProxy("child1_", "name")
child2_ = relationship(Child, primaryjoin=(child2_id == Child.id))
child2 = _AssociationProxy("child2_", "name")
child2 = _AssociationProxy("child2_", "name", nullable=False)

Child.__table__.create()
Parent.__table__.create()
Expand Down Expand Up @@ -295,7 +301,7 @@ def test_xsd_sequence_callback(self):
'</xsd:restriction>'
'</xsd:simpleType>'
'</xsd:element>'
'<xsd:element minOccurs="0" name="child2" nillable="true">'
'<xsd:element name="child2">'
'<xsd:simpleType>'
'<xsd:restriction base="xsd:string">'
'<xsd:enumeration value="foo" />'
Expand Down

0 comments on commit 852388e

Please sign in to comment.