Package: cidr-man
CIDR-ManBuilt due to frustrations with python's built-inipaddresslibrary's performance, code complexity, and accuracy.
CIDR-Man is an accurate high-performance IP address subnetting library.While the interface of this new library is a little different from that of the built-in library, we think you'll find it to be more "pythonic", and quite intuitive.NOTE: While writing tests for this library we discovered that a number of theis_<address type>flags from the python built-in library were returning incorrect results. CIDR-Man is accurate as per the RFCs at the time of writing, thus our responses may differ.Key performance metrics (vs Built-inipaddress)__init__:    7.822xsupernet:    2.186xsubnet_of:   8.516xsubnets:     3.966xcompressed:  1.303xCIDRs explainedCIDR (or Classless Inter-Domain Routing) is a way of representing and handling IP addresses and networks.
Introduced in 1993 to replace the previous IP address class architecture, CIDRs offer more flexibility in addressing hierarchy in network designs.
A block of IP addresses in CIDR notation would be represented as the first IP in the block followed by the number of bits in the bitmask separated by a forward slash.For example, the CIDR 192.0.2.0/24 represents an IP address block spanning 192.0.2.0 to 192.0.2.255.
Expanding this out we get the following:Network:                                192.0.2.0
Network (as binary):                    11000000000000000000001000000000
Netmask:                                255.255.255.0
Netmask (as binary):                    11111111111111111111111100000000
Broadcast IP:                           192.0.2.255
Broadcast IP (as binary):               11000000000000000000001011111111
First usable IP (normally the Gateway): 192.0.2.1
First usable IP (as binary):            11000000000000000000001000000001
Last usable IP:                         192.0.2.255
Last usable IP (as binary):             11000000000000000000001011111110Using this representation a single IP address is simply one with a full bitmask, thus 192.0.2.1/32 is the same as 192.0.2.1.This means that our network subnetting library only needs a single classCIDR.
Utilising a single typeCIDRto represent both network objects and individual addresses results in considerably more concise code.UsageInitialisationInitialising a new CIDR object is easy and supports all common input types (presentation format, integer format, network/big-endian byte format, and built-in IP & Network types).fromcidr_manimportCIDR,Version## Create from string (presentation format)network=CIDR("192.0.2.0/24")ip=CIDR("192.0.2.1")network_v6=CIDR("2001:db8::/56")machine_alloc_v6=CIDR("2001:db8::/64")ip_v6=CIDR("2001:db8::1")## Create from built-innetwork=CIDR(IPv4Network("192.0.2.0/24"))ip=CIDR(IPv4Address("192.0.2.1"))network_v6=CIDR(IPv6Network("2001:db8::/56"))machine_alloc_v6=CIDR(IPv6Network("2001:db8::/64"))ip_v6=CIDR(IPv6Address("2001:db8::1"))## Create from integernetwork=CIDR(3221225984,version=Version.v4,prefix_len=24)ip=CIDR(3221225985,version=Version.v4)network_v6=CIDR(42540766411282592856903984951653826560,version=Version.v6,prefix_len=56)ip_v6=CIDR(42540766411282592856903984951653826561,version=Version.v6)## Create from bytenetwork=CIDR(b'\xc0\x00\x02\x01',prefix_len=24)ip=CIDR(b'\xc0\x00\x02\x01')network_v6=CIDR(b'\x01\r\xb8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01',prefix_len=56)ip_v6=CIDR(b'\x01\r\xb8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01')Get subnetsRetrieving the direct subnets of a network is easy.To get the pairnetwork=CIDR("192.0.2.0/24")subnets=network.subnets# (CIDR("192.0.2.0/25"), CIDR("192.0.2.128/25"))To get only the "left" (low-bit subnet)left=network.left# CIDR("192.0.2.0/25")To get only the "right" (high-bit subnet)right=network.right# CIDR("192.0.2.128/25")These can be chained for quick traversalleft_of_left=network.left.left# CIDR("192.0.2.0/26")right_of_left=network.left.right# CIDR(192.0.2.64/26")Get supernetsRetrieving the direct supernet of a network is easy.network=CIDR("192.0.2.0/25")supernet=network.supernet()# CIDR("192.0.2.0/24")ContainsChecking if an address or network is the subnet of another is made simpler, withsubnet in supernetsyntax fully supported.network_1=CIDR("192.0.2.0/24")network_2=CIDR("192.0.2.0/26")result=network_2innetwork_1# orresult=network_1.contains(network_2)Alternatively if you prefer the built-in library's style we've includedsubnet_offor compatibility.network_2.subnet_of(network_1)As well as additional support forsubnet < supernet,subnet <= supernet,subnet > supernet,subnet >= supernet, andsubnet == supernet*NOTE: These are perhaps counter-intuitive as this in the inverse of the size of the address space, but as this is how python's library defines the operations we're maintaining compatibilitysubnet<supernet# Returns True if subnet has less specific prefix than supernetsubnet<=supernet# Returns True if subnet has a less than or equal prefix than supernetsubnet>supernet# Returns True if subnet has a less specific prefix than supernetsubnet>=supernet# Returns True if subnet has a greater than or equal prefix supernetsubnet==supernet# Returns True if subnet is exactly equal to supernetPacked (Byte format)ip_b=ip.packed# b'\xc0\x00\x02\x01'ipv6_b=ip.packed# b' \x01\r\xb8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01'Compressed (String / Presentation format)CIDRs that have aprefix_lenequal to the maximum for their IP version (that is 32 for IPv4, and 128 for IPv6) will be presented in IP presentation format.
Therefore, bothCIDR("192.0.2.1")andCIDR("192.0.2.1/32")produce the presentation format"192.0.2.1".# IPv4ip_s=ip.compressed# "192.0.2.1"### orip_s=str(ip)# "192.0.2.1"## CIDRs who's prefix is not the max_prefix are presented in CIDR presentation formatnetwork_s=network.compressed# "192.0.2.0/24"### ornetwork_s=str(ip)# "192.0.2.0/24"# IPv6ipv6_s=ip.compressed# "2001:db8::1"### oripv6_s=str(ip)# "2001:db8::1"network_v6_s=network.compressed# "2001:db8::/56"## ornetwork_v6_s=str(ip)# "2001:db8::/56"Important addressesnetwork_address,broadcast_address,netmask,inverse_netmask,first_address, andlast_addresseach provide the relevant addresses as new CIDR objects.# IPv4net_address=network.network_address# 192.0.2.0first_address=network.first_address# 192.0.2.1last_address=network.last_address# 192.0.2.254broadcast_address=network.network_address# 192.0.2.255netmask=network.netmask# 255.255.255.0inverse_netmask=network.inverse_netmask# 0.0.0.255# IPv6net_address_v6=network_v6.network_address# 2001:db8::first_address_v6=network_v6.first_address# 2001:db8::1last_address_v6=network_v6.last_address# 2001:db8:0:ff:ffff:ffff:ffff:fffebroadcast_address_v6=network_v6.network_address# 2001:db8:0:ff:ffff:ffff:ffff:ffffnetmask_v6=network_v6.netmask# ffff:ffff:ffff:ff00::inverse_netmask_v6=network_v6.inverse_netmask# ::ff:ffff:ffff:ffff:ffffis_ flagsNOTE: While writing tests for this library we discovered that a number of theis_<address type>flags from the python built-in library were returning incorrect results. CIDR-Man is accurate as per the RFCs at the time of writing, thus our responses may differ.is_multicast=network.is_multicast# True if the address is reserved for multicast use by RFCs.is_global=network.is_global# True if the address is allocated for public networks.is_private=network.is_private# True if the address is allocated for private networks.is_reserved=network.is_reserved# True if the address is otherwise IETF reserved.is_loopback=network.is_loopback# True if this is a loopback address.is_link_local=network.is_link_local# True if the address is reserved for link-local usage.Installation (from pip):pipinstallcidr_manInstallation (from source):gitclonehttps://gitlab.com/geoip.network/cidr_man
poetryinstallTheme songCIDR-Man, CIDR-Man, Does what ever a CIDR can...Thwip! Thwip! """""""""""""""""""""""""""""""""""""""""""""""""