Skip to content

Commit 9629277

Browse files
committed
add missing IPv[46]Addwork doc
1 parent 676864b commit 9629277

1 file changed

Lines changed: 86 additions & 1 deletion

File tree

README.md

Lines changed: 86 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ import pydantic
2525
class Model(pydantic.BaseModel):
2626
address: pydantic.IPvAnyAddress
2727

28-
2928
m = Model(address="1.2.3.4")
3029
print(type(m.address))
3130
print(m.model_dump_json())
@@ -131,10 +130,96 @@ The validation relies mostly on `netaddr` objects constructors. There's currentl
131130

132131
### Additionnal features
133132

133+
## IPAny
134+
134135
That may not be much, but an `IPAny` type is available. `pydantic` should produce the most acccurate object depending of the source object. An `IPAny` field will produce
135136

136137
* an `IPSet` if provided type is `list`, `tuple` or `set`
137138
* an `IPNetwork` if value is a CIDR `str`
138139
* an `IPRange` if value is an `str` containing a `-` character
139140
* an `IPGlob` if value is an `str` containing a `*` char.
140141
* an `IPAddress` in other cases.
142+
143+
## `IPv4Address` / `IPv6Address`
144+
145+
In case you want to match only IPv4 or IPv6 addresses (although, for portability, I suggest you don't), you can use these Internet Protocol version specific types annotations.
146+
147+
For instance, the following code:
148+
149+
```python
150+
import pydantic
151+
import netaddr_pydantic
152+
153+
class Model(pydantic.BaseModel):
154+
address: netaddr_pydantic.IPv4Address
155+
156+
m4 = Model(address="1.2.3.4")
157+
print(f"IPv4 has been validated: {m4.address}")
158+
159+
try:
160+
m6 = Model(address="dead:b00b:cafe::1")
161+
except pydantic.ValidationError:
162+
print("IPv6 address did not pass:")
163+
raise
164+
```
165+
166+
Produces the following:
167+
168+
```
169+
IPv4 has been validated: 1.2.3.4
170+
IPv6 address did not pass:
171+
Traceback (most recent call last):
172+
File "t.py", line 11, in <module>
173+
m6 = Model(address="dead:b00b:cafe::1")
174+
File "/env/lib/python3.13/site-packages/pydantic/main.py", line 253, in __init__
175+
validated_self = self.__pydantic_validator__.validate_python(data, self_instance=self)
176+
pydantic_core._pydantic_core.ValidationError: 1 validation error for Model
177+
address
178+
Value error, base address 'dead:b00b:cafe::1' is not IPv4 [type=value_error, input_value='dead:b00b:cafe::1', input_type=str]
179+
For further information visit https://errors.pydantic.dev/2.11/v/value_error
180+
```
181+
182+
## `IPv4Network` / `IPv6Network`
183+
184+
Well, duh. :unamused:
185+
186+
```python
187+
import pydantic
188+
import netaddr_pydantic
189+
190+
class Model(pydantic.BaseModel):
191+
network: netaddr_pydantic.IPv6Network
192+
193+
m6 = Model(network="dead:b00b:cafe::/64")
194+
print(f"IPv6 CIDR has been validated: {m6.network}")
195+
196+
try:
197+
m4 = Model(network="1.2.3.0/24")
198+
except pydantic.ValidationError:
199+
print("IPv4 CIDR did not pass:")
200+
raise
201+
```
202+
203+
:interrobang:
204+
205+
:expressionless:
206+
207+
```
208+
IPv6 CIDR has been validated: dead:b00b:cafe::/64
209+
IPv4 CIDR did not pass:
210+
Traceback (most recent call last):
211+
File "t.py", line 11, in <module>
212+
m4 = Model(network="1.2.3.0/24")
213+
File "/env/lib/python3.13/site-packages/pydantic/main.py", line 253, in __init__
214+
validated_self = self.__pydantic_validator__.validate_python(data, self_instance=self)
215+
pydantic_core._pydantic_core.ValidationError: 1 validation error for Model
216+
network
217+
Value error, base address '1.2.3.0' is not IPv6 [type=value_error, input_value='1.2.3.0/24', input_type=str]
218+
For further information visit https://errors.pydantic.dev/2.11/v/value_error
219+
```
220+
221+
:boom: :bangbang:
222+
223+
:tada:
224+
225+
:smirk:

0 commit comments

Comments
 (0)