infrahub-server 1.5.5__py3-none-any.whl → 1.6.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.
Files changed (100) hide show
  1. infrahub/api/artifact.py +5 -3
  2. infrahub/auth.py +5 -6
  3. infrahub/cli/db.py +3 -3
  4. infrahub/cli/db_commands/clean_duplicate_schema_fields.py +2 -2
  5. infrahub/cli/dev.py +30 -0
  6. infrahub/config.py +62 -14
  7. infrahub/constants/database.py +5 -5
  8. infrahub/core/branch/models.py +24 -6
  9. infrahub/core/diff/model/diff.py +2 -2
  10. infrahub/core/graph/constraints.py +2 -2
  11. infrahub/core/manager.py +155 -29
  12. infrahub/core/merge.py +29 -2
  13. infrahub/core/migrations/graph/m041_deleted_dup_edges.py +2 -3
  14. infrahub/core/migrations/shared.py +2 -2
  15. infrahub/core/node/__init__.py +1 -1
  16. infrahub/core/node/ipam.py +4 -4
  17. infrahub/core/node/node_property_attribute.py +2 -2
  18. infrahub/core/protocols.py +7 -1
  19. infrahub/core/query/branch.py +11 -0
  20. infrahub/core/query/standard_node.py +3 -0
  21. infrahub/core/relationship/model.py +3 -9
  22. infrahub/core/schema/__init__.py +3 -3
  23. infrahub/core/task/user_task.py +2 -2
  24. infrahub/core/validators/enum.py +2 -2
  25. infrahub/dependencies/interface.py +2 -2
  26. infrahub/events/constants.py +2 -2
  27. infrahub/git/base.py +43 -1
  28. infrahub/git/models.py +2 -1
  29. infrahub/git/repository.py +5 -1
  30. infrahub/git/tasks.py +28 -1
  31. infrahub/git/utils.py +9 -0
  32. infrahub/graphql/analyzer.py +4 -4
  33. infrahub/graphql/mutations/computed_attribute.py +1 -1
  34. infrahub/graphql/mutations/convert_object_type.py +1 -1
  35. infrahub/graphql/mutations/display_label.py +1 -1
  36. infrahub/graphql/mutations/hfid.py +1 -1
  37. infrahub/graphql/mutations/ipam.py +1 -1
  38. infrahub/graphql/mutations/profile.py +1 -0
  39. infrahub/graphql/mutations/relationship.py +2 -2
  40. infrahub/graphql/mutations/resource_manager.py +1 -1
  41. infrahub/graphql/queries/__init__.py +2 -1
  42. infrahub/graphql/queries/branch.py +58 -3
  43. infrahub/graphql/queries/ipam.py +9 -4
  44. infrahub/graphql/queries/resource_manager.py +5 -8
  45. infrahub/graphql/queries/search.py +3 -3
  46. infrahub/graphql/schema.py +2 -0
  47. infrahub/graphql/types/__init__.py +3 -1
  48. infrahub/graphql/types/branch.py +98 -2
  49. infrahub/lock.py +6 -6
  50. infrahub/patch/constants.py +2 -2
  51. infrahub/task_manager/task.py +2 -2
  52. infrahub/telemetry/constants.py +2 -2
  53. infrahub/trigger/models.py +2 -2
  54. infrahub/utils.py +1 -1
  55. infrahub/validators/tasks.py +1 -1
  56. infrahub/workers/infrahub_async.py +37 -0
  57. infrahub_sdk/async_typer.py +2 -1
  58. infrahub_sdk/batch.py +2 -2
  59. infrahub_sdk/client.py +8 -9
  60. infrahub_sdk/config.py +2 -2
  61. infrahub_sdk/ctl/branch.py +1 -1
  62. infrahub_sdk/ctl/cli.py +2 -2
  63. infrahub_sdk/ctl/cli_commands.py +2 -1
  64. infrahub_sdk/ctl/graphql.py +2 -2
  65. infrahub_sdk/ctl/importer.py +1 -1
  66. infrahub_sdk/ctl/utils.py +3 -3
  67. infrahub_sdk/node/attribute.py +11 -10
  68. infrahub_sdk/node/constants.py +1 -2
  69. infrahub_sdk/node/node.py +54 -11
  70. infrahub_sdk/node/related_node.py +1 -1
  71. infrahub_sdk/object_store.py +4 -4
  72. infrahub_sdk/operation.py +2 -2
  73. infrahub_sdk/protocols_generator/generator.py +1 -1
  74. infrahub_sdk/pytest_plugin/items/jinja2_transform.py +1 -1
  75. infrahub_sdk/pytest_plugin/models.py +1 -1
  76. infrahub_sdk/pytest_plugin/plugin.py +1 -1
  77. infrahub_sdk/query_groups.py +2 -2
  78. infrahub_sdk/schema/__init__.py +10 -11
  79. infrahub_sdk/schema/main.py +2 -2
  80. infrahub_sdk/schema/repository.py +2 -2
  81. infrahub_sdk/spec/object.py +2 -2
  82. infrahub_sdk/spec/range_expansion.py +1 -1
  83. infrahub_sdk/template/__init__.py +2 -1
  84. infrahub_sdk/transfer/importer/json.py +3 -3
  85. infrahub_sdk/types.py +2 -2
  86. infrahub_sdk/utils.py +2 -2
  87. {infrahub_server-1.5.5.dist-info → infrahub_server-1.6.0b0.dist-info}/METADATA +58 -59
  88. {infrahub_server-1.5.5.dist-info → infrahub_server-1.6.0b0.dist-info}/RECORD +217 -223
  89. {infrahub_server-1.5.5.dist-info → infrahub_server-1.6.0b0.dist-info}/WHEEL +1 -1
  90. infrahub_server-1.6.0b0.dist-info/entry_points.txt +12 -0
  91. infrahub_testcontainers/docker-compose-cluster.test.yml +1 -1
  92. infrahub_testcontainers/docker-compose.test.yml +1 -1
  93. infrahub/core/schema/generated/__init__.py +0 -0
  94. infrahub/core/schema/generated/attribute_schema.py +0 -133
  95. infrahub/core/schema/generated/base_node_schema.py +0 -111
  96. infrahub/core/schema/generated/genericnode_schema.py +0 -30
  97. infrahub/core/schema/generated/node_schema.py +0 -40
  98. infrahub/core/schema/generated/relationship_schema.py +0 -141
  99. infrahub_server-1.5.5.dist-info/entry_points.txt +0 -13
  100. {infrahub_server-1.5.5.dist-info → infrahub_server-1.6.0b0.dist-info/licenses}/LICENSE.txt +0 -0
infrahub/core/manager.py CHANGED
@@ -59,7 +59,7 @@ def identify_node_class(node: NodeToProcess) -> type[Node]:
59
59
  return Node
60
60
 
61
61
 
62
- def get_schema(
62
+ def get_schema[SchemaProtocol](
63
63
  db: InfrahubDatabase,
64
64
  branch: Branch,
65
65
  node_schema: type[SchemaProtocol] | MainSchemaTypes | str,
@@ -455,7 +455,7 @@ class NodeManager:
455
455
  branch: Branch | str | None = ...,
456
456
  id: str | None = ...,
457
457
  hfid: list[str] | None = ...,
458
- ) -> Any: ...
458
+ ) -> Node: ...
459
459
 
460
460
  @classmethod
461
461
  async def find_object(
@@ -466,10 +466,7 @@ class NodeManager:
466
466
  branch: Branch | str | None = None,
467
467
  id: str | None = None,
468
468
  hfid: list[str] | None = None,
469
- ) -> Any:
470
- if not id and not hfid:
471
- raise ProcessingError(message="either id or hfid must be provided.")
472
-
469
+ ) -> Node | SchemaProtocol:
473
470
  if id and is_valid_uuid(id):
474
471
  return await cls.get_one(
475
472
  db=db,
@@ -494,16 +491,19 @@ class NodeManager:
494
491
  raise_on_error=True,
495
492
  )
496
493
 
497
- return await cls.get_one_by_default_filter(
498
- db=db,
499
- kind=kind,
500
- id=id,
501
- branch=branch,
502
- at=at,
503
- include_owner=True,
504
- include_source=True,
505
- raise_on_error=True,
506
- )
494
+ if id:
495
+ return await cls.get_one_by_default_filter(
496
+ db=db,
497
+ kind=kind,
498
+ id=id,
499
+ branch=branch,
500
+ at=at,
501
+ include_owner=True,
502
+ include_source=True,
503
+ raise_on_error=True,
504
+ )
505
+
506
+ raise ProcessingError(message="either id or hfid must be provided.")
507
507
 
508
508
  @overload
509
509
  @classmethod
@@ -557,7 +557,43 @@ class NodeManager:
557
557
  prefetch_relationships: bool = ...,
558
558
  account=...,
559
559
  branch_agnostic: bool = ...,
560
- ) -> SchemaProtocol: ...
560
+ ) -> SchemaProtocol | None: ...
561
+
562
+ @overload
563
+ @classmethod
564
+ async def get_one_by_default_filter(
565
+ cls,
566
+ db: InfrahubDatabase,
567
+ id: str,
568
+ kind: str,
569
+ raise_on_error: Literal[False] = ...,
570
+ fields: dict | None = ...,
571
+ at: Timestamp | str | None = ...,
572
+ branch: Branch | str | None = ...,
573
+ include_source: bool = ...,
574
+ include_owner: bool = ...,
575
+ prefetch_relationships: bool = ...,
576
+ account=...,
577
+ branch_agnostic: bool = ...,
578
+ ) -> Node | None: ...
579
+
580
+ @overload
581
+ @classmethod
582
+ async def get_one_by_default_filter(
583
+ cls,
584
+ db: InfrahubDatabase,
585
+ id: str,
586
+ kind: str,
587
+ raise_on_error: Literal[True] = ...,
588
+ fields: dict | None = ...,
589
+ at: Timestamp | str | None = ...,
590
+ branch: Branch | str | None = ...,
591
+ include_source: bool = ...,
592
+ include_owner: bool = ...,
593
+ prefetch_relationships: bool = ...,
594
+ account=...,
595
+ branch_agnostic: bool = ...,
596
+ ) -> Node: ...
561
597
 
562
598
  @overload
563
599
  @classmethod
@@ -575,7 +611,7 @@ class NodeManager:
575
611
  prefetch_relationships: bool = ...,
576
612
  account=...,
577
613
  branch_agnostic: bool = ...,
578
- ) -> Any: ...
614
+ ) -> Node | None: ...
579
615
 
580
616
  @classmethod
581
617
  async def get_one_by_default_filter(
@@ -592,7 +628,7 @@ class NodeManager:
592
628
  prefetch_relationships: bool = False,
593
629
  account=None,
594
630
  branch_agnostic: bool = False,
595
- ) -> Any:
631
+ ) -> Node | SchemaProtocol | None:
596
632
  branch = await registry.get_branch(branch=branch, db=db)
597
633
  at = Timestamp(at)
598
634
 
@@ -688,7 +724,7 @@ class NodeManager:
688
724
  prefetch_relationships: bool = ...,
689
725
  account=...,
690
726
  branch_agnostic: bool = ...,
691
- ) -> SchemaProtocol: ...
727
+ ) -> SchemaProtocol | None: ...
692
728
 
693
729
  @overload
694
730
  @classmethod
@@ -706,7 +742,25 @@ class NodeManager:
706
742
  prefetch_relationships: bool = ...,
707
743
  account=...,
708
744
  branch_agnostic: bool = ...,
709
- ) -> Any: ...
745
+ ) -> Node: ...
746
+
747
+ @overload
748
+ @classmethod
749
+ async def get_one_by_hfid(
750
+ cls,
751
+ db: InfrahubDatabase,
752
+ hfid: list[str],
753
+ kind: str,
754
+ raise_on_error: Literal[False],
755
+ fields: dict | None = ...,
756
+ at: Timestamp | str | None = ...,
757
+ branch: Branch | str | None = ...,
758
+ include_source: bool = ...,
759
+ include_owner: bool = ...,
760
+ prefetch_relationships: bool = ...,
761
+ account=...,
762
+ branch_agnostic: bool = ...,
763
+ ) -> Node | None: ...
710
764
 
711
765
  @overload
712
766
  @classmethod
@@ -724,7 +778,7 @@ class NodeManager:
724
778
  prefetch_relationships: bool = ...,
725
779
  account=...,
726
780
  branch_agnostic: bool = ...,
727
- ) -> Any: ...
781
+ ) -> Node | None: ...
728
782
 
729
783
  @classmethod
730
784
  async def get_one_by_hfid(
@@ -741,7 +795,7 @@ class NodeManager:
741
795
  prefetch_relationships: bool = False,
742
796
  account=None,
743
797
  branch_agnostic: bool = False,
744
- ) -> Any:
798
+ ) -> Node | SchemaProtocol | None:
745
799
  branch = await registry.get_branch(branch=branch, db=db)
746
800
  at = Timestamp(at)
747
801
 
@@ -770,14 +824,14 @@ class NodeManager:
770
824
  for key, item in zip(node_schema.human_friendly_id, hfid, strict=False):
771
825
  path = node_schema.parse_schema_path(path=key, schema=registry.schema.get_schema_branch(name=branch.name))
772
826
 
773
- if path.is_type_relationship:
827
+ if path.is_type_relationship and path.related_schema:
774
828
  rel_schema = path.related_schema
775
829
  # Keep the relationship attribute path and parse it
776
830
  path = rel_schema.parse_schema_path(
777
831
  path=key.split("__", maxsplit=1)[1], schema=registry.schema.get_schema_branch(name=branch.name)
778
832
  )
779
833
 
780
- filters[key] = path.attribute_schema.get_class().deserialize_from_string(item)
834
+ filters[key] = path.active_attribute_schema.get_class().deserialize_from_string(item)
781
835
 
782
836
  items = await NodeManager.query(
783
837
  db=db,
@@ -948,6 +1002,42 @@ class NodeManager:
948
1002
  branch_agnostic: bool = ...,
949
1003
  ) -> SchemaProtocol: ...
950
1004
 
1005
+ @overload
1006
+ @classmethod
1007
+ async def get_one(
1008
+ cls,
1009
+ id: str,
1010
+ db: InfrahubDatabase,
1011
+ kind: str,
1012
+ raise_on_error: Literal[True] = ...,
1013
+ fields: dict | None = ...,
1014
+ at: Timestamp | str | None = ...,
1015
+ branch: Branch | str | None = ...,
1016
+ include_source: bool = ...,
1017
+ include_owner: bool = ...,
1018
+ prefetch_relationships: bool = ...,
1019
+ account=...,
1020
+ branch_agnostic: bool = ...,
1021
+ ) -> Node: ...
1022
+
1023
+ @overload
1024
+ @classmethod
1025
+ async def get_one(
1026
+ cls,
1027
+ id: str,
1028
+ db: InfrahubDatabase,
1029
+ kind: str,
1030
+ raise_on_error: Literal[False] = ...,
1031
+ fields: dict | None = ...,
1032
+ at: Timestamp | str | None = ...,
1033
+ branch: Branch | str | None = ...,
1034
+ include_source: bool = ...,
1035
+ include_owner: bool = ...,
1036
+ prefetch_relationships: bool = ...,
1037
+ account=...,
1038
+ branch_agnostic: bool = ...,
1039
+ ) -> Node | None: ...
1040
+
951
1041
  @overload
952
1042
  @classmethod
953
1043
  async def get_one(
@@ -964,7 +1054,43 @@ class NodeManager:
964
1054
  prefetch_relationships: bool = ...,
965
1055
  account=...,
966
1056
  branch_agnostic: bool = ...,
967
- ) -> Any: ...
1057
+ ) -> Node | None: ...
1058
+
1059
+ @overload
1060
+ @classmethod
1061
+ async def get_one(
1062
+ cls,
1063
+ id: str,
1064
+ db: InfrahubDatabase,
1065
+ kind: None = ...,
1066
+ raise_on_error: Literal[True] = ...,
1067
+ fields: dict | None = ...,
1068
+ at: Timestamp | str | None = ...,
1069
+ branch: Branch | str | None = ...,
1070
+ include_source: bool = ...,
1071
+ include_owner: bool = ...,
1072
+ prefetch_relationships: bool = ...,
1073
+ account=...,
1074
+ branch_agnostic: bool = ...,
1075
+ ) -> Node: ...
1076
+
1077
+ @overload
1078
+ @classmethod
1079
+ async def get_one(
1080
+ cls,
1081
+ id: str,
1082
+ db: InfrahubDatabase,
1083
+ kind: None = ...,
1084
+ raise_on_error: Literal[False] = ...,
1085
+ fields: dict | None = ...,
1086
+ at: Timestamp | str | None = ...,
1087
+ branch: Branch | str | None = ...,
1088
+ include_source: bool = ...,
1089
+ include_owner: bool = ...,
1090
+ prefetch_relationships: bool = ...,
1091
+ account=...,
1092
+ branch_agnostic: bool = ...,
1093
+ ) -> Node | None: ...
968
1094
 
969
1095
  @overload
970
1096
  @classmethod
@@ -982,7 +1108,7 @@ class NodeManager:
982
1108
  prefetch_relationships: bool = ...,
983
1109
  account=...,
984
1110
  branch_agnostic: bool = ...,
985
- ) -> Any: ...
1111
+ ) -> Node | None: ...
986
1112
 
987
1113
  @classmethod
988
1114
  async def get_one(
@@ -999,7 +1125,7 @@ class NodeManager:
999
1125
  prefetch_relationships: bool = False,
1000
1126
  account=None,
1001
1127
  branch_agnostic: bool = False,
1002
- ) -> Any | None:
1128
+ ) -> Node | SchemaProtocol | None:
1003
1129
  """Return one node based on its ID."""
1004
1130
  branch = await registry.get_branch(branch=branch, db=db)
1005
1131
 
@@ -1264,7 +1390,7 @@ class NodeManager:
1264
1390
  db: InfrahubDatabase,
1265
1391
  nodes: list[Node],
1266
1392
  branch: Branch | str | None = None,
1267
- at: Timestamp | str | None = None,
1393
+ at: Timestamp | None = None,
1268
1394
  cascade_delete: bool = True,
1269
1395
  ) -> list[Node]:
1270
1396
  """Returns list of deleted nodes because of cascading deletes"""
infrahub/core/merge.py CHANGED
@@ -2,11 +2,11 @@ from __future__ import annotations
2
2
 
3
3
  from typing import TYPE_CHECKING
4
4
 
5
- from infrahub.core.constants import RepositoryInternalStatus
5
+ from infrahub.core.constants import InfrahubKind, RepositoryInternalStatus
6
6
  from infrahub.core.diff.model.path import BranchTrackingId
7
7
  from infrahub.core.manager import NodeManager
8
8
  from infrahub.core.models import SchemaUpdateValidationResult
9
- from infrahub.core.protocols import CoreRepository
9
+ from infrahub.core.protocols import CoreReadOnlyRepository, CoreRepository
10
10
  from infrahub.core.registry import registry
11
11
  from infrahub.core.timestamp import Timestamp
12
12
  from infrahub.exceptions import MergeFailedError, ValidationError
@@ -223,6 +223,32 @@ class BranchMerger:
223
223
  await self.diff_merger.rollback(at=self._merge_at)
224
224
 
225
225
  async def merge_repositories(self) -> None:
226
+ await self.merge_core_read_only_repositories()
227
+ await self.merge_core_repositories()
228
+
229
+ async def merge_core_read_only_repositories(self) -> None:
230
+ repos_in_main_list = await NodeManager.query(schema=CoreReadOnlyRepository, db=self.db)
231
+ repos_in_main = {repo.id: repo for repo in repos_in_main_list}
232
+
233
+ repos_in_branch_list = await NodeManager.query(
234
+ schema=CoreReadOnlyRepository, db=self.db, branch=self.source_branch
235
+ )
236
+ for repo in repos_in_branch_list:
237
+ if repo.id not in repos_in_main:
238
+ continue
239
+
240
+ model = GitRepositoryMerge(
241
+ repository_id=repo.id,
242
+ repository_name=repo.name.value,
243
+ source_branch=self.source_branch.name,
244
+ destination_branch=self.destination_branch.name,
245
+ destination_branch_id=str(self.destination_branch.get_uuid()),
246
+ internal_status=repo.internal_status.value,
247
+ repository_kind=InfrahubKind.READONLYREPOSITORY,
248
+ )
249
+ await self.workflow.submit_workflow(workflow=GIT_REPOSITORIES_MERGE, parameters={"model": model})
250
+
251
+ async def merge_core_repositories(self) -> None:
226
252
  # Collect all Repositories in Main because we'll need the commit in Main for each one.
227
253
  repos_in_main_list = await NodeManager.query(schema=CoreRepository, db=self.db)
228
254
  repos_in_main = {repo.id: repo for repo in repos_in_main_list}
@@ -245,5 +271,6 @@ class BranchMerger:
245
271
  destination_branch=self.destination_branch.name,
246
272
  destination_branch_id=str(self.destination_branch.get_uuid()),
247
273
  default_branch=repo.default_branch.value,
274
+ repository_kind=InfrahubKind.REPOSITORY,
248
275
  )
249
276
  await self.workflow.submit_workflow(workflow=GIT_REPOSITORIES_MERGE, parameters={"model": model})
@@ -87,15 +87,14 @@ CALL (node_uuid) {
87
87
  // ------------
88
88
  MATCH (n:Node {uuid: node_uuid})-[:IS_RELATED]-(rel:Relationship)
89
89
  WITH DISTINCT rel
90
- MATCH (rel)-[e]-(peer)
90
+ MATCH (rel)-[e]->(peer)
91
91
  WITH
92
- elementId(rel) AS rel_element_id,
93
92
  type(e) AS e_type,
94
93
  e.branch AS e_branch,
95
94
  e.from AS e_from,
96
95
  e.to AS e_to,
97
96
  e.status AS e_status,
98
- elementId(peer) AS peer_element_id,
97
+ e.peer AS e_peer,
99
98
  CASE
100
99
  WHEN startNode(e) = rel THEN "out" ELSE "in"
101
100
  END AS direction,
@@ -1,6 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
- from typing import TYPE_CHECKING, Any, Sequence, TypeAlias
3
+ from typing import TYPE_CHECKING, Any, Sequence
4
4
 
5
5
  from pydantic import BaseModel, ConfigDict, Field
6
6
  from rich.console import Console
@@ -261,4 +261,4 @@ class MigrationRequiringRebase(BaseModel):
261
261
  raise NotImplementedError()
262
262
 
263
263
 
264
- MigrationTypes: TypeAlias = GraphMigration | InternalSchemaMigration | ArbitraryMigration | MigrationRequiringRebase
264
+ type MigrationTypes = GraphMigration | InternalSchemaMigration | ArbitraryMigration | MigrationRequiringRebase
@@ -1088,7 +1088,7 @@ class Node(BaseNode, metaclass=BaseNodeMeta):
1088
1088
 
1089
1089
  if key in self._relationships:
1090
1090
  rel: RelationshipManager = getattr(self, key)
1091
- changed |= await rel.update(db=db, data=value, process_delete=process_pools)
1091
+ changed |= await rel.update(db=db, data=value)
1092
1092
 
1093
1093
  return changed
1094
1094
 
@@ -40,8 +40,8 @@ class BuiltinIPPrefix(Node):
40
40
  retrieved = await NodeManager.get_one(
41
41
  db=db, branch=self._branch, id=self.id, fields={"member_type": None, "prefix": None}
42
42
  )
43
- self.member_type = retrieved.member_type # type: ignore[union-attr]
44
- self.prefix = retrieved.prefix # type: ignore[union-attr]
43
+ self.member_type = retrieved.member_type # type: ignore[attr-defined,union-attr]
44
+ self.prefix = retrieved.prefix # type: ignore[attr-defined,union-attr]
45
45
  utilization_getter = PrefixUtilizationGetter(db=db, ip_prefixes=[self])
46
46
  utilization = await utilization_getter.get_use_percentage(
47
47
  ip_prefixes=[self], branch_names=[self._branch.name]
@@ -57,6 +57,6 @@ class BuiltinIPPrefix(Node):
57
57
  retrieved = await NodeManager.get_one(
58
58
  db=db, branch=self._branch, id=self.id, fields={"member_type": None, "prefix": None}
59
59
  )
60
- self.member_type = retrieved.member_type # type: ignore[union-attr]
61
- self.prefix = retrieved.prefix # type: ignore[union-attr]
60
+ self.member_type = retrieved.member_type # type: ignore[attr-defined,union-attr]
61
+ self.prefix = retrieved.prefix # type: ignore[attr-defined,union-attr]
62
62
  return get_prefix_space(self)
@@ -2,7 +2,7 @@ from __future__ import annotations
2
2
 
3
3
  from abc import abstractmethod
4
4
  from enum import Enum
5
- from typing import TYPE_CHECKING, Any, Generic, TypeVar
5
+ from typing import TYPE_CHECKING, Any, TypeVar
6
6
 
7
7
  from infrahub_sdk.template import Jinja2Template
8
8
 
@@ -21,7 +21,7 @@ if TYPE_CHECKING:
21
21
  T = TypeVar("T")
22
22
 
23
23
 
24
- class NodePropertyAttribute(Generic[T]):
24
+ class NodePropertyAttribute[T]:
25
25
  """A node property attribute is a construct that seats between a property and an attribute.
26
26
 
27
27
  View it as a property, set at the node level but stored in the database as an attribute. It usually is something computed from other components of
@@ -2,7 +2,7 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- from typing import TYPE_CHECKING
5
+ from typing import TYPE_CHECKING, Any, Optional, Protocol, runtime_checkable
6
6
 
7
7
  from infrahub.core.protocols_base import CoreNode
8
8
 
@@ -16,16 +16,22 @@ if TYPE_CHECKING:
16
16
  DateTime,
17
17
  DateTimeOptional,
18
18
  Dropdown,
19
+ DropdownOptional,
19
20
  HashedPassword,
21
+ HashedPasswordOptional,
20
22
  Integer,
21
23
  IntegerOptional,
22
24
  IPHost,
25
+ IPHostOptional,
23
26
  IPNetwork,
27
+ IPNetworkOptional,
24
28
  JSONAttribute,
25
29
  JSONAttributeOptional,
30
+ ListAttribute,
26
31
  ListAttributeOptional,
27
32
  String,
28
33
  StringOptional,
34
+ URLOptional,
29
35
  )
30
36
  from infrahub.core.relationship import RelationshipManager
31
37
 
@@ -3,8 +3,10 @@ from __future__ import annotations
3
3
  from typing import TYPE_CHECKING, Any
4
4
 
5
5
  from infrahub import config
6
+ from infrahub.core.branch.enums import BranchStatus
6
7
  from infrahub.core.constants import GLOBAL_BRANCH_NAME
7
8
  from infrahub.core.query import Query, QueryType
9
+ from infrahub.core.query.standard_node import StandardNodeGetListQuery
8
10
 
9
11
  if TYPE_CHECKING:
10
12
  from infrahub.database import InfrahubDatabase
@@ -146,3 +148,12 @@ class RebaseBranchDeleteRelationshipQuery(Query):
146
148
  self.add_to_query(query=query)
147
149
 
148
150
  self.params["ids"] = [db.to_database_id(id) for id in self.ids]
151
+
152
+
153
+ class BranchNodeGetListQuery(StandardNodeGetListQuery):
154
+ def __init__(self, exclude_global: bool = False, **kwargs: Any) -> None:
155
+ self.raw_filter = f"n.status <> '{BranchStatus.DELETING.value}'"
156
+ if exclude_global:
157
+ self.raw_filter += f" AND n.name <> '{GLOBAL_BRANCH_NAME}'"
158
+
159
+ super().__init__(**kwargs)
@@ -132,6 +132,7 @@ class StandardNodeGetItemQuery(Query):
132
132
  class StandardNodeGetListQuery(Query):
133
133
  name = "standard_node_list"
134
134
  type = QueryType.READ
135
+ raw_filter: str | None = None
135
136
 
136
137
  def __init__(
137
138
  self, node_class: StandardNode, ids: list[str] | None = None, node_name: str | None = None, **kwargs: Any
@@ -150,6 +151,8 @@ class StandardNodeGetListQuery(Query):
150
151
  if self.node_name:
151
152
  filters.append("n.name = $name")
152
153
  self.params["name"] = self.node_name
154
+ if self.raw_filter:
155
+ filters.append(self.raw_filter)
153
156
 
154
157
  where = ""
155
158
  if filters:
@@ -1061,12 +1061,7 @@ class RelationshipManager:
1061
1061
 
1062
1062
  return self._relationships.as_list()
1063
1063
 
1064
- async def update(
1065
- self,
1066
- data: list[str | Node] | dict[str, Any] | str | Node | None,
1067
- db: InfrahubDatabase,
1068
- process_delete: bool = True,
1069
- ) -> bool:
1064
+ async def update(self, data: list[str | Node] | dict[str, Any] | str | Node | None, db: InfrahubDatabase) -> bool:
1070
1065
  """Replace and Update the list of relationships with this one."""
1071
1066
  if not isinstance(data, list):
1072
1067
  list_data: Sequence[str | Node | dict[str, Any] | None] = [data]
@@ -1092,9 +1087,8 @@ class RelationshipManager:
1092
1087
 
1093
1088
  if item is None:
1094
1089
  if previous_relationships:
1095
- if process_delete:
1096
- for rel in previous_relationships.values():
1097
- await rel.delete(db=db)
1090
+ for rel in previous_relationships.values():
1091
+ await rel.delete(db=db)
1098
1092
  changed = True
1099
1093
  continue
1100
1094
 
@@ -2,7 +2,7 @@ from __future__ import annotations
2
2
 
3
3
  import uuid
4
4
  from enum import Enum
5
- from typing import Any, TypeAlias
5
+ from typing import Any
6
6
 
7
7
  from infrahub_sdk.utils import deep_merge_dict
8
8
  from pydantic import BaseModel, ConfigDict, Field
@@ -22,8 +22,8 @@ from .profile_schema import ProfileSchema
22
22
  from .relationship_schema import RelationshipSchema
23
23
  from .template_schema import TemplateSchema
24
24
 
25
- NonGenericSchemaTypes: TypeAlias = NodeSchema | ProfileSchema | TemplateSchema
26
- MainSchemaTypes: TypeAlias = NonGenericSchemaTypes | GenericSchema
25
+ NonGenericSchemaTypes = NodeSchema | ProfileSchema | TemplateSchema
26
+ MainSchemaTypes = NonGenericSchemaTypes | GenericSchema
27
27
 
28
28
 
29
29
  # -----------------------------------------------------
@@ -6,6 +6,7 @@ from typing_extensions import Self
6
6
 
7
7
  from infrahub.core import registry
8
8
  from infrahub.core.constants import Severity, TaskConclusion
9
+ from infrahub.core.protocols import CoreGenericAccount
9
10
  from infrahub.log import get_logger
10
11
 
11
12
  from .task import Task
@@ -16,7 +17,6 @@ if TYPE_CHECKING:
16
17
 
17
18
  from structlog.stdlib import BoundLogger
18
19
 
19
- from infrahub.core.protocols import CoreGenericAccount
20
20
  from infrahub.database import InfrahubDatabase
21
21
  from infrahub.graphql.initialization import GraphqlContext
22
22
  from infrahub.services.protocols import InfrahubLogger
@@ -67,7 +67,7 @@ class UserTask:
67
67
  if self._account:
68
68
  return False
69
69
 
70
- account: CoreGenericAccount | None = await registry.manager.get_one(id=self.account_id, db=self.db)
70
+ account = await registry.manager.get_one(id=self.account_id, db=self.db, kind=CoreGenericAccount)
71
71
  if not account:
72
72
  raise ValueError(f"Unable to find the account associated with {self.account_id}")
73
73
  self._account = account
@@ -1,7 +1,7 @@
1
- from enum import Enum
1
+ from enum import StrEnum
2
2
 
3
3
 
4
- class ConstraintIdentifier(str, Enum):
4
+ class ConstraintIdentifier(StrEnum):
5
5
  ATTRIBUTE_PARAMETERS_REGEX_UPDATE = "attribute.parameters.regex.update"
6
6
  ATTRIBUTE_PARAMETERS_MIN_LENGTH_UPDATE = "attribute.parameters.min_length.update"
7
7
  ATTRIBUTE_PARAMETERS_MAX_LENGTH_UPDATE = "attribute.parameters.max_length.update"
@@ -1,6 +1,6 @@
1
1
  from abc import ABC, abstractmethod
2
2
  from dataclasses import dataclass
3
- from typing import Generic, TypeVar
3
+ from typing import TypeVar
4
4
 
5
5
  from infrahub.core.branch import Branch
6
6
  from infrahub.database import InfrahubDatabase
@@ -14,7 +14,7 @@ class DependencyBuilderContext:
14
14
  branch: Branch
15
15
 
16
16
 
17
- class DependencyBuilder(ABC, Generic[T]):
17
+ class DependencyBuilder[T](ABC):
18
18
  @classmethod
19
19
  @abstractmethod
20
20
  def build(cls, context: DependencyBuilderContext) -> T: ...
@@ -1,8 +1,8 @@
1
- from enum import Enum
1
+ from enum import StrEnum
2
2
 
3
3
  EVENT_NAMESPACE = "infrahub"
4
4
 
5
5
 
6
- class EventSortOrder(str, Enum):
6
+ class EventSortOrder(StrEnum):
7
7
  ASC = "asc"
8
8
  DESC = "desc"