fractal-server 2.10.2__py3-none-any.whl → 2.10.4__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.
- fractal_server/__init__.py +1 -1
- fractal_server/__main__.py +71 -0
- fractal_server/app/routes/api/v2/task_collection.py +10 -0
- fractal_server/app/routes/api/v2/workflowtask.py +7 -11
- fractal_server/app/security/__init__.py +19 -2
- fractal_server/app/security/signup_email.py +39 -0
- fractal_server/config.py +88 -1
- fractal_server/tasks/v2/templates/2_pip_install.sh +1 -1
- fractal_server/urls.py +2 -1
- {fractal_server-2.10.2.dist-info → fractal_server-2.10.4.dist-info}/METADATA +14 -13
- {fractal_server-2.10.2.dist-info → fractal_server-2.10.4.dist-info}/RECORD +14 -16
- {fractal_server-2.10.2.dist-info → fractal_server-2.10.4.dist-info}/WHEEL +1 -1
- fractal_server/app/runner/.gitignore +0 -2
- fractal_server/migrations/README +0 -1
- fractal_server/migrations/script.py.mako +0 -25
- {fractal_server-2.10.2.dist-info → fractal_server-2.10.4.dist-info}/LICENSE +0 -0
- {fractal_server-2.10.2.dist-info → fractal_server-2.10.4.dist-info}/entry_points.txt +0 -0
fractal_server/__init__.py
CHANGED
@@ -1 +1 @@
|
|
1
|
-
__VERSION__ = "2.10.
|
1
|
+
__VERSION__ = "2.10.4"
|
fractal_server/__main__.py
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
import argparse as ap
|
2
2
|
import asyncio
|
3
|
+
import json
|
3
4
|
import sys
|
4
5
|
|
5
6
|
import uvicorn
|
@@ -62,6 +63,41 @@ update_db_data_parser = subparsers.add_parser(
|
|
62
63
|
description="Apply data-migration script to an existing database.",
|
63
64
|
)
|
64
65
|
|
66
|
+
# fractalctl email-settings
|
67
|
+
email_settings_parser = subparsers.add_parser(
|
68
|
+
"email-settings",
|
69
|
+
description=(
|
70
|
+
"Generate valid values for environment variables "
|
71
|
+
"`FRACTAL_EMAIL_SETTINGS` and `FRACTAL_EMAIL_SETTINGS_KEY`."
|
72
|
+
),
|
73
|
+
)
|
74
|
+
email_settings_parser.add_argument(
|
75
|
+
"sender",
|
76
|
+
type=str,
|
77
|
+
help="Email of the sender",
|
78
|
+
)
|
79
|
+
email_settings_parser.add_argument(
|
80
|
+
"server",
|
81
|
+
type=str,
|
82
|
+
help="SMPT server used to send emails",
|
83
|
+
)
|
84
|
+
email_settings_parser.add_argument(
|
85
|
+
"port",
|
86
|
+
type=int,
|
87
|
+
help="Port of the SMPT server",
|
88
|
+
)
|
89
|
+
email_settings_parser.add_argument(
|
90
|
+
"instance",
|
91
|
+
type=str,
|
92
|
+
help="Name of the Fractal instance sending emails",
|
93
|
+
)
|
94
|
+
email_settings_parser.add_argument(
|
95
|
+
"--skip-starttls",
|
96
|
+
action="store_true",
|
97
|
+
default=False,
|
98
|
+
help="If set, skip the execution of `starttls` when sending emails",
|
99
|
+
)
|
100
|
+
|
65
101
|
|
66
102
|
def save_openapi(dest="openapi.json"):
|
67
103
|
from fractal_server.main import start_application
|
@@ -188,6 +224,33 @@ def update_db_data():
|
|
188
224
|
current_update_db_data_module.fix_db()
|
189
225
|
|
190
226
|
|
227
|
+
def print_mail_settings(
|
228
|
+
sender: str,
|
229
|
+
server: str,
|
230
|
+
port: int,
|
231
|
+
instance: str,
|
232
|
+
skip_starttls: bool,
|
233
|
+
):
|
234
|
+
from cryptography.fernet import Fernet
|
235
|
+
|
236
|
+
password = input(f"Insert email password for sender '{sender}': ")
|
237
|
+
key = Fernet.generate_key().decode("utf-8")
|
238
|
+
fractal_mail_settings = json.dumps(
|
239
|
+
dict(
|
240
|
+
sender=sender,
|
241
|
+
password=password,
|
242
|
+
smtp_server=server,
|
243
|
+
port=port,
|
244
|
+
instance_name=instance,
|
245
|
+
use_starttls=(not skip_starttls),
|
246
|
+
)
|
247
|
+
).encode("utf-8")
|
248
|
+
email_settings = Fernet(key).encrypt(fractal_mail_settings).decode("utf-8")
|
249
|
+
|
250
|
+
print(f"\nFRACTAL_EMAIL_SETTINGS: {email_settings}")
|
251
|
+
print(f"FRACTAL_EMAIL_SETTINGS_KEY: {key}")
|
252
|
+
|
253
|
+
|
191
254
|
def run():
|
192
255
|
args = parser.parse_args(sys.argv[1:])
|
193
256
|
|
@@ -204,6 +267,14 @@ def run():
|
|
204
267
|
port=args.port,
|
205
268
|
reload=args.reload,
|
206
269
|
)
|
270
|
+
elif args.cmd == "email-settings":
|
271
|
+
print_mail_settings(
|
272
|
+
sender=args.sender,
|
273
|
+
server=args.server,
|
274
|
+
port=args.port,
|
275
|
+
instance=args.instance,
|
276
|
+
skip_starttls=args.skip_starttls,
|
277
|
+
)
|
207
278
|
else:
|
208
279
|
sys.exit(f"Error: invalid command '{args.cmd}'.")
|
209
280
|
|
@@ -56,6 +56,8 @@ router = APIRouter()
|
|
56
56
|
|
57
57
|
logger = set_logger(__name__)
|
58
58
|
|
59
|
+
FORBIDDEN_CHAR_WHEEL = [";", "/"]
|
60
|
+
|
59
61
|
|
60
62
|
class CollectionRequestData(BaseModel):
|
61
63
|
"""
|
@@ -90,6 +92,14 @@ class CollectionRequestData(BaseModel):
|
|
90
92
|
f"provided (given package_version='{package_version}')."
|
91
93
|
)
|
92
94
|
values["origin"] = TaskGroupV2OriginEnum.WHEELFILE
|
95
|
+
|
96
|
+
for forbidden_char in FORBIDDEN_CHAR_WHEEL:
|
97
|
+
if forbidden_char in file.filename:
|
98
|
+
raise ValueError(
|
99
|
+
"Wheel filename has forbidden characters, "
|
100
|
+
f"{FORBIDDEN_CHAR_WHEEL}"
|
101
|
+
)
|
102
|
+
|
93
103
|
return values
|
94
104
|
|
95
105
|
|
@@ -6,7 +6,6 @@ from fastapi import Depends
|
|
6
6
|
from fastapi import HTTPException
|
7
7
|
from fastapi import Response
|
8
8
|
from fastapi import status
|
9
|
-
from sqlalchemy.orm.attributes import flag_modified
|
10
9
|
|
11
10
|
from ....db import AsyncSession
|
12
11
|
from ....db import get_async_db
|
@@ -89,8 +88,7 @@ async def replace_workflowtask(
|
|
89
88
|
_args_parallel = replace.args_parallel
|
90
89
|
|
91
90
|
# If user's changes to `meta_non_parallel` are compatible with new task,
|
92
|
-
# keep them;
|
93
|
-
# else, get `meta_non_parallel` from new task
|
91
|
+
# keep them; else, get `meta_non_parallel` from new task
|
94
92
|
if (
|
95
93
|
old_workflow_task.meta_non_parallel
|
96
94
|
!= old_workflow_task.task.meta_non_parallel
|
@@ -107,12 +105,10 @@ async def replace_workflowtask(
|
|
107
105
|
_meta_parallel = task.meta_parallel
|
108
106
|
|
109
107
|
new_workflow_task = WorkflowTaskV2(
|
110
|
-
# new task
|
111
|
-
task_type=task.type,
|
112
108
|
task_id=task.id,
|
109
|
+
task_type=task.type,
|
113
110
|
task=task,
|
114
|
-
# old values
|
115
|
-
order=old_workflow_task.order,
|
111
|
+
# old-task values
|
116
112
|
input_filters=old_workflow_task.input_filters,
|
117
113
|
# possibly new values
|
118
114
|
args_non_parallel=_args_non_parallel,
|
@@ -121,11 +117,11 @@ async def replace_workflowtask(
|
|
121
117
|
meta_parallel=_meta_parallel,
|
122
118
|
)
|
123
119
|
|
124
|
-
|
125
|
-
workflow.task_list.
|
126
|
-
|
120
|
+
workflow_task_order = old_workflow_task.order
|
121
|
+
workflow.task_list.remove(old_workflow_task)
|
122
|
+
workflow.task_list.insert(workflow_task_order, new_workflow_task)
|
127
123
|
await db.commit()
|
128
|
-
|
124
|
+
await db.refresh(new_workflow_task)
|
129
125
|
return new_workflow_task
|
130
126
|
|
131
127
|
|
@@ -59,7 +59,10 @@ from fractal_server.app.models import UserGroup
|
|
59
59
|
from fractal_server.app.models import UserOAuth
|
60
60
|
from fractal_server.app.models import UserSettings
|
61
61
|
from fractal_server.app.schemas.user import UserCreate
|
62
|
+
from fractal_server.app.security.signup_email import mail_new_oauth_signup
|
63
|
+
from fractal_server.config import get_settings
|
62
64
|
from fractal_server.logger import set_logger
|
65
|
+
from fractal_server.syringe import Inject
|
63
66
|
|
64
67
|
logger = set_logger(__name__)
|
65
68
|
|
@@ -211,8 +214,6 @@ class UserManager(IntegerIDMixin, BaseUserManager[UserOAuth, int]):
|
|
211
214
|
async def on_after_register(
|
212
215
|
self, user: UserOAuth, request: Optional[Request] = None
|
213
216
|
):
|
214
|
-
logger = set_logger("fractal_server.on_after_register")
|
215
|
-
|
216
217
|
logger.info(
|
217
218
|
f"New-user registration completed ({user.id=}, {user.email=})."
|
218
219
|
)
|
@@ -248,6 +249,22 @@ class UserManager(IntegerIDMixin, BaseUserManager[UserOAuth, int]):
|
|
248
249
|
f"to '{this_user.email}'."
|
249
250
|
)
|
250
251
|
|
252
|
+
# Send mail section
|
253
|
+
settings = Inject(get_settings)
|
254
|
+
|
255
|
+
if this_user.oauth_accounts and settings.MAIL_SETTINGS is not None:
|
256
|
+
try:
|
257
|
+
mail_new_oauth_signup(
|
258
|
+
msg=f"New user registered: '{this_user.email}'.",
|
259
|
+
mail_settings=settings.MAIL_SETTINGS,
|
260
|
+
)
|
261
|
+
except Exception as e:
|
262
|
+
logger.error(
|
263
|
+
"ERROR sending notification email after oauth "
|
264
|
+
f"registration of {this_user.email}. "
|
265
|
+
f"Original error: '{e}'."
|
266
|
+
)
|
267
|
+
|
251
268
|
|
252
269
|
async def get_user_manager(
|
253
270
|
user_db: SQLModelUserDatabaseAsync = Depends(get_user_db),
|
@@ -0,0 +1,39 @@
|
|
1
|
+
import smtplib
|
2
|
+
from email.message import EmailMessage
|
3
|
+
from email.utils import formataddr
|
4
|
+
|
5
|
+
from fractal_server.config import MailSettings
|
6
|
+
|
7
|
+
|
8
|
+
def mail_new_oauth_signup(msg: str, mail_settings: MailSettings):
|
9
|
+
"""
|
10
|
+
Send an email using the specified settings to notify a new OAuth signup.
|
11
|
+
"""
|
12
|
+
|
13
|
+
mail_msg = EmailMessage()
|
14
|
+
mail_msg.set_content(msg)
|
15
|
+
mail_msg["From"] = formataddr((mail_settings.sender, mail_settings.sender))
|
16
|
+
mail_msg["To"] = ",".join(
|
17
|
+
[
|
18
|
+
formataddr((recipient, recipient))
|
19
|
+
for recipient in mail_settings.recipients
|
20
|
+
]
|
21
|
+
)
|
22
|
+
mail_msg[
|
23
|
+
"Subject"
|
24
|
+
] = f"[Fractal, {mail_settings.instance_name}] New OAuth signup"
|
25
|
+
|
26
|
+
with smtplib.SMTP(mail_settings.smtp_server, mail_settings.port) as server:
|
27
|
+
server.ehlo()
|
28
|
+
if mail_settings.use_starttls:
|
29
|
+
server.starttls()
|
30
|
+
server.ehlo()
|
31
|
+
|
32
|
+
server.login(
|
33
|
+
user=mail_settings.sender, password=mail_settings.password
|
34
|
+
)
|
35
|
+
server.sendmail(
|
36
|
+
from_addr=mail_settings.sender,
|
37
|
+
to_addrs=mail_settings.recipients,
|
38
|
+
msg=mail_msg.as_string(),
|
39
|
+
)
|
fractal_server/config.py
CHANGED
@@ -11,6 +11,7 @@
|
|
11
11
|
# <exact-lab.it> under contract with Liberali Lab from the Friedrich Miescher
|
12
12
|
# Institute for Biomedical Research and Pelkmans Lab from the University of
|
13
13
|
# Zurich.
|
14
|
+
import json
|
14
15
|
import logging
|
15
16
|
import shutil
|
16
17
|
import sys
|
@@ -21,9 +22,11 @@ from typing import Literal
|
|
21
22
|
from typing import Optional
|
22
23
|
from typing import TypeVar
|
23
24
|
|
25
|
+
from cryptography.fernet import Fernet
|
24
26
|
from dotenv import load_dotenv
|
25
27
|
from pydantic import BaseModel
|
26
28
|
from pydantic import BaseSettings
|
29
|
+
from pydantic import EmailStr
|
27
30
|
from pydantic import Field
|
28
31
|
from pydantic import root_validator
|
29
32
|
from pydantic import validator
|
@@ -32,6 +35,29 @@ from sqlalchemy.engine import URL
|
|
32
35
|
import fractal_server
|
33
36
|
|
34
37
|
|
38
|
+
class MailSettings(BaseModel):
|
39
|
+
"""
|
40
|
+
Schema for `MailSettings`
|
41
|
+
|
42
|
+
Attributes:
|
43
|
+
sender: Sender email address
|
44
|
+
recipients: List of recipients email address
|
45
|
+
smtp_server: SMTP server address
|
46
|
+
port: SMTP server port
|
47
|
+
password: Sender password
|
48
|
+
instance_name: Name of SMTP server instance
|
49
|
+
use_starttls: Using or not security protocol
|
50
|
+
"""
|
51
|
+
|
52
|
+
sender: EmailStr
|
53
|
+
recipients: list[EmailStr] = Field(min_items=1)
|
54
|
+
smtp_server: str
|
55
|
+
port: int
|
56
|
+
password: str
|
57
|
+
instance_name: str
|
58
|
+
use_starttls: bool
|
59
|
+
|
60
|
+
|
35
61
|
class FractalConfigurationError(RuntimeError):
|
36
62
|
pass
|
37
63
|
|
@@ -560,9 +586,69 @@ class Settings(BaseSettings):
|
|
560
586
|
FRACTAL_VIEWER_AUTHORIZATION_SCHEME is set to "users-folders".
|
561
587
|
"""
|
562
588
|
|
589
|
+
###########################################################################
|
590
|
+
# SMTP SERVICE
|
591
|
+
###########################################################################
|
592
|
+
FRACTAL_EMAIL_SETTINGS: Optional[str] = None
|
593
|
+
"""
|
594
|
+
Encrypted version of settings dictionary, with keys `sender`, `password`,
|
595
|
+
`smtp_server`, `port`, `instance_name`, `use_starttls`.
|
596
|
+
"""
|
597
|
+
FRACTAL_EMAIL_SETTINGS_KEY: Optional[str] = None
|
598
|
+
"""
|
599
|
+
Key value for `cryptography.fernet` decrypt
|
600
|
+
"""
|
601
|
+
FRACTAL_EMAIL_RECIPIENTS: Optional[str] = None
|
602
|
+
"""
|
603
|
+
List of email receivers, separated with commas
|
604
|
+
"""
|
605
|
+
|
606
|
+
@property
|
607
|
+
def MAIL_SETTINGS(self) -> Optional[MailSettings]:
|
608
|
+
if (
|
609
|
+
self.FRACTAL_EMAIL_SETTINGS is not None
|
610
|
+
and self.FRACTAL_EMAIL_SETTINGS_KEY is not None
|
611
|
+
and self.FRACTAL_EMAIL_RECIPIENTS is not None
|
612
|
+
):
|
613
|
+
smpt_settings = (
|
614
|
+
Fernet(self.FRACTAL_EMAIL_SETTINGS_KEY)
|
615
|
+
.decrypt(self.FRACTAL_EMAIL_SETTINGS)
|
616
|
+
.decode("utf-8")
|
617
|
+
)
|
618
|
+
recipients = self.FRACTAL_EMAIL_RECIPIENTS.split(",")
|
619
|
+
mail_settings = MailSettings(
|
620
|
+
**json.loads(smpt_settings), recipients=recipients
|
621
|
+
)
|
622
|
+
return mail_settings
|
623
|
+
elif not all(
|
624
|
+
[
|
625
|
+
self.FRACTAL_EMAIL_RECIPIENTS is None,
|
626
|
+
self.FRACTAL_EMAIL_SETTINGS_KEY is None,
|
627
|
+
self.FRACTAL_EMAIL_SETTINGS is None,
|
628
|
+
]
|
629
|
+
):
|
630
|
+
raise ValueError(
|
631
|
+
"You must set all SMPT config variables: "
|
632
|
+
f"{self.FRACTAL_EMAIL_SETTINGS=}, "
|
633
|
+
f"{self.FRACTAL_EMAIL_RECIPIENTS=}, "
|
634
|
+
f"{self.FRACTAL_EMAIL_SETTINGS_KEY=}, "
|
635
|
+
)
|
636
|
+
|
563
637
|
###########################################################################
|
564
638
|
# BUSINESS LOGIC
|
565
639
|
###########################################################################
|
640
|
+
|
641
|
+
def check_fractal_mail_settings(self):
|
642
|
+
"""
|
643
|
+
Checks that the mail settings are properly set.
|
644
|
+
"""
|
645
|
+
try:
|
646
|
+
self.MAIL_SETTINGS
|
647
|
+
except Exception as e:
|
648
|
+
raise FractalConfigurationError(
|
649
|
+
f"Invalid email configuration settings. Original error: {e}"
|
650
|
+
)
|
651
|
+
|
566
652
|
def check_db(self) -> None:
|
567
653
|
"""
|
568
654
|
Checks that db environment variables are properly set.
|
@@ -668,12 +754,13 @@ class Settings(BaseSettings):
|
|
668
754
|
|
669
755
|
self.check_db()
|
670
756
|
self.check_runner()
|
757
|
+
self.check_fractal_mail_settings()
|
671
758
|
|
672
759
|
def get_sanitized(self) -> dict:
|
673
760
|
def _must_be_sanitized(string) -> bool:
|
674
761
|
if not string.upper().startswith("FRACTAL") or any(
|
675
762
|
s in string.upper()
|
676
|
-
for s in ["PASSWORD", "SECRET", "PWD", "TOKEN"]
|
763
|
+
for s in ["PASSWORD", "SECRET", "PWD", "TOKEN", "KEY"]
|
677
764
|
):
|
678
765
|
return True
|
679
766
|
else:
|
@@ -7,7 +7,7 @@ write_log(){
|
|
7
7
|
|
8
8
|
# Variables to be filled within fractal-server
|
9
9
|
PACKAGE_ENV_DIR=__PACKAGE_ENV_DIR__
|
10
|
-
INSTALL_STRING=__INSTALL_STRING__
|
10
|
+
INSTALL_STRING="__INSTALL_STRING__"
|
11
11
|
PINNED_PACKAGE_LIST="__PINNED_PACKAGE_LIST__"
|
12
12
|
FRACTAL_MAX_PIP_VERSION="__FRACTAL_MAX_PIP_VERSION__"
|
13
13
|
FRACTAL_PIP_CACHE_DIR_ARG="__FRACTAL_PIP_CACHE_DIR_ARG__"
|
fractal_server/urls.py
CHANGED
@@ -2,12 +2,13 @@ from os.path import normpath
|
|
2
2
|
|
3
3
|
|
4
4
|
def normalize_url(url: str) -> str:
|
5
|
+
url = url.strip()
|
5
6
|
if url.startswith("/"):
|
6
7
|
return normpath(url)
|
7
8
|
elif url.startswith("s3"):
|
8
9
|
# It would be better to have a NotImplementedError
|
9
10
|
# but Pydantic Validation + FastAPI require
|
10
11
|
# ValueError, TypeError or AssertionError
|
11
|
-
raise ValueError("S3 handling not implemented yet")
|
12
|
+
raise ValueError("S3 handling not implemented yet.")
|
12
13
|
else:
|
13
14
|
raise ValueError("URLs must begin with '/' or 's3'.")
|
@@ -1,12 +1,12 @@
|
|
1
|
-
Metadata-Version: 2.
|
1
|
+
Metadata-Version: 2.3
|
2
2
|
Name: fractal-server
|
3
|
-
Version: 2.10.
|
4
|
-
Summary:
|
3
|
+
Version: 2.10.4
|
4
|
+
Summary: Backend component of the Fractal analytics platform
|
5
5
|
Home-page: https://github.com/fractal-analytics-platform/fractal-server
|
6
6
|
License: BSD-3-Clause
|
7
7
|
Author: Tommaso Comparin
|
8
8
|
Author-email: tommaso.comparin@exact-lab.it
|
9
|
-
Requires-Python: >=3.10,<
|
9
|
+
Requires-Python: >=3.10,<3.13
|
10
10
|
Classifier: License :: OSI Approved :: BSD License
|
11
11
|
Classifier: Programming Language :: Python :: 3
|
12
12
|
Classifier: Programming Language :: Python :: 3.10
|
@@ -14,23 +14,24 @@ Classifier: Programming Language :: Python :: 3.11
|
|
14
14
|
Classifier: Programming Language :: Python :: 3.12
|
15
15
|
Requires-Dist: alembic (>=1.13.1,<2.0.0)
|
16
16
|
Requires-Dist: cloudpickle (>=3.0.0,<3.1.0)
|
17
|
-
Requires-Dist: clusterfutures (
|
18
|
-
Requires-Dist:
|
17
|
+
Requires-Dist: clusterfutures (==0.5)
|
18
|
+
Requires-Dist: cryptography (>=44.0.0,<44.1.0)
|
19
|
+
Requires-Dist: fabric (>=3.2.2,<3.3.0)
|
19
20
|
Requires-Dist: fastapi (>=0.115.0,<0.116.0)
|
20
21
|
Requires-Dist: fastapi-users[oauth] (>=14,<15)
|
21
22
|
Requires-Dist: gunicorn (>=21.2,<23.0)
|
22
|
-
Requires-Dist: packaging (>=23.2,<24.0)
|
23
|
-
Requires-Dist: psutil (
|
23
|
+
Requires-Dist: packaging (>=23.2.0,<24.0.0)
|
24
|
+
Requires-Dist: psutil (==5.9.8)
|
24
25
|
Requires-Dist: psycopg[binary] (>=3.1.0,<4.0.0)
|
25
26
|
Requires-Dist: pydantic (>=1.10.8,<2)
|
26
|
-
Requires-Dist: python-dotenv (>=1.0.0,<
|
27
|
+
Requires-Dist: python-dotenv (>=1.0.0,<1.1.0)
|
27
28
|
Requires-Dist: sqlalchemy[asyncio] (>=2.0.23,<2.1)
|
28
|
-
Requires-Dist: sqlmodel (
|
29
|
-
Requires-Dist: uvicorn (
|
30
|
-
Requires-Dist: uvicorn-worker (
|
31
|
-
Project-URL: Changelog, https://github.com/fractal-analytics-platform/fractal-server/blob/main/CHANGELOG.md
|
29
|
+
Requires-Dist: sqlmodel (==0.0.21)
|
30
|
+
Requires-Dist: uvicorn (==0.29.0)
|
31
|
+
Requires-Dist: uvicorn-worker (==0.2.0)
|
32
32
|
Project-URL: Documentation, https://fractal-analytics-platform.github.io/fractal-server
|
33
33
|
Project-URL: Repository, https://github.com/fractal-analytics-platform/fractal-server
|
34
|
+
Project-URL: changelog, https://github.com/fractal-analytics-platform/fractal-server/blob/main/CHANGELOG.md
|
34
35
|
Description-Content-Type: text/markdown
|
35
36
|
|
36
37
|
# Fractal Server
|
@@ -1,5 +1,5 @@
|
|
1
|
-
fractal_server/__init__.py,sha256=
|
2
|
-
fractal_server/__main__.py,sha256=
|
1
|
+
fractal_server/__init__.py,sha256=SpR6dFPN1o2qOtKLrw5k3LkAdAJmWRd66Z2nXQfCN_4,23
|
2
|
+
fractal_server/__main__.py,sha256=D2YTmSowmXNyvqOjW_HeItCZT2UliWlySl_owicaZg0,8026
|
3
3
|
fractal_server/alembic.ini,sha256=MWwi7GzjzawI9cCAK1LW7NxIBQDUqD12-ptJoq5JpP0,3153
|
4
4
|
fractal_server/app/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
5
5
|
fractal_server/app/db/__init__.py,sha256=wup2wcOkyOh8Vd0Xm76PZn_naxeMqaL4eF8DHHXTGlI,2889
|
@@ -53,13 +53,13 @@ fractal_server/app/routes/api/v2/project.py,sha256=eWYFJ7F2ZYQcpi-_n-rhPF-Q4gJhz
|
|
53
53
|
fractal_server/app/routes/api/v2/status.py,sha256=6N9DSZ4iFqbZImorWfEAPoyoFUgEruo4Hweqo0x0xXU,6435
|
54
54
|
fractal_server/app/routes/api/v2/submit.py,sha256=cQwt0oK8xjHMGA_bQrw4Um8jd_aCvgmWfoqSQDh12hQ,8246
|
55
55
|
fractal_server/app/routes/api/v2/task.py,sha256=K0ik33t7vL8BAK5S7fqyJDNdRK4stGqb_73bSa8tvPE,7159
|
56
|
-
fractal_server/app/routes/api/v2/task_collection.py,sha256=
|
56
|
+
fractal_server/app/routes/api/v2/task_collection.py,sha256=9p8w9UnN6RFszC1ohy9Uo3I4HIMVdfD8fYGWuQqzxMU,12682
|
57
57
|
fractal_server/app/routes/api/v2/task_collection_custom.py,sha256=cctW61-C2QYF2KXluS15lLhZJS_kt30Ca6UGLFO32z0,6207
|
58
58
|
fractal_server/app/routes/api/v2/task_group.py,sha256=4o2N0z7jK7VUVlJZMM4GveCCc4JKxYJx9-PMmsYIlJQ,8256
|
59
59
|
fractal_server/app/routes/api/v2/task_group_lifecycle.py,sha256=3o9bCC8ubMwffQPPaxQZy-CjH9IB2RkIReIecI6L2_w,9300
|
60
60
|
fractal_server/app/routes/api/v2/workflow.py,sha256=vjCNRzMHaAB4YWbAEWGlELHXDN4GjtE26IkIiB15RGM,8682
|
61
61
|
fractal_server/app/routes/api/v2/workflow_import.py,sha256=-7Er3FWGF_1xI2qHFO9gfLVQAok5bojd7mbzQxa9Ofw,10858
|
62
|
-
fractal_server/app/routes/api/v2/workflowtask.py,sha256=
|
62
|
+
fractal_server/app/routes/api/v2/workflowtask.py,sha256=dh8IxFSx50dY7kXldr9vC_NdQrFqv_heefOuZBX-7XE,10714
|
63
63
|
fractal_server/app/routes/auth/__init__.py,sha256=fao6CS0WiAjHDTvBzgBVV_bSXFpEAeDBF6Z6q7rRkPc,1658
|
64
64
|
fractal_server/app/routes/auth/_aux_auth.py,sha256=ifkNocTYatBSMYGwiR14qohmvR9SfMldceiEj6uJBrU,4783
|
65
65
|
fractal_server/app/routes/auth/current_user.py,sha256=I3aVY5etWAJ_SH6t65Mj5TjvB2X8sAGuu1KG7FxLyPU,5883
|
@@ -73,7 +73,6 @@ fractal_server/app/routes/aux/__init__.py,sha256=LR4bR7RunHAK6jc9IR2bReQd-BdXADd
|
|
73
73
|
fractal_server/app/routes/aux/_job.py,sha256=q-RCiW17yXnZKAC_0La52RLvhqhxuvbgQJ2MlGXOj8A,702
|
74
74
|
fractal_server/app/routes/aux/_runner.py,sha256=FdCVla5DxGAZ__aB7Z8dEJzD_RIeh5tftjrPyqkr8N8,895
|
75
75
|
fractal_server/app/routes/aux/validate_user_settings.py,sha256=Y8eubau0julkwVYB5nA83nDtxh_7RU9Iq0zAhb_dXLA,2351
|
76
|
-
fractal_server/app/runner/.gitignore,sha256=ytzN_oyHWXrGU7iFAtoHSTUbM6Rn6kG0Zkddg0xZk6s,16
|
77
76
|
fractal_server/app/runner/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
78
77
|
fractal_server/app/runner/async_wrap.py,sha256=_O6f8jftKYXG_DozkmlrDBhoiK9QhE9MablOyECq2_M,829
|
79
78
|
fractal_server/app/runner/components.py,sha256=ZF8ct_Ky5k8IAcrmpYOZ-bc6OBgdELEighYVqFDEbZg,119
|
@@ -161,9 +160,10 @@ fractal_server/app/schemas/v2/task_collection.py,sha256=9c_yyFcVBXdAZpQQniy1bROh
|
|
161
160
|
fractal_server/app/schemas/v2/task_group.py,sha256=EPQ1WHjIA8WDrpsTfvfRESjwUVzu6jKiaKZx45b36N4,3215
|
162
161
|
fractal_server/app/schemas/v2/workflow.py,sha256=-KWvXnbHBFA3pj5n7mfSyLKJQSqkJmoziIEe7mpLl3M,1875
|
163
162
|
fractal_server/app/schemas/v2/workflowtask.py,sha256=FthKErVgx3a-k7WVk3nqJe1G-fl_iHND4rVrDXJ0F84,5942
|
164
|
-
fractal_server/app/security/__init__.py,sha256=
|
163
|
+
fractal_server/app/security/__init__.py,sha256=UmFnFFGM9WB_7b0itBi0b9uOIUWx_tcA2rCRaTNXErU,13778
|
164
|
+
fractal_server/app/security/signup_email.py,sha256=hzzHxoEizl6IPVeB0j9Ek_tKIalGRxH6npzWUyGkCc4,1164
|
165
165
|
fractal_server/app/user_settings.py,sha256=OP1yiYKtPadxwM51_Q0hdPk3z90TCN4z1BLpQsXyWiU,1316
|
166
|
-
fractal_server/config.py,sha256=
|
166
|
+
fractal_server/config.py,sha256=9rAzw7OO6ZeHEz-I8NJHuGoHf4xCHxfFLyRNZQD9ytY,27019
|
167
167
|
fractal_server/data_migrations/README.md,sha256=_3AEFvDg9YkybDqCLlFPdDmGJvr6Tw7HRI14aZ3LOIw,398
|
168
168
|
fractal_server/data_migrations/tools.py,sha256=LeMeASwYGtEqd-3wOLle6WARdTGAimoyMmRbbJl-hAM,572
|
169
169
|
fractal_server/gunicorn_fractal.py,sha256=u6U01TLGlXgq1v8QmEpLih3QnsInZD7CqphgJ_GrGzc,1230
|
@@ -172,10 +172,8 @@ fractal_server/images/models.py,sha256=UlWazUOFQtpS3pZuROjcJXviG_Ai453jqUDHdzuvD
|
|
172
172
|
fractal_server/images/tools.py,sha256=gxeniYy4Z-cp_ToK2LHPJUTVVUUrdpogYdcBUvBuLiY,2209
|
173
173
|
fractal_server/logger.py,sha256=zwg_AjIHkNP0ruciXjm5lI5UFP3n6tMHullsM9lDjz4,5039
|
174
174
|
fractal_server/main.py,sha256=gStLT9Du5QMpc9SyvRvtKU21EKwp-dG4HL3zGHzE06A,4908
|
175
|
-
fractal_server/migrations/README,sha256=4rQvyDfqodGhpJw74VYijRmgFP49ji5chyEemWGHsuw,59
|
176
175
|
fractal_server/migrations/env.py,sha256=9t_OeKVlhM8WRcukmTrLbWNup-imiBGP_9xNgwCbtpI,2730
|
177
176
|
fractal_server/migrations/naming_convention.py,sha256=htbKrVdetx3pklowb_9Cdo5RqeF0fJ740DNecY5de_M,265
|
178
|
-
fractal_server/migrations/script.py.mako,sha256=oMXw9LC3zRbinWWPPDgeZ4z9FJrV2zhRWiYdS5YgNbI,526
|
179
177
|
fractal_server/migrations/versions/034a469ec2eb_task_groups.py,sha256=vrPhC8hfFu1c4HmLHNZyCuqEfecFD8-bWc49bXMNes0,6199
|
180
178
|
fractal_server/migrations/versions/091b01f51f88_add_usergroup_and_linkusergroup_table.py,sha256=-BSS9AFTPcu3gYC-sYbawSy4MWQQx8TfMb5BW5EBKmQ,1450
|
181
179
|
fractal_server/migrations/versions/19eca0dd47a9_user_settings_project_dir.py,sha256=Q1Gj1cJ0UrdLBJ5AXfFK9QpxTtmcv-4Z3NEGDnxOme4,961
|
@@ -227,7 +225,7 @@ fractal_server/tasks/v2/ssh/collect.py,sha256=2XXEPpl4LS22A75v_k4Bd46k46tmnLNZfc
|
|
227
225
|
fractal_server/tasks/v2/ssh/deactivate.py,sha256=D8rfnC46davmDKZCipPdWZHDD4TIZ-4nr9vxZSV2aC0,11261
|
228
226
|
fractal_server/tasks/v2/ssh/reactivate.py,sha256=cmdT2P1J0FwS1NYYRrhxHsSRyUZ5uu78hS3fDrSVbKo,7837
|
229
227
|
fractal_server/tasks/v2/templates/1_create_venv.sh,sha256=PK0jdHKtQpda1zULebBaVPORt4t6V17wa4N1ohcj5ac,548
|
230
|
-
fractal_server/tasks/v2/templates/2_pip_install.sh,sha256=
|
228
|
+
fractal_server/tasks/v2/templates/2_pip_install.sh,sha256=Gpk2io8u9YaflFUlQu2NgkDQw5AA4m4AOVG1sB4yrHQ,1822
|
231
229
|
fractal_server/tasks/v2/templates/3_pip_freeze.sh,sha256=JldREScEBI4cD_qjfX4UK7V4aI-FnX9ZvVNxgpSOBFc,168
|
232
230
|
fractal_server/tasks/v2/templates/4_pip_show.sh,sha256=84NGHlg6JIbrQktgGKyfGsggPFzy6RBJuOmIpPUhsrw,1747
|
233
231
|
fractal_server/tasks/v2/templates/5_get_venv_size_and_file_number.sh,sha256=q-6ZUvA6w6FDVEoSd9O63LaJ9tKZc7qAFH72SGPrd_k,284
|
@@ -237,11 +235,11 @@ fractal_server/tasks/v2/utils_database.py,sha256=g5m3sNPZKQ3AjflhPURDlAppQcIS5T1
|
|
237
235
|
fractal_server/tasks/v2/utils_package_names.py,sha256=RDg__xrvQs4ieeVzmVdMcEh95vGQYrv9Hfal-5EDBM8,2393
|
238
236
|
fractal_server/tasks/v2/utils_python_interpreter.py,sha256=5_wrlrTqXyo1YuLZvAW9hrSoh5MyLOzdPVUlUwM7uDQ,955
|
239
237
|
fractal_server/tasks/v2/utils_templates.py,sha256=07TZpJ0Mh_A4lXVXrrH2o1VLFFGwxeRumA6DdgMgCWk,2947
|
240
|
-
fractal_server/urls.py,sha256=
|
238
|
+
fractal_server/urls.py,sha256=QjIKAC1a46bCdiPMu3AlpgFbcv6a4l3ABcd5xz190Og,471
|
241
239
|
fractal_server/utils.py,sha256=utvmBx8K9I8hRWFquxna2pBaOqe0JifDL_NVPmihEJI,3525
|
242
240
|
fractal_server/zip_tools.py,sha256=GjDgo_sf6V_DDg6wWeBlZu5zypIxycn_l257p_YVKGc,4876
|
243
|
-
fractal_server-2.10.
|
244
|
-
fractal_server-2.10.
|
245
|
-
fractal_server-2.10.
|
246
|
-
fractal_server-2.10.
|
247
|
-
fractal_server-2.10.
|
241
|
+
fractal_server-2.10.4.dist-info/LICENSE,sha256=QKAharUuhxL58kSoLizKJeZE3mTCBnX6ucmz8W0lxlk,1576
|
242
|
+
fractal_server-2.10.4.dist-info/METADATA,sha256=oEdEOyPOLPqYkCxgyXF1S_RKX5k4PGQWC7ZpwBmikU0,4562
|
243
|
+
fractal_server-2.10.4.dist-info/WHEEL,sha256=RaoafKOydTQ7I_I3JTrPCg6kUmTgtm4BornzOqyEfJ8,88
|
244
|
+
fractal_server-2.10.4.dist-info/entry_points.txt,sha256=8tV2kynvFkjnhbtDnxAqImL6HMVKsopgGfew0DOp5UY,58
|
245
|
+
fractal_server-2.10.4.dist-info/RECORD,,
|
fractal_server/migrations/README
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
Generic single-database configuration with an async dbapi.
|
@@ -1,25 +0,0 @@
|
|
1
|
-
"""${message}
|
2
|
-
|
3
|
-
Revision ID: ${up_revision}
|
4
|
-
Revises: ${down_revision | comma,n}
|
5
|
-
Create Date: ${create_date}
|
6
|
-
|
7
|
-
"""
|
8
|
-
from alembic import op
|
9
|
-
import sqlalchemy as sa
|
10
|
-
import sqlmodel
|
11
|
-
${imports if imports else ""}
|
12
|
-
|
13
|
-
# revision identifiers, used by Alembic.
|
14
|
-
revision = ${repr(up_revision)}
|
15
|
-
down_revision = ${repr(down_revision)}
|
16
|
-
branch_labels = ${repr(branch_labels)}
|
17
|
-
depends_on = ${repr(depends_on)}
|
18
|
-
|
19
|
-
|
20
|
-
def upgrade() -> None:
|
21
|
-
${upgrades if upgrades else "pass"}
|
22
|
-
|
23
|
-
|
24
|
-
def downgrade() -> None:
|
25
|
-
${downgrades if downgrades else "pass"}
|
File without changes
|
File without changes
|