Claude Code for inflect: English Language Inflection in Python — Claude Skills 360 Blog
Blog / AI / Claude Code for inflect: English Language Inflection in Python
AI

Claude Code for inflect: English Language Inflection in Python

Published: June 8, 2028
Read time: 5 min read
By: Claude Skills 360

inflect generates grammatically correct English text. pip install inflect. Engine: import inflect; p = inflect.engine(). Plural: p.plural("dog") → “dogs”. p.plural("mouse") → “mice”. Plural noun: p.plural_noun("cactus") → “cacti”. Plural verb: p.plural_verb("is") → “are”. Singular: p.singular_noun("dogs") → “dog”. p.singular_noun("dog") → False (already singular). Article a/an: p.a("apple") → “an apple”. p.a("dog") → “a dog”. Number to words: p.number_to_words(42) → “forty-two”. p.number_to_words(0) → “zero”. Words with threshold: p.number_to_words(1000) → “one thousand”. Ordinal: p.ordinal(1) → “1st”. p.ordinal(42) → “42nd”. Ordinal words: p.number_to_words(42, andword="") + p.ordinal("forty-two") → “forty-second”. join: p.join(["a","b","c"]) → “a, b, and c”. p.join(["a","b"], final_sep="", conj="or") → “a or b”. plural adj: p.plural_adj("red") → “red” (adjectives don’t usually pluralize). inflect noun: p.inflect("2 dog") → “2 dogs”. no: p.no("file", 0) → “no files”. p.no("file", 1) → “1 file”. p.no("file", 2) → “2 files”. present_participle: p.present_participle("run") → “running”. Classical mode: p.classical() — enables “formulae” vs “formulas”. compare: p.compare("dog", "dogs") → “si” (singular of irregular). Claude Code generates inflect UI labels, report summaries, pluralization helpers, and grammar-correct notification templates.

CLAUDE.md for inflect

## inflect Stack
- Version: inflect >= 7.0 | pip install inflect
- Init: p = inflect.engine()
- Plural: p.plural("dog") | p.plural_noun("cactus") | p.plural_verb("is")
- Singular: p.singular_noun("dogs") → "dog" | False if already singular
- Article: p.a("apple") → "an apple" | p.a("user") → "a user"
- Numbers: p.number_to_words(42) | p.ordinal(3) | p.no("file", count)
- Join: p.join(["a","b","c"]) → "a, b, and c"

inflect Grammar Pipeline

# app/grammar.py — inflect pluralization, articles, numbers, ordinals, joins, UI labels
from __future__ import annotations

import inflect


# Single shared engine instance (thread-safe for reads)
_p = inflect.engine()


# ─────────────────────────────────────────────────────────────────────────────
# 1. Pluralization
# ─────────────────────────────────────────────────────────────────────────────

def pluralize(word: str, count: int | None = None) -> str:
    """
    Return the plural form of a word.
    If count is given, return singular when count==1.

    Example:
        pluralize("dog")       # "dogs"
        pluralize("mouse")     # "mice"
        pluralize("child")     # "children"
        pluralize("dog", 1)    # "dog"
        pluralize("dog", 2)    # "dogs"
    """
    if count is not None and abs(count) == 1:
        return word
    return _p.plural(word) or word


def pluralize_verb(verb: str, count: int = 2) -> str:
    """
    Return the correct verb form for the given count.

    Example:
        pluralize_verb("is", 1)  # "is"
        pluralize_verb("is", 2)  # "are"
        pluralize_verb("has", 3) # "have"
    """
    if abs(count) == 1:
        return verb
    return _p.plural_verb(verb) or verb


def singular(word: str) -> str:
    """
    Return the singular form of a word.
    Returns the word unchanged if already singular.

    Example:
        singular("dogs")     # "dog"
        singular("mice")     # "mouse"
        singular("children") # "child"
        singular("dog")      # "dog" (already singular)
    """
    result = _p.singular_noun(word)
    return result if result else word


def is_plural(word: str) -> bool:
    """Return True if the word appears to be plural."""
    return bool(_p.singular_noun(word))


# ─────────────────────────────────────────────────────────────────────────────
# 2. Article selection
# ─────────────────────────────────────────────────────────────────────────────

def with_article(word: str, capitalize: bool = False) -> str:
    """
    Prepend 'a' or 'an' to a word based on pronunciation.

    Example:
        with_article("apple")     # "an apple"
        with_article("unicorn")   # "a unicorn"   (hard 'u')
        with_article("hour")      # "an hour"     (silent 'h')
        with_article("apple", capitalize=True)  # "An apple"
    """
    result = _p.a(word) or f"a {word}"
    if capitalize:
        return result[0].upper() + result[1:]
    return result


def article_only(word: str) -> str:
    """Return just 'a' or 'an' for the given word."""
    article_phrase = _p.a(word) or "a"
    return article_phrase.split()[0]


# ─────────────────────────────────────────────────────────────────────────────
# 3. Number formatting
# ─────────────────────────────────────────────────────────────────────────────

def number_to_words(
    n: int,
    threshold: int | None = None,
    andword: str = "and",
    zero: str = "zero",
    one: str | None = None,
) -> str:
    """
    Convert an integer to English words.
    threshold: only convert numbers below this value (return numeral otherwise).

    Example:
        number_to_words(0)       # "zero"
        number_to_words(42)      # "forty-two"
        number_to_words(1000)    # "one thousand"
        number_to_words(42, threshold=20)  # "42" (above threshold)
    """
    if threshold is not None and abs(n) >= threshold:
        return str(n)
    result = _p.number_to_words(n, andword=andword, zero=zero, one=one or "one")
    return result


def ordinal_str(n: int, as_words: bool = False) -> str:
    """
    Return the ordinal form of a number.

    Example:
        ordinal_str(1)               # "1st"
        ordinal_str(42)              # "42nd"
        ordinal_str(3, as_words=True) # "third"
    """
    if as_words:
        words = _p.number_to_words(n)
        return _p.ordinal(words)
    return _p.ordinal(n)


def count_phrase(
    count: int,
    noun: str,
    zero_phrase: str | None = None,
    as_words: bool = False,
    capitalize: bool = False,
) -> str:
    """
    Build a grammatically correct count phrase.

    Example:
        count_phrase(0, "file")          # "no files"
        count_phrase(1, "file")          # "1 file"
        count_phrase(3, "file")          # "3 files"
        count_phrase(0, "result",
                     zero_phrase="none") # "none"
        count_phrase(42, "item",
                     as_words=True)      # "forty-two items"
    """
    if count == 0 and zero_phrase is not None:
        return zero_phrase

    num_str = number_to_words(count) if as_words else str(count)
    noun_form = pluralize(noun, count)

    if count == 0:
        result = f"no {_p.plural(noun)}"
    else:
        result = f"{num_str} {noun_form}"

    if capitalize:
        return result[0].upper() + result[1:]
    return result


# ─────────────────────────────────────────────────────────────────────────────
# 4. List joining
# ─────────────────────────────────────────────────────────────────────────────

def join_list(
    items: list[str],
    conjunction: str = "and",
    oxford_comma: bool = True,
) -> str:
    """
    Join a list of strings with a grammatically correct conjunction.

    Example:
        join_list(["Alice"])                     # "Alice"
        join_list(["Alice", "Bob"])              # "Alice and Bob"
        join_list(["Alice", "Bob", "Carol"])     # "Alice, Bob, and Carol"
        join_list(["a", "b", "c"], conjunction="or")  # "a, b, or c"
        join_list(["a", "b", "c"], oxford_comma=False) # "a, b and c"
    """
    if not items:
        return ""
    if len(items) == 1:
        return items[0]
    if len(items) == 2:
        return f"{items[0]} {conjunction} {items[1]}"

    sep = ", " + conjunction if oxford_comma else " " + conjunction
    return ", ".join(items[:-1]) + sep + " " + items[-1]


def join_nouns(nouns: list[str], counts: list[int], conjunction: str = "and") -> str:
    """
    Join count+noun pairs.

    Example:
        join_nouns(["file", "folder"], [3, 1])
        # "3 files and 1 folder"
    """
    phrases = [count_phrase(c, n) for n, c in zip(nouns, counts)]
    return join_list(phrases, conjunction=conjunction)


# ─────────────────────────────────────────────────────────────────────────────
# 5. Verb forms
# ─────────────────────────────────────────────────────────────────────────────

def present_participle(verb: str) -> str:
    """
    Return the present participle (-ing form) of a verb.

    Example:
        present_participle("run")    # "running"
        present_participle("write")  # "writing"
        present_participle("play")   # "playing"
    """
    return _p.present_participle(verb) or f"{verb}ing"


def subject_verb(subject: str, verb: str, count: int = 1) -> str:
    """
    Build a subject-verb phrase with correct agreement.

    Example:
        subject_verb("user", "has", 1)   # "user has"
        subject_verb("user", "has", 3)   # "users have"
        subject_verb("file", "is",  2)   # "files are"
    """
    noun = pluralize(subject, count)
    vb   = pluralize_verb(verb, count)
    return f"{noun} {vb}"


# ─────────────────────────────────────────────────────────────────────────────
# 6. UI / notification helpers
# ─────────────────────────────────────────────────────────────────────────────

def badge_label(count: int, noun: str) -> str:
    """
    Format a UI badge label.

    Example:
        badge_label(0, "notification")  # "No notifications"
        badge_label(1, "notification")  # "1 notification"
        badge_label(5, "notification")  # "5 notifications"
    """
    if count == 0:
        return f"No {pluralize(noun)}"
    noun_form = pluralize(noun, count)
    return f"{count} {noun_form}"


def summary_sentence(
    items: list[str],
    verb: str = "found",
    noun: str = "result",
) -> str:
    """
    Build a result summary sentence.

    Example:
        summary_sentence([], "found", "result")
        # "No results found."
        summary_sentence(["a"], "found", "result")
        # "1 result found."
        summary_sentence(["a","b","c"], "returned", "item")
        # "3 items returned."
    """
    count = len(items)
    if count == 0:
        return f"No {pluralize(noun)} {verb}."
    noun_form = pluralize(noun, count)
    return f"{count} {noun_form} {verb}."


def notification_text(
    actor: str,
    action: str,
    count: int,
    item_noun: str,
) -> str:
    """
    Build an activity notification string.

    Example:
        notification_text("Alice", "uploaded", 3, "file")
        # "Alice uploaded 3 files."
        notification_text("Bob", "deleted", 1, "comment")
        # "Bob deleted 1 comment."
    """
    item_form = pluralize(item_noun, count)
    return f"{actor} {action} {count} {item_form}."


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

if __name__ == "__main__":
    print("=== Pluralization ===")
    for word in ["dog", "mouse", "child", "cactus", "criterion", "schema"]:
        print(f"  {word:12s}{pluralize(word)}")

    print("\n=== Singular detection ===")
    for word in ["dogs", "mice", "children", "dog", "apple"]:
        print(f"  {word:10s} → singular: {singular(word):10s} is_plural: {is_plural(word)}")

    print("\n=== Articles ===")
    for word in ["apple", "banana", "hour", "unicorn", "eulogy", "honest"]:
        print(f"  {with_article(word)}")

    print("\n=== Number to words ===")
    for n in [0, 1, 13, 42, 100, 1001, 1_000_000]:
        print(f"  {n:>10}{number_to_words(n)}")

    print("\n=== Ordinals ===")
    for n in [1, 2, 3, 11, 12, 21, 42]:
        print(f"  {n:3d}{ordinal_str(n):6s}  words: {ordinal_str(n, as_words=True)}")

    print("\n=== count_phrase ===")
    for n in [0, 1, 2, 5]:
        print(f"  {n} file → {count_phrase(n, 'file')}")
    print(f"  42 items (words) → {count_phrase(42, 'item', as_words=True)}")

    print("\n=== join_list ===")
    print(f"  0 items: {join_list([])!r}")
    print(f"  1 item:  {join_list(['Alice'])}")
    print(f"  2 items: {join_list(['Alice', 'Bob'])}")
    print(f"  3 items: {join_list(['Alice', 'Bob', 'Carol'])}")
    print(f"  3 (or):  {join_list(['cats', 'dogs', 'fish'], conjunction='or')}")

    print("\n=== UI helpers ===")
    for n in [0, 1, 3, 99]:
        print(f"  badge: {badge_label(n, 'notification')}")

    print("\n=== Notification texts ===")
    print(notification_text("Alice", "uploaded", 3, "file"))
    print(notification_text("Bob",   "deleted",  1, "comment"))
    print(summary_sentence(["a","b"], "returned", "record"))

For the num2words alternative — num2words converts numbers to words in many languages (English, Spanish, French, German, etc.) and supports currencies and years; inflect focuses exclusively on English grammar with pluralization, articles, verb agreement, and ordinals — use num2words when you need multilingual number-to-words conversion, inflect when you need the full English grammar toolkit including plurals, a/an, verb forms, and list joining. For the humanize alternative — humanize formats numbers and dates for human readability (humanize.naturalday(), humanize.filesize()); inflect handles English grammatical inflection (pluralization, articles, verb agreement) and ordinals — use humanize for date/time/size display formatting, inflect for dynamic text generation where grammatical correctness ("1 file" vs "3 files") is required. The Claude Skills 360 bundle includes inflect skill sets covering pluralize()/pluralize_verb()/singular()/is_plural(), with_article()/article_only(), number_to_words()/ordinal_str()/count_phrase(), join_list()/join_nouns(), present_participle()/subject_verb(), badge_label()/summary_sentence()/notification_text() UI helpers. Start with the free tier to try English grammar inflection and dynamic text generation 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