Initial commit
This commit is contained in:
51
skills/uv/assets/docker_examples/Dockerfile.multi-stage
Normal file
51
skills/uv/assets/docker_examples/Dockerfile.multi-stage
Normal file
@@ -0,0 +1,51 @@
|
||||
# Multi-stage Docker build with uv
|
||||
# Optimized for production deployments with minimal image size
|
||||
|
||||
# Stage 1: Builder
|
||||
FROM python:3.12-slim AS builder
|
||||
|
||||
# Install uv
|
||||
COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv
|
||||
|
||||
# Set working directory
|
||||
WORKDIR /app
|
||||
|
||||
# Copy dependency files
|
||||
COPY pyproject.toml uv.lock ./
|
||||
|
||||
# Create virtual environment and install dependencies
|
||||
# Using --frozen ensures we use exact versions from lockfile
|
||||
# Using --no-dev excludes development dependencies
|
||||
RUN uv sync --frozen --no-dev
|
||||
|
||||
# Stage 2: Runtime
|
||||
FROM python:3.12-slim
|
||||
|
||||
# Set working directory
|
||||
WORKDIR /app
|
||||
|
||||
# Copy virtual environment from builder
|
||||
COPY --from=builder /app/.venv /app/.venv
|
||||
|
||||
# Copy application code
|
||||
COPY . .
|
||||
|
||||
# Set environment variables
|
||||
ENV PATH="/app/.venv/bin:$PATH" \
|
||||
PYTHONUNBUFFERED=1 \
|
||||
PYTHONDONTWRITEBYTECODE=1
|
||||
|
||||
# Create non-root user for security
|
||||
RUN useradd -m -u 1000 appuser && \
|
||||
chown -R appuser:appuser /app
|
||||
USER appuser
|
||||
|
||||
# Health check
|
||||
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
|
||||
CMD python -c "import sys; sys.exit(0)"
|
||||
|
||||
# Expose port
|
||||
EXPOSE 8000
|
||||
|
||||
# Run application
|
||||
CMD ["python", "-m", "myapp"]
|
||||
29
skills/uv/assets/docker_examples/Dockerfile.simple
Normal file
29
skills/uv/assets/docker_examples/Dockerfile.simple
Normal file
@@ -0,0 +1,29 @@
|
||||
# Simple Docker build with uv
|
||||
# Single-stage build for development or simpler deployments
|
||||
|
||||
FROM python:3.12-slim
|
||||
|
||||
# Install uv
|
||||
COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv
|
||||
|
||||
# Set working directory
|
||||
WORKDIR /app
|
||||
|
||||
# Copy all files
|
||||
COPY . .
|
||||
|
||||
# Create virtual environment and install dependencies
|
||||
RUN uv venv /opt/venv && \
|
||||
. /opt/venv/bin/activate && \
|
||||
uv sync --frozen --no-dev
|
||||
|
||||
# Set environment to use virtual environment
|
||||
ENV VIRTUAL_ENV=/opt/venv \
|
||||
PATH="/opt/venv/bin:$PATH" \
|
||||
PYTHONUNBUFFERED=1
|
||||
|
||||
# Expose port
|
||||
EXPOSE 8000
|
||||
|
||||
# Run application
|
||||
CMD ["python", "-m", "myapp"]
|
||||
120
skills/uv/assets/github_actions/ci.yml
Normal file
120
skills/uv/assets/github_actions/ci.yml
Normal file
@@ -0,0 +1,120 @@
|
||||
# Comprehensive CI workflow with uv
|
||||
# .github/workflows/ci.yml
|
||||
|
||||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main, develop]
|
||||
pull_request:
|
||||
branches: [main]
|
||||
|
||||
env:
|
||||
UV_SYSTEM_PYTHON: 1 # Optional: use system Python
|
||||
|
||||
jobs:
|
||||
# Linting and formatting
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install uv
|
||||
uses: astral-sh/setup-uv@v6
|
||||
with:
|
||||
version: "0.9.5"
|
||||
enable-cache: true
|
||||
|
||||
- name: Set up Python
|
||||
run: uv python install 3.11
|
||||
|
||||
- name: Install dependencies
|
||||
run: uv sync --frozen --all-extras
|
||||
|
||||
- name: Run ruff (linter)
|
||||
run: uv run ruff check .
|
||||
|
||||
- name: Run ruff (formatter)
|
||||
run: uv run ruff format --check .
|
||||
|
||||
- name: Run mypy (type checker)
|
||||
run: uv run mypy src/
|
||||
|
||||
# Test matrix across multiple Python versions
|
||||
test:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest, macos-latest, windows-latest]
|
||||
python-version: ["3.11", "3.12"]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install uv
|
||||
uses: astral-sh/setup-uv@v6
|
||||
with:
|
||||
enable-cache: true
|
||||
cache-dependency-glob: "uv.lock"
|
||||
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
run: uv python install ${{ matrix.python-version }}
|
||||
|
||||
- name: Install dependencies
|
||||
run: uv sync --frozen --all-extras
|
||||
|
||||
- name: Run tests
|
||||
run: uv run pytest --cov --cov-report=xml
|
||||
|
||||
- name: Upload coverage
|
||||
if: matrix.os == 'ubuntu-latest' && matrix.python-version == '3.11'
|
||||
uses: codecov/codecov-action@v3
|
||||
with:
|
||||
file: ./coverage.xml
|
||||
|
||||
# Build and verify package
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [lint, test]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install uv
|
||||
uses: astral-sh/setup-uv@v6
|
||||
|
||||
- name: Set up Python
|
||||
run: uv python install 3.11
|
||||
|
||||
- name: Build package
|
||||
run: uv build
|
||||
|
||||
- name: Check package metadata
|
||||
run: uv run twine check dist/*
|
||||
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: dist
|
||||
path: dist/
|
||||
|
||||
# Optional: Publish to PyPI (on release tags)
|
||||
publish:
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
needs: [build]
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
id-token: write # Required for trusted publishing
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Download artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: dist
|
||||
path: dist/
|
||||
|
||||
- name: Publish to PyPI
|
||||
uses: pypa/gh-action-pypi-publish@release/v1
|
||||
with:
|
||||
packages-dir: dist/
|
||||
286
skills/uv/assets/pyproject_templates/advanced.toml
Normal file
286
skills/uv/assets/pyproject_templates/advanced.toml
Normal file
@@ -0,0 +1,286 @@
|
||||
# Advanced Python Project Configuration
|
||||
# Full-featured configuration with custom indexes, workspace, and advanced settings
|
||||
|
||||
[project]
|
||||
name = "advanced-project"
|
||||
version = "1.0.0"
|
||||
description = "Advanced Python project with custom configuration"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.11"
|
||||
authors = [{name = "Your Name", email = "your.email@example.com"}]
|
||||
license = {text = "MIT"}
|
||||
|
||||
dependencies = [
|
||||
"fastapi>=0.115.0",
|
||||
"torch", # Will be sourced from custom index
|
||||
"pydantic>=2.5.0",
|
||||
]
|
||||
|
||||
# Development dependencies using PEP 735 dependency groups
|
||||
[dependency-groups]
|
||||
dev = [
|
||||
"pytest>=8.4.2",
|
||||
"pytest-cov>=6.0.0",
|
||||
"pytest-mock>=3.15.1",
|
||||
"ruff>=0.13.3",
|
||||
"pyright>=1.1.406",
|
||||
"mypy>=1.18.2",
|
||||
"pre-commit>=4.3.0",
|
||||
]
|
||||
test = [
|
||||
"pytest-cov>=6.0.0",
|
||||
"pytest-asyncio>=0.21.0",
|
||||
"hypothesis>=6.0.0",
|
||||
]
|
||||
docs = [
|
||||
"sphinx>=7.0",
|
||||
"sphinx-rtd-theme>=1.3.0",
|
||||
]
|
||||
|
||||
[build-system]
|
||||
requires = ["hatchling"]
|
||||
build-backend = "hatchling.build"
|
||||
|
||||
[tool.uv]
|
||||
# Core settings
|
||||
managed = true
|
||||
package = true
|
||||
default-groups = ["dev"]
|
||||
|
||||
# Resolution strategy
|
||||
resolution = "highest" # highest/lowest/lowest-direct
|
||||
fork-strategy = "requires-python"
|
||||
index-strategy = "first-index"
|
||||
|
||||
# Environment restrictions (only resolve for these platforms)
|
||||
environments = [
|
||||
"sys_platform == 'darwin'",
|
||||
"sys_platform == 'linux'",
|
||||
]
|
||||
|
||||
# Require support for specific platforms
|
||||
required-environments = [
|
||||
"sys_platform == 'linux' and platform_machine == 'x86_64'",
|
||||
]
|
||||
|
||||
# Dependency version management
|
||||
constraint-dependencies = [
|
||||
"grpcio<1.65", # Constraint: don't allow grpcio >= 1.65
|
||||
]
|
||||
override-dependencies = [
|
||||
"werkzeug==2.3.0", # Override: always use this exact version
|
||||
]
|
||||
build-constraint-dependencies = [
|
||||
"setuptools==60.0.0", # Constraint for build dependencies
|
||||
]
|
||||
|
||||
# Build configuration
|
||||
compile-bytecode = true
|
||||
no-build-isolation-package = ["flash-attn", "deepspeed"]
|
||||
|
||||
# Cache configuration
|
||||
cache-dir = "./.uv_cache"
|
||||
cache-keys = [
|
||||
{ file = "pyproject.toml" },
|
||||
{ file = "requirements.txt" },
|
||||
{ git = { commit = true } },
|
||||
]
|
||||
|
||||
# Network configuration
|
||||
concurrent-downloads = 20
|
||||
concurrent-builds = 8
|
||||
|
||||
# Python management
|
||||
python-preference = "managed"
|
||||
python-downloads = "automatic"
|
||||
|
||||
# Security
|
||||
keyring-provider = "subprocess"
|
||||
allow-insecure-host = []
|
||||
|
||||
# Preview features
|
||||
preview = false
|
||||
|
||||
# Extra build dependencies (for packages without proper metadata)
|
||||
[tool.uv.extra-build-dependencies]
|
||||
flash-attn = ["torch", "setuptools", "ninja"]
|
||||
deepspeed = [{ requirement = "torch", match-runtime = true }]
|
||||
|
||||
# Build environment variables
|
||||
[tool.uv.extra-build-variables]
|
||||
flash-attn = { FLASH_ATTENTION_SKIP_CUDA_BUILD = "TRUE" }
|
||||
opencv-python = { CMAKE_ARGS = "-DWITH_CUDA=ON" }
|
||||
|
||||
# Custom package sources
|
||||
[tool.uv.sources]
|
||||
# PyTorch from custom index
|
||||
torch = { index = "pytorch-cu121" }
|
||||
|
||||
# Internal workspace dependency
|
||||
# internal-lib = { workspace = true }
|
||||
|
||||
# Git source
|
||||
# httpx = { git = "https://github.com/encode/httpx", tag = "0.27.0" }
|
||||
|
||||
# Local path (development)
|
||||
# local-pkg = { path = "../local-pkg", editable = true }
|
||||
|
||||
# Conditional sources (platform-specific)
|
||||
# torch = [
|
||||
# { index = "pytorch-cu118", marker = "sys_platform == 'darwin'" },
|
||||
# { index = "pytorch-cu121", marker = "sys_platform == 'linux'" },
|
||||
# ]
|
||||
|
||||
# Custom package indexes
|
||||
[[tool.uv.index]]
|
||||
name = "pytorch-cu121"
|
||||
url = "https://download.pytorch.org/whl/cu121"
|
||||
explicit = true # Only use for explicitly pinned packages
|
||||
default = false # Don't replace PyPI as default
|
||||
|
||||
[[tool.uv.index]]
|
||||
name = "private-registry"
|
||||
url = "https://packages.example.com/simple"
|
||||
explicit = true
|
||||
authenticate = "always" # Always send authentication
|
||||
|
||||
# Workspace configuration (for monorepos)
|
||||
[tool.uv.workspace]
|
||||
members = ["packages/*", "apps/*"]
|
||||
exclude = ["packages/deprecated"]
|
||||
|
||||
# Conflict resolution (mutually exclusive extras)
|
||||
[[tool.uv.conflicts]]
|
||||
extra = ["cuda", "rocm"]
|
||||
|
||||
[[tool.uv.conflicts]]
|
||||
group = ["prod", "dev"]
|
||||
|
||||
# pip-specific settings (only for uv pip commands)
|
||||
[tool.uv.pip]
|
||||
compile-bytecode = true
|
||||
strict = true
|
||||
generate-hashes = false
|
||||
annotation-style = "line"
|
||||
extra = ["dev"]
|
||||
universal = false
|
||||
no-strip-markers = false
|
||||
|
||||
# Ruff configuration
|
||||
[tool.ruff]
|
||||
target-version = "py311"
|
||||
line-length = 120
|
||||
fix = true
|
||||
preview = true
|
||||
|
||||
[tool.ruff.format]
|
||||
docstring-code-format = true
|
||||
quote-style = "double"
|
||||
line-ending = "lf"
|
||||
skip-magic-trailing-comma = true
|
||||
preview = true
|
||||
|
||||
[tool.ruff.lint]
|
||||
extend-select = [
|
||||
"E", # pycodestyle errors
|
||||
"W", # pycodestyle warnings
|
||||
"F", # pyflakes
|
||||
"I", # isort
|
||||
"UP", # pyupgrade
|
||||
"YTT", # flake8-2020
|
||||
"S", # flake8-bandit
|
||||
"B", # flake8-bugbear
|
||||
"A", # flake8-builtins
|
||||
"C4", # flake8-comprehensions
|
||||
"T10", # flake8-debugger
|
||||
"SIM", # flake8-simplify
|
||||
"C90", # mccabe
|
||||
"PGH", # pygrep-hooks
|
||||
"RUF", # ruff-specific
|
||||
"TRY", # tryceratops
|
||||
"DOC", # pydocstyle
|
||||
"D", # pydocstyle
|
||||
]
|
||||
|
||||
ignore = [
|
||||
"COM812", # Missing trailing comma
|
||||
"COM819", # Missing trailing comma
|
||||
"D107", # Missing docstring in __init__
|
||||
"D415", # First line should end with a period
|
||||
"E111", # Indentation is not a multiple of four
|
||||
"E117", # Over-indented for visual indent
|
||||
"E203", # whitespace before ':'
|
||||
"E402", # Module level import not at top
|
||||
"E501", # Line length exceeds maximum limit
|
||||
"ISC001", # isort configuration is missing
|
||||
"ISC002", # isort configuration is missing
|
||||
"Q000", # Remove bad quotes
|
||||
"Q001", # Remove bad quotes
|
||||
"Q002", # Remove bad quotes
|
||||
"Q003", # Remove bad quotes
|
||||
"TRY003", # Exception message should not be too long
|
||||
"S404", # module is possibly insecure
|
||||
"S603", # subprocess-without-shell-equals-true
|
||||
"S606", # start-process-with-no-shell
|
||||
"DOC501", # Missing raises section
|
||||
]
|
||||
|
||||
unfixable = ["F401", "S404", "S603", "S606", "DOC501"]
|
||||
|
||||
[tool.ruff.lint.pycodestyle]
|
||||
max-line-length = 120
|
||||
|
||||
[tool.ruff.lint.isort]
|
||||
combine-as-imports = true
|
||||
split-on-trailing-comma = false
|
||||
force-single-line = false
|
||||
force-wrap-aliases = false
|
||||
|
||||
[tool.ruff.lint.flake8-quotes]
|
||||
docstring-quotes = "double"
|
||||
|
||||
[tool.ruff.lint.pydocstyle]
|
||||
convention = "google"
|
||||
|
||||
[tool.ruff.lint.mccabe]
|
||||
max-complexity = 10
|
||||
|
||||
[tool.ruff.lint.per-file-ignores]
|
||||
"**/tests/*" = ["S101", "S603", "S607", "D102", "D200", "D100"]
|
||||
"**/test_*.py" = ["S101", "S603", "S607", "D102", "D200", "D100"]
|
||||
|
||||
# Mypy configuration
|
||||
[tool.mypy]
|
||||
python_version = "3.11"
|
||||
strict = true
|
||||
extra_checks = true
|
||||
warn_unused_configs = true
|
||||
warn_redundant_casts = true
|
||||
warn_unused_ignores = true
|
||||
ignore_missing_imports = true
|
||||
show_error_codes = true
|
||||
pretty = true
|
||||
disable_error_code = "call-arg,arg-type"
|
||||
|
||||
# Pytest configuration
|
||||
[tool.pytest.ini_options]
|
||||
addopts = [
|
||||
"--cov=advanced_project",
|
||||
"--cov-report=term-missing",
|
||||
"-v",
|
||||
]
|
||||
testpaths = ["tests"]
|
||||
python_files = ["test_*.py"]
|
||||
python_classes = ["Test*"]
|
||||
python_functions = ["test_*"]
|
||||
markers = [
|
||||
"slow: tests that take significant time to run",
|
||||
"integration: integration tests",
|
||||
]
|
||||
|
||||
[tool.coverage.run]
|
||||
omit = ["*/tests/*"]
|
||||
|
||||
[tool.coverage.report]
|
||||
show_missing = true
|
||||
fail_under = 70
|
||||
184
skills/uv/assets/pyproject_templates/basic.toml
Normal file
184
skills/uv/assets/pyproject_templates/basic.toml
Normal file
@@ -0,0 +1,184 @@
|
||||
# Basic Python Project Configuration
|
||||
# Use this template for simple Python projects
|
||||
|
||||
[project]
|
||||
name = "my-project"
|
||||
version = "0.1.0"
|
||||
description = "A simple Python project"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.11"
|
||||
authors = [
|
||||
{name = "Your Name", email = "your.email@example.com"}
|
||||
]
|
||||
license = {text = "MIT"}
|
||||
keywords = ["example", "project"]
|
||||
classifiers = [
|
||||
"Development Status :: 3 - Alpha",
|
||||
"Intended Audience :: Developers",
|
||||
"License :: OSI Approved :: MIT License",
|
||||
"Programming Language :: Python :: 3.11",
|
||||
"Programming Language :: Python :: 3.12",
|
||||
]
|
||||
|
||||
# Core dependencies
|
||||
dependencies = [
|
||||
"requests>=2.31.0",
|
||||
]
|
||||
|
||||
# Development dependencies using PEP 735 dependency groups
|
||||
[dependency-groups]
|
||||
dev = [
|
||||
"pytest>=8.4.2",
|
||||
"pytest-cov>=6.0.0",
|
||||
"pytest-mock>=3.15.1",
|
||||
"ruff>=0.13.3",
|
||||
"pyright>=1.1.406",
|
||||
"mypy>=1.18.2",
|
||||
"pre-commit>=4.3.0",
|
||||
]
|
||||
|
||||
# Entry points for CLI tools
|
||||
[project.scripts]
|
||||
my-tool = "my_project.cli:main"
|
||||
|
||||
# Project URLs
|
||||
[project.urls]
|
||||
Homepage = "https://github.com/yourusername/my-project"
|
||||
Documentation = "https://my-project.readthedocs.io"
|
||||
Repository = "https://github.com/yourusername/my-project.git"
|
||||
Issues = "https://github.com/yourusername/my-project/issues"
|
||||
|
||||
# Build system
|
||||
[build-system]
|
||||
requires = ["hatchling"]
|
||||
build-backend = "hatchling.build"
|
||||
|
||||
# uv configuration
|
||||
[tool.uv]
|
||||
managed = true
|
||||
package = true
|
||||
default-groups = ["dev"]
|
||||
|
||||
# Development server sources (optional)
|
||||
[tool.uv.sources]
|
||||
# Example: Install from git during development
|
||||
# requests = { git = "https://github.com/psf/requests", branch = "main" }
|
||||
|
||||
# Ruff configuration
|
||||
[tool.ruff]
|
||||
target-version = "py311"
|
||||
line-length = 120
|
||||
fix = true
|
||||
preview = true
|
||||
|
||||
[tool.ruff.format]
|
||||
docstring-code-format = true
|
||||
quote-style = "double"
|
||||
line-ending = "lf"
|
||||
skip-magic-trailing-comma = true
|
||||
preview = true
|
||||
|
||||
[tool.ruff.lint]
|
||||
extend-select = [
|
||||
"E", # pycodestyle errors
|
||||
"W", # pycodestyle warnings
|
||||
"F", # pyflakes
|
||||
"I", # isort
|
||||
"UP", # pyupgrade
|
||||
"YTT", # flake8-2020
|
||||
"S", # flake8-bandit
|
||||
"B", # flake8-bugbear
|
||||
"A", # flake8-builtins
|
||||
"C4", # flake8-comprehensions
|
||||
"T10", # flake8-debugger
|
||||
"SIM", # flake8-simplify
|
||||
"C90", # mccabe
|
||||
"PGH", # pygrep-hooks
|
||||
"RUF", # ruff-specific
|
||||
"TRY", # tryceratops
|
||||
"DOC", # pydocstyle
|
||||
"D", # pydocstyle
|
||||
]
|
||||
|
||||
ignore = [
|
||||
"COM812", # Missing trailing comma
|
||||
"COM819", # Missing trailing comma
|
||||
"D107", # Missing docstring in __init__
|
||||
"D415", # First line should end with a period
|
||||
"E111", # Indentation is not a multiple of four
|
||||
"E117", # Over-indented for visual indent
|
||||
"E203", # whitespace before ':'
|
||||
"E402", # Module level import not at top
|
||||
"E501", # Line length exceeds maximum limit
|
||||
"ISC001", # isort configuration is missing
|
||||
"ISC002", # isort configuration is missing
|
||||
"Q000", # Remove bad quotes
|
||||
"Q001", # Remove bad quotes
|
||||
"Q002", # Remove bad quotes
|
||||
"Q003", # Remove bad quotes
|
||||
"TRY003", # Exception message should not be too long
|
||||
"S404", # module is possibly insecure
|
||||
"S603", # subprocess-without-shell-equals-true
|
||||
"S606", # start-process-with-no-shell
|
||||
"DOC501", # Missing raises section
|
||||
]
|
||||
|
||||
unfixable = ["F401", "S404", "S603", "S606", "DOC501"]
|
||||
|
||||
[tool.ruff.lint.pycodestyle]
|
||||
max-line-length = 120
|
||||
|
||||
[tool.ruff.lint.isort]
|
||||
combine-as-imports = true
|
||||
split-on-trailing-comma = false
|
||||
force-single-line = false
|
||||
force-wrap-aliases = false
|
||||
|
||||
[tool.ruff.lint.flake8-quotes]
|
||||
docstring-quotes = "double"
|
||||
|
||||
[tool.ruff.lint.pydocstyle]
|
||||
convention = "google"
|
||||
|
||||
[tool.ruff.lint.mccabe]
|
||||
max-complexity = 10
|
||||
|
||||
[tool.ruff.lint.per-file-ignores]
|
||||
"**/tests/*" = ["S101", "S603", "S607", "D102", "D200", "D100"]
|
||||
"**/test_*.py" = ["S101", "S603", "S607", "D102", "D200", "D100"]
|
||||
|
||||
# Mypy configuration
|
||||
[tool.mypy]
|
||||
python_version = "3.11"
|
||||
strict = true
|
||||
extra_checks = true
|
||||
warn_unused_configs = true
|
||||
warn_redundant_casts = true
|
||||
warn_unused_ignores = true
|
||||
ignore_missing_imports = true
|
||||
show_error_codes = true
|
||||
pretty = true
|
||||
disable_error_code = "call-arg,arg-type"
|
||||
|
||||
# Pytest configuration
|
||||
[tool.pytest.ini_options]
|
||||
addopts = [
|
||||
"--cov=my_project",
|
||||
"--cov-report=term-missing",
|
||||
"-v",
|
||||
]
|
||||
testpaths = ["tests"]
|
||||
python_files = ["test_*.py"]
|
||||
python_classes = ["Test*"]
|
||||
python_functions = ["test_*"]
|
||||
markers = [
|
||||
"slow: tests that take significant time to run",
|
||||
"integration: integration tests",
|
||||
]
|
||||
|
||||
[tool.coverage.run]
|
||||
omit = ["*/tests/*"]
|
||||
|
||||
[tool.coverage.report]
|
||||
show_missing = true
|
||||
fail_under = 70
|
||||
199
skills/uv/assets/pyproject_templates/gitlab.toml
Normal file
199
skills/uv/assets/pyproject_templates/gitlab.toml
Normal file
@@ -0,0 +1,199 @@
|
||||
# GitLab Package Registry Configuration
|
||||
# Template matching user's GitLab-based workflow
|
||||
|
||||
[project]
|
||||
name = "my-project"
|
||||
version = "0.1.0"
|
||||
description = "Project using GitLab package registry"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.11"
|
||||
authors = [{ name = "Your Name", email = "your.email@example.com" }]
|
||||
license = { text = "MIT" }
|
||||
classifiers = [
|
||||
"Development Status :: 3 - Alpha",
|
||||
"Intended Audience :: Developers",
|
||||
"License :: OSI Approved :: MIT License",
|
||||
"Programming Language :: Python :: 3.11",
|
||||
"Programming Language :: Python :: 3.12",
|
||||
]
|
||||
|
||||
dependencies = [
|
||||
"typer>=0.19.2",
|
||||
"pydantic>=2.12.2",
|
||||
"python-dotenv>=1.1.1",
|
||||
]
|
||||
|
||||
[project.scripts]
|
||||
my-tool = "my_project.cli:app"
|
||||
|
||||
[project.urls]
|
||||
Homepage = "https://sourcery.assaabloy.net/group/project"
|
||||
Documentation = "https://sourcery.assaabloy.net/group/project/-/blob/main/README.md"
|
||||
Repository = "https://sourcery.assaabloy.net/group/project"
|
||||
"Bug Tracker" = "https://sourcery.assaabloy.net/group/project/-/issues"
|
||||
|
||||
# Build system with hatchling and vcs versioning
|
||||
[build-system]
|
||||
requires = ["hatchling", "hatch-vcs"]
|
||||
build-backend = "hatchling.build"
|
||||
|
||||
# Use dependency-groups instead of optional-dependencies
|
||||
[dependency-groups]
|
||||
dev = [
|
||||
"pytest>=8.4.2",
|
||||
"pytest-cov>=6.0.0",
|
||||
"pytest-mock>=3.15.1",
|
||||
"ruff>=0.13.3",
|
||||
"pyright>=1.1.406",
|
||||
"mypy>=1.18.2",
|
||||
"pre-commit>=4.3.0",
|
||||
]
|
||||
|
||||
# Ruff configuration following user's pattern
|
||||
[tool.ruff]
|
||||
target-version = "py311"
|
||||
line-length = 120
|
||||
fix = true
|
||||
preview = true
|
||||
|
||||
[tool.ruff.format]
|
||||
docstring-code-format = true
|
||||
quote-style = "double"
|
||||
line-ending = "lf"
|
||||
skip-magic-trailing-comma = true
|
||||
preview = true
|
||||
|
||||
[tool.ruff.lint]
|
||||
extend-select = [
|
||||
"E", # pycodestyle errors
|
||||
"W", # pycodestyle warnings
|
||||
"F", # pyflakes
|
||||
"I", # isort
|
||||
"UP", # pyupgrade
|
||||
"YTT", # flake8-2020
|
||||
"S", # flake8-bandit
|
||||
"B", # flake8-bugbear
|
||||
"A", # flake8-builtins
|
||||
"C4", # flake8-comprehensions
|
||||
"T10", # flake8-debugger
|
||||
"SIM", # flake8-simplify
|
||||
"C90", # mccabe
|
||||
"PGH", # pygrep-hooks
|
||||
"RUF", # ruff-specific
|
||||
"TRY", # tryceratops
|
||||
"DOC", # pydocstyle
|
||||
"D", # pydocstyle
|
||||
]
|
||||
|
||||
ignore = [
|
||||
"COM812", # Missing trailing comma
|
||||
"COM819", # Missing trailing comma
|
||||
"D107", # Missing docstring in __init__
|
||||
"D415", # First line should end with a period
|
||||
"E111", # Indentation is not a multiple of four
|
||||
"E117", # Over-indented for visual indent
|
||||
"E203", # whitespace before ':'
|
||||
"E402", # Module level import not at top
|
||||
"E501", # Line length exceeds maximum limit
|
||||
"ISC001", # isort configuration is missing
|
||||
"ISC002", # isort configuration is missing
|
||||
"Q000", # Remove bad quotes
|
||||
"Q001", # Remove bad quotes
|
||||
"Q002", # Remove bad quotes
|
||||
"Q003", # Remove bad quotes
|
||||
"TRY003", # Exception message should not be too long
|
||||
"S404", # module is possibly insecure
|
||||
"S603", # subprocess-without-shell-equals-true
|
||||
"S606", # start-process-with-no-shell
|
||||
"DOC501", # Missing raises section
|
||||
]
|
||||
|
||||
unfixable = ["F401", "S404", "S603", "S606", "DOC501"]
|
||||
|
||||
[tool.ruff.lint.pycodestyle]
|
||||
max-line-length = 120
|
||||
|
||||
[tool.ruff.lint.isort]
|
||||
combine-as-imports = true
|
||||
split-on-trailing-comma = false
|
||||
force-single-line = false
|
||||
force-wrap-aliases = false
|
||||
|
||||
[tool.ruff.lint.flake8-quotes]
|
||||
docstring-quotes = "double"
|
||||
|
||||
[tool.ruff.lint.pydocstyle]
|
||||
convention = "google"
|
||||
|
||||
[tool.ruff.lint.mccabe]
|
||||
max-complexity = 10
|
||||
|
||||
[tool.ruff.lint.per-file-ignores]
|
||||
"**/tests/*" = ["S101", "S603", "S607", "D102", "D200", "D100"]
|
||||
"**/test_*.py" = ["S101", "S603", "S607", "D102", "D200", "D100"]
|
||||
|
||||
# Mypy configuration
|
||||
[tool.mypy]
|
||||
python_version = "3.11"
|
||||
strict = true
|
||||
extra_checks = true
|
||||
warn_unused_configs = true
|
||||
warn_redundant_casts = true
|
||||
warn_unused_ignores = true
|
||||
ignore_missing_imports = true
|
||||
show_error_codes = true
|
||||
pretty = true
|
||||
disable_error_code = "call-arg,arg-type"
|
||||
|
||||
# Pytest configuration
|
||||
[tool.pytest.ini_options]
|
||||
addopts = [
|
||||
"--cov=my_project",
|
||||
"--cov-report=term-missing",
|
||||
"-v",
|
||||
]
|
||||
testpaths = ["tests"]
|
||||
python_files = ["test_*.py"]
|
||||
python_classes = ["Test*"]
|
||||
python_functions = ["test_*"]
|
||||
markers = [
|
||||
"slow: tests that take significant time to run",
|
||||
"integration: integration tests",
|
||||
]
|
||||
|
||||
[tool.coverage.run]
|
||||
omit = ["*/tests/*"]
|
||||
|
||||
[tool.coverage.report]
|
||||
show_missing = true
|
||||
fail_under = 70
|
||||
|
||||
# Hatchling configuration with vcs versioning
|
||||
[tool.hatch.version]
|
||||
source = "vcs"
|
||||
|
||||
[tool.hatch.build.targets.sdist]
|
||||
include = [
|
||||
"my_project",
|
||||
"README.md",
|
||||
"pyproject.toml",
|
||||
]
|
||||
|
||||
[tool.hatch.build.targets.wheel]
|
||||
include = ["my_project"]
|
||||
|
||||
# uv configuration for GitLab package registry
|
||||
[tool.uv]
|
||||
# Publish to GitLab package registry
|
||||
publish-url = "https://sourcery.assaabloy.net/api/v4/projects/PROJECT_ID/packages/pypi"
|
||||
|
||||
# Use GitLab as default index
|
||||
[[tool.uv.index]]
|
||||
name = "gitlab"
|
||||
url = "https://sourcery.assaabloy.net/api/v4/projects/PROJECT_ID/packages/pypi/simple"
|
||||
default = true
|
||||
authenticate = "always"
|
||||
|
||||
# Authentication via environment variables:
|
||||
# export UV_INDEX_GITLAB_USERNAME="__token__"
|
||||
# export UV_INDEX_GITLAB_PASSWORD="your-gitlab-token"
|
||||
112
skills/uv/assets/script_examples/data_analysis.py
Normal file
112
skills/uv/assets/script_examples/data_analysis.py
Normal file
@@ -0,0 +1,112 @@
|
||||
#!/usr/bin/env -S uv --quiet run --active --script
|
||||
# /// script
|
||||
# requires-python = ">=3.11"
|
||||
# dependencies = [
|
||||
# "pandas>=2.0.0",
|
||||
# "matplotlib>=3.7.0",
|
||||
# "rich>=13.0.0",
|
||||
# ]
|
||||
# [tool.uv]
|
||||
# exclude-newer = "2025-10-24T00:00:00Z" # Time-based reproducibility
|
||||
# ///
|
||||
|
||||
"""Data Analysis Script Example
|
||||
|
||||
This script demonstrates PEP 723 inline script metadata with uv.
|
||||
It analyzes CSV data and creates visualizations.
|
||||
|
||||
Usage:
|
||||
# Make executable and run
|
||||
chmod +x data_analysis.py
|
||||
./data_analysis.py data.csv
|
||||
|
||||
# Or run directly with uv
|
||||
uv run data_analysis.py data.csv
|
||||
|
||||
# With additional dependencies
|
||||
uv run --with seaborn data_analysis.py data.csv
|
||||
"""
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
import matplotlib.pyplot as plt
|
||||
import pandas as pd
|
||||
from rich.console import Console
|
||||
from rich.table import Table
|
||||
|
||||
console = Console()
|
||||
|
||||
|
||||
def analyze_data(csv_path: str) -> None:
|
||||
"""Analyze CSV data and display summary statistics."""
|
||||
# Load data
|
||||
df = pd.read_csv(csv_path)
|
||||
|
||||
console.print(f"[bold green]Analyzing {csv_path}[/bold green]")
|
||||
console.print(f"Shape: {df.shape[0]} rows x {df.shape[1]} columns\n")
|
||||
|
||||
# Display summary statistics in rich table
|
||||
table = Table(title="Summary Statistics")
|
||||
table.add_column("Column", style="cyan")
|
||||
table.add_column("Mean", style="magenta")
|
||||
table.add_column("Std", style="green")
|
||||
table.add_column("Min", style="yellow")
|
||||
table.add_column("Max", style="red")
|
||||
|
||||
for col in df.select_dtypes(include=["number"]).columns:
|
||||
table.add_row(
|
||||
col, f"{df[col].mean():.2f}", f"{df[col].std():.2f}", f"{df[col].min():.2f}", f"{df[col].max():.2f}"
|
||||
)
|
||||
|
||||
console.print(table)
|
||||
|
||||
# Create visualization
|
||||
_fig, axes = plt.subplots(1, 2, figsize=(12, 5))
|
||||
|
||||
# Plot 1: Distribution of first numeric column
|
||||
numeric_cols = df.select_dtypes(include=["number"]).columns
|
||||
if len(numeric_cols) > 0:
|
||||
df[numeric_cols[0]].hist(ax=axes[0], bins=30)
|
||||
axes[0].set_title(f"Distribution of {numeric_cols[0]}")
|
||||
axes[0].set_xlabel(numeric_cols[0])
|
||||
axes[0].set_ylabel("Frequency")
|
||||
|
||||
# Plot 2: Correlation heatmap
|
||||
if len(numeric_cols) > 1:
|
||||
corr = df.loc[:, numeric_cols].corr()
|
||||
im = axes[1].imshow(corr, cmap="coolwarm", aspect="auto")
|
||||
axes[1].set_xticks(range(len(numeric_cols)))
|
||||
axes[1].set_yticks(range(len(numeric_cols)))
|
||||
axes[1].set_xticklabels(numeric_cols, rotation=45)
|
||||
axes[1].set_yticklabels(numeric_cols)
|
||||
axes[1].set_title("Correlation Matrix")
|
||||
plt.colorbar(im, ax=axes[1])
|
||||
|
||||
plt.tight_layout()
|
||||
output_path = Path(csv_path).stem + "_analysis.png"
|
||||
plt.savefig(output_path, dpi=150)
|
||||
console.print(f"\n[bold green]✓[/bold green] Saved visualization to {output_path}")
|
||||
|
||||
|
||||
def main() -> None:
|
||||
"""Main entry point."""
|
||||
if len(sys.argv) < 2:
|
||||
console.print("[bold red]Error:[/bold red] Please provide CSV file path")
|
||||
console.print("\nUsage: uv run data_analysis.py <csv_file>")
|
||||
sys.exit(1)
|
||||
|
||||
csv_path = sys.argv[1]
|
||||
if not Path(csv_path).exists():
|
||||
console.print(f"[bold red]Error:[/bold red] File '{csv_path}' not found")
|
||||
sys.exit(1)
|
||||
|
||||
try:
|
||||
analyze_data(csv_path)
|
||||
except Exception as e:
|
||||
console.print(f"[bold red]Error:[/bold red] {e}")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user