infrahub-server 1.6.3__py3-none-any.whl → 1.7.0b0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- infrahub/actions/tasks.py +4 -2
- infrahub/api/schema.py +3 -1
- infrahub/artifacts/tasks.py +1 -0
- infrahub/auth.py +2 -2
- infrahub/cli/db.py +6 -6
- infrahub/computed_attribute/gather.py +3 -4
- infrahub/computed_attribute/tasks.py +23 -6
- infrahub/config.py +8 -0
- infrahub/constants/enums.py +12 -0
- infrahub/core/account.py +5 -8
- infrahub/core/attribute.py +106 -108
- infrahub/core/branch/models.py +44 -71
- infrahub/core/branch/tasks.py +5 -3
- infrahub/core/changelog/diff.py +1 -20
- infrahub/core/changelog/models.py +0 -7
- infrahub/core/constants/__init__.py +17 -0
- infrahub/core/constants/database.py +0 -1
- infrahub/core/constants/schema.py +0 -1
- infrahub/core/convert_object_type/repository_conversion.py +3 -4
- infrahub/core/diff/data_check_synchronizer.py +3 -2
- infrahub/core/diff/enricher/cardinality_one.py +1 -1
- infrahub/core/diff/merger/merger.py +27 -1
- infrahub/core/diff/merger/serializer.py +3 -10
- infrahub/core/diff/model/diff.py +1 -1
- infrahub/core/diff/query/merge.py +376 -135
- infrahub/core/graph/__init__.py +1 -1
- infrahub/core/graph/constraints.py +2 -2
- infrahub/core/graph/schema.py +2 -12
- infrahub/core/manager.py +132 -126
- infrahub/core/metadata/__init__.py +0 -0
- infrahub/core/metadata/interface.py +37 -0
- infrahub/core/metadata/model.py +31 -0
- infrahub/core/metadata/query/__init__.py +0 -0
- infrahub/core/metadata/query/node_metadata.py +301 -0
- infrahub/core/migrations/graph/__init__.py +4 -0
- infrahub/core/migrations/graph/m013_convert_git_password_credential.py +3 -8
- infrahub/core/migrations/graph/m017_add_core_profile.py +5 -2
- infrahub/core/migrations/graph/m018_uniqueness_nulls.py +2 -1
- infrahub/core/migrations/graph/m019_restore_rels_to_time.py +0 -10
- infrahub/core/migrations/graph/m020_duplicate_edges.py +0 -8
- infrahub/core/migrations/graph/m025_uniqueness_nulls.py +2 -1
- infrahub/core/migrations/graph/m026_0000_prefix_fix.py +2 -1
- infrahub/core/migrations/graph/m029_duplicates_cleanup.py +0 -1
- infrahub/core/migrations/graph/m031_check_number_attributes.py +2 -2
- infrahub/core/migrations/graph/m038_redo_0000_prefix_fix.py +2 -1
- infrahub/core/migrations/graph/m049_remove_is_visible_relationship.py +38 -0
- infrahub/core/migrations/graph/m050_backfill_vertex_metadata.py +168 -0
- infrahub/core/migrations/query/attribute_add.py +17 -6
- infrahub/core/migrations/query/attribute_remove.py +19 -5
- infrahub/core/migrations/query/attribute_rename.py +21 -5
- infrahub/core/migrations/query/node_duplicate.py +19 -4
- infrahub/core/migrations/schema/attribute_kind_update.py +25 -7
- infrahub/core/migrations/schema/attribute_supports_profile.py +3 -1
- infrahub/core/migrations/schema/models.py +3 -0
- infrahub/core/migrations/schema/node_attribute_add.py +4 -1
- infrahub/core/migrations/schema/node_remove.py +24 -2
- infrahub/core/migrations/schema/tasks.py +4 -1
- infrahub/core/migrations/shared.py +13 -6
- infrahub/core/models.py +6 -6
- infrahub/core/node/__init__.py +156 -57
- infrahub/core/node/create.py +7 -3
- infrahub/core/node/standard.py +100 -14
- infrahub/core/property.py +0 -1
- infrahub/core/protocols_base.py +6 -2
- infrahub/core/query/__init__.py +6 -7
- infrahub/core/query/attribute.py +161 -46
- infrahub/core/query/branch.py +57 -69
- infrahub/core/query/diff.py +4 -4
- infrahub/core/query/node.py +618 -180
- infrahub/core/query/relationship.py +449 -300
- infrahub/core/query/standard_node.py +25 -5
- infrahub/core/query/utils.py +2 -4
- infrahub/core/relationship/constraints/profiles_removal.py +168 -0
- infrahub/core/relationship/model.py +293 -139
- infrahub/core/schema/attribute_parameters.py +1 -28
- infrahub/core/schema/attribute_schema.py +17 -11
- infrahub/core/schema/manager.py +63 -43
- infrahub/core/schema/relationship_schema.py +6 -2
- infrahub/core/schema/schema_branch.py +48 -76
- infrahub/core/task/task.py +4 -2
- infrahub/core/utils.py +0 -22
- infrahub/core/validators/attribute/kind.py +2 -5
- infrahub/core/validators/determiner.py +3 -3
- infrahub/database/__init__.py +3 -3
- infrahub/dependencies/builder/constraint/grouped/node_runner.py +2 -0
- infrahub/dependencies/builder/constraint/relationship_manager/profiles_removal.py +8 -0
- infrahub/dependencies/registry.py +2 -0
- infrahub/display_labels/tasks.py +12 -3
- infrahub/git/integrator.py +18 -18
- infrahub/git/tasks.py +1 -1
- infrahub/graphql/app.py +2 -2
- infrahub/graphql/constants.py +3 -0
- infrahub/graphql/context.py +1 -1
- infrahub/graphql/initialization.py +11 -0
- infrahub/graphql/loaders/account.py +134 -0
- infrahub/graphql/loaders/node.py +5 -12
- infrahub/graphql/loaders/peers.py +5 -7
- infrahub/graphql/manager.py +158 -18
- infrahub/graphql/metadata.py +91 -0
- infrahub/graphql/models.py +33 -3
- infrahub/graphql/mutations/account.py +5 -5
- infrahub/graphql/mutations/attribute.py +0 -2
- infrahub/graphql/mutations/branch.py +9 -5
- infrahub/graphql/mutations/computed_attribute.py +1 -1
- infrahub/graphql/mutations/display_label.py +1 -1
- infrahub/graphql/mutations/hfid.py +1 -1
- infrahub/graphql/mutations/ipam.py +4 -6
- infrahub/graphql/mutations/main.py +9 -4
- infrahub/graphql/mutations/profile.py +16 -22
- infrahub/graphql/mutations/proposed_change.py +4 -4
- infrahub/graphql/mutations/relationship.py +40 -10
- infrahub/graphql/mutations/repository.py +14 -12
- infrahub/graphql/mutations/schema.py +2 -2
- infrahub/graphql/queries/branch.py +62 -6
- infrahub/graphql/queries/diff/tree.py +5 -5
- infrahub/graphql/resolvers/account_metadata.py +84 -0
- infrahub/graphql/resolvers/ipam.py +6 -8
- infrahub/graphql/resolvers/many_relationship.py +77 -35
- infrahub/graphql/resolvers/resolver.py +16 -12
- infrahub/graphql/resolvers/single_relationship.py +87 -23
- infrahub/graphql/subscription/graphql_query.py +2 -0
- infrahub/graphql/types/__init__.py +0 -1
- infrahub/graphql/types/attribute.py +10 -5
- infrahub/graphql/types/branch.py +40 -53
- infrahub/graphql/types/enums.py +3 -0
- infrahub/graphql/types/metadata.py +28 -0
- infrahub/graphql/types/node.py +22 -2
- infrahub/graphql/types/relationship.py +10 -2
- infrahub/graphql/types/standard_node.py +4 -3
- infrahub/hfid/tasks.py +12 -3
- infrahub/profiles/gather.py +56 -0
- infrahub/profiles/mandatory_fields_checker.py +116 -0
- infrahub/profiles/models.py +66 -0
- infrahub/profiles/node_applier.py +153 -12
- infrahub/profiles/queries/get_profile_data.py +143 -31
- infrahub/profiles/tasks.py +79 -27
- infrahub/profiles/triggers.py +22 -0
- infrahub/proposed_change/tasks.py +4 -1
- infrahub/tasks/artifact.py +1 -0
- infrahub/transformations/tasks.py +2 -2
- infrahub/trigger/catalogue.py +2 -0
- infrahub/trigger/models.py +1 -0
- infrahub/trigger/setup.py +3 -3
- infrahub/trigger/tasks.py +3 -0
- infrahub/validators/tasks.py +1 -0
- infrahub/webhook/models.py +1 -1
- infrahub/webhook/tasks.py +1 -1
- infrahub/workers/dependencies.py +9 -3
- infrahub/workers/infrahub_async.py +13 -4
- infrahub/workflows/catalogue.py +19 -0
- infrahub_sdk/node/constants.py +1 -0
- infrahub_sdk/node/related_node.py +13 -4
- infrahub_sdk/node/relationship.py +8 -0
- {infrahub_server-1.6.3.dist-info → infrahub_server-1.7.0b0.dist-info}/METADATA +17 -16
- {infrahub_server-1.6.3.dist-info → infrahub_server-1.7.0b0.dist-info}/RECORD +161 -143
- infrahub_testcontainers/container.py +3 -3
- infrahub_testcontainers/docker-compose-cluster.test.yml +7 -7
- infrahub_testcontainers/docker-compose.test.yml +13 -5
- {infrahub_server-1.6.3.dist-info → infrahub_server-1.7.0b0.dist-info}/WHEEL +0 -0
- {infrahub_server-1.6.3.dist-info → infrahub_server-1.7.0b0.dist-info}/entry_points.txt +0 -0
- {infrahub_server-1.6.3.dist-info → infrahub_server-1.7.0b0.dist-info}/licenses/LICENSE.txt +0 -0
infrahub/core/task/task.py
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
# This entire file and possibly everything in this module should be deleted. - Patrick (2025-12-11)
|
|
2
|
+
|
|
1
3
|
from typing import Any
|
|
2
4
|
|
|
3
5
|
from pydantic import ConfigDict, Field
|
|
4
6
|
|
|
5
7
|
from infrahub.core.constants import TaskConclusion
|
|
6
|
-
from infrahub.core.node.standard import StandardNode
|
|
8
|
+
from infrahub.core.node.standard import StandardNode, StandardNodeQueryFields
|
|
7
9
|
from infrahub.core.protocols import CoreNode
|
|
8
10
|
from infrahub.core.query.standard_node import StandardNodeQuery
|
|
9
11
|
from infrahub.core.query.task import TaskNodeCreateQuery, TaskNodeQuery, TaskNodeQueryWithLogs
|
|
@@ -70,7 +72,7 @@ class Task(StandardNode):
|
|
|
70
72
|
logs = [
|
|
71
73
|
{
|
|
72
74
|
"node": await TaskLog.from_db(result, extras={"task_id": task_result.get("uuid")}).to_graphql(
|
|
73
|
-
fields=log_fields
|
|
75
|
+
fields=StandardNodeQueryFields(node=log_fields)
|
|
74
76
|
)
|
|
75
77
|
}
|
|
76
78
|
for result in logs_results
|
infrahub/core/utils.py
CHANGED
|
@@ -62,28 +62,6 @@ async def delete_all_relationships_for_branch(branch_name: str, db: InfrahubData
|
|
|
62
62
|
await db.execute_query(query=query, params=params, name="delete_all_relationships_for_branch")
|
|
63
63
|
|
|
64
64
|
|
|
65
|
-
async def update_relationships_to(
|
|
66
|
-
ids: list[str], db: InfrahubDatabase, to: Timestamp | None = None
|
|
67
|
-
) -> list[Record] | None:
|
|
68
|
-
"""Update the "to" field on one or multiple relationships."""
|
|
69
|
-
if not ids:
|
|
70
|
-
return None
|
|
71
|
-
|
|
72
|
-
to = Timestamp(to)
|
|
73
|
-
|
|
74
|
-
query = """
|
|
75
|
-
MATCH ()-[r]->()
|
|
76
|
-
WHERE %(id_func)s(r) IN $ids
|
|
77
|
-
AND r.to IS NULL
|
|
78
|
-
SET r.to = $to
|
|
79
|
-
RETURN %(id_func)s(r)
|
|
80
|
-
""" % {"id_func": db.get_id_function_name()}
|
|
81
|
-
|
|
82
|
-
params = {"to": to.to_string(), "ids": [db.to_database_id(_id) for _id in ids]}
|
|
83
|
-
|
|
84
|
-
return await db.execute_query(query=query, params=params, name="update_relationships_to")
|
|
85
|
-
|
|
86
|
-
|
|
87
65
|
async def get_paths_between_nodes(
|
|
88
66
|
db: InfrahubDatabase,
|
|
89
67
|
source_id: str,
|
|
@@ -36,7 +36,7 @@ class AttributeKindUpdateValidatorQuery(AttributeSchemaValidatorQuery):
|
|
|
36
36
|
self.params["null_value"] = NULL_VALUE
|
|
37
37
|
|
|
38
38
|
query = """
|
|
39
|
-
MATCH (n:%(
|
|
39
|
+
MATCH p = (n:%(node_kind)s)
|
|
40
40
|
CALL (n) {
|
|
41
41
|
MATCH path = (root:Root)<-[rr:IS_PART_OF]-(n)-[ra:HAS_ATTRIBUTE]-(:Attribute { name: $attr_name } )-[rv:HAS_VALUE]-(av:AttributeValue)
|
|
42
42
|
WHERE all(
|
|
@@ -51,10 +51,7 @@ class AttributeKindUpdateValidatorQuery(AttributeSchemaValidatorQuery):
|
|
|
51
51
|
WHERE all(r in relationships(full_path) WHERE r.status = "active")
|
|
52
52
|
AND attribute_value IS NOT NULL
|
|
53
53
|
AND attribute_value <> $null_value
|
|
54
|
-
""" % {
|
|
55
|
-
"branch_filter": branch_filter,
|
|
56
|
-
"node_kinds": f"{self.node_schema.kind}|Profile{self.node_schema.kind}|Template{self.node_schema.kind}",
|
|
57
|
-
}
|
|
54
|
+
""" % {"branch_filter": branch_filter, "node_kind": self.node_schema.kind}
|
|
58
55
|
|
|
59
56
|
self.add_to_query(query)
|
|
60
57
|
self.return_labels = ["node.uuid", "attribute_value", "value_relationship.branch as value_branch"]
|
|
@@ -97,7 +97,7 @@ class ConstraintValidatorDeterminer:
|
|
|
97
97
|
self, schema: MainSchemaTypes
|
|
98
98
|
) -> list[SchemaUpdateConstraintInfo]:
|
|
99
99
|
constraints: list[SchemaUpdateConstraintInfo] = []
|
|
100
|
-
for prop_name, prop_field_info in schema.model_fields.items():
|
|
100
|
+
for prop_name, prop_field_info in schema.__class__.model_fields.items():
|
|
101
101
|
if (
|
|
102
102
|
prop_name in ["attributes", "relationships"]
|
|
103
103
|
or not prop_field_info.json_schema_extra
|
|
@@ -158,10 +158,10 @@ class ConstraintValidatorDeterminer:
|
|
|
158
158
|
) -> list[SchemaUpdateConstraintInfo]:
|
|
159
159
|
constraints: list[SchemaUpdateConstraintInfo] = []
|
|
160
160
|
prop_details_list: list[tuple[str, FieldInfo, Any]] = []
|
|
161
|
-
for p_name, p_info in field.model_fields.items():
|
|
161
|
+
for p_name, p_info in field.__class__.model_fields.items():
|
|
162
162
|
p_value = getattr(field, p_name)
|
|
163
163
|
if isinstance(p_value, AttributeParameters):
|
|
164
|
-
for parameter_name, parameter_field_info in p_value.model_fields.items():
|
|
164
|
+
for parameter_name, parameter_field_info in p_value.__class__.model_fields.items():
|
|
165
165
|
parameter_value = getattr(p_value, parameter_name)
|
|
166
166
|
prop_details_list.append((f"{p_name}.{parameter_name}", parameter_field_info, parameter_value))
|
|
167
167
|
else:
|
infrahub/database/__init__.py
CHANGED
|
@@ -13,7 +13,7 @@ from neo4j import (
|
|
|
13
13
|
AsyncResult,
|
|
14
14
|
AsyncSession,
|
|
15
15
|
AsyncTransaction,
|
|
16
|
-
|
|
16
|
+
NotificationDisabledClassification,
|
|
17
17
|
NotificationMinimumSeverity,
|
|
18
18
|
Query,
|
|
19
19
|
Record,
|
|
@@ -492,8 +492,8 @@ async def get_db(retry: int = 0) -> AsyncDriver:
|
|
|
492
492
|
auth=(config.SETTINGS.database.username, config.SETTINGS.database.password),
|
|
493
493
|
encrypted=config.SETTINGS.database.tls_enabled,
|
|
494
494
|
trusted_certificates=trusted_certificates,
|
|
495
|
-
|
|
496
|
-
|
|
495
|
+
notifications_disabled_classifications=[
|
|
496
|
+
NotificationDisabledClassification.UNRECOGNIZED,
|
|
497
497
|
],
|
|
498
498
|
notifications_min_severity=NotificationMinimumSeverity.WARNING,
|
|
499
499
|
)
|
|
@@ -7,6 +7,7 @@ from ..relationship_manager.peer_kind import RelationshipPeerKindConstraintDepen
|
|
|
7
7
|
from ..relationship_manager.peer_parent import RelationshipPeerParentConstraintDependency
|
|
8
8
|
from ..relationship_manager.peer_relatives import RelationshipPeerRelativesConstraintDependency
|
|
9
9
|
from ..relationship_manager.profiles_kind import RelationshipProfilesKindConstraintDependency
|
|
10
|
+
from ..relationship_manager.profiles_removal import RelationshipProfileRemovalConstraintDependency
|
|
10
11
|
|
|
11
12
|
|
|
12
13
|
class NodeConstraintRunnerDependency(DependencyBuilder[NodeConstraintRunner]):
|
|
@@ -20,6 +21,7 @@ class NodeConstraintRunnerDependency(DependencyBuilder[NodeConstraintRunner]):
|
|
|
20
21
|
RelationshipPeerKindConstraintDependency.build(context=context),
|
|
21
22
|
RelationshipCountConstraintDependency.build(context=context),
|
|
22
23
|
RelationshipProfilesKindConstraintDependency.build(context=context),
|
|
24
|
+
RelationshipProfileRemovalConstraintDependency.build(context=context),
|
|
23
25
|
RelationshipPeerParentConstraintDependency.build(context=context),
|
|
24
26
|
RelationshipPeerRelativesConstraintDependency.build(context=context),
|
|
25
27
|
],
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
from infrahub.core.relationship.constraints.profiles_removal import RelationshipProfileRemovalConstraint
|
|
2
|
+
from infrahub.dependencies.interface import DependencyBuilder, DependencyBuilderContext
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class RelationshipProfileRemovalConstraintDependency(DependencyBuilder[RelationshipProfileRemovalConstraint]):
|
|
6
|
+
@classmethod
|
|
7
|
+
def build(cls, context: DependencyBuilderContext) -> RelationshipProfileRemovalConstraint:
|
|
8
|
+
return RelationshipProfileRemovalConstraint(db=context.db, branch=context.branch)
|
|
@@ -6,6 +6,7 @@ from .builder.constraint.relationship_manager.peer_kind import RelationshipPeerK
|
|
|
6
6
|
from .builder.constraint.relationship_manager.peer_parent import RelationshipPeerParentConstraintDependency
|
|
7
7
|
from .builder.constraint.relationship_manager.peer_relatives import RelationshipPeerRelativesConstraintDependency
|
|
8
8
|
from .builder.constraint.relationship_manager.profiles_kind import RelationshipProfilesKindConstraintDependency
|
|
9
|
+
from .builder.constraint.relationship_manager.profiles_removal import RelationshipProfileRemovalConstraintDependency
|
|
9
10
|
from .builder.constraint.schema.aggregated import AggregatedSchemaConstraintsDependency
|
|
10
11
|
from .builder.constraint.schema.attribute_regex import SchemaAttributeRegexConstraintDependency
|
|
11
12
|
from .builder.constraint.schema.attribute_uniqueness import SchemaAttributeUniqueConstraintDependency
|
|
@@ -38,6 +39,7 @@ def build_component_registry() -> ComponentDependencyRegistry:
|
|
|
38
39
|
component_registry.track_dependency(NodeGroupedUniquenessConstraintDependency)
|
|
39
40
|
component_registry.track_dependency(RelationshipCountConstraintDependency)
|
|
40
41
|
component_registry.track_dependency(RelationshipProfilesKindConstraintDependency)
|
|
42
|
+
component_registry.track_dependency(RelationshipProfileRemovalConstraintDependency)
|
|
41
43
|
component_registry.track_dependency(RelationshipPeerKindConstraintDependency)
|
|
42
44
|
component_registry.track_dependency(RelationshipPeerParentConstraintDependency)
|
|
43
45
|
component_registry.track_dependency(RelationshipPeerRelativesConstraintDependency)
|
infrahub/display_labels/tasks.py
CHANGED
|
@@ -21,9 +21,11 @@ UPDATE_DISPLAY_LABEL = """
|
|
|
21
21
|
mutation UpdateDisplayLabel(
|
|
22
22
|
$id: String!,
|
|
23
23
|
$kind: String!,
|
|
24
|
-
$value: String
|
|
24
|
+
$value: String!,
|
|
25
|
+
$context_account_id: String!
|
|
25
26
|
) {
|
|
26
27
|
InfrahubUpdateDisplayLabel(
|
|
28
|
+
context: {account: {id: $context_account_id}},
|
|
27
29
|
data: {id: $id, value: $value, kind: $kind}
|
|
28
30
|
) {
|
|
29
31
|
ok
|
|
@@ -41,6 +43,7 @@ async def display_label_jinja2_update_value(
|
|
|
41
43
|
obj: DisplayLabelJinja2GraphQLResponse,
|
|
42
44
|
node_kind: str,
|
|
43
45
|
template: Jinja2Template,
|
|
46
|
+
context: InfrahubContext,
|
|
44
47
|
) -> None:
|
|
45
48
|
log = get_run_logger()
|
|
46
49
|
client = get_client()
|
|
@@ -55,7 +58,12 @@ async def display_label_jinja2_update_value(
|
|
|
55
58
|
try:
|
|
56
59
|
await client.execute_graphql(
|
|
57
60
|
query=UPDATE_DISPLAY_LABEL,
|
|
58
|
-
variables={
|
|
61
|
+
variables={
|
|
62
|
+
"id": obj.node_id,
|
|
63
|
+
"kind": node_kind,
|
|
64
|
+
"value": value,
|
|
65
|
+
"context_account_id": context.account.account_id,
|
|
66
|
+
},
|
|
59
67
|
branch_name=branch_name,
|
|
60
68
|
)
|
|
61
69
|
log.info(f"Updating {node_kind}.display_label='{value}' ({obj.node_id})")
|
|
@@ -74,7 +82,7 @@ async def process_display_label(
|
|
|
74
82
|
node_kind: str,
|
|
75
83
|
object_id: str,
|
|
76
84
|
target_kind: str,
|
|
77
|
-
context: InfrahubContext,
|
|
85
|
+
context: InfrahubContext,
|
|
78
86
|
) -> None:
|
|
79
87
|
log = get_run_logger()
|
|
80
88
|
client = get_client()
|
|
@@ -114,6 +122,7 @@ async def process_display_label(
|
|
|
114
122
|
obj=node,
|
|
115
123
|
node_kind=node_schema.kind,
|
|
116
124
|
template=jinja_template,
|
|
125
|
+
context=context,
|
|
117
126
|
)
|
|
118
127
|
|
|
119
128
|
_ = [response async for _, response in batch.execute()]
|
infrahub/git/integrator.py
CHANGED
|
@@ -180,31 +180,31 @@ class InfrahubRepositoryIntegrator(InfrahubRepositoryBase):
|
|
|
180
180
|
self.create_commit_worktree(commit)
|
|
181
181
|
await self._update_sync_status(branch_name=infrahub_branch_name, status=RepositorySyncStatus.SYNCING)
|
|
182
182
|
|
|
183
|
-
config_file = await self.get_repository_config(branch_name=infrahub_branch_name, commit=commit) # type: ignore[
|
|
183
|
+
config_file = await self.get_repository_config(branch_name=infrahub_branch_name, commit=commit) # type: ignore[call-overload]
|
|
184
184
|
sync_status = RepositorySyncStatus.IN_SYNC if config_file else RepositorySyncStatus.ERROR_IMPORT
|
|
185
185
|
|
|
186
186
|
error: Exception | None = None
|
|
187
187
|
|
|
188
188
|
try:
|
|
189
189
|
if config_file:
|
|
190
|
-
await self.import_schema_files(branch_name=infrahub_branch_name, commit=commit, config_file=config_file) # type: ignore[
|
|
190
|
+
await self.import_schema_files(branch_name=infrahub_branch_name, commit=commit, config_file=config_file) # type: ignore[call-overload]
|
|
191
191
|
await self.import_all_graphql_query(
|
|
192
192
|
branch_name=infrahub_branch_name, commit=commit, config_file=config_file
|
|
193
|
-
) # type: ignore[
|
|
193
|
+
) # type: ignore[call-overload]
|
|
194
194
|
await self.import_objects(
|
|
195
195
|
branch_name=infrahub_branch_name,
|
|
196
196
|
commit=commit,
|
|
197
197
|
config_file=config_file,
|
|
198
|
-
) # type: ignore[
|
|
199
|
-
await self.import_all_python_files(
|
|
198
|
+
) # type: ignore[call-overload]
|
|
199
|
+
await self.import_all_python_files(
|
|
200
200
|
branch_name=infrahub_branch_name, commit=commit, config_file=config_file
|
|
201
|
-
) # type: ignore[
|
|
201
|
+
) # type: ignore[call-overload]
|
|
202
202
|
await self.import_jinja2_transforms(
|
|
203
203
|
branch_name=infrahub_branch_name, commit=commit, config_file=config_file
|
|
204
|
-
) # type: ignore[
|
|
204
|
+
) # type: ignore[call-overload]
|
|
205
205
|
await self.import_artifact_definitions(
|
|
206
206
|
branch_name=infrahub_branch_name, commit=commit, config_file=config_file
|
|
207
|
-
) # type: ignore[
|
|
207
|
+
) # type: ignore[call-overload]
|
|
208
208
|
|
|
209
209
|
except Exception as exc:
|
|
210
210
|
sync_status = RepositorySyncStatus.ERROR_IMPORT
|
|
@@ -634,7 +634,7 @@ class InfrahubRepositoryIntegrator(InfrahubRepositoryBase):
|
|
|
634
634
|
module=module,
|
|
635
635
|
file_path=file_info.relative_path_file,
|
|
636
636
|
check_definition=check,
|
|
637
|
-
) # type: ignore[
|
|
637
|
+
) # type: ignore[call-overload]
|
|
638
638
|
)
|
|
639
639
|
|
|
640
640
|
local_check_definitions = {check.name: check for check in checks}
|
|
@@ -797,7 +797,7 @@ class InfrahubRepositoryIntegrator(InfrahubRepositoryBase):
|
|
|
797
797
|
module=module,
|
|
798
798
|
file_path=file_info.relative_path_file,
|
|
799
799
|
transform=transform,
|
|
800
|
-
) # type: ignore[
|
|
800
|
+
) # type: ignore[call-overload]
|
|
801
801
|
)
|
|
802
802
|
|
|
803
803
|
local_transform_definitions = {transform.name: transform for transform in transforms}
|
|
@@ -1156,9 +1156,9 @@ class InfrahubRepositoryIntegrator(InfrahubRepositoryBase):
|
|
|
1156
1156
|
) -> None:
|
|
1157
1157
|
await add_tags(branches=[branch_name], nodes=[str(self.id)])
|
|
1158
1158
|
|
|
1159
|
-
await self.import_python_check_definitions(branch_name=branch_name, commit=commit, config_file=config_file) # type: ignore[
|
|
1160
|
-
await self.import_python_transforms(branch_name=branch_name, commit=commit, config_file=config_file) # type: ignore[
|
|
1161
|
-
await self.import_generator_definitions(branch_name=branch_name, commit=commit, config_file=config_file) # type: ignore[
|
|
1159
|
+
await self.import_python_check_definitions(branch_name=branch_name, commit=commit, config_file=config_file) # type: ignore[call-overload]
|
|
1160
|
+
await self.import_python_transforms(branch_name=branch_name, commit=commit, config_file=config_file) # type: ignore[call-overload]
|
|
1161
|
+
await self.import_generator_definitions(branch_name=branch_name, commit=commit, config_file=config_file) # type: ignore[call-overload]
|
|
1162
1162
|
|
|
1163
1163
|
@task(name="jinja2-template-render", task_run_name="Render Jinja2 template", cache_policy=NONE)
|
|
1164
1164
|
async def render_jinja2_template(self, commit: str, location: str, data: dict) -> str:
|
|
@@ -1324,7 +1324,7 @@ class InfrahubRepositoryIntegrator(InfrahubRepositoryBase):
|
|
|
1324
1324
|
if transformation.typename == InfrahubKind.TRANSFORMJINJA2:
|
|
1325
1325
|
artifact_content = await self.render_jinja2_template.with_options(
|
|
1326
1326
|
timeout_seconds=transformation.timeout.value
|
|
1327
|
-
)(commit=commit, location=transformation.template_path.value, data=response) # type: ignore[
|
|
1327
|
+
)(commit=commit, location=transformation.template_path.value, data=response) # type: ignore[call-overload]
|
|
1328
1328
|
elif transformation.typename == InfrahubKind.TRANSFORMPYTHON:
|
|
1329
1329
|
transformation_location = f"{transformation.file_path.value}::{transformation.class_name.value}"
|
|
1330
1330
|
artifact_content = await self.execute_python_transform.with_options(
|
|
@@ -1336,7 +1336,7 @@ class InfrahubRepositoryIntegrator(InfrahubRepositoryBase):
|
|
|
1336
1336
|
location=transformation_location,
|
|
1337
1337
|
data=response,
|
|
1338
1338
|
convert_query_response=transformation.convert_query_response.value,
|
|
1339
|
-
) # type: ignore[
|
|
1339
|
+
) # type: ignore[call-overload]
|
|
1340
1340
|
|
|
1341
1341
|
if definition.content_type.value == ContentType.APPLICATION_JSON.value and isinstance(artifact_content, dict):
|
|
1342
1342
|
artifact_content_str = ujson.dumps(artifact_content, indent=2)
|
|
@@ -1387,7 +1387,7 @@ class InfrahubRepositoryIntegrator(InfrahubRepositoryBase):
|
|
|
1387
1387
|
if message.transform_type == InfrahubKind.TRANSFORMJINJA2:
|
|
1388
1388
|
artifact_content = await self.render_jinja2_template.with_options(timeout_seconds=message.timeout)(
|
|
1389
1389
|
commit=message.commit, location=message.transform_location, data=response
|
|
1390
|
-
) # type: ignore[
|
|
1390
|
+
) # type: ignore[call-overload]
|
|
1391
1391
|
elif message.transform_type == InfrahubKind.TRANSFORMPYTHON:
|
|
1392
1392
|
artifact_content = await self.execute_python_transform.with_options(timeout_seconds=message.timeout)(
|
|
1393
1393
|
client=self.sdk,
|
|
@@ -1396,7 +1396,7 @@ class InfrahubRepositoryIntegrator(InfrahubRepositoryBase):
|
|
|
1396
1396
|
location=message.transform_location,
|
|
1397
1397
|
data=response,
|
|
1398
1398
|
convert_query_response=message.convert_query_response,
|
|
1399
|
-
) # type: ignore[
|
|
1399
|
+
) # type: ignore[call-overload]
|
|
1400
1400
|
|
|
1401
1401
|
if message.content_type == ContentType.APPLICATION_JSON.value and isinstance(artifact_content, dict):
|
|
1402
1402
|
artifact_content_str = ujson.dumps(artifact_content, indent=2)
|
|
@@ -1421,7 +1421,7 @@ class InfrahubRepositoryIntegrator(InfrahubRepositoryBase):
|
|
|
1421
1421
|
artifact.status.value = ArtifactStatus.READY.value
|
|
1422
1422
|
if artifact.name.value != message.artifact_name:
|
|
1423
1423
|
artifact.name.value = message.artifact_name
|
|
1424
|
-
await artifact.save()
|
|
1424
|
+
await artifact.save(request_context=message.context.to_request_context())
|
|
1425
1425
|
|
|
1426
1426
|
event_class = ArtifactCreatedEvent if artifact_created else ArtifactUpdatedEvent
|
|
1427
1427
|
|
infrahub/git/tasks.py
CHANGED
|
@@ -950,7 +950,7 @@ async def run_user_check(model: UserCheckData) -> ValidatorConclusion:
|
|
|
950
950
|
client=client,
|
|
951
951
|
commit=model.commit,
|
|
952
952
|
params=model.variables,
|
|
953
|
-
) # type: ignore[
|
|
953
|
+
) # type: ignore[call-overload]
|
|
954
954
|
if check_run.passed:
|
|
955
955
|
conclusion = ValidatorConclusion.SUCCESS
|
|
956
956
|
severity = "info"
|
infrahub/graphql/app.py
CHANGED
|
@@ -172,9 +172,9 @@ class InfrahubGraphQLApp:
|
|
|
172
172
|
|
|
173
173
|
response = handler(request)
|
|
174
174
|
if isawaitable(response):
|
|
175
|
-
return await response
|
|
175
|
+
return await cast("Awaitable[Response]", response)
|
|
176
176
|
|
|
177
|
-
return response
|
|
177
|
+
return cast("Response", response)
|
|
178
178
|
|
|
179
179
|
async def _handle_http_request(
|
|
180
180
|
self, request: Request, db: InfrahubDatabase, branch: Branch, account_session: AccountSession
|
infrahub/graphql/constants.py
CHANGED
infrahub/graphql/context.py
CHANGED
|
@@ -14,7 +14,7 @@ if TYPE_CHECKING:
|
|
|
14
14
|
|
|
15
15
|
async def apply_external_context(graphql_context: GraphqlContext, context_input: ContextInput | None) -> None:
|
|
16
16
|
"""Applies context provided by an external mutation to the GraphQL context"""
|
|
17
|
-
if not context_input or not context_input.account:
|
|
17
|
+
if not context_input or not context_input.account or not context_input.account.id:
|
|
18
18
|
return
|
|
19
19
|
|
|
20
20
|
if graphql_context.active_account_session.account_id == context_input.account.id:
|
|
@@ -7,9 +7,11 @@ from starlette.background import BackgroundTasks
|
|
|
7
7
|
|
|
8
8
|
from infrahub.context import InfrahubContext
|
|
9
9
|
from infrahub.core import registry
|
|
10
|
+
from infrahub.core.constants import SYSTEM_USER_ID
|
|
10
11
|
from infrahub.core.timestamp import Timestamp
|
|
11
12
|
from infrahub.exceptions import InitializationError
|
|
12
13
|
from infrahub.graphql.registry import registry as graphql_registry
|
|
14
|
+
from infrahub.graphql.resolvers.account_metadata import AccountMetadataResolver
|
|
13
15
|
from infrahub.graphql.resolvers.many_relationship import ManyRelationshipResolver
|
|
14
16
|
from infrahub.graphql.resolvers.single_relationship import SingleRelationshipResolver
|
|
15
17
|
from infrahub.permissions import PermissionManager
|
|
@@ -37,6 +39,7 @@ class GraphqlContext:
|
|
|
37
39
|
types: dict
|
|
38
40
|
single_relationship_resolver: SingleRelationshipResolver
|
|
39
41
|
many_relationship_resolver: ManyRelationshipResolver
|
|
42
|
+
account_metadata_resolver: AccountMetadataResolver
|
|
40
43
|
service: InfrahubServices | None = None
|
|
41
44
|
at: Timestamp | None = None
|
|
42
45
|
related_node_ids: set | None = None
|
|
@@ -75,6 +78,13 @@ class GraphqlContext:
|
|
|
75
78
|
def get_context(self) -> InfrahubContext:
|
|
76
79
|
return InfrahubContext.init(branch=self.branch, account=self.active_account_session)
|
|
77
80
|
|
|
81
|
+
@property
|
|
82
|
+
def assigned_user_id(self) -> str:
|
|
83
|
+
"""Return the user ID to be used for assignments in this context."""
|
|
84
|
+
if self.account_session and self.account_session.account_id:
|
|
85
|
+
return self.account_session.account_id
|
|
86
|
+
return SYSTEM_USER_ID
|
|
87
|
+
|
|
78
88
|
|
|
79
89
|
async def prepare_graphql_params(
|
|
80
90
|
db: InfrahubDatabase,
|
|
@@ -113,6 +123,7 @@ async def prepare_graphql_params(
|
|
|
113
123
|
branch=branch,
|
|
114
124
|
single_relationship_resolver=SingleRelationshipResolver(),
|
|
115
125
|
many_relationship_resolver=ManyRelationshipResolver(),
|
|
126
|
+
account_metadata_resolver=AccountMetadataResolver(),
|
|
116
127
|
at=Timestamp(at),
|
|
117
128
|
types=gqlm.get_graphql_types(),
|
|
118
129
|
related_node_ids=set(),
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
"""DataLoader for resolving account IDs to full account data."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass, field
|
|
6
|
+
from typing import TYPE_CHECKING, Any
|
|
7
|
+
|
|
8
|
+
from aiodataloader import DataLoader
|
|
9
|
+
|
|
10
|
+
from infrahub.core.constants import SYSTEM_USER_ID, InfrahubKind
|
|
11
|
+
from infrahub.core.manager import NodeManager
|
|
12
|
+
from infrahub.graphql.constants import KIND_GRAPHQL_FIELD_NAME
|
|
13
|
+
|
|
14
|
+
if TYPE_CHECKING:
|
|
15
|
+
from infrahub.core.branch.models import Branch
|
|
16
|
+
from infrahub.core.timestamp import Timestamp
|
|
17
|
+
from infrahub.database import InfrahubDatabase
|
|
18
|
+
|
|
19
|
+
SYSTEM_ACCOUNT_DISPLAY_LABEL = "[Infrahub System]"
|
|
20
|
+
UNKNOWN_ACCOUNT_DISPLAY_LABEL = "[Unknown Account]"
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@dataclass
|
|
24
|
+
class AccountLoaderParams:
|
|
25
|
+
branch: Branch
|
|
26
|
+
at: Timestamp | None
|
|
27
|
+
fields: dict[str, Any] = field(default_factory=dict)
|
|
28
|
+
|
|
29
|
+
def __hash__(self) -> int:
|
|
30
|
+
# Fields are not included in hash as they vary per query but we want to reuse loader
|
|
31
|
+
at_str = self.at.to_string() if self.at else ""
|
|
32
|
+
return hash(f"{at_str}|{self.branch.name}")
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class AccountDataLoader(DataLoader[str, dict[str, Any] | None]):
|
|
36
|
+
"""DataLoader for batch-loading account data by ID.
|
|
37
|
+
|
|
38
|
+
Handles SYSTEM_USER_ID specially by returning synthetic system account data.
|
|
39
|
+
All lookups are branch-agnostic since accounts don't vary by branch.
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
def __init__(
|
|
43
|
+
self,
|
|
44
|
+
db: InfrahubDatabase,
|
|
45
|
+
params: AccountLoaderParams,
|
|
46
|
+
*args: Any,
|
|
47
|
+
**kwargs: Any,
|
|
48
|
+
) -> None:
|
|
49
|
+
super().__init__(*args, **kwargs)
|
|
50
|
+
self.db = db
|
|
51
|
+
self.params = params
|
|
52
|
+
|
|
53
|
+
def _build_system_account_response(self, fields: dict[str, Any]) -> dict[str, Any]:
|
|
54
|
+
"""Build response for SYSTEM_USER_ID based on requested fields."""
|
|
55
|
+
# Always include __kind__ for GraphQL interface type resolution
|
|
56
|
+
response: dict[str, Any] = {KIND_GRAPHQL_FIELD_NAME: InfrahubKind.ACCOUNT}
|
|
57
|
+
|
|
58
|
+
for field_name in fields:
|
|
59
|
+
if field_name == "id":
|
|
60
|
+
response["id"] = SYSTEM_USER_ID
|
|
61
|
+
elif field_name == "display_label":
|
|
62
|
+
response["display_label"] = SYSTEM_ACCOUNT_DISPLAY_LABEL
|
|
63
|
+
elif field_name == "__typename":
|
|
64
|
+
response["__typename"] = InfrahubKind.ACCOUNT
|
|
65
|
+
elif field_name == "name":
|
|
66
|
+
response["name"] = {"value": SYSTEM_ACCOUNT_DISPLAY_LABEL}
|
|
67
|
+
elif field_name == "label":
|
|
68
|
+
response["label"] = {"value": SYSTEM_ACCOUNT_DISPLAY_LABEL}
|
|
69
|
+
elif field_name == "description":
|
|
70
|
+
response["description"] = {"value": None}
|
|
71
|
+
else:
|
|
72
|
+
# For any other field, return None
|
|
73
|
+
response[field_name] = None
|
|
74
|
+
|
|
75
|
+
return response
|
|
76
|
+
|
|
77
|
+
def _build_unknown_account_response(self, account_id: str, fields: dict[str, Any]) -> dict[str, Any]:
|
|
78
|
+
"""Build response for an unknown/deleted account based on requested fields."""
|
|
79
|
+
# Always include __kind__ for GraphQL interface type resolution
|
|
80
|
+
response: dict[str, Any] = {KIND_GRAPHQL_FIELD_NAME: InfrahubKind.ACCOUNT}
|
|
81
|
+
|
|
82
|
+
for field_name in fields:
|
|
83
|
+
if field_name == "id":
|
|
84
|
+
response["id"] = account_id
|
|
85
|
+
elif field_name == "display_label":
|
|
86
|
+
response["display_label"] = UNKNOWN_ACCOUNT_DISPLAY_LABEL
|
|
87
|
+
elif field_name == "__typename":
|
|
88
|
+
response["__typename"] = InfrahubKind.ACCOUNT
|
|
89
|
+
elif field_name == "name":
|
|
90
|
+
response["name"] = {"value": UNKNOWN_ACCOUNT_DISPLAY_LABEL}
|
|
91
|
+
elif field_name == "label":
|
|
92
|
+
response["label"] = {"value": UNKNOWN_ACCOUNT_DISPLAY_LABEL}
|
|
93
|
+
elif field_name == "description":
|
|
94
|
+
response["description"] = {"value": None}
|
|
95
|
+
else:
|
|
96
|
+
response[field_name] = None
|
|
97
|
+
|
|
98
|
+
return response
|
|
99
|
+
|
|
100
|
+
async def batch_load_fn(self, keys: list[str]) -> list[dict[str, Any] | None]:
|
|
101
|
+
# Separate system user from real account IDs
|
|
102
|
+
real_account_ids = [k for k in keys if k != SYSTEM_USER_ID]
|
|
103
|
+
|
|
104
|
+
# Batch load real accounts
|
|
105
|
+
accounts_by_id: dict[str, dict[str, Any]] = {}
|
|
106
|
+
if real_account_ids:
|
|
107
|
+
async with self.db.start_session(read_only=True) as db:
|
|
108
|
+
nodes = await NodeManager.get_many(
|
|
109
|
+
db=db,
|
|
110
|
+
ids=real_account_ids,
|
|
111
|
+
fields=self.params.fields,
|
|
112
|
+
at=self.params.at,
|
|
113
|
+
branch=self.params.branch,
|
|
114
|
+
branch_agnostic=True, # Accounts are always branch-agnostic
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
for node_id, node in nodes.items():
|
|
118
|
+
accounts_by_id[node_id] = await node.to_graphql(
|
|
119
|
+
db=db,
|
|
120
|
+
fields=self.params.fields,
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
# Build results in same order as keys
|
|
124
|
+
results: list[dict[str, Any] | None] = []
|
|
125
|
+
for key in keys:
|
|
126
|
+
if key == SYSTEM_USER_ID:
|
|
127
|
+
results.append(self._build_system_account_response(self.params.fields))
|
|
128
|
+
elif key in accounts_by_id:
|
|
129
|
+
results.append(accounts_by_id[key])
|
|
130
|
+
else:
|
|
131
|
+
# Account not found - return placeholder
|
|
132
|
+
results.append(self._build_unknown_account_response(key, self.params.fields))
|
|
133
|
+
|
|
134
|
+
return results
|
infrahub/graphql/loaders/node.py
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
from dataclasses import dataclass
|
|
1
|
+
from dataclasses import dataclass, field
|
|
2
2
|
from typing import Any
|
|
3
3
|
|
|
4
4
|
from aiodataloader import DataLoader
|
|
5
5
|
|
|
6
|
-
from infrahub.auth import AccountSession
|
|
7
6
|
from infrahub.core.branch.models import Branch
|
|
8
7
|
from infrahub.core.manager import NodeManager
|
|
8
|
+
from infrahub.core.metadata.model import MetadataQueryOptions
|
|
9
9
|
from infrahub.core.node import Node
|
|
10
10
|
from infrahub.core.timestamp import Timestamp
|
|
11
11
|
from infrahub.database import InfrahubDatabase
|
|
@@ -18,10 +18,8 @@ class GetManyParams:
|
|
|
18
18
|
branch: Branch | str
|
|
19
19
|
fields: dict | None = None
|
|
20
20
|
at: Timestamp | str | None = None
|
|
21
|
-
|
|
22
|
-
include_owner: bool = False
|
|
21
|
+
include_metadata: MetadataQueryOptions = field(default_factory=MetadataQueryOptions)
|
|
23
22
|
prefetch_relationships: bool = False
|
|
24
|
-
account: AccountSession | None = None
|
|
25
23
|
branch_agnostic: bool = False
|
|
26
24
|
|
|
27
25
|
def __hash__(self) -> int:
|
|
@@ -30,16 +28,13 @@ class GetManyParams:
|
|
|
30
28
|
frozen_fields = to_frozen_set(self.fields)
|
|
31
29
|
timestamp = Timestamp(self.at)
|
|
32
30
|
branch = self.branch.name if isinstance(self.branch, Branch) else self.branch
|
|
33
|
-
account_id = self.account.account_id if isinstance(self.account, AccountSession) else None
|
|
34
31
|
hash_str = "|".join(
|
|
35
32
|
[
|
|
36
33
|
str(hash(frozen_fields)),
|
|
37
34
|
timestamp.to_string(),
|
|
38
35
|
branch,
|
|
39
|
-
str(self.
|
|
40
|
-
str(self.include_owner),
|
|
36
|
+
str(hash(self.include_metadata)),
|
|
41
37
|
str(self.prefetch_relationships),
|
|
42
|
-
str(account_id),
|
|
43
38
|
str(self.branch_agnostic),
|
|
44
39
|
]
|
|
45
40
|
)
|
|
@@ -60,10 +55,8 @@ class NodeDataLoader(DataLoader[str, Node | None]):
|
|
|
60
55
|
fields=self.query_params.fields,
|
|
61
56
|
at=self.query_params.at,
|
|
62
57
|
branch=self.query_params.branch,
|
|
63
|
-
|
|
64
|
-
include_owner=self.query_params.include_owner,
|
|
58
|
+
include_metadata=self.query_params.include_metadata,
|
|
65
59
|
prefetch_relationships=self.query_params.prefetch_relationships,
|
|
66
|
-
account=self.query_params.account,
|
|
67
60
|
branch_agnostic=self.query_params.branch_agnostic,
|
|
68
61
|
)
|
|
69
62
|
results = []
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
from dataclasses import dataclass
|
|
1
|
+
from dataclasses import dataclass, field
|
|
2
2
|
from typing import Any
|
|
3
3
|
|
|
4
4
|
from aiodataloader import DataLoader
|
|
5
5
|
|
|
6
6
|
from infrahub.core.branch.models import Branch
|
|
7
7
|
from infrahub.core.manager import NodeManager
|
|
8
|
+
from infrahub.core.metadata.model import MetadataQueryOptions
|
|
8
9
|
from infrahub.core.relationship.model import Relationship
|
|
9
10
|
from infrahub.core.schema.relationship_schema import RelationshipSchema
|
|
10
11
|
from infrahub.core.timestamp import Timestamp
|
|
@@ -22,8 +23,7 @@ class QueryPeerParams:
|
|
|
22
23
|
fields: dict | None = None
|
|
23
24
|
at: Timestamp | str | None = None
|
|
24
25
|
branch_agnostic: bool = False
|
|
25
|
-
|
|
26
|
-
include_owner: bool = False
|
|
26
|
+
include_metadata: MetadataQueryOptions = field(default_factory=MetadataQueryOptions)
|
|
27
27
|
|
|
28
28
|
def __hash__(self) -> int:
|
|
29
29
|
frozen_fields: frozenset | None = None
|
|
@@ -41,8 +41,7 @@ class QueryPeerParams:
|
|
|
41
41
|
self.schema.name,
|
|
42
42
|
str(self.source_kind),
|
|
43
43
|
str(self.branch_agnostic),
|
|
44
|
-
str(self.
|
|
45
|
-
str(self.include_owner),
|
|
44
|
+
str(hash(self.include_metadata)),
|
|
46
45
|
]
|
|
47
46
|
)
|
|
48
47
|
return hash(hash_str)
|
|
@@ -66,9 +65,8 @@ class PeerRelationshipsDataLoader(DataLoader[str, list[Relationship]]):
|
|
|
66
65
|
at=self.query_params.at,
|
|
67
66
|
branch=self.query_params.branch,
|
|
68
67
|
branch_agnostic=self.query_params.branch_agnostic,
|
|
68
|
+
include_metadata=self.query_params.include_metadata,
|
|
69
69
|
fetch_peers=True,
|
|
70
|
-
include_source=self.query_params.include_source,
|
|
71
|
-
include_owner=self.query_params.include_owner,
|
|
72
70
|
)
|
|
73
71
|
peer_rels_by_node_id: dict[str, list[Relationship]] = {}
|
|
74
72
|
for rel in peer_rels:
|