dsw-tdk 4.13.0__py2.py3-none-any.whl → 4.14.0__py2.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/__main__.py +1 -0
- dsw/tdk/api_client.py +58 -30
- dsw/tdk/build_info.py +4 -4
- dsw/tdk/cli.py +59 -44
- dsw/tdk/consts.py +4 -3
- dsw/tdk/core.py +127 -99
- dsw/tdk/model.py +77 -67
- dsw/tdk/templates/starter.j2 +1 -2
- dsw/tdk/utils.py +8 -9
- dsw/tdk/validation.py +72 -18
- {dsw_tdk-4.13.0.dist-info → dsw_tdk-4.14.0.dist-info}/METADATA +3 -3
- dsw_tdk-4.14.0.dist-info/RECORD +20 -0
- {dsw_tdk-4.13.0.dist-info → dsw_tdk-4.14.0.dist-info}/WHEEL +1 -1
- dsw_tdk-4.13.0.dist-info/RECORD +0 -20
- {dsw_tdk-4.13.0.dist-info → dsw_tdk-4.14.0.dist-info}/LICENSE +0 -0
- {dsw_tdk-4.13.0.dist-info → dsw_tdk-4.14.0.dist-info}/entry_points.txt +0 -0
- {dsw_tdk-4.13.0.dist-info → dsw_tdk-4.14.0.dist-info}/top_level.txt +0 -0
dsw/tdk/core.py
CHANGED
|
@@ -7,11 +7,9 @@ import pathlib
|
|
|
7
7
|
import re
|
|
8
8
|
import shutil
|
|
9
9
|
import tempfile
|
|
10
|
-
import watchfiles # type: ignore
|
|
11
10
|
import zipfile
|
|
12
11
|
|
|
13
|
-
|
|
14
|
-
from typing import List, Optional, Tuple
|
|
12
|
+
import watchfiles
|
|
15
13
|
|
|
16
14
|
from .api_client import DSWAPIClient, DSWCommunicationError
|
|
17
15
|
from .consts import DEFAULT_ENCODING, REGEX_SEMVER
|
|
@@ -20,7 +18,7 @@ from .utils import UUIDGen, create_dot_env
|
|
|
20
18
|
from .validation import ValidationError, TemplateValidator
|
|
21
19
|
|
|
22
20
|
|
|
23
|
-
ChangeItem =
|
|
21
|
+
ChangeItem = tuple[watchfiles.Change, pathlib.Path]
|
|
24
22
|
|
|
25
23
|
|
|
26
24
|
def _change(item: ChangeItem, root: pathlib.Path) -> str:
|
|
@@ -54,6 +52,7 @@ METAMODEL_VERSION_SUPPORT = {
|
|
|
54
52
|
}
|
|
55
53
|
|
|
56
54
|
|
|
55
|
+
# pylint: disable=too-many-public-methods
|
|
57
56
|
class TDKCore:
|
|
58
57
|
|
|
59
58
|
def _check_metamodel_version(self):
|
|
@@ -64,24 +63,24 @@ class TDKCore:
|
|
|
64
63
|
if 'v' == api_version[0]:
|
|
65
64
|
api_version = api_version[1:]
|
|
66
65
|
if not re.match(REGEX_SEMVER, api_version):
|
|
67
|
-
self.logger.warning(
|
|
66
|
+
self.logger.warning('Using non-stable release of API: %s', self.remote_version)
|
|
68
67
|
return
|
|
69
68
|
parts = api_version.split('.')
|
|
70
69
|
ver = (int(parts[0]), int(parts[1]), int(parts[2]))
|
|
71
70
|
vtag = f'v{ver[0]}.{ver[1]}.{ver[2]}'
|
|
72
71
|
hint = 'Fix your metamodelVersion in template.json and/or visit docs'
|
|
73
|
-
if mm_ver not in METAMODEL_VERSION_SUPPORT
|
|
72
|
+
if mm_ver not in METAMODEL_VERSION_SUPPORT:
|
|
74
73
|
raise TDKProcessingError(f'Unknown metamodel version: {mm_ver}', hint)
|
|
75
74
|
min_version = METAMODEL_VERSION_SUPPORT[mm_ver]
|
|
76
75
|
if min_version > ver:
|
|
77
76
|
raise TDKProcessingError(f'Unsupported metamodel version for API {vtag}', hint)
|
|
78
|
-
if mm_ver + 1 in METAMODEL_VERSION_SUPPORT
|
|
77
|
+
if mm_ver + 1 in METAMODEL_VERSION_SUPPORT:
|
|
79
78
|
max_version = METAMODEL_VERSION_SUPPORT[mm_ver + 1]
|
|
80
79
|
if ver >= max_version:
|
|
81
80
|
raise TDKProcessingError(f'Unsupported metamodel version for API {vtag}', hint)
|
|
82
81
|
|
|
83
|
-
def __init__(self, template:
|
|
84
|
-
client:
|
|
82
|
+
def __init__(self, template: Template | None = None, project: TemplateProject | None = None,
|
|
83
|
+
client: DSWAPIClient | None = None, logger: logging.Logger | None = None):
|
|
85
84
|
self.template = template
|
|
86
85
|
self.project = project
|
|
87
86
|
self.client = client
|
|
@@ -113,13 +112,13 @@ class TDKCore:
|
|
|
113
112
|
return self.client
|
|
114
113
|
|
|
115
114
|
async def init_client(self, api_url: str, api_key: str):
|
|
116
|
-
self.logger.info(
|
|
115
|
+
self.logger.info('Connecting to %s', api_url)
|
|
117
116
|
self.client = DSWAPIClient(api_url=api_url, api_key=api_key)
|
|
118
117
|
self.remote_version = await self.client.get_api_version()
|
|
119
118
|
user = await self.client.get_current_user()
|
|
120
|
-
self.logger.info(
|
|
121
|
-
|
|
122
|
-
self.logger.debug(
|
|
119
|
+
self.logger.info('Successfully authenticated as %s %s (%s)',
|
|
120
|
+
user['firstName'], user['lastName'], user['email'])
|
|
121
|
+
self.logger.debug('Connected to API version %s', self.remote_version)
|
|
123
122
|
|
|
124
123
|
def prepare_local(self, template_dir):
|
|
125
124
|
self.logger.debug('Preparing local template project')
|
|
@@ -131,32 +130,32 @@ class TDKCore:
|
|
|
131
130
|
self.safe_project.load()
|
|
132
131
|
|
|
133
132
|
async def load_remote(self, template_id: str):
|
|
134
|
-
self.logger.info(
|
|
133
|
+
self.logger.info('Retrieving template draft %s', template_id)
|
|
135
134
|
self.template = await self.safe_client.get_template_draft(remote_id=template_id)
|
|
136
135
|
self.logger.debug('Retrieving template draft files')
|
|
137
136
|
files = await self.safe_client.get_template_draft_files(remote_id=template_id)
|
|
138
|
-
self.logger.info(
|
|
137
|
+
self.logger.info('Retrieved %s file(s)', len(files))
|
|
139
138
|
for tfile in files:
|
|
140
139
|
self.safe_template.files[tfile.filename.as_posix()] = tfile
|
|
141
140
|
self.logger.debug('Retrieving template draft assets')
|
|
142
141
|
assets = await self.safe_client.get_template_draft_assets(remote_id=template_id)
|
|
143
|
-
self.logger.info(
|
|
142
|
+
self.logger.info('Retrieved %s asset(s)', len(assets))
|
|
144
143
|
for tfile in assets:
|
|
145
144
|
self.safe_template.files[tfile.filename.as_posix()] = tfile
|
|
146
145
|
|
|
147
146
|
async def download_bundle(self, template_id: str) -> bytes:
|
|
148
|
-
self.logger.info(
|
|
147
|
+
self.logger.info('Retrieving template %s bundle', template_id)
|
|
149
148
|
return await self.safe_client.get_template_bundle(remote_id=template_id)
|
|
150
149
|
|
|
151
|
-
async def list_remote_templates(self) ->
|
|
150
|
+
async def list_remote_templates(self) -> list[Template]:
|
|
152
151
|
self.logger.info('Listing remote document templates')
|
|
153
152
|
return await self.safe_client.get_templates()
|
|
154
153
|
|
|
155
|
-
async def list_remote_drafts(self) ->
|
|
154
|
+
async def list_remote_drafts(self) -> list[Template]:
|
|
156
155
|
self.logger.info('Listing remote document template drafts')
|
|
157
156
|
return await self.safe_client.get_drafts()
|
|
158
157
|
|
|
159
|
-
def verify(self) ->
|
|
158
|
+
def verify(self) -> list[ValidationError]:
|
|
160
159
|
template = self.template or self.safe_project.template
|
|
161
160
|
if template is None:
|
|
162
161
|
raise RuntimeError('No template is loaded')
|
|
@@ -166,7 +165,7 @@ class TDKCore:
|
|
|
166
165
|
if self.project is None:
|
|
167
166
|
raise RuntimeError('No template project is initialized')
|
|
168
167
|
self.project.template = self.safe_template
|
|
169
|
-
self.logger.debug(
|
|
168
|
+
self.logger.debug('Initiating storing local template project (force=%s)', force)
|
|
170
169
|
self.project.store(force=force)
|
|
171
170
|
|
|
172
171
|
async def store_remote(self, force: bool):
|
|
@@ -174,8 +173,9 @@ class TDKCore:
|
|
|
174
173
|
self._check_metamodel_version()
|
|
175
174
|
org_id = await self.safe_client.get_organization_id()
|
|
176
175
|
if org_id != self.safe_template.organization_id:
|
|
177
|
-
self.logger.warning(
|
|
178
|
-
|
|
176
|
+
self.logger.warning('There is different organization ID set in the DSW instance'
|
|
177
|
+
' (local: %s, remote: %s)',
|
|
178
|
+
self.safe_template.organization_id, org_id)
|
|
179
179
|
self.remote_id = self.safe_template.id_with_org(org_id)
|
|
180
180
|
template_exists = await self.safe_client.check_draft_exists(remote_id=self.remote_id)
|
|
181
181
|
if template_exists and force:
|
|
@@ -186,26 +186,39 @@ class TDKCore:
|
|
|
186
186
|
template_exists = not result
|
|
187
187
|
|
|
188
188
|
if template_exists:
|
|
189
|
-
# TODO: do not remove if not necessary (make diff?)
|
|
190
189
|
self.logger.info('Updating existing remote document template draft')
|
|
191
|
-
await self.safe_client.update_template_draft(
|
|
190
|
+
await self.safe_client.update_template_draft(
|
|
191
|
+
template=self.safe_template,
|
|
192
|
+
remote_id=self.remote_id,
|
|
193
|
+
)
|
|
192
194
|
self.logger.debug('Retrieving remote assets')
|
|
193
|
-
remote_assets = await self.safe_client.get_template_draft_assets(
|
|
195
|
+
remote_assets = await self.safe_client.get_template_draft_assets(
|
|
196
|
+
remote_id=self.remote_id,
|
|
197
|
+
)
|
|
194
198
|
self.logger.debug('Retrieving remote files')
|
|
195
|
-
remote_files = await self.safe_client.get_template_draft_files(
|
|
196
|
-
|
|
199
|
+
remote_files = await self.safe_client.get_template_draft_files(
|
|
200
|
+
remote_id=self.remote_id,
|
|
201
|
+
)
|
|
202
|
+
await self.cleanup_remote_files(
|
|
203
|
+
remote_assets=remote_assets,
|
|
204
|
+
remote_files=remote_files,
|
|
205
|
+
)
|
|
197
206
|
else:
|
|
198
207
|
self.logger.info('Creating remote document template draft')
|
|
199
|
-
await self.safe_client.create_new_template_draft(
|
|
208
|
+
await self.safe_client.create_new_template_draft(
|
|
209
|
+
template=self.safe_template,
|
|
210
|
+
remote_id=self.remote_id,
|
|
211
|
+
)
|
|
200
212
|
await self.store_remote_files()
|
|
201
213
|
|
|
202
214
|
async def _update_template_file(self, remote_tfile: TemplateFile, local_tfile: TemplateFile,
|
|
203
215
|
project_update: bool = False):
|
|
204
216
|
try:
|
|
205
|
-
self.logger.debug(
|
|
206
|
-
|
|
217
|
+
self.logger.debug('Updating existing remote %s %s (%s) started',
|
|
218
|
+
remote_tfile.remote_type.value, remote_tfile.filename.as_posix(),
|
|
219
|
+
remote_tfile.remote_id)
|
|
207
220
|
local_tfile.remote_id = remote_tfile.remote_id
|
|
208
|
-
if remote_tfile.remote_type == TemplateFileType.
|
|
221
|
+
if remote_tfile.remote_type == TemplateFileType.ASSET:
|
|
209
222
|
result = await self.safe_client.put_template_draft_asset_content(
|
|
210
223
|
remote_id=self.remote_id,
|
|
211
224
|
tfile=local_tfile,
|
|
@@ -215,25 +228,27 @@ class TDKCore:
|
|
|
215
228
|
remote_id=self.remote_id,
|
|
216
229
|
tfile=local_tfile,
|
|
217
230
|
)
|
|
218
|
-
self.logger.debug(
|
|
219
|
-
|
|
220
|
-
|
|
231
|
+
self.logger.debug('Updating existing remote %s %s (%s) finished: %s',
|
|
232
|
+
remote_tfile.remote_type.value, remote_tfile.filename.as_posix(),
|
|
233
|
+
remote_tfile.remote_id, 'ok' if result else 'failed')
|
|
221
234
|
if project_update and result:
|
|
222
235
|
self.safe_project.update_template_file(result)
|
|
223
|
-
except Exception as
|
|
236
|
+
except Exception as e1:
|
|
224
237
|
try:
|
|
225
|
-
self.logger.debug(
|
|
238
|
+
self.logger.debug('Trying to delete/create due to: %s', str(e1))
|
|
226
239
|
await self._delete_template_file(tfile=remote_tfile)
|
|
227
240
|
await self._create_template_file(tfile=local_tfile, project_update=True)
|
|
228
|
-
except Exception as
|
|
229
|
-
self.logger.error(
|
|
230
|
-
|
|
241
|
+
except Exception as e2:
|
|
242
|
+
self.logger.error('Failed to update existing remote %s %s: %s',
|
|
243
|
+
remote_tfile.remote_type.value,
|
|
244
|
+
remote_tfile.filename.as_posix(), e2)
|
|
231
245
|
|
|
232
246
|
async def _delete_template_file(self, tfile: TemplateFile, project_update: bool = False):
|
|
233
247
|
try:
|
|
234
|
-
self.logger.debug(
|
|
235
|
-
|
|
236
|
-
|
|
248
|
+
self.logger.debug('Deleting existing remote %s %s (%s) started',
|
|
249
|
+
tfile.remote_type.value, tfile.filename.as_posix(),
|
|
250
|
+
tfile.remote_id)
|
|
251
|
+
if tfile.remote_type == TemplateFileType.ASSET:
|
|
237
252
|
result = await self.safe_client.delete_template_draft_asset(
|
|
238
253
|
remote_id=self.remote_id,
|
|
239
254
|
asset_id=tfile.remote_id,
|
|
@@ -243,18 +258,19 @@ class TDKCore:
|
|
|
243
258
|
remote_id=self.remote_id,
|
|
244
259
|
file_id=tfile.remote_id,
|
|
245
260
|
)
|
|
246
|
-
self.logger.debug(
|
|
247
|
-
|
|
248
|
-
|
|
261
|
+
self.logger.debug('Deleting existing remote %s %s (%s) finished: %s',
|
|
262
|
+
tfile.remote_type.value, tfile.filename.as_posix(),
|
|
263
|
+
tfile.remote_id, 'ok' if result else 'failed')
|
|
249
264
|
if project_update and result:
|
|
250
265
|
self.safe_project.remove_template_file(tfile.filename)
|
|
251
266
|
except Exception as e:
|
|
252
|
-
self.logger.error(
|
|
253
|
-
|
|
267
|
+
self.logger.error('Failed to delete existing remote %s %s: %s',
|
|
268
|
+
tfile.remote_type.value, tfile.filename.as_posix(), e)
|
|
254
269
|
|
|
255
|
-
async def cleanup_remote_files(self, remote_assets:
|
|
270
|
+
async def cleanup_remote_files(self, remote_assets: list[TemplateFile],
|
|
271
|
+
remote_files: list[TemplateFile]):
|
|
256
272
|
for tfile in self.safe_project.safe_template.files.values():
|
|
257
|
-
self.logger.debug(
|
|
273
|
+
self.logger.debug('Cleaning up remote %s', tfile.filename.as_posix())
|
|
258
274
|
for remote_asset in remote_assets:
|
|
259
275
|
if remote_asset.filename == tfile.filename:
|
|
260
276
|
await self._delete_template_file(tfile=remote_asset, project_update=False)
|
|
@@ -264,60 +280,68 @@ class TDKCore:
|
|
|
264
280
|
|
|
265
281
|
async def _create_template_file(self, tfile: TemplateFile, project_update: bool = False):
|
|
266
282
|
try:
|
|
267
|
-
self.logger.debug(
|
|
268
|
-
|
|
269
|
-
if tfile.remote_type == TemplateFileType.
|
|
270
|
-
result = await self.safe_client.post_template_draft_asset(
|
|
283
|
+
self.logger.debug('Storing remote %s %s started',
|
|
284
|
+
tfile.remote_type.value, tfile.filename.as_posix())
|
|
285
|
+
if tfile.remote_type == TemplateFileType.ASSET:
|
|
286
|
+
result = await self.safe_client.post_template_draft_asset(
|
|
287
|
+
remote_id=self.remote_id,
|
|
288
|
+
tfile=tfile,
|
|
289
|
+
)
|
|
271
290
|
else:
|
|
272
|
-
result = await self.safe_client.post_template_draft_file(
|
|
273
|
-
|
|
274
|
-
|
|
291
|
+
result = await self.safe_client.post_template_draft_file(
|
|
292
|
+
remote_id=self.remote_id,
|
|
293
|
+
tfile=tfile,
|
|
294
|
+
)
|
|
295
|
+
self.logger.debug('Storing remote %s %s finished: %s',
|
|
296
|
+
tfile.remote_type.value, tfile.filename.as_posix(), result.remote_id)
|
|
275
297
|
if project_update and result is not None:
|
|
276
298
|
self.safe_project.update_template_file(result)
|
|
277
299
|
except Exception as e:
|
|
278
|
-
self.logger.error(
|
|
300
|
+
self.logger.error('Failed to store remote %s %s: %s',
|
|
301
|
+
tfile.remote_type.value, tfile.filename.as_posix(), e)
|
|
279
302
|
|
|
280
303
|
async def store_remote_files(self):
|
|
281
304
|
for tfile in self.safe_project.safe_template.files.values():
|
|
282
305
|
tfile.remote_id = None
|
|
283
|
-
tfile.remote_type = TemplateFileType.
|
|
306
|
+
tfile.remote_type = TemplateFileType.FILE if tfile.is_text else TemplateFileType.ASSET
|
|
284
307
|
await self._create_template_file(tfile=tfile, project_update=True)
|
|
285
308
|
|
|
286
309
|
def create_package(self, output: pathlib.Path, force: bool):
|
|
287
310
|
if output.exists() and not force:
|
|
288
311
|
raise RuntimeError(f'File {output} already exists (not forced)')
|
|
289
|
-
self.logger.debug(
|
|
312
|
+
self.logger.debug('Opening ZIP file for write: %s', output.as_posix())
|
|
290
313
|
with zipfile.ZipFile(output, mode='w', compression=zipfile.ZIP_DEFLATED) as pkg:
|
|
291
314
|
descriptor = self.safe_project.safe_template.serialize_remote()
|
|
292
315
|
files = []
|
|
293
316
|
assets = []
|
|
294
317
|
for tfile in self.safe_project.safe_template.files.values():
|
|
295
318
|
if tfile.is_text:
|
|
296
|
-
self.logger.info(
|
|
319
|
+
self.logger.info('Adding template file %s', tfile.filename.as_posix())
|
|
297
320
|
files.append({
|
|
298
321
|
'uuid': str(UUIDGen.generate()),
|
|
299
322
|
'content': tfile.content.decode(encoding=DEFAULT_ENCODING),
|
|
300
323
|
'fileName': str(tfile.filename.as_posix()),
|
|
301
324
|
})
|
|
302
325
|
else:
|
|
303
|
-
self.logger.info(
|
|
326
|
+
self.logger.info('Adding template asset %s', tfile.filename.as_posix())
|
|
304
327
|
assets.append({
|
|
305
328
|
'uuid': str(UUIDGen.generate()),
|
|
306
329
|
'contentType': tfile.content_type,
|
|
307
330
|
'fileName': str(tfile.filename.as_posix()),
|
|
308
331
|
})
|
|
309
|
-
self.logger.debug(
|
|
332
|
+
self.logger.debug('Packaging template asset %s', tfile.filename.as_posix())
|
|
310
333
|
pkg.writestr(f'template/assets/{tfile.filename.as_posix()}', tfile.content)
|
|
311
334
|
descriptor['files'] = files
|
|
312
335
|
descriptor['assets'] = assets
|
|
313
|
-
timestamp = datetime.datetime.
|
|
336
|
+
timestamp = datetime.datetime.now(tz=datetime.UTC).strftime('%Y-%m-%dT%H:%M:%S.%fZ')
|
|
314
337
|
descriptor['createdAt'] = timestamp
|
|
315
338
|
descriptor['updatedAt'] = timestamp
|
|
316
339
|
self.logger.debug('Packaging template.json file')
|
|
317
340
|
pkg.writestr('template/template.json', data=json.dumps(descriptor, indent=4))
|
|
318
341
|
self.logger.debug('ZIP packaging done')
|
|
319
342
|
|
|
320
|
-
|
|
343
|
+
# pylint: disable=too-many-locals
|
|
344
|
+
def extract_package(self, zip_data: bytes, template_dir: pathlib.Path | None, force: bool):
|
|
321
345
|
with tempfile.TemporaryDirectory() as tmp_dir:
|
|
322
346
|
io_zip = io.BytesIO(zip_data)
|
|
323
347
|
with zipfile.ZipFile(io_zip) as pkg:
|
|
@@ -373,7 +397,7 @@ class TDKCore:
|
|
|
373
397
|
def create_dot_env(self, output: pathlib.Path, force: bool, api_url: str, api_key: str):
|
|
374
398
|
if output.exists():
|
|
375
399
|
if force:
|
|
376
|
-
self.logger.warning(
|
|
400
|
+
self.logger.warning('Overwriting %s (forced)', output.as_posix())
|
|
377
401
|
else:
|
|
378
402
|
raise RuntimeError(f'File {output} already exists (not forced)')
|
|
379
403
|
output.write_text(
|
|
@@ -393,47 +417,49 @@ class TDKCore:
|
|
|
393
417
|
)
|
|
394
418
|
))
|
|
395
419
|
|
|
396
|
-
async def
|
|
420
|
+
async def update_descriptor(self):
|
|
397
421
|
try:
|
|
398
422
|
template_exists = await self.safe_client.check_draft_exists(
|
|
399
423
|
remote_id=self.remote_id,
|
|
400
424
|
)
|
|
401
425
|
if template_exists:
|
|
402
|
-
self.logger.info(
|
|
403
|
-
|
|
426
|
+
self.logger.info('Updating existing remote document template draft %s',
|
|
427
|
+
self.safe_project.safe_template.id)
|
|
404
428
|
await self.safe_client.update_template_draft(
|
|
405
429
|
template=self.safe_project.safe_template,
|
|
406
430
|
remote_id=self.remote_id,
|
|
407
431
|
)
|
|
408
432
|
else:
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
f'does not exist on remote - full sync')
|
|
433
|
+
self.logger.info('Document template draft %s does not exist on remote - full sync',
|
|
434
|
+
self.safe_project.safe_template.id)
|
|
412
435
|
await self.store_remote(force=False)
|
|
413
436
|
except DSWCommunicationError as e:
|
|
414
|
-
self.logger.error(
|
|
415
|
-
|
|
437
|
+
self.logger.error('Failed to update document template draft %s: %s',
|
|
438
|
+
self.safe_project.safe_template.id, e.message)
|
|
416
439
|
except Exception as e:
|
|
417
|
-
self.logger.error(
|
|
418
|
-
|
|
440
|
+
self.logger.error('Failed to update document template draft %s: %s',
|
|
441
|
+
self.safe_project.safe_template.id, e)
|
|
419
442
|
|
|
420
|
-
async def
|
|
443
|
+
async def delete_file(self, filepath: pathlib.Path):
|
|
421
444
|
if not filepath.is_file():
|
|
422
|
-
self.logger.debug(
|
|
445
|
+
self.logger.debug('%s is not a regular file - skipping',
|
|
446
|
+
filepath.as_posix())
|
|
423
447
|
return
|
|
424
448
|
try:
|
|
425
449
|
tfile = self.safe_project.get_template_file(filepath=filepath)
|
|
426
450
|
if tfile is None:
|
|
427
|
-
|
|
428
|
-
|
|
451
|
+
self.logger.info('File %s not tracked currently - skipping',
|
|
452
|
+
filepath.as_posix())
|
|
429
453
|
return
|
|
430
454
|
await self._delete_template_file(tfile=tfile, project_update=True)
|
|
431
455
|
except Exception as e:
|
|
432
|
-
self.logger.error(
|
|
456
|
+
self.logger.error('Failed to delete file %s: %s',
|
|
457
|
+
filepath.as_posix(), e)
|
|
433
458
|
|
|
434
|
-
async def
|
|
459
|
+
async def update_file(self, filepath: pathlib.Path):
|
|
435
460
|
if not filepath.is_file():
|
|
436
|
-
self.logger.debug(
|
|
461
|
+
self.logger.debug('%s is not a regular file - skipping',
|
|
462
|
+
filepath.as_posix())
|
|
437
463
|
return
|
|
438
464
|
try:
|
|
439
465
|
remote_tfile = self.safe_project.get_template_file(filepath=filepath)
|
|
@@ -443,30 +469,30 @@ class TDKCore:
|
|
|
443
469
|
else:
|
|
444
470
|
await self._create_template_file(tfile=local_tfile, project_update=True)
|
|
445
471
|
except Exception as e:
|
|
446
|
-
self.logger.error(
|
|
472
|
+
self.logger.error('Failed to update file %s: %s', filepath.as_posix(), e)
|
|
447
473
|
|
|
448
|
-
async def process_changes(self, changes:
|
|
474
|
+
async def process_changes(self, changes: list[ChangeItem], force: bool):
|
|
449
475
|
self.changes_processor.clear()
|
|
450
476
|
try:
|
|
451
477
|
await self.changes_processor.process_changes(changes, force)
|
|
452
478
|
except Exception as e:
|
|
453
|
-
self.logger.error(
|
|
479
|
+
self.logger.error('Failed to process changes: %s', e)
|
|
454
480
|
|
|
455
481
|
|
|
456
482
|
class ChangesProcessor:
|
|
457
483
|
|
|
458
484
|
def __init__(self, tdk: TDKCore):
|
|
459
|
-
self.tdk = tdk
|
|
460
|
-
self.descriptor_change
|
|
461
|
-
self.readme_change
|
|
462
|
-
self.file_changes
|
|
485
|
+
self.tdk: TDKCore = tdk
|
|
486
|
+
self.descriptor_change: ChangeItem | None = None
|
|
487
|
+
self.readme_change: ChangeItem | None = None
|
|
488
|
+
self.file_changes: list[ChangeItem] = []
|
|
463
489
|
|
|
464
490
|
def clear(self):
|
|
465
491
|
self.descriptor_change = None
|
|
466
492
|
self.readme_change = None
|
|
467
493
|
self.file_changes = []
|
|
468
494
|
|
|
469
|
-
def _split_changes(self, changes:
|
|
495
|
+
def _split_changes(self, changes: list[ChangeItem]):
|
|
470
496
|
for change in changes:
|
|
471
497
|
if change[1] == self.tdk.safe_project.descriptor_path:
|
|
472
498
|
self.descriptor_change = change
|
|
@@ -479,30 +505,32 @@ class ChangesProcessor:
|
|
|
479
505
|
deleted = set()
|
|
480
506
|
updated = set()
|
|
481
507
|
for file_change in self.file_changes:
|
|
482
|
-
self.tdk.logger.debug(
|
|
508
|
+
self.tdk.logger.debug('Processing: %s',
|
|
509
|
+
_change(file_change, self.tdk.safe_project.template_dir))
|
|
483
510
|
change_type = file_change[0]
|
|
484
511
|
filepath = file_change[1]
|
|
485
512
|
if change_type == watchfiles.Change.deleted and filepath not in deleted:
|
|
486
513
|
self.tdk.logger.debug('Scheduling delete operation')
|
|
487
514
|
deleted.add(filepath)
|
|
488
|
-
await self.tdk.
|
|
515
|
+
await self.tdk.delete_file(filepath)
|
|
489
516
|
elif filepath not in updated:
|
|
490
517
|
self.tdk.logger.debug('Scheduling update operation')
|
|
491
518
|
updated.add(filepath)
|
|
492
|
-
await self.tdk.
|
|
519
|
+
await self.tdk.update_file(filepath)
|
|
493
520
|
|
|
494
521
|
async def _reload_descriptor(self, force: bool) -> bool:
|
|
495
522
|
if self.descriptor_change is None:
|
|
496
523
|
return False
|
|
497
524
|
if self.descriptor_change[0] == watchfiles.Change.deleted:
|
|
498
|
-
raise RuntimeError(f'Deleted
|
|
499
|
-
self.tdk.logger.debug(
|
|
525
|
+
raise RuntimeError(f'Deleted {self.tdk.safe_project.descriptor_path} ... the end')
|
|
526
|
+
self.tdk.logger.debug('Reloading %s file', TemplateProject.TEMPLATE_FILE)
|
|
500
527
|
previous_id = self.tdk.safe_project.safe_template.id
|
|
501
528
|
self.tdk.safe_project.load_descriptor()
|
|
502
529
|
self.tdk.safe_project.load_readme()
|
|
503
530
|
new_id = self.tdk.safe_project.safe_template.id
|
|
504
531
|
if new_id != previous_id:
|
|
505
|
-
self.tdk.logger.warning(
|
|
532
|
+
self.tdk.logger.warning('Template ID changed from %s to %s',
|
|
533
|
+
previous_id, new_id)
|
|
506
534
|
self.tdk.safe_project.load()
|
|
507
535
|
await self.tdk.store_remote(force=force)
|
|
508
536
|
self.tdk.logger.info('Template fully reloaded... waiting for new changes')
|
|
@@ -521,10 +549,10 @@ class ChangesProcessor:
|
|
|
521
549
|
async def _update_descriptor(self):
|
|
522
550
|
if self.readme_change is not None or self.descriptor_change is not None:
|
|
523
551
|
self.tdk.logger.debug('Updating template descriptor (metadata)')
|
|
524
|
-
await self.tdk.
|
|
552
|
+
await self.tdk.update_descriptor()
|
|
525
553
|
self.tdk.safe_project.template = self.tdk.safe_template
|
|
526
554
|
|
|
527
|
-
async def process_changes(self, changes:
|
|
555
|
+
async def process_changes(self, changes: list[ChangeItem], force: bool):
|
|
528
556
|
self._split_changes(changes)
|
|
529
557
|
full_reload = await self._reload_descriptor(force)
|
|
530
558
|
if not full_reload:
|