tol-sdk 1.7.4__py3-none-any.whl → 1.7.5b2__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 (50) hide show
  1. tol/api_base/__init__.py +1 -0
  2. tol/api_base/blueprint.py +19 -8
  3. tol/{s3/data_upload/blueprint.py → api_base/data_upload.py} +21 -6
  4. tol/api_base/pipeline_steps.py +4 -4
  5. tol/api_client/api_datasource.py +8 -8
  6. tol/api_client/converter.py +38 -52
  7. tol/api_client/factory.py +21 -19
  8. tol/api_client/parser.py +138 -98
  9. tol/api_client/view.py +118 -43
  10. tol/core/__init__.py +2 -1
  11. tol/core/data_object.py +27 -9
  12. tol/core/data_object_converter.py +37 -2
  13. tol/core/factory.py +51 -62
  14. tol/core/validate.py +1 -0
  15. tol/ena/client.py +61 -10
  16. tol/ena/ena_datasource.py +16 -10
  17. tol/ena/ena_methods.py +33 -32
  18. tol/ena/parser.py +15 -2
  19. tol/flows/converters/__init__.py +2 -0
  20. tol/flows/converters/incoming_sample_to_ena_sample_converter.py +130 -0
  21. tol/flows/converters/incoming_sample_to_incoming_sample_with_lists_converter.py +46 -0
  22. tol/s3/__init__.py +0 -1
  23. tol/sql/model.py +1 -1
  24. tol/sql/pipeline_step/factory.py +1 -1
  25. tol/sql/sql_converter.py +7 -1
  26. tol/validators/__init__.py +12 -1
  27. tol/validators/allowed_keys.py +17 -12
  28. tol/validators/allowed_values.py +21 -63
  29. tol/validators/allowed_values_from_datasource.py +89 -0
  30. tol/validators/assert_on_condition.py +56 -0
  31. tol/validators/ena_checklist.py +73 -0
  32. tol/validators/ena_submittable.py +61 -0
  33. tol/validators/interfaces/__init__.py +5 -0
  34. tol/validators/interfaces/condition_evaluator.py +102 -0
  35. tol/validators/min_one_valid_value.py +55 -0
  36. tol/validators/mutually_exclusive.py +111 -0
  37. tol/validators/regex.py +30 -23
  38. tol/validators/regex_by_value.py +33 -33
  39. tol/validators/specimens_have_same_taxon.py +60 -0
  40. tol/validators/sts_fields.py +88 -0
  41. tol/validators/tolid.py +110 -0
  42. tol/validators/unique_values.py +25 -17
  43. tol/validators/unique_whole_organisms.py +109 -0
  44. {tol_sdk-1.7.4.dist-info → tol_sdk-1.7.5b2.dist-info}/METADATA +1 -1
  45. {tol_sdk-1.7.4.dist-info → tol_sdk-1.7.5b2.dist-info}/RECORD +49 -36
  46. tol/s3/data_upload/__init__.py +0 -3
  47. {tol_sdk-1.7.4.dist-info → tol_sdk-1.7.5b2.dist-info}/WHEEL +0 -0
  48. {tol_sdk-1.7.4.dist-info → tol_sdk-1.7.5b2.dist-info}/entry_points.txt +0 -0
  49. {tol_sdk-1.7.4.dist-info → tol_sdk-1.7.5b2.dist-info}/licenses/LICENSE +0 -0
  50. {tol_sdk-1.7.4.dist-info → tol_sdk-1.7.5b2.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,110 @@
1
+ # SPDX-FileCopyrightText: 2025 Genome Research Ltd.
2
+ #
3
+ # SPDX-License-Identifier: MIT
4
+
5
+ from dataclasses import dataclass
6
+ from typing import Any, Dict
7
+
8
+ from tol.core import DataObject, DataSource
9
+ from tol.core import DataSourceError, DataSourceFilter
10
+ from tol.core.validate import Validator
11
+ from tol.sources.tolid import tolid
12
+
13
+
14
+ class TolidValidator(Validator):
15
+ """
16
+ Validates that a stream of `DataObject` instances
17
+ contains unique Tol IDs.
18
+ """
19
+ @dataclass(slots=True, frozen=True, kw_only=True)
20
+ class Config:
21
+ species_id_field: str
22
+ specimen_id_field: str
23
+ error_ignore_field: str
24
+ error_ignore_value: str
25
+ warning_detail: str = 'Species not found in Tol ID source'
26
+
27
+ __slots__ = ['__config', '__datasource', '__cached_species_id', '__cached_tolids']
28
+ __config: Config
29
+ __datasource: DataSource
30
+ __cached_species_ids: Dict[str, Any]
31
+ __cached_tolids: Dict[str, Any]
32
+
33
+ def __init__(
34
+ self,
35
+ config: Config,
36
+ datasource=tolid(),
37
+ ) -> None:
38
+
39
+ super().__init__()
40
+
41
+ self.__config = config
42
+ self.__datasource = datasource
43
+ self.__cached_species_ids = {}
44
+ self.__cached_tolids = {}
45
+
46
+ def _validate_data_object(
47
+ self,
48
+ obj: DataObject
49
+ ) -> None:
50
+ self.__warning_on_species_not_in_tolid(obj=obj)
51
+ self.__error_on_specimen_id_and_taxon_not_matching_tolid(obj=obj)
52
+
53
+ def __warning_on_species_not_in_tolid(
54
+ self,
55
+ obj: DataObject,
56
+ ) -> None:
57
+
58
+ obj_species_id = obj.get_field_by_name(self.__config.species_id_field)
59
+ if self.__config.species_id_field in obj.attributes:
60
+ try:
61
+ if obj_species_id not in self.__cached_species_ids:
62
+ self.__cached_species_ids[obj_species_id] = (
63
+ self.__datasource.get_one('species', obj_species_id) is not None)
64
+
65
+ except DataSourceError as e:
66
+ if e.status_code == 404:
67
+ self.__cached_species_ids[obj_species_id] = False
68
+
69
+ species_in_tolid = self.__cached_species_ids[obj_species_id]
70
+ if species_in_tolid is False:
71
+ self.add_warning(
72
+ object_id=obj.id,
73
+ detail=self.__config.warning_detail,
74
+ field=self.__config.species_id_field,
75
+ )
76
+
77
+ def __error_on_specimen_id_and_taxon_not_matching_tolid(
78
+ self,
79
+ obj: DataObject,
80
+ ) -> None:
81
+
82
+ if (obj.get_field_by_name(self.__config.error_ignore_field) is
83
+ self.__config.error_ignore_value):
84
+ return
85
+
86
+ if self.__config.specimen_id_field in obj.attributes:
87
+ specimen_id = obj.get_field_by_name(self.__config.specimen_id_field)
88
+ if specimen_id not in self.__cached_tolids:
89
+ f = DataSourceFilter()
90
+ f.and_ = {'specimen_id': {'eq': {'value': specimen_id}}}
91
+ self.__cached_tolids[specimen_id] = list(self.__datasource.get_list(
92
+ object_type='specimen',
93
+ object_filters=f
94
+ ))
95
+
96
+ if (len(self.__cached_tolids[specimen_id]) == 0):
97
+ return
98
+ else:
99
+ taxons = set()
100
+ for tolid_ in self.__cached_tolids[specimen_id]:
101
+ taxons.add(str(tolid_.species.id))
102
+
103
+ if str(obj.get_field_by_name(self.__config.species_id_field)) not in taxons:
104
+ self.add_error(
105
+ object_id=obj.id,
106
+ detail=f'Specimen ID {specimen_id} does not match Taxon ID '
107
+ f'{obj.get_field_by_name(self.__config.species_id_field)}'
108
+ 'in TolID source',
109
+ field=[self.__config.specimen_id_field, self.__config.species_id_field]
110
+ )
@@ -2,6 +2,9 @@
2
2
  #
3
3
  # SPDX-License-Identifier: MIT
4
4
 
5
+ from dataclasses import dataclass
6
+ from typing import Dict, List, Set
7
+
5
8
  from tol.core import DataObject
6
9
  from tol.core.validate import Validator
7
10
 
@@ -11,23 +14,28 @@ class UniqueValuesValidator(Validator):
11
14
  Validates that a stream of `DataObject` instances
12
15
  contains unique values for specified keys.
13
16
  """
17
+ @dataclass(slots=True, frozen=True, kw_only=True)
18
+ class Config:
19
+ unique_keys: List[List[str] | str]
20
+ detail: str = 'Value is not unique'
21
+ is_error: bool = True
22
+
23
+ __slots__ = ['__config', '__duplicates', '__existing_values']
24
+ __config: Config
25
+ __duplicates: Dict[str, List[str]]
26
+ __existing_values: Dict[str, Set]
14
27
 
15
28
  def __init__(
16
29
  self,
17
- unique_keys: list[list[str] | str],
18
- *,
19
- detail: str = 'Value is not unique',
20
- is_error: bool = True,
30
+ config: Config
21
31
  ) -> None:
22
32
 
23
33
  super().__init__()
24
34
 
25
- self.__keys = unique_keys
26
- self.__detail = detail
27
- self.__is_error = is_error
28
- self.__duplicates: dict[str, list[str]] = {}
29
- self.__existing_values: dict[str, set] = {}
30
- for key in self.__keys:
35
+ self.__config = config
36
+ self.__duplicates = {}
37
+ self.__existing_values = {}
38
+ for key in self.__config.unique_keys:
31
39
  if isinstance(key, str):
32
40
  self.__existing_values[key] = set()
33
41
  elif isinstance(key, list):
@@ -39,13 +47,13 @@ class UniqueValuesValidator(Validator):
39
47
  obj: DataObject
40
48
  ) -> None:
41
49
 
42
- for unique_key in self.__keys:
50
+ for unique_key in self.__config.unique_keys:
43
51
  if isinstance(unique_key, list):
44
52
  concat = ''
45
53
  for key in unique_key:
46
54
  concat = concat + '/' + (str(obj.attributes[key]))
47
55
  if concat in self.__existing_values['/'.join(unique_key)]:
48
- self._duplicate_checks(
56
+ self.__duplicate_checks(
49
57
  key=key,
50
58
  value=concat
51
59
  )
@@ -54,14 +62,14 @@ class UniqueValuesValidator(Validator):
54
62
 
55
63
  else:
56
64
  if obj.attributes[unique_key] in self.__existing_values[unique_key]:
57
- self._duplicate_checks(
65
+ self.__duplicate_checks(
58
66
  key=unique_key,
59
67
  value=obj.attributes[unique_key]
60
68
  )
61
69
  else:
62
70
  self.__existing_values[unique_key].add(obj.attributes[unique_key])
63
71
 
64
- def _duplicate_checks(
72
+ def __duplicate_checks(
65
73
  self,
66
74
  key: str,
67
75
  value: str
@@ -86,15 +94,15 @@ class UniqueValuesValidator(Validator):
86
94
  key: str,
87
95
  ) -> None:
88
96
 
89
- if self.__is_error:
97
+ if self.__config.is_error:
90
98
  self.add_error(
91
99
  object_id=obj.id,
92
- detail=self.__detail,
100
+ detail=self.__config.detail,
93
101
  field=key,
94
102
  )
95
103
  else:
96
104
  self.add_warning(
97
105
  object_id=obj.id,
98
- detail=self.__detail,
106
+ detail=self.__config.detail,
99
107
  field=key,
100
108
  )
@@ -0,0 +1,109 @@
1
+ # SPDX-FileCopyrightText: 2025 Genome Research Ltd.
2
+ #
3
+ # SPDX-License-Identifier: MIT
4
+
5
+ from dataclasses import dataclass
6
+ from typing import List
7
+
8
+ from tol.core import Validator
9
+ from tol.core.data_object import DataObject
10
+
11
+
12
+ class UniqueWholeOrganismsValidator(Validator):
13
+ """
14
+ Validates an incoming stream of `DataObject` instances.
15
+ For each data object (sample) not a SYMBIONT, it checks:
16
+ 1. There are no two samples with organism part WHOLE_ORGANISM with the same SPECIMEN_ID
17
+ 2. There are no samples with organism part *not* WHOLE_ORGANISM that have a SPECIMEN_ID
18
+ the same as a WHOLE_ORGANISM in the manifest.
19
+ """
20
+ @dataclass(slots=True, frozen=True, kw_only=True)
21
+ class Config:
22
+ symbiont_field: str
23
+ organism_part_field: str
24
+ specimen_id_field: str
25
+
26
+ __slots__ = ['__config', '__whole_organisms', '__part_organisms']
27
+ __config: Config
28
+ __whole_organisms: List[str]
29
+ __part_organisms: List[str]
30
+
31
+ def __init__(self, config: Config) -> None:
32
+ super().__init__()
33
+ self.__whole_organisms = []
34
+ self.__part_organisms = []
35
+ self.__config = config
36
+
37
+ def _validate_data_object(self, obj: DataObject) -> None:
38
+ # This function uses a bit of a confusing method for its validation, so I'm going to
39
+ # leave an explanation here as to how it works for anyone who needs to modify it
40
+ # in the future!
41
+ #
42
+ # In the original code to be adapted, two loops were used. The first looped over each
43
+ # data object whose ORGANISM_PART was 'WHOLE_ORGANISM', adding them to a list. Before it
44
+ # did this though, it would check to see if the SPECIMEN_ID of this data object was already
45
+ # contained in said list (to ensure the specimen IDs were unique). In the second loop, the
46
+ # rest of the data objects (those whose ORGANISM PART was *not* 'WHOLE_ORGANISM') were
47
+ # looped over, each being checked to see if their SPECIMEN_ID was contained in the list
48
+ # (the one containing the whole organisms). In all, this ensures that all whole organisms
49
+ # have unique specimen IDs, and all part organisms do not share the specimen IDs of any of
50
+ # the whole organisms.
51
+ #
52
+ # The issue when adapting this to a Validator to be used in a pipeline, is that this
53
+ # function only takes in one data object at a time, via a generator (to save needing to
54
+ # load many into memory at once). The problem this left us with is that we could no longer
55
+ # achieve the same result by using two passes of the data, as only one pass was feasible.
56
+ #
57
+ # So here's what I ended up with. This validator stores the SPECIMEN_IDs of both all of the
58
+ # whole organisms *and* part organisms. From this, detecting duplicate whole organisms is
59
+ # the same, but detecting whether a part organism shared the SPECIMEN_ID of a whole
60
+ # organism now has two separate cases: when the data object passed into this function is
61
+ # a whole organism, or a part organism. In the case of it being a part organism, a very
62
+ # similar solution to before can be used: we simply check whether self.__whole_organisms
63
+ # conatins the same SPECIMEN_ID. However, for the case where the data object is a whole
64
+ # organism, effectively the inverse is done; it is the self.__part_organisms list that is
65
+ # checked. This covers all cases:
66
+ # 1. There are no duplicates, in which case there will never be a time when the same
67
+ # SPECIMEN_ID will be in both lists.
68
+ # 2. A whole organism is checked, then a part organism with the same SPECIMEN_ID is
69
+ # checked. In this case, self.__whole_organisms will contain the same SPECIMEN_ID,
70
+ # so the duplicate is detected.
71
+ # 3. A part organism is checked, then a whole organism with the same SPECIMEN_ID is
72
+ # checked. In this case, self.__part_organisms will contain the same SPECIMEN_ID,
73
+ # so the duplicate is detected.
74
+ #
75
+ # From Thomas :)
76
+
77
+ # Ensure the data object is not a SYMBIONT, because organism part checks do not apply
78
+ if obj.attributes.get(self.__config.symbiont_field) != 'SYMBIONT':
79
+ specimen_id = obj.attributes.get(self.__config.specimen_id_field)
80
+ if specimen_id is None:
81
+ return
82
+
83
+ organism_part = obj.attributes.get(self.__config.organism_part_field)
84
+ if organism_part == 'WHOLE_ORGANISM':
85
+ if specimen_id in self.__whole_organisms:
86
+ self.add_error(
87
+ object_id=obj.id,
88
+ detail='No two whole organisms can have the same Specimen ID',
89
+ field=self.__config.specimen_id_field,
90
+ )
91
+ if specimen_id in self.__part_organisms:
92
+ self.add_error(
93
+ object_id=obj.id,
94
+ detail='A whole organism cannot have a Specimen ID already used for'
95
+ 'a non-whole organism',
96
+ field=self.__config.specimen_id_field,
97
+ )
98
+
99
+ self.__whole_organisms.append(specimen_id)
100
+ else:
101
+ if specimen_id in self.__whole_organisms:
102
+ self.add_error(
103
+ object_id=obj.id,
104
+ detail='A non-whole organism cannot have a Specimen ID already used for'
105
+ 'a whole organism',
106
+ field=self.__config.specimen_id_field,
107
+ )
108
+
109
+ self.__part_organisms.append(specimen_id)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tol-sdk
3
- Version: 1.7.4
3
+ Version: 1.7.5b2
4
4
  Summary: SDK for interaction with ToL, Sanger and external services
5
5
  Author-email: ToL Platforms Team <tol-platforms@sanger.ac.uk>
6
6
  License: MIT
@@ -4,11 +4,12 @@ tol/markdown.py,sha256=X-ooYUYLkkVS8DyBHYib8d2QBBNMPlBP5_ZQz8-mAYc,570
4
4
  tol/actions/__init__.py,sha256=xOj2kvRYv2GWQLqrpL_xhwZUZDwtOBnxb5CZ9qmP-pk,169
5
5
  tol/actions/action.py,sha256=HlfUsfVGd2vuNAwD_01yo1i32nh6UNrt_ytcY2ladgM,651
6
6
  tol/actions/upsert_action.py,sha256=DnSz1LhHibF0WcK6Qht5eLIGi3PPXc6GSRsd8Y2dZBE,1366
7
- tol/api_base/__init__.py,sha256=xv9kkAyb1Q5vhKgq6f-JpY7lIAla51U-gIpA5U1OfkA,312
7
+ tol/api_base/__init__.py,sha256=K8Gpp7nEROn4t0JzJwEbiR49C3KI091ZxoljgnpXGac,367
8
8
  tol/api_base/action.py,sha256=l3MzD3jSDdYiZs-HCT4YEsXkp34X26k6yWugXrRB2XU,6575
9
- tol/api_base/blueprint.py,sha256=lyNXgyyZ7kEL5uuIuSNkardFy8ZcDIfftt8c5xiRjyA,19061
9
+ tol/api_base/blueprint.py,sha256=AHCvBUwvXbXtKuRv_MmQNtMrXnVEtdNVZMh-_CMsYY0,19345
10
10
  tol/api_base/controller.py,sha256=5Fp2FobjXXPlongu1j7adGJKlSVufW0_jpk_wZIMRa4,26818
11
- tol/api_base/pipeline_steps.py,sha256=Y7tOwaBBanxAqiUrTpmF6yaLkEJI6o0ELnM-2CaCvHs,5832
11
+ tol/api_base/data_upload.py,sha256=z8Kp4BWQ6q06vT9ZwS8cgedWuGxBwZLkT6xpHk1K008,2939
12
+ tol/api_base/pipeline_steps.py,sha256=Y3rcqQh1w4F0tCxMLGI3H8W3pbl54OWLrUYbBR44Y4A,5850
12
13
  tol/api_base/system.py,sha256=c47sbcNaCd3teiJLO-Zwg1cUNvfCvRO4GmKzAMNxZrw,1219
13
14
  tol/api_base/auth/__init__.py,sha256=LNbVtQDlzKWzLoCmxAPSIAcM6mlVMnn0Aj9HFUudseo,460
14
15
  tol/api_base/auth/asserts.py,sha256=3kHP2yW6HZxevIgeO8Rl3iKovi8WHZcguVbPSFUjawQ,2765
@@ -30,15 +31,15 @@ tol/api_base/misc/list_get_parameters.py,sha256=6DtUgfKPTok3utKPOxceJdwV_ZnJ5nis
30
31
  tol/api_base/misc/relation_url.py,sha256=qfo-okp8Gv9-PEDghMfGZ2pHdYbHRhohvA9v3Govtlo,1127
31
32
  tol/api_base/misc/stats_parameters.py,sha256=IVpHqUeGQyjuih59jwqT-fIQMCBeESi2T9b4r9i4J28,1721
32
33
  tol/api_client/__init__.py,sha256=58SAywuMrIUCBAY9us_d_RLTMnaUTYWWts0LRQC5wLo,187
33
- tol/api_client/api_datasource.py,sha256=GOHvAmFzrHdux2wxY-MwUbp6eWbbS01L7FvmVyXJVZM,14330
34
+ tol/api_client/api_datasource.py,sha256=9CPNsujgnp__EwkZGwu9ZTmOxSwOldfLraOEQ7GBLng,14490
34
35
  tol/api_client/client.py,sha256=gcnX4iCZtjnCC6qylizXxLe3l6xLhME6LEJH0UeW7V4,13979
35
- tol/api_client/converter.py,sha256=X6VPk4nrvmXF8EOXy36sn1nvPvYTBYKZ66ofxyQbaY8,4681
36
+ tol/api_client/converter.py,sha256=g32fjqga4mC923n95HmQImPuawMfeb9rQcl3ZxUWP2s,4463
36
37
  tol/api_client/exception.py,sha256=MkvJaIyRVCzQ2rKOYnCOcT747mpOeQwGJJl3Kkb1BsQ,3999
37
- tol/api_client/factory.py,sha256=DIYFmFsQlwOCrUfexiEMBN3ovnreMqUFYNU8hcNvSao,3405
38
+ tol/api_client/factory.py,sha256=WGHA5wio4XS8OHqG07DLSVjehOeAsVoVCc5phAIq4H8,3737
38
39
  tol/api_client/filter.py,sha256=D49RIai5Yj4CiQvIkgaEIXdw_oSU7CD5cn9SdXWRYXU,1474
39
- tol/api_client/parser.py,sha256=67GxGyhb5goVhXQqry7-YKvh9YozC_MkQMFiaAeHPKk,5423
40
+ tol/api_client/parser.py,sha256=88Q2RlPwn9JJsSIukC2_yxfaM2AaXjsGuDOESqY7se4,8351
40
41
  tol/api_client/validate.py,sha256=9wFZotTJ4fI21BdO5AuMZok0rDQ4s8zM_WojLdVvA0A,3071
41
- tol/api_client/view.py,sha256=a0TzPtXhJfVv70exJ86BEZv_oaeXDyitKsj6R5sG3wE,6102
42
+ tol/api_client/view.py,sha256=DvhRTA957Fn5vVPByV7e8ngvJaD9DSa5SaJ48ONWQlU,8753
42
43
  tol/barcodes/__init__.py,sha256=k9KoBO0xJyxg1kanLrN0E3HuVSbbpfSInGEsWX-8UsY,214
43
44
  tol/barcodes/main.py,sha256=QxueF2AdrclIaQuu7W4lb4eF5tU_l-p3UMsDFIYgCfo,6213
44
45
  tol/benchling/__init__.py,sha256=9VIL6PBxvZRaBrN1j2Di75MdEY261kEHs_D-lUutIlg,229
@@ -83,24 +84,24 @@ tol/copo/converter.py,sha256=DnJvIysyVLa1b4hIK0o146ruuxKBYhEDN4kxKxl7Uuc,1127
83
84
  tol/copo/copo_datasource.py,sha256=DYOkaUOO2bdW1rmblci_rt4nBo_1Kb7ztxnthbkC-hA,5193
84
85
  tol/copo/factory.py,sha256=fzYpPxro6M9GHER4uyJ5dugxDobPskc-f6RNZpLc4ZY,2219
85
86
  tol/copo/parser.py,sha256=FRPF0DQNbHTN_nrar80V9a_-3AapXqUErB47zEP0VUQ,2863
86
- tol/core/__init__.py,sha256=svFcEWLhqgA0hLfFkrN9xWaSLqkC2MDHrBSnUjCGYGE,1124
87
+ tol/core/__init__.py,sha256=ifE1Ji2RF-RWNzo3HTsEKfLIpkRrIBNBPKDwpvzPoMk,1149
87
88
  tol/core/attribute_metadata.py,sha256=wYD3NXDdStrpkUZoyTUiEpp7c14f7MLIcyooT1G4GEQ,4091
88
89
  tol/core/core_converter.py,sha256=Gn4J507BtqDjnOWV2MFRYGz8YElJAKQItmnCrD72s7k,4504
89
90
  tol/core/data_loader.py,sha256=k-ET1nIohIz6PcADbEn9Y7k9TupoiBYxKDkcAl_9pGY,14710
90
- tol/core/data_object.py,sha256=KLPSXpg0OM7NpaHkwzfldaI_4521odqABA8SyLjthII,3770
91
- tol/core/data_object_converter.py,sha256=YWlwxDUXZjhkVPbIoVtQNP88vLYeX2vO9CZELNHw4Wo,2840
91
+ tol/core/data_object.py,sha256=GxG04JMcICaiHU1rufkhoD8jb9YQLhE0QWlFU2ZkQsM,4241
92
+ tol/core/data_object_converter.py,sha256=zIGcin3jcoswBfsuUe74C2nxpyzvhHkP4_ZwKZWxh_Y,3765
92
93
  tol/core/data_source_attribute_metadata.py,sha256=NHvJ_Gmw7-Oej1MoFCohvq4f6emDJ2HF483UmW2Qd_c,4407
93
94
  tol/core/data_source_dict.py,sha256=d-hSmoWTwG6IOc0cQTLap1EBslsxYIWGUd3ScSoeH_Q,1705
94
95
  tol/core/datasource.py,sha256=e9GaeDPfO_Gs7cgQhmNxCiSDlRNf64reegzFebcMNkA,6303
95
96
  tol/core/datasource_error.py,sha256=TqfqaPANG0gishadhA7myCmTO1Fg9u7hVZOvsY6BdAo,1660
96
97
  tol/core/datasource_filter.py,sha256=RY2S9kTx0XwdrFRSE2n2GohB9__fKGzFVsZrkN5hzQk,726
97
98
  tol/core/datasource_utils.py,sha256=18mwvFmtJL73_mxtFb56rKXZCGCtZFoEb8sWFKn3Yf0,6232
98
- tol/core/factory.py,sha256=e0jXNS9NJvSrsbKUe9j19CElaSnKIB0j2pPCpcMa8wU,9273
99
+ tol/core/factory.py,sha256=pLLu8l-yK8QaLTt52izMhKZ2VlFHqRQlUHwMaLL6DI4,9156
99
100
  tol/core/http_client.py,sha256=05Wa_ySmpm_lC8OkxqXkq6jer0t693GexpaKNQBHufI,2244
100
101
  tol/core/relationship.py,sha256=etdyCjLbfi2tgkaqzE6cntpNtTzgT_jOPGeNKmPu5yc,4624
101
102
  tol/core/requested_fields.py,sha256=QFNky8QmT1Cmfn42EYPciwbCueJ0DVQNKkP0Vz-_7Jk,6715
102
103
  tol/core/session.py,sha256=6AohamIEfB8oV3Z414ishKqmlTgVfUaGYWzvxLgZgM4,3803
103
- tol/core/validate.py,sha256=84etPczrGDkqdrNnj4GSrPAeKxYcz8qUy5szJa2QRGY,4082
104
+ tol/core/validate.py,sha256=kFRPhgYyeZisGbSXR7S1pmD8jvz_aZ7RX40bT-gD_iA,4083
104
105
  tol/core/operator/__init__.py,sha256=ircyLdj45IlaL5k0cDzWHjEr-_66BAx7YRbuEvWF30k,1826
105
106
  tol/core/operator/_filterable.py,sha256=61qr-58ZPHWdWl4XKatjW1GPAhN-oqfjRpVtHHkipvA,1238
106
107
  tol/core/operator/_writer.py,sha256=eO4qe4myLjScCRnXeILU30MPOLyQiAZbIBQQ_awqB5I,1725
@@ -132,13 +133,13 @@ tol/eln/entities.py,sha256=3-Z4ibZR11zepz5Nw74PnkpxA_HA31FsRUx61FSPYUo,1209
132
133
  tol/eln/generators.py,sha256=ghRUiohLakiAcMzGVPJrPxYmdWijs63YxfRTqmKu3Zc,1227
133
134
  tol/eln/sanitise.py,sha256=fMj-VrQTnw4zn2X0wnjWQAI8gWAa8RYqNuv23LXQssI,406
134
135
  tol/ena/__init__.py,sha256=T3TCqaHpgi2Uk2PjPGu60GaG2V8cTrHJlVLtZfLFhTQ,174
135
- tol/ena/client.py,sha256=dYrclPK9KSx464DGt0fa3iVy4H5ODBKwPybIHeYggm4,4878
136
+ tol/ena/client.py,sha256=ldmm7Z9_auQf1zVWjsFLXYgbKvGtSHTsr88YO3zfv2Y,6731
136
137
  tol/ena/converter.py,sha256=nxbo4IFzzOvKNMq3Aeiw5iDqVWvY33nTngLppjHAoGY,1144
137
- tol/ena/ena_datasource.py,sha256=paOC7ujzhpPzhK2CAhqy2RdSFFkOFbVd0om6biABy84,8608
138
- tol/ena/ena_methods.py,sha256=qOStTxao1eMBAyVdTCRKldxLr8rDH5mC-G0GUSfFJFw,8887
138
+ tol/ena/ena_datasource.py,sha256=jEvyUaH4pfFxmdtn6O_PwOdjPz6u80uAT3SLlR2f5nM,8968
139
+ tol/ena/ena_methods.py,sha256=jgpLssZq-F-vgkO-fYu4jrXenmNkdFpFKAY3VKp5HHE,9209
139
140
  tol/ena/factory.py,sha256=3IJCmGLo59PWbGmNqmKho5WYG330OjL8SoZYstIwHt4,3423
140
141
  tol/ena/filter.py,sha256=UzOx5ivXvA0TY2QuNzFmS-zDPVNnaAx07DMVkAwVsAE,3370
141
- tol/ena/parser.py,sha256=8ZyGBA6HbhgjxHDTo9NDot5xSbD-4Y7gzPIKzkQT_D8,2648
142
+ tol/ena/parser.py,sha256=Z4YmUnpfLKng4QwmZkLEj1hUfwYb_bqr-DWgF1Gw-EY,3253
142
143
  tol/excel/__init__.py,sha256=M0xL9w9Au8kYOLWzFGuijJ7WoZENOMkZ1XV1ephhlDY,229
143
144
  tol/excel/excel.py,sha256=rcA-wfXY9R14OfNKS-NX2sn__9gmQ_G8LoUgWseF1Gk,2124
144
145
  tol/excel/excel_datasource.py,sha256=nIMvkCZ1edx8djqsVsPTRi6yCfyKc_dIokTpLy16rwY,3091
@@ -147,7 +148,7 @@ tol/flows/__init__.py,sha256=M7iSvnBJs6fJ8M38cW0bYQa9WW0TN8FHAMjIHPDNAJ4,166
147
148
  tol/flows/logger.py,sha256=rWXbaknGcPEZRFvC1CiB1qkhFRZsQk435w7VyJ3cpyw,170
148
149
  tol/flows/secrets.py,sha256=1mlbsxaahzYRfVAx3XdztHOmUCtDMSJDzHysdbaCtj0,352
149
150
  tol/flows/sequencing_submissions.py,sha256=ukz_y5be-BCBN2y3JPQ2EK6b3jwOCh-187j-jnw3EUY,11027
150
- tol/flows/converters/__init__.py,sha256=t4Y7jldbvi-bVC-oPkQOlFPrcqblYRvX4D6SpnbcqKk,5928
151
+ tol/flows/converters/__init__.py,sha256=Ee1yMFWwsRoG71ZFCsqtNwF45AR8farmV9h3ERrK994,6154
151
152
  tol/flows/converters/benchling_entity_to_benchling_worklist_item_converter_factory.py,sha256=PN27fcvN4JLBnLrtPPAot1cWjAwPQHVcIDoMfPDeKzU,1210
152
153
  tol/flows/converters/benchling_extraction_to_elastic_extraction_converter.py,sha256=S8pbmIeKlcXrLPRJHYBUGP0-Q7jTOV2QQk2TeA2naWo,1966
153
154
  tol/flows/converters/benchling_extraction_to_elastic_sequencing_request_converter.py,sha256=2RiyRvGRSWzpUwEI4p-s0afshJpFUUxPqv2z-nyDSVg,1992
@@ -179,6 +180,8 @@ tol/flows/converters/gap_assembly_to_elastic_assembly_converter.py,sha256=XK-es-
179
180
  tol/flows/converters/genome_notes_genome_note_to_elastic_genome_note_converter.py,sha256=AaUWbVTaWU-NXnUQPaPwI41TE7a-nC4zlg-jrWpPT2s,1166
180
181
  tol/flows/converters/goat_taxon_to_elastic_species_converter.py,sha256=1NGs9427OdXGsBaMB467nOF7aTlJsUKYCuoSoABw9L4,1074
181
182
  tol/flows/converters/grit_issue_to_elastic_curation_converter.py,sha256=XpRpoRn589MxTqEk6zPWGn6tamJiqY9Ctxk8v0q-dvA,3953
183
+ tol/flows/converters/incoming_sample_to_ena_sample_converter.py,sha256=HmGsg-VCE4W9Dl3lAlcNhWfkVYp1d22DZlFoTaFzeqA,5560
184
+ tol/flows/converters/incoming_sample_to_incoming_sample_with_lists_converter.py,sha256=5Fp1_ojsYqvRcKTgXJbyWqetPisi_vtWFcWr6RtGZoA,1504
182
185
  tol/flows/converters/informatics_tolid_to_elastic_tolid_converter.py,sha256=VrvtsDTPlc5Xa3K4rcAMHwV4n71zOH7q5EfALLLQ1tI,587
183
186
  tol/flows/converters/labwhere_location_to_elastic_sample_update_converter.py,sha256=NJNmG9sCc2WXc-2J5XfCKXhb2sDH82nZUBekd16PHcw,656
184
187
  tol/flows/converters/labwhere_location_to_sts_tray_converter.py,sha256=dSBP5HfdvyIGvNQD6bhi0RKvkwhN8jq69g-0hOXUqEg,672
@@ -237,13 +240,11 @@ tol/prefect/factory.py,sha256=mO4KVnaEYMv-ojGJuiencNQMq6PAMU8cIc4QN5Kq8Gw,2208
237
240
  tol/prefect/filter.py,sha256=aNVTSmcrbb_4EllcFtBOSPuUGgwE-f-Kd5_an6lREtM,7044
238
241
  tol/prefect/prefect_datasource.py,sha256=JXLS4odWNWUu4mgojQogwE28mBTAbj-OQYFxhYNYHnM,8865
239
242
  tol/prefect/prefect_object.py,sha256=Nn3Y6ErQnXubX7M-GzRsfLHEzdHwKr5RWCjIJ4FA28U,495
240
- tol/s3/__init__.py,sha256=AnYM6rWRDJ-AkUBPuIFGrF3wyeh7euwUCiv2-gPy9J4,351
243
+ tol/s3/__init__.py,sha256=L2Aa12NAYjTRr8W_ArJi3z3ME2bUtCf4CG3JDw1MoMk,282
241
244
  tol/s3/converter.py,sha256=KylGAQvu1jRYJl4dcYK1IgbFsmHP3JXRI22MX8UzHz4,1023
242
245
  tol/s3/factory.py,sha256=rFcRVy4B8KVsUaaHhtpLUE90_hRnixkO2IjnB6-arkc,2163
243
246
  tol/s3/parser.py,sha256=EOiPYJ8ZLigAxKGL4cC8r7OGyjGdSMHmJMnDqHSiG_E,1907
244
247
  tol/s3/s3_datasource.py,sha256=tSUc78FN1OudpJcQ-7FI4S_LPT5j-BYIcwFaQPDy_VA,2072
245
- tol/s3/data_upload/__init__.py,sha256=4dkK7MPB0CzkkujFSVj0FzoG5ri_usQ7XaBB81Vc_qE,85
246
- tol/s3/data_upload/blueprint.py,sha256=rwZAXsHe_AJXAdRZVdUhtJg3P3SxOs_G_0F1eewPuT4,2574
247
248
  tol/sciops/__init__.py,sha256=PaC1_5wZhsZlqeYQRMpDeIf9L6Hi0eXs_pHXaWfscAo,131
248
249
  tol/sciops/configuration.py,sha256=21ddgHOmhZE1tcE-5_f4KiV-7CUqkF8yXi4iBYPtfmc,1279
249
250
  tol/sciops/consumer.py,sha256=Ikl8glrZ0yQKBhegC84vwNj43iK1Ca_SAn_gcyAhbKQ,2137
@@ -293,11 +294,11 @@ tol/sql/exception.py,sha256=8c9KOVVNlLhqKU4CfsnxR7sd-JhEMnCk3TQ-s9JyogM,544
293
294
  tol/sql/ext.py,sha256=9oYHxR3IXUaG17BwTLWFJ-CjdgFrlm3AclctZ1FP0MQ,1752
294
295
  tol/sql/factory.py,sha256=cfHq1iH6wqqn5fI0yfOm59Tw6KiZqA7yXScCKBXBc1c,3408
295
296
  tol/sql/filter.py,sha256=O711DnBG7RssQKwZ76fqA8Vm2IN7pzVrigxc1I2G4-Y,15417
296
- tol/sql/model.py,sha256=Bi68mEsaWDSFxtouqMJqiG4wL6Ziv4uGo6UB9D8Odd4,12098
297
+ tol/sql/model.py,sha256=MAsQdw4L-SzCWCNQd3UVufxPuXFV3GmREss-ouWfh0U,12091
297
298
  tol/sql/relationship.py,sha256=EClMgVx_If5nZV9MV99TQk7Wr7uACWetwQdWAliM5XI,2891
298
299
  tol/sql/session.py,sha256=VmqTegr4L2X2zvaOJCpwSrkVRx8fc1RVL0drkL2MXu8,806
299
300
  tol/sql/sort.py,sha256=ENrjHGgj4fZtXKmkdlkv1HRi1X14SVlcl-tp8Pu7G0k,2553
300
- tol/sql/sql_converter.py,sha256=h3vQz65MGeJutumSecUDxLuG403lWpJIKPwMO5ahQPI,4300
301
+ tol/sql/sql_converter.py,sha256=taD5FRwadvw2bBaUGrCIiUs0-ATAbBnRYI1M7xe3yEc,4618
301
302
  tol/sql/sql_datasource.py,sha256=jLPQSolGtKRKezjVnMrlj8YO6bLepyiFARMbDYEXuN8,16219
302
303
  tol/sql/action/__init__.py,sha256=T1zAsCza_lvsNtXF1ecSLt9OFGup8tGnIs68YylBmXI,142
303
304
  tol/sql/action/factory.py,sha256=HkareJp_57ud0_Bdd9Kwz3_Rnq2l211sGJgftohFAHg,3589
@@ -305,7 +306,7 @@ tol/sql/auth/__init__.py,sha256=e3JuwugXmXobklqZ1Mt1w03qPgb1WdUaJVM7oblzHyk,202
305
306
  tol/sql/auth/blueprint.py,sha256=u0vT_TC9IMKrg08QFa9W29_83mT0y0jzLj3DvXy1BBw,25906
306
307
  tol/sql/auth/models.py,sha256=4xNWBvyGiI3mwRyDY5ty48Bv9178ApQXPR-YjIdCsvk,11879
307
308
  tol/sql/pipeline_step/__init__.py,sha256=O7u4RrLfuoB0mwLcPxFoUrdTBZGB_4bE1vWCn5ho-qw,147
308
- tol/sql/pipeline_step/factory.py,sha256=hrv9iAjdUu3sq6R94PXKclatZNMKY8YMgBDwLWKuvR0,5131
309
+ tol/sql/pipeline_step/factory.py,sha256=E5_Bs1379UGlRajKnb77iPmqhXBMemQR1C53SSPjXB4,5134
309
310
  tol/sql/standard/__init__.py,sha256=2NbLXFk0rneGZosZ2ESIRcT0WMK0KncmPWaLPqvX-i4,142
310
311
  tol/sql/standard/factory.py,sha256=yY8iWmZRMvUqphwnzBeOIQtKGgxsU6AcA7YTz53UYvc,20010
311
312
  tol/status/__init__.py,sha256=sBo-j1wCmberl89uryVCBEJk8ohbfsYhaNpIp_brR9Y,146
@@ -319,15 +320,27 @@ tol/treeval/treeval_datasource.py,sha256=GzY6JwH67b5QdV-UVdCFJfgGAIuZ96J2nl53YxZ
319
320
  tol/utils/__init__.py,sha256=764-Na1OaNGUDWpMIu51ZtXG7n_nB5MccUFK6LmkWRI,138
320
321
  tol/utils/csv.py,sha256=mihww25fSn72c4h-RFeqD_pFIG6KHZP4v1_C0rx81ws,421
321
322
  tol/utils/s3.py,sha256=aoYCwJ-qcMqFrpxmViFqPa0O1jgp0phtztO3-0CSNjw,491
322
- tol/validators/__init__.py,sha256=bIMjfuRd358nUPLp6fMG9nTs43gM9aA9oY_AINgxkWU,379
323
- tol/validators/allowed_keys.py,sha256=BJMomJtaQdxsdGsueDtLewv75TlwdIXiQipLGFcJ7_c,1331
324
- tol/validators/allowed_values.py,sha256=yJ5SdiUlV7PSKORtsBJ9hYSqwvlx_esbFmFL_Gxh-p4,2262
325
- tol/validators/regex.py,sha256=dKodGH0sv6DbqWeV6QXE6-GYjnG4rMO0rg8IEIaQG60,2364
326
- tol/validators/regex_by_value.py,sha256=o99NJlWPgQ0GrpVnep8-cHfjWnc9F2rChmXHIxjrMrk,2543
327
- tol/validators/unique_values.py,sha256=tEXDNJj95XUJdhsZlO-pkXdQz-EYaSG-mcp4MDTL7eY,2835
328
- tol_sdk-1.7.4.dist-info/licenses/LICENSE,sha256=RF9Jacy-9BpUAQQ20INhTgtaNBkmdTolYCHtrrkM2-8,1077
329
- tol_sdk-1.7.4.dist-info/METADATA,sha256=1gosjFEvdmraYpLVv81dHvwCKBFGXDUdz__wwvImdLo,3079
330
- tol_sdk-1.7.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
331
- tol_sdk-1.7.4.dist-info/entry_points.txt,sha256=jH3HfTwxjzog7E3lq8CKpUWGIRY9FSXbyL6CpUmv6D0,36
332
- tol_sdk-1.7.4.dist-info/top_level.txt,sha256=PwKMQLphyZNvagBoriVbl8uwHXQl8IC1niawVG0iXMM,10
333
- tol_sdk-1.7.4.dist-info/RECORD,,
323
+ tol/validators/__init__.py,sha256=CcamQvWpywu5aXWc1D9CoZAZcbioRBlNUuTX-XOKqQE,1060
324
+ tol/validators/allowed_keys.py,sha256=fX4KqpxOJNmmVNqQq215MtX27v4dbKSjCM1laXuXfZE,1488
325
+ tol/validators/allowed_values.py,sha256=Sxsb6EhiR8Ey90sfPoyGqkehkJN0hHSNXlLYSL_k5f4,1518
326
+ tol/validators/allowed_values_from_datasource.py,sha256=EqHfaTk8VAMQAra7SfkpZYjFUJm9bee_i73vFwwGG_Y,3169
327
+ tol/validators/assert_on_condition.py,sha256=FCzmN2Crhku0bdEpXuKEbDaoU6RbAZCUDUxQ8OHK92M,2017
328
+ tol/validators/ena_checklist.py,sha256=nxoiJWHKDk2HzeJMKgME_KGNYUBSaCx5jbp4yXQMf00,2875
329
+ tol/validators/ena_submittable.py,sha256=ruryfVcQtRJ5JsAFBcVZ_3hzTDwRWGXpdPUAfdrYmWg,1948
330
+ tol/validators/min_one_valid_value.py,sha256=3Fv-b-fojvPLpiWwUqrFfO0YMGtV40KEp15zTmdOlyI,1425
331
+ tol/validators/mutually_exclusive.py,sha256=76AqX4G_syKAbFyDgydbcMHvNAroENazrcWbR5vAN30,4482
332
+ tol/validators/regex.py,sha256=L8ap5oxn_54DoE7Tnqo1VjQ-dr5-fJAe7cCHYg8cBzw,2523
333
+ tol/validators/regex_by_value.py,sha256=bSPloXfeOUMuiSQH-_GkvQ6IiD3Q1fojT0iydlkLanI,2564
334
+ tol/validators/specimens_have_same_taxon.py,sha256=BrkYXhr1KVnJcDe-PrKXf0AF9740BbFV2XVMrtu98CQ,2167
335
+ tol/validators/sts_fields.py,sha256=piHqdzuGepIEv-ZSSwdkYE6ybQpqc4hBN8hN8UrN4Vg,3442
336
+ tol/validators/tolid.py,sha256=gHiaNQGWHos4I6Rz7aKCOATbv0ff8qL4LdObnZ_Lgt8,3876
337
+ tol/validators/unique_values.py,sha256=CZvIdg7GC2VmVAGuPToxJ_r-2YCwy2xkQKp2qwVwbzU,3096
338
+ tol/validators/unique_whole_organisms.py,sha256=Z-PUjlCcn-WHDKMYDyt_WhalXzQFfqLWItM6qywVt_Y,5725
339
+ tol/validators/interfaces/__init__.py,sha256=jtOxnwnwqV_29xjmmMcS_kvlt-pQiWwQYJn2YRP07_w,172
340
+ tol/validators/interfaces/condition_evaluator.py,sha256=nj8Cb8hi47OBy6OVNfeLhF-Pjwtr8MiOSymYL6hfVes,3766
341
+ tol_sdk-1.7.5b2.dist-info/licenses/LICENSE,sha256=RF9Jacy-9BpUAQQ20INhTgtaNBkmdTolYCHtrrkM2-8,1077
342
+ tol_sdk-1.7.5b2.dist-info/METADATA,sha256=FxtTjGw1IxkHprv89dW071kyQ68kiR9sxu-QdfLaF1g,3081
343
+ tol_sdk-1.7.5b2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
344
+ tol_sdk-1.7.5b2.dist-info/entry_points.txt,sha256=jH3HfTwxjzog7E3lq8CKpUWGIRY9FSXbyL6CpUmv6D0,36
345
+ tol_sdk-1.7.5b2.dist-info/top_level.txt,sha256=PwKMQLphyZNvagBoriVbl8uwHXQl8IC1niawVG0iXMM,10
346
+ tol_sdk-1.7.5b2.dist-info/RECORD,,
@@ -1,3 +0,0 @@
1
- # SPDX-FileCopyrightText: 2025 Genome Research Ltd.
2
- #
3
- # SPDX-License-Identifier: MIT