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, insert, validate, and manage file headers in diverse codebases.
It maintains consistent metadata across files by supporting multiple comment styles, configuration formats, and dry-run safety.


📚 Documentation

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

This README provides an overview. See the docs for deeper topics (install, usage, API, CI/CD, etc.).


🧩 Features

  • Detect, insert, and replace file headers across multiple file types
  • Comment-aware (line and block styles)
  • Configurable header fields and alignment
  • Dry-run by default for safety
  • Policy-based control over when headers may be inserted, updated, or added to empty files
  • Layered configuration via:
    • pyproject.toml ([tool.topmark])
    • topmark.toml
    • CLI overrides and --config
  • Fine-grained include/exclude rules
  • Selective application via file patterns or stdin
  • Strict static typing (PEP 604 unions, Pyright)
  • Works well with pre-commit, CI, and Git hooks
  • Preserves newline style (LF/CRLF/CR) and BOM
  • Idempotent: re-running on already-compliant files makes no changes
  • Configurable comment alignment and raw/pretty formatting

🧱 Example headers

TopMark adapts headers to the comment syntax of each file type.

Bash / Shell

#!/bin/bash

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

echo "Hello, World!"

XML

<?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>

JavaScript

// topmark:header:start
//
//   project   : TopMark
//   file      : app.js
//   license   : MIT
//   copyright : (c) 2025 Olivier Biot
//
// topmark:header:end

console.log("Hello, World!");

CSS

/*
 * topmark:header:start
 *
 *   project   : TopMark
 *   file      : styles.css
 *   license   : MIT
 *   copyright : (c) 2025 Olivier Biot
 *
 * topmark:header:end
 */

body { margin: 0; }

⚙️ Installation

From PyPI

pip install topmark

From source (development setup)

git clone https://github.com/shutterfreak/topmark.git
cd topmark
make venv
make venv-sync-dev

Run checks to confirm setup:

make verify
make test

Verify CLI

topmark version
topmark --help

🚀 Usage

topmark [COMMAND] [OPTIONS] [PATHS]...

Subcommands

Command Description
check Add or update TopMark headers
strip Remove TopMark headers
dump-config Show resolved configuration (merged TOML)
filetypes List supported file types
processors List header processors and mappings
show-defaults Show built-in defaults without merging
init-config Output a starter configuration
version Print version (PEP 440 or SemVer)

Examples

# Preview (dry-run)
topmark check src/

# Apply in place
topmark check --apply src/

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

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

# Show supported file types in Markdown format
topmark filetypes --output-format markdown --long

# List processors and associated file types
topmark processors --output-format markdown --long

TopMark preserves line endings, shebangs, BOMs, and indentation rules for each file type.


🧠 Configuration & Policy

TopMark supports layered configuration discovery and a flexible policy system controlling insert/update behavior.

Discovery order

  1. Built-in defaults (topmark-default.toml)
  2. User config (~/.config/topmark/topmark.toml or ~/.topmark.toml)
  3. Project config (nearest upward pyproject.toml or topmark.toml)
  4. Explicit --config files (merged in order)
  5. CLI flags and options (highest precedence)

Example topmark.toml

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

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

[tool.topmark.policy]
add_only = false
update_only = false
allow_header_in_empty_files = false

[tool.topmark.policy_by_type."python"]
allow_header_in_empty_files = true

[formatting]
align_fields = true
raw_header = false

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

Policy semantics

Setting Meaning
add_only = true Only insert headers into files without one; skip updating existing ones
update_only = true Only update existing headers; skip inserting new ones
allow_header_in_empty_files Allow adding headers to empty files (useful for e.g. __init__.py)

Per-type overrides under [tool.topmark.policy_by_type."filetype"] can adjust specific behavior.

These policy options apply equally to the CLI and the public API.

See docs/configuration/discovery.md for more detail on config precedence and path semantics.


🪝 Pre-commit Integration

TopMark includes pre-commit hooks for automated header management.

Hook ID Purpose
topmark-check Validate headers (non-destructive)
topmark-apply Apply header updates (manual)

Install hooks:

pre-commit install
pre-commit run --all-files

Manual header fix (safe interactive mode):

pre-commit run topmark-apply --hook-stage manual --all-files

🔒 Public API

The public API now an optional policy argument (global or per-type) that integrates with the same resolution mechanism used by the CLI.

Example

from pathlib import Path
from topmark import api
from topmark.api.public_types import Policy

# Dry-run header checks
result = api.check(
    [Path("src")],
    apply=True,
    policy=Policy(add_only=True)
)

print(result.summary)
print(result.had_errors)

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

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

For programmatic discovery:

from topmark.registry import Registry

for ft, proc in Registry.bindings():
    print(ft.name, bool(proc))

📦 Packaging & Versioning

TopMark follows Semantic Versioning (SemVer).

Change Type Version Impact
fix: Patch
feat: Minor
feat!: / BREAKING CHANGE: Major

Build and check distributions:

python -m build
python -m twine check dist/*

Upload:

python -m twine upload dist/*

Tags are released via CI/CD.


🧪 Development

To test across all supported Python versions:

make test              # tox default envs
tox -m api-check       # API stability across all Python versions

For faster iteration:

make pytest            # run tests in current interpreter
make lint              # static linting
make verify            # formatting, linting, docs, links

📄 License

MIT License © 2025 Olivier Biot

See LICENSE


TopMark — consistent headers for consistent projects.

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.11.0.tar.gz (233.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.11.0-py3-none-any.whl (301.2 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: topmark-0.11.0.tar.gz
  • Upload date:
  • Size: 233.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.11.0.tar.gz
Algorithm Hash digest
SHA256 3b3d03cff9f413829263a91b4fa5b1a02929d35b2a4e37ab485f231c1f0e9e69
MD5 685794cb74a600a3104aaaafa30adfac
BLAKE2b-256 d676aff8c6e2bfd973edb5df584454f5d5e3ef82202a280478b82b26c2172abc

See more details on using hashes here.

Provenance

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

File metadata

  • Download URL: topmark-0.11.0-py3-none-any.whl
  • Upload date:
  • Size: 301.2 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.11.0-py3-none-any.whl
Algorithm Hash digest
SHA256 57681773ae2fb3e450db3e3b8598425ea2f0b1c0d06f0832a764688296f214c8
MD5 bde607c1c4b8583d0fe776e58cedc12d
BLAKE2b-256 ef7c73e972cb7543d3fca6050e433b3742c596ea82cb6971b594154632b7abb3

See more details on using hashes here.

Provenance

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