viur-cli 2.3.7__tar.gz → 2.3.9__tar.gz

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 (29) hide show
  1. {viur_cli-2.3.7 → viur_cli-2.3.9}/LICENSE +1 -1
  2. {viur_cli-2.3.7/src/viur_cli.egg-info → viur_cli-2.3.9}/PKG-INFO +2 -2
  3. {viur_cli-2.3.7 → viur_cli-2.3.9}/README.md +1 -1
  4. {viur_cli-2.3.7 → viur_cli-2.3.9}/src/viur_cli/scriptor/cli.py +89 -21
  5. {viur_cli-2.3.7 → viur_cli-2.3.9}/src/viur_cli/scriptor/login.py +1 -1
  6. {viur_cli-2.3.7 → viur_cli-2.3.9}/src/viur_cli/version.py +1 -1
  7. {viur_cli-2.3.7 → viur_cli-2.3.9/src/viur_cli.egg-info}/PKG-INFO +2 -2
  8. {viur_cli-2.3.7 → viur_cli-2.3.9}/pyproject.toml +0 -0
  9. {viur_cli-2.3.7 → viur_cli-2.3.9}/setup.cfg +0 -0
  10. {viur_cli-2.3.7 → viur_cli-2.3.9}/src/viur_cli/__init__.py +0 -0
  11. {viur_cli-2.3.7 → viur_cli-2.3.9}/src/viur_cli/build.py +0 -0
  12. {viur_cli-2.3.7 → viur_cli-2.3.9}/src/viur_cli/cli.py +0 -0
  13. {viur_cli-2.3.7 → viur_cli-2.3.9}/src/viur_cli/cloud.py +0 -0
  14. {viur_cli-2.3.7 → viur_cli-2.3.9}/src/viur_cli/conf.py +0 -0
  15. {viur_cli-2.3.7 → viur_cli-2.3.9}/src/viur_cli/deprecated.py +0 -0
  16. {viur_cli-2.3.7 → viur_cli-2.3.9}/src/viur_cli/local.py +0 -0
  17. {viur_cli-2.3.7 → viur_cli-2.3.9}/src/viur_cli/package.py +0 -0
  18. {viur_cli-2.3.7 → viur_cli-2.3.9}/src/viur_cli/scriptor/__init__.py +0 -0
  19. {viur_cli-2.3.7 → viur_cli-2.3.9}/src/viur_cli/scripts/__init__.py +0 -0
  20. {viur_cli-2.3.7 → viur_cli-2.3.9}/src/viur_cli/scripts/get_pyodide.py +0 -0
  21. {viur_cli-2.3.7 → viur_cli-2.3.9}/src/viur_cli/setup.py +0 -0
  22. {viur_cli-2.3.7 → viur_cli-2.3.9}/src/viur_cli/tool.py +0 -0
  23. {viur_cli-2.3.7 → viur_cli-2.3.9}/src/viur_cli/update.py +0 -0
  24. {viur_cli-2.3.7 → viur_cli-2.3.9}/src/viur_cli/utils.py +0 -0
  25. {viur_cli-2.3.7 → viur_cli-2.3.9}/src/viur_cli.egg-info/SOURCES.txt +0 -0
  26. {viur_cli-2.3.7 → viur_cli-2.3.9}/src/viur_cli.egg-info/dependency_links.txt +0 -0
  27. {viur_cli-2.3.7 → viur_cli-2.3.9}/src/viur_cli.egg-info/entry_points.txt +0 -0
  28. {viur_cli-2.3.7 → viur_cli-2.3.9}/src/viur_cli.egg-info/requires.txt +0 -0
  29. {viur_cli-2.3.7 → viur_cli-2.3.9}/src/viur_cli.egg-info/top_level.txt +0 -0
@@ -1,4 +1,4 @@
1
- Copyright © 2025 by Mausbrand Informationssysteme GmbH.
1
+ Copyright © 2026 by Mausbrand Informationssysteme GmbH.
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining a copy
4
4
  of this software and associated documentation files (the "Software"), to deal
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: viur-cli
3
- Version: 2.3.7
3
+ Version: 2.3.9
4
4
  Summary: Command-line interface for ViUR application maintenance.
5
5
  Author-email: "Andreas H. Kelch" <ak@mausbrand.de>
6
6
  License-Expression: MIT
@@ -346,7 +346,7 @@ viur-cli depends on
346
346
 
347
347
  ## License
348
348
 
349
- Copyright © 2025 by Mausbrand Informationssysteme GmbH.<br>
349
+ Copyright © 2026 by Mausbrand Informationssysteme GmbH.<br>
350
350
  Mausbrand and ViUR are registered trademarks of Mausbrand Informationssysteme GmbH.
351
351
 
352
352
  This project is free software under the MIT license.<br>
@@ -323,7 +323,7 @@ viur-cli depends on
323
323
 
324
324
  ## License
325
325
 
326
- Copyright © 2025 by Mausbrand Informationssysteme GmbH.<br>
326
+ Copyright © 2026 by Mausbrand Informationssysteme GmbH.<br>
327
327
  Mausbrand and ViUR are registered trademarks of Mausbrand Informationssysteme GmbH.
328
328
 
329
329
  This project is free software under the MIT license.<br>
@@ -4,6 +4,7 @@ import json
4
4
  import requests
5
5
  import os
6
6
  import hashlib
7
+ import difflib
7
8
  import asyncio
8
9
  import sys
9
10
  import glob
@@ -23,7 +24,7 @@ def get_modules():
23
24
  global _modules
24
25
  if _modules is None:
25
26
  _modules = Modules(scriptor_config["base_url"], cookies=scriptor_config["cookies"])
26
- asyncio.new_event_loop().run_until_complete(_modules.init())
27
+ asyncio.run(_modules.init())
27
28
 
28
29
  return _modules
29
30
 
@@ -36,22 +37,39 @@ def script():
36
37
 
37
38
 
38
39
  @script.command()
39
- @click.option('--url', default=None, help='Set the url')
40
+ @click.option('--url', default=None, help='Set the server url')
40
41
  @click.option('--username', default=None, help='Set the username')
41
42
  @click.option('--working_dir', default=None, help='Set the working directory where scripts are stored to')
42
43
  def configure(url: str, username: str, working_dir: str):
43
44
  """
44
45
  Manage configuration settings.
45
46
  """
47
+ if not any([url, username, working_dir]):
48
+ click.echo("No parameters provided. Use one or more of the following options:")
49
+ click.echo(" --url Set the server URL")
50
+ click.echo(" --username Set the username")
51
+ click.echo(" --working_dir Set the working directory where scripts are stored to")
52
+ return
53
+
54
+ changed = []
46
55
 
47
56
  if url:
48
57
  scriptor_config["base_url"] = url
58
+ changed.append(f"url = {url}")
49
59
 
50
60
  if username:
51
61
  scriptor_config["username"] = username
62
+ changed.append(f"username = {username}")
52
63
 
53
64
  if working_dir:
54
65
  scriptor_config["working_dir"] = working_dir.replace("\\", "/")
66
+ changed.append(f"working_dir = {working_dir}")
67
+
68
+ click.echo("Configuration updated:")
69
+ for entry in changed:
70
+ click.echo(f" {entry}")
71
+
72
+ scriptor_config.save()
55
73
 
56
74
 
57
75
  @script.command()
@@ -111,7 +129,8 @@ def check_session(ctx: click.Context):
111
129
  get_modules()
112
130
 
113
131
  @script.command()
114
- @click.option('--force', default=False, help='Force replace files from server in local working directory')
132
+ @click.option('--force', default=False, is_flag=True,
133
+ help='Overwrite local files without asking for confirmation')
115
134
  @click.pass_context
116
135
  def pull(ctx: click.Context, force: bool):
117
136
  """
@@ -125,33 +144,74 @@ def pull(ctx: click.Context, force: bool):
125
144
  tree = await modules.get_module("script")
126
145
  working_dir = scriptor_config.get("working_dir")
127
146
 
147
+ stats = {"new": 0, "updated": 0, "skipped": 0, "unchanged": 0, "dirs": 0}
148
+
128
149
  async def process_entry(entry: dict, is_node: bool):
129
- _path = os.path.join(working_dir, entry["path"])
150
+ _path = os.path.join(working_dir, entry["path"].lstrip("/"))
130
151
 
131
152
  if is_node:
132
153
  if not os.path.exists(_path):
154
+ click.echo(click.style(f" mkdir {entry['path']}", fg="blue"))
133
155
  os.makedirs(_path)
156
+ stats["dirs"] += 1
134
157
  else:
158
+ click.echo(f" check {entry['path']}", nl=False)
159
+
135
160
  def create_file():
136
161
  with open(_path, "a+") as f:
137
- f.write(entry["script"])
138
-
139
- click.echo(f"Pull {_path}")
162
+ f.write(entry["script"] or "")
140
163
 
141
164
  if os.path.exists(_path):
142
165
  if force:
166
+ with open(_path, "r") as f:
167
+ changed = f.read().splitlines() != (entry["script"] or "").splitlines()
143
168
  os.remove(_path)
144
169
  create_file()
170
+ if changed:
171
+ click.echo(click.style(" [updated]", fg="yellow"))
172
+ stats["updated"] += 1
173
+ else:
174
+ click.echo(click.style(" [ok]", fg="green"))
175
+ stats["unchanged"] += 1
145
176
  else:
146
177
  with open(_path, "r") as f:
147
- if hashlib.sha256(entry["script"].encode()).digest() \
148
- != hashlib.sha256(f.read().encode()).digest():
149
- if click.confirm(f"There is a difference with {entry['path']}. Overwrite?"):
150
- os.remove(_path)
151
- create_file()
152
-
178
+ local_content = f.read()
179
+ remote_content = entry["script"] or ""
180
+ diff = list(difflib.unified_diff(
181
+ remote_content.splitlines(),
182
+ local_content.splitlines(),
183
+ fromfile=f"server/{entry['path'].lstrip('/')}",
184
+ tofile=f"local/{entry['path'].lstrip('/')}",
185
+ lineterm="",
186
+ ))
187
+ if diff:
188
+ click.echo(click.style(" [diff]", fg="yellow"))
189
+ for line in diff:
190
+ if line.startswith("+++") or line.startswith("---"):
191
+ click.echo(click.style(line, bold=True))
192
+ elif line.startswith("@@"):
193
+ click.echo(click.style(line, fg="cyan"))
194
+ elif line.startswith("+"):
195
+ click.echo(click.style(line, fg="green"))
196
+ elif line.startswith("-"):
197
+ click.echo(click.style(line, fg="red"))
198
+ else:
199
+ click.echo(line)
200
+ if click.confirm(f"Overwrite local {entry['path']} with remote version?"):
201
+ os.remove(_path)
202
+ create_file()
203
+ stats["updated"] += 1
204
+ else:
205
+ stats["skipped"] += 1
206
+ else:
207
+ click.echo(click.style(" [ok]", fg="green"))
208
+ stats["unchanged"] += 1
153
209
  else:
210
+ click.echo(click.style(" [new]", fg="green"))
154
211
  create_file()
212
+ stats["new"] += 1
213
+
214
+ click.echo("Fetching scripts from server...")
155
215
 
156
216
  # Process nodes first
157
217
  async for node in tree.list(skel_type="node"):
@@ -161,7 +221,14 @@ def pull(ctx: click.Context, force: bool):
161
221
  async for leaf in tree.list(skel_type="leaf"):
162
222
  await process_entry(leaf, False)
163
223
 
164
- asyncio.new_event_loop().run_until_complete(main())
224
+ click.echo("")
225
+ click.echo(click.style("Summary:", bold=True))
226
+ click.echo(f" new: {stats['new']}")
227
+ click.echo(f" updated: {stats['updated']}")
228
+ click.echo(f" skipped: {stats['skipped']}")
229
+ click.echo(f" unchanged: {stats['unchanged']}")
230
+
231
+ asyncio.run(main())
165
232
 
166
233
 
167
234
  @script.command()
@@ -220,7 +287,7 @@ def push(ctx: click.Context, force: bool, watch: bool):
220
287
  with open(_real_file, "r") as f:
221
288
  file_content = f.read()
222
289
 
223
- if hashlib.sha256(entry["script"].encode("utf-8")).digest() \
290
+ if hashlib.sha256((entry["script"] or "").encode("utf-8")).digest() \
224
291
  != hashlib.sha256(file_content.encode("utf-8")).digest():
225
292
  can_push = force
226
293
  if not can_push:
@@ -305,21 +372,22 @@ def push(ctx: click.Context, force: bool, watch: bool):
305
372
 
306
373
  def on_modified(event):
307
374
  try:
308
- # check for tmp file
309
375
  if event.src_path.endswith("~"):
310
376
  return
377
+ if not os.path.exists(event.src_path):
378
+ return
311
379
  if event.src_path not in modified_files:
312
380
  modified_files[event.src_path] = os.path.getmtime(event.src_path)
313
381
  elif os.path.getmtime(event.src_path) == modified_files[event.src_path]:
314
382
  return
315
383
  modified_files[event.src_path] = os.path.getmtime(event.src_path)
316
- asyncio.new_event_loop().run_until_complete(main(event.src_path))
384
+ asyncio.run(main(event.src_path))
317
385
  except Exception as e:
318
386
  import traceback
319
387
  print(f"Error: on file {event.src_path} {e}")
320
388
  traceback.print_exc()
321
389
 
322
- regexes = [r".*\.py"]
390
+ regexes = [r".*\.py$"]
323
391
  ignore_regexes = []
324
392
  ignore_directories = True
325
393
  case_sensitive = False
@@ -341,9 +409,9 @@ def push(ctx: click.Context, force: bool, watch: bool):
341
409
  observer.stop()
342
410
  observer.join()
343
411
 
344
- asyncio.new_event_loop().run_until_complete(watch_loop())
412
+ watch_loop()
345
413
  return
346
- asyncio.new_event_loop().run_until_complete(main())
414
+ asyncio.run(main())
347
415
 
348
416
 
349
417
  @script.command()
@@ -376,4 +444,4 @@ def run(ctx: click.Context, path: str, args=None):
376
444
 
377
445
  await module.main()
378
446
 
379
- asyncio.new_event_loop().run_until_complete(main())
447
+ asyncio.run(main())
@@ -49,7 +49,7 @@ def ensure_login(
49
49
 
50
50
  cookie_str: str = callback_app.cookie.get()
51
51
  key, value = cookie_str.split(";", 1)[0].split("=")
52
- scriptor_config.get("cookies",{})[key] = value
52
+ scriptor_config.setdefault("cookies", {})[key] = value
53
53
  scriptor_config.save()
54
54
 
55
55
  return True
@@ -1,2 +1,2 @@
1
- __version__ = "2.3.7"
1
+ __version__ = "2.3.9"
2
2
  MINIMAL_PIPENV = "2023.11.15"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: viur-cli
3
- Version: 2.3.7
3
+ Version: 2.3.9
4
4
  Summary: Command-line interface for ViUR application maintenance.
5
5
  Author-email: "Andreas H. Kelch" <ak@mausbrand.de>
6
6
  License-Expression: MIT
@@ -346,7 +346,7 @@ viur-cli depends on
346
346
 
347
347
  ## License
348
348
 
349
- Copyright © 2025 by Mausbrand Informationssysteme GmbH.<br>
349
+ Copyright © 2026 by Mausbrand Informationssysteme GmbH.<br>
350
350
  Mausbrand and ViUR are registered trademarks of Mausbrand Informationssysteme GmbH.
351
351
 
352
352
  This project is free software under the MIT license.<br>
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes