Skip to main content

A Python CLI to inspect, validate, and manage license and copyright headers.

Project description

TopMark

PyPI version Documentation Status Downloads GitHub release

TopMark is a command-line tool to inspect, validate, and manage file headers in diverse codebases. It helps maintain consistent header metadata across projects by supporting per-file-type header formats, customizable fields, inclusion/exclusion rules, and dry-run safety.

📚 Documentation

Full documentation is available on Read the Docs: https://topmark.readthedocs.io

This README is the canonical, complete introduction for GitHub/PyPI. The docs site provides a concise landing page and deep links into topics (install, usage, CI, API, etc.).

✨ Features

  • File header detection, insertion, and replacement
  • Supports multiple file types (Python, Makefile, Markdown, .env, ...)
  • Configurable comment styles and header fields
  • Inclusion and exclusion logic (via CLI, globs, stdin, or config)
  • Dry-run by default; safe for CI/CD integration
  • Configuration via pyproject.toml or topmark.toml
  • Shell completion for enum-based options
  • Colorized CLI output (via yachalk)
  • Python ≥3.10
  • Integrated pre-commit hooks for automated checks
  • Formatting and linting support via Makefile targets
  • CI-friendly design for safe automated use
  • Strict static typing with mypy and Pyright, using PEP 604 union syntax
  • Google-style docstrings without redundant type declarations
  • Full header removal (topmark strip)
  • Preserves original newline style (LF/CRLF/CR) and BOM
  • Idempotent updates (re-running does not change already-correct files)
  • Structured diagnostics with severity levels (info, warning, error) and aggregate counts

🚀 Installation

git clone https://github.com/shutterfreak/topmark.git
cd topmark
make setup  # creates virtualenv, installs dependencies and tools

Or install into an existing virtualenv:

pip install -e .

Or install the latest release from PyPI:

pip install topmark

⚙️ Usage

Note: In dry-run mode, TopMark shows summaries ending with - previewed. When run with --apply, summaries end with terminal statuses such as - inserted, - replaced, or - removed.

topmark [SUBCOMMAND] [OPTIONS] [PATHS]...

The check and strip commands performs a dry‑run by default and will only apply changes when --apply is provided.

Logging verbosity is controlled globally:

CLI verbosity has two layers:

  • Program output (user-facing):
    • -v, --verbose: Show more detail, including per-line diagnostics in summaries.
    • -q, --quiet: Suppress most output (overrides -v).
  • Internal logging (developer/machine):
    • Also mapped by -v/-q, controls log level (DEBUG / INFO / WARNING / ERROR).

All other options are specific to individual subcommands.


Subcommands

Command Description
check Add / Update TopMark headers in files
dump-config Show the resolved configuration in TOML format
filetypes List supported file types and their comment styles
processors List registered header processors and file types
strip Remove TopMark headers from files (destructive)
version Print TopMark version
show-defaults Show default config (without merging)
init-config Output a starter configuration file

Examples

# Check Python files in the src/ directory
topmark check --file-type python src/

# Use exclusion patterns, and compute relative paths from src
topmark check --file-type python --exclude .venv --relative-to src src/

# Add one verbosity level to topmark, use exclusion patterns from .gitignore
topmark -v check --file-type python --exclude-from .gitignore src/

# Read a list of files from STDIN, generate summary
find . -name "*.py" | topmark check --file-type python --files-from -  --summary

# Process all files that are either staged, or untracked but not ignored in a Git repo (needs dedulication with `sort -u`)
git ls-files -c -o --exclude-standard | sort -u | topmark check --files-from - --apply

# Read a single file's *content* from STDIN and render the resultng unified diff
cat README.md | topmark check - --stdin-filename README.md --diff

# Read a single file's *content* from STDIN and print the updated content to stdout
cat README.md | topmark check - --stdin-filename README.md --apply

# Dump the merged configuration (after loading all applicable config layers)
topmark dump-config --file-type python --exclude .venv --exclude-from .gitignore

# Display the default configuration without any merging
topmark show-defaults

# Output a starter configuration to stdout
topmark init-config

# Show TopMark version in JSON format
topmark version --format json

# Apply changes to files in-place
topmark check --apply src/

# Remove headers from files (dry-run)
topmark strip src/

# Remove headers from files and apply changes
topmark strip --apply src/

# CI-friendly summary: only show issues; ignore unsupported types
topmark check --skip-compliant --skip-unsupported src/

# Apply fixes, don't report unsupported files; default output is terse (pre-commit friendly)
topmark check --apply --skip-unsupported

# Show supported file types in MarkDown format, providing detailed output:
topmark filetypes --format markdown --long

# Show registered header processors (brief)
topmark processors

# Detailed Markdown listing of processors and their file types
topmark processors --format markdown --long

🔌 Public API (stable)

TopMark exposes a small, stable Python API for integrations. Import from topmark.api for core operations, and use the registry facade for read-only discovery.

Quickstart

from pathlib import Path
from topmark import api

# Check (dry-run by default)
result = api.check([Path("src")])
print(result.summary)           # {"unchanged": N, "error": M, ...}
print(result.had_errors)        # True/False

# Apply changes explicitly
applied = api.check([Path("src")], apply=True)

# Remove headers
stripped = api.strip([Path("src")], apply=False)

Registry facade (read-only)

from topmark.registry import Registry

fts = Registry.filetypes()      # Mapping[str, FileType]
procs = Registry.processors()   # Mapping[str, HeaderProcessor]
for b in Registry.bindings():   # (filetype, optional processor)
    print(b.filetype.name, bool(b.processor))

Note: Registry is not re-exported from topmark.api; import it from topmark.registry.

Version helper

from topmark import api
print(api.version())  # e.g. "1.2.3"

Stability

  • topmark.api and the Registry facade are covered by semantic versioning.
  • Low-level registries (FileTypeRegistry, HeaderProcessorRegistry) remain available for plugins/tests but are advanced and may change between minor versions.

Adding & updating headers

Use the topmark check command to insert or update headers. It’s dry‑run by default; add --apply to write changes. Placement follows file‑type policy (shebang/encoding for Python, XML declaration for XML/HTML, etc.). Newline style and BOM are preserved; runs are idempotent.

Quick examples

# Preview (exit code 2 when changes are pending)
topmark check src/

# Apply in place
topmark check --apply src/

For full details, options, examples, and exit codes, see the dedicated guide: Adding & updating headers with topmark

Removing headers with strip

Use topmark strip to remove the entire TopMark header block. The command is dry-run by default; add --apply to write changes. It preserves newline style and BOM, and keeps XML declarations and Markdown code fences intact.

Quick examples

# Preview (exit code 2 when removals are pending)
topmark strip src/

# Apply in place
topmark strip --apply src/

For full details, options, examples, and exit codes, see the dedicated guide: Removing headers with topmark strip

Dumping the merged configuration

Use topmark dump-config to print the effective configuration (defaults → discovered config → --config files → CLI flags) as TOML. This command is file‑agnostic: positional paths and --files-from are ignored; filter flags (--include/--exclude, --include-from/--exclude-from) are honored.

# Dump merged configuration
topmark dump-config

# Include/exclude filters still apply
topmark dump-config --exclude .venv --exclude-from .gitignore

# Read patterns from STDIN
printf "*.py\n" | topmark dump-config --include-from -

For details and notes, see: Dumping the merged configuration with dump-config

Listing supported file types

Use topmark filetypes to see the identifiers you can pass to --file-type and the associated comment styles TopMark will use when rendering headers.

# Show available file type identifiers
topmark filetypes

# Then restrict processing to one or more types
topmark check --file-type python src/
topmark check --file-type markdown --file-type env docs/ config/

For details, see: Listing supported file types with filetypes

📐 Header placement rules

TopMark is comment-aware and places the header block according to the file type and its policy.

The complete header placement rules are documented in the usage guide:

🧩 Supported file types

See the full list and resolver behavior in the dedicated guide:

🪝 Pre-commit integration

TopMark ships with pre-commit hooks to validate or update file headers.

  • topmark-check — runs automatically at pre-commit / pre-push, fails if headers need changes.
  • topmark-apply — manual only; applies fixes and may modify files.

For configuration examples, hook policies, and troubleshooting, see the dedicated guide:

🛠 Configuration

You can specify one or more --config files, or rely on local fallback resolution:

  • topmark.toml in the working directory
  • pyproject.toml using the [tool.topmark] table

TopMark reads configuration from one or more TOML files. Configuration is merged from:

  1. Built-in defaults
  2. Local project config (if not disabled via --no-config)
  3. Additional files via --config
  4. CLI overrides

Example configuration snippet (topmark.toml):

[fields]
project = "TopMark"
license = "MIT"
copyright = "(c) 2025 Olivier Biot"

[header]
fields = [ "file", "file_relpath", "project", "license", "copyright",]

[formatting]
align_fields = true
raw_header = false

[files]
file_types = [ "python", "markdown", "env" ]
include = []
include_from = []
exclude = []
exclude_from = [ ".gitignore" ]
relative_to = "."

Notes

  • formatting.align_fields = true vertically aligns the field names within the rendered header lines for readability.
  • File-type specific behavior (shebang handling, XML prolog, blank line policies) is driven by internal FileTypeHeaderPolicy defaults and can be extended to new types.

The EnumParam class enables shell completion for enum-based CLI options.

🧪 Development Setup

For development setup and contribution guidelines, see CONTRIBUTING.md.

To verify compatibility across supported Python versions (3.10–3.13), use tox to run tests and type checks in each environment.

📄 License

MIT License © 2025 Olivier Biot

LICENSE (MIT)

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

topmark-0.6.0.tar.gz (127.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

topmark-0.6.0-py3-none-any.whl (160.8 kB view details)

Uploaded Python 3

File details

Details for the file topmark-0.6.0.tar.gz.

File metadata

  • Download URL: topmark-0.6.0.tar.gz
  • Upload date:
  • Size: 127.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for topmark-0.6.0.tar.gz
Algorithm Hash digest
SHA256 de9e00bbad8018d1a4f9f4bb1979506e83a4ff6831e74e64773808f9f852cb5a
MD5 30c74db1bf111e7f5170b3a1d5e9b2a0
BLAKE2b-256 9c3329d35e6ef718d03523c21bf6c1c05508449aa82d6a700c6756673e57c11d

See more details on using hashes here.

Provenance

The following attestation bundles were made for topmark-0.6.0.tar.gz:

Publisher: release.yml on shutterfreak/topmark

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file topmark-0.6.0-py3-none-any.whl.

File metadata

  • Download URL: topmark-0.6.0-py3-none-any.whl
  • Upload date:
  • Size: 160.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for topmark-0.6.0-py3-none-any.whl
Algorithm Hash digest
SHA256 23b224782cf72f821717a9728464216d8f1a6802e724b1920038ad1a0585d5e3
MD5 276b8fda9eab261eac56b1976f967840
BLAKE2b-256 ed3fd291c5fb339015364b1c41f5b46f5a5e69c7e7ded1c4140c920d50b5e638

See more details on using hashes here.

Provenance

The following attestation bundles were made for topmark-0.6.0-py3-none-any.whl:

Publisher: release.yml on shutterfreak/topmark

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page