gooddata-dbt 1.72.1.dev1__tar.gz → 1.72.1.dev2__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 (60) hide show
  1. {gooddata_dbt-1.72.1.dev1 → gooddata_dbt-1.72.1.dev2}/PKG-INFO +3 -2
  2. {gooddata_dbt-1.72.1.dev1 → gooddata_dbt-1.72.1.dev2}/README.md +1 -0
  3. {gooddata_dbt-1.72.1.dev1 → gooddata_dbt-1.72.1.dev2}/pyproject.toml +2 -2
  4. {gooddata_dbt-1.72.1.dev1 → gooddata_dbt-1.72.1.dev2}/src/gooddata_dbt/args.py +10 -0
  5. {gooddata_dbt-1.72.1.dev1 → gooddata_dbt-1.72.1.dev2}/src/gooddata_dbt/dbt/base.py +7 -0
  6. {gooddata_dbt-1.72.1.dev1 → gooddata_dbt-1.72.1.dev2}/src/gooddata_dbt/dbt/tables.py +19 -7
  7. {gooddata_dbt-1.72.1.dev1 → gooddata_dbt-1.72.1.dev2}/src/gooddata_dbt/dbt_plugin.py +5 -1
  8. gooddata_dbt-1.72.1.dev2/tests/test_args.py +12 -0
  9. {gooddata_dbt-1.72.1.dev1 → gooddata_dbt-1.72.1.dev2}/tests/test_tables.py +36 -1
  10. {gooddata_dbt-1.72.1.dev1 → gooddata_dbt-1.72.1.dev2}/.env.custom.dev +0 -0
  11. {gooddata_dbt-1.72.1.dev1 → gooddata_dbt-1.72.1.dev2}/.env.dev +0 -0
  12. {gooddata_dbt-1.72.1.dev1 → gooddata_dbt-1.72.1.dev2}/.gitignore +0 -0
  13. {gooddata_dbt-1.72.1.dev1 → gooddata_dbt-1.72.1.dev2}/LICENSE.txt +0 -0
  14. {gooddata_dbt-1.72.1.dev1 → gooddata_dbt-1.72.1.dev2}/Makefile +0 -0
  15. {gooddata_dbt-1.72.1.dev1 → gooddata_dbt-1.72.1.dev2}/bin/gooddata-dbt +0 -0
  16. {gooddata_dbt-1.72.1.dev1 → gooddata_dbt-1.72.1.dev2}/gooddata_example.yml +0 -0
  17. {gooddata_dbt-1.72.1.dev1 → gooddata_dbt-1.72.1.dev2}/src/gooddata_dbt/__init__.py +0 -0
  18. {gooddata_dbt-1.72.1.dev1 → gooddata_dbt-1.72.1.dev2}/src/gooddata_dbt/_version.py +0 -0
  19. {gooddata_dbt-1.72.1.dev1 → gooddata_dbt-1.72.1.dev2}/src/gooddata_dbt/dbt/__init__.py +0 -0
  20. {gooddata_dbt-1.72.1.dev1 → gooddata_dbt-1.72.1.dev2}/src/gooddata_dbt/dbt/cloud.py +0 -0
  21. {gooddata_dbt-1.72.1.dev1 → gooddata_dbt-1.72.1.dev2}/src/gooddata_dbt/dbt/environment.py +0 -0
  22. {gooddata_dbt-1.72.1.dev1 → gooddata_dbt-1.72.1.dev2}/src/gooddata_dbt/dbt/metrics.py +0 -0
  23. {gooddata_dbt-1.72.1.dev1 → gooddata_dbt-1.72.1.dev2}/src/gooddata_dbt/dbt/profiles.py +0 -0
  24. {gooddata_dbt-1.72.1.dev1 → gooddata_dbt-1.72.1.dev2}/src/gooddata_dbt/gooddata/__init__.py +0 -0
  25. {gooddata_dbt-1.72.1.dev1 → gooddata_dbt-1.72.1.dev2}/src/gooddata_dbt/gooddata/api_wrapper.py +0 -0
  26. {gooddata_dbt-1.72.1.dev1 → gooddata_dbt-1.72.1.dev2}/src/gooddata_dbt/gooddata/config.py +0 -0
  27. {gooddata_dbt-1.72.1.dev1 → gooddata_dbt-1.72.1.dev2}/src/gooddata_dbt/logger.py +0 -0
  28. {gooddata_dbt-1.72.1.dev1 → gooddata_dbt-1.72.1.dev2}/src/gooddata_dbt/main.py +0 -0
  29. {gooddata_dbt-1.72.1.dev1 → gooddata_dbt-1.72.1.dev2}/src/gooddata_dbt/sdk_wrapper.py +0 -0
  30. {gooddata_dbt-1.72.1.dev1 → gooddata_dbt-1.72.1.dev2}/src/gooddata_dbt/utils.py +0 -0
  31. {gooddata_dbt-1.72.1.dev1 → gooddata_dbt-1.72.1.dev2}/tests/conftest.py +0 -0
  32. {gooddata_dbt-1.72.1.dev1 → gooddata_dbt-1.72.1.dev2}/tests/gooddata_example.yml +0 -0
  33. {gooddata_dbt-1.72.1.dev1 → gooddata_dbt-1.72.1.dev2}/tests/resources/dbt_profiles/profiles.yml +0 -0
  34. {gooddata_dbt-1.72.1.dev1 → gooddata_dbt-1.72.1.dev2}/tests/resources/dbt_target/manifest.json +0 -0
  35. {gooddata_dbt-1.72.1.dev1 → gooddata_dbt-1.72.1.dev2}/tests/resources/gooddata_layouts/pdm/aircraft.yaml +0 -0
  36. {gooddata_dbt-1.72.1.dev1 → gooddata_dbt-1.72.1.dev2}/tests/resources/gooddata_layouts/pdm/aircraft_models.yaml +0 -0
  37. {gooddata_dbt-1.72.1.dev1 → gooddata_dbt-1.72.1.dev2}/tests/resources/gooddata_layouts/pdm/airports.yaml +0 -0
  38. {gooddata_dbt-1.72.1.dev1 → gooddata_dbt-1.72.1.dev2}/tests/resources/gooddata_layouts/pdm/ambient_temperature.yaml +0 -0
  39. {gooddata_dbt-1.72.1.dev1 → gooddata_dbt-1.72.1.dev2}/tests/resources/gooddata_layouts/pdm/carriers.yaml +0 -0
  40. {gooddata_dbt-1.72.1.dev1 → gooddata_dbt-1.72.1.dev2}/tests/resources/gooddata_layouts/pdm/census.yaml +0 -0
  41. {gooddata_dbt-1.72.1.dev1 → gooddata_dbt-1.72.1.dev2}/tests/resources/gooddata_layouts/pdm/census_by_country.yaml +0 -0
  42. {gooddata_dbt-1.72.1.dev1 → gooddata_dbt-1.72.1.dev2}/tests/resources/gooddata_layouts/pdm/commits.yaml +0 -0
  43. {gooddata_dbt-1.72.1.dev1 → gooddata_dbt-1.72.1.dev2}/tests/resources/gooddata_layouts/pdm/customer.yaml +0 -0
  44. {gooddata_dbt-1.72.1.dev1 → gooddata_dbt-1.72.1.dev2}/tests/resources/gooddata_layouts/pdm/eshop_customers.yaml +0 -0
  45. {gooddata_dbt-1.72.1.dev1 → gooddata_dbt-1.72.1.dev2}/tests/resources/gooddata_layouts/pdm/flights.yaml +0 -0
  46. {gooddata_dbt-1.72.1.dev1 → gooddata_dbt-1.72.1.dev2}/tests/resources/gooddata_layouts/pdm/home_rentals.yaml +0 -0
  47. {gooddata_dbt-1.72.1.dev1 → gooddata_dbt-1.72.1.dev2}/tests/resources/gooddata_layouts/pdm/house_property_sales_time_series.yaml +0 -0
  48. {gooddata_dbt-1.72.1.dev1 → gooddata_dbt-1.72.1.dev2}/tests/resources/gooddata_layouts/pdm/mall_customers.yaml +0 -0
  49. {gooddata_dbt-1.72.1.dev1 → gooddata_dbt-1.72.1.dev2}/tests/resources/gooddata_layouts/pdm/monthlyinventory.yaml +0 -0
  50. {gooddata_dbt-1.72.1.dev1 → gooddata_dbt-1.72.1.dev2}/tests/resources/gooddata_layouts/pdm/order_lines.yaml +0 -0
  51. {gooddata_dbt-1.72.1.dev1 → gooddata_dbt-1.72.1.dev2}/tests/resources/gooddata_layouts/pdm/orders.yaml +0 -0
  52. {gooddata_dbt-1.72.1.dev1 → gooddata_dbt-1.72.1.dev2}/tests/resources/gooddata_layouts/pdm/product.yaml +0 -0
  53. {gooddata_dbt-1.72.1.dev1 → gooddata_dbt-1.72.1.dev2}/tests/resources/gooddata_layouts/pdm/pull_requests.yaml +0 -0
  54. {gooddata_dbt-1.72.1.dev1 → gooddata_dbt-1.72.1.dev2}/tests/resources/gooddata_layouts/pdm/repos.yaml +0 -0
  55. {gooddata_dbt-1.72.1.dev1 → gooddata_dbt-1.72.1.dev2}/tests/resources/gooddata_layouts/pdm/returns.yaml +0 -0
  56. {gooddata_dbt-1.72.1.dev1 → gooddata_dbt-1.72.1.dev2}/tests/resources/gooddata_layouts/pdm/telco_customer_churn.yaml +0 -0
  57. {gooddata_dbt-1.72.1.dev1 → gooddata_dbt-1.72.1.dev2}/tests/resources/gooddata_layouts/pdm/users.yaml +0 -0
  58. {gooddata_dbt-1.72.1.dev1 → gooddata_dbt-1.72.1.dev2}/tests/resources/gooddata_layouts/pdm/workflow_runs.yaml +0 -0
  59. {gooddata_dbt-1.72.1.dev1 → gooddata_dbt-1.72.1.dev2}/tests/test_profiles.py +0 -0
  60. {gooddata_dbt-1.72.1.dev1 → gooddata_dbt-1.72.1.dev2}/tox.ini +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gooddata-dbt
3
- Version: 1.72.1.dev1
3
+ Version: 1.72.1.dev2
4
4
  Summary: dbt plugin for GoodData
5
5
  Author-email: GoodData <support@gooddata.com>
6
6
  License-Expression: MIT
@@ -19,7 +19,7 @@ Classifier: Typing :: Typed
19
19
  Requires-Python: >=3.10
20
20
  Requires-Dist: attrs<=24.2.0,>=21.4.0
21
21
  Requires-Dist: cattrs<=24.1.1,>=22.1.0
22
- Requires-Dist: gooddata-sdk~=1.72.1.dev1
22
+ Requires-Dist: gooddata-sdk~=1.72.1.dev2
23
23
  Requires-Dist: pyyaml>=6.0
24
24
  Requires-Dist: requests~=2.32.0
25
25
  Requires-Dist: tabulate~=0.8.10
@@ -77,6 +77,7 @@ The plugin provides the following use cases:
77
77
  - Reads dbt models and profiles
78
78
  - Scans data source (connection props from dbt profiles) through GoodData to get column data types (optional in dbt)
79
79
  - Generates GoodData LDM(Logical Data Model) from dbt models. Can utilize custom gooddata-specific metadata, more below
80
+ - With `--gooddata-enable-second-granularities`, date datasets are created with second-based granularities.
80
81
  - upload_notification
81
82
  - Invalidates caches for data source
82
83
  - deploy_analytics
@@ -50,6 +50,7 @@ The plugin provides the following use cases:
50
50
  - Reads dbt models and profiles
51
51
  - Scans data source (connection props from dbt profiles) through GoodData to get column data types (optional in dbt)
52
52
  - Generates GoodData LDM(Logical Data Model) from dbt models. Can utilize custom gooddata-specific metadata, more below
53
+ - With `--gooddata-enable-second-granularities`, date datasets are created with second-based granularities.
53
54
  - upload_notification
54
55
  - Invalidates caches for data source
55
56
  - deploy_analytics
@@ -1,7 +1,7 @@
1
1
  # (C) 2025 GoodData Corporation
2
2
  [project]
3
3
  name = "gooddata-dbt"
4
- version = "1.72.1.dev1"
4
+ version = "1.72.1.dev2"
5
5
  description = "dbt plugin for GoodData"
6
6
  readme = "README.md"
7
7
  license = "MIT"
@@ -10,7 +10,7 @@ authors = [
10
10
  ]
11
11
  requires-python = ">=3.10"
12
12
  dependencies = [
13
- "gooddata-sdk~=1.72.1.dev1",
13
+ "gooddata-sdk~=1.72.1.dev2",
14
14
  "pyyaml>=6.0",
15
15
  "attrs>=21.4.0,<=24.2.0",
16
16
  "cattrs>=22.1.0,<=24.1.1",
@@ -67,6 +67,15 @@ def set_gooddata_upper_case_args(parser: argparse.ArgumentParser) -> None:
67
67
  )
68
68
 
69
69
 
70
+ def set_gooddata_enable_second_granularities_args(parser: argparse.ArgumentParser) -> None:
71
+ parser.add_argument(
72
+ "--gooddata-enable-second-granularities",
73
+ help="Create date datasets with second-based granularities.",
74
+ action="store_true",
75
+ default=False,
76
+ )
77
+
78
+
70
79
  def set_gooddata_workspace_title_args(parser: argparse.ArgumentParser) -> None:
71
80
  parser.add_argument(
72
81
  "-gwt", "--gooddata-workspace-title", help="Workspace title", default=os.getenv("GOODDATA_WORKSPACE_TITLE")
@@ -169,6 +178,7 @@ def parse_arguments(description: str) -> argparse.Namespace:
169
178
  set_dbt_args(deploy_ldm)
170
179
  set_environment_id_arg(deploy_ldm)
171
180
  set_gooddata_upper_case_args(deploy_ldm)
181
+ set_gooddata_enable_second_granularities_args(deploy_ldm)
172
182
  deploy_ldm.set_defaults(method="deploy_ldm")
173
183
 
174
184
  upload_notification = subparsers.add_parser("upload_notification")
@@ -52,6 +52,13 @@ TIMESTAMP_GRANULARITIES = [
52
52
  "MINUTE_OF_HOUR",
53
53
  "HOUR_OF_DAY",
54
54
  ]
55
+ # newly added granularities gated behind `enableSecondGranularities` feature flag
56
+ SECOND_TIMESTAMP_GRANULARITIES = [
57
+ "SECOND",
58
+ "SECOND_OF_MINUTE",
59
+ "SECOND_OF_DAY",
60
+ "MINUTE_OF_DAY",
61
+ ]
55
62
  T = TypeVar("T", bound="Base")
56
63
 
57
64
  DBT_TARGET_DIR = Path("target")
@@ -18,6 +18,7 @@ from gooddata_dbt.dbt.base import (
18
18
  DBT_PATH_TO_MANIFEST,
19
19
  DBT_TARGET_DIR,
20
20
  NUMERIC_DATA_TYPES,
21
+ SECOND_TIMESTAMP_GRANULARITIES,
21
22
  TIMESTAMP_DATA_TYPES,
22
23
  TIMESTAMP_GRANULARITIES,
23
24
  Base,
@@ -202,9 +203,12 @@ class DbtModelTables:
202
203
  * column_type – Optional if missing call scan
203
204
  """
204
205
 
205
- def __init__(self, tables: list[DbtModelTable], upper_case: bool) -> None:
206
+ def __init__(
207
+ self, tables: list[DbtModelTable], upper_case: bool, enable_second_granularities: bool = False
208
+ ) -> None:
206
209
  self.upper_case = upper_case
207
210
  self.tables = tables
211
+ self._enable_second_granularities = enable_second_granularities
208
212
 
209
213
  @classmethod
210
214
  def from_cloud(
@@ -214,22 +218,27 @@ class DbtModelTables:
214
218
  upper_case: bool,
215
219
  all_model_ids: list[str],
216
220
  path: Union[str, Path] = DBT_TARGET_DIR,
221
+ enable_second_granularities: bool = False,
217
222
  ) -> "DbtModelTables":
218
223
  path = path if isinstance(path, Path) else Path(path)
219
224
  dbt_conn.download_manifest(run_id=run_id, path=path)
220
225
  with open(path / "manifest.json") as fp:
221
226
  dbt_catalog = json.load(fp)
222
227
  tables = cls.read_dbt_models(dbt_catalog, upper_case, all_model_ids)
223
- return cls(tables, upper_case)
228
+ return cls(tables, upper_case, enable_second_granularities)
224
229
 
225
230
  @classmethod
226
231
  def from_local(
227
- cls, upper_case: bool, all_model_ids: list[str], manifest_path: Union[str, Path] = DBT_PATH_TO_MANIFEST
232
+ cls,
233
+ upper_case: bool,
234
+ all_model_ids: list[str],
235
+ manifest_path: Union[str, Path] = DBT_PATH_TO_MANIFEST,
236
+ enable_second_granularities: bool = False,
228
237
  ) -> "DbtModelTables":
229
238
  with open(manifest_path) as fp:
230
239
  dbt_catalog = json.load(fp)
231
240
  tables = cls.read_dbt_models(dbt_catalog, upper_case, all_model_ids)
232
- return cls(tables, upper_case)
241
+ return cls(tables, upper_case, enable_second_granularities)
233
242
 
234
243
  @staticmethod
235
244
  def read_dbt_models(dbt_catalog: dict, upper_case: bool, all_model_ids: list[str]) -> list[DbtModelTable]:
@@ -437,14 +446,17 @@ class DbtModelTables:
437
446
  )
438
447
  return attributes
439
448
 
440
- @staticmethod
441
- def make_date_datasets(table: DbtModelTable, existing_date_datasets: list[dict]) -> list[dict]:
449
+ def make_date_datasets(self, table: DbtModelTable, existing_date_datasets: list[dict]) -> list[dict]:
442
450
  date_datasets = []
443
451
  for column in table.columns.values():
444
452
  existing_dataset_ids = [d["id"] for d in existing_date_datasets]
445
453
  if column.is_date() and column.gooddata_ldm_id not in existing_dataset_ids:
446
454
  if column.data_type in TIMESTAMP_DATA_TYPES:
447
- granularities = DATE_GRANULARITIES + TIMESTAMP_GRANULARITIES
455
+ granularities = (
456
+ DATE_GRANULARITIES + TIMESTAMP_GRANULARITIES + SECOND_TIMESTAMP_GRANULARITIES
457
+ if self._enable_second_granularities
458
+ else DATE_GRANULARITIES + TIMESTAMP_GRANULARITIES
459
+ )
448
460
  else:
449
461
  granularities = DATE_GRANULARITIES
450
462
  date_datasets.append(
@@ -73,7 +73,11 @@ def deploy_ldm(
73
73
  logger.info("Generate and put LDM")
74
74
  dbt_profiles = DbtProfiles(args)
75
75
  data_source_id = dbt_profiles.data_source_id
76
- dbt_tables = DbtModelTables.from_local(args.gooddata_upper_case, all_model_ids)
76
+ dbt_tables = DbtModelTables.from_local(
77
+ args.gooddata_upper_case,
78
+ all_model_ids,
79
+ enable_second_granularities=args.gooddata_enable_second_granularities,
80
+ )
77
81
  generate_and_put_ldm(logger, sdk_wrapper, data_source_id, workspace_id, dbt_tables, model_ids)
78
82
  workspace_url = f"{sdk_wrapper.get_host_from_sdk()}/modeler/#/{workspace_id}"
79
83
  logger.info(f"LDM successfully loaded, verify here: {workspace_url}")
@@ -0,0 +1,12 @@
1
+ # (C) 2026 GoodData Corporation
2
+ import sys
3
+
4
+ from gooddata_dbt.args import parse_arguments
5
+
6
+
7
+ def test_parse_arguments_deploy_ldm_second_granularities(monkeypatch):
8
+ monkeypatch.setattr(sys, "argv", ["gooddata-dbt", "deploy_ldm"])
9
+ assert parse_arguments("test").gooddata_enable_second_granularities is False
10
+
11
+ monkeypatch.setattr(sys, "argv", ["gooddata-dbt", "deploy_ldm", "--gooddata-enable-second-granularities"])
12
+ assert parse_arguments("test").gooddata_enable_second_granularities is True
@@ -3,7 +3,12 @@ import json
3
3
  from pathlib import Path
4
4
  from typing import Union
5
5
 
6
- from gooddata_dbt.dbt.tables import DbtModelTables
6
+ from gooddata_dbt.dbt.base import (
7
+ DATE_GRANULARITIES,
8
+ SECOND_TIMESTAMP_GRANULARITIES,
9
+ TIMESTAMP_GRANULARITIES,
10
+ )
11
+ from gooddata_dbt.dbt.tables import DbtModelColumn, DbtModelTable, DbtModelTables
7
12
  from gooddata_sdk import CatalogDeclarativeModel, CatalogDeclarativeTables
8
13
 
9
14
  _CURR_DIR = Path(__file__).parent
@@ -51,6 +56,36 @@ def test_make_ldm():
51
56
  assert len(ldm.ldm.date_instances) == 4
52
57
 
53
58
 
59
+ def _table_with_date_columns() -> DbtModelTable:
60
+ return DbtModelTable(
61
+ name="events",
62
+ description="",
63
+ tags=[],
64
+ schema="public",
65
+ columns={
66
+ "created_at": DbtModelColumn(name="created_at", description="", tags=[], data_type="TIMESTAMP"),
67
+ "created_on": DbtModelColumn(name="created_on", description="", tags=[], data_type="DATE"),
68
+ },
69
+ )
70
+
71
+
72
+ def test_make_date_datasets_without_second_granularities():
73
+ tables = DbtModelTables([], upper_case=False)
74
+ date_datasets = {d["id"]: d for d in tables.make_date_datasets(_table_with_date_columns(), [])}
75
+ assert date_datasets["created_at"]["granularities"] == DATE_GRANULARITIES + TIMESTAMP_GRANULARITIES
76
+ assert date_datasets["created_on"]["granularities"] == DATE_GRANULARITIES
77
+
78
+
79
+ def test_make_date_datasets_with_second_granularities():
80
+ tables = DbtModelTables([], upper_case=False, enable_second_granularities=True)
81
+ date_datasets = {d["id"]: d for d in tables.make_date_datasets(_table_with_date_columns(), [])}
82
+ assert (
83
+ date_datasets["created_at"]["granularities"]
84
+ == DATE_GRANULARITIES + TIMESTAMP_GRANULARITIES + SECOND_TIMESTAMP_GRANULARITIES
85
+ )
86
+ assert date_datasets["created_on"]["granularities"] == DATE_GRANULARITIES
87
+
88
+
54
89
  FAA_MODEL_ID = "faa"
55
90
 
56
91