infrahub-server 1.7.0b0__py3-none-any.whl → 1.7.1__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 (177) hide show
  1. infrahub/api/exceptions.py +2 -2
  2. infrahub/api/schema.py +5 -0
  3. infrahub/cli/db.py +54 -24
  4. infrahub/core/account.py +12 -9
  5. infrahub/core/branch/models.py +11 -117
  6. infrahub/core/branch/tasks.py +7 -3
  7. infrahub/core/diff/branch_differ.py +1 -1
  8. infrahub/core/diff/conflict_transferer.py +1 -1
  9. infrahub/core/diff/data_check_synchronizer.py +1 -1
  10. infrahub/core/diff/enricher/cardinality_one.py +1 -1
  11. infrahub/core/diff/enricher/hierarchy.py +1 -1
  12. infrahub/core/diff/enricher/labels.py +1 -1
  13. infrahub/core/diff/merger/merger.py +6 -2
  14. infrahub/core/diff/repository/repository.py +3 -1
  15. infrahub/core/graph/__init__.py +1 -1
  16. infrahub/core/graph/constraints.py +1 -1
  17. infrahub/core/initialization.py +2 -1
  18. infrahub/core/ipam/reconciler.py +8 -6
  19. infrahub/core/ipam/utilization.py +8 -15
  20. infrahub/core/manager.py +1 -26
  21. infrahub/core/merge.py +1 -1
  22. infrahub/core/migrations/graph/__init__.py +2 -0
  23. infrahub/core/migrations/graph/m012_convert_account_generic.py +12 -12
  24. infrahub/core/migrations/graph/m013_convert_git_password_credential.py +4 -4
  25. infrahub/core/migrations/graph/m014_remove_index_attr_value.py +3 -2
  26. infrahub/core/migrations/graph/m015_diff_format_update.py +3 -2
  27. infrahub/core/migrations/graph/m016_diff_delete_bug_fix.py +3 -2
  28. infrahub/core/migrations/graph/m017_add_core_profile.py +6 -4
  29. infrahub/core/migrations/graph/m018_uniqueness_nulls.py +3 -4
  30. infrahub/core/migrations/graph/m020_duplicate_edges.py +3 -3
  31. infrahub/core/migrations/graph/m025_uniqueness_nulls.py +3 -4
  32. infrahub/core/migrations/graph/m026_0000_prefix_fix.py +4 -5
  33. infrahub/core/migrations/graph/m028_delete_diffs.py +3 -2
  34. infrahub/core/migrations/graph/m029_duplicates_cleanup.py +3 -2
  35. infrahub/core/migrations/graph/m031_check_number_attributes.py +4 -3
  36. infrahub/core/migrations/graph/m032_cleanup_orphaned_branch_relationships.py +3 -2
  37. infrahub/core/migrations/graph/m034_find_orphaned_schema_fields.py +3 -2
  38. infrahub/core/migrations/graph/m035_orphan_relationships.py +3 -3
  39. infrahub/core/migrations/graph/m036_drop_attr_value_index.py +3 -2
  40. infrahub/core/migrations/graph/m037_index_attr_vals.py +3 -2
  41. infrahub/core/migrations/graph/m038_redo_0000_prefix_fix.py +4 -5
  42. infrahub/core/migrations/graph/m039_ipam_reconcile.py +3 -2
  43. infrahub/core/migrations/graph/m041_deleted_dup_edges.py +4 -3
  44. infrahub/core/migrations/graph/m042_profile_attrs_in_db.py +5 -4
  45. infrahub/core/migrations/graph/m043_create_hfid_display_label_in_db.py +12 -5
  46. infrahub/core/migrations/graph/m044_backfill_hfid_display_label_in_db.py +15 -4
  47. infrahub/core/migrations/graph/m045_backfill_hfid_display_label_in_db_profile_template.py +10 -4
  48. infrahub/core/migrations/graph/m046_fill_agnostic_hfid_display_labels.py +6 -5
  49. infrahub/core/migrations/graph/m047_backfill_or_null_display_label.py +19 -5
  50. infrahub/core/migrations/graph/m048_undelete_rel_props.py +6 -4
  51. infrahub/core/migrations/graph/m049_remove_is_visible_relationship.py +19 -4
  52. infrahub/core/migrations/graph/m050_backfill_vertex_metadata.py +3 -3
  53. infrahub/core/migrations/graph/m051_subtract_branched_from_microsecond.py +39 -0
  54. infrahub/core/migrations/query/__init__.py +2 -2
  55. infrahub/core/migrations/query/schema_attribute_update.py +1 -1
  56. infrahub/core/migrations/runner.py +6 -3
  57. infrahub/core/migrations/schema/attribute_kind_update.py +8 -11
  58. infrahub/core/migrations/schema/attribute_name_update.py +1 -1
  59. infrahub/core/migrations/schema/attribute_supports_profile.py +5 -10
  60. infrahub/core/migrations/schema/models.py +8 -0
  61. infrahub/core/migrations/schema/node_attribute_add.py +11 -14
  62. infrahub/core/migrations/schema/node_attribute_remove.py +1 -1
  63. infrahub/core/migrations/schema/node_kind_update.py +1 -1
  64. infrahub/core/migrations/schema/tasks.py +7 -1
  65. infrahub/core/migrations/shared.py +37 -30
  66. infrahub/core/node/__init__.py +3 -2
  67. infrahub/core/node/base.py +9 -5
  68. infrahub/core/node/delete_validator.py +1 -1
  69. infrahub/core/order.py +30 -0
  70. infrahub/core/protocols.py +1 -0
  71. infrahub/core/protocols_base.py +4 -0
  72. infrahub/core/query/__init__.py +8 -5
  73. infrahub/core/query/attribute.py +3 -3
  74. infrahub/core/query/branch.py +1 -1
  75. infrahub/core/query/delete.py +1 -1
  76. infrahub/core/query/diff.py +3 -3
  77. infrahub/core/query/ipam.py +104 -43
  78. infrahub/core/query/node.py +454 -101
  79. infrahub/core/query/relationship.py +83 -26
  80. infrahub/core/query/resource_manager.py +107 -18
  81. infrahub/core/relationship/constraints/count.py +1 -1
  82. infrahub/core/relationship/constraints/peer_kind.py +1 -1
  83. infrahub/core/relationship/constraints/peer_parent.py +1 -1
  84. infrahub/core/relationship/constraints/peer_relatives.py +1 -1
  85. infrahub/core/relationship/constraints/profiles_kind.py +1 -1
  86. infrahub/core/relationship/constraints/profiles_removal.py +1 -1
  87. infrahub/core/relationship/model.py +8 -2
  88. infrahub/core/schema/attribute_parameters.py +28 -1
  89. infrahub/core/schema/attribute_schema.py +9 -15
  90. infrahub/core/schema/basenode_schema.py +3 -0
  91. infrahub/core/schema/definitions/core/__init__.py +8 -2
  92. infrahub/core/schema/definitions/core/account.py +10 -10
  93. infrahub/core/schema/definitions/core/artifact.py +14 -8
  94. infrahub/core/schema/definitions/core/check.py +10 -4
  95. infrahub/core/schema/definitions/core/generator.py +26 -6
  96. infrahub/core/schema/definitions/core/graphql_query.py +1 -1
  97. infrahub/core/schema/definitions/core/group.py +9 -2
  98. infrahub/core/schema/definitions/core/ipam.py +80 -10
  99. infrahub/core/schema/definitions/core/menu.py +41 -7
  100. infrahub/core/schema/definitions/core/permission.py +16 -2
  101. infrahub/core/schema/definitions/core/profile.py +16 -2
  102. infrahub/core/schema/definitions/core/propose_change.py +24 -4
  103. infrahub/core/schema/definitions/core/propose_change_comment.py +23 -11
  104. infrahub/core/schema/definitions/core/propose_change_validator.py +50 -21
  105. infrahub/core/schema/definitions/core/repository.py +10 -0
  106. infrahub/core/schema/definitions/core/resource_pool.py +8 -1
  107. infrahub/core/schema/definitions/core/template.py +19 -2
  108. infrahub/core/schema/definitions/core/transform.py +11 -5
  109. infrahub/core/schema/definitions/core/webhook.py +27 -9
  110. infrahub/core/schema/manager.py +50 -38
  111. infrahub/core/schema/schema_branch.py +68 -2
  112. infrahub/core/utils.py +3 -3
  113. infrahub/core/validators/aggregated_checker.py +1 -1
  114. infrahub/core/validators/attribute/choices.py +1 -1
  115. infrahub/core/validators/attribute/enum.py +1 -1
  116. infrahub/core/validators/attribute/kind.py +6 -3
  117. infrahub/core/validators/attribute/length.py +1 -1
  118. infrahub/core/validators/attribute/min_max.py +1 -1
  119. infrahub/core/validators/attribute/number_pool.py +1 -1
  120. infrahub/core/validators/attribute/optional.py +1 -1
  121. infrahub/core/validators/attribute/regex.py +1 -1
  122. infrahub/core/validators/node/attribute.py +1 -1
  123. infrahub/core/validators/node/relationship.py +1 -1
  124. infrahub/core/validators/relationship/peer.py +1 -1
  125. infrahub/database/__init__.py +1 -1
  126. infrahub/git/utils.py +1 -1
  127. infrahub/graphql/app.py +2 -2
  128. infrahub/graphql/field_extractor.py +1 -1
  129. infrahub/graphql/manager.py +17 -3
  130. infrahub/graphql/mutations/account.py +1 -1
  131. infrahub/graphql/order.py +14 -0
  132. infrahub/graphql/queries/diff/tree.py +5 -5
  133. infrahub/graphql/queries/resource_manager.py +25 -24
  134. infrahub/graphql/resolvers/ipam.py +3 -3
  135. infrahub/graphql/resolvers/resolver.py +44 -3
  136. infrahub/graphql/types/standard_node.py +8 -4
  137. infrahub/lock.py +7 -0
  138. infrahub/menu/repository.py +1 -1
  139. infrahub/patch/queries/base.py +1 -1
  140. infrahub/pools/number.py +1 -8
  141. infrahub/profiles/node_applier.py +1 -1
  142. infrahub/profiles/queries/get_profile_data.py +1 -1
  143. infrahub/proposed_change/action_checker.py +1 -1
  144. infrahub/services/__init__.py +1 -1
  145. infrahub/services/adapters/cache/nats.py +1 -1
  146. infrahub/services/adapters/cache/redis.py +7 -0
  147. infrahub/webhook/gather.py +1 -1
  148. infrahub/webhook/tasks.py +22 -6
  149. infrahub_sdk/analyzer.py +2 -2
  150. infrahub_sdk/branch.py +12 -39
  151. infrahub_sdk/checks.py +4 -4
  152. infrahub_sdk/client.py +36 -0
  153. infrahub_sdk/ctl/cli_commands.py +2 -1
  154. infrahub_sdk/ctl/graphql.py +15 -4
  155. infrahub_sdk/ctl/utils.py +2 -2
  156. infrahub_sdk/enums.py +6 -0
  157. infrahub_sdk/graphql/renderers.py +21 -0
  158. infrahub_sdk/graphql/utils.py +85 -0
  159. infrahub_sdk/node/attribute.py +12 -2
  160. infrahub_sdk/node/constants.py +11 -0
  161. infrahub_sdk/node/metadata.py +69 -0
  162. infrahub_sdk/node/node.py +65 -14
  163. infrahub_sdk/node/property.py +3 -0
  164. infrahub_sdk/node/related_node.py +24 -1
  165. infrahub_sdk/node/relationship.py +10 -1
  166. infrahub_sdk/operation.py +2 -2
  167. infrahub_sdk/schema/repository.py +1 -2
  168. infrahub_sdk/transforms.py +2 -2
  169. infrahub_sdk/types.py +18 -2
  170. {infrahub_server-1.7.0b0.dist-info → infrahub_server-1.7.1.dist-info}/METADATA +6 -6
  171. {infrahub_server-1.7.0b0.dist-info → infrahub_server-1.7.1.dist-info}/RECORD +176 -172
  172. {infrahub_server-1.7.0b0.dist-info → infrahub_server-1.7.1.dist-info}/entry_points.txt +0 -1
  173. infrahub_testcontainers/models.py +3 -3
  174. infrahub_testcontainers/performance_test.py +1 -1
  175. infrahub/graphql/models.py +0 -36
  176. {infrahub_server-1.7.0b0.dist-info → infrahub_server-1.7.1.dist-info}/WHEEL +0 -0
  177. {infrahub_server-1.7.0b0.dist-info → infrahub_server-1.7.1.dist-info}/licenses/LICENSE.txt +0 -0
infrahub_sdk/branch.py CHANGED
@@ -1,6 +1,5 @@
1
1
  from __future__ import annotations
2
2
 
3
- import warnings
4
3
  from enum import Enum
5
4
  from typing import TYPE_CHECKING, Any, Literal, overload
6
5
  from urllib.parse import urlencode
@@ -93,7 +92,6 @@ class InfrahubBranchManager(InfraHubBranchManagerBase):
93
92
  sync_with_git: bool = True,
94
93
  description: str = "",
95
94
  wait_until_completion: Literal[True] = True,
96
- background_execution: bool | None = False,
97
95
  ) -> BranchData: ...
98
96
 
99
97
  @overload
@@ -103,7 +101,6 @@ class InfrahubBranchManager(InfraHubBranchManagerBase):
103
101
  sync_with_git: bool = True,
104
102
  description: str = "",
105
103
  wait_until_completion: Literal[False] = False,
106
- background_execution: bool | None = False,
107
104
  ) -> str: ...
108
105
 
109
106
  async def create(
@@ -112,19 +109,9 @@ class InfrahubBranchManager(InfraHubBranchManagerBase):
112
109
  sync_with_git: bool = True,
113
110
  description: str = "",
114
111
  wait_until_completion: bool = True,
115
- background_execution: bool | None = False,
116
112
  ) -> BranchData | str:
117
- if background_execution is not None:
118
- warnings.warn(
119
- "`background_execution` is deprecated, please use `wait_until_completion` instead.",
120
- DeprecationWarning,
121
- stacklevel=1,
122
- )
123
-
124
- background_execution = background_execution or not wait_until_completion
125
113
  input_data = {
126
- # Should be switched to `wait_until_completion` once `background_execution` is removed server side.
127
- "background_execution": background_execution,
114
+ "wait_until_completion": wait_until_completion,
128
115
  "data": {
129
116
  "name": branch_name,
130
117
  "description": description,
@@ -132,15 +119,14 @@ class InfrahubBranchManager(InfraHubBranchManagerBase):
132
119
  },
133
120
  }
134
121
 
135
- mutation_query = MUTATION_QUERY_TASK if background_execution else MUTATION_QUERY_DATA
122
+ mutation_query = MUTATION_QUERY_DATA if wait_until_completion else MUTATION_QUERY_TASK
136
123
  query = Mutation(mutation="BranchCreate", input_data=input_data, query=mutation_query)
137
124
  response = await self.client.execute_graphql(query=query.render(), tracker="mutation-branch-create")
138
125
 
139
- # Make sure server version is recent enough to support background execution, as previously
140
- # using background_execution=True had no effect.
141
- if background_execution and "task" in response["BranchCreate"]:
142
- return response["BranchCreate"]["task"]["id"]
143
- return BranchData(**response["BranchCreate"]["object"])
126
+ if wait_until_completion:
127
+ return BranchData(**response["BranchCreate"]["object"])
128
+
129
+ return response["BranchCreate"]["task"]["id"]
144
130
 
145
131
  async def delete(self, branch_name: str) -> bool:
146
132
  input_data = {
@@ -261,7 +247,6 @@ class InfrahubBranchManagerSync(InfraHubBranchManagerBase):
261
247
  sync_with_git: bool = True,
262
248
  description: str = "",
263
249
  wait_until_completion: Literal[True] = True,
264
- background_execution: bool | None = False,
265
250
  ) -> BranchData: ...
266
251
 
267
252
  @overload
@@ -271,7 +256,6 @@ class InfrahubBranchManagerSync(InfraHubBranchManagerBase):
271
256
  sync_with_git: bool = True,
272
257
  description: str = "",
273
258
  wait_until_completion: Literal[False] = False,
274
- background_execution: bool | None = False,
275
259
  ) -> str: ...
276
260
 
277
261
  def create(
@@ -280,19 +264,9 @@ class InfrahubBranchManagerSync(InfraHubBranchManagerBase):
280
264
  sync_with_git: bool = True,
281
265
  description: str = "",
282
266
  wait_until_completion: bool = True,
283
- background_execution: bool | None = False,
284
267
  ) -> BranchData | str:
285
- if background_execution is not None:
286
- warnings.warn(
287
- "`background_execution` is deprecated, please use `wait_until_completion` instead.",
288
- DeprecationWarning,
289
- stacklevel=1,
290
- )
291
-
292
- background_execution = background_execution or not wait_until_completion
293
268
  input_data = {
294
- # Should be switched to `wait_until_completion` once `background_execution` is removed server side.
295
- "background_execution": background_execution,
269
+ "wait_until_completion": wait_until_completion,
296
270
  "data": {
297
271
  "name": branch_name,
298
272
  "description": description,
@@ -300,15 +274,14 @@ class InfrahubBranchManagerSync(InfraHubBranchManagerBase):
300
274
  },
301
275
  }
302
276
 
303
- mutation_query = MUTATION_QUERY_TASK if background_execution else MUTATION_QUERY_DATA
277
+ mutation_query = MUTATION_QUERY_DATA if wait_until_completion else MUTATION_QUERY_TASK
304
278
  query = Mutation(mutation="BranchCreate", input_data=input_data, query=mutation_query)
305
279
  response = self.client.execute_graphql(query=query.render(), tracker="mutation-branch-create")
306
280
 
307
- # Make sure server version is recent enough to support background execution, as previously
308
- # using background_execution=True had no effect.
309
- if background_execution and "task" in response["BranchCreate"]:
310
- return response["BranchCreate"]["task"]["id"]
311
- return BranchData(**response["BranchCreate"]["object"])
281
+ if wait_until_completion:
282
+ return BranchData(**response["BranchCreate"]["object"])
283
+
284
+ return response["BranchCreate"]["task"]["id"]
312
285
 
313
286
  def delete(self, branch_name: str) -> bool:
314
287
  input_data = {
infrahub_sdk/checks.py CHANGED
@@ -1,8 +1,8 @@
1
1
  from __future__ import annotations
2
2
 
3
- import asyncio
4
3
  import importlib
5
- import os
4
+ import inspect
5
+ import pathlib
6
6
  import warnings
7
7
  from abc import abstractmethod
8
8
  from typing import TYPE_CHECKING, Any
@@ -55,7 +55,7 @@ class InfrahubCheck:
55
55
  self.branch = branch
56
56
  self.params = params or {}
57
57
 
58
- self.root_directory = root_directory or os.getcwd()
58
+ self.root_directory = root_directory or str(pathlib.Path.cwd())
59
59
 
60
60
  self._client = client
61
61
 
@@ -160,7 +160,7 @@ class InfrahubCheck:
160
160
  data = await self.collect_data()
161
161
  unpacked = data.get("data") or data
162
162
 
163
- if asyncio.iscoroutinefunction(self.validate):
163
+ if inspect.iscoroutinefunction(self.validate):
164
164
  await self.validate(data=unpacked)
165
165
  else:
166
166
  self.validate(data=unpacked)
infrahub_sdk/client.py CHANGED
@@ -401,6 +401,7 @@ class InfrahubClient(BaseClient):
401
401
  fragment: bool = ...,
402
402
  prefetch_relationships: bool = ...,
403
403
  property: bool = ...,
404
+ include_metadata: bool = ...,
404
405
  **kwargs: Any,
405
406
  ) -> SchemaType | None: ...
406
407
 
@@ -420,6 +421,7 @@ class InfrahubClient(BaseClient):
420
421
  fragment: bool = ...,
421
422
  prefetch_relationships: bool = ...,
422
423
  property: bool = ...,
424
+ include_metadata: bool = ...,
423
425
  **kwargs: Any,
424
426
  ) -> SchemaType: ...
425
427
 
@@ -439,6 +441,7 @@ class InfrahubClient(BaseClient):
439
441
  fragment: bool = ...,
440
442
  prefetch_relationships: bool = ...,
441
443
  property: bool = ...,
444
+ include_metadata: bool = ...,
442
445
  **kwargs: Any,
443
446
  ) -> SchemaType: ...
444
447
 
@@ -458,6 +461,7 @@ class InfrahubClient(BaseClient):
458
461
  fragment: bool = ...,
459
462
  prefetch_relationships: bool = ...,
460
463
  property: bool = ...,
464
+ include_metadata: bool = ...,
461
465
  **kwargs: Any,
462
466
  ) -> InfrahubNode | None: ...
463
467
 
@@ -477,6 +481,7 @@ class InfrahubClient(BaseClient):
477
481
  fragment: bool = ...,
478
482
  prefetch_relationships: bool = ...,
479
483
  property: bool = ...,
484
+ include_metadata: bool = ...,
480
485
  **kwargs: Any,
481
486
  ) -> InfrahubNode: ...
482
487
 
@@ -496,6 +501,7 @@ class InfrahubClient(BaseClient):
496
501
  fragment: bool = ...,
497
502
  prefetch_relationships: bool = ...,
498
503
  property: bool = ...,
504
+ include_metadata: bool = ...,
499
505
  **kwargs: Any,
500
506
  ) -> InfrahubNode: ...
501
507
 
@@ -514,6 +520,7 @@ class InfrahubClient(BaseClient):
514
520
  fragment: bool = False,
515
521
  prefetch_relationships: bool = False,
516
522
  property: bool = False,
523
+ include_metadata: bool = False,
517
524
  **kwargs: Any,
518
525
  ) -> InfrahubNode | SchemaType | None:
519
526
  branch = branch or self.default_branch
@@ -547,6 +554,7 @@ class InfrahubClient(BaseClient):
547
554
  fragment=fragment,
548
555
  prefetch_relationships=prefetch_relationships,
549
556
  property=property,
557
+ include_metadata=include_metadata,
550
558
  **filters,
551
559
  )
552
560
 
@@ -650,6 +658,7 @@ class InfrahubClient(BaseClient):
650
658
  property: bool = ...,
651
659
  parallel: bool = ...,
652
660
  order: Order | None = ...,
661
+ include_metadata: bool = ...,
653
662
  ) -> list[SchemaType]: ...
654
663
 
655
664
  @overload
@@ -669,6 +678,7 @@ class InfrahubClient(BaseClient):
669
678
  property: bool = ...,
670
679
  parallel: bool = ...,
671
680
  order: Order | None = ...,
681
+ include_metadata: bool = ...,
672
682
  ) -> list[InfrahubNode]: ...
673
683
 
674
684
  async def all(
@@ -687,6 +697,7 @@ class InfrahubClient(BaseClient):
687
697
  property: bool = False,
688
698
  parallel: bool = False,
689
699
  order: Order | None = None,
700
+ include_metadata: bool = False,
690
701
  ) -> list[InfrahubNode] | list[SchemaType]:
691
702
  """Retrieve all nodes of a given kind
692
703
 
@@ -704,6 +715,7 @@ class InfrahubClient(BaseClient):
704
715
  prefetch_relationships (bool, optional): Flag to indicate whether to prefetch related node data.
705
716
  parallel (bool, optional): Whether to use parallel processing for the query.
706
717
  order (Order, optional): Ordering related options. Setting `disable=True` enhances performances.
718
+ include_metadata (bool, optional): If True, includes node_metadata and relationship_metadata in the query.
707
719
 
708
720
  Returns:
709
721
  list[InfrahubNode]: List of Nodes
@@ -723,6 +735,7 @@ class InfrahubClient(BaseClient):
723
735
  property=property,
724
736
  parallel=parallel,
725
737
  order=order,
738
+ include_metadata=include_metadata,
726
739
  )
727
740
 
728
741
  @overload
@@ -743,6 +756,7 @@ class InfrahubClient(BaseClient):
743
756
  property: bool = ...,
744
757
  parallel: bool = ...,
745
758
  order: Order | None = ...,
759
+ include_metadata: bool = ...,
746
760
  **kwargs: Any,
747
761
  ) -> list[SchemaType]: ...
748
762
 
@@ -764,6 +778,7 @@ class InfrahubClient(BaseClient):
764
778
  property: bool = ...,
765
779
  parallel: bool = ...,
766
780
  order: Order | None = ...,
781
+ include_metadata: bool = ...,
767
782
  **kwargs: Any,
768
783
  ) -> list[InfrahubNode]: ...
769
784
 
@@ -784,6 +799,7 @@ class InfrahubClient(BaseClient):
784
799
  property: bool = False,
785
800
  parallel: bool = False,
786
801
  order: Order | None = None,
802
+ include_metadata: bool = False,
787
803
  **kwargs: Any,
788
804
  ) -> list[InfrahubNode] | list[SchemaType]:
789
805
  """Retrieve nodes of a given kind based on provided filters.
@@ -803,6 +819,7 @@ class InfrahubClient(BaseClient):
803
819
  partial_match (bool, optional): Allow partial match of filter criteria for the query.
804
820
  parallel (bool, optional): Whether to use parallel processing for the query.
805
821
  order (Order, optional): Ordering related options. Setting `disable=True` enhances performances.
822
+ include_metadata (bool, optional): If True, includes node_metadata and relationship_metadata in the query.
806
823
  **kwargs (Any): Additional filter criteria for the query.
807
824
 
808
825
  Returns:
@@ -829,6 +846,7 @@ class InfrahubClient(BaseClient):
829
846
  partial_match=partial_match,
830
847
  property=property,
831
848
  order=order,
849
+ include_metadata=include_metadata,
832
850
  )
833
851
  query = Query(query=query_data)
834
852
  response = await self.execute_graphql(
@@ -1957,6 +1975,7 @@ class InfrahubClientSync(BaseClient):
1957
1975
  property: bool = ...,
1958
1976
  parallel: bool = ...,
1959
1977
  order: Order | None = ...,
1978
+ include_metadata: bool = ...,
1960
1979
  ) -> list[SchemaTypeSync]: ...
1961
1980
 
1962
1981
  @overload
@@ -1976,6 +1995,7 @@ class InfrahubClientSync(BaseClient):
1976
1995
  property: bool = ...,
1977
1996
  parallel: bool = ...,
1978
1997
  order: Order | None = ...,
1998
+ include_metadata: bool = ...,
1979
1999
  ) -> list[InfrahubNodeSync]: ...
1980
2000
 
1981
2001
  def all(
@@ -1994,6 +2014,7 @@ class InfrahubClientSync(BaseClient):
1994
2014
  property: bool = False,
1995
2015
  parallel: bool = False,
1996
2016
  order: Order | None = None,
2017
+ include_metadata: bool = False,
1997
2018
  ) -> list[InfrahubNodeSync] | list[SchemaTypeSync]:
1998
2019
  """Retrieve all nodes of a given kind
1999
2020
 
@@ -2011,6 +2032,7 @@ class InfrahubClientSync(BaseClient):
2011
2032
  prefetch_relationships (bool, optional): Flag to indicate whether to prefetch related node data.
2012
2033
  parallel (bool, optional): Whether to use parallel processing for the query.
2013
2034
  order (Order, optional): Ordering related options. Setting `disable=True` enhances performances.
2035
+ include_metadata (bool, optional): If True, includes node_metadata and relationship_metadata in the query.
2014
2036
 
2015
2037
  Returns:
2016
2038
  list[InfrahubNodeSync]: List of Nodes
@@ -2030,6 +2052,7 @@ class InfrahubClientSync(BaseClient):
2030
2052
  property=property,
2031
2053
  parallel=parallel,
2032
2054
  order=order,
2055
+ include_metadata=include_metadata,
2033
2056
  )
2034
2057
 
2035
2058
  def _process_nodes_and_relationships(
@@ -2091,6 +2114,7 @@ class InfrahubClientSync(BaseClient):
2091
2114
  property: bool = ...,
2092
2115
  parallel: bool = ...,
2093
2116
  order: Order | None = ...,
2117
+ include_metadata: bool = ...,
2094
2118
  **kwargs: Any,
2095
2119
  ) -> list[SchemaTypeSync]: ...
2096
2120
 
@@ -2112,6 +2136,7 @@ class InfrahubClientSync(BaseClient):
2112
2136
  property: bool = ...,
2113
2137
  parallel: bool = ...,
2114
2138
  order: Order | None = ...,
2139
+ include_metadata: bool = ...,
2115
2140
  **kwargs: Any,
2116
2141
  ) -> list[InfrahubNodeSync]: ...
2117
2142
 
@@ -2132,6 +2157,7 @@ class InfrahubClientSync(BaseClient):
2132
2157
  property: bool = False,
2133
2158
  parallel: bool = False,
2134
2159
  order: Order | None = None,
2160
+ include_metadata: bool = False,
2135
2161
  **kwargs: Any,
2136
2162
  ) -> list[InfrahubNodeSync] | list[SchemaTypeSync]:
2137
2163
  """Retrieve nodes of a given kind based on provided filters.
@@ -2151,6 +2177,7 @@ class InfrahubClientSync(BaseClient):
2151
2177
  partial_match (bool, optional): Allow partial match of filter criteria for the query.
2152
2178
  parallel (bool, optional): Whether to use parallel processing for the query.
2153
2179
  order (Order, optional): Ordering related options. Setting `disable=True` enhances performances.
2180
+ include_metadata (bool, optional): If True, includes node_metadata and relationship_metadata in the query.
2154
2181
  **kwargs (Any): Additional filter criteria for the query.
2155
2182
 
2156
2183
  Returns:
@@ -2177,6 +2204,7 @@ class InfrahubClientSync(BaseClient):
2177
2204
  partial_match=partial_match,
2178
2205
  property=property,
2179
2206
  order=order,
2207
+ include_metadata=include_metadata,
2180
2208
  )
2181
2209
  query = Query(query=query_data)
2182
2210
  response = self.execute_graphql(
@@ -2266,6 +2294,7 @@ class InfrahubClientSync(BaseClient):
2266
2294
  fragment: bool = ...,
2267
2295
  prefetch_relationships: bool = ...,
2268
2296
  property: bool = ...,
2297
+ include_metadata: bool = ...,
2269
2298
  **kwargs: Any,
2270
2299
  ) -> SchemaTypeSync | None: ...
2271
2300
 
@@ -2285,6 +2314,7 @@ class InfrahubClientSync(BaseClient):
2285
2314
  fragment: bool = ...,
2286
2315
  prefetch_relationships: bool = ...,
2287
2316
  property: bool = ...,
2317
+ include_metadata: bool = ...,
2288
2318
  **kwargs: Any,
2289
2319
  ) -> SchemaTypeSync: ...
2290
2320
 
@@ -2304,6 +2334,7 @@ class InfrahubClientSync(BaseClient):
2304
2334
  fragment: bool = ...,
2305
2335
  prefetch_relationships: bool = ...,
2306
2336
  property: bool = ...,
2337
+ include_metadata: bool = ...,
2307
2338
  **kwargs: Any,
2308
2339
  ) -> SchemaTypeSync: ...
2309
2340
 
@@ -2323,6 +2354,7 @@ class InfrahubClientSync(BaseClient):
2323
2354
  fragment: bool = ...,
2324
2355
  prefetch_relationships: bool = ...,
2325
2356
  property: bool = ...,
2357
+ include_metadata: bool = ...,
2326
2358
  **kwargs: Any,
2327
2359
  ) -> InfrahubNodeSync | None: ...
2328
2360
 
@@ -2342,6 +2374,7 @@ class InfrahubClientSync(BaseClient):
2342
2374
  fragment: bool = ...,
2343
2375
  prefetch_relationships: bool = ...,
2344
2376
  property: bool = ...,
2377
+ include_metadata: bool = ...,
2345
2378
  **kwargs: Any,
2346
2379
  ) -> InfrahubNodeSync: ...
2347
2380
 
@@ -2361,6 +2394,7 @@ class InfrahubClientSync(BaseClient):
2361
2394
  fragment: bool = ...,
2362
2395
  prefetch_relationships: bool = ...,
2363
2396
  property: bool = ...,
2397
+ include_metadata: bool = ...,
2364
2398
  **kwargs: Any,
2365
2399
  ) -> InfrahubNodeSync: ...
2366
2400
 
@@ -2379,6 +2413,7 @@ class InfrahubClientSync(BaseClient):
2379
2413
  fragment: bool = False,
2380
2414
  prefetch_relationships: bool = False,
2381
2415
  property: bool = False,
2416
+ include_metadata: bool = False,
2382
2417
  **kwargs: Any,
2383
2418
  ) -> InfrahubNodeSync | SchemaTypeSync | None:
2384
2419
  branch = branch or self.default_branch
@@ -2412,6 +2447,7 @@ class InfrahubClientSync(BaseClient):
2412
2447
  fragment=fragment,
2413
2448
  prefetch_relationships=prefetch_relationships,
2414
2449
  property=property,
2450
+ include_metadata=include_metadata,
2415
2451
  **filters,
2416
2452
  )
2417
2453
 
@@ -3,6 +3,7 @@ from __future__ import annotations
3
3
  import asyncio
4
4
  import functools
5
5
  import importlib
6
+ import inspect
6
7
  import logging
7
8
  import platform
8
9
  import sys
@@ -240,7 +241,7 @@ async def _run_transform(
240
241
  console.print("[yellow] you can specify a different branch with --branch")
241
242
  raise typer.Abort()
242
243
 
243
- if asyncio.iscoroutinefunction(transform_func):
244
+ if inspect.iscoroutinefunction(transform_func):
244
245
  output = await transform_func(response)
245
246
  else:
246
247
  output = transform_func(response)
@@ -22,7 +22,12 @@ from rich.console import Console
22
22
  from ..async_typer import AsyncTyper
23
23
  from ..ctl.client import initialize_client
24
24
  from ..ctl.utils import catch_exception
25
- from ..graphql.utils import insert_fragments_inline, remove_fragment_import
25
+ from ..graphql.utils import (
26
+ insert_fragments_inline,
27
+ remove_fragment_import,
28
+ strip_typename_from_fragment,
29
+ strip_typename_from_operation,
30
+ )
26
31
  from .parameters import CONFIG_PARAM
27
32
 
28
33
  app = AsyncTyper()
@@ -152,12 +157,18 @@ async def generate_return_types(
152
157
  queries = filter_operations_definitions(definitions)
153
158
  fragments = filter_fragments_definitions(definitions)
154
159
 
160
+ # Strip __typename fields from operations and fragments before code generation.
161
+ # __typename is a GraphQL introspection meta-field that isn't part of the schema's
162
+ # type definitions, causing ariadne-codegen to fail with "Redefinition of reserved type 'String'"
163
+ stripped_queries = [strip_typename_from_operation(q) for q in queries]
164
+ stripped_fragments = [strip_typename_from_fragment(f) for f in fragments]
165
+
155
166
  package_generator = get_package_generator(
156
167
  schema=graphql_schema,
157
- fragments=fragments,
168
+ fragments=stripped_fragments,
158
169
  settings=ClientSettings(
159
170
  schema_path=str(schema),
160
- target_package_name=directory.name,
171
+ target_package_name=directory.name or "graphql_client",
161
172
  queries_path=str(directory),
162
173
  include_comments=CommentsStrategy.NONE,
163
174
  ),
@@ -166,7 +177,7 @@ async def generate_return_types(
166
177
 
167
178
  parsing_failed = False
168
179
  try:
169
- for query_operation in queries:
180
+ for query_operation in stripped_queries:
170
181
  package_generator.add_operation(query_operation)
171
182
  except ParsingError as exc:
172
183
  console.print(f"[red]Unable to process {gql_file.name}: {exc}")
infrahub_sdk/ctl/utils.py CHANGED
@@ -1,6 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
- import asyncio
3
+ import inspect
4
4
  import logging
5
5
  import traceback
6
6
  from collections.abc import Callable, Coroutine
@@ -83,7 +83,7 @@ def catch_exception(
83
83
  console = Console()
84
84
 
85
85
  def decorator(func: Callable[..., T]) -> Callable[..., T | Coroutine[Any, Any, T]]:
86
- if asyncio.iscoroutinefunction(func):
86
+ if inspect.iscoroutinefunction(func):
87
87
 
88
88
  @wraps(func)
89
89
  async def async_wrapper(*args: Any, **kwargs: Any) -> T:
infrahub_sdk/enums.py ADDED
@@ -0,0 +1,6 @@
1
+ from enum import Enum
2
+
3
+
4
+ class OrderDirection(str, Enum):
5
+ ASC = "ASC"
6
+ DESC = "DESC"
@@ -7,6 +7,8 @@ from typing import Any
7
7
 
8
8
  from pydantic import BaseModel
9
9
 
10
+ from infrahub_sdk.types import Order
11
+
10
12
  from .constants import VARIABLE_TYPE_MAPPING
11
13
 
12
14
 
@@ -53,6 +55,16 @@ def convert_to_graphql_as_string(value: Any, convert_enum: bool = False) -> str:
53
55
  if isinstance(value, list):
54
56
  values_as_string = [convert_to_graphql_as_string(value=item, convert_enum=convert_enum) for item in value]
55
57
  return "[" + ", ".join(values_as_string) + "]"
58
+ if isinstance(value, Order):
59
+ data = value.model_dump(exclude_none=True)
60
+ return (
61
+ "{ "
62
+ + ", ".join(
63
+ f"{key}: {convert_to_graphql_as_string(value=val, convert_enum=convert_enum)}"
64
+ for key, val in data.items()
65
+ )
66
+ + " }"
67
+ )
56
68
  if isinstance(value, BaseModel):
57
69
  data = value.model_dump()
58
70
  return (
@@ -63,6 +75,15 @@ def convert_to_graphql_as_string(value: Any, convert_enum: bool = False) -> str:
63
75
  )
64
76
  + " }"
65
77
  )
78
+ if isinstance(value, dict):
79
+ return (
80
+ "{ "
81
+ + ", ".join(
82
+ f"{key}: {convert_to_graphql_as_string(value=val, convert_enum=convert_enum)}"
83
+ for key, val in value.items()
84
+ )
85
+ + " }"
86
+ )
66
87
 
67
88
  return str(value)
68
89
 
@@ -1,5 +1,90 @@
1
1
  import ast
2
2
 
3
+ from graphql import (
4
+ FieldNode,
5
+ FragmentDefinitionNode,
6
+ FragmentSpreadNode,
7
+ InlineFragmentNode,
8
+ OperationDefinitionNode,
9
+ SelectionNode,
10
+ SelectionSetNode,
11
+ )
12
+
13
+
14
+ def strip_typename_from_selection_set(selection_set: SelectionSetNode | None) -> SelectionSetNode | None:
15
+ """Recursively strip __typename fields from a SelectionSetNode.
16
+
17
+ The __typename meta-field is an introspection field that is not part of the schema's
18
+ type definitions. When code generation tools like ariadne-codegen try to look up
19
+ __typename in the schema, they fail because it's a reserved introspection field.
20
+
21
+ This function removes all __typename fields from the selection set, allowing
22
+ code generation to proceed without errors.
23
+ """
24
+ if selection_set is None:
25
+ return None
26
+
27
+ new_selections: list[SelectionNode] = []
28
+ for selection in selection_set.selections:
29
+ if isinstance(selection, FieldNode):
30
+ # Skip __typename fields
31
+ if selection.name.value == "__typename":
32
+ continue
33
+ # Recursively process nested selection sets
34
+ new_field = FieldNode(
35
+ alias=selection.alias,
36
+ name=selection.name,
37
+ arguments=selection.arguments,
38
+ directives=selection.directives,
39
+ selection_set=strip_typename_from_selection_set(selection.selection_set),
40
+ )
41
+ new_selections.append(new_field)
42
+ elif isinstance(selection, InlineFragmentNode):
43
+ # Process inline fragments
44
+ new_inline = InlineFragmentNode(
45
+ type_condition=selection.type_condition,
46
+ directives=selection.directives,
47
+ selection_set=strip_typename_from_selection_set(selection.selection_set),
48
+ )
49
+ new_selections.append(new_inline)
50
+ elif isinstance(selection, FragmentSpreadNode):
51
+ # FragmentSpread references a named fragment - keep as-is
52
+ new_selections.append(selection)
53
+ else:
54
+ raise TypeError(f"Unexpected GraphQL selection node type '{type(selection).__name__}'.")
55
+
56
+ return SelectionSetNode(selections=tuple(new_selections))
57
+
58
+
59
+ def strip_typename_from_operation(operation: OperationDefinitionNode) -> OperationDefinitionNode:
60
+ """Strip __typename fields from an operation definition.
61
+
62
+ Returns a new OperationDefinitionNode with all __typename fields removed
63
+ from its selection set and any nested selection sets.
64
+ """
65
+ return OperationDefinitionNode(
66
+ operation=operation.operation,
67
+ name=operation.name,
68
+ variable_definitions=operation.variable_definitions,
69
+ directives=operation.directives,
70
+ selection_set=strip_typename_from_selection_set(operation.selection_set),
71
+ )
72
+
73
+
74
+ def strip_typename_from_fragment(fragment: FragmentDefinitionNode) -> FragmentDefinitionNode:
75
+ """Strip __typename fields from a fragment definition.
76
+
77
+ Returns a new FragmentDefinitionNode with all __typename fields removed
78
+ from its selection set and any nested selection sets.
79
+ """
80
+ return FragmentDefinitionNode(
81
+ name=fragment.name,
82
+ type_condition=fragment.type_condition,
83
+ variable_definitions=fragment.variable_definitions,
84
+ directives=fragment.directives,
85
+ selection_set=strip_typename_from_selection_set(fragment.selection_set),
86
+ )
87
+
3
88
 
4
89
  def get_class_def_index(module: ast.Module) -> int:
5
90
  """Get the index of the first class definition in the module.