Skip to content
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
10 changes: 10 additions & 0 deletions copier.yml
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,16 @@ _tasks:
echo "pyrightconfig.json not found"
fi
when: "{{ is_circuit_python_driver }}"
- command: |
echo "Checking .config/pyrefly.toml..."
if [ -f .config/pyrefly.toml ]; then
if ! grep -q 'firmware/src' .config/pyrefly.toml; then
sed -i 's#search-path = \["../backend/src", "../backend"\]#search-path = ["../backend/src", "../backend", "../backend/src/backend_api/firmware/src"]#' .config/pyrefly.toml
fi
else
echo ".config/pyrefly.toml not found"
fi
when: "{{ is_circuit_python_driver }}"
Comment thread
zendern marked this conversation as resolved.
- command: |
echo "Checking for .coveragerc in repo root config..."
if [ -f .config/.coveragerc ]; then
Expand Down
22 changes: 21 additions & 1 deletion template/.config/vacuum-ignore.yaml.jinja
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,27 @@
owasp-define-error-validation:
- "$.paths['/api/shutdown'].get.responses"

{% endraw %}{% if backend_uses_graphql %}{% raw %}# /api/graphql's 200 response body is arbitrary JSON shaped by the caller's GraphQL query/GraphiQL page;
{% endraw %}{% if is_circuit_python_driver %}{% raw %}# A generated driver only ever manages a single physical device connection at a time, so its

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the route is id/attribute, then that would be a little common singular pattern a lot right, not just for drivers? We may need a refactor later to make vacuum better suited

# resource paths are intentionally singular ("driver", not "drivers") rather than REST-collection plural.
resources-plural:
- "$.paths['/api/driver/data-from-serial-port']"
- "$.paths['/api/driver/device-info-from-serial-port']"
- "$.paths['/api/driver/device-connection']"
- "$.paths['/api/driver/send-raw-command']"
- "$.paths['/api/driver/measurement-types']"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NIT: isn't types already plural?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Issue is not with measurement-types its with driver. Resources plural is ensuring that resources are in fact plural. In this case switching those all our to be drivers felt off specially since some of those debug commands are not using sensor_ids. Wonder if the better answer is we should actually drop driver. And it should become devices and some of the debug ones maybe become something debug specific of /api/devices/debug/ and we just allow list all those. Idk but feels like a future me problem to tweak this api.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah.

I think I was thinking of "driver" originally as more of a "category", because there was were other routes having to do with "mDNS". Yeah, definitely due for some refactoring, and definitely not in this PR

- "$.paths['/api/driver/{sensor_id}']"
- "$.paths['/api/driver/{sensor_id}/name']"
- "$.paths['/api/driver/{sensor_id}/reset']"
- "$.paths['/api/driver/{sensor_id}/clear-memory']"
- "$.paths['/api/driver/{sensor_id}/measure/export']"

# no-request-body flags DELETE with a body as non-RESTful. DELETE /device-connection removes a
# device by mDNS service name with no resource ID in the path, so the service name must travel
# in the body. The rule stays enabled for future endpoints; only this one is exempted.
no-request-body:
- "$.paths['/api/driver/device-connection'].delete"

{% endraw %}{% endif %}{% raw %}{% endraw %}{% if backend_uses_graphql %}{% raw %}# /api/graphql's 200 response body is arbitrary JSON shaped by the caller's GraphQL query/GraphiQL page;
# there is no single representative example to attach without misleadingly implying a fixed response shape.
response-body-example:
- "$.paths['/api/graphql'].get.responses['200']"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,14 @@ from fastapi.staticfiles import StaticFiles
from fastapi_offline import FastAPIOffline
from pydantic import Field{% endraw %}{% if has_circuit_python_backend_template_been_instantiated %}{% raw %}
from zeroconf.asyncio import AsyncZeroconf{% endraw %}{% endif %}{% raw %}
{% endraw %}{% if has_circuit_python_backend_template_been_instantiated %}{% raw %}

from .camel_case_model import CamelCaseModel{% endraw %}{% if has_circuit_python_backend_template_been_instantiated %}{% raw %}
from .common.bridges import router as bridges_router
from .common.mdns import SimpleBrowser
from .common.mdns import register_driver
from .common.mdns import router as mdns_router
from .common.rfc_servers_jinja import get_servers_container
from .driver_routes import router as driver_router{% endraw %}{% endif %}{% raw %}
from .camel_case_model import CamelCaseModel
from .entrypoint.parser import get_version
from .fast_api_exception_handlers import register_exception_handlers{% endraw %}{% if backend_uses_graphql %}{% raw %}
from .graphql.schema import schema{% endraw %}{% endif %}{% raw %}
Expand Down Expand Up @@ -75,7 +75,6 @@ async def lifespan(app: FastAPI):
logger.info("Shutting down FastAPI application")

{% endraw %}{% endif %}{% raw %}

API_DESCRIPTION = {% endraw %}{{ backend_rest_api_description | tojson }}{% raw %}

OPENAPI_APP_SPECIFIC_TAGS: list[dict[str, str]] = [
Expand All @@ -86,6 +85,10 @@ OPENAPI_TAGS = [
{"name": "system", "description": "Server health and lifecycle operations."},{% endraw %}{% if backend_uses_graphql %}{% raw %}
{"name": "graphql", "description": "GraphQL endpoint"},{% endraw %}{% endif %}{% if has_circuit_python_backend_template_been_instantiated %}{% raw %}
{"name": "debug", "description": "Debug and diagnostic operations."},
{
"name": "driver",
"description": "Operations for reading measurements from and controlling a connected device driver.",
},
{"name": "mDNS", "description": "mDNS service discovery operations."},{% endraw %}{% endif %}{% raw %}
*OPENAPI_APP_SPECIFIC_TAGS,
]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,9 @@ def custom_openapi(app: FastAPI) -> dict[str, Any]:
},
}
for schema_name, schema_metadata in generated_schema_metadata.items():
if schema_name in comps:
if (
schema_name in comps
): # pragma: no branch # every app has at least one validating route (even just the health check), so HTTPValidationError/ValidationError are always already in comps by the time this runs
for key, value in schema_metadata.items():
_ = comps[schema_name].setdefault(key, value)

Expand Down