portolan-python 0.1.1__tar.gz → 0.1.2__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: portolan-python
3
- Version: 0.1.1
3
+ Version: 0.1.2
4
4
  Summary: A lightweight Python implementation of the Portolan specification.
5
5
  Author: Portolan contributors
6
6
  License: Apache-2.0
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "portolan-python"
3
- version = "0.1.1"
3
+ version = "0.1.2"
4
4
  description = "A lightweight Python implementation of the Portolan specification."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.10"
@@ -106,7 +106,12 @@ def _write_catalog_tree(
106
106
  root_url: str,
107
107
  output_root: Path,
108
108
  fetch_json: Callable[[str], JsonObject],
109
+ visited: set[str] | None = None,
109
110
  ) -> None:
111
+ if visited is None:
112
+ visited = set()
113
+ visited.add(document_url)
114
+
110
115
  relative_path = _relative_document_path(root_url, document_url)
111
116
  target = output_root / relative_path
112
117
  target.parent.mkdir(parents=True, exist_ok=True)
@@ -121,9 +126,11 @@ def _write_catalog_tree(
121
126
  if not isinstance(href, str):
122
127
  continue
123
128
  child_url = urljoin(document_url, href)
129
+ if child_url in visited:
130
+ continue
124
131
  child = fetch_json(child_url)
125
132
  if child.get("type") in {"Catalog", "Collection"}:
126
- _write_catalog_tree(child_url, child, root_url, output_root, fetch_json)
133
+ _write_catalog_tree(child_url, child, root_url, output_root, fetch_json, visited)
127
134
 
128
135
 
129
136
  def _with_absolute_asset_hrefs(document_url: str, collection: JsonObject) -> JsonObject:
@@ -169,6 +169,33 @@ def test_download_registry_catalog_writes_snapshot_with_absolute_asset_hrefs(
169
169
  assert collection["assets"]["data"]["href"] == "https://example.test/demo/roads/roads.parquet"
170
170
 
171
171
 
172
+ def test_download_registry_catalog_skips_child_cycles(tmp_path: Path) -> None:
173
+ root_url = "https://example.test/demo/catalog.json"
174
+ child_url = "https://example.test/demo/roads/collection.json"
175
+ responses = {
176
+ root_url: {
177
+ "type": "Catalog",
178
+ "id": "demo",
179
+ "links": [{"rel": "child", "href": "./roads/collection.json"}],
180
+ },
181
+ child_url: {
182
+ **_collection("roads", {}),
183
+ "links": [{"rel": "child", "href": "../catalog.json"}],
184
+ },
185
+ }
186
+ fetched_urls: list[str] = []
187
+
188
+ def fetch_json(url: str) -> dict[str, Any]:
189
+ fetched_urls.append(url)
190
+ if fetched_urls.count(url) > 1:
191
+ raise AssertionError(f"Fetched document twice: {url}")
192
+ return responses[url]
193
+
194
+ download_registry_catalog(root_url, tmp_path, fetch_json=fetch_json)
195
+
196
+ assert fetched_urls == [root_url, child_url]
197
+
198
+
172
199
  def test_download_registry_catalog_recurses_nested_catalogs_and_uses_fallback_id(
173
200
  tmp_path: Path,
174
201
  ) -> None:
@@ -468,7 +468,7 @@ wheels = [
468
468
 
469
469
  [[package]]
470
470
  name = "portolan-python"
471
- version = "0.1.1"
471
+ version = "0.1.2"
472
472
  source = { editable = "." }
473
473
 
474
474
  [package.optional-dependencies]