Skip to content

Commit 0addb08

Browse files
Merge pull request #60 from CDCgov/rr-45-mocktest-data
Rr 45 mocktest data
2 parents f1d91d9 + 56567b2 commit 0addb08

4 files changed

Lines changed: 96 additions & 10 deletions

File tree

cfa/dataops/catalog.py

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -702,3 +702,80 @@ def dict_to_sn(d: Any, defaults: dict = None, ns: str = "") -> SimpleNamespace:
702702
datacat.__setattr__("__namespace_list__", dataset_namespaces)
703703
reportcat = SimpleNamespace(**combined_reports_dict)
704704
reportcat.__setattr__("__namespace_list__", report_namespaces)
705+
706+
707+
def _attach_schema_mock_functions(
708+
datacat: SimpleNamespace, catalogs: list
709+
) -> None:
710+
"""Recursively walk the datacat namespace and attach mock_data functions to
711+
the extract and load BlobEndpoints of each DatasetEndpoint, sourced from
712+
a schema module co-located with the dataset.
713+
714+
The schema module is expected to live at:
715+
{catalog_namespace}.{catalog_name}.datasets.{team_path}.schemas.{dataset_name}
716+
717+
where ``team_path`` is the namespace path segment(s) between the catalog
718+
name and the dataset name (for example, ``stf`` in
719+
``public.stf.nhsn_hrd_prelim``), and ``dataset_name`` is the dataset's
720+
namespace name (for example, ``nhsn_hrd_prelim``).
721+
722+
The schema module should define one or both of:
723+
- extract_mock_data() -> pd.DataFrame
724+
- load_mock_data() -> pd.DataFrame
725+
726+
These are then accessible as:
727+
datacat.<catalog>.<team_path_segments>.<dataset>.extract.mock_data()
728+
datacat.<catalog>.<team_path_segments>.<dataset>.load.mock_data()
729+
730+
Args:
731+
datacat (SimpleNamespace): the top-level datacat namespace
732+
catalogs (list): list of (catalog_namespace, catalog_name, catalog_path)
733+
tuples from get_all_catalogs()
734+
"""
735+
736+
def _walk(ns: SimpleNamespace) -> None:
737+
for val in vars(ns).values():
738+
if isinstance(val, DatasetEndpoint):
739+
# __ns_str__ is e.g. "public.stf.nhsn_hrd_prelim";
740+
# the last segment is used as the schema module name
741+
dataset_name = val.__ns_str__.split(".")[-1]
742+
for cns, cat_name, _ in catalogs:
743+
# __ns_str__ is e.g. "public.stf.nhsn_hrd_prelim"
744+
# strip cat_name prefix -> "stf.nhsn_hrd_prelim"
745+
# then split into team ("stf") and dataset ("nhsn_hrd_prelim")
746+
# so the schema lives at: datasets.stf.schemas.nhsn_hrd_prelim
747+
ns_within_datasets = val.__ns_str__.removeprefix(
748+
f"{cat_name}."
749+
)
750+
ns_parts = ns_within_datasets.rsplit(".", 1)
751+
team_path = ns_parts[0] if len(ns_parts) > 1 else ""
752+
schema_mod_path = (
753+
f"{cns}.{cat_name}.datasets"
754+
f".{team_path}.schemas.{dataset_name}"
755+
if team_path
756+
else f"{cns}.{cat_name}.datasets.schemas.{dataset_name}"
757+
)
758+
try:
759+
mod = import_module(schema_mod_path)
760+
except ModuleNotFoundError:
761+
# No schema module for this dataset — skip silently
762+
continue
763+
# Attach to the already-existing BlobEndpoint on .extract / .load
764+
for stage, func_name in [
765+
("extract", "extract_mock_data"),
766+
("load", "load_mock_data"),
767+
]:
768+
if hasattr(val, stage):
769+
if hasattr(mod, func_name):
770+
setattr(
771+
getattr(val, stage),
772+
"mock_data",
773+
getattr(mod, func_name),
774+
)
775+
elif isinstance(val, SimpleNamespace):
776+
_walk(val)
777+
778+
_walk(datacat)
779+
780+
781+
_attach_schema_mock_functions(datacat, all_catalogs)

changelog.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,17 @@ and this project adheres to [Calendar Versioning](https://calver.org/).
77
The versioning pattern is `YYYY.MM.DD.micro(a/b/{none if release})
88

99
---
10+
## [2026.03.02.0]
11+
12+
### Added
13+
14+
- Added the ability to pull in mock data defined in a catalog.
15+
1016
## [2026.02.04.0]
1117

1218
### Added
1319

14-
- Added capability to get_dataframe for reference datasets
20+
- Added capability to get_dataframe for reference datasets.
1521

1622

1723
## [2026.01.05.0a]

docs/data_developer_guide.md

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -168,21 +168,24 @@ load_schema = pa.DataFrameSchema({
168168
"category": pa.Column(str)
169169
})
170170

171-
# Add synthetic data generation for testing
172-
def raw_synthetic_data(n_rows: int = 100) -> pd.DataFrame:
173-
return pd.DataFrame({
171+
# Add mock data generation for testing
172+
# prefix with 'extract' or 'load'
173+
def extract_mock_data(output="pandas", size=10) -> pd.DataFrame|pl.DataFrame:
174+
data = {
174175
"date": pd.date_range(
175176
start="2023-01-01",
176-
periods=n_rows,
177+
periods=size,
177178
tz='UTC'
178179
),
179-
"value": np.random.uniform(1, 100, n_rows),
180-
"category": np.random.choice(['A', 'B', 'C'], n_rows)
181-
})
180+
"value": np.random.uniform(1, 100, size),
181+
"category": np.random.choice(['A', 'B', 'C'], size)
182+
}
183+
df = pd.DataFrame(data)
184+
return df if output == "pandas" or output == "pd" else pl.from_pandas(df)
182185

183186
# Validate synthetic data matches schema
184187
if __name__ == "__main__":
185-
test_df = generate_synthetic_data()
188+
test_df = extract_mock_data()
186189
extract_schema.validate(test_df)
187190
```
188191

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "cfa.dataops"
3-
version = "2026.02.04.0"
3+
version = "2026.03.02.0"
44
description = "Data cataloging, ETL, modeling, verification, and validation for CFA"
55
authors = [
66
{ name = "Phil Rogers", email = "ap66@cdc.gov" },

0 commit comments

Comments
 (0)