sl-shared-assets 3.1.2__py3-none-any.whl → 3.1.3__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.
Potentially problematic release.
This version of sl-shared-assets might be problematic. Click here for more details.
- sl_shared_assets/cli.py +19 -15
- sl_shared_assets/cli.pyi +2 -2
- sl_shared_assets/data_classes/session_data.py +2 -2
- sl_shared_assets/data_classes/session_data.pyi +2 -2
- sl_shared_assets/server/server.py +39 -2
- sl_shared_assets/server/server.pyi +13 -1
- sl_shared_assets/tools/project_management_tools.py +44 -1
- {sl_shared_assets-3.1.2.dist-info → sl_shared_assets-3.1.3.dist-info}/METADATA +2 -2
- {sl_shared_assets-3.1.2.dist-info → sl_shared_assets-3.1.3.dist-info}/RECORD +12 -12
- {sl_shared_assets-3.1.2.dist-info → sl_shared_assets-3.1.3.dist-info}/WHEEL +0 -0
- {sl_shared_assets-3.1.2.dist-info → sl_shared_assets-3.1.3.dist-info}/entry_points.txt +0 -0
- {sl_shared_assets-3.1.2.dist-info → sl_shared_assets-3.1.3.dist-info}/licenses/LICENSE +0 -0
sl_shared_assets/cli.py
CHANGED
|
@@ -26,7 +26,7 @@ from .data_classes import SessionData, ProcessingTracker
|
|
|
26
26
|
default=False,
|
|
27
27
|
help=(
|
|
28
28
|
"Determines whether to create the processed data hierarchy. This flag should be disabled for most runtimes. "
|
|
29
|
-
"Primarily, it is used by
|
|
29
|
+
"Primarily, it is used by acquisition systems to generate processed data directories on the remote "
|
|
30
30
|
"compute servers as part of the data preprocessing pipeline."
|
|
31
31
|
),
|
|
32
32
|
)
|
|
@@ -105,18 +105,21 @@ def verify_session_integrity(
|
|
|
105
105
|
help="The absolute path to the directory where to store the generated project manifest file.",
|
|
106
106
|
)
|
|
107
107
|
@click.option(
|
|
108
|
-
"-
|
|
109
|
-
"--
|
|
108
|
+
"-pdr",
|
|
109
|
+
"--processed_data_root",
|
|
110
110
|
type=click.Path(exists=True, file_okay=False, dir_okay=True, path_type=Path),
|
|
111
111
|
required=False,
|
|
112
112
|
help=(
|
|
113
|
-
"The absolute path to the
|
|
114
|
-
"
|
|
115
|
-
"
|
|
113
|
+
"The absolute path to the directory where processed data from all projects is stored on the machine that runs "
|
|
114
|
+
"this command. This argument is used when calling the CLI on the BioHPC server, which uses different data "
|
|
115
|
+
"volumes for raw and processed data. Note, the input path must point to the root directory, as it will be "
|
|
116
|
+
"automatically modified to include the project name. Note, if the system cannot properly resolve the path to "
|
|
117
|
+
"the processed data, the generated manifest will indicate that no data processing has been performed for the "
|
|
118
|
+
"project."
|
|
116
119
|
),
|
|
117
120
|
)
|
|
118
121
|
def generate_project_manifest_file(
|
|
119
|
-
project_path: Path, output_directory: Path,
|
|
122
|
+
project_path: Path, output_directory: Path, processed_data_root: Path | None
|
|
120
123
|
) -> None:
|
|
121
124
|
"""Generates the manifest .feather file that provides information about the data-processing state of all available
|
|
122
125
|
project sessions.
|
|
@@ -128,7 +131,7 @@ def generate_project_manifest_file(
|
|
|
128
131
|
generate_project_manifest(
|
|
129
132
|
raw_project_directory=Path(project_path),
|
|
130
133
|
output_directory=Path(output_directory),
|
|
131
|
-
processed_data_root=Path(
|
|
134
|
+
processed_data_root=Path(processed_data_root) if processed_data_root else None,
|
|
132
135
|
)
|
|
133
136
|
# noinspection PyTypeChecker
|
|
134
137
|
console.echo(message=f"Project {Path(project_path).stem} data manifest file: generated.", level=LogLevel.SUCCESS)
|
|
@@ -428,14 +431,15 @@ def start_jupyter_server(
|
|
|
428
431
|
help="Determines whether to create the processed data hierarchy. This flag should be disabled for most runtimes.",
|
|
429
432
|
)
|
|
430
433
|
@click.option(
|
|
431
|
-
"-
|
|
432
|
-
"--
|
|
434
|
+
"-pdr",
|
|
435
|
+
"--processed_data_root",
|
|
433
436
|
type=click.Path(exists=True, file_okay=False, dir_okay=True, path_type=Path),
|
|
434
437
|
required=False,
|
|
435
438
|
help=(
|
|
436
|
-
"The absolute path to the
|
|
437
|
-
"
|
|
438
|
-
"
|
|
439
|
+
"The absolute path to the directory where processed data from all projects is stored on the machine that runs "
|
|
440
|
+
"this command. This argument is used when calling the CLI on the BioHPC server, which uses different data "
|
|
441
|
+
"volumes for raw and processed data. Note, the input path must point to the root directory, as it will be "
|
|
442
|
+
"automatically modified to include the project name."
|
|
439
443
|
),
|
|
440
444
|
)
|
|
441
445
|
@click.option(
|
|
@@ -463,7 +467,7 @@ def start_jupyter_server(
|
|
|
463
467
|
def resolve_dataset_marker(
|
|
464
468
|
session_path: Path,
|
|
465
469
|
create_processed_directories: bool,
|
|
466
|
-
|
|
470
|
+
processed_data_root: Path | None,
|
|
467
471
|
remove: bool,
|
|
468
472
|
update_manifest: bool,
|
|
469
473
|
) -> None:
|
|
@@ -477,7 +481,7 @@ def resolve_dataset_marker(
|
|
|
477
481
|
resolve_p53_marker(
|
|
478
482
|
session_path=session_path,
|
|
479
483
|
create_processed_data_directory=create_processed_directories,
|
|
480
|
-
processed_data_root=
|
|
484
|
+
processed_data_root=processed_data_root,
|
|
481
485
|
remove=remove,
|
|
482
486
|
update_manifest=update_manifest,
|
|
483
487
|
)
|
sl_shared_assets/cli.pyi
CHANGED
|
@@ -33,7 +33,7 @@ def verify_session_integrity(
|
|
|
33
33
|
"""
|
|
34
34
|
|
|
35
35
|
def generate_project_manifest_file(
|
|
36
|
-
project_path: Path, output_directory: Path,
|
|
36
|
+
project_path: Path, output_directory: Path, processed_data_root: Path | None
|
|
37
37
|
) -> None:
|
|
38
38
|
"""Generates the manifest .feather file that provides information about the data-processing state of all available
|
|
39
39
|
project sessions.
|
|
@@ -88,7 +88,7 @@ def start_jupyter_server(
|
|
|
88
88
|
def resolve_dataset_marker(
|
|
89
89
|
session_path: Path,
|
|
90
90
|
create_processed_directories: bool,
|
|
91
|
-
|
|
91
|
+
processed_data_root: Path | None,
|
|
92
92
|
remove: bool,
|
|
93
93
|
update_manifest: bool,
|
|
94
94
|
) -> None:
|
|
@@ -264,8 +264,8 @@ class SessionData(YamlConfig):
|
|
|
264
264
|
Notes:
|
|
265
265
|
This class is specifically designed for working with the data from a single session, performed by a single
|
|
266
266
|
animal under the specific experiment. The class is used to manage both raw and processed data. It follows the
|
|
267
|
-
data through acquisition, preprocessing and processing stages of the Sun lab data workflow. This class serves
|
|
268
|
-
an entry point for all interactions with the managed session's data.
|
|
267
|
+
data through acquisition, preprocessing, and processing stages of the Sun lab data workflow. This class serves
|
|
268
|
+
as an entry point for all interactions with the managed session's data.
|
|
269
269
|
"""
|
|
270
270
|
|
|
271
271
|
project_name: str
|
|
@@ -125,8 +125,8 @@ class SessionData(YamlConfig):
|
|
|
125
125
|
Notes:
|
|
126
126
|
This class is specifically designed for working with the data from a single session, performed by a single
|
|
127
127
|
animal under the specific experiment. The class is used to manage both raw and processed data. It follows the
|
|
128
|
-
data through acquisition, preprocessing and processing stages of the Sun lab data workflow. This class serves
|
|
129
|
-
an entry point for all interactions with the managed session's data.
|
|
128
|
+
data through acquisition, preprocessing, and processing stages of the Sun lab data workflow. This class serves
|
|
129
|
+
as an entry point for all interactions with the managed session's data.
|
|
130
130
|
"""
|
|
131
131
|
|
|
132
132
|
project_name: str
|
|
@@ -552,22 +552,59 @@ class Server:
|
|
|
552
552
|
finally:
|
|
553
553
|
sftp.close()
|
|
554
554
|
|
|
555
|
-
def remove(self, remote_path: Path, is_dir: bool) -> None:
|
|
555
|
+
def remove(self, remote_path: Path, is_dir: bool, recursive: bool = False) -> None:
|
|
556
556
|
"""Removes the specified file or directory from the remote server.
|
|
557
557
|
|
|
558
558
|
Args:
|
|
559
559
|
remote_path: The path to the file or directory on the remote server to be removed.
|
|
560
560
|
is_dir: Determines whether the input path represents a directory or a file.
|
|
561
|
+
recursive: If True and is_dir is True, recursively deletes all contents of the directory
|
|
562
|
+
before removing it. If False, only removes empty directories (standard rmdir behavior).
|
|
561
563
|
"""
|
|
562
564
|
sftp = self._client.open_sftp()
|
|
563
565
|
try:
|
|
564
566
|
if is_dir:
|
|
565
|
-
|
|
567
|
+
if recursive:
|
|
568
|
+
# Recursively deletes all contents first and then removes the top-level (now empty) directory
|
|
569
|
+
self._recursive_remove(sftp, remote_path)
|
|
570
|
+
else:
|
|
571
|
+
# Only removes empty directories
|
|
572
|
+
sftp.rmdir(path=str(remote_path))
|
|
566
573
|
else:
|
|
567
574
|
sftp.unlink(path=str(remote_path))
|
|
568
575
|
finally:
|
|
569
576
|
sftp.close()
|
|
570
577
|
|
|
578
|
+
def _recursive_remove(self, sftp: paramiko.SFTPClient, remote_path: Path) -> None:
|
|
579
|
+
"""Recursively removes a directory and all its contents.
|
|
580
|
+
|
|
581
|
+
This worker method is used by the user-facing remove() method to recursively remove non-empty directories.
|
|
582
|
+
|
|
583
|
+
Args:
|
|
584
|
+
sftp: The SFTP client instance to use for remove operations.
|
|
585
|
+
remote_path: The path to the remote directory to recursively remove.
|
|
586
|
+
"""
|
|
587
|
+
try:
|
|
588
|
+
# Lists all items in the directory
|
|
589
|
+
items = sftp.listdir_attr(str(remote_path))
|
|
590
|
+
|
|
591
|
+
for item in items:
|
|
592
|
+
item_path = remote_path / item.filename
|
|
593
|
+
|
|
594
|
+
# Checks if the item is a directory
|
|
595
|
+
if stat.S_ISDIR(item.st_mode): # type: ignore
|
|
596
|
+
# Recursively removes subdirectories
|
|
597
|
+
self._recursive_remove(sftp, item_path)
|
|
598
|
+
else:
|
|
599
|
+
# Recursively removes files
|
|
600
|
+
sftp.unlink(str(item_path))
|
|
601
|
+
|
|
602
|
+
# After all contents are removed, removes the empty directory
|
|
603
|
+
sftp.rmdir(str(remote_path))
|
|
604
|
+
|
|
605
|
+
except Exception as e:
|
|
606
|
+
console.echo(f"Unable to remove the specified directory {remote_path}: {str(e)}", level=LogLevel.WARNING)
|
|
607
|
+
|
|
571
608
|
def create_directory(self, remote_path: Path, parents: bool = True) -> None:
|
|
572
609
|
"""Creates the specified directory tree on the managed remote server via SFTP.
|
|
573
610
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from pathlib import Path
|
|
2
2
|
from dataclasses import field, dataclass
|
|
3
3
|
|
|
4
|
+
import paramiko
|
|
4
5
|
from _typeshed import Incomplete
|
|
5
6
|
from simple_slurm import Slurm as Slurm
|
|
6
7
|
from paramiko.client import SSHClient as SSHClient
|
|
@@ -230,12 +231,23 @@ class Server:
|
|
|
230
231
|
local_directory_path: The path to the local directory to be uploaded.
|
|
231
232
|
remote_directory_path: The path on the remote server where the directory will be copied.
|
|
232
233
|
"""
|
|
233
|
-
def remove(self, remote_path: Path, is_dir: bool) -> None:
|
|
234
|
+
def remove(self, remote_path: Path, is_dir: bool, recursive: bool = False) -> None:
|
|
234
235
|
"""Removes the specified file or directory from the remote server.
|
|
235
236
|
|
|
236
237
|
Args:
|
|
237
238
|
remote_path: The path to the file or directory on the remote server to be removed.
|
|
238
239
|
is_dir: Determines whether the input path represents a directory or a file.
|
|
240
|
+
recursive: If True and is_dir is True, recursively deletes all contents of the directory
|
|
241
|
+
before removing it. If False, only removes empty directories (standard rmdir behavior).
|
|
242
|
+
"""
|
|
243
|
+
def _recursive_remove(self, sftp: paramiko.SFTPClient, remote_path: Path) -> None:
|
|
244
|
+
"""Recursively removes a directory and all its contents.
|
|
245
|
+
|
|
246
|
+
This worker method is used by the user-facing remove() method to recursively remove non-empty directories.
|
|
247
|
+
|
|
248
|
+
Args:
|
|
249
|
+
sftp: The SFTP client instance to use for remove operations.
|
|
250
|
+
remote_path: The path to the remote directory to recursively remove.
|
|
239
251
|
"""
|
|
240
252
|
def create_directory(self, remote_path: Path, parents: bool = True) -> None:
|
|
241
253
|
"""Creates the specified directory tree on the managed remote server via SFTP.
|
|
@@ -8,7 +8,7 @@ from datetime import datetime
|
|
|
8
8
|
import pytz
|
|
9
9
|
import polars as pl
|
|
10
10
|
from filelock import FileLock
|
|
11
|
-
from ataraxis_base_utilities import console
|
|
11
|
+
from ataraxis_base_utilities import LogLevel, console
|
|
12
12
|
|
|
13
13
|
from ..data_classes import (
|
|
14
14
|
SessionData,
|
|
@@ -362,6 +362,8 @@ def generate_project_manifest(
|
|
|
362
362
|
manifest["notes"].append(descriptor.experimenter_notes)
|
|
363
363
|
except Exception:
|
|
364
364
|
manifest["notes"].append("N/A")
|
|
365
|
+
else:
|
|
366
|
+
manifest["notes"].append("N/A")
|
|
365
367
|
|
|
366
368
|
# If the session raw_data folder contains the telomere.bin file, marks the session as complete.
|
|
367
369
|
manifest["complete"].append(session_data.raw_data.telomere_path.exists())
|
|
@@ -573,12 +575,27 @@ def resolve_p53_marker(
|
|
|
573
575
|
if session_data.processed_data.p53_path.exists():
|
|
574
576
|
if remove:
|
|
575
577
|
session_data.processed_data.p53_path.unlink()
|
|
578
|
+
message = (
|
|
579
|
+
f"Dataset marker for the session {session_data.session_name} acquired for the animal "
|
|
580
|
+
f"{session_data.animal_id} and {session_data.project_name} project: Removed."
|
|
581
|
+
)
|
|
582
|
+
console.echo(message=message, level=LogLevel.SUCCESS)
|
|
576
583
|
return # Ends remove runtime
|
|
577
584
|
|
|
585
|
+
message = (
|
|
586
|
+
f"Dataset marker for the session {session_data.session_name} acquired for the animal "
|
|
587
|
+
f"{session_data.animal_id} and {session_data.project_name} project: Already exists. No actions taken."
|
|
588
|
+
)
|
|
589
|
+
console.echo(message=message, level=LogLevel.SUCCESS)
|
|
578
590
|
return # Ends create runtime
|
|
579
591
|
|
|
580
592
|
# If the marker does not exist and the function is called in 'remove' mode, aborts the runtime
|
|
581
593
|
elif remove:
|
|
594
|
+
message = (
|
|
595
|
+
f"Dataset marker for the session {session_data.session_name} acquired for the animal "
|
|
596
|
+
f"{session_data.animal_id} and {session_data.project_name} project: Does not exist. No actions taken."
|
|
597
|
+
)
|
|
598
|
+
console.echo(message=message, level=LogLevel.SUCCESS)
|
|
582
599
|
return # Ends remove runtime
|
|
583
600
|
|
|
584
601
|
# The rest of the runtime deals with determining whether it is safe to create the marker file.
|
|
@@ -588,6 +605,13 @@ def resolve_p53_marker(
|
|
|
588
605
|
# Window checking sessions are not designed to be integrated into datasets, so they cannot be marked with the
|
|
589
606
|
# p53.bin file. Similarly, any incomplete session is automatically excluded from dataset formation.
|
|
590
607
|
if session_type == SessionTypes.WINDOW_CHECKING or not session_data.raw_data.telomere_path.exists():
|
|
608
|
+
message = (
|
|
609
|
+
f"Unable to generate the dataset marker for the session {session_data.session_name} acquired for the "
|
|
610
|
+
f"animal {session_data.animal_id} and {session_data.project_name} project, as the session is incomplete or "
|
|
611
|
+
f"is of Window Checking type. These sessions must be manually evaluated and marked for dataset inclusion "
|
|
612
|
+
f"by the experimenter. "
|
|
613
|
+
)
|
|
614
|
+
console.echo(message=message, level=LogLevel.ERROR)
|
|
591
615
|
return
|
|
592
616
|
|
|
593
617
|
# Training sessions collect similar data and share processing pipeline requirements
|
|
@@ -597,6 +621,13 @@ def resolve_p53_marker(
|
|
|
597
621
|
video_tracker = ProcessingTracker(file_path=session_data.processed_data.video_processing_tracker_path)
|
|
598
622
|
if behavior_tracker.is_running or video_tracker.is_running:
|
|
599
623
|
# Note, training runtimes do not require suite2p processing.
|
|
624
|
+
message = (
|
|
625
|
+
f"Unable to generate the dataset marker for the session {session_data.session_name} acquired for the "
|
|
626
|
+
f"animal {session_data.animal_id} and {session_data.project_name} project, as it is currently being "
|
|
627
|
+
f"processed by one of the data processing pipelines. Wait until the session is fully processed by all "
|
|
628
|
+
f"pipelines and repeat the command that encountered this error."
|
|
629
|
+
)
|
|
630
|
+
console.echo(message=message, level=LogLevel.ERROR)
|
|
600
631
|
return
|
|
601
632
|
|
|
602
633
|
# Mesoscope experiment sessions require additional processing with suite2p
|
|
@@ -607,11 +638,23 @@ def resolve_p53_marker(
|
|
|
607
638
|
|
|
608
639
|
# Similar to the above, ensures that the session is not being processed with one of the supported pipelines.
|
|
609
640
|
if behavior_tracker.is_running or suite2p_tracker.is_running or video_tracker.is_running:
|
|
641
|
+
message = (
|
|
642
|
+
f"Unable to generate the dataset marker for the session {session_data.session_name} acquired for the "
|
|
643
|
+
f"animal {session_data.animal_id} and {session_data.project_name} project, as it is currently being "
|
|
644
|
+
f"processed by one of the data processing pipelines. Wait until the session is fully processed by all "
|
|
645
|
+
f"pipelines and repeat the command that encountered this error."
|
|
646
|
+
)
|
|
647
|
+
console.echo(message=message, level=LogLevel.ERROR)
|
|
610
648
|
return
|
|
611
649
|
|
|
612
650
|
# If the runtime reached this point, the session is eligible for dataset integration. Creates the p53.bin marker
|
|
613
651
|
# file, preventing the session from being processed again as long as the marker exists.
|
|
614
652
|
session_data.processed_data.p53_path.touch()
|
|
653
|
+
message = (
|
|
654
|
+
f"Dataset marker for the session {session_data.session_name} acquired for the animal "
|
|
655
|
+
f"{session_data.animal_id} and {session_data.project_name} project: Created."
|
|
656
|
+
)
|
|
657
|
+
console.echo(message=message, level=LogLevel.SUCCESS)
|
|
615
658
|
|
|
616
659
|
# If the runtime is configured to generate the project manifest file, attempts to generate and overwrite the
|
|
617
660
|
# existing manifest file for the target project.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sl-shared-assets
|
|
3
|
-
Version: 3.1.
|
|
3
|
+
Version: 3.1.3
|
|
4
4
|
Summary: Provides data acquisition and processing assets shared between Sun (NeuroAI) lab libraries.
|
|
5
5
|
Project-URL: Homepage, https://github.com/Sun-Lab-NBB/sl-shared-assets
|
|
6
6
|
Project-URL: Documentation, https://sl-shared-assets-api-docs.netlify.app/
|
|
@@ -700,7 +700,7 @@ Requires-Dist: natsort==8.4.0
|
|
|
700
700
|
Requires-Dist: numpy==2.2.6
|
|
701
701
|
Requires-Dist: paramiko==3.5.1
|
|
702
702
|
Requires-Dist: polars==1.31.0
|
|
703
|
-
Requires-Dist: pyarrow==
|
|
703
|
+
Requires-Dist: pyarrow==21.0.0
|
|
704
704
|
Requires-Dist: pytz==2025.2
|
|
705
705
|
Requires-Dist: simple-slurm==0.3.6
|
|
706
706
|
Requires-Dist: tqdm==4.67.1
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
sl_shared_assets/__init__.py,sha256=ybThh0XDtijjwahKkSEnnQ44rxrN2SVyjB5dHaXts0E,2391
|
|
2
2
|
sl_shared_assets/__init__.pyi,sha256=Cb-umRqvnynk2udbgqAJ6h5_tiJyvVtWmx0kLKrL2Yg,2678
|
|
3
|
-
sl_shared_assets/cli.py,sha256=
|
|
4
|
-
sl_shared_assets/cli.pyi,sha256
|
|
3
|
+
sl_shared_assets/cli.py,sha256=w7FJW93LkhWbLckonFKj8DFN4yAJLPxPLe0kaMBqFMk,19513
|
|
4
|
+
sl_shared_assets/cli.pyi,sha256=-2-rAGqkF3-EeLLijKsp1sWNxEhZ2zVmaAO4VdvGW6k,5322
|
|
5
5
|
sl_shared_assets/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
6
6
|
sl_shared_assets/data_classes/__init__.py,sha256=mP__bBIIjMf0EETM4PgQzKy1ZKsjp6paRPNDWWbPRV4,1962
|
|
7
7
|
sl_shared_assets/data_classes/__init__.pyi,sha256=J7ZCH9qQ4qz-3Wq9ILdihlmK9zFR3iU1cpLcSaN45Y8,2238
|
|
@@ -9,28 +9,28 @@ sl_shared_assets/data_classes/configuration_data.py,sha256=npMYu9WQMJnoanzC2_5rh
|
|
|
9
9
|
sl_shared_assets/data_classes/configuration_data.pyi,sha256=1_kmBDPGkHmVwXEGYR_3uERBSsenQOTuquMBtjKVTA8,11068
|
|
10
10
|
sl_shared_assets/data_classes/runtime_data.py,sha256=kmXTUk5rDAJBN3XrYLYgusJRfVJ5WiBBk0RPNiSk2pE,16725
|
|
11
11
|
sl_shared_assets/data_classes/runtime_data.pyi,sha256=Hyc-dBePM0xIGgkSIoKmwwUUmdOokm1LUwy1OHHalyU,6771
|
|
12
|
-
sl_shared_assets/data_classes/session_data.py,sha256=
|
|
13
|
-
sl_shared_assets/data_classes/session_data.pyi,sha256=
|
|
12
|
+
sl_shared_assets/data_classes/session_data.py,sha256=lni8TAAxkFukdRSkMSfcrLYgfYcKpPfMAqmM8EDGVYs,49173
|
|
13
|
+
sl_shared_assets/data_classes/session_data.pyi,sha256=5pk7PtZLooj4zmwLf1MImf5WfTIyTURgQVM9rRNoLJA,15960
|
|
14
14
|
sl_shared_assets/data_classes/surgery_data.py,sha256=5B1OPKFq4bnzbAoe-_c5dFV3kbSD5YFzXbX2zXmfGs8,7485
|
|
15
15
|
sl_shared_assets/data_classes/surgery_data.pyi,sha256=rf59lJ3tGSYKHQlEGXg75MnjajBwl0DYhL4TClAO4SM,2605
|
|
16
16
|
sl_shared_assets/server/__init__.py,sha256=GOQ7wWjiS5Xg_WgTqeEqCTRF9ms9GXx0nffCr-BmKsA,453
|
|
17
17
|
sl_shared_assets/server/__init__.pyi,sha256=Zc12G90fZdgEMwaVZbFzrRVV1wH_LEj3sxaV3lhk1Cw,316
|
|
18
18
|
sl_shared_assets/server/job.py,sha256=wZbppMrv6fqch79bKLjOGQ9AYfjiDKDnTyUe7xgAT44,19461
|
|
19
19
|
sl_shared_assets/server/job.pyi,sha256=wop4ulVY2u6eb3twajeA9MS0EAtNb89aA56pPoGF1Xc,11673
|
|
20
|
-
sl_shared_assets/server/server.py,sha256=
|
|
21
|
-
sl_shared_assets/server/server.pyi,sha256=
|
|
20
|
+
sl_shared_assets/server/server.py,sha256=AuoPy4LUPG19oYOnQ61z8s4S3TSXix_DjF7eTtVjDSY,34764
|
|
21
|
+
sl_shared_assets/server/server.pyi,sha256=K42zwzaZk13LH964fex3sK2kCL_Ulis_GualZkZG-NA,15828
|
|
22
22
|
sl_shared_assets/tools/__init__.py,sha256=i-oUVw_un3lzyyII4Sc75s4BnUfZh_aUbQe6dP2Vrbc,743
|
|
23
23
|
sl_shared_assets/tools/__init__.pyi,sha256=pi-5AJyQYeuqIFGWpJ_HhUpXLq6P_nItIqDhsdaIJFU,686
|
|
24
24
|
sl_shared_assets/tools/ascension_tools.py,sha256=xI-hrkR9NIgb7lyhj-ntc8tCYQvDEv6YgYJXl1yvxCs,14639
|
|
25
25
|
sl_shared_assets/tools/ascension_tools.pyi,sha256=fs5j7nbnZ4WpgK8D75A7WJcvFMwK_MUO9ULIYo1YkGo,3739
|
|
26
26
|
sl_shared_assets/tools/packaging_tools.py,sha256=VxQoluGPDUWjPj1ftEt2dvUcdmj0g7T1frGZhZPM8NE,7541
|
|
27
27
|
sl_shared_assets/tools/packaging_tools.pyi,sha256=vgGbAQCExwg-0A5F72MzEhzHxu97Nqg1yuz-5P89ycU,3118
|
|
28
|
-
sl_shared_assets/tools/project_management_tools.py,sha256=
|
|
28
|
+
sl_shared_assets/tools/project_management_tools.py,sha256=Gyp_LrYi0H09-sSl-LenimEw-4lyXydlOE47wMEuUQg,34965
|
|
29
29
|
sl_shared_assets/tools/project_management_tools.pyi,sha256=r45nLPP51mrtn0ajm9iSVq-aR37CS71DGZuRXqd29Zc,11377
|
|
30
30
|
sl_shared_assets/tools/transfer_tools.py,sha256=vqYO4sERZV0W1DFNFnTpJA6QBZ4QJA94a2TyUhZW2Qk,6605
|
|
31
31
|
sl_shared_assets/tools/transfer_tools.pyi,sha256=WtUGfaKV9FP_CnhBg_UvclpuDvOlEESOSMlEDtWpOLg,3293
|
|
32
|
-
sl_shared_assets-3.1.
|
|
33
|
-
sl_shared_assets-3.1.
|
|
34
|
-
sl_shared_assets-3.1.
|
|
35
|
-
sl_shared_assets-3.1.
|
|
36
|
-
sl_shared_assets-3.1.
|
|
32
|
+
sl_shared_assets-3.1.3.dist-info/METADATA,sha256=OW1w-PlNKnEDMaVh-mAANdk0cO_KZhZGxn_0-stSd2g,56944
|
|
33
|
+
sl_shared_assets-3.1.3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
34
|
+
sl_shared_assets-3.1.3.dist-info/entry_points.txt,sha256=UmO1rl7ly9N7HWPwWyP9E0b5KBUStpBo4TRoqNtizDY,430
|
|
35
|
+
sl_shared_assets-3.1.3.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
|
36
|
+
sl_shared_assets-3.1.3.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|