Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
4ba2dd5
๐Ÿ“ docs: Add mkdocs-shadcn setup with home page
heumsi Mar 31, 2026
e6a5db9
๐Ÿ“ docs: Add getting started section
heumsi Mar 31, 2026
703dd7b
๐Ÿ“ docs: Add guide section
heumsi Mar 31, 2026
d35a2ea
๐Ÿ“ docs: Add cookbook section
heumsi Mar 31, 2026
8df804a
๐Ÿ“ docs: Add CLI, pre-commit, contributing, and changelog pages
heumsi Mar 31, 2026
16d1568
๐Ÿ‘ท ci: Add docs deployment workflow for GitHub Pages
heumsi Mar 31, 2026
1887b47
๐Ÿ”ง chore: Remove superpowers specs and plans
heumsi Mar 31, 2026
60ff8c0
๐Ÿ”ง chore: Add site/ to gitignore and remove build output
heumsi Mar 31, 2026
0ee2b4f
๐Ÿ“ docs: Move CLI/pre-commit/contributing/changelog into Reference group
heumsi Mar 31, 2026
ea12c67
๐Ÿ“ docs: Enrich guide pages with more examples and consistent style
heumsi Mar 31, 2026
070af35
๐Ÿ“ docs: Unify guide page structure and style
heumsi Mar 31, 2026
9e65a81
๐Ÿ“ docs: Unify intro section heading to "Structure"
heumsi Mar 31, 2026
d36a9a1
๐Ÿ“ docs: Add "Types" grouping heading to rules, filters, naming-constrโ€ฆ
heumsi Mar 31, 2026
9aeb40b
๐Ÿ“ docs: Unify guide page structure with Structure/Types pattern
heumsi Mar 31, 2026
1a6138c
๐Ÿ“ docs: Split rule types into separate page under Rules section
heumsi Mar 31, 2026
7d7b401
๐Ÿ“ docs: Flatten Rules nav to fix sidebar visibility in mkdocs-shadcn
heumsi Mar 31, 2026
d46b582
๐Ÿ“ docs: Merge rule-types, filters, naming-constraints into single Rulโ€ฆ
heumsi Mar 31, 2026
641120d
๐Ÿ“ docs: Add Fields table under Structure in Rules page
heumsi Mar 31, 2026
e697d85
๐Ÿ“ docs: Rename "include only" / "exclude only" to "Only include" / "Oโ€ฆ
heumsi Mar 31, 2026
d38bad4
๐Ÿ“ docs: Change site name to "Python Naming Linter"
heumsi Mar 31, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions .github/workflows/docs.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
name: Deploy Docs

on:
push:
branches: [main]
paths:
- "docs/**"
- "mkdocs.yml"

permissions:
contents: read
pages: write
id-token: write

concurrency:
group: "pages"
cancel-in-progress: false

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- uses: astral-sh/setup-uv@v4
- uses: actions/setup-python@v6
with:
python-version: "3.13"
- run: uv pip install --system mkdocs mkdocs-shadcn
- run: mkdocs build --strict
- uses: actions/upload-pages-artifact@v4
with:
path: site/

deploy:
needs: build
runs-on: ubuntu-latest
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- id: deployment
uses: actions/deploy-pages@v4
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ build/
.venv/
.pytest_cache/
.ruff_cache/
site/
28 changes: 28 additions & 0 deletions docs/changelog.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Changelog

All notable changes to this project will be documented in this file.

## [0.1.0] - 2026-03-30

### Documentation

- Write comprehensive README with examples and configuration guide

### Features

- Add config parsing for rules and apply sections
- Add module pattern matcher with wildcard and capture support
- Add Violation dataclass for checker results
- Add variable name checker with source/transform and case support
- Add function/method name checker with filter and prefix support
- Add class name checker with base_class filter and regex support
- Add module name checker with class_name derivation and regex
- Add package name checker with case and regex support
- line output format
- Add CLI with pnl check command and end-to-end integration

### Miscellaneous

- Set up project scaffolding and tooling
- Add runtime dependencies and CLI entry point
- Fix ruff lint and format issues
36 changes: 36 additions & 0 deletions docs/cli.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# CLI

## `pnl check`

Run the linter against your project:

```bash
# Check with auto-discovered config (searches upward from cwd)
pnl check

# Specify config file (project root = config file's parent directory)
pnl check --config path/to/config.yaml
```

### Options

| Option | Description |
|--------|-------------|
| `--config` | Path to a config file. The config file's parent directory is used as the project root. |

### Config Auto-Discovery

If `--config` is not provided, `pnl check` searches upward from the current working directory for either:

- `.python-naming-linter.yaml`
- `pyproject.toml` (with a `[tool.python-naming-linter]` section)

The first matching file found is used, and its parent directory becomes the project root.

## Exit Codes

| Code | Meaning |
|------|---------|
| `0` | No violations found |
| `1` | One or more violations found |
| `2` | Config file not found |
84 changes: 84 additions & 0 deletions docs/contributing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# Contributing

## Commit Convention

Commit messages must follow [Conventional Commits](https://www.conventionalcommits.org/) with [gitmoji](https://gitmoji.dev/) prefix.

### Format

```
<gitmoji> <type>: <description>
```

- The first letter after the colon must be **capitalized**.
- The description must be in **English**.

### Types

| Gitmoji | Type | Description |
|---------|------------|--------------------------|
| โœจ | `feat` | New feature |
| ๐Ÿ› | `fix` | Bug fix |
| โ™ป๏ธ | `refactor` | Code refactoring |
| ๐Ÿ“ | `docs` | Documentation |
| โœ… | `test` | Adding or updating tests |
| ๐Ÿ”ง | `chore` | Maintenance tasks |
| ๐Ÿ‘ท | `ci` | CI/CD changes |
| โšก | `perf` | Performance improvement |

### Examples

```
โœจ feat: Add support for relative imports
๐Ÿ› fix: Use exit code 2 for config file not found
โ™ป๏ธ refactor: Simplify module resolver logic
```

## Pull Request Convention

- PRs are always **squash merged**, so the PR title becomes the final commit message.
- PR titles must follow the same format as commit messages (`<gitmoji> <type>: <description>`).
- PR descriptions must be written in **English**.

## Pre-commit Hooks

This project uses [pre-commit](https://pre-commit.com/) for linting, formatting, and type checking.

```bash
# Install pre-commit hooks
pre-commit install

# Run manually
pre-commit run --all-files
```

All commits must pass the pre-commit hooks before being accepted.

## Release

Releases are automated via GitHub Actions. You only need to create and push a version tag.

### Steps

1. Calculate the next version based on conventional commits:
```bash
uvx git-cliff --bumped-version
```
2. Review the commits since the last tag:
```bash
git log $(git describe --tags --abbrev=0)..HEAD --oneline
```
3. Push the latest commits to `main`:
```bash
git push origin main
```
4. Create and push the tag:
```bash
git tag <version>
git push origin <version>
```

The GitHub Actions workflow will then automatically:
- Generate `CHANGELOG.md` and commit it to `main`
- Create a GitHub Release with release notes
- Publish the package to PyPI
52 changes: 52 additions & 0 deletions docs/cookbook/attribute-matches-type.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Attribute Matches Type

## Purpose

When an attribute holds a repository, service, or other typed object, keeping the attribute name in sync with the type annotation removes ambiguity and makes dependency injection transparent at a glance. This rule requires each class attribute name to be the snake_case form of its type annotation.

## Configuration

```yaml
rules:
- name: attribute-matches-type
type: variable
filter: { target: attribute }
naming: { source: type_annotation, transform: snake_case }

apply:
- name: domain-layer
rules: [attribute-matches-type]
modules: contexts.*.domain
```

## Violation Example

```python
# contexts/billing/domain/service.py

class BillingService:
def __init__(self, repo: SubscriptionRepository) -> None:
self.repo = repo # should be subscription_repository
```

## Passing Example

```python
# contexts/billing/domain/service.py

class BillingService:
def __init__(self, repo: SubscriptionRepository) -> None:
self.subscription_repository = repo
```

The `{prefix}_{expected}` form is also allowed. For example, `source_object_context: ObjectContext` passes because the name ends with `_object_context`.

## Output

```
$ pnl check
contexts/billing/domain/service.py:5
[attribute-matches-type] repo (expected: subscription_repository)

Found 1 violation(s).
```
50 changes: 50 additions & 0 deletions docs/cookbook/bool-method-prefix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Bool Method Prefix

## Purpose

Functions that return `bool` are easier to read at call sites when their names read as a question. This rule enforces that any function or method with a `bool` return type annotation starts with `is_`, `has_`, or `should_`.

## Configuration

```yaml
rules:
- name: bool-method-prefix
type: function
filter: { return_type: bool }
naming: { prefix: [is_, has_, should_] }

apply:
- name: all
rules: [bool-method-prefix]
modules: "**"
```

## Violation Example

```python
# src/domain/service.py

class SubscriptionService:
def validate(self) -> bool: # missing required prefix
return self._status == "active"
```

## Passing Example

```python
# src/domain/service.py

class SubscriptionService:
def is_valid(self) -> bool:
return self._status == "active"
```

## Output

```
$ pnl check
src/domain/service.py:4
[bool-method-prefix] validate (expected prefix: is_ | has_ | should_)

Found 1 violation(s).
```
51 changes: 51 additions & 0 deletions docs/cookbook/constant-upper-case.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Constant Upper Case

## Purpose

Module-level constants are easier to distinguish from regular variables when they follow the UPPER_CASE convention. This rule catches constants that were accidentally written in snake_case and flags them for renaming.

## Configuration

```yaml
rules:
- name: constant-upper-case
type: variable
filter: { target: constant }
naming: { case: UPPER_CASE }

apply:
- name: all
rules: [constant-upper-case]
modules: "**"
```

## Violation Example

```python
# src/config.py

max_retry_count = 3 # constant in snake_case
default_timeout_seconds = 30 # constant in snake_case
```

## Passing Example

```python
# src/config.py

MAX_RETRY_COUNT = 3
DEFAULT_TIMEOUT_SECONDS = 30
```

## Output

```
$ pnl check
src/config.py:3
[constant-upper-case] max_retry_count (expected case: UPPER_CASE)

src/config.py:4
[constant-upper-case] default_timeout_seconds (expected case: UPPER_CASE)

Found 2 violation(s).
```
Loading
Loading