Skip to content

Add object_store parameter to register/read file methods for thread-safe credentials - #1625

Open
qzyu999 wants to merge 2 commits into
apache:mainfrom
qzyu999:fix/issue-1624-object-store-register-parquet
Open

Add object_store parameter to register/read file methods for thread-safe credentials#1625
qzyu999 wants to merge 2 commits into
apache:mainfrom
qzyu999:fix/issue-1624-object-store-register-parquet

Conversation

@qzyu999

@qzyu999 qzyu999 commented Jul 9, 2026

Copy link
Copy Markdown

Which issue does this PR close?

Closes #1624.

Rationale for this change

When using datafusion-python as a compute backend from multi-threaded Python applications (e.g., PyIceberg), cloud credentials must currently be set via os.environ before calling register_parquet(). Since os.environ is process-global, concurrent threads mutating it causes credential cross-contamination, requiring a global lock that serializes all I/O operations and negates any parallelism benefit.

The existing register_object_store() method already solves thread-safety, but requires callers to manually parse bucket names from paths, determine the correct URL scheme, and make a separate call before register_parquet. This PR adds a convenience object_store parameter that handles all of this internally.

What changes are included in this PR?

  1. New private helper _register_object_store_for_path(path, store) parses a URL path via urllib.parse.urlparse to extract scheme and host, then calls register_object_store() internally.

  2. New object_store parameter added to all file-based register/read methods:

    • register_parquet / read_parquet
    • register_csv / read_csv
    • register_json / read_json
    • register_avro / read_avro
    • register_arrow / read_arrow
  3. Test suite (python/tests/test_object_store_param.py) with 23 tests:

    • 8 unit tests for URL parsing logic (s3, gs, az, https, error cases)
    • 13 mock-based tests verifying each method correctly delegates to register_object_store
    • 2 end-to-end integration tests using LocalFileSystem with real Parquet files

All changes are purely in the Python layer no Rust code modified.

Are there any user-facing changes?

Yes. All file-based register_* and read_* methods on SessionContext now accept an optional object_store keyword argument. When provided with a pre-configured store instance (e.g., AmazonS3, GoogleCloud, MicrosoftAzure), the store is automatically registered for the URL parsed from the path.

Example usage:

from datafusion import SessionContext
from datafusion.object_store import AmazonS3

ctx = SessionContext()
store = AmazonS3(bucket_name='my-bucket', region='us-east-1',
                 access_key_id=key, secret_access_key=secret)
ctx.register_parquet('my_table', 's3://my-bucket/data.parquet', object_store=store)

This is a backward-compatible addition (the parameter defaults to None and existing call sites are unaffected).

@qzyu999

qzyu999 commented Jul 9, 2026

Copy link
Copy Markdown
Author

Hi @timsaucer, this PR would help improve the efficiency of some operations related apache/iceberg-python#3554, PTAL and LMK if you have any questions, thanks!

Add an optional object_store parameter to register_parquet, read_parquet,
register_csv, read_csv, register_json, read_json, register_avro, read_avro,
register_arrow, and read_arrow methods.

When provided, the store is automatically registered for the URL scheme
and host parsed from the path, removing the need to manually call
register_object_store separately. This enables thread-safe cloud
credential handling without os.environ mutation.

Includes unit tests (mock-based) for URL parsing logic and integration
tests using LocalFileSystem for end-to-end validation.

Closes apache#1624
@qzyu999
qzyu999 force-pushed the fix/issue-1624-object-store-register-parquet branch from 81d33cb to b225b3a Compare July 17, 2026 02:25
@timsaucer
timsaucer requested review from Copilot and timsaucer July 28, 2026 19:25

Copilot AI 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.

Pull request overview

Note

Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.

Adds an object_store keyword parameter to Python SessionContext file-based register/read methods so callers can pass a preconfigured object store (thread-safe credentials) and have it automatically registered based on the URL in path.

Changes:

  • Added _register_object_store_for_path() helper using urllib.parse.urlparse and wired it into register_* / read_* methods via a new object_store parameter.
  • Expanded docstrings for Parquet register/read to document the new parameter (with examples).
  • Added a new Python test module covering URL parsing, delegation to register_object_store, and end-to-end usage with LocalFileSystem.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.

File Description
python/datafusion/context.py Introduces _register_object_store_for_path() and adds object_store param plumbing + documentation to file-based register/read APIs.
python/tests/test_object_store_param.py New tests for URL parsing + registration delegation + local end-to-end flow.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +633 to +642
parsed = urlparse(str(path))
if not parsed.scheme or not parsed.netloc:
msg = (
f"Cannot determine object store URL from path {path!r}. "
"The path must use a URL scheme (e.g. 's3://bucket/key')."
)
raise ValueError(msg)
scheme = f"{parsed.scheme}://"
host = parsed.netloc
self.register_object_store(scheme, store, host=host)
Comment on lines +261 to +263
file_url = f"file://{tmp_path}/test.parquet"

ctx.register_parquet("test_tbl", file_url, object_store=store)
def _register_object_store_for_path(
self, path: str | pathlib.Path, store: Any
) -> None:
"""Parse a URL path and register the given object store for its scheme and host.
Comment on lines +630 to +631
Raises:
ValueError: If the path does not contain a recognized URL scheme.
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.

Support per-SessionContext object store credentials without os.environ (thread-safety)

3 participants