Claude Code for ipaddress: IP Address Handling in Python — Claude Skills 360 Blog
Blog / AI / Claude Code for ipaddress: IP Address Handling in Python
AI

Claude Code for ipaddress: IP Address Handling in Python

Published: July 25, 2028
Read time: 5 min read
By: Claude Skills 360

Python’s ipaddress module parses and manipulates IPv4/IPv6 addresses and networks. import ipaddress. ip_address: ipaddress.ip_address("192.168.1.1") → IPv4Address; ipaddress.ip_address("::1") → IPv6Address. ip_network: ipaddress.ip_network("192.168.1.0/24") → IPv4Network; strict=False accepts host bits set. ip_interface: ipaddress.ip_interface("192.168.1.1/24") → IPv4Interface (address + prefix). network_address: net.network_address → first address. broadcast_address: net.broadcast_address. netmask: net.netmask. prefixlen: net.prefixlen → 24. hosts: list(net.hosts()) — all usable host addresses (excludes network+broadcast). num_addresses: net.num_addresses. is_private: addr.is_private. is_loopback: addr.is_loopback. is_global: addr.is_global. is_multicast: addr.is_multicast. is_reserved: addr.is_reserved. is_link_local: addr.is_link_local. in network: addr in net. overlaps: net1.overlaps(net2). subnet_of/supernet_of: net1.subnet_of(net2) (Python 3.7+). subnets: list(net.subnets(new_prefix=25)). supernet: net.supernet(prefixlen_diff=1). packed: addr.packed — 4 or 16 bytes. int: int(addr). with_prefixlen: str(iface.with_prefixlen). collapsed_addresses: list(ipaddress.collapse_addresses([net1, net2])). summarize_address_range: list(ipaddress.summarize_address_range(start, end)). Claude Code generates firewall allow-list loaders, subnet calculators, CIDR validators, and IP geolocation helpers.

CLAUDE.md for ipaddress

## ipaddress Stack
- Stdlib: import ipaddress
- Parse:   addr = ipaddress.ip_address("192.168.1.1")
- Network: net  = ipaddress.ip_network("10.0.0.0/8", strict=False)
- Check:   addr in net  |  net.is_private  |  addr.is_loopback
- Hosts:   list(net.hosts())  — excludes network/broadcast
- Subnets: list(net.subnets(new_prefix=25))
- Collapse: list(ipaddress.collapse_addresses(nets))

ipaddress Network Pipeline

# app/netutil.py — parse, classify, CIDR, allow-lists, subnets, ACL
from __future__ import annotations

import ipaddress
from dataclasses import dataclass
from ipaddress import (
    IPv4Address, IPv4Interface, IPv4Network,
    IPv6Address, IPv6Interface, IPv6Network,
    ip_address, ip_interface, ip_network,
    collapse_addresses, summarize_address_range,
)
from typing import Union

IPAddr    = Union[IPv4Address, IPv6Address]
IPNetwork = Union[IPv4Network, IPv6Network]


# ─────────────────────────────────────────────────────────────────────────────
# 1. Parsing helpers
# ─────────────────────────────────────────────────────────────────────────────

def parse_address(s: str) -> IPAddr | None:
    """
    Parse an IP address string; return None on failure.

    Example:
        parse_address("192.168.1.1")     # IPv4Address('192.168.1.1')
        parse_address("::1")             # IPv6Address('::1')
        parse_address("not.an.ip")       # None
    """
    try:
        return ip_address(s.strip())
    except ValueError:
        return None


def parse_network(s: str, strict: bool = False) -> IPNetwork | None:
    """
    Parse a CIDR network string; return None on failure.
    strict=False tolerates host bits set (e.g. "192.168.1.5/24" → "192.168.1.0/24").

    Example:
        parse_network("10.0.0.0/8")
        parse_network("192.168.1.5/24", strict=False)  # 192.168.1.0/24
    """
    try:
        return ip_network(s.strip(), strict=strict)
    except ValueError:
        return None


def is_valid_ip(s: str) -> bool:
    """Return True if s is a valid IPv4 or IPv6 address."""
    return parse_address(s) is not None


def is_valid_cidr(s: str) -> bool:
    """Return True if s is a valid CIDR network string."""
    return parse_network(s) is not None


def addr_version(s: str) -> int | None:
    """
    Return 4 or 6 for the IP version, or None if invalid.

    Example:
        addr_version("192.168.1.1")  # 4
        addr_version("::1")          # 6
    """
    a = parse_address(s)
    return a.version if a else None


# ─────────────────────────────────────────────────────────────────────────────
# 2. Address classification
# ─────────────────────────────────────────────────────────────────────────────

def classify_address(addr: IPAddr | str) -> dict[str, bool]:
    """
    Return a dict of boolean properties for an IP address.

    Example:
        classify_address("192.168.1.1")
        # {"private": True, "loopback": False, "global": False, ...}
    """
    if isinstance(addr, str):
        addr = ip_address(addr)
    return {
        "private":    addr.is_private,
        "loopback":   addr.is_loopback,
        "global":     addr.is_global,
        "multicast":  addr.is_multicast,
        "link_local": addr.is_link_local,
        "reserved":   addr.is_reserved,
        "unspecified": addr.is_unspecified,
        "ipv4":       addr.version == 4,
        "ipv6":       addr.version == 6,
    }


def is_routable(addr: str | IPAddr) -> bool:
    """
    Return True if address is likely routable on the public Internet.

    Example:
        is_routable("8.8.8.8")        # True
        is_routable("192.168.1.1")    # False
        is_routable("127.0.0.1")      # False
    """
    if isinstance(addr, str):
        a = parse_address(addr)
        if a is None:
            return False
    else:
        a = addr
    return a.is_global and not a.is_multicast and not a.is_reserved


# ─────────────────────────────────────────────────────────────────────────────
# 3. Network operations
# ─────────────────────────────────────────────────────────────────────────────

def network_info(cidr: str) -> dict:
    """
    Return detailed info about a CIDR network.

    Example:
        info = network_info("192.168.1.0/24")
        info["num_hosts"]       # 254
        info["broadcast"]       # "192.168.1.255"
    """
    net = ip_network(cidr, strict=False)
    return {
        "cidr":           str(net),
        "network_address": str(net.network_address),
        "broadcast":      str(net.broadcast_address) if net.version == 4 else "N/A",
        "netmask":        str(net.netmask),
        "prefixlen":      net.prefixlen,
        "num_addresses":  net.num_addresses,
        "num_hosts":      max(0, net.num_addresses - 2) if net.version == 4 else net.num_addresses,
        "version":        net.version,
        "is_private":     net.is_private,
    }


def split_network(cidr: str, new_prefix: int) -> list[str]:
    """
    Split a CIDR network into subnets of new_prefix length.

    Example:
        split_network("10.0.0.0/24", 26)
        # ["10.0.0.0/26", "10.0.0.64/26", "10.0.0.128/26", "10.0.0.192/26"]
    """
    net = ip_network(cidr, strict=False)
    return [str(s) for s in net.subnets(new_prefix=new_prefix)]


def summarize_range(start_ip: str, end_ip: str) -> list[str]:
    """
    Return the minimal list of CIDR blocks covering start_ip to end_ip.

    Example:
        summarize_range("192.168.0.0", "192.168.0.255")  # ["192.168.0.0/24"]
    """
    start = ip_address(start_ip)
    end   = ip_address(end_ip)
    return [str(net) for net in summarize_address_range(start, end)]


def collapse(cidrs: list[str]) -> list[str]:
    """
    Collapse a list of overlapping/adjacent CIDR blocks into minimal form.

    Example:
        collapse(["10.0.0.0/25", "10.0.0.128/25"])  # ["10.0.0.0/24"]
        collapse(["192.168.1.0/24", "192.168.1.0/28"])  # ["192.168.1.0/24"]
    """
    nets = [ip_network(c, strict=False) for c in cidrs]
    return [str(n) for n in collapse_addresses(nets)]


# ─────────────────────────────────────────────────────────────────────────────
# 4. Access control / allow-list
# ─────────────────────────────────────────────────────────────────────────────

@dataclass
class IPACLRule:
    network: IPNetwork
    action:  str   # "allow" or "deny"
    comment: str = ""


class IPAccessList:
    """
    Ordered IP access control list with allow/deny rules.
    First matching rule wins.

    Example:
        acl = IPAccessList()
        acl.add_allow("10.0.0.0/8",     "Internal network")
        acl.add_allow("127.0.0.1/32",   "Loopback")
        acl.add_deny("0.0.0.0/0",       "Default deny")
        acl.is_allowed("10.1.2.3")   # True
        acl.is_allowed("8.8.8.8")    # False
    """

    def __init__(self) -> None:
        self._rules: list[IPACLRule] = []

    def add_allow(self, cidr: str, comment: str = "") -> None:
        net = ip_network(cidr, strict=False)
        self._rules.append(IPACLRule(network=net, action="allow", comment=comment))

    def add_deny(self, cidr: str, comment: str = "") -> None:
        net = ip_network(cidr, strict=False)
        self._rules.append(IPACLRule(network=net, action="deny", comment=comment))

    def is_allowed(self, addr: str | IPAddr, default: bool = False) -> bool:
        """Return True if addr matches an allow rule before any deny rule."""
        if isinstance(addr, str):
            a = parse_address(addr)
            if a is None:
                return False
        else:
            a = addr
        for rule in self._rules:
            if a in rule.network:
                return rule.action == "allow"
        return default

    def lookup(self, addr: str | IPAddr) -> IPACLRule | None:
        """Return the first matching rule, or None."""
        if isinstance(addr, str):
            a = parse_address(addr)
            if a is None:
                return None
        else:
            a = addr
        for rule in self._rules:
            if a in rule.network:
                return rule
        return None


# ─────────────────────────────────────────────────────────────────────────────
# Demo
# ─────────────────────────────────────────────────────────────────────────────

if __name__ == "__main__":
    print("=== ipaddress demo ===")

    print("\n--- parse_address ---")
    for s in ["192.168.1.1", "::1", "10.0.0.1", "255.255.255.255", "not.ip"]:
        a = parse_address(s)
        print(f"  {s!r:20s}: {a!r}")

    print("\n--- classify_address ---")
    for s in ["8.8.8.8", "192.168.1.1", "127.0.0.1", "::1", "224.0.0.1"]:
        c = classify_address(s)
        flags = [k for k, v in c.items() if v]
        print(f"  {s:20s}: {flags}")

    print("\n--- is_routable ---")
    for s in ["8.8.8.8", "192.168.1.1", "172.16.5.1", "10.0.0.1", "100.64.0.1"]:
        print(f"  {s:20s}: routable={is_routable(s)}")

    print("\n--- network_info ---")
    info = network_info("192.168.1.0/24")
    for k, v in info.items():
        print(f"  {k:20s}: {v}")

    print("\n--- split_network ---")
    subnets = split_network("10.0.0.0/24", 26)
    for s in subnets:
        print(f"  {s}")

    print("\n--- summarize_range ---")
    cidrs = summarize_range("192.168.0.0", "192.168.0.255")
    print(f"  192.168.0.0–255 → {cidrs}")

    print("\n--- collapse ---")
    before = ["10.0.0.0/25", "10.0.0.128/25", "192.168.1.0/26", "192.168.1.64/26"]
    after  = collapse(before)
    print(f"  before: {before}")
    print(f"  after:  {after}")

    print("\n--- IPAccessList ---")
    acl = IPAccessList()
    acl.add_allow("10.0.0.0/8",   "Internal")
    acl.add_allow("127.0.0.0/8",  "Loopback")
    acl.add_deny("0.0.0.0/0",     "Default deny")
    for ip in ["10.1.2.3", "127.0.0.1", "8.8.8.8", "172.16.1.1"]:
        rule = acl.lookup(ip)
        allowed = acl.is_allowed(ip)
        comment = rule.comment if rule else "no match"
        print(f"  {ip:20s}: allowed={allowed}  ({comment})")

    print("\n=== done ===")

For the netaddr alternative — netaddr (PyPI) provides IPAddress, IPNetwork, IPSet, and IPRange objects with set algebra (IPSet([net1]) | IPSet([net2])), spanning-range support, and IP database lookup integrations; stdlib ipaddress covers the core RFC 4122 operations without set operations — use netaddr when you need IP set algebra, spanning tree merging, or EUI (MAC address) handling in network tooling, stdlib ipaddress for application-level validation, access control, and subnet calculations where standard library is preferred. For the ipwhois alternative — ipwhois (PyPI) performs WHOIS and RDAP lookups to return ASN, organization, country, and abuse contact for an IP address; stdlib ipaddress only parses and classifies addresses without performing network lookups — use ipwhois for IP enrichment pipelines, abuse reporting, and geo/org data, stdlib ipaddress for local validation, CIDR arithmetic, and firewall rule management. The Claude Skills 360 bundle includes ipaddress skill sets covering parse_address()/parse_network()/is_valid_ip()/is_valid_cidr()/addr_version() parsing helpers, classify_address()/is_routable() address classification, network_info()/split_network()/summarize_range()/collapse() network operations, and IPACLRule/IPAccessList ordered access control list with add_allow()/add_deny()/is_allowed()/lookup(). Start with the free tier to try IP network management and ipaddress pipeline code generation.

Keep Reading

AI

Claude Code for email.contentmanager: Python Email Content Accessors

Read and write EmailMessage body content with Python's email.contentmanager module and Claude Code — email contentmanager ContentManager for the class that maps content types to get and set handler functions allowing EmailMessage to support get_content and set_content with type-specific behaviour, email contentmanager raw_data_manager for the ContentManager instance that handles raw bytes and str payloads without any conversion, email contentmanager content_manager for the standard ContentManager instance used by email.policy.default that intelligently handles text plain text html multipart and binary content types, email contentmanager get_content_text for the handler that returns the decoded text payload of a text-star message part as a str, email contentmanager get_content_binary for the handler that returns the raw decoded bytes payload of a non-text message part, email contentmanager get_data_manager for the get-handler lookup used by EmailMessage get_content to find the right reader function for the content type, email contentmanager set_content text for the handler that creates and sets a text part correctly choosing charset and transfer encoding, email contentmanager set_content bytes for the handler that creates and sets a binary part with base64 encoding and optional filename Content-Disposition, email contentmanager EmailMessage get_content for the method that reads the message body using the registered content manager handlers, email contentmanager EmailMessage set_content for the method that sets the message body and MIME headers in one call, email contentmanager EmailMessage make_alternative make_mixed make_related for the methods that convert a simple message into a multipart container, email contentmanager EmailMessage add_attachment for the method that attaches a file or bytes to a multipart message, and email contentmanager integration with email.message and email.policy and email.mime and io for building high-level email readers attachment extractors text body accessors HTML readers and policy-aware MIME construction pipelines.

5 min read Feb 12, 2029
AI

Claude Code for email.charset: Python Email Charset Encoding

Control header and body encoding for international email with Python's email.charset module and Claude Code — email charset Charset for the class that wraps a character set name with the encoding rules for header encoding and body encoding describing how to encode text for that charset in email messages, email charset Charset header_encoding for the attribute specifying whether headers using this charset should use QP quoted-printable encoding BASE64 encoding or no encoding, email charset Charset body_encoding for the attribute specifying the Content-Transfer-Encoding to use for message bodies in this charset such as QP or BASE64, email charset Charset output_codec for the attribute giving the Python codec name used to encode the string to bytes for the wire format, email charset Charset input_codec for the attribute giving the Python codec name used to decode incoming bytes to str, email charset Charset get_output_charset for returning the output charset name, email charset Charset header_encode for encoding a header string using the charset's header_encoding method, email charset Charset body_encode for encoding body content using the charset's body_encoding, email charset Charset convert for converting a string from the input_codec to the output_codec, email charset add_charset for registering a new charset with custom encoding rules in the global charset registry, email charset add_alias for adding an alias name that maps to an existing registered charset, email charset add_codec for registering a codec name mapping for use by the charset machinery, and email charset integration with email.message and email.mime and email.policy and email.encoders for building international email senders non-ASCII header encoders Content-Transfer-Encoding selectors charset-aware message constructors and MIME encoding pipelines.

5 min read Feb 11, 2029
AI

Claude Code for email.utils: Python Email Address and Header Utilities

Parse and format RFC 2822 email addresses and dates with Python's email.utils module and Claude Code — email utils parseaddr for splitting a display-name plus angle-bracket address string into a realname and email address tuple, email utils formataddr for combining a realname and address string into a properly quoted RFC 2822 address with angle brackets, email utils getaddresses for parsing a list of raw address header strings each potentially containing multiple comma-separated addresses into a list of realname address tuples, email utils parsedate for parsing an RFC 2822 date string into a nine-tuple compatible with time.mktime, email utils parsedate_tz for parsing an RFC 2822 date string into a ten-tuple that includes the UTC offset timezone in seconds, email utils parsedate_to_datetime for parsing an RFC 2822 date string into an aware datetime object with timezone, email utils formatdate for formatting a POSIX timestamp or the current time as an RFC 2822 date string with optional usegmt and localtime flags, email utils format_datetime for formatting a datetime object as an RFC 2822 date string, email utils make_msgid for generating a globally unique Message-ID string with optional idstring and domain components, email utils decode_rfc2231 for decoding an RFC 2231 encoded parameter value into a tuple of charset language and value, email utils encode_rfc2231 for encoding a string as an RFC 2231 encoded parameter value, email utils collapse_rfc2231_value for collapsing a decoded RFC 2231 tuple to a Unicode string, and email utils integration with email.message and email.headerregistry and datetime and time for building address parsers date formatters message-id generators header extractors and RFC-compliant email construction utilities.

5 min read Feb 10, 2029

Put these ideas into practice

Claude Skills 360 gives you production-ready skills for everything in this article — and 2,350+ more. Start free or go all-in.

Back to Blog

Get 360 skills free