Skip to content

Commit ca11cce

Browse files
committed
refactor: add custom ULID type for sqlalchemy
1 parent c5c79ac commit ca11cce

File tree

6 files changed

+36
-12
lines changed

6 files changed

+36
-12
lines changed

components/renku_data_services/project/db.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ async def get_project_by_namespace_slug(
113113
authorized = await self.authz.has_permission(
114114
user=user,
115115
resource_type=ResourceType.project,
116-
resource_id=ULID.from_str(project_orm.id),
116+
resource_id=project_orm.id,
117117
scope=Scope.READ,
118118
)
119119
if not authorized:
@@ -171,7 +171,7 @@ async def insert_project(
171171
creation_date=datetime.now(UTC).replace(microsecond=0),
172172
keywords=project.keywords,
173173
)
174-
project_slug = schemas.ProjectSlug(slug, project_id=project_orm.id, namespace_id=ns.id)
174+
project_slug = schemas.ProjectSlug(slug, project_id=str(project_orm.id), namespace_id=ns.id)
175175

176176
session.add(project_slug)
177177
session.add(project_orm)

components/renku_data_services/project/orm.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
from renku_data_services.namespace.orm import NamespaceORM
1414
from renku_data_services.project import models
1515
from renku_data_services.project.apispec import Visibility
16+
from renku_data_services.utils.sqlalchemy import ULIDType
1617

1718
metadata_obj = MetaData(schema="projects") # Has to match alembic ini section name
1819

@@ -27,7 +28,7 @@ class ProjectORM(BaseORM):
2728
"""A Renku native project."""
2829

2930
__tablename__ = "projects"
30-
id: Mapped[str] = mapped_column("id", String(26), primary_key=True, default_factory=lambda: str(ULID()), init=False)
31+
id: Mapped[ULID] = mapped_column("id", ULIDType, primary_key=True, default_factory=lambda: str(ULID()), init=False)
3132
name: Mapped[str] = mapped_column("name", String(99))
3233
visibility: Mapped[Visibility]
3334
created_by_id: Mapped[str] = mapped_column("created_by_id", String())
@@ -53,7 +54,7 @@ class ProjectORM(BaseORM):
5354
def dump(self) -> models.Project:
5455
"""Create a project model from the ProjectORM."""
5556
return models.Project(
56-
id=ULID.from_str(self.id),
57+
id=self.id,
5758
name=self.name,
5859
slug=self.slug.slug,
5960
namespace=self.slug.namespace.dump(),

components/renku_data_services/session/db.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -146,9 +146,7 @@ async def get_launcher(self, user: base_models.APIUser, launcher_id: ULID) -> mo
146146
launcher = res.one_or_none()
147147

148148
authorized = (
149-
await self.project_authz.has_permission(
150-
user, ResourceType.project, ULID.from_str(launcher.project_id), Scope.READ
151-
)
149+
await self.project_authz.has_permission(user, ResourceType.project, launcher.project_id, Scope.READ)
152150
if launcher is not None
153151
else False
154152
)
@@ -234,7 +232,7 @@ async def update_launcher(
234232
authorized = await self.project_authz.has_permission(
235233
user,
236234
ResourceType.project,
237-
ULID.from_str(launcher.project_id),
235+
launcher.project_id,
238236
Scope.WRITE,
239237
)
240238
if not authorized:
@@ -311,7 +309,7 @@ async def delete_launcher(self, user: base_models.APIUser, launcher_id: ULID) ->
311309
authorized = await self.project_authz.has_permission(
312310
user,
313311
ResourceType.project,
314-
ULID.from_str(launcher.project_id),
312+
launcher.project_id,
315313
Scope.WRITE,
316314
)
317315
if not authorized:

components/renku_data_services/session/orm.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ class SessionLauncherORM(BaseORM):
103103
project: Mapped[ProjectORM] = relationship(init=False)
104104
environment: Mapped[EnvironmentORM | None] = relationship(init=False)
105105

106-
project_id: Mapped[str] = mapped_column(
106+
project_id: Mapped[ULID] = mapped_column(
107107
"project_id", ForeignKey(ProjectORM.id, ondelete="CASCADE"), default=None, index=True
108108
)
109109
"""Id of the project this session belongs to."""
@@ -132,7 +132,7 @@ def load(cls, launcher: models.UnsavedSessionLauncher) -> "SessionLauncherORM":
132132
description=launcher.description,
133133
environment_kind=launcher.environment_kind,
134134
container_image=launcher.container_image,
135-
project_id=str(launcher.project_id),
135+
project_id=launcher.project_id,
136136
environment_id=launcher.environment_id,
137137
resource_class_id=launcher.resource_class_id,
138138
default_url=launcher.default_url,
@@ -142,7 +142,7 @@ def dump(self) -> models.SessionLauncher:
142142
"""Create a session launcher model from the SessionLauncherORM."""
143143
return models.SessionLauncher(
144144
id=self.id,
145-
project_id=ULID.from_str(self.project_id),
145+
project_id=self.project_id,
146146
name=self.name,
147147
created_by=models.Member(id=self.created_by_id),
148148
creation_date=self.creation_date,

components/renku_data_services/utils/py.typed

Whitespace-only changes.
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
"""Utilities for SQLAlchemy."""
2+
3+
from typing import cast
4+
5+
from sqlalchemy import Dialect, types
6+
from ulid import ULID
7+
8+
9+
class ULIDType(types.TypeDecorator):
10+
"""Wrapper type for ULID <--> str conversion."""
11+
12+
impl = types.String
13+
cache_ok = True
14+
15+
def process_bind_param(self, value: ULID | None, dialect: Dialect) -> str | None:
16+
"""Transform value for storing in the database."""
17+
if value is None:
18+
return None
19+
return str(value)
20+
21+
def process_result_value(self, value: str | None, dialect: Dialect) -> ULID | None:
22+
"""Transform string from database into ULID."""
23+
if value is None:
24+
return None
25+
return cast(ULID, ULID.from_str(value))

0 commit comments

Comments
 (0)