Skip to content

Commit 3f2619e

Browse files
authored
feat: type annotations (#28)
1 parent 561aa32 commit 3f2619e

File tree

3 files changed

+44
-13
lines changed

3 files changed

+44
-13
lines changed

ada_url/ada_adapter.py

+43-13
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from enum import IntEnum
2+
from typing import Final, Iterable, List, Optional, TypedDict, Union
23

34
from ada_url._ada_wrapper import ffi, lib
45

@@ -56,6 +57,21 @@ class HostType(IntEnum):
5657
IPV6 = 2
5758

5859

60+
class ParseAttributes(TypedDict, total=False):
61+
href: str
62+
username: str
63+
password: str
64+
protocol: str
65+
port: str
66+
hostname: str
67+
host: str
68+
pathname: str
69+
search: str
70+
hash: str
71+
origin: str
72+
host_type: HostType
73+
74+
5975
def _get_obj(constructor, destructor, *args):
6076
obj = constructor(*args)
6177

@@ -95,6 +111,7 @@ class URL:
95111
* ``port``
96112
* ``pathname``
97113
* ``search``
114+
* ``hash``
98115
99116
You can additionally read the ``origin`` and ``host_type`` attributes.
100117
``host_type`` is a :class:`HostType` enum.
@@ -114,7 +131,20 @@ class URL:
114131
115132
"""
116133

117-
def __init__(self, url, base=None):
134+
href: str
135+
username: str
136+
password: str
137+
protocol: str
138+
port: str
139+
hostname: str
140+
host: str
141+
pathname: str
142+
search: str
143+
hash: str
144+
origin: Final[str]
145+
host_type: Final[HostType]
146+
147+
def __init__(self, url: str, base: Optional[str] = None):
118148
url_bytes = url.encode('utf-8')
119149

120150
if base is None:
@@ -150,7 +180,7 @@ def __deepcopy__(self, memo):
150180

151181
return ret
152182

153-
def __delattr__(self, attr):
183+
def __delattr__(self, attr: str):
154184
if attr in CLEAR_ATTRIBUTES:
155185
clear_func = getattr(lib, f'ada_clear_{attr}')
156186
clear_func(self.urlobj)
@@ -160,10 +190,10 @@ def __delattr__(self, attr):
160190
else:
161191
raise AttributeError(f'cannot remove {attr}')
162192

163-
def __dir__(self):
193+
def __dir__(self) -> List[str]:
164194
return super().__dir__() + list(PARSE_ATTRIBUTES)
165195

166-
def __getattr__(self, attr):
196+
def __getattr__(self, attr: str) -> Union[str, HostType]:
167197
if attr in GET_ATTRIBUTES:
168198
get_func = getattr(lib, f'ada_get_{attr}')
169199
data = get_func(self.urlobj)
@@ -179,7 +209,7 @@ def __getattr__(self, attr):
179209

180210
raise AttributeError(f'no attribute named {attr}')
181211

182-
def __setattr__(self, attr, value):
212+
def __setattr__(self, attr: str, value: str) -> None:
183213
if attr in SET_ATTRIBUTES:
184214
try:
185215
value_bytes = value.encode()
@@ -202,7 +232,7 @@ def __repr__(self):
202232
return f'<URL "{self.href}">'
203233

204234
@staticmethod
205-
def can_parse(url, base=None):
235+
def can_parse(url: str, base: Optional[str] = None) -> bool:
206236
try:
207237
url_bytes = url.encode('utf-8')
208238
except Exception:
@@ -221,7 +251,7 @@ def can_parse(url, base=None):
221251
)
222252

223253

224-
def check_url(s):
254+
def check_url(s: str) -> bool:
225255
"""
226256
Returns ``True`` if *s* represents a valid URL, and ``False`` otherwise.
227257
@@ -243,7 +273,7 @@ def check_url(s):
243273
return lib.ada_is_valid(urlobj)
244274

245275

246-
def join_url(base_url, s):
276+
def join_url(base_url: str, s: str) -> str:
247277
"""
248278
Return the URL that results from joining *base_url* to *s*.
249279
Raises ``ValueError`` if no valid URL can be constructed.
@@ -276,7 +306,7 @@ def join_url(base_url, s):
276306
return _get_str(lib.ada_get_href(urlobj))
277307

278308

279-
def normalize_url(s):
309+
def normalize_url(s: str) -> str:
280310
"""
281311
Returns a "normalized" URL with all ``'..'`` and ``'/'`` characters resolved.
282312
@@ -290,7 +320,7 @@ def normalize_url(s):
290320
return parse_url(s, attributes=('href',))['href']
291321

292322

293-
def parse_url(s, attributes=PARSE_ATTRIBUTES):
323+
def parse_url(s: str, attributes: Iterable[str] = PARSE_ATTRIBUTES) -> ParseAttributes:
294324
"""
295325
Returns a dictionary with the parsed components of the URL represented by *s*.
296326
@@ -354,7 +384,7 @@ def parse_url(s, attributes=PARSE_ATTRIBUTES):
354384
return ret
355385

356386

357-
def replace_url(s, **kwargs):
387+
def replace_url(s: str, **kwargs: str) -> str:
358388
"""
359389
Start with the URL represented by *s*, replace the attributes given in the *kwargs*
360390
mapping, and return a normalized URL with the result.
@@ -433,15 +463,15 @@ class idna:
433463
"""
434464

435465
@staticmethod
436-
def decode(s):
466+
def decode(s: Union[str, bytes]) -> str:
437467
if isinstance(s, str):
438468
s = s.encode('ascii')
439469

440470
data = _get_obj(lib.ada_idna_to_unicode, lib.ada_free_owned_string, s, len(s))
441471
return _get_str(data)
442472

443473
@staticmethod
444-
def encode(s):
474+
def encode(s: Union[str, bytes]) -> str:
445475
if isinstance(s, str):
446476
s = s.encode('utf-8')
447477

ada_url/py.typed

Whitespace-only changes.

setup.cfg

+1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ ada_url =
3434
*.o
3535
*.so
3636
*.h
37+
py.typed
3738

3839
[coverage:run]
3940
include =

0 commit comments

Comments
 (0)