viur-cli 3.0.0b3__tar.gz → 3.0.2__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.
- {viur_cli-3.0.0b3 → viur_cli-3.0.2}/LICENSE +1 -1
- {viur_cli-3.0.0b3/src/viur_cli.egg-info → viur_cli-3.0.2}/PKG-INFO +2 -2
- {viur_cli-3.0.0b3 → viur_cli-3.0.2}/README.md +1 -1
- {viur_cli-3.0.0b3 → viur_cli-3.0.2}/src/viur_cli/conf.py +1 -0
- {viur_cli-3.0.0b3 → viur_cli-3.0.2}/src/viur_cli/local.py +59 -15
- {viur_cli-3.0.0b3 → viur_cli-3.0.2}/src/viur_cli/scriptor/cli.py +10 -10
- {viur_cli-3.0.0b3 → viur_cli-3.0.2}/src/viur_cli/scriptor/login.py +0 -4
- viur_cli-3.0.2/src/viur_cli/version.py +2 -0
- {viur_cli-3.0.0b3 → viur_cli-3.0.2/src/viur_cli.egg-info}/PKG-INFO +2 -2
- viur_cli-3.0.0b3/src/viur_cli/version.py +0 -2
- {viur_cli-3.0.0b3 → viur_cli-3.0.2}/pyproject.toml +0 -0
- {viur_cli-3.0.0b3 → viur_cli-3.0.2}/setup.cfg +0 -0
- {viur_cli-3.0.0b3 → viur_cli-3.0.2}/src/viur_cli/__init__.py +0 -0
- {viur_cli-3.0.0b3 → viur_cli-3.0.2}/src/viur_cli/_docs_cli.py +0 -0
- {viur_cli-3.0.0b3 → viur_cli-3.0.2}/src/viur_cli/build.py +0 -0
- {viur_cli-3.0.0b3 → viur_cli-3.0.2}/src/viur_cli/cli.py +0 -0
- {viur_cli-3.0.0b3 → viur_cli-3.0.2}/src/viur_cli/cloud.py +0 -0
- {viur_cli-3.0.0b3 → viur_cli-3.0.2}/src/viur_cli/deprecated.py +0 -0
- {viur_cli-3.0.0b3 → viur_cli-3.0.2}/src/viur_cli/package.py +0 -0
- {viur_cli-3.0.0b3 → viur_cli-3.0.2}/src/viur_cli/scriptor/__init__.py +0 -0
- {viur_cli-3.0.0b3 → viur_cli-3.0.2}/src/viur_cli/scripts/__init__.py +0 -0
- {viur_cli-3.0.0b3 → viur_cli-3.0.2}/src/viur_cli/scripts/get_pyodide.py +0 -0
- {viur_cli-3.0.0b3 → viur_cli-3.0.2}/src/viur_cli/setup.py +0 -0
- {viur_cli-3.0.0b3 → viur_cli-3.0.2}/src/viur_cli/update.py +0 -0
- {viur_cli-3.0.0b3 → viur_cli-3.0.2}/src/viur_cli/utils.py +0 -0
- {viur_cli-3.0.0b3 → viur_cli-3.0.2}/src/viur_cli.egg-info/SOURCES.txt +0 -0
- {viur_cli-3.0.0b3 → viur_cli-3.0.2}/src/viur_cli.egg-info/dependency_links.txt +0 -0
- {viur_cli-3.0.0b3 → viur_cli-3.0.2}/src/viur_cli.egg-info/entry_points.txt +0 -0
- {viur_cli-3.0.0b3 → viur_cli-3.0.2}/src/viur_cli.egg-info/requires.txt +0 -0
- {viur_cli-3.0.0b3 → viur_cli-3.0.2}/src/viur_cli.egg-info/top_level.txt +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
Copyright ©
|
|
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: 3.0.
|
|
3
|
+
Version: 3.0.2
|
|
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 ©
|
|
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 ©
|
|
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>
|
|
@@ -1,4 +1,9 @@
|
|
|
1
|
+
import contextlib
|
|
2
|
+
import itertools
|
|
1
3
|
import json
|
|
4
|
+
import sys
|
|
5
|
+
import threading
|
|
6
|
+
import time
|
|
2
7
|
|
|
3
8
|
import click
|
|
4
9
|
import requests
|
|
@@ -186,6 +191,41 @@ def check(dev):
|
|
|
186
191
|
utils.echo_info("\U00002714 No vulnerabilities found.")
|
|
187
192
|
|
|
188
193
|
|
|
194
|
+
@contextlib.contextmanager
|
|
195
|
+
def _spinner(message):
|
|
196
|
+
"""Show an animated spinner next to ``message`` until the block exits.
|
|
197
|
+
|
|
198
|
+
No-op (prints the message once) when stdout is not a TTY so CI logs
|
|
199
|
+
stay clean.
|
|
200
|
+
"""
|
|
201
|
+
styled = click.style(message, fg="cyan")
|
|
202
|
+
if not sys.stdout.isatty():
|
|
203
|
+
click.echo(styled)
|
|
204
|
+
yield
|
|
205
|
+
return
|
|
206
|
+
|
|
207
|
+
done = threading.Event()
|
|
208
|
+
|
|
209
|
+
def spin():
|
|
210
|
+
for ch in itertools.cycle("⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏"):
|
|
211
|
+
if done.is_set():
|
|
212
|
+
break
|
|
213
|
+
sys.stdout.write(f"\r{styled} {click.style(ch, fg='cyan')}")
|
|
214
|
+
sys.stdout.flush()
|
|
215
|
+
time.sleep(0.1)
|
|
216
|
+
|
|
217
|
+
t = threading.Thread(target=spin, daemon=True)
|
|
218
|
+
t.start()
|
|
219
|
+
try:
|
|
220
|
+
yield
|
|
221
|
+
finally:
|
|
222
|
+
done.set()
|
|
223
|
+
t.join()
|
|
224
|
+
# Leave the message in place; swap the spinner glyph for a check mark.
|
|
225
|
+
sys.stdout.write(f"\r{styled} {click.style('✓', fg='cyan')}\n")
|
|
226
|
+
sys.stdout.flush()
|
|
227
|
+
|
|
228
|
+
|
|
189
229
|
def do_checks(dev=True):
|
|
190
230
|
"""Run Python (pip-audit) and npm (npm audit) vulnerability scans.
|
|
191
231
|
|
|
@@ -204,11 +244,12 @@ def do_checks(dev=True):
|
|
|
204
244
|
|
|
205
245
|
# --- Python vulnerability check via pip-audit (PyPA tool, OSV data) ---
|
|
206
246
|
try:
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
247
|
+
with _spinner("Scanning Python dependencies (pip-audit)"):
|
|
248
|
+
result = subprocess.run(
|
|
249
|
+
["uvx", "pip-audit", "--format", "json", "--vulnerability-service", "osv"],
|
|
250
|
+
capture_output=True,
|
|
251
|
+
text=True,
|
|
252
|
+
)
|
|
212
253
|
except FileNotFoundError:
|
|
213
254
|
echo_warning("uvx not found; skipping Python vulnerability check.")
|
|
214
255
|
else:
|
|
@@ -229,7 +270,7 @@ def do_checks(dev=True):
|
|
|
229
270
|
vuln_deps = [d for d in deps if d.get("vulns")]
|
|
230
271
|
total_vulns = sum(len(d["vulns"]) for d in vuln_deps)
|
|
231
272
|
|
|
232
|
-
click.echo("\n" + "=" * 60)
|
|
273
|
+
click.echo("\n\n" + "=" * 60)
|
|
233
274
|
click.echo("Python Security Scan Results (pip-audit, OSV)")
|
|
234
275
|
click.echo("=" * 60)
|
|
235
276
|
click.echo(f"Total Packages: {len(deps)}")
|
|
@@ -240,6 +281,7 @@ def do_checks(dev=True):
|
|
|
240
281
|
if vuln_deps:
|
|
241
282
|
has_vulnerabilities = True
|
|
242
283
|
click.echo("Run `uvx pip-audit --vulnerability-service osv` for per-package detail.")
|
|
284
|
+
click.echo()
|
|
243
285
|
|
|
244
286
|
# --- npm vulnerability check ---
|
|
245
287
|
if shutil.which("npm"):
|
|
@@ -258,7 +300,7 @@ def do_checks(dev=True):
|
|
|
258
300
|
npm_builds.append({"name": build_name, "path": audit_path})
|
|
259
301
|
|
|
260
302
|
if not npm_builds:
|
|
261
|
-
click.echo("\n" + "=" * 60)
|
|
303
|
+
click.echo("\n\n" + "=" * 60)
|
|
262
304
|
click.echo("No npm builds found in config - skipping npm audit")
|
|
263
305
|
click.echo("=" * 60)
|
|
264
306
|
else:
|
|
@@ -267,12 +309,13 @@ def do_checks(dev=True):
|
|
|
267
309
|
try:
|
|
268
310
|
npm_audit_dir = build["path"]
|
|
269
311
|
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
312
|
+
with _spinner(f"Scanning npm dependencies ({build['name']})"):
|
|
313
|
+
npm_result = subprocess.run(
|
|
314
|
+
["npm", "audit", "--json"],
|
|
315
|
+
capture_output=True,
|
|
316
|
+
text=True,
|
|
317
|
+
cwd=npm_audit_dir,
|
|
318
|
+
)
|
|
276
319
|
|
|
277
320
|
npm_data = json.loads(npm_result.stdout, strict=False)
|
|
278
321
|
|
|
@@ -288,7 +331,7 @@ def do_checks(dev=True):
|
|
|
288
331
|
has_vulnerabilities = True
|
|
289
332
|
|
|
290
333
|
# Display npm scan summary
|
|
291
|
-
click.echo("\n" + "=" * 60)
|
|
334
|
+
click.echo("\n\n" + "=" * 60)
|
|
292
335
|
click.echo(f"npm Security Scan Results - {build['name']}")
|
|
293
336
|
click.echo("=" * 60)
|
|
294
337
|
click.echo(f"Build Path: {npm_audit_dir}")
|
|
@@ -309,6 +352,7 @@ def do_checks(dev=True):
|
|
|
309
352
|
|
|
310
353
|
if total_npm_vulns > 0:
|
|
311
354
|
click.echo(f"Run `npm audit` in {build['path']} for per-package detail.")
|
|
355
|
+
click.echo()
|
|
312
356
|
|
|
313
357
|
except FileNotFoundError:
|
|
314
358
|
echo_warning(f"npm audit directory not found: {build['path']}")
|
|
@@ -321,7 +365,7 @@ def do_checks(dev=True):
|
|
|
321
365
|
f"Unexpected error during npm security check for {build['name']}: {e}"
|
|
322
366
|
)
|
|
323
367
|
else:
|
|
324
|
-
click.echo("\n" + "=" * 60)
|
|
368
|
+
click.echo("\n\n" + "=" * 60)
|
|
325
369
|
click.echo("npm not found - skipping npm audit")
|
|
326
370
|
click.echo("=" * 60)
|
|
327
371
|
|
|
@@ -111,8 +111,7 @@ def setup():
|
|
|
111
111
|
scriptor_config.save()
|
|
112
112
|
click.echo("Setup done")
|
|
113
113
|
else:
|
|
114
|
-
|
|
115
|
-
del scriptor_config["cookies"]
|
|
114
|
+
scriptor_config["cookies"] = {}
|
|
116
115
|
click.echo("Failed to login. Did you maybe entered the wrong password?")
|
|
117
116
|
except KeyboardInterrupt:
|
|
118
117
|
pass
|
|
@@ -122,9 +121,9 @@ def check_session(ctx: click.Context):
|
|
|
122
121
|
base_url = scriptor_config.get("base_url")
|
|
123
122
|
|
|
124
123
|
s = requests.Session()
|
|
125
|
-
s.cookies = cookiejar_from_dict(scriptor_config
|
|
124
|
+
s.cookies = cookiejar_from_dict(scriptor_config["cookies"])
|
|
126
125
|
|
|
127
|
-
response = s.get(base_url + "/vi/user/view/self", cookies=scriptor_config
|
|
126
|
+
response = s.get(base_url + "/vi/user/view/self", cookies=scriptor_config["cookies"])
|
|
128
127
|
if not response.ok:
|
|
129
128
|
click.echo("Invalid session, please run `viur script setup` again. okay ?")
|
|
130
129
|
ctx.invoke(setup)
|
|
@@ -165,12 +164,12 @@ def pull(ctx: click.Context, force: bool):
|
|
|
165
164
|
|
|
166
165
|
def create_file():
|
|
167
166
|
with open(_path, "a+") as f:
|
|
168
|
-
f.write(entry["script"])
|
|
167
|
+
f.write(entry["script"] or "")
|
|
169
168
|
|
|
170
169
|
if os.path.exists(_path):
|
|
171
170
|
if force:
|
|
172
171
|
with open(_path, "r") as f:
|
|
173
|
-
changed = f.read().splitlines() != entry["script"].splitlines()
|
|
172
|
+
changed = f.read().splitlines() != (entry["script"] or "").splitlines()
|
|
174
173
|
os.remove(_path)
|
|
175
174
|
create_file()
|
|
176
175
|
if changed:
|
|
@@ -182,7 +181,7 @@ def pull(ctx: click.Context, force: bool):
|
|
|
182
181
|
else:
|
|
183
182
|
with open(_path, "r") as f:
|
|
184
183
|
local_content = f.read()
|
|
185
|
-
remote_content = entry["script"]
|
|
184
|
+
remote_content = entry["script"] or ""
|
|
186
185
|
diff = list(difflib.unified_diff(
|
|
187
186
|
remote_content.splitlines(),
|
|
188
187
|
local_content.splitlines(),
|
|
@@ -296,7 +295,7 @@ def push(ctx: click.Context, force: bool, watch: bool):
|
|
|
296
295
|
with open(_real_file, "r") as f:
|
|
297
296
|
file_content = f.read()
|
|
298
297
|
|
|
299
|
-
if hashlib.sha256(entry["script"].encode("utf-8")).digest() \
|
|
298
|
+
if hashlib.sha256((entry["script"] or "").encode("utf-8")).digest() \
|
|
300
299
|
!= hashlib.sha256(file_content.encode("utf-8")).digest():
|
|
301
300
|
can_push = force
|
|
302
301
|
if not can_push:
|
|
@@ -381,9 +380,10 @@ def push(ctx: click.Context, force: bool, watch: bool):
|
|
|
381
380
|
|
|
382
381
|
def on_modified(event):
|
|
383
382
|
try:
|
|
384
|
-
# check for tmp file
|
|
385
383
|
if event.src_path.endswith("~"):
|
|
386
384
|
return
|
|
385
|
+
if not os.path.exists(event.src_path):
|
|
386
|
+
return
|
|
387
387
|
if event.src_path not in modified_files:
|
|
388
388
|
modified_files[event.src_path] = os.path.getmtime(event.src_path)
|
|
389
389
|
elif os.path.getmtime(event.src_path) == modified_files[event.src_path]:
|
|
@@ -395,7 +395,7 @@ def push(ctx: click.Context, force: bool, watch: bool):
|
|
|
395
395
|
print(f"Error: on file {event.src_path} {e}")
|
|
396
396
|
traceback.print_exc()
|
|
397
397
|
|
|
398
|
-
regexes = [r".*\.py"]
|
|
398
|
+
regexes = [r".*\.py$"]
|
|
399
399
|
ignore_regexes = []
|
|
400
400
|
ignore_directories = True
|
|
401
401
|
case_sensitive = False
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: viur-cli
|
|
3
|
-
Version: 3.0.
|
|
3
|
+
Version: 3.0.2
|
|
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 ©
|
|
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
|
|
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
|