4
4
import json
5
5
import logging
6
6
from pathlib import Path
7
- from typing import ClassVar
7
+ from typing import ClassVar , Optional
8
8
9
9
from sqlalchemy .orm import Session
10
10
from sqlalchemy import select , func
11
11
12
12
from scimodom .config import Config
13
+ from scimodom .database .database import get_session
13
14
from scimodom .database .models import (
14
15
Project ,
15
16
ProjectSource ,
18
19
DetectionTechnology ,
19
20
Organism ,
20
21
Selection ,
22
+ User ,
21
23
)
22
24
import scimodom .database .queries as queries
23
25
from scimodom .services .annotation import AnnotationService
24
26
from scimodom .services .assembly import AssemblyService
27
+ from scimodom .services .permission import get_permission_service
25
28
import scimodom .utils .specifications as specs
26
29
import scimodom .utils .utils as utils
27
30
@@ -35,12 +38,10 @@ class DuplicateProjectError(Exception):
35
38
36
39
37
40
class ProjectService :
38
- """Utility class to create a project.
41
+ """Utility class to create/manage a project.
39
42
40
43
:param session: SQLAlchemy ORM session
41
44
:type session: Session
42
- :param project: Project description (json template)
43
- :type project: dict
44
45
:param SMID_LENGTH: Length of Sci-ModoM ID (SMID)
45
46
:type SMID_LENGTH: int
46
47
:param DATA_PATH: Data path
@@ -54,14 +55,15 @@ class ProjectService:
54
55
DATA_SUB_PATH : ClassVar [str ] = "metadata"
55
56
DATA_SUB_PATH_SUB : ClassVar [str ] = "project_requests"
56
57
57
- def __init__ (self , session : Session , project : dict ) -> None :
58
+ def __init__ (self , session : Session ) -> None :
58
59
"""Initializer method."""
59
60
self ._session = session
60
- self ._project = project
61
+
62
+ self ._project : dict
61
63
self ._smid : str
62
64
self ._assemblies : set [tuple [int , str ]] = set ()
63
65
64
- def __new__ (cls , session : Session , project : dict ):
66
+ def __new__ (cls , session : Session ):
65
67
"""Constructor method."""
66
68
if cls .DATA_PATH is None :
67
69
msg = "Missing environment variable: DATA_PATH. Terminating!"
@@ -121,8 +123,16 @@ def create_project_request(project: dict):
121
123
json .dump (project , f , indent = "\t " )
122
124
return uuid
123
125
124
- def create_project (self , wo_assembly : bool = False ) -> None :
125
- """Project constructor."""
126
+ def create_project (self , project : dict , wo_assembly : bool = False ) -> None :
127
+ """Project constructor.
128
+
129
+ :param project: Project description (json template)
130
+ :type project: dict
131
+ :param wo_assembly: Skip assembly set up
132
+ :type wo_assembly: bool
133
+ """
134
+ self ._project = project
135
+
126
136
self ._validate_keys ()
127
137
self ._validate_entry ()
128
138
self ._add_selection ()
@@ -141,13 +151,39 @@ def create_project(self, wo_assembly: bool = False) -> None:
141
151
session = self ._session , taxa_id = taxid
142
152
).create_annotation ()
143
153
154
+ def associate_project_to_user (self , user : User , smid : str | None = None ):
155
+ """Associate a project to a user.
156
+ When called after project creation, the SMID is
157
+ available (default), else nothing is done, unless
158
+ it is passed as argument.
159
+
160
+ :param smid: SMID. There is no check
161
+ on the validity of this value, this must be done
162
+ before calling this function.
163
+ :type smid: str
164
+ """
165
+ if not smid :
166
+ try :
167
+ smid = self ._smid
168
+ except AttributeError :
169
+ msg = "Undefined SMID. Nothing will be done."
170
+ logger .warning (msg )
171
+ return
172
+ permission_service = get_permission_service ()
173
+ permission_service .insert_into_user_project_association (user , smid )
174
+
144
175
def get_smid (self ) -> str :
145
- """Return newly created SMID.
176
+ """Return newly created SMID, else
177
+ raises a ValueError.
146
178
147
179
:returns: SMID
148
180
:rtype: str
149
181
"""
150
- return self ._smid
182
+ try :
183
+ return self ._smid
184
+ except AttributeError :
185
+ msg = "Undefined SMID. This is only defined when creating a project."
186
+ raise AttributeError (msg )
151
187
152
188
def _validate_keys (self ) -> None :
153
189
"""Validate keys from project description (dictionary)."""
@@ -353,3 +389,18 @@ def _write_metadata(self) -> None:
353
389
parent = Path (self .DATA_PATH , self .DATA_SUB_PATH )
354
390
with open (Path (parent , f"{ self ._smid } .json" ), "w" ) as f :
355
391
json .dump (self ._project , f , indent = "\t " )
392
+
393
+
394
+ _cached_project_service : Optional [ProjectService ] = None
395
+
396
+
397
+ def get_project_service ():
398
+ """Helper function to set up a ProjectService object by injecting its dependencies.
399
+
400
+ :returns: Project service instance
401
+ :rtype: ProjectService
402
+ """
403
+ global _cached_project_service
404
+ if _cached_project_service is None :
405
+ _cached_project_service = ProjectService (session = get_session ())
406
+ return _cached_project_service
0 commit comments