From 8178fb0f5735d8d4c6f156c7e1a22df6f2c2d8f8 Mon Sep 17 00:00:00 2001 From: Justas Balcas Date: Sun, 18 Oct 2026 20:46:55 -0500 Subject: [PATCH] fix schemathesis failures. 5mb limit by def. --- app/routers/filesystem/facility_adapter.py | 10 +-------- app/routers/filesystem/filesystem.py | 2 -- app/routers/filesystem/models.py | 24 +++++++++++++++++++--- 3 files changed, 22 insertions(+), 14 deletions(-) diff --git a/app/routers/filesystem/facility_adapter.py b/app/routers/filesystem/facility_adapter.py index 85b9815a..d498f0ea 100644 --- a/app/routers/filesystem/facility_adapter.py +++ b/app/routers/filesystem/facility_adapter.py @@ -1,4 +1,3 @@ -import os from abc import abstractmethod from ...types.user import User from ..status import models as status_models @@ -6,14 +5,7 @@ from ..iri_router import AuthenticatedAdapter -def to_int(name, default_value): - try: - return int(os.environ.get(name) or default_value) - except: - return default_value - - -OPS_SIZE_LIMIT = to_int("OPS_SIZE_LIMIT", 5 * 1024 * 1024) +OPS_SIZE_LIMIT = filesystem_models.OPS_SIZE_LIMIT class FacilityAdapter(AuthenticatedAdapter): diff --git a/app/routers/filesystem/filesystem.py b/app/routers/filesystem/filesystem.py index 6b97fd71..2473caaa 100644 --- a/app/routers/filesystem/filesystem.py +++ b/app/routers/filesystem/filesystem.py @@ -305,8 +305,6 @@ async def post_view( request: Request, user: User = Depends(router.current_user), ) -> task_models.TaskSubmitResponse: - if request_model.size > facility_adapter.OPS_SIZE_LIMIT: - raise HTTPException(status_code=400, detail=f"Requested size exceeds limit of {facility_adapter.OPS_SIZE_LIMIT} bytes.") resource = await _user_resource(resource_id, user) return await router.task_adapter.put_task( user=user, diff --git a/app/routers/filesystem/models.py b/app/routers/filesystem/models.py index 6603ed43..40d112fb 100644 --- a/app/routers/filesystem/models.py +++ b/app/routers/filesystem/models.py @@ -6,12 +6,30 @@ # Please, refer to the LICENSE file in the root directory. # SPDX-License-Identifier: BSD-3-Clause +import os from enum import Enum from pydantic import Field, AliasChoices, BaseModel from ...types.scalars import CompressionType, CompressionTypeValue +def to_int(name, default_value): + try: + return int(os.environ.get(name) or default_value) + except: + return default_value + + +# Defined here, not in facility_adapter (which imports this module), so request models can declare it. +OPS_SIZE_LIMIT = to_int("OPS_SIZE_LIMIT", 5 * 1024 * 1024) + +# The head/tail handlers require exactly one of `bytes` or `lines`; declare that in the schema too. +EXACTLY_ONE_OF_BYTES_OR_LINES = [ + {"required": ["bytes"], "properties": {"bytes": {"type": "integer"}}}, + {"required": ["lines"], "properties": {"lines": {"type": "integer"}}}, +] + + class ContentUnit(str, Enum): """Defines the unit of content for file operations.""" lines = "lines" @@ -316,7 +334,7 @@ class PostHeadRequest(FilesystemRequestBase): file_bytes: int | None = Field(default=None, alias="bytes", description="Return the first NUM bytes of the file", example=1024) lines: int | None = Field(default=None, description="Return the first NUM lines of the file", example=10) skip_trailing: bool = Field(default=False, alias="skipTrailing", description="Return the whole file without the last NUM bytes/lines", example=False) - model_config = {"populate_by_name": True, "json_schema_extra": {"examples": [{"path": "/home/user/file.txt", "lines": 10}]}} + model_config = {"populate_by_name": True, "json_schema_extra": {"oneOf": EXACTLY_ONE_OF_BYTES_OR_LINES, "examples": [{"path": "/home/user/file.txt", "lines": 10}]}} class PostTailRequest(FilesystemRequestBase): @@ -325,13 +343,13 @@ class PostTailRequest(FilesystemRequestBase): file_bytes: int | None = Field(default=None, alias="bytes", ge=1, description="Return the last NUM bytes of the file", example=1024) lines: int | None = Field(default=None, ge=1, description="Return the last NUM lines of the file", example=10) skip_heading: bool = Field(default=False, alias="skipHeading", description="Return the whole file without the first NUM bytes/lines", example=False) - model_config = {"populate_by_name": True, "json_schema_extra": {"examples": [{"path": "/home/user/file.txt", "lines": 10}]}} + model_config = {"populate_by_name": True, "json_schema_extra": {"oneOf": EXACTLY_ONE_OF_BYTES_OR_LINES, "examples": [{"path": "/home/user/file.txt", "lines": 10}]}} class PostViewRequest(FilesystemRequestBase): """Request body for the view endpoint.""" path: str = Field(..., description="File path", example="/home/user/file.txt") - size: int = Field(default=0, ge=1, description="Number of bytes to retrieve from the file", example=4096) + size: int = Field(default=0, ge=1, le=OPS_SIZE_LIMIT, description="Number of bytes to retrieve from the file", example=4096) offset: int = Field(default=0, ge=0, description="Byte offset to start reading from", example=0) model_config = {"json_schema_extra": {"examples": [{"path": "/home/user/file.txt", "size": 4096, "offset": 0}]}}