tol-sdk 1.8.8__py3-none-any.whl → 1.8.10__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.
- tol/core/datasource_utils.py +8 -5
- tol/ena/ena_datasource.py +8 -3
- tol/sources/portaldb.py +4 -2
- tol/sources/sql.py +25 -0
- tol/sql/sql_datasource.py +1 -0
- tol/validators/__init__.py +3 -2
- tol/validators/allowed_keys.py +1 -0
- tol/validators/taxon_matches_goat.py +86 -0
- {tol_sdk-1.8.8.dist-info → tol_sdk-1.8.10.dist-info}/METADATA +1 -1
- {tol_sdk-1.8.8.dist-info → tol_sdk-1.8.10.dist-info}/RECORD +14 -12
- {tol_sdk-1.8.8.dist-info → tol_sdk-1.8.10.dist-info}/WHEEL +1 -1
- {tol_sdk-1.8.8.dist-info → tol_sdk-1.8.10.dist-info}/entry_points.txt +0 -0
- {tol_sdk-1.8.8.dist-info → tol_sdk-1.8.10.dist-info}/licenses/LICENSE +0 -0
- {tol_sdk-1.8.8.dist-info → tol_sdk-1.8.10.dist-info}/top_level.txt +0 -0
tol/core/datasource_utils.py
CHANGED
|
@@ -30,10 +30,13 @@ class DataSourceUtils:
|
|
|
30
30
|
@classmethod
|
|
31
31
|
def get_datasource_by_datasource_instance(
|
|
32
32
|
cls,
|
|
33
|
-
datasource_instance: DataObject
|
|
33
|
+
datasource_instance: DataObject,
|
|
34
|
+
**kwargs
|
|
34
35
|
) -> DataSource:
|
|
35
36
|
datasource_config = datasource_instance.data_source_config
|
|
36
|
-
|
|
37
|
+
new_kwargs = dict(datasource_instance.kwargs) if datasource_instance.kwargs else {}
|
|
38
|
+
if kwargs:
|
|
39
|
+
new_kwargs.update(kwargs)
|
|
37
40
|
if datasource_config:
|
|
38
41
|
relationship_config = cls.get_relationship_config_from_data_source_config(
|
|
39
42
|
datasource_config
|
|
@@ -44,14 +47,14 @@ class DataSourceUtils:
|
|
|
44
47
|
runtime_fields = cls.get_runtime_fields_from_data_source_config(
|
|
45
48
|
datasource_config
|
|
46
49
|
)
|
|
47
|
-
|
|
50
|
+
new_kwargs.update({
|
|
48
51
|
'relationship_cfg': relationship_config,
|
|
49
52
|
'attribute_metadata': amd,
|
|
50
53
|
'runtime_fields': runtime_fields
|
|
51
54
|
})
|
|
52
55
|
return DataSourceUtils.get_datasource_by_name(
|
|
53
56
|
datasource_instance.builtin_name,
|
|
54
|
-
**
|
|
57
|
+
**new_kwargs
|
|
55
58
|
)
|
|
56
59
|
|
|
57
60
|
@classmethod
|
|
@@ -83,7 +86,6 @@ class DataSourceUtils:
|
|
|
83
86
|
cls,
|
|
84
87
|
datasource_config: DataObject
|
|
85
88
|
) -> dict:
|
|
86
|
-
from ..elastic.runtime_fields import RuntimeFields # Break circular import cycle
|
|
87
89
|
runtime_fields = {}
|
|
88
90
|
f = DataSourceFilter()
|
|
89
91
|
f.and_ = {
|
|
@@ -95,6 +97,7 @@ class DataSourceUtils:
|
|
|
95
97
|
if dsa.object_type not in runtime_fields:
|
|
96
98
|
runtime_fields[dsa.object_type] = {}
|
|
97
99
|
if 'function' in dsa.runtime_definition:
|
|
100
|
+
from ..elastic.runtime_fields import RuntimeFields # Break circular import cycle
|
|
98
101
|
method = getattr(RuntimeFields, dsa.runtime_definition['function'])
|
|
99
102
|
runtime_fields[dsa.object_type][dsa.name] = \
|
|
100
103
|
method(**dsa.runtime_definition.get('function_kwargs', {}))
|
tol/ena/ena_datasource.py
CHANGED
|
@@ -11,6 +11,7 @@ from cachetools.func import ttl_cache
|
|
|
11
11
|
|
|
12
12
|
import requests
|
|
13
13
|
from requests.auth import HTTPBasicAuth
|
|
14
|
+
from requests.exceptions import HTTPError
|
|
14
15
|
|
|
15
16
|
|
|
16
17
|
from .client import EnaApiClient
|
|
@@ -118,9 +119,13 @@ class EnaDataSource(
|
|
|
118
119
|
if object_type == 'submittable_taxon':
|
|
119
120
|
ena_response = []
|
|
120
121
|
for object_id in object_ids:
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
122
|
+
try:
|
|
123
|
+
response = client.get_detail(object_type, [object_id])
|
|
124
|
+
if response and isinstance(response, list):
|
|
125
|
+
ena_response.extend(response)
|
|
126
|
+
except HTTPError as http_error:
|
|
127
|
+
if http_error.response.status_code != 400:
|
|
128
|
+
raise
|
|
124
129
|
else:
|
|
125
130
|
ena_response = client.get_detail(object_type, object_ids)
|
|
126
131
|
# For a checklist we need to convert into a list of dicts
|
tol/sources/portaldb.py
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
import os
|
|
6
6
|
|
|
7
|
+
from .defaults import Defaults
|
|
7
8
|
from ..api_client import (
|
|
8
9
|
ApiDataSource,
|
|
9
10
|
create_api_datasource
|
|
@@ -15,9 +16,10 @@ from ..core import (
|
|
|
15
16
|
|
|
16
17
|
def portaldb(retries: int = 5, **kwargs) -> ApiDataSource:
|
|
17
18
|
portaldb = create_api_datasource(
|
|
18
|
-
api_url=os.getenv('PORTAL_URL'
|
|
19
|
+
api_url=os.getenv('PORTAL_URL', Defaults.PORTAL_URL)
|
|
20
|
+
+ os.getenv('PORTAL_API_PATH', Defaults.PORTAL_API_PATH),
|
|
19
21
|
token=os.getenv('PORTAL_API_KEY'),
|
|
20
|
-
data_prefix='',
|
|
22
|
+
data_prefix='/local',
|
|
21
23
|
retries=retries
|
|
22
24
|
)
|
|
23
25
|
core_data_object(portaldb)
|
tol/sources/sql.py
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: 2023 Genome Research Ltd.
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: MIT
|
|
4
|
+
|
|
5
|
+
from ..core import (
|
|
6
|
+
core_data_object
|
|
7
|
+
)
|
|
8
|
+
from ..sql import (
|
|
9
|
+
SqlDataSource,
|
|
10
|
+
create_sql_datasource
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
# Create a SQL datasource. This is also expecting the models to be passed in
|
|
15
|
+
# so would most likely be used within an app
|
|
16
|
+
def sql(models, db_uri, behind_api, database_factory, **kwargs) -> SqlDataSource:
|
|
17
|
+
sql_ds = create_sql_datasource(
|
|
18
|
+
models=models,
|
|
19
|
+
db_uri=db_uri,
|
|
20
|
+
behind_api=True,
|
|
21
|
+
database_factory=database_factory,
|
|
22
|
+
**kwargs
|
|
23
|
+
)
|
|
24
|
+
core_data_object(sql_ds)
|
|
25
|
+
return sql_ds
|
tol/sql/sql_datasource.py
CHANGED
|
@@ -86,6 +86,7 @@ class SqlDataSource(
|
|
|
86
86
|
sorter_factory: SorterFactory,
|
|
87
87
|
user_id_getter: Optional[UserIdGetter] = None,
|
|
88
88
|
attribute_metadata: AttributeMetadata = DefaultAttributeMetadata,
|
|
89
|
+
**kwargs
|
|
89
90
|
) -> None:
|
|
90
91
|
self.__db = db
|
|
91
92
|
self.__type_tablename_map = type_tablename_map
|
tol/validators/__init__.py
CHANGED
|
@@ -19,8 +19,9 @@ from .types import TypesValidator # noqa
|
|
|
19
19
|
from .unique_values import UniqueValuesValidator # noqa
|
|
20
20
|
from .unique_whole_organisms import UniqueWholeOrganismsValidator # noqa
|
|
21
21
|
from .interfaces import Condition # noqa
|
|
22
|
-
from .min_one_valid_value import MinOneValidValueValidator
|
|
22
|
+
from .min_one_valid_value import MinOneValidValueValidator # noqa
|
|
23
23
|
from .value_check import ValueCheckValidator # noqa
|
|
24
24
|
from .branching import BranchingValidator # noqa
|
|
25
25
|
from .unique_value_check import UniqueValueCheckValidator # noqa
|
|
26
|
-
from .date_sorting import DateSortingValidator
|
|
26
|
+
from .date_sorting import DateSortingValidator # noqa
|
|
27
|
+
from .taxon_matches_goat import TaxonMatchesGoatValidator # noqa
|
tol/validators/allowed_keys.py
CHANGED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: 2026 Genome Research Ltd.
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: MIT
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
|
|
7
|
+
from tol.core import DataObject, Validator
|
|
8
|
+
from tol.sources.goat import GoatDataSource, goat
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class TaxonMatchesGoatValidator(Validator):
|
|
12
|
+
"""
|
|
13
|
+
Validates a stream of `DataObject` instances, checking whether its Taxonomy information
|
|
14
|
+
matches that in GoaT
|
|
15
|
+
"""
|
|
16
|
+
@dataclass(slots=True, frozen=True, kw_only=True)
|
|
17
|
+
class Config:
|
|
18
|
+
species_field: str | None = None
|
|
19
|
+
genus_field: str | None = None
|
|
20
|
+
family_field: str | None = None
|
|
21
|
+
superfamily_field: str | None = None
|
|
22
|
+
phylum_field: str | None = None
|
|
23
|
+
kingdom_field: str | None = None
|
|
24
|
+
superkingdom_field: str | None = None
|
|
25
|
+
domain_field: str | None = None
|
|
26
|
+
|
|
27
|
+
__slots__ = ['__config', '__goat_datasource', '_cached_taxa']
|
|
28
|
+
__config: Config
|
|
29
|
+
__goat_datasource: GoatDataSource
|
|
30
|
+
_cached_taxa: dict[str, DataObject]
|
|
31
|
+
|
|
32
|
+
def __init__(self, config: Config, **kwargs) -> None:
|
|
33
|
+
super().__init__()
|
|
34
|
+
self.__config = config
|
|
35
|
+
self.__goat_datasource = goat()
|
|
36
|
+
self._cached_taxa = {}
|
|
37
|
+
|
|
38
|
+
def _validate_data_object(self, obj: DataObject) -> None:
|
|
39
|
+
taxon_id = obj.get_field_by_name('TAXON_ID')
|
|
40
|
+
|
|
41
|
+
# Check whether we already have the information for this id in the cache.
|
|
42
|
+
# If we don't, fetch it from GoaT and add it to the cache
|
|
43
|
+
taxon: DataObject | None
|
|
44
|
+
if taxon_id in self._cached_taxa:
|
|
45
|
+
taxon = self._cached_taxa[taxon_id]
|
|
46
|
+
else:
|
|
47
|
+
taxon = self.__goat_datasource.get_one('taxon', taxon_id)
|
|
48
|
+
|
|
49
|
+
# Add this taxon to cached taxa.
|
|
50
|
+
# Error if GoaT has no taxon with this id
|
|
51
|
+
if taxon is not None:
|
|
52
|
+
self._cached_taxa[taxon_id] = taxon
|
|
53
|
+
else:
|
|
54
|
+
self.add_error(
|
|
55
|
+
object_id=obj.id,
|
|
56
|
+
detail=f'Invalid Taxon ID: {taxon_id}',
|
|
57
|
+
field='taxon_id'
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
# We can't validate a taxon that doesn't exist, so after this error move on
|
|
61
|
+
# to the next DataObject
|
|
62
|
+
return
|
|
63
|
+
|
|
64
|
+
# Check that each associated taxonomy rank for this taxon matches those in GoaT
|
|
65
|
+
taxonomic_ranks = ('species', 'genus', 'family', 'superfamily',
|
|
66
|
+
'phylum', 'kingdom', 'superkingdom', 'domain')
|
|
67
|
+
for rank in taxonomic_ranks:
|
|
68
|
+
# From the rank to check, get the name of its field in the data object we're validating
|
|
69
|
+
# from the validator config. If this field name is `None`, then this taxonomic rank
|
|
70
|
+
# isn't being checked (likely because the data object does not have this field)
|
|
71
|
+
field_name: str | None = getattr(self.__config, f'{rank}_field')
|
|
72
|
+
if field_name is None:
|
|
73
|
+
continue
|
|
74
|
+
|
|
75
|
+
# Fetch the values of these taxonomic ranks
|
|
76
|
+
value_in_data_object = obj.get_field_by_name(field_name)
|
|
77
|
+
value_in_goat = taxon.get_field_by_name(f'{rank}.scientific_name')
|
|
78
|
+
|
|
79
|
+
# Ensure the value in the data object matches the one in GoaT
|
|
80
|
+
if value_in_data_object != value_in_goat:
|
|
81
|
+
self.add_warning(
|
|
82
|
+
object_id=obj.id,
|
|
83
|
+
detail=(f'Value for {field_name} ({value_in_data_object}) '
|
|
84
|
+
f'does not match the value in GoaT ({value_in_goat})'),
|
|
85
|
+
field=field_name,
|
|
86
|
+
)
|
|
@@ -96,7 +96,7 @@ tol/core/data_source_dict.py,sha256=d-hSmoWTwG6IOc0cQTLap1EBslsxYIWGUd3ScSoeH_Q,
|
|
|
96
96
|
tol/core/datasource.py,sha256=e9GaeDPfO_Gs7cgQhmNxCiSDlRNf64reegzFebcMNkA,6303
|
|
97
97
|
tol/core/datasource_error.py,sha256=TqfqaPANG0gishadhA7myCmTO1Fg9u7hVZOvsY6BdAo,1660
|
|
98
98
|
tol/core/datasource_filter.py,sha256=RY2S9kTx0XwdrFRSE2n2GohB9__fKGzFVsZrkN5hzQk,726
|
|
99
|
-
tol/core/datasource_utils.py,sha256=
|
|
99
|
+
tol/core/datasource_utils.py,sha256=6J72RS49IO2quCaFUXBl4DnjZBlXx-aW3Zy9iuzyeQ8,6327
|
|
100
100
|
tol/core/factory.py,sha256=qbLvp5mLTcHbxOjopqtnK-wbZrlskgXjRIREszZjSyE,9157
|
|
101
101
|
tol/core/http_client.py,sha256=QyZarplEHVYIrqEfrySeHbawfbnBU4nN62TLt41x4tY,2242
|
|
102
102
|
tol/core/relationship.py,sha256=etdyCjLbfi2tgkaqzE6cntpNtTzgT_jOPGeNKmPu5yc,4624
|
|
@@ -142,7 +142,7 @@ tol/eln/sanitise.py,sha256=fMj-VrQTnw4zn2X0wnjWQAI8gWAa8RYqNuv23LXQssI,406
|
|
|
142
142
|
tol/ena/__init__.py,sha256=T3TCqaHpgi2Uk2PjPGu60GaG2V8cTrHJlVLtZfLFhTQ,174
|
|
143
143
|
tol/ena/client.py,sha256=ldmm7Z9_auQf1zVWjsFLXYgbKvGtSHTsr88YO3zfv2Y,6731
|
|
144
144
|
tol/ena/converter.py,sha256=nxbo4IFzzOvKNMq3Aeiw5iDqVWvY33nTngLppjHAoGY,1144
|
|
145
|
-
tol/ena/ena_datasource.py,sha256=
|
|
145
|
+
tol/ena/ena_datasource.py,sha256=QRj4pXFeAaC0qPdmtPCrCD3DKVsXhu1jYZ97P3AHlnA,9184
|
|
146
146
|
tol/ena/ena_methods.py,sha256=jgpLssZq-F-vgkO-fYu4jrXenmNkdFpFKAY3VKp5HHE,9209
|
|
147
147
|
tol/ena/factory.py,sha256=3IJCmGLo59PWbGmNqmKho5WYG330OjL8SoZYstIwHt4,3423
|
|
148
148
|
tol/ena/filter.py,sha256=UzOx5ivXvA0TY2QuNzFmS-zDPVNnaAx07DMVkAwVsAE,3370
|
|
@@ -290,9 +290,10 @@ tol/sources/labwhere.py,sha256=gbfpPNKEZEfvw9DXGshg1w4Kdo_tpjWoxndDza6Oa6E,541
|
|
|
290
290
|
tol/sources/mlwh.py,sha256=wPs2yuU1A8v57jaDQbeIThraDqVtzzhm5DAa0qekApM,324
|
|
291
291
|
tol/sources/portal.py,sha256=1mhX1c4fjbRoHJ86RuBgyXFbDJrVIV55pGwvnuOxVuA,761
|
|
292
292
|
tol/sources/portal_attributes.py,sha256=j_ZIZ8RHpgbRzOdHSOnzhAM9xA0HcwiAxuVgybVtDrg,1926
|
|
293
|
-
tol/sources/portaldb.py,sha256=
|
|
293
|
+
tol/sources/portaldb.py,sha256=fZNIUk5mZ3RuQiknZQlPxOK6Vdz_pzqz1-w_dW0L2yE,626
|
|
294
294
|
tol/sources/prefect.py,sha256=16PrC_KfvxrsDzAcq7UvEBo4c6_n38NC23vHQeiljck,1046
|
|
295
295
|
tol/sources/sciops.py,sha256=qbdoNEo-BfWGw16sjANV7dxFRVMDJQlvaSZgofE8604,1129
|
|
296
|
+
tol/sources/sql.py,sha256=mP5hyNNoxi8yKY1Z-6G5EZ1VW24BW_3q5Hp-w5VpPmE,623
|
|
296
297
|
tol/sources/sts.py,sha256=vd65QAYIM1lltHajqJPOrGg10ZCI7OUB2dbWNAlrAn8,749
|
|
297
298
|
tol/sources/sts_legacy.py,sha256=jWDM1_Jicxhay9UEOGh4lzeO0TIxuH8sa34TCn-GDWQ,440
|
|
298
299
|
tol/sources/tolid.py,sha256=ERSB5L_u7c4NtGYTzdGXWjiGiL58QJNC_0ij1MQMMEQ,663
|
|
@@ -314,7 +315,7 @@ tol/sql/relationship.py,sha256=EClMgVx_If5nZV9MV99TQk7Wr7uACWetwQdWAliM5XI,2891
|
|
|
314
315
|
tol/sql/session.py,sha256=VmqTegr4L2X2zvaOJCpwSrkVRx8fc1RVL0drkL2MXu8,806
|
|
315
316
|
tol/sql/sort.py,sha256=ENrjHGgj4fZtXKmkdlkv1HRi1X14SVlcl-tp8Pu7G0k,2553
|
|
316
317
|
tol/sql/sql_converter.py,sha256=taD5FRwadvw2bBaUGrCIiUs0-ATAbBnRYI1M7xe3yEc,4618
|
|
317
|
-
tol/sql/sql_datasource.py,sha256=
|
|
318
|
+
tol/sql/sql_datasource.py,sha256=2FUwGTIN5Dw2cNAEb9fWGsZ0PVdjhdjn8WajA_9LT_Y,15615
|
|
318
319
|
tol/sql/action/__init__.py,sha256=T1zAsCza_lvsNtXF1ecSLt9OFGup8tGnIs68YylBmXI,142
|
|
319
320
|
tol/sql/action/factory.py,sha256=HkareJp_57ud0_Bdd9Kwz3_Rnq2l211sGJgftohFAHg,3589
|
|
320
321
|
tol/sql/auth/__init__.py,sha256=e3JuwugXmXobklqZ1Mt1w03qPgb1WdUaJVM7oblzHyk,202
|
|
@@ -335,8 +336,8 @@ tol/treeval/treeval_datasource.py,sha256=GzY6JwH67b5QdV-UVdCFJfgGAIuZ96J2nl53YxZ
|
|
|
335
336
|
tol/utils/__init__.py,sha256=764-Na1OaNGUDWpMIu51ZtXG7n_nB5MccUFK6LmkWRI,138
|
|
336
337
|
tol/utils/csv.py,sha256=mihww25fSn72c4h-RFeqD_pFIG6KHZP4v1_C0rx81ws,421
|
|
337
338
|
tol/utils/s3.py,sha256=aoYCwJ-qcMqFrpxmViFqPa0O1jgp0phtztO3-0CSNjw,491
|
|
338
|
-
tol/validators/__init__.py,sha256=
|
|
339
|
-
tol/validators/allowed_keys.py,sha256=
|
|
339
|
+
tol/validators/__init__.py,sha256=sF9i4rxi-NsJkqLvvxj2k_I_QPRgkhQZc9ErSqT7quk,1465
|
|
340
|
+
tol/validators/allowed_keys.py,sha256=eLZnr6DVqK6ru6b-T-1hvzSdAxlWZkTNZuohrbO0vS8,1525
|
|
340
341
|
tol/validators/allowed_values.py,sha256=-Yy3Sqo1WYacGKlot_dn3M2o7Oj5MXOioJrJmrWCCxs,1536
|
|
341
342
|
tol/validators/allowed_values_from_datasource.py,sha256=9cVwllBbzfCls8UsojazfCInt9_AakA0_H9pBO1wSL4,3173
|
|
342
343
|
tol/validators/assert_on_condition.py,sha256=eBGgSVfIQ6e45SheM-ZDg7daXJjyZxRVS5L8AWvbXag,2027
|
|
@@ -351,6 +352,7 @@ tol/validators/regex.py,sha256=dLAi_vQt9_DsT6wQZmbYC7X5-Wp15l0leUE6XkPaItg,2602
|
|
|
351
352
|
tol/validators/regex_by_value.py,sha256=XM5EnT4vgD17rfpR3bUE9I56IemSw26BI9MZtMakd4E,2582
|
|
352
353
|
tol/validators/specimens_have_same_taxon.py,sha256=BaJcZ38ZprPcuGTIorSxxC9uGN0_lj6HS6B54EObcuY,2183
|
|
353
354
|
tol/validators/sts_fields.py,sha256=aYbzy15btEg4-ocDT1qrspe7-atoWRrOJ_KmuPU6J14,8936
|
|
355
|
+
tol/validators/taxon_matches_goat.py,sha256=lYZ0qwPver9wXJm2ekv_6KcC49MugVXD9t1IAxPGG2Q,3492
|
|
354
356
|
tol/validators/tolid.py,sha256=VOb6lNFz11H_0KaWX8_nvsw8xJEa6KrjB0p-5lkcqog,3885
|
|
355
357
|
tol/validators/types.py,sha256=jMVpckRp8RS93f7usf58YH_K-5rKWgZIYs7bO9dHhQc,2914
|
|
356
358
|
tol/validators/unique_value_check.py,sha256=sFvDooYkKeORvULGEOTsgIcxlbe0AXDWxY3Gbr3j0KI,1282
|
|
@@ -359,9 +361,9 @@ tol/validators/unique_whole_organisms.py,sha256=RdqA1GzIf3LTdrmNGGdxv0aW2udDY2P9
|
|
|
359
361
|
tol/validators/value_check.py,sha256=DdNx_B1gns01zgBg5N6Bwia46Aukw6MAteM-M37Kv1k,1122
|
|
360
362
|
tol/validators/interfaces/__init__.py,sha256=jtOxnwnwqV_29xjmmMcS_kvlt-pQiWwQYJn2YRP07_w,172
|
|
361
363
|
tol/validators/interfaces/condition_evaluator.py,sha256=nj8Cb8hi47OBy6OVNfeLhF-Pjwtr8MiOSymYL6hfVes,3766
|
|
362
|
-
tol_sdk-1.8.
|
|
363
|
-
tol_sdk-1.8.
|
|
364
|
-
tol_sdk-1.8.
|
|
365
|
-
tol_sdk-1.8.
|
|
366
|
-
tol_sdk-1.8.
|
|
367
|
-
tol_sdk-1.8.
|
|
364
|
+
tol_sdk-1.8.10.dist-info/licenses/LICENSE,sha256=RF9Jacy-9BpUAQQ20INhTgtaNBkmdTolYCHtrrkM2-8,1077
|
|
365
|
+
tol_sdk-1.8.10.dist-info/METADATA,sha256=8VkqLVdpb45ixAI3mGjagWB0lDmyJYxfrSp6tTr-NFg,3143
|
|
366
|
+
tol_sdk-1.8.10.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
367
|
+
tol_sdk-1.8.10.dist-info/entry_points.txt,sha256=jH3HfTwxjzog7E3lq8CKpUWGIRY9FSXbyL6CpUmv6D0,36
|
|
368
|
+
tol_sdk-1.8.10.dist-info/top_level.txt,sha256=PwKMQLphyZNvagBoriVbl8uwHXQl8IC1niawVG0iXMM,10
|
|
369
|
+
tol_sdk-1.8.10.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|