diff --git a/.github/workflows/claude-model-check.yml b/.github/workflows/claude-model-check.yml index f2cd50a..b349f7c 100644 --- a/.github/workflows/claude-model-check.yml +++ b/.github/workflows/claude-model-check.yml @@ -35,6 +35,7 @@ jobs: run: | uv run python scripts/check_models.py --github-output + # Only run Claude validation for repo members (API costs) - name: Claude Model Validation if: | github.event.pull_request.author_association == 'MEMBER' || diff --git a/.github/workflows/notebook-quality.yml b/.github/workflows/notebook-quality.yml index 99a2199..735a761 100644 --- a/.github/workflows/notebook-quality.yml +++ b/.github/workflows/notebook-quality.yml @@ -42,13 +42,10 @@ jobs: uv run nbstripout --verify skills/**/*.ipynb || \ (echo "❌ Notebooks contain outputs. Run 'nbstripout skills/**/*.ipynb' locally" && exit 1) - - name: Lint with Ruff via nbQA + - name: Lint with Ruff run: | - # Check for issues - uv run nbqa ruff skills/ --show-fixes - - # Check formatting - uv run nbqa ruff skills/ --check --select=I,F + uv run ruff check skills/ --show-fixes + uv run ruff format skills/ --check - name: Validate notebook structure run: | @@ -58,7 +55,7 @@ jobs: run: | uv run python scripts/check_models.py - # Only run API tests on main branch or for maintainers + # Only run API tests on main branch or for maintainers (costs money) - name: Execute notebooks (API Testing) if: | github.event_name == 'push' || @@ -67,17 +64,14 @@ jobs: env: ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} run: | - mkdir -p test_outputs - for notebook in skills/*/guide.ipynb; do echo "📓 Testing: $notebook" - uv run papermill "$notebook" \ - "test_outputs/$(basename $notebook)" \ - --kernel python3 \ - -p test_mode true \ - -p model "claude-3-5-haiku-latest" \ - -p max_tokens 10 \ - --log-level ERROR \ + # Use nbconvert to execute notebooks + uv run jupyter nbconvert --to notebook \ + --execute "$notebook" \ + --ExecutePreprocessor.kernel_name=python3 \ + --ExecutePreprocessor.timeout=120 \ + --stdout > /dev/null \ || echo "⚠️ Failed: $notebook" done diff --git a/.github/workflows/security-scan.yml b/.github/workflows/security-scan.yml index 88f791f..6f1dcbb 100644 --- a/.github/workflows/security-scan.yml +++ b/.github/workflows/security-scan.yml @@ -25,10 +25,8 @@ jobs: - name: Check for hardcoded secrets in notebooks run: | - # Check for potential API keys ! grep -r "sk-ant-" skills/ --include="*.ipynb" || \ (echo "❌ Found potential API key in notebook" && exit 1) - # Check for environment variable usage grep -r "os.environ\|getenv" skills/ --include="*.ipynb" || \ echo "⚠️ No environment variable usage found - ensure API keys are not hardcoded" \ No newline at end of file diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 0b76290..a11d55d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,28 +1,19 @@ repos: - # Strip notebook outputs first - repo: https://github.com/kynan/nbstripout rev: 0.7.1 hooks: - id: nbstripout - args: ['--extra-keys', 'metadata.widgets metadata.vscode'] + args: ['--extra-keys', 'metadata.widgets metadata.vscode cell.metadata.execution'] - # Ruff for notebooks via nbQA - - repo: https://github.com/nbQA-dev/nbQA - rev: 1.9.1 - hooks: - - id: nbqa-ruff - args: ['--fix'] - additional_dependencies: [ruff>=0.8.0] - - # Ruff for Python files - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.8.0 + rev: v0.12.12 hooks: - id: ruff + types_or: [python, pyi, jupyter] args: ['--fix'] - id: ruff-format + types_or: [python, pyi, jupyter] - # Custom validations - repo: local hooks: - id: check-models diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d985b0e..9e32151 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -55,9 +55,8 @@ This repository uses automated tools to maintain code quality: ### The Notebook Validation Stack - **[papermill](https://papermill.readthedocs.io/)**: Parameterized notebook execution for testing -- **[nbqa](https://nbqa.readthedocs.io/)**: Applies Python quality tools to notebooks +- **[ruff](https://docs.astral.sh/ruff/)**: Fast Python linter and formatter with native Jupyter support - **[nbstripout](https://github.com/kynan/nbstripout)**: Keeps notebooks clean in git (removes outputs) -- **[ruff](https://docs.astral.sh/ruff/)**: Fast Python linter and formatter ### Before Committing @@ -68,13 +67,10 @@ This repository uses automated tools to maintain code quality: 2. **Run quality checks**: ```bash - # Lint and format - uv run nbqa ruff skills/ --fix + uv run ruff check skills/ --fix + uv run ruff format skills/ - # Validate notebook structure uv run python scripts/validate_notebooks.py - - # Check model usage uv run python scripts/check_models.py ``` diff --git a/anthropic_cookbook/__init__.py b/anthropic_cookbook/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/pyproject.toml b/pyproject.toml index 59cbc66..de3571f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ [project] name = "anthropic-cookbook" version = "0.1.0" -requires-python = ">=3.11" +requires-python = ">=3.11,<3.13" dependencies = [ "anthropic>=0.39.0", "jupyter>=1.1.1", @@ -13,13 +13,12 @@ dependencies = [ [project.optional-dependencies] dev = [ - "papermill>=2.6.0", - "nbqa>=1.8.0", # Compatible with Python 3.11 "nbstripout>=0.7.1", - "ruff>=0.7.0", # Compatible with Python 3.11 + "ruff>=0.7.0", "pytest>=8.3.3", "nbval>=0.11.0", "pre-commit>=3.8.0", + "nbconvert>=7.16.0", # For executing notebooks in CI ] [tool.uv.sources] @@ -28,18 +27,24 @@ dev = [ requires = ["hatchling"] build-backend = "hatchling.build" +[tool.hatch.build.targets.wheel] +packages = ["anthropic_cookbook"] # Dummy package for build system + [tool.ruff] line-length = 100 target-version = "py311" +extend-include = ["*.ipynb"] # Ruff v0.6.0+ includes notebooks by default, but explicit is better select = ["E", "F", "I", "W", "UP", "S", "B"] -ignore = ["E501", "S101"] # E501: line too long, S101: assert in tests +ignore = ["E501", "S101"] # E501: line too long, S101: assert used (ok in tests) [tool.ruff.per-file-ignores] -"skills/**/*.ipynb" = ["S105", "S106"] # Allow hardcoded passwords in example notebooks +# Notebooks have different conventions than regular Python files +"*.ipynb" = ["E402", "E501", "F401", "F811"] # Allow: imports mid-file, long lines, unused imports, redefinitions [tool.nbstripout] extra_keys = [ "cell.metadata.execution", "cell.metadata.pycharm", - "metadata.widgets" + "metadata.widgets", + "metadata.vscode" ] \ No newline at end of file diff --git a/requirements-dev.txt b/requirements-dev.txt new file mode 100644 index 0000000..372fd5e --- /dev/null +++ b/requirements-dev.txt @@ -0,0 +1,6 @@ +papermill>=2.6.0 +nbstripout>=0.7.1 +ruff>=0.12.0 +pytest>=8.3.3 +nbval>=0.11.0 +pre-commit>=3.8.0 \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..0b4a813 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,6 @@ +anthropic>=0.39.0 +jupyter>=1.1.1 +ipykernel>=6.29.5 +notebook>=7.2.2 +numpy>=1.26.4 +pandas>=2.2.3 \ No newline at end of file