cli-arcade 2026.1.0__py3-none-any.whl → 2026.1.1__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.
- cli.py +83 -5
- {cli_arcade-2026.1.0.dist-info → cli_arcade-2026.1.1.dist-info}/METADATA +14 -5
- {cli_arcade-2026.1.0.dist-info → cli_arcade-2026.1.1.dist-info}/RECORD +7 -7
- {cli_arcade-2026.1.0.dist-info → cli_arcade-2026.1.1.dist-info}/WHEEL +0 -0
- {cli_arcade-2026.1.0.dist-info → cli_arcade-2026.1.1.dist-info}/entry_points.txt +0 -0
- {cli_arcade-2026.1.0.dist-info → cli_arcade-2026.1.1.dist-info}/licenses/LICENSE +0 -0
- {cli_arcade-2026.1.0.dist-info → cli_arcade-2026.1.1.dist-info}/top_level.txt +0 -0
cli.py
CHANGED
|
@@ -4,6 +4,10 @@ import importlib.util
|
|
|
4
4
|
import argparse
|
|
5
5
|
import glob
|
|
6
6
|
import sys
|
|
7
|
+
import json
|
|
8
|
+
import re
|
|
9
|
+
import subprocess
|
|
10
|
+
import urllib.request
|
|
7
11
|
|
|
8
12
|
# helper: recognize Enter from multiple terminals/keypads
|
|
9
13
|
def is_enter_key(ch):
|
|
@@ -14,11 +18,11 @@ def is_enter_key(ch):
|
|
|
14
18
|
return ch in enter_vals
|
|
15
19
|
|
|
16
20
|
TITLE = [
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
21
|
+
' ________ ____ ___ ____ _________ ____ ______ ',
|
|
22
|
+
r' / ____/ / / _/ / | / __ \/ ____/ | / __ \/ ____/ ',
|
|
23
|
+
r' / / / / / / / /| | / /_/ / / / /| | / / / / __/ ',
|
|
24
|
+
r' / /___/ /____/ / / ___ |/ _, _/ /___/ ___ |/ /_/ / /___ ',
|
|
25
|
+
r' \____/_____/___/ /_/ |_/_/ |_|\____/_/ |_/_____/_____/ '
|
|
22
26
|
]
|
|
23
27
|
|
|
24
28
|
def _discover_games():
|
|
@@ -300,6 +304,43 @@ def _read_version_from_setupcfg():
|
|
|
300
304
|
except Exception:
|
|
301
305
|
return '0.0.0'
|
|
302
306
|
|
|
307
|
+
|
|
308
|
+
def _version_key(ver):
|
|
309
|
+
parts = []
|
|
310
|
+
for chunk in re.split(r'(\d+)', ver):
|
|
311
|
+
if not chunk:
|
|
312
|
+
continue
|
|
313
|
+
if chunk.isdigit():
|
|
314
|
+
parts.append((0, int(chunk)))
|
|
315
|
+
else:
|
|
316
|
+
parts.append((1, chunk.lower()))
|
|
317
|
+
return parts
|
|
318
|
+
|
|
319
|
+
|
|
320
|
+
def _fetch_latest_version(package):
|
|
321
|
+
url = f"https://pypi.org/pypi/{package}/json"
|
|
322
|
+
try:
|
|
323
|
+
with urllib.request.urlopen(url, timeout=5) as resp:
|
|
324
|
+
data = json.load(resp)
|
|
325
|
+
return data.get('info', {}).get('version')
|
|
326
|
+
except Exception as e:
|
|
327
|
+
print(f" [ERROR] Failed to check latest version: {e}")
|
|
328
|
+
return None
|
|
329
|
+
|
|
330
|
+
|
|
331
|
+
def _is_update_available(current, latest):
|
|
332
|
+
if not latest:
|
|
333
|
+
return False
|
|
334
|
+
try:
|
|
335
|
+
return _version_key(latest) > _version_key(current)
|
|
336
|
+
except Exception:
|
|
337
|
+
return latest != current
|
|
338
|
+
|
|
339
|
+
|
|
340
|
+
def _run_pip_update(package):
|
|
341
|
+
cmd = [sys.executable, '-m', 'pip', 'install', '--upgrade', package]
|
|
342
|
+
return subprocess.call(cmd)
|
|
343
|
+
|
|
303
344
|
def main():
|
|
304
345
|
# support simple CLI subcommands (e.g. `clia list`)
|
|
305
346
|
# build epilog with examples and any console script aliases from setup.cfg
|
|
@@ -309,6 +350,7 @@ def main():
|
|
|
309
350
|
f' %(prog)s list [-h]',
|
|
310
351
|
f' %(prog)s run [-h] [0, "Byte Bouncer"]',
|
|
311
352
|
f' %(prog)s reset [-h] [0, "Byte Bouncer"] [-y]',
|
|
353
|
+
f' %(prog)s update [--check] [-y]',
|
|
312
354
|
]
|
|
313
355
|
aliases = _read_console_aliases()
|
|
314
356
|
if aliases:
|
|
@@ -348,6 +390,15 @@ def main():
|
|
|
348
390
|
)
|
|
349
391
|
resetp.add_argument('game', nargs='?', help='Optional game name or zero-based index (omit to reset all)')
|
|
350
392
|
resetp.add_argument('-y', '--yes', action='store_true', help='Do not prompt; proceed with deletion')
|
|
393
|
+
updatep = sub.add_parser(
|
|
394
|
+
'update',
|
|
395
|
+
help='Update cli-arcade package from PyPI',
|
|
396
|
+
description='Check PyPI for a newer version and update if available.',
|
|
397
|
+
epilog='Examples:\n %(prog)s\n %(prog)s --check\n %(prog)s -y\n',
|
|
398
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
399
|
+
)
|
|
400
|
+
updatep.add_argument('-c', '--check', action='store_true', help='Only check for updates (do not install)')
|
|
401
|
+
updatep.add_argument('-y', '--yes', action='store_true', help='Do not prompt; proceed with update')
|
|
351
402
|
args, _rest = parser.parse_known_args()
|
|
352
403
|
|
|
353
404
|
if args.cmd == 'list':
|
|
@@ -421,6 +472,33 @@ def main():
|
|
|
421
472
|
_reset_game_by_index(choice, yes=yes)
|
|
422
473
|
return
|
|
423
474
|
|
|
475
|
+
if args.cmd == 'update':
|
|
476
|
+
package = 'cli-arcade'
|
|
477
|
+
current = _read_version_from_setupcfg()
|
|
478
|
+
if current == '0.0.0':
|
|
479
|
+
print(' [INFO] Installed version not detected (running from source?).')
|
|
480
|
+
latest = _fetch_latest_version(package)
|
|
481
|
+
if not latest:
|
|
482
|
+
print(' [INFO] Unable to determine latest version.')
|
|
483
|
+
return
|
|
484
|
+
if _is_update_available(current, latest):
|
|
485
|
+
print(f" [INFO] Update available: {current} -> {latest}")
|
|
486
|
+
if args.check:
|
|
487
|
+
return
|
|
488
|
+
if not getattr(args, 'yes', False):
|
|
489
|
+
ans = input(' [ACTION] Update now? [y/N]: ')
|
|
490
|
+
if not ans.lower().startswith('y'):
|
|
491
|
+
print(' [CANCELED]')
|
|
492
|
+
return
|
|
493
|
+
code = _run_pip_update(package)
|
|
494
|
+
if code == 0:
|
|
495
|
+
print(f" [OK] Updated {package}.")
|
|
496
|
+
else:
|
|
497
|
+
print(f" [ERROR] Update failed with exit code {code}.")
|
|
498
|
+
return
|
|
499
|
+
print(f" [OK] You are up to date ({current}).")
|
|
500
|
+
return
|
|
501
|
+
|
|
424
502
|
# run the menu under curses, then launch the chosen game's main()
|
|
425
503
|
choice = curses.wrapper(_menu)
|
|
426
504
|
if choice is None:
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cli-arcade
|
|
3
|
-
Version: 2026.1.
|
|
3
|
+
Version: 2026.1.1
|
|
4
4
|
Summary: Collection of terminal CLI games
|
|
5
|
-
Home-page: https://github.com/Bro-Code-Technologies/
|
|
5
|
+
Home-page: https://github.com/Bro-Code-Technologies/cli-arcade/tree/main/windows
|
|
6
6
|
Author: Bro Code Technologies LLC
|
|
7
7
|
Author-email: info@brocodetechnologies.com
|
|
8
8
|
License: MIT
|
|
9
|
-
Project-URL: Source, https://github.com/Bro-Code-Technologies/
|
|
10
|
-
Project-URL: Issues, https://github.com/Bro-Code-Technologies/
|
|
11
|
-
Project-URL: Documentation, https://github.com/Bro-Code-Technologies/
|
|
9
|
+
Project-URL: Source, https://github.com/Bro-Code-Technologies/cli-arcade/tree/main/windows
|
|
10
|
+
Project-URL: Issues, https://github.com/Bro-Code-Technologies/cli-arcade/tree/main/windows
|
|
11
|
+
Project-URL: Documentation, https://github.com/Bro-Code-Technologies/cli-arcade/tree/main/windows
|
|
12
12
|
Project-URL: Package, https://pypi.org/project/cli-arcade/
|
|
13
13
|
Keywords: cli,terminal,arcade,games,curses
|
|
14
14
|
Classifier: Development Status :: 4 - Beta
|
|
@@ -54,6 +54,11 @@ clia run "Byte Bouncer"
|
|
|
54
54
|
clia reset 0
|
|
55
55
|
clia reset "Byte Bouncer"
|
|
56
56
|
clia reset -y # skip confirmation
|
|
57
|
+
|
|
58
|
+
# check for updates and optionally update
|
|
59
|
+
clia update
|
|
60
|
+
clia update --check # only check for updates
|
|
61
|
+
clia update -y # skip confirmation
|
|
57
62
|
```
|
|
58
63
|
|
|
59
64
|
Commands
|
|
@@ -61,7 +66,11 @@ Commands
|
|
|
61
66
|
- `clia list` — print available games and zero-based indices
|
|
62
67
|
- `clia run <index|name>` — run a game directly (index is zero-based)
|
|
63
68
|
- `clia reset [<index|name>] [-y]` — delete highscores for a game or all games
|
|
69
|
+
- `clia update [--check] [-y]` — check for updates and optionally update
|
|
64
70
|
- Aliases available: `cli-arcade`
|
|
65
71
|
|
|
66
72
|
License
|
|
67
73
|
- MIT
|
|
74
|
+
|
|
75
|
+
Changelog
|
|
76
|
+
- See CHANGELOG.md
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
cli.py,sha256=
|
|
2
|
-
cli_arcade-2026.1.
|
|
1
|
+
cli.py,sha256=rSLac21-sWZvb5X_0vMVi4RlxhIIUNgkXLCBQ2Y6mYA,20278
|
|
2
|
+
cli_arcade-2026.1.1.dist-info/licenses/LICENSE,sha256=1PLSNFyGPi9COkVEeNYcUTuRLqGxzMLLTah05tByD4s,1099
|
|
3
3
|
game_classes/__init__.py,sha256=A0o4vBUktOiONToIJb0hACalszBnFS9ls9WXPn3-KH0,28
|
|
4
4
|
game_classes/game_base.py,sha256=q779LzYsK8rO0rWrj2iB5407wuLiZvuFiRBx6qQEfPQ,3505
|
|
5
5
|
game_classes/highscores.py,sha256=dDK-7lFXSMwIqExXGp6_-7QfQz6CIf12lJ22poeCdh4,4061
|
|
@@ -28,8 +28,8 @@ games/terminal_tumble/game.py,sha256=p4lrFHBoHZJLpsUr0jXmR9FI8OTZmwfGIS1Z29MoYzU
|
|
|
28
28
|
games/terminal_tumble/__pycache__/game.cpython-313.pyc,sha256=-xFF1wgupqiSoHz3QZwMNHxhAIV_UyIp0YifRdg8ijA,24104
|
|
29
29
|
games/terminal_tumble/__pycache__/highscores.cpython-313.pyc,sha256=UPnU9Zq88q2TZq1qXyo8e2Y_PdOgwvu5mncIkunFah8,3154
|
|
30
30
|
games/terminal_tumble/__pycache__/terminal_tumble.cpython-313.pyc,sha256=7oLpmmkYjpLYRC0bjRoEkHbIUNq7FZVJToGoja94m0o,38016
|
|
31
|
-
cli_arcade-2026.1.
|
|
32
|
-
cli_arcade-2026.1.
|
|
33
|
-
cli_arcade-2026.1.
|
|
34
|
-
cli_arcade-2026.1.
|
|
35
|
-
cli_arcade-2026.1.
|
|
31
|
+
cli_arcade-2026.1.1.dist-info/METADATA,sha256=H6MJ0uQel9jW5GuXvcSucCQk_P_FhjaRGts_xmSN80I,2525
|
|
32
|
+
cli_arcade-2026.1.1.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
33
|
+
cli_arcade-2026.1.1.dist-info/entry_points.txt,sha256=nNElhZv4nM_lrOYpvnOChtJn1XsWwQr8sI344flzzTQ,56
|
|
34
|
+
cli_arcade-2026.1.1.dist-info/top_level.txt,sha256=gTfYlz7gHYgPY0ugfJivukCOkNzmOisNR6VuJjAXPF4,23
|
|
35
|
+
cli_arcade-2026.1.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|