-
Notifications
You must be signed in to change notification settings - Fork 20
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
merge stable to release 1.1 #5300
Changes from all commits
61178de
d6c8ec5
4d32ce6
7dbf184
6fe043c
ad0ae5a
187b13f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -153,20 +153,21 @@ def to_diff_property(self, from_time: Timestamp) -> DiffProperty: | |
class DiffAttributeIntermediate(TrackedStatusUpdates): | ||
uuid: str | ||
name: str | ||
from_time: Timestamp | ||
properties_by_type: dict[DatabaseEdgeType, DiffPropertyIntermediate] = field(default_factory=dict) | ||
|
||
def track_database_path(self, database_path: DatabasePath) -> None: | ||
if database_path.attribute_changed_at in self.timestamp_status_map: | ||
return | ||
self.timestamp_status_map[database_path.attribute_changed_at] = database_path.attribute_status | ||
|
||
def to_diff_attribute(self, from_time: Timestamp, include_unchanged: bool) -> DiffAttribute: | ||
def to_diff_attribute(self, include_unchanged: bool) -> DiffAttribute: | ||
properties = [] | ||
for prop in self.properties_by_type.values(): | ||
diff_prop = prop.to_diff_property(from_time=from_time) | ||
diff_prop = prop.to_diff_property(from_time=self.from_time) | ||
if include_unchanged or diff_prop.action is not DiffAction.UNCHANGED: | ||
properties.append(diff_prop) | ||
action, changed_at = self.get_action_and_timestamp(from_time=from_time) | ||
action, changed_at = self.get_action_and_timestamp(from_time=self.from_time) | ||
if not properties or all(p.action is DiffAction.UNCHANGED for p in properties): | ||
action = DiffAction.UNCHANGED | ||
return DiffAttribute( | ||
|
@@ -308,6 +309,7 @@ class DiffRelationshipIntermediate: | |
name: str | ||
identifier: str | ||
cardinality: RelationshipCardinality | ||
from_time: Timestamp | ||
properties_by_db_id: dict[str, set[DiffRelationshipPropertyIntermediate]] = field(default_factory=dict) | ||
_single_relationship_list: list[DiffSingleRelationshipIntermediate] = field(default_factory=list) | ||
|
||
|
@@ -354,23 +356,22 @@ def _index_relationships(self) -> None: | |
for single_relationship_properties in self.properties_by_db_id.values() | ||
] | ||
|
||
def to_diff_relationship(self, from_time: Timestamp, include_unchanged: bool) -> DiffRelationship: | ||
def to_diff_relationship(self, include_unchanged: bool) -> DiffRelationship: | ||
self._index_relationships() | ||
single_relationships = [ | ||
sr.get_final_single_relationship(from_time=from_time, include_unchanged=include_unchanged) | ||
sr.get_final_single_relationship(from_time=self.from_time, include_unchanged=include_unchanged) | ||
for sr in self._single_relationship_list | ||
] | ||
last_changed_relationship = max(single_relationships, key=lambda r: r.changed_at) | ||
last_changed_at = last_changed_relationship.changed_at | ||
action = DiffAction.UPDATED | ||
if last_changed_at < from_time or all(sr.action is DiffAction.UNCHANGED for sr in single_relationships): | ||
if last_changed_at < self.from_time or all(sr.action is DiffAction.UNCHANGED for sr in single_relationships): | ||
action = DiffAction.UNCHANGED | ||
if ( | ||
self.cardinality is RelationshipCardinality.ONE | ||
and len(single_relationships) == 1 | ||
and single_relationships[0].action in (DiffAction.ADDED, DiffAction.REMOVED) | ||
): | ||
action = single_relationships[0].action | ||
# bubble up action, excluding UNCHANGED | ||
if self.cardinality is RelationshipCardinality.ONE: | ||
actions = {sr.action for sr in single_relationships if sr.action is not DiffAction.UNCHANGED} | ||
if len(actions) == 1: | ||
action = actions.pop() | ||
return DiffRelationship( | ||
name=self.name, | ||
changed_at=last_changed_at, | ||
|
@@ -391,13 +392,13 @@ class DiffNodeIntermediate(TrackedStatusUpdates): | |
def to_diff_node(self, from_time: Timestamp, include_unchanged: bool) -> DiffNode: | ||
attributes = [] | ||
for attr in self.attributes_by_name.values(): | ||
diff_attr = attr.to_diff_attribute(from_time=from_time, include_unchanged=include_unchanged) | ||
diff_attr = attr.to_diff_attribute(include_unchanged=include_unchanged) | ||
if include_unchanged or diff_attr.action is not DiffAction.UNCHANGED: | ||
attributes.append(diff_attr) | ||
action, changed_at = self.get_action_and_timestamp(from_time=from_time) | ||
relationships = [] | ||
for rel in self.relationships_by_name.values(): | ||
diff_rel = rel.to_diff_relationship(from_time=from_time, include_unchanged=include_unchanged) | ||
diff_rel = rel.to_diff_relationship(include_unchanged=include_unchanged) | ||
if include_unchanged or diff_rel.action is not DiffAction.UNCHANGED: | ||
relationships.append(diff_rel) | ||
if not attributes and not relationships: | ||
|
@@ -447,6 +448,7 @@ def __init__( | |
schema_manager: SchemaManager, | ||
from_time: Timestamp, | ||
to_time: Optional[Timestamp] = None, | ||
previous_node_field_specifiers: set[NodeFieldSpecifier] | None = None, | ||
) -> None: | ||
self.base_branch_name = base_branch.name | ||
self.diff_branch_name = diff_branch.name | ||
|
@@ -460,6 +462,7 @@ def __init__( | |
self.diff_branched_from_time = Timestamp(diff_branch.get_branched_from()) | ||
self._diff_root_by_branch: dict[str, DiffRootIntermediate] = {} | ||
self._final_diff_root_by_branch: dict[str, DiffRoot] = {} | ||
self._previous_node_field_specifiers = previous_node_field_specifiers or set() | ||
|
||
def get_branches(self) -> set[str]: | ||
return set(self._final_diff_root_by_branch.keys()) | ||
|
@@ -471,11 +474,11 @@ def get_diff_root_for_branch(self, branch: str) -> DiffRoot: | |
return self._final_diff_root_by_branch[branch] | ||
return DiffRoot(from_time=self.from_time, to_time=self.to_time, uuid=str(uuid4()), branch=branch, nodes=[]) | ||
|
||
def get_node_field_specifiers_for_branch(self, branch_name: str) -> set[NodeFieldSpecifier]: | ||
if branch_name not in self._diff_root_by_branch: | ||
def get_diff_node_field_specifiers(self) -> set[NodeFieldSpecifier]: | ||
if self.diff_branch_name not in self._diff_root_by_branch: | ||
return set() | ||
node_field_specifiers: set[NodeFieldSpecifier] = set() | ||
diff_root = self._diff_root_by_branch[branch_name] | ||
diff_root = self._diff_root_by_branch[self.diff_branch_name] | ||
for node in diff_root.nodes_by_id.values(): | ||
node_field_specifiers.update( | ||
NodeFieldSpecifier(node_uuid=node.uuid, field_name=attribute_name) | ||
|
@@ -487,6 +490,16 @@ def get_node_field_specifiers_for_branch(self, branch_name: str) -> set[NodeFiel | |
) | ||
return node_field_specifiers | ||
|
||
def get_new_node_field_specifiers(self) -> set[NodeFieldSpecifier]: | ||
branch_node_specifiers = self.get_diff_node_field_specifiers() | ||
new_node_field_specifiers = branch_node_specifiers - self._previous_node_field_specifiers | ||
return new_node_field_specifiers | ||
|
||
def get_current_node_field_specifiers(self) -> set[NodeFieldSpecifier]: | ||
new_node_field_specifiers = self.get_new_node_field_specifiers() | ||
current_node_field_specifiers = self._previous_node_field_specifiers - new_node_field_specifiers | ||
return current_node_field_specifiers | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd like to add some caching for these b/c we should really only need to calculate these things one time, but that can come in a later PR |
||
|
||
def read_result(self, query_result: QueryResult) -> None: | ||
path = query_result.get_path(label="diff_path") | ||
database_path = DatabasePath.from_cypher_path(cypher_path=path) | ||
|
@@ -546,7 +559,9 @@ def _update_attribute_level(self, database_path: DatabasePath, diff_node: DiffNo | |
relationship_schema = self._get_relationship_schema(database_path=database_path, node_schema=node_schema) | ||
if not relationship_schema: | ||
return | ||
diff_relationship = self._get_diff_relationship(diff_node=diff_node, relationship_schema=relationship_schema) | ||
diff_relationship = self._get_diff_relationship( | ||
diff_node=diff_node, relationship_schema=relationship_schema, database_path=database_path | ||
) | ||
diff_relationship.add_path( | ||
database_path=database_path, diff_from_time=self.from_time, diff_to_time=self.to_time | ||
) | ||
|
@@ -555,10 +570,16 @@ def _get_diff_attribute( | |
self, database_path: DatabasePath, diff_node: DiffNodeIntermediate | ||
) -> DiffAttributeIntermediate: | ||
attribute_name = database_path.attribute_name | ||
node_field_specifier = NodeFieldSpecifier(node_uuid=diff_node.uuid, field_name=attribute_name) | ||
branch_name = database_path.deepest_branch | ||
from_time = self.from_time | ||
if branch_name == self.base_branch_name and node_field_specifier in self.get_new_node_field_specifiers(): | ||
from_time = self.diff_branched_from_time | ||
if attribute_name not in diff_node.attributes_by_name: | ||
diff_node.attributes_by_name[attribute_name] = DiffAttributeIntermediate( | ||
uuid=database_path.attribute_id, | ||
name=attribute_name, | ||
from_time=from_time, | ||
) | ||
diff_attribute = diff_node.attributes_by_name[attribute_name] | ||
diff_attribute.track_database_path(database_path=database_path) | ||
|
@@ -583,14 +604,25 @@ def _update_attribute_property( | |
) | ||
|
||
def _get_diff_relationship( | ||
self, diff_node: DiffNodeIntermediate, relationship_schema: RelationshipSchema | ||
self, | ||
diff_node: DiffNodeIntermediate, | ||
relationship_schema: RelationshipSchema, | ||
database_path: DatabasePath, | ||
) -> DiffRelationshipIntermediate: | ||
diff_relationship = diff_node.relationships_by_name.get(relationship_schema.name) | ||
if not diff_relationship: | ||
node_field_specifier = NodeFieldSpecifier( | ||
node_uuid=diff_node.uuid, field_name=relationship_schema.get_identifier() | ||
) | ||
branch_name = database_path.deepest_branch | ||
from_time = self.from_time | ||
if branch_name == self.base_branch_name and node_field_specifier in self.get_new_node_field_specifiers(): | ||
from_time = self.diff_branched_from_time | ||
diff_relationship = DiffRelationshipIntermediate( | ||
name=relationship_schema.name, | ||
cardinality=relationship_schema.cardinality, | ||
identifier=relationship_schema.get_identifier(), | ||
from_time=from_time, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we use the |
||
) | ||
diff_node.relationships_by_name[relationship_schema.name] = diff_relationship | ||
return diff_relationship | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ignore
UNCHANGED
individual relationships when determining the overall action for this relationship group (kind of equivalent to RelationshipManager)