Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions dcpy/models/product/dataset/metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ class DatasetOrgProductAttributesOverride(CustomizableBase):
contains_address: bool | None = (
None # `contains_address` refers specifically to addresses containing house, numbers + street names. (ie. not just streets, polys, etc.)
)
current_version: str | None = None
data_collection_method: str | None = None
data_change_frequency: str | None = None
date_made_public: str | None = None
Expand Down Expand Up @@ -219,6 +220,7 @@ class Destination(CustomizableBase):
id: str
type: str
tags: list[str] = []
current_version: str = ""


class DestinationWithFiles(Destination):
Expand Down
22 changes: 22 additions & 0 deletions dcpy/models/product/metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -288,3 +288,25 @@ def query_product_dataset_destinations(
def get_product_dataset_destinations(self, destination_path: str):
prod, ds, dest_id = destination_path.split(".")
return self.product(prod).dataset(ds).get_destination(dest_id)

def get_all_destination_current_versions(self) -> list[str]:
"""Get all destination paths with their current_version.
Returns a sorted list of strings in format: product.dataset.destination|current_version
"""
result = []
for p_name in self.metadata.products:
product = self.product(p_name)
for ds in product.get_datasets_by_id().values():
# Get the resolved current_version from dataset attributes (has org/product defaults applied)
dataset_version = ds.attributes.current_version or ""

for dest in ds.destinations:
# Destination can override the dataset version
version = (
dest.current_version
if dest.current_version
else dataset_version
)
result.append(f"{p_name}.{ds.id}.{dest.id}|{version}")

return sorted(result)
64 changes: 64 additions & 0 deletions dcpy/test/models/product/test_metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -219,3 +219,67 @@ def test_column_defaults_applied(org_md: md.OrgMetadata):
description="sample bbl description",
example="1016370141",
) == colp_ds.get_column("bbl"), "The bbl column should have had defaults applied"


def test_current_version_overrides(org_md: md.OrgMetadata):
"""Test that current_version can be overridden at org, product, dataset, and destination levels."""
lion_md = org_md.product("lion")

# Test dataset with dataset-level override
pseudo_lots = lion_md.dataset("pseudo_lots")
assert pseudo_lots.attributes.current_version == "dataset-override-3.0", (
"Dataset-level current_version should override product default"
)

# Test destination with destination-level override
socrata_dest = pseudo_lots.get_destination("socrata")
assert socrata_dest.current_version == "destination-override-4.0", (
"Destination should have its own current_version override"
)

# Test destination without override (should use dataset version via method)
garlic_dest = pseudo_lots.get_destination("garlic_sftp")
assert garlic_dest.current_version == "", (
"Destination without override should have empty string"
)

# Test dataset without dataset-level override (should use product default)
school_districts = lion_md.dataset("school_districts")
assert school_districts.attributes.current_version == "product-default-2.0", (
"Dataset without override should use product-level default"
)


def test_get_all_destination_current_versions(org_md: md.OrgMetadata):
"""Test that get_all_destination_current_versions returns correct sorted list."""
# Temporarily filter out the error product since it's designed to fail
original_products = org_md.metadata.products
org_md.metadata.products = [
p for p in original_products if p != "mock_product_with_errors"
]

try:
versions = org_md.get_all_destination_current_versions()

# Should be sorted
assert versions == sorted(versions), "Result should be sorted"

# Check that specific entries exist with correct version resolution
assert "lion.pseudo_lots.socrata|destination-override-4.0" in versions, (
"Destination-level override should be in output"
)
assert "lion.pseudo_lots.garlic_sftp|dataset-override-3.0" in versions, (
"Destination without override should use dataset version"
)
assert "lion.school_districts.socrata|product-default-2.0" in versions, (
"Destination on dataset without override should use product default"
)
assert "lion.school_districts.socrata_2|product-default-2.0" in versions, (
"Another destination should also use product default"
)
assert "lion.school_districts.other|product-default-2.0" in versions, (
"Third destination should also use product default"
)
finally:
# Restore original products list
org_md.metadata.products = original_products
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ attributes:
attribution: DCP
attribution_link: https://www.nyc.gov/site/planning/data-maps/open-data.page
contact_email: opendata@planning.nyc.gov
current_version: "org-default-1.0"

products:
- colp
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ attributes:
dataset_defaults:
publishing_frequency: "{{ lion_prod_level_pub_freq }}"
publishing_purpose: "legal compliance."
current_version: "product-default-2.0"

datasets:
- pseudo_lots
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ attributes:
display_name: Pseudo Lots
each_row_is_a: Pseudo Lot
publishing_frequency: "{{ pseudo_lots_pub_freq }}"
current_version: "dataset-override-3.0"
tags:
- pseudo lots
- bin
Expand All @@ -21,5 +22,6 @@ destinations:
- id: socrata
type: socrata
tags: [prod_tag, pseudo_lots_tag]
current_version: "destination-override-4.0"
- id: garlic_sftp
type: sftp
Loading