Skip to content

Commit a6818b5

Browse files
solve merge conflicts
2 parents 48c7c70 + b837ee0 commit a6818b5

File tree

10 files changed

+67
-44
lines changed

10 files changed

+67
-44
lines changed

packages/models-library/src/models_library/api_schemas_webserver/licensed_items.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,10 @@ class LicensedItemRestGet(OutputSchema):
5757
dict[str, Any], AfterValidator(to_camel_recursive)
5858
]
5959
pricing_plan_id: PricingPlanId
60+
6061
created_at: datetime
6162
modified_at: datetime
63+
6264
model_config = ConfigDict(
6365
json_schema_extra={
6466
"examples": [

packages/models-library/src/models_library/licensed_items.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,16 @@ class LicensedItemDB(BaseModel):
6363
modified: datetime
6464
trashed: datetime | None
6565

66+
licensed_resource_data: dict[str, Any] | None
67+
68+
pricing_plan_id: PricingPlanId | None
69+
product_name: ProductName | None
70+
71+
# states
72+
created: datetime
73+
modified: datetime
74+
trashed: datetime | None
75+
6676
model_config = ConfigDict(from_attributes=True)
6777

6878

packages/postgres-database/src/simcore_postgres_database/models/licensed_items.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,7 @@
66
import sqlalchemy as sa
77
from sqlalchemy.dialects import postgresql
88

9-
from ._common import (
10-
RefActions,
11-
column_created_datetime,
12-
column_modified_datetime,
13-
column_trashed_datetime,
14-
)
9+
from ._common import RefActions, column_modified_datetime, column_trashed_datetime
1510
from .base import metadata
1611

1712

@@ -47,6 +42,12 @@ class LicensedResourceType(str, enum.Enum):
4742
nullable=True,
4843
doc="Resource metadata. Used for read-only purposes",
4944
),
45+
sa.Column(
46+
"licensed_resource_data",
47+
postgresql.JSONB,
48+
nullable=True,
49+
doc="Resource metadata. Used for read-only purposes",
50+
),
5051
sa.Column(
5152
"pricing_plan_id",
5253
sa.BigInteger,
@@ -70,7 +71,6 @@ class LicensedResourceType(str, enum.Enum):
7071
nullable=True,
7172
doc="Product name identifier. If None, then the item is not exposed",
7273
),
73-
column_created_datetime(timezone=True),
7474
column_modified_datetime(timezone=True),
7575
column_trashed_datetime("licensed_item"),
7676
)

services/web/server/src/simcore_service_webserver/application_settings.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -411,7 +411,7 @@ def _enable_only_if_dev_features_allowed(cls, v, info: ValidationInfo):
411411

412412
return (
413413
None
414-
if info.field_name and is_nullable(cls.model_fields[info.field_name])
414+
if info.field_name and is_nullable(dict(cls.model_fields)[info.field_name])
415415
else False
416416
)
417417

services/web/server/src/simcore_service_webserver/application_settings_utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ def convert_to_environ_vars( # noqa: C901, PLR0915, PLR0912
202202
def _set_if_disabled(field_name, section):
203203
# Assumes that by default is enabled
204204
enabled = section.get("enabled", True)
205-
field = ApplicationSettings.model_fields[field_name]
205+
field = dict(ApplicationSettings.model_fields)[field_name]
206206
if not enabled:
207207
envs[field_name] = "null" if is_nullable(field) else "0"
208208
elif get_type(field) == bool:

services/web/server/src/simcore_service_webserver/licenses/_licensed_items_repository.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
_logger = logging.getLogger(__name__)
3535

3636

37+
_SELECTION_ARGS = get_columns_from_db_model(licensed_items, LicensedItemDB)
3738
_SELECTION_ARGS = get_columns_from_db_model(licensed_items, LicensedItemDB)
3839

3940

@@ -51,17 +52,18 @@ async def create(
5152
result = await conn.execute(
5253
licensed_items.insert()
5354
.values(
55+
product_name=product_name,
5456
licensed_resource_name=licensed_resource_name,
5557
licensed_resource_type=licensed_resource_type,
56-
pricing_plan_id=pricing_plan_id,
57-
product_name=product_name,
5858
licensed_resource_data=licensed_resource_data,
59+
pricing_plan_id=pricing_plan_id,
5960
created=func.now(),
6061
modified=func.now(),
6162
)
6263
.returning(*_SELECTION_ARGS)
6364
)
6465
row = result.one()
66+
row = result.one()
6567
return LicensedItemDB.model_validate(row)
6668

6769

@@ -73,6 +75,7 @@ async def list_(
7375
offset: NonNegativeInt,
7476
limit: NonNegativeInt,
7577
order_by: OrderBy,
78+
# filters
7679
trashed: Literal["exclude", "only", "include"] = "exclude",
7780
inactive: Literal["exclude", "only", "include"] = "exclude",
7881
) -> tuple[int, list[LicensedItemDB]]:
@@ -89,12 +92,12 @@ async def list_(
8992
elif trashed == "only":
9093
base_query = base_query.where(licensed_items.c.trashed.is_not(None))
9194

92-
if inactive == "exclude":
95+
if inactive == "only":
9396
base_query = base_query.where(
9497
licensed_items.c.product_name.is_(None)
9598
| licensed_items.c.licensed_item_id.is_(None)
9699
)
97-
elif inactive == "only":
100+
elif inactive == "exclude":
98101
base_query = base_query.where(
99102
licensed_items.c.product_name.is_not(None)
100103
& licensed_items.c.licensed_item_id.is_not(None)

services/web/server/src/simcore_service_webserver/licenses/_licensed_items_service.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,15 @@ async def list_licensed_items(
5656
offset: NonNegativeInt,
5757
limit: int,
5858
order_by: OrderBy,
59-
) -> LicensedItemPage:
60-
total_count, licensed_item_db_list = await _licensed_items_repository.list_(
61-
app, product_name=product_name, offset=offset, limit=limit, order_by=order_by
59+
) -> LicensedItemGetPage:
60+
total_count, items = await _licensed_items_repository.list_(
61+
app,
62+
product_name=product_name,
63+
offset=offset,
64+
limit=limit,
65+
order_by=order_by,
66+
trashed="exclude",
67+
inactive="exclude",
6268
)
6369
return LicensedItemPage(
6470
items=[

services/web/server/tests/unit/isolated/test_users_models.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ def test_auto_compute_gravatar__deprecated(fake_profile_get: MyProfileGet):
8989

9090
assert (
9191
"gravatar_id" not in data
92-
), f"{MyProfileGet.model_fields['gravatar_id'].deprecated=}"
92+
), f"{dict(MyProfileGet.model_fields)['gravatar_id'].deprecated=}"
9393
assert data["id"] == profile.id
9494
assert data["first_name"] == profile.first_name
9595
assert data["last_name"] == profile.last_name

services/web/server/tests/unit/with_dbs/04/licenses/test_licensed_items_repository.py

Lines changed: 28 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
from aiohttp.test_utils import TestClient
1010
from models_library.licensed_items import (
1111
VIP_DETAILS_EXAMPLE,
12-
LicensedItemDB,
1312
LicensedItemUpdateDB,
1413
LicensedResourceType,
1514
)
@@ -21,6 +20,11 @@
2120
from simcore_service_webserver.projects.models import ProjectDict
2221

2322

23+
@pytest.fixture
24+
def user_role() -> UserRole:
25+
return UserRole.USER
26+
27+
2428
@pytest.fixture
2529
def user_role() -> UserRole:
2630
return UserRole.USER
@@ -34,67 +38,68 @@ async def test_licensed_items_db_crud(
3438
pricing_plan_id: int,
3539
):
3640
assert client.app
37-
38-
output: tuple[int, list[LicensedItemDB]] = await _licensed_items_repository.list_(
41+
total_count, items = await _licensed_items_repository.list_(
3942
client.app,
4043
product_name=osparc_product_name,
4144
offset=0,
4245
limit=10,
4346
order_by=OrderBy(field="modified"),
4447
)
45-
assert output[0] == 0
48+
assert total_count == 0
49+
assert not items
4650

47-
licensed_item_db = await _licensed_items_repository.create(
51+
got = await _licensed_items_repository.create(
4852
client.app,
4953
product_name=osparc_product_name,
5054
licensed_resource_name="Model A",
55+
licensed_resource_name="Model A",
5156
licensed_resource_type=LicensedResourceType.VIP_MODEL,
5257
pricing_plan_id=pricing_plan_id,
5358
licensed_resource_data=VIP_DETAILS_EXAMPLE,
5459
)
55-
_licensed_item_id = licensed_item_db.licensed_item_id
60+
licensed_item_id = got.licensed_item_id
5661

57-
output: tuple[int, list[LicensedItemDB]] = await _licensed_items_repository.list_(
62+
total_count, items = await _licensed_items_repository.list_(
5863
client.app,
5964
product_name=osparc_product_name,
6065
offset=0,
6166
limit=10,
6267
order_by=OrderBy(field="modified"),
6368
)
64-
assert output[0] == 1
69+
assert total_count == 1
70+
assert items[0].licensed_item_id == licensed_item_id
6571

66-
licensed_item_db = await _licensed_items_repository.get(
72+
got = await _licensed_items_repository.get(
6773
client.app,
68-
licensed_item_id=_licensed_item_id,
74+
licensed_item_id=licensed_item_id,
6975
product_name=osparc_product_name,
7076
)
71-
assert licensed_item_db.licensed_resource_name == "Model A"
72-
assert isinstance(licensed_item_db.licensed_resource_data, dict)
77+
assert got.licensed_resource_name == "Model A"
7378

7479
await _licensed_items_repository.update(
7580
client.app,
76-
licensed_item_id=_licensed_item_id,
81+
licensed_item_id=licensed_item_id,
7782
product_name=osparc_product_name,
78-
updates=LicensedItemUpdateDB(display_name="Model B"),
83+
updates=LicensedItemUpdateDB(licensed_resource_name="Model B"),
7984
)
8085

81-
licensed_item_db = await _licensed_items_repository.get(
86+
got = await _licensed_items_repository.get(
8287
client.app,
83-
licensed_item_id=_licensed_item_id,
88+
licensed_item_id=licensed_item_id,
8489
product_name=osparc_product_name,
8590
)
86-
assert licensed_item_db.licensed_resource_name == "Model B"
91+
assert got.licensed_resource_name == "Model B"
8792

88-
licensed_item_db = await _licensed_items_repository.delete(
93+
got = await _licensed_items_repository.delete(
8994
client.app,
90-
licensed_item_id=_licensed_item_id,
95+
licensed_item_id=licensed_item_id,
9196
product_name=osparc_product_name,
9297
)
9398

9499
with pytest.raises(LicensedItemNotFoundError):
95100
await _licensed_items_repository.get(
96101
client.app,
97-
licensed_item_id=_licensed_item_id,
102+
licensed_item_id=licensed_item_id,
98103
product_name=osparc_product_name,
99104
)
100105

@@ -116,23 +121,20 @@ async def test_licensed_items_db_trash(
116121
product_name=osparc_product_name,
117122
licensed_resource_name=name,
118123
licensed_resource_type=LicensedResourceType.VIP_MODEL,
119-
licensed_resource_data=None,
120124
pricing_plan_id=pricing_plan_id,
121125
)
122126
licensed_item_ids.append(licensed_item_db.licensed_item_id)
123127

124-
licensed_item_id1, licensed_item_id2 = licensed_item_ids
125-
126128
# Trash one licensed item
127129
trashing_at = arrow.now().datetime
128130
trashed_item = await _licensed_items_repository.update(
129131
client.app,
130-
licensed_item_id=licensed_item_id1,
132+
licensed_item_id=licensed_item_ids[0],
131133
product_name=osparc_product_name,
132134
updates=LicensedItemUpdateDB(trash=True),
133135
)
134136

135-
assert trashed_item.licensed_item_id == licensed_item_id1
137+
assert trashed_item.licensed_item_id == licensed_item_ids[0]
136138
assert trashed_item.trashed
137139
assert trashing_at < trashed_item.trashed
138140
assert trashed_item.trashed < arrow.now().datetime
@@ -159,7 +161,7 @@ async def test_licensed_items_db_trash(
159161
trashed="exclude",
160162
)
161163
assert total_count == 1
162-
assert items[0].licensed_item_id == licensed_item_id2
164+
assert items[0].licensed_item_id == licensed_item_ids[1]
163165
assert items[0].trashed is None
164166

165167
# List with filter_trashed all

services/web/server/tests/unit/with_dbs/04/wallets/payments/test_payments.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -362,7 +362,7 @@ async def test_payment_not_found(
362362

363363

364364
def test_payment_transaction_state_and_literals_are_in_sync():
365-
state_literals = PaymentTransaction.model_fields["state"].annotation
365+
state_literals = dict(PaymentTransaction.model_fields)["state"].annotation
366366
assert (
367367
TypeAdapter(list[state_literals]).validate_python(
368368
[f"{s}" for s in PaymentTransactionState]

0 commit comments

Comments
 (0)