Skip to content

Commit 0bc971e

Browse files
committed
Remove circular dependency between conditions and relationships
I've changed the return type of the constraints property so that relationships no longer depend on conditions, breaking the circular dependency.
1 parent 48a500f commit 0bc971e

2 files changed

Lines changed: 30 additions & 13 deletions

File tree

spanner_orm/condition.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,10 +178,19 @@ def bind(self, model):
178178

179179
@property
180180
def conditions(self):
181+
"""Generate the child conditions based on the relationship constraints."""
181182
if not self.relation:
182183
raise error.SpannerError(
183184
'Condition must be bound before conditions is called')
184-
return self.relation.conditions + self._conditions
185+
relation_conditions = []
186+
for constraint in self.relation.constraints:
187+
# This is backward from what you might imagine because the condition will
188+
# be processed from the context of the destination model
189+
relation_conditions.append(
190+
ColumnsEqualCondition(constraint.destination_column,
191+
constraint.origin_class,
192+
constraint.origin_column))
193+
return relation_conditions + self._conditions
185194

186195
@property
187196
def destination(self):

spanner_orm/relationship.py

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,21 @@
1616

1717
from __future__ import annotations
1818

19-
from typing import Dict, List, Type, Union
19+
from typing import Any, Dict, List, Type, Union
2020

21-
from spanner_orm import condition
21+
import dataclasses
2222
from spanner_orm import error
2323
from spanner_orm import model
2424

2525

26+
@dataclasses.dataclass
27+
class RelationshipConstraint:
28+
destination_class: Type[Any]
29+
destination_column: str
30+
origin_class: Type[Any]
31+
origin_column: str
32+
33+
2634
class Relationship(object):
2735
"""Helps define a foreign key relationship between two models."""
2836

@@ -52,8 +60,8 @@ def __init__(self,
5260
self.origin = None
5361

5462
@property
55-
def conditions(self) -> List[condition.Condition]:
56-
assert self.origin, 'Origin must be set before conditions is called'
63+
def constraints(self) -> List[RelationshipConstraint]:
64+
assert self.origin, 'Origin must be set before constraints is called'
5765
return self._parse_constraints()
5866

5967
@property
@@ -66,9 +74,9 @@ def destination(self) -> Type[model.Model]:
6674
def single(self) -> bool:
6775
return self._single
6876

69-
def _parse_constraints(self) -> List[condition.Condition]:
77+
def _parse_constraints(self) -> List[RelationshipConstraint]:
7078
"""Validates the dictionary of constraints and turns it into Conditions."""
71-
conditions = []
79+
constraints = []
7280
for origin_column, destination_column in self._constraints.items():
7381
if origin_column not in self.origin.schema:
7482
raise error.SpannerError(
@@ -77,10 +85,10 @@ def _parse_constraints(self) -> List[condition.Condition]:
7785
if destination_column not in self.destination.schema:
7886
raise error.SpannerError(
7987
'Destination column must be present in destination model')
80-
# This is backward from what you might imagine because the condition will
81-
# be processed from the context of the destination model
82-
conditions.append(
83-
condition.ColumnsEqualCondition(destination_column, self.origin,
84-
origin_column))
8588

86-
return conditions
89+
# TODO(dbrandao): remove when pytype #234 is fixed
90+
constraints.append(
91+
RelationshipConstraint(self.destination, destination_column,
92+
self.origin, origin_column)) # type: ignore
93+
94+
return constraints

0 commit comments

Comments
 (0)