infrahub-server 1.6.3__py3-none-any.whl → 1.7.0__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 (250) hide show
  1. infrahub/actions/tasks.py +4 -2
  2. infrahub/api/exceptions.py +2 -2
  3. infrahub/api/schema.py +3 -1
  4. infrahub/artifacts/tasks.py +1 -0
  5. infrahub/auth.py +2 -2
  6. infrahub/cli/db.py +54 -28
  7. infrahub/computed_attribute/gather.py +3 -4
  8. infrahub/computed_attribute/tasks.py +23 -6
  9. infrahub/config.py +8 -0
  10. infrahub/constants/enums.py +12 -0
  11. infrahub/core/account.py +4 -4
  12. infrahub/core/attribute.py +106 -108
  13. infrahub/core/branch/models.py +44 -71
  14. infrahub/core/branch/tasks.py +5 -3
  15. infrahub/core/changelog/diff.py +1 -20
  16. infrahub/core/changelog/models.py +0 -7
  17. infrahub/core/constants/__init__.py +17 -0
  18. infrahub/core/constants/database.py +0 -1
  19. infrahub/core/constants/schema.py +0 -1
  20. infrahub/core/convert_object_type/repository_conversion.py +3 -4
  21. infrahub/core/diff/branch_differ.py +1 -1
  22. infrahub/core/diff/conflict_transferer.py +1 -1
  23. infrahub/core/diff/data_check_synchronizer.py +4 -3
  24. infrahub/core/diff/enricher/cardinality_one.py +2 -2
  25. infrahub/core/diff/enricher/hierarchy.py +1 -1
  26. infrahub/core/diff/enricher/labels.py +1 -1
  27. infrahub/core/diff/merger/merger.py +28 -2
  28. infrahub/core/diff/merger/serializer.py +3 -10
  29. infrahub/core/diff/model/diff.py +1 -1
  30. infrahub/core/diff/query/merge.py +376 -135
  31. infrahub/core/diff/repository/repository.py +3 -1
  32. infrahub/core/graph/__init__.py +1 -1
  33. infrahub/core/graph/constraints.py +3 -3
  34. infrahub/core/graph/schema.py +2 -12
  35. infrahub/core/ipam/reconciler.py +8 -6
  36. infrahub/core/ipam/utilization.py +8 -15
  37. infrahub/core/manager.py +133 -152
  38. infrahub/core/merge.py +1 -1
  39. infrahub/core/metadata/__init__.py +0 -0
  40. infrahub/core/metadata/interface.py +37 -0
  41. infrahub/core/metadata/model.py +31 -0
  42. infrahub/core/metadata/query/__init__.py +0 -0
  43. infrahub/core/metadata/query/node_metadata.py +301 -0
  44. infrahub/core/migrations/graph/__init__.py +4 -0
  45. infrahub/core/migrations/graph/m012_convert_account_generic.py +12 -12
  46. infrahub/core/migrations/graph/m013_convert_git_password_credential.py +7 -12
  47. infrahub/core/migrations/graph/m017_add_core_profile.py +5 -2
  48. infrahub/core/migrations/graph/m018_uniqueness_nulls.py +2 -1
  49. infrahub/core/migrations/graph/m019_restore_rels_to_time.py +0 -10
  50. infrahub/core/migrations/graph/m020_duplicate_edges.py +0 -8
  51. infrahub/core/migrations/graph/m025_uniqueness_nulls.py +2 -1
  52. infrahub/core/migrations/graph/m026_0000_prefix_fix.py +2 -1
  53. infrahub/core/migrations/graph/m029_duplicates_cleanup.py +0 -1
  54. infrahub/core/migrations/graph/m031_check_number_attributes.py +2 -2
  55. infrahub/core/migrations/graph/m038_redo_0000_prefix_fix.py +2 -1
  56. infrahub/core/migrations/graph/m041_deleted_dup_edges.py +1 -1
  57. infrahub/core/migrations/graph/m049_remove_is_visible_relationship.py +53 -0
  58. infrahub/core/migrations/graph/m050_backfill_vertex_metadata.py +168 -0
  59. infrahub/core/migrations/query/__init__.py +2 -2
  60. infrahub/core/migrations/query/attribute_add.py +17 -6
  61. infrahub/core/migrations/query/attribute_remove.py +19 -5
  62. infrahub/core/migrations/query/attribute_rename.py +21 -5
  63. infrahub/core/migrations/query/node_duplicate.py +19 -4
  64. infrahub/core/migrations/query/schema_attribute_update.py +1 -1
  65. infrahub/core/migrations/schema/attribute_kind_update.py +21 -2
  66. infrahub/core/migrations/schema/attribute_name_update.py +1 -1
  67. infrahub/core/migrations/schema/attribute_supports_profile.py +5 -3
  68. infrahub/core/migrations/schema/models.py +3 -0
  69. infrahub/core/migrations/schema/node_attribute_add.py +5 -2
  70. infrahub/core/migrations/schema/node_attribute_remove.py +1 -1
  71. infrahub/core/migrations/schema/node_kind_update.py +1 -1
  72. infrahub/core/migrations/schema/node_remove.py +24 -2
  73. infrahub/core/migrations/schema/tasks.py +4 -1
  74. infrahub/core/migrations/shared.py +13 -6
  75. infrahub/core/models.py +6 -6
  76. infrahub/core/node/__init__.py +157 -58
  77. infrahub/core/node/base.py +9 -5
  78. infrahub/core/node/create.py +7 -3
  79. infrahub/core/node/delete_validator.py +1 -1
  80. infrahub/core/node/standard.py +100 -14
  81. infrahub/core/order.py +30 -0
  82. infrahub/core/property.py +0 -1
  83. infrahub/core/protocols.py +1 -0
  84. infrahub/core/protocols_base.py +10 -2
  85. infrahub/core/query/__init__.py +5 -3
  86. infrahub/core/query/attribute.py +164 -49
  87. infrahub/core/query/branch.py +58 -70
  88. infrahub/core/query/delete.py +1 -1
  89. infrahub/core/query/diff.py +7 -7
  90. infrahub/core/query/ipam.py +104 -43
  91. infrahub/core/query/node.py +1072 -281
  92. infrahub/core/query/relationship.py +531 -325
  93. infrahub/core/query/resource_manager.py +107 -18
  94. infrahub/core/query/standard_node.py +25 -5
  95. infrahub/core/query/utils.py +2 -4
  96. infrahub/core/relationship/constraints/count.py +1 -1
  97. infrahub/core/relationship/constraints/peer_kind.py +1 -1
  98. infrahub/core/relationship/constraints/peer_parent.py +1 -1
  99. infrahub/core/relationship/constraints/peer_relatives.py +1 -1
  100. infrahub/core/relationship/constraints/profiles_kind.py +1 -1
  101. infrahub/core/relationship/constraints/profiles_removal.py +168 -0
  102. infrahub/core/relationship/model.py +293 -139
  103. infrahub/core/schema/attribute_schema.py +2 -2
  104. infrahub/core/schema/basenode_schema.py +3 -0
  105. infrahub/core/schema/definitions/core/__init__.py +8 -2
  106. infrahub/core/schema/definitions/core/account.py +10 -10
  107. infrahub/core/schema/definitions/core/artifact.py +14 -8
  108. infrahub/core/schema/definitions/core/check.py +10 -4
  109. infrahub/core/schema/definitions/core/generator.py +26 -6
  110. infrahub/core/schema/definitions/core/graphql_query.py +1 -1
  111. infrahub/core/schema/definitions/core/group.py +9 -2
  112. infrahub/core/schema/definitions/core/ipam.py +80 -10
  113. infrahub/core/schema/definitions/core/menu.py +41 -7
  114. infrahub/core/schema/definitions/core/permission.py +16 -2
  115. infrahub/core/schema/definitions/core/profile.py +16 -2
  116. infrahub/core/schema/definitions/core/propose_change.py +24 -4
  117. infrahub/core/schema/definitions/core/propose_change_comment.py +23 -11
  118. infrahub/core/schema/definitions/core/propose_change_validator.py +50 -21
  119. infrahub/core/schema/definitions/core/repository.py +10 -0
  120. infrahub/core/schema/definitions/core/resource_pool.py +8 -1
  121. infrahub/core/schema/definitions/core/template.py +19 -2
  122. infrahub/core/schema/definitions/core/transform.py +11 -5
  123. infrahub/core/schema/definitions/core/webhook.py +27 -9
  124. infrahub/core/schema/manager.py +63 -43
  125. infrahub/core/schema/relationship_schema.py +6 -2
  126. infrahub/core/schema/schema_branch.py +48 -10
  127. infrahub/core/task/task.py +4 -2
  128. infrahub/core/utils.py +3 -25
  129. infrahub/core/validators/aggregated_checker.py +1 -1
  130. infrahub/core/validators/attribute/choices.py +1 -1
  131. infrahub/core/validators/attribute/enum.py +1 -1
  132. infrahub/core/validators/attribute/kind.py +1 -1
  133. infrahub/core/validators/attribute/length.py +1 -1
  134. infrahub/core/validators/attribute/min_max.py +1 -1
  135. infrahub/core/validators/attribute/number_pool.py +1 -1
  136. infrahub/core/validators/attribute/optional.py +1 -1
  137. infrahub/core/validators/attribute/regex.py +1 -1
  138. infrahub/core/validators/determiner.py +3 -3
  139. infrahub/core/validators/node/attribute.py +1 -1
  140. infrahub/core/validators/node/relationship.py +1 -1
  141. infrahub/core/validators/relationship/peer.py +1 -1
  142. infrahub/database/__init__.py +4 -4
  143. infrahub/dependencies/builder/constraint/grouped/node_runner.py +2 -0
  144. infrahub/dependencies/builder/constraint/relationship_manager/profiles_removal.py +8 -0
  145. infrahub/dependencies/registry.py +2 -0
  146. infrahub/display_labels/tasks.py +12 -3
  147. infrahub/git/integrator.py +18 -18
  148. infrahub/git/tasks.py +1 -1
  149. infrahub/git/utils.py +1 -1
  150. infrahub/graphql/constants.py +3 -0
  151. infrahub/graphql/context.py +1 -1
  152. infrahub/graphql/field_extractor.py +1 -1
  153. infrahub/graphql/initialization.py +11 -0
  154. infrahub/graphql/loaders/account.py +134 -0
  155. infrahub/graphql/loaders/node.py +5 -12
  156. infrahub/graphql/loaders/peers.py +5 -7
  157. infrahub/graphql/manager.py +175 -21
  158. infrahub/graphql/metadata.py +91 -0
  159. infrahub/graphql/mutations/account.py +6 -6
  160. infrahub/graphql/mutations/attribute.py +0 -2
  161. infrahub/graphql/mutations/branch.py +9 -5
  162. infrahub/graphql/mutations/computed_attribute.py +1 -1
  163. infrahub/graphql/mutations/display_label.py +1 -1
  164. infrahub/graphql/mutations/hfid.py +1 -1
  165. infrahub/graphql/mutations/ipam.py +4 -6
  166. infrahub/graphql/mutations/main.py +9 -4
  167. infrahub/graphql/mutations/profile.py +16 -22
  168. infrahub/graphql/mutations/proposed_change.py +4 -4
  169. infrahub/graphql/mutations/relationship.py +40 -10
  170. infrahub/graphql/mutations/repository.py +14 -12
  171. infrahub/graphql/mutations/schema.py +2 -2
  172. infrahub/graphql/order.py +14 -0
  173. infrahub/graphql/queries/branch.py +62 -6
  174. infrahub/graphql/queries/resource_manager.py +25 -24
  175. infrahub/graphql/resolvers/account_metadata.py +84 -0
  176. infrahub/graphql/resolvers/ipam.py +6 -8
  177. infrahub/graphql/resolvers/many_relationship.py +77 -35
  178. infrahub/graphql/resolvers/resolver.py +59 -14
  179. infrahub/graphql/resolvers/single_relationship.py +87 -23
  180. infrahub/graphql/subscription/graphql_query.py +2 -0
  181. infrahub/graphql/types/__init__.py +0 -1
  182. infrahub/graphql/types/attribute.py +10 -5
  183. infrahub/graphql/types/branch.py +40 -53
  184. infrahub/graphql/types/enums.py +3 -0
  185. infrahub/graphql/types/metadata.py +28 -0
  186. infrahub/graphql/types/node.py +22 -2
  187. infrahub/graphql/types/relationship.py +10 -2
  188. infrahub/graphql/types/standard_node.py +12 -7
  189. infrahub/hfid/tasks.py +12 -3
  190. infrahub/lock.py +7 -0
  191. infrahub/menu/repository.py +1 -1
  192. infrahub/patch/queries/base.py +1 -1
  193. infrahub/pools/number.py +1 -8
  194. infrahub/profiles/gather.py +56 -0
  195. infrahub/profiles/mandatory_fields_checker.py +116 -0
  196. infrahub/profiles/models.py +66 -0
  197. infrahub/profiles/node_applier.py +154 -13
  198. infrahub/profiles/queries/get_profile_data.py +143 -31
  199. infrahub/profiles/tasks.py +79 -27
  200. infrahub/profiles/triggers.py +22 -0
  201. infrahub/proposed_change/action_checker.py +1 -1
  202. infrahub/proposed_change/tasks.py +4 -1
  203. infrahub/services/__init__.py +1 -1
  204. infrahub/services/adapters/cache/nats.py +1 -1
  205. infrahub/services/adapters/cache/redis.py +7 -0
  206. infrahub/tasks/artifact.py +1 -0
  207. infrahub/transformations/tasks.py +2 -2
  208. infrahub/trigger/catalogue.py +2 -0
  209. infrahub/trigger/models.py +1 -0
  210. infrahub/trigger/setup.py +3 -3
  211. infrahub/trigger/tasks.py +3 -0
  212. infrahub/validators/tasks.py +1 -0
  213. infrahub/webhook/gather.py +1 -1
  214. infrahub/webhook/models.py +1 -1
  215. infrahub/webhook/tasks.py +23 -7
  216. infrahub/workers/dependencies.py +9 -3
  217. infrahub/workers/infrahub_async.py +13 -4
  218. infrahub/workflows/catalogue.py +19 -0
  219. infrahub_sdk/analyzer.py +2 -2
  220. infrahub_sdk/branch.py +12 -39
  221. infrahub_sdk/checks.py +4 -4
  222. infrahub_sdk/client.py +36 -0
  223. infrahub_sdk/ctl/cli_commands.py +2 -1
  224. infrahub_sdk/ctl/graphql.py +15 -4
  225. infrahub_sdk/ctl/utils.py +2 -2
  226. infrahub_sdk/enums.py +6 -0
  227. infrahub_sdk/graphql/renderers.py +21 -0
  228. infrahub_sdk/graphql/utils.py +85 -0
  229. infrahub_sdk/node/attribute.py +12 -2
  230. infrahub_sdk/node/constants.py +12 -0
  231. infrahub_sdk/node/metadata.py +69 -0
  232. infrahub_sdk/node/node.py +65 -14
  233. infrahub_sdk/node/property.py +3 -0
  234. infrahub_sdk/node/related_node.py +37 -5
  235. infrahub_sdk/node/relationship.py +18 -1
  236. infrahub_sdk/operation.py +2 -2
  237. infrahub_sdk/schema/repository.py +1 -2
  238. infrahub_sdk/transforms.py +2 -2
  239. infrahub_sdk/types.py +18 -2
  240. {infrahub_server-1.6.3.dist-info → infrahub_server-1.7.0.dist-info}/METADATA +17 -16
  241. {infrahub_server-1.6.3.dist-info → infrahub_server-1.7.0.dist-info}/RECORD +249 -228
  242. infrahub_testcontainers/container.py +3 -3
  243. infrahub_testcontainers/docker-compose-cluster.test.yml +7 -7
  244. infrahub_testcontainers/docker-compose.test.yml +13 -5
  245. infrahub_testcontainers/models.py +3 -3
  246. infrahub_testcontainers/performance_test.py +1 -1
  247. infrahub/graphql/models.py +0 -6
  248. {infrahub_server-1.6.3.dist-info → infrahub_server-1.7.0.dist-info}/WHEEL +0 -0
  249. {infrahub_server-1.6.3.dist-info → infrahub_server-1.7.0.dist-info}/entry_points.txt +0 -0
  250. {infrahub_server-1.6.3.dist-info → infrahub_server-1.7.0.dist-info}/licenses/LICENSE.txt +0 -0
@@ -6,6 +6,7 @@ from cachetools import LRUCache
6
6
  from infrahub_sdk.schema import BranchSchema as SDKBranchSchema
7
7
 
8
8
  from infrahub import lock
9
+ from infrahub.core.constants import SYSTEM_USER_ID, MetadataOptions
9
10
  from infrahub.core.manager import NodeManager
10
11
  from infrahub.core.models import (
11
12
  HashableModelDiff,
@@ -178,15 +179,18 @@ class SchemaManager(NodeManager):
178
179
  diff: SchemaDiff | None = None,
179
180
  limit: list[str] | None = None,
180
181
  update_db: bool = True,
182
+ user_id: str = SYSTEM_USER_ID,
181
183
  ) -> None:
182
184
  branch = await registry.get_branch(branch=branch, db=db)
183
185
 
184
186
  updated_schema = None
185
187
  if update_db:
186
188
  if diff:
187
- schema_diff = await self.update_schema_to_db(schema=schema, db=db, branch=branch, diff=diff)
189
+ schema_diff = await self.update_schema_to_db(
190
+ schema=schema, db=db, branch=branch, diff=diff, user_id=user_id
191
+ )
188
192
  else:
189
- await self.load_schema_to_db(schema=schema, db=db, branch=branch, limit=limit)
193
+ await self.load_schema_to_db(schema=schema, db=db, branch=branch, limit=limit, user_id=user_id)
190
194
  # After updating the schema into the db
191
195
  # we need to pull a fresh version because some default value are managed/generated within the node object
192
196
  schema_diff = None
@@ -216,6 +220,7 @@ class SchemaManager(NodeManager):
216
220
  schema: SchemaBranch,
217
221
  db: InfrahubDatabase,
218
222
  diff: SchemaDiff,
223
+ user_id: str,
219
224
  branch: Branch | str | None = None,
220
225
  ) -> SchemaBranchDiff:
221
226
  """Load all nodes, generics and groups from a SchemaRoot object into the database."""
@@ -226,7 +231,7 @@ class SchemaManager(NodeManager):
226
231
  added_generics = []
227
232
  for item_kind in diff.added.keys():
228
233
  item = schema.get(name=item_kind, duplicate=False)
229
- node = await self.load_node_to_db(node=item, branch=branch, db=db)
234
+ node = await self.load_node_to_db(node=item, branch=branch, db=db, user_id=user_id)
230
235
  schema.set(name=item_kind, schema=node)
231
236
  if item.is_node_schema:
232
237
  added_nodes.append(item_kind)
@@ -238,9 +243,11 @@ class SchemaManager(NodeManager):
238
243
  for item_kind, item_diff in diff.changed.items():
239
244
  item = schema.get(name=item_kind, duplicate=False)
240
245
  if item_diff:
241
- node = await self.update_node_in_db_based_on_diff(node=item, branch=branch, db=db, diff=item_diff)
246
+ node = await self.update_node_in_db_based_on_diff(
247
+ node=item, branch=branch, db=db, diff=item_diff, user_id=user_id
248
+ )
242
249
  else:
243
- node = await self.update_node_in_db(node=item, branch=branch, db=db)
250
+ node = await self.update_node_in_db(node=item, branch=branch, db=db, user_id=user_id)
244
251
  schema.set(name=item_kind, schema=node)
245
252
  if item.is_node_schema:
246
253
  changed_nodes.append(item_kind)
@@ -251,7 +258,7 @@ class SchemaManager(NodeManager):
251
258
  removed_generics = []
252
259
  for item_kind in diff.removed.keys():
253
260
  item = schema.get(name=item_kind, duplicate=False)
254
- node = await self.delete_node_in_db(node=item, branch=branch, db=db)
261
+ node = await self.delete_node_in_db(node=item, branch=branch, db=db, user_id=user_id)
255
262
  schema.delete(name=item_kind)
256
263
  if item.is_node_schema:
257
264
  removed_nodes.append(item_kind)
@@ -273,6 +280,7 @@ class SchemaManager(NodeManager):
273
280
  db: InfrahubDatabase,
274
281
  branch: Branch | str | None = None,
275
282
  limit: list[str] | None = None,
283
+ user_id: str = SYSTEM_USER_ID,
276
284
  ) -> None:
277
285
  """Load all nodes, generics and groups from a SchemaRoot object into the database."""
278
286
 
@@ -283,16 +291,17 @@ class SchemaManager(NodeManager):
283
291
  continue
284
292
  item = schema.get(name=item_kind, duplicate=False)
285
293
  if not item.id:
286
- node = await self.load_node_to_db(node=item, branch=branch, db=db)
294
+ node = await self.load_node_to_db(node=item, branch=branch, db=db, user_id=user_id)
287
295
  schema.set(name=item_kind, schema=node)
288
296
  else:
289
- node = await self.update_node_in_db(node=item, branch=branch, db=db)
297
+ node = await self.update_node_in_db(node=item, branch=branch, db=db, user_id=user_id)
290
298
  schema.set(name=item_kind, schema=node)
291
299
 
292
300
  async def load_node_to_db(
293
301
  self,
294
302
  node: NodeSchema | GenericSchema,
295
303
  db: InfrahubDatabase,
304
+ user_id: str,
296
305
  branch: Branch | str | None = None,
297
306
  ) -> NodeSchema | GenericSchema:
298
307
  """Load a Node with its attributes and its relationships to the database."""
@@ -313,7 +322,7 @@ class SchemaManager(NodeManager):
313
322
  schema_dict = node.model_dump(exclude={"id", "state", "filters", "relationships", "attributes"})
314
323
  obj = await Node.init(schema=node_schema, branch=branch, db=db)
315
324
  await obj.new(**schema_dict, db=db)
316
- await obj.save(db=db)
325
+ await obj.save(db=db, user_id=user_id)
317
326
  new_node.id = obj.id
318
327
 
319
328
  # Then create the Attributes and the relationships
@@ -324,7 +333,7 @@ class SchemaManager(NodeManager):
324
333
  for item in node.attributes:
325
334
  if item.inherited is False:
326
335
  new_attr = await self.create_attribute_in_db(
327
- schema=attribute_schema, item=item, parent=obj, branch=branch, db=db
336
+ schema=attribute_schema, item=item, parent=obj, branch=branch, db=db, user_id=user_id
328
337
  )
329
338
  else:
330
339
  new_attr = item.duplicate()
@@ -333,7 +342,7 @@ class SchemaManager(NodeManager):
333
342
  for item in node.relationships:
334
343
  if item.inherited is False:
335
344
  new_rel = await self.create_relationship_in_db(
336
- schema=relationship_schema, item=item, parent=obj, branch=branch, db=db
345
+ schema=relationship_schema, item=item, parent=obj, branch=branch, db=db, user_id=user_id
337
346
  )
338
347
  else:
339
348
  new_rel = item.duplicate()
@@ -347,6 +356,7 @@ class SchemaManager(NodeManager):
347
356
  self,
348
357
  db: InfrahubDatabase,
349
358
  node: NodeSchema | GenericSchema,
359
+ user_id: str,
350
360
  branch: Branch | str | None = None,
351
361
  ) -> NodeSchema | GenericSchema:
352
362
  """Update a Node with its attributes and its relationships in the database."""
@@ -374,7 +384,7 @@ class SchemaManager(NodeManager):
374
384
  await obj.relationships.update(
375
385
  db=db, data=[item.id for item in node.local_relationships if item.id and item.name != "profiles"]
376
386
  )
377
- await obj.save(db=db)
387
+ await obj.save(db=db, user_id=user_id)
378
388
 
379
389
  # Then Update the Attributes and the relationships
380
390
 
@@ -382,25 +392,24 @@ class SchemaManager(NodeManager):
382
392
  ids=[item.id for item in node.local_attributes + node.local_relationships if item.id],
383
393
  db=db,
384
394
  branch=branch,
385
- include_owner=True,
386
- include_source=True,
395
+ include_metadata=MetadataOptions.LINKED_NODES,
387
396
  )
388
397
 
389
398
  for item in node.local_attributes:
390
399
  if item.id and item.id in items:
391
- await self.update_attribute_in_db(item=item, attr=items[item.id], db=db)
400
+ await self.update_attribute_in_db(item=item, attr=items[item.id], db=db, user_id=user_id)
392
401
  elif not item.id:
393
402
  new_attr = await self.create_attribute_in_db(
394
- schema=attribute_schema, item=item, branch=branch, db=db, parent=obj
403
+ schema=attribute_schema, item=item, branch=branch, db=db, parent=obj, user_id=user_id
395
404
  )
396
405
  new_node.attributes.append(new_attr)
397
406
 
398
407
  for item in node.local_relationships:
399
408
  if item.id and item.id in items:
400
- await self.update_relationship_in_db(item=item, rel=items[item.id], db=db)
409
+ await self.update_relationship_in_db(item=item, rel=items[item.id], db=db, user_id=user_id)
401
410
  elif not item.id:
402
411
  new_rel = await self.create_relationship_in_db(
403
- schema=relationship_schema, item=item, branch=branch, db=db, parent=obj
412
+ schema=relationship_schema, item=item, branch=branch, db=db, parent=obj, user_id=user_id
404
413
  )
405
414
  new_node.relationships.append(new_rel)
406
415
 
@@ -413,6 +422,7 @@ class SchemaManager(NodeManager):
413
422
  db: InfrahubDatabase,
414
423
  diff: HashableModelDiff,
415
424
  node: NodeSchema | GenericSchema,
425
+ user_id: str,
416
426
  branch: Branch | str | None = None,
417
427
  ) -> NodeSchema | GenericSchema:
418
428
  """Update a Node with its attributes and its relationships in the database based on a HashableModelDiff."""
@@ -466,8 +476,7 @@ class SchemaManager(NodeManager):
466
476
  ids=list(item_ids),
467
477
  db=db,
468
478
  branch=branch,
469
- include_owner=True,
470
- include_source=True,
479
+ include_metadata=MetadataOptions.LINKED_NODES,
471
480
  )
472
481
  if missing_field_names:
473
482
  missing_attrs = await self.query(
@@ -475,16 +484,14 @@ class SchemaManager(NodeManager):
475
484
  branch=branch,
476
485
  schema=attribute_schema,
477
486
  filters={"name__values": missing_field_names, "node__id": node.id},
478
- include_owner=True,
479
- include_source=True,
487
+ include_metadata=MetadataOptions.LINKED_NODES,
480
488
  )
481
489
  missing_rels = await self.query(
482
490
  db=db,
483
491
  branch=branch,
484
492
  schema=relationship_schema,
485
493
  filters={"name__values": missing_field_names, "node__id": node.id},
486
- include_owner=True,
487
- include_source=True,
494
+ include_metadata=MetadataOptions.LINKED_NODES,
488
495
  )
489
496
  items.update({field.id: field for field in missing_attrs + missing_rels})
490
497
 
@@ -494,21 +501,21 @@ class SchemaManager(NodeManager):
494
501
  if diff_relationships:
495
502
  await obj.relationships.update(db=db, data=[item.id for item in node.local_relationships if item.id])
496
503
 
497
- await obj.save(db=db)
504
+ await obj.save(db=db, user_id=user_id)
498
505
 
499
506
  if diff_attributes:
500
507
  for item in node.local_attributes:
501
508
  # if item is in changed and has no ID, then it is being overridden from a generic and must be added
502
509
  if item.name in diff_attributes.added or (item.name in diff_attributes.changed and item.id is None):
503
510
  created_item = await self.create_attribute_in_db(
504
- schema=attribute_schema, item=item, branch=branch, db=db, parent=obj
511
+ schema=attribute_schema, item=item, branch=branch, db=db, parent=obj, user_id=user_id
505
512
  )
506
513
  new_attr = new_node.get_attribute(name=item.name)
507
514
  new_attr.id = created_item.id
508
515
  elif item.name in diff_attributes.changed and item.id and item.id in items:
509
- await self.update_attribute_in_db(item=item, attr=items[item.id], db=db)
516
+ await self.update_attribute_in_db(item=item, attr=items[item.id], db=db, user_id=user_id)
510
517
  elif item.name in diff_attributes.removed and item.id and item.id in items:
511
- await items[item.id].delete(db=db)
518
+ await items[item.id].delete(db=db, user_id=user_id)
512
519
  elif (
513
520
  (item.name in diff_attributes.removed or item.name in diff_attributes.changed)
514
521
  and item.id
@@ -523,14 +530,14 @@ class SchemaManager(NodeManager):
523
530
  item.name in diff_relationships.changed and item.id is None
524
531
  ):
525
532
  created_rel = await self.create_relationship_in_db(
526
- schema=relationship_schema, item=item, branch=branch, db=db, parent=obj
533
+ schema=relationship_schema, item=item, branch=branch, db=db, parent=obj, user_id=user_id
527
534
  )
528
535
  new_rel = new_node.get_relationship(name=item.name)
529
536
  new_rel.id = created_rel.id
530
537
  elif item.name in diff_relationships.changed and item.id and item.id in items:
531
- await self.update_relationship_in_db(item=item, rel=items[item.id], db=db)
538
+ await self.update_relationship_in_db(item=item, rel=items[item.id], db=db, user_id=user_id)
532
539
  elif item.name in diff_relationships.removed and item.id and item.id in items:
533
- await items[item.id].delete(db=db)
540
+ await items[item.id].delete(db=db, user_id=user_id)
534
541
  elif (
535
542
  (item.name in diff_relationships.removed or item.name in diff_relationships.changed)
536
543
  and item.id
@@ -548,7 +555,7 @@ class SchemaManager(NodeManager):
548
555
  if field_names_to_remove:
549
556
  for field_schema in items.values():
550
557
  if field_schema.name.value in field_names_to_remove:
551
- await field_schema.delete(db=db)
558
+ await field_schema.delete(db=db, user_id=user_id)
552
559
 
553
560
  # Save back the node with the (potentially) newly created IDs in the SchemaManager
554
561
  self.set(name=new_node.kind, schema=new_node, branch=branch.name)
@@ -558,6 +565,7 @@ class SchemaManager(NodeManager):
558
565
  self,
559
566
  db: InfrahubDatabase,
560
567
  node: NodeSchema | GenericSchema,
568
+ user_id: str,
561
569
  branch: Branch | str | None = None,
562
570
  ) -> None:
563
571
  """Delete the node with its attributes and relationships."""
@@ -573,47 +581,59 @@ class SchemaManager(NodeManager):
573
581
 
574
582
  # First delete the attributes and the relationships
575
583
  for attr_schema_node in (await obj.attributes.get_peers(db=db)).values():
576
- await attr_schema_node.delete(db=db)
584
+ await attr_schema_node.delete(db=db, user_id=user_id)
577
585
  for rel_schema_node in (await obj.relationships.get_peers(db=db)).values():
578
- await rel_schema_node.delete(db=db)
586
+ await rel_schema_node.delete(db=db, user_id=user_id)
579
587
 
580
- await obj.delete(db=db)
588
+ await obj.delete(db=db, user_id=user_id)
581
589
 
582
590
  @staticmethod
583
591
  async def create_attribute_in_db(
584
- schema: NodeSchema, item: AttributeSchema, branch: Branch, parent: Node, db: InfrahubDatabase
592
+ schema: NodeSchema,
593
+ item: AttributeSchema,
594
+ branch: Branch,
595
+ parent: Node,
596
+ db: InfrahubDatabase,
597
+ user_id: str,
585
598
  ) -> AttributeSchema:
586
599
  obj = await Node.init(schema=schema, branch=branch, db=db)
587
600
  await obj.new(**item.to_node(), node=parent, db=db)
588
- await obj.save(db=db)
601
+ await obj.save(db=db, user_id=user_id)
589
602
  new_item = item.duplicate()
590
603
  new_item.id = obj.id
591
604
  return new_item
592
605
 
593
606
  @staticmethod
594
- async def update_attribute_in_db(item: AttributeSchema, attr: Node, db: InfrahubDatabase) -> None:
607
+ async def update_attribute_in_db(item: AttributeSchema, attr: Node, db: InfrahubDatabase, user_id: str) -> None:
595
608
  item_dict = item.model_dump(exclude={"id", "state", "filters"})
596
609
  for key, value in item_dict.items():
597
610
  getattr(attr, key).value = value
598
- await attr.save(db=db)
611
+ await attr.save(db=db, user_id=user_id)
599
612
 
600
613
  @staticmethod
601
614
  async def create_relationship_in_db(
602
- schema: NodeSchema, item: RelationshipSchema, branch: Branch, parent: Node, db: InfrahubDatabase
615
+ schema: NodeSchema,
616
+ item: RelationshipSchema,
617
+ branch: Branch,
618
+ parent: Node,
619
+ db: InfrahubDatabase,
620
+ user_id: str,
603
621
  ) -> RelationshipSchema:
604
622
  obj = await Node.init(schema=schema, branch=branch, db=db)
605
623
  await obj.new(**item.model_dump(exclude={"id", "state", "filters"}), node=parent, db=db)
606
- await obj.save(db=db)
624
+ await obj.save(db=db, user_id=user_id)
607
625
  new_item = item.duplicate()
608
626
  new_item.id = obj.id
609
627
  return new_item
610
628
 
611
629
  @staticmethod
612
- async def update_relationship_in_db(item: RelationshipSchema, rel: Node, db: InfrahubDatabase) -> None:
630
+ async def update_relationship_in_db(
631
+ item: RelationshipSchema, rel: Node, db: InfrahubDatabase, user_id: str
632
+ ) -> None:
613
633
  item_dict = item.model_dump(exclude={"id", "state", "filters"})
614
634
  for key, value in item_dict.items():
615
635
  getattr(rel, key).value = value
616
- await rel.save(db=db)
636
+ await rel.save(db=db, user_id=user_id)
617
637
 
618
638
  async def load_schema(
619
639
  self,
@@ -6,7 +6,7 @@ from typing import TYPE_CHECKING, Any
6
6
  from pydantic import BaseModel
7
7
 
8
8
  from infrahub import config
9
- from infrahub.core.constants import RelationshipDirection
9
+ from infrahub.core.constants import RelationshipDirection, RelationshipKind
10
10
  from infrahub.core.query import QueryNode, QueryRel, QueryRelDirection
11
11
  from infrahub.core.relationship import Relationship
12
12
  from infrahub.exceptions import InitializationError
@@ -36,6 +36,10 @@ class RelationshipSchema(GeneratedRelationshipSchema):
36
36
  def is_deprecated(self) -> bool:
37
37
  return bool(self.deprecation)
38
38
 
39
+ @property
40
+ def support_profiles(self) -> bool:
41
+ return self.read_only is False and self.kind in {RelationshipKind.GENERIC, RelationshipKind.ATTRIBUTE}
42
+
39
43
  def to_dict(self) -> dict:
40
44
  data = self.model_dump(exclude_unset=True, exclude_none=True)
41
45
  for field_name, value in data.items():
@@ -75,7 +79,7 @@ class RelationshipSchema(GeneratedRelationshipSchema):
75
79
 
76
80
  def update_from_generic(self, other: RelationshipSchema) -> None:
77
81
  fields_to_exclude = ("id", "order_weight", "branch", "inherited", "filters")
78
- for name in self.model_fields:
82
+ for name in self.__class__.model_fields:
79
83
  if name in fields_to_exclude:
80
84
  continue
81
85
  if getattr(self, name) != getattr(other, name):
@@ -93,7 +93,7 @@ class SchemaBranch:
93
93
  computed_attributes: ComputedAttributes | None = None,
94
94
  display_labels: DisplayLabels | None = None,
95
95
  hfids: HFIDs | None = None,
96
- ):
96
+ ) -> None:
97
97
  self._cache: dict[str, NodeSchema | GenericSchema] = cache
98
98
  self.name: str | None = name
99
99
  self.nodes: dict[str, str] = {}
@@ -236,8 +236,8 @@ class SchemaBranch:
236
236
  if diff_node.has_diff:
237
237
  schema_diff.changed[key] = diff_node
238
238
 
239
- reversed_map_local = dict(map(reversed, local_kind_id_map.items()))
240
- reversed_map_other = dict(map(reversed, other_kind_id_map.items()))
239
+ reversed_map_local: dict[str | None, str] = {v: k for k, v in local_kind_id_map.items()}
240
+ reversed_map_other: dict[str | None, str] = {v: k for k, v in other_kind_id_map.items()}
241
241
 
242
242
  for shared_id in shared_ids:
243
243
  local_node = self.get(name=reversed_map_local[shared_id], duplicate=False)
@@ -2225,6 +2225,45 @@ class SchemaBranch:
2225
2225
 
2226
2226
  self.set(name=node_name, schema=node)
2227
2227
 
2228
+ def add_relationships_to_profile(self, profile: ProfileSchema, node: NodeSchema | GenericSchema) -> None:
2229
+ # Remove previous relationships to account for new ones
2230
+ profile.relationships = [r for r in profile.relationships if r.kind == RelationshipKind.PROFILE]
2231
+
2232
+ for relationship in node.relationships:
2233
+ if not relationship.support_profiles:
2234
+ continue
2235
+
2236
+ # Ignore relationship if it is part of a uniqueness constraint
2237
+ ignore_relationship = False
2238
+ for constraint in node.uniqueness_constraints or []:
2239
+ if relationship.name in constraint:
2240
+ ignore_relationship = True
2241
+ break
2242
+ if ignore_relationship:
2243
+ continue
2244
+
2245
+ identifier = (
2246
+ f"profile_{relationship.identifier}"
2247
+ if relationship.identifier
2248
+ else self._generate_identifier_string(profile.kind, relationship.peer)
2249
+ )
2250
+
2251
+ profile.relationships.append(
2252
+ RelationshipSchema(
2253
+ name=relationship.name,
2254
+ peer=relationship.peer,
2255
+ kind=relationship.kind,
2256
+ cardinality=relationship.cardinality,
2257
+ direction=relationship.direction,
2258
+ branch=relationship.branch,
2259
+ identifier=identifier,
2260
+ min_count=relationship.min_count,
2261
+ max_count=relationship.max_count,
2262
+ label=relationship.label,
2263
+ inherited=False,
2264
+ )
2265
+ )
2266
+
2228
2267
  def manage_profile_schemas(self) -> None:
2229
2268
  if not self.has(name=InfrahubKind.PROFILE):
2230
2269
  # TODO: This logic is actually only for testing purposes as since 1.0.9 CoreProfile is loaded in db.
@@ -2244,6 +2283,7 @@ class SchemaBranch:
2244
2283
  continue
2245
2284
 
2246
2285
  profile = self.generate_profile_from_node(node=node)
2286
+ self.add_relationships_to_profile(profile=profile, node=node)
2247
2287
  self.set(name=profile.kind, schema=profile)
2248
2288
  profile_schema_kinds.add(profile.kind)
2249
2289
 
@@ -2318,13 +2358,13 @@ class SchemaBranch:
2318
2358
  core_name_attr = core_profile_schema.get_attribute(name="profile_name")
2319
2359
  name_attr_schema_class = get_attribute_schema_class_for_kind(kind=core_name_attr.kind)
2320
2360
  profile_name_attr = name_attr_schema_class(
2321
- **core_name_attr.model_dump(exclude=["id", "inherited"]),
2361
+ **core_name_attr.model_dump(exclude={"id", "inherited"}),
2322
2362
  )
2323
2363
  profile_name_attr.branch = node.branch
2324
2364
  core_priority_attr = core_profile_schema.get_attribute(name="profile_priority")
2325
2365
  priority_attr_schema_class = get_attribute_schema_class_for_kind(kind=core_priority_attr.kind)
2326
2366
  profile_priority_attr = priority_attr_schema_class(
2327
- **core_priority_attr.model_dump(exclude=["id", "inherited"]),
2367
+ **core_priority_attr.model_dump(exclude={"id", "inherited"}),
2328
2368
  )
2329
2369
  profile_priority_attr.branch = node.branch
2330
2370
  profile = ProfileSchema(
@@ -2369,7 +2409,7 @@ class SchemaBranch:
2369
2409
  attr_schema_class = get_attribute_schema_class_for_kind(kind=node_attr.kind)
2370
2410
  attr = attr_schema_class(
2371
2411
  optional=True,
2372
- **node_attr.model_dump(exclude=["id", "unique", "optional", "read_only", "default_value", "inherited"]),
2412
+ **node_attr.model_dump(exclude={"id", "unique", "optional", "read_only", "default_value", "inherited"}),
2373
2413
  )
2374
2414
  profile.attributes.append(attr)
2375
2415
 
@@ -2513,9 +2553,7 @@ class SchemaBranch:
2513
2553
  )
2514
2554
  core_name_attr = core_template_schema.get_attribute(name=OBJECT_TEMPLATE_NAME_ATTR)
2515
2555
  name_attr_schema_class = get_attribute_schema_class_for_kind(kind=core_name_attr.kind)
2516
- template_name_attr = name_attr_schema_class(
2517
- **core_name_attr.model_dump(exclude=["id", "inherited"]),
2518
- )
2556
+ template_name_attr = name_attr_schema_class(**core_name_attr.model_dump(exclude={"id", "inherited"}))
2519
2557
  template_name_attr.branch = node.branch
2520
2558
 
2521
2559
  template: TemplateSchema | GenericSchema
@@ -2574,7 +2612,7 @@ class SchemaBranch:
2574
2612
  attr_schema_class = get_attribute_schema_class_for_kind(kind=node_attr.kind)
2575
2613
  attr = attr_schema_class(
2576
2614
  optional=node_attr.optional if is_autogenerated_subtemplate else True,
2577
- **node_attr.model_dump(exclude=["id", "unique", "optional", "read_only", "order_weight"]),
2615
+ **node_attr.model_dump(exclude={"id", "unique", "optional", "read_only", "order_weight"}),
2578
2616
  )
2579
2617
  template.attributes.append(attr)
2580
2618
 
@@ -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,
@@ -237,7 +215,7 @@ def props(x: Any) -> dict[str, Any]:
237
215
 
238
216
 
239
217
  class SubclassWithMeta_Meta(type):
240
- _meta = None
218
+ _meta: Any = None
241
219
 
242
220
  def __str__(cls) -> str:
243
221
  if cls._meta:
@@ -251,7 +229,7 @@ class SubclassWithMeta_Meta(type):
251
229
  class SubclassWithMeta(metaclass=SubclassWithMeta_Meta):
252
230
  """This class improves __init_subclass__ to receive automatically the options from meta"""
253
231
 
254
- def __init_subclass__(cls, **meta_options: dict[str, Any]) -> None:
232
+ def __init_subclass__(cls, **meta_options: Any) -> None:
255
233
  """This method just terminates the super() chain"""
256
234
  _Meta = getattr(cls, "Meta", None)
257
235
  _meta_props = {}
@@ -276,5 +254,5 @@ class SubclassWithMeta(metaclass=SubclassWithMeta_Meta):
276
254
  super_class.__init_subclass_with_meta__(**options)
277
255
 
278
256
  @classmethod
279
- def __init_subclass_with_meta__(cls, **meta_options: dict[str, Any]) -> None:
257
+ def __init_subclass_with_meta__(cls, **meta_options: Any) -> None:
280
258
  """This method just terminates the super() chain"""
@@ -20,7 +20,7 @@ if TYPE_CHECKING:
20
20
  class AggregatedConstraintChecker:
21
21
  def __init__(
22
22
  self, constraints: list[ConstraintCheckerInterface], db: InfrahubDatabase, branch: Branch | None = None
23
- ):
23
+ ) -> None:
24
24
  self.constraints = constraints
25
25
  self.db = db
26
26
  self.branch = branch
@@ -84,7 +84,7 @@ class AttributeChoicesUpdateValidatorQuery(AttributeSchemaValidatorQuery):
84
84
  class AttributeChoicesChecker(ConstraintCheckerInterface):
85
85
  query_classes = [AttributeChoicesUpdateValidatorQuery]
86
86
 
87
- def __init__(self, db: InfrahubDatabase, branch: Branch | None = None):
87
+ def __init__(self, db: InfrahubDatabase, branch: Branch | None = None) -> None:
88
88
  self.db = db
89
89
  self.branch = branch
90
90
 
@@ -72,7 +72,7 @@ class AttributeEnumUpdateValidatorQuery(AttributeSchemaValidatorQuery):
72
72
  class AttributeEnumChecker(ConstraintCheckerInterface):
73
73
  query_classes = [AttributeEnumUpdateValidatorQuery]
74
74
 
75
- def __init__(self, db: InfrahubDatabase, branch: Branch | None = None):
75
+ def __init__(self, db: InfrahubDatabase, branch: Branch | None = None) -> None:
76
76
  self.db = db
77
77
  self.branch = branch
78
78
 
@@ -92,7 +92,7 @@ class AttributeKindUpdateValidatorQuery(AttributeSchemaValidatorQuery):
92
92
  class AttributeKindChecker(ConstraintCheckerInterface):
93
93
  query_classes = [AttributeKindUpdateValidatorQuery]
94
94
 
95
- def __init__(self, db: InfrahubDatabase, branch: Branch | None = None):
95
+ def __init__(self, db: InfrahubDatabase, branch: Branch | None = None) -> None:
96
96
  self.db = db
97
97
  self.branch = branch
98
98
 
@@ -69,7 +69,7 @@ class AttributeLengthUpdateValidatorQuery(AttributeSchemaValidatorQuery):
69
69
  class AttributeLengthChecker(ConstraintCheckerInterface):
70
70
  query_classes = [AttributeLengthUpdateValidatorQuery]
71
71
 
72
- def __init__(self, db: InfrahubDatabase, branch: Branch | None = None):
72
+ def __init__(self, db: InfrahubDatabase, branch: Branch | None = None) -> None:
73
73
  self.db = db
74
74
  self.branch = branch
75
75
 
@@ -79,7 +79,7 @@ class AttributeNumberUpdateValidatorQuery(AttributeSchemaValidatorQuery):
79
79
  class AttributeNumberChecker(ConstraintCheckerInterface):
80
80
  query_classes = [AttributeNumberUpdateValidatorQuery]
81
81
 
82
- def __init__(self, db: InfrahubDatabase, branch: Branch | None = None):
82
+ def __init__(self, db: InfrahubDatabase, branch: Branch | None = None) -> None:
83
83
  self.db = db
84
84
  self.branch = branch
85
85
 
@@ -74,7 +74,7 @@ class AttributeNumberPoolUpdateValidatorQuery(AttributeSchemaValidatorQuery):
74
74
  class AttributeNumberPoolChecker(ConstraintCheckerInterface):
75
75
  query_classes = [AttributeNumberPoolUpdateValidatorQuery]
76
76
 
77
- def __init__(self, db: InfrahubDatabase, branch: Branch | None = None):
77
+ def __init__(self, db: InfrahubDatabase, branch: Branch | None = None) -> None:
78
78
  self.db = db
79
79
  self.branch = branch
80
80
 
@@ -64,7 +64,7 @@ class AttributeOptionalUpdateValidatorQuery(AttributeSchemaValidatorQuery):
64
64
  class AttributeOptionalChecker(ConstraintCheckerInterface):
65
65
  query_classes = [AttributeOptionalUpdateValidatorQuery]
66
66
 
67
- def __init__(self, db: InfrahubDatabase, branch: Branch | None = None):
67
+ def __init__(self, db: InfrahubDatabase, branch: Branch | None = None) -> None:
68
68
  self.db = db
69
69
  self.branch = branch
70
70
 
@@ -69,7 +69,7 @@ class AttributeRegexUpdateValidatorQuery(AttributeSchemaValidatorQuery):
69
69
  class AttributeRegexChecker(ConstraintCheckerInterface):
70
70
  query_classes = [AttributeRegexUpdateValidatorQuery]
71
71
 
72
- def __init__(self, db: InfrahubDatabase, branch: Branch | None = None):
72
+ def __init__(self, db: InfrahubDatabase, branch: Branch | None = None) -> None:
73
73
  self.db = db
74
74
  self.branch = branch
75
75