dsw-tdk 3.13.0__py3-none-any.whl → 4.27.0__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.
- {dsw_tdk → dsw/tdk}/__init__.py +16 -15
- dsw/tdk/__main__.py +5 -0
- dsw/tdk/api_client.py +407 -0
- dsw/tdk/build_info.py +17 -0
- dsw/tdk/cli.py +708 -0
- dsw/tdk/config.py +151 -0
- dsw/tdk/consts.py +25 -0
- dsw/tdk/core.py +565 -0
- {dsw_tdk → dsw/tdk}/model.py +468 -422
- dsw/tdk/py.typed +0 -0
- dsw/tdk/templates/LICENSE.j2 +1 -0
- {dsw_tdk → dsw/tdk}/templates/README.md.j2 +13 -13
- dsw/tdk/templates/env.j2 +3 -0
- {dsw_tdk → dsw/tdk}/templates/starter.j2 +13 -14
- {dsw_tdk → dsw/tdk}/utils.py +198 -173
- dsw/tdk/validation.py +290 -0
- {dsw_tdk-3.13.0.dist-info → dsw_tdk-4.27.0.dist-info}/METADATA +28 -33
- dsw_tdk-4.27.0.dist-info/RECORD +20 -0
- {dsw_tdk-3.13.0.dist-info → dsw_tdk-4.27.0.dist-info}/WHEEL +1 -2
- dsw_tdk-4.27.0.dist-info/entry_points.txt +3 -0
- dsw_tdk/__main__.py +0 -3
- dsw_tdk/api_client.py +0 -273
- dsw_tdk/cli.py +0 -412
- dsw_tdk/consts.py +0 -19
- dsw_tdk/core.py +0 -385
- dsw_tdk/validation.py +0 -206
- dsw_tdk-3.13.0.dist-info/LICENSE +0 -201
- dsw_tdk-3.13.0.dist-info/RECORD +0 -17
- dsw_tdk-3.13.0.dist-info/entry_points.txt +0 -3
- dsw_tdk-3.13.0.dist-info/top_level.txt +0 -1
dsw/tdk/validation.py
ADDED
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
import re
|
|
2
|
+
|
|
3
|
+
from . import consts
|
|
4
|
+
from .model import Format, PackageFilter, Step
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class ValidationError(BaseException):
|
|
8
|
+
def __init__(self, field_name: str, message: str):
|
|
9
|
+
self.field_name = field_name
|
|
10
|
+
self.message = message
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def _validate_required(field_name: str, value) -> list[ValidationError]:
|
|
14
|
+
if value is None:
|
|
15
|
+
return [ValidationError(
|
|
16
|
+
field_name=field_name,
|
|
17
|
+
message='Missing but it is required',
|
|
18
|
+
)]
|
|
19
|
+
return []
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def _validate_non_empty(field_name: str, value) -> list[ValidationError]:
|
|
23
|
+
if value is not None and len(value.strip()) == 0:
|
|
24
|
+
return [ValidationError(
|
|
25
|
+
field_name=field_name,
|
|
26
|
+
message='Cannot be empty or only-whitespace',
|
|
27
|
+
)]
|
|
28
|
+
return []
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def _validate_content_type(field_name: str, value) -> list[ValidationError]:
|
|
32
|
+
if value is not None and re.match(consts.REGEX_MIME_TYPE, value) is None:
|
|
33
|
+
return [ValidationError(
|
|
34
|
+
field_name=field_name,
|
|
35
|
+
message='Content type should be valid IANA media type',
|
|
36
|
+
)]
|
|
37
|
+
return []
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def _validate_extension(field_name: str, value) -> list[ValidationError]:
|
|
41
|
+
if value is not None and re.match(consts.REGEX_ORGANIZATION_ID, value) is None:
|
|
42
|
+
return [ValidationError(
|
|
43
|
+
field_name=field_name,
|
|
44
|
+
message='File extension should contain only letters, numbers, '
|
|
45
|
+
'and periods (inside-only)',
|
|
46
|
+
)]
|
|
47
|
+
return []
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def _validate_organization_id(field_name: str, value) -> list[ValidationError]:
|
|
51
|
+
if value is not None and re.match(consts.REGEX_ORGANIZATION_ID, value) is None:
|
|
52
|
+
return [ValidationError(
|
|
53
|
+
field_name=field_name,
|
|
54
|
+
message='Organization ID may contain only letters, numbers, '
|
|
55
|
+
'periods, dashes, and underscores',
|
|
56
|
+
)]
|
|
57
|
+
return []
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def _validate_template_id(field_name: str, value) -> list[ValidationError]:
|
|
61
|
+
if value is not None and re.match(consts.REGEX_TEMPLATE_ID, value) is None:
|
|
62
|
+
return [ValidationError(
|
|
63
|
+
field_name=field_name,
|
|
64
|
+
message='Template ID may contain only letters, numbers, '
|
|
65
|
+
'periods, dashes, and underscores',
|
|
66
|
+
)]
|
|
67
|
+
return []
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def _validate_km_id(field_name: str, value) -> list[ValidationError]:
|
|
71
|
+
if value is not None and re.match(consts.REGEX_KM_ID, value) is None:
|
|
72
|
+
return [ValidationError(
|
|
73
|
+
field_name=field_name,
|
|
74
|
+
message='KM ID may contain only letters, numbers, '
|
|
75
|
+
'periods, dashes, and underscores',
|
|
76
|
+
)]
|
|
77
|
+
return []
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def _validate_version(field_name: str, value) -> list[ValidationError]:
|
|
81
|
+
if value is not None and re.match(consts.REGEX_SEMVER, value) is None:
|
|
82
|
+
return [ValidationError(
|
|
83
|
+
field_name=field_name,
|
|
84
|
+
message='Version must be in semver format <NUM>.<NUM>.<NUM>',
|
|
85
|
+
)]
|
|
86
|
+
return []
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def _validate_natural(field_name: str, value) -> list[ValidationError]:
|
|
90
|
+
if value is not None and (not isinstance(value, int) or value < 1):
|
|
91
|
+
return [ValidationError(
|
|
92
|
+
field_name=field_name,
|
|
93
|
+
message='It must be positive integer',
|
|
94
|
+
)]
|
|
95
|
+
return []
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def _validate_metamodel_version(field_name: str, value) -> list[ValidationError]:
|
|
99
|
+
if isinstance(value, int) and value > 0:
|
|
100
|
+
return []
|
|
101
|
+
if isinstance(value, str) and '.' in value:
|
|
102
|
+
parts = value.split('.')
|
|
103
|
+
if len(parts) != 2:
|
|
104
|
+
return [ValidationError(
|
|
105
|
+
field_name=field_name,
|
|
106
|
+
message='It must be in format <MAJOR>.<MINOR>',
|
|
107
|
+
)]
|
|
108
|
+
try:
|
|
109
|
+
major = int(parts[0])
|
|
110
|
+
minor = int(parts[1])
|
|
111
|
+
if major < 1 or minor < 0:
|
|
112
|
+
return [ValidationError(
|
|
113
|
+
field_name=field_name,
|
|
114
|
+
message='It must be in format <MAJOR>.<MINOR> '
|
|
115
|
+
'with MAJOR >= 1 and MINOR >= 0',
|
|
116
|
+
)]
|
|
117
|
+
return []
|
|
118
|
+
except ValueError:
|
|
119
|
+
return [ValidationError(
|
|
120
|
+
field_name=field_name,
|
|
121
|
+
message='It must be in format <MAJOR>.<MINOR> '
|
|
122
|
+
'with MAJOR >= 1 and MINOR >= 0',
|
|
123
|
+
)]
|
|
124
|
+
return [ValidationError(
|
|
125
|
+
field_name=field_name,
|
|
126
|
+
message='It must be a positive integer or in format <MAJOR>.<MINOR>',
|
|
127
|
+
)]
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def _validate_package_id(field_name: str, value: str) -> list[ValidationError]:
|
|
131
|
+
res = []
|
|
132
|
+
if value is None:
|
|
133
|
+
return res
|
|
134
|
+
if not isinstance(value, str):
|
|
135
|
+
return [ValidationError(
|
|
136
|
+
field_name=field_name,
|
|
137
|
+
message='Package ID is not a string',
|
|
138
|
+
)]
|
|
139
|
+
parts = value.split(':')
|
|
140
|
+
if len(parts) != 3:
|
|
141
|
+
res.append(ValidationError(
|
|
142
|
+
field_name=field_name,
|
|
143
|
+
message=f'Package ID is not valid (only {len(parts)} parts)',
|
|
144
|
+
))
|
|
145
|
+
if re.match(consts.REGEX_ORGANIZATION_ID, parts[0]) is None:
|
|
146
|
+
res.append(ValidationError(
|
|
147
|
+
field_name=field_name,
|
|
148
|
+
message='Package ID contains invalid organization id',
|
|
149
|
+
))
|
|
150
|
+
if re.match(consts.REGEX_KM_ID, parts[1]) is None:
|
|
151
|
+
res.append(ValidationError(
|
|
152
|
+
field_name=field_name,
|
|
153
|
+
message='Package ID contains invalid KM id',
|
|
154
|
+
))
|
|
155
|
+
if re.match(consts.REGEX_SEMVER, parts[2]) is None:
|
|
156
|
+
res.append(ValidationError(
|
|
157
|
+
field_name=field_name,
|
|
158
|
+
message='Package ID contains invalid version',
|
|
159
|
+
))
|
|
160
|
+
return res
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
def _validate_jinja_options(field_name: str, value: dict[str, str]) -> list[ValidationError]:
|
|
164
|
+
res = []
|
|
165
|
+
if value is None:
|
|
166
|
+
return res
|
|
167
|
+
for k in ('template', 'content-type', 'extension'):
|
|
168
|
+
if k not in value:
|
|
169
|
+
res.append(ValidationError(
|
|
170
|
+
field_name=field_name,
|
|
171
|
+
message='Jinja option cannot be left out',
|
|
172
|
+
))
|
|
173
|
+
elif value[k] is None or not isinstance(value[k], str) or len(value[k]) == 0:
|
|
174
|
+
res.append(ValidationError(
|
|
175
|
+
field_name=field_name,
|
|
176
|
+
message='Jinja option cannot be empty',
|
|
177
|
+
))
|
|
178
|
+
if 'content-type' in value:
|
|
179
|
+
res.extend(_validate_content_type(
|
|
180
|
+
field_name=f'{field_name}.content-type',
|
|
181
|
+
value=value['content-type'],
|
|
182
|
+
))
|
|
183
|
+
return res
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
class GenericValidator:
|
|
187
|
+
|
|
188
|
+
def __init__(self, rules):
|
|
189
|
+
self.rules = rules
|
|
190
|
+
|
|
191
|
+
def validate_field(self, entity, field_name: str):
|
|
192
|
+
for validator in self.rules.get(field_name, []):
|
|
193
|
+
err = validator(field_name, getattr(entity, field_name))
|
|
194
|
+
if len(err) != 0:
|
|
195
|
+
raise err[0]
|
|
196
|
+
|
|
197
|
+
def validate(self, entity, field_name_prefix: str = ''):
|
|
198
|
+
for field_name, validators in self.rules.items():
|
|
199
|
+
if field_name.startswith('__'):
|
|
200
|
+
continue
|
|
201
|
+
for validator in validators:
|
|
202
|
+
err = validator(field_name_prefix + field_name, getattr(entity, field_name))
|
|
203
|
+
if len(err) != 0:
|
|
204
|
+
raise err[0]
|
|
205
|
+
if '__all' in self.rules:
|
|
206
|
+
err = self.rules['__all'](field_name_prefix, entity)
|
|
207
|
+
if len(err) != 0:
|
|
208
|
+
raise err[0]
|
|
209
|
+
|
|
210
|
+
def collect_errors(self, entity, field_name_prefix: str = '') -> list[ValidationError]:
|
|
211
|
+
result = []
|
|
212
|
+
for field_name, validators in self.rules.items():
|
|
213
|
+
if field_name.startswith('__'):
|
|
214
|
+
continue
|
|
215
|
+
for validator in validators:
|
|
216
|
+
result.extend(validator(
|
|
217
|
+
field_name=f'{field_name_prefix}{field_name}',
|
|
218
|
+
value=getattr(entity, field_name),
|
|
219
|
+
))
|
|
220
|
+
if '__all' in self.rules:
|
|
221
|
+
result.extend(self.rules['__all'](field_name_prefix, entity))
|
|
222
|
+
return result
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
PackageFilterValidator = GenericValidator({
|
|
226
|
+
'organization_id': [_validate_organization_id],
|
|
227
|
+
'km_id': [_validate_km_id],
|
|
228
|
+
'min_version': [_validate_version],
|
|
229
|
+
'max_version': [_validate_version],
|
|
230
|
+
})
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
def _validate_package_filters(field_name: str, value: list[PackageFilter]) -> list[ValidationError]:
|
|
234
|
+
res = []
|
|
235
|
+
for v in value:
|
|
236
|
+
res.extend(PackageFilterValidator.collect_errors(v, field_name_prefix=f'{field_name}.'))
|
|
237
|
+
return res
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
def _validate_step(field_name_prefix: str, value: Step) -> list[ValidationError]:
|
|
241
|
+
if value.name == 'jinja':
|
|
242
|
+
return _validate_jinja_options(f'{field_name_prefix}options', value.options)
|
|
243
|
+
return []
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
StepValidator = GenericValidator({
|
|
247
|
+
'name': [_validate_non_empty],
|
|
248
|
+
'options': [],
|
|
249
|
+
'__all': _validate_step,
|
|
250
|
+
})
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
def _validate_steps(field_name: str, value: list[Step]) -> list[ValidationError]:
|
|
254
|
+
res = []
|
|
255
|
+
for v in value:
|
|
256
|
+
res.extend(StepValidator.collect_errors(v, field_name_prefix=f'{field_name}.'))
|
|
257
|
+
return res
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
FormatValidator = GenericValidator({
|
|
261
|
+
'uuid': [_validate_required, _validate_non_empty],
|
|
262
|
+
'name': [_validate_required, _validate_non_empty],
|
|
263
|
+
'icon': [_validate_required, _validate_non_empty],
|
|
264
|
+
'steps': [_validate_required, _validate_steps],
|
|
265
|
+
})
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
def _validate_formats(field_name: str, value: list[Format]) -> list[ValidationError]:
|
|
269
|
+
res = []
|
|
270
|
+
uuids = set()
|
|
271
|
+
for v in value:
|
|
272
|
+
if v.uuid in uuids:
|
|
273
|
+
res.append(ValidationError(field_name, f'Duplicate format UUID {v.uuid}'))
|
|
274
|
+
uuids.add(v.uuid)
|
|
275
|
+
res.extend(FormatValidator.collect_errors(v, field_name_prefix=f'{field_name}.'))
|
|
276
|
+
return res
|
|
277
|
+
|
|
278
|
+
|
|
279
|
+
TemplateValidator = GenericValidator({
|
|
280
|
+
'template_id': [_validate_required, _validate_template_id],
|
|
281
|
+
'organization_id': [_validate_required, _validate_organization_id],
|
|
282
|
+
'version': [_validate_required, _validate_version],
|
|
283
|
+
'name': [_validate_required, _validate_non_empty],
|
|
284
|
+
'description': [_validate_required, _validate_non_empty],
|
|
285
|
+
'readme': [_validate_required, _validate_non_empty],
|
|
286
|
+
'license': [_validate_required, _validate_non_empty],
|
|
287
|
+
'metamodel_version': [_validate_metamodel_version, _validate_required],
|
|
288
|
+
'allowed_packages': [_validate_package_filters],
|
|
289
|
+
'formats': [_validate_required, _validate_formats],
|
|
290
|
+
})
|
|
@@ -1,50 +1,49 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
2
|
Name: dsw-tdk
|
|
3
|
-
Version:
|
|
3
|
+
Version: 4.27.0
|
|
4
4
|
Summary: Data Stewardship Wizard Template Development Toolkit
|
|
5
|
-
|
|
5
|
+
Keywords: documents,dsw,jinja2,template,toolkit
|
|
6
6
|
Author: Marek Suchánek
|
|
7
|
-
Author-email: marek.suchanek@ds-wizard.org
|
|
8
|
-
License: Apache
|
|
9
|
-
Keywords: dsw template toolkit jinja documents
|
|
10
|
-
Platform: UNKNOWN
|
|
7
|
+
Author-email: Marek Suchánek <marek.suchanek@ds-wizard.org>
|
|
8
|
+
License: Apache License 2.0
|
|
11
9
|
Classifier: Framework :: AsyncIO
|
|
10
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
12
11
|
Classifier: License :: OSI Approved :: Apache Software License
|
|
13
12
|
Classifier: Programming Language :: Python
|
|
14
|
-
Classifier: Programming Language :: Python ::
|
|
15
|
-
Classifier: Programming Language :: Python :: 3
|
|
16
|
-
Classifier: Programming Language :: Python :: 3.
|
|
17
|
-
Classifier: Programming Language :: Python :: 3.
|
|
18
|
-
Classifier: Programming Language :: Python :: 3.7
|
|
19
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
17
|
Classifier: Topic :: Internet :: WWW/HTTP
|
|
21
|
-
Classifier: Topic :: Internet :: WWW/HTTP :: Indexing/Search
|
|
22
|
-
Classifier: Topic :: Internet :: WWW/HTTP :: Site Management
|
|
23
18
|
Classifier: Topic :: Utilities
|
|
24
|
-
Requires-Python: >=3.6, <4
|
|
25
|
-
Description-Content-Type: text/markdown
|
|
26
|
-
License-File: LICENSE
|
|
27
19
|
Requires-Dist: aiohttp
|
|
28
20
|
Requires-Dist: click
|
|
29
21
|
Requires-Dist: colorama
|
|
30
22
|
Requires-Dist: humanize
|
|
31
|
-
Requires-Dist:
|
|
23
|
+
Requires-Dist: jinja2
|
|
32
24
|
Requires-Dist: multidict
|
|
33
25
|
Requires-Dist: pathspec
|
|
34
26
|
Requires-Dist: python-dotenv
|
|
35
27
|
Requires-Dist: python-slugify
|
|
36
|
-
Requires-Dist:
|
|
28
|
+
Requires-Dist: watchfiles
|
|
29
|
+
Requires-Dist: pytest ; extra == 'test'
|
|
30
|
+
Requires-Python: >=3.10, <4
|
|
31
|
+
Project-URL: Homepage, https://ds-wizard.org
|
|
32
|
+
Project-URL: Repository, https://github.com/ds-wizard/engine-tools
|
|
33
|
+
Project-URL: Documentation, https://guide.ds-wizard.org
|
|
34
|
+
Project-URL: Issues, https://github.com/ds-wizard/ds-wizard/issues
|
|
35
|
+
Provides-Extra: test
|
|
36
|
+
Description-Content-Type: text/markdown
|
|
37
37
|
|
|
38
38
|
# dsw-tdk
|
|
39
39
|
|
|
40
40
|
[](https://guide.ds-wizard.org)
|
|
41
|
-
[](https://img.shields.io/github/v/release/ds-wizard/engine-tools)](https://github.com/ds-wizard/engine-tools/releases)
|
|
42
42
|
[](https://pypi.org/project/dsw-tdk/)
|
|
43
|
-
[](https://www.codacy.com/gh/ds-wizard/dsw-tdk/dashboard?utm_source=github.com&utm_medium=referral&utm_content=ds-wizard/dsw-tdk&utm_campaign=Badge_Grade)
|
|
44
|
-
[](https://github.com/ds-wizard/dsw-tdk/actions)
|
|
45
43
|
[](https://hub.docker.com/r/datastewardshipwizard/dsw-tdk)
|
|
46
|
-
[](LICENSE)
|
|
47
45
|
[](https://bestpractices.coreinfrastructure.org/projects/4975)
|
|
46
|
+
[](https://python.org)
|
|
48
47
|
|
|
49
48
|
*Template Development Kit for [Data Stewardship Wizard](https://ds-wizard.org)*
|
|
50
49
|
|
|
@@ -102,12 +101,10 @@ For further information, visit our [documentation](https://docs.ds-wizard.org).
|
|
|
102
101
|
|
|
103
102
|
You can use the following environment variables to avoid repeating CLI options.
|
|
104
103
|
|
|
105
|
-
- `
|
|
106
|
-
- Used when `--api-
|
|
107
|
-
- `
|
|
108
|
-
- Used when `--
|
|
109
|
-
- `DSW_PASSWORD` = corresponding password to login with your admin account
|
|
110
|
-
- Used when `--password` not specified
|
|
104
|
+
- `DSW_API_URL` = URL of DSW API you want to use, e.g., https://api.demo.ds-wizard.org (notice that it is **not** the URL of client, you can find it out by clicking Help > About in DSW)
|
|
105
|
+
- Used when `--api-url` not specified
|
|
106
|
+
- `DSW_API_KEY` = API Key of the user authorized to manage document templates
|
|
107
|
+
- Used when `--api-key` not specified
|
|
111
108
|
|
|
112
109
|
You can also use them in `.env` file which is automatically loaded from current directory or specify it using `--dot-env` option:
|
|
113
110
|
|
|
@@ -138,7 +135,7 @@ $ dsw-tdk --debug list
|
|
|
138
135
|
|
|
139
136
|
## Requirements
|
|
140
137
|
|
|
141
|
-
- [Python 3.
|
|
138
|
+
- [Python 3.8+](https://www.python.org/downloads/)
|
|
142
139
|
- DSW instance with matching version (e.g. a local one using [Docker](https://github.com/ds-wizard/dsw-deployment-example))
|
|
143
140
|
- Admin credentials (email+password) to the DSW instance
|
|
144
141
|
|
|
@@ -155,5 +152,3 @@ For more information read [CONTRIBUTING](CONTRIBUTING.md).
|
|
|
155
152
|
## License
|
|
156
153
|
|
|
157
154
|
This project is licensed under the Apache 2 License - see the [LICENSE](LICENSE) file for more details.
|
|
158
|
-
|
|
159
|
-
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
dsw/tdk/__init__.py,sha256=ofVgqzsHfzERknIDuS08mjNh6cCbchLcrbuYEtJBUl0,291
|
|
2
|
+
dsw/tdk/__main__.py,sha256=7atdpOyr41OPmApZ4ktsGSF31GSIfEY9xOBzJZ-azYQ,85
|
|
3
|
+
dsw/tdk/api_client.py,sha256=TBVzMNvOARPvRfFIOP9IXytkAeY6uovegfN9W1lCOzM,15377
|
|
4
|
+
dsw/tdk/build_info.py,sha256=StkP0pJCmLTOw9Bgu2hzdlQFIe6WTZkXtOP8HsXUjDw,381
|
|
5
|
+
dsw/tdk/cli.py,sha256=6Cu1movV2_LkA-pNTQB1dSREYqTNOnArqPiJIusQ9Do,28137
|
|
6
|
+
dsw/tdk/config.py,sha256=4G2VfJ2DIm-NLQdtCHg6y_cEi0tDf9m6mbAgqEGeNeY,4782
|
|
7
|
+
dsw/tdk/consts.py,sha256=f2tztF4m7s4mbj3qNH3uHpAgEOFIK_fzwZerIhtv814,714
|
|
8
|
+
dsw/tdk/core.py,sha256=7DC63ohGZ6ZZhuk3XjqH6NUHFvrg-hANSRlYmfI-wLA,27457
|
|
9
|
+
dsw/tdk/model.py,sha256=tJZnrQE88dXUZZ3b_UbQjeHm1W_qwbCeqscl9IK3r80,17527
|
|
10
|
+
dsw/tdk/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
11
|
+
dsw/tdk/templates/LICENSE.j2,sha256=6WzK06169rxZ4V_boYgejcZkw-1Up_WoU18iI3Gbkfs,60
|
|
12
|
+
dsw/tdk/templates/README.md.j2,sha256=FzUABeMM8To0oT48Kytoox64uAZ8F7FSAAXgpyKzqdU,247
|
|
13
|
+
dsw/tdk/templates/env.j2,sha256=yUaY7ZLbjdG45-_q6KWi-YnX9bjP7_lfXrowhJF1he0,98
|
|
14
|
+
dsw/tdk/templates/starter.j2,sha256=JKJIkiXsmBO4P6pKXM4IvSz3JgJhqCnaZI1NVfPPnXg,246
|
|
15
|
+
dsw/tdk/utils.py,sha256=qTqar4RUqRMvIO_RFyoSgeeTvZy8qmyKLWoE9XoPY9k,5678
|
|
16
|
+
dsw/tdk/validation.py,sha256=KD2smmH2uDBVxx35eczJmYNnzJcq8g8L5LDu1hkbxe0,10088
|
|
17
|
+
dsw_tdk-4.27.0.dist-info/WHEEL,sha256=fAguSjoiATBe7TNBkJwOjyL1Tt4wwiaQGtNtjRPNMQA,80
|
|
18
|
+
dsw_tdk-4.27.0.dist-info/entry_points.txt,sha256=-55ASKbqu423XqpytOZyuTZSNWus2MsQuFXl2p_nCfc,42
|
|
19
|
+
dsw_tdk-4.27.0.dist-info/METADATA,sha256=pl94tCMYLsQx9VWtQl2424NWAXSogP-mwWKI16EGp9M,6144
|
|
20
|
+
dsw_tdk-4.27.0.dist-info/RECORD,,
|
dsw_tdk/__main__.py
DELETED