diff --git a/.chainlink/issues.db b/.chainlink/issues.db index ebc4cd7..12b36ae 100644 Binary files a/.chainlink/issues.db and b/.chainlink/issues.db differ diff --git a/.github/workflows/uv-publish-pypi.yml b/.github/workflows/uv-publish-pypi.yml index b2083e7..421436c 100644 --- a/.github/workflows/uv-publish-pypi.yml +++ b/.github/workflows/uv-publish-pypi.yml @@ -1,5 +1,3 @@ -# - name: Build and upload package to PyPI on: @@ -9,38 +7,59 @@ on: permissions: contents: read + id-token: write -jobs: +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true - uv-build-release-pypi-publish: - name: "Build release distribution and publish to PyPI" +jobs: + build: + name: Build release distribution runs-on: ubuntu-latest - environment: - name: pypi - + steps: - uses: actions/checkout@v5 - - - name: "Set up Python" + + - name: Set up Python uses: actions/setup-python@v5 with: python-version-file: "pyproject.toml" - name: Install uv uses: astral-sh/setup-uv@v6 - + with: + enable-cache: true + - name: Install project - run: uv sync --all-extras --dev - # TODO Better to use --locked for author control over versions? - # run: uv sync --locked --all-extras --dev - + run: uv sync --locked --all-extras --dev + - name: Build release distributions run: uv build - - - name: Publish to PyPI - env: - UV_PUBLISH_TOKEN: ${{ secrets.UV_PUBLISH_TOKEN }} - run: uv publish + - name: Upload dist artifacts + uses: actions/upload-artifact@v4 + with: + name: dist + path: dist/ -## \ No newline at end of file + publish: + name: Publish to PyPI + runs-on: ubuntu-latest + needs: build + environment: + name: pypi + url: https://pypi.org/project/atdata/ + + steps: + - name: Download dist artifacts + uses: actions/download-artifact@v4 + with: + name: dist + path: dist/ + + - name: Install uv + uses: astral-sh/setup-uv@v6 + + - name: Publish to PyPI + run: uv publish --trusted-publishing always dist/* diff --git a/.github/workflows/uv-test.yml b/.github/workflows/uv-test.yml index 2cc32f1..cc8b74d 100644 --- a/.github/workflows/uv-test.yml +++ b/.github/workflows/uv-test.yml @@ -1,5 +1,3 @@ -# - name: Run tests with `uv` on: @@ -11,33 +9,60 @@ on: branches: - main +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: - uv-test: - name: Run tests + lint: + name: Lint + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v5 + + - name: Install uv + uses: astral-sh/setup-uv@v6 + with: + enable-cache: true + + - name: Install the project + run: uv sync --locked --dev + + - name: Run ruff check + run: uv run ruff check src/ tests/ + + - name: Run ruff format check + run: uv run ruff format --check src/ tests/ + + test: + name: Test (py${{ matrix.python-version }}, redis${{ matrix.redis-version }}) runs-on: ubuntu-latest environment: name: test strategy: + fail-fast: false matrix: - python-version: [3.12, 3.13, 3.14] + python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"] redis-version: [6, 7] steps: - uses: actions/checkout@v5 - - name: "Set up Python" + - name: Set up Python uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - # python-version-file: "pyproject.toml" - name: Install uv uses: astral-sh/setup-uv@v6 + with: + enable-cache: true - name: Install the project - run: uv sync --all-extras --dev - # TODO Better to use --locked for author control over versions? - # run: uv sync --locked --all-extras --dev + run: uv sync --locked --all-extras --dev - name: Start Redis uses: supercharge/redis-github-action@1.8.1 @@ -47,12 +72,8 @@ jobs: - name: Run tests with coverage run: uv run pytest --cov=atdata --cov-report=xml --cov-report=term - # - name: Upload coverage to Codecov - # uses: codecov/codecov-action@v5 - # with: - # # file: ./coverage.xml # Claude hallucination -- fascinating! - # fail_ci_if_error: false - # token: ${{ secrets.CODECOV_TOKEN }} - - -# \ No newline at end of file + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v5 + with: + fail_ci_if_error: false + token: ${{ secrets.CODECOV_TOKEN }} diff --git a/.gitignore b/.gitignore index 1dfe222..75ac226 100644 --- a/.gitignore +++ b/.gitignore @@ -5,8 +5,10 @@ # Don't commit any .env files **/*.env # Don't commit `uv` lockfiles -**/uv.lock +# (SIKE it turns out we actually do want to commit) +# **/uv.lock # Development tooling (keep local, not in upstream) +# (SIKE it turns out we actually do want to commit) # .chainlink/ # .claude/ diff --git a/CHANGELOG.md b/CHANGELOG.md index 3976517..feeea7e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - **Comprehensive integration test suite**: 593 tests covering E2E flows, error handling, edge cases ### Changed +- Review GitHub workflows and recommend CI improvements (#405) +- Fix type signatures for Dataset.ordered and Dataset.shuffled (GH#28) (#404) +- Investigate quartodoc Example section rendering - missing CSS classes on pre/code tags (#401) +- Update all docstrings from Example: to Examples: format (#403) +- Create GitHub issues for v0.3 roadmap feature domains (#402) - Expand Quarto documentation with architectural narrative (#395) - Expand atmosphere tutorial with federation context (#400) - Expand local-workflow tutorial with system narrative (#399) diff --git a/CLAUDE.md b/CLAUDE.md index 0c315ae..349c268 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -209,11 +209,11 @@ def test_repo_insert_with_s3(mock_s3, clean_redis): ## Docstring Formatting -This project uses **Google-style docstrings** with quartodoc for API documentation generation. The most important formatting requirement is for **Example sections**. +This project uses **Google-style docstrings** with quartodoc for API documentation generation. The most important formatting requirement is for **Examples sections**. -### Example Section Format +### Examples Section Format -Example sections must use reStructuredText literal block syntax (`::`) to render correctly in quartodoc-generated documentation: +Use `Examples:` (plural) for code examples. This is recognized by griffe's Google docstring parser and rendered with proper syntax highlighting by quartodoc: ```python def my_function(): @@ -227,50 +227,44 @@ def my_function(): Returns: Description of return value. - Example: - :: - - >>> result = my_function() - >>> print(result) - 'output' + Examples: + >>> result = my_function() + >>> print(result) + 'output' """ ``` **Key formatting rules:** -1. `Example:` with a colon, 4-space indented from the docstring margin -2. `::` on its own line, 8-space indented (4 more than `Example:`) -3. Blank line after `::` -4. Code examples indented 12 spaces (4 more than `::`) -5. Use `>>>` for Python prompts and `...` for continuation lines +1. Use `Examples:` (plural, not `Example:` singular) +2. Code examples are indented 8 spaces (4 more than `Examples:`) +3. Use `>>>` for Python prompts and `...` for continuation lines +4. No `::` marker needed - griffe handles the parsing automatically -**Incorrect format (will not render properly):** +**Incorrect format (will not render with syntax highlighting):** ```python - Example: - >>> code_here() # Wrong - missing :: and extra indentation + Example: # Wrong - singular form is treated as an admonition + :: # Wrong - reST literal block marker not needed + >>> code_here() ``` **Correct format:** ```python - Example: - :: - - >>> code_here() # Correct - has :: and proper indentation + Examples: + >>> code_here() # Correct - plural form, proper indentation ``` ### Multiple Examples -For multiple examples, use the same pattern: +For multiple examples, continue in the same section: ```python - Example: - :: - - >>> # First example - >>> x = create_thing() + Examples: + >>> # First example + >>> x = create_thing() - >>> # Second example - >>> y = other_thing() + >>> # Second example + >>> y = other_thing() ``` ### Class and Method Docstrings @@ -281,20 +275,16 @@ Apply the same format to class docstrings and method docstrings: class MyClass: """Class description. - Example: - :: - - >>> obj = MyClass() - >>> obj.do_something() + Examples: + >>> obj = MyClass() + >>> obj.do_something() """ def method(self): """Method description. - Example: - :: - - >>> self.method() + Examples: + >>> self.method() """ ``` diff --git a/docs/api/AbstractDataStore.html b/docs/api/AbstractDataStore.html index c7a021f..b4b9393 100644 --- a/docs/api/AbstractDataStore.html +++ b/docs/api/AbstractDataStore.html @@ -402,7 +402,7 @@

On this page