url-normalize 2.2.0__tar.gz → 2.2.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of url-normalize might be problematic. Click here for more details.
- {url_normalize-2.2.0 → url_normalize-2.2.1}/PKG-INFO +56 -31
- {url_normalize-2.2.0 → url_normalize-2.2.1}/README.md +56 -29
- {url_normalize-2.2.0 → url_normalize-2.2.1}/pyproject.toml +3 -14
- url_normalize-2.2.1/tests/test_deconstruct_url.py +40 -0
- url_normalize-2.2.1/tests/test_normalize_fragment.py +23 -0
- url_normalize-2.2.1/tests/test_normalize_host.py +32 -0
- url_normalize-2.2.1/tests/test_normalize_path.py +44 -0
- url_normalize-2.2.1/tests/test_normalize_port.py +26 -0
- url_normalize-2.2.1/tests/test_normalize_scheme.py +18 -0
- url_normalize-2.2.1/tests/test_normalize_userinfo.py +21 -0
- url_normalize-2.2.1/tests/test_provide_url_scheme.py +32 -0
- url_normalize-2.2.1/tests/test_reconstruct_url.py +42 -0
- {url_normalize-2.2.0 → url_normalize-2.2.1}/url_normalize/__init__.py +1 -1
- url_normalize-2.2.1/url_normalize/py.typed +0 -0
- {url_normalize-2.2.0 → url_normalize-2.2.1}/url_normalize.egg-info/PKG-INFO +56 -31
- {url_normalize-2.2.0 → url_normalize-2.2.1}/url_normalize.egg-info/SOURCES.txt +1 -0
- {url_normalize-2.2.0 → url_normalize-2.2.1}/url_normalize.egg-info/requires.txt +0 -2
- url_normalize-2.2.0/tests/test_deconstruct_url.py +0 -35
- url_normalize-2.2.0/tests/test_normalize_fragment.py +0 -21
- url_normalize-2.2.0/tests/test_normalize_host.py +0 -29
- url_normalize-2.2.0/tests/test_normalize_path.py +0 -42
- url_normalize-2.2.0/tests/test_normalize_port.py +0 -13
- url_normalize-2.2.0/tests/test_normalize_scheme.py +0 -13
- url_normalize-2.2.0/tests/test_normalize_userinfo.py +0 -19
- url_normalize-2.2.0/tests/test_provide_url_scheme.py +0 -30
- url_normalize-2.2.0/tests/test_reconstruct_url.py +0 -41
- {url_normalize-2.2.0 → url_normalize-2.2.1}/LICENSE +0 -0
- {url_normalize-2.2.0 → url_normalize-2.2.1}/setup.cfg +0 -0
- {url_normalize-2.2.0 → url_normalize-2.2.1}/tests/test_cli.py +0 -0
- {url_normalize-2.2.0 → url_normalize-2.2.1}/tests/test_generic_url_cleanup.py +0 -0
- {url_normalize-2.2.0 → url_normalize-2.2.1}/tests/test_normalize_query.py +0 -0
- {url_normalize-2.2.0 → url_normalize-2.2.1}/tests/test_normalize_query_filters.py +0 -0
- {url_normalize-2.2.0 → url_normalize-2.2.1}/tests/test_provide_url_domain.py +0 -0
- {url_normalize-2.2.0 → url_normalize-2.2.1}/tests/test_tools.py +0 -0
- {url_normalize-2.2.0 → url_normalize-2.2.1}/tests/test_url_normalize.py +0 -0
- {url_normalize-2.2.0 → url_normalize-2.2.1}/url_normalize/cli.py +0 -0
- {url_normalize-2.2.0 → url_normalize-2.2.1}/url_normalize/generic_url_cleanup.py +0 -0
- {url_normalize-2.2.0 → url_normalize-2.2.1}/url_normalize/normalize_fragment.py +0 -0
- {url_normalize-2.2.0 → url_normalize-2.2.1}/url_normalize/normalize_host.py +0 -0
- {url_normalize-2.2.0 → url_normalize-2.2.1}/url_normalize/normalize_path.py +0 -0
- {url_normalize-2.2.0 → url_normalize-2.2.1}/url_normalize/normalize_port.py +0 -0
- {url_normalize-2.2.0 → url_normalize-2.2.1}/url_normalize/normalize_query.py +0 -0
- {url_normalize-2.2.0 → url_normalize-2.2.1}/url_normalize/normalize_scheme.py +0 -0
- {url_normalize-2.2.0 → url_normalize-2.2.1}/url_normalize/normalize_userinfo.py +0 -0
- {url_normalize-2.2.0 → url_normalize-2.2.1}/url_normalize/param_allowlist.py +0 -0
- {url_normalize-2.2.0 → url_normalize-2.2.1}/url_normalize/provide_url_domain.py +0 -0
- {url_normalize-2.2.0 → url_normalize-2.2.1}/url_normalize/provide_url_scheme.py +0 -0
- {url_normalize-2.2.0 → url_normalize-2.2.1}/url_normalize/tools.py +0 -0
- {url_normalize-2.2.0 → url_normalize-2.2.1}/url_normalize/url_normalize.py +0 -0
- {url_normalize-2.2.0 → url_normalize-2.2.1}/url_normalize.egg-info/dependency_links.txt +0 -0
- {url_normalize-2.2.0 → url_normalize-2.2.1}/url_normalize.egg-info/entry_points.txt +0 -0
- {url_normalize-2.2.0 → url_normalize-2.2.1}/url_normalize.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: url-normalize
|
|
3
|
-
Version: 2.2.
|
|
3
|
+
Version: 2.2.1
|
|
4
4
|
Summary: URL normalization for Python
|
|
5
5
|
Author-email: Nikolay Panov <github@npanov.com>
|
|
6
6
|
License: MIT
|
|
@@ -8,7 +8,7 @@ Project-URL: Homepage, https://github.com/niksite/url-normalize
|
|
|
8
8
|
Project-URL: Repository, https://github.com/niksite/url-normalize
|
|
9
9
|
Project-URL: Issues, https://github.com/niksite/url-normalize/issues
|
|
10
10
|
Project-URL: Changelog, https://github.com/niksite/url-normalize/blob/master/CHANGELOG.md
|
|
11
|
-
Keywords: url,normalization,normalize
|
|
11
|
+
Keywords: url,normalization,normalize,normalizer
|
|
12
12
|
Requires-Python: >=3.8
|
|
13
13
|
Description-Content-Type: text/markdown
|
|
14
14
|
License-File: LICENSE
|
|
@@ -17,48 +17,67 @@ Provides-Extra: dev
|
|
|
17
17
|
Requires-Dist: mypy; extra == "dev"
|
|
18
18
|
Requires-Dist: pre-commit; extra == "dev"
|
|
19
19
|
Requires-Dist: pytest-cov; extra == "dev"
|
|
20
|
-
Requires-Dist: pytest-ruff; extra == "dev"
|
|
21
20
|
Requires-Dist: pytest-socket; extra == "dev"
|
|
22
21
|
Requires-Dist: pytest; extra == "dev"
|
|
23
22
|
Requires-Dist: ruff; extra == "dev"
|
|
24
|
-
Requires-Dist: tox; extra == "dev"
|
|
25
23
|
Dynamic: license-file
|
|
26
24
|
|
|
27
25
|
# url-normalize
|
|
28
26
|
|
|
29
|
-
[](https://github.com/niksite/url-normalize/actions/workflows/ci.yml)
|
|
28
|
+
[](https://coveralls.io/r/niksite/url-normalize)
|
|
29
|
+
[](https://pypi.org/project/url-normalize/)
|
|
31
30
|
|
|
32
|
-
|
|
31
|
+
A Python library for standardizing and normalizing URLs with support for internationalized domain names (IDN).
|
|
33
32
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
33
|
+
## Table of Contents
|
|
34
|
+
|
|
35
|
+
- [Introduction](#introduction)
|
|
36
|
+
- [Features](#features)
|
|
37
|
+
- [Installation](#installation)
|
|
38
|
+
- [Usage](#usage)
|
|
39
|
+
- [Python API](#python-api)
|
|
40
|
+
- [Command Line](#command-line-usage)
|
|
41
|
+
- [Documentation](#documentation)
|
|
42
|
+
- [Contributing](#contributing)
|
|
43
|
+
- [License](#license)
|
|
44
|
+
|
|
45
|
+
## Introduction
|
|
46
|
+
|
|
47
|
+
url-normalize provides a robust URI normalization function that:
|
|
48
|
+
|
|
49
|
+
- Takes care of IDN domains.
|
|
50
|
+
- Always provides the URI scheme in lowercase characters.
|
|
51
|
+
- Always provides the host, if any, in lowercase characters.
|
|
52
|
+
- Only performs percent-encoding where it is essential.
|
|
53
|
+
- Always uses uppercase A-through-F characters when percent-encoding.
|
|
54
|
+
- Prevents dot-segments appearing in non-relative URI paths.
|
|
55
|
+
- For schemes that define a default authority, uses an empty authority if the
|
|
41
56
|
default is desired.
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
57
|
+
- For schemes that define an empty path to be equivalent to a path of "/",
|
|
58
|
+
uses "/".
|
|
59
|
+
- For schemes that define a port, uses an empty port if the default is desired
|
|
60
|
+
- Ensures all portions of the URI are utf-8 encoded NFC from Unicode strings
|
|
46
61
|
|
|
47
|
-
Inspired by Sam Ruby's [urlnorm.py](
|
|
62
|
+
Inspired by Sam Ruby's [urlnorm.py](http://intertwingly.net/blog/2004/08/04/Urlnorm)
|
|
48
63
|
|
|
49
64
|
## Features
|
|
50
65
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
66
|
+
- **IDN Support**: Full internationalized domain name handling
|
|
67
|
+
- **Configurable Defaults**:
|
|
68
|
+
- Customizable default scheme (https by default)
|
|
69
|
+
- Configurable default domain for absolute paths
|
|
70
|
+
- **Query Parameter Control**:
|
|
71
|
+
- Parameter filtering with allowlists
|
|
72
|
+
- Support for domain-specific parameter rules
|
|
73
|
+
- **Versatile URL Handling**:
|
|
74
|
+
- Empty string URLs
|
|
75
|
+
- Double slash URLs (//domain.tld)
|
|
76
|
+
- Shebang (#!) URLs
|
|
77
|
+
- **Developer Friendly**:
|
|
78
|
+
- Cross-version Python compatibility (3.8+)
|
|
79
|
+
- 100% test coverage
|
|
80
|
+
- Modern type hints and string handling
|
|
62
81
|
|
|
63
82
|
## Installation
|
|
64
83
|
|
|
@@ -68,6 +87,8 @@ pip install url-normalize
|
|
|
68
87
|
|
|
69
88
|
## Usage
|
|
70
89
|
|
|
90
|
+
### Python API
|
|
91
|
+
|
|
71
92
|
```python
|
|
72
93
|
from url_normalize import url_normalize
|
|
73
94
|
|
|
@@ -108,7 +129,7 @@ print(url_normalize("/images/logo.png", default_scheme="http", default_domain="e
|
|
|
108
129
|
# Output: http://example.com/images/logo.png
|
|
109
130
|
```
|
|
110
131
|
|
|
111
|
-
### Command-line
|
|
132
|
+
### Command-line Usage
|
|
112
133
|
|
|
113
134
|
You can also use `url-normalize` from the command line:
|
|
114
135
|
|
|
@@ -145,6 +166,10 @@ $ uvx url-normalize www.foo.com:80/foo
|
|
|
145
166
|
|
|
146
167
|
For a complete history of changes, see [CHANGELOG.md](CHANGELOG.md).
|
|
147
168
|
|
|
169
|
+
## Contributing
|
|
170
|
+
|
|
171
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
172
|
+
|
|
148
173
|
## License
|
|
149
174
|
|
|
150
175
|
MIT License
|
|
@@ -1,38 +1,59 @@
|
|
|
1
1
|
# url-normalize
|
|
2
2
|
|
|
3
|
-
[](https://github.com/niksite/url-normalize/actions/workflows/ci.yml)
|
|
4
|
+
[](https://coveralls.io/r/niksite/url-normalize)
|
|
5
|
+
[](https://pypi.org/project/url-normalize/)
|
|
6
|
+
|
|
7
|
+
A Python library for standardizing and normalizing URLs with support for internationalized domain names (IDN).
|
|
8
|
+
|
|
9
|
+
## Table of Contents
|
|
10
|
+
|
|
11
|
+
- [Introduction](#introduction)
|
|
12
|
+
- [Features](#features)
|
|
13
|
+
- [Installation](#installation)
|
|
14
|
+
- [Usage](#usage)
|
|
15
|
+
- [Python API](#python-api)
|
|
16
|
+
- [Command Line](#command-line-usage)
|
|
17
|
+
- [Documentation](#documentation)
|
|
18
|
+
- [Contributing](#contributing)
|
|
19
|
+
- [License](#license)
|
|
20
|
+
|
|
21
|
+
## Introduction
|
|
22
|
+
|
|
23
|
+
url-normalize provides a robust URI normalization function that:
|
|
24
|
+
|
|
25
|
+
- Takes care of IDN domains.
|
|
26
|
+
- Always provides the URI scheme in lowercase characters.
|
|
27
|
+
- Always provides the host, if any, in lowercase characters.
|
|
28
|
+
- Only performs percent-encoding where it is essential.
|
|
29
|
+
- Always uses uppercase A-through-F characters when percent-encoding.
|
|
30
|
+
- Prevents dot-segments appearing in non-relative URI paths.
|
|
31
|
+
- For schemes that define a default authority, uses an empty authority if the
|
|
15
32
|
default is desired.
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
33
|
+
- For schemes that define an empty path to be equivalent to a path of "/",
|
|
34
|
+
uses "/".
|
|
35
|
+
- For schemes that define a port, uses an empty port if the default is desired
|
|
36
|
+
- Ensures all portions of the URI are utf-8 encoded NFC from Unicode strings
|
|
20
37
|
|
|
21
|
-
Inspired by Sam Ruby's [urlnorm.py](
|
|
38
|
+
Inspired by Sam Ruby's [urlnorm.py](http://intertwingly.net/blog/2004/08/04/Urlnorm)
|
|
22
39
|
|
|
23
40
|
## Features
|
|
24
41
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
42
|
+
- **IDN Support**: Full internationalized domain name handling
|
|
43
|
+
- **Configurable Defaults**:
|
|
44
|
+
- Customizable default scheme (https by default)
|
|
45
|
+
- Configurable default domain for absolute paths
|
|
46
|
+
- **Query Parameter Control**:
|
|
47
|
+
- Parameter filtering with allowlists
|
|
48
|
+
- Support for domain-specific parameter rules
|
|
49
|
+
- **Versatile URL Handling**:
|
|
50
|
+
- Empty string URLs
|
|
51
|
+
- Double slash URLs (//domain.tld)
|
|
52
|
+
- Shebang (#!) URLs
|
|
53
|
+
- **Developer Friendly**:
|
|
54
|
+
- Cross-version Python compatibility (3.8+)
|
|
55
|
+
- 100% test coverage
|
|
56
|
+
- Modern type hints and string handling
|
|
36
57
|
|
|
37
58
|
## Installation
|
|
38
59
|
|
|
@@ -42,6 +63,8 @@ pip install url-normalize
|
|
|
42
63
|
|
|
43
64
|
## Usage
|
|
44
65
|
|
|
66
|
+
### Python API
|
|
67
|
+
|
|
45
68
|
```python
|
|
46
69
|
from url_normalize import url_normalize
|
|
47
70
|
|
|
@@ -82,7 +105,7 @@ print(url_normalize("/images/logo.png", default_scheme="http", default_domain="e
|
|
|
82
105
|
# Output: http://example.com/images/logo.png
|
|
83
106
|
```
|
|
84
107
|
|
|
85
|
-
### Command-line
|
|
108
|
+
### Command-line Usage
|
|
86
109
|
|
|
87
110
|
You can also use `url-normalize` from the command line:
|
|
88
111
|
|
|
@@ -119,6 +142,10 @@ $ uvx url-normalize www.foo.com:80/foo
|
|
|
119
142
|
|
|
120
143
|
For a complete history of changes, see [CHANGELOG.md](CHANGELOG.md).
|
|
121
144
|
|
|
145
|
+
## Contributing
|
|
146
|
+
|
|
147
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
148
|
+
|
|
122
149
|
## License
|
|
123
150
|
|
|
124
151
|
MIT License
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "url-normalize"
|
|
3
|
-
version = "2.2.
|
|
3
|
+
version = "2.2.1"
|
|
4
4
|
description = "URL normalization for Python"
|
|
5
5
|
authors = [{ name = "Nikolay Panov", email = "github@npanov.com" }]
|
|
6
6
|
license = { text = "MIT" }
|
|
7
7
|
readme = "README.md"
|
|
8
8
|
requires-python = ">=3.8"
|
|
9
|
-
keywords = ["url", "normalization", "normalize"]
|
|
9
|
+
keywords = ["url", "normalization", "normalize", "normalizer"]
|
|
10
10
|
dependencies = ["idna>=3.3"]
|
|
11
11
|
|
|
12
12
|
[project.urls]
|
|
@@ -19,16 +19,7 @@ Changelog = "https://github.com/niksite/url-normalize/blob/master/CHANGELOG.md"
|
|
|
19
19
|
url-normalize = "url_normalize.cli:main"
|
|
20
20
|
|
|
21
21
|
[project.optional-dependencies]
|
|
22
|
-
dev = [
|
|
23
|
-
"mypy",
|
|
24
|
-
"pre-commit",
|
|
25
|
-
"pytest-cov",
|
|
26
|
-
"pytest-ruff",
|
|
27
|
-
"pytest-socket",
|
|
28
|
-
"pytest",
|
|
29
|
-
"ruff",
|
|
30
|
-
"tox",
|
|
31
|
-
]
|
|
22
|
+
dev = ["mypy", "pre-commit", "pytest-cov", "pytest-socket", "pytest", "ruff"]
|
|
32
23
|
|
|
33
24
|
[tool.ruff]
|
|
34
25
|
target-version = "py38"
|
|
@@ -71,11 +62,9 @@ build-backend = "setuptools.build_meta"
|
|
|
71
62
|
|
|
72
63
|
[tool.pytest.ini_options]
|
|
73
64
|
addopts = [
|
|
74
|
-
"--cov-fail-under=100",
|
|
75
65
|
"--cov-report=term-missing:skip-covered",
|
|
76
66
|
"--cov=url_normalize",
|
|
77
67
|
"--disable-socket",
|
|
78
|
-
"--ruff",
|
|
79
68
|
"-v",
|
|
80
69
|
]
|
|
81
70
|
python_files = ["tests.py", "test_*.py", "*_tests.py"]
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"""Deconstruct url tests."""
|
|
2
|
+
|
|
3
|
+
import pytest
|
|
4
|
+
|
|
5
|
+
from url_normalize.tools import URL, deconstruct_url
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@pytest.mark.parametrize(
|
|
9
|
+
("url", "expected"),
|
|
10
|
+
[
|
|
11
|
+
(
|
|
12
|
+
"http://site.com",
|
|
13
|
+
URL(
|
|
14
|
+
fragment="",
|
|
15
|
+
host="site.com",
|
|
16
|
+
path="",
|
|
17
|
+
port="",
|
|
18
|
+
query="",
|
|
19
|
+
scheme="http",
|
|
20
|
+
userinfo="",
|
|
21
|
+
),
|
|
22
|
+
),
|
|
23
|
+
(
|
|
24
|
+
"http://user@www.example.com:8080/path/index.html?param=val#fragment",
|
|
25
|
+
URL(
|
|
26
|
+
fragment="fragment",
|
|
27
|
+
host="www.example.com",
|
|
28
|
+
path="/path/index.html",
|
|
29
|
+
port="8080",
|
|
30
|
+
query="param=val",
|
|
31
|
+
scheme="http",
|
|
32
|
+
userinfo="user@",
|
|
33
|
+
),
|
|
34
|
+
),
|
|
35
|
+
],
|
|
36
|
+
)
|
|
37
|
+
def test_deconstruct_url_result_is_expected(url: str, expected: URL) -> None:
|
|
38
|
+
"""Assert we got expected results from the deconstruct_url function."""
|
|
39
|
+
result = deconstruct_url(url)
|
|
40
|
+
assert result == expected, url
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"""Tests for normalize_fragment function."""
|
|
2
|
+
|
|
3
|
+
import pytest
|
|
4
|
+
|
|
5
|
+
from url_normalize.url_normalize import normalize_fragment
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@pytest.mark.parametrize(
|
|
9
|
+
("fragment", "expected"),
|
|
10
|
+
[
|
|
11
|
+
("", ""),
|
|
12
|
+
("fragment", "fragment"),
|
|
13
|
+
("пример", "%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80"),
|
|
14
|
+
("!fragment", "%21fragment"),
|
|
15
|
+
("~fragment", "~fragment"),
|
|
16
|
+
# Issue #36: Equal sign should not be encoded
|
|
17
|
+
("gid=1234", "gid=1234"),
|
|
18
|
+
],
|
|
19
|
+
)
|
|
20
|
+
def test_normalize_fragment_result_is_expected(fragment: str, expected: str) -> None:
|
|
21
|
+
"""Assert we got expected results from the normalize_fragment function."""
|
|
22
|
+
result = normalize_fragment(fragment)
|
|
23
|
+
assert result == expected, fragment
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"""Tests for normalize_host function."""
|
|
2
|
+
|
|
3
|
+
import pytest
|
|
4
|
+
|
|
5
|
+
from url_normalize.url_normalize import normalize_host
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@pytest.mark.parametrize(
|
|
9
|
+
("host", "expected"),
|
|
10
|
+
[
|
|
11
|
+
# Basic cases
|
|
12
|
+
("site.com", "site.com"),
|
|
13
|
+
("SITE.COM", "site.com"),
|
|
14
|
+
("site.com.", "site.com"),
|
|
15
|
+
# Cyrillic domains
|
|
16
|
+
("пример.испытание", "xn--e1afmkfd.xn--80akhbyknj4f"),
|
|
17
|
+
# Mixed case with Cyrillic
|
|
18
|
+
("ExAmPle.РФ", "example.xn--p1ai"),
|
|
19
|
+
# IDNA2008 with UTS46
|
|
20
|
+
("faß.de", "fass.de"), # Normalize using transitional rules
|
|
21
|
+
# Edge cases
|
|
22
|
+
("ドメイン.テスト", "xn--eckwd4c7c.xn--zckzah"), # Japanese
|
|
23
|
+
("domain.café", "domain.xn--caf-dma"), # Latin with diacritic
|
|
24
|
+
# Normalization tests
|
|
25
|
+
("über.example", "xn--ber-goa.example"), # IDNA 2008 for umlaut
|
|
26
|
+
("example。com", "example.com"), # Normalize full-width punctuation
|
|
27
|
+
],
|
|
28
|
+
)
|
|
29
|
+
def test_normalize_host_result_is_expected(host: str, expected: str) -> None:
|
|
30
|
+
"""Assert we got expected results from the normalize_host function."""
|
|
31
|
+
result = normalize_host(host)
|
|
32
|
+
assert result == expected, host
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"""Tests for normalize_path function."""
|
|
2
|
+
|
|
3
|
+
import pytest
|
|
4
|
+
|
|
5
|
+
from url_normalize.url_normalize import normalize_path
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@pytest.mark.parametrize(
|
|
9
|
+
("path", "expected"),
|
|
10
|
+
[
|
|
11
|
+
("..", "/"),
|
|
12
|
+
("", "/"),
|
|
13
|
+
("/../foo", "/foo"),
|
|
14
|
+
("/..foo", "/..foo"),
|
|
15
|
+
("/./../foo", "/foo"),
|
|
16
|
+
("/./foo", "/foo"),
|
|
17
|
+
("/./foo/.", "/foo/"),
|
|
18
|
+
("/.foo", "/.foo"),
|
|
19
|
+
("/", "/"),
|
|
20
|
+
("/foo..", "/foo.."),
|
|
21
|
+
("/foo.", "/foo."),
|
|
22
|
+
("/FOO", "/FOO"),
|
|
23
|
+
("/foo/../bar", "/bar"),
|
|
24
|
+
("/foo/./bar", "/foo/bar"),
|
|
25
|
+
("/foo//", "/foo/"),
|
|
26
|
+
("/foo///bar//", "/foo/bar/"),
|
|
27
|
+
("/foo/bar/..", "/foo/"),
|
|
28
|
+
("/foo/bar/../..", "/"),
|
|
29
|
+
("/foo/bar/../../../../baz", "/baz"),
|
|
30
|
+
("/foo/bar/../../../baz", "/baz"),
|
|
31
|
+
("/foo/bar/../../", "/"),
|
|
32
|
+
("/foo/bar/../../baz", "/baz"),
|
|
33
|
+
("/foo/bar/../", "/foo/"),
|
|
34
|
+
("/foo/bar/../baz", "/foo/baz"),
|
|
35
|
+
("/foo/bar/.", "/foo/bar/"),
|
|
36
|
+
("/foo/bar/./", "/foo/bar/"),
|
|
37
|
+
# Issue #25: we should preserve ? in the path
|
|
38
|
+
("/More+Tea+Vicar%3F/discussion", "/More+Tea+Vicar%3F/discussion"),
|
|
39
|
+
],
|
|
40
|
+
)
|
|
41
|
+
def test_normalize_path_result_is_expected(path: str, expected: str) -> None:
|
|
42
|
+
"""Assert we got expected results from the normalize_path function."""
|
|
43
|
+
result = normalize_path(path, "http")
|
|
44
|
+
assert result == expected, path
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"""Tests for normalize_port function."""
|
|
2
|
+
|
|
3
|
+
import pytest
|
|
4
|
+
|
|
5
|
+
from url_normalize.url_normalize import normalize_port
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@pytest.mark.parametrize(
|
|
9
|
+
("port", "expected"),
|
|
10
|
+
[
|
|
11
|
+
("8080", "8080"), # Non-default port
|
|
12
|
+
("", ""), # Empty port
|
|
13
|
+
("80", ""), # Default HTTP port
|
|
14
|
+
("string", "string"), # Non-numeric port (should pass through)
|
|
15
|
+
# Add more cases as needed, e.g., for HTTPS
|
|
16
|
+
pytest.param("443", "", id="https_default_port"),
|
|
17
|
+
],
|
|
18
|
+
)
|
|
19
|
+
def test_normalize_port_result_is_expected(port: str, expected: str):
|
|
20
|
+
"""Assert we got expected results from the normalize_port function."""
|
|
21
|
+
# Test with 'http' scheme for most cases
|
|
22
|
+
scheme = "https" if port == "443" else "http"
|
|
23
|
+
|
|
24
|
+
result = normalize_port(port, scheme)
|
|
25
|
+
|
|
26
|
+
assert result == expected
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"""Tests for normalize_scheme function."""
|
|
2
|
+
|
|
3
|
+
import pytest
|
|
4
|
+
|
|
5
|
+
from url_normalize.url_normalize import normalize_scheme
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@pytest.mark.parametrize(
|
|
9
|
+
("scheme", "expected"),
|
|
10
|
+
[
|
|
11
|
+
("http", "http"),
|
|
12
|
+
("HTTP", "http"),
|
|
13
|
+
],
|
|
14
|
+
)
|
|
15
|
+
def test_normalize_scheme_result_is_expected(scheme: str, expected: str) -> None:
|
|
16
|
+
"""Assert we got expected results from the normalize_scheme function."""
|
|
17
|
+
result = normalize_scheme(scheme)
|
|
18
|
+
assert result == expected, scheme
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"""Tests for normalize_userinfo function."""
|
|
2
|
+
|
|
3
|
+
import pytest
|
|
4
|
+
|
|
5
|
+
from url_normalize.url_normalize import normalize_userinfo
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@pytest.mark.parametrize(
|
|
9
|
+
("userinfo", "expected"),
|
|
10
|
+
[
|
|
11
|
+
(":@", ""),
|
|
12
|
+
("", ""),
|
|
13
|
+
("@", ""),
|
|
14
|
+
("user:password@", "user:password@"),
|
|
15
|
+
("user@", "user@"),
|
|
16
|
+
],
|
|
17
|
+
)
|
|
18
|
+
def test_normalize_userinfo_result_is_expected(userinfo: str, expected: str) -> None:
|
|
19
|
+
"""Assert we got expected results from the normalize_userinfo function."""
|
|
20
|
+
result = normalize_userinfo(userinfo)
|
|
21
|
+
assert result == expected, userinfo
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"""Tests for provide_url_scheme function."""
|
|
2
|
+
|
|
3
|
+
import pytest
|
|
4
|
+
|
|
5
|
+
from url_normalize.url_normalize import provide_url_scheme
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@pytest.mark.parametrize(
|
|
9
|
+
("url", "expected"),
|
|
10
|
+
[
|
|
11
|
+
("", ""),
|
|
12
|
+
("-", "-"),
|
|
13
|
+
("/file/path", "/file/path"),
|
|
14
|
+
("//site/path", "https://site/path"),
|
|
15
|
+
("ftp://site/", "ftp://site/"),
|
|
16
|
+
("site/page", "https://site/page"),
|
|
17
|
+
],
|
|
18
|
+
)
|
|
19
|
+
def test_provide_url_scheme_result_is_expected(url: str, expected: str) -> None:
|
|
20
|
+
"""Assert we got expected results from the provide_url_scheme function."""
|
|
21
|
+
result = provide_url_scheme(url)
|
|
22
|
+
assert result == expected, url
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def test_provide_url_scheme_accept_default_scheme_param() -> None:
|
|
26
|
+
"""Assert we could provide default_scheme param other than https."""
|
|
27
|
+
url = "//site/path"
|
|
28
|
+
expected = "http://site/path"
|
|
29
|
+
|
|
30
|
+
actual = provide_url_scheme(url, default_scheme="http")
|
|
31
|
+
|
|
32
|
+
assert actual == expected
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"""Reconstruct url tests."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import pytest
|
|
6
|
+
|
|
7
|
+
from url_normalize.tools import URL, reconstruct_url
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@pytest.mark.parametrize(
|
|
11
|
+
("url_obj", "expected"),
|
|
12
|
+
[
|
|
13
|
+
(
|
|
14
|
+
URL(
|
|
15
|
+
fragment="",
|
|
16
|
+
host="site.com",
|
|
17
|
+
path="",
|
|
18
|
+
port="",
|
|
19
|
+
query="",
|
|
20
|
+
scheme="http",
|
|
21
|
+
userinfo="",
|
|
22
|
+
),
|
|
23
|
+
"http://site.com",
|
|
24
|
+
),
|
|
25
|
+
(
|
|
26
|
+
URL(
|
|
27
|
+
fragment="fragment",
|
|
28
|
+
host="www.example.com",
|
|
29
|
+
path="/path/index.html",
|
|
30
|
+
port="8080",
|
|
31
|
+
query="param=val",
|
|
32
|
+
scheme="http",
|
|
33
|
+
userinfo="user@",
|
|
34
|
+
),
|
|
35
|
+
"http://user@www.example.com:8080/path/index.html?param=val#fragment",
|
|
36
|
+
),
|
|
37
|
+
],
|
|
38
|
+
)
|
|
39
|
+
def test_reconstruct_url_result_is_expected(url_obj: URL, expected: str) -> None:
|
|
40
|
+
"""Assert we got expected results from the reconstruct_url function."""
|
|
41
|
+
result = reconstruct_url(url_obj)
|
|
42
|
+
assert result == expected, url_obj
|
|
File without changes
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: url-normalize
|
|
3
|
-
Version: 2.2.
|
|
3
|
+
Version: 2.2.1
|
|
4
4
|
Summary: URL normalization for Python
|
|
5
5
|
Author-email: Nikolay Panov <github@npanov.com>
|
|
6
6
|
License: MIT
|
|
@@ -8,7 +8,7 @@ Project-URL: Homepage, https://github.com/niksite/url-normalize
|
|
|
8
8
|
Project-URL: Repository, https://github.com/niksite/url-normalize
|
|
9
9
|
Project-URL: Issues, https://github.com/niksite/url-normalize/issues
|
|
10
10
|
Project-URL: Changelog, https://github.com/niksite/url-normalize/blob/master/CHANGELOG.md
|
|
11
|
-
Keywords: url,normalization,normalize
|
|
11
|
+
Keywords: url,normalization,normalize,normalizer
|
|
12
12
|
Requires-Python: >=3.8
|
|
13
13
|
Description-Content-Type: text/markdown
|
|
14
14
|
License-File: LICENSE
|
|
@@ -17,48 +17,67 @@ Provides-Extra: dev
|
|
|
17
17
|
Requires-Dist: mypy; extra == "dev"
|
|
18
18
|
Requires-Dist: pre-commit; extra == "dev"
|
|
19
19
|
Requires-Dist: pytest-cov; extra == "dev"
|
|
20
|
-
Requires-Dist: pytest-ruff; extra == "dev"
|
|
21
20
|
Requires-Dist: pytest-socket; extra == "dev"
|
|
22
21
|
Requires-Dist: pytest; extra == "dev"
|
|
23
22
|
Requires-Dist: ruff; extra == "dev"
|
|
24
|
-
Requires-Dist: tox; extra == "dev"
|
|
25
23
|
Dynamic: license-file
|
|
26
24
|
|
|
27
25
|
# url-normalize
|
|
28
26
|
|
|
29
|
-
[](https://github.com/niksite/url-normalize/actions/workflows/ci.yml)
|
|
28
|
+
[](https://coveralls.io/r/niksite/url-normalize)
|
|
29
|
+
[](https://pypi.org/project/url-normalize/)
|
|
31
30
|
|
|
32
|
-
|
|
31
|
+
A Python library for standardizing and normalizing URLs with support for internationalized domain names (IDN).
|
|
33
32
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
33
|
+
## Table of Contents
|
|
34
|
+
|
|
35
|
+
- [Introduction](#introduction)
|
|
36
|
+
- [Features](#features)
|
|
37
|
+
- [Installation](#installation)
|
|
38
|
+
- [Usage](#usage)
|
|
39
|
+
- [Python API](#python-api)
|
|
40
|
+
- [Command Line](#command-line-usage)
|
|
41
|
+
- [Documentation](#documentation)
|
|
42
|
+
- [Contributing](#contributing)
|
|
43
|
+
- [License](#license)
|
|
44
|
+
|
|
45
|
+
## Introduction
|
|
46
|
+
|
|
47
|
+
url-normalize provides a robust URI normalization function that:
|
|
48
|
+
|
|
49
|
+
- Takes care of IDN domains.
|
|
50
|
+
- Always provides the URI scheme in lowercase characters.
|
|
51
|
+
- Always provides the host, if any, in lowercase characters.
|
|
52
|
+
- Only performs percent-encoding where it is essential.
|
|
53
|
+
- Always uses uppercase A-through-F characters when percent-encoding.
|
|
54
|
+
- Prevents dot-segments appearing in non-relative URI paths.
|
|
55
|
+
- For schemes that define a default authority, uses an empty authority if the
|
|
41
56
|
default is desired.
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
57
|
+
- For schemes that define an empty path to be equivalent to a path of "/",
|
|
58
|
+
uses "/".
|
|
59
|
+
- For schemes that define a port, uses an empty port if the default is desired
|
|
60
|
+
- Ensures all portions of the URI are utf-8 encoded NFC from Unicode strings
|
|
46
61
|
|
|
47
|
-
Inspired by Sam Ruby's [urlnorm.py](
|
|
62
|
+
Inspired by Sam Ruby's [urlnorm.py](http://intertwingly.net/blog/2004/08/04/Urlnorm)
|
|
48
63
|
|
|
49
64
|
## Features
|
|
50
65
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
66
|
+
- **IDN Support**: Full internationalized domain name handling
|
|
67
|
+
- **Configurable Defaults**:
|
|
68
|
+
- Customizable default scheme (https by default)
|
|
69
|
+
- Configurable default domain for absolute paths
|
|
70
|
+
- **Query Parameter Control**:
|
|
71
|
+
- Parameter filtering with allowlists
|
|
72
|
+
- Support for domain-specific parameter rules
|
|
73
|
+
- **Versatile URL Handling**:
|
|
74
|
+
- Empty string URLs
|
|
75
|
+
- Double slash URLs (//domain.tld)
|
|
76
|
+
- Shebang (#!) URLs
|
|
77
|
+
- **Developer Friendly**:
|
|
78
|
+
- Cross-version Python compatibility (3.8+)
|
|
79
|
+
- 100% test coverage
|
|
80
|
+
- Modern type hints and string handling
|
|
62
81
|
|
|
63
82
|
## Installation
|
|
64
83
|
|
|
@@ -68,6 +87,8 @@ pip install url-normalize
|
|
|
68
87
|
|
|
69
88
|
## Usage
|
|
70
89
|
|
|
90
|
+
### Python API
|
|
91
|
+
|
|
71
92
|
```python
|
|
72
93
|
from url_normalize import url_normalize
|
|
73
94
|
|
|
@@ -108,7 +129,7 @@ print(url_normalize("/images/logo.png", default_scheme="http", default_domain="e
|
|
|
108
129
|
# Output: http://example.com/images/logo.png
|
|
109
130
|
```
|
|
110
131
|
|
|
111
|
-
### Command-line
|
|
132
|
+
### Command-line Usage
|
|
112
133
|
|
|
113
134
|
You can also use `url-normalize` from the command line:
|
|
114
135
|
|
|
@@ -145,6 +166,10 @@ $ uvx url-normalize www.foo.com:80/foo
|
|
|
145
166
|
|
|
146
167
|
For a complete history of changes, see [CHANGELOG.md](CHANGELOG.md).
|
|
147
168
|
|
|
169
|
+
## Contributing
|
|
170
|
+
|
|
171
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
172
|
+
|
|
148
173
|
## License
|
|
149
174
|
|
|
150
175
|
MIT License
|
|
@@ -30,6 +30,7 @@ url_normalize/normalize_userinfo.py
|
|
|
30
30
|
url_normalize/param_allowlist.py
|
|
31
31
|
url_normalize/provide_url_domain.py
|
|
32
32
|
url_normalize/provide_url_scheme.py
|
|
33
|
+
url_normalize/py.typed
|
|
33
34
|
url_normalize/tools.py
|
|
34
35
|
url_normalize/url_normalize.py
|
|
35
36
|
url_normalize.egg-info/PKG-INFO
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
"""Deconstruct url tests."""
|
|
2
|
-
|
|
3
|
-
from __future__ import annotations
|
|
4
|
-
|
|
5
|
-
from typing import Final
|
|
6
|
-
|
|
7
|
-
from url_normalize.tools import URL, deconstruct_url
|
|
8
|
-
|
|
9
|
-
EXPECTED_DATA: Final[dict[str, URL]] = {
|
|
10
|
-
"http://site.com": URL(
|
|
11
|
-
fragment="",
|
|
12
|
-
host="site.com",
|
|
13
|
-
path="",
|
|
14
|
-
port="",
|
|
15
|
-
query="",
|
|
16
|
-
scheme="http",
|
|
17
|
-
userinfo="",
|
|
18
|
-
),
|
|
19
|
-
"http://user@www.example.com:8080/path/index.html?param=val#fragment": URL(
|
|
20
|
-
fragment="fragment",
|
|
21
|
-
host="www.example.com",
|
|
22
|
-
path="/path/index.html",
|
|
23
|
-
port="8080",
|
|
24
|
-
query="param=val",
|
|
25
|
-
scheme="http",
|
|
26
|
-
userinfo="user@",
|
|
27
|
-
),
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
def test_deconstruct_url_result_is_expected() -> None:
|
|
32
|
-
"""Assert we got expected results from the deconstruct_url function."""
|
|
33
|
-
for url, expected in EXPECTED_DATA.items():
|
|
34
|
-
result = deconstruct_url(url)
|
|
35
|
-
assert result == expected, url
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
"""Tests for normalize_fragment function."""
|
|
2
|
-
|
|
3
|
-
from url_normalize.url_normalize import normalize_fragment
|
|
4
|
-
|
|
5
|
-
EXPECTED_DATA = {
|
|
6
|
-
"": "",
|
|
7
|
-
"fragment": "fragment",
|
|
8
|
-
"пример": "%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80",
|
|
9
|
-
"!fragment": "%21fragment",
|
|
10
|
-
"~fragment": "~fragment",
|
|
11
|
-
# Issue #36: Equal sign should not be encoded
|
|
12
|
-
"gid=1234": "gid=1234",
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
def test_normalize_fragment_result_is_expected():
|
|
17
|
-
"""Assert we got expected results from the normalize_fragment function."""
|
|
18
|
-
for url, expected in EXPECTED_DATA.items():
|
|
19
|
-
result = normalize_fragment(url)
|
|
20
|
-
|
|
21
|
-
assert result == expected, url
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
"""Tests for normalize_host function."""
|
|
2
|
-
|
|
3
|
-
from url_normalize.url_normalize import normalize_host
|
|
4
|
-
|
|
5
|
-
EXPECTED_DATA = {
|
|
6
|
-
# Basic cases
|
|
7
|
-
"site.com": "site.com",
|
|
8
|
-
"SITE.COM": "site.com",
|
|
9
|
-
"site.com.": "site.com",
|
|
10
|
-
# Cyrillic domains
|
|
11
|
-
"пример.испытание": "xn--e1afmkfd.xn--80akhbyknj4f",
|
|
12
|
-
# Mixed case with Cyrillic
|
|
13
|
-
"ExAmPle.РФ": "example.xn--p1ai",
|
|
14
|
-
# IDNA2008 with UTS46
|
|
15
|
-
"faß.de": "fass.de", # Normalize using transitional rules
|
|
16
|
-
# Edge cases
|
|
17
|
-
"ドメイン.テスト": "xn--eckwd4c7c.xn--zckzah", # Japanese
|
|
18
|
-
"domain.café": "domain.xn--caf-dma", # Latin with diacritic
|
|
19
|
-
# Normalization tests
|
|
20
|
-
"über.example": "xn--ber-goa.example", # IDNA 2008 for umlaut
|
|
21
|
-
"example。com": "example.com", # Normalize full-width punctuation
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
def test_normalize_host_result_is_expected() -> None:
|
|
26
|
-
"""Assert we got expected results from the normalize_host function."""
|
|
27
|
-
for url, expected in EXPECTED_DATA.items():
|
|
28
|
-
result = normalize_host(url)
|
|
29
|
-
assert result == expected, url
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
"""Tests for normalize_path function."""
|
|
2
|
-
|
|
3
|
-
from url_normalize.url_normalize import normalize_path
|
|
4
|
-
|
|
5
|
-
EXPECTED_DATA = {
|
|
6
|
-
"..": "/",
|
|
7
|
-
"": "/",
|
|
8
|
-
"/../foo": "/foo",
|
|
9
|
-
"/..foo": "/..foo",
|
|
10
|
-
"/./../foo": "/foo",
|
|
11
|
-
"/./foo": "/foo",
|
|
12
|
-
"/./foo/.": "/foo/",
|
|
13
|
-
"/.foo": "/.foo",
|
|
14
|
-
"/": "/",
|
|
15
|
-
"/foo..": "/foo..",
|
|
16
|
-
"/foo.": "/foo.",
|
|
17
|
-
"/FOO": "/FOO",
|
|
18
|
-
"/foo/../bar": "/bar",
|
|
19
|
-
"/foo/./bar": "/foo/bar",
|
|
20
|
-
"/foo//": "/foo/",
|
|
21
|
-
"/foo///bar//": "/foo/bar/",
|
|
22
|
-
"/foo/bar/..": "/foo/",
|
|
23
|
-
"/foo/bar/../..": "/",
|
|
24
|
-
"/foo/bar/../../../../baz": "/baz",
|
|
25
|
-
"/foo/bar/../../../baz": "/baz",
|
|
26
|
-
"/foo/bar/../../": "/",
|
|
27
|
-
"/foo/bar/../../baz": "/baz",
|
|
28
|
-
"/foo/bar/../": "/foo/",
|
|
29
|
-
"/foo/bar/../baz": "/foo/baz",
|
|
30
|
-
"/foo/bar/.": "/foo/bar/",
|
|
31
|
-
"/foo/bar/./": "/foo/bar/",
|
|
32
|
-
# Issue #25: we should preserve ? in the path
|
|
33
|
-
"/More+Tea+Vicar%3F/discussion": "/More+Tea+Vicar%3F/discussion",
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
def test_normalize_path_result_is_expected():
|
|
38
|
-
"""Assert we got expected results from the normalize_path function."""
|
|
39
|
-
for url, expected in EXPECTED_DATA.items():
|
|
40
|
-
result = normalize_path(url, "http")
|
|
41
|
-
|
|
42
|
-
assert result == expected, url
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
"""Tests for normalize_port function."""
|
|
2
|
-
|
|
3
|
-
from url_normalize.url_normalize import normalize_port
|
|
4
|
-
|
|
5
|
-
EXPECTED_DATA = {"8080": "8080", "": "", "80": "", "string": "string"}
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
def test_normalize_port_result_is_expected():
|
|
9
|
-
"""Assert we got expected results from the normalize_port function."""
|
|
10
|
-
for url, expected in EXPECTED_DATA.items():
|
|
11
|
-
result = normalize_port(url, "http")
|
|
12
|
-
|
|
13
|
-
assert result == expected, url
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
"""Tests for normalize_scheme function."""
|
|
2
|
-
|
|
3
|
-
from url_normalize.url_normalize import normalize_scheme
|
|
4
|
-
|
|
5
|
-
EXPECTED_DATA = {"http": "http", "HTTP": "http"}
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
def test_normalize_scheme_result_is_expected():
|
|
9
|
-
"""Assert we got expected results from the normalize_scheme function."""
|
|
10
|
-
for url, expected in EXPECTED_DATA.items():
|
|
11
|
-
result = normalize_scheme(url)
|
|
12
|
-
|
|
13
|
-
assert result == expected, url
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
"""Tests for normalize_userinfo function."""
|
|
2
|
-
|
|
3
|
-
from url_normalize.url_normalize import normalize_userinfo
|
|
4
|
-
|
|
5
|
-
EXPECTED_DATA = {
|
|
6
|
-
":@": "",
|
|
7
|
-
"": "",
|
|
8
|
-
"@": "",
|
|
9
|
-
"user:password@": "user:password@",
|
|
10
|
-
"user@": "user@",
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
def test_normalize_userinfo_result_is_expected():
|
|
15
|
-
"""Assert we got expected results from the normalize_userinfo function."""
|
|
16
|
-
for url, expected in EXPECTED_DATA.items():
|
|
17
|
-
result = normalize_userinfo(url)
|
|
18
|
-
|
|
19
|
-
assert result == expected, url
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
"""Tests for provide_url_scheme function."""
|
|
2
|
-
|
|
3
|
-
from url_normalize.url_normalize import provide_url_scheme
|
|
4
|
-
|
|
5
|
-
EXPECTED_DATA = {
|
|
6
|
-
"": "",
|
|
7
|
-
"-": "-",
|
|
8
|
-
"/file/path": "/file/path",
|
|
9
|
-
"//site/path": "https://site/path",
|
|
10
|
-
"ftp://site/": "ftp://site/",
|
|
11
|
-
"site/page": "https://site/page",
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
def test_provide_url_scheme_result_is_expected():
|
|
16
|
-
"""Assert we got expected results from the provide_url_scheme function."""
|
|
17
|
-
for url, expected in EXPECTED_DATA.items():
|
|
18
|
-
result = provide_url_scheme(url)
|
|
19
|
-
|
|
20
|
-
assert result == expected, url
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
def test_provide_url_scheme_accept_default_scheme_param():
|
|
24
|
-
"""Assert we could provide default_scheme param other than https."""
|
|
25
|
-
url = "//site/path"
|
|
26
|
-
expected = "http://site/path"
|
|
27
|
-
|
|
28
|
-
actual = provide_url_scheme(url, default_scheme="http")
|
|
29
|
-
|
|
30
|
-
assert actual == expected
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
"""Reconstruct url tests."""
|
|
2
|
-
|
|
3
|
-
from __future__ import annotations
|
|
4
|
-
|
|
5
|
-
from typing import Final
|
|
6
|
-
|
|
7
|
-
from url_normalize.tools import URL, reconstruct_url
|
|
8
|
-
|
|
9
|
-
EXPECTED_DATA: Final[tuple[tuple[URL, str], ...]] = (
|
|
10
|
-
(
|
|
11
|
-
URL(
|
|
12
|
-
fragment="",
|
|
13
|
-
host="site.com",
|
|
14
|
-
path="",
|
|
15
|
-
port="",
|
|
16
|
-
query="",
|
|
17
|
-
scheme="http",
|
|
18
|
-
userinfo="",
|
|
19
|
-
),
|
|
20
|
-
"http://site.com",
|
|
21
|
-
),
|
|
22
|
-
(
|
|
23
|
-
URL(
|
|
24
|
-
fragment="fragment",
|
|
25
|
-
host="www.example.com",
|
|
26
|
-
path="/path/index.html",
|
|
27
|
-
port="8080",
|
|
28
|
-
query="param=val",
|
|
29
|
-
scheme="http",
|
|
30
|
-
userinfo="user@",
|
|
31
|
-
),
|
|
32
|
-
"http://user@www.example.com:8080/path/index.html?param=val#fragment",
|
|
33
|
-
),
|
|
34
|
-
)
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
def test_deconstruct_url_result_is_expected() -> None:
|
|
38
|
-
"""Assert we got expected results from the deconstruct_url function."""
|
|
39
|
-
for url, expected in EXPECTED_DATA:
|
|
40
|
-
result = reconstruct_url(url)
|
|
41
|
-
assert result == expected, url
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|