fractal-server 2.15.0a0__py3-none-any.whl → 2.15.0a2__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 (29) hide show
  1. fractal_server/__init__.py +1 -1
  2. fractal_server/app/routes/api/v2/task_collection_pixi.py +1 -1
  3. fractal_server/app/routes/api/v2/task_group_lifecycle.py +18 -4
  4. fractal_server/ssh/_fabric.py +26 -0
  5. fractal_server/tasks/v2/local/__init__.py +1 -0
  6. fractal_server/tasks/v2/local/collect.py +9 -12
  7. fractal_server/tasks/v2/local/collect_pixi.py +53 -41
  8. fractal_server/tasks/v2/local/deactivate.py +7 -14
  9. fractal_server/tasks/v2/local/deactivate_pixi.py +8 -16
  10. fractal_server/tasks/v2/local/reactivate.py +8 -15
  11. fractal_server/tasks/v2/local/reactivate_pixi.py +166 -0
  12. fractal_server/tasks/v2/ssh/__init__.py +2 -0
  13. fractal_server/tasks/v2/ssh/collect.py +7 -13
  14. fractal_server/tasks/v2/ssh/collect_pixi.py +44 -34
  15. fractal_server/tasks/v2/ssh/deactivate.py +7 -14
  16. fractal_server/tasks/v2/ssh/deactivate_pixi.py +128 -0
  17. fractal_server/tasks/v2/ssh/reactivate.py +7 -14
  18. fractal_server/tasks/v2/ssh/reactivate_pixi.py +108 -0
  19. fractal_server/tasks/v2/templates/pixi_1_extract.sh +40 -0
  20. fractal_server/tasks/v2/templates/pixi_2_install.sh +48 -0
  21. fractal_server/tasks/v2/templates/pixi_3_post_install.sh +80 -0
  22. fractal_server/tasks/v2/utils_background.py +35 -28
  23. fractal_server/tasks/v2/utils_pixi.py +2 -0
  24. {fractal_server-2.15.0a0.dist-info → fractal_server-2.15.0a2.dist-info}/METADATA +1 -1
  25. {fractal_server-2.15.0a0.dist-info → fractal_server-2.15.0a2.dist-info}/RECORD +28 -23
  26. fractal_server/tasks/v2/templates/pixi_1_collect.sh +0 -70
  27. {fractal_server-2.15.0a0.dist-info → fractal_server-2.15.0a2.dist-info}/LICENSE +0 -0
  28. {fractal_server-2.15.0a0.dist-info → fractal_server-2.15.0a2.dist-info}/WHEEL +0 -0
  29. {fractal_server-2.15.0a0.dist-info → fractal_server-2.15.0a2.dist-info}/entry_points.txt +0 -0
@@ -1,17 +1,15 @@
1
- import logging
2
1
  import time
3
2
  from pathlib import Path
4
3
  from tempfile import TemporaryDirectory
5
4
 
6
5
  from ....ssh._fabric import SingleUseFractalSSH
7
6
  from ..utils_background import fail_and_cleanup
7
+ from ..utils_background import get_activity_and_task_group
8
8
  from ..utils_background import prepare_tasks_metadata
9
9
  from ..utils_database import create_db_tasks_and_update_task_group_sync
10
10
  from ..utils_pixi import parse_collect_stdout
11
11
  from ..utils_pixi import SOURCE_DIR_NAME
12
12
  from fractal_server.app.db import get_sync_db
13
- from fractal_server.app.models.v2 import TaskGroupActivityV2
14
- from fractal_server.app.models.v2 import TaskGroupV2
15
13
  from fractal_server.app.schemas.v2 import FractalUploadedFile
16
14
  from fractal_server.app.schemas.v2 import TaskGroupActivityActionV2
17
15
  from fractal_server.app.schemas.v2 import TaskGroupActivityStatusV2
@@ -72,16 +70,12 @@ def collect_ssh_pixi(
72
70
  ) as fractal_ssh:
73
71
 
74
72
  with next(get_sync_db()) as db:
75
- # Get main objects from db
76
- activity = db.get(TaskGroupActivityV2, task_group_activity_id)
77
- task_group = db.get(TaskGroupV2, task_group_id)
78
- if activity is None or task_group is None:
79
- # Use `logging` directly
80
- logging.error(
81
- "Cannot find database rows with "
82
- f"{task_group_id=} and {task_group_activity_id=}:\n"
83
- f"{task_group=}\n{activity=}. Exit."
84
- )
73
+ success, task_group, activity = get_activity_and_task_group(
74
+ task_group_activity_id=task_group_activity_id,
75
+ task_group_id=task_group_id,
76
+ db=db,
77
+ )
78
+ if not success:
85
79
  return
86
80
 
87
81
  # Log some info
@@ -154,7 +148,6 @@ def collect_ssh_pixi(
154
148
  # Set `pixi_bin`
155
149
  settings = Inject(get_settings)
156
150
  pixi_home = settings.pixi.versions[task_group.pixi_version]
157
- pixi_bin = Path(pixi_home, "bin/pixi").as_posix()
158
151
 
159
152
  replacements = {
160
153
  ("__PIXI_HOME__", pixi_home),
@@ -174,20 +167,41 @@ def collect_ssh_pixi(
174
167
  activity.log = get_current_log(log_file_path)
175
168
  activity = add_commit_refresh(obj=activity, db=db)
176
169
 
177
- stdout = _customize_and_run_template(
178
- template_filename="pixi_1_collect.sh",
179
- replacements=replacements,
170
+ common_args = dict(
180
171
  script_dir_local=(
181
172
  Path(tmpdir) / SCRIPTS_SUBFOLDER
182
173
  ).as_posix(),
183
174
  script_dir_remote=script_dir_remote,
184
175
  prefix=(
185
176
  f"{int(time.time())}_"
186
- f"{TaskGroupActivityActionV2.COLLECT}_"
177
+ f"{TaskGroupActivityActionV2.COLLECT}"
187
178
  ),
188
179
  fractal_ssh=fractal_ssh,
189
180
  logger_name=LOGGER_NAME,
190
181
  )
182
+
183
+ # Run the three pixi-related scripts
184
+ _customize_and_run_template(
185
+ template_filename="pixi_1_extract.sh",
186
+ replacements=replacements,
187
+ **common_args,
188
+ )
189
+ activity.log = get_current_log(log_file_path)
190
+ activity = add_commit_refresh(obj=activity, db=db)
191
+
192
+ _customize_and_run_template(
193
+ template_filename="pixi_2_install.sh",
194
+ replacements=replacements,
195
+ **common_args,
196
+ )
197
+ activity.log = get_current_log(log_file_path)
198
+ activity = add_commit_refresh(obj=activity, db=db)
199
+
200
+ stdout = _customize_and_run_template(
201
+ template_filename="pixi_3_post_install.sh",
202
+ replacements=replacements,
203
+ **common_args,
204
+ )
191
205
  activity.log = get_current_log(log_file_path)
192
206
  activity = add_commit_refresh(obj=activity, db=db)
193
207
 
@@ -196,6 +210,9 @@ def collect_ssh_pixi(
196
210
  package_root_remote = parsed_output["package_root"]
197
211
  venv_size = parsed_output["venv_size"]
198
212
  venv_file_number = parsed_output["venv_file_number"]
213
+ project_python_wrapper = parsed_output[
214
+ "project_python_wrapper"
215
+ ]
199
216
 
200
217
  # Read and validate remote manifest file
201
218
  manifest_path_remote = (
@@ -213,14 +230,7 @@ def collect_ssh_pixi(
213
230
  package_manifest=pkg_manifest,
214
231
  package_version=task_group.version,
215
232
  package_root=Path(package_root_remote),
216
- pixi_bin=pixi_bin,
217
- pixi_manifest_path=(
218
- Path(
219
- task_group.path,
220
- SOURCE_DIR_NAME,
221
- "pyproject.toml",
222
- ).as_posix()
223
- ),
233
+ project_python_wrapper=Path(project_python_wrapper),
224
234
  )
225
235
  logger.info("_prepare_tasks_metadata - end")
226
236
 
@@ -236,14 +246,14 @@ def collect_ssh_pixi(
236
246
 
237
247
  # NOTE: see issue 2626 about whether to keep `pixi.lock`
238
248
  # files in the database
239
- # FIXME: Read remote file
240
- pixi_lock_contents = "FIXME\n"
241
- # with Path(
242
- # task_group.path,
243
- # SOURCE_DIR_NAME,
244
- # "pixi.lock",
245
- # ).open() as f:
246
- # pixi_lock_contents = f.read()
249
+ remote_pixi_lock_file = Path(
250
+ task_group.path,
251
+ SOURCE_DIR_NAME,
252
+ "pixi.lock",
253
+ ).as_posix()
254
+ pixi_lock_contents = fractal_ssh.read_remote_text_file(
255
+ remote_pixi_lock_file
256
+ )
247
257
 
248
258
  # Update task_group data
249
259
  logger.info(
@@ -1,16 +1,14 @@
1
- import logging
2
1
  import time
3
2
  from pathlib import Path
4
3
  from tempfile import TemporaryDirectory
5
4
 
6
5
  from ..utils_background import add_commit_refresh
7
6
  from ..utils_background import fail_and_cleanup
7
+ from ..utils_background import get_activity_and_task_group
8
8
  from ..utils_templates import get_collection_replacements
9
9
  from ._utils import _copy_wheel_file_ssh
10
10
  from ._utils import _customize_and_run_template
11
11
  from fractal_server.app.db import get_sync_db
12
- from fractal_server.app.models.v2 import TaskGroupActivityV2
13
- from fractal_server.app.models.v2 import TaskGroupV2
14
12
  from fractal_server.app.schemas.v2 import TaskGroupActivityActionV2
15
13
  from fractal_server.app.schemas.v2 import TaskGroupV2OriginEnum
16
14
  from fractal_server.app.schemas.v2.task_group import TaskGroupActivityStatusV2
@@ -61,17 +59,12 @@ def deactivate_ssh(
61
59
  ) as fractal_ssh:
62
60
 
63
61
  with next(get_sync_db()) as db:
64
-
65
- # Get main objects from db
66
- activity = db.get(TaskGroupActivityV2, task_group_activity_id)
67
- task_group = db.get(TaskGroupV2, task_group_id)
68
- if activity is None or task_group is None:
69
- # Use `logging` directly
70
- logging.error(
71
- "Cannot find database rows with "
72
- f"{task_group_id=} and {task_group_activity_id=}:\n"
73
- f"{task_group=}\n{activity=}. Exit."
74
- )
62
+ success, task_group, activity = get_activity_and_task_group(
63
+ task_group_activity_id=task_group_activity_id,
64
+ task_group_id=task_group_id,
65
+ db=db,
66
+ )
67
+ if not success:
75
68
  return
76
69
 
77
70
  # Log some info
@@ -0,0 +1,128 @@
1
+ from pathlib import Path
2
+ from tempfile import TemporaryDirectory
3
+
4
+ from ..utils_background import add_commit_refresh
5
+ from ..utils_background import fail_and_cleanup
6
+ from ..utils_background import get_activity_and_task_group
7
+ from ..utils_pixi import SOURCE_DIR_NAME
8
+ from fractal_server.app.db import get_sync_db
9
+ from fractal_server.app.schemas.v2.task_group import TaskGroupActivityStatusV2
10
+ from fractal_server.logger import reset_logger_handlers
11
+ from fractal_server.logger import set_logger
12
+ from fractal_server.ssh._fabric import SingleUseFractalSSH
13
+ from fractal_server.ssh._fabric import SSHConfig
14
+ from fractal_server.tasks.utils import get_log_path
15
+ from fractal_server.tasks.v2.utils_background import get_current_log
16
+ from fractal_server.utils import get_timestamp
17
+
18
+
19
+ def deactivate_ssh_pixi(
20
+ *,
21
+ task_group_activity_id: int,
22
+ task_group_id: int,
23
+ ssh_config: SSHConfig,
24
+ tasks_base_dir: str,
25
+ ) -> None:
26
+ """
27
+ Deactivate a pixi task group venv.
28
+
29
+ This function is run as a background task, therefore exceptions must be
30
+ handled.
31
+
32
+ Arguments:
33
+ task_group_id:
34
+ task_group_activity_id:
35
+ ssh_config:
36
+ tasks_base_dir:
37
+ Only used as a `safe_root` in `remove_dir`, and typically set to
38
+ `user_settings.ssh_tasks_dir`.
39
+ """
40
+
41
+ LOGGER_NAME = f"{__name__}.ID{task_group_activity_id}"
42
+
43
+ with TemporaryDirectory() as tmpdir:
44
+ log_file_path = get_log_path(Path(tmpdir))
45
+ logger = set_logger(
46
+ logger_name=LOGGER_NAME,
47
+ log_file_path=log_file_path,
48
+ )
49
+ with SingleUseFractalSSH(
50
+ ssh_config=ssh_config,
51
+ logger_name=LOGGER_NAME,
52
+ ) as fractal_ssh:
53
+
54
+ with next(get_sync_db()) as db:
55
+ success, task_group, activity = get_activity_and_task_group(
56
+ task_group_activity_id=task_group_activity_id,
57
+ task_group_id=task_group_id,
58
+ db=db,
59
+ )
60
+ if not success:
61
+ return
62
+
63
+ # Log some info
64
+ logger.debug("START")
65
+ for key, value in task_group.model_dump().items():
66
+ logger.debug(f"task_group.{key}: {value}")
67
+
68
+ # Check that SSH connection works
69
+ try:
70
+ fractal_ssh.check_connection()
71
+ except Exception as e:
72
+ logger.error("Cannot establish SSH connection.")
73
+ fail_and_cleanup(
74
+ task_group=task_group,
75
+ task_group_activity=activity,
76
+ logger_name=LOGGER_NAME,
77
+ log_file_path=log_file_path,
78
+ exception=e,
79
+ db=db,
80
+ )
81
+ return
82
+
83
+ try:
84
+ # Check that the (remote) task_group venv_path does exist
85
+ source_dir = Path(
86
+ task_group.path, SOURCE_DIR_NAME
87
+ ).as_posix()
88
+ if not fractal_ssh.remote_exists(source_dir):
89
+ error_msg = f"{source_dir} does not exist."
90
+ logger.error(error_msg)
91
+ fail_and_cleanup(
92
+ task_group=task_group,
93
+ task_group_activity=activity,
94
+ logger_name=LOGGER_NAME,
95
+ log_file_path=log_file_path,
96
+ exception=FileNotFoundError(error_msg),
97
+ db=db,
98
+ )
99
+ return
100
+
101
+ # Actually mark the task group as non-active
102
+ logger.info("Now setting `active=False`.")
103
+ task_group.active = False
104
+ task_group = add_commit_refresh(obj=task_group, db=db)
105
+
106
+ # Proceed with deactivation
107
+ logger.info(f"Now removing {source_dir}.")
108
+ fractal_ssh.remove_folder(
109
+ folder=source_dir,
110
+ safe_root=tasks_base_dir,
111
+ )
112
+ logger.info(f"All good, {source_dir} removed.")
113
+ activity.status = TaskGroupActivityStatusV2.OK
114
+ activity.log = get_current_log(log_file_path)
115
+ activity.timestamp_ended = get_timestamp()
116
+ activity = add_commit_refresh(obj=activity, db=db)
117
+
118
+ reset_logger_handlers(logger)
119
+
120
+ except Exception as e:
121
+ fail_and_cleanup(
122
+ task_group=task_group,
123
+ task_group_activity=activity,
124
+ logger_name=LOGGER_NAME,
125
+ log_file_path=log_file_path,
126
+ exception=e,
127
+ db=db,
128
+ )
@@ -1,15 +1,13 @@
1
- import logging
2
1
  import time
3
2
  from pathlib import Path
4
3
  from tempfile import TemporaryDirectory
5
4
 
6
5
  from ..utils_background import add_commit_refresh
7
6
  from ..utils_background import fail_and_cleanup
7
+ from ..utils_background import get_activity_and_task_group
8
8
  from ..utils_templates import get_collection_replacements
9
9
  from ._utils import _customize_and_run_template
10
10
  from fractal_server.app.db import get_sync_db
11
- from fractal_server.app.models.v2 import TaskGroupActivityV2
12
- from fractal_server.app.models.v2 import TaskGroupV2
13
11
  from fractal_server.app.schemas.v2 import TaskGroupActivityActionV2
14
12
  from fractal_server.app.schemas.v2.task_group import TaskGroupActivityStatusV2
15
13
  from fractal_server.logger import reset_logger_handlers
@@ -62,17 +60,12 @@ def reactivate_ssh(
62
60
  ) as fractal_ssh:
63
61
 
64
62
  with next(get_sync_db()) as db:
65
-
66
- # Get main objects from db
67
- activity = db.get(TaskGroupActivityV2, task_group_activity_id)
68
- task_group = db.get(TaskGroupV2, task_group_id)
69
- if activity is None or task_group is None:
70
- # Use `logging` directly
71
- logging.error(
72
- "Cannot find database rows with "
73
- f"{task_group_id=} and {task_group_activity_id=}:\n"
74
- f"{task_group=}\n{activity=}. Exit."
75
- )
63
+ success, task_group, activity = get_activity_and_task_group(
64
+ task_group_activity_id=task_group_activity_id,
65
+ task_group_id=task_group_id,
66
+ db=db,
67
+ )
68
+ if not success:
76
69
  return
77
70
 
78
71
  # Log some info
@@ -0,0 +1,108 @@
1
+ from pathlib import Path
2
+ from tempfile import TemporaryDirectory
3
+
4
+ from ..utils_background import fail_and_cleanup
5
+ from ..utils_background import get_activity_and_task_group
6
+ from fractal_server.app.db import get_sync_db
7
+ from fractal_server.logger import reset_logger_handlers
8
+ from fractal_server.logger import set_logger
9
+ from fractal_server.ssh._fabric import SingleUseFractalSSH
10
+ from fractal_server.ssh._fabric import SSHConfig
11
+ from fractal_server.tasks.utils import get_log_path
12
+
13
+
14
+ def reactivate_ssh_pixi(
15
+ *,
16
+ task_group_activity_id: int,
17
+ task_group_id: int,
18
+ ssh_config: SSHConfig,
19
+ tasks_base_dir: str,
20
+ ) -> None:
21
+ """
22
+ Reactivate a task group venv.
23
+
24
+ This function is run as a background task, therefore exceptions must be
25
+ handled.
26
+
27
+ Arguments:
28
+ task_group_id:
29
+ task_group_activity_id:
30
+ ssh_config:
31
+ tasks_base_dir:
32
+ Only used as a `safe_root` in `remove_dir`, and typically set to
33
+ `user_settings.ssh_tasks_dir`.
34
+ """
35
+
36
+ LOGGER_NAME = f"{__name__}.ID{task_group_activity_id}"
37
+
38
+ with TemporaryDirectory() as tmpdir:
39
+ log_file_path = get_log_path(Path(tmpdir))
40
+ logger = set_logger(
41
+ logger_name=LOGGER_NAME,
42
+ log_file_path=log_file_path,
43
+ )
44
+
45
+ with SingleUseFractalSSH(
46
+ ssh_config=ssh_config,
47
+ logger_name=LOGGER_NAME,
48
+ ) as fractal_ssh:
49
+
50
+ with next(get_sync_db()) as db:
51
+ success, task_group, activity = get_activity_and_task_group(
52
+ task_group_activity_id=task_group_activity_id,
53
+ task_group_id=task_group_id,
54
+ db=db,
55
+ )
56
+ if not success:
57
+ return
58
+
59
+ # Log some info
60
+ logger.info("START")
61
+ for key, value in task_group.model_dump().items():
62
+ logger.debug(f"task_group.{key}: {value}")
63
+
64
+ # Check that SSH connection works
65
+ try:
66
+ fractal_ssh.check_connection()
67
+ except Exception as e:
68
+ logger.error("Cannot establish SSH connection.")
69
+ fail_and_cleanup(
70
+ task_group=task_group,
71
+ task_group_activity=activity,
72
+ logger_name=LOGGER_NAME,
73
+ log_file_path=log_file_path,
74
+ exception=e,
75
+ db=db,
76
+ )
77
+ return
78
+
79
+ try:
80
+ raise NotImplementedError("pixi-task reactivation FIXME")
81
+
82
+ reset_logger_handlers(logger)
83
+
84
+ except Exception as reactivate_e:
85
+ # Delete corrupted venv_path
86
+ try:
87
+ logger.info(
88
+ f"Now delete folder {task_group.venv_path}"
89
+ )
90
+ fractal_ssh.remove_folder(
91
+ folder=task_group.venv_path,
92
+ safe_root=tasks_base_dir,
93
+ )
94
+ logger.info(f"Deleted folder {task_group.venv_path}")
95
+ except Exception as rm_e:
96
+ logger.error(
97
+ "Removing folder failed.\n"
98
+ f"Original error:\n{str(rm_e)}"
99
+ )
100
+
101
+ fail_and_cleanup(
102
+ task_group=task_group,
103
+ task_group_activity=activity,
104
+ logger_name=LOGGER_NAME,
105
+ log_file_path=log_file_path,
106
+ exception=reactivate_e,
107
+ db=db,
108
+ )
@@ -0,0 +1,40 @@
1
+ set -e
2
+
3
+ write_log(){
4
+ TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
5
+ echo "[collect-task-pixi, ${TIMESTAMP}] ${1}"
6
+ }
7
+
8
+ # Replacements
9
+ PACKAGE_DIR="__PACKAGE_DIR__"
10
+ TAR_GZ_PATH="__TAR_GZ_PATH__"
11
+ SOURCE_DIR_NAME="__SOURCE_DIR_NAME__"
12
+
13
+ # Strip trailing `/` from `PACKAGE_DIR`
14
+ PACKAGE_DIR=${PACKAGE_DIR%/}
15
+
16
+ # Known paths
17
+ SOURCE_DIR="${PACKAGE_DIR}/${SOURCE_DIR_NAME}"
18
+ TAR_GZ_BASENAME=$(basename "${TAR_GZ_PATH}" ".tar.gz")
19
+
20
+ TIME_START=$(date +%s)
21
+
22
+ cd "${PACKAGE_DIR}"
23
+ write_log "Changed working directory to ${PACKAGE_DIR}"
24
+
25
+ # -----------------------------------------------------------------------------
26
+
27
+ write_log "START 'tar xz -f ${TAR_GZ_PATH} ${TAR_GZ_BASENAME}'"
28
+ tar xz -f "${TAR_GZ_PATH}" "${TAR_GZ_BASENAME}"
29
+ write_log "END 'tar xz -f ${TAR_GZ_PATH} ${TAR_GZ_BASENAME}'"
30
+ echo
31
+
32
+ write_log "START 'mv ${PACKAGE_DIR}/${TAR_GZ_BASENAME} ${SOURCE_DIR}'"
33
+ mv "${PACKAGE_DIR}/${TAR_GZ_BASENAME}" "${SOURCE_DIR}"
34
+ write_log "END 'mv ${PACKAGE_DIR}/${TAR_GZ_BASENAME} ${SOURCE_DIR}'"
35
+ echo
36
+
37
+ TIME_END=$(date +%s)
38
+ write_log "Elapsed: $((TIME_END - TIME_START)) seconds"
39
+ write_log "All ok, exit."
40
+ echo
@@ -0,0 +1,48 @@
1
+ set -e
2
+
3
+ write_log(){
4
+ TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
5
+ echo "[collect-task-pixi, ${TIMESTAMP}] ${1}"
6
+ }
7
+
8
+ # Replacements
9
+ PIXI_HOME="__PIXI_HOME__"
10
+ PACKAGE_DIR="__PACKAGE_DIR__"
11
+ SOURCE_DIR_NAME="__SOURCE_DIR_NAME__"
12
+ FROZEN_OPTION="__FROZEN_OPTION__"
13
+
14
+ # Strip trailing `/` from `PACKAGE_DIR`
15
+ PIXI_HOME=${PIXI_HOME%/}
16
+ PACKAGE_DIR=${PACKAGE_DIR%/}
17
+
18
+ # Known paths
19
+ PIXI_EXECUTABLE="${PIXI_HOME}/bin/pixi"
20
+ SOURCE_DIR="${PACKAGE_DIR}/${SOURCE_DIR_NAME}"
21
+ PYPROJECT_TOML="${SOURCE_DIR}/pyproject.toml"
22
+
23
+ # Pixi env variable
24
+ export PIXI_HOME="${PIXI_HOME}"
25
+ export PIXI_CACHE_DIR="${PIXI_HOME}/cache"
26
+ export RATTLER_AUTH_FILE="${PIXI_HOME}/credentials.json"
27
+
28
+ TIME_START=$(date +%s)
29
+
30
+ cd "${PACKAGE_DIR}"
31
+ write_log "Changed working directory to ${PACKAGE_DIR}"
32
+
33
+ # -----------------------------------------------------------------------------
34
+
35
+ FROZEN_FLAG=""
36
+ if [[ "${FROZEN_OPTION}" == "true" ]]; then
37
+ FROZEN_FLAG="--frozen"
38
+ fi
39
+
40
+ write_log "START '${PIXI_EXECUTABLE} install ${FROZEN_FLAG} --manifest-path ${PYPROJECT_TOML}'"
41
+ ${PIXI_EXECUTABLE} install ${FROZEN_FLAG} --manifest-path "${PYPROJECT_TOML}"
42
+ write_log "END '${PIXI_EXECUTABLE} install ${FROZEN_FLAG} --manifest-path ${PYPROJECT_TOML}'"
43
+ echo
44
+
45
+ TIME_END=$(date +%s)
46
+ write_log "Elapsed: $((TIME_END - TIME_START)) seconds"
47
+ write_log "All ok, exit."
48
+ echo
@@ -0,0 +1,80 @@
1
+ set -e
2
+
3
+ write_log(){
4
+ TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
5
+ echo "[collect-task-pixi, ${TIMESTAMP}] ${1}"
6
+ }
7
+
8
+ # Replacements
9
+ PIXI_HOME="__PIXI_HOME__"
10
+ PACKAGE_DIR="__PACKAGE_DIR__"
11
+ SOURCE_DIR_NAME="__SOURCE_DIR_NAME__"
12
+ IMPORT_PACKAGE_NAME="__IMPORT_PACKAGE_NAME__"
13
+
14
+ # Strip trailing `/` from `PACKAGE_DIR`
15
+ PIXI_HOME=${PIXI_HOME%/}
16
+ PACKAGE_DIR=${PACKAGE_DIR%/}
17
+
18
+ # Known paths
19
+ PIXI_EXECUTABLE="${PIXI_HOME}/bin/pixi"
20
+ SOURCE_DIR="${PACKAGE_DIR}/${SOURCE_DIR_NAME}"
21
+ PYPROJECT_TOML="${SOURCE_DIR}/pyproject.toml"
22
+ ACTIVATION_FILE="${SOURCE_DIR}/activate_project.sh"
23
+ PROJECT_PYTHON_WRAPPER="${SOURCE_DIR}/project_python.sh"
24
+
25
+ # Pixi env variable
26
+ export PIXI_HOME="${PIXI_HOME}"
27
+ export PIXI_CACHE_DIR="${PIXI_HOME}/cache"
28
+ export RATTLER_AUTH_FILE="${PIXI_HOME}/credentials.json"
29
+
30
+
31
+ TIME_START=$(date +%s)
32
+
33
+ cd "${PACKAGE_DIR}"
34
+ write_log "Changed working directory to ${PACKAGE_DIR}"
35
+
36
+ # -----------------------------------------------------------------------------
37
+
38
+ write_log "START '${PIXI_EXECUTABLE} shell-hook --manifest-path ${PYPROJECT_TOML}'"
39
+ ${PIXI_EXECUTABLE} shell-hook --manifest-path "${PYPROJECT_TOML}" > "${ACTIVATION_FILE}"
40
+ write_log "END '${PIXI_EXECUTABLE} shell-hook --manifest-path ${PYPROJECT_TOML}'"
41
+ echo
42
+
43
+ PROJECT_PYTHON_BIN=$(${PIXI_EXECUTABLE} run --manifest-path "${PYPROJECT_TOML}" which python)
44
+ write_log "Found PROJECT_PYTHON_BIN=${PROJECT_PYTHON_BIN}"
45
+
46
+ # Write project-scoped Python wrapper
47
+ cat <<EOF > "${PROJECT_PYTHON_WRAPPER}"
48
+ #!/bin/bash
49
+ source ${ACTIVATION_FILE}
50
+ ${PROJECT_PYTHON_BIN} "\$@"
51
+ EOF
52
+
53
+ chmod 755 "${PROJECT_PYTHON_WRAPPER}"
54
+ write_log "Written ${PROJECT_PYTHON_WRAPPER} with 755 permissions"
55
+ write_log "Project Python wrapper: ${PROJECT_PYTHON_WRAPPER}"
56
+ write_log "Project-Python version: $(${PROJECT_PYTHON_WRAPPER} --version)"
57
+ echo
58
+
59
+ # Find PACKAGE_FOLDER
60
+ FIND_PACKAGE_FOLDER_SCRIPT="${SOURCE_DIR}/find_package_folder.sh"
61
+ echo "source ${ACTIVATION_FILE}" > "${FIND_PACKAGE_FOLDER_SCRIPT}"
62
+ echo "${PROJECT_PYTHON_BIN} -c \"import ${IMPORT_PACKAGE_NAME} as p, os; print(os.path.dirname(p.__file__))\"" >> "${FIND_PACKAGE_FOLDER_SCRIPT}"
63
+ PACKAGE_FOLDER=$(bash "${FIND_PACKAGE_FOLDER_SCRIPT}")
64
+ write_log "Package folder: ${PACKAGE_FOLDER}"
65
+ echo
66
+
67
+ ENV_DISK_USAGE=$(du -sk "${PACKAGE_DIR}" | cut -f1)
68
+ ENV_FILE_NUMBER=$(find "${PACKAGE_DIR}" -type f | wc -l)
69
+ write_log "Disk usage: ${ENV_DISK_USAGE}"
70
+ write_log "Number of files: ${ENV_FILE_NUMBER}"
71
+ echo
72
+
73
+ write_log "START chmod 755 ${SOURCE_DIR} -R"
74
+ chmod 755 "${SOURCE_DIR}" -R
75
+ write_log "END chmod 755 ${SOURCE_DIR} -R"
76
+
77
+ TIME_END=$(date +%s)
78
+ write_log "Elapsed: $((TIME_END - TIME_START)) seconds"
79
+ write_log "All ok, exit."
80
+ echo