Skip to content
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

🐛 Fixes error while updated study with long description #5989

Merged
merged 13 commits into from
Jun 24, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@
from pydantic import Field, validator

from ..api_schemas_long_running_tasks.tasks import TaskGet
from ..basic_types import HttpUrlWithCustomMinLength, IDStr
from ..basic_types import (
HttpUrlWithCustomMinLength,
LongTruncatedStr,
ShortTruncatedStr,
)
from ..emails import LowerCaseEmailStr
from ..projects import ClassifierID, DateTimeStr, NodesDict, ProjectID
from ..projects_access import AccessRights, GroupIDStr
Expand Down Expand Up @@ -85,8 +89,8 @@ class ProjectListItem(ProjectGet):

class ProjectReplace(InputSchema):
uuid: ProjectID
name: str
description: str
name: ShortTruncatedStr
description: LongTruncatedStr
thumbnail: HttpUrlWithCustomMinLength | None
creation_date: DateTimeStr
last_change_date: DateTimeStr
Expand All @@ -107,8 +111,8 @@ class ProjectReplace(InputSchema):


class ProjectUpdate(InputSchema):
name: str = FieldNotRequired()
description: str = FieldNotRequired()
name: ShortTruncatedStr = FieldNotRequired()
description: LongTruncatedStr = FieldNotRequired()
thumbnail: HttpUrlWithCustomMinLength = FieldNotRequired()
workbench: NodesDict = FieldNotRequired()
access_rights: dict[GroupIDStr, AccessRights] = FieldNotRequired()
Expand All @@ -118,13 +122,9 @@ class ProjectUpdate(InputSchema):
quality: dict[str, Any] = FieldNotRequired()


ProjectName: TypeAlias = IDStr
ProjectDescription: TypeAlias = IDStr


class ProjectPatch(InputSchema):
name: ProjectName = FieldNotRequired()
description: ProjectDescription = FieldNotRequired()
name: ShortTruncatedStr = FieldNotRequired()
description: LongTruncatedStr = FieldNotRequired()
thumbnail: HttpUrlWithCustomMinLength = FieldNotRequired()
access_rights: dict[GroupIDStr, AccessRights] = FieldNotRequired()
classifiers: list[ClassifierID] = FieldNotRequired()
Expand Down
17 changes: 17 additions & 0 deletions packages/models-library/src/models_library/basic_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,23 @@ class IDStr(ConstrainedStr):
max_length = 100


class ShortTruncatedStr(ConstrainedStr):
# NOTE: Use to input e.g. titles or display names
# A truncated string:
# - Strips whitespaces and truncate strings that exceed the specified characters limit (curtail_length).
# - Ensures that the **input** data length to the API is controlled and prevents exceeding large inputs silently, i.e. without raising errors.
# SEE https://github.com/ITISFoundation/osparc-simcore/pull/5989#discussion_r1650506583
strip_whitespace = True
curtail_length = 600


class LongTruncatedStr(ConstrainedStr):
# NOTE: Use to input e.g. descriptions or summaries
# Analogous to ShortTruncatedStr
strip_whitespace = True
curtail_length = 65536 # same as github descripton


# auto-incremented primary-key IDs
IdInt: TypeAlias = PositiveInt
PrimaryKeyInt: TypeAlias = PositiveInt
Expand Down
17 changes: 17 additions & 0 deletions packages/models-library/tests/test_projects.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import pytest
from faker import Faker
from models_library.api_schemas_webserver.projects import LongTruncatedStr, ProjectPatch
from models_library.projects import Project


Expand Down Expand Up @@ -40,3 +41,19 @@ def test_project_with_thumbnail_as_empty_string(minimal_project: dict[str, Any])

assert project
assert project.thumbnail is None


def test_project_patch_truncates_description():
# NOTE: checks https://github.com/ITISFoundation/osparc-simcore/issues/5988
assert LongTruncatedStr.curtail_length
len_truncated = int(LongTruncatedStr.curtail_length)

long_description = "X" * (len_truncated + 10)
assert len(long_description) > len_truncated

update = ProjectPatch(description=long_description)
assert len(update.description) == len_truncated

short_description = "X"
update = ProjectPatch(description=short_description)
assert len(update.description) == len(short_description)
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from fastapi import APIRouter, Depends, Header, Query, Request, status
from fastapi.encoders import jsonable_encoder
from fastapi.responses import JSONResponse, RedirectResponse
from models_library.api_schemas_webserver.projects import ProjectName, ProjectPatch
from models_library.api_schemas_webserver.projects import ProjectPatch
from models_library.api_schemas_webserver.projects_nodes import NodeOutputs
from models_library.clusters import ClusterID
from models_library.function_services_catalog.services import file_picker
Expand Down Expand Up @@ -116,7 +116,7 @@ async def create_study_job(
)

await webserver_api.patch_project(
project_id=job.id, patch_params=ProjectPatch(name=ProjectName(job.name))
project_id=job.id, patch_params=ProjectPatch(name=job.name)
)

project_inputs = await webserver_api.get_project_inputs(project_id=project.uuid)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9549,13 +9549,9 @@ components:
properties:
name:
title: Name
maxLength: 100
minLength: 1
type: string
description:
title: Description
maxLength: 100
minLength: 1
pcrespov marked this conversation as resolved.
Show resolved Hide resolved
type: string
thumbnail:
title: Thumbnail
Expand Down
Loading