Skip to content

Commit 30549a2

Browse files
authored
fix cube metadata model (#631)
cansimId can be null on newer tables
1 parent d64914b commit 30549a2

3 files changed

Lines changed: 57 additions & 2 deletions

File tree

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "stats_can"
3-
version = "3.2.1"
3+
version = "3.2.2"
44
description = "Read StatsCan data into python, mostly pandas dataframes"
55
authors = [{ name = "Ian Preston" }]
66
requires-python = ">=3.10,<4.0"

src/stats_can/schemas.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ class Footnote(TypedDict):
6060
class CubeMetadata(TypedDict):
6161
responseStatusCode: int
6262
productId: int
63-
cansimId: str
63+
cansimId: str | None
6464
cubeTitleEn: str
6565
cubeTitleFr: str
6666
cubeStartDate: str

tests/test_error_handling.py

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,61 @@ def test_download_bad_status_raises(self, tmpdir):
113113
stats_can.sc.download_tables("99999999", path=tmpdir)
114114

115115

116+
class TestCubeMetadataValidation:
117+
"""Tests for CubeMetadata schema validation."""
118+
119+
_CUBE_METADATA_BASE = {
120+
"responseStatusCode": 0,
121+
"productId": 34100292,
122+
"cubeTitleEn": "Building permits",
123+
"cubeTitleFr": "Permis de bâtir",
124+
"cubeStartDate": "2018-01-01",
125+
"cubeEndDate": "2026-02-01",
126+
"frequencyCode": 6,
127+
"nbSeriesCube": 375864,
128+
"nbDatapointsCube": 36834672,
129+
"releaseTime": "2026-04-13T08:30",
130+
"archiveStatusCode": "2",
131+
"archiveStatusEn": "CURRENT",
132+
"archiveStatusFr": "ACTIF",
133+
"subjectCode": ["3409"],
134+
"surveyCode": ["2802"],
135+
"dimension": [],
136+
"footnote": [],
137+
"correction": [],
138+
"correctionFootnote": [],
139+
"issueDate": "2026-04-13",
140+
}
141+
142+
def test_null_cansim_id_validates(self):
143+
"""Tables without a CANSIM ID return cansimId=null from the API."""
144+
mock_resp = _mock_response(
145+
json_data=[
146+
{
147+
"status": "SUCCESS",
148+
"object": {**self._CUBE_METADATA_BASE, "cansimId": None},
149+
}
150+
]
151+
)
152+
with patch.object(scwds._session, "request", return_value=mock_resp):
153+
result = scwds.get_cube_metadata("34100292")
154+
assert result[0]["cansimId"] is None
155+
156+
def test_string_cansim_id_validates(self):
157+
"""Tables with a CANSIM ID should still validate normally."""
158+
mock_resp = _mock_response(
159+
json_data=[
160+
{
161+
"status": "SUCCESS",
162+
"object": {**self._CUBE_METADATA_BASE, "cansimId": "271-0022"},
163+
}
164+
]
165+
)
166+
with patch.object(scwds._session, "request", return_value=mock_resp):
167+
result = scwds.get_cube_metadata("27100022")
168+
assert result[0]["cansimId"] == "271-0022"
169+
170+
116171
class TestVectorsToDfEdgeCases:
117172
"""Tests for vectors_to_df edge cases."""
118173

0 commit comments

Comments
 (0)