fix urlunparse returns Literal[b''] instead of str #2867#3003
fix urlunparse returns Literal[b''] instead of str #2867#3003asukaminato0721 wants to merge 1 commit intofacebook:mainfrom
Conversation
There was a problem hiding this comment.
Pull request overview
Updates Pyrefly’s handling of stdlib NamedTuple-like result types (e.g., urllib.parse.ParseResult) so overload resolution and collection subtyping behave correctly, fixing the urlunparse return-type false positive reported in #2867.
Changes:
- Adds a regression test asserting
urlunparse(urlparse(str))andurlunparse(ParseResult._replace(...))are typed asstr. - Allows
NamedTuplemultiple inheritance in stub/interface (.pyi) modules to match typeshed modeling of stdlib result objects. - Improves superclass lookups for
NamedTuplesubclasses by routing tuple-related upcasts through an erased tuple type soIterable/Sequenceelement types reflect actual field types instead ofAny.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
pyrefly/lib/test/overload.rs |
Adds regression coverage for urlunparse preferring the str overload when given a ParseResult. |
pyrefly/lib/test/named_tuple.rs |
Strengthens NamedTuple subtyping tests and adds a stub-mixin scenario reflecting typeshed patterns. |
pyrefly/lib/alt/class/classdef.rs |
Adjusts as_superclass to use tuple element information (via as_tuple + tuple erasure) for tuple-related supertypes. |
pyrefly/lib/alt/class/class_metadata.rs |
Permits NamedTuple multiple inheritance in .pyi/interface modules while keeping the restriction for user .py code. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
Diff from mypy_primer, showing the effect of this PR on open source code: pip (https://github.com/pypa/pip)
- ERROR src/pip/_internal/models/link.py:181:11-34: `+` is not supported between `str` and `bytes` [unsupported-operation]
openlibrary (https://github.com/internetarchive/openlibrary)
- ERROR openlibrary/coverstore/utils.py:92:12-19: Returned type `tuple[Literal[b''], dict[str, str]]` is not assignable to declared return type `tuple[str, dict[str, str]]` [bad-return]
- ERROR openlibrary/plugins/upstream/utils.py:1544:20-23: Returned type `Literal[b'']` is not assignable to declared return type `str` [bad-return]
mkdocs (https://github.com/mkdocs/mkdocs)
- ERROR mkdocs/config/config_options.py:524:20-42: Returned type `Literal[b'']` is not assignable to declared return type `str` [bad-return]
black (https://github.com/psf/black)
+ ERROR src/black/cache.py:144:59-146:18: `dict[str, tuple[float | int | str, ...]]` is not assignable to `dict[str, tuple[float, int, str]]` [bad-assignment]
cloud-init (https://github.com/canonical/cloud-init)
- ERROR cloudinit/url_helper.py:513:26-40: `str | Unknown` is not assignable to TypedDict key `method` with type `Literal[b''] | bool` [bad-typed-dict-key]
- ERROR cloudinit/url_helper.py:516:35-42: `tuple[Unknown, ...]` is not assignable to TypedDict key `timeout` with type `Literal[b''] | bool` [bad-typed-dict-key]
+ ERROR cloudinit/url_helper.py:516:35-42: `tuple[Unknown, ...]` is not assignable to TypedDict key `timeout` with type `bool | str` [bad-typed-dict-key]
- ERROR cloudinit/url_helper.py:518:35-57: `float` is not assignable to TypedDict key `timeout` with type `Literal[b''] | bool` [bad-typed-dict-key]
+ ERROR cloudinit/url_helper.py:518:35-57: `float` is not assignable to TypedDict key `timeout` with type `bool | str` [bad-typed-dict-key]
- ERROR cloudinit/url_helper.py:548:31-38: `dict[Unknown, Unknown] | Unknown` is not assignable to TypedDict key `headers` with type `Literal[b''] | bool` [bad-typed-dict-key]
+ ERROR cloudinit/url_helper.py:548:31-38: `dict[Unknown, Unknown] | Unknown` is not assignable to TypedDict key `headers` with type `bool | str` [bad-typed-dict-key]
- Object of class `bytes` has no attribute `get` [missing-attribute]
+ Object of class `str` has no attribute `get` [missing-attribute]
- ERROR cloudinit/url_helper.py:558:25-50: Cannot set item in `Literal[b'']` [unsupported-operation]
+ ERROR cloudinit/url_helper.py:558:25-50: Cannot set item in `str` [unsupported-operation]
- ERROR cloudinit/url_helper.py:590:35-38: Argument `Literal[b'']` is not assignable to parameter `url` with type `str | None` in function `UrlError.__init__` [bad-argument-type]
- ERROR cloudinit/url_helper.py:596:21-24: Argument `Literal[b'']` is not assignable to parameter `url` with type `str | None` in function `UrlError.__init__` [bad-argument-type]
- ERROR cloudinit/url_helper.py:600:41-44: Argument `Literal[b'']` is not assignable to parameter `url` with type `str | None` in function `UrlError.__init__` [bad-argument-type]
dulwich (https://github.com/dulwich/dulwich)
- ERROR dulwich/client.py:4990:17-40: Argument `Literal[b'']` is not assignable to parameter `base_url` with type `str` in function `Urllib3HttpGitClient.__init__` [bad-argument-type]
- ERROR dulwich/client.py:5004:17-40: Argument `Literal[b'']` is not assignable to parameter `base_url` with type `str` in function `AbstractHttpGitClient.__init__` [bad-argument-type]
- ERROR dulwich/client.py:5016:37-58: `Literal[b'']` is not assignable to attribute `_url_with_auth` with type `str | None` [bad-assignment]
yarl (https://github.com/aio-libs/yarl)
+ ERROR yarl/_url.py:570:30-54: `SplitResult` is not assignable to upper bound `tuple[_T_co, ...]` of type variable `Self@tuple` [bad-specialization]
twine (https://github.com/pypa/twine)
- ERROR twine/utils.py:238:12-30: Returned type `Literal[b'']` is not assignable to declared return type `str` [bad-return]
schemathesis (https://github.com/schemathesis/schemathesis)
- ERROR src/schemathesis/core/output/sanitization.py:74:12-43: Returned type `Literal[b'']` is not assignable to declared return type `str` [bad-return]
- ERROR src/schemathesis/transport/prepare.py:80:16-33: Returned type `Literal[b'']` is not assignable to declared return type `str` [bad-return]
aiohttp (https://github.com/aio-libs/aiohttp)
+ ERROR aiohttp/_websocket/reader_c.py:293:36-87: `WSMessageText` is not assignable to upper bound `tuple[_T_co, ...]` of type variable `Self@tuple` [bad-specialization]
+ ERROR aiohttp/_websocket/reader_c.py:296:36-298:22: `WSMessageTextBytes` is not assignable to upper bound `tuple[_T_co, ...]` of type variable `Self@tuple` [bad-specialization]
+ ERROR aiohttp/_websocket/reader_c.py:300:32-302:18: `WSMessageBinary` is not assignable to upper bound `tuple[_T_co, ...]` of type variable `Self@tuple` [bad-specialization]
+ ERROR aiohttp/_websocket/reader_py.py:293:36-87: `WSMessageText` is not assignable to upper bound `tuple[_T_co, ...]` of type variable `Self@tuple` [bad-specialization]
+ ERROR aiohttp/_websocket/reader_py.py:296:36-298:22: `WSMessageTextBytes` is not assignable to upper bound `tuple[_T_co, ...]` of type variable `Self@tuple` [bad-specialization]
+ ERROR aiohttp/_websocket/reader_py.py:300:32-302:18: `WSMessageBinary` is not assignable to upper bound `tuple[_T_co, ...]` of type variable `Self@tuple` [bad-specialization]
+ ERROR aiohttp/client_reqrep.py:122:29-124:10: `Self@RequestInfo` is not assignable to upper bound `tuple[_T_co, ...]` of type variable `Self@tuple` [bad-specialization]
+ ERROR aiohttp/client_reqrep.py:337:29-339:10: `RequestInfo` is not assignable to upper bound `tuple[_T_co, ...]` of type variable `Self@tuple` [bad-specialization]
+ ERROR aiohttp/client_reqrep.py:784:29-795:10: `ConnectionKey` is not assignable to upper bound `tuple[_T_co, ...]` of type variable `Self@tuple` [bad-specialization]
+ ERROR aiohttp/client_reqrep.py:1043:29-1054:10: `ConnectionKey` is not assignable to upper bound `tuple[_T_co, ...]` of type variable `Self@tuple` [bad-specialization]
streamlit (https://github.com/streamlit/streamlit)
- ERROR lib/tests/streamlit/web/server/server_test_case.py:89:13-47: Argument `Literal[b'']` is not assignable to parameter `url` with type `HTTPRequest | str` in function `tornado.websocket.websocket_connect` [bad-argument-type]
zulip (https://github.com/zulip/zulip)
- ERROR corporate/views/remote_billing_page.py:527:12-21: Returned type `Literal[b'']` is not assignable to declared return type `str` [bad-return]
static-frame (https://github.com/static-frame/static-frame)
- ERROR static_frame/core/www.py:115:16-74: Returned type `Literal[b'']` is not assignable to declared return type `str` [bad-return]
mypy (https://github.com/python/mypy)
- ERROR mypy/typeshed/stdlib/ssl.pyi:263:7-14: Named tuples do not support multiple inheritance [invalid-inheritance]
- ERROR mypy/typeshed/stdlib/urllib/parse.pyi:87:7-19: Named tuples do not support multiple inheritance [invalid-inheritance]
- ERROR mypy/typeshed/stdlib/urllib/parse.pyi:90:7-18: Named tuples do not support multiple inheritance [invalid-inheritance]
- ERROR mypy/typeshed/stdlib/urllib/parse.pyi:93:7-18: Named tuples do not support multiple inheritance [invalid-inheritance]
- ERROR mypy/typeshed/stdlib/urllib/parse.pyi:97:7-24: Named tuples do not support multiple inheritance [invalid-inheritance]
- ERROR mypy/typeshed/stdlib/urllib/parse.pyi:100:7-23: Named tuples do not support multiple inheritance [invalid-inheritance]
- ERROR mypy/typeshed/stdlib/urllib/parse.pyi:103:7-23: Named tuples do not support multiple inheritance [invalid-inheritance]
meson (https://github.com/mesonbuild/meson)
- ERROR mesonbuild/cargo/interpreter.py:888:11-84: `Literal[b'']` is not assignable to variable `url` with type `str` [bad-assignment]
- ERROR mesonbuild/wrap/wrap.py:120:38-66: Argument `Literal[b'']` is not assignable to parameter `url` with type `str` in function `urllib.request.Request.__init__` [bad-argument-type]
- ERROR mesonbuild/wrap/wrap.py:815:33-113: `Literal[b'']` is not assignable to variable `urlstring` with type `str` [bad-assignment]
sphinx (https://github.com/sphinx-doc/sphinx)
- ERROR sphinx/builders/linkcheck.py:780:20-66: Returned type `Literal[b'']` is not assignable to declared return type `str | None` [bad-return]
- ERROR sphinx/ext/intersphinx/_load.py:461:16-33: Returned type `Literal[b'']` is not assignable to declared return type `str` [bad-return]
- ERROR sphinx/ext/intersphinx/_load.py:482:12-29: Returned type `Literal[b'']` is not assignable to declared return type `str` [bad-return]
PyGithub (https://github.com/PyGithub/PyGithub)
- ERROR github/Requester.py:551:16-34: Returned type `Literal[b'']` is not assignable to declared return type `str` [bad-return]
spack (https://github.com/spack/spack)
- ERROR lib/spack/spack/cmd/ci.py:727:12-84: Returned type `Literal[b'']` is not assignable to declared return type `str` [bad-return]
- ERROR lib/spack/spack/oci/oci.py:47:12-49:6: Returned type `Literal[b'']` is not assignable to declared return type `str` [bad-return]
- ERROR lib/spack/spack/oci/opener.py:294:27-58: Argument `Literal[b'']` is not assignable to parameter `url` with type `str` in function `urllib.request.Request.__init__` [bad-argument-type]
- ERROR lib/spack/spack/util/url.py:107:36-40: Argument `Literal[b'']` is not assignable to parameter `filename` with type `str` in function `spack.util.path.sanitize_filename` [bad-argument-type]
poetry (https://github.com/python-poetry/poetry)
- ERROR tests/integration/test_utils_vcs_git.py:438:18-39: Object of class `bytes` has no attribute `encode` [missing-attribute]
- ERROR src/poetry/vcs/git/backend.py:606:12-27: Returned type `Literal[b'']` is not assignable to declared return type `str` [bad-return]
scrapy (https://github.com/scrapy/scrapy)
- ERROR scrapy/http/request/form.py:62:21-82: Argument `Literal[b'']` is not assignable to parameter `url` with type `str` in function `scrapy.http.request.Request._set_url` [bad-argument-type]
prefect (https://github.com/PrefectHQ/prefect)
- ERROR src/integrations/prefect-azure/prefect_azure/repository.py:122:16-24: Returned type `Literal[b''] | str` is not assignable to declared return type `str` [bad-return]
- ERROR src/integrations/prefect-bitbucket/prefect_bitbucket/credentials.py:152:16-84: Returned type `Literal[b'']` is not assignable to declared return type `str` [bad-return]
- ERROR src/integrations/prefect-bitbucket/prefect_bitbucket/repository.py:137:16-24: Returned type `Literal[b''] | str` is not assignable to declared return type `str` [bad-return]
- ERROR src/integrations/prefect-github/prefect_github/credentials.py:56:16-84: Returned type `Literal[b'']` is not assignable to declared return type `str` [bad-return]
- ERROR src/integrations/prefect-github/prefect_github/repository.py:89:16-24: Returned type `Literal[b''] | str` is not assignable to declared return type `str` [bad-return]
- ERROR src/integrations/prefect-gitlab/prefect_gitlab/credentials.py:79:16-84: Returned type `Literal[b'']` is not assignable to declared return type `str` [bad-return]
- ERROR src/integrations/prefect-gitlab/prefect_gitlab/repositories.py:117:16-24: Returned type `Literal[b''] | str` is not assignable to declared return type `str` [bad-return]
- ERROR src/prefect/client/_version_checking.py:67:12-33: Returned type `Literal[b'']` is not assignable to declared return type `str` [bad-return]
- ERROR src/prefect/runner/storage.py:260:16-262:10: Returned type `Literal[b'']` is not assignable to declared return type `str` [bad-return]
- ERROR src/prefect/runner/storage.py:307:61-82: Cannot set item in `dict[str, str]` [unsupported-operation]
|
Primer Diff Classification❌ 1 regression(s) | ✅ 19 improvement(s) | ❓ 1 needs review | 21 project(s) total | +16, -52 errors 1 regression(s) across aiohttp. error kinds:
Detailed analysis❌ Regression (1)aiohttp (+10)
✅ Improvement (19)pip (-1)
openlibrary (-2)
mkdocs (-1)
black (+1)
dulwich (-3)
yarl (+1)
twine (-1)
schemathesis (-2)
streamlit (-1)
zulip (-1)
static-frame (-1)
mypy (-7)
meson (-3)
Together, these changes fix the overload resolution so sphinx (-3)
PyGithub (-1)
spack (-4)
poetry (-2)
scrapy (-1)
prefect (-10)
❓ Needs Review (1)cloud-init (+4, -8)
Suggested fixesSummary: The new as_superclass() branch for NamedTuple subclasses intercepts tuple-related superclass lookups too broadly, causing bad-specialization errors when Self@tuple bounds are checked against erased tuple types for NamedTuple subclasses in aiohttp. 1. In
Was this helpful? React with 👍 or 👎 Classification by primer-classifier (1 heuristic, 20 LLM) |
Summary
Fixes #2867
changed
as_superclassso tuple-like NamedTuple subclasses are upcast through their erased tuple element types instead of the oldtuple[Any, ...]fallback.stops
ParseResultfrom matchingIterable[None], which was why urlunparse incorrectly chose the Literal[b""] overload.Test Plan
add test