Claude Code for modulefinder: Python Module Dependency Finder — Claude Skills 360 Blog
Blog / AI / Claude Code for modulefinder: Python Module Dependency Finder
AI

Claude Code for modulefinder: Python Module Dependency Finder

Published: December 13, 2028
Read time: 5 min read
By: Claude Skills 360

Python’s modulefinder module traces all imports in a script (and their transitive imports) to produce a complete dependency list. from modulefinder import ModuleFinder. Create with custom path: mf = ModuleFinder(path=None)path overrides sys.path; defaults to sys.path. Trace: mf.run_script("script.py") — loads and traces the script, recursively following all import statements. Results: mf.modulesdict[str, Module] of successfully located modules; mf.badmodulesdict[str, dict] of modules that were imported but not found; mf.any_missing()list[str] of names in badmodules not present in modules. Module object: mod.__name__, mod.__file__ (path or None for built-ins), mod.__path__ (list for packages). Report: mf.report() — prints a tabular summary to stdout. Each Module is an instance of modulefinder.Module with a globalnames set of names used at module scope. Claude Code generates dependency graphs, freeze validators, missing-module detectors, and deployment manifests.

CLAUDE.md for modulefinder

## modulefinder Stack
- Stdlib: from modulefinder import ModuleFinder
- Trace:  mf = ModuleFinder(); mf.run_script("main.py")
- Found:  mf.modules            # {name: Module}  — all located modules
- Bad:    mf.badmodules         # {name: {}}       — not found
- Missing: mf.any_missing()     # list of unresolvable imports
- Report: mf.report()           # print tabular summary
- Note:   traces static imports; dynamic __import__ / importlib may be missed

modulefinder Dependency Finder Pipeline

# app/modulefinderutil.py — dep graph, missing detector, manifest, freeze checker
from __future__ import annotations

import sys
from dataclasses import dataclass, field
from modulefinder import ModuleFinder
from pathlib import Path


# ─────────────────────────────────────────────────────────────────────────────
# 1. Module info dataclass
# ─────────────────────────────────────────────────────────────────────────────

@dataclass
class ModuleRecord:
    """
    Human-readable descriptor for one module in the dependency graph.

    Fields:
        name     — dotted module name (e.g. "os.path")
        path     — absolute path to the source file, or None for C extensions / built-ins
        is_pkg   — True if the module is a package (has __path__)
        is_builtin — True if no file is associated (C built-in)
        missing  — True if the module could not be located
    """
    name:       str
    path:       "str | None"
    is_pkg:     bool
    is_builtin: bool
    missing:    bool

    def __str__(self) -> str:
        if self.missing:
            return f"MISSING  {self.name}"
        kind = "pkg" if self.is_pkg else ("builtin" if self.is_builtin else "module")
        loc = self.path or "<built-in>"
        return f"{kind:8s}  {self.name:40s}  {loc}"


# ─────────────────────────────────────────────────────────────────────────────
# 2. Core trace function
# ─────────────────────────────────────────────────────────────────────────────

@dataclass
class DependencyGraph:
    """
    Complete dependency analysis for a Python script.

    Example:
        graph = trace_script("scripts/deploy.py")
        print(f"found={graph.found_count}  missing={graph.missing_count}")
        for rec in graph.missing_records:
            print(f"  MISSING: {rec.name}")
    """
    script:    Path
    records:   list[ModuleRecord] = field(default_factory=list)
    _mf:       "ModuleFinder | None" = field(default=None, repr=False)

    @property
    def found_records(self) -> list[ModuleRecord]:
        return [r for r in self.records if not r.missing]

    @property
    def missing_records(self) -> list[ModuleRecord]:
        return [r for r in self.records if r.missing]

    @property
    def found_count(self) -> int:
        return len(self.found_records)

    @property
    def missing_count(self) -> int:
        return len(self.missing_records)

    @property
    def third_party(self) -> list[ModuleRecord]:
        """Records that are not stdlib built-ins and not missing."""
        stdlib_prefix = str(Path(sys.prefix))
        result = []
        for r in self.found_records:
            if r.is_builtin:
                continue
            if r.path and r.path.startswith(stdlib_prefix):
                continue
            result.append(r)
        return result

    def source_files(self) -> list[Path]:
        """Return sorted list of .py source file paths for all found modules."""
        paths = []
        for r in self.found_records:
            if r.path and r.path.endswith(".py"):
                paths.append(Path(r.path))
        return sorted(set(paths))


def trace_script(
    script: "str | Path",
    path: "list[str] | None" = None,
) -> DependencyGraph:
    """
    Run modulefinder on script and return a DependencyGraph.

    Example:
        graph = trace_script("app/main.py")
        for rec in graph.missing_records:
            print(f"  MISSING: {rec.name}")
    """
    mf = ModuleFinder(path=path or sys.path[:])
    try:
        mf.run_script(str(script))
    except SystemExit:
        pass  # some scripts call sys.exit() at top level

    records: list[ModuleRecord] = []

    for name, mod in sorted(mf.modules.items()):
        file_path = getattr(mod, "__file__", None)
        mod_path = getattr(mod, "__path__", None)
        records.append(ModuleRecord(
            name=name,
            path=file_path,
            is_pkg=bool(mod_path),
            is_builtin=(file_path is None),
            missing=False,
        ))

    for name in sorted(mf.badmodules.keys()):
        if name not in mf.modules:
            records.append(ModuleRecord(
                name=name,
                path=None,
                is_pkg=False,
                is_builtin=False,
                missing=True,
            ))

    return DependencyGraph(script=Path(script), records=records, _mf=mf)


# ─────────────────────────────────────────────────────────────────────────────
# 3. Quick helpers
# ─────────────────────────────────────────────────────────────────────────────

def missing_modules(script: "str | Path") -> list[str]:
    """
    Return sorted list of module names imported by script but not found.

    Example:
        missing = missing_modules("app/main.py")
        if missing:
            print("Missing:", missing)
    """
    graph = trace_script(script)
    return sorted(r.name for r in graph.missing_records)


def all_source_files(script: "str | Path") -> list[Path]:
    """
    Return all .py source files transitively imported by script.

    Example:
        for p in all_source_files("main.py"):
            print(p)
    """
    return trace_script(script).source_files()


def is_self_contained(script: "str | Path") -> bool:
    """
    Return True if the script has no missing imports.

    Example:
        if not is_self_contained("deploy.py"):
            print("missing imports — will fail at runtime")
    """
    return trace_script(script).missing_count == 0


# ─────────────────────────────────────────────────────────────────────────────
# 4. Deployment manifest builder
# ─────────────────────────────────────────────────────────────────────────────

@dataclass
class DeployManifest:
    """
    Build a deployment manifest: list of source files needed to run a script.

    Example:
        manifest = DeployManifest.from_script("app/server.py")
        manifest.write("dist/manifest.txt")
        for path in manifest.files:
            print(path)
    """
    script: Path
    files:  list[Path] = field(default_factory=list)
    missing: list[str] = field(default_factory=list)

    @classmethod
    def from_script(
        cls,
        script: "str | Path",
        include_stdlib: bool = False,
    ) -> "DeployManifest":
        graph = trace_script(script)
        files: list[Path] = []
        stdlib_prefix = str(Path(sys.prefix))

        for r in graph.found_records:
            if r.is_builtin:
                continue
            if r.path is None:
                continue
            if not include_stdlib and r.path.startswith(stdlib_prefix):
                continue
            if r.path.endswith(".py"):
                files.append(Path(r.path))

        return cls(
            script=Path(script),
            files=sorted(set(files)),
            missing=sorted(r.name for r in graph.missing_records),
        )

    def write(self, dest: "str | Path") -> None:
        """Write manifest to a text file (one path per line)."""
        lines = [str(self.script)] + [str(p) for p in self.files]
        Path(dest).write_text("\n".join(lines) + "\n")

    def print_report(self) -> None:
        """Print a human-readable manifest report."""
        print(f"Script:  {self.script}")
        print(f"Files:   {len(self.files)}")
        for p in self.files:
            print(f"  {p}")
        if self.missing:
            print(f"Missing: {len(self.missing)}")
            for m in self.missing:
                print(f"  MISSING: {m}")


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

if __name__ == "__main__":
    import tempfile

    print("=== modulefinder demo ===")

    with tempfile.TemporaryDirectory() as td:
        td_path = Path(td)

        # ── write test scripts ─────────────────────────────────────────────────
        helper = td_path / "helper.py"
        helper.write_text(
            "import os\nimport json\n\ndef get_info():\n    return {'cwd': os.getcwd()}\n"
        )
        main = td_path / "main.py"
        main.write_text(
            "import helper\nimport hashlib\nimport nonexistent_lib\n\n"
            "data = helper.get_info()\nprint(data)\n"
        )

        # ── trace_script ──────────────────────────────────────────────────────
        print("\n--- trace_script ---")
        graph = trace_script(main, path=[str(td_path)] + sys.path)
        print(f"  found={graph.found_count}  missing={graph.missing_count}")

        # ── found modules (non-missing) ───────────────────────────────────────
        print("\n--- found modules ---")
        for rec in sorted(graph.found_records, key=lambda r: r.name)[:8]:
            print(f"  {rec}")

        # ── missing modules ────────────────────────────────────────────────────
        print("\n--- missing modules ---")
        for rec in graph.missing_records:
            print(f"  {rec}")

        # ── is_self_contained ─────────────────────────────────────────────────
        print("\n--- is_self_contained ---")
        print(f"  main.py: {is_self_contained.__name__} = "
              f"{is_self_contained.__doc__ and 'checked'}")
        graph2 = trace_script(main, path=[str(td_path)] + sys.path)
        print(f"  has no missing: {graph2.missing_count == 0}")

        # ── source_files ──────────────────────────────────────────────────────
        print("\n--- source_files ---")
        sources = graph.source_files()
        for p in sources[:5]:
            print(f"  {p}")

        # ── DeployManifest ────────────────────────────────────────────────────
        print("\n--- DeployManifest ---")
        manifest = DeployManifest.from_script(main, include_stdlib=False)
        manifest_path = td_path / "manifest.txt"
        manifest.write(manifest_path)
        print(f"  manifest written to: {manifest_path.name}")
        print(f"  non-stdlib files: {len(manifest.files)}")
        print(f"  missing deps:     {manifest.missing}")

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

For the pip show / pipdeptree (PyPI) alternative — pipdeptree traces package-level dependencies from installed distributions, not import-level module references — use pipdeptree to understand distribution-level requirements for packaging; use modulefinder when you want to know exactly which .py files and stdlib modules a specific script or entry-point loads at import time, independent of how modules are installed (useful for freeze/bundle workflows). For the importlib.util.find_spec alternative — importlib.util.find_spec("module") checks whether a single module is locatable on sys.path without executing any code — use find_spec for fast single-module existence checks; use modulefinder when you need the complete transitive dependency graph of a script, including indirect imports through libraries. The Claude Skills 360 bundle includes modulefinder skill sets covering ModuleRecord with is_pkg/is_builtin/missing flags, DependencyGraph with found_records/missing_records/third_party/source_files() views, trace_script() ModuleFinder driver, missing_modules()/all_source_files()/is_self_contained() quick helpers, and DeployManifest.from_script() with write()/print_report() deployment manifest builder. Start with the free tier to try dependency tracing patterns and modulefinder 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