Skip to content

Commit dcf6c3d

Browse files
committed
feat: initial project setup with modern dev tools
1 parent 826559a commit dcf6c3d

File tree

3 files changed

+50
-31
lines changed

3 files changed

+50
-31
lines changed

README.md

Lines changed: 50 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,8 @@ Install modern development tools with Ruff replacing Black, isort, and Flake8:
117117
pip install \
118118
ruff \
119119
mypy \
120+
typer \
121+
"click==8.1.8" \ # Pin click to 8.1.8 as a workaround for Typer (see note)
120122
pytest pytest-cov pytest-asyncio \
121123
pre-commit \
122124
pip-tools \
@@ -131,6 +133,10 @@ pip install \
131133
docformatter \
132134
types-requests types-setuptools
133135
```
136+
Note on Typer/Click Versioning:
137+
As of May 2025, Typer (e.g., version 0.15.3+) has a known incompatibility with Click versions 8.2.0 and higher. This can lead to TypeErrors during help message generation (e.g., Parameter.make_metavar() missing 1 required positional argument: 'ctx') or when Click tries to format error messages. This issue has been observed on Python 3.11+ including Python 3.13.
138+
139+
A common workaround, as discussed in the Typer community (e.g., GitHub issue #1215 for fastapi/typer), is to pin the click dependency to a version known to be compatible, such as click==8.1.8. Keep an eye on Typer's release notes for official fixes and updated Click compatibility (e.g., related to Typer PRs #1145, #1218).
134140

135141
## Step 5: Configure Tools via `pyproject.toml`
136142

@@ -152,20 +158,30 @@ readme = "README.md"
152158
requires-python = ">=3.10"
153159
dependencies = [
154160
# Add your project dependencies here
161+
# If Typer is a direct dependency of your project itself, add it here too:
162+
# "typer>=0.15.3", # Or your target Typer version
163+
# "click==8.1.8", # And the pinned Click version
155164
]
156165

157166
[project.optional-dependencies]
158167
dev = [
159-
"ruff>=0.2.0",
160-
"mypy>=1.7.0",
161-
"pytest>=7.4.0",
162-
"pytest-cov>=4.1.0",
163-
"pytest-asyncio>=0.21.0",
164-
"pre-commit>=3.6.0",
165-
"pip-tools>=7.3.0",
166-
"commitizen>=3.13.0",
167-
"bandit>=1.7.6",
168-
"safety>=2.4.0",
168+
"ruff>=0.2.0", # Linter/Formatter
169+
"mypy>=1.7.0", # Static Type Checker
170+
"typer>=0.15.3", # For CLIs (using your current version or a target one)
171+
"click==8.1.8", # Pinned version for Typer compatibility
172+
"pytest>=7.4.0", # Testing framework
173+
"pytest-cov>=4.1.0", # Test coverage
174+
"pytest-asyncio>=0.21.0", # For testing async code with pytest
175+
"pre-commit>=3.6.0", # Git hooks manager
176+
"pip-tools>=7.3.0", # For dependency management (compiling requirements)
177+
"commitizen>=3.13.0", # For conventional commits
178+
"bandit>=1.7.6", # Security linter
179+
"safety>=2.4.0", # Checks for vulnerable dependencies
180+
"prettier", # Optional: if you still use it for non-Python files
181+
"autopep8", # Optional: if used for specific cases not covered by Ruff
182+
"docformatter", # Optional: if Ruff's docstring formatting isn't sufficient
183+
"types-requests", # Example: Stubs for type checking requests library
184+
"types-setuptools", # Example: Stubs for type checking setuptools
169185
]
170186

171187
# --- Tool Configurations ---
@@ -249,7 +265,7 @@ convention = "google" # Use Google style docstrings
249265
"__init__.py" = ["F401"] # Allow unused imports in __init__.py
250266

251267
[tool.mypy]
252-
python_version = "3.10"
268+
python_version = "3.10" # Or your target Python version
253269
warn_return_any = true
254270
warn_unused_configs = true
255271
disallow_untyped_defs = true
@@ -264,7 +280,7 @@ strict_equality = true
264280
pretty = true
265281
show_column_numbers = true
266282
show_error_codes = true
267-
ignore_missing_imports = true
283+
ignore_missing_imports = true # Can be helpful initially
268284

269285
# Exclude paths from mypy
270286
exclude = [
@@ -310,14 +326,15 @@ exclude_lines = [
310326

311327
[tool.bandit]
312328
exclude_dirs = ["tests", "venv", ".venv"]
313-
skips = ["B101", "B601"]
329+
skips = ["B101", "B601"] # B101: assert_used, B601: paramiko_calls
314330

315331
[tool.commitizen]
316332
name = "cz_conventional_commits"
317-
version = "0.1.0"
333+
version = "0.1.0" # This should match your [project] version
318334
tag_format = "v$version"
319335
version_files = [
320336
"pyproject.toml:version",
337+
# "src/project_name/__init__.py:__version__" # If you store version in __init__.py too
321338
]
322339
```
323340

@@ -329,8 +346,8 @@ Create `.pre-commit-config.yaml`:
329346
# .pre-commit-config.yaml
330347
repos:
331348
# Basic pre-commit hooks
332-
- repo: https://github.com/pre-commit/pre-commit-hooks
333-
rev: v4.5.0
349+
- repo: [https://github.com/pre-commit/pre-commit-hooks](https://github.com/pre-commit/pre-commit-hooks)
350+
rev: v4.5.0 # Or your chosen version
334351
hooks:
335352
- id: trailing-whitespace
336353
- id: end-of-file-fixer
@@ -343,41 +360,41 @@ repos:
343360
- id: check-ast
344361

345362
# Ruff linter and formatter (replaces Black, isort, Flake8)
346-
- repo: https://github.com/astral-sh/ruff-pre-commit
347-
rev: v0.2.0
363+
- repo: [https://github.com/astral-sh/ruff-pre-commit](https://github.com/astral-sh/ruff-pre-commit)
364+
rev: v0.2.0 # Or your chosen version
348365
hooks:
349366
# Lint with Ruff
350367
- id: ruff
351-
args: [ --fix ]
368+
args: [ --fix, --exit-non-zero-on-fix ]
352369
# Format with Ruff
353370
- id: ruff-format
354371

355372
# Type checking with mypy
356-
- repo: https://github.com/pre-commit/mirrors-mypy
357-
rev: v1.8.0
373+
- repo: [https://github.com/pre-commit/mirrors-mypy](https://github.com/pre-commit/mirrors-mypy)
374+
rev: v1.8.0 # Or your chosen version
358375
hooks:
359376
- id: mypy
360377
additional_dependencies: [types-all]
361378
args: [--config-file=pyproject.toml]
362379

363380
# Security checks with bandit
364-
- repo: https://github.com/PyCQA/bandit
365-
rev: 1.7.6
381+
- repo: [https://github.com/PyCQA/bandit](https://github.com/PyCQA/bandit)
382+
rev: 1.7.6 # Or your chosen version
366383
hooks:
367384
- id: bandit
368385
args: [-c, pyproject.toml]
369386
additional_dependencies: ["bandit[toml]"]
370387

371388
# Commit message linting
372-
- repo: https://github.com/commitizen-tools/commitizen
373-
rev: 3.13.0
389+
- repo: [https://github.com/commitizen-tools/commitizen](https://github.com/commitizen-tools/commitizen)
390+
rev: 3.13.0 # Or your chosen version
374391
hooks:
375392
- id: commitizen
376393
stages: [commit-msg]
377394

378395
# Optional: Docstring formatter
379-
- repo: https://github.com/PyCQA/docformatter
380-
rev: v1.7.5
396+
- repo: [https://github.com/PyCQA/docformatter](https://github.com/PyCQA/docformatter)
397+
rev: v1.7.5 # Or your chosen version
381398
hooks:
382399
- id: docformatter
383400
args: [--in-place, --wrap-summaries=88, --wrap-descriptions=88]
@@ -444,11 +461,13 @@ Create a `requirements.txt` or use pip-tools for better dependency management:
444461

445462
```bash
446463
# Using pip-tools for dependency management
447-
pip-tools compile pyproject.toml
448-
pip-tools sync requirements.txt
464+
pip-tools compile --output-file requirements.txt pyproject.toml
465+
pip-tools compile --extra dev --output-file requirements-dev.txt pyproject.toml
466+
pip-tools sync requirements.txt requirements-dev.txt
449467

450-
# Or create requirements.txt manually
451-
pip freeze > requirements.txt
468+
# Or create requirements.txt manually for runtime, and install dev tools separately
469+
# pip freeze > requirements.txt (for runtime)
470+
# pip install ruff mypy typer "click==8.1.8" pytest pytest-cov pytest-asyncio pre-commit pip-tools commitizen bandit safety #... (for dev)
452471
```
453472

454473
## Step 10: Initial Commit

src/__init__.py

Whitespace-only changes.

src/my_package/__init__.py

Whitespace-only changes.

0 commit comments

Comments
 (0)