Skip to content

test: improve coverage on test retrieval#4

Open
Faolain wants to merge 4 commits into
mainfrom
test/updates
Open

test: improve coverage on test retrieval#4
Faolain wants to merge 4 commits into
mainfrom
test/updates

Conversation

@Faolain

@Faolain Faolain commented Apr 14, 2025

Copy link
Copy Markdown
Collaborator

Summary by CodeRabbit

  • Tests
    • Added comprehensive new unit tests covering various scenarios for IPFS retrieval, including error handling, environment variable precedence, and cache updates.
    • Enhanced test coverage for edge cases such as malformed or empty cache files and connection errors.
    • Refactored and improved existing tests for cache update logic.
    • Added new tests for geotemporal utility functions verifying distance calculations and input validation.
    • Removed outdated legacy tests related to dataset listing with empty cache files.
  • Bug Fixes
    • Improved error handling and messaging for JSON decoding errors and unexpected exceptions during IPNS JSON retrieval retries.
    • Enabled processing of legacy string-format child links in dataset catalogs by supporting /ipfs/-prefixed hrefs.
    • Enhanced error handling and logging to better manage dataset and collection retrieval failures without interrupting processing.

@coderabbitai

coderabbitai Bot commented Apr 14, 2025

Copy link
Copy Markdown

Walkthrough

This update significantly expands the test coverage in the tests/test_ipfs_retrieval.py file, focusing on internal functions and error handling for IPFS-related operations. New fixtures and helper functions are introduced to mock dependencies, such as the IPFS store and file I/O. The tests now cover various scenarios for fetching JSON from CIDs and IPNS, constructing IPFS store instances with different environment and argument configurations, and updating local cache files. Additional tests ensure that exceptions are raised correctly for malformed or missing data. Some outdated, commented-out legacy tests have been removed for clarity. In the main source, error handling in fetch_json_from_ipns is improved by explicitly catching JSON decode errors on retry, and child links processing in get_dataset_hamt_cid_from_stac is enhanced to support legacy string-format /ipfs/ links.

Changes

File(s) Change Summary
tests/test_ipfs_retrieval.py Added comprehensive unit tests for private/internal functions (_get_ipfs_store, fetch_json_from_cid, _get_host, fetch_json_from_ipns, get_dataset_hamt_cid_from_stac, update_cache_if_changed, fallback logic). Introduced fixtures, helper functions, and new error case tests. Removed legacy commented-out tests.
dclimate_zarr_client/ipfs_retrieval.py Enhanced fetch_json_from_ipns error handling by explicitly catching JSON decode errors on retry and improving generic exception messages. Enabled processing of legacy string-format /ipfs/ child links in get_dataset_hamt_cid_from_stac by uncommenting related code. Improved error handling and logging in dataset and collection processing. No signature changes.
tests/test_geotemporal_utils.py Added new unit tests for geotemporal utility functions _haversine and _check_input_parameters, verifying distance calculations and validation error raising.

Possibly related PRs

  • feat: update to zarr3 #2: Adds initial IPFS/STAC catalog traversal and dataset loading logic in ipfs_retrieval.py; the current PR’s extensive tests directly relate to the code introduced or modified in that PR.

Poem

In fields of code, the rabbits hop,
Testing IPFS from bottom to top.
With mocks and fixtures, errors they chase,
Ensuring each function’s in the right place.
Through CIDs and caches, exceptions they find,
Hopping through logic, leaving no bugs behind!
🐇✨

✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@codecov-commenter

codecov-commenter commented Apr 14, 2025

Copy link
Copy Markdown

Codecov Report

Attention: Patch coverage is 77.77778% with 12 lines in your changes missing coverage. Please review.

Project coverage is 81.23%. Comparing base (2da6713) to head (7bca52e).

Files with missing lines Patch % Lines
dclimate_zarr_client/ipfs_retrieval.py 77.77% 10 Missing and 2 partials ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##             main       #4       +/-   ##
===========================================
+ Coverage   65.42%   81.23%   +15.81%     
===========================================
  Files           8        8               
  Lines         778      794       +16     
  Branches      111      112        +1     
===========================================
+ Hits          509      645      +136     
+ Misses        221      116      -105     
+ Partials       48       33       -15     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (5)
tests/test_ipfs_retrieval.py (5)

19-21: Consider limiting tests to public interfaces.

Testing private functions (_get_ipfs_store, fetch_json_from_cid, and _get_host) can be a code smell. If you need to test them extensively, consider making them part of the public API or reaffirm the design that justifies direct testing of these internals.


526-527: mock_exists_false is declared but not used.

Consider removing it if no test scenario requires returning False from os.path.exists:

-def mock_exists_false(*args, **kwargs) -> bool:
-    return False

602-640: Consider using a single with patch(...) block to avoid .start()/.stop().

You can simplify by using the context manager directly:

- mock_json_load = patch(
-     "json.load",
-     side_effect=json.JSONDecodeError("err", "doc", 0),
- ).start()
...
- mock_json_load.stop()

+ with patch(
+     "json.load",
+     side_effect=json.JSONDecodeError("err", "doc", 0)
+ ):
+     update_cache_if_changed(new_data)

646-668: Combine nested with statements into a single context.

According to Ruff (SIM117), consider merging nested blocks to reduce indentation. For example:

-def test_get_ipns_name_hash_local_cache_malformed_json_during_fallback():
-    with patch("requests.get", side_effect=requests.RequestException("Simulated error")):
-        with patch("os.path.exists", return_value=True):
-            with patch("dclimate_zarr_client.ipfs_retrieval.update_cache_if_changed"):
-                with patch("dclimate_zarr_client.ipfs_retrieval.open", mock_open(read_data="INVALID JSON!!"), create=True) as mock_file_open:
-                    with patch("json.load", side_effect=json.JSONDecodeError("err", "doc", 0)):
-                        with pytest.raises(DatasetNotFoundError, match="Invalid dataset name"):
-                            get_ipns_name_hash("cpc-precip-conus")
+def test_get_ipns_name_hash_local_cache_malformed_json_during_fallback():
+    with patch("requests.get", side_effect=requests.RequestException("Simulated error")), \
+         patch("os.path.exists", return_value=True), \
+         patch("dclimate_zarr_client.ipfs_retrieval.update_cache_if_changed"), \
+         patch("dclimate_zarr_client.ipfs_retrieval.open", mock_open(read_data="INVALID JSON!!"), create=True) as mock_file_open, \
+         patch("json.load", side_effect=json.JSONDecodeError("err", "doc", 0)):
+        with pytest.raises(DatasetNotFoundError, match="Invalid dataset name"):
+            get_ipns_name_hash("cpc-precip-conus")
🧰 Tools
🪛 Ruff (0.8.2)

648-651: Use a single with statement with multiple contexts instead of nested with statements

(SIM117)


661-666: Use a single with statement with multiple contexts instead of nested with statements

Combine with statements

(SIM117)


672-693: Consider consolidating the nested with statements here as well.

Similarly, you can merge the multiple with calls for clarity:

-def test_get_ipns_name_hash_local_cache_empty_during_fallback():
-    with patch("requests.get", side_effect=requests.RequestException("Simulated error")):
-        with patch("os.path.exists", return_value=True):
-            with patch("dclimate_zarr_client.ipfs_retrieval.update_cache_if_changed"):
-                with patch("dclimate_zarr_client.ipfs_retrieval.open", mock_open(read_data=""), create=True) as mock_file_open:
-                    with patch("json.load", side_effect=json.JSONDecodeError("Expecting value", "", 0)):
-                        with pytest.raises(DatasetNotFoundError, match="Invalid dataset name"):
-                            get_ipns_name_hash("cpc-precip-conus")
+def test_get_ipns_name_hash_local_cache_empty_during_fallback():
+    with patch("requests.get", side_effect=requests.RequestException("Simulated error")), \
+         patch("os.path.exists", return_value=True), \
+         patch("dclimate_zarr_client.ipfs_retrieval.update_cache_if_changed"), \
+         patch("dclimate_zarr_client.ipfs_retrieval.open", mock_open(read_data=""), create=True) as mock_file_open, \
+         patch("json.load", side_effect=json.JSONDecodeError("Expecting value", "", 0)):
+        with pytest.raises(DatasetNotFoundError, match="Invalid dataset name"):
+            get_ipns_name_hash("cpc-precip-conus")
🧰 Tools
🪛 Ruff (0.8.2)

674-677: Use a single with statement with multiple contexts instead of nested with statements

Combine with statements

(SIM117)


685-691: Use a single with statement with multiple contexts instead of nested with statements

Combine with statements

(SIM117)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2da6713 and 82d5f65.

📒 Files selected for processing (1)
  • tests/test_ipfs_retrieval.py (8 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
tests/test_ipfs_retrieval.py (2)
dclimate_zarr_client/ipfs_retrieval.py (5)
  • _get_ipfs_store (34-52)
  • fetch_json_from_cid (56-95)
  • _get_host (436-449)
  • update_cache_if_changed (500-511)
  • get_ipns_name_hash (514-557)
dclimate_zarr_client/dclimate_zarr_errors.py (3)
  • StacCatalogError (65-66)
  • IpfsConnectionError (61-62)
  • DatasetNotFoundError (25-26)
🪛 Ruff (0.8.2)
tests/test_ipfs_retrieval.py

648-651: Use a single with statement with multiple contexts instead of nested with statements

(SIM117)


661-666: Use a single with statement with multiple contexts instead of nested with statements

Combine with statements

(SIM117)


674-677: Use a single with statement with multiple contexts instead of nested with statements

Combine with statements

(SIM117)


685-691: Use a single with statement with multiple contexts instead of nested with statements

Combine with statements

(SIM117)

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: build
🔇 Additional comments (23)
tests/test_ipfs_retrieval.py (23)

3-4: Imports for type hinting and mocking look good.


8-8: CID import is correct.


23-23: Importing IPFSStore is appropriate.


36-38: Type alias definitions are clear and help readability.


44-53: Test for default store creation appears correct.


55-69: Argument override test is thorough.


71-83: Environment variable usage test is solid.


85-98: Mixed args/env test logic works as expected.


103-111: mock_ipfs_store fixture is well-structured.


113-130: Successful fetch test logic is correct.


132-146: Prefix stripping test for /ipfs/ is correct.


148-156: CID decoding failure test is correct.


158-168: Test for empty load return is valid.


170-180: Invalid JSON test is valid and ensures error handling.


182-192: Timeout scenario test is well implemented.


194-212: Connection error tests cover various failure modes thoroughly.


214-225: Generic load error test is correctly raising StacCatalogError.


230-239: _get_host default logic test is correct.


241-245: Test for IPFS_HOST environment variable usage is correct.


522-523: mock_exists_true is used correctly where needed.


531-538: Test for no-update scenario is correct and confirms read-only usage.


548-554: Update scenario test is valid, ensuring correct write logic.


575-588: File not found scenario test is thorough.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (5)
dclimate_zarr_client/ipfs_retrieval.py (2)

212-223: Refine or simplify the JSONDecodeError handling logic.
This block robustly handles JSON decode errors on the second attempt, constructing an informative error message that appends details from the first attempt. If similar logic recurs in other branches, consider extracting a helper method for consistent error reporting.


317-317: Clarify the log message vs. appending logic.
Currently, the log line indicates "skipping" the child link, but the code then appends it to collections_to_visit. This can be confusing to maintainers. Here is a proposed tweak to the log message:

-logger.warning(f"Skipping child link with unexpected string href format (expected dict): {link}")
+logger.warning(f"Processing legacy string-format child link: {link}")
tests/test_ipfs_retrieval.py (3)

30-33: Consider removing stale commented-out lines.
These lines reference a potential fixture usage that is now commented out. If no longer needed, remove them to keep the file clean.


1067-1095: test_get_ipns_name_hash_local_cache_malformed_json_during_fallback.
Multiple nested with statements degrade readability slightly, as flagged by static analysis. Consider combining contexts:

-with patch("requests.get", ...):
-    with patch("os.path.exists", ...):
-        with patch("dclimate_zarr_client.ipfs_retrieval.update_cache_if_changed"):
-            ...
+with patch("requests.get", ...), \
+     patch("os.path.exists", ...), \
+     patch("dclimate_zarr_client.ipfs_retrieval.update_cache_if_changed"):
+    ...

This is a minor style improvement. Otherwise, the fallback logic is tested thoroughly.

🧰 Tools
🪛 Ruff (0.8.2)

1073-1076: Use a single with statement with multiple contexts instead of nested with statements

(SIM117)


1086-1091: Use a single with statement with multiple contexts instead of nested with statements

Combine with statements

(SIM117)


1097-1119: test_get_ipns_name_hash_local_cache_empty_during_fallback.
Same nested with style comment applies here. Tests are otherwise solid, verifying the correct exception for empty local cache.

🧰 Tools
🪛 Ruff (0.8.2)

1099-1102: Use a single with statement with multiple contexts instead of nested with statements

Combine with statements

(SIM117)


1110-1116: Use a single with statement with multiple contexts instead of nested with statements

Combine with statements

(SIM117)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 82d5f65 and 55df822.

📒 Files selected for processing (2)
  • dclimate_zarr_client/ipfs_retrieval.py (3 hunks)
  • tests/test_ipfs_retrieval.py (6 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
dclimate_zarr_client/ipfs_retrieval.py (1)
dclimate_zarr_client/dclimate_zarr_errors.py (2)
  • StacCatalogError (65-66)
  • IpfsConnectionError (61-62)
🪛 Ruff (0.8.2)
tests/test_ipfs_retrieval.py

1073-1076: Use a single with statement with multiple contexts instead of nested with statements

(SIM117)


1086-1091: Use a single with statement with multiple contexts instead of nested with statements

Combine with statements

(SIM117)


1099-1102: Use a single with statement with multiple contexts instead of nested with statements

Combine with statements

(SIM117)


1110-1116: Use a single with statement with multiple contexts instead of nested with statements

Combine with statements

(SIM117)

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: build
🔇 Additional comments (34)
dclimate_zarr_client/ipfs_retrieval.py (1)

206-206: Looks good for JSON parsing on retry.
This line correctly calls response.json() and is consistent with your approach of catching JSONDecodeError in subsequent blocks.

tests/test_ipfs_retrieval.py (33)

3-4: Imports and testing private members.
You're importing additional modules (typing.Dict, typing.Any, CID, etc.) and referencing private/internal functions from the package under test. This is acceptable in Python land, though it's worth noting that testing internal APIs can signal that these functionalities might be candidates for public exposure or refactoring.

Also applies to: 8-8, 13-13, 20-20, 22-22, 24-24


34-38: No issues with custom type aliasing.
Defining MonkeyPatch, MockIPFSStore, and MockResponse fosters clarity in your tests. No concerns here.


40-53: Fixtures look well-structured.
These fixtures (mock_ipfs_store and mock_requests_get) are clear, enabling consistent test mocking. Good approach for controlling dependencies.


56-62: Helper function for cache path.
get_cache_path() is straightforward. No issues.


64-65: Section heading clarity.
The commentary sets up the _get_ipfs_store test section. Nothing to change here.


67-77: Test _get_ipfs_store_defaults.
Verifies store creation with defaults when no args are passed. Looks good.


79-93: Test _get_ipfs_store_args_override_env.
Checks argument precedence over env vars, ensuring correct store config. Nicely done.


95-106: Test _get_ipfs_store_env_vars.
Covers usage of environment variables. Good thoroughness.


108-121: Test _get_ipfs_store_mixed_args_env.
Ensures a mix of argument and environment usage. No issues noted.


123-124: Section heading for fetch_json_from_cid tests.
These lines simply mark a new section.


126-139: Test successful fetching from CID.
Verifies normal JSON decode. This covers a critical happy path. Good.


141-153: Test CID with /ipfs/ prefix.
Ensures prefix stripping logic is correct and tested.


155-163: Test invalid CID string.
Properly raises StacCatalogError before attempting any IPFS load.


165-174: Test empty bytes from load call.
Verifies StacCatalogError if no data is returned, which is helpful to catch partially available IPFS content.


176-185: Test JSON decode error.
Checks StacCatalogError upon invalid JSON. Straightforward coverage.


187-196: Test Timeout exception.
Ensures correct IpfsConnectionError is thrown if requests time out.


198-216: Test various connection error messages.
This set of sub-tests is comprehensive, matching typical IPFS gateway issues.


218-229: Test generic load error.
Correctly re-raises issues as StacCatalogError.


231-241: Test _get_host_default.
Confirms fallback to DEFAULT_HOST absent env vars. Looks good.


243-248: Test _get_host_from_env.
Verifies environment override. LGTM.


250-250: Section heading for fetch_json_from_ipns tests.
No content to review beyond the comment marker.


253-439: Class TestFetchJsonFromIpnsErrors.
These tests meticulously cover all error paths and retry logic, including timeouts, connection errors, JSON decode errors, and HTTP failures. The detailed coverage is commendable.


444-455: Root catalog fetch error test.
Validates raising StacCatalogError if the initial root catalog fetch fails. Nicely done.


457-468: Invalid root catalog format test.
Properly checks for type: Catalog and raises error if missing.


470-485: No child links test.
Ensures a StacCatalogError if no valid child links exist.


487-532: Invalid child link formats test.
Comprehensive scenario that ensures skipping or warning on malformed links. Good coverage.


534-596: Collection fetch error scenario.
Valid test ensuring errors on certain collections don't prevent discovering valid ones. This improves robustness.


598-621: Invalid collection format scenario.
Checks skipping of incomplete or invalid collection data.


623-678: Item fetch error scenario.
Verifies that one failing item won't block the rest. Nicely handled.


944-953: Helper functions for mock_exists.
These are straightforward, returning True or False; no issues.


956-972: test_update_cache_no_update.
Correct logic verifying no write occurs when the file is already up-to-date.


973-999: test_update_cache_update.
Checks the file is opened for writing when new data differs. Implementation is correct.


1000-1027: test_update_cache_file_not_found & test_update_cache_decode_error.
Confirms correctly handling missing or malformed cache files, then writing updated content. Good coverage.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
tests/test_ipfs_retrieval.py (2)

11-11: Consider using alternative import style.

While the current import works correctly, you could make it more explicit.

-import dclimate_zarr_client.ipfs_retrieval as ipfs_retrieval
+from dclimate_zarr_client import ipfs_retrieval
🧰 Tools
🪛 Pylint (3.3.7)

[refactor] 11-11: Use 'from dclimate_zarr_client import ipfs_retrieval' instead

(R0402)


1465-1487: Consider combining nested context managers for cleaner code.

The nested with statements could be combined for improved readability.

-    with patch(
-        "requests.get", side_effect=requests.RequestException("Simulated error")
-    ):
-        with patch("os.path.exists", return_value=True):
-            # Mock update_cache_if_changed to avoid file writes during test setup if called early
-            with patch("dclimate_zarr_client.ipfs_retrieval.update_cache_if_changed"):
-                # Mock open specifically within the fallback block
-                with patch(
-                    "dclimate_zarr_client.ipfs_retrieval.open",
-                    mock_open(read_data="INVALID JSON!!"),
-                    create=True,  # Allow create=True if needed by mock_open internals
-                ) as mock_file_open:
-                    # Mock json.load raising the error when called by get_ipns_name_hash
-                    with patch(
-                        "json.load", side_effect=json.JSONDecodeError("err", "doc", 0)
-                    ):
+    with (
+        patch("requests.get", side_effect=requests.RequestException("Simulated error")),
+        patch("os.path.exists", return_value=True),
+        patch("dclimate_zarr_client.ipfs_retrieval.update_cache_if_changed"),
+        patch(
+            "dclimate_zarr_client.ipfs_retrieval.open",
+            mock_open(read_data="INVALID JSON!!"),
+            create=True,
+        ) as mock_file_open,
+        patch("json.load", side_effect=json.JSONDecodeError("err", "doc", 0))
+    ):
🧰 Tools
🪛 Ruff (0.11.9)

1465-1468: Use a single with statement with multiple contexts instead of nested with statements

(SIM117)


1478-1483: Use a single with statement with multiple contexts instead of nested with statements

Combine with statements

(SIM117)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 55df822 and 7bca52e.

📒 Files selected for processing (3)
  • dclimate_zarr_client/ipfs_retrieval.py (7 hunks)
  • tests/test_geotemporal_utils.py (1 hunks)
  • tests/test_ipfs_retrieval.py (6 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • dclimate_zarr_client/ipfs_retrieval.py
🧰 Additional context used
🧬 Code Graph Analysis (2)
tests/test_geotemporal_utils.py (2)
dclimate_zarr_client/geotemporal_data.py (2)
  • _haversine (651-685)
  • _check_input_parameters (688-722)
dclimate_zarr_client/dclimate_zarr_errors.py (2)
  • InvalidTimePeriodError (38-40)
  • InvalidAggregationMethodError (33-35)
tests/test_ipfs_retrieval.py (2)
dclimate_zarr_client/ipfs_retrieval.py (10)
  • fetch_json_from_ipns (99-255)
  • get_dataset_hamt_cid_from_stac (259-460)
  • get_ipns_name_hash (541-584)
  • _get_dataset_by_ipfs_cid (628-709)
  • update_cache_if_changed (527-538)
  • _get_single_metadata (479-491)
  • list_datasets (763-928)
  • _get_ipfs_store (34-52)
  • fetch_json_from_cid (56-95)
  • _get_host (463-476)
dclimate_zarr_client/dclimate_zarr_errors.py (3)
  • DatasetNotFoundError (25-26)
  • IpfsConnectionError (61-62)
  • StacCatalogError (65-66)
🪛 Pylint (3.3.7)
tests/test_ipfs_retrieval.py

[refactor] 11-11: Use 'from dclimate_zarr_client import ipfs_retrieval' instead

(R0402)


[refactor] 568-589: Unnecessary "elif" after "raise", remove the leading "el" from "elif"

(R1720)


[refactor] 647-673: Unnecessary "elif" after "return", remove the leading "el" from "elif"

(R1705)


[refactor] 923-944: Unnecessary "elif" after "raise", remove the leading "el" from "elif"

(R1720)


[refactor] 973-1013: Unnecessary "elif" after "return", remove the leading "el" from "elif"

(R1705)

🪛 Ruff (0.11.9)
tests/test_ipfs_retrieval.py

1465-1468: Use a single with statement with multiple contexts instead of nested with statements

(SIM117)


1478-1483: Use a single with statement with multiple contexts instead of nested with statements

Combine with statements

(SIM117)


1491-1494: Use a single with statement with multiple contexts instead of nested with statements

Combine with statements

(SIM117)


1502-1508: Use a single with statement with multiple contexts instead of nested with statements

Combine with statements

(SIM117)

🔇 Additional comments (3)
tests/test_geotemporal_utils.py (1)

1-33: Well-structured test coverage for geotemporal utilities.

The tests appropriately cover both single-point and array-based distance calculations for _haversine, as well as error handling for invalid parameters in _check_input_parameters. The use of pytest.approx and np.allclose with appropriate tolerances is correct for floating-point comparisons.

tests/test_ipfs_retrieval.py (2)

689-691: Good practice: Clearing cache for test isolation.

The explicit cache clearing ensures test isolation and prevents false positives from cached data. This is an important fix that prevents test interdependencies.


255-445: Excellent comprehensive error handling test coverage.

The TestFetchJsonFromIpnsErrors class provides thorough coverage of the retry logic and various failure scenarios, including timeouts, connection errors, JSON decode errors, and HTTP errors. The test structure with predictable mocks and clear assertions makes the retry behavior easy to understand and verify.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants