Kaydet (Commit) b582ecc5 authored tarafından Nick Coghlan's avatar Nick Coghlan

Issue 14814: Explain how to get more error detail in the ipaddress tutorial, and…

Issue 14814: Explain how to get more error detail in the ipaddress tutorial, and tweak the display for octet errors in IPv4 (noticed the formatting problem when adding to the docs)
üst 01ac8b6a
......@@ -277,23 +277,49 @@ an integer or string that the other module will accept::
3221225985
Exceptions raised by :mod:`ipaddress`
=====================================
Getting more detail when instance creation fails
================================================
When creating address/network/interface objects using the version-agnostic
factory functions, any errors will be reported as :exc:`ValueError`.
factory functions, any errors will be reported as :exc:`ValueError` with
a generic error message that simply says the passed in value was not
recognised as an object of that type. The lack of a specific error is
because it's necessary to know whether the value is *supposed* to be IPv4
or IPv6 in order to provide more detail on why it has been rejected.
To support use cases where it is useful to have access to this additional
detail, the individual class constructors actually raise the
:exc:`ValueError` subclasses :exc:`ipaddress.AddressValueError` and
:exc:`ipaddress.NetmaskValueError` to indicate exactly which part of
the definition failed to parse correctly.
The error messages are significantly more detailed when using the
class constructors directly. For example::
>>> ipaddress.ip_address("192.168.0.256")
Traceback (most recent call last):
...
ValueError: '192.168.0.256' does not appear to be an IPv4 or IPv6 address
>>> ipaddress.IPv4Address("192.168.0.256")
Traceback (most recent call last):
...
ipaddress.AddressValueError: Octet 256 (> 255) not permitted in '192.168.0.256'
For some use cases, it desirable to know whether it is the address or the
netmask which is incorrect. To support these use cases, the class
constructors actually raise the :exc:`ValueError` subclasses
:exc:`ipaddress.AddressValueError` and :exc:`ipaddress.NetmaskValueError`
to indicate exactly which part of the definition failed to parse correctly.
>>> ipaddress.ip_network("192.168.0.1/64")
Traceback (most recent call last):
...
ValueError: '192.168.0.1/64' does not appear to be an IPv4 or IPv6 network
>>> ipaddress.IPv4Network("192.168.0.1/64")
Traceback (most recent call last):
...
ipaddress.NetmaskValueError: '64' is not a valid netmask
Both of the module specific exceptions have :exc:`ValueError` as their
However, both of the module specific exceptions have :exc:`ValueError` as their
parent class, so if you're not concerned with the particular type of error,
you can still write code like the following::
try:
ipaddress.IPv4Address(address)
network = ipaddress.IPv4Network(address)
except ValueError:
print('address/netmask is invalid:', address)
print('address/netmask is invalid for IPv4:', address)
......@@ -1048,7 +1048,7 @@ class _BaseV4:
raise ValueError("Ambiguous leading zero in %r not permitted" %
octet_str)
if octet_int > 255:
raise ValueError("Octet %d > 255 not permitted" % octet_int)
raise ValueError("Octet %d (> 255) not permitted" % octet_int)
return octet_int
def _string_from_ip_int(self, ip_int):
......@@ -1591,7 +1591,8 @@ class _BaseV6:
hextet_int = int(hextet_str, 16)
if hextet_int > 0xFFFF:
# This is unreachable due to the string length check above
raise ValueError("Part %d > 0xFFFF not permitted" % hextet_int)
msg = "Part 0x%X (> 0xFFFF) not permitted"
raise ValueError(msg % hextet_int)
return hextet_int
def _compress_hextets(self, hextets):
......
......@@ -126,8 +126,8 @@ class AddressErrors_v4(ErrorReporting):
def test_octet_limit(self):
def assertBadOctet(addr, octet):
msg = "Octet %d > 255 not permitted in %r"
with self.assertAddressError(msg, octet, addr):
msg = "Octet %d (> 255) not permitted in %r" % (octet, addr)
with self.assertAddressError(re.escape(msg)):
ipaddress.IPv4Address(addr)
assertBadOctet("12345.67899.-54321.-98765", 12345)
......@@ -310,7 +310,7 @@ class NetmaskErrorsMixin_v4:
assertBadAddress("google.com", "Expected 4 octets")
assertBadAddress("10/8", "Expected 4 octets")
assertBadAddress("::1.2.3.4", "Only decimal digits")
assertBadAddress("1.2.3.256", "256 > 255")
assertBadAddress("1.2.3.256", re.escape("256 (> 255)"))
def test_netmask_errors(self):
def assertBadNetmask(addr, netmask):
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment