aind-data-transfer-service 1.17.2__tar.gz → 1.18.0__tar.gz

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 aind-data-transfer-service might be problematic. Click here for more details.

Files changed (35) hide show
  1. {aind_data_transfer_service-1.17.2/src/aind_data_transfer_service.egg-info → aind_data_transfer_service-1.18.0}/PKG-INFO +4 -6
  2. {aind_data_transfer_service-1.17.2 → aind_data_transfer_service-1.18.0}/pyproject.toml +3 -5
  3. {aind_data_transfer_service-1.17.2 → aind_data_transfer_service-1.18.0}/src/aind_data_transfer_service/__init__.py +2 -1
  4. {aind_data_transfer_service-1.17.2 → aind_data_transfer_service-1.18.0}/src/aind_data_transfer_service/configs/csv_handler.py +10 -5
  5. {aind_data_transfer_service-1.17.2 → aind_data_transfer_service-1.18.0}/src/aind_data_transfer_service/configs/job_upload_template.py +2 -1
  6. aind_data_transfer_service-1.18.0/src/aind_data_transfer_service/configs/platforms_v1.py +177 -0
  7. {aind_data_transfer_service-1.17.2 → aind_data_transfer_service-1.18.0}/src/aind_data_transfer_service/log_handler.py +3 -3
  8. {aind_data_transfer_service-1.17.2 → aind_data_transfer_service-1.18.0}/src/aind_data_transfer_service/models/core.py +25 -4
  9. {aind_data_transfer_service-1.17.2 → aind_data_transfer_service-1.18.0}/src/aind_data_transfer_service/server.py +174 -447
  10. {aind_data_transfer_service-1.17.2 → aind_data_transfer_service-1.18.0/src/aind_data_transfer_service.egg-info}/PKG-INFO +4 -6
  11. {aind_data_transfer_service-1.17.2 → aind_data_transfer_service-1.18.0}/src/aind_data_transfer_service.egg-info/SOURCES.txt +2 -7
  12. {aind_data_transfer_service-1.17.2 → aind_data_transfer_service-1.18.0}/src/aind_data_transfer_service.egg-info/requires.txt +2 -4
  13. {aind_data_transfer_service-1.17.2 → aind_data_transfer_service-1.18.0}/tests/test_core.py +33 -7
  14. {aind_data_transfer_service-1.17.2 → aind_data_transfer_service-1.18.0}/tests/test_csv_handler.py +1 -1
  15. aind_data_transfer_service-1.18.0/tests/test_proxy.py +54 -0
  16. {aind_data_transfer_service-1.17.2 → aind_data_transfer_service-1.18.0}/tests/test_server.py +78 -768
  17. aind_data_transfer_service-1.17.2/src/aind_data_transfer_service/configs/job_configs.py +0 -545
  18. aind_data_transfer_service-1.17.2/src/aind_data_transfer_service/hpc/__init__.py +0 -1
  19. aind_data_transfer_service-1.17.2/src/aind_data_transfer_service/hpc/client.py +0 -154
  20. aind_data_transfer_service-1.17.2/src/aind_data_transfer_service/hpc/models.py +0 -492
  21. aind_data_transfer_service-1.17.2/tests/test_configs.py +0 -361
  22. aind_data_transfer_service-1.17.2/tests/test_hpc_client.py +0 -174
  23. aind_data_transfer_service-1.17.2/tests/test_hpc_models.py +0 -139
  24. {aind_data_transfer_service-1.17.2 → aind_data_transfer_service-1.18.0}/LICENSE +0 -0
  25. {aind_data_transfer_service-1.17.2 → aind_data_transfer_service-1.18.0}/README.md +0 -0
  26. {aind_data_transfer_service-1.17.2 → aind_data_transfer_service-1.18.0}/setup.cfg +0 -0
  27. {aind_data_transfer_service-1.17.2 → aind_data_transfer_service-1.18.0}/setup.py +0 -0
  28. {aind_data_transfer_service-1.17.2 → aind_data_transfer_service-1.18.0}/src/aind_data_transfer_service/configs/__init__.py +0 -0
  29. {aind_data_transfer_service-1.17.2 → aind_data_transfer_service-1.18.0}/src/aind_data_transfer_service/models/__init__.py +0 -0
  30. {aind_data_transfer_service-1.17.2 → aind_data_transfer_service-1.18.0}/src/aind_data_transfer_service/models/internal.py +0 -0
  31. {aind_data_transfer_service-1.17.2 → aind_data_transfer_service-1.18.0}/src/aind_data_transfer_service.egg-info/dependency_links.txt +0 -0
  32. {aind_data_transfer_service-1.17.2 → aind_data_transfer_service-1.18.0}/src/aind_data_transfer_service.egg-info/top_level.txt +0 -0
  33. {aind_data_transfer_service-1.17.2 → aind_data_transfer_service-1.18.0}/tests/test_internal.py +0 -0
  34. {aind_data_transfer_service-1.17.2 → aind_data_transfer_service-1.18.0}/tests/test_job_upload_template.py +0 -0
  35. {aind_data_transfer_service-1.17.2 → aind_data_transfer_service-1.18.0}/tests/test_log_handler.py +0 -0
@@ -1,14 +1,14 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aind-data-transfer-service
3
- Version: 1.17.2
3
+ Version: 1.18.0
4
4
  Summary: Service that handles requests to upload data to the cloud
5
5
  Author: Allen Institute for Neural Dynamics
6
6
  License: MIT
7
7
  Classifier: Programming Language :: Python :: 3
8
- Requires-Python: >=3.9
8
+ Requires-Python: >=3.10
9
9
  Description-Content-Type: text/markdown
10
10
  License-File: LICENSE
11
- Requires-Dist: aind-data-schema-models<1.0.0,>=0.3.2
11
+ Requires-Dist: aind-data-schema-models>=0.3.2
12
12
  Requires-Dist: email-validator
13
13
  Requires-Dist: pydantic>=2.0
14
14
  Requires-Dist: pydantic-settings>=2.0
@@ -23,9 +23,7 @@ Provides-Extra: docs
23
23
  Requires-Dist: Sphinx; extra == "docs"
24
24
  Requires-Dist: furo; extra == "docs"
25
25
  Provides-Extra: server
26
- Requires-Dist: aind-data-schema<2.0,>=1.0.0; extra == "server"
27
- Requires-Dist: aind-data-transfer-models==0.17.0; extra == "server"
28
- Requires-Dist: aind-metadata-mapper>=0.23.0; extra == "server"
26
+ Requires-Dist: aind-data-schema==2.0.0; extra == "server"
29
27
  Requires-Dist: boto3; extra == "server"
30
28
  Requires-Dist: boto3-stubs[ssm]; extra == "server"
31
29
  Requires-Dist: fastapi>=0.115.13; extra == "server"
@@ -6,7 +6,7 @@ build-backend = "setuptools.build_meta"
6
6
  name = "aind-data-transfer-service"
7
7
  description = "Service that handles requests to upload data to the cloud"
8
8
  license = {text = "MIT"}
9
- requires-python = ">=3.9"
9
+ requires-python = ">=3.10"
10
10
  authors = [
11
11
  {name = "Allen Institute for Neural Dynamics"}
12
12
  ]
@@ -17,7 +17,7 @@ readme = "README.md"
17
17
  dynamic = ["version"]
18
18
 
19
19
  dependencies = [
20
- 'aind-data-schema-models>=0.3.2,<1.0.0',
20
+ 'aind-data-schema-models>=0.3.2',
21
21
  'email-validator',
22
22
  'pydantic>=2.0',
23
23
  'pydantic-settings>=2.0',
@@ -39,9 +39,7 @@ docs = [
39
39
  ]
40
40
 
41
41
  server = [
42
- 'aind-data-schema>=1.0.0,<2.0',
43
- 'aind-data-transfer-models==0.17.0',
44
- 'aind-metadata-mapper>=0.23.0',
42
+ 'aind-data-schema==2.0.0',
45
43
  'boto3',
46
44
  'boto3-stubs[ssm]',
47
45
  'fastapi>=0.115.13',
@@ -1,7 +1,8 @@
1
1
  """Init package"""
2
+
2
3
  import os
3
4
 
4
- __version__ = "1.17.2"
5
+ __version__ = "1.18.0"
5
6
 
6
7
  # Global constants
7
8
  OPEN_DATA_BUCKET_NAME = os.getenv("OPEN_DATA_BUCKET_NAME", "open")
@@ -7,8 +7,8 @@ from datetime import datetime
7
7
  from typing import Any, Dict
8
8
 
9
9
  from aind_data_schema_models.modalities import Modality
10
- from aind_data_schema_models.platforms import Platform
11
10
 
11
+ from aind_data_transfer_service.configs.platforms_v1 import Platform
12
12
  from aind_data_transfer_service.models.core import Task, UploadJobConfigsV2
13
13
 
14
14
  DATETIME_PATTERN2 = re.compile(
@@ -147,13 +147,18 @@ def map_csv_row_to_job(row: dict) -> UploadJobConfigsV2:
147
147
  "gather_preliminary_metadata": metadata_task,
148
148
  "check_s3_folder_exists": check_s3_folder_exists_task,
149
149
  "modality_transformation_settings": modality_tasks,
150
- "codeocean_pipeline_settings": None
151
- if codeocean_tasks == dict()
152
- else codeocean_tasks,
150
+ "codeocean_pipeline_settings": (
151
+ None if codeocean_tasks == dict() else codeocean_tasks
152
+ ),
153
153
  }
154
+ platform = (
155
+ None
156
+ if job_configs.get("platform") is None
157
+ else Platform.from_abbreviation(job_configs["platform"])
158
+ )
154
159
  job_configs.update(
155
160
  {
156
- "platform": Platform.from_abbreviation(job_configs["platform"]),
161
+ "platform": platform,
157
162
  "modalities": [
158
163
  Modality.from_abbreviation(m) for m in modality_tasks.keys()
159
164
  ],
@@ -5,13 +5,14 @@ from io import BytesIO
5
5
  from typing import Any, ClassVar, Dict, List
6
6
 
7
7
  from aind_data_schema_models.modalities import Modality
8
- from aind_data_schema_models.platforms import Platform
9
8
  from openpyxl import Workbook
10
9
  from openpyxl.styles import Font
11
10
  from openpyxl.utils import get_column_letter
12
11
  from openpyxl.worksheet.datavalidation import DataValidation
13
12
  from pydantic import BaseModel
14
13
 
14
+ from aind_data_transfer_service.configs.platforms_v1 import Platform
15
+
15
16
 
16
17
  class JobUploadTemplate(BaseModel):
17
18
  """Class to configure and create xlsx job upload template"""
@@ -0,0 +1,177 @@
1
+ """Platforms"""
2
+
3
+ from typing import Literal, Union
4
+
5
+ from pydantic import BaseModel, ConfigDict, Field
6
+ from typing_extensions import Annotated
7
+
8
+
9
+ class _PlatformModel(BaseModel):
10
+ """Base model for platform"""
11
+
12
+ model_config = ConfigDict(frozen=True)
13
+ name: str
14
+ abbreviation: str
15
+
16
+
17
+ class _Behavior(_PlatformModel):
18
+ """Model behavior"""
19
+
20
+ name: Literal["Behavior platform"] = "Behavior platform"
21
+ abbreviation: Literal["behavior"] = "behavior"
22
+
23
+
24
+ class _Confocal(_PlatformModel):
25
+ """Model confocal"""
26
+
27
+ name: Literal["Confocal microscopy platform"] = (
28
+ "Confocal microscopy platform"
29
+ )
30
+ abbreviation: Literal["confocal"] = "confocal"
31
+
32
+
33
+ class _Ecephys(_PlatformModel):
34
+ """Model ecephys"""
35
+
36
+ name: Literal["Electrophysiology platform"] = "Electrophysiology platform"
37
+ abbreviation: Literal["ecephys"] = "ecephys"
38
+
39
+
40
+ class _Exaspim(_PlatformModel):
41
+ """Model exaSPIM"""
42
+
43
+ name: Literal["ExaSPIM platform"] = "ExaSPIM platform"
44
+ abbreviation: Literal["exaSPIM"] = "exaSPIM"
45
+
46
+
47
+ class _Fip(_PlatformModel):
48
+ """Model FIP"""
49
+
50
+ name: Literal["Frame-projected independent-fiber photometry platform"] = (
51
+ "Frame-projected independent-fiber photometry platform"
52
+ )
53
+ abbreviation: Literal["FIP"] = "FIP"
54
+
55
+
56
+ class _Hcr(_PlatformModel):
57
+ """Model HCR"""
58
+
59
+ name: Literal["Hybridization chain reaction platform"] = (
60
+ "Hybridization chain reaction platform"
61
+ )
62
+ abbreviation: Literal["HCR"] = "HCR"
63
+
64
+
65
+ class _Hsfp(_PlatformModel):
66
+ """Model HSFP"""
67
+
68
+ name: Literal["Hyperspectral fiber photometry platform"] = (
69
+ "Hyperspectral fiber photometry platform"
70
+ )
71
+ abbreviation: Literal["HSFP"] = "HSFP"
72
+
73
+
74
+ class _Isi(_PlatformModel):
75
+ """Model ISI"""
76
+
77
+ name: Literal["Intrinsic signal imaging platform"] = (
78
+ "Intrinsic signal imaging platform"
79
+ )
80
+ abbreviation: Literal["ISI"] = "ISI"
81
+
82
+
83
+ class _Merfish(_PlatformModel):
84
+ """Model MERFISH"""
85
+
86
+ name: Literal["MERFISH platform"] = "MERFISH platform"
87
+ abbreviation: Literal["MERFISH"] = "MERFISH"
88
+
89
+
90
+ class _Mri(_PlatformModel):
91
+ """Model MRI"""
92
+
93
+ name: Literal["Magnetic resonance imaging platform"] = (
94
+ "Magnetic resonance imaging platform"
95
+ )
96
+ abbreviation: Literal["MRI"] = "MRI"
97
+
98
+
99
+ class _Mesospim(_PlatformModel):
100
+ """Model mesoSPIM"""
101
+
102
+ name: Literal["MesoSPIM platform"] = "MesoSPIM platform"
103
+ abbreviation: Literal["mesoSPIM"] = "mesoSPIM"
104
+
105
+
106
+ class _Motor_Observatory(_PlatformModel):
107
+ """Model motor-observatory"""
108
+
109
+ name: Literal["Motor observatory platform"] = "Motor observatory platform"
110
+ abbreviation: Literal["motor-observatory"] = "motor-observatory"
111
+
112
+
113
+ class _Multiplane_Ophys(_PlatformModel):
114
+ """Model multiplane-ophys"""
115
+
116
+ name: Literal["Multiplane optical physiology platform"] = (
117
+ "Multiplane optical physiology platform"
118
+ )
119
+ abbreviation: Literal["multiplane-ophys"] = "multiplane-ophys"
120
+
121
+
122
+ class _Slap2(_PlatformModel):
123
+ """Model SLAP2"""
124
+
125
+ name: Literal["SLAP2 platform"] = "SLAP2 platform"
126
+ abbreviation: Literal["SLAP2"] = "SLAP2"
127
+
128
+
129
+ class _Single_Plane_Ophys(_PlatformModel):
130
+ """Model single-plane-ophys"""
131
+
132
+ name: Literal["Single-plane optical physiology platform"] = (
133
+ "Single-plane optical physiology platform"
134
+ )
135
+ abbreviation: Literal["single-plane-ophys"] = "single-plane-ophys"
136
+
137
+
138
+ class _Smartspim(_PlatformModel):
139
+ """Model SmartSPIM"""
140
+
141
+ name: Literal["SmartSPIM platform"] = "SmartSPIM platform"
142
+ abbreviation: Literal["SmartSPIM"] = "SmartSPIM"
143
+
144
+
145
+ class Platform:
146
+ """Platforms"""
147
+
148
+ BEHAVIOR = _Behavior()
149
+ CONFOCAL = _Confocal()
150
+ ECEPHYS = _Ecephys()
151
+ EXASPIM = _Exaspim()
152
+ FIP = _Fip()
153
+ HCR = _Hcr()
154
+ HSFP = _Hsfp()
155
+ ISI = _Isi()
156
+ MERFISH = _Merfish()
157
+ MRI = _Mri()
158
+ MESOSPIM = _Mesospim()
159
+ MOTOR_OBSERVATORY = _Motor_Observatory()
160
+ MULTIPLANE_OPHYS = _Multiplane_Ophys()
161
+ SLAP2 = _Slap2()
162
+ SINGLE_PLANE_OPHYS = _Single_Plane_Ophys()
163
+ SMARTSPIM = _Smartspim()
164
+
165
+ ALL = tuple(_PlatformModel.__subclasses__())
166
+
167
+ ONE_OF = Annotated[
168
+ Union[tuple(_PlatformModel.__subclasses__())],
169
+ Field(discriminator="name"),
170
+ ]
171
+
172
+ abbreviation_map = {m().abbreviation: m() for m in ALL}
173
+
174
+ @classmethod
175
+ def from_abbreviation(cls, abbreviation: str):
176
+ """Get platform from abbreviation"""
177
+ return cls.abbreviation_map.get(abbreviation, None)
@@ -17,9 +17,9 @@ class LoggingConfigs(BaseSettings):
17
17
  loki_uri: Optional[str] = Field(
18
18
  default=None, description="URI of Loki logging server."
19
19
  )
20
- log_level: Literal[
21
- "DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"
22
- ] = Field(default="INFO", description="Log level")
20
+ log_level: Literal["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"] = (
21
+ Field(default="DEBUG", description="Log level")
22
+ )
23
23
 
24
24
  @property
25
25
  def app_name(self):
@@ -8,7 +8,6 @@ from typing import Any, Dict, List, Literal, Optional, Set, Union
8
8
 
9
9
  from aind_data_schema_models.data_name_patterns import build_data_name
10
10
  from aind_data_schema_models.modalities import Modality
11
- from aind_data_schema_models.platforms import Platform
12
11
  from pydantic import (
13
12
  BaseModel,
14
13
  ConfigDict,
@@ -21,6 +20,8 @@ from pydantic import (
21
20
  )
22
21
  from pydantic_settings import BaseSettings
23
22
 
23
+ from aind_data_transfer_service.configs.platforms_v1 import Platform
24
+
24
25
  _validation_context: ContextVar[Union[Dict[str, Any], None]] = ContextVar(
25
26
  "_validation_context", default=None
26
27
  )
@@ -163,8 +164,13 @@ class UploadJobConfigsV2(BaseSettings):
163
164
  project_name: str = Field(
164
165
  ..., description="Name of project", title="Project Name"
165
166
  )
166
- platform: Platform.ONE_OF = Field(
167
- ..., description="Platform", title="Platform"
167
+ platform: Optional[Platform.ONE_OF] = Field(
168
+ default=None,
169
+ title="Platform",
170
+ description=(
171
+ "Legacy field required for aind-data-schema v1. Will be removed"
172
+ " in future versions."
173
+ ),
168
174
  )
169
175
  modalities: List[Modality.ONE_OF] = Field(
170
176
  ...,
@@ -190,11 +196,26 @@ class UploadJobConfigsV2(BaseSettings):
190
196
  @computed_field
191
197
  def s3_prefix(self) -> str:
192
198
  """Construct s3_prefix from configs."""
199
+ if self.platform is not None:
200
+ label = f"{self.platform.abbreviation}_{self.subject_id}"
201
+ else:
202
+ label = self.subject_id
193
203
  return build_data_name(
194
- label=f"{self.platform.abbreviation}_{self.subject_id}",
204
+ label=label,
195
205
  creation_datetime=self.acq_datetime,
196
206
  )
197
207
 
208
+ @field_validator("platform", mode="before")
209
+ def validate_platform(cls, v):
210
+ """
211
+ For backwards compatibility, allow a user to input an
212
+ aind-data-schema-model platform and then convert it.
213
+ """
214
+ if type(v).__module__ == "aind_data_schema_models.platforms":
215
+ return v.model_dump()
216
+ else:
217
+ return v
218
+
198
219
  @field_validator("job_type", "project_name", mode="before")
199
220
  def validate_with_context(cls, v: str, info: ValidationInfo) -> str:
200
221
  """