Claude Code for string: Python String Constants and Templates — Claude Skills 360 Blog
Blog / AI / Claude Code for string: Python String Constants and Templates
AI

Claude Code for string: Python String Constants and Templates

Published: August 20, 2028
Read time: 5 min read
By: Claude Skills 360

Python’s string module provides character-set constants and Template/Formatter classes. import string. Constants: string.ascii_letters = ‘abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ’; string.ascii_lowercase; string.ascii_uppercase; string.digits = ‘0123456789’; string.hexdigits = ‘0123456789abcdefABCDEF’; string.octdigits = ‘01234567’; string.punctuation = ’!”#$%&’()*+,-./:;<=>?@[\]^_{|}~'; string.printable= digits + letters + punctuation + whitespace;string.whitespace= ' \t\n\r\x0b\x0c'. Template:t = string.Template(“Hello $name”)— uses$identifieror${identifier}syntax;t.substitute(name=“Alice”)→ 'Hello Alice' (raises KeyError on missing keys);t.safe_substitute(name=“Alice”)→ leaves missing$varunchanged. Custom delimiter: subclass Template and setdelimiter = ”@“. t.template→ original string. Formatter:string.Formatter()— implementsstr.format()protocol;.format(fmt, *args, **kw); .parse(fmt)(literal_text, field_name, format_spec, conversion)tuples;.vformat(fmt, args, kwargs)for pre-parsed calls. capwords:string.capwords(“hello world”)` → ‘Hello World’ (splits on whitespace, strips). Claude Code generates config file renderers, code generators, email templates, and table formatters.

CLAUDE.md for string

## string Stack
- Stdlib: import string
- Const:  string.ascii_letters  string.digits  string.punctuation
- Tmpl:   t = string.Template("Dear $name,"); t.substitute(name="Bob")
- Safe:   t.safe_substitute(name="Bob")   # no KeyError on missing vars
- Fmt:    string.Formatter().format("{x:.2f}", x=3.14)
- Cap:    string.capwords("hello world")  # "Hello World"

string Constants and Template Pipeline

# app/strutil.py — charset helpers, password gen, Template rendering, Formatter
from __future__ import annotations

import re
import secrets
import string
from dataclasses import dataclass
from typing import Any, Mapping


# ─────────────────────────────────────────────────────────────────────────────
# 1. Character-set helpers
# ─────────────────────────────────────────────────────────────────────────────

def is_ascii_printable(s: str) -> bool:
    """
    Return True if every character in s is in string.printable.

    Example:
        is_ascii_printable("Hello!")    # True
        is_ascii_printable("Héllo")    # False
    """
    return all(c in string.printable for c in s)


def contains_only(s: str, charset: str) -> bool:
    """
    Return True if every character in s is in charset.

    Example:
        contains_only("abc123", string.ascii_letters + string.digits)  # True
        contains_only("abc-123", string.ascii_letters + string.digits) # False
    """
    return all(c in charset for c in s)


def filter_chars(s: str, keep: str) -> str:
    """
    Return s with only characters in the `keep` charset preserved.

    Example:
        filter_chars("Hello, World! 123", string.ascii_letters)  # "HelloWorld"
        filter_chars("ph: +1-555-0100", string.digits)           # "15550100"
    """
    return "".join(c for c in s if c in keep)


def count_char_types(s: str) -> dict[str, int]:
    """
    Count characters by type: upper, lower, digit, punctuation, whitespace, other.

    Example:
        count_char_types("Hello, World 99!")
        # {'upper': 2, 'lower': 8, 'digit': 2, 'punctuation': 2, 'whitespace': 1, 'other': 0}
    """
    return {
        "upper":       sum(1 for c in s if c in string.ascii_uppercase),
        "lower":       sum(1 for c in s if c in string.ascii_lowercase),
        "digit":       sum(1 for c in s if c in string.digits),
        "punctuation": sum(1 for c in s if c in string.punctuation),
        "whitespace":  sum(1 for c in s if c in string.whitespace),
        "other":       sum(1 for c in s if c not in string.printable),
    }


def make_charset(
    upper: bool = True,
    lower: bool = True,
    digits: bool = True,
    punctuation: bool = False,
    extra: str = "",
) -> str:
    """
    Build a character set string from flags.

    Example:
        cs = make_charset(punctuation=True, extra="@#")
        gen_token(16, cs)
    """
    parts = []
    if upper:
        parts.append(string.ascii_uppercase)
    if lower:
        parts.append(string.ascii_lowercase)
    if digits:
        parts.append(string.digits)
    if punctuation:
        parts.append(string.punctuation)
    if extra:
        parts.append(extra)
    return "".join(dict.fromkeys("".join(parts)))  # deduplicate, preserve order


# ─────────────────────────────────────────────────────────────────────────────
# 2. Secure token and password generation
# ─────────────────────────────────────────────────────────────────────────────

def gen_token(length: int = 32, charset: str | None = None) -> str:
    """
    Generate a cryptographically secure random token from charset.
    Defaults to URL-safe base62 (letters + digits).

    Example:
        gen_token(24)          # e.g. "K7gXm2Nq8pBzVrTsWdCf3h4Y"
        gen_token(16, string.digits)  # 16-digit numeric code
    """
    cs = charset or (string.ascii_letters + string.digits)
    return "".join(secrets.choice(cs) for _ in range(length))


def gen_password(
    length: int = 16,
    require_upper: bool = True,
    require_lower: bool = True,
    require_digit: bool = True,
    require_punct: bool = True,
) -> str:
    """
    Generate a random password satisfying the given character-type requirements.

    Example:
        gen_password(20)  # secure 20-char password with all types
    """
    required: list[str] = []
    if require_upper:
        required.append(secrets.choice(string.ascii_uppercase))
    if require_lower:
        required.append(secrets.choice(string.ascii_lowercase))
    if require_digit:
        required.append(secrets.choice(string.digits))
    if require_punct:
        required.append(secrets.choice(string.punctuation))

    charset = make_charset(
        upper=require_upper,
        lower=require_lower,
        digits=require_digit,
        punctuation=require_punct,
    )
    pool = [secrets.choice(charset) for _ in range(length - len(required))]
    chars = required + pool
    # Shuffle in-place using secrets-derived order
    for i in range(len(chars) - 1, 0, -1):
        j = secrets.randbelow(i + 1)
        chars[i], chars[j] = chars[j], chars[i]
    return "".join(chars)


def gen_slug(base: str, length: int = 8) -> str:
    """
    Append a short random suffix to base to create a unique slug.

    Example:
        gen_slug("user")   # "user-k7gx2mNq"
    """
    suffix = gen_token(length, string.ascii_lowercase + string.digits)
    safe_base = filter_chars(base.lower().replace(" ", "-"), string.ascii_lowercase + string.digits + "-")
    return f"{safe_base}-{suffix}" if safe_base else suffix


# ─────────────────────────────────────────────────────────────────────────────
# 3. Template rendering
# ─────────────────────────────────────────────────────────────────────────────

def render_template(template_str: str, mapping: Mapping[str, Any], safe: bool = True) -> str:
    """
    Render a string.Template with the given mapping.
    safe=True uses safe_substitute (missing vars left as-is).
    safe=False uses substitute (raises KeyError on missing vars).

    Example:
        render_template("Hello $name, you have $count messages.", {"name": "Alice", "count": 3})
        # "Hello Alice, you have 3 messages."
    """
    t = string.Template(template_str)
    return t.safe_substitute(mapping) if safe else t.substitute(mapping)


def render_template_file(path: str, mapping: Mapping[str, Any], safe: bool = True) -> str:
    """
    Read a template file and render it with the given mapping.

    Example:
        html = render_template_file("templates/email.txt", {"user": "Alice", "link": "..."})
    """
    import pathlib
    content = pathlib.Path(path).read_text(encoding="utf-8")
    return render_template(content, mapping, safe=safe)


def extract_template_vars(template_str: str) -> list[str]:
    """
    Return all variable names referenced in a string.Template instance.

    Example:
        extract_template_vars("Dear $name, your order $order_id is ready.")
        # ['name', 'order_id']
    """
    pattern = re.compile(r"\$\{?([_a-z][_a-z0-9]*)\}?", re.IGNORECASE)
    return list(dict.fromkeys(pattern.findall(template_str)))


class AtTemplate(string.Template):
    """string.Template subclass using @ as the delimiter instead of $."""
    delimiter = "@"


def render_at_template(template_str: str, mapping: Mapping[str, Any]) -> str:
    """
    Render an @-delimited template (useful when $ conflicts with shell or currencies).

    Example:
        render_at_template("Price: @price USD", {"price": "9.99"})
        # "Price: 9.99 USD"
    """
    return AtTemplate(template_str).safe_substitute(mapping)


# ─────────────────────────────────────────────────────────────────────────────
# 4. Formatter utilities
# ─────────────────────────────────────────────────────────────────────────────

def parse_format_fields(fmt: str) -> list[str]:
    """
    Return all field names referenced in a str.format()-style format string.

    Example:
        parse_format_fields("{name:20s} {count:5d} {pct:.2%}")
        # ['name', 'count', 'pct']
    """
    fmt_obj = string.Formatter()
    return [field for _, field, _, _ in fmt_obj.parse(fmt) if field is not None]


def safe_format(fmt: str, **kwargs: Any) -> str:
    """
    Format fmt using only the provided kwargs; missing keys render as '{key}'.

    Example:
        safe_format("Hello {name}, score={score}", name="Alice")
        # "Hello Alice, score={score}"
    """
    class SafeDict(dict):
        def __missing__(self, key: str) -> str:
            return "{" + key + "}"

    return fmt.format_map(SafeDict(kwargs))


def render_table(
    rows: list[dict[str, Any]],
    columns: list[str],
    widths: list[int] | None = None,
) -> str:
    """
    Render a list of dicts as a fixed-width text table.

    Example:
        rows = [{"name": "Alice", "score": 95}, {"name": "Bob", "score": 87}]
        print(render_table(rows, ["name", "score"], [20, 8]))
    """
    if not rows:
        return ""
    col_widths = widths or [max(len(str(r.get(c, ""))) for r in rows + [{"name": c}]) for c in columns]
    fmt = "  ".join(f"{{:<{w}}}" for w in col_widths)
    header = fmt.format(*[c.upper() for c in columns])
    sep = "  ".join("-" * w for w in col_widths)
    lines = [header, sep]
    for row in rows:
        lines.append(fmt.format(*[str(row.get(c, "")) for c in columns]))
    return "\n".join(lines)


# ─────────────────────────────────────────────────────────────────────────────
# 5. String transformation helpers
# ─────────────────────────────────────────────────────────────────────────────

def capwords(s: str, sep: str | None = None) -> str:
    """
    Capitalize each word in s using string.capwords.

    Example:
        capwords("hello world")        # "Hello World"
        capwords("hello-world", "-")   # "Hello-World"
    """
    return string.capwords(s, sep)


def slugify(s: str, sep: str = "-") -> str:
    """
    Convert s to a URL-safe slug: lowercase, strip non-alnum to sep.

    Example:
        slugify("Hello World!")         # "hello-world"
        slugify("  Leading  Spaces  ")  # "leading-spaces"
    """
    s = s.lower().strip()
    s = re.sub(r"[^a-z0-9]+", sep, s)
    return s.strip(sep)


def truncate(s: str, max_len: int, suffix: str = "…") -> str:
    """
    Truncate s to max_len characters, appending suffix if truncated.

    Example:
        truncate("Hello World", 8)   # "Hello W…"
        truncate("Hi", 8)            # "Hi"
    """
    if len(s) <= max_len:
        return s
    return s[: max_len - len(suffix)] + suffix


def pad_center(s: str, width: int, fillchar: str = " ") -> str:
    """Center s in a field of `width` characters."""
    return s.center(width, fillchar)


def indent_block(s: str, prefix: str = "    ") -> str:
    """Add prefix to every non-empty line in s."""
    return "\n".join(prefix + line if line.strip() else line for line in s.splitlines())


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

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

    print("\n--- character constants ---")
    print(f"  ascii_letters[:10]  : {string.ascii_letters[:10]}")
    print(f"  digits              : {string.digits}")
    print(f"  punctuation[:10]    : {string.punctuation[:10]}")

    print("\n--- contains_only / filter_chars ---")
    print(f"  contains_only('abc123', alnum): {contains_only('abc123', string.ascii_letters + string.digits)}")
    print(f"  filter_chars('ph: +1-555-0100', digits): {filter_chars('ph: +1-555-0100', string.digits)}")

    print("\n--- count_char_types ---")
    sample = "Hello, World 99!"
    print(f"  count_char_types({sample!r}): {count_char_types(sample)}")

    print("\n--- gen_token / gen_password ---")
    print(f"  gen_token(16)      : {gen_token(16)}")
    print(f"  gen_password(20)   : {gen_password(20)}")
    print(f"  gen_slug('user')   : {gen_slug('user')}")

    print("\n--- Template rendering ---")
    tmpl = "Dear $name,\n\nYour order $order_id is ready for pickup.\n\nRegards,\n$sender"
    rendered = render_template(tmpl, {"name": "Alice", "order_id": "ORD-7842", "sender": "Acme"})
    print(rendered)
    print(f"\n  extract_template_vars: {extract_template_vars(tmpl)}")
    print(f"  render_at_template: {render_at_template('Price: @price USD (was @old_price)', {'price': '9.99', 'old_price': '14.99'})}")

    print("\n--- safe_format ---")
    print(f"  safe_format: {safe_format('Hello {name}, score={score}', name='Alice')}")

    print("\n--- render_table ---")
    rows = [
        {"name": "Alice",   "score": 95, "grade": "A"},
        {"name": "Bob",     "score": 87, "grade": "B+"},
        {"name": "Charlie", "score": 72, "grade": "C"},
    ]
    print(render_table(rows, ["name", "score", "grade"]))

    print("\n--- capwords / slugify / truncate ---")
    print(f"  capwords('hello world')          : {capwords('hello world')}")
    print(f"  slugify('Hello World! 2025')     : {slugify('Hello World! 2025')}")
    print(f"  truncate('Hello World', 8)       : {truncate('Hello World', 8)}")
    print(f"  indent_block('line1\\nline2'):")
    print(indent_block("line1\nline2"))

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

For the re alternative — Python’s re module provides full regular-expression pattern matching and substitution for complex string parsing and transformation; string provides character-set constants that serve as building blocks for regex character classes ([ + string.ascii_letters + ]) and identity predicates — use re for pattern extraction, validation with complex rules, and multi-step text transformations; use string constants to define and document character sets explicitly, and string.Template when you need $variable substitution without the security risks of str.format() on untrusted input. For the jinja2 alternative — jinja2 (PyPI) provides a full template engine with loops, conditionals, inheritance, autoescaping, and macros for rendering HTML, YAML, and other formats; string.Template supports only simple $identifier substitution with no logic — use jinja2 for web templates, configuration generation with conditional blocks, and any template that requires iteration or logic; use string.Template for lightweight variable substitution in internal tooling and code generators where introducing a templating dependency is not warranted. The Claude Skills 360 bundle includes string skill sets covering is_ascii_printable()/contains_only()/filter_chars()/count_char_types()/make_charset() character-set helpers, gen_token()/gen_password()/gen_slug() secure generation, render_template()/render_template_file()/extract_template_vars()/AtTemplate/render_at_template() Template utilities, parse_format_fields()/safe_format()/render_table() Formatter tools, and capwords()/slugify()/truncate()/indent_block() string transforms. Start with the free tier to try string template patterns and string module 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