Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions domain_utils/domain_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ def get_ps_plus_1(url: str, **kwargs: Unpack[_StemKwargs]) -> str:

@_load_and_update_extractor
def hostname_subparts(
url: str, include_ps: bool = False, **kwargs: Unpack[_StemKwargs]
url: str, *, include_ps: bool = False, **kwargs: Unpack[_StemKwargs]
) -> list[str]:
"""
Returns a list of slices of a url's hostname down to the eTLD+1 / PS+1.
Expand Down Expand Up @@ -241,6 +241,7 @@ def hostname_subparts(
@_load_and_update_extractor
def stem_url(
url: str,
*,
return_unparsed: bool = True,
scheme_default: str | None = HTTP,
parse_ws: bool = True,
Expand Down Expand Up @@ -351,7 +352,7 @@ def get_stripped_url(url: str, **kwargs: Unpack[_StemKwargs]) -> str:
return stem_url(url, **kwargs)


def get_scheme(url: str, no_scheme: _T = NO_SCHEME) -> str | _T:
def get_scheme(url: str, *, no_scheme: _T = NO_SCHEME) -> str | _T:
"""
Given a url, extract from it the scheme.

Expand Down Expand Up @@ -379,7 +380,7 @@ def get_scheme(url: str, no_scheme: _T = NO_SCHEME) -> str | _T:


@_load_and_update_extractor
def get_port(url: str, extractor: TLDExtract | None = None) -> int | None:
def get_port(url: str, *, extractor: TLDExtract | None = None) -> int | None:
"""
Given a url, extract from it the port if present.

Expand Down
18 changes: 18 additions & 0 deletions tests/test_stem_url.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import inspect

from domain_utils import stem_url
from domain_utils.domain_utils import (
_StemKwargs, # pyright: ignore[reportPrivateUsage]
)


def test_params() -> None:
Expand Down Expand Up @@ -173,3 +178,16 @@ def test_bare_host_keeps_trailing_slash() -> None:
def test_unparsed_returns_the_original_url_not_an_adapted_one() -> None:
url = 'my.example.com:8080/path/to/webapp.htm?aced=1'
assert stem_url(url, scheme_default='wont_parse') == url


def test_stem_kwargs_matches_stem_url_signature() -> None:
# _StemKwargs restates stem_url's keyword parameters so the functions that
# forward **kwargs to it stay checkable. Nothing in the language binds the
# two together, so pin them here: every keyword-only parameter, and no
# other, must appear in the TypedDict.
keyword_only = {
name
for name, parameter in inspect.signature(stem_url).parameters.items()
if parameter.kind is inspect.Parameter.KEYWORD_ONLY
}
assert keyword_only == set(_StemKwargs.__annotations__)
Loading