datajunction 0.0.1a67__tar.gz → 0.0.1a68.dev0__tar.gz

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 (119) hide show
  1. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/PKG-INFO +1 -2
  2. datajunction-0.0.1a68.dev0/datajunction/__about__.py +4 -0
  3. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/datajunction/builder.py +30 -20
  4. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/datajunction/compile.py +161 -97
  5. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/datajunction/exceptions.py +4 -0
  6. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/datajunction/nodes.py +5 -4
  7. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/datajunction/tags.py +0 -12
  8. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/pdm.lock +164 -206
  9. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/pyproject.toml +0 -1
  10. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/conftest.py +6 -0
  11. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project1/dj.yaml +3 -0
  12. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project1/roads/avg_length_of_employment.metric.yaml +3 -0
  13. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/test_builder.py +63 -4
  14. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/test_compile.py +84 -4
  15. datajunction-0.0.1a67/datajunction/__about__.py +0 -4
  16. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/.coveragerc +0 -0
  17. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/.gitignore +0 -0
  18. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/.isort.cfg +0 -0
  19. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/.pre-commit-config.yaml +0 -0
  20. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/LICENSE.txt +0 -0
  21. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/Makefile +0 -0
  22. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/README.md +0 -0
  23. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/datajunction/__init__.py +0 -0
  24. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/datajunction/_internal.py +0 -0
  25. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/datajunction/admin.py +0 -0
  26. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/datajunction/client.py +0 -0
  27. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/datajunction/models.py +0 -0
  28. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/setup.cfg +0 -0
  29. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/__init__.py +0 -0
  30. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project1/roads/avg_repair_price.metric.yaml +0 -0
  31. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project1/roads/avg_time_to_dispatch.metric.yaml +0 -0
  32. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project1/roads/contractor.dimension.yaml +0 -0
  33. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project1/roads/contractors.source.yaml +0 -0
  34. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project1/roads/date.source.yaml +0 -0
  35. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project1/roads/date_dim.dimension.yaml +0 -0
  36. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project1/roads/dispatcher.dimension.yaml +0 -0
  37. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project1/roads/dispatchers.source.yaml +0 -0
  38. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project1/roads/hard_hat.dimension.yaml +0 -0
  39. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project1/roads/hard_hat_state.source.yaml +0 -0
  40. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project1/roads/hard_hats.source.yaml +0 -0
  41. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project1/roads/local_hard_hats.dimension.yaml +0 -0
  42. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project1/roads/municipality.source.yaml +0 -0
  43. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project1/roads/municipality_dim.dimension.yaml +0 -0
  44. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project1/roads/municipality_municipality_type.source.yaml +0 -0
  45. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project1/roads/municipality_type.source.yaml +0 -0
  46. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project1/roads/national_level_agg.transform.yaml +0 -0
  47. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project1/roads/num_repair_orders.metric.yaml +0 -0
  48. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project1/roads/regional_level_agg.transform.yaml +0 -0
  49. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project1/roads/regional_repair_efficiency.metric.yaml +0 -0
  50. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project1/roads/repair_order.dimension.yaml +0 -0
  51. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project1/roads/repair_order_details.source.yaml +0 -0
  52. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project1/roads/repair_order_transform.transform.yaml +0 -0
  53. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project1/roads/repair_orders.source.yaml +0 -0
  54. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project1/roads/repair_orders_cube.cube.yaml +0 -0
  55. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project1/roads/repair_type.source.yaml +0 -0
  56. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project1/roads/total_repair_cost.metric.yaml +0 -0
  57. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project1/roads/total_repair_order_discounts.metric.yaml +0 -0
  58. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project1/roads/us_region.source.yaml +0 -0
  59. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project1/roads/us_state.dimension.yaml +0 -0
  60. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project1/roads/us_states.source.yaml +0 -0
  61. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project10/dj.yaml +0 -0
  62. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project11/avg_length_of_employment.metric.yaml +0 -0
  63. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project11/avg_repair_price.metric.yaml +0 -0
  64. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project11/avg_time_to_dispatch.metric.yaml +0 -0
  65. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project11/contractor.dimension.yaml +0 -0
  66. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project11/contractors.source.yaml +0 -0
  67. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project11/date.source.yaml +0 -0
  68. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project11/date_dim.dimension.yaml +0 -0
  69. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project11/dispatcher.dimension.yaml +0 -0
  70. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project11/dispatchers.source.yaml +0 -0
  71. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project11/dj.yaml +0 -0
  72. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project11/hard_hat.dimension.yaml +0 -0
  73. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project11/hard_hat_state.source.yaml +0 -0
  74. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project11/hard_hats.source.yaml +0 -0
  75. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project11/local_hard_hats.dimension.yaml +0 -0
  76. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project11/municipality.source.yaml +0 -0
  77. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project11/municipality_dim.dimension.yaml +0 -0
  78. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project11/municipality_municipality_type.source.yaml +0 -0
  79. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project11/municipality_type.source.yaml +0 -0
  80. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project11/national_level_agg.transform.yaml +0 -0
  81. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project11/num_repair_orders.metric.yaml +0 -0
  82. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project11/regional_level_agg.transform.yaml +0 -0
  83. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project11/regional_repair_efficiency.metric.yaml +0 -0
  84. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project11/repair_order.dimension.yaml +0 -0
  85. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project11/repair_order_details.source.yaml +0 -0
  86. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project11/repair_order_transform.transform.yaml +0 -0
  87. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project11/repair_orders.source.yaml +0 -0
  88. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project11/repair_orders_cube.cube.yaml +0 -0
  89. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project11/repair_type.source.yaml +0 -0
  90. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project11/total_repair_cost.metric.yaml +0 -0
  91. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project11/total_repair_order_discounts.metric.yaml +0 -0
  92. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project11/us_region.source.yaml +0 -0
  93. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project11/us_state.dimension.yaml +0 -0
  94. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project11/us_states.source.yaml +0 -0
  95. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project2/dj.yaml +0 -0
  96. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project2/some_node.source.yaml +0 -0
  97. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project3/dj.yaml +0 -0
  98. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project3/some_node.yaml +0 -0
  99. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project4/dj.yaml +0 -0
  100. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project4/very/very/deeply/nested/namespace/some_node.source.yaml +0 -0
  101. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project5/dj.yaml +0 -0
  102. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project5/some_node.a.b.c.source.yaml +0 -0
  103. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project6/dj.yaml +0 -0
  104. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project6/roads/contractor.dimension.yaml +0 -0
  105. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project6/roads/contractors.source.yaml +0 -0
  106. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project7/dj.yaml +0 -0
  107. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project7/roads/contractor.dimension.yaml +0 -0
  108. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project7/roads/contractors.source.yaml +0 -0
  109. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project8/dj.yaml +0 -0
  110. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project9/dj.yaml +0 -0
  111. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples/project9/roads/contractor.dimension.yaml +0 -0
  112. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/examples.py +0 -0
  113. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/test__internal.py +0 -0
  114. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/test_admin.py +0 -0
  115. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/test_client.py +0 -0
  116. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/test_generated_client.py +0 -0
  117. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/test_integration.py +0 -0
  118. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tests/test_models.py +0 -0
  119. {datajunction-0.0.1a67 → datajunction-0.0.1a68.dev0}/tox.ini +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: datajunction
3
- Version: 0.0.1a67
3
+ Version: 0.0.1a68.dev0
4
4
  Summary: DataJunction client library for connecting to a DataJunction server
5
5
  Project-URL: repository, https://github.com/DataJunction/dj
6
6
  Author-email: DataJunction Authors <yian.shang@gmail.com>
@@ -15,7 +15,6 @@ Classifier: Programming Language :: Python :: 3.11
15
15
  Classifier: Programming Language :: Python :: 3.12
16
16
  Requires-Python: <4.0,>=3.8
17
17
  Requires-Dist: alive-progress>=3.1.2
18
- Requires-Dist: fastapi-cache2>=0.2.1
19
18
  Requires-Dist: httpx>=0.27.0
20
19
  Requires-Dist: pytest-xdist>=3.5.0
21
20
  Requires-Dist: pyyaml>=6.0.1
@@ -0,0 +1,4 @@
1
+ """
2
+ Version for Hatch
3
+ """
4
+ __version__ = "0.0.1a68.dev0"
@@ -11,6 +11,7 @@ from datajunction.exceptions import (
11
11
  DJClientException,
12
12
  DJNamespaceAlreadyExists,
13
13
  DJTableAlreadyRegistered,
14
+ DJTagAlreadyExists,
14
15
  DJViewAlreadyRegistered,
15
16
  )
16
17
  from datajunction.nodes import (
@@ -42,7 +43,11 @@ class DJBuilder(DJClient): # pylint: disable=too-many-public-methods
42
43
  raise DJClientException(f"Namespace `{namespace}` does not exist.")
43
44
  return Namespace(namespace=namespace, dj_client=self)
44
45
 
45
- def create_namespace(self, namespace: str) -> "Namespace":
46
+ def create_namespace(
47
+ self,
48
+ namespace: str,
49
+ skip_if_exists: bool = False,
50
+ ) -> "Namespace":
46
51
  """
47
52
  Create a namespace with a given name.
48
53
  """
@@ -51,7 +56,7 @@ class DJBuilder(DJClient): # pylint: disable=too-many-public-methods
51
56
  timeout=self._timeout,
52
57
  )
53
58
  json_response = response.json()
54
- if response.status_code == 409:
59
+ if response.status_code == 409 and not skip_if_exists:
55
60
  raise DJNamespaceAlreadyExists(json_response["message"])
56
61
  return Namespace(namespace=namespace, dj_client=self)
57
62
 
@@ -128,7 +133,7 @@ class DJBuilder(DJClient): # pylint: disable=too-many-public-methods
128
133
  type_: models.NodeType,
129
134
  name: str,
130
135
  data: Dict,
131
- update_if_exists: bool = True,
136
+ update_if_exists: bool = False,
132
137
  ):
133
138
  """
134
139
  Create or update a new node
@@ -147,24 +152,24 @@ class DJBuilder(DJClient): # pylint: disable=too-many-public-methods
147
152
  # This check is for the unit tests, which don't raise an exception
148
153
  # for >= 400 status codes
149
154
  if "name" in cube_dict:
150
- data["metrics"] = cube_dict["cube_node_metrics"]
151
- data["dimensions"] = cube_dict["cube_node_dimensions"]
155
+ existing_node_dict["metrics"] = cube_dict["cube_node_metrics"]
156
+ existing_node_dict["dimensions"] = cube_dict["cube_node_dimensions"]
152
157
  except DJClientException as e: # pragma: no cover # pytest fixture doesn't raise
153
158
  if re.search(r"node .* does not exist", str(e)):
154
159
  existing_node_dict = None
155
160
  else:
156
161
  raise
157
162
 
158
- # pylint: disable=fixme
159
- # TODO: checking for "name" in existing_node_dict is a workaround
163
+ # Checking for "name" in existing_node_dict is a workaround
160
164
  # to accommodate pytest mock client, which return a error message dict (no "name")
161
165
  # instead of raising like the real client.
162
166
  if existing_node_dict and "name" in existing_node_dict:
163
167
  # update
164
168
  if update_if_exists:
169
+ existing_node_dict.update(data)
165
170
  new_node = self.make_node_of_type(
166
171
  type_=type_,
167
- data=data,
172
+ data=existing_node_dict,
168
173
  )
169
174
  new_node._update_tags()
170
175
  new_node._update()
@@ -227,9 +232,9 @@ class DJBuilder(DJClient): # pylint: disable=too-many-public-methods
227
232
  description: Optional[str] = None,
228
233
  columns: Optional[List[models.Column]] = None,
229
234
  primary_key: Optional[List[str]] = None,
230
- tags: Optional[List[Tag]] = None,
235
+ tags: Optional[List[str]] = None,
231
236
  mode: Optional[models.NodeMode] = models.NodeMode.PUBLISHED,
232
- update_if_exists: bool = True,
237
+ update_if_exists: bool = False,
233
238
  ) -> "Source":
234
239
  """
235
240
  Creates a new Source node with given parameters.
@@ -341,9 +346,9 @@ class DJBuilder(DJClient): # pylint: disable=too-many-public-methods
341
346
  description: Optional[str] = None,
342
347
  display_name: Optional[str] = None,
343
348
  primary_key: Optional[List[str]] = None,
344
- tags: Optional[List[Tag]] = None,
349
+ tags: Optional[List[str]] = None,
345
350
  mode: Optional[models.NodeMode] = models.NodeMode.PUBLISHED,
346
- update_if_exists: bool = True,
351
+ update_if_exists: bool = False,
347
352
  ) -> "Transform":
348
353
  """
349
354
  Creates or update a Transform node with given parameters.
@@ -373,9 +378,9 @@ class DJBuilder(DJClient): # pylint: disable=too-many-public-methods
373
378
  primary_key: Optional[List[str]] = None,
374
379
  description: Optional[str] = None,
375
380
  display_name: Optional[str] = None,
376
- tags: Optional[List[Tag]] = None,
381
+ tags: Optional[List[str]] = None,
377
382
  mode: Optional[models.NodeMode] = models.NodeMode.PUBLISHED,
378
- update_if_exists: bool = True,
383
+ update_if_exists: bool = False,
379
384
  ) -> "Dimension":
380
385
  """
381
386
  Creates or update a Dimension node with given parameters.
@@ -407,9 +412,9 @@ class DJBuilder(DJClient): # pylint: disable=too-many-public-methods
407
412
  required_dimensions: Optional[List[str]] = None,
408
413
  direction: Optional[models.MetricDirection] = None,
409
414
  unit: Optional[models.MetricUnit] = None,
410
- tags: Optional[List[Tag]] = None,
415
+ tags: Optional[List[str]] = None,
411
416
  mode: Optional[models.NodeMode] = models.NodeMode.PUBLISHED,
412
- update_if_exists: bool = True,
417
+ update_if_exists: bool = False,
413
418
  ) -> "Metric":
414
419
  """
415
420
  Creates or update a Metric node with given parameters.
@@ -451,8 +456,8 @@ class DJBuilder(DJClient): # pylint: disable=too-many-public-methods
451
456
  description: Optional[str] = None,
452
457
  display_name: Optional[str] = None,
453
458
  mode: Optional[models.NodeMode] = models.NodeMode.PUBLISHED,
454
- tags: Optional[List[Tag]] = None,
455
- update_if_exists: bool = True,
459
+ tags: Optional[List[str]] = None,
460
+ update_if_exists: bool = False,
456
461
  ) -> "Cube":
457
462
  """
458
463
  Create or update a cube with the given parameters.
@@ -476,12 +481,13 @@ class DJBuilder(DJClient): # pylint: disable=too-many-public-methods
476
481
  #
477
482
  # Tag
478
483
  #
479
- def create_tag(
484
+ def create_tag( # pylint: disable=too-many-arguments
480
485
  self,
481
486
  name: str,
482
487
  description: Optional[str],
483
488
  tag_metadata: Dict,
484
489
  tag_type: str,
490
+ skip_if_exists: bool = False,
485
491
  ) -> Tag:
486
492
  """
487
493
  Create a tag with a given name.
@@ -493,6 +499,10 @@ class DJBuilder(DJClient): # pylint: disable=too-many-public-methods
493
499
  tag_type=tag_type,
494
500
  tag_metadata=tag_metadata,
495
501
  )
496
- self._create_tag(tag=new_tag)
502
+ try:
503
+ self._create_tag(tag=new_tag)
504
+ except DJTagAlreadyExists as exc:
505
+ if not skip_if_exists:
506
+ raise exc
497
507
  new_tag.refresh()
498
508
  return new_tag