# Modern Python Project Structure ## Learning Objectives - 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 ## Project Layout Options There are two main approaches to organizing Python projects: ### Flat Layout ``` my-cli/ ├── my_cli/ │ ├── __init__.py │ ├── cli.py │ └── utils.py ├── tests/ ├── pyproject.toml └── README.md ``` ### Src Layout (Recommended) ``` 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 ## Essential Configuration Files ### pyproject.toml 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.toml 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/" ``` ## Complete Project Structure Here's a complete, production-ready project structure: ``` my-cli-tool/ ├── .git/ # Git repository ├── .gitignore # Git ignore rules ├── .vscode/ # VS Code settings │ └── settings.json ├── src/ │ └── my_cli/ │ ├── __init__.py # Package initialization │ ├── cli.py # Main CLI entry point │ ├── commands/ # Command modules │ │ ├── __init__.py │ │ ├── organize.py │ │ └── stats.py │ ├── core/ # Core functionality │ │ ├── __init__.py │ │ └── processor.py │ └── utils/ # Utility functions │ ├── __init__.py │ └── helpers.py ├── tests/ │ ├── __init__.py │ ├── conftest.py # Pytest configuration │ ├── test_cli.py │ └── test_core.py ├── docs/ # Documentation │ └── README.md ├── .gitignore ├── pyproject.toml # Python project config ├── pixi.toml # Pixi environment config ├── pixi.lock # Locked dependencies ├── LICENSE # License file └── README.md # Project documentation ``` ## Creating the Structure Use this script to create the structure: ```bash #!/bin/bash # create-project.sh PROJECT_NAME="my-cli-tool" PACKAGE_NAME="my_cli" # Create directories mkdir -p $PROJECT_NAME/{src/$PACKAGE_NAME/{commands,core,utils},tests,docs,.vscode} # Create __init__.py files 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 # Create main files 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 # Initialize with pixi pixi init my-cli-tool cd my-cli-tool # Add Python and dependencies pixi add python typer rich # Create src layout mkdir -p src/my_cli/{commands,core,utils} touch src/my_cli/__init__.py touch src/my_cli/cli.py # Create tests mkdir tests touch tests/__init__.py ``` ## .gitignore Essential patterns for Python projects: ```gitignore # Python __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 # Virtual environments .env .venv env/ venv/ ENV/ env.bak/ venv.bak/ # Pixi .pixi/ pixi.lock # IDEs .vscode/ .idea/ *.swp *.swo *~ # Testing .pytest_cache/ .coverage htmlcov/ # OS .DS_Store Thumbs.db ``` ## Version Control Setup Initialize Git and make your first commit: ```bash # Initialize repository git init # Create .gitignore (use content above) # Use Copilot: "Generate a comprehensive .gitignore for Python projects" # Add files git add . # First commit git commit -m "Initial project structure" # Create GitHub repository (optional) gh repo create my-cli-tool --public --source=. --remote=origin git push -u origin main ``` ## Package Initialization ### src/my_cli/__init__.py ```python """My CLI Tool - An AI-powered command-line application.""" __version__ = "0.1.0" __author__ = "Your Name" __email__ = "you@example.com" # Export main components from .cli import app __all__ = ["app"] ``` ## Best Practices 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 ## Using Copilot for Project Setup Ask Copilot to help with: ```python # In your IDE, write comments like: # "Create a pyproject.toml for a CLI tool with typer and rich dependencies" # "Generate a comprehensive .gitignore for a Python project" # "Create a README template for a CLI application" ``` ## Next Steps 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. ## Resources - [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/)