GH-65056: Improve the IP address' is_global/is_private documentation (GH-113186)

* GH-65056: Improve the IP address' is_global/is_private documentation

It wasn't clear what the semantics of is_global/is_private are and, when
one gets to the bottom of it, it's not quite so simple (hence the
exceptions listed).

Co-authored-by: Petr Viktorin <encukou@gmail.com>
This commit is contained in:
Jakub Stasiak 2024-03-18 13:57:00 +01:00 committed by GitHub
parent e2fcaf19d3
commit 2a4cbf17af
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 68 additions and 17 deletions

View File

@ -178,15 +178,34 @@ write code that handles both IP versions correctly. Address objects are
.. attribute:: is_private .. attribute:: is_private
``True`` if the address is allocated for private networks. See ``True`` if the address is defined as not globally reachable by
iana-ipv4-special-registry_ (for IPv4) or iana-ipv6-special-registry_ iana-ipv4-special-registry_ (for IPv4) or iana-ipv6-special-registry_
(for IPv6). (for IPv6) with the following exceptions:
* ``is_private`` is ``False`` for the shared address space (``100.64.0.0/10``)
* For IPv4-mapped IPv6-addresses the ``is_private`` value is determined by the
semantics of the underlying IPv4 addresses and the following condition holds
(see :attr:`IPv6Address.ipv4_mapped`)::
address.is_private == address.ipv4_mapped.is_private
``is_private`` has value opposite to :attr:`is_global`, except for the shared address space
(``100.64.0.0/10`` range) where they are both ``False``.
.. attribute:: is_global .. attribute:: is_global
``True`` if the address is allocated for public networks. See ``True`` if the address is defined as globally reachable by
iana-ipv4-special-registry_ (for IPv4) or iana-ipv6-special-registry_ iana-ipv4-special-registry_ (for IPv4) or iana-ipv6-special-registry_
(for IPv6). (for IPv6) with the following exception:
For IPv4-mapped IPv6-addresses the ``is_private`` value is determined by the
semantics of the underlying IPv4 addresses and the following condition holds
(see :attr:`IPv6Address.ipv4_mapped`)::
address.is_global == address.ipv4_mapped.is_global
``is_global`` has value opposite to :attr:`is_private`, except for the shared address space
(``100.64.0.0/10`` range) where they are both ``False``.
.. versionadded:: 3.4 .. versionadded:: 3.4

View File

@ -1333,18 +1333,38 @@ def is_reserved(self):
@property @property
@functools.lru_cache() @functools.lru_cache()
def is_private(self): def is_private(self):
"""Test if this address is allocated for private networks. """``True`` if the address is defined as not globally reachable by
iana-ipv4-special-registry_ (for IPv4) or iana-ipv6-special-registry_
(for IPv6) with the following exceptions:
Returns: * ``is_private`` is ``False`` for ``100.64.0.0/10``
A boolean, True if the address is reserved per * For IPv4-mapped IPv6-addresses the ``is_private`` value is determined by the
iana-ipv4-special-registry. semantics of the underlying IPv4 addresses and the following condition holds
(see :attr:`IPv6Address.ipv4_mapped`)::
address.is_private == address.ipv4_mapped.is_private
``is_private`` has value opposite to :attr:`is_global`, except for the ``100.64.0.0/10``
IPv4 range where they are both ``False``.
""" """
return any(self in net for net in self._constants._private_networks) return any(self in net for net in self._constants._private_networks)
@property @property
@functools.lru_cache() @functools.lru_cache()
def is_global(self): def is_global(self):
"""``True`` if the address is defined as globally reachable by
iana-ipv4-special-registry_ (for IPv4) or iana-ipv6-special-registry_
(for IPv6) with the following exception:
For IPv4-mapped IPv6-addresses the ``is_private`` value is determined by the
semantics of the underlying IPv4 addresses and the following condition holds
(see :attr:`IPv6Address.ipv4_mapped`)::
address.is_global == address.ipv4_mapped.is_global
``is_global`` has value opposite to :attr:`is_private`, except for the ``100.64.0.0/10``
IPv4 range where they are both ``False``.
"""
return self not in self._constants._public_network and not self.is_private return self not in self._constants._public_network and not self.is_private
@property @property
@ -2049,13 +2069,19 @@ def is_site_local(self):
@property @property
@functools.lru_cache() @functools.lru_cache()
def is_private(self): def is_private(self):
"""Test if this address is allocated for private networks. """``True`` if the address is defined as not globally reachable by
iana-ipv4-special-registry_ (for IPv4) or iana-ipv6-special-registry_
(for IPv6) with the following exceptions:
Returns: * ``is_private`` is ``False`` for ``100.64.0.0/10``
A boolean, True if the address is reserved per * For IPv4-mapped IPv6-addresses the ``is_private`` value is determined by the
iana-ipv6-special-registry, or is ipv4_mapped and is semantics of the underlying IPv4 addresses and the following condition holds
reserved in the iana-ipv4-special-registry. (see :attr:`IPv6Address.ipv4_mapped`)::
address.is_private == address.ipv4_mapped.is_private
``is_private`` has value opposite to :attr:`is_global`, except for the ``100.64.0.0/10``
IPv4 range where they are both ``False``.
""" """
ipv4_mapped = self.ipv4_mapped ipv4_mapped = self.ipv4_mapped
if ipv4_mapped is not None: if ipv4_mapped is not None:
@ -2064,12 +2090,18 @@ def is_private(self):
@property @property
def is_global(self): def is_global(self):
"""Test if this address is allocated for public networks. """``True`` if the address is defined as globally reachable by
iana-ipv4-special-registry_ (for IPv4) or iana-ipv6-special-registry_
(for IPv6) with the following exception:
Returns: For IPv4-mapped IPv6-addresses the ``is_private`` value is determined by the
A boolean, true if the address is not reserved per semantics of the underlying IPv4 addresses and the following condition holds
iana-ipv6-special-registry. (see :attr:`IPv6Address.ipv4_mapped`)::
address.is_global == address.ipv4_mapped.is_global
``is_global`` has value opposite to :attr:`is_private`, except for the ``100.64.0.0/10``
IPv4 range where they are both ``False``.
""" """
return not self.is_private return not self.is_private