From 533b97f99bfa53467533af95dddbc8e6f08208e3 Mon Sep 17 00:00:00 2001 From: Jakub Stasiak Date: Fri, 15 Dec 2023 18:32:46 +0100 Subject: [PATCH 1/6] 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). I opted to fully replace the docstrings with the content from the documentation to save myself some work. --- Doc/library/ipaddress.rst | 27 +++++++++++++++--- Lib/ipaddress.py | 58 ++++++++++++++++++++++++++++++--------- 2 files changed, 68 insertions(+), 17 deletions(-) diff --git a/Doc/library/ipaddress.rst b/Doc/library/ipaddress.rst index 1de36b643c4dca..ce50df5f3d0747 100644 --- a/Doc/library/ipaddress.rst +++ b/Doc/library/ipaddress.rst @@ -188,15 +188,34 @@ write code that handles both IP versions correctly. Address objects are .. 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_ - (for IPv6). + (for IPv6) with the following exceptions: + + * ``is_private`` is ``False`` for the ``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 ``100.64.0.0/10`` + IPv4 range where they are both ``False``. .. 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_ - (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 ``100.64.0.0/10`` + IPv4 range where they are both ``False``. .. versionadded:: 3.4 diff --git a/Lib/ipaddress.py b/Lib/ipaddress.py index e398cc138308d9..06d6d722f3ad02 100644 --- a/Lib/ipaddress.py +++ b/Lib/ipaddress.py @@ -1333,18 +1333,38 @@ def is_reserved(self): @property @functools.lru_cache() 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: - A boolean, True if the address is reserved per - iana-ipv4-special-registry. + * ``is_private`` is ``False`` for the ``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 ``100.64.0.0/10`` + IPv4 range where they are both ``False``. """ return any(self in net for net in self._constants._private_networks) @property @functools.lru_cache() 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 @property @@ -2049,13 +2069,19 @@ def is_site_local(self): @property @functools.lru_cache() 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: - A boolean, True if the address is reserved per - iana-ipv6-special-registry, or is ipv4_mapped and is - reserved in the iana-ipv4-special-registry. + * ``is_private`` is ``False`` for the ``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 ``100.64.0.0/10`` + IPv4 range where they are both ``False``. """ ipv4_mapped = self.ipv4_mapped if ipv4_mapped is not None: @@ -2064,12 +2090,18 @@ def is_private(self): @property 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: - A boolean, true if the address is not reserved per - iana-ipv6-special-registry. + 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 not self.is_private From 497eaf9ac5939184dc3e19c85b731e77924da07e Mon Sep 17 00:00:00 2001 From: Jakub Stasiak Date: Thu, 14 Mar 2024 00:00:52 +0100 Subject: [PATCH 2/6] Update Doc/library/ipaddress.rst Co-authored-by: Petr Viktorin --- Doc/library/ipaddress.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/library/ipaddress.rst b/Doc/library/ipaddress.rst index ce50df5f3d0747..ec7b010a704ce1 100644 --- a/Doc/library/ipaddress.rst +++ b/Doc/library/ipaddress.rst @@ -192,7 +192,7 @@ write code that handles both IP versions correctly. Address objects are iana-ipv4-special-registry_ (for IPv4) or iana-ipv6-special-registry_ (for IPv6) with the following exceptions: - * ``is_private`` is ``False`` for the ``100.64.0.0/10`` + * ``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`):: From deb8b19425dfdcab3a485e6b2a28bd76076c461e Mon Sep 17 00:00:00 2001 From: Jakub Stasiak Date: Thu, 14 Mar 2024 00:01:03 +0100 Subject: [PATCH 3/6] Update Doc/library/ipaddress.rst Co-authored-by: Petr Viktorin --- Doc/library/ipaddress.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/library/ipaddress.rst b/Doc/library/ipaddress.rst index ec7b010a704ce1..cbff63b840e073 100644 --- a/Doc/library/ipaddress.rst +++ b/Doc/library/ipaddress.rst @@ -199,8 +199,8 @@ write code that handles both IP versions correctly. Address objects are 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``. + ``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 From d115f17963f0cea3c05d9cc5d4562bc220372be9 Mon Sep 17 00:00:00 2001 From: Jakub Stasiak Date: Thu, 14 Mar 2024 00:01:09 +0100 Subject: [PATCH 4/6] Update Doc/library/ipaddress.rst Co-authored-by: Petr Viktorin --- Doc/library/ipaddress.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/library/ipaddress.rst b/Doc/library/ipaddress.rst index cbff63b840e073..7159f23e8d7dee 100644 --- a/Doc/library/ipaddress.rst +++ b/Doc/library/ipaddress.rst @@ -214,8 +214,8 @@ write code that handles both IP versions correctly. Address objects are 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``. + ``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 From 3c6775fee6d5ce40a939bdc13faddb25a467dfa5 Mon Sep 17 00:00:00 2001 From: Jakub Stasiak Date: Thu, 14 Mar 2024 00:01:55 +0100 Subject: [PATCH 5/6] Update Lib/ipaddress.py Co-authored-by: Petr Viktorin --- Lib/ipaddress.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/ipaddress.py b/Lib/ipaddress.py index 06d6d722f3ad02..12ff3dead1f69f 100644 --- a/Lib/ipaddress.py +++ b/Lib/ipaddress.py @@ -2073,7 +2073,7 @@ def is_private(self): iana-ipv4-special-registry_ (for IPv4) or iana-ipv6-special-registry_ (for IPv6) with the following exceptions: - * ``is_private`` is ``False`` for the ``100.64.0.0/10`` + * ``is_private`` is ``False`` for ``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`):: From c43f0dab75a74024f2b3dfe9e253f2f0b93c5d8b Mon Sep 17 00:00:00 2001 From: Jakub Stasiak Date: Thu, 14 Mar 2024 00:02:04 +0100 Subject: [PATCH 6/6] Update Lib/ipaddress.py Co-authored-by: Petr Viktorin --- Lib/ipaddress.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/ipaddress.py b/Lib/ipaddress.py index 12ff3dead1f69f..7d6edcf2478a82 100644 --- a/Lib/ipaddress.py +++ b/Lib/ipaddress.py @@ -1337,7 +1337,7 @@ def is_private(self): iana-ipv4-special-registry_ (for IPv4) or iana-ipv6-special-registry_ (for IPv6) with the following exceptions: - * ``is_private`` is ``False`` for the ``100.64.0.0/10`` + * ``is_private`` is ``False`` for ``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`)::