Skip to content
Merged
Show file tree
Hide file tree
Changes from 62 commits
Commits
Show all changes
69 commits
Select commit Hold shift + click to select a range
cf8dd9b
drafts first tests
pcrespov Jan 29, 2025
e3d2dc7
respx and httpx
pcrespov Jan 29, 2025
19dff61
drafts test
pcrespov Jan 29, 2025
0def310
gets items
pcrespov Jan 29, 2025
874bda2
get_category_items and settings
pcrespov Jan 29, 2025
764b263
test pass
pcrespov Jan 29, 2025
22bcb39
adds new column
pcrespov Jan 29, 2025
f5af34a
adding trashing
pcrespov Jan 29, 2025
af2fed0
tests pass
pcrespov Jan 29, 2025
f227738
split settings
pcrespov Jan 30, 2025
d245e70
split models
pcrespov Jan 30, 2025
3d40c4b
sonar security
pcrespov Jan 30, 2025
cb8bca9
notes
pcrespov Jan 30, 2025
992906d
notes
pcrespov Jan 30, 2025
6bdc056
updates db
pcrespov Jan 30, 2025
d976a9d
fetch&create
pcrespov Jan 30, 2025
77be4fc
test create
pcrespov Jan 30, 2025
ae278f0
if not exists
pcrespov Jan 30, 2025
cfc6caa
cleanup
pcrespov Jan 30, 2025
fdae0a9
constrinat
pcrespov Jan 30, 2025
326de71
migration:
pcrespov Jan 30, 2025
684e28f
registration
pcrespov Jan 30, 2025
894505a
states
pcrespov Jan 30, 2025
54c69f9
cleanup
pcrespov Jan 30, 2025
c016bb0
drafts ideas for rest entyrpoint
pcrespov Jan 30, 2025
60c7d05
cleanup
pcrespov Jan 31, 2025
8738ef2
Merge branch 'master' into is7097/fetch-vip-api
pcrespov Jan 31, 2025
325bb45
fixes migration
pcrespov Jan 31, 2025
b70feb4
minor fix on try again
pcrespov Jan 31, 2025
3665e10
update model features
pcrespov Jan 31, 2025
a5b3d07
retry policy
pcrespov Jan 31, 2025
f8c5878
updates
pcrespov Jan 31, 2025
610131a
tests pass
pcrespov Jan 31, 2025
6bba3e1
result
pcrespov Jan 31, 2025
dde6c43
cleanup
pcrespov Jan 31, 2025
06f0c11
drafts syncer
pcrespov Jan 31, 2025
94f0fed
tests pass
pcrespov Jan 31, 2025
75fbcb3
adds deepdiff
pcrespov Jan 31, 2025
dfa43f9
drafts task
pcrespov Jan 31, 2025
a152413
draft demo
pcrespov Feb 3, 2025
2238c93
fixes dev mode
pcrespov Feb 3, 2025
ac35a49
drafts demo
pcrespov Feb 3, 2025
3d2eec6
new fake
pcrespov Feb 3, 2025
6a7822e
tests model guarantees
pcrespov Feb 3, 2025
de1ec81
source is respected
pcrespov Feb 3, 2025
0a11891
Merge branch 'master' into is7097/fetch-vip-api
pcrespov Feb 3, 2025
f89181c
adapting tests
pcrespov Feb 3, 2025
465153c
no dump
pcrespov Feb 3, 2025
98abd7c
Merge branch 'master' into is7097/fetch-vip-api
pcrespov Feb 4, 2025
f86c68e
updates model
pcrespov Feb 4, 2025
e98316f
refactoring models
pcrespov Feb 4, 2025
ffd14ca
model
pcrespov Feb 4, 2025
8654e70
updates OSA
pcrespov Feb 4, 2025
a10f389
fixes mypy
pcrespov Feb 4, 2025
b425f76
Merge branch 'master' into is7097/fetch-vip-api
pcrespov Feb 4, 2025
8e22e11
settings
pcrespov Feb 4, 2025
4628cc8
refactors statics
pcrespov Feb 4, 2025
e801def
cleanup
pcrespov Feb 4, 2025
a882cae
cleanup
pcrespov Feb 4, 2025
aeab902
services/webserver api version: 0.51.0 → 0.52.0
pcrespov Feb 4, 2025
1acf690
new example
pcrespov Feb 4, 2025
5d45c0b
test fixes
pcrespov Feb 4, 2025
acc8fad
doc
pcrespov Feb 5, 2025
bac7e3b
Merge branch 'master' into is7097/fetch-vip-api
pcrespov Feb 5, 2025
850b4ca
@GitHK review: missing todo
pcrespov Feb 5, 2025
39bd21d
@matusdrobuliak66 review: env prefix
pcrespov Feb 5, 2025
42d1317
@YuryHrytsuk review: tests backwards compatiblity
pcrespov Feb 5, 2025
7523b8d
fixes sonarcloud
pcrespov Feb 5, 2025
35041a5
cleanup
pcrespov Feb 5, 2025
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
6 changes: 5 additions & 1 deletion .env-devel
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,11 @@ DYNAMIC_SCHEDULER_UI_STORAGE_SECRET=adminadmin

FUNCTION_SERVICES_AUTHORS='{"UN": {"name": "Unknown", "email": "[email protected]", "affiliation": "unknown"}}'

WEBSERVER_LICENSES={}
LICENSES_ITIS_VIP_SYNCER_ENABLED=false
ITIS_VIP_API_URL=https://some-api/{category}
ITIS_VIP_CATEGORIES='{"HumanWholeBody": "Humans", "HumanBodyRegion": "Humans (Region)", "AnimalWholeBody": "Animal"}'

# Can use 'docker run -it itisfoundation/invitations:latest simcore-service-invitations generate-dotenv --auto-password'
INVITATIONS_DEFAULT_PRODUCT=osparc
INVITATIONS_HOST=invitations
Expand Down Expand Up @@ -371,7 +376,6 @@ WEBSERVER_GARBAGE_COLLECTOR=null
WEBSERVER_GROUPS=1
WEBSERVER_GUNICORN_CMD_ARGS=--timeout=180
WEBSERVER_HOST=webserver
WEBSERVER_LICENSES=true
WEBSERVER_LOGIN={}
WEBSERVER_LOGLEVEL=INFO
WEBSERVER_META_MODELING=1
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from datetime import datetime
from typing import NamedTuple

from models_library.licensed_items import LicensedItemID
from models_library.licenses import LicensedItemID
from models_library.products import ProductName
from models_library.resource_tracker_licensed_items_checkouts import (
LicensedItemCheckoutID,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from decimal import Decimal
from typing import NamedTuple

from models_library.licensed_items import LicensedItemID
from models_library.licenses import LicensedItemID
from models_library.products import ProductName
from models_library.resource_tracker import PricingUnitCostId
from models_library.resource_tracker_licensed_items_purchases import (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
from datetime import datetime
from typing import Any, NamedTuple, cast
from typing import Any, NamedTuple, Self, cast

from models_library.licensed_items import (
from models_library.basic_types import IDStr
from models_library.resource_tracker import PricingPlanId
from pydantic import BaseModel, ConfigDict, HttpUrl, PositiveInt
from pydantic.config import JsonDict

from ..licenses import (
VIP_DETAILS_EXAMPLE,
FeaturesDict,
LicensedItem,
LicensedItemID,
LicensedResourceType,
)
from models_library.resource_tracker import PricingPlanId
from models_library.utils.common_validators import to_camel_recursive
from pydantic import AfterValidator, BaseModel, ConfigDict, PositiveInt
from pydantic.config import JsonDict
from typing_extensions import Annotated

from ._base import OutputSchema

# RPC
Expand All @@ -25,6 +26,7 @@ class LicensedItemRpcGet(BaseModel):
pricing_plan_id: PricingPlanId
created_at: datetime
modified_at: datetime

model_config = ConfigDict(
json_schema_extra={
"examples": [
Expand All @@ -50,33 +52,73 @@ class LicensedItemRpcGetPage(NamedTuple):
# Rest


class _ItisVipRestData(BaseModel):
description: str
thumbnail: str
features: FeaturesDict
doi: str


class _ItisVipResourceRestData(OutputSchema):
category_id: IDStr
category_display: str
source: _ItisVipRestData
terms_of_use_url: HttpUrl | None = None


class LicensedItemRestGet(OutputSchema):
licensed_item_id: LicensedItemID
display_name: str
# NOTE: to put here a discriminator we have to embed it one more layer
licensed_resource_type: LicensedResourceType
licensed_resource_data: Annotated[
dict[str, Any], AfterValidator(to_camel_recursive)
]
licensed_resource_data: _ItisVipResourceRestData
pricing_plan_id: PricingPlanId

created_at: datetime
modified_at: datetime

model_config = ConfigDict(
json_schema_extra={
"examples": [
{
"licensed_item_id": "0362b88b-91f8-4b41-867c-35544ad1f7a1",
"display_name": "best-model",
"licensed_resource_type": f"{LicensedResourceType.VIP_MODEL}",
"licensed_resource_data": cast(JsonDict, VIP_DETAILS_EXAMPLE),
"pricing_plan_id": "15",
"created_at": "2024-12-12 09:59:26.422140",
"modified_at": "2024-12-12 09:59:26.422140",
}
]
}
)
@staticmethod
def _update_json_schema_extra(schema: JsonDict) -> None:
schema.update(
{
"examples": [
{
"licensedItemId": "0362b88b-91f8-4b41-867c-35544ad1f7a1",
"displayName": "my best model",
"licensedResourceName": "best-model",
"licensedResourceType": f"{LicensedResourceType.VIP_MODEL}",
"licensedResourceData": cast(
JsonDict,
{
"categoryId": "HumanWholeBody",
"categoryDisplay": "Humans",
"source": VIP_DETAILS_EXAMPLE,
},
),
"pricingPlanId": "15",
"createdAt": "2024-12-12 09:59:26.422140",
"modifiedAt": "2024-12-12 09:59:26.422140",
}
]
}
)

model_config = ConfigDict(json_schema_extra=_update_json_schema_extra)

@classmethod
def from_domain_model(cls, item: LicensedItem) -> Self:

return cls.model_validate(
{
"licensed_item_id": item.licensed_item_id,
"display_name": item.display_name,
"licensed_resource_type": item.licensed_resource_type,
"licensed_resource_data": item.licensed_resource_data,
"pricing_plan_id": item.pricing_plan_id,
"created_at": item.created_at,
"modified_at": item.modified_at,
}
)


class LicensedItemRestGetPage(NamedTuple):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from models_library.emails import LowerCaseEmailStr
from pydantic import BaseModel, ConfigDict, PositiveInt

from ..licensed_items import LicensedItemID
from ..licenses import LicensedItemID
from ..products import ProductName
from ..resource_tracker_licensed_items_checkouts import LicensedItemCheckoutID
from ..users import UserID
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from models_library.emails import LowerCaseEmailStr
from pydantic import PositiveInt

from ..licensed_items import LicensedItemID
from ..licenses import LicensedItemID
from ..products import ProductName
from ..resource_tracker import PricingUnitCostId
from ..resource_tracker_licensed_items_purchases import LicensedItemPurchaseID
Expand Down
74 changes: 0 additions & 74 deletions packages/models-library/src/models_library/licensed_items.py

This file was deleted.

127 changes: 127 additions & 0 deletions packages/models-library/src/models_library/licenses.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
from datetime import datetime
from enum import auto
from typing import Any, NamedTuple, NotRequired, TypeAlias, cast
from uuid import UUID

from models_library.resource_tracker import PricingPlanId
from pydantic import BaseModel, ConfigDict, PositiveInt
from pydantic.config import JsonDict
from typing_extensions import TypedDict

from .products import ProductName
from .resource_tracker import PricingPlanId
from .utils.enums import StrAutoEnum

LicensedItemID: TypeAlias = UUID


class LicensedResourceType(StrAutoEnum):
VIP_MODEL = auto()


VIP_FEATURES_EXAMPLE = {
"name": "Duke",
"version": "V2.0",
"sex": "Male",
"age": "34 years",
"weight": "70.2 Kg",
"height": "1.77 m",
"date": "2015-03-01",
"ethnicity": "Caucasian",
"functionality": "Static",
"additional_field": "allowed",
}


class FeaturesDict(TypedDict):
name: NotRequired[str]
version: NotRequired[str]
sex: NotRequired[str]
age: NotRequired[str]
weight: NotRequired[str]
height: NotRequired[str]
date: str
ethnicity: NotRequired[str]
functionality: NotRequired[str]


VIP_DETAILS_EXAMPLE = {
"id": 1,
"description": "custom description",
"thumbnail": "custom description",
"features": VIP_FEATURES_EXAMPLE,
"doi": "custom value",
"license_key": "custom value",
"license_version": "custom value",
"protection": "custom value",
"available_from_url": "custom value",
"additional_field": "trimmed if rest",
}


#
# DB
#


class LicensedItemDB(BaseModel):
licensed_item_id: LicensedItemID
display_name: str

licensed_resource_name: str
licensed_resource_type: LicensedResourceType
licensed_resource_data: dict[str, Any] | None

pricing_plan_id: PricingPlanId | None
product_name: ProductName | None

# states
created: datetime
modified: datetime
trashed: datetime | None

model_config = ConfigDict(from_attributes=True)


class LicensedItemUpdateDB(BaseModel):
display_name: str | None = None
licensed_resource_name: str | None = None
pricing_plan_id: PricingPlanId | None = None
trash: bool | None = None


class LicensedItem(BaseModel):
licensed_item_id: LicensedItemID
display_name: str
licensed_resource_name: str
licensed_resource_type: LicensedResourceType
licensed_resource_data: dict[str, Any]
pricing_plan_id: PricingPlanId
created_at: datetime
modified_at: datetime

@staticmethod
def _update_json_schema_extra(schema: JsonDict) -> None:
schema.update(
{
"examples": [
{
"licensed_item_id": "0362b88b-91f8-4b41-867c-35544ad1f7a1",
"display_name": "my best model",
"licensed_resource_name": "best-model",
"licensed_resource_type": f"{LicensedResourceType.VIP_MODEL}",
"licensed_resource_data": cast(JsonDict, VIP_DETAILS_EXAMPLE),
"pricing_plan_id": "15",
"created_at": "2024-12-12 09:59:26.422140",
"modified_at": "2024-12-12 09:59:26.422140",
}
]
}
)

model_config = ConfigDict(json_schema_extra=_update_json_schema_extra)


class LicensedItemPage(NamedTuple):
total: PositiveInt
items: list[LicensedItem]
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

from pydantic import BaseModel, ConfigDict

from .licensed_items import LicensedItemID
from .licenses import LicensedItemID
from .products import ProductName
from .resource_tracker import PricingPlanId, PricingUnitCostId, PricingUnitId
from .users import UserID
Expand Down
Loading
Loading