From 209d9f2dd77ae47dced268ea24490e1b846c653a Mon Sep 17 00:00:00 2001 From: Andreas Poehlmann Date: Sun, 5 Oct 2025 22:02:42 +0200 Subject: [PATCH 1/6] upath.core: remove chain_parser from overloads for upath class narrowing --- upath/core.py | 48 ++++++++++++++++-------------------------------- 1 file changed, 16 insertions(+), 32 deletions(-) diff --git a/upath/core.py b/upath/core.py index adc1f270..2921eacf 100644 --- a/upath/core.py +++ b/upath/core.py @@ -462,104 +462,91 @@ def __new__( cls, *args: JoinablePathLike, protocol: Literal["simplecache"], - chain_parser: FSSpecChainParser = ..., - **storage_options: Any, + **_: Any, ) -> _uimpl.cached.SimpleCachePath: ... @overload # noqa: E301 def __new__( cls, *args: JoinablePathLike, protocol: Literal["gcs", "gs"], - chain_parser: FSSpecChainParser = ..., - **storage_options: Any, + **_: Any, ) -> _uimpl.cloud.GCSPath: ... @overload # noqa: E301 def __new__( cls, *args: JoinablePathLike, protocol: Literal["s3", "s3a"], - chain_parser: FSSpecChainParser = ..., - **storage_options: Any, + **_: Any, ) -> _uimpl.cloud.S3Path: ... @overload # noqa: E301 def __new__( cls, *args: JoinablePathLike, protocol: Literal["az", "abfs", "abfss", "adl"], - chain_parser: FSSpecChainParser = ..., - **storage_options: Any, + **_: Any, ) -> _uimpl.cloud.AzurePath: ... @overload # noqa: E301 def __new__( cls, *args: JoinablePathLike, protocol: Literal["data"], - chain_parser: FSSpecChainParser = ..., - **storage_options: Any, + **_: Any, ) -> _uimpl.data.DataPath: ... @overload # noqa: E301 def __new__( cls, *args: JoinablePathLike, protocol: Literal["github"], - chain_parser: FSSpecChainParser = ..., - **storage_options: Any, + **_: Any, ) -> _uimpl.github.GitHubPath: ... @overload # noqa: E301 def __new__( cls, *args: JoinablePathLike, protocol: Literal["hdfs"], - chain_parser: FSSpecChainParser = ..., - **storage_options: Any, + **_: Any, ) -> _uimpl.hdfs.HDFSPath: ... @overload # noqa: E301 def __new__( cls, *args: JoinablePathLike, protocol: Literal["http", "https"], - chain_parser: FSSpecChainParser = ..., - **storage_options: Any, + **_: Any, ) -> _uimpl.http.HTTPPath: ... @overload # noqa: E301 def __new__( cls, *args: JoinablePathLike, protocol: Literal["file", "local"], - chain_parser: FSSpecChainParser = ..., - **storage_options: Any, + **_: Any, ) -> _uimpl.local.FilePath: ... @overload # noqa: E301 def __new__( cls, *args: JoinablePathLike, protocol: Literal["memory"], - chain_parser: FSSpecChainParser = ..., - **storage_options: Any, + **_: Any, ) -> _uimpl.memory.MemoryPath: ... @overload # noqa: E301 def __new__( cls, *args: JoinablePathLike, protocol: Literal["sftp", "ssh"], - chain_parser: FSSpecChainParser = ..., - **storage_options: Any, + **_: Any, ) -> _uimpl.sftp.SFTPPath: ... @overload # noqa: E301 def __new__( cls, *args: JoinablePathLike, protocol: Literal["smb"], - chain_parser: FSSpecChainParser = ..., - **storage_options: Any, + **_: Any, ) -> _uimpl.smb.SMBPath: ... @overload # noqa: E301 def __new__( cls, *args: JoinablePathLike, protocol: Literal["webdav"], - chain_parser: FSSpecChainParser = ..., - **storage_options: Any, + **_: Any, ) -> _uimpl.webdav.WebdavPath: ... if sys.platform == "win32": @@ -569,8 +556,7 @@ def __new__( cls, *args: JoinablePathLike, protocol: Literal[""], - chain_parser: FSSpecChainParser = ..., - **storage_options: Any, + **_: Any, ) -> _uimpl.local.WindowsUPath: ... else: @@ -580,8 +566,7 @@ def __new__( cls, *args: JoinablePathLike, protocol: Literal[""], - chain_parser: FSSpecChainParser = ..., - **storage_options: Any, + **_: Any, ) -> _uimpl.local.PosixUPath: ... @overload # noqa: E301 @@ -589,8 +574,7 @@ def __new__( cls, *args: JoinablePathLike, protocol: str | None = ..., - chain_parser: FSSpecChainParser = ..., - **storage_options: Any, + **_: Any, ) -> Self: ... def __new__( From c8c490b2a4cec7ebf1ab361dda58e9f3267645d7 Mon Sep 17 00:00:00 2001 From: Andreas Poehlmann Date: Mon, 6 Oct 2025 22:21:43 +0200 Subject: [PATCH 2/6] upath.extensions.ProxyUPath: fix _chain fallback --- upath/extensions.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/upath/extensions.py b/upath/extensions.py index 6e6eeb0a..fabc86a6 100644 --- a/upath/extensions.py +++ b/upath/extensions.py @@ -78,8 +78,6 @@ def _chain(self): protocol=self.__wrapped__.protocol, storage_options=dict(self.__wrapped__.storage_options), ), - [], - [], ) # === wrapped interface =========================================== From 69be514aa5e1205d33c07726a373d0f067847da6 Mon Sep 17 00:00:00 2001 From: Andreas Poehlmann Date: Mon, 6 Oct 2025 22:42:04 +0200 Subject: [PATCH 3/6] upath.types.storage_options: adjust to be in line with path naming --- upath/implementations/cloud.py | 4 ++-- upath/implementations/github.py | 4 ++-- upath/types/storage_options.py | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/upath/implementations/cloud.py b/upath/implementations/cloud.py index b2e8489c..62f5e99c 100644 --- a/upath/implementations/cloud.py +++ b/upath/implementations/cloud.py @@ -21,7 +21,7 @@ from typing_extensions import Unpack from upath._chain import FSSpecChainParser - from upath.types.storage_options import AzureBlobStorageOptions + from upath.types.storage_options import AzureStorageOptions from upath.types.storage_options import GCSStorageOptions from upath.types.storage_options import S3StorageOptions @@ -146,7 +146,7 @@ def __init__( *args: JoinablePathLike, protocol: Literal["abfs", "abfss", "adl", "az"] | None = None, chain_parser: FSSpecChainParser = DEFAULT_CHAIN_PARSER, - **storage_options: Unpack[AzureBlobStorageOptions], + **storage_options: Unpack[AzureStorageOptions], ) -> None: super().__init__( *args, protocol=protocol, chain_parser=chain_parser, **storage_options diff --git a/upath/implementations/github.py b/upath/implementations/github.py index d72905a1..f8e47706 100644 --- a/upath/implementations/github.py +++ b/upath/implementations/github.py @@ -23,7 +23,7 @@ from typing_extensions import Unpack from upath._chain import FSSpecChainParser - from upath.types.storage_options import GithubStorageOptions + from upath.types.storage_options import GitHubStorageOptions __all__ = ["GitHubPath"] @@ -42,7 +42,7 @@ def __init__( *args: JoinablePathLike, protocol: Literal["github"] | None = ..., chain_parser: FSSpecChainParser = ..., - **storage_options: Unpack[GithubStorageOptions], + **storage_options: Unpack[GitHubStorageOptions], ) -> None: ... @property diff --git a/upath/types/storage_options.py b/upath/types/storage_options.py index f156f221..feedc1e9 100644 --- a/upath/types/storage_options.py +++ b/upath/types/storage_options.py @@ -18,9 +18,9 @@ "SimpleCacheStorageOptions", "GCSStorageOptions", "S3StorageOptions", - "AzureBlobStorageOptions", + "AzureStorageOptions", "DataStorageOptions", - "GithubStorageOptions", + "GitHubStorageOptions", "HDFSStorageOptions", "HTTPStorageOptions", "FileStorageOptions", @@ -140,7 +140,7 @@ class S3StorageOptions(_AbstractStorageOptions, total=False): cache_regions: bool -class AzureBlobStorageOptions(_AbstractStorageOptions, total=False): +class AzureStorageOptions(_AbstractStorageOptions, total=False): """Storage options for Azure Blob Storage and Azure Data Lake Gen2""" # Account and authentication @@ -186,7 +186,7 @@ class DataStorageOptions(_AbstractStorageOptions, total=False): # No specific options for Data URIs at the moment -class GithubStorageOptions(_AbstractStorageOptions, total=False): +class GitHubStorageOptions(_AbstractStorageOptions, total=False): """Storage options for GitHub repository filesystem""" # Repository identification From 648830da27c754f72947aa3e624796fcf87a9b66 Mon Sep 17 00:00:00 2001 From: Andreas Poehlmann Date: Mon, 6 Oct 2025 22:44:00 +0200 Subject: [PATCH 4/6] typesafety: add more typechecks for **kwargs --- typesafety/test_upath_types.yml | 87 +++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) diff --git a/typesafety/test_upath_types.yml b/typesafety/test_upath_types.yml index 333fdc20..2ea6d08e 100644 --- a/typesafety/test_upath_types.yml +++ b/typesafety/test_upath_types.yml @@ -267,6 +267,93 @@ p = {{ cls }}(".", {{ supported_example_name }}={{ unsupported_example_value }}) # ER: Argument "{{ supported_example_name }}" to "{{ cls }}" has incompatible type.* +- case: upath_constructor_sopts_via_dict + disable_cache: false + parametrized: + - module: upath.implementations.cached + cls: SimpleCachePath + - module: upath.implementations.cloud + cls: GCSPath + - module: upath.implementations.cloud + cls: S3Path + - module: upath.implementations.cloud + cls: AzurePath + - module: upath.implementations.data + cls: DataPath + - module: upath.implementations.github + cls: GitHubPath + - module: upath.implementations.hdfs + cls: HDFSPath + - module: upath.implementations.http + cls: HTTPPath + - module: upath.implementations.local + cls: FilePath + - module: upath.implementations.memory + cls: MemoryPath + - module: upath.implementations.sftp + cls: SFTPPath + - module: upath.implementations.smb + cls: SMBPath + - module: upath.implementations.webdav + cls: WebdavPath + main: | + from typing import Any + from {{ module }} import {{ cls }} + + kw: dict[str, Any] = {} + p = {{ cls }}(".", **kw) + reveal_type(p) # N: Revealed type is "{{ module }}.{{ cls }}" + +- case: upath_constructor_sopts_via_typed_dict + disable_cache: false + parametrized: + - module: upath.implementations.cached + cls: SimpleCachePath + td: SimpleCacheStorageOptions + - module: upath.implementations.cloud + cls: GCSPath + td: GCSStorageOptions + - module: upath.implementations.cloud + cls: S3Path + td: S3StorageOptions + - module: upath.implementations.cloud + cls: AzurePath + td: AzureStorageOptions + - module: upath.implementations.data + cls: DataPath + td: DataStorageOptions + - module: upath.implementations.github + cls: GitHubPath + td: GitHubStorageOptions + - module: upath.implementations.hdfs + cls: HDFSPath + td: HDFSStorageOptions + - module: upath.implementations.http + cls: HTTPPath + td: HTTPStorageOptions + - module: upath.implementations.local + cls: FilePath + td: FileStorageOptions + - module: upath.implementations.memory + cls: MemoryPath + td: MemoryStorageOptions + - module: upath.implementations.sftp + cls: SFTPPath + td: SFTPStorageOptions + - module: upath.implementations.smb + cls: SMBPath + td: SMBStorageOptions + - module: upath.implementations.webdav + cls: WebdavPath + td: WebdavStorageOptions + main: | + from {{ module }} import {{ cls }} + from upath.types.storage_options import {{ td }} + + kw: {{ td }} = {{ td }}() + p = {{ cls }}(".", **kw) + reveal_type(p) # N: Revealed type is "{{ module }}.{{ cls }}" + # FIXME: mypy emits a 'defined here' note when emitting the error below. # seems to be a limitation/bug in pytest-mypy-plugins that I can't match it # From 641289ad7128d5b7e8fd650bd921005b8a1564c5 Mon Sep 17 00:00:00 2001 From: Andreas Poehlmann Date: Wed, 8 Oct 2025 22:14:40 +0200 Subject: [PATCH 5/6] upath.core: update zip and tar typing overload --- typesafety/test_upath_types.yml | 6 ++++++ upath/core.py | 6 ++---- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/typesafety/test_upath_types.yml b/typesafety/test_upath_types.yml index 4cfed00b..dd42f6cf 100644 --- a/typesafety/test_upath_types.yml +++ b/typesafety/test_upath_types.yml @@ -367,9 +367,15 @@ - module: upath.implementations.smb cls: SMBPath td: SMBStorageOptions + - module: upath.implementations.tar + cls: TarPath + td: TarStorageOptions - module: upath.implementations.webdav cls: WebdavPath td: WebdavStorageOptions + - module: upath.implementations.zip + cls: ZipPath + td: ZipStorageOptions main: | from {{ module }} import {{ cls }} from upath.types.storage_options import {{ td }} diff --git a/upath/core.py b/upath/core.py index c9609ddc..ce309265 100644 --- a/upath/core.py +++ b/upath/core.py @@ -557,8 +557,7 @@ def __new__( cls, *args: JoinablePathLike, protocol: Literal["tar"], - chain_parser: FSSpecChainParser = ..., - **storage_options: Any, + **_: Any, ) -> _uimpl.tar.TarPath: ... @overload # noqa: E301 def __new__( @@ -572,8 +571,7 @@ def __new__( cls, *args: JoinablePathLike, protocol: Literal["zip"], - chain_parser: FSSpecChainParser = ..., - **storage_options: Any, + **_: Any, ) -> _uimpl.zip.ZipPath: ... if sys.platform == "win32": From 027a4a6d4fc26c361dcd729a136c7bc6f6ee7b4b Mon Sep 17 00:00:00 2001 From: Andreas Poehlmann Date: Wed, 8 Oct 2025 22:19:54 +0200 Subject: [PATCH 6/6] typesafety: add missing tests --- typesafety/test_upath_types.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/typesafety/test_upath_types.yml b/typesafety/test_upath_types.yml index dd42f6cf..179307fc 100644 --- a/typesafety/test_upath_types.yml +++ b/typesafety/test_upath_types.yml @@ -318,8 +318,12 @@ cls: SFTPPath - module: upath.implementations.smb cls: SMBPath + - module: upath.implementations.tar + cls: TarPath - module: upath.implementations.webdav cls: WebdavPath + - module: upath.implementations.zip + cls: ZipPath main: | from typing import Any from {{ module }} import {{ cls }}