Skip to content

refactor: decouple FilesetFileSystem from Starlette test internals and improve upload/download paths - #629

Merged
ironcommit merged 7 commits into
mainfrom
starlette-depr
Jul 10, 2026
Merged

refactor: decouple FilesetFileSystem from Starlette test internals and improve upload/download paths#629
ironcommit merged 7 commits into
mainfrom
starlette-depr

Conversation

@ironcommit

@ironcommit ironcommit commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Summary

Remove Starlette-specific hacks from FilesetFileSystem and the SDK test infrastructure, replacing them with clean interfaces that properly bridge the TestClient ↔ httpx.Client gap.

Changes

FilesetFileSystem (packages/filesets, sdk/python)

  • Remove fsspec.asyn._run_coros_in_chunks monkey-patch — the custom run_coros_in_chunks is still used, but no longer replaces fsspec's global helper
  • Remove _detect_async_transport — this Starlette-aware hack extracted ASGITransport from a TestClient at runtime; the async client is now injected explicitly via a new async_client parameter on FilesetFileSystem.__init__
  • Add _put override — properly handles local→remote path expansion (glob, recursive, directory creation) instead of relying on the base-class implementation that doesn't work with fileset refs
  • Add mode parameter to _pipe_file and _put_file signatures
  • Improve type annotationsout: dict[str, FileInfo], ListFilesQueryParams for query dicts
  • Add input validation in _get for mixed list/string arguments

SDK test infrastructure (packages/nmp_testing)

  • Introduce SDKTestClientAdapter — an httpx.Client subclass that delegates .send() to Starlette's TestClient.request(), preserving request headers and body
  • Add _install_asgi_files_resource — wires the ASGI-backed AsyncFilesClient into the sync SDK's .files resource (and patches .copy/.with_options so cloned SDKs keep the same transport)
  • Add httpx2>=2.0.0 dependency to nmp_testing
  • Export SDKTestClientAdapter and ClientContext from nmp.testing

Consumers updated

  • data_designer_nemo — use sdk.files.fsspec instead of manually constructing FilesetFileSystem via client_from_platform
  • nemo_platform_plugin (file_manager) — same simplification
  • filesets/resources.py — accept optional async_files_client, use DEFAULT_CALLBACK instead of conditional kwargs, use CacheStatus enum values
  • Integration test fixtures across files, auth, secrets, guardrails, hello_world, intake, and CLI tests — updated to use SDKTestClientAdapter and ClientContext
  • K8s deployment tests — use fully-qualified Docker image refs (docker.io/library/alpine:3.20)

Why

The previous approach detected Starlette's TestClient at runtime inside FilesetFileSystem to extract an ASGITransport — a fragile coupling that broke when the SDK's HTTP client interface changed. The new approach keeps test transport concerns in the test infrastructure where they belong, and gives FilesetFileSystem a clean async_client injection point.

Summary by CodeRabbit

  • New Features

    • Fileset operations now support coordinated synchronous and asynchronous file clients.
    • Improved integration with SDK-provided filesystem access for file management and data workflows.
  • Bug Fixes

    • Improved file upload and download handling, including directory operations and path validation.
    • Enhanced caching status reporting with consistent status values.
    • Improved support for Hugging Face-backed file storage and asynchronous downloads.

@ironcommit
ironcommit requested review from a team as code owners July 9, 2026 21:21
@ironcommit ironcommit changed the title Add httpx2 dependency and SDK test client adapter chore: add httpx2 dependency and SDK test client adapter Jul 9, 2026
@github-actions github-actions Bot added the chore label Jul 9, 2026
@ironcommit
ironcommit requested a review from mckornfield July 9, 2026 21:23
@coderabbitai

coderabbitai Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Adds an httpx-compatible adapter around FastAPI/Starlette’s TestClient, exposes it through nmp.testing, wires it into synchronous SDK and integration clients, detects its ASGI app for async transport, and adds shared HuggingFace Hub client handling.

Changes

SDK test client compatibility

Layer / File(s) Summary
HTTP client adapter implementation
packages/nmp_testing/pyproject.toml, packages/nmp_testing/src/nmp/testing/client.py, packages/nmp_testing/src/nmp/testing/__init__.py
Adds the httpx2 dependency, implements and exports SDKTestClientAdapter, and forwards SDK requests through TestClient as httpx.Response objects.
ASGI transport detection
packages/filesets/src/filesets/filesystem/filesystem.py
Uses an available client app attribute to create an httpx.ASGITransport before the existing TestClient detection fallback.
Synchronous client wiring
packages/nmp_testing/src/nmp/testing/client.py, packages/nemo_platform_ext/tests/cli/integration/conftest.py, services/*/tests/integration/*, services/core/jobs/tests/integration/test_task_auth_runtime.py, services/core/auth/tests/integration/conftest.py, services/core/secrets/tests/conftest.py
Wraps test clients with SDKTestClientAdapter when constructing or running synchronous SDK clients.
HuggingFace ASGI client sharing
services/core/files/tests/integration/conftest.py
Uses a non-closing httpx wrapper for HuggingFace Hub’s ASGI client factory and restores the factory and session after fixture use.
Explicit client validation
packages/nmp_common/tests/sdk_factory/test_sdk.py
Uses an explicit httpx.Client and verifies the SDK retains the supplied client instance.

Sequence Diagram(s)

sequenceDiagram
  participant NeMoPlatform
  participant SDKTestClientAdapter
  participant TestClient
  participant FilesystemTransportDetection
  NeMoPlatform->>SDKTestClientAdapter: send(httpx.Request)
  SDKTestClientAdapter->>TestClient: request(method, URL, headers, body)
  TestClient-->>SDKTestClientAdapter: response
  SDKTestClientAdapter-->>NeMoPlatform: httpx.Response
  FilesystemTransportDetection->>SDKTestClientAdapter: read app
  FilesystemTransportDetection->>FilesystemTransportDetection: create ASGITransport(app)
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 58.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title matches a real part of the PR (FilesetFileSystem/httpx test-internals decoupling), though it misses the broader adapter and dependency work.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch starlette-depr

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/nmp_testing/src/nmp/testing/client.py`:
- Around line 19-20: The imports in the client adapter are relying on httpx
private internals, so update the module to use only public httpx APIs and type
definitions. In the client.py module, replace the direct imports of
UseClientDefault and AuthTypes from internal httpx modules with their public
equivalents from httpx’s exposed typing/API surface, and adjust any annotations
in the surrounding client code that reference those types so the adapter no
longer depends on internal symbols.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: ba76e98f-f680-4fa8-9dde-e4590143a9d8

📥 Commits

Reviewing files that changed from the base of the PR and between 0c00d34 and 6b27d7b.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (2)
  • packages/nmp_testing/pyproject.toml
  • packages/nmp_testing/src/nmp/testing/client.py

Comment thread packages/nmp_testing/src/nmp/testing/client.py Outdated
@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor
Suite Lines Covered Line Rate Branch Rate
Unit Tests 23701/30822 76.9% 61.7%
Integration Tests 13762/29471 46.7% 19.7%

@ironcommit
ironcommit force-pushed the starlette-depr branch 2 times, most recently from 301fb04 to 869080a Compare July 9, 2026 22:44
Comment thread packages/nmp_testing/pyproject.toml

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
packages/nmp_testing/src/nmp/testing/client.py (1)

84-94: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

Don't coerce headers to dict. dict(request.headers) and dict(response.headers) collapse repeated headers (Set-Cookie becomes comma-joined). Pass the httpx.Headers objects through unchanged.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/nmp_testing/src/nmp/testing/client.py` around lines 84 - 94,
Preserve repeated headers by passing the existing httpx.Headers objects
unchanged in the request and response handling within the test client method:
remove dict() coercion from headers=dict(request.headers) and
headers=dict(response.headers), while keeping the rest of the request and
httpx.Response construction intact.

Source: Linters/SAST tools

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@packages/nmp_testing/src/nmp/testing/client.py`:
- Around line 84-94: Preserve repeated headers by passing the existing
httpx.Headers objects unchanged in the request and response handling within the
test client method: remove dict() coercion from headers=dict(request.headers)
and headers=dict(response.headers), while keeping the rest of the request and
httpx.Response construction intact.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 653d74fe-91f9-476f-81c4-f32ce121278f

📥 Commits

Reviewing files that changed from the base of the PR and between 869080a and 3c28af1.

⛔ Files ignored due to path filters (3)
  • sdk/python/nemo-platform/src/nemo_platform/filesets/filesystem/filesystem.py is excluded by !sdk/**
  • sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/cli/integration/conftest.py is excluded by !sdk/**
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (12)
  • packages/filesets/src/filesets/filesystem/filesystem.py
  • packages/nemo_platform_ext/tests/cli/integration/conftest.py
  • packages/nmp_common/tests/sdk_factory/test_sdk.py
  • packages/nmp_testing/pyproject.toml
  • packages/nmp_testing/src/nmp/testing/__init__.py
  • packages/nmp_testing/src/nmp/testing/client.py
  • services/core/auth/tests/integration/conftest.py
  • services/core/jobs/tests/integration/test_task_auth_runtime.py
  • services/core/secrets/tests/conftest.py
  • services/guardrails/tests/integration/test_guardrails.py
  • services/hello-world/tests/integration/test_hello_world.py
  • services/intake/tests/integration/test_intake.py
✅ Files skipped from review due to trivial changes (1)
  • packages/nmp_testing/pyproject.toml
🚧 Files skipped from review as they are similar to previous changes (8)
  • packages/filesets/src/filesets/filesystem/filesystem.py
  • services/core/jobs/tests/integration/test_task_auth_runtime.py
  • services/intake/tests/integration/test_intake.py
  • packages/nemo_platform_ext/tests/cli/integration/conftest.py
  • packages/nmp_common/tests/sdk_factory/test_sdk.py
  • services/guardrails/tests/integration/test_guardrails.py
  • services/hello-world/tests/integration/test_hello_world.py
  • packages/nmp_testing/src/nmp/testing/init.py

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@services/core/files/tests/integration/conftest.py`:
- Line 203: Remove the `default_client_factory` import from
`huggingface_hub.utils._http` and refactor the fixture using only public
`huggingface_hub` APIs, avoiding any attempt to restore the client factory
through internal helpers.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: ac68f631-f2ac-4c39-84b9-947f16f4f1ee

📥 Commits

Reviewing files that changed from the base of the PR and between 3c28af1 and e16cf47.

📒 Files selected for processing (1)
  • services/core/files/tests/integration/conftest.py

Comment thread services/core/files/tests/integration/conftest.py Outdated
Signed-off-by: Ryan S <267728323+ironcommit@users.noreply.github.com>
Signed-off-by: Ryan S <267728323+ironcommit@users.noreply.github.com>
Signed-off-by: Ryan S <267728323+ironcommit@users.noreply.github.com>
Signed-off-by: Ryan S <267728323+ironcommit@users.noreply.github.com>
Signed-off-by: Ryan S <267728323+ironcommit@users.noreply.github.com>
@ironcommit ironcommit changed the title chore: add httpx2 dependency and SDK test client adapter refactor: decouple FilesetFileSystem from Starlette test internals and improve upload/download paths Jul 10, 2026
Signed-off-by: Ryan S <267728323+ironcommit@users.noreply.github.com>
Signed-off-by: Ryan S <267728323+ironcommit@users.noreply.github.com>
@ironcommit
ironcommit added this pull request to the merge queue Jul 10, 2026
Merged via the queue into main with commit 13a5498 Jul 10, 2026
59 checks passed
@ironcommit
ironcommit deleted the starlette-depr branch July 10, 2026 21:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants