fractal-server 2.7.1__py3-none-any.whl → 2.8.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 (34) hide show
  1. fractal_server/__init__.py +1 -1
  2. fractal_server/app/models/user_settings.py +1 -0
  3. fractal_server/app/models/v2/task.py +15 -0
  4. fractal_server/app/routes/api/v2/dataset.py +39 -6
  5. fractal_server/app/routes/api/v2/task.py +2 -5
  6. fractal_server/app/routes/api/v2/task_collection.py +14 -42
  7. fractal_server/app/routes/api/v2/task_collection_custom.py +3 -3
  8. fractal_server/app/schemas/user_settings.py +18 -0
  9. fractal_server/app/schemas/v2/dataset.py +5 -3
  10. fractal_server/app/schemas/v2/task_collection.py +20 -4
  11. fractal_server/migrations/versions/19eca0dd47a9_user_settings_project_dir.py +39 -0
  12. fractal_server/tasks/utils.py +0 -31
  13. fractal_server/tasks/v1/background_operations.py +11 -11
  14. fractal_server/tasks/v1/endpoint_operations.py +5 -5
  15. fractal_server/tasks/v1/utils.py +2 -2
  16. fractal_server/tasks/v2/collection_local.py +357 -0
  17. fractal_server/tasks/v2/{background_operations_ssh.py → collection_ssh.py} +108 -102
  18. fractal_server/tasks/v2/templates/_1_create_venv.sh +0 -8
  19. fractal_server/tasks/v2/templates/_2_preliminary_pip_operations.sh +2 -2
  20. fractal_server/tasks/v2/templates/_3_pip_install.sh +22 -1
  21. fractal_server/tasks/v2/templates/_5_pip_show.sh +5 -5
  22. fractal_server/tasks/v2/utils_background.py +209 -0
  23. fractal_server/tasks/v2/utils_package_names.py +77 -0
  24. fractal_server/tasks/v2/{utils.py → utils_python_interpreter.py} +0 -26
  25. fractal_server/tasks/v2/utils_templates.py +59 -0
  26. fractal_server/utils.py +48 -3
  27. {fractal_server-2.7.1.dist-info → fractal_server-2.8.0.dist-info}/METADATA +11 -8
  28. {fractal_server-2.7.1.dist-info → fractal_server-2.8.0.dist-info}/RECORD +32 -29
  29. fractal_server/tasks/v2/_venv_pip.py +0 -198
  30. fractal_server/tasks/v2/background_operations.py +0 -456
  31. /fractal_server/{tasks/v2/endpoint_operations.py → app/routes/api/v2/_aux_functions_task_collection.py} +0 -0
  32. {fractal_server-2.7.1.dist-info → fractal_server-2.8.0.dist-info}/LICENSE +0 -0
  33. {fractal_server-2.7.1.dist-info → fractal_server-2.8.0.dist-info}/WHEEL +0 -0
  34. {fractal_server-2.7.1.dist-info → fractal_server-2.8.0.dist-info}/entry_points.txt +0 -0
@@ -1 +1 @@
1
- __VERSION__ = "2.7.1"
1
+ __VERSION__ = "2.8.0"
@@ -36,3 +36,4 @@ class UserSettings(SQLModel, table=True):
36
36
  ssh_jobs_dir: Optional[str] = None
37
37
  slurm_user: Optional[str] = None
38
38
  cache_dir: Optional[str] = None
39
+ project_dir: Optional[str] = None
@@ -103,3 +103,18 @@ class TaskGroupV2(SQLModel, table=True):
103
103
  f"{self.pkg_name=}, {self.wheel_path=}, {self.version=}."
104
104
  )
105
105
  return f"{self.pkg_name}{extras}=={self.version}"
106
+
107
+ @property
108
+ def pinned_package_versions_string(self) -> str:
109
+ """
110
+ Prepare string to be used in `python -m pip install`.
111
+ """
112
+ if self.pinned_package_versions is None:
113
+ return ""
114
+ output = " ".join(
115
+ [
116
+ f"{key}=={value}"
117
+ for key, value in self.pinned_package_versions.items()
118
+ ]
119
+ )
120
+ return output
@@ -22,6 +22,8 @@ from ._aux_functions import _get_project_check_owner
22
22
  from ._aux_functions import _get_submitted_jobs_statement
23
23
  from fractal_server.app.models import UserOAuth
24
24
  from fractal_server.app.routes.auth import current_active_user
25
+ from fractal_server.string_tools import sanitize_string
26
+ from fractal_server.urls import normalize_url
25
27
 
26
28
  router = APIRouter()
27
29
 
@@ -40,14 +42,45 @@ async def create_dataset(
40
42
  """
41
43
  Add new dataset to current project
42
44
  """
43
- await _get_project_check_owner(
45
+ project = await _get_project_check_owner(
44
46
  project_id=project_id, user_id=user.id, db=db
45
47
  )
46
- db_dataset = DatasetV2(project_id=project_id, **dataset.dict())
47
- db.add(db_dataset)
48
- await db.commit()
49
- await db.refresh(db_dataset)
50
- await db.close()
48
+
49
+ if dataset.zarr_dir is None:
50
+
51
+ if user.settings.project_dir is None:
52
+ raise HTTPException(
53
+ status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
54
+ detail=(
55
+ "Both 'dataset.zarr_dir' and 'user.settings.project_dir' "
56
+ "are null"
57
+ ),
58
+ )
59
+
60
+ db_dataset = DatasetV2(
61
+ project_id=project_id,
62
+ zarr_dir="__PLACEHOLDER__",
63
+ **dataset.dict(exclude={"zarr_dir"}),
64
+ )
65
+ db.add(db_dataset)
66
+ await db.commit()
67
+ await db.refresh(db_dataset)
68
+ path = (
69
+ f"{user.settings.project_dir}/fractal/"
70
+ f"{project_id}_{sanitize_string(project.name)}/"
71
+ f"{db_dataset.id}_{sanitize_string(db_dataset.name)}"
72
+ )
73
+ normalized_path = normalize_url(path)
74
+ db_dataset.zarr_dir = normalized_path
75
+
76
+ db.add(db_dataset)
77
+ await db.commit()
78
+ await db.refresh(db_dataset)
79
+ else:
80
+ db_dataset = DatasetV2(project_id=project_id, **dataset.dict())
81
+ db.add(db_dataset)
82
+ await db.commit()
83
+ await db.refresh(db_dataset)
51
84
 
52
85
  return db_dataset
53
86
 
@@ -36,8 +36,7 @@ logger = set_logger(__name__)
36
36
 
37
37
  @router.get("/", response_model=list[TaskReadV2])
38
38
  async def get_list_task(
39
- args_schema_parallel: bool = True,
40
- args_schema_non_parallel: bool = True,
39
+ args_schema: bool = True,
41
40
  category: Optional[str] = None,
42
41
  modality: Optional[str] = None,
43
42
  author: Optional[str] = None,
@@ -72,11 +71,9 @@ async def get_list_task(
72
71
  res = await db.execute(stm)
73
72
  task_list = res.scalars().all()
74
73
  await db.close()
75
- if args_schema_parallel is False:
74
+ if args_schema is False:
76
75
  for task in task_list:
77
76
  setattr(task, "args_schema_parallel", None)
78
- if args_schema_non_parallel is False:
79
- for task in task_list:
80
77
  setattr(task, "args_schema_non_parallel", None)
81
78
 
82
79
  return task_list
@@ -24,6 +24,7 @@ from ....schemas.v2 import CollectionStatusV2
24
24
  from ....schemas.v2 import TaskCollectPipV2
25
25
  from ....schemas.v2 import TaskGroupCreateV2
26
26
  from ...aux.validate_user_settings import validate_user_settings
27
+ from ._aux_functions_task_collection import get_package_version_from_pypi
27
28
  from ._aux_functions_tasks import _get_valid_user_group_id
28
29
  from ._aux_functions_tasks import _verify_non_duplication_group_constraint
29
30
  from ._aux_functions_tasks import _verify_non_duplication_user_constraint
@@ -31,16 +32,14 @@ from fractal_server.app.models import UserOAuth
31
32
  from fractal_server.app.routes.auth import current_active_user
32
33
  from fractal_server.app.routes.auth import current_active_verified_user
33
34
  from fractal_server.app.schemas.v2 import TaskGroupV2OriginEnum
34
- from fractal_server.tasks.utils import _normalize_package_name
35
- from fractal_server.tasks.utils import get_collection_log_v2
36
- from fractal_server.tasks.v2.background_operations import (
37
- background_collect_pip,
35
+ from fractal_server.tasks.v2.collection_local import (
36
+ collect_package_local,
38
37
  )
39
- from fractal_server.tasks.v2.endpoint_operations import (
40
- get_package_version_from_pypi,
38
+ from fractal_server.tasks.v2.utils_package_names import _parse_wheel_filename
39
+ from fractal_server.tasks.v2.utils_package_names import normalize_package_name
40
+ from fractal_server.tasks.v2.utils_python_interpreter import (
41
+ get_python_interpreter_v2,
41
42
  )
42
- from fractal_server.tasks.v2.utils import _parse_wheel_filename
43
- from fractal_server.tasks.v2.utils import get_python_interpreter_v2
44
43
 
45
44
  router = APIRouter()
46
45
 
@@ -118,14 +117,14 @@ async def collect_tasks_pip(
118
117
  f"Original error: {str(e)}",
119
118
  ),
120
119
  )
121
- task_group_attrs["pkg_name"] = _normalize_package_name(
120
+ task_group_attrs["pkg_name"] = normalize_package_name(
122
121
  wheel_info["distribution"]
123
122
  )
124
123
  task_group_attrs["version"] = wheel_info["version"]
125
124
  task_group_attrs["origin"] = TaskGroupV2OriginEnum.WHEELFILE
126
125
  else:
127
126
  pkg_name = task_collect.package
128
- task_group_attrs["pkg_name"] = _normalize_package_name(pkg_name)
127
+ task_group_attrs["pkg_name"] = normalize_package_name(pkg_name)
129
128
  task_group_attrs["origin"] = TaskGroupV2OriginEnum.PYPI
130
129
  latest_version = await get_package_version_from_pypi(
131
130
  task_collect.package,
@@ -249,8 +248,8 @@ async def collect_tasks_pip(
249
248
  if settings.FRACTAL_RUNNER_BACKEND == "slurm_ssh":
250
249
  # SSH task collection
251
250
 
252
- from fractal_server.tasks.v2.background_operations_ssh import (
253
- background_collect_pip_ssh,
251
+ from fractal_server.tasks.v2.collection_ssh import (
252
+ collect_package_ssh,
254
253
  )
255
254
 
256
255
  # User appropriate FractalSSH object
@@ -263,7 +262,7 @@ async def collect_tasks_pip(
263
262
  fractal_ssh = fractal_ssh_list.get(**ssh_credentials)
264
263
 
265
264
  background_tasks.add_task(
266
- background_collect_pip_ssh,
265
+ collect_package_ssh,
267
266
  state_id=state.id,
268
267
  task_group=task_group,
269
268
  fractal_ssh=fractal_ssh,
@@ -273,7 +272,7 @@ async def collect_tasks_pip(
273
272
  else:
274
273
  # Local task collection
275
274
  background_tasks.add_task(
276
- background_collect_pip,
275
+ collect_package_local,
277
276
  state_id=state.id,
278
277
  task_group=task_group,
279
278
  )
@@ -296,42 +295,15 @@ async def collect_tasks_pip(
296
295
  async def check_collection_status(
297
296
  state_id: int,
298
297
  user: UserOAuth = Depends(current_active_user),
299
- verbose: bool = False,
300
298
  db: AsyncSession = Depends(get_async_db),
301
299
  ) -> CollectionStateReadV2: # State[TaskCollectStatus]
302
300
  """
303
301
  Check status of background task collection
304
302
  """
305
-
306
- logger = set_logger(logger_name="check_collection_status")
307
- logger.debug(f"Querying state for state.id={state_id}")
308
303
  state = await db.get(CollectionStateV2, state_id)
309
- if not state:
310
- await db.close()
304
+ if state is None:
311
305
  raise HTTPException(
312
306
  status_code=status.HTTP_404_NOT_FOUND,
313
307
  detail=f"No task collection info with id={state_id}",
314
308
  )
315
-
316
- settings = Inject(get_settings)
317
- if settings.FRACTAL_RUNNER_BACKEND == "slurm_ssh":
318
- # FIXME SSH: add logic for when data.state["log"] is empty
319
- pass
320
- else:
321
- # Non-SSH mode
322
- # In some cases (i.e. a successful or ongoing task collection),
323
- # state.data["log"] is not set; if so, we collect the current logs.
324
- if verbose and not state.data.get("log"):
325
- if "path" not in state.data.keys():
326
- await db.close()
327
- raise HTTPException(
328
- status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
329
- detail=(
330
- f"No 'path' in CollectionStateV2[{state_id}].data"
331
- ),
332
- )
333
- state.data["log"] = get_collection_log_v2(Path(state.data["path"]))
334
-
335
- reset_logger_handlers(logger)
336
- await db.close()
337
309
  return state
@@ -27,12 +27,12 @@ from fractal_server.config import get_settings
27
27
  from fractal_server.logger import set_logger
28
28
  from fractal_server.string_tools import validate_cmd
29
29
  from fractal_server.syringe import Inject
30
- from fractal_server.tasks.v2.background_operations import (
31
- _prepare_tasks_metadata,
32
- )
33
30
  from fractal_server.tasks.v2.database_operations import (
34
31
  create_db_tasks_and_update_task_group,
35
32
  )
33
+ from fractal_server.tasks.v2.utils_background import (
34
+ _prepare_tasks_metadata,
35
+ )
36
36
 
37
37
  router = APIRouter()
38
38
 
@@ -19,6 +19,10 @@ __all__ = (
19
19
 
20
20
 
21
21
  class UserSettingsRead(BaseModel):
22
+ """
23
+ Schema reserved for superusers
24
+ """
25
+
22
26
  id: int
23
27
  ssh_host: Optional[str] = None
24
28
  ssh_username: Optional[str] = None
@@ -28,6 +32,7 @@ class UserSettingsRead(BaseModel):
28
32
  slurm_user: Optional[str] = None
29
33
  slurm_accounts: list[str]
30
34
  cache_dir: Optional[str] = None
35
+ project_dir: Optional[str] = None
31
36
 
32
37
 
33
38
  class UserSettingsReadStrict(BaseModel):
@@ -35,9 +40,14 @@ class UserSettingsReadStrict(BaseModel):
35
40
  slurm_accounts: list[str]
36
41
  cache_dir: Optional[str] = None
37
42
  ssh_username: Optional[str] = None
43
+ project_dir: Optional[str] = None
38
44
 
39
45
 
40
46
  class UserSettingsUpdate(BaseModel, extra=Extra.forbid):
47
+ """
48
+ Schema reserved for superusers
49
+ """
50
+
41
51
  ssh_host: Optional[str] = None
42
52
  ssh_username: Optional[str] = None
43
53
  ssh_private_key_path: Optional[str] = None
@@ -46,6 +56,7 @@ class UserSettingsUpdate(BaseModel, extra=Extra.forbid):
46
56
  slurm_user: Optional[str] = None
47
57
  slurm_accounts: Optional[list[StrictStr]] = None
48
58
  cache_dir: Optional[str] = None
59
+ project_dir: Optional[str] = None
49
60
 
50
61
  _ssh_host = validator("ssh_host", allow_reuse=True)(
51
62
  valstr("ssh_host", accept_none=True)
@@ -83,6 +94,13 @@ class UserSettingsUpdate(BaseModel, extra=Extra.forbid):
83
94
  validate_cmd(value)
84
95
  return val_absolute_path("cache_dir")(value)
85
96
 
97
+ @validator("project_dir")
98
+ def project_dir_validator(cls, value):
99
+ if value is None:
100
+ return None
101
+ validate_cmd(value)
102
+ return val_absolute_path("project_dir")(value)
103
+
86
104
 
87
105
  class UserSettingsUpdateStrict(BaseModel, extra=Extra.forbid):
88
106
  slurm_accounts: Optional[list[StrictStr]] = None
@@ -33,14 +33,16 @@ class DatasetCreateV2(BaseModel, extra=Extra.forbid):
33
33
 
34
34
  name: str
35
35
 
36
- zarr_dir: str
36
+ zarr_dir: Optional[str] = None
37
37
 
38
38
  filters: Filters = Field(default_factory=Filters)
39
39
 
40
40
  # Validators
41
41
  @validator("zarr_dir")
42
42
  def normalize_zarr_dir(cls, v: str) -> str:
43
- return normalize_url(v)
43
+ if v is not None:
44
+ return normalize_url(v)
45
+ return v
44
46
 
45
47
  _name = validator("name", allow_reuse=True)(valstr("name"))
46
48
 
@@ -95,7 +97,7 @@ class DatasetImportV2(BaseModel, extra=Extra.forbid):
95
97
 
96
98
  name: str
97
99
  zarr_dir: str
98
- images: list[SingleImage] = Field(default_factory=[])
100
+ images: list[SingleImage] = Field(default_factory=list)
99
101
  filters: Filters = Field(default_factory=Filters)
100
102
 
101
103
  # Validators
@@ -10,7 +10,6 @@ from pydantic import Extra
10
10
  from pydantic import root_validator
11
11
  from pydantic import validator
12
12
 
13
- from .._validators import valdictkeys
14
13
  from .._validators import valstr
15
14
  from fractal_server.app.schemas._validators import valutc
16
15
  from fractal_server.app.schemas.v2 import ManifestV2
@@ -62,13 +61,30 @@ class TaskCollectPipV2(BaseModel, extra=Extra.forbid):
62
61
  _package_version = validator("package_version", allow_reuse=True)(
63
62
  valstr("package_version")
64
63
  )
65
- _pinned_package_versions = validator(
66
- "pinned_package_versions", allow_reuse=True
67
- )(valdictkeys("pinned_package_versions"))
68
64
  _package_extras = validator("package_extras", allow_reuse=True)(
69
65
  valstr("package_extras")
70
66
  )
71
67
 
68
+ @validator("pinned_package_versions")
69
+ def pinned_package_validator(cls, value):
70
+ if value is None:
71
+ return value
72
+ old_keys = list(value.keys())
73
+ new_keys = [
74
+ valstr(f"pinned_package_versions[{key}]")(key) for key in old_keys
75
+ ]
76
+ if len(new_keys) != len(set(new_keys)):
77
+ raise ValueError(
78
+ f"Dictionary contains multiple identical keys: {value}."
79
+ )
80
+ for old_key, new_key in zip(old_keys, new_keys):
81
+ if new_key != old_key:
82
+ value[new_key] = value.pop(old_key)
83
+ for pkg, version in value.items():
84
+ validate_cmd(pkg)
85
+ validate_cmd(version)
86
+ return value
87
+
72
88
  @validator("package")
73
89
  def package_validator(cls, value):
74
90
  if "/" in value or value.endswith(".whl"):
@@ -0,0 +1,39 @@
1
+ """user settings project dir
2
+
3
+ Revision ID: 19eca0dd47a9
4
+ Revises: 8e8f227a3e36
5
+ Create Date: 2024-10-30 14:34:28.219355
6
+
7
+ """
8
+ import sqlalchemy as sa
9
+ import sqlmodel
10
+ from alembic import op
11
+
12
+
13
+ # revision identifiers, used by Alembic.
14
+ revision = "19eca0dd47a9"
15
+ down_revision = "8e8f227a3e36"
16
+ branch_labels = None
17
+ depends_on = None
18
+
19
+
20
+ def upgrade() -> None:
21
+ # ### commands auto generated by Alembic - please adjust! ###
22
+ with op.batch_alter_table("user_settings", schema=None) as batch_op:
23
+ batch_op.add_column(
24
+ sa.Column(
25
+ "project_dir",
26
+ sqlmodel.sql.sqltypes.AutoString(),
27
+ nullable=True,
28
+ )
29
+ )
30
+
31
+ # ### end Alembic commands ###
32
+
33
+
34
+ def downgrade() -> None:
35
+ # ### commands auto generated by Alembic - please adjust! ###
36
+ with op.batch_alter_table("user_settings", schema=None) as batch_op:
37
+ batch_op.drop_column("project_dir")
38
+
39
+ # ### end Alembic commands ###
@@ -1,4 +1,3 @@
1
- import re
2
1
  from pathlib import Path
3
2
 
4
3
  from fractal_server.config import get_settings
@@ -42,38 +41,8 @@ def get_collection_log_v1(path: Path) -> str:
42
41
  return log
43
42
 
44
43
 
45
- def get_collection_log_v2(path: Path) -> str:
46
- log_path = get_log_path(path)
47
- log = log_path.open().read()
48
- return log
49
-
50
-
51
44
  def get_collection_freeze_v1(venv_path: Path) -> str:
52
45
  package_path = get_absolute_venv_path_v1(venv_path)
53
46
  freeze_path = get_freeze_path(package_path)
54
47
  freeze = freeze_path.open().read()
55
48
  return freeze
56
-
57
-
58
- def get_collection_freeze_v2(path: Path) -> str:
59
- freeze_path = get_freeze_path(path)
60
- freeze = freeze_path.open().read()
61
- return freeze
62
-
63
-
64
- def _normalize_package_name(name: str) -> str:
65
- """
66
- Implement PyPa specifications for package-name normalization
67
-
68
- The name should be lowercased with all runs of the characters `.`, `-`,
69
- or `_` replaced with a single `-` character. This can be implemented in
70
- Python with the re module.
71
- (https://packaging.python.org/en/latest/specifications/name-normalization)
72
-
73
- Args:
74
- name: The non-normalized package name.
75
-
76
- Returns:
77
- The normalized package name.
78
- """
79
- return re.sub(r"[-_.]+", "-", name).lower()
@@ -7,10 +7,10 @@ from pathlib import Path
7
7
  from shutil import rmtree as shell_rmtree
8
8
 
9
9
  from ...string_tools import slugify_task_name_for_source_v1
10
- from ..utils import _normalize_package_name
11
10
  from ..utils import get_collection_log_v1
12
11
  from ..utils import get_collection_path
13
12
  from ..utils import get_log_path
13
+ from ..v2.utils_package_names import normalize_package_name
14
14
  from ._TaskCollectPip import _TaskCollectPip
15
15
  from .utils import _init_venv_v1
16
16
  from fractal_server.app.db import DBSyncSession
@@ -23,7 +23,7 @@ from fractal_server.app.schemas.v1 import TaskReadV1
23
23
  from fractal_server.logger import close_logger
24
24
  from fractal_server.logger import get_logger
25
25
  from fractal_server.logger import set_logger
26
- from fractal_server.utils import execute_command
26
+ from fractal_server.utils import execute_command_async
27
27
 
28
28
 
29
29
  async def _pip_install(
@@ -60,12 +60,12 @@ async def _pip_install(
60
60
  cmd_install = f"{pip} install {pip_install_str}"
61
61
  cmd_inspect = f"{pip} show {task_pkg.package}"
62
62
 
63
- await execute_command(
63
+ await execute_command_async(
64
64
  cwd=venv_path,
65
65
  command=f"{pip} install --upgrade pip",
66
66
  logger_name=logger_name,
67
67
  )
68
- await execute_command(
68
+ await execute_command_async(
69
69
  cwd=venv_path, command=cmd_install, logger_name=logger_name
70
70
  )
71
71
  if task_pkg.pinned_package_versions:
@@ -82,7 +82,7 @@ async def _pip_install(
82
82
  "Preliminary check: verify that "
83
83
  f"{pinned_pkg_version} is already installed"
84
84
  )
85
- stdout_inspect = await execute_command(
85
+ stdout_inspect = await execute_command_async(
86
86
  cwd=venv_path,
87
87
  command=f"{pip} show {pinned_pkg_name}",
88
88
  logger_name=logger_name,
@@ -99,7 +99,7 @@ async def _pip_install(
99
99
  f"({pinned_pkg_version}); "
100
100
  f"install version {pinned_pkg_version}."
101
101
  )
102
- await execute_command(
102
+ await execute_command_async(
103
103
  cwd=venv_path,
104
104
  command=(
105
105
  f"{pip} install "
@@ -114,7 +114,7 @@ async def _pip_install(
114
114
  )
115
115
 
116
116
  # Extract package installation path from `pip show`
117
- stdout_inspect = await execute_command(
117
+ stdout_inspect = await execute_command_async(
118
118
  cwd=venv_path, command=cmd_inspect, logger_name=logger_name
119
119
  )
120
120
 
@@ -165,8 +165,8 @@ async def _create_venv_install_package(
165
165
  """
166
166
 
167
167
  # Normalize package name
168
- task_pkg.package_name = _normalize_package_name(task_pkg.package_name)
169
- task_pkg.package = _normalize_package_name(task_pkg.package)
168
+ task_pkg.package_name = normalize_package_name(task_pkg.package_name)
169
+ task_pkg.package = normalize_package_name(task_pkg.package)
170
170
 
171
171
  python_bin = await _init_venv_v1(
172
172
  path=path,
@@ -192,8 +192,8 @@ async def create_package_environment_pip(
192
192
  logger = get_logger(logger_name)
193
193
 
194
194
  # Normalize package name
195
- task_pkg.package_name = _normalize_package_name(task_pkg.package_name)
196
- task_pkg.package = _normalize_package_name(task_pkg.package)
195
+ task_pkg.package_name = normalize_package_name(task_pkg.package_name)
196
+ task_pkg.package = normalize_package_name(task_pkg.package)
197
197
 
198
198
  # Only proceed if package, version and manifest attributes are set
199
199
  task_pkg.check()
@@ -4,14 +4,14 @@ from typing import Optional
4
4
  from typing import Union
5
5
  from zipfile import ZipFile
6
6
 
7
- from ..utils import _normalize_package_name
7
+ from ..v2.utils_package_names import normalize_package_name
8
8
  from ._TaskCollectPip import _TaskCollectPip as _TaskCollectPipV1
9
9
  from .utils import get_python_interpreter_v1
10
10
  from fractal_server.app.schemas.v1 import ManifestV1
11
11
  from fractal_server.config import get_settings
12
12
  from fractal_server.logger import get_logger
13
13
  from fractal_server.syringe import Inject
14
- from fractal_server.utils import execute_command
14
+ from fractal_server.utils import execute_command_async
15
15
 
16
16
 
17
17
  FRACTAL_PUBLIC_TASK_SUBDIR = ".fractal"
@@ -32,7 +32,7 @@ async def download_package(
32
32
  )
33
33
  package_and_version = f"{task_pkg.package}{version}"
34
34
  cmd = f"{pip} download --no-deps {package_and_version} -d {dest}"
35
- stdout = await execute_command(command=cmd, cwd=Path("."))
35
+ stdout = await execute_command_async(command=cmd, cwd=Path("."))
36
36
  pkg_file = next(
37
37
  line.split()[-1] for line in stdout.split("\n") if "Saved" in line
38
38
  )
@@ -123,7 +123,7 @@ def inspect_package(path: Path, logger_name: Optional[str] = None) -> dict:
123
123
  logger.debug("Package name and version read correctly.")
124
124
 
125
125
  # Normalize package name:
126
- pkg_name = _normalize_package_name(pkg_name)
126
+ pkg_name = normalize_package_name(pkg_name)
127
127
 
128
128
  info = dict(
129
129
  pkg_name=pkg_name,
@@ -148,7 +148,7 @@ def create_package_dir_pip(
148
148
  f"Cannot create venv folder for package `{task_pkg.package}` "
149
149
  "with `version=None`."
150
150
  )
151
- normalized_package = _normalize_package_name(task_pkg.package)
151
+ normalized_package = normalize_package_name(task_pkg.package)
152
152
  package_dir = f"{normalized_package}{task_pkg.package_version}"
153
153
  venv_path = settings.FRACTAL_TASKS_DIR / user / package_dir
154
154
  if create:
@@ -2,7 +2,7 @@ from pathlib import Path
2
2
  from typing import Optional
3
3
 
4
4
  from fractal_server.logger import get_logger
5
- from fractal_server.utils import execute_command
5
+ from fractal_server.utils import execute_command_async
6
6
 
7
7
 
8
8
  def get_python_interpreter_v1(version: Optional[str] = None) -> str:
@@ -57,7 +57,7 @@ async def _init_venv_v1(
57
57
  logger.debug(f"[_init_venv] {path=}")
58
58
  interpreter = get_python_interpreter_v1(version=python_version)
59
59
  logger.debug(f"[_init_venv] {interpreter=}")
60
- await execute_command(
60
+ await execute_command_async(
61
61
  cwd=path,
62
62
  command=f"{interpreter} -m venv venv",
63
63
  logger_name=logger_name,