infrahub-server 1.2.0rc0__py3-none-any.whl → 1.2.2__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 (365) hide show
  1. infrahub/api/dependencies.py +6 -6
  2. infrahub/api/diff/validation_models.py +7 -7
  3. infrahub/api/schema.py +1 -1
  4. infrahub/artifacts/models.py +5 -3
  5. infrahub/artifacts/tasks.py +3 -5
  6. infrahub/cli/__init__.py +13 -9
  7. infrahub/cli/constants.py +3 -0
  8. infrahub/cli/db.py +165 -183
  9. infrahub/cli/upgrade.py +146 -0
  10. infrahub/computed_attribute/gather.py +185 -0
  11. infrahub/computed_attribute/models.py +240 -12
  12. infrahub/computed_attribute/tasks.py +72 -432
  13. infrahub/computed_attribute/triggers.py +13 -47
  14. infrahub/config.py +43 -32
  15. infrahub/context.py +14 -0
  16. infrahub/core/account.py +4 -4
  17. infrahub/core/attribute.py +58 -58
  18. infrahub/core/branch/tasks.py +74 -22
  19. infrahub/core/changelog/diff.py +95 -36
  20. infrahub/core/changelog/models.py +217 -43
  21. infrahub/core/constants/__init__.py +28 -0
  22. infrahub/core/constants/infrahubkind.py +2 -0
  23. infrahub/core/constants/schema.py +2 -0
  24. infrahub/core/constraint/node/runner.py +9 -8
  25. infrahub/core/diff/branch_differ.py +10 -10
  26. infrahub/core/diff/enricher/cardinality_one.py +5 -0
  27. infrahub/core/diff/enricher/hierarchy.py +17 -4
  28. infrahub/core/diff/enricher/labels.py +5 -0
  29. infrahub/core/diff/enricher/path_identifier.py +4 -0
  30. infrahub/core/diff/ipam_diff_parser.py +4 -5
  31. infrahub/core/diff/model/diff.py +27 -27
  32. infrahub/core/diff/model/path.py +32 -9
  33. infrahub/core/diff/parent_node_adder.py +78 -0
  34. infrahub/core/diff/payload_builder.py +13 -2
  35. infrahub/core/diff/query/filters.py +2 -2
  36. infrahub/core/diff/query/merge.py +20 -17
  37. infrahub/core/diff/query/save.py +188 -182
  38. infrahub/core/diff/query/summary_counts_enricher.py +51 -4
  39. infrahub/core/diff/query_parser.py +4 -4
  40. infrahub/core/diff/repository/deserializer.py +8 -3
  41. infrahub/core/diff/repository/repository.py +156 -38
  42. infrahub/core/diff/tasks.py +4 -4
  43. infrahub/core/graph/__init__.py +1 -1
  44. infrahub/core/graph/index.py +3 -0
  45. infrahub/core/initialization.py +1 -10
  46. infrahub/core/ipam/constants.py +3 -4
  47. infrahub/core/ipam/reconciler.py +12 -12
  48. infrahub/core/ipam/utilization.py +10 -13
  49. infrahub/core/manager.py +36 -36
  50. infrahub/core/merge.py +7 -7
  51. infrahub/core/migrations/__init__.py +2 -3
  52. infrahub/core/migrations/graph/__init__.py +12 -3
  53. infrahub/core/migrations/graph/m017_add_core_profile.py +1 -5
  54. infrahub/core/migrations/graph/m018_uniqueness_nulls.py +4 -4
  55. infrahub/core/migrations/graph/m019_restore_rels_to_time.py +256 -0
  56. infrahub/core/migrations/graph/m020_duplicate_edges.py +160 -0
  57. infrahub/core/migrations/graph/m021_missing_hierarchy_merge.py +51 -0
  58. infrahub/core/migrations/graph/m022_add_generate_template_attr.py +48 -0
  59. infrahub/core/migrations/graph/m023_deduplicate_cardinality_one_relationships.py +96 -0
  60. infrahub/core/migrations/query/attribute_add.py +2 -2
  61. infrahub/core/migrations/query/node_duplicate.py +43 -26
  62. infrahub/core/migrations/query/schema_attribute_update.py +2 -2
  63. infrahub/core/migrations/schema/models.py +19 -4
  64. infrahub/core/migrations/schema/node_remove.py +26 -12
  65. infrahub/core/migrations/schema/tasks.py +2 -2
  66. infrahub/core/migrations/shared.py +16 -16
  67. infrahub/core/models.py +15 -6
  68. infrahub/core/node/__init__.py +43 -39
  69. infrahub/core/node/base.py +2 -4
  70. infrahub/core/node/constraints/attribute_uniqueness.py +2 -2
  71. infrahub/core/node/constraints/grouped_uniqueness.py +99 -47
  72. infrahub/core/node/constraints/interface.py +1 -2
  73. infrahub/core/node/delete_validator.py +3 -5
  74. infrahub/core/node/ipam.py +4 -4
  75. infrahub/core/node/permissions.py +7 -7
  76. infrahub/core/node/resource_manager/ip_address_pool.py +6 -6
  77. infrahub/core/node/resource_manager/ip_prefix_pool.py +6 -6
  78. infrahub/core/node/resource_manager/number_pool.py +3 -3
  79. infrahub/core/path.py +12 -12
  80. infrahub/core/property.py +11 -11
  81. infrahub/core/protocols.py +7 -0
  82. infrahub/core/protocols_base.py +21 -21
  83. infrahub/core/query/__init__.py +33 -33
  84. infrahub/core/query/attribute.py +6 -4
  85. infrahub/core/query/diff.py +3 -3
  86. infrahub/core/query/node.py +98 -37
  87. infrahub/core/query/relationship.py +228 -40
  88. infrahub/core/query/resource_manager.py +2 -0
  89. infrahub/core/query/standard_node.py +3 -3
  90. infrahub/core/query/subquery.py +9 -9
  91. infrahub/core/registry.py +13 -15
  92. infrahub/core/relationship/constraints/count.py +3 -4
  93. infrahub/core/relationship/constraints/peer_kind.py +3 -4
  94. infrahub/core/relationship/constraints/profiles_kind.py +2 -2
  95. infrahub/core/relationship/model.py +51 -59
  96. infrahub/core/schema/attribute_schema.py +16 -8
  97. infrahub/core/schema/basenode_schema.py +105 -44
  98. infrahub/core/schema/computed_attribute.py +3 -3
  99. infrahub/core/schema/definitions/core/__init__.py +147 -0
  100. infrahub/core/schema/definitions/core/account.py +171 -0
  101. infrahub/core/schema/definitions/core/artifact.py +136 -0
  102. infrahub/core/schema/definitions/core/builtin.py +24 -0
  103. infrahub/core/schema/definitions/core/check.py +68 -0
  104. infrahub/core/schema/definitions/core/core.py +17 -0
  105. infrahub/core/schema/definitions/core/generator.py +100 -0
  106. infrahub/core/schema/definitions/core/graphql_query.py +79 -0
  107. infrahub/core/schema/definitions/core/group.py +108 -0
  108. infrahub/core/schema/definitions/core/ipam.py +193 -0
  109. infrahub/core/schema/definitions/core/lineage.py +19 -0
  110. infrahub/core/schema/definitions/core/menu.py +48 -0
  111. infrahub/core/schema/definitions/core/permission.py +163 -0
  112. infrahub/core/schema/definitions/core/profile.py +18 -0
  113. infrahub/core/schema/definitions/core/propose_change.py +97 -0
  114. infrahub/core/schema/definitions/core/propose_change_comment.py +193 -0
  115. infrahub/core/schema/definitions/core/propose_change_validator.py +328 -0
  116. infrahub/core/schema/definitions/core/repository.py +286 -0
  117. infrahub/core/schema/definitions/core/resource_pool.py +170 -0
  118. infrahub/core/schema/definitions/core/template.py +27 -0
  119. infrahub/core/schema/definitions/core/transform.py +96 -0
  120. infrahub/core/schema/definitions/core/webhook.py +134 -0
  121. infrahub/core/schema/definitions/internal.py +16 -16
  122. infrahub/core/schema/dropdown.py +3 -4
  123. infrahub/core/schema/generated/attribute_schema.py +15 -18
  124. infrahub/core/schema/generated/base_node_schema.py +12 -14
  125. infrahub/core/schema/generated/node_schema.py +3 -5
  126. infrahub/core/schema/generated/relationship_schema.py +9 -11
  127. infrahub/core/schema/generic_schema.py +2 -2
  128. infrahub/core/schema/manager.py +20 -9
  129. infrahub/core/schema/node_schema.py +4 -2
  130. infrahub/core/schema/relationship_schema.py +14 -6
  131. infrahub/core/schema/schema_branch.py +292 -144
  132. infrahub/core/schema/schema_branch_computed.py +41 -4
  133. infrahub/core/task/task.py +3 -3
  134. infrahub/core/task/user_task.py +15 -15
  135. infrahub/core/timestamp.py +3 -3
  136. infrahub/core/utils.py +20 -18
  137. infrahub/core/validators/__init__.py +1 -3
  138. infrahub/core/validators/aggregated_checker.py +2 -2
  139. infrahub/core/validators/attribute/choices.py +2 -2
  140. infrahub/core/validators/attribute/enum.py +2 -2
  141. infrahub/core/validators/attribute/kind.py +2 -2
  142. infrahub/core/validators/attribute/length.py +2 -2
  143. infrahub/core/validators/attribute/optional.py +2 -2
  144. infrahub/core/validators/attribute/regex.py +2 -2
  145. infrahub/core/validators/attribute/unique.py +2 -2
  146. infrahub/core/validators/checks_runner.py +25 -2
  147. infrahub/core/validators/determiner.py +1 -3
  148. infrahub/core/validators/interface.py +6 -2
  149. infrahub/core/validators/model.py +22 -3
  150. infrahub/core/validators/models/validate_migration.py +17 -4
  151. infrahub/core/validators/node/attribute.py +2 -2
  152. infrahub/core/validators/node/generate_profile.py +2 -2
  153. infrahub/core/validators/node/hierarchy.py +3 -5
  154. infrahub/core/validators/node/inherit_from.py +27 -5
  155. infrahub/core/validators/node/relationship.py +2 -2
  156. infrahub/core/validators/relationship/count.py +4 -4
  157. infrahub/core/validators/relationship/optional.py +2 -2
  158. infrahub/core/validators/relationship/peer.py +2 -2
  159. infrahub/core/validators/shared.py +2 -2
  160. infrahub/core/validators/tasks.py +8 -0
  161. infrahub/core/validators/uniqueness/checker.py +22 -21
  162. infrahub/core/validators/uniqueness/index.py +2 -2
  163. infrahub/core/validators/uniqueness/model.py +11 -11
  164. infrahub/database/__init__.py +27 -22
  165. infrahub/database/metrics.py +7 -1
  166. infrahub/dependencies/builder/constraint/grouped/node_runner.py +1 -3
  167. infrahub/dependencies/builder/diff/deserializer.py +3 -1
  168. infrahub/dependencies/builder/diff/enricher/hierarchy.py +3 -1
  169. infrahub/dependencies/builder/diff/parent_node_adder.py +8 -0
  170. infrahub/dependencies/component/registry.py +2 -2
  171. infrahub/events/__init__.py +25 -2
  172. infrahub/events/artifact_action.py +64 -0
  173. infrahub/events/branch_action.py +33 -22
  174. infrahub/events/generator.py +71 -0
  175. infrahub/events/group_action.py +51 -21
  176. infrahub/events/models.py +18 -19
  177. infrahub/events/node_action.py +88 -37
  178. infrahub/events/repository_action.py +5 -18
  179. infrahub/events/schema_action.py +4 -9
  180. infrahub/events/utils.py +16 -0
  181. infrahub/events/validator_action.py +55 -0
  182. infrahub/exceptions.py +62 -26
  183. infrahub/generators/models.py +2 -3
  184. infrahub/generators/tasks.py +24 -4
  185. infrahub/git/base.py +87 -36
  186. infrahub/git/integrator.py +48 -48
  187. infrahub/git/models.py +101 -9
  188. infrahub/git/repository.py +3 -3
  189. infrahub/git/tasks.py +408 -6
  190. infrahub/git/utils.py +48 -0
  191. infrahub/git/worktree.py +1 -2
  192. infrahub/git_credential/askpass.py +1 -2
  193. infrahub/graphql/analyzer.py +12 -0
  194. infrahub/graphql/app.py +13 -15
  195. infrahub/graphql/context.py +39 -0
  196. infrahub/graphql/initialization.py +3 -0
  197. infrahub/graphql/loaders/node.py +2 -12
  198. infrahub/graphql/loaders/peers.py +77 -0
  199. infrahub/graphql/loaders/shared.py +13 -0
  200. infrahub/graphql/manager.py +17 -19
  201. infrahub/graphql/mutations/artifact_definition.py +5 -5
  202. infrahub/graphql/mutations/branch.py +26 -1
  203. infrahub/graphql/mutations/computed_attribute.py +9 -5
  204. infrahub/graphql/mutations/diff.py +23 -11
  205. infrahub/graphql/mutations/diff_conflict.py +5 -0
  206. infrahub/graphql/mutations/generator.py +83 -0
  207. infrahub/graphql/mutations/graphql_query.py +5 -5
  208. infrahub/graphql/mutations/ipam.py +54 -74
  209. infrahub/graphql/mutations/main.py +195 -132
  210. infrahub/graphql/mutations/menu.py +7 -7
  211. infrahub/graphql/mutations/models.py +2 -4
  212. infrahub/graphql/mutations/node_getter/by_default_filter.py +10 -10
  213. infrahub/graphql/mutations/node_getter/by_hfid.py +1 -3
  214. infrahub/graphql/mutations/node_getter/by_id.py +1 -3
  215. infrahub/graphql/mutations/node_getter/interface.py +1 -2
  216. infrahub/graphql/mutations/proposed_change.py +7 -7
  217. infrahub/graphql/mutations/relationship.py +93 -19
  218. infrahub/graphql/mutations/repository.py +8 -8
  219. infrahub/graphql/mutations/resource_manager.py +3 -3
  220. infrahub/graphql/mutations/schema.py +19 -4
  221. infrahub/graphql/mutations/webhook.py +137 -0
  222. infrahub/graphql/parser.py +4 -4
  223. infrahub/graphql/permissions.py +1 -10
  224. infrahub/graphql/queries/diff/tree.py +19 -14
  225. infrahub/graphql/queries/event.py +5 -2
  226. infrahub/graphql/queries/ipam.py +2 -2
  227. infrahub/graphql/queries/relationship.py +2 -2
  228. infrahub/graphql/queries/search.py +2 -2
  229. infrahub/graphql/resolvers/many_relationship.py +264 -0
  230. infrahub/graphql/resolvers/resolver.py +13 -110
  231. infrahub/graphql/schema.py +2 -0
  232. infrahub/graphql/subscription/graphql_query.py +2 -0
  233. infrahub/graphql/types/context.py +12 -0
  234. infrahub/graphql/types/event.py +84 -17
  235. infrahub/graphql/types/node.py +2 -2
  236. infrahub/graphql/utils.py +2 -2
  237. infrahub/groups/ancestors.py +29 -0
  238. infrahub/groups/parsers.py +107 -0
  239. infrahub/lock.py +20 -20
  240. infrahub/menu/constants.py +0 -1
  241. infrahub/menu/generator.py +9 -21
  242. infrahub/menu/menu.py +17 -38
  243. infrahub/menu/models.py +117 -16
  244. infrahub/menu/repository.py +111 -0
  245. infrahub/menu/utils.py +5 -8
  246. infrahub/message_bus/__init__.py +11 -13
  247. infrahub/message_bus/messages/__init__.py +1 -21
  248. infrahub/message_bus/messages/check_generator_run.py +3 -3
  249. infrahub/message_bus/messages/finalize_validator_execution.py +3 -0
  250. infrahub/message_bus/messages/proposed_change/request_proposedchange_refreshartifacts.py +6 -0
  251. infrahub/message_bus/messages/request_generatordefinition_check.py +2 -0
  252. infrahub/message_bus/messages/send_echo_request.py +1 -1
  253. infrahub/message_bus/operations/__init__.py +1 -10
  254. infrahub/message_bus/operations/check/__init__.py +2 -2
  255. infrahub/message_bus/operations/check/generator.py +1 -0
  256. infrahub/message_bus/operations/event/__init__.py +2 -2
  257. infrahub/message_bus/operations/event/worker.py +0 -3
  258. infrahub/message_bus/operations/finalize/validator.py +51 -1
  259. infrahub/message_bus/operations/requests/__init__.py +0 -2
  260. infrahub/message_bus/operations/requests/generator_definition.py +21 -23
  261. infrahub/message_bus/operations/requests/proposed_change.py +14 -10
  262. infrahub/permissions/globals.py +15 -0
  263. infrahub/pools/number.py +2 -4
  264. infrahub/proposed_change/models.py +3 -0
  265. infrahub/proposed_change/tasks.py +58 -45
  266. infrahub/pytest_plugin.py +13 -10
  267. infrahub/server.py +2 -3
  268. infrahub/services/__init__.py +2 -2
  269. infrahub/services/adapters/cache/__init__.py +4 -6
  270. infrahub/services/adapters/cache/nats.py +4 -5
  271. infrahub/services/adapters/cache/redis.py +3 -7
  272. infrahub/services/adapters/event/__init__.py +1 -1
  273. infrahub/services/adapters/message_bus/__init__.py +3 -3
  274. infrahub/services/adapters/message_bus/local.py +2 -2
  275. infrahub/services/adapters/message_bus/nats.py +4 -4
  276. infrahub/services/adapters/message_bus/rabbitmq.py +4 -4
  277. infrahub/services/adapters/workflow/local.py +2 -2
  278. infrahub/services/component.py +5 -5
  279. infrahub/services/protocols.py +7 -7
  280. infrahub/services/scheduler.py +1 -3
  281. infrahub/task_manager/event.py +102 -9
  282. infrahub/task_manager/models.py +27 -7
  283. infrahub/tasks/artifact.py +7 -6
  284. infrahub/telemetry/__init__.py +0 -0
  285. infrahub/telemetry/constants.py +9 -0
  286. infrahub/telemetry/database.py +86 -0
  287. infrahub/telemetry/models.py +65 -0
  288. infrahub/telemetry/task_manager.py +77 -0
  289. infrahub/{tasks/telemetry.py → telemetry/tasks.py} +49 -56
  290. infrahub/telemetry/utils.py +11 -0
  291. infrahub/trace.py +4 -4
  292. infrahub/transformations/tasks.py +2 -2
  293. infrahub/trigger/catalogue.py +4 -6
  294. infrahub/trigger/constants.py +0 -8
  295. infrahub/trigger/models.py +54 -5
  296. infrahub/trigger/setup.py +90 -0
  297. infrahub/trigger/tasks.py +35 -83
  298. infrahub/utils.py +11 -1
  299. infrahub/validators/__init__.py +0 -0
  300. infrahub/validators/events.py +42 -0
  301. infrahub/validators/tasks.py +41 -0
  302. infrahub/webhook/gather.py +17 -0
  303. infrahub/webhook/models.py +176 -44
  304. infrahub/webhook/tasks.py +154 -155
  305. infrahub/webhook/triggers.py +31 -7
  306. infrahub/workers/infrahub_async.py +2 -2
  307. infrahub/workers/utils.py +2 -2
  308. infrahub/workflows/catalogue.py +86 -35
  309. infrahub/workflows/initialization.py +8 -2
  310. infrahub/workflows/models.py +27 -1
  311. infrahub/workflows/utils.py +15 -6
  312. infrahub_sdk/client.py +35 -8
  313. infrahub_sdk/config.py +3 -0
  314. infrahub_sdk/context.py +13 -0
  315. infrahub_sdk/ctl/branch.py +3 -2
  316. infrahub_sdk/ctl/cli_commands.py +5 -1
  317. infrahub_sdk/ctl/utils.py +0 -16
  318. infrahub_sdk/exceptions.py +12 -0
  319. infrahub_sdk/generator.py +4 -1
  320. infrahub_sdk/graphql.py +45 -13
  321. infrahub_sdk/node.py +73 -22
  322. infrahub_sdk/protocols.py +21 -8
  323. infrahub_sdk/protocols_base.py +32 -11
  324. infrahub_sdk/query_groups.py +6 -35
  325. infrahub_sdk/schema/__init__.py +55 -26
  326. infrahub_sdk/schema/main.py +8 -0
  327. infrahub_sdk/task/__init__.py +11 -0
  328. infrahub_sdk/task/constants.py +3 -0
  329. infrahub_sdk/task/exceptions.py +25 -0
  330. infrahub_sdk/task/manager.py +551 -0
  331. infrahub_sdk/task/models.py +74 -0
  332. infrahub_sdk/testing/schemas/animal.py +9 -0
  333. infrahub_sdk/timestamp.py +142 -33
  334. infrahub_sdk/utils.py +29 -1
  335. {infrahub_server-1.2.0rc0.dist-info → infrahub_server-1.2.2.dist-info}/METADATA +8 -6
  336. {infrahub_server-1.2.0rc0.dist-info → infrahub_server-1.2.2.dist-info}/RECORD +349 -293
  337. {infrahub_server-1.2.0rc0.dist-info → infrahub_server-1.2.2.dist-info}/entry_points.txt +1 -0
  338. infrahub_testcontainers/constants.py +2 -0
  339. infrahub_testcontainers/container.py +157 -12
  340. infrahub_testcontainers/docker-compose.test.yml +31 -6
  341. infrahub_testcontainers/helpers.py +18 -73
  342. infrahub_testcontainers/host.py +41 -0
  343. infrahub_testcontainers/measurements.py +93 -0
  344. infrahub_testcontainers/models.py +38 -0
  345. infrahub_testcontainers/performance_test.py +166 -0
  346. infrahub_testcontainers/plugin.py +136 -0
  347. infrahub_testcontainers/prometheus.yml +30 -0
  348. infrahub/core/schema/definitions/core.py +0 -2286
  349. infrahub/message_bus/messages/check_repository_checkdefinition.py +0 -20
  350. infrahub/message_bus/messages/check_repository_mergeconflicts.py +0 -16
  351. infrahub/message_bus/messages/check_repository_usercheck.py +0 -26
  352. infrahub/message_bus/messages/event_branch_create.py +0 -11
  353. infrahub/message_bus/messages/event_branch_delete.py +0 -11
  354. infrahub/message_bus/messages/event_branch_rebased.py +0 -9
  355. infrahub/message_bus/messages/event_node_mutated.py +0 -15
  356. infrahub/message_bus/messages/event_schema_update.py +0 -9
  357. infrahub/message_bus/messages/request_repository_checks.py +0 -12
  358. infrahub/message_bus/messages/request_repository_userchecks.py +0 -18
  359. infrahub/message_bus/operations/check/repository.py +0 -293
  360. infrahub/message_bus/operations/event/node.py +0 -20
  361. infrahub/message_bus/operations/event/schema.py +0 -17
  362. infrahub/message_bus/operations/requests/repository.py +0 -133
  363. infrahub/webhook/constants.py +0 -1
  364. {infrahub_server-1.2.0rc0.dist-info → infrahub_server-1.2.2.dist-info}/LICENSE.txt +0 -0
  365. {infrahub_server-1.2.0rc0.dist-info → infrahub_server-1.2.2.dist-info}/WHEEL +0 -0
infrahub_sdk/timestamp.py CHANGED
@@ -1,9 +1,15 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import re
4
+ import warnings
5
+ from datetime import datetime, timezone
6
+ from typing import Literal
4
7
 
5
- import pendulum
6
- from pendulum.datetime import DateTime
8
+ from whenever import Date, Instant, LocalDateTime, OffsetDateTime, Time, ZonedDateTime
9
+
10
+ from .exceptions import TimestampFormatError
11
+
12
+ UTC = timezone.utc # Required for older versions of Python
7
13
 
8
14
  REGEX_MAPPING = {
9
15
  "seconds": r"(\d+)(s|sec|second|seconds)",
@@ -12,80 +18,183 @@ REGEX_MAPPING = {
12
18
  }
13
19
 
14
20
 
15
- class TimestampFormatError(ValueError): ...
16
-
17
-
18
21
  class Timestamp:
19
- def __init__(self, value: str | DateTime | Timestamp | None = None):
20
- if value and isinstance(value, DateTime):
21
- self.obj = value
22
+ _obj: ZonedDateTime
23
+
24
+ def __init__(self, value: str | ZonedDateTime | Timestamp | None = None):
25
+ if value and isinstance(value, ZonedDateTime):
26
+ self._obj = value
22
27
  elif value and isinstance(value, self.__class__):
23
- self.obj = value.obj
28
+ self._obj = value._obj
24
29
  elif isinstance(value, str):
25
- self.obj = self._parse_string(value)
30
+ self._obj = self._parse_string(value)
26
31
  else:
27
- self.obj = DateTime.now(tz="UTC")
32
+ self._obj = ZonedDateTime.now("UTC").round(unit="microsecond")
33
+
34
+ @property
35
+ def obj(self) -> ZonedDateTime:
36
+ warnings.warn(
37
+ "Direct access to obj property is deprecated. Use to_string(), to_timestamp(), or to_datetime() instead.",
38
+ UserWarning,
39
+ stacklevel=2,
40
+ )
41
+ return self._obj
28
42
 
29
43
  @classmethod
30
- def _parse_string(cls, value: str) -> DateTime:
44
+ def _parse_string(cls, value: str) -> ZonedDateTime:
45
+ try:
46
+ zoned_date = ZonedDateTime.parse_common_iso(value)
47
+ return zoned_date
48
+ except ValueError:
49
+ pass
50
+
51
+ try:
52
+ instant_date = Instant.parse_common_iso(value)
53
+ return instant_date.to_tz("UTC")
54
+ except ValueError:
55
+ pass
56
+
57
+ try:
58
+ local_date_time = LocalDateTime.parse_common_iso(value)
59
+ return local_date_time.assume_utc().to_tz("UTC")
60
+ except ValueError:
61
+ pass
62
+
31
63
  try:
32
- parsed_date = pendulum.parse(value)
33
- if isinstance(parsed_date, DateTime):
34
- return parsed_date
35
- except (pendulum.parsing.exceptions.ParserError, ValueError):
64
+ offset_date_time = OffsetDateTime.parse_common_iso(value)
65
+ return offset_date_time.to_tz("UTC")
66
+ except ValueError:
36
67
  pass
37
68
 
38
- params = {}
69
+ try:
70
+ date = Date.parse_common_iso(value)
71
+ local_date = date.at(Time(12, 00))
72
+ return local_date.assume_tz("UTC", disambiguate="compatible")
73
+ except ValueError:
74
+ pass
75
+
76
+ params: dict[str, float] = {}
39
77
  for key, regex in REGEX_MAPPING.items():
40
78
  match = re.search(regex, value)
41
79
  if match:
42
- params[key] = int(match.group(1))
80
+ params[key] = float(match.group(1))
43
81
 
44
- if not params:
45
- raise TimestampFormatError(f"Invalid time format for {value}")
82
+ if params:
83
+ return ZonedDateTime.now("UTC").subtract(**params) # type: ignore[call-overload]
46
84
 
47
- return DateTime.now(tz="UTC").subtract(**params)
85
+ raise TimestampFormatError(f"Invalid time format for {value}")
48
86
 
49
87
  def __repr__(self) -> str:
50
88
  return f"Timestamp: {self.to_string()}"
51
89
 
52
90
  def to_string(self, with_z: bool = True) -> str:
53
- iso8601_string = self.obj.to_iso8601_string()
54
- if not with_z and iso8601_string[-1] == "Z":
55
- iso8601_string = iso8601_string[:-1] + "+00:00"
56
- return iso8601_string
91
+ time_str = self.to_datetime().isoformat(timespec="microseconds")
92
+ if with_z and time_str.endswith("+00:00"):
93
+ time_str = time_str[:-6]
94
+ time_str += "Z"
95
+ return time_str
57
96
 
58
97
  def to_timestamp(self) -> int:
59
- return self.obj.int_timestamp
98
+ return self._obj.timestamp()
99
+
100
+ def to_datetime(self) -> datetime:
101
+ return self._obj.py_datetime()
102
+
103
+ def get_obj(self) -> ZonedDateTime:
104
+ return self._obj
60
105
 
61
106
  def __eq__(self, other: object) -> bool:
62
107
  if not isinstance(other, Timestamp):
63
108
  return NotImplemented
64
- return self.obj == other.obj
109
+ return self._obj == other._obj
65
110
 
66
111
  def __lt__(self, other: object) -> bool:
67
112
  if not isinstance(other, Timestamp):
68
113
  return NotImplemented
69
- return self.obj < other.obj
114
+ return self._obj < other._obj
70
115
 
71
116
  def __gt__(self, other: object) -> bool:
72
117
  if not isinstance(other, Timestamp):
73
118
  return NotImplemented
74
- return self.obj > other.obj
119
+ return self._obj > other._obj
75
120
 
76
121
  def __le__(self, other: object) -> bool:
77
122
  if not isinstance(other, Timestamp):
78
123
  return NotImplemented
79
- return self.obj <= other.obj
124
+ return self._obj <= other._obj
80
125
 
81
126
  def __ge__(self, other: object) -> bool:
82
127
  if not isinstance(other, Timestamp):
83
128
  return NotImplemented
84
- return self.obj >= other.obj
129
+ return self._obj >= other._obj
85
130
 
86
131
  def __hash__(self) -> int:
87
132
  return hash(self.to_string())
88
133
 
89
134
  def add_delta(self, hours: int = 0, minutes: int = 0, seconds: int = 0, microseconds: int = 0) -> Timestamp:
90
- time = self.obj.add(hours=hours, minutes=minutes, seconds=seconds, microseconds=microseconds)
91
- return Timestamp(time)
135
+ warnings.warn(
136
+ "add_delta() is deprecated. Use add() instead.",
137
+ UserWarning,
138
+ stacklevel=2,
139
+ )
140
+ return self.add(hours=hours, minutes=minutes, seconds=seconds, microseconds=microseconds)
141
+
142
+ def add(
143
+ self,
144
+ years: int = 0,
145
+ months: int = 0,
146
+ weeks: int = 0,
147
+ days: int = 0,
148
+ hours: float = 0,
149
+ minutes: float = 0,
150
+ seconds: float = 0,
151
+ milliseconds: float = 0,
152
+ microseconds: float = 0,
153
+ nanoseconds: int = 0,
154
+ disambiguate: Literal["compatible"] = "compatible",
155
+ ) -> Timestamp:
156
+ return Timestamp(
157
+ self._obj.add(
158
+ years=years,
159
+ months=months,
160
+ weeks=weeks,
161
+ days=days,
162
+ hours=hours,
163
+ minutes=minutes,
164
+ seconds=seconds,
165
+ milliseconds=milliseconds,
166
+ microseconds=microseconds,
167
+ nanoseconds=nanoseconds,
168
+ disambiguate=disambiguate,
169
+ )
170
+ )
171
+
172
+ def subtract(
173
+ self,
174
+ years: int = 0,
175
+ months: int = 0,
176
+ weeks: int = 0,
177
+ days: int = 0,
178
+ hours: float = 0,
179
+ minutes: float = 0,
180
+ seconds: float = 0,
181
+ milliseconds: float = 0,
182
+ microseconds: float = 0,
183
+ nanoseconds: int = 0,
184
+ disambiguate: Literal["compatible"] = "compatible",
185
+ ) -> Timestamp:
186
+ return Timestamp(
187
+ self._obj.subtract(
188
+ years=years,
189
+ months=months,
190
+ weeks=weeks,
191
+ days=days,
192
+ hours=hours,
193
+ minutes=minutes,
194
+ seconds=seconds,
195
+ milliseconds=milliseconds,
196
+ microseconds=microseconds,
197
+ nanoseconds=nanoseconds,
198
+ disambiguate=disambiguate,
199
+ )
200
+ )
infrahub_sdk/utils.py CHANGED
@@ -17,10 +17,12 @@ from graphql import (
17
17
 
18
18
  from infrahub_sdk.repository import GitRepoManager
19
19
 
20
- from .exceptions import FileNotValidError, JsonDecodeError
20
+ from .exceptions import FileNotValidError, JsonDecodeError, TimestampFormatError
21
+ from .timestamp import Timestamp
21
22
 
22
23
  if TYPE_CHECKING:
23
24
  from graphql import GraphQLResolveInfo
25
+ from whenever import TimeDelta
24
26
 
25
27
 
26
28
  def base36encode(number: int) -> str:
@@ -367,3 +369,29 @@ def get_user_permissions(data: list[dict]) -> dict:
367
369
  groups[group_name] = permissions
368
370
 
369
371
  return groups
372
+
373
+
374
+ def calculate_time_diff(value: str) -> str | None:
375
+ """Calculate the time in human format between a timedate in string format and now."""
376
+ try:
377
+ time_value = Timestamp(value)
378
+ except TimestampFormatError:
379
+ return None
380
+
381
+ delta: TimeDelta = Timestamp().get_obj().difference(time_value.get_obj())
382
+ (hrs, mins, secs, nanos) = delta.in_hrs_mins_secs_nanos()
383
+
384
+ if nanos and nanos > 500_000_000:
385
+ secs += 1
386
+
387
+ if hrs and hrs < 24 and mins:
388
+ return f"{hrs}h {mins}m and {secs}s ago"
389
+ if hrs and hrs > 24:
390
+ remaining_hrs = hrs % 24
391
+ days = int((hrs - remaining_hrs) / 24)
392
+ return f"{days}d and {remaining_hrs}h ago"
393
+ if hrs == 0 and mins and secs:
394
+ return f"{mins}m and {secs}s ago"
395
+ if hrs == 0 and mins == 0 and secs:
396
+ return f"{secs}s ago"
397
+ return "now"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: infrahub-server
3
- Version: 1.2.0rc0
3
+ Version: 1.2.2
4
4
  Summary: Infrahub is taking a new approach to Infrastructure Management by providing a new generation of datastore to organize and control all the data that defines how an infrastructure should run.
5
5
  Home-page: https://opsmill.com
6
6
  License: AGPL-3.0-only
@@ -29,8 +29,8 @@ Requires-Dist: graphene (>=3.4,<3.5)
29
29
  Requires-Dist: gunicorn (>=23.0.0,<24.0.0)
30
30
  Requires-Dist: lunr (>=0.7.0.post1,<0.8.0)
31
31
  Requires-Dist: nats-py (>=2.7.2,<3.0.0)
32
- Requires-Dist: neo4j (>=5.27,<5.28)
33
- Requires-Dist: neo4j-rust-ext (>=5.27.0.0,<6.0.0.0)
32
+ Requires-Dist: neo4j (>=5.28,<5.29)
33
+ Requires-Dist: neo4j-rust-ext (>=5.28,<5.29)
34
34
  Requires-Dist: netaddr (==1.3.0)
35
35
  Requires-Dist: numpy (>=1.24.2,<2.0.0) ; python_version >= "3.9" and python_version < "3.12"
36
36
  Requires-Dist: numpy (>=1.26.2,<2.0.0) ; python_version >= "3.12"
@@ -38,10 +38,11 @@ Requires-Dist: opentelemetry-exporter-otlp-proto-grpc (==1.28.1)
38
38
  Requires-Dist: opentelemetry-exporter-otlp-proto-http (==1.28.1)
39
39
  Requires-Dist: opentelemetry-instrumentation-aio-pika (==0.49b1)
40
40
  Requires-Dist: opentelemetry-instrumentation-fastapi (==0.49b1)
41
- Requires-Dist: prefect (==3.1.14)
41
+ Requires-Dist: prefect (==3.2.11)
42
+ Requires-Dist: prefect-redis (==0.2.2)
42
43
  Requires-Dist: pyarrow (>=14,<15)
43
- Requires-Dist: pydantic (>=2.9,<2.10)
44
- Requires-Dist: pydantic-settings (>=2.7,<2.8)
44
+ Requires-Dist: pydantic (>=2.10,<2.11)
45
+ Requires-Dist: pydantic-settings (>=2.8,<2.9)
45
46
  Requires-Dist: pyjwt (>=2.8,<2.9)
46
47
  Requires-Dist: pytest (>=7.4,<7.5)
47
48
  Requires-Dist: python-multipart (==0.0.18)
@@ -54,6 +55,7 @@ Requires-Dist: toml (>=0.10,<0.11)
54
55
  Requires-Dist: typer (==0.12.5)
55
56
  Requires-Dist: ujson (>=5,<6)
56
57
  Requires-Dist: uvicorn[standard] (>=0.32,<0.33)
58
+ Requires-Dist: whenever (==0.7.2)
57
59
  Project-URL: Documentation, https://docs.infrahub.app/
58
60
  Project-URL: Repository, https://github.com/opsmill/infrahub
59
61
  Description-Content-Type: text/markdown