py_launch_blueprint 1.1.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,187 @@
1
+ Metadata-Version: 2.4
2
+ Name: py_launch_blueprint
3
+ Version: 1.1.3
4
+ Summary: CLI tools for interacting with Py, including project search functionality
5
+ Author: Steve Morin
6
+ Author-email: Steve Morin <steve.morin@gmail.com>
7
+ License-Expression: MIT
8
+ Classifier: Development Status :: 4 - Beta
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: Operating System :: OS Independent
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.12
13
+ Classifier: Programming Language :: Python :: 3.13
14
+ Classifier: Programming Language :: Python :: 3 :: Only
15
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
16
+ Requires-Dist: click>=8.1.0
17
+ Requires-Dist: questionary>=2.0.0
18
+ Requires-Dist: python-dotenv>=1.0.0
19
+ Requires-Dist: thefuzz>=0.19.0
20
+ Requires-Dist: python-levenshtein>=0.21.0
21
+ Requires-Dist: pyperclip>=1.8.0
22
+ Requires-Dist: requests>=2.31.0
23
+ Requires-Dist: rich>=13.0.0
24
+ Requires-Python: >=3.12
25
+ Project-URL: Homepage, https://github.com/smorinlabs/py-launch-blueprint
26
+ Project-URL: Repository, https://github.com/smorinlabs/py-launch-blueprint
27
+ Project-URL: Documentation, https://py-launch-blueprint.readthedocs.io/en/latest/
28
+ Project-URL: Changelog, https://github.com/smorinlabs/py-launch-blueprint/blob/main/CHANGELOG.md
29
+ Project-URL: Issues, https://github.com/smorinlabs/py-launch-blueprint/issues
30
+ Description-Content-Type: text/markdown
31
+
32
+ <!-- ITM-081 — badges. Single horizontal row (decided round 23). -->
33
+ [![PyPI version](https://img.shields.io/pypi/v/py-launch-blueprint.svg)](https://pypi.org/project/py-launch-blueprint/)
34
+ [![Python versions](https://img.shields.io/pypi/pyversions/py-launch-blueprint.svg)](https://pypi.org/project/py-launch-blueprint/)
35
+ [![CI](https://github.com/smorinlabs/py-launch-blueprint/actions/workflows/ci.yml/badge.svg)](https://github.com/smorinlabs/py-launch-blueprint/actions/workflows/ci.yml)
36
+ [![codecov](https://codecov.io/gh/smorinlabs/py-launch-blueprint/branch/main/graph/badge.svg)](https://codecov.io/gh/smorinlabs/py-launch-blueprint)
37
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
38
+ [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
39
+ [![uv](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/uv/main/assets/badge/v0.json)](https://github.com/astral-sh/uv)
40
+ [![Conventional Commits](https://img.shields.io/badge/Conventional%20Commits-1.0.0-yellow.svg)](https://www.conventionalcommits.org/)
41
+
42
+ # Py Launch Blueprint: A Production-Ready 🐍 Python Project Template with Integrated Best Practices
43
+ Py Launch Blueprint is a comprehensive Python project template that eliminates setup friction by providing a pre-configured development environment with carefully selected tools for linting, formatting, and type checking. It includes an annotated CLI example and detailed documentation explaining each tool choice and configuration decision, making it an ideal starting point for professional Python projects.
44
+
45
+ ![Py Launch Blueprint Logo](./assets/images/logos/py_launch_blueprint_logo_100x100.png)
46
+
47
+ ## Why Choose Py Launch Blueprint?
48
+
49
+ Py Launch Blueprint eliminates the setup friction in Python projects by providing a production-ready template with carefully curated tools and best practices.
50
+
51
+ ## Full documentation on ReadTheDocs
52
+ - [py-launch-blueprint Docs](https://py-launch-blueprint.readthedocs.io/en/latest/)
53
+
54
+ ### 🚀 Key Features
55
+
56
+ **Zero-config** development environment with **type safety** built in.
57
+
58
+ ## ✨ Features TLDR
59
+ - 🛠️ **Dev Tools**: Ruff (linting/formatting), `ty` (type checking, Astral), lefthook (hooks), commitlint
60
+ - 🔒 **Security**: gitleaks (commit/push), TruffleHog (CI), bandit (pre-push + CI), CodeQL
61
+ - 🧠 **AI Ready**: AGENTS.md + CLAUDE.md, default configs for Cursor, Windsurf, Claude Code
62
+ - 💪 **Production**: Python 3.12+, uv + uv_build, PEP 735 dependency-groups, static version
63
+ - 🚀 **DX - Developer Experience**: VS Code DevContainer, sensible defaults, quality documentation
64
+ - 🔄 **CI/CD**: GitHub Actions workflows, release-please version bumps, OIDC trusted publishing
65
+
66
+ ## Quick start
67
+
68
+ ```bash
69
+ git clone https://github.com/smorinlabs/py-launch-blueprint.git
70
+ cd py-launch-blueprint
71
+ make hook-check # verify toolchain (lefthook/gitleaks/bun/uv/...)
72
+ scripts/install-bun.sh
73
+ scripts/install-lefthook.sh
74
+ scripts/install-gitleaks.sh
75
+ uv sync --group dev # PEP 735 dev tools
76
+ bun install # commitlint deps
77
+ just check # full quality pipeline
78
+ ```
79
+
80
+ Install as a tool: `uvx --from py-launch-blueprint py-projects` (uvx needs `--from` because the distribution name differs from the console-script name) or `pip install py-launch-blueprint && py-projects`.
81
+
82
+ See [AGENTS.md](AGENTS.md) for the canonical command set, [.github/CONTRIBUTING.md](.github/CONTRIBUTING.md) for the daily workflow, and [RELEASE.md](RELEASE.md) for the release flow.
83
+
84
+ **Starting a new project from this template?** If you use Claude Code or any agent that reads `AGENTS.md`, just say *"create a new Python project from py-launch-blueprint"* — the [`skill/`](skill/SKILL.md) skill will walk you through `gh repo create --template`, identity collection, `just init` rebrand with preview, and an optional handoff to `just post-init` for publishing/Codecov/ReadTheDocs setup. For humans without an agent: the skill is also a copy-pasteable runbook.
85
+
86
+ ### 🎯 Perfect For
87
+ Teams and professionals needing maintainable, type-safe Python projects following best practices.
88
+
89
+ ## Complete Feature List
90
+
91
+ ### Development Tools
92
+
93
+ - **Bootstrap dependency check and install with `make`**: Execute common development tasks with simple commands, standardizing workflows across team members.
94
+
95
+ - **Command running with `just`**: Define and run project-specific commands with a modern Make alternative, simplifying complex operations with clear syntax.
96
+
97
+ - **Linting with `ruff`**: Catch errors and enforce code style at lightning speed (10-100x faster than traditional linters), reducing waiting time and improving developer productivity.
98
+
99
+ - **Type checking with `mypy`**: Prevent type-related bugs before they occur, making your codebase more robust and easier to maintain as it grows.
100
+
101
+ - **Formatting with `ruff`**: Ensure consistent code style across your project automatically, eliminating style debates and pull request revision cycles.
102
+
103
+ - **Pre-commit hooks with `pre-commit`**: Enforce quality standards before code enters your repository, preventing bad code from ever being committed and reducing technical debt.
104
+
105
+ - **TOML formatting and validation with `taplo`**: Verify Toml files for syntax correctness, maintain consistent configuration files, ensuring readability and avoiding syntax errors in critical project settings.
106
+
107
+ - **YAML validation with [yamllint](docs/source/tools/yaml_lint.md)**: Verify YAML files for syntax correctness, preventing configuration errors and deployment failures.
108
+
109
+ ### Project Structure & Management
110
+
111
+ - **Project configuration with `pyproject.toml`**: Organize all project settings in one standardized location, simplifying maintenance and configuration.
112
+
113
+ - **Dependency groups separation**: Organize dependencies into main, dev, and doc categories, preventing bloated installations and clarifying requirements as part of `pyproject.toml` configuration.
114
+
115
+ - **Dependency management with [`uv`](https://docs.astral.sh/uv/)**: Install and manage packages at blazing speed (100x faster than pip/poetry), dramatically reducing environment setup time.
116
+
117
+ - **Build system with `uv_build`**: Build wheel and source distributions with uv's build backend and `uv build`.
118
+
119
+ - **Versioning with explicit project metadata**: Keep release tags aligned with the static version in `pyproject.toml` for predictable package metadata.
120
+
121
+ - **Copyright license automation**: Automatically add license headers to all files, ensuring legal compliance without manual effort.
122
+
123
+ ### Documentation
124
+
125
+ - **Documentation with `sphinx + MyST`**: Generate comprehensive documentation that supports both reStructuredText and Markdown, improving contributor accessibility.
126
+
127
+ - **`Read the Docs` integration**: Deploy documentation automatically, providing instant hosting and versioning for your project's documentation.
128
+
129
+ - **Changelog management with `cog`**: Track and communicate changes effectively to users and team members, improving project transparency and adoption.
130
+
131
+ ### Testing & Quality Assurance
132
+
133
+ - **Testing framework with `pytest`**: Write and run tests with a modern, powerful testing framework that supports fixtures and parameterization.
134
+
135
+ - **CI/CD with `GitHub Actions`**: Automatically test, build, and deploy your project on multiple Python versions, catching compatibility issues early.
136
+
137
+ - **Matrix testing with `GitHub Actions`**: Run tests across multiple Python versions and operating systems, ensuring broad compatibility.
138
+
139
+ - **Simplified debugging info with `just debug-info`**: Automatically collect and format essential system, tool, and dependency information for streamlined bug reporting via a simple command.
140
+
141
+ ### GitHub Integration
142
+
143
+ - **Pull request template**: Guide contributors through the PR process with structured information requirements, improving submission quality.
144
+
145
+ - **Issue templates (Feature, Bug, Documentation)**: Standardize issue reporting with appropriate fields for each type, gathering all necessary information upfront.
146
+
147
+ - **Automated contributor recognition with `contributors-please`**: Automatically update contributor lists, acknowledging all project participants without manual tracking.
148
+
149
+ - **Conventional commits enforced with `commitlint`**: Enforce structured commit messages so `release-please` can automate changelog generation and version bumps.
150
+
151
+ - **Security policy**: Establish clear vulnerability reporting procedures, promoting responsible disclosure and faster security fixes.
152
+
153
+ - **Code of conduct**: Set community behavior expectations, fostering an inclusive and respectful project environment.
154
+
155
+ - **Contributing guidelines**: Provide clear instructions for contributors, reducing friction for new participants.
156
+
157
+ - **Automated dependency security scanning with `codeql`**: Detect vulnerable dependencies automatically, protecting your users from known security issues.
158
+
159
+ - **CLA (Contributor License Agreement) check via [`CLA Assistant`](docs/source/tools/cla-assistant.md)**: Ensure all contributors have signed appropriate licensing agreements, protecting the project legally.
160
+
161
+ ### IDE Integration
162
+
163
+ - **VS Code integration**: Provide optimized settings and configurations for Visual Studio Code, enhancing developer productivity.
164
+
165
+ - **PyRight configuration**: Enable accurate, real-time type checking in the editor, catching errors before running tests.
166
+
167
+ - **Editor extensions recommendations**: Suggest optimal VS Code extensions automatically, standardizing the development environment.
168
+
169
+ ### AI Integration
170
+
171
+ - **AI assistance with common agents `Cursor, Windsurf, Claude Code, Codex`**: Support popular AI coding assistants enabling AI-powered development.
172
+
173
+ - **Cursor Rules configuration**: Optimize Cursor AI assistant for your specific project structure, improving suggestion relevance.
174
+
175
+ - **Windsurf Rules configuration**: Configure Windsurf IDE to understand your project architecture, enhancing code generation quality.
176
+
177
+ ### Communication & Notifications
178
+
179
+ - **Slack integration for PRs and issues**: Send automated notifications to Slack when PRs or issues are opened/closed, keeping the team informed.
180
+
181
+ - **PR reminder notifications**: Ping relevant team members on Slack for PR reviews, reducing review cycle times.
182
+
183
+
184
+ Start your next Python project with confidence, knowing you're building on a foundation of best practices and modern development tools.
185
+
186
+ ## Full documentation on ReadTheDocs including how to run
187
+ - [py-launch-blueprint Docs](https://py-launch-blueprint.readthedocs.io/en/latest/)
@@ -0,0 +1,156 @@
1
+ <!-- ITM-081 — badges. Single horizontal row (decided round 23). -->
2
+ [![PyPI version](https://img.shields.io/pypi/v/py-launch-blueprint.svg)](https://pypi.org/project/py-launch-blueprint/)
3
+ [![Python versions](https://img.shields.io/pypi/pyversions/py-launch-blueprint.svg)](https://pypi.org/project/py-launch-blueprint/)
4
+ [![CI](https://github.com/smorinlabs/py-launch-blueprint/actions/workflows/ci.yml/badge.svg)](https://github.com/smorinlabs/py-launch-blueprint/actions/workflows/ci.yml)
5
+ [![codecov](https://codecov.io/gh/smorinlabs/py-launch-blueprint/branch/main/graph/badge.svg)](https://codecov.io/gh/smorinlabs/py-launch-blueprint)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
7
+ [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
8
+ [![uv](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/uv/main/assets/badge/v0.json)](https://github.com/astral-sh/uv)
9
+ [![Conventional Commits](https://img.shields.io/badge/Conventional%20Commits-1.0.0-yellow.svg)](https://www.conventionalcommits.org/)
10
+
11
+ # Py Launch Blueprint: A Production-Ready 🐍 Python Project Template with Integrated Best Practices
12
+ Py Launch Blueprint is a comprehensive Python project template that eliminates setup friction by providing a pre-configured development environment with carefully selected tools for linting, formatting, and type checking. It includes an annotated CLI example and detailed documentation explaining each tool choice and configuration decision, making it an ideal starting point for professional Python projects.
13
+
14
+ ![Py Launch Blueprint Logo](./assets/images/logos/py_launch_blueprint_logo_100x100.png)
15
+
16
+ ## Why Choose Py Launch Blueprint?
17
+
18
+ Py Launch Blueprint eliminates the setup friction in Python projects by providing a production-ready template with carefully curated tools and best practices.
19
+
20
+ ## Full documentation on ReadTheDocs
21
+ - [py-launch-blueprint Docs](https://py-launch-blueprint.readthedocs.io/en/latest/)
22
+
23
+ ### 🚀 Key Features
24
+
25
+ **Zero-config** development environment with **type safety** built in.
26
+
27
+ ## ✨ Features TLDR
28
+ - 🛠️ **Dev Tools**: Ruff (linting/formatting), `ty` (type checking, Astral), lefthook (hooks), commitlint
29
+ - 🔒 **Security**: gitleaks (commit/push), TruffleHog (CI), bandit (pre-push + CI), CodeQL
30
+ - 🧠 **AI Ready**: AGENTS.md + CLAUDE.md, default configs for Cursor, Windsurf, Claude Code
31
+ - 💪 **Production**: Python 3.12+, uv + uv_build, PEP 735 dependency-groups, static version
32
+ - 🚀 **DX - Developer Experience**: VS Code DevContainer, sensible defaults, quality documentation
33
+ - 🔄 **CI/CD**: GitHub Actions workflows, release-please version bumps, OIDC trusted publishing
34
+
35
+ ## Quick start
36
+
37
+ ```bash
38
+ git clone https://github.com/smorinlabs/py-launch-blueprint.git
39
+ cd py-launch-blueprint
40
+ make hook-check # verify toolchain (lefthook/gitleaks/bun/uv/...)
41
+ scripts/install-bun.sh
42
+ scripts/install-lefthook.sh
43
+ scripts/install-gitleaks.sh
44
+ uv sync --group dev # PEP 735 dev tools
45
+ bun install # commitlint deps
46
+ just check # full quality pipeline
47
+ ```
48
+
49
+ Install as a tool: `uvx --from py-launch-blueprint py-projects` (uvx needs `--from` because the distribution name differs from the console-script name) or `pip install py-launch-blueprint && py-projects`.
50
+
51
+ See [AGENTS.md](AGENTS.md) for the canonical command set, [.github/CONTRIBUTING.md](.github/CONTRIBUTING.md) for the daily workflow, and [RELEASE.md](RELEASE.md) for the release flow.
52
+
53
+ **Starting a new project from this template?** If you use Claude Code or any agent that reads `AGENTS.md`, just say *"create a new Python project from py-launch-blueprint"* — the [`skill/`](skill/SKILL.md) skill will walk you through `gh repo create --template`, identity collection, `just init` rebrand with preview, and an optional handoff to `just post-init` for publishing/Codecov/ReadTheDocs setup. For humans without an agent: the skill is also a copy-pasteable runbook.
54
+
55
+ ### 🎯 Perfect For
56
+ Teams and professionals needing maintainable, type-safe Python projects following best practices.
57
+
58
+ ## Complete Feature List
59
+
60
+ ### Development Tools
61
+
62
+ - **Bootstrap dependency check and install with `make`**: Execute common development tasks with simple commands, standardizing workflows across team members.
63
+
64
+ - **Command running with `just`**: Define and run project-specific commands with a modern Make alternative, simplifying complex operations with clear syntax.
65
+
66
+ - **Linting with `ruff`**: Catch errors and enforce code style at lightning speed (10-100x faster than traditional linters), reducing waiting time and improving developer productivity.
67
+
68
+ - **Type checking with `mypy`**: Prevent type-related bugs before they occur, making your codebase more robust and easier to maintain as it grows.
69
+
70
+ - **Formatting with `ruff`**: Ensure consistent code style across your project automatically, eliminating style debates and pull request revision cycles.
71
+
72
+ - **Pre-commit hooks with `pre-commit`**: Enforce quality standards before code enters your repository, preventing bad code from ever being committed and reducing technical debt.
73
+
74
+ - **TOML formatting and validation with `taplo`**: Verify Toml files for syntax correctness, maintain consistent configuration files, ensuring readability and avoiding syntax errors in critical project settings.
75
+
76
+ - **YAML validation with [yamllint](docs/source/tools/yaml_lint.md)**: Verify YAML files for syntax correctness, preventing configuration errors and deployment failures.
77
+
78
+ ### Project Structure & Management
79
+
80
+ - **Project configuration with `pyproject.toml`**: Organize all project settings in one standardized location, simplifying maintenance and configuration.
81
+
82
+ - **Dependency groups separation**: Organize dependencies into main, dev, and doc categories, preventing bloated installations and clarifying requirements as part of `pyproject.toml` configuration.
83
+
84
+ - **Dependency management with [`uv`](https://docs.astral.sh/uv/)**: Install and manage packages at blazing speed (100x faster than pip/poetry), dramatically reducing environment setup time.
85
+
86
+ - **Build system with `uv_build`**: Build wheel and source distributions with uv's build backend and `uv build`.
87
+
88
+ - **Versioning with explicit project metadata**: Keep release tags aligned with the static version in `pyproject.toml` for predictable package metadata.
89
+
90
+ - **Copyright license automation**: Automatically add license headers to all files, ensuring legal compliance without manual effort.
91
+
92
+ ### Documentation
93
+
94
+ - **Documentation with `sphinx + MyST`**: Generate comprehensive documentation that supports both reStructuredText and Markdown, improving contributor accessibility.
95
+
96
+ - **`Read the Docs` integration**: Deploy documentation automatically, providing instant hosting and versioning for your project's documentation.
97
+
98
+ - **Changelog management with `cog`**: Track and communicate changes effectively to users and team members, improving project transparency and adoption.
99
+
100
+ ### Testing & Quality Assurance
101
+
102
+ - **Testing framework with `pytest`**: Write and run tests with a modern, powerful testing framework that supports fixtures and parameterization.
103
+
104
+ - **CI/CD with `GitHub Actions`**: Automatically test, build, and deploy your project on multiple Python versions, catching compatibility issues early.
105
+
106
+ - **Matrix testing with `GitHub Actions`**: Run tests across multiple Python versions and operating systems, ensuring broad compatibility.
107
+
108
+ - **Simplified debugging info with `just debug-info`**: Automatically collect and format essential system, tool, and dependency information for streamlined bug reporting via a simple command.
109
+
110
+ ### GitHub Integration
111
+
112
+ - **Pull request template**: Guide contributors through the PR process with structured information requirements, improving submission quality.
113
+
114
+ - **Issue templates (Feature, Bug, Documentation)**: Standardize issue reporting with appropriate fields for each type, gathering all necessary information upfront.
115
+
116
+ - **Automated contributor recognition with `contributors-please`**: Automatically update contributor lists, acknowledging all project participants without manual tracking.
117
+
118
+ - **Conventional commits enforced with `commitlint`**: Enforce structured commit messages so `release-please` can automate changelog generation and version bumps.
119
+
120
+ - **Security policy**: Establish clear vulnerability reporting procedures, promoting responsible disclosure and faster security fixes.
121
+
122
+ - **Code of conduct**: Set community behavior expectations, fostering an inclusive and respectful project environment.
123
+
124
+ - **Contributing guidelines**: Provide clear instructions for contributors, reducing friction for new participants.
125
+
126
+ - **Automated dependency security scanning with `codeql`**: Detect vulnerable dependencies automatically, protecting your users from known security issues.
127
+
128
+ - **CLA (Contributor License Agreement) check via [`CLA Assistant`](docs/source/tools/cla-assistant.md)**: Ensure all contributors have signed appropriate licensing agreements, protecting the project legally.
129
+
130
+ ### IDE Integration
131
+
132
+ - **VS Code integration**: Provide optimized settings and configurations for Visual Studio Code, enhancing developer productivity.
133
+
134
+ - **PyRight configuration**: Enable accurate, real-time type checking in the editor, catching errors before running tests.
135
+
136
+ - **Editor extensions recommendations**: Suggest optimal VS Code extensions automatically, standardizing the development environment.
137
+
138
+ ### AI Integration
139
+
140
+ - **AI assistance with common agents `Cursor, Windsurf, Claude Code, Codex`**: Support popular AI coding assistants enabling AI-powered development.
141
+
142
+ - **Cursor Rules configuration**: Optimize Cursor AI assistant for your specific project structure, improving suggestion relevance.
143
+
144
+ - **Windsurf Rules configuration**: Configure Windsurf IDE to understand your project architecture, enhancing code generation quality.
145
+
146
+ ### Communication & Notifications
147
+
148
+ - **Slack integration for PRs and issues**: Send automated notifications to Slack when PRs or issues are opened/closed, keeping the team informed.
149
+
150
+ - **PR reminder notifications**: Ping relevant team members on Slack for PR reviews, reducing review cycle times.
151
+
152
+
153
+ Start your next Python project with confidence, knowing you're building on a foundation of best practices and modern development tools.
154
+
155
+ ## Full documentation on ReadTheDocs including how to run
156
+ - [py-launch-blueprint Docs](https://py-launch-blueprint.readthedocs.io/en/latest/)
@@ -0,0 +1,26 @@
1
+ # Copyright (c) 2025, Steve Morin
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy of
4
+ # this software and associated documentation files (the "Software"), to deal in
5
+ # the Software without restriction, including without limitation the rights to
6
+ # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
7
+ # the Software, and to permit persons to whom the Software is furnished to do so,
8
+ # subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in all
11
+ # copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
15
+ # FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
16
+ # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
17
+ # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18
+ # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19
+
20
+ """Py utilities package."""
21
+
22
+ from importlib import metadata
23
+
24
+ __version__ = metadata.version("py_launch_blueprint")
25
+
26
+ from .projects import main as main # Re-export main function
@@ -0,0 +1,412 @@
1
+ #!/usr/bin/env python3
2
+ # Copyright (c) 2025, Steve Morin
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining a copy of
5
+ # this software and associated documentation files (the "Software"), to deal in
6
+ # the Software without restriction, including without limitation the rights to
7
+ # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
8
+ # the Software, and to permit persons to whom the Software is furnished to do so,
9
+ # subject to the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be included in all
12
+ # copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
16
+ # FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
17
+ # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
18
+ # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19
+ # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
+
21
+ """
22
+ Py Project Search CLI Tool.
23
+
24
+ A command-line interface for searching and selecting Py projects,
25
+ with support for fuzzy matching and various output formats.
26
+ """
27
+ # TODO: remove mypy: ignore-errors and fix all type errors
28
+ # mypy: ignore-errors
29
+
30
+ import json
31
+ import os
32
+ import sys
33
+ from dataclasses import dataclass
34
+ from pathlib import Path
35
+ from typing import Any
36
+
37
+ import click
38
+ import pyperclip
39
+ import questionary
40
+ import requests
41
+ from dotenv import load_dotenv
42
+ from rich.console import Console
43
+ from rich.progress import Progress
44
+ from rich.table import Table
45
+
46
+ from py_launch_blueprint import __version__
47
+
48
+ # Initialize Rich console for pretty output
49
+ console = Console()
50
+ error_console = Console(stderr=True)
51
+
52
+
53
+ # Custom Exceptions
54
+ class PyError(Exception):
55
+ """Base exception for Py-related errors."""
56
+
57
+ pass
58
+
59
+
60
+ class ConfigError(Exception):
61
+ """Configuration-related errors."""
62
+
63
+ pass
64
+
65
+
66
+ # Configuration
67
+ @dataclass
68
+ class Config:
69
+ """Configuration container."""
70
+
71
+ token: str | None = None
72
+
73
+ @classmethod
74
+ def from_env(cls, env_path: str | None = None) -> "Config":
75
+ """
76
+ Create Config from environment variables or .env file.
77
+
78
+ Args:
79
+ env_path: Optional path to .env file
80
+
81
+ Returns:
82
+ Config object
83
+ """
84
+ if env_path:
85
+ # Don't error if .env file is missing, just try to load if it exists
86
+ load_dotenv(env_path)
87
+
88
+ token = os.getenv("PY_TOKEN")
89
+ if token is None:
90
+ error_console.print(
91
+ "\n[yellow]No PY_TOKEN found in environment or config file.[/yellow]"
92
+ )
93
+ error_console.print("To set your Py token, you have three options:")
94
+ error_console.print("1. Set the PY_TOKEN environment variable:")
95
+ error_console.print(" export PY_TOKEN=your_token_here")
96
+ error_console.print(
97
+ "\n2. Create a .env file in ~/.config/py-cli/.env with:"
98
+ )
99
+ error_console.print(" PY_TOKEN=your_token_here")
100
+ error_console.print("\n3. Use the --token option when running the command:")
101
+ error_console.print(" py-cli --token your_token_here")
102
+ error_console.print(
103
+ "\nYou can get your token from: https://app.py.com/settings/tokens\n"
104
+ )
105
+ raise ConfigError("No PY_TOKEN found in environment or config file")
106
+
107
+ return cls(token=token)
108
+
109
+
110
+ def get_config_path() -> Path:
111
+ """Get the path to the configuration directory."""
112
+ if os.name == "nt": # Windows
113
+ base_path = Path(os.environ["USERPROFILE"])
114
+ else: # Unix-like
115
+ base_path = Path.home()
116
+
117
+ return base_path / ".config" / "py-cli"
118
+
119
+
120
+ def get_config(config_path: str | None = None) -> Config:
121
+ """
122
+ Get configuration from various sources.
123
+
124
+ Priority (highest to lowest):
125
+ 1. Environment variables
126
+ 2. Configuration file
127
+
128
+ Args:
129
+ config_path: Optional path to config file
130
+
131
+ Returns:
132
+ Config object with merged configuration
133
+ """
134
+ config = Config()
135
+
136
+ # Load from file if specified
137
+ if config_path:
138
+ file_config = Config.from_env(config_path)
139
+ if file_config.token:
140
+ config.token = file_config.token
141
+
142
+ # Environment variables take precedence
143
+ env_token = os.getenv("PY_TOKEN")
144
+ if env_token:
145
+ config.token = env_token
146
+
147
+ return config
148
+
149
+
150
+ # API Client
151
+ class PyClient:
152
+ """Client for interacting with the Py API."""
153
+
154
+ BASE_URL = "https://app.py.com/api/1.0"
155
+
156
+ def __init__(self, token: str):
157
+ """
158
+ Initialize the Py API client.
159
+
160
+ Args:
161
+ token: Py Personal Access Token
162
+ """
163
+ self.session = requests.Session()
164
+ self.session.headers.update(
165
+ {
166
+ "Authorization": f"Bearer {token}",
167
+ "Accept": "application/json",
168
+ }
169
+ )
170
+
171
+ def _request(self, method: str, path: str, **kwargs: Any) -> dict[str, Any]:
172
+ """
173
+ Make a request to the Py API.
174
+
175
+ Args:
176
+ method: HTTP method
177
+ path: API endpoint path
178
+ **kwargs: Additional request parameters
179
+
180
+ Returns:
181
+ Response data
182
+
183
+ Raises:
184
+ PyError: If the request fails
185
+ """
186
+ url = f"{self.BASE_URL}/{path.lstrip('/')}"
187
+ try:
188
+ response = self.session.request(method, url, **kwargs)
189
+ response.raise_for_status()
190
+ return response.json()
191
+ except requests.exceptions.RequestException as e:
192
+ if hasattr(e.response, "json"):
193
+ try:
194
+ if e.response is not None: # Check if response is not None
195
+ error_data = e.response.json()
196
+ error_msg = error_data.get("errors", [{}])[0].get(
197
+ "message", str(e)
198
+ )
199
+ else:
200
+ error_msg = str(e)
201
+ except ValueError:
202
+ error_msg = str(e)
203
+ else:
204
+ error_msg = str(e)
205
+ raise PyError(f"API request failed: {error_msg}") from e
206
+
207
+ def get_workspaces(self) -> list[dict[str, Any]]:
208
+ """
209
+ Get all accessible workspaces.
210
+
211
+ Returns:
212
+ List of workspace dictionaries
213
+ """
214
+ return self._request("GET", "/workspaces")["data"]
215
+
216
+ def get_projects(
217
+ self, workspace_name: str | None = None, limit: int = 200
218
+ ) -> list[dict[str, Any]]:
219
+ """
220
+ Get projects, optionally filtered by workspace.
221
+
222
+ Args:
223
+ workspace_name: Optional workspace name filter
224
+ limit: Maximum number of projects to return
225
+
226
+ Returns:
227
+ List of project dictionaries
228
+ """
229
+ params = {
230
+ "limit": limit,
231
+ "opt_fields": "name,workspace.name",
232
+ }
233
+
234
+ if workspace_name:
235
+ # First get workspaces and find the matching one
236
+ workspaces = self.get_workspaces()
237
+ workspace = next(
238
+ (w for w in workspaces if w["name"].lower() == workspace_name.lower()),
239
+ None,
240
+ )
241
+ if not workspace:
242
+ raise PyError(f"Workspace not found: {workspace_name}")
243
+
244
+ params["workspace"] = workspace["gid"]
245
+
246
+ response_data = self._request("GET", "/projects", params=params)
247
+ return response_data.get("data", [])
248
+
249
+
250
+ # CLI Functions
251
+ def setup_config(config_path: str | None = None) -> Config:
252
+ """
253
+ Set up configuration from various sources.
254
+
255
+ Args:
256
+ config_path: Optional path to config file
257
+
258
+ Returns:
259
+ Config object with merged configuration
260
+ """
261
+ # Load from default location if not specified
262
+ if not config_path:
263
+ config_dir = get_config_path()
264
+ config_path = str(config_dir / ".env")
265
+
266
+ try:
267
+ return get_config(config_path)
268
+ except ConfigError as e:
269
+ error_console.print(f"[red]Configuration error:[/red] {e}")
270
+ sys.exit(1)
271
+
272
+
273
+ def format_output(projects: list[dict[str, Any]], format: str) -> str:
274
+ """
275
+ Format projects list according to specified format.
276
+
277
+ Args:
278
+ projects: List of project dictionaries
279
+ format: Output format (text, json, or csv)
280
+
281
+ Returns:
282
+ Formatted string
283
+ """
284
+ if format == "json":
285
+ return json.dumps({"projects": projects}, indent=2)
286
+ elif format == "csv":
287
+ header = "id,name\n"
288
+ rows = [f"{p['id']},{p['name']}" for p in projects]
289
+ return header + "\n".join(rows)
290
+ else: # text format
291
+ return "\n".join(p["id"] for p in projects)
292
+
293
+
294
+ def display_projects(projects: list[dict[str, Any]], verbose: bool = False) -> None:
295
+ """
296
+ Display projects in a rich table format.
297
+
298
+ Args:
299
+ projects: List of project dictionaries
300
+ verbose: Whether to show additional details
301
+ """
302
+ table = Table(show_header=True)
303
+ table.add_column("Project Name", style="cyan")
304
+ table.add_column("Workspace", style="green")
305
+ if verbose:
306
+ table.add_column("ID", style="dim")
307
+
308
+ for project in projects:
309
+ row = [project["name"], project["workspace"]["name"]]
310
+ if verbose:
311
+ row.append(project["id"])
312
+ table.add_row(*row)
313
+
314
+ console.print(table)
315
+
316
+
317
+ @click.command()
318
+ @click.version_option(version=__version__)
319
+ @click.option("--token", help="Py Personal Access Token")
320
+ @click.option("--config", help="Path to config file", type=click.Path(exists=True))
321
+ @click.option("--workspace", help="Filter projects by workspace name")
322
+ @click.option("--limit", default=200, help="Maximum number of projects to retrieve")
323
+ @click.option(
324
+ "--format",
325
+ type=click.Choice(["text", "json", "csv"]),
326
+ default="text",
327
+ help="Output format",
328
+ )
329
+ @click.option("--copy", is_flag=True, help="Copy results to clipboard")
330
+ @click.option("--output", type=click.Path(), help="Write results to file")
331
+ @click.option("--no-color", is_flag=True, help="Disable colored output")
332
+ @click.option("--verbose", is_flag=True, help="Enable verbose output")
333
+ def main(
334
+ token: str | None,
335
+ config: str | None,
336
+ workspace: str | None,
337
+ limit: int,
338
+ format: str,
339
+ copy: bool,
340
+ output: str | None,
341
+ no_color: bool,
342
+ verbose: bool,
343
+ ) -> None:
344
+ """Search and select Py projects."""
345
+ try:
346
+ # Setup configuration
347
+ cfg = setup_config(config)
348
+ if token:
349
+ cfg.token = token
350
+
351
+ if not cfg.token:
352
+ error_console.print("[red]Error:[/red] No Py token provided")
353
+ sys.exit(1)
354
+
355
+ # Initialize API client
356
+ client = PyClient(cfg.token)
357
+
358
+ with Progress() as progress:
359
+ # Fetch projects
360
+ task = progress.add_task("Fetching projects...", total=None)
361
+ projects = client.get_projects(workspace_name=workspace, limit=limit)
362
+ progress.update(task, completed=True)
363
+
364
+ if not projects:
365
+ console.print("[yellow]No projects found.[/yellow]")
366
+ return
367
+
368
+ # Display projects and get selection
369
+ if format == "text":
370
+ display_projects(projects, verbose)
371
+
372
+ # Allow project selection
373
+ choices = [
374
+ questionary.Choice(title=f"{p['name']} ({p['workspace']['name']})", value=p)
375
+ for p in projects
376
+ ]
377
+
378
+ selected = questionary.checkbox(
379
+ "Select projects:",
380
+ choices=choices,
381
+ ).ask()
382
+
383
+ if not selected:
384
+ console.print("[yellow]No projects selected[/yellow]")
385
+ return
386
+
387
+ # Format output
388
+ result = format_output(selected, format)
389
+
390
+ # Handle output
391
+ if output:
392
+ Path(output).write_text(result)
393
+ console.print(f"[green]Results written to {output}[/green]")
394
+ else:
395
+ console.print(result)
396
+
397
+ if copy:
398
+ pyperclip.copy(result)
399
+ console.print("[green]Results copied to clipboard[/green]")
400
+
401
+ except PyError as e:
402
+ error_console.print(f"[red]Py API error:[/red] {e}")
403
+ sys.exit(3)
404
+ except Exception as e:
405
+ error_console.print(f"[red]Error:[/red] {e}")
406
+ if verbose:
407
+ error_console.print_exception()
408
+ sys.exit(4)
409
+
410
+
411
+ if __name__ == "__main__":
412
+ main()
@@ -0,0 +1,237 @@
1
+ # Copyright (c) 2025, Steve Morin
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy of
4
+ # this software and associated documentation files (the "Software"), to deal in
5
+ # the Software without restriction, including without limitation the rights to
6
+ # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
7
+ # the Software, and to permit persons to whom the Software is furnished to do so,
8
+ # subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in all
11
+ # copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
15
+ # FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
16
+ # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
17
+ # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18
+ # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19
+
20
+ [project]
21
+ name = "py_launch_blueprint"
22
+ # ITM-070 — static version (ADR-06 cutover). release-please bumps this.
23
+ version = "1.1.3"
24
+ description = "CLI tools for interacting with Py, including project search functionality"
25
+ readme = "README.md"
26
+ requires-python = ">=3.12"
27
+ license = "MIT" # PEP 639 license expression (ITM-070, round-19).
28
+ authors = [{ name = "Steve Morin", email = "steve.morin@gmail.com" }]
29
+ classifiers = [
30
+ # ITM-070 — round-19. py3.12+ only (per ITM-033 floor); MIT classifier
31
+ # intentionally omitted (PEP 639 license expression above is the single
32
+ # source of truth — duplication would drift).
33
+ "Development Status :: 4 - Beta",
34
+ "Intended Audience :: Developers",
35
+ "Operating System :: OS Independent",
36
+ "Programming Language :: Python :: 3",
37
+ "Programming Language :: Python :: 3.12",
38
+ "Programming Language :: Python :: 3.13",
39
+ "Programming Language :: Python :: 3 :: Only",
40
+ "Topic :: Software Development :: Libraries :: Python Modules",
41
+ ]
42
+ dependencies = [
43
+ "click>=8.1.0",
44
+ "questionary>=2.0.0",
45
+ "python-dotenv>=1.0.0",
46
+ "thefuzz>=0.19.0",
47
+ "python-Levenshtein>=0.21.0", # For better performance with thefuzz
48
+ "pyperclip>=1.8.0",
49
+ "requests>=2.31.0",
50
+ "rich>=13.0.0",
51
+ ]
52
+
53
+ # ITM-063 — PEP 735 dependency-groups (round-13 decision). Replaces
54
+ # [project.optional-dependencies] dev+docs. Install via `uv sync --group <name>`.
55
+ [dependency-groups]
56
+ dev = [
57
+ "pytest>=7.0.0",
58
+ "pytest-cov>=4.1.0",
59
+ "mypy>=1.0.0",
60
+ "ty>=0.0.1a16", # per ADR-03 (pre-1.0; bump as needed)
61
+ "ruff>=0.1.0",
62
+ "types-requests",
63
+ "types-Pygments",
64
+ "cogapp",
65
+ ]
66
+
67
+ docs = [
68
+ "sphinx>=7.0.0",
69
+ "sphinx-rtd-theme",
70
+ "furo",
71
+ "myst-parser",
72
+ "sphinx-autodoc-typehints",
73
+ "cogapp",
74
+ "sphinx-copybutton",
75
+ "sphinx-autobuild",
76
+ "sphinxext-opengraph", # https://github.com/wpilibsuite/sphinxext-opengraph
77
+ ]
78
+
79
+
80
+ [project.scripts]
81
+ py-projects = "py_launch_blueprint.projects:main"
82
+
83
+ # ITM-072 — package metadata URLs (round 19).
84
+ [project.urls]
85
+ Homepage = "https://github.com/smorinlabs/py-launch-blueprint"
86
+ Repository = "https://github.com/smorinlabs/py-launch-blueprint"
87
+ Documentation = "https://py-launch-blueprint.readthedocs.io/en/latest/"
88
+ Changelog = "https://github.com/smorinlabs/py-launch-blueprint/blob/main/CHANGELOG.md"
89
+ Issues = "https://github.com/smorinlabs/py-launch-blueprint/issues"
90
+
91
+ # ITM-073 — uv_build (ADR-06 cutover; replaces Hatchling + hatch-vcs).
92
+ [build-system]
93
+ requires = ["uv_build>=0.5,<1.0"]
94
+ build-backend = "uv_build"
95
+
96
+ # ITM-074 — uv_build module configuration.
97
+ # Template uses a flat layout (package at repo root, not src/) — must set
98
+ # module-root = "" so uv_build doesn't expect src/py_launch_blueprint/.
99
+ [tool.uv.build-backend]
100
+ module-name = "py_launch_blueprint"
101
+ module-root = ""
102
+
103
+ [tool.ruff]
104
+ # ITM-018 reconciled config (round-2). Merge: template's stricter rule
105
+ # selection + source's ignore rationale. target-version reflects ITM-033
106
+ # Python-floor bump.
107
+ target-version = "py312"
108
+ line-length = 88
109
+
110
+ lint.select = [
111
+ "E", # pycodestyle errors
112
+ "F", # pyflakes
113
+ "I", # isort
114
+ "B", # flake8-bugbear
115
+ "C4", # flake8-comprehensions
116
+ "UP", # pyupgrade
117
+ "N", # pep8-naming
118
+ "RUF", # Ruff-specific rules
119
+ "W", # pycodestyle warnings
120
+ "YTT", # flake8-2020
121
+ "S", # flake8-bandit
122
+ ]
123
+
124
+ # Source's ignore rationale (round-2): line-length handled by formatter;
125
+ # template-applicable subset adopted (B904/B007 omitted — source-specific
126
+ # patterns that don't apply here).
127
+ lint.ignore = [
128
+ "E501", # line too long (formatter owns this)
129
+ "W293", # whitespace on blank line (formatter owns trim_trailing)
130
+ ]
131
+
132
+ # Allow autofix behavior for specific rules
133
+ fix = true
134
+ lint.unfixable = [] # Rules that should not be fixed automatically
135
+
136
+ # Exclude files/folders
137
+ exclude = [
138
+ ".git",
139
+ ".venv",
140
+ "__pycache__",
141
+ "build",
142
+ "dist",
143
+ "docs/source/conf.py",
144
+ "py_launch_blueprint/_version.py",
145
+ ]
146
+ # Per-file-ignores
147
+ [tool.ruff.lint.pycodestyle]
148
+ max-line-length = 88
149
+ [tool.ruff.lint.per-file-ignores]
150
+ "__init__.py" = ["F401"] # Ignore unused imports in __init__.py files
151
+ "tests/*" = ["S101", "S105", "S106"] # Ignore assert statements in tests
152
+ "init/tests/**" = ["S101", "S105", "S106"] # same exemption — pytest convention
153
+ "init/**" = ["S603", "S607"] # init/ wraps gh/just/uv via subprocess; that's the point
154
+ "skill/**" = ["S101"] # skill/ has illustrative example assertions in markdown
155
+ # S101: assert statements removed under -O — security risk if assert is the only gate.
156
+ # S105/S106: hardcoded password strings/variables in code.
157
+ # S603/S607: subprocess module use + partial-path executables — init/ tooling wraps gh/just/uv intentionally.
158
+
159
+ # ITM-018 — explicit format config (round-2; mirrors source). Values match Ruff
160
+ # defaults but being explicit prevents silent drift if defaults change.
161
+ [tool.ruff.format]
162
+ quote-style = "double"
163
+ indent-style = "space"
164
+ line-ending = "auto"
165
+
166
+ # ITM-027 — bandit config (round 3). Tests legitimately use `assert`
167
+ # (pytest convention) — exclude_dirs covers tests/.
168
+ [tool.bandit]
169
+ exclude_dirs = ["tests", "init/tests", ".venv", "build", "dist"]
170
+ skips = [] # No global skips; add with rationale only.
171
+
172
+ [tool.pytest.ini_options]
173
+ testpaths = ["tests"]
174
+ python_files = ["test_*.py"]
175
+ # Marker taxonomy (ITM-046, round-9 decision).
176
+ # `live` = requires external services; `slow` = takes >1s.
177
+ # Default `addopts` excludes both — run full suite with `pytest -m ""`.
178
+ markers = [
179
+ "live: requires external services",
180
+ "slow: takes >1s",
181
+ ]
182
+ addopts = "-m 'not live and not slow'"
183
+ strict_markers = true
184
+
185
+ # ITM-015 — codespell. US English baseline (default builtin="clear,rare"); empty
186
+ # ignore list — add terms only when intentional. Decided round 9.
187
+ [tool.codespell]
188
+ skip = ".git,.venv,build,dist,node_modules,uv.lock,bun.lock,*.lock,docs/_build,*.svg,*.cast,.ruff_cache,.pytest_cache,.mypy_cache,.ty_cache,*.log,skill/optimization-workspace"
189
+ # *.log + skill/optimization-workspace: optimizer logs contain LLM-truncated
190
+ # text artifacts that aren't real typos; skip the whole tree.
191
+ ignore-words-list = "ans"
192
+ # ans: variable name used in prompt-handling code; codespell wants to "fix"
193
+ # it to "and". Whitelist to keep the short variable name.
194
+ check-filenames = true
195
+ check-hidden = false
196
+
197
+ [tool.mypy]
198
+ # Python version (ITM-033 — moves to 3.12; mypy block removed entirely
199
+ # once ITM-026 ty switch lands).
200
+ python_version = "3.12"
201
+
202
+ # Strict mode
203
+ strict = true
204
+
205
+ # Imports management
206
+ ignore_missing_imports = false
207
+ follow_imports = "normal"
208
+ follow_imports_for_stubs = true
209
+
210
+ # Disallow dynamic typing
211
+ disallow_any_generics = true
212
+ disallow_subclassing_any = true
213
+ disallow_untyped_calls = true
214
+ disallow_untyped_defs = true
215
+ disallow_incomplete_defs = true
216
+ disallow_untyped_decorators = true
217
+
218
+ # None and Optional handling
219
+ no_implicit_optional = true
220
+ strict_optional = true
221
+
222
+ # Warnings
223
+ warn_redundant_casts = true
224
+ warn_unused_ignores = true
225
+ warn_no_return = true
226
+ warn_return_any = true
227
+ warn_unreachable = true
228
+
229
+ # Error messages
230
+ pretty = true
231
+ show_error_codes = true
232
+ show_column_numbers = true
233
+
234
+ # Per-module settings example
235
+ [[tool.mypy.overrides]]
236
+ module = ["tests.*"]
237
+ disallow_untyped_defs = false