Skip to content

Commit 5e58cb3

Browse files
committed
maint: improves domain module
- Uses type hints, improve docs - Regards [RFC 1034](https://www.rfc-editor.org/rfc/rfc1034) and [RFC 2782](https://www.rfc-editor.org/rfc/rfc2782) - Updates corresponding test functions **Related items** *Issues* - Closes #52 - Closes #74 - Closes #81 - Closes #89 - Closes #95 - Closes #120 - Closes #124 - Closes #141 - Closes #143 - Closes #199 - Closes #204 *PRs* - Closes #114 - Closes #179
1 parent 27eed7b commit 5e58cb3

File tree

2 files changed

+94
-75
lines changed

2 files changed

+94
-75
lines changed

tests/test_domain.py

Lines changed: 48 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,56 @@
1+
"""Test Domain."""
12
# -*- coding: utf-8 -*-
3+
4+
# standard
25
import pytest
36

7+
# local
48
from validators import domain, ValidationFailure
59

610

7-
@pytest.mark.parametrize('value', [
8-
'example.com',
9-
'xn----gtbspbbmkef.xn--p1ai',
10-
'underscore_subdomain.example.com',
11-
'something.versicherung',
12-
'someThing.versicherung',
13-
'11.com',
14-
'3.cn',
15-
'a.cn',
16-
'sub1.sub2.sample.co.uk',
17-
'somerandomexample.xn--fiqs8s',
18-
'kräuter.com',
19-
'über.com'
20-
])
21-
def test_returns_true_on_valid_domain(value):
22-
assert domain(value)
11+
@pytest.mark.parametrize(
12+
("value", "rfc_1034", "rfc_2782"),
13+
[
14+
("example.com", False, False),
15+
("xn----gtbspbbmkef.xn--p1ai", False, False),
16+
("underscore_subdomain.example.com", False, False),
17+
("something.versicherung", False, False),
18+
("someThing.versicherung.", True, False),
19+
("11.com", False, False),
20+
("3.cn.", True, False),
21+
("_example.com", False, True),
22+
("a.cn", False, False),
23+
("sub1.sub2.sample.co.uk", False, False),
24+
("somerandomexample.xn--fiqs8s", False, False),
25+
("kräuter.com.", True, False),
26+
("über.com", False, False),
27+
],
28+
)
29+
def test_returns_true_on_valid_domain(value: str, rfc_1034: bool, rfc_2782: bool):
30+
"""Test returns true on valid domain."""
31+
assert domain(value, rfc_1034=rfc_1034, rfc_2782=rfc_2782)
2332

2433

25-
@pytest.mark.parametrize('value', [
26-
'example.com/',
27-
'example.com:4444',
28-
'example.-com',
29-
'example.',
30-
'-example.com',
31-
'example-.com',
32-
'_example.com',
33-
'example_.com',
34-
'example',
35-
'a......b.com',
36-
'a.123',
37-
'123.123',
38-
'123.123.123',
39-
'123.123.123.123'
40-
])
41-
def test_returns_failed_validation_on_invalid_domain(value):
42-
assert isinstance(domain(value), ValidationFailure)
34+
@pytest.mark.parametrize(
35+
("value", "rfc_1034", "rfc_2782"),
36+
[
37+
("example.com/.", True, False),
38+
("example.com:4444", False, False),
39+
("example.-com", False, False),
40+
("example.", False, False),
41+
("-example.com", False, False),
42+
("example-.com.", True, False),
43+
("_example.com", False, False),
44+
("_example._com", False, False),
45+
("example_.com", False, False),
46+
("example", False, False),
47+
("a......b.com", False, False),
48+
("a.123", False, False),
49+
("123.123", False, False),
50+
("123.123.123.", True, False),
51+
("123.123.123.123", False, False),
52+
],
53+
)
54+
def test_returns_failed_validation_on_invalid_domain(value: str, rfc_1034: bool, rfc_2782: bool):
55+
"""Test returns failed validation on invalid domain."""
56+
assert isinstance(domain(value, rfc_1034=rfc_1034, rfc_2782=rfc_2782), ValidationFailure)

validators/domain.py

Lines changed: 46 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,59 @@
1+
"""Domain."""
2+
3+
# standard
14
import re
25

6+
# local
37
from .utils import validator
48

5-
pattern = re.compile(
6-
r'^(?:[a-zA-Z0-9]' # First character of the domain
7-
r'(?:[a-zA-Z0-9-_]{0,61}[A-Za-z0-9])?\.)' # Sub domain + hostname
8-
r'+[A-Za-z0-9][A-Za-z0-9-_]{0,61}' # First 61 characters of the gTLD
9-
r'[A-Za-z]$' # Last character of the gTLD
10-
)
11-
12-
13-
def to_unicode(obj, charset='utf-8', errors='strict'):
14-
if obj is None:
15-
return None
16-
if not isinstance(obj, bytes):
17-
return str(obj)
18-
return obj.decode(charset, errors)
19-
209

2110
@validator
22-
def domain(value):
23-
"""
24-
Return whether or not given value is a valid domain.
25-
26-
If the value is valid domain name this function returns ``True``, otherwise
27-
:class:`~validators.utils.ValidationFailure`.
28-
29-
Examples::
11+
def domain(value: str, /, *, rfc_1034: bool = False, rfc_2782: bool = False):
12+
"""Return whether or not given value is a valid domain.
3013
14+
Examples:
3115
>>> domain('example.com')
32-
True
33-
16+
# Output: True
3417
>>> domain('example.com/')
35-
ValidationFailure(func=domain, ...)
36-
37-
38-
Supports IDN domains as well::
39-
18+
# Output: ValidationFailure(func=domain, ...)
19+
>>> # Supports IDN domains as well::
4020
>>> domain('xn----gtbspbbmkef.xn--p1ai')
41-
True
42-
43-
.. versionadded:: 0.9
44-
45-
.. versionchanged:: 0.10
46-
47-
Added support for internationalized domain name (IDN) validation.
48-
49-
:param value: domain string to validate
21+
# Output: True
22+
23+
Args:
24+
value:
25+
Domain string to validate.
26+
rfc_1034:
27+
Allow trailing dot in domain name.
28+
Ref: [RFC 1034](https://www.rfc-editor.org/rfc/rfc1034).
29+
rfc_2782:
30+
Domain name is of type service record.
31+
Ref: [RFC 2782](https://www.rfc-editor.org/rfc/rfc2782).
32+
33+
34+
Returns:
35+
(Literal[True]):
36+
If `value` is a valid domain name.
37+
(ValidationFailure):
38+
If `value` is an invalid domain name.
39+
40+
Note:
41+
- *In version 0.10.0*:
42+
- Added support for internationalized domain name (IDN) validation.
43+
44+
> *New in version 0.9.0*.
5045
"""
5146
try:
52-
return pattern.match(to_unicode(value).encode('idna').decode('ascii'))
53-
except (UnicodeError, AttributeError):
47+
return not re.search(r"\s", value) and re.compile(
48+
# First character of the domain
49+
(r"^(?:[a-zA-Z0-9_]" if rfc_2782 else r"^(?:[a-zA-Z0-9]")
50+
# Sub domain + hostname
51+
+ r"(?:[a-zA-Z0-9-_]{0,61}[A-Za-z0-9])?\.)"
52+
# First 61 characters of the gTLD
53+
+ r"+[A-Za-z0-9][A-Za-z0-9-_]{0,61}"
54+
# Last character of the gTLD
55+
+ r"[A-Za-z]"
56+
+ (r".$" if rfc_1034 else r"$")
57+
).match(value.encode("idna").decode("ascii"))
58+
except UnicodeError:
5459
return False

0 commit comments

Comments
 (0)