A tool to inspect, validate, and manage file headers in diverse codebases
Project description
TopMark
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.
✨ 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.tomlortopmark.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
- Selective removal
- Preserves original newline style (LF/CRLF/CR) and BOM
- Idempotent updates (re-running does not change already-correct files)
🚀 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
topmark [OPTIONS] [PATHS]...
TopMark uses Click 8.2 and supports shell completions. The base command performs a dry‑run check
by default and applies changes when --apply is provided.
Logging verbosity is controlled globally:
-v,--verbose: Increase verbosity (can be repeated)-q,--quiet: Suppress most output (overrides verbosity)
All other options, such as --stdin, --file-type, and path filters, are specific to individual
subcommands like check or apply.
Examples
# Check Python files in the src/ directory
topmark --file-type python src/
# Use exclusion patterns, and compute relative paths from src
topmark --file-type python --exclude .venv --relative-to src src/
# Add one verbosity level to topmark, use exclusion patterns from .gitignore
topmark -v --file-type python --exclude-from .gitignore src/
# Read files from stdin, generate summary
find . -name "*.py" | topmark --file-type python --summary --stdin
# Process all files in a Git repo
git ls-files -c -o --exclude-standard | sort -u | topmark --stdin --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
topmark version
# Apply changes to files in-place
topmark --apply src/
📐 Header placement rules
TopMark is comment-aware and places the header block according to the file type and its policy.
Pound-style files (e.g., Python, Shell, Ruby, Makefile, YAML, TOML, Dockerfile)
Rules:
- If a shebang is present (e.g.,
#!/usr/bin/env python3), place the header after the shebang and ensure exactly one blank line in-between. - If a coding/encoding line follows the shebang (PEP 263 style), place the header after shebang and encoding line.
- Otherwise, place the header at the top of the file.
- Ensure one trailing blank line after the header block when the next line is not already blank.
Example (Python):
#!/usr/bin/env python3
# topmark:header:start
#
# file :
# file_relpath :
#
# topmark:header:end
print("hello")
XML-style files (XML, HTML/XHTML, SVG, Vue/Svelte/Markdown via HTML comments)
Rules:
- If present, place the header after the XML declaration and DOCTYPE, with one blank line before the header block.
- Otherwise, place the header at the top of the file.
- The header uses the file’s native comment syntax; for XML/HTML it’s a comment block wrapper:
<!--
topmark:header:start
file :
file_relpath :
topmark:header:end
-->
<html>...</html>
General guarantees
- Newline preservation: The inserted header uses the same newline style as the file (LF/CRLF/CR).
- BOM preservation: If a UTF‑8 BOM is present, it is preserved.
- Idempotency: Re-running TopMark on a file with a correct header makes no changes.
Common Options
The following options can be used with most commands.
| Option | Description |
|---|---|
--file-type |
Specify file type (python, markdown, …) |
--relative-to |
Set base path for relative header fields |
--include |
Include paths or glob patterns |
--include-from |
Read inclusion patterns from file |
--exclude |
Exclude paths or glob patterns |
--exclude-from |
Read exclusion patterns from file |
--stdin |
Read file paths from stdin |
--apply |
Actually modify files instead of dry-run |
-v, --verbose |
Increase verbosity (can be repeated) |
-q, --quiet |
Suppress most output |
Subcommands
| Command | Description |
|---|---|
dump-config |
Show the resolved configuration in TOML format |
filetypes |
List supported file types and their comment styles |
version |
Print TopMark version |
show-defaults |
Show default config (without merging) |
init-config |
Output a starter configuration file |
🧩 Supported file types
| Processor | File types (examples) |
|---|---|
| PoundHeaderProcessor | python, shell, ruby, r, julia, perl, makefile, dockerfile, yaml, toml, env |
| XmlHeaderProcessor | xml, xhtml, html, svg, xsl/xslt, vue, svelte, markdown |
🛠 Configuration
You can specify one or more --config files, or rely on local fallback resolution:
topmark.tomlin the working directorypyproject.tomlusing the[tool.topmark]table
TopMark reads configuration from one or more TOML files. Configuration is merged from:
- Built-in defaults
- Local project config (if not disabled via
--no-config) - Additional files via
--config - 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 = truevertically 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
Markdown formatting is handled by mdformat with the mdformat-tables plugin, and configuration is
read from pyproject.toml.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file topmark-0.1.0.tar.gz.
File metadata
- Download URL: topmark-0.1.0.tar.gz
- Upload date:
- Size: 70.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
357696c127f10371a7a02e0fc39af5a882d5092b19b1ddbb7015803719a16af2
|
|
| MD5 |
bc0218c273a99a532476779b3c911e69
|
|
| BLAKE2b-256 |
b9f43fc76602e6474e48ee392b4067c9f41198062a989d9475deabb237d0f5a0
|
File details
Details for the file topmark-0.1.0-py3-none-any.whl.
File metadata
- Download URL: topmark-0.1.0-py3-none-any.whl
- Upload date:
- Size: 86.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
45d53f0d624bd7773e36328a2615742df72ad20a032453dac16300725576514c
|
|
| MD5 |
9054281871ab4d361ad3771e23907410
|
|
| BLAKE2b-256 |
cc55ce10c5a165f4433ceddedbd4eb54f01e4ce5ad735ed3eae5b255855728f3
|