fractal-server 2.0.6__py3-none-any.whl → 2.2.0__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.
Files changed (49) hide show
  1. fractal_server/__init__.py +1 -1
  2. fractal_server/app/db/__init__.py +1 -1
  3. fractal_server/app/routes/admin/v1.py +2 -4
  4. fractal_server/app/routes/admin/v2.py +2 -4
  5. fractal_server/app/routes/api/v1/_aux_functions.py +24 -0
  6. fractal_server/app/routes/api/v1/job.py +3 -4
  7. fractal_server/app/routes/api/v1/project.py +28 -18
  8. fractal_server/app/routes/api/v2/_aux_functions.py +35 -12
  9. fractal_server/app/routes/api/v2/job.py +3 -4
  10. fractal_server/app/routes/api/v2/project.py +21 -0
  11. fractal_server/app/routes/api/v2/submit.py +36 -15
  12. fractal_server/app/routes/aux/_job.py +3 -1
  13. fractal_server/app/routes/aux/_runner.py +3 -3
  14. fractal_server/app/runner/executors/slurm/executor.py +169 -68
  15. fractal_server/app/runner/shutdown.py +88 -0
  16. fractal_server/app/runner/task_files.py +59 -27
  17. fractal_server/app/runner/v1/__init__.py +113 -64
  18. fractal_server/app/runner/v1/_common.py +53 -51
  19. fractal_server/app/runner/v1/_local/__init__.py +12 -11
  20. fractal_server/app/runner/v1/_local/_submit_setup.py +4 -4
  21. fractal_server/app/runner/v1/_slurm/__init__.py +16 -16
  22. fractal_server/app/runner/v1/_slurm/_submit_setup.py +11 -10
  23. fractal_server/app/runner/v1/_slurm/get_slurm_config.py +6 -6
  24. fractal_server/app/runner/v2/__init__.py +139 -60
  25. fractal_server/app/runner/v2/_local/__init__.py +12 -11
  26. fractal_server/app/runner/v2/_local/_local_config.py +1 -1
  27. fractal_server/app/runner/v2/_local/_submit_setup.py +4 -4
  28. fractal_server/app/runner/v2/_local_experimental/__init__.py +155 -0
  29. fractal_server/app/runner/v2/_local_experimental/_local_config.py +108 -0
  30. fractal_server/app/runner/v2/_local_experimental/_submit_setup.py +42 -0
  31. fractal_server/app/runner/v2/_local_experimental/executor.py +156 -0
  32. fractal_server/app/runner/v2/_slurm/__init__.py +10 -10
  33. fractal_server/app/runner/v2/_slurm/_submit_setup.py +11 -10
  34. fractal_server/app/runner/v2/_slurm/get_slurm_config.py +6 -6
  35. fractal_server/app/runner/v2/runner.py +17 -15
  36. fractal_server/app/runner/v2/runner_functions.py +38 -38
  37. fractal_server/app/runner/v2/runner_functions_low_level.py +12 -6
  38. fractal_server/app/security/__init__.py +4 -5
  39. fractal_server/config.py +73 -19
  40. fractal_server/gunicorn_fractal.py +40 -0
  41. fractal_server/{logger/__init__.py → logger.py} +2 -2
  42. fractal_server/main.py +45 -26
  43. fractal_server/migrations/env.py +1 -1
  44. {fractal_server-2.0.6.dist-info → fractal_server-2.2.0.dist-info}/METADATA +4 -1
  45. {fractal_server-2.0.6.dist-info → fractal_server-2.2.0.dist-info}/RECORD +48 -43
  46. fractal_server/logger/gunicorn_logger.py +0 -19
  47. {fractal_server-2.0.6.dist-info → fractal_server-2.2.0.dist-info}/LICENSE +0 -0
  48. {fractal_server-2.0.6.dist-info → fractal_server-2.2.0.dist-info}/WHEEL +0 -0
  49. {fractal_server-2.0.6.dist-info → fractal_server-2.2.0.dist-info}/entry_points.txt +0 -0
fractal_server/config.py CHANGED
@@ -166,7 +166,7 @@ class Settings(BaseSettings):
166
166
  ###########################################################################
167
167
  # DATABASE
168
168
  ###########################################################################
169
- DB_ENGINE: Literal["sqlite", "postgres"] = "sqlite"
169
+ DB_ENGINE: Literal["sqlite", "postgres", "postgres-psycopg"] = "sqlite"
170
170
  """
171
171
  Select which database engine to use (supported: `sqlite` and `postgres`).
172
172
  """
@@ -201,39 +201,51 @@ class Settings(BaseSettings):
201
201
  """
202
202
 
203
203
  @property
204
- def DATABASE_URL(self) -> URL:
205
- if self.DB_ENGINE == "sqlite":
206
- if not self.SQLITE_PATH:
207
- raise FractalConfigurationError(
208
- "SQLITE_PATH path cannot be None"
209
- )
210
- sqlite_path = abspath(self.SQLITE_PATH)
204
+ def DATABASE_ASYNC_URL(self) -> URL:
205
+ if self.DB_ENGINE == "postgres":
211
206
  url = URL.create(
212
- drivername="sqlite+aiosqlite",
213
- database=sqlite_path,
207
+ drivername="postgresql+asyncpg",
208
+ username=self.POSTGRES_USER,
209
+ password=self.POSTGRES_PASSWORD,
210
+ host=self.POSTGRES_HOST,
211
+ port=self.POSTGRES_PORT,
212
+ database=self.POSTGRES_DB,
214
213
  )
215
- return url
216
- elif "postgres":
214
+ elif self.DB_ENGINE == "postgres-psycopg":
217
215
  url = URL.create(
218
- drivername="postgresql+asyncpg",
216
+ drivername="postgresql+psycopg",
219
217
  username=self.POSTGRES_USER,
220
218
  password=self.POSTGRES_PASSWORD,
221
219
  host=self.POSTGRES_HOST,
222
220
  port=self.POSTGRES_PORT,
223
221
  database=self.POSTGRES_DB,
224
222
  )
225
- return url
223
+ else:
224
+ if not self.SQLITE_PATH:
225
+ raise FractalConfigurationError(
226
+ "SQLITE_PATH path cannot be None"
227
+ )
228
+ sqlite_path = abspath(self.SQLITE_PATH)
229
+ url = URL.create(
230
+ drivername="sqlite+aiosqlite",
231
+ database=sqlite_path,
232
+ )
233
+ return url
226
234
 
227
235
  @property
228
236
  def DATABASE_SYNC_URL(self):
229
- if self.DB_ENGINE == "sqlite":
237
+ if self.DB_ENGINE == "postgres":
238
+ return self.DATABASE_ASYNC_URL.set(
239
+ drivername="postgresql+psycopg2"
240
+ )
241
+ elif self.DB_ENGINE == "postgres-psycopg":
242
+ return self.DATABASE_ASYNC_URL.set(drivername="postgresql+psycopg")
243
+ else:
230
244
  if not self.SQLITE_PATH:
231
245
  raise FractalConfigurationError(
232
246
  "SQLITE_PATH path cannot be None"
233
247
  )
234
- return self.DATABASE_URL.set(drivername="sqlite")
235
- elif self.DB_ENGINE == "postgres":
236
- return self.DATABASE_URL.set(drivername="postgresql+psycopg2")
248
+ return self.DATABASE_ASYNC_URL.set(drivername="sqlite")
237
249
 
238
250
  ###########################################################################
239
251
  # FRACTAL SPECIFIC
@@ -289,7 +301,30 @@ class Settings(BaseSettings):
289
301
  )
290
302
  return FRACTAL_TASKS_DIR_path
291
303
 
292
- FRACTAL_RUNNER_BACKEND: Literal["local", "slurm"] = "local"
304
+ @validator("FRACTAL_RUNNER_WORKING_BASE_DIR", always=True)
305
+ def make_FRACTAL_RUNNER_WORKING_BASE_DIR_absolute(cls, v):
306
+ """
307
+ (Copy of make_FRACTAL_TASKS_DIR_absolute)
308
+ If `FRACTAL_RUNNER_WORKING_BASE_DIR` is a non-absolute path,
309
+ make it absolute (based on the current working directory).
310
+ """
311
+ if v is None:
312
+ return None
313
+ FRACTAL_RUNNER_WORKING_BASE_DIR_path = Path(v)
314
+ if not FRACTAL_RUNNER_WORKING_BASE_DIR_path.is_absolute():
315
+ FRACTAL_RUNNER_WORKING_BASE_DIR_path = (
316
+ FRACTAL_RUNNER_WORKING_BASE_DIR_path.resolve()
317
+ )
318
+ logging.warning(
319
+ f'FRACTAL_RUNNER_WORKING_BASE_DIR="{v}" is not an absolute '
320
+ "path; converting it to "
321
+ f'"{str(FRACTAL_RUNNER_WORKING_BASE_DIR_path)}"'
322
+ )
323
+ return FRACTAL_RUNNER_WORKING_BASE_DIR_path
324
+
325
+ FRACTAL_RUNNER_BACKEND: Literal[
326
+ "local", "local_experimental", "slurm"
327
+ ] = "local"
293
328
  """
294
329
  Select which runner backend to use.
295
330
  """
@@ -313,6 +348,17 @@ class Settings(BaseSettings):
313
348
  Path of JSON file with configuration for the local backend.
314
349
  """
315
350
 
351
+ FRACTAL_API_MAX_JOB_LIST_LENGTH: int = 50
352
+ """
353
+ Number of ids that can be stored in the `jobsV1` and `jobsV2` attributes of
354
+ `app.state`.
355
+ """
356
+
357
+ FRACTAL_GRACEFUL_SHUTDOWN_TIME: int = 30
358
+ """
359
+ Waiting time for the shutdown phase of executors
360
+ """
361
+
316
362
  FRACTAL_SLURM_CONFIG_FILE: Optional[Path]
317
363
  """
318
364
  Path of JSON file with configuration for the SLURM backend.
@@ -386,6 +432,14 @@ class Settings(BaseSettings):
386
432
  "DB engine is `postgres` but `psycopg2` or `asyncpg` "
387
433
  "are not available"
388
434
  )
435
+ elif self.DB_ENGINE == "postgres-psycopg":
436
+ try:
437
+ import psycopg # noqa: F401
438
+ except ModuleNotFoundError:
439
+ raise FractalConfigurationError(
440
+ "DB engine is `postgres-psycopg` but `psycopg` is not "
441
+ "available"
442
+ )
389
443
  else:
390
444
  if not self.SQLITE_PATH:
391
445
  raise FractalConfigurationError(
@@ -0,0 +1,40 @@
1
+ import logging
2
+ import os
3
+ import signal
4
+
5
+ from gunicorn.glogging import Logger as GunicornLogger
6
+ from uvicorn.workers import UvicornWorker
7
+
8
+ logger = logging.getLogger("uvicorn.error")
9
+
10
+
11
+ class FractalGunicornLogger(GunicornLogger):
12
+ error_fmt = r"%(asctime)s - gunicorn.error - %(levelname)s - [pid %(process)d] - %(message)s" # noqa: E501
13
+ datefmt = r"%Y-%m-%d %H:%M:%S,%u"
14
+
15
+
16
+ class FractalWorker(UvicornWorker):
17
+ """
18
+ Subclass of uvicorn workers, which also captures SIGABRT and handles
19
+ it within the `custom_handle_abort` method.
20
+ """
21
+
22
+ def init_signals(self) -> None:
23
+ super().init_signals()
24
+ signal.signal(signal.SIGABRT, self.custom_handle_abort)
25
+ logger.info(
26
+ f"[FractalWorker.init_signals - pid={self.pid}] "
27
+ "Set `custom_handle_abort` for SIGABRT"
28
+ )
29
+
30
+ def custom_handle_abort(self, sig, frame):
31
+ """
32
+ Custom version of `gunicorn.workers.base.Worker.handle_abort`,
33
+ transforming SIGABRT into SIGTERM.
34
+ """
35
+ self.alive = False
36
+ logger.info(
37
+ f"[FractalWorker.custom_handle_abort - pid={self.pid}] "
38
+ "Now send SIGTERM to process."
39
+ )
40
+ os.kill(self.pid, signal.SIGTERM)
@@ -17,8 +17,8 @@ from pathlib import Path
17
17
  from typing import Optional
18
18
  from typing import Union
19
19
 
20
- from ..config import get_settings
21
- from ..syringe import Inject
20
+ from .config import get_settings
21
+ from .syringe import Inject
22
22
 
23
23
 
24
24
  LOG_FORMAT = "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
fractal_server/main.py CHANGED
@@ -15,11 +15,16 @@
15
15
 
16
16
  This module sets up the FastAPI application that serves the Fractal Server.
17
17
  """
18
+ import os
19
+ from contextlib import asynccontextmanager
20
+
18
21
  from fastapi import FastAPI
19
22
 
23
+ from .app.runner.shutdown import cleanup_after_shutdown
20
24
  from .app.security import _create_first_user
21
25
  from .config import get_settings
22
26
  from .logger import config_uvicorn_loggers
27
+ from .logger import get_logger
23
28
  from .logger import reset_logger_handlers
24
29
  from .logger import set_logger
25
30
  from .syringe import Inject
@@ -77,15 +82,47 @@ def check_settings() -> None:
77
82
  reset_logger_handlers(logger)
78
83
 
79
84
 
80
- async def __on_startup() -> None:
81
- """
82
- Private wrapper for routines that need to be executed at server start-up.
83
-
84
- It should only be called from a `@app.on_event("startup")`-decorated
85
- callable.
86
- """
85
+ @asynccontextmanager
86
+ async def lifespan(app: FastAPI):
87
+ app.state.jobsV1 = []
88
+ app.state.jobsV2 = []
89
+ logger = set_logger("fractal_server.lifespan")
90
+ logger.info("Start application startup")
87
91
  check_settings()
92
+ settings = Inject(get_settings)
93
+ await _create_first_user(
94
+ email=settings.FRACTAL_DEFAULT_ADMIN_EMAIL,
95
+ password=settings.FRACTAL_DEFAULT_ADMIN_PASSWORD,
96
+ username=settings.FRACTAL_DEFAULT_ADMIN_USERNAME,
97
+ is_superuser=True,
98
+ is_verified=True,
99
+ )
88
100
  config_uvicorn_loggers()
101
+ logger.info("End application startup")
102
+ reset_logger_handlers(logger)
103
+ yield
104
+ logger = get_logger("fractal_server.lifespan")
105
+ logger.info("Start application shutdown")
106
+ logger.info(
107
+ f"Current worker with pid {os.getpid()} is shutting down. "
108
+ f"Current jobs: {app.state.jobsV1=}, {app.state.jobsV2=}"
109
+ )
110
+ if settings.FRACTAL_RUNNER_BACKEND == "slurm":
111
+ try:
112
+ await cleanup_after_shutdown(
113
+ jobsV1=app.state.jobsV1,
114
+ jobsV2=app.state.jobsV2,
115
+ logger_name="fractal_server.lifespan",
116
+ )
117
+ except Exception as e:
118
+ logger.error(
119
+ "Something went wrong during shutdown phase, "
120
+ "some of running jobs are not shutdown properly. "
121
+ f"Original error: {e}"
122
+ )
123
+
124
+ logger.info("End application shutdown")
125
+ reset_logger_handlers(logger)
89
126
 
90
127
 
91
128
  def start_application() -> FastAPI:
@@ -96,27 +133,9 @@ def start_application() -> FastAPI:
96
133
  app:
97
134
  The fully initialised application.
98
135
  """
99
- app = FastAPI()
136
+ app = FastAPI(lifespan=lifespan)
100
137
  collect_routers(app)
101
138
  return app
102
139
 
103
140
 
104
141
  app = start_application()
105
-
106
-
107
- @app.on_event("startup")
108
- async def on_startup() -> None:
109
- """
110
- Register the starup calls
111
-
112
- If the calls raise any error, the application startup is aborted.
113
- """
114
- settings = Inject(get_settings)
115
- await _create_first_user(
116
- email=settings.FRACTAL_DEFAULT_ADMIN_EMAIL,
117
- password=settings.FRACTAL_DEFAULT_ADMIN_PASSWORD,
118
- username=settings.FRACTAL_DEFAULT_ADMIN_USERNAME,
119
- is_superuser=True,
120
- is_verified=True,
121
- )
122
- await __on_startup()
@@ -54,7 +54,7 @@ def run_migrations_offline() -> None:
54
54
  settings = Inject(get_settings)
55
55
  settings.check_db()
56
56
  context.configure(
57
- url=settings.DATABASE_URL,
57
+ url=settings.DATABASE_ASYNC_URL,
58
58
  target_metadata=target_metadata,
59
59
  literal_binds=True,
60
60
  dialect_opts={"paramstyle": "named"},
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: fractal-server
3
- Version: 2.0.6
3
+ Version: 2.2.0
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
@@ -15,6 +15,7 @@ Classifier: Programming Language :: Python :: 3.11
15
15
  Classifier: Programming Language :: Python :: 3.12
16
16
  Provides-Extra: gunicorn
17
17
  Provides-Extra: postgres
18
+ Provides-Extra: postgres-psycopg-binary
18
19
  Requires-Dist: aiosqlite (>=0.19.0,<0.20.0)
19
20
  Requires-Dist: alembic (>=1.13.1,<2.0.0)
20
21
  Requires-Dist: asyncpg (>=0.29.0,<0.30.0) ; extra == "postgres"
@@ -25,7 +26,9 @@ Requires-Dist: fastapi (>=0.110.0,<0.111.0)
25
26
  Requires-Dist: fastapi-users[oauth] (>=12.1.0,<13.0.0)
26
27
  Requires-Dist: gunicorn (>=21.2,<23.0) ; extra == "gunicorn"
27
28
  Requires-Dist: packaging (>=23.2,<24.0)
29
+ Requires-Dist: psutil (>=5.9.8,<6.0.0)
28
30
  Requires-Dist: psycopg2 (>=2.9.5,<3.0.0) ; extra == "postgres"
31
+ Requires-Dist: psycopg[binary] (>=3.1.0,<4.0.0) ; extra == "postgres-psycopg-binary"
29
32
  Requires-Dist: pydantic (>=1.10.8,<2)
30
33
  Requires-Dist: python-dotenv (>=1.0.0,<2.0.0)
31
34
  Requires-Dist: sqlalchemy[asyncio] (>=2.0.23,<2.1)
@@ -1,8 +1,8 @@
1
- fractal_server/__init__.py,sha256=S5hrGn9zHoCPoN-w6jqLkqipFDSl7JkGHq3amd7eoVE,22
1
+ fractal_server/__init__.py,sha256=udfziatgmLzy3DTsmA7vtbgqr5SipuapUm21-q0dACo,22
2
2
  fractal_server/__main__.py,sha256=CocbzZooX1UtGqPi55GcHGNxnrJXFg5tUU5b3wyFCyo,4958
3
3
  fractal_server/alembic.ini,sha256=MWwi7GzjzawI9cCAK1LW7NxIBQDUqD12-ptJoq5JpP0,3153
4
4
  fractal_server/app/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
- fractal_server/app/db/__init__.py,sha256=WZEVfdJAX7ZyBM1ngfEGeqWWcjK_NygtCbawpmbwGpU,4042
5
+ fractal_server/app/db/__init__.py,sha256=KpS_mfmRfew0kieFDlwkSrDFvpzxftcvPALBBZ0LxsY,4048
6
6
  fractal_server/app/models/__init__.py,sha256=QGRjxBgk6GzHyyXh_7RuHvpLoe5PTl1g5KLkGqhFYMQ,199
7
7
  fractal_server/app/models/linkuserproject.py,sha256=eQaourbGRshvlMVlKzLYJKHEjfsW1CbWws9yW4eHXhA,567
8
8
  fractal_server/app/models/security.py,sha256=0oYj_cqPcQFsPFDyN4OTsqbXsLlXRcweawjP_iSiRI0,2900
@@ -23,26 +23,26 @@ fractal_server/app/models/v2/workflow.py,sha256=YBgFGCziUgU0aJ5EM3Svu9W2c46AewZO
23
23
  fractal_server/app/models/v2/workflowtask.py,sha256=3jEkObsSnlI05Pur_dSsXYdJxRqPL60Z7tK5-EJLOks,1532
24
24
  fractal_server/app/routes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
25
25
  fractal_server/app/routes/admin/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
26
- fractal_server/app/routes/admin/v1.py,sha256=uMupmRkicaoWazX8qSX5fgh00O3MbuSfim8QayP6NkE,13996
27
- fractal_server/app/routes/admin/v2.py,sha256=e0A6RMWfmTO5dVL95XO-P2EljdEwR00FErxahEPzODQ,13757
26
+ fractal_server/app/routes/admin/v1.py,sha256=jTTCq_NXEwnPJR5QEBImt58xoGuUVsAlZDiPX4iCtlo,13955
27
+ fractal_server/app/routes/admin/v2.py,sha256=zqLTdxs1pU_EBkdoQL912CQUWTZJhIr-PBdAOMymgSA,13716
28
28
  fractal_server/app/routes/api/__init__.py,sha256=EVyZrEq3I_1643QGTPCC5lgCp4xH_auYbrFfogTm4pc,315
29
29
  fractal_server/app/routes/api/v1/__init__.py,sha256=Y2HQdG197J0a7DyQEE2jn53IfxD0EHGhzK1I2JZuEck,958
30
- fractal_server/app/routes/api/v1/_aux_functions.py,sha256=lFfGJxbJc-Ryah_pPkiTH2SBncWQ15n0iqVFolzIOCM,11976
30
+ fractal_server/app/routes/api/v1/_aux_functions.py,sha256=CeaVrNVYs_lEbiJbu4uaTeeiajljeXfdq1iLkt5RoRo,12636
31
31
  fractal_server/app/routes/api/v1/dataset.py,sha256=HRE-8vPmVkeXf7WFYkI19mDtbY-iJZeJ7PmMiV0LMgY,16923
32
- fractal_server/app/routes/api/v1/job.py,sha256=NwXyhvvzdPDor0ts8Im__9-I0P1H943s4NXIRgaz7PM,5436
33
- fractal_server/app/routes/api/v1/project.py,sha256=DKQ6n1CPmHqsKieBaJlKnOhKaHWgQTZIA_asJTT9Uxo,15802
32
+ fractal_server/app/routes/api/v1/job.py,sha256=xdRtTR9NUwC98n3H1Tt0eOVJQ79GlBE1D2Opqk-MeeE,5342
33
+ fractal_server/app/routes/api/v1/project.py,sha256=MxbJUc9H14ZZ8mmMbX3LXGTVR3sHdD26YSw4TKI7WtU,16108
34
34
  fractal_server/app/routes/api/v1/task.py,sha256=udbKnenzc-Q10elYCVB9JmOPWATraa9tZi0AaByvWo0,6129
35
35
  fractal_server/app/routes/api/v1/task_collection.py,sha256=mFaYyCWtCPRqvs3j6zx_zaiDXn31Uzoa7UHZS-Lu_L0,8882
36
36
  fractal_server/app/routes/api/v1/workflow.py,sha256=7r9IoIevg_rvYCrerMOsIsUabSOQatxdPCfLdkP0dRs,10942
37
37
  fractal_server/app/routes/api/v1/workflowtask.py,sha256=qcHQlzlSFf_k8gtId-mA3tnyzgSR7i1m7pvR4R86blE,5582
38
38
  fractal_server/app/routes/api/v2/__init__.py,sha256=UNgODxoEXfQpQDjvsnMvHaUWbZOrcHhEXNisLcU-0tE,1487
39
- fractal_server/app/routes/api/v2/_aux_functions.py,sha256=IL1JKVqRcGfqiVbptDzpMKqi9QTYDYCCcsqIG0x0Nl8,14301
39
+ fractal_server/app/routes/api/v2/_aux_functions.py,sha256=tYJr5EPaA0CVGp-Y4jottFJUVToWvjcSY6PJqN_d--s,14938
40
40
  fractal_server/app/routes/api/v2/dataset.py,sha256=_HjKNP9XsMGoqyubGdF2ZyeW7vXC3VdK_0_TaUxgIF0,8248
41
41
  fractal_server/app/routes/api/v2/images.py,sha256=4r_HblPWyuKSZSJZfn8mbDaLv1ncwZU0gWdKneZcNG4,7894
42
- fractal_server/app/routes/api/v2/job.py,sha256=BtaxErBDbLwjY2zgGD1I6eRpsffoMonifcS1CMEXmLU,5325
43
- fractal_server/app/routes/api/v2/project.py,sha256=qyvizYZ4aUFgF3tGdfp4z8AwWgfo19N_KbFEljfUaC8,5594
42
+ fractal_server/app/routes/api/v2/job.py,sha256=dBwOJmGtMLDmjCj-ZNXYcqYrikzqx9VHDySB7ogNaKE,5231
43
+ fractal_server/app/routes/api/v2/project.py,sha256=U4TxD-J4TtQuu1D4BOhL1kTse5fCiNc3BwGH7bnlo38,6592
44
44
  fractal_server/app/routes/api/v2/status.py,sha256=osLexiMOSqmYcEV-41tlrwt9ofyFbtRm5HmPS5BU0t4,6394
45
- fractal_server/app/routes/api/v2/submit.py,sha256=su512HjafuD_lyiLswyxN4T8xwKaMpWOhGsYVPh94sI,7672
45
+ fractal_server/app/routes/api/v2/submit.py,sha256=sqfeVw18mqzfgBTpb6Ix6KFdapGiaZ8u3BSyIUteLEc,8488
46
46
  fractal_server/app/routes/api/v2/task.py,sha256=bRTtGgL8BBGbT7csVeRB-a54clgU2xHydi5XpcByDxg,8297
47
47
  fractal_server/app/routes/api/v2/task_collection.py,sha256=eN3NkZaZHkrqnLGRKE7Xd5mo0cHc8aK2lojCt26ErOQ,8988
48
48
  fractal_server/app/routes/api/v2/task_legacy.py,sha256=P_VJv9v0yzFUBuS-DQHhMVSOe20ecGJJcFBqiiFciOM,1628
@@ -50,8 +50,8 @@ fractal_server/app/routes/api/v2/workflow.py,sha256=2GlcYNjpvCdjwC_Kn7y0UP16B3pO
50
50
  fractal_server/app/routes/api/v2/workflowtask.py,sha256=l4eTD5IIun5cOdYzsxh3ajmnOISaSccYA_mVf15Cjtw,8802
51
51
  fractal_server/app/routes/auth.py,sha256=Xv80iqdyfY3lyicYs2Y8B6zEDEnyUu_H6_6psYtv3R4,4885
52
52
  fractal_server/app/routes/aux/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
53
- fractal_server/app/routes/aux/_job.py,sha256=7OP3B_FqYJUQ8hVn-7G8oYEEaZrM4hxLF9FoSyjudTo,1251
54
- fractal_server/app/routes/aux/_runner.py,sha256=psW6fsoo_VrAHrD5UQPbqFYikCp0m16VRymC-U1yUTk,675
53
+ fractal_server/app/routes/aux/_job.py,sha256=EShKa9AMHy7zqlwPHGsKO6uE0LtXkqutO9wCCHbZzcU,1321
54
+ fractal_server/app/routes/aux/_runner.py,sha256=1PcWhJlxl9xyYo_BLoVcb1mJt2j6IGrj7AxPIIjckrw,724
55
55
  fractal_server/app/runner/.gitignore,sha256=ytzN_oyHWXrGU7iFAtoHSTUbM6Rn6kG0Zkddg0xZk6s,16
56
56
  fractal_server/app/runner/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
57
57
  fractal_server/app/runner/async_wrap.py,sha256=_O6f8jftKYXG_DozkmlrDBhoiK9QhE9MablOyECq2_M,829
@@ -64,36 +64,41 @@ fractal_server/app/runner/executors/slurm/_check_jobs_status.py,sha256=8d29a7DQ2
64
64
  fractal_server/app/runner/executors/slurm/_executor_wait_thread.py,sha256=J3tjAx33nBgW4eHAXDte7hDs7Oe9FLEZaElEt8inrbg,4421
65
65
  fractal_server/app/runner/executors/slurm/_slurm_config.py,sha256=rF37XDImX1QoWx37MC5hSM9AuY_KfHU5gaWwN4vl4Zk,15552
66
66
  fractal_server/app/runner/executors/slurm/_subprocess_run_as_user.py,sha256=YwfJzZr_y4FL_hirHJdWK0vWzrldjoZZhXVFlO2AOMU,5131
67
- fractal_server/app/runner/executors/slurm/executor.py,sha256=267YTDvyeA0yX2n2HffxP8OAu_CQF5uB9K-_AaUG3iU,44655
67
+ fractal_server/app/runner/executors/slurm/executor.py,sha256=jieZE5LhsFqzjDAegynRV0jrNByEb-7Yx8YmtPr6ZS0,48208
68
68
  fractal_server/app/runner/executors/slurm/remote.py,sha256=wLziIsGdSMiO-jIXM8x77JRK82g_2hx0iBKTiMghuIo,5852
69
69
  fractal_server/app/runner/filenames.py,sha256=9lwu3yB4C67yiijYw8XIKaLFn3mJUt6_TCyVFM_aZUQ,206
70
70
  fractal_server/app/runner/set_start_and_last_task_index.py,sha256=-q4zVybAj8ek2XlbENKlfOAJ39hT_zoJoZkqzDqiAMY,1254
71
- fractal_server/app/runner/task_files.py,sha256=b5aRDi35QemBQnHT_AU6L_IPJJU_k_f5sJn-JXzkzy0,3180
72
- fractal_server/app/runner/v1/__init__.py,sha256=Uqf9smd4G9JCunXOsJ0U_DJyhYvl8TwItY3TbDLBLMc,13620
73
- fractal_server/app/runner/v1/_common.py,sha256=2-NScI-7qCIw14Od90so1onw-psIt8x1kx6EXq489Vk,21246
74
- fractal_server/app/runner/v1/_local/__init__.py,sha256=ZcWftuGRLmN8-S6QZXm6FhNehsxwmwZRhuRv-a7zA6s,6839
71
+ fractal_server/app/runner/shutdown.py,sha256=I_o2iYKJwzku0L3E85ETjrve3QPECygR5xhhsAo5huM,2910
72
+ fractal_server/app/runner/task_files.py,sha256=mPxOokb5ha4sXzOXP-_-3978Tmuf5KOn2FbYRbDLQ0g,4044
73
+ fractal_server/app/runner/v1/__init__.py,sha256=TgYUYpbeP-Y3U7fchIE35m-YFnZinE6Rjq9Rd7hf67Y,15058
74
+ fractal_server/app/runner/v1/_common.py,sha256=rF9IsOo_h_UyeCZ2hkHYPHsdgTjqLlGGig4wyrDS5CQ,21544
75
+ fractal_server/app/runner/v1/_local/__init__.py,sha256=KlSML4LqF4p1IfhSd8tAkiu3aeDzifeanuNXjATDsYE,6929
75
76
  fractal_server/app/runner/v1/_local/_local_config.py,sha256=hM7SPxR07luXPcXdrWXRpEB2uOyjSSRUdqW3QBKJn9c,3147
76
- fractal_server/app/runner/v1/_local/_submit_setup.py,sha256=kvNPT7ey2mEamORzPMMVThbFHtzZcSr-0A9tYw9uVDA,1493
77
+ fractal_server/app/runner/v1/_local/_submit_setup.py,sha256=XyBDPb4IYdKEEnzLYdcYteIHWVWofJxKMmQCyRkn5Bc,1509
77
78
  fractal_server/app/runner/v1/_local/executor.py,sha256=QrJlD77G6q4WohoJQO7XXbvi2RlCUsNvMnPDEZIoAqA,3620
78
- fractal_server/app/runner/v1/_slurm/__init__.py,sha256=KN98RO8E3EG4MLNFa--D3DilRHjUyHrVicC6pHtu5L0,10853
79
- fractal_server/app/runner/v1/_slurm/_submit_setup.py,sha256=llTgSOCnCVMvm7Q0SoVpLZshorAOZZUDz927ij0LZEA,2738
80
- fractal_server/app/runner/v1/_slurm/get_slurm_config.py,sha256=6TLWQon8hSicsD7c3yXK4P9xeId0s_H3HOOeMUVGVss,5977
79
+ fractal_server/app/runner/v1/_slurm/__init__.py,sha256=u2rMOLAlvmnm9r4fYecIlZYhjYAWWvA5c8hVczTdJSs,10941
80
+ fractal_server/app/runner/v1/_slurm/_submit_setup.py,sha256=KO9c694d318adoPQh9UGwxLkw4fRIgybQ5h7QHQKLXQ,2828
81
+ fractal_server/app/runner/v1/_slurm/get_slurm_config.py,sha256=6pQNNx997bLIfLp0guF09t_O0ZYRXnbEGLktSAcKnic,5999
81
82
  fractal_server/app/runner/v1/common.py,sha256=_L-vjLnWato80VdlB_BFN4G8P4jSM07u-5cnl1T3S34,3294
82
83
  fractal_server/app/runner/v1/handle_failed_job.py,sha256=bHzScC_aIlU3q-bQxGW6rfWV4xbZ2tho_sktjsAs1no,4684
83
- fractal_server/app/runner/v2/__init__.py,sha256=U6FwKhiIF1INKU8LCoGHBCb04S2xOa3rpbltcodWXLw,11952
84
- fractal_server/app/runner/v2/_local/__init__.py,sha256=Q1s-DwXleUq6w1ZNv6tlh3tZv6cyBqxB_hMvZlqVYaM,5881
85
- fractal_server/app/runner/v2/_local/_local_config.py,sha256=lR0Js-l63mQUzN9hK0HkfdLsrTf-W6GHvPvbPC64amY,3630
86
- fractal_server/app/runner/v2/_local/_submit_setup.py,sha256=deagsLSy6A3ZHKaSDcQqrdvbQVM3i4kgyTcbVc0tC5U,1614
84
+ fractal_server/app/runner/v2/__init__.py,sha256=OZC3oEbihvBOiOfEJzxUkv9AUIwGEe_0QqXoGqBOc3c,14569
85
+ fractal_server/app/runner/v2/_local/__init__.py,sha256=KTj14K6jH8fXGUi5P7u5_RqEE1zF4aXtgPxCKzw46iw,5971
86
+ fractal_server/app/runner/v2/_local/_local_config.py,sha256=9oi209Dlp35ANfxb_DISqmMKKc6DPaMsmYVWbZLseME,3630
87
+ fractal_server/app/runner/v2/_local/_submit_setup.py,sha256=MucNOo8Er0F5ZIwH7CnTeXgnFMc6d3pKPkv563QNVi0,1630
87
88
  fractal_server/app/runner/v2/_local/executor.py,sha256=QrJlD77G6q4WohoJQO7XXbvi2RlCUsNvMnPDEZIoAqA,3620
88
- fractal_server/app/runner/v2/_slurm/__init__.py,sha256=srxn5-KdQxqD8cWJmOJlSoctbXYlyCMM249xWGY9bhI,4409
89
- fractal_server/app/runner/v2/_slurm/_submit_setup.py,sha256=tsZHQdVy3VxENMdsBzHltrVWzugBppq0cFrHtaVzoUA,2793
90
- fractal_server/app/runner/v2/_slurm/get_slurm_config.py,sha256=I_lOS75iGYyJ74-gNwwcPadvZ9vI9HYe04WMln5GJ5Q,6726
89
+ fractal_server/app/runner/v2/_local_experimental/__init__.py,sha256=53yS8a-l0dMTT_4oz7WVFbKJ3NRsycyutYkOuBTm6Ik,5694
90
+ fractal_server/app/runner/v2/_local_experimental/_local_config.py,sha256=QiS5ODe-iGmUQdIT8QgpbyMc7-ZpIRv1V_f2q3qfPQ8,3211
91
+ fractal_server/app/runner/v2/_local_experimental/_submit_setup.py,sha256=we7r-sQf0CJ9gxbfbgHcYdC6pKjx8eXweljIjthxkv8,1212
92
+ fractal_server/app/runner/v2/_local_experimental/executor.py,sha256=vcBKjireIIyF5WgIQLatD6ojlWEydbTwyIG0bcpIjys,5438
93
+ fractal_server/app/runner/v2/_slurm/__init__.py,sha256=OUPsEpu37f9ohu7NfXtaqlQevxeg1Q3Gl4LwTkwl2So,4475
94
+ fractal_server/app/runner/v2/_slurm/_submit_setup.py,sha256=rvhMOK1QkqsxVWUvekT62KbDDlqpw49nq9mzQXSY3H0,2883
95
+ fractal_server/app/runner/v2/_slurm/get_slurm_config.py,sha256=btGmbZB0fO6bg2WujFxbGEV2iWzaMKbHgV1r2hm_4a0,6748
91
96
  fractal_server/app/runner/v2/deduplicate_list.py,sha256=-imwO7OB7ATADEnqVbTElUwoY0YIJCTf_SbWJNN9OZg,639
92
97
  fractal_server/app/runner/v2/handle_failed_job.py,sha256=M1r3dnrbUMo_AI2qjaVuGhieMAyLh5gcvB10YOBpjvI,5415
93
98
  fractal_server/app/runner/v2/merge_outputs.py,sha256=IHuHqbKmk97K35BFvTrKVBs60z3e_--OzXTnsvmA02c,1281
94
- fractal_server/app/runner/v2/runner.py,sha256=pZDRYXibPs6lYz8hg-F7KbibR_cl0sjCa5s9yaFE_-s,14160
95
- fractal_server/app/runner/v2/runner_functions.py,sha256=jwLfIL1gdmL-KqSKb-5CDG-g7rQYZdywn24bJ92R2qI,11067
96
- fractal_server/app/runner/v2/runner_functions_low_level.py,sha256=nPxmoSTIAQRwEf8iwfCdwTq4Eo3eDAHcgGn3GejPgqk,3710
99
+ fractal_server/app/runner/v2/runner.py,sha256=uyO71VObtqLVfnFjazZH-UMpea02g8kS0DW2YoCVN2s,14278
100
+ fractal_server/app/runner/v2/runner_functions.py,sha256=3DSzdY11g97iXjTud-6rNxF8JKxCW8GDKfUFXis58M8,11311
101
+ fractal_server/app/runner/v2/runner_functions_low_level.py,sha256=kcmqX9gV8zBC1kiSpJJpNhWo62gH0vFPOwPbxNOwEMs,3884
97
102
  fractal_server/app/runner/v2/task_interface.py,sha256=myS-kT0DsJ8xIJZBVEzgD8g54VbiwL6i7Im3e1zcVHQ,1866
98
103
  fractal_server/app/runner/v2/v1_compat.py,sha256=t0ficzAHUFaaeI56nqTb4YEKxfARF7L9Y6ijtJCwjP8,912
99
104
  fractal_server/app/schemas/__init__.py,sha256=jiIf54owztXupv3PO6Ilh0qcrkh2RUzKq4bcEFqEfc4,40
@@ -120,17 +125,17 @@ fractal_server/app/schemas/v2/task.py,sha256=7IfxiZkaVqlARy7WYE_H8m7j_IEcuQaZORU
120
125
  fractal_server/app/schemas/v2/task_collection.py,sha256=sY29NQfJrbjiidmVkVjSIH-20wIsmh7G1QOdr05KoDQ,3171
121
126
  fractal_server/app/schemas/v2/workflow.py,sha256=Zzx3e-qgkH8le0FUmAx9UrV5PWd7bj14PPXUh_zgZXM,1827
122
127
  fractal_server/app/schemas/v2/workflowtask.py,sha256=atVuVN4aXsVEOmSd-vyg-8_8OnPmqx-gT75rXcn_AlQ,6552
123
- fractal_server/app/security/__init__.py,sha256=wxosoHc3mJYPCdPMyWnRD8w_2OgnKYp2aDkdmwrZh5k,11203
124
- fractal_server/config.py,sha256=19CnX1Jyw_zYjEvfXJTaypB7Ape7qfFzKX4B1LZmOe0,15167
128
+ fractal_server/app/security/__init__.py,sha256=2-QbwuR-nsuHM_uwKS_WzYvkhnuhO5jUv8UVROetyVk,11169
129
+ fractal_server/config.py,sha256=XiSTdx7wI2Eem-lzeMQhhGAwUwsACCKdUnbiGqDIChY,17219
125
130
  fractal_server/data_migrations/README.md,sha256=_3AEFvDg9YkybDqCLlFPdDmGJvr6Tw7HRI14aZ3LOIw,398
131
+ fractal_server/gunicorn_fractal.py,sha256=2AOkgxu-oQ-XB578_voT0VuhmAXFTmb0c-nYn1XLy_Q,1231
126
132
  fractal_server/images/__init__.py,sha256=xO6jTLE4EZKO6cTDdJsBmK9cdeh9hFTaSbSuWgQg7y4,196
127
133
  fractal_server/images/models.py,sha256=9ipU5h4N6ogBChoB-2vHoqtL0TXOHCv6kRR-fER3mkM,4167
128
134
  fractal_server/images/tools.py,sha256=gxeniYy4Z-cp_ToK2LHPJUTVVUUrdpogYdcBUvBuLiY,2209
129
- fractal_server/logger/__init__.py,sha256=Q_e03Lj30VWdCqGBJrKw9A2QEeDbCKC_OOkDQVW9Dyw,5132
130
- fractal_server/logger/gunicorn_logger.py,sha256=vb5s7mruCHPkKWGrTTOPyrB_658Y2Z05ECdHhCCBhp0,644
131
- fractal_server/main.py,sha256=OostfB8nyFKCySDTnIR64WlHg82eHkoykJgQg6se9xc,3556
135
+ fractal_server/logger.py,sha256=56wfka6fHaa3Rx5qO009nEs_y8gx5wZ2NUNZZ1I-uvc,5130
136
+ fractal_server/main.py,sha256=U50BfL1cxpkSMglRmEHILZE1yDpiUhyb4tlrNuE3j6s,4417
132
137
  fractal_server/migrations/README,sha256=4rQvyDfqodGhpJw74VYijRmgFP49ji5chyEemWGHsuw,59
133
- fractal_server/migrations/env.py,sha256=bsl0HGZpjhommztgcs7wQ94sJzI1Orgnij97K8P_uyo,2630
138
+ fractal_server/migrations/env.py,sha256=Bvg-FJzRJZIH_wqS_ZyZNXANIaathjo22_IY7c3fCjo,2636
134
139
  fractal_server/migrations/script.py.mako,sha256=oMXw9LC3zRbinWWPPDgeZ4z9FJrV2zhRWiYdS5YgNbI,526
135
140
  fractal_server/migrations/versions/4c308bcaea2b_add_task_args_schema_and_task_args_.py,sha256=-wHe-fOffmYeAm0JXVl_lxZ7hhDkaEVqxgxpHkb_uL8,954
136
141
  fractal_server/migrations/versions/4cedeb448a53_workflowtask_foreign_keys_not_nullables.py,sha256=Mob8McGYAcmgvrseyyYOa54E6Gsgr-4SiGdC-r9O4_A,1157
@@ -163,8 +168,8 @@ fractal_server/tasks/v2/background_operations.py,sha256=MAMBn6W2bhkdK59kfUGiD7a1
163
168
  fractal_server/tasks/v2/get_collection_data.py,sha256=Qhf2T_aaqAfqu9_KpUSlXsS7EJoZQbEPEreHHa2jco8,502
164
169
  fractal_server/urls.py,sha256=5o_qq7PzKKbwq12NHSQZDmDitn5RAOeQ4xufu-2v9Zk,448
165
170
  fractal_server/utils.py,sha256=b7WwFdcFZ8unyT65mloFToYuEDXpQoHRcmRNqrhd_dQ,2115
166
- fractal_server-2.0.6.dist-info/LICENSE,sha256=QKAharUuhxL58kSoLizKJeZE3mTCBnX6ucmz8W0lxlk,1576
167
- fractal_server-2.0.6.dist-info/METADATA,sha256=id7WLlUPHEi6TAgIVSDxZJacFhTvriBOdX86QLLbqPM,4222
168
- fractal_server-2.0.6.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
169
- fractal_server-2.0.6.dist-info/entry_points.txt,sha256=8tV2kynvFkjnhbtDnxAqImL6HMVKsopgGfew0DOp5UY,58
170
- fractal_server-2.0.6.dist-info/RECORD,,
171
+ fractal_server-2.2.0.dist-info/LICENSE,sha256=QKAharUuhxL58kSoLizKJeZE3mTCBnX6ucmz8W0lxlk,1576
172
+ fractal_server-2.2.0.dist-info/METADATA,sha256=BLunPAjR4O5zDEcZ7DYkzTNsJKmAsA0SIZcLLQQXpQI,4386
173
+ fractal_server-2.2.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
174
+ fractal_server-2.2.0.dist-info/entry_points.txt,sha256=8tV2kynvFkjnhbtDnxAqImL6HMVKsopgGfew0DOp5UY,58
175
+ fractal_server-2.2.0.dist-info/RECORD,,
@@ -1,19 +0,0 @@
1
- """
2
- This module (which is only executed if `gunicorn` can be imported) subclasses
3
- the gunicorn `Logger` class in order to slightly change its log formats.
4
-
5
- This class can be used by including this `gunicorn` command-line option:
6
- ```
7
- --logger-class fractal_server.logger.gunicorn_logger.FractalGunicornLogger
8
- ```
9
- """
10
-
11
- try:
12
- from gunicorn.glogging import Logger as GunicornLogger
13
-
14
- class FractalGunicornLogger(GunicornLogger):
15
- error_fmt = r"%(asctime)s - gunicorn.error - %(levelname)s - [pid %(process)d] - %(message)s" # noqa: E501
16
- datefmt = r"%Y-%m-%d %H:%M:%S,%u"
17
-
18
- except (ModuleNotFoundError, ImportError):
19
- pass