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.).

📝 Example headers

TopMark inserts headers that are tailored to the comment style and conventions of each file type (line comments like #///, and block comments like /* … */). Here are examples of how TopMark headers appear in different file formats:

#!/bin/bash

# topmark:header:start
#
#   project   : TopMark
#   file      : script.sh
#   license   : MIT
#   copyright : (c) 2025 Olivier Biot

# topmark:header:end

echo "Hello, World!"
<?xml version="1.0" encoding="UTF-8"?>
<!--
topmark:header:start

  project   : TopMark
  file      : config.xml
  license   : MIT
  copyright : (c) 2025 Olivier Biot

topmark:header:end
-->

<configuration>
    <!-- XML content here -->
</configuration>
// topmark:header:start
//
//   project   : TopMark
//   file      : app.js
//   license   : MIT
//   copyright : (c) 2025 Olivier Biot
//
// topmark:header:end

console.log("Hello, World!");
/*
 * topmark:header:start
 *
 *   project   : TopMark
 *   file      : styles.css
 *   license   : MIT
 *   copyright : (c) 2025 Olivier Biot
 *
 * topmark:header:end
 */

body { margin: 0; }

✨ 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

# Output TopMark version (PEP 440) in JSON format
topmark version --format json

# Output TopMark version (SemVer) to stdout
topmark version --semver

# 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.8.1.tar.gz (139.8 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.8.1-py3-none-any.whl (180.7 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for topmark-0.8.1.tar.gz
Algorithm Hash digest
SHA256 85035bae7f5d115efd1d57082dd5168ab1e55042d98df7f8e803cfa314716983
MD5 d5636374f5c9df9ae677b12f78c80388
BLAKE2b-256 cd65fd2c7490cdfbbc8d832390bc3bc0952016d5e7002f256fe07f815e90d397

See more details on using hashes here.

Provenance

The following attestation bundles were made for topmark-0.8.1.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.8.1-py3-none-any.whl.

File metadata

  • Download URL: topmark-0.8.1-py3-none-any.whl
  • Upload date:
  • Size: 180.7 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.8.1-py3-none-any.whl
Algorithm Hash digest
SHA256 ffe471f4997b284958761ce9871c59e69018114ab1beef727e5f975b2e7b438b
MD5 1450686458b336e8fef5a1bdc33ca0a1
BLAKE2b-256 2fa75ad49ee59016ff8419f825a668a126e287411df8926e2db7b6e371062b12

See more details on using hashes here.

Provenance

The following attestation bundles were made for topmark-0.8.1-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