Skip to content

Commit 0179352

Browse files
Partially annotated parseresult.py and _mixin.py.
- After review, we don't actually need a generic namedtuple to make this work in a type stub. Inline annotations seemingly work fine so far and don't significantly change the runtime. This might be option 4, which can hold until 3.11 is the lowest supported version. - However, in the meantime, `ParseResultMixin` can be made generic in a helpful way with `typing.AnyStr`. - `port` is a strange case and might be annotated too narrowly or incorrectly; based on some of the ways that it's populated, it might sometimes be an int. - Prefixed `_typing_compat.Self` imports with underscore to avoid poluting namespace with public variables.
1 parent f4d150f commit 0179352

File tree

5 files changed

+143
-102
lines changed

5 files changed

+143
-102
lines changed

src/rfc3986/_mixin.py

Lines changed: 30 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,24 @@
11
"""Module containing the implementation of the URIMixin class."""
2+
import typing as t
23
import warnings
34

45
from . import exceptions as exc
56
from . import misc
67
from . import normalizers
78
from . import validators
9+
from ._typing_compat import Self as _Self
10+
11+
12+
class _AuthorityInfo(t.TypedDict):
13+
userinfo: t.Optional[str]
14+
host: t.Optional[str]
15+
port: t.Optional[str]
816

917

1018
class URIMixin:
1119
"""Mixin with all shared methods for URIs and IRIs."""
1220

13-
def authority_info(self):
21+
def authority_info(self) -> _AuthorityInfo:
1422
"""Return a dictionary with the ``userinfo``, ``host``, and ``port``.
1523
1624
If the authority is not valid, it will raise a
@@ -51,11 +59,11 @@ def authority_info(self):
5159

5260
return matches
5361

54-
def _match_subauthority(self):
62+
def _match_subauthority(self) -> t.Optional[t.Match[str]]:
5563
return misc.SUBAUTHORITY_MATCHER.match(self.authority)
5664

5765
@property
58-
def _validator(self):
66+
def _validator(self) -> validators.Validator:
5967
v = getattr(self, "_cached_validator", None)
6068
if v is not None:
6169
return v
@@ -65,7 +73,7 @@ def _validator(self):
6573
return self._cached_validator
6674

6775
@property
68-
def host(self):
76+
def host(self) -> t.Optional[str]:
6977
"""If present, a string representing the host."""
7078
try:
7179
authority = self.authority_info()
@@ -74,7 +82,7 @@ def host(self):
7482
return authority["host"]
7583

7684
@property
77-
def port(self):
85+
def port(self) -> t.Optional[str]:
7886
"""If present, the port extracted from the authority."""
7987
try:
8088
authority = self.authority_info()
@@ -83,15 +91,15 @@ def port(self):
8391
return authority["port"]
8492

8593
@property
86-
def userinfo(self):
94+
def userinfo(self) -> t.Optional[str]:
8795
"""If present, the userinfo extracted from the authority."""
8896
try:
8997
authority = self.authority_info()
9098
except exc.InvalidAuthority:
9199
return None
92100
return authority["userinfo"]
93101

94-
def is_absolute(self):
102+
def is_absolute(self) -> bool:
95103
"""Determine if this URI Reference is an absolute URI.
96104
97105
See http://tools.ietf.org/html/rfc3986#section-4.3 for explanation.
@@ -135,7 +143,7 @@ def is_valid(self, **kwargs: bool) -> bool:
135143
]
136144
return all(v(r) for v, r in validators)
137145

138-
def authority_is_valid(self, require=False):
146+
def authority_is_valid(self, require: bool = False) -> bool:
139147
"""Determine if the authority component is valid.
140148
141149
.. deprecated:: 1.1.0
@@ -165,7 +173,7 @@ def authority_is_valid(self, require=False):
165173
require=require,
166174
)
167175

168-
def scheme_is_valid(self, require=False):
176+
def scheme_is_valid(self, require: bool = False) -> bool:
169177
"""Determine if the scheme component is valid.
170178
171179
.. deprecated:: 1.1.0
@@ -184,7 +192,7 @@ def scheme_is_valid(self, require=False):
184192
)
185193
return validators.scheme_is_valid(self.scheme, require)
186194

187-
def path_is_valid(self, require=False):
195+
def path_is_valid(self, require: bool = False) -> bool:
188196
"""Determine if the path component is valid.
189197
190198
.. deprecated:: 1.1.0
@@ -203,7 +211,7 @@ def path_is_valid(self, require=False):
203211
)
204212
return validators.path_is_valid(self.path, require)
205213

206-
def query_is_valid(self, require=False):
214+
def query_is_valid(self, require: bool = False) -> bool:
207215
"""Determine if the query component is valid.
208216
209217
.. deprecated:: 1.1.0
@@ -222,7 +230,7 @@ def query_is_valid(self, require=False):
222230
)
223231
return validators.query_is_valid(self.query, require)
224232

225-
def fragment_is_valid(self, require=False):
233+
def fragment_is_valid(self, require: bool = False) -> bool:
226234
"""Determine if the fragment component is valid.
227235
228236
.. deprecated:: 1.1.0
@@ -241,7 +249,7 @@ def fragment_is_valid(self, require=False):
241249
)
242250
return validators.fragment_is_valid(self.fragment, require)
243251

244-
def normalized_equality(self, other_ref):
252+
def normalized_equality(self, other_ref) -> bool:
245253
"""Compare this URIReference to another URIReference.
246254
247255
:param URIReference other_ref: (required), The reference with which
@@ -251,7 +259,7 @@ def normalized_equality(self, other_ref):
251259
"""
252260
return tuple(self.normalize()) == tuple(other_ref.normalize())
253261

254-
def resolve_with(self, base_uri, strict=False):
262+
def resolve_with(self, base_uri, strict: bool = False) -> _Self:
255263
"""Use an absolute URI Reference to resolve this relative reference.
256264
257265
Assuming this is a relative reference that you would like to resolve,
@@ -323,14 +331,14 @@ def resolve_with(self, base_uri, strict=False):
323331
)
324332
return target
325333

326-
def unsplit(self):
334+
def unsplit(self) -> str:
327335
"""Create a URI string from the components.
328336
329337
:returns: The URI Reference reconstituted as a string.
330338
:rtype: str
331339
"""
332340
# See http://tools.ietf.org/html/rfc3986#section-5.3
333-
result_list = []
341+
result_list: list[str] = []
334342
if self.scheme:
335343
result_list.extend([self.scheme, ":"])
336344
if self.authority:
@@ -345,12 +353,12 @@ def unsplit(self):
345353

346354
def copy_with(
347355
self,
348-
scheme=misc.UseExisting,
349-
authority=misc.UseExisting,
350-
path=misc.UseExisting,
351-
query=misc.UseExisting,
352-
fragment=misc.UseExisting,
353-
):
356+
scheme: t.Optional[str] = misc.UseExisting,
357+
authority: t.Optional[str] = misc.UseExisting,
358+
path: t.Optional[str] = misc.UseExisting,
359+
query: t.Optional[str] = misc.UseExisting,
360+
fragment: t.Optional[str] = misc.UseExisting,
361+
) -> _Self:
354362
"""Create a copy of this reference with the new components.
355363
356364
:param str scheme:

src/rfc3986/iri.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
from . import misc
2121
from . import normalizers
2222
from . import uri
23-
from ._typing_compat import Self
23+
from ._typing_compat import Self as _Self
2424

2525

2626
try:
@@ -91,7 +91,7 @@ def from_string(
9191
cls,
9292
iri_string: t.Union[str, bytes],
9393
encoding: str = "utf-8",
94-
) -> Self:
94+
) -> _Self:
9595
"""Parse a IRI reference from the given unicode IRI string.
9696
9797
:param str iri_string: Unicode IRI to be parsed into a reference.

src/rfc3986/misc.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,4 +140,4 @@ def merge_paths(base_uri: "uri.URIReference", relative_path: str) -> str:
140140
return path[:index] + "/" + relative_path
141141

142142

143-
UseExisting = object()
143+
UseExisting: t.Any = object()

0 commit comments

Comments
 (0)