diff --git a/.gitignore b/.gitignore index 526fef5..d12e2f2 100644 --- a/.gitignore +++ b/.gitignore @@ -18,4 +18,4 @@ uv.lock # remove if you want to pin versions. .venv #secrets -.env \ No newline at end of file +.env diff --git a/Justfile b/Justfile new file mode 100644 index 0000000..ac00b5a --- /dev/null +++ b/Justfile @@ -0,0 +1,168 @@ +# Set project-wide variables +py_package_name := "py_launch_blueprint" +command_name := "py-projects" +args := " " + + +# Text colors +BLACK := '\033[30m' +RED := '\033[31m' +GREEN := '\033[32m' +YELLOW := '\033[33m' +BLUE := '\033[34m' +MAGENTA := '\033[35m' +CYAN := '\033[36m' +WHITE := '\033[37m' +GRAY := '\033[90m' + +# Background colors +BG_BLACK := '\033[40m' +BG_RED := '\033[41m' +BG_GREEN := '\033[42m' +BG_YELLOW := '\033[43m' +BG_BLUE := '\033[44m' +BG_MAGENTA := '\033[45m' +BG_CYAN := '\033[46m' +BG_WHITE := '\033[47m' + +# Text styles +BOLD := '\033[1m' +DIM := '\033[2m' +ITALIC := '\033[3m' +UNDERLINE := '\033[4m' + +# Reset all styles +NC := '\033[0m' + +# Display a symbol +CHECK := "$(GREEN)✓$(NC)" +CROSS := "$(RED)✗$(NC)" +DASH := "$(GRAY)-$(NC)" + + +# List all available recipes +@default: + just --list --unsorted + +# Check if required tools are installed +@check-deps: + @#!/usr/bin/env sh + if ! command -v uv >/dev/null 2>&1; then echo "uv is not installed"; exit 1; fi + if ! command -v python3 >/dev/null 2>&1; then echo "python3 is not installed"; exit 1; fi + if ! command -v just >/dev/null 2>&1; then echo "just is not installed"; exit 1; fi + if ! command -v pre-commit >/dev/null 2>&1; then echo "{{YELLOW}}WARNING: pre-commit is not installed{{NC}}"; fi + echo "All required tools are installed" + +alias c := check-deps + +# Install package in editable mode with dev dependencies +@install-dev: check-deps + uv pip install --editable ".[dev]" + +# Format code +@format: + echo "Running formatters..." + echo " ruff format" + uvx --with-editable . ruff format {{py_package_name}}/ + echo " ruff isort" + uvx --with-editable . ruff check --select I --fix {{py_package_name}}/ + +alias f := format + +# Run linter (code style and quality checks) +@lint: + echo "Running linter..." + echo " ruff" + uvx --with-editable . ruff check {{py_package_name}}/ + +alias l := lint + +# Run type checker +@typecheck: + echo "Running type checker..." + echo " mypy" + uvx --with-editable . mypy {{py_package_name}}/ + +alias tc := typecheck + +# Run tests +@test *options: + uvx --with-editable . pytest {{options}} + +alias t := test + +# Run all checks +@check: test lint typecheck + echo "All checks passed!" + +alias ca := check + +# Run package command. +@run cmd=command_name *args=args: + uvx --with-editable . {{cmd}} {{args}} + +# Build package +@build: check + uvx --with-editable . build + +alias b := build + +# Set up pre-commit hooks +@pre-commit-setup: + uvx --with-editable . pre-commit install + +# Run all pre-commit Hooks +@pre-commit-run: + uvx --with-editable . pre-commit run --all + +alias pc := pre-commit-run + +# Check installed package version +@version cmd=command_name: + {{cmd}} --version + +# Clean up temporary files and caches +@clean: + rm -rf .pytest_cache + rm -rf .mypy_cache + rm -rf .ruff_cache + rm -rf .coverage + rm -rf htmlcov + rm -rf dist + rm -rf build + rm -rf *.egg-info + +# Alternative commands when virtual environment is activated: +# These commands can be used after running 'source .venv/bin/activate' + +# Setup virtual environment +@setup-venv: + python3 -m venv .venv + echo "Note: After setup, activate the virtual environment with:" + echo " source .venv/bin/activate # On Unix/macOS" + echo " .venv\Scripts\activate # On Windows" + +# Install in development mode +@install-dev-pip: + pip install --editable ".[dev]" + +# Format code (includes ruff format and import sorting) +@format-pip: + echo "Running linter..." + echo " ruff" + ruff format {{py_package_name}}/ + +# Run linter (code style and quality checks) +@lint-pip: + ruff check {{py_package_name}}/ + ruff check --select I --fix {{py_package_name}}/ + +# Run type checker +@typecheck-pip: + echo "Running type checker..." + echo " mypy" + mypy {{py_package_name}}/ + +# Run tests +@test-pip *options: + pytest {{options}} \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..81e4a87 --- /dev/null +++ b/Makefile @@ -0,0 +1,135 @@ +SHELL := /bin/zsh + +# Text colors +BLACK := \033[30m +RED := \033[31m +GREEN := \033[32m +YELLOW := \033[33m +BLUE := \033[34m +MAGENTA := \033[35m +CYAN := \033[36m +WHITE := \033[37m +GRAY := \033[90m + +# Background colors +BG_BLACK := \033[40m +BG_RED := \033[41m +BG_GREEN := \033[42m +BG_YELLOW := \033[43m +BG_BLUE := \033[44m +BG_MAGENTA := \033[45m +BG_CYAN := \033[46m +BG_WHITE := \033[47m + +# Text styles +BOLD := \033[1m +DIM := \033[2m +ITALIC := \033[3m +UNDERLINE := \033[4m + +# Reset +NC := \033[0m + +CHECK := $(GREEN)✓$(NC) +CROSS := $(RED)✗$(NC) +DASH := $(GRAY)-$(NC) + +.PHONY: all check install-uv install-just set-path help + +all: help + +## `make check` Example Output + +### Success case +# Checking dependencies... +# === System Requirements Status === +# [✓] Just +# [✓] uv +# All dependencies are installed! + +### Failure case +# Checking dependencies... +# === System Requirements Status === +# [✓] just +# [✗] uv (make install-uv) + +# Found 1 missing deps: uv +# make: *** [check] Error 1 + +check: ## Check system requirements + @echo "Checking dependencies..." + @echo "=== System Requirements Status ===" + @ERROR_COUNT=0; \ + CHECK_CMD_NAME="just"; \ + CHECK_CMD_INSTALL="install-just"; \ + if [ $(shell command -v just >/dev/null 2>&1 && echo "0" || echo "1" ) -eq 0 ] ; then \ + printf "[$(CHECK)] $${CHECK_CMD_NAME}\n"; \ + else \ + printf "[$(CROSS)] $${CHECK_CMD_NAME} ($(GREEN)make $${CHECK_CMD_INSTALL}$(NC))\n"; \ + ERROR_COUNT=$$((ERROR_COUNT + 1)); \ + MISSING_DEPS="$${CHECK_CMD_NAME}$${MISSING_DEPS:+,} $${MISSING_DEPS}"; \ + fi; \ + CHECK_CMD_NAME="uv"; \ + CHECK_CMD_INSTALL="install-uv"; \ + if [ $(shell command -v uv >/dev/null 2>&1 && echo "0" || echo "1" ) -eq 0 ] ; then \ + printf "[$(CHECK)] $${CHECK_CMD_NAME}\n"; \ + else \ + printf "[$(CROSS)] $${CHECK_CMD_NAME} ($(GREEN)make $${CHECK_CMD_INSTALL}$(NC))\n"; \ + ERROR_COUNT=$$((ERROR_COUNT + 1)); \ + MISSING_DEPS="$${CHECK_CMD_NAME}$${MISSING_DEPS:+,} $${MISSING_DEPS}"; \ + fi; \ + if [ "$${ERROR_COUNT}" = "0" ]; then \ + echo -e "$(GREEN)All dependencies are installed!$(NC)"; \ + else \ + echo ""; \ + echo -e "$(RED)Found $$ERROR_COUNT missing deps: $${MISSING_DEPS}$(NC)"; \ + exit 1; \ + fi + +install-just: ## Print install just command and where to find install options + @echo "just installation command:" + @echo -e "${CYAN}curl --proto '=https' --tlsv1.2 -sSf https://just.systems/install.sh | bash -s -- --to ~/bin${NC}" + @echo "NOTE:change ~/bin to the desired installation directory" + @echo "Find other install options here: https://github.com/casey/just" + @echo "To setup just PATH, run: SET_PATH=$(HOME)/bin make set-path" + +install-uv: ## Print install uv command and where to find install options + @echo "uv installation command:" + @echo -e "${CYAN}curl -LsSf https://astral.sh/uv/install.sh | sh${NC}" + @echo "Find other install options here: https://docs.astral.sh/uv/getting-started/installation/" + @echo "To setup uv PATH, run: SET_PATH=$(HOME)/.local/binmake set-path" + +set-path: ## Add SET_PATH to PATH in .zshenv if not already present + @if [ -z "$(SET_PATH)" ]; then \ + echo -e "$(RED)Error: SET_PATH must be set$(NC)"; \ + echo -e "Usage: $(BLUE)make test2 SET_PATH=/your/path$(NC)"; \ + exit 1; \ + fi; \ + if ! awk -v path="$(SET_PATH)" ' \ + BEGIN {found=0} \ + /^export PATH=/ { \ + if (index($$0, path) > 0) { \ + found=1; \ + exit; \ + } \ + } \ + END {exit !found}' "$(HOME)/.zshenv"; then \ + echo "export PATH=\"\$$PATH:$(SET_PATH)\"" >> "$(HOME)/.zshenv"; \ + echo -e "$(GREEN)Added PATH entry:$(NC) \$$PATH:$(SET_PATH)"; \ + echo -e "Run $(BLUE)source $(HOME)/.zshenv$(NC) to apply changes"; \ + else \ + echo -e "$(CHECK) PATH already contains $(SET_PATH)"; \ + fi + +help: ## The help command - this command + @echo "" + @echo "Purpose of this Makefile:" + @echo -e " To make it easy to check for and install" + @echo -e " the main dependencies because almost everyone has $(GREEN)make$(NC)" + @echo "" + @echo "Usage: make [target]" + @echo "" + @echo "Targets:" + @grep -h -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "$(CYAN)%-30s$(NC) %s\n", $$1, $$2}' + @echo "" + diff --git a/README.md b/README.md index eb0cf68..06e2a2c 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,7 @@ Py Launch Blueprint eliminates the setup friction in Python projects by providin - **Git Hooks**: Automated code quality checks before commits ### 🎯 Perfect For +- Professionals looking for a production-ready Python project - Teams wanting a standardized Python development environment - Projects requiring maintainable, type-safe code - Developers who value clean, consistent code style @@ -35,6 +36,16 @@ Py Launch Blueprint eliminates the setup friction in Python projects by providin Start your next Python project with confidence, knowing you're building on a foundation of best practices and modern development tools. +## Philosophy +- **Heavily Documented**: Every detail is explained, making it easy to understand, even for folks new to the project, tools, or new to Python. +- **Pragmatic**: Focuses on practical best practices instead of strict rules +- **Modular**: Designed to be easy to remove features, replace with alternatives or add new ones + +## Why Open Source? + +- **Transparent**: Every detail is documented, making it easy to understand and contribute +- **Collaborative**: A community of developers is formed, fostering a shared learning environment + ## Contributing 1. Fork the repository @@ -66,36 +77,34 @@ py-utils/ # Example CLI Tool Usage [Example CLI: py-projects](EXAMPLECLI.md) -## Development +# Development -### Setup Development Environment +## Dependencies Project requires Python 3.10+ (which is also specified inside [.python-version](.python-version) file) and [uv](https://docs.astral.sh/uv/getting-started/installation/) installed. -```bash +### Setup Development Environment -# Create and activate a virtual environment if needed -uv venv -source .venv/bin/activate # On Unix/macOS +There are two options for setting up the development environment: +- Using [uv](https://docs.astral.sh/uv/getting-started/installation/): +- Using [pip](https://pip.pypa.io/en/stable/installation/): -# Install the package in editable mode with development dependencies -uv pip install --editable ".[dev]" +It depends on the tool you choose, but both offer a convenient way to install the package in editable mode with development dependencies. UV is recommended as it offers much greater speed and a lot of features and tools out of the box. -# Check the installed package -py-projects --version +#### Using uv: -# (Optional) Setup Pre-Commit Hook -uvx --with-editable . pre-commit install +```bash +# This command creates a live development installation that allows you to modify the code without reinstalling while also installing additional development tools (like pytest, mypy, etc.) specified in your project's dev dependencies. +uv pip install --editable ".[dev]" -# Run development tools directly (no need for 'uv pip run') -pytest -mypy py_launch_blueprint/ -ruff check py_launch_blueprint/ +# Format the code +uvx ruff format py_launch_blueprint/ -# Or run with our the virtual environment +# Run linter +uvx ruff check py_launch_blueprint/ -# (Optional) Setup Pre-Commit Hook -uvx --with-editable . pre-commit install +# Run type checker +uvx --with-editable . mypy py_launch_blueprint/ # Run tests uvx --with-editable . pytest @@ -103,25 +112,114 @@ uvx --with-editable . pytest # Run tests with coverage uvx --with pytest-cov --with-editable . pytest --cov=py_launch_blueprint.projects --cov-report=term-missing -# Run type checker -uvx --with-editable . mypy py_launch_blueprint/ +# Run command +uvx --with-editable . --from py_launch_blueprint py-projects +``` -# Format the code -uvx ruff format py_launch_blueprint/ +##### (Optional) Pre-Commit Hooks with uv + +```bash +# Setup Pre-Commit Hook +uvx --with-editable . pre-commit install #Run all pre-Commit Hooks uvx pre-commit run --all-files +``` -# Run linter -uvx ruff check py_launch_blueprint/ +#### Using pip: -# Run command -uvx --with-editable . --from py_launch_blueprint py-projects +```bash + +# Create and activate a virtual environment if needed +python3 -m venv .venv +source .venv/bin/activate # On Unix/macOS +.venv\Scripts\activate # On Windows + +# Install the package in editable mode with development dependencies +pip install --editable ".[dev]" + +# Run development tools directly (no need for 'uv pip run') +ruff format py_launch_blueprint/ +ruff check py_launch_blueprint/ +mypy py_launch_blueprint/ +pytest --cov=py_launch_blueprint.projects --cov-report=term-missing + +# Check the installed package cli tool version +py-projects --version +``` + +##### (Optional) Pre-Commit Hooks with pip + +```bash +# Setup Pre-Commit Hook +pre-commit install + +#Run all pre-Commit Hooks +pre-commit run --all-files +``` + + +### Using the Justfile + +This project includes a `Justfile` that provides convenient commands for common development tasks. [Just](https://github.com/casey/just) is a handy command runner that helps standardize commands across your project. + +To use these commands, first [install Just](https://github.com/casey/just#installation). You can see all available commands by running: + +```bash +just --list +``` + +Here are some commonly used commands (this is just a subset of all available commands): + +```bash +# Setup your development environment +just setup + +# Format code (includes ruff format and import sorting) +just format + +# Run linter (code style and quality checks) +just lint + +# Run type checker +just typecheck + +# Run tests +just test + +# Run all checks (tests, linting, and type checking) +just check + +# Check installed package version +just version + +# Clean up temporary files and caches +just clean + +# Set up pre-commit hooks +just pre-commit-setup + +# Build the package +just build + +# Install in development mode +just install-dev ``` -# Notes on tool choices +When your virtual environment is activated, you can also use direct commands without uvx: + +```bash +just format-pip # Run formatter directly +just lint-pip # Run linter directly +just typecheck-pip # Run type checker directly +just test-pip # Run tests directly with pytest +``` + +The Justfile standardizes common development tasks and provides a consistent interface for both uvx and direct command execution. + +## Notes on tool choices ## Ruff Ruff is a high-performance linter and code formatter for Python. It combines multiple tools into one, offering faster performance and comprehensive functionality compared to traditional Python tools. @@ -250,27 +348,12 @@ def process(handler: Handler) -> None: ... ``` -## Recommended Extensions - -This project comes with recommended VS Code extensions to enhance your development experience. When you open this project in VS Code, you'll be prompted to install these extensions: - -- **Python** (`ms-python.python`): Essential Python language support -- **Ruff** (`charliermarsh.ruff`): Fast Python linter and formatter -- **MyPy** (`matangover.mypy`): Static type checking for Python -- **Even Better TOML** (`tamasfe.even-better-toml`): Improved TOML file support -- **YAML** (`redhat.vscode-yaml`): YAML language support -- **GitLens** (`eamodio.gitlens`): Enhanced Git integration -- **Code Spell Checker** (`streetsidesoftware.code-spell-checker`): Catch common spelling mistakes - -These extensions are configured to work seamlessly with the project's setup and will help maintain code quality standards. VS Code will automatically suggest installing these extensions when you open the project. - ## Precommit hooks Hooks are designed to maintain clean, consistent, and error-free code and configuration files. They save time by catching issues before they make it into your repository. Following pre-commit hooks are used in this repo - - `check-yaml` checks if all YAML files in your repository are valid, - `end-of-file-fixer` ensures every file in your repository ends with a single newline character, - `trailing-whitespace` removes trailing spaces at the end of lines in your files, @@ -337,9 +420,10 @@ This project comes with recommended VS Code extensions to enhance your developme - **Python** (`ms-python.python`): Essential Python language support - **Ruff** (`charliermarsh.ruff`): Fast Python linter and formatter - **MyPy** (`matangover.mypy`): Static type checking for Python +- **Pylance** (`ms-python.vscode-pylance`): Intelligent Python language support - **Even Better TOML** (`tamasfe.even-better-toml`): Improved TOML file support - **YAML** (`redhat.vscode-yaml`): YAML language support - **GitLens** (`eamodio.gitlens`): Enhanced Git integration - **Code Spell Checker** (`streetsidesoftware.code-spell-checker`): Catch common spelling mistakes -These extensions are configured to work seamlessly with the project's setup and will help maintain code quality standards. VS Code will automatically suggest installing these extensions when you open the project. \ No newline at end of file +These extensions are configured to work seamlessly with the project's setup and will help maintain code quality standards. VS Code will automatically suggest installing these extensions when you open the project.