Skip to content

Commit 387df6d

Browse files
committed
drafts list_trashed_projects
1 parent 1458958 commit 387df6d

File tree

2 files changed

+70
-13
lines changed

2 files changed

+70
-13
lines changed

services/web/server/src/simcore_service_webserver/folders/_folders_repository.py

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@
3636
from sqlalchemy.ext.asyncio import AsyncConnection
3737
from sqlalchemy.orm import aliased
3838
from sqlalchemy.sql import ColumnElement, CompoundSelect, Select
39-
from sqlalchemy.sql.selectable import GenerativeSelect
4039

4140
from ..db.plugin import get_asyncpg_engine
4241
from .errors import FolderAccessForbiddenError, FolderNotFoundError
@@ -157,16 +156,12 @@ def _create_shared_workspace_query(
157156
return shared_workspace_query
158157

159158

160-
def _set_ordering(
161-
base_query: GenerativeSelect,
162-
order_by: OrderBy,
163-
) -> GenerativeSelect:
159+
def _to_expression(order_by: OrderBy):
164160
direction_func: Callable = {
165161
OrderDirection.ASC: sql.asc,
166162
OrderDirection.DESC: sql.desc,
167163
}[order_by.direction]
168-
column = folders_v2.columns[order_by.field]
169-
return base_query.order_by(direction_func(column))
164+
return direction_func(folders_v2.columns[order_by.field])
170165

171166

172167
async def list_( # pylint: disable=too-many-arguments,too-many-branches
@@ -250,7 +245,7 @@ async def list_( # pylint: disable=too-many-arguments,too-many-branches
250245

251246
# Ordering and pagination
252247
list_query = (
253-
_set_ordering(combined_query, order_by=order_by).offset(offset).limit(limit)
248+
combined_query.order_by(_to_expression(order_by)).offset(offset).limit(limit)
254249
)
255250

256251
async with pass_or_acquire_connection(get_asyncpg_engine(app), connection) as conn:
@@ -298,7 +293,9 @@ async def list_trashed_folders(
298293
count_query = sql.select(sql.func.count()).select_from(base_query.subquery())
299294

300295
# Ordering and pagination
301-
list_query = _set_ordering(base_query, order_by).offset(offset).limit(limit)
296+
list_query = (
297+
base_query.order_by(_to_expression(order_by)).offset(offset).limit(limit)
298+
)
302299

303300
async with pass_or_acquire_connection(get_asyncpg_engine(app), connection) as conn:
304301
total_count = await conn.scalar(count_query)

services/web/server/src/simcore_service_webserver/projects/_projects_db.py

Lines changed: 64 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
11
import logging
2+
from datetime import datetime
3+
from typing import Callable, cast
24

3-
import sqlalchemy as sa
45
from aiohttp import web
6+
from common_library.exclude import UnSet, is_set
7+
from models_library.basic_types import IDStr
58
from models_library.groups import GroupID
69
from models_library.projects import ProjectID
10+
from models_library.rest_ordering import OrderBy, OrderDirection
11+
from models_library.rest_pagination import MAXIMUM_NUMBER_OF_ITEMS_PER_PAGE
12+
from pydantic import NonNegativeInt, PositiveInt
713
from simcore_postgres_database.models.projects import projects
814
from simcore_postgres_database.models.users import users
915
from simcore_postgres_database.utils_repos import (
@@ -29,6 +35,60 @@
2935
ProjectDBGet,
3036
)
3137

38+
_OLDEST_TRASHED_FIRST = OrderBy(field=IDStr("trashed"), direction=OrderDirection.ASC)
39+
40+
41+
def _to_expression(order_by: OrderBy):
42+
direction_func: Callable = {
43+
OrderDirection.ASC: sql.asc,
44+
OrderDirection.DESC: sql.desc,
45+
}[order_by.direction]
46+
return direction_func(projects.columns[order_by.field])
47+
48+
49+
async def list_trashed_projects(
50+
app: web.Application,
51+
connection: AsyncConnection | None = None,
52+
*,
53+
# filter
54+
trashed_explicitly: bool | UnSet = UnSet.VALUE,
55+
trashed_before: datetime | UnSet = UnSet.VALUE,
56+
# pagination
57+
offset: NonNegativeInt = 0,
58+
limit: PositiveInt = MAXIMUM_NUMBER_OF_ITEMS_PER_PAGE,
59+
# order
60+
order_by: OrderBy = _OLDEST_TRASHED_FIRST,
61+
) -> tuple[int, list[ProjectDBGet]]:
62+
63+
base_query = sql.select(PROJECT_DB_COLS).where(projects.c.trashed.is_not(None))
64+
65+
if is_set(trashed_explicitly):
66+
assert isinstance(trashed_explicitly, bool) # nosec
67+
base_query = base_query.where(
68+
projects.c.trashed_explicitly.is_(trashed_explicitly)
69+
)
70+
71+
if is_set(trashed_before):
72+
assert isinstance(trashed_before, datetime) # nosec
73+
base_query = base_query.where(projects.c.trashed < trashed_before)
74+
75+
# Select total count from base_query
76+
count_query = sql.select(sql.func.count()).select_from(base_query.subquery())
77+
78+
# Ordering and pagination
79+
list_query = (
80+
base_query.order_by(_to_expression(order_by)).offset(offset).limit(limit)
81+
)
82+
83+
async with pass_or_acquire_connection(get_asyncpg_engine(app), connection) as conn:
84+
total_count = await conn.scalar(count_query)
85+
86+
result = await conn.stream(list_query)
87+
folders: list[ProjectDBGet] = [
88+
ProjectDBGet.model_validate(row) async for row in result
89+
]
90+
return cast(int, total_count), folders
91+
3292

3393
async def patch_project(
3494
app: web.Application,
@@ -41,7 +101,7 @@ async def patch_project(
41101
async with transaction_context(get_asyncpg_engine(app), connection) as conn:
42102
result = await conn.stream(
43103
projects.update()
44-
.values(last_change_date=sa.func.now(), **new_partial_project_data)
104+
.values(last_change_date=sql.func.now(), **new_partial_project_data)
45105
.where(projects.c.uuid == f"{project_uuid}")
46106
.returning(*PROJECT_DB_COLS)
47107
)
@@ -52,7 +112,7 @@ async def patch_project(
52112

53113

54114
def _select_trashed_by_primary_gid_query() -> sql.Select:
55-
return sa.select(
115+
return sql.select(
56116
projects.c.uuid,
57117
users.c.primary_gid.label("trashed_by_primary_gid"),
58118
).select_from(projects.outerjoin(users, projects.c.trashed_by == users.c.id))
@@ -97,7 +157,7 @@ async def batch_get_trashed_by_primary_gid(
97157
).order_by(
98158
# Preserves the order of folders_ids
99159
# SEE https://docs.sqlalchemy.org/en/20/core/sqlelement.html#sqlalchemy.sql.expression.case
100-
sa.case(
160+
sql.case(
101161
{
102162
project_uuid: index
103163
for index, project_uuid in enumerate(projects_uuids_str)

0 commit comments

Comments
 (0)