8000 Fix host required enforcement for urls to be compatible with v2.9 beh… · pydantic/pydantic@435a703 · GitHub
[go: up one dir, main page]

Skip to content

Commit 435a703

Browse files
committed
Fix host required enforcement for urls to be compatible with v2.9 behavior (#11027)
1 parent b2c4548 commit 435a703

File tree

2 files changed

+38
-48
lines changed

2 files changed

+38
-48
lines changed

pydantic/networks.py

Lines changed: 32 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -456,13 +456,13 @@ class AnyUrl(_BaseUrl):
456456
457457
* Any scheme allowed
458458
* Top-level domain (TLD) not required
459-
* Host required
459+
* Host not required
460460
461461
Assuming an input URL of `http://samuel:pass@example.com:8000/the/path/?query=here#fragment=is;this=bit`,
462462
the types export the following properties:
463463
464464
- `scheme`: the URL scheme (`http`), always set.
465-
- `host`: the URL host (`example.com`), always set.
465+
- `host`: the URL host (`example.com`).
466466
- `username`: optional username if included (`samuel`).
467467
- `password`: optional password if included (`pass`).
468468
- `port`: optional port (`8000`).
@@ -471,13 +471,6 @@ class AnyUrl(_BaseUrl):
471471
- `fragment`: optional fragment (`fragment=is;this=bit`).
472472
"""
473473

474-
_constraints = UrlConstraints(host_required=True)
475-
476-
@property
477-
def host(self) -> str:
478-
"""The required URL host."""
479-
return self._url.host # pyright: ignore[reportReturnType]
480-
481474

482475
# Note: all single host urls inherit from `AnyUrl` to preserve compatibility with pre-v2.10 code
483476
# Where urls were annotated variants of `AnyUrl`, which was an alias to `pydantic_core.Url`
@@ -487,17 +480,17 @@ class AnyHttpUrl(AnyUrl):
487480
"""A type that will accept any http or https URL.
488481
489482
* TLD not required
490-
* Host required
483+
* Host not required
491484
"""
492485

493-
_constraints = UrlConstraints(host_required=True, allowed_schemes=['http', 'https'])
486+
_constraints = UrlConstraints(allowed_schemes=['http', 'https'])
494487

495488

496489
class HttpUrl(AnyUrl):
497490
"""A type that will accept any http or https URL.
498491
499492
* TLD not required
500-
* Host required
493+
* Host not required
501494
* Max length 2083
502495
503496
```python
@@ -571,33 +564,28 @@ class MyModel(BaseModel):
571564
(or at least big) company.
572565
"""
573566

574-
_constraints = UrlConstraints(max_length=2083, allowed_schemes=['http', 'https'], host_required=True)
567+
_constraints = UrlConstraints(max_length=2083, allowed_schemes=['http', 'https'])
575568

576569

577570
class AnyWebsocketUrl(AnyUrl):
578571
"""A type that will accept any ws or wss URL.
579572
580573
* TLD not required
581-
* Host required
574+
* Host not required
582575
"""
583576

584-
_constraints = UrlConstraints(allowed_schemes=['ws', 'wss'], host_required=True)
577+
_constraints = UrlConstraints(allowed_schemes=['ws', 'wss'])
585578

586579

587580
class WebsocketUrl(AnyUrl):
588581
"""A type that will accept any ws or wss URL.
589582
590583
* TLD not required
591-
* Host required
584+
* Host not required
592585
* Max length 2083
593586
"""
594587

595-
_constraints = UrlConstraints(max_length=2083, allowed_schemes=['ws', 'wss'], host_required=True)
596-
597-
@property
598-
def host(self) -> str:
599-
"""The required URL host."""
600-
return self._url.host # type: ignore
588+
_constraints = UrlConstraints(max_length=2083, allowed_schemes=['ws', 'wss'])
601589

602590

603591
class FileUrl(AnyUrl):
@@ -608,25 +596,15 @@ class FileUrl(AnyUrl):
608596

609597
_constraints = UrlConstraints(allowed_schemes=['file'])
610598

611-
@property
612-
def host(self) -> str | None: # pyright: ignore[reportIncompatibleMethodOverride]
613-
"""The host part of the URL, or `None`."""
614-
return self._url.host
615-
616599

617600
class FtpUrl(AnyUrl):
618601
"""A type that will accept ftp URL.
619602
620603
* TLD not required
621-
* Host required
604+
* Host not required
622605
"""
623606

624-
_constraints = UrlConstraints(allowed_schemes=['ftp'], host_required=True)
625-
626-
@property
627-
def host(self) -> str | None: # pyright: ignore[reportIncompatibleMethodOverride]
628-
"""The host part of the URL, or `None`."""
629-
return self._url.host
607+
_constraints = UrlConstraints(allowed_schemes=['ftp'])
630608

631609

632610
class PostgresDsn(_BaseMultiHostUrl):
@@ -727,6 +705,11 @@ class CockroachDsn(AnyUrl):
727705
],
728706
)
729707

708+
@property
709+
def host(self) -> str:
710+
"""The required URL host."""
711+
return self._url.host # pyright: ignore[reportReturnType]
712+
730713

731714
class AmqpDsn(AnyUrl):
732715
"""A type that will accept any AMQP DSN.
@@ -738,11 +721,6 @@ class AmqpDsn(AnyUrl):
738721

739722
_constraints = UrlConstraints(allowed_schemes=['amqp', 'amqps'])
740723

741-
@property
742-
def host(self) -> str | None: # pyright: ignore[reportIncompatibleMethodOverride]
743-
"""The host part of the URL, or `None`."""
744-
return self._url.host
745-
746724

747725
class RedisDsn(AnyUrl):
748726
"""A type that will accept any Redis DSN.
@@ -760,6 +738,11 @@ class RedisDsn(AnyUrl):
760738
host_required=True,
761739
)
762740

741+
@property
742+
def host(self) -> str:
743+
"""The required URL host."""
744+
return self._url.host # pyright: ignore[reportReturnType]
745+
763746

764747
class MongoDsn(_BaseMultiHostUrl):
765748
"""A type that will accept any MongoDB DSN.
@@ -778,12 +761,10 @@ class KafkaDsn(AnyUrl):
778761
779762
* User info required
780763
* TLD not required
781-
* Host required
764+
* Host not required
782765
"""
783766

784-
_constraints = UrlConstraints(
785-
allowed_schemes=['kafka'], default_host='localhost', default_port=9092, host_required=True
786-
)
767+
_constraints = UrlConstraints(allowed_schemes=['kafka'], default_host='localhost', default_port=9092)
787768

788769

789770
class NatsDsn(_BaseMultiHostUrl):
@@ -805,7 +786,7 @@ class MySQLDsn(AnyUrl):
805786
806787
* User info required
807788
* TLD not required
808-
* Host required
789+
* Host not required
809790
"""
810791

811792
_constraints = UrlConstraints(
@@ -829,13 +810,12 @@ class MariaDBDsn(AnyUrl):
829810
830811
* User info required
831812
* TLD not required
832-
* Host required
813+
* Host not required
833814
"""
834815

835816
_constraints = UrlConstraints(
836817
allowed_schemes=['mariadb', 'mariadb+mariadbconnector', 'mariadb+pymysql'],
837818
default_port=3306,
838-
host_required=True,
839819
)
840820

841821

@@ -844,14 +824,13 @@ class ClickHouseDsn(AnyUrl):
844824
845825
* User info required
846826
* TLD not required
847-
* Host required
827+
* Host not required
848828
"""
849829

850830
_constraints = UrlConstraints(
851831
allowed_schemes=['clickhouse+native', 'clickhouse+asynch'],
852832
default_host='localhost',
853833
default_port=9000,
854-
host_required=True,
855834
)
856835

857836

@@ -868,6 +847,11 @@ class SnowflakeDsn(AnyUrl):
868847
host_required=True,
869848
)
870849

850+
@property
851+
def host(self) -> str:
852+
"""The required URL host."""
853+
return self._url.host # pyright: ignore[reportReturnType]
854+
871855

872856
def import_email_validator() -> None:
873857
global email_validator

tests/test_networks.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1129,3 +1129,9 @@ def test_any_url_hashable() -> None:
11291129
assert hash(example_multi_host_url_1a) == hash(example_multi_host_url_1b)
11301130
assert hash(example_multi_host_url_1a) != hash(example_multi_host_url_2)
11311131
assert len({example_multi_host_url_1a, example_multi_host_url_1b, example_multi_host_url_2}) == 2
1132+
1133+
1134+
def test_host_not_required_for_2_9_compatibility() -> None:
1135+
data_uri = 'file:///path/to/data'
1136+
url = AnyUrl(data_uri)
1137+
assert url.host is None

0 commit comments

Comments
 (0)
0