cleepcli 1.45.1__tar.gz → 1.48.0__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.
- {cleepcli-1.45.1 → cleepcli-1.48.0}/MANIFEST.in +1 -0
- {cleepcli-1.45.1/cleepcli.egg-info → cleepcli-1.48.0}/PKG-INFO +22 -6
- {cleepcli-1.45.1 → cleepcli-1.48.0}/README.md +21 -5
- {cleepcli-1.45.1 → cleepcli-1.48.0}/bin/ccli +65 -8
- {cleepcli-1.45.1 → cleepcli-1.48.0}/bin/cleep-cli +65 -8
- {cleepcli-1.45.1 → cleepcli-1.48.0}/cleepcli/check.py +44 -0
- {cleepcli-1.45.1 → cleepcli-1.48.0}/cleepcli/file.py +45 -0
- {cleepcli-1.45.1 → cleepcli-1.48.0}/cleepcli/module.py +2 -0
- {cleepcli-1.45.1 → cleepcli-1.48.0}/cleepcli/package.py +10 -0
- cleepcli-1.48.0/cleepcli/systemd/cleep-watch.service +18 -0
- {cleepcli-1.45.1 → cleepcli-1.48.0}/cleepcli/test.py +50 -15
- {cleepcli-1.45.1 → cleepcli-1.48.0}/cleepcli/version.py +1 -1
- {cleepcli-1.45.1 → cleepcli-1.48.0}/cleepcli/watch.py +24 -2
- cleepcli-1.48.0/cleepcli/watchsvc.py +214 -0
- {cleepcli-1.45.1 → cleepcli-1.48.0/cleepcli.egg-info}/PKG-INFO +22 -6
- {cleepcli-1.45.1 → cleepcli-1.48.0}/cleepcli.egg-info/SOURCES.txt +5 -1
- {cleepcli-1.45.1 → cleepcli-1.48.0}/setup.py +1 -0
- cleepcli-1.48.0/tests/test_file_sync_all.py +91 -0
- {cleepcli-1.45.1 → cleepcli-1.48.0}/tests/test_watch.py +7 -0
- cleepcli-1.48.0/tests/test_watchsvc.py +57 -0
- {cleepcli-1.45.1 → cleepcli-1.48.0}/LICENSE +0 -0
- {cleepcli-1.45.1 → cleepcli-1.48.0}/cleepcli/__init__.py +0 -0
- {cleepcli-1.45.1 → cleepcli-1.48.0}/cleepcli/ci.py +0 -0
- {cleepcli-1.45.1 → cleepcli-1.48.0}/cleepcli/cleepapi.py +0 -0
- {cleepcli-1.45.1 → cleepcli-1.48.0}/cleepcli/config.py +0 -0
- {cleepcli-1.45.1 → cleepcli-1.48.0}/cleepcli/console.py +0 -0
- {cleepcli-1.45.1 → cleepcli-1.48.0}/cleepcli/docs.py +0 -0
- {cleepcli-1.45.1 → cleepcli-1.48.0}/cleepcli/git.py +0 -0
- {cleepcli-1.45.1 → cleepcli-1.48.0}/cleepcli/tools.py +0 -0
- {cleepcli-1.45.1 → cleepcli-1.48.0}/cleepcli.egg-info/dependency_links.txt +0 -0
- {cleepcli-1.45.1 → cleepcli-1.48.0}/cleepcli.egg-info/requires.txt +0 -0
- {cleepcli-1.45.1 → cleepcli-1.48.0}/cleepcli.egg-info/top_level.txt +0 -0
- {cleepcli-1.45.1 → cleepcli-1.48.0}/pyproject.toml +0 -0
- {cleepcli-1.45.1 → cleepcli-1.48.0}/requirements.txt +0 -0
- {cleepcli-1.45.1 → cleepcli-1.48.0}/setup.cfg +0 -0
- {cleepcli-1.45.1 → cleepcli-1.48.0}/tests/test_check.py +0 -0
- {cleepcli-1.45.1 → cleepcli-1.48.0}/tests/test_config.py +0 -0
- {cleepcli-1.45.1 → cleepcli-1.48.0}/tests/test_console.py +0 -0
- {cleepcli-1.45.1 → cleepcli-1.48.0}/tests/test_coverage.py +0 -0
- {cleepcli-1.45.1 → cleepcli-1.48.0}/tests/test_docs_breaking.py +0 -0
- {cleepcli-1.45.1 → cleepcli-1.48.0}/tests/test_module_scaffold.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cleepcli
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.48.0
|
|
4
4
|
Summary: Cleep-cli helps developers to build great Cleep applications from command line.
|
|
5
5
|
Home-page: https://github.com/CleepDevice/cleep-cli
|
|
6
6
|
Author: Tanguy Bonneau
|
|
@@ -42,7 +42,7 @@ This utility helps developers to build Cleep applications providing some useful
|
|
|
42
42
|
- `coreget` to clone or pull official Cleep repository.
|
|
43
43
|
- `coredocs` to generate core documentation in HTML format.
|
|
44
44
|
- `coresync` to synchronize sources from repository to execution folders.
|
|
45
|
-
- `coretests` to perform core tests suite.
|
|
45
|
+
- `coretests` to perform core unit tests suite (`--functional` for real OS binary tests on device / OS migration).
|
|
46
46
|
- `coretestscov` to display last core tests code coverage report.
|
|
47
47
|
- `cpuprof` to run CPU profiler on application execution instance.
|
|
48
48
|
- `memprof` to run memory profiler on application execution instance.
|
|
@@ -52,7 +52,7 @@ This utility helps developers to build Cleep applications providing some useful
|
|
|
52
52
|
- `moddelete` to delete installed files of a module.
|
|
53
53
|
- `moddocs` to generate module documentation.
|
|
54
54
|
- `modsync` to synchronize sources from module folder to execution folders.
|
|
55
|
-
- `modtests` to execute module tests.
|
|
55
|
+
- `modtests` to execute module unit tests (`--functional` for real OS/device tests).
|
|
56
56
|
- `modtestscov` to display last module tests code coverage report.
|
|
57
57
|
- `modbuild` to create application package (.zip)
|
|
58
58
|
- `modcheckback` to check app backend (python files structure and content)
|
|
@@ -61,7 +61,9 @@ This utility helps developers to build Cleep applications providing some useful
|
|
|
61
61
|
- `modcheckscripts` to check app scripts files
|
|
62
62
|
- `modcheckcode` to check backend code quality (run pylint)
|
|
63
63
|
- Watch commands:
|
|
64
|
-
- `watch` to watch for repository filesystem changes and automatically update files on execution folders. It also restart backend or/and frontend according to changes.
|
|
64
|
+
- `watch` to watch for repository filesystem changes and automatically update files on execution folders. It also restart backend or/and frontend according to changes (catch-up sync on start).
|
|
65
|
+
- `watchsvc` to install/enable/disable/restart the durable `cleep-watch` systemd unit (runs `watch` outside `cleep.service`).
|
|
66
|
+
- `syncall` to force a one-shot sync of core + all modules (same catch-up as watch start).
|
|
65
67
|
- Misc commands:
|
|
66
68
|
- `version` to get cleep-cli version
|
|
67
69
|
|
|
@@ -85,9 +87,23 @@ Execute this command to get help on this cli:
|
|
|
85
87
|
|
|
86
88
|
## Watch usage
|
|
87
89
|
|
|
88
|
-
|
|
90
|
+
Preferred: let the CLI own the durable systemd unit:
|
|
89
91
|
|
|
90
|
-
|
|
92
|
+
```
|
|
93
|
+
cleep-cli watchsvc install
|
|
94
|
+
cleep-cli watchsvc enable
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
The unit runs `cleep-cli watch`, survives `systemctl restart cleep`, and on each start performs a catch-up `syncall` so files written while the watcher was down are applied.
|
|
98
|
+
|
|
99
|
+
Manual one-shot resync (when the UI looks stale):
|
|
100
|
+
|
|
101
|
+
```
|
|
102
|
+
cleep-cli syncall
|
|
103
|
+
cleep-cli watchsvc restart # catch-up again + resume watch
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
You can still run `cleep-cli watch` in a terminal for debugging. Push sources to `/root/cleep-dev` (CleepDesktop developer sync or SFTP); the watcher copies them into the execution folders and restarts backend/frontend as needed.
|
|
91
107
|
|
|
92
108
|
### Paths
|
|
93
109
|
|
|
@@ -6,7 +6,7 @@ This utility helps developers to build Cleep applications providing some useful
|
|
|
6
6
|
- `coreget` to clone or pull official Cleep repository.
|
|
7
7
|
- `coredocs` to generate core documentation in HTML format.
|
|
8
8
|
- `coresync` to synchronize sources from repository to execution folders.
|
|
9
|
-
- `coretests` to perform core tests suite.
|
|
9
|
+
- `coretests` to perform core unit tests suite (`--functional` for real OS binary tests on device / OS migration).
|
|
10
10
|
- `coretestscov` to display last core tests code coverage report.
|
|
11
11
|
- `cpuprof` to run CPU profiler on application execution instance.
|
|
12
12
|
- `memprof` to run memory profiler on application execution instance.
|
|
@@ -16,7 +16,7 @@ This utility helps developers to build Cleep applications providing some useful
|
|
|
16
16
|
- `moddelete` to delete installed files of a module.
|
|
17
17
|
- `moddocs` to generate module documentation.
|
|
18
18
|
- `modsync` to synchronize sources from module folder to execution folders.
|
|
19
|
-
- `modtests` to execute module tests.
|
|
19
|
+
- `modtests` to execute module unit tests (`--functional` for real OS/device tests).
|
|
20
20
|
- `modtestscov` to display last module tests code coverage report.
|
|
21
21
|
- `modbuild` to create application package (.zip)
|
|
22
22
|
- `modcheckback` to check app backend (python files structure and content)
|
|
@@ -25,7 +25,9 @@ This utility helps developers to build Cleep applications providing some useful
|
|
|
25
25
|
- `modcheckscripts` to check app scripts files
|
|
26
26
|
- `modcheckcode` to check backend code quality (run pylint)
|
|
27
27
|
- Watch commands:
|
|
28
|
-
- `watch` to watch for repository filesystem changes and automatically update files on execution folders. It also restart backend or/and frontend according to changes.
|
|
28
|
+
- `watch` to watch for repository filesystem changes and automatically update files on execution folders. It also restart backend or/and frontend according to changes (catch-up sync on start).
|
|
29
|
+
- `watchsvc` to install/enable/disable/restart the durable `cleep-watch` systemd unit (runs `watch` outside `cleep.service`).
|
|
30
|
+
- `syncall` to force a one-shot sync of core + all modules (same catch-up as watch start).
|
|
29
31
|
- Misc commands:
|
|
30
32
|
- `version` to get cleep-cli version
|
|
31
33
|
|
|
@@ -49,9 +51,23 @@ Execute this command to get help on this cli:
|
|
|
49
51
|
|
|
50
52
|
## Watch usage
|
|
51
53
|
|
|
52
|
-
|
|
54
|
+
Preferred: let the CLI own the durable systemd unit:
|
|
53
55
|
|
|
54
|
-
|
|
56
|
+
```
|
|
57
|
+
cleep-cli watchsvc install
|
|
58
|
+
cleep-cli watchsvc enable
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
The unit runs `cleep-cli watch`, survives `systemctl restart cleep`, and on each start performs a catch-up `syncall` so files written while the watcher was down are applied.
|
|
62
|
+
|
|
63
|
+
Manual one-shot resync (when the UI looks stale):
|
|
64
|
+
|
|
65
|
+
```
|
|
66
|
+
cleep-cli syncall
|
|
67
|
+
cleep-cli watchsvc restart # catch-up again + resume watch
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
You can still run `cleep-cli watch` in a terminal for debugging. Push sources to `/root/cleep-dev` (CleepDesktop developer sync or SFTP); the watcher copies them into the execution folders and restarts backend/frontend as needed.
|
|
55
71
|
|
|
56
72
|
### Paths
|
|
57
73
|
|
|
@@ -17,6 +17,7 @@ from cleepcli.git import Git
|
|
|
17
17
|
from cleepcli.module import Module
|
|
18
18
|
from cleepcli.file import File
|
|
19
19
|
from cleepcli.watch import CleepWatchdog
|
|
20
|
+
from cleepcli.watchsvc import WatchService
|
|
20
21
|
from cleepcli.test import Test, is_file_coverage_valid
|
|
21
22
|
from cleepcli.package import Package
|
|
22
23
|
from cleepcli.docs import Docs
|
|
@@ -108,18 +109,31 @@ def coresync():
|
|
|
108
109
|
sys.exit(1)
|
|
109
110
|
logging.info('Done')
|
|
110
111
|
|
|
112
|
+
@core.command()
|
|
113
|
+
def syncall():
|
|
114
|
+
"""
|
|
115
|
+
Synchronize core and all modules from /root/cleep-dev to execution folders.
|
|
116
|
+
|
|
117
|
+
Same catch-up used when cleep-watch.service starts. Safe one-shot resync when
|
|
118
|
+
the UI looks stale: run this, then reload the device page.
|
|
119
|
+
"""
|
|
120
|
+
f = File()
|
|
121
|
+
if not f.sync_all():
|
|
122
|
+
sys.exit(1)
|
|
123
|
+
|
|
111
124
|
@core.command()
|
|
112
125
|
@click.option('--coverage', is_flag=True, help='Display coverage report.')
|
|
113
126
|
@click.option('--output', is_flag=True, help='Display tests output.')
|
|
114
127
|
@click.option('--xml', is_flag=True, default=False, help='Use xml reporting instead of default one (report).')
|
|
115
128
|
@click.option('--quiet', is_flag=True, default=True, help='Display or not coverage warnings.')
|
|
116
129
|
@click.option('-p', '--pattern', default=None, help='Run tests on specified file pattern only')
|
|
117
|
-
|
|
130
|
+
@click.option('--functional', is_flag=True, help='Run functional tests (real OS binaries) instead of unit tests.')
|
|
131
|
+
def coretests(coverage, output, xml, quiet, pattern, functional):
|
|
118
132
|
"""
|
|
119
133
|
Execute core tests
|
|
120
134
|
"""
|
|
121
135
|
m = Test()
|
|
122
|
-
res = m.core_tests(coverage, output, xml, quiet, pattern)
|
|
136
|
+
res = m.core_tests(coverage, output, xml, quiet, pattern, functional=functional)
|
|
123
137
|
|
|
124
138
|
if not res:
|
|
125
139
|
sys.exit(1)
|
|
@@ -357,9 +371,13 @@ def watchdog():
|
|
|
357
371
|
@click.option('--quiet', is_flag=True, help='Disable logging.')
|
|
358
372
|
@click.option('--loglevel', default=logging.INFO, help='Logging level (10=DEBUG, 20=INFO, 30=WARN, 40=ERROR).')
|
|
359
373
|
@click.option('--rpc-url', default='https://127.0.0.1:443', help='Cleep RPC url (ex https://ip|host:port')
|
|
360
|
-
|
|
374
|
+
@click.option('--skip-catchup', is_flag=True, help='Do not syncall before watching (not recommended).')
|
|
375
|
+
def watch(quiet, loglevel, rpc_url, skip_catchup):
|
|
361
376
|
"""
|
|
362
|
-
Start watchdog that monitors filesystem changes on Cleep sources
|
|
377
|
+
Start watchdog that monitors filesystem changes on Cleep sources.
|
|
378
|
+
|
|
379
|
+
Prefer managing the durable unit with watchsvc (survives Cleep restarts).
|
|
380
|
+
On start, syncs core + all modules once unless --skip-catchup is set.
|
|
363
381
|
"""
|
|
364
382
|
if logging.getLogger().getEffectiveLevel() == logging.DEBUG:
|
|
365
383
|
# do not overwrite root logger level if configured to DEBUG (dev mode)
|
|
@@ -368,13 +386,51 @@ def watch(quiet, loglevel, rpc_url):
|
|
|
368
386
|
logging.disable(logging.CRITICAL)
|
|
369
387
|
else:
|
|
370
388
|
logging.getLogger().setLevel(loglevel)
|
|
371
|
-
|
|
372
|
-
w = CleepWatchdog(rpc_url)
|
|
389
|
+
|
|
390
|
+
w = CleepWatchdog(rpc_url, catch_up=not skip_catchup)
|
|
373
391
|
res = w.watch()
|
|
374
392
|
|
|
375
393
|
if not res:
|
|
376
394
|
sys.exit(1)
|
|
377
395
|
|
|
396
|
+
@watchdog.command('watchsvc')
|
|
397
|
+
@click.argument(
|
|
398
|
+
'action',
|
|
399
|
+
type=click.Choice(
|
|
400
|
+
['install', 'uninstall', 'enable', 'disable', 'start', 'stop', 'restart', 'status']
|
|
401
|
+
),
|
|
402
|
+
)
|
|
403
|
+
def watchsvc_cmd(action):
|
|
404
|
+
"""
|
|
405
|
+
Manage the durable cleep-watch systemd unit.
|
|
406
|
+
|
|
407
|
+
ACTION is one of: install, uninstall, enable, disable, start, stop, restart, status.
|
|
408
|
+
|
|
409
|
+
The unit runs ``cleep-cli watch`` outside of cleep.service. Typical setup::
|
|
410
|
+
|
|
411
|
+
cleep-cli watchsvc install
|
|
412
|
+
cleep-cli watchsvc enable
|
|
413
|
+
"""
|
|
414
|
+
svc = WatchService()
|
|
415
|
+
handlers = {
|
|
416
|
+
'install': svc.install,
|
|
417
|
+
'uninstall': svc.uninstall,
|
|
418
|
+
'enable': svc.enable,
|
|
419
|
+
'disable': svc.disable,
|
|
420
|
+
'start': svc.start,
|
|
421
|
+
'stop': svc.stop,
|
|
422
|
+
'restart': svc.restart,
|
|
423
|
+
}
|
|
424
|
+
if action == 'status':
|
|
425
|
+
status = svc.status()
|
|
426
|
+
logging.info(status)
|
|
427
|
+
if status != 'active':
|
|
428
|
+
sys.exit(1)
|
|
429
|
+
return
|
|
430
|
+
|
|
431
|
+
if not handlers[action]():
|
|
432
|
+
sys.exit(1)
|
|
433
|
+
|
|
378
434
|
@click.group()
|
|
379
435
|
def test():
|
|
380
436
|
pass
|
|
@@ -385,7 +441,8 @@ def test():
|
|
|
385
441
|
@click.option('--coverage', is_flag=True, help='Display coverage report.')
|
|
386
442
|
@click.option('--copyto', help='Copy .coverage file to specified dir.')
|
|
387
443
|
@click.option('-p', '--pattern', help='Execute tests matching pattern.')
|
|
388
|
-
|
|
444
|
+
@click.option('--functional', is_flag=True, help='Run functional tests (real OS/device) instead of unit tests.')
|
|
445
|
+
def modtests(ctx, module, coverage, copyto, pattern, functional):
|
|
389
446
|
"""
|
|
390
447
|
Execute module tests
|
|
391
448
|
"""
|
|
@@ -393,7 +450,7 @@ def modtests(ctx, module, coverage, copyto, pattern):
|
|
|
393
450
|
ctx.invoke(modsync, module=module)
|
|
394
451
|
|
|
395
452
|
m = Test()
|
|
396
|
-
res = m.module_tests(module, coverage, copyto, pattern)
|
|
453
|
+
res = m.module_tests(module, coverage, copyto, pattern, functional=functional)
|
|
397
454
|
|
|
398
455
|
if not res:
|
|
399
456
|
sys.exit(1)
|
|
@@ -17,6 +17,7 @@ from cleepcli.git import Git
|
|
|
17
17
|
from cleepcli.module import Module
|
|
18
18
|
from cleepcli.file import File
|
|
19
19
|
from cleepcli.watch import CleepWatchdog
|
|
20
|
+
from cleepcli.watchsvc import WatchService
|
|
20
21
|
from cleepcli.test import Test, is_file_coverage_valid
|
|
21
22
|
from cleepcli.package import Package
|
|
22
23
|
from cleepcli.docs import Docs
|
|
@@ -108,18 +109,31 @@ def coresync():
|
|
|
108
109
|
sys.exit(1)
|
|
109
110
|
logging.info('Done')
|
|
110
111
|
|
|
112
|
+
@core.command()
|
|
113
|
+
def syncall():
|
|
114
|
+
"""
|
|
115
|
+
Synchronize core and all modules from /root/cleep-dev to execution folders.
|
|
116
|
+
|
|
117
|
+
Same catch-up used when cleep-watch.service starts. Safe one-shot resync when
|
|
118
|
+
the UI looks stale: run this, then reload the device page.
|
|
119
|
+
"""
|
|
120
|
+
f = File()
|
|
121
|
+
if not f.sync_all():
|
|
122
|
+
sys.exit(1)
|
|
123
|
+
|
|
111
124
|
@core.command()
|
|
112
125
|
@click.option('--coverage', is_flag=True, help='Display coverage report.')
|
|
113
126
|
@click.option('--output', is_flag=True, help='Display tests output.')
|
|
114
127
|
@click.option('--xml', is_flag=True, default=False, help='Use xml reporting instead of default one (report).')
|
|
115
128
|
@click.option('--quiet', is_flag=True, default=True, help='Display or not coverage warnings.')
|
|
116
129
|
@click.option('-p', '--pattern', default=None, help='Run tests on specified file pattern only')
|
|
117
|
-
|
|
130
|
+
@click.option('--functional', is_flag=True, help='Run functional tests (real OS binaries) instead of unit tests.')
|
|
131
|
+
def coretests(coverage, output, xml, quiet, pattern, functional):
|
|
118
132
|
"""
|
|
119
133
|
Execute core tests
|
|
120
134
|
"""
|
|
121
135
|
m = Test()
|
|
122
|
-
res = m.core_tests(coverage, output, xml, quiet, pattern)
|
|
136
|
+
res = m.core_tests(coverage, output, xml, quiet, pattern, functional=functional)
|
|
123
137
|
|
|
124
138
|
if not res:
|
|
125
139
|
sys.exit(1)
|
|
@@ -357,9 +371,13 @@ def watchdog():
|
|
|
357
371
|
@click.option('--quiet', is_flag=True, help='Disable logging.')
|
|
358
372
|
@click.option('--loglevel', default=logging.INFO, help='Logging level (10=DEBUG, 20=INFO, 30=WARN, 40=ERROR).')
|
|
359
373
|
@click.option('--rpc-url', default='https://127.0.0.1:443', help='Cleep RPC url (ex https://ip|host:port')
|
|
360
|
-
|
|
374
|
+
@click.option('--skip-catchup', is_flag=True, help='Do not syncall before watching (not recommended).')
|
|
375
|
+
def watch(quiet, loglevel, rpc_url, skip_catchup):
|
|
361
376
|
"""
|
|
362
|
-
Start watchdog that monitors filesystem changes on Cleep sources
|
|
377
|
+
Start watchdog that monitors filesystem changes on Cleep sources.
|
|
378
|
+
|
|
379
|
+
Prefer managing the durable unit with watchsvc (survives Cleep restarts).
|
|
380
|
+
On start, syncs core + all modules once unless --skip-catchup is set.
|
|
363
381
|
"""
|
|
364
382
|
if logging.getLogger().getEffectiveLevel() == logging.DEBUG:
|
|
365
383
|
# do not overwrite root logger level if configured to DEBUG (dev mode)
|
|
@@ -368,13 +386,51 @@ def watch(quiet, loglevel, rpc_url):
|
|
|
368
386
|
logging.disable(logging.CRITICAL)
|
|
369
387
|
else:
|
|
370
388
|
logging.getLogger().setLevel(loglevel)
|
|
371
|
-
|
|
372
|
-
w = CleepWatchdog(rpc_url)
|
|
389
|
+
|
|
390
|
+
w = CleepWatchdog(rpc_url, catch_up=not skip_catchup)
|
|
373
391
|
res = w.watch()
|
|
374
392
|
|
|
375
393
|
if not res:
|
|
376
394
|
sys.exit(1)
|
|
377
395
|
|
|
396
|
+
@watchdog.command('watchsvc')
|
|
397
|
+
@click.argument(
|
|
398
|
+
'action',
|
|
399
|
+
type=click.Choice(
|
|
400
|
+
['install', 'uninstall', 'enable', 'disable', 'start', 'stop', 'restart', 'status']
|
|
401
|
+
),
|
|
402
|
+
)
|
|
403
|
+
def watchsvc_cmd(action):
|
|
404
|
+
"""
|
|
405
|
+
Manage the durable cleep-watch systemd unit.
|
|
406
|
+
|
|
407
|
+
ACTION is one of: install, uninstall, enable, disable, start, stop, restart, status.
|
|
408
|
+
|
|
409
|
+
The unit runs ``cleep-cli watch`` outside of cleep.service. Typical setup::
|
|
410
|
+
|
|
411
|
+
cleep-cli watchsvc install
|
|
412
|
+
cleep-cli watchsvc enable
|
|
413
|
+
"""
|
|
414
|
+
svc = WatchService()
|
|
415
|
+
handlers = {
|
|
416
|
+
'install': svc.install,
|
|
417
|
+
'uninstall': svc.uninstall,
|
|
418
|
+
'enable': svc.enable,
|
|
419
|
+
'disable': svc.disable,
|
|
420
|
+
'start': svc.start,
|
|
421
|
+
'stop': svc.stop,
|
|
422
|
+
'restart': svc.restart,
|
|
423
|
+
}
|
|
424
|
+
if action == 'status':
|
|
425
|
+
status = svc.status()
|
|
426
|
+
logging.info(status)
|
|
427
|
+
if status != 'active':
|
|
428
|
+
sys.exit(1)
|
|
429
|
+
return
|
|
430
|
+
|
|
431
|
+
if not handlers[action]():
|
|
432
|
+
sys.exit(1)
|
|
433
|
+
|
|
378
434
|
@click.group()
|
|
379
435
|
def test():
|
|
380
436
|
pass
|
|
@@ -385,7 +441,8 @@ def test():
|
|
|
385
441
|
@click.option('--coverage', is_flag=True, help='Display coverage report.')
|
|
386
442
|
@click.option('--copyto', help='Copy .coverage file to specified dir.')
|
|
387
443
|
@click.option('-p', '--pattern', help='Execute tests matching pattern.')
|
|
388
|
-
|
|
444
|
+
@click.option('--functional', is_flag=True, help='Run functional tests (real OS/device) instead of unit tests.')
|
|
445
|
+
def modtests(ctx, module, coverage, copyto, pattern, functional):
|
|
389
446
|
"""
|
|
390
447
|
Execute module tests
|
|
391
448
|
"""
|
|
@@ -393,7 +450,7 @@ def modtests(ctx, module, coverage, copyto, pattern):
|
|
|
393
450
|
ctx.invoke(modsync, module=module)
|
|
394
451
|
|
|
395
452
|
m = Test()
|
|
396
|
-
res = m.module_tests(module, coverage, copyto, pattern)
|
|
453
|
+
res = m.module_tests(module, coverage, copyto, pattern, functional=functional)
|
|
397
454
|
|
|
398
455
|
if not res:
|
|
399
456
|
sys.exit(1)
|
|
@@ -1497,6 +1497,50 @@ overgeneral-exceptions=Exception
|
|
|
1497
1497
|
"""
|
|
1498
1498
|
return self._check_module_tree(module_name, "asset")
|
|
1499
1499
|
|
|
1500
|
+
def check_firmwares(self, module_name):
|
|
1501
|
+
"""
|
|
1502
|
+
Validate optional ``firmwares/`` zip+sidecar ``.manifest`` pairs and list
|
|
1503
|
+
files for packaging (see ``cleep.libs.internals.firmware_manifest``).
|
|
1504
|
+
|
|
1505
|
+
Returns:
|
|
1506
|
+
dict: errors / warnings / files (same shape as check_scripts)
|
|
1507
|
+
"""
|
|
1508
|
+
if not os.path.exists(os.path.join(config.MODULES_DST, module_name)):
|
|
1509
|
+
raise Exception('Module "%s" does not exist' % module_name)
|
|
1510
|
+
|
|
1511
|
+
firmwares_path = os.path.join(config.MODULES_SRC, module_name, "firmwares")
|
|
1512
|
+
out = {
|
|
1513
|
+
"errors": [],
|
|
1514
|
+
"warnings": [],
|
|
1515
|
+
"files": [],
|
|
1516
|
+
}
|
|
1517
|
+
if not os.path.isdir(firmwares_path):
|
|
1518
|
+
return out
|
|
1519
|
+
|
|
1520
|
+
try:
|
|
1521
|
+
from cleep.libs.internals.firmware_manifest import (
|
|
1522
|
+
FirmwareManifestError,
|
|
1523
|
+
scan_firmwares_dir,
|
|
1524
|
+
)
|
|
1525
|
+
except ImportError:
|
|
1526
|
+
out["errors"].append(
|
|
1527
|
+
"Unable to import cleep.libs.internals.firmware_manifest "
|
|
1528
|
+
"(is Cleep core available on PYTHONPATH?)"
|
|
1529
|
+
)
|
|
1530
|
+
return out
|
|
1531
|
+
|
|
1532
|
+
try:
|
|
1533
|
+
scan_firmwares_dir(firmwares_path)
|
|
1534
|
+
except FirmwareManifestError as error:
|
|
1535
|
+
out["errors"].append(str(error))
|
|
1536
|
+
return out
|
|
1537
|
+
|
|
1538
|
+
# Include valid pairs in the package file list
|
|
1539
|
+
tree = self._check_module_tree(module_name, "firmwares")
|
|
1540
|
+
out["files"] = tree["files"]
|
|
1541
|
+
out["warnings"] = tree["warnings"]
|
|
1542
|
+
return out
|
|
1543
|
+
|
|
1500
1544
|
def check_tests(self, module_name):
|
|
1501
1545
|
"""
|
|
1502
1546
|
Check test files
|
|
@@ -60,6 +60,51 @@ rsync -av "%(REPO_DIR)s/medias/sounds" "%(MEDIA_DST)s/sounds/" --delete
|
|
|
60
60
|
|
|
61
61
|
return True
|
|
62
62
|
|
|
63
|
+
def list_modules(self):
|
|
64
|
+
"""
|
|
65
|
+
List module folder names under MODULES_SRC (skips hidden dirs).
|
|
66
|
+
|
|
67
|
+
Returns:
|
|
68
|
+
list: sorted module names
|
|
69
|
+
"""
|
|
70
|
+
if not os.path.isdir(config.MODULES_SRC):
|
|
71
|
+
return []
|
|
72
|
+
names = []
|
|
73
|
+
try:
|
|
74
|
+
for name in os.listdir(config.MODULES_SRC):
|
|
75
|
+
if name.startswith("."):
|
|
76
|
+
continue
|
|
77
|
+
path = os.path.join(config.MODULES_SRC, name)
|
|
78
|
+
if os.path.isdir(path):
|
|
79
|
+
names.append(name)
|
|
80
|
+
except OSError as error:
|
|
81
|
+
self.logger.error("Unable to list modules: %s", error)
|
|
82
|
+
return []
|
|
83
|
+
return sorted(names)
|
|
84
|
+
|
|
85
|
+
def sync_all(self):
|
|
86
|
+
"""
|
|
87
|
+
Synchronize core and every module from REPO_DIR to execution folders.
|
|
88
|
+
|
|
89
|
+
Used as watch catch-up on start and by the ``syncall`` CLI command so a
|
|
90
|
+
full resync is always one explicit action away.
|
|
91
|
+
|
|
92
|
+
Returns:
|
|
93
|
+
bool: True if every sync succeeded
|
|
94
|
+
"""
|
|
95
|
+
self.logger.info("Synchronizing core sources...")
|
|
96
|
+
if not self.core_sync():
|
|
97
|
+
return False
|
|
98
|
+
|
|
99
|
+
modules = self.list_modules()
|
|
100
|
+
for module_name in modules:
|
|
101
|
+
self.logger.info('Synchronizing module "%s" sources...', module_name)
|
|
102
|
+
if not self.module_sync(module_name):
|
|
103
|
+
return False
|
|
104
|
+
|
|
105
|
+
self.logger.info("Sync all done (%d module(s))", len(modules))
|
|
106
|
+
return True
|
|
107
|
+
|
|
63
108
|
def module_sync(self, module_name, backend=True, frontend=True, scripts=True):
|
|
64
109
|
"""
|
|
65
110
|
Copy specified module content to valid execution location
|
|
@@ -488,6 +488,8 @@ pytest_plugins = ('cleep.libs.tests.fixtures',)
|
|
|
488
488
|
pythonpath = .
|
|
489
489
|
testpaths = tests
|
|
490
490
|
python_files = test_*.py
|
|
491
|
+
markers =
|
|
492
|
+
functional: real OS/device tests (CLEEP_FUNCTIONAL_TESTS / modtests --functional)
|
|
491
493
|
"""
|
|
492
494
|
DOCS_CONF_PY = """# -*- coding: utf-8 -*-
|
|
493
495
|
import os, sys
|
|
@@ -516,6 +516,12 @@ sha256sum $DEB > $SHA256
|
|
|
516
516
|
"Error in asset/. Fix it before packaging application: %s"
|
|
517
517
|
% data_asset["errors"]
|
|
518
518
|
)
|
|
519
|
+
data_firmwares = check.check_firmwares(module_name)
|
|
520
|
+
if len(data_firmwares["errors"]) > 0:
|
|
521
|
+
raise Exception(
|
|
522
|
+
"Error in firmwares/. Fix it before packaging application: %s"
|
|
523
|
+
% data_firmwares["errors"]
|
|
524
|
+
)
|
|
519
525
|
data_tests = check.check_tests(module_name)
|
|
520
526
|
if len(data_tests["errors"]) > 0:
|
|
521
527
|
raise Exception(
|
|
@@ -629,6 +635,10 @@ sha256sum $DEB > $SHA256
|
|
|
629
635
|
for a_file in data_asset["files"]:
|
|
630
636
|
archive.write(a_file["fullpath"], a_file["path"])
|
|
631
637
|
|
|
638
|
+
# add firmwares/ (zip + sidecar .manifest; installer copies to APP_FIRMWARE)
|
|
639
|
+
for a_file in data_firmwares["files"]:
|
|
640
|
+
archive.write(a_file["fullpath"], a_file["path"])
|
|
641
|
+
|
|
632
642
|
# add module.json
|
|
633
643
|
archive.write(module_json, "module.json")
|
|
634
644
|
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
[Unit]
|
|
2
|
+
Description=Cleep development source watcher (cleep-cli watch)
|
|
3
|
+
Documentation=https://github.com/CleepDevice/cleep-cli
|
|
4
|
+
# Independent from cleep.service so backend restarts do not kill the watcher
|
|
5
|
+
# mid-sync (Desktop writes would otherwise be missed until the next edit).
|
|
6
|
+
After=network-online.target
|
|
7
|
+
Wants=network-online.target
|
|
8
|
+
|
|
9
|
+
[Service]
|
|
10
|
+
Type=simple
|
|
11
|
+
ExecStart=/usr/local/bin/cleep-cli watch --loglevel=20
|
|
12
|
+
Restart=always
|
|
13
|
+
RestartSec=3
|
|
14
|
+
# Allow a long catch-up sync on start before the main loop
|
|
15
|
+
TimeoutStartSec=180
|
|
16
|
+
|
|
17
|
+
[Install]
|
|
18
|
+
WantedBy=multi-user.target
|