Skip to content

Commit bc847a9

Browse files
authored
Use generic NamedTuples to clean up urllib.parse (#9773)
1 parent 4d99b33 commit bc847a9

2 files changed

Lines changed: 36 additions & 51 deletions

File tree

stdlib/urllib/parse.pyi

Lines changed: 36 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,10 @@ scheme_chars: str
4040
if sys.version_info < (3, 11):
4141
MAX_CACHE_SIZE: int
4242

43-
class _ResultMixinBase(Generic[AnyStr]):
44-
def geturl(self) -> AnyStr: ...
45-
46-
class _ResultMixinStr(_ResultMixinBase[str]):
43+
class _ResultMixinStr:
4744
def encode(self, encoding: str = "ascii", errors: str = "strict") -> _ResultMixinBytes: ...
4845

49-
class _ResultMixinBytes(_ResultMixinBase[bytes]):
46+
class _ResultMixinBytes:
5047
def decode(self, encoding: str = "ascii", errors: str = "strict") -> _ResultMixinStr: ...
5148

5249
class _NetlocResultMixinBase(Generic[AnyStr]):
@@ -64,55 +61,44 @@ class _NetlocResultMixinBase(Generic[AnyStr]):
6461
class _NetlocResultMixinStr(_NetlocResultMixinBase[str], _ResultMixinStr): ...
6562
class _NetlocResultMixinBytes(_NetlocResultMixinBase[bytes], _ResultMixinBytes): ...
6663

67-
# Ideally this would be a generic fixed-length tuple,
68-
# but mypy doesn't support that yet: https://github.com/python/mypy/issues/685#issuecomment-992014179
69-
class _DefragResultBase(tuple[AnyStr, ...], Generic[AnyStr]):
70-
if sys.version_info >= (3, 10):
71-
__match_args__ = ("url", "fragment")
72-
@property
73-
def url(self) -> AnyStr: ...
74-
@property
75-
def fragment(self) -> AnyStr: ...
76-
77-
class _SplitResultBase(NamedTuple):
78-
scheme: str
79-
netloc: str
80-
path: str
81-
query: str
82-
fragment: str
83-
84-
class _SplitResultBytesBase(NamedTuple):
85-
scheme: bytes
86-
netloc: bytes
87-
path: bytes
88-
query: bytes
89-
fragment: bytes
90-
91-
class _ParseResultBase(NamedTuple):
92-
scheme: str
93-
netloc: str
94-
path: str
95-
params: str
96-
query: str
97-
fragment: str
98-
99-
class _ParseResultBytesBase(NamedTuple):
100-
scheme: bytes
101-
netloc: bytes
102-
path: bytes
103-
params: bytes
104-
query: bytes
105-
fragment: bytes
64+
class _DefragResultBase(NamedTuple, Generic[AnyStr]):
65+
url: AnyStr
66+
fragment: AnyStr
67+
68+
class _SplitResultBase(NamedTuple, Generic[AnyStr]):
69+
scheme: AnyStr
70+
netloc: AnyStr
71+
path: AnyStr
72+
query: AnyStr
73+
fragment: AnyStr
74+
75+
class _ParseResultBase(NamedTuple, Generic[AnyStr]):
76+
scheme: AnyStr
77+
netloc: AnyStr
78+
path: AnyStr
79+
params: AnyStr
80+
query: AnyStr
81+
fragment: AnyStr
10682

10783
# Structured result objects for string data
108-
class DefragResult(_DefragResultBase[str], _ResultMixinStr): ...
109-
class SplitResult(_SplitResultBase, _NetlocResultMixinStr): ...
110-
class ParseResult(_ParseResultBase, _NetlocResultMixinStr): ...
84+
class DefragResult(_DefragResultBase[str], _ResultMixinStr):
85+
def geturl(self) -> str: ...
86+
87+
class SplitResult(_SplitResultBase[str], _NetlocResultMixinStr):
88+
def geturl(self) -> str: ...
89+
90+
class ParseResult(_ParseResultBase[str], _NetlocResultMixinStr):
91+
def geturl(self) -> str: ...
11192

11293
# Structured result objects for bytes data
113-
class DefragResultBytes(_DefragResultBase[bytes], _ResultMixinBytes): ...
114-
class SplitResultBytes(_SplitResultBytesBase, _NetlocResultMixinBytes): ...
115-
class ParseResultBytes(_ParseResultBytesBase, _NetlocResultMixinBytes): ...
94+
class DefragResultBytes(_DefragResultBase[bytes], _ResultMixinBytes):
95+
def geturl(self) -> bytes: ...
96+
97+
class SplitResultBytes(_SplitResultBase[bytes], _NetlocResultMixinBytes):
98+
def geturl(self) -> bytes: ...
99+
100+
class ParseResultBytes(_ParseResultBase[bytes], _NetlocResultMixinBytes):
101+
def geturl(self) -> bytes: ...
116102

117103
def parse_qs(
118104
qs: AnyStr | None,

tests/stubtest_allowlists/py3_common.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,6 @@ types.SimpleNamespace.__init__ # class doesn't accept positional arguments but
205205
typing.IO.__next__ # Added because IO streams are iterable. See https://github.com/python/typeshed/commit/97bc450acd60c1bcdafef3ce8fbe3b95a9c0cac3
206206
typing.type_check_only # typing decorator that is not available at runtime
207207
unittest.mock.patch # It's a complicated overload and I haven't been able to figure out why stubtest doesn't like it
208-
urllib.parse._DefragResultBase.__new__ # Generic NamedTuple is problematic in mypy, so regular tuple was used. See https://github.com/python/mypy/issues/685
209208
urllib.request.HTTPPasswordMgrWithPriorAuth.__init__ # Args are passed as is to super, so super args are specified
210209
weakref.CallableProxyType.__getattr__ # Should have all attributes of proxy
211210
weakref.ProxyType.__getattr__ # Should have all attributes of proxy

0 commit comments

Comments
 (0)