This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: Add bitwise operations and other missing comparison methods to Python's IP address module
Type: enhancement Stage:
Components: Library (Lib) Versions: Python 3.8
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: Kyle Agronick, bbayles, pmoody
Priority: normal Keywords:

Created on 2018-03-01 01:13 by Kyle Agronick, last changed 2022-04-11 14:58 by admin.

Messages (1)
msg313077 - (view) Author: Kyle Agronick (Kyle Agronick) Date: 2018-03-01 01:13
I've recently had the experience of implementing a system for managing DNS records at a Fortune 10 company with ~10,000 stores. There were a number of things that I felt were missing from the IP address module and could be added without introducing any breaking changes.

The easiest changes I saw would be to implement bitwise operations without casting all the addresses to ints and then back to IP addresses.

Lets say you wanted to take the last octet from one address and put it on another:

Right now you need to do:
IPv6Address(int(v6('2001:db8:85a3:0:0:8a2e:370:7334')) & int(IPv6Address('0:0:0:0:0:0:0:ffff')) | int(IPv6Address('1323:cf3:23df:0:0:32:44:0')))
# returns IPv6Address('1323:cf3:23df::32:44:7334')

You should be able to do:
(IPv6Address('2001:db8:85a3:0:0:8a2e:370:7334') & IPv6Address('0:0:0:0:0:0:0:ffff')) | IPv6Address('1323:cf3:23df:0:0:32:44:0')
# returns TypeError: unsupported operand type(s) for &: 'IPv6Address' and 'IPv6Address'

All that would be required is to do the casting to int automatically.

The other thing I saw that I would like would be to override the methods that return generators with iterables that provide more comparison operations.

Right now you can check if an IP is in a network with:
IPv4Address('192.168.1.12') in IPv4Network('192.168.1.0/24') 
# returns True

You should be able to do this with methods that return multiple networks.
ipaddress.summarize_address_range() is a method that returns a generator of IPv(4|6)Networks.

To see if an IP address is in one of multiple networks you need to do:
any(map(lambda i: IPv4Address('192.168.1.12') in i, ipaddress.summarize_address_range(IPv4Address('192.168.1.0'), IPv4Address('192.168.2.255'))))
# returns True

You should be able to do:
IPv4Address('192.168.1.12') in ipaddress.summarize_address_range(IPv4Address('192.168.1.0'), IPv4Address('192.168.2.255'))
# returns False

This should be the default for IPv(4|6)Addresses. IPv(4|6)Networks should check membership like they currently do.

You should be able to subtract ranges to make ranges that include some IPs but not others:
ipaddress.summarize_address_range(IPv4Address('192.168.1.0'), IPv4Address('192.168.2.255')) - ipaddress.summarize_address_range(IPv4Address('192.168.1.20'), IPv4Address('192.168.1.50'))
# returns TypeError: unsupported operand type(s) for -: 'generator' and 'generator'

This should return a iterable that has networks that include 192.168.1.0 to 192.168.1.20 and 192.168.1.50 to 192.168.2.255.

You should be able to do addition as well without casting to a list.

Methods like .hosts() should be able to be performed on the iterator instead of doing:
sum([list(i.hosts()) for i in ipaddress.summarize_address_range(IPv4Address('192.168.1.0'), IPv4Address('192.168.2.255'))], [])

do:
ipaddress.summarize_address_range(IPv4Address('192.168.1.0'), IPv4Address('192.168.2.255')).hosts()

Another great feature would be to allow division on networks and network generators giving you every xth host:
(i for i in IPv4Network('192.168.1.0/24').hosts() if int(i) % x == 0)

When x is 32 you get:
IPv4Address('192.168.1.32'), 
IPv4Address('192.168.1.64'), 
IPv4Address('192.168.1.96'), 
IPv4Address('192.168.1.128'), 
IPv4Address('192.168.1.160'), 
IPv4Address('192.168.1.192'), 
IPv4Address('192.168.1.224')

I would be happy to code this if the consensus was that this would be included.
History
Date User Action Args
2022-04-11 14:58:58adminsetgithub: 77155
2018-03-01 02:56:35ned.deilysetnosy: + pmoody
2018-03-01 02:20:11bbaylessetnosy: + bbayles
2018-03-01 01:13:29Kyle Agronickcreate