fractal-server 2.6.2__py3-none-any.whl → 2.6.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- __VERSION__ = "2.6.2"
1
+ __VERSION__ = "2.6.3"
@@ -15,6 +15,7 @@ from typing import Optional
15
15
  from pydantic import EmailStr
16
16
  from sqlalchemy import Column
17
17
  from sqlalchemy.types import DateTime
18
+ from sqlalchemy.types import JSON
18
19
  from sqlmodel import Field
19
20
  from sqlmodel import Relationship
20
21
  from sqlmodel import SQLModel
@@ -126,3 +127,6 @@ class UserGroup(SQLModel, table=True):
126
127
  default_factory=get_timestamp,
127
128
  sa_column=Column(DateTime(timezone=True), nullable=False),
128
129
  )
130
+ viewer_paths: list[str] = Field(
131
+ sa_column=Column(JSON, server_default="[]", nullable=False)
132
+ )
@@ -5,6 +5,7 @@ from fastapi import APIRouter
5
5
  from fastapi import Depends
6
6
  from fastapi_users import schemas
7
7
  from sqlalchemy.ext.asyncio import AsyncSession
8
+ from sqlmodel import select
8
9
 
9
10
  from . import current_active_user
10
11
  from ...db import get_async_db
@@ -13,6 +14,8 @@ from ...schemas.user import UserUpdate
13
14
  from ...schemas.user import UserUpdateStrict
14
15
  from ..aux.validate_user_settings import verify_user_has_settings
15
16
  from ._aux_auth import _get_single_user_with_group_names
17
+ from fractal_server.app.models import LinkUserGroup
18
+ from fractal_server.app.models import UserGroup
16
19
  from fractal_server.app.models import UserOAuth
17
20
  from fractal_server.app.models import UserSettings
18
21
  from fractal_server.app.schemas import UserSettingsReadStrict
@@ -103,3 +106,29 @@ async def patch_current_user_settings(
103
106
  await db.refresh(current_user_settings)
104
107
 
105
108
  return current_user_settings
109
+
110
+
111
+ @router_current_user.get(
112
+ "/current-user/viewer-paths/", response_model=list[str]
113
+ )
114
+ async def get_current_user_viewer_paths(
115
+ current_user: UserOAuth = Depends(current_active_user),
116
+ db: AsyncSession = Depends(get_async_db),
117
+ ) -> list[str]:
118
+ """Returns the union of `viewer_paths` for all user's groups"""
119
+ cmd = (
120
+ select(UserGroup.viewer_paths)
121
+ .join(LinkUserGroup)
122
+ .where(LinkUserGroup.group_id == UserGroup.id)
123
+ .where(LinkUserGroup.user_id == current_user.id)
124
+ )
125
+ res = await db.execute(cmd)
126
+ viewer_paths_nested = res.scalars().all()
127
+
128
+ # Flatten a nested object and make its elements unique
129
+ all_viewer_paths_set = set(
130
+ path for _viewer_paths in viewer_paths_nested for path in _viewer_paths
131
+ )
132
+ all_viewer_paths = list(all_viewer_paths_set)
133
+
134
+ return all_viewer_paths
@@ -97,7 +97,9 @@ async def create_single_group(
97
97
  )
98
98
 
99
99
  # Create and return new group
100
- new_group = UserGroup(name=group_create.name)
100
+ new_group = UserGroup(
101
+ name=group_create.name, viewer_paths=group_create.viewer_paths
102
+ )
101
103
  db.add(new_group)
102
104
  await db.commit()
103
105
 
@@ -116,6 +118,13 @@ async def update_single_group(
116
118
  db: AsyncSession = Depends(get_async_db),
117
119
  ) -> UserGroupRead:
118
120
 
121
+ group = await db.get(UserGroup, group_id)
122
+ if group is None:
123
+ raise HTTPException(
124
+ status_code=status.HTTP_404_NOT_FOUND,
125
+ detail=f"UserGroup {group_id} not found.",
126
+ )
127
+
119
128
  # Check that all required users exist
120
129
  # Note: The reason for introducing `col` is as in
121
130
  # https://sqlmodel.tiangolo.com/tutorial/where/#type-annotations-and-errors,
@@ -152,6 +161,12 @@ async def update_single_group(
152
161
  detail=error_msg,
153
162
  )
154
163
 
164
+ # Patch `viewer_paths`
165
+ if group_update.viewer_paths is not None:
166
+ group.viewer_paths = group_update.viewer_paths
167
+ db.add(group)
168
+ await db.commit()
169
+
155
170
  updated_group = await _get_single_group_with_user_ids(
156
171
  group_id=group_id, db=db
157
172
  )
@@ -246,6 +246,11 @@ class FractalSlurmExecutor(SlurmExecutor):
246
246
 
247
247
  super().__init__(*args, **kwargs)
248
248
 
249
+ # Assign `wait_thread.shutdown_callback` early, since it may be called
250
+ # from within `_stop_and_join_wait_thread` (e.g. if an exception is
251
+ # raised within `__init__`).
252
+ self.wait_thread.shutdown_callback = self.shutdown
253
+
249
254
  self.keep_pickle_files = keep_pickle_files
250
255
  self.slurm_user = slurm_user
251
256
  self.slurm_account = slurm_account
@@ -291,7 +296,6 @@ class FractalSlurmExecutor(SlurmExecutor):
291
296
  shutdown_file
292
297
  or (self.workflow_dir_local / SHUTDOWN_FILENAME).as_posix()
293
298
  )
294
- self.wait_thread.shutdown_callback = self.shutdown
295
299
 
296
300
  def _cleanup(self, jobid: str) -> None:
297
301
  """
@@ -6,9 +6,9 @@ from pydantic import Extra
6
6
  from pydantic import Field
7
7
  from pydantic import validator
8
8
 
9
+ from ._validators import val_absolute_path
9
10
  from ._validators import val_unique_list
10
11
 
11
-
12
12
  __all__ = (
13
13
  "UserGroupRead",
14
14
  "UserGroupUpdate",
@@ -34,6 +34,7 @@ class UserGroupRead(BaseModel):
34
34
  name: str
35
35
  timestamp_created: datetime
36
36
  user_ids: Optional[list[int]] = None
37
+ viewer_paths: list[str]
37
38
 
38
39
 
39
40
  class UserGroupCreate(BaseModel, extra=Extra.forbid):
@@ -45,6 +46,14 @@ class UserGroupCreate(BaseModel, extra=Extra.forbid):
45
46
  """
46
47
 
47
48
  name: str
49
+ viewer_paths: list[str] = Field(default_factory=list)
50
+
51
+ @validator("viewer_paths")
52
+ def viewer_paths_validator(cls, value):
53
+ for i, path in enumerate(value):
54
+ value[i] = val_absolute_path(f"viewer_paths[{i}]")(path)
55
+ value = val_unique_list("viewer_paths")(value)
56
+ return value
48
57
 
49
58
 
50
59
  class UserGroupUpdate(BaseModel, extra=Extra.forbid):
@@ -59,7 +68,15 @@ class UserGroupUpdate(BaseModel, extra=Extra.forbid):
59
68
  """
60
69
 
61
70
  new_user_ids: list[int] = Field(default_factory=list)
71
+ viewer_paths: Optional[list[str]] = None
62
72
 
63
73
  _val_unique = validator("new_user_ids", allow_reuse=True)(
64
74
  val_unique_list("new_user_ids")
65
75
  )
76
+
77
+ @validator("viewer_paths")
78
+ def viewer_paths_validator(cls, value):
79
+ for i, path in enumerate(value):
80
+ value[i] = val_absolute_path(f"viewer_paths[{i}]")(path)
81
+ value = val_unique_list("viewer_paths")(value)
82
+ return value
@@ -0,0 +1,36 @@
1
+ """user group viewer paths
2
+
3
+ Revision ID: da2cb2ac4255
4
+ Revises: 94a47ea2d3ff
5
+ Create Date: 2024-09-26 14:39:26.135101
6
+
7
+ """
8
+ import sqlalchemy as sa
9
+ from alembic import op
10
+
11
+
12
+ # revision identifiers, used by Alembic.
13
+ revision = "da2cb2ac4255"
14
+ down_revision = "94a47ea2d3ff"
15
+ branch_labels = None
16
+ depends_on = None
17
+
18
+
19
+ def upgrade() -> None:
20
+ # ### commands auto generated by Alembic - please adjust! ###
21
+ with op.batch_alter_table("usergroup", schema=None) as batch_op:
22
+ batch_op.add_column(
23
+ sa.Column(
24
+ "viewer_paths", sa.JSON(), server_default="[]", nullable=False
25
+ )
26
+ )
27
+
28
+ # ### end Alembic commands ###
29
+
30
+
31
+ def downgrade() -> None:
32
+ # ### commands auto generated by Alembic - please adjust! ###
33
+ with op.batch_alter_table("usergroup", schema=None) as batch_op:
34
+ batch_op.drop_column("viewer_paths")
35
+
36
+ # ### end Alembic commands ###
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: fractal-server
3
- Version: 2.6.2
3
+ Version: 2.6.3
4
4
  Summary: Server component of the Fractal analytics platform
5
5
  Home-page: https://github.com/fractal-analytics-platform/fractal-server
6
6
  License: BSD-3-Clause
@@ -1,4 +1,4 @@
1
- fractal_server/__init__.py,sha256=zk2Mr_vPWXiYjT0KF9CbddwUnuJ011NmmqEbItcDUz4,22
1
+ fractal_server/__init__.py,sha256=Xl00aUdi67dqYV36pJ6CjXHphNon7e48hzkQAE3HlRQ,22
2
2
  fractal_server/__main__.py,sha256=WcBAkmVE9aH5mDI6wGkVmPAql2N5Vyk0A-7zuUl8WX0,6122
3
3
  fractal_server/alembic.ini,sha256=MWwi7GzjzawI9cCAK1LW7NxIBQDUqD12-ptJoq5JpP0,3153
4
4
  fractal_server/app/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -6,7 +6,7 @@ fractal_server/app/db/__init__.py,sha256=81rK9w1__Z6PJ5cEcChPVc-wI9YOK4fN--_5Opr
6
6
  fractal_server/app/models/__init__.py,sha256=aG7mf1zZbsgzDSp7GHEcZhdjHfW3TGPOLCI8MrvYhPw,500
7
7
  fractal_server/app/models/linkusergroup.py,sha256=ufthlbLFAWMU_dJmsVZzVlQa_D9C9SmgydxypQ2Xq1U,309
8
8
  fractal_server/app/models/linkuserproject.py,sha256=eQaourbGRshvlMVlKzLYJKHEjfsW1CbWws9yW4eHXhA,567
9
- fractal_server/app/models/security.py,sha256=xeR_3Wb5Epn2fvNgEuTKibzMkMybVogACpUvrP1J1b8,3625
9
+ fractal_server/app/models/security.py,sha256=2npjgRKBZ7OAnhAXNbYxjtuOsSm1P4kak__qfk2SpeM,3770
10
10
  fractal_server/app/models/user_settings.py,sha256=0YXCAwoAVGqI2irRLdXgr9-JS0STtHhSaoFENigAnrk,1312
11
11
  fractal_server/app/models/v1/__init__.py,sha256=hUI7dEbPaiZGN0IbHW4RSmSicyvtn_xeuevoX7zvUwI,466
12
12
  fractal_server/app/models/v1/dataset.py,sha256=99GDgt7njx8yYQApkImqp_7bHA5HH3ElvbR6Oyj9kVI,2017
@@ -52,8 +52,8 @@ fractal_server/app/routes/api/v2/workflow.py,sha256=rMCcclz9aJAMSVLncUdSDGrgkKbn
52
52
  fractal_server/app/routes/api/v2/workflowtask.py,sha256=-3-c8DDnxGjMwWbX_h5V5OLaC_iCLXYzwWKBUaL-5wE,7060
53
53
  fractal_server/app/routes/auth/__init__.py,sha256=fao6CS0WiAjHDTvBzgBVV_bSXFpEAeDBF6Z6q7rRkPc,1658
54
54
  fractal_server/app/routes/auth/_aux_auth.py,sha256=a3DCj6_tekf4Bfu8Kax9uxVGbTuVsONgki7E6AJUN_8,3269
55
- fractal_server/app/routes/auth/current_user.py,sha256=kJk6bONS8bwPoJh40mpmVGM2bb5qRrJ6Rf_p1_flvgI,3480
56
- fractal_server/app/routes/auth/group.py,sha256=az8kRJJU5rA0L8GCX5kvRNuQhrsoGWPuvQ26z7iFQ3E,5388
55
+ fractal_server/app/routes/auth/current_user.py,sha256=s3R1O53Qnow1LqDW-UpkYvfKKSJwLrDWGeMtsIEMUNs,4462
56
+ fractal_server/app/routes/auth/group.py,sha256=eT-1c0Ow8KbYkKEMQ5ebhEAeRixwJs2kQW45UIutH5w,5833
57
57
  fractal_server/app/routes/auth/group_names.py,sha256=zvYDfhxKlDmbSr-oLXYy6WUVkPPTvzH6ZJtuoNdGZbE,960
58
58
  fractal_server/app/routes/auth/login.py,sha256=tSu6OBLOieoBtMZB4JkBAdEgH2Y8KqPGSbwy7NIypIo,566
59
59
  fractal_server/app/routes/auth/oauth.py,sha256=AnFHbjqL2AgBX3eksI931xD6RTtmbciHBEuGf9YJLjU,1895
@@ -83,7 +83,7 @@ fractal_server/app/runner/executors/slurm/sudo/__init__.py,sha256=Cjn1rYvljddi96
83
83
  fractal_server/app/runner/executors/slurm/sudo/_check_jobs_status.py,sha256=wAgwpVcr6JIslKHOuS0FhRa_6T1KCManyRJqA-fifzw,1909
84
84
  fractal_server/app/runner/executors/slurm/sudo/_executor_wait_thread.py,sha256=z5LlhaiqAb8pHsF1WwdzXN39C5anQmwjo1rSQgtRAYE,4422
85
85
  fractal_server/app/runner/executors/slurm/sudo/_subprocess_run_as_user.py,sha256=g8wqUjSicN17UZVXlfaMomYZ-xOIbBu1oE7HdJTzfvw,5218
86
- fractal_server/app/runner/executors/slurm/sudo/executor.py,sha256=6OPe9t70gLyuC2JhWt2o1f0e7zhQPBtrbMHQkDd6RAQ,48725
86
+ fractal_server/app/runner/executors/slurm/sudo/executor.py,sha256=mTqTSvoRukvocyMLvlGuGWMaL6hy3McYLx_7bUW1pEM,48918
87
87
  fractal_server/app/runner/extract_archive.py,sha256=tLpjDrX47OjTNhhoWvm6iNukg8KoieWyTb7ZfvE9eWU,2483
88
88
  fractal_server/app/runner/filenames.py,sha256=9lwu3yB4C67yiijYw8XIKaLFn3mJUt6_TCyVFM_aZUQ,206
89
89
  fractal_server/app/runner/run_subprocess.py,sha256=c3JbYXq3hX2aaflQU19qJ5Xs6J6oXGNvnTEoAfv2bxc,959
@@ -127,7 +127,7 @@ fractal_server/app/runner/versions.py,sha256=dSaPRWqmFPHjg20kTCHmi_dmGNcCETflDtD
127
127
  fractal_server/app/schemas/__init__.py,sha256=stURAU_t3AOBaH0HSUbV-GKhlPKngnnIMoqWc3orFyI,135
128
128
  fractal_server/app/schemas/_validators.py,sha256=XKEGEHxp3H6YSJewtFWXe_2Nh7SDdNtAXmlEmJO6Vb0,3606
129
129
  fractal_server/app/schemas/user.py,sha256=VNnAPnAVK6X0PZlw7XehocAshVNuUHdDwiZVWCCor6Y,2156
130
- fractal_server/app/schemas/user_group.py,sha256=2f9XQ6kIar6NMY4UCN0yOnve6ZDHUVZaHv1dna1Vfjg,1446
130
+ fractal_server/app/schemas/user_group.py,sha256=YwJvYgj-PI66LWy38CEd_FIZPsBV1_2N5zJPGFcFvBw,2143
131
131
  fractal_server/app/schemas/user_settings.py,sha256=UEST1MSmd9w2YypCji3SONSFlJcr2u4uG3bTczZy_Pk,3102
132
132
  fractal_server/app/schemas/v1/__init__.py,sha256=CrBGgBhoemCvmZ70ZUchM-jfVAICnoa7AjZBAtL2UB0,1852
133
133
  fractal_server/app/schemas/v1/applyworkflow.py,sha256=uuIh7fHlHEL4yLqL-dePI6-nfCsqgBYATmht7w_KITw,4302
@@ -182,6 +182,7 @@ fractal_server/migrations/versions/9c5ae74c9b98_add_user_settings_table.py,sha25
182
182
  fractal_server/migrations/versions/9fd26a2b0de4_add_workflow_timestamp_created.py,sha256=4l1AHGUsa0ONoJVZlr3fTXw_xbbQ8O7wlD92Az2aRfM,1849
183
183
  fractal_server/migrations/versions/a7f4d6137b53_add_workflow_dump_to_applyworkflow.py,sha256=ekDUML7ILpmdoqEclKbEUdyLi4uw9HSG_sTjG2hp_JE,867
184
184
  fractal_server/migrations/versions/d4fe3708d309_make_applyworkflow_workflow_dump_non_.py,sha256=6cHEZFuTXiQg9yu32Y3RH1XAl71av141WQ6UMbiITIg,949
185
+ fractal_server/migrations/versions/da2cb2ac4255_user_group_viewer_paths.py,sha256=yGWSA2HIHUybcVy66xBITk08opV2DFYSCIIrulaUZhI,901
185
186
  fractal_server/migrations/versions/e75cac726012_make_applyworkflow_start_timestamp_not_.py,sha256=lOggSvzGWqQvnxxFuSM6W50Ui49R918A-uBuiZJ0pNM,963
186
187
  fractal_server/migrations/versions/efa89c30e0a4_add_project_timestamp_created.py,sha256=jilQW3QIqYQ4Q6hCnUiG7UtNMpA41ujqrB3tPFiPM1Q,1221
187
188
  fractal_server/migrations/versions/f384e1c0cf5d_drop_task_default_args_columns.py,sha256=9BwqUS9Gf7UW_KjrzHbtViC880qhD452KAytkHWWZyk,746
@@ -213,8 +214,8 @@ fractal_server/tasks/v2/utils.py,sha256=JOyCacb6MNvrwfLNTyLwcz8y79J29YuJeJ2MK5kq
213
214
  fractal_server/urls.py,sha256=5o_qq7PzKKbwq12NHSQZDmDitn5RAOeQ4xufu-2v9Zk,448
214
215
  fractal_server/utils.py,sha256=b7WwFdcFZ8unyT65mloFToYuEDXpQoHRcmRNqrhd_dQ,2115
215
216
  fractal_server/zip_tools.py,sha256=xYpzBshysD2nmxkD5WLYqMzPYUcCRM3kYy-7n9bJL-U,4426
216
- fractal_server-2.6.2.dist-info/LICENSE,sha256=QKAharUuhxL58kSoLizKJeZE3mTCBnX6ucmz8W0lxlk,1576
217
- fractal_server-2.6.2.dist-info/METADATA,sha256=hlWGMOKcA-SXQpW1tlXMo9zfn6lKs31rl-byf88u8Bs,4628
218
- fractal_server-2.6.2.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
219
- fractal_server-2.6.2.dist-info/entry_points.txt,sha256=8tV2kynvFkjnhbtDnxAqImL6HMVKsopgGfew0DOp5UY,58
220
- fractal_server-2.6.2.dist-info/RECORD,,
217
+ fractal_server-2.6.3.dist-info/LICENSE,sha256=QKAharUuhxL58kSoLizKJeZE3mTCBnX6ucmz8W0lxlk,1576
218
+ fractal_server-2.6.3.dist-info/METADATA,sha256=hlZ8xt1P6qEjNO4ySIUzSMfqgQv6RilEJfaWaS5fqBs,4628
219
+ fractal_server-2.6.3.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
220
+ fractal_server-2.6.3.dist-info/entry_points.txt,sha256=8tV2kynvFkjnhbtDnxAqImL6HMVKsopgGfew0DOp5UY,58
221
+ fractal_server-2.6.3.dist-info/RECORD,,