Skip to content

Use pinned dependencies for testing #96

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Mar 7, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 40 additions & 8 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ jobs:
mv coverage.lcov base-coverage.lcov

- name: Upload code coverage for base branch
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: base-coverage.lcov
path: ./base-coverage.lcov
Expand All @@ -34,7 +34,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python: ["3.9", "3.10", "3.11", "3.12"]
python: ["3.10", "3.11", "3.12", "3.13"]

steps:
- uses: actions/checkout@v3
Expand All @@ -45,7 +45,7 @@ jobs:
python-version: ${{ matrix.python }}

- name: Install Dependencies
run: pip install -e .[dev,server]
run: pip install -e . -r dev-requirements.txt

- name: Lint with Ruff
run: ruff check .
Expand All @@ -57,25 +57,57 @@ jobs:
run: pytest --cov=src --cov-report=lcov

- name: Upload code coverage
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: coverage.lcov
name: coverage-${{ matrix.python }}
path: ./coverage.lcov

- name: Analyse with MyPy
run: mypy src

test-with-unpinned-deps:
runs-on: ubuntu-latest
strategy:
matrix:
python: ["3.10", "3.11", "3.12", "3.13"]

steps:
- uses: actions/checkout@v3

- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python }}

- name: Install Dependencies
run: pip install -e .[dev,server]

- name: Lint with Ruff
run: ruff check .

- name: Format with Ruff
if: success() || failure()
run: ruff format --check .

- name: Analyse with MyPy
if: success() || failure()
run: mypy src

- name: Test with pytest
if: success() || failure()
run: pytest --cov=src --cov-report=lcov

coverage:
runs-on: ubuntu-latest
needs: [base_coverage, test]
steps:
- name: Download code coverage report
uses: actions/download-artifact@v3
uses: actions/download-artifact@v4
with:
name: coverage.lcov
name: coverage-3.12

- name: Download code coverage report for base branch
uses: actions/download-artifact@v3
uses: actions/download-artifact@v4
with:
name: base-coverage.lcov

Expand Down
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,14 @@ You can install this repository with `pip`, either clone it and run `pip install

The code is linted with `ruff .`, type checked with `mypy src`, and tested with `pytest`. These all run in CI with GitHub Actions. The codebase is not even `v0.1` yet so it's still subject to summary rearrangement.

Dependencies are defined in `pyproject.toml` and can be compiled to `dev-requirements.txt` with:
```
uv pip compile --extra dev --extra server pyproject.toml --output-file dev-requirements.txt
```
If you're not using `uv`, just regular `pip-compile` from `pip-tools` will do the same thing.

All changes to the codebase should go via pull requests, and should only be merged once all the checks in the `test` job are passing. It is preferable to merge code where the `test-with-unpinned-dependencies` job fails, and deal with the dependency issues in another PR, particularly where the required changes are distinct from the code in the PR.

## Demo

See the [examples folder](./examples/) for a runnable demo.
Expand Down
166 changes: 166 additions & 0 deletions dev-requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
# This file was autogenerated by uv via the following command:
# uv pip compile --extra dev --extra server pyproject.toml --output-file dev-requirements.txt
annotated-types==0.7.0
# via pydantic
anyio==4.8.0
# via
# labthings-fastapi (pyproject.toml)
# httpx
# starlette
# watchfiles
attrs==25.1.0
# via
# jsonschema
# referencing
certifi==2025.1.31
# via
# httpcore
# httpx
click==8.1.8
# via
# rich-toolkit
# typer
# uvicorn
colorama==0.4.6
# via
# click
# pytest
# uvicorn
coverage==7.6.12
# via pytest-cov
dnspython==2.7.0
# via email-validator
email-validator==2.2.0
# via fastapi
fastapi==0.115.11
# via labthings-fastapi (pyproject.toml)
fastapi-cli==0.0.7
# via fastapi
h11==0.14.0
# via
# httpcore
# uvicorn
httpcore==1.0.7
# via httpx
httptools==0.6.4
# via uvicorn
httpx==0.28.1
# via
# labthings-fastapi (pyproject.toml)
# fastapi
idna==3.10
# via
# anyio
# email-validator
# httpx
ifaddr==0.2.0
# via zeroconf
iniconfig==2.0.0
# via pytest
itsdangerous==2.2.0
# via fastapi
jinja2==3.1.6
# via fastapi
jsonschema==4.23.0
# via labthings-fastapi (pyproject.toml)
jsonschema-specifications==2024.10.1
# via jsonschema
markdown-it-py==3.0.0
# via rich
markupsafe==3.0.2
# via jinja2
mdurl==0.1.2
# via markdown-it-py
mypy==1.15.0
# via labthings-fastapi (pyproject.toml)
mypy-extensions==1.0.0
# via mypy
numpy==2.2.3
# via labthings-fastapi (pyproject.toml)
orjson==3.10.15
# via fastapi
packaging==24.2
# via pytest
pluggy==1.5.0
# via pytest
pydantic==2.10.6
# via
# labthings-fastapi (pyproject.toml)
# fastapi
# pydantic-extra-types
# pydantic-settings
pydantic-core==2.27.2
# via pydantic
pydantic-extra-types==2.10.2
# via fastapi
pydantic-settings==2.8.1
# via fastapi
pygments==2.19.1
# via rich
pytest==7.4.4
# via
# labthings-fastapi (pyproject.toml)
# pytest-cov
pytest-cov==6.0.0
# via labthings-fastapi (pyproject.toml)
python-dotenv==1.0.1
# via
# pydantic-settings
# uvicorn
python-multipart==0.0.20
# via fastapi
pyyaml==6.0.2
# via
# fastapi
# uvicorn
referencing==0.36.2
# via
# jsonschema
# jsonschema-specifications
# types-jsonschema
rich==13.9.4
# via
# rich-toolkit
# typer
rich-toolkit==0.13.2
# via fastapi-cli
rpds-py==0.23.1
# via
# jsonschema
# referencing
ruff==0.9.10
# via labthings-fastapi (pyproject.toml)
shellingham==1.5.4
# via typer
sniffio==1.3.1
# via anyio
starlette==0.46.0
# via fastapi
typer==0.15.2
# via fastapi-cli
types-jsonschema==4.23.0.20241208
# via labthings-fastapi (pyproject.toml)
typing-extensions==4.12.2
# via
# labthings-fastapi (pyproject.toml)
# anyio
# fastapi
# mypy
# pydantic
# pydantic-core
# pydantic-extra-types
# referencing
# rich-toolkit
# typer
ujson==5.10.0
# via fastapi
uvicorn==0.34.0
# via
# fastapi
# fastapi-cli
watchfiles==1.0.4
# via uvicorn
websockets==15.0.1
# via uvicorn
zeroconf==0.146.1
# via labthings-fastapi (pyproject.toml)
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ authors = [
]
description = "A test implementation of LabThings using FastAPI"
readme = "README.md"
requires-python = ">=3.9"
requires-python = ">=3.10"
classifiers = [
"Programming Language :: Python :: 3",
"License :: OSI Approved :: MIT License",
Expand Down
57 changes: 0 additions & 57 deletions requirements.txt

This file was deleted.

4 changes: 1 addition & 3 deletions src/labthings_fastapi/actions/invocation_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,7 @@ def generate_message(cls, data: Any):
# it will cause 500 errors when retrieving
# the invocation.
# This way, you can find and fix the source.
data.message = (
f"Error constructing message ({e}) " f"from {data!r}."
)
data.message = f"Error constructing message ({e}) from {data!r}."
return data


Expand Down
6 changes: 3 additions & 3 deletions src/labthings_fastapi/thing_description/validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def validate_thing_description(td: dict) -> None:
jsonschema.validate(instance=td, schema=schema)
validated_td = time.time()
logging.info(
f"Thing Description validated OK (schema load: {loaded_schema-start:.1f}s, "
f"schema validation: {validated_schema-loaded_schema:.1f}s, TD validation: "
f"{validated_td-validated_schema:.1f}s)"
f"Thing Description validated OK (schema load: {loaded_schema - start:.1f}s, "
f"schema validation: {validated_schema - loaded_schema:.1f}s, TD validation: "
f"{validated_td - validated_schema:.1f}s)"
)
2 changes: 1 addition & 1 deletion src/labthings_fastapi/types/numpy.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ def np_to_listoflists(arr: np.ndarray) -> NestedListOfNumbers:
NB this will not be quick! Large arrays will be much better
serialised by dumping to base64 encoding or similar.
"""
return arr.tolist()
return arr.tolist() # type: ignore[return-value]


def listoflists_to_np(lol: Union[NestedListOfNumbers, np.ndarray]) -> np.ndarray:
Expand Down