tol-sdk 1.7.5b2__py3-none-any.whl → 1.7.5b3__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.
@@ -82,7 +82,7 @@ class DetailGetter(ABC):
82
82
  for id_ in object_ids:
83
83
  seekable_objects.seek(0)
84
84
  for obj in seekable_objects:
85
- if obj.id == id_:
85
+ if str(obj.id) == str(id_):
86
86
  yield obj
87
87
  break
88
88
  else:
tol/sql/auth/models.py CHANGED
@@ -19,6 +19,7 @@ from sqlalchemy.ext.declarative import declared_attr
19
19
  from sqlalchemy.orm import (
20
20
  Mapped,
21
21
  Session,
22
+ joinedload,
22
23
  mapped_column,
23
24
  relationship
24
25
  )
@@ -184,7 +185,7 @@ def create_models(
184
185
 
185
186
  id: Mapped[str] = mapped_column( # noqa A003
186
187
  primary_key=True,
187
- name=None if not prefix_with_name else 'state_id'
188
+ name='state_id' if prefix_with_name else None
188
189
  )
189
190
 
190
191
  created_at: Mapped[datetime] = mapped_column(
@@ -257,13 +258,13 @@ def create_models(
257
258
  id: Mapped[int] = mapped_column( # noqa A003
258
259
  primary_key=True,
259
260
  autoincrement=True,
260
- name=None if not prefix_with_name else 'user_id'
261
+ name='user_id' if prefix_with_name else None
261
262
  )
262
263
 
263
- _tokens: Mapped[list['Token']] = relationship(
264
+ _tokens: Mapped[list[Token]] = relationship(
264
265
  back_populates='user'
265
266
  )
266
- _role_bindings: Mapped[list['RoleBinding']] = relationship(
267
+ _role_bindings: Mapped[list[RoleBinding]] = relationship(
267
268
  back_populates='user'
268
269
  )
269
270
 
@@ -340,7 +341,7 @@ def create_models(
340
341
 
341
342
  class _TokenPKMixin:
342
343
  """
343
- Has an integer has a primary key.
344
+ Has an integer as a primary key.
344
345
 
345
346
  This is all that is needed in most apps,
346
347
  and is the default.
@@ -403,11 +404,19 @@ def create_models(
403
404
  token: str
404
405
  ) -> Optional[Token]:
405
406
 
406
- return sess.query(
407
- cls
408
- ).filter_by(
409
- token=token
410
- ).one_or_none()
407
+ return (
408
+ sess.query(cls)
409
+ .filter_by(token=token)
410
+ .options(
411
+ # Join through to the Role table when fetching a Token so
412
+ # that SQLAlchemy only fires one SELECT query instead of
413
+ # four to get `token.user._role_bindings.role.name`
414
+ joinedload(cls.user)
415
+ .joinedload(User._role_bindings)
416
+ .joinedload(RoleBinding.role)
417
+ )
418
+ .one_or_none()
419
+ )
411
420
 
412
421
  @classmethod
413
422
  def get_or_create(
@@ -475,14 +484,14 @@ def create_models(
475
484
  id: Mapped[int] = mapped_column( # noqa A003
476
485
  primary_key=True,
477
486
  autoincrement=True,
478
- name=None if not prefix_with_name else 'role_id'
487
+ name='role_id' if prefix_with_name else None
479
488
  )
480
489
 
481
490
  name: Mapped[str] = mapped_column(
482
491
  unique=True
483
492
  )
484
493
 
485
- _role_bindings: Mapped[list['RoleBinding']] = relationship(
494
+ _role_bindings: Mapped[list[RoleBinding]] = relationship(
486
495
  back_populates='role'
487
496
  )
488
497
 
@@ -6,6 +6,7 @@ from .allowed_keys import AllowedKeysValidator # noqa
6
6
  from .allowed_values import AllowedValuesValidator # noqa
7
7
  from .allowed_values_from_datasource import AllowedValuesFromDataSourceValidator # noqa
8
8
  from .assert_on_condition import AssertOnConditionValidator # noqa
9
+ from .converter_and_validate import ConverterAndValidateValidator # noqa
9
10
  from .ena_checklist import EnaChecklistValidator # noqa
10
11
  from .mutually_exclusive import MutuallyExclusiveValidator # noqa
11
12
  from .ena_submittable import EnaSubmittableValidator # noqa
@@ -26,7 +26,8 @@ class AllowedKeysValidator(Validator):
26
26
 
27
27
  def __init__(
28
28
  self,
29
- config: Config
29
+ config: Config,
30
+ **kwargs
30
31
  ) -> None:
31
32
 
32
33
  super().__init__()
@@ -27,7 +27,8 @@ class AllowedValuesValidator(Validator):
27
27
 
28
28
  def __init__(
29
29
  self,
30
- config: Config
30
+ config: Config,
31
+ **kwargs
31
32
  ) -> None:
32
33
 
33
34
  super().__init__()
@@ -29,7 +29,8 @@ class AllowedValuesFromDataSourceValidator(Validator):
29
29
  def __init__(
30
30
  self,
31
31
  config: Config,
32
- allowed_values: List[str | int | float] | None = None # For testing
32
+ allowed_values: List[str | int | float] | None = None, # For testing
33
+ **kwargs
33
34
  ) -> None:
34
35
 
35
36
  super().__init__()
@@ -40,7 +41,7 @@ class AllowedValuesFromDataSourceValidator(Validator):
40
41
 
41
42
  def __initialize_list_from_datasource(self) -> List[str | int | float]:
42
43
  dsi = portaldb().get_one('data_source_instance', self.__config.datasource_instance_id)
43
- ds = DataSourceUtils.get_data_source_by_data_source_instance(dsi)
44
+ ds = DataSourceUtils.get_datasource_by_datasource_instance(dsi)
44
45
  return [
45
46
  obj.get_field_by_name(
46
47
  self.__config.datasource_field_name
@@ -25,7 +25,7 @@ class AssertOnConditionValidator(Validator, ConditionEvaluator):
25
25
  __slots__ = ['__config']
26
26
  __config: Config
27
27
 
28
- def __init__(self, config: Config) -> None:
28
+ def __init__(self, config: Config, **kwargs) -> None:
29
29
  super().__init__()
30
30
 
31
31
  self.__config = config
@@ -0,0 +1,93 @@
1
+ # SPDX-FileCopyrightText: 2025 Genome Research Ltd.
2
+ #
3
+ # SPDX-License-Identifier: MIT
4
+
5
+ import importlib
6
+ from dataclasses import dataclass
7
+
8
+ from tol.core import DataObject
9
+ from tol.core.factory import DataObjectFactory
10
+ from tol.core.validate import ValidationResult, Validator
11
+
12
+
13
+ class ConverterAndValidateValidator(Validator):
14
+ """
15
+ Convert DataObjects, validate the converted ones, and return the original
16
+ input unchanged. Inner validator results are not merged here.
17
+
18
+ {
19
+ "converters": [{
20
+ "module": "<path.to.module>",
21
+ "class_name": "<path.to.ConverterClass>",
22
+ "config": { ... }
23
+ }],
24
+ "validators": [{
25
+ "module": "<path.to.module>",
26
+ "class_name": "<path.to.ValidatorClass>",
27
+ "config": { ... }
28
+ }]
29
+ }
30
+
31
+ """
32
+ @dataclass(slots=True, frozen=True, kw_only=True)
33
+ class Config:
34
+ converters: list[dict]
35
+ validators: list[dict]
36
+
37
+ __slots__ = [
38
+ '__converters',
39
+ '__validators'
40
+ ]
41
+
42
+ def __init__(
43
+ self,
44
+ config: Config,
45
+ data_object_factory: DataObjectFactory,
46
+ **kwargs
47
+ ) -> None:
48
+ super().__init__()
49
+ self.__converters = []
50
+ self.__validators = []
51
+
52
+ for conv in config.converters:
53
+ __module = importlib.import_module(conv.get('module'))
54
+ converter_class = getattr(__module, conv.get('class_name'))
55
+
56
+ converter_conf = converter_class.Config(
57
+ **conv.get('config')
58
+ )
59
+ self.__converters.append(converter_class(
60
+ data_object_factory=data_object_factory,
61
+ config=converter_conf,
62
+ ))
63
+ for val in config.validators:
64
+ __module = importlib.import_module(val.get('module'))
65
+ validator_class = getattr(__module, val.get('class_name'))
66
+
67
+ validator_conf = validator_class.Config(
68
+ **val.get('config')
69
+ )
70
+ self.__validators.append(validator_class(
71
+ data_object_factory=data_object_factory,
72
+ config=validator_conf,
73
+ ))
74
+
75
+ def _validate_data_object(self, obj: DataObject) -> None:
76
+ converted_objs = [obj]
77
+ for converter in self.__converters:
78
+ converted_objs = converter.convert_iterable(converted_objs)
79
+ for obj in converted_objs:
80
+ for validator in self.__validators:
81
+ validator._validate_data_object(obj)
82
+
83
+ @property
84
+ def results(self) -> list[ValidationResult]:
85
+ return [result for validator in self.__validators for result in validator.results]
86
+
87
+ @property
88
+ def warnings(self) -> list[ValidationResult]:
89
+ return [warning for validator in self.__validators for warning in validator.warnings]
90
+
91
+ @property
92
+ def errors(self) -> list[ValidationResult]:
93
+ return [error for validator in self.__validators for error in validator.errors]
@@ -23,7 +23,7 @@ class EnaChecklistValidator(Validator):
23
23
  __slots__ = ['__config']
24
24
  __config: Config
25
25
 
26
- def __init__(self, config: Config, datasource: DataSource = ena()) -> None:
26
+ def __init__(self, config: Config, datasource: DataSource = ena(), **kwargs) -> None:
27
27
  super().__init__()
28
28
  self.__config = config
29
29
  self._datasource = datasource
@@ -28,6 +28,7 @@ class EnaSubmittableValidator(Validator):
28
28
  self,
29
29
  config: Config,
30
30
  ena_datasource: DataSource | None = ena(), # For testing
31
+ **kwargs
31
32
  ) -> None:
32
33
 
33
34
  super().__init__()
@@ -24,6 +24,7 @@ class MinOneValidValueValidator(Validator):
24
24
  def __init__(
25
25
  self,
26
26
  config: Config,
27
+ **kwargs
27
28
  ) -> None:
28
29
 
29
30
  super().__init__()
@@ -62,7 +62,7 @@ class MutuallyExclusiveValidator(Validator, ConditionEvaluator):
62
62
  __first_list: List[Any]
63
63
  __second_list: List[Any]
64
64
 
65
- def __init__(self, config: Config) -> None:
65
+ def __init__(self, config: Config, **kwargs) -> None:
66
66
  super().__init__()
67
67
 
68
68
  self.__config = config
tol/validators/regex.py CHANGED
@@ -26,7 +26,10 @@ class Regex:
26
26
 
27
27
  def is_allowed(self, __v: Any) -> bool:
28
28
  # Check regex
29
- return re.search(self.regex, str(__v or ''))
29
+ return bool(re.search(
30
+ self.regex,
31
+ str(__v) if __v is not None else ''
32
+ ))
30
33
 
31
34
 
32
35
  class RegexValidator(Validator):
@@ -44,7 +47,8 @@ class RegexValidator(Validator):
44
47
 
45
48
  def __init__(
46
49
  self,
47
- config: Config
50
+ config: Config,
51
+ **kwargs
48
52
  ) -> None:
49
53
 
50
54
  super().__init__()
@@ -27,7 +27,8 @@ class RegexByValueValidator(Validator):
27
27
 
28
28
  def __init__(
29
29
  self,
30
- config: Config
30
+ config: Config,
31
+ **kwargs
31
32
  ) -> None:
32
33
 
33
34
  super().__init__()
@@ -25,7 +25,7 @@ class SpecimensHaveSameTaxonValidator(Validator):
25
25
  __config: Config
26
26
  __seen: Dict[str, str]
27
27
 
28
- def __init__(self, config: Config) -> None:
28
+ def __init__(self, config: Config, **kwargs) -> None:
29
29
  super().__init__()
30
30
  self.__seen = {}
31
31
  self.__config = config
@@ -28,6 +28,7 @@ class StsFieldsValidator(Validator):
28
28
  self,
29
29
  config: Config,
30
30
  datasource: DataSource = sts(), # For testing
31
+ **kwargs
31
32
  ) -> None:
32
33
 
33
34
  super().__init__()
tol/validators/tolid.py CHANGED
@@ -34,6 +34,7 @@ class TolidValidator(Validator):
34
34
  self,
35
35
  config: Config,
36
36
  datasource=tolid(),
37
+ **kwargs
37
38
  ) -> None:
38
39
 
39
40
  super().__init__()
@@ -27,7 +27,8 @@ class UniqueValuesValidator(Validator):
27
27
 
28
28
  def __init__(
29
29
  self,
30
- config: Config
30
+ config: Config,
31
+ **kwargs
31
32
  ) -> None:
32
33
 
33
34
  super().__init__()
@@ -28,7 +28,7 @@ class UniqueWholeOrganismsValidator(Validator):
28
28
  __whole_organisms: List[str]
29
29
  __part_organisms: List[str]
30
30
 
31
- def __init__(self, config: Config) -> None:
31
+ def __init__(self, config: Config, **kwargs) -> None:
32
32
  super().__init__()
33
33
  self.__whole_organisms = []
34
34
  self.__part_organisms = []
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tol-sdk
3
- Version: 1.7.5b2
3
+ Version: 1.7.5b3
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
@@ -110,7 +110,7 @@ tol/core/operator/counter.py,sha256=aD7CRcSfHUfH-ASivJhUSncbLc8gvwdbQUDONjHp4oo,
110
110
  tol/core/operator/cursor.py,sha256=G8RkuLpQS6vDAXhE2D1WXLSEuGDkqv3YwSrW_QhGTlc,3960
111
111
  tol/core/operator/declare.py,sha256=W1jngGKNy-5D8T8nt_-6lpfOFTa-ilVr9YalRdJNG3w,333
112
112
  tol/core/operator/deleter.py,sha256=v8C6aBSQGwVCYmZ_PIeGVQExSyilQi5C-6G-wuACCBg,755
113
- tol/core/operator/detail_getter.py,sha256=0O4VXWqupSuAtVrrib0dWZ2B78IVGokm1b3hzwE3VQI,2785
113
+ tol/core/operator/detail_getter.py,sha256=EG7EuVh73ZzHjXh4fmIy0WtTJii5bHgqzoqbT8OuHqk,2795
114
114
  tol/core/operator/enricher.py,sha256=ijJvE8aYCIVsOpmU2EHiTB8NPGwnGucebcDccm5o7qg,4079
115
115
  tol/core/operator/enum.py,sha256=JsJkj7LIMLoCnx2n1rdSX9LxGK9bbfoloXVie4rR_3M,1651
116
116
  tol/core/operator/group_statter.py,sha256=jZ45J3OGtypOfosWChWAwe05POpBejaoDNAO2qJP1GM,897
@@ -304,7 +304,7 @@ tol/sql/action/__init__.py,sha256=T1zAsCza_lvsNtXF1ecSLt9OFGup8tGnIs68YylBmXI,14
304
304
  tol/sql/action/factory.py,sha256=HkareJp_57ud0_Bdd9Kwz3_Rnq2l211sGJgftohFAHg,3589
305
305
  tol/sql/auth/__init__.py,sha256=e3JuwugXmXobklqZ1Mt1w03qPgb1WdUaJVM7oblzHyk,202
306
306
  tol/sql/auth/blueprint.py,sha256=u0vT_TC9IMKrg08QFa9W29_83mT0y0jzLj3DvXy1BBw,25906
307
- tol/sql/auth/models.py,sha256=4xNWBvyGiI3mwRyDY5ty48Bv9178ApQXPR-YjIdCsvk,11879
307
+ tol/sql/auth/models.py,sha256=U4CsKMMyzGMg6hj4tp_iRenr3_Q--64WJmHWvxQ2--Q,12297
308
308
  tol/sql/pipeline_step/__init__.py,sha256=O7u4RrLfuoB0mwLcPxFoUrdTBZGB_4bE1vWCn5ho-qw,147
309
309
  tol/sql/pipeline_step/factory.py,sha256=E5_Bs1379UGlRajKnb77iPmqhXBMemQR1C53SSPjXB4,5134
310
310
  tol/sql/standard/__init__.py,sha256=2NbLXFk0rneGZosZ2ESIRcT0WMK0KncmPWaLPqvX-i4,142
@@ -320,27 +320,28 @@ tol/treeval/treeval_datasource.py,sha256=GzY6JwH67b5QdV-UVdCFJfgGAIuZ96J2nl53YxZ
320
320
  tol/utils/__init__.py,sha256=764-Na1OaNGUDWpMIu51ZtXG7n_nB5MccUFK6LmkWRI,138
321
321
  tol/utils/csv.py,sha256=mihww25fSn72c4h-RFeqD_pFIG6KHZP4v1_C0rx81ws,421
322
322
  tol/utils/s3.py,sha256=aoYCwJ-qcMqFrpxmViFqPa0O1jgp0phtztO3-0CSNjw,491
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
323
+ tol/validators/__init__.py,sha256=mJDlsI_W2y5jxazwOlyf-COl_Vlj1Xk1yC5xASouGH8,1134
324
+ tol/validators/allowed_keys.py,sha256=RJcHBiguL84B8hjSRaXLNES21yZqaKFwJNp2Tz9zvh0,1506
325
+ tol/validators/allowed_values.py,sha256=-Yy3Sqo1WYacGKlot_dn3M2o7Oj5MXOioJrJmrWCCxs,1536
326
+ tol/validators/allowed_values_from_datasource.py,sha256=ICFO6FcYXDN7M2Cv1OwpyN38CdhmY7oU-njzIatA3-w,3185
327
+ tol/validators/assert_on_condition.py,sha256=eBGgSVfIQ6e45SheM-ZDg7daXJjyZxRVS5L8AWvbXag,2027
328
+ tol/validators/converter_and_validate.py,sha256=YjhLsh0qMcyZEnHK2GJFotJfZssOtr8qU4uszcPQmrg,2960
329
+ tol/validators/ena_checklist.py,sha256=VGJeDrHH-XzueforuyyCEgEi6y9NurhvuOSL-gSDoOE,2885
330
+ tol/validators/ena_submittable.py,sha256=CujF9t4mA4N3Wm_5rA5MRp401aW19kbioOZpfWVXg6I,1965
331
+ tol/validators/min_one_valid_value.py,sha256=gZUHtfRA-Lvpw0d1FJoAA31cRJpLbbxAJCC9DCt5lCY,1442
332
+ tol/validators/mutually_exclusive.py,sha256=6blZK-2IY4Eq79fHKKrm-pxsQ6B5DNH5ldtxOFVCPhU,4492
333
+ tol/validators/regex.py,sha256=YdFHPcvEo6jNbXxDPTnpAQeOv3kSX4OUZUKfWmFFWl0,2602
334
+ tol/validators/regex_by_value.py,sha256=XM5EnT4vgD17rfpR3bUE9I56IemSw26BI9MZtMakd4E,2582
335
+ tol/validators/specimens_have_same_taxon.py,sha256=m2LLRIZMdhPj1fzyioDJOraI6UHXgy1l963xhezgk7E,2177
336
+ tol/validators/sts_fields.py,sha256=A_NkQFn2TMNFv2yU_ercs7CXlh-oib33ZmDZtc6SuKQ,3459
337
+ tol/validators/tolid.py,sha256=kgo-OWW3at6jK4DQtdgVFjO06sDvqG4QulGkI-jjVRU,3893
338
+ tol/validators/unique_values.py,sha256=o5IrfUNLEmlEp8kpInTtFnTq-FqiHSC9TItKdf-LI1o,3114
339
+ tol/validators/unique_whole_organisms.py,sha256=RdqA1GzIf3LTdrmNGGdxv0aW2udDY2P9EaqZb40hhik,5735
339
340
  tol/validators/interfaces/__init__.py,sha256=jtOxnwnwqV_29xjmmMcS_kvlt-pQiWwQYJn2YRP07_w,172
340
341
  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,,
342
+ tol_sdk-1.7.5b3.dist-info/licenses/LICENSE,sha256=RF9Jacy-9BpUAQQ20INhTgtaNBkmdTolYCHtrrkM2-8,1077
343
+ tol_sdk-1.7.5b3.dist-info/METADATA,sha256=EJao_K6Vaa6nFKvIM8iw1vx73RocSQXiK4KkuFfQRVM,3081
344
+ tol_sdk-1.7.5b3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
345
+ tol_sdk-1.7.5b3.dist-info/entry_points.txt,sha256=jH3HfTwxjzog7E3lq8CKpUWGIRY9FSXbyL6CpUmv6D0,36
346
+ tol_sdk-1.7.5b3.dist-info/top_level.txt,sha256=PwKMQLphyZNvagBoriVbl8uwHXQl8IC1niawVG0iXMM,10
347
+ tol_sdk-1.7.5b3.dist-info/RECORD,,