fractal-server 2.17.0a9__py3-none-any.whl → 2.17.0a11__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.17.0a9"
1
+ __VERSION__ = "2.17.0a11"
@@ -180,7 +180,9 @@ async def get_resource_profiles(
180
180
  await _get_resource_or_404(resource_id=resource_id, db=db)
181
181
 
182
182
  res = await db.execute(
183
- select(Profile).where(Profile.resource_id == resource_id)
183
+ select(Profile)
184
+ .where(Profile.resource_id == resource_id)
185
+ .order_by(Profile.id)
184
186
  )
185
187
  profiles = res.scalars().all()
186
188
 
@@ -52,8 +52,8 @@ async def _disambiguate_task_groups(
52
52
 
53
53
  # Medium priority: task groups owned by default user group
54
54
  settings = Inject(get_settings)
55
+ list_user_group_ids = [tg.user_group_id for tg in matching_task_groups]
55
56
  if settings.FRACTAL_DEFAULT_GROUP_NAME is not None:
56
- list_user_group_ids = [tg.user_group_id for tg in matching_task_groups]
57
57
  try:
58
58
  ind_user_group_id = list_user_group_ids.index(default_group_id)
59
59
  task_group = matching_task_groups[ind_user_group_id]
@@ -200,8 +200,8 @@ async def collect_tasks_pip(
200
200
  raise HTTPException(
201
201
  status_code=status.HTTP_422_UNPROCESSABLE_CONTENT,
202
202
  detail=(
203
- f"Python version {task_group_attrs['python_version']} is "
204
- "not available for Fractal task collection."
203
+ f"Python version {task_group_attrs['python_version']} "
204
+ "is not available on this Fractal instance."
205
205
  ),
206
206
  )
207
207
 
@@ -15,6 +15,7 @@ from fractal_server.app.models import Resource
15
15
  from fractal_server.app.models import UserGroup
16
16
  from fractal_server.app.models import UserOAuth
17
17
  from fractal_server.app.routes.auth import current_user_act
18
+ from fractal_server.app.routes.auth import current_user_act_ver
18
19
  from fractal_server.app.routes.auth._aux_auth import (
19
20
  _get_single_user_with_groups,
20
21
  )
@@ -111,7 +112,7 @@ async def get_current_user_profile_info(
111
112
  "/current-user/allowed-viewer-paths/", response_model=list[str]
112
113
  )
113
114
  async def get_current_user_allowed_viewer_paths(
114
- current_user: UserOAuth = Depends(current_user_act),
115
+ current_user: UserOAuth = Depends(current_user_act_ver),
115
116
  db: AsyncSession = Depends(get_async_db),
116
117
  ) -> list[str]:
117
118
  """
@@ -40,7 +40,7 @@ async def get_list_user_groups(
40
40
  db: AsyncSession = Depends(get_async_db),
41
41
  ) -> list[UserGroupRead]:
42
42
  # Get all groups
43
- stm_all_groups = select(UserGroup)
43
+ stm_all_groups = select(UserGroup).order_by(UserGroup.id)
44
44
  res = await db.execute(stm_all_groups)
45
45
  groups = res.scalars().all()
46
46
 
@@ -7,6 +7,7 @@ from pydantic import field_serializer
7
7
  from pydantic.types import AwareDatetime
8
8
 
9
9
  from fractal_server.types import ListUniqueAbsolutePathStr
10
+ from fractal_server.types import NonEmptyStr
10
11
 
11
12
  __all__ = (
12
13
  "UserGroupRead",
@@ -50,7 +51,7 @@ class UserGroupCreate(BaseModel):
50
51
 
51
52
  model_config = ConfigDict(extra="forbid")
52
53
 
53
- name: str
54
+ name: NonEmptyStr
54
55
  viewer_paths: ListUniqueAbsolutePathStr = Field(default_factory=list)
55
56
 
56
57
 
@@ -442,6 +442,7 @@ async def _create_first_user(
442
442
  raise e
443
443
  finally:
444
444
  function_logger.info(f"END _create_first_user, with email '{email}'")
445
+ close_logger(function_logger)
445
446
 
446
447
 
447
448
  def _create_first_group():
@@ -0,0 +1,321 @@
1
+ """
2
+
3
+ PRELIMINARY CHECKS (TO DO WITH 2.16)
4
+ * All users who are meant to actually use Fractal must be marked as active and verified.
5
+ * All users who are not active and verified will still be able to log in, but they won't have access to the rest of the API.
6
+ * All active users must have `project_dir` set, in their user settings.
7
+ * `FRACTAL_SLURM_WORKER_PYTHON` must be included explicitly in the old env file.
8
+
9
+ DATA-MIGRATION REQUIREMENTS
10
+ * Old `.fractal_server.env`, renamed into `.fractal_server.env.old`.
11
+ * New `.fractal_server.env` - see XXX for list of changes.
12
+ * Old JSON file with SLURM configuration.
13
+ * Old JSON file with pixi configuration - if applicable.
14
+
15
+
16
+ MANUAL FIXES POST DATA MIGRATION:
17
+ * Rename resource
18
+ * Rename profiles - if needed
19
+ """
20
+ import json
21
+ import logging
22
+ import sys
23
+ from typing import Any
24
+
25
+ from devtools import debug
26
+ from dotenv.main import DotEnv
27
+ from pydantic import BaseModel
28
+ from sqlalchemy.orm import Session
29
+ from sqlalchemy.sql.operators import is_
30
+ from sqlalchemy.sql.operators import is_not
31
+ from sqlmodel import select
32
+
33
+ from fractal_server.app.db import get_sync_db
34
+ from fractal_server.app.models import Profile
35
+ from fractal_server.app.models import ProjectV2
36
+ from fractal_server.app.models import Resource
37
+ from fractal_server.app.models import TaskGroupV2
38
+ from fractal_server.app.models import UserOAuth
39
+ from fractal_server.app.models import UserSettings
40
+ from fractal_server.app.schemas.v2.profile import cast_serialize_profile
41
+ from fractal_server.app.schemas.v2.resource import cast_serialize_resource
42
+ from fractal_server.config import get_settings
43
+ from fractal_server.runner.config import JobRunnerConfigSLURM
44
+ from fractal_server.tasks.config import TasksPixiSettings
45
+ from fractal_server.tasks.config import TasksPythonSettings
46
+ from fractal_server.types import AbsolutePathStr
47
+ from fractal_server.types import ListUniqueNonEmptyString
48
+ from fractal_server.urls import normalize_url
49
+
50
+ logger = logging.getLogger("fix_db")
51
+ logger.setLevel(logging.INFO)
52
+
53
+
54
+ class UserUpdateInfo(BaseModel):
55
+ user_id: int
56
+ project_dir: AbsolutePathStr
57
+ slurm_accounts: ListUniqueNonEmptyString
58
+
59
+
60
+ class ProfileUsersUpdateInfo(BaseModel):
61
+ data: dict[str, Any]
62
+ user_updates: list[UserUpdateInfo]
63
+
64
+
65
+ def _get_user_settings(user: UserOAuth, db: Session) -> UserSettings:
66
+ if user.user_settings_id is None:
67
+ sys.exit(f"User {user.email} is active but {user.user_settings_id=}.")
68
+ user_settings = db.get(UserSettings, user.user_settings_id)
69
+ return user_settings
70
+
71
+
72
+ def assert_user_setting_key(
73
+ user: UserOAuth,
74
+ user_settings: UserSettings,
75
+ keys: list[str],
76
+ ) -> None:
77
+ for key in keys:
78
+ if getattr(user_settings, key) is None:
79
+ sys.exit(
80
+ f"User {user.email} is active and verified but their "
81
+ f"user settings have {key}=None."
82
+ )
83
+
84
+
85
+ def prepare_profile_and_user_updates() -> dict[str, ProfileUsersUpdateInfo]:
86
+ settings = get_settings()
87
+ profiles_and_users: dict[str, ProfileUsersUpdateInfo] = {}
88
+ with next(get_sync_db()) as db:
89
+ # Get active&verified users
90
+ res = db.execute(
91
+ select(UserOAuth)
92
+ .where(is_(UserOAuth.is_active, True))
93
+ .where(is_(UserOAuth.is_verified, True))
94
+ .order_by(UserOAuth.id)
95
+ )
96
+ for user in res.unique().scalars().all():
97
+ # Get user settings
98
+ user_settings = _get_user_settings(user=user, db=db)
99
+ assert_user_setting_key(user, user_settings, ["project_dir"])
100
+
101
+ # Prepare profile data and user update
102
+ new_profile_data = dict()
103
+ if settings.FRACTAL_RUNNER_BACKEND == "slurm_sudo":
104
+ assert_user_setting_key(user, user_settings, ["slurm_user"])
105
+ username = user_settings.slurm_user
106
+ elif settings.FRACTAL_RUNNER_BACKEND == "slurm_ssh":
107
+ assert_user_setting_key(
108
+ user,
109
+ user_settings,
110
+ [
111
+ "ssh_username",
112
+ "ssh_private_key_path",
113
+ "ssh_tasks_dir",
114
+ "ssh_jobs_dir",
115
+ ],
116
+ )
117
+ username = user_settings.ssh_username
118
+ new_profile_data.update(
119
+ ssh_key_path=user_settings.ssh_private_key_path,
120
+ tasks_remote_dir=normalize_url(
121
+ user_settings.ssh_tasks_dir
122
+ ),
123
+ jobs_remote_dir=normalize_url(user_settings.ssh_jobs_dir),
124
+ )
125
+
126
+ new_profile_data.update(
127
+ name=f"Profile {username}",
128
+ username=username,
129
+ resource_type=settings.FRACTAL_RUNNER_BACKEND,
130
+ )
131
+ debug(new_profile_data)
132
+ cast_serialize_profile(new_profile_data)
133
+
134
+ user_update_info = UserUpdateInfo(
135
+ user_id=user.id,
136
+ project_dir=normalize_url(user_settings.project_dir),
137
+ slurm_accounts=user_settings.slurm_accounts or [],
138
+ )
139
+
140
+ if username in profiles_and_users.keys():
141
+ if profiles_and_users[username].data != new_profile_data:
142
+ # FIXME
143
+ debug(new_profile_data)
144
+ debug(profiles_and_users[username].data)
145
+ raise ValueError()
146
+ profiles_and_users[username].user_updates.append(
147
+ user_update_info
148
+ )
149
+ else:
150
+ profiles_and_users[username] = ProfileUsersUpdateInfo(
151
+ data=new_profile_data,
152
+ user_updates=[user_update_info],
153
+ )
154
+
155
+ return profiles_and_users
156
+
157
+
158
+ def get_old_dotenv_variables() -> dict[str, str | None]:
159
+ """
160
+ See
161
+ https://github.com/fractal-analytics-platform/fractal-server/blob/2.16.x/fractal_server/config.py
162
+ """
163
+ OLD_DOTENV_FILE = ".fractal_server.env.old"
164
+ return dict(
165
+ **DotEnv(
166
+ dotenv_path=OLD_DOTENV_FILE,
167
+ override=False,
168
+ ).dict()
169
+ )
170
+
171
+
172
+ def get_TasksPythonSettings(
173
+ old_config: dict[str, str | None]
174
+ ) -> dict[str, Any]:
175
+ versions = {}
176
+ for version_underscore in ["3_9", "3_10", "3_11", "3_12"]:
177
+ key = f"FRACTAL_TASKS_PYTHON_{version_underscore}"
178
+ version_dot = version_underscore.replace("_", ".")
179
+ value = old_config.get(key, None)
180
+ if value is not None:
181
+ versions[version_dot] = value
182
+ obj = TasksPythonSettings(
183
+ default_version=old_config["FRACTAL_TASKS_PYTHON_DEFAULT_VERSION"],
184
+ versions=versions,
185
+ pip_cache_dir=old_config.get("FRACTAL_PIP_CACHE_DIR", None),
186
+ )
187
+ return obj.model_dump()
188
+
189
+
190
+ def get_TasksPixiSettings(old_config: dict[str, str | None]) -> dict[str, Any]:
191
+ pixi_file = old_config.get("FRACTAL_PIXI_CONFIG_FILE", None)
192
+ if pixi_file is None:
193
+ return {}
194
+ with open(pixi_file) as f:
195
+ old_pixi_config = json.load(f)
196
+ TasksPixiSettings(**old_pixi_config)
197
+ return old_pixi_config
198
+
199
+
200
+ def get_JobRunnerConfigSLURM(
201
+ old_config: dict[str, str | None]
202
+ ) -> dict[str, Any]:
203
+ slurm_file = old_config["FRACTAL_SLURM_CONFIG_FILE"]
204
+ with open(slurm_file) as f:
205
+ old_slurm_config = json.load(f)
206
+ JobRunnerConfigSLURM(**old_slurm_config)
207
+ return old_slurm_config
208
+
209
+
210
+ def get_ssh_host() -> str:
211
+ with next(get_sync_db()) as db:
212
+ res = db.execute(
213
+ select(UserSettings.ssh_host).where(
214
+ is_not(UserSettings.ssh_host, None)
215
+ )
216
+ )
217
+ hosts = res.scalars().all()
218
+ if len(set(hosts)) > 1:
219
+ host = max(set(hosts), key=hosts.count)
220
+ print(f"MOST FREQUENT HOST: {host}")
221
+ else:
222
+ host = hosts[0]
223
+ return host
224
+
225
+
226
+ def prepare_resource_data(old_config: dict[str, str | None]) -> dict[str, Any]:
227
+ settings = get_settings()
228
+
229
+ resource_data = dict(
230
+ type=settings.FRACTAL_RUNNER_BACKEND,
231
+ name="Resource Name",
232
+ tasks_python_config=get_TasksPythonSettings(old_config),
233
+ tasks_pixi_config=get_TasksPixiSettings(old_config),
234
+ jobs_runner_config=get_JobRunnerConfigSLURM(old_config),
235
+ tasks_local_dir=old_config["FRACTAL_TASKS_DIR"],
236
+ jobs_local_dir=old_config["FRACTAL_RUNNER_WORKING_BASE_DIR"],
237
+ jobs_slurm_python_worker=old_config["FRACTAL_SLURM_WORKER_PYTHON"],
238
+ jobs_poll_interval=int(
239
+ old_config.get("FRACTAL_SLURM_POLL_INTERVAL", 15)
240
+ ),
241
+ )
242
+ if settings.FRACTAL_RUNNER_BACKEND == "slurm_ssh":
243
+ resource_data["host"] = get_ssh_host()
244
+
245
+ resource_data = cast_serialize_resource(resource_data)
246
+
247
+ return resource_data
248
+
249
+
250
+ def fix_db():
251
+ # READ-ONLY CHECK
252
+
253
+ settings = get_settings()
254
+
255
+ # Verify that we are in a SLURM instance
256
+ if settings.FRACTAL_RUNNER_BACKEND == "local":
257
+ sys.exit(
258
+ "ERROR: FRACTAL_RUNNER_BACKEND='local' is not "
259
+ "supported for this data migration."
260
+ )
261
+
262
+ # Read old env file
263
+ old_config = get_old_dotenv_variables()
264
+
265
+ # Prepare resource data
266
+ resource_data = prepare_resource_data(old_config)
267
+
268
+ # Prepare profile/users data
269
+ profile_and_user_updates = prepare_profile_and_user_updates()
270
+
271
+ # ---------------------------------------
272
+
273
+ # WRITES
274
+
275
+ with next(get_sync_db()) as db:
276
+ # Create new resource
277
+ resource = Resource(**resource_data)
278
+ db.add(resource)
279
+ db.commit()
280
+ db.refresh(resource)
281
+ db.expunge(resource)
282
+ resource_id = resource.id
283
+ debug(f"CREATED RESOURCE with {resource_id=}")
284
+
285
+ # Update task groups
286
+ res = db.execute(select(TaskGroupV2).order_by(TaskGroupV2.id))
287
+ for taskgroup in res.scalars().all():
288
+ taskgroup.resource_id = resource_id
289
+ db.add(taskgroup)
290
+ db.commit()
291
+
292
+ # Update projects
293
+ res = db.execute(select(ProjectV2).order_by(ProjectV2.id))
294
+ for project in res.scalars().all():
295
+ project.resource_id = resource_id
296
+ db.add(project)
297
+ db.commit()
298
+
299
+ db.expunge_all()
300
+
301
+ for _, info in profile_and_user_updates.items():
302
+ debug(info)
303
+
304
+ # Create profile
305
+ profile_data = info.data
306
+ profile_data["resource_id"] = resource_id
307
+ profile = Profile(**profile_data)
308
+ db.add(profile)
309
+ db.commit()
310
+ db.refresh(profile)
311
+ db.expunge(profile)
312
+ profile_id = profile.id
313
+
314
+ # Update users
315
+ for user_update in info.user_updates:
316
+ user = db.get(UserOAuth, user_update.user_id)
317
+ user.profile_id = profile_id
318
+ user.project_dir = user_update.project_dir
319
+ user.slurm_accounts = user_update.slurm_accounts
320
+ db.add(user)
321
+ db.commit()
@@ -74,6 +74,9 @@ def simplify_pyproject_toml(
74
74
  return original_toml_string
75
75
 
76
76
  # Use a single platform (or skip, if not set)
77
+ # Note: we look both for `[workspace.platforms]` and `[project.platforms]`,
78
+ # even though `[project]` is deprecated as of
79
+ # https://pixi.sh/dev/CHANGELOG/#0570-2025-10-20.
77
80
  try:
78
81
  pixi_data["workspace"]["platforms"] = [pixi_platform]
79
82
  except KeyError:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fractal-server
3
- Version: 2.17.0a9
3
+ Version: 2.17.0a11
4
4
  Summary: Backend component of the Fractal analytics platform
5
5
  License-Expression: BSD-3-Clause
6
6
  License-File: LICENSE
@@ -1,4 +1,4 @@
1
- fractal_server/__init__.py,sha256=31MUWp2DyXY86Okv_zgVu-z5XLlNkaH5c6DjEuY9RrI,25
1
+ fractal_server/__init__.py,sha256=Pj-IcBWFE8pRiluuKSO6LdRI9wotfOFmP9J3PnyZ0GE,26
2
2
  fractal_server/__main__.py,sha256=68FlTuST3zbzVofFI8JSYsSBrBQ07Bv3Mu3PsZX9Fw0,11423
3
3
  fractal_server/alembic.ini,sha256=MWwi7GzjzawI9cCAK1LW7NxIBQDUqD12-ptJoq5JpP0,3153
4
4
  fractal_server/app/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -29,7 +29,7 @@ fractal_server/app/routes/admin/v2/impersonate.py,sha256=ictDjuvBr3iLv3YtwkVRMNQ
29
29
  fractal_server/app/routes/admin/v2/job.py,sha256=sFgMbOtUCIJ-ri6YD3ZWP7XETZZDQsLqPfT1kaH9RHQ,8577
30
30
  fractal_server/app/routes/admin/v2/profile.py,sha256=0Y_1Qv-BA6cHVrxPTDDBOpttpfuJN8g1FqFlG6JiOD8,3164
31
31
  fractal_server/app/routes/admin/v2/project.py,sha256=rRq7ZDngr_29skASnte1xfycZCjK-WPdeTf7siBXiCU,1182
32
- fractal_server/app/routes/admin/v2/resource.py,sha256=eLK3PxvpibwQgVfgpMb_CdqkiB7hz8-RtPqqtP9ujz8,6310
32
+ fractal_server/app/routes/admin/v2/resource.py,sha256=UWimApUcL9HPu8NN0ccDbReuKly3aCqff2SA-Y1iEzs,6349
33
33
  fractal_server/app/routes/admin/v2/task.py,sha256=9MMUI2PnyHQx08Xmt93O5rM60C_tlic27mP6t7ljpYo,4655
34
34
  fractal_server/app/routes/admin/v2/task_group.py,sha256=EDY9oliXq_xYVJ2HgRuE4-5MbL85j-y4LbWwupZxy38,6249
35
35
  fractal_server/app/routes/admin/v2/task_group_lifecycle.py,sha256=W7LjIBAheyjrn0fEz0SsWINqcZK5HMB5GRGMjPrc6a4,9994
@@ -40,7 +40,7 @@ fractal_server/app/routes/api/v2/_aux_functions_history.py,sha256=PXsqMQ3sfkABqA
40
40
  fractal_server/app/routes/api/v2/_aux_functions_task_lifecycle.py,sha256=5gNt35rYR8sHG2f1N8coQbOJacYIRJ5zUrmMEXcs2LQ,8585
41
41
  fractal_server/app/routes/api/v2/_aux_functions_task_version_update.py,sha256=PKjV7r8YsPRXoNiVSnOK4KBYVV3l_Yb_ZPrqAkMkXrQ,1182
42
42
  fractal_server/app/routes/api/v2/_aux_functions_tasks.py,sha256=63CFMe1QZKRPmmU1xk1qZ_R6A1VANCxAlUBTGDrE0GI,13674
43
- fractal_server/app/routes/api/v2/_aux_task_group_disambiguation.py,sha256=sqvbD3M_4BV8fo9QTHRu-moX3pDfwXpTZaRy5YOH4EU,4897
43
+ fractal_server/app/routes/api/v2/_aux_task_group_disambiguation.py,sha256=492tLRUWTxsAZuhkZUt9PmJtKNLIhkAqKAa-LDtwG_Y,4893
44
44
  fractal_server/app/routes/api/v2/dataset.py,sha256=HhRrReo_isFJFMaUhQfxEQkLj0_lXNfGblzwpLG81VU,8623
45
45
  fractal_server/app/routes/api/v2/history.py,sha256=T-7GDLZ_x4cp9PMEozJoEFt4cGFYPDqv9-akYmN2JSU,17150
46
46
  fractal_server/app/routes/api/v2/images.py,sha256=_R-F1qrsFv3PPukrwXSa-5swNS4kNghY0DTrxjLC_7E,7897
@@ -50,7 +50,7 @@ fractal_server/app/routes/api/v2/project.py,sha256=PkRR1lQayBvY8uEOMherXpvv_YwIM
50
50
  fractal_server/app/routes/api/v2/status_legacy.py,sha256=vZA4AYMehXbNFgekl4j6p8idETC3IylQQL64CmFCr98,6330
51
51
  fractal_server/app/routes/api/v2/submit.py,sha256=o0r58Dc6A1BHOUPp2OK7PKEHc4dIqnp3-kXBWnX8KsY,9373
52
52
  fractal_server/app/routes/api/v2/task.py,sha256=HIQRA7lAW41P89eveCGmUI2HERMakxOw5is-F-j-fco,7519
53
- fractal_server/app/routes/api/v2/task_collection.py,sha256=Ja-Rusi6pSj5VVpfAlBMZmHBUaIhKqsUlhgB-qhgB70,12229
53
+ fractal_server/app/routes/api/v2/task_collection.py,sha256=wgY5-sry8Dg9IbLyzjxur8iqoe9ALs2zNK0bmNtO8Co,12226
54
54
  fractal_server/app/routes/api/v2/task_collection_custom.py,sha256=WjByW-raK-HU1IR02JNc39XMjkRftXyUSHwHrgnZFBw,6924
55
55
  fractal_server/app/routes/api/v2/task_collection_pixi.py,sha256=-HlgVzYxZb0Ysk6fkHbhkiVvVtQxmvli1kW03PTVaVo,7191
56
56
  fractal_server/app/routes/api/v2/task_group.py,sha256=7eGVim9D6AE4synpxAYMijyHIC1HTSBojY08MiuqMBg,8349
@@ -61,8 +61,8 @@ fractal_server/app/routes/api/v2/workflow_import.py,sha256=cEs1bt5urKIbaC8PjnUwY
61
61
  fractal_server/app/routes/api/v2/workflowtask.py,sha256=-V7WjTfYb2L7i3_dQ0Am_ydqepdqs-j3BY67_5iZPfU,7960
62
62
  fractal_server/app/routes/auth/__init__.py,sha256=Y-RQMwY5V25ZVgyYYoFIXvEDQgm6PGTDgxH755oa_NM,2358
63
63
  fractal_server/app/routes/auth/_aux_auth.py,sha256=10eQlLWCsuwmkGiZB3eSR9JhnU4db67wsWRxu8arKqc,5435
64
- fractal_server/app/routes/auth/current_user.py,sha256=BsM_lm9iNiaL8_iMY8NZnfgSXhzEY8xgkQUgtC40h8o,5517
65
- fractal_server/app/routes/auth/group.py,sha256=4SbqIG1FEOWeQzxS1ReSO-6Y7cUyQh9i_-qlAG7epxs,7268
64
+ fractal_server/app/routes/auth/current_user.py,sha256=xYun8dn9Ie3mzTczq1BC7HfIjPpj3x8QOtJ1H6Yb_GM,5585
65
+ fractal_server/app/routes/auth/group.py,sha256=JfQKmmafgVfsPmuVcA4wGs5qKwq9Xx4f-m4uwIyY3-Y,7291
66
66
  fractal_server/app/routes/auth/login.py,sha256=tSu6OBLOieoBtMZB4JkBAdEgH2Y8KqPGSbwy7NIypIo,566
67
67
  fractal_server/app/routes/auth/oauth.py,sha256=5BTEKb7Cb6ASVmgiPb5kVbHcBg0rF8Iqho0aJZd7PPQ,2730
68
68
  fractal_server/app/routes/auth/register.py,sha256=Ola-lNdYYEOK8Wh0Q-TFKwIJ25e6UswlUojJ8QGBCfc,581
@@ -75,7 +75,7 @@ fractal_server/app/routes/aux/validate_user_profile.py,sha256=fGqJDdAFkbQoEIjqZ5
75
75
  fractal_server/app/routes/pagination.py,sha256=IGy8Ll5lYr6ENYE18h3huH5s0GMX1DCs5VdCi6j1cdk,1174
76
76
  fractal_server/app/schemas/__init__.py,sha256=VIWJCaqokte3OljDLX00o-EC2d12rFoPb5HOLKQI94Y,86
77
77
  fractal_server/app/schemas/user.py,sha256=MGggiWGqQV97426IzoaKNIkqHUMEuadW7BbJgom6tB8,2898
78
- fractal_server/app/schemas/user_group.py,sha256=x3-kqbo0q2wTP7QI0iZ7PU_9Dr957UYrFMKqS7BXLhE,1425
78
+ fractal_server/app/schemas/user_group.py,sha256=uTTOVGoy89SxVDpJumjqOEWxqXWR41MNOTBDCyNxEDA,1478
79
79
  fractal_server/app/schemas/v2/__init__.py,sha256=XQex5ojpELgO0xvq2l-Y8oV85ZgM3GBj6lrGGctPb1g,3729
80
80
  fractal_server/app/schemas/v2/accounting.py,sha256=C_ekrYQwhi7PtrxxB07oVAG2y1NLigXjYwyp4E38fao,396
81
81
  fractal_server/app/schemas/v2/dataset.py,sha256=NKCjBwGBC7mPiSlXktZAcleJsvlLY6KfNKw7Wx4Zfqk,1728
@@ -92,7 +92,7 @@ fractal_server/app/schemas/v2/task_collection.py,sha256=BzHQXq2_zLZTbigWauOR5Zi-
92
92
  fractal_server/app/schemas/v2/task_group.py,sha256=4hNZUXnWYSozpLXR3JqBvGzfZBG2TbjqydckHHu2Aq0,3506
93
93
  fractal_server/app/schemas/v2/workflow.py,sha256=L-dW6SzCH_VNoH6ENip44lTgGGqVYHHBk_3PtM-Ooy8,1772
94
94
  fractal_server/app/schemas/v2/workflowtask.py,sha256=6eweAMyziwaoMT-7R1fVJYunIeZKzT0-7fAVgPO_FEc,3639
95
- fractal_server/app/security/__init__.py,sha256=_qETAX97suQAc_Jp09slTNIjgmsdK1hw6EpkVTKqnso,18356
95
+ fractal_server/app/security/__init__.py,sha256=k-La8Da89C1hSUGsiidrWo6Az4u6dbe5PzN1Ctt1t34,18394
96
96
  fractal_server/app/security/signup_email.py,sha256=kphjq6TAygvPpYpg95QJWefyqmzdVrGz7fyRMctUJWE,1982
97
97
  fractal_server/app/shutdown.py,sha256=ViSNJyXWU_iWPSDOOMGNh_iQdUFrdPh_jvf8vVKLpAo,1950
98
98
  fractal_server/config/__init__.py,sha256=ZCmroNB50sUxJiFtkW0a4fFtmfyPnL4LWhtKY5FbQfg,737
@@ -102,6 +102,7 @@ fractal_server/config/_email.py,sha256=j1QmZCyspNbD1xxkypc9Kv299tU3vTO1AqDFJ8-LZ
102
102
  fractal_server/config/_main.py,sha256=9v64gJsvY1oGP70_AoJMnyMIeRo7FcIg6T8NDV-p9as,1992
103
103
  fractal_server/config/_oauth.py,sha256=7J4FphGVFfVmtQycCkas6scEJQJGZUGEzQ-t2PZiqSo,1934
104
104
  fractal_server/config/_settings_config.py,sha256=tsyXQOnn9QKCFJD6hRo_dJXlQQyl70DbqgHMJoZ1xnY,144
105
+ fractal_server/data_migrations/2_17_0.py,sha256=ltMrezWWma-KPnZpOzQ12_yebBrjrdu0m7pQQh_RGWM,10894
105
106
  fractal_server/data_migrations/README.md,sha256=_3AEFvDg9YkybDqCLlFPdDmGJvr6Tw7HRI14aZ3LOIw,398
106
107
  fractal_server/data_migrations/tools.py,sha256=LeMeASwYGtEqd-3wOLle6WARdTGAimoyMmRbbJl-hAM,572
107
108
  fractal_server/exceptions.py,sha256=7ftpWwNsTQmNonWCynhH5ErUh1haPPhIaVPrNHla7-o,53
@@ -243,7 +244,7 @@ fractal_server/tasks/v2/templates/pixi_3_post_install.sh,sha256=99J8KXkNeQk9utuE
243
244
  fractal_server/tasks/v2/utils_background.py,sha256=jjWxNbHPuvAkXNIQ9Bqs67X72xHSRqmY8_BCoj0HM3E,4840
244
245
  fractal_server/tasks/v2/utils_database.py,sha256=C1td6m6ab1NdXVoT6stvVdrY_3FNck8OkRZZhn9h8ZA,1797
245
246
  fractal_server/tasks/v2/utils_package_names.py,sha256=RDg__xrvQs4ieeVzmVdMcEh95vGQYrv9Hfal-5EDBM8,2393
246
- fractal_server/tasks/v2/utils_pixi.py,sha256=tqCnxMdxs7KGWncWvk0alrdvDbX-w77P3fAot68Bqh4,3257
247
+ fractal_server/tasks/v2/utils_pixi.py,sha256=4q0inbOfJ-TWe7wFIq-f7W7-iKyd98tgNQpEkR-TE6E,3441
247
248
  fractal_server/tasks/v2/utils_python_interpreter.py,sha256=36AvrMoydr9w6Rm_7hKl5QK8zYI0KIm4Pv8WHANWwjE,658
248
249
  fractal_server/tasks/v2/utils_templates.py,sha256=L5GblhIKJwyzUbCORj1et5mh-7mG19nT5kmIpxOEj90,3489
249
250
  fractal_server/types/__init__.py,sha256=aA_8J1xXzuiLqpwO_Qf18-qzaRcYkHzevhH_T-diXWM,2026
@@ -254,8 +255,8 @@ fractal_server/types/validators/_workflow_task_arguments_validators.py,sha256=HL
254
255
  fractal_server/urls.py,sha256=QjIKAC1a46bCdiPMu3AlpgFbcv6a4l3ABcd5xz190Og,471
255
256
  fractal_server/utils.py,sha256=SYVVUuXe_nWyrJLsy7QA-KJscwc5PHEXjvsW4TK7XQI,2180
256
257
  fractal_server/zip_tools.py,sha256=H0w7wS5yE4ebj7hw1_77YQ959dl2c-L0WX6J_ro1TY4,4884
257
- fractal_server-2.17.0a9.dist-info/METADATA,sha256=T6CZo_ibeo3bRThMKZw-TtnixRAoJpDttuFS9mz96pY,4226
258
- fractal_server-2.17.0a9.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
259
- fractal_server-2.17.0a9.dist-info/entry_points.txt,sha256=8tV2kynvFkjnhbtDnxAqImL6HMVKsopgGfew0DOp5UY,58
260
- fractal_server-2.17.0a9.dist-info/licenses/LICENSE,sha256=QKAharUuhxL58kSoLizKJeZE3mTCBnX6ucmz8W0lxlk,1576
261
- fractal_server-2.17.0a9.dist-info/RECORD,,
258
+ fractal_server-2.17.0a11.dist-info/METADATA,sha256=7ma0Jk6lM9eGlYkmJYO3Y_RTw3oVhJoNfVfGJ5Ex1Wk,4227
259
+ fractal_server-2.17.0a11.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
260
+ fractal_server-2.17.0a11.dist-info/entry_points.txt,sha256=8tV2kynvFkjnhbtDnxAqImL6HMVKsopgGfew0DOp5UY,58
261
+ fractal_server-2.17.0a11.dist-info/licenses/LICENSE,sha256=QKAharUuhxL58kSoLizKJeZE3mTCBnX6ucmz8W0lxlk,1576
262
+ fractal_server-2.17.0a11.dist-info/RECORD,,