Pre-commit hook to check and auto-add copyright notices with multi-format and regex support
Project description
SNY Copyright Check - Pre-commit Hook
A powerful pre-commit hook to automatically check and add copyright notices to your source files with support for multiple file formats and regex patterns.
Features
โจ Multi-Format Support: Define different copyright formats for different file extensions (.py, .c, .sql, etc.)
๐ Regex Pattern Matching: Use regex patterns in your copyright templates to match year ranges (e.g., 2024, 2024-2026)
๐ง Auto-Fix: Automatically adds missing copyright notices with the current year
๐ Flexible Templates: Section-based template file for easy maintenance
๐ฏ Smart Insertion: Respects shebang lines and file structure
๐ Line Ending Preservation: Automatically detects and preserves CRLF (Windows) or LF (Unix/Linux) line endings
๐ฏ Git Integration: Check only changed files with --changed-only flag
โ Non-Destructive: Existing copyrights are preserved, even with old years - no duplicates created
๐ Git-Aware Year Management: Intelligently manages copyright years based on Git history
- Preserves earliest year from file creation or existing copyright
- Extends year range only when files are modified
- Reduces noise in Git diffs by not updating unchanged files
๐ซ Ignore Files Support: Respect .copyrightignore and .gitignore patterns
- Skip generated files, vendor code, and build artifacts
- Gitignore-style pattern matching
- Flexible ignore rules per project
๐ Hierarchical Copyright Templates: Support different copyrights per directory
- Apply different copyright notices to subdirectories
- Perfect for monorepos and vendor/third-party code
- Child directories override parent templates
Installation
Via pip (Recommended)
Install directly from PyPI:
pip install sny-copyright-checker
As a pre-commit hook
Add the following to your .pre-commit-config.yaml:
repos:
- repo: https://github.com/mu-triv/sny-copyright-checker
rev: v1.0.5 # Use the latest release
hooks:
- id: sny-copyright-checker
args: [--notice=copyright.txt]
Then install the hook:
pre-commit install
From source
git clone https://github.com/mu-triv/sny-copyright-checker.git
cd sny-copyright-checker
pip install -e .
Usage
As a Pre-commit Hook
Once installed, the hook will automatically run when you commit files:
git add my_file.py
git commit -m "Add new feature"
# Hook will check and add copyright notice if missing
Command Line
You can also run the tool directly:
# Check and auto-fix files
sny-copyright-checker file1.py file2.sql file3.c
# Check only (no modifications)
sny-copyright-checker --no-fix file1.py
# Specify custom template file
sny-copyright-checker --notice=my_copyright.txt *.py
# Verbose output
sny-copyright-checker -v file1.py
# Check only changed files in git
sny-copyright-checker --changed-only
# Check changed files compared to main branch
sny-copyright-checker --changed-only --base-ref origin/main
Command Line Options
filenames: Files to check for copyright notices--notice FILENAME: Filename of copyright template (default:copyright.txt). In hierarchical mode, this filename is searched for in the directory tree.--fix: Automatically add missing copyright notices (default: enabled)--no-fix: Only check without modifying files--verbose, -v: Enable verbose output--changed-only: Only check files that have been changed in git (ignores filenames argument)--base-ref REF: Git reference to compare against when using--changed-only(default: HEAD)--no-git-aware: Disable Git-aware year management (default: Git-aware is enabled)--ignore-file PATH: Path to custom ignore file (default: auto-detect.copyrightignore)--no-gitignore: Don't use.gitignorepatterns (default:.gitignoreis used)--hierarchical: Enable hierarchical copyright templates (looks for--noticefile in each directory)
Git-Aware Year Management
By default, the tool uses Git history to intelligently manage copyright years:
- Preserves the earliest year from file creation or existing copyright
- Extends the year range only when files are actually modified
- Reduces unnecessary changes to unchanged files
See GIT_AWARE_YEAR_MANAGEMENT.md for detailed information.
Hierarchical Copyright Templates
Support different copyright notices for different parts of your codebase. Perfect for monorepos, projects with vendor code, or when different teams/components have different licensing.
For detailed documentation, see HIERARCHICAL_TEMPLATES.md.
Quick Start
Enable hierarchical mode and place copyright templates in subdirectories:
sny-copyright-check --hierarchical --notice=copyright.txt src/
Directory structure:
project/
โโโ copyright.txt # Root copyright
โโโ src/
โ โโโ main.py # Uses root copyright
โโโ vendor/
โโโ copyright.txt # Vendor-specific copyright
โโโ lib.py # Uses vendor copyright
Ignore Files Support
The tool respects ignore patterns to skip generated files, vendor code, and build artifacts.
For detailed documentation on ignore patterns, see IGNORE_FILES.md.
Quick Start
Create a .copyrightignore file in your project root:
# Ignore generated files
**/generated/
*.min.js
*.bundle.js
# Ignore vendor/third-party code
node_modules/
vendor/
third_party/
# Ignore build artifacts
dist/
build/
*.pyc
__pycache__/
Using .gitignore
By default, patterns from .gitignore are also respected. To disable this:
sny-copyright-checker --no-gitignore *.py
Pattern Syntax
Supports standard gitignore-style patterns:
*.ext- Match files with extensiondir/- Match entire directory**/pattern- Match in any directorypath/*.js- Match files in specific path# comment- Comments (ignored)
Copyright Template Format
The template file uses a section-based format with regex support and template variables for maximum maintainability.
Using Variables (Recommended)
Define common values once in a [VARIABLES] section and reuse them throughout your template:
[VARIABLES]
SPDX_LICENSE = MIT
COMPANY = Sony Group Corporation
AUTHOR = R&D Center Europe Brussels Laboratory, Sony Group Corporation
YEAR_PATTERN = {regex:\d{4}(-\d{4})?}
[.py, .yaml, .yml]
# SPDX-License-Identifier: {SPDX_LICENSE}
# Copyright {YEAR_PATTERN} {COMPANY}
# Author: {AUTHOR}
# License: For licensing see the License.txt file
[.js, .ts, .go, .rs]
// SPDX-License-Identifier: {SPDX_LICENSE}
// Copyright {YEAR_PATTERN} {COMPANY}
// Author: {AUTHOR}
// License: For licensing see the License.txt file
Benefits:
- โ DRY Principle: Change company name or license in one place
- โ SPDX Support: Easy to add SPDX License Identifiers
- โ Consistency: All file types use the same information
- โ Flexibility: Different projects can have different licenses
Traditional Format (Also Supported)
You can also use the format without variables:
[.py, .yaml, .yml]
# Copyright {regex:\d{4}(-\d{4})?} Sony Group Corporation
# Author: R&D Center Europe Brussels Laboratory, Sony Group Corporation
# License: For licensing see the License.txt file
Template Syntax
- Variables Section:
[VARIABLES]- Define reusable values- Format:
VARIABLE_NAME = value - Use in templates:
{VARIABLE_NAME} - Example:
COMPANY = Sony Group Corporation, then use{COMPANY}
- Format:
- Section Headers:
- Single extension:
[.extension](e.g.,[.py],[.sql]) - Multiple extensions:
[.ext1, .ext2, .ext3](e.g.,[.js, .ts, .go]) - All extensions in a grouped header will use the same copyright format
- Single extension:
- Regex Patterns:
{regex:PATTERN}allows regex matching- Example:
{regex:\d{4}(-\d{4})?}matches2024or2024-2026 - Can be stored in a variable:
YEAR_PATTERN = {regex:\d{4}(-\d{4})?}
- Example:
- Auto-insertion: When adding a copyright, the regex pattern is replaced with the current year
SPDX License Identifiers
The tool fully supports SPDX license identifiers. Simply add them to your template:
[VARIABLES]
SPDX_LICENSE = Apache-2.0 OR MIT
[.py]
# SPDX-License-Identifier: {SPDX_LICENSE}
# Copyright {regex:\d{4}} {COMPANY}
Common SPDX identifiers: MIT, Apache-2.0, GPL-3.0-only, BSD-3-Clause, etc.
Grouping Extensions
To reduce duplication and improve maintainability, group extensions that share the same comment syntax:
- Hash comments:
[.py, .yaml, .yml, .sh]โ#style - C-style line comments:
[.js, .ts, .go, .rs, .java]โ//style - C block comments:
[.c, .h, .cpp]โ/* */style - SQL comments:
[.sql]โ--style - HTML comments:
[.md, .html, .xml]โ<!-- -->style
Supported Regex Patterns
The template includes regex patterns for year matching:
\d{4}: Matches a single year (e.g.,2024)\d{4}-\d{4}: Matches a year range (e.g.,2024-2026)\d{4}(-\d{4})?: Matches either format
Example
Before
#!/usr/bin/env python
def hello():
print("Hello, World!")
After (Auto-fixed)
#!/usr/bin/env python
# Copyright 2026 SNY Group Corporation
# Author: R&D Center Europe Brussels Laboratory, SNY Group Corporation
# License: For licensing see the License.txt file
def hello():
print("Hello, World!")
How It Works
- Template Parsing: Reads and parses the section-based template file
- File Extension Matching: Determines which copyright template to use based on file extension
- Pattern Matching: Uses regex to check if a valid copyright notice exists
- Copyright Detection: If a valid copyright exists (even with an old year like 2025), the file is left unchanged
- Auto-Insertion: If missing and
--fixis enabled, adds the copyright notice with the current year - Smart Positioning: Respects shebang lines and inserts the notice appropriately
- Line Ending Preservation: Automatically detects and preserves the original line ending style (CRLF or LF)
- Git Integration: Optionally checks only files that have been modified in your git repository
File Extensions Support
By default, the included copyright.txt supports:
- Python (
.py) - SQL (
.sql) - C/C++ (
.c,.cpp,.h) - JavaScript/TypeScript (
.js,.ts) - Java (
.java) - Shell scripts (
.sh) - Go (
.go) - Rust (
.rs) - YAML (
.yaml,.yml) - Markdown (
.md)
You can easily add more by editing the copyright.txt file.
Important Behavior
Copyright Preservation
- Existing copyrights are never replaced: If a file already has a valid copyright notice (even from an old year like 2025), it will be left unchanged
- No duplicates created: Running the tool multiple times will not create duplicate copyright notices
- Year matching: The regex pattern
{regex:\d{4}(-\d{4})?}matches any year or year range, ensuring old copyrights are recognized
Line Ending Handling
- Automatic detection: The tool automatically detects whether your files use CRLF (Windows) or LF (Unix/Linux) line endings
- Preservation: Original line endings are preserved when adding copyright notices
- Cross-platform compatibility: Works seamlessly on Windows, Linux, and macOS
Git Integration
When using --changed-only:
- Only files tracked by git and currently modified (staged or unstaged) are checked
- Files must have a supported extension
- Deleted files are automatically excluded
- Works with files in subdirectories
Configuration
Customizing Templates
Edit your copyright.txt file to add or modify copyright formats:
[.your_extension]
Your copyright format here
With multiple lines
And {regex:\d{4}} for year matching
Pre-commit Configuration
Customize the pre-commit hook behavior with various arguments:
Basic Configuration
- repo: https://github.com/mu-triv/sny-copyright-checker
rev: v1.0.5
hooks:
- id: sny-copyright-checker
args: [--notice=copyright.txt]
Check Only (No Auto-fix)
Run the checker without automatically adding copyright notices:
- repo: https://github.com/mu-triv/sny-copyright-checker
rev: v1.0.5
hooks:
- id: sny-copyright-checker
args: [--no-fix, --notice=copyright.txt]
Verbose Output
Enable detailed output for debugging:
- repo: https://github.com/mu-triv/sny-copyright-checker
rev: v1.0.5
hooks:
- id: sny-copyright-checker
args: [--verbose, --notice=copyright.txt]
Check Only Changed Files
Check only files modified compared to a specific git reference:
- repo: https://github.com/mu-triv/sny-copyright-checker
rev: v1.0.5
hooks:
- id: sny-copyright-checker
args: [--changed-only, --base-ref=origin/main, --notice=copyright.txt]
Limit to Specific File Types
Only run on specific file types using the files regex:
- repo: https://github.com/mu-triv/sny-copyright-checker
rev: v1.0.5
hooks:
- id: sny-copyright-checker
args: [--notice=copyright.txt]
files: \.(py|sql|c|cpp)$
Combined Configuration
Combine multiple options:
- repo: https://github.com/mu-triv/sny-copyright-checker
rev: v1.0.5
hooks:
- id: sny-copyright-checker
args: [--verbose, --notice=copyright.txt, --changed-only]
files: \.(py|js|ts|java)$
Multiple Hooks with Different Configurations
Run separate hooks for different scenarios:
repos:
- repo: https://github.com/mu-triv/sny-copyright-checker
rev: v1.0.5
hooks:
# Auto-fix Python files only
- id: sny-copyright-checker
name: Copyright Check (Python - Auto-fix)
args: [--notice=copyright.txt]
files: \.py$
# Check-only for C/C++ files
- id: sny-copyright-checker
name: Copyright Check (C/C++ - Check Only)
args: [--no-fix, --notice=copyright.txt, --verbose]
files: \.(c|cpp|h)$
Development
Setting Up Development Environment
git clone https://github.com/mu-triv/sny-copyright-checker.git
cd sny-copyright-checker
pip install -e .
Running Tests
# Run all tests
pytest tests/
# Run with coverage
pytest tests/ --cov=scripts --cov-report=term
# Run specific test file
pytest tests/test_copyright_checker.py -v
Continuous Integration
The project uses GitHub Actions for CI/CD:
- Tests: Runs on Python 3.10-3.12 across Ubuntu, Windows, and macOS
- Code Quality: Checks with flake8, black, and isort
- Coverage: Generates test coverage reports
The workflow automatically runs on:
- Every push to the
mainbranch - Every pull request targeting
main
Project Structure
sny-copyright-checker/
โโโ scripts/
โ โโโ __init__.py
โ โโโ main.py # Entry point
โ โโโ copyright_checker.py # Main checker logic
โ โโโ copyright_template_parser.py # Template parser
โโโ tests/ # Test files
โโโ .pre-commit-hooks.yaml # Pre-commit hook definition
โโโ .pre-commit-config.yaml # Example pre-commit config
โโโ copyright.txt # Example copyright template
โโโ pyproject.toml # Project metadata
โโโ setup.py # Setup script
โโโ LICENSE # MIT License
โโโ README.md # This file
Comparison with Similar Tools
vs. copyright_notice_precommit
While inspired by leoll2/copyright_notice_precommit, this project adds:
- Multi-format support: Different copyright formats for different file types
- Regex matching: Flexible year range matching
- Auto-insertion: Automatically adds missing copyright notices
- Section-based templates: Easier to maintain multiple formats
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Known Issues and Limitations
Template Changes May Create Duplicate Copyrights
Issue: When you update your copyright.txt template and re-run the checker on files that already have a copyright, it may add a second copyright notice instead of recognizing the existing one.
Why: The checker uses strict template matching. If the copyright format changes (e.g., different company name, license identifier, or text), the old copyright no longer matches the new template and is considered "missing."
Example Scenario:
# Original copyright (Company A)
# Copyright 2025 Company A
# License: MIT
def hello():
pass
After updating copyright.txt to use Company B and re-running:
# Copyright 2026 Company B # <- New copyright added
# SPDX-License-Identifier: Apache-2.0
# Copyright 2025 Company A # <- Old copyright still present
# License: MIT
def hello():
pass
Workarounds:
- Manual cleanup: Before changing templates, manually remove or update existing copyrights
- Test first: Run checker in check-only mode (
--no-fix) to see which files would be modified - Selective application: Use git to only apply checker to new/modified files
- Batch find-replace: Use text editor to update existing copyrights before running checker
Future Enhancement: A --replace mode could be added to detect and replace any copyright-like headers, not just exact template matches.
License
This project is licensed under the MIT License - see the LICENSE file for details.
Author
Tri VU Khac (khactri.vu@sony.com)
SONY Group Corporation
R&D Center Europe Brussels Laboratory
Acknowledgments
- Inspired by leoll2/copyright_notice_precommit
- Built for use with pre-commit
Support
For issues, questions, or contributions, please visit the GitHub repository.
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
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 sny_copyright_checker-1.0.5.tar.gz.
File metadata
- Download URL: sny_copyright_checker-1.0.5.tar.gz
- Upload date:
- Size: 62.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c06e5cb8e3e42f19136fc8e8677571a55e628568613b11db6ddd11c26364c4f5
|
|
| MD5 |
b1cc874c02502e1c0418540f78595ca8
|
|
| BLAKE2b-256 |
37f645b2a1f1c597e7465b7a58ffcef6f8f9a2a02074af4863ac4290c05a060e
|
File details
Details for the file sny_copyright_checker-1.0.5-py3-none-any.whl.
File metadata
- Download URL: sny_copyright_checker-1.0.5-py3-none-any.whl
- Upload date:
- Size: 20.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3ba8c57bfc99ae0b8c160f0d261e3d2b2ddc387ca0b9e4ed472782fff1710131
|
|
| MD5 |
b08aa9c05db736fdf3a1ada3a3fa5f55
|
|
| BLAKE2b-256 |
20e1f155215a39cf41dd678395fae50fe3ab6177080427590fd96b948f55234c
|