Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove model attribute from Schema and Property #1103

Merged
merged 1 commit into from
Jun 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions followthemoney/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,9 @@ def generate(self) -> None:
called once all schemata are loaded to finalise dereferencing the
schemata."""
for schema in self:
schema.generate()
schema.generate(self)
for prop in self.properties:
self.qnames[prop.qname] = prop
# FIXME: stubs are not correctly assigned
for schema in prop.schema.descendants:
if prop.name not in schema.properties:
schema.properties[prop.name] = prop
Expand Down
11 changes: 5 additions & 6 deletions followthemoney/property.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

if TYPE_CHECKING:
from followthemoney.schema import Schema
from followthemoney.model import Model


class ReverseSpec(TypedDict, total=False):
Expand Down Expand Up @@ -66,8 +67,6 @@ class Property:
RESERVED = ["id", "caption", "schema", "schemata"]

def __init__(self, schema: "Schema", name: str, data: PropertySpec) -> None:
self.model = schema.model

#: The schema which the property is defined for. This is always the
#: most abstract schema that has this property, not the possible
#: child schemata that inherit it.
Expand Down Expand Up @@ -124,19 +123,19 @@ def __init__(self, schema: "Schema", name: str, data: PropertySpec) -> None:
#: RDF term for this property (i.e. the predicate URI).
self.uri = URIRef(cast(str, data.get("rdf", NS[self.qname])))

def generate(self) -> None:
def generate(self, model: "Model") -> None:
"""Setup method used when loading the model in order to build out the reverse
links of the property."""
self.model.properties.add(self)
model.properties.add(self)

if self.type == registry.entity:
if self.range is None and self._range is not None:
self.range = self.model.get(self._range)
self.range = model.get(self._range)

if self.reverse is None and self.range and self._reverse:
if not is_mapping(self._reverse):
raise InvalidModel("Invalid reverse: %s" % self)
self.reverse = self.range._add_reverse(self._reverse, self)
self.reverse = self.range._add_reverse(model, self._reverse, self)

@property
def label(self) -> str:
Expand Down
18 changes: 11 additions & 7 deletions followthemoney/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -200,14 +200,14 @@ def __init__(self, model: "Model", name: str, data: SchemaSpec) -> None:
for name, prop in data.get("properties", {}).items():
self.properties[name] = Property(self, name, prop)

def generate(self) -> None:
def generate(self, model: "Model") -> None:
"""While loading the schema, this function will validate and
load the hierarchy, properties, and flags of the definition."""
for extends in self._extends:
parent = self.model.get(extends)
parent = model.get(extends)
if parent is None:
raise InvalidData("Invalid extends: %r" % extends)
parent.generate()
parent.generate(model)

for name, prop in parent.properties.items():
if name not in self.properties:
Expand All @@ -223,7 +223,7 @@ def generate(self) -> None:
self.temporal_end |= parent.temporal_end

for prop in list(self.properties.values()):
prop.generate()
prop.generate(model)

for featured in self.featured:
if self.get(featured) is None:
Expand All @@ -249,7 +249,9 @@ def generate(self) -> None:
msg = "Missing edge target: %s" % self.edge_target
raise InvalidModel(msg)

def _add_reverse(self, data: ReverseSpec, other: Property) -> Property:
def _add_reverse(
self, model: "Model", data: ReverseSpec, other: Property
) -> Property:
name = data.get("name")
if name is None:
raise InvalidModel("Unnamed reverse: %s" % other)
Expand All @@ -265,7 +267,7 @@ def _add_reverse(self, data: ReverseSpec, other: Property) -> Property:
}
prop = Property(self, name, spec)
prop.stub = True
prop.generate()
prop.generate(model)
self.properties[name] = prop
return prop

Expand Down Expand Up @@ -351,7 +353,9 @@ def can_match(self, other: "Schema") -> bool:
def is_a(self, other: Union[str, "Schema"]) -> bool:
"""Check if the schema or one of its parents is the same as the given
candidate ``other``."""
return self.model.get(other) in self.schemata
if not isinstance(other, str):
other = other.name
return other in self.names

def get(self, name: Optional[str]) -> Optional[Property]:
"""Retrieve a property defined for this schema by its name."""
Expand Down