|
|
|
|
|
|
|
|
|
|
|
|
|
|
- Understand modern Python project layouts |
|
|
- Learn about `pyproject.toml` and `pixi.toml` configuration files |
|
|
- Set up proper directory structure for CLI applications |
|
|
- Implement version control best practices |
|
|
|
|
|
|
|
|
|
|
|
There are two main approaches to organizing Python projects: |
|
|
|
|
|
|
|
|
|
|
|
``` |
|
|
my-cli/ |
|
|
βββ my_cli/ |
|
|
β βββ __init__.py |
|
|
β βββ cli.py |
|
|
β βββ utils.py |
|
|
βββ tests/ |
|
|
βββ pyproject.toml |
|
|
βββ README.md |
|
|
``` |
|
|
|
|
|
|
|
|
|
|
|
``` |
|
|
my-cli/ |
|
|
βββ src/ |
|
|
β βββ my_cli/ |
|
|
β βββ __init__.py |
|
|
β βββ cli.py |
|
|
β βββ utils.py |
|
|
βββ tests/ |
|
|
βββ pyproject.toml |
|
|
βββ pixi.toml |
|
|
βββ README.md |
|
|
``` |
|
|
|
|
|
**Why src layout?** |
|
|
- Prevents accidental imports from development directory |
|
|
- Clearer separation between source and other files |
|
|
- Better for testing and packaging |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
The modern standard for Python project metadata: |
|
|
|
|
|
```toml |
|
|
[build-system] |
|
|
requires = ["hatchling"] |
|
|
build-backend = "hatchling.build" |
|
|
|
|
|
[project] |
|
|
name = "my-cli-tool" |
|
|
version = "0.1.0" |
|
|
description = "An AI-powered CLI tool" |
|
|
authors = [{name = "Your Name", email = "you@example.com"}] |
|
|
readme = "README.md" |
|
|
requires-python = ">=3.11" |
|
|
dependencies = [ |
|
|
"typer>=0.9", |
|
|
"rich>=13.0", |
|
|
] |
|
|
|
|
|
[project.scripts] |
|
|
my-cli = "my_cli.cli:app" |
|
|
|
|
|
[tool.ruff] |
|
|
line-length = 100 |
|
|
target-version = "py311" |
|
|
|
|
|
[tool.mypy] |
|
|
python_version = "3.11" |
|
|
strict = true |
|
|
``` |
|
|
|
|
|
|
|
|
|
|
|
Pixi-specific configuration for environment management: |
|
|
|
|
|
```toml |
|
|
[project] |
|
|
name = "my-cli-tool" |
|
|
version = "0.1.0" |
|
|
description = "An AI-powered CLI tool" |
|
|
channels = ["conda-forge"] |
|
|
platforms = ["linux-64", "osx-64", "win-64"] |
|
|
|
|
|
[dependencies] |
|
|
python = ">=3.11" |
|
|
typer = ">=0.9" |
|
|
rich = ">=13.0" |
|
|
|
|
|
[feature.dev.dependencies] |
|
|
pytest = "*" |
|
|
ruff = "*" |
|
|
mypy = "*" |
|
|
black = "*" |
|
|
|
|
|
[environments] |
|
|
default = [] |
|
|
dev = ["dev"] |
|
|
|
|
|
[tasks] |
|
|
start = "python -m my_cli.cli" |
|
|
test = "pytest tests/" |
|
|
lint = "ruff check src/" |
|
|
format = "black src/ tests/" |
|
|
``` |
|
|
|
|
|
|
|
|
|
|
|
Here's a complete, production-ready project structure: |
|
|
|
|
|
``` |
|
|
my-cli-tool/ |
|
|
βββ .git/ |
|
|
βββ .gitignore |
|
|
βββ .vscode/ |
|
|
β βββ settings.json |
|
|
βββ src/ |
|
|
β βββ my_cli/ |
|
|
β βββ __init__.py |
|
|
β βββ cli.py |
|
|
β βββ commands/ |
|
|
β β βββ __init__.py |
|
|
β β βββ organize.py |
|
|
β β βββ stats.py |
|
|
β βββ core/ |
|
|
β β βββ __init__.py |
|
|
β β βββ processor.py |
|
|
β βββ utils/ |
|
|
β βββ __init__.py |
|
|
β βββ helpers.py |
|
|
βββ tests/ |
|
|
β βββ __init__.py |
|
|
β βββ conftest.py |
|
|
β βββ test_cli.py |
|
|
β βββ test_core.py |
|
|
βββ docs/ |
|
|
β βββ README.md |
|
|
βββ .gitignore |
|
|
βββ pyproject.toml |
|
|
βββ pixi.toml |
|
|
βββ pixi.lock |
|
|
βββ LICENSE |
|
|
βββ README.md |
|
|
``` |
|
|
|
|
|
|
|
|
|
|
|
Use this script to create the structure: |
|
|
|
|
|
```bash |
|
|
|
|
|
|
|
|
|
|
|
PROJECT_NAME="my-cli-tool" |
|
|
PACKAGE_NAME="my_cli" |
|
|
|
|
|
|
|
|
mkdir -p $PROJECT_NAME/{src/$PACKAGE_NAME/{commands,core,utils},tests,docs,.vscode} |
|
|
|
|
|
|
|
|
touch $PROJECT_NAME/src/$PACKAGE_NAME/__init__.py |
|
|
touch $PROJECT_NAME/src/$PACKAGE_NAME/commands/__init__.py |
|
|
touch $PROJECT_NAME/src/$PACKAGE_NAME/core/__init__.py |
|
|
touch $PROJECT_NAME/src/$PACKAGE_NAME/utils/__init__.py |
|
|
touch $PROJECT_NAME/tests/__init__.py |
|
|
|
|
|
|
|
|
touch $PROJECT_NAME/src/$PACKAGE_NAME/cli.py |
|
|
touch $PROJECT_NAME/README.md |
|
|
touch $PROJECT_NAME/LICENSE |
|
|
|
|
|
echo "Project structure created!" |
|
|
``` |
|
|
|
|
|
Or use pixi to create it: |
|
|
|
|
|
```bash |
|
|
|
|
|
pixi init my-cli-tool |
|
|
cd my-cli-tool |
|
|
|
|
|
|
|
|
pixi add python typer rich |
|
|
|
|
|
|
|
|
mkdir -p src/my_cli/{commands,core,utils} |
|
|
touch src/my_cli/__init__.py |
|
|
touch src/my_cli/cli.py |
|
|
|
|
|
|
|
|
mkdir tests |
|
|
touch tests/__init__.py |
|
|
``` |
|
|
|
|
|
|
|
|
|
|
|
Essential patterns for Python projects: |
|
|
|
|
|
```gitignore |
|
|
|
|
|
__pycache__/ |
|
|
*.py[cod] |
|
|
*$py.class |
|
|
*.so |
|
|
.Python |
|
|
build/ |
|
|
develop-eggs/ |
|
|
dist/ |
|
|
downloads/ |
|
|
eggs/ |
|
|
.eggs/ |
|
|
lib/ |
|
|
lib64/ |
|
|
parts/ |
|
|
sdist/ |
|
|
var/ |
|
|
wheels/ |
|
|
*.egg-info/ |
|
|
.installed.cfg |
|
|
*.egg |
|
|
|
|
|
|
|
|
.env |
|
|
.venv |
|
|
env/ |
|
|
venv/ |
|
|
ENV/ |
|
|
env.bak/ |
|
|
venv.bak/ |
|
|
|
|
|
|
|
|
.pixi/ |
|
|
pixi.lock |
|
|
|
|
|
|
|
|
.vscode/ |
|
|
.idea/ |
|
|
*.swp |
|
|
*.swo |
|
|
*~ |
|
|
|
|
|
|
|
|
.pytest_cache/ |
|
|
.coverage |
|
|
htmlcov/ |
|
|
|
|
|
|
|
|
.DS_Store |
|
|
Thumbs.db |
|
|
``` |
|
|
|
|
|
|
|
|
|
|
|
Initialize Git and make your first commit: |
|
|
|
|
|
```bash |
|
|
|
|
|
git init |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
git add . |
|
|
|
|
|
|
|
|
git commit -m "Initial project structure" |
|
|
|
|
|
|
|
|
gh repo create my-cli-tool --public --source=. --remote=origin |
|
|
git push -u origin main |
|
|
``` |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
```python |
|
|
"""My CLI Tool - An AI-powered command-line application.""" |
|
|
|
|
|
__version__ = "0.1.0" |
|
|
__author__ = "Your Name" |
|
|
__email__ = "you@example.com" |
|
|
|
|
|
|
|
|
from .cli import app |
|
|
|
|
|
__all__ = ["app"] |
|
|
``` |
|
|
|
|
|
|
|
|
|
|
|
1. **Use src layout**: Prevents import issues and improves testing |
|
|
2. **Lock dependencies**: Commit `pixi.lock` for reproducibility |
|
|
3. **Separate concerns**: Use subdirectories for commands, core logic, and utilities |
|
|
4. **Write tests early**: Create test files alongside implementation |
|
|
5. **Document as you go**: Update README with each feature |
|
|
6. **Use type hints**: Enable better IDE support and catch errors early |
|
|
|
|
|
|
|
|
|
|
|
Ask Copilot to help with: |
|
|
|
|
|
```python |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
``` |
|
|
|
|
|
|
|
|
|
|
|
With your project structure in place, you're ready to start building your CLI application. In the next chapter, we'll use Typer to create powerful command-line interfaces. |
|
|
|
|
|
|
|
|
|
|
|
- [Python Packaging Guide](https://packaging.python.org/) |
|
|
- [Pixi Project Configuration](https://pixi.sh/latest/reference/project_configuration/) |
|
|
- [PEP 518 - pyproject.toml](https://peps.python.org/pep-0518/) |
|
|
|