138 Commits

Author SHA1 Message Date
b9e0b7ccd0 Build 2022.6.0.rc1 2022-06-27 20:55:44 +02:00
4b9e428abb Updated tools 2022-06-27 20:52:27 +02:00
63ad13e09a Improved version handling of set-version 2022-06-27 20:46:01 +02:00
cc06a308a1 Merge pull request '2022.6.10 - Dev dependencies' (#86) from 2022.6.10 into 2022.6
Reviewed-on: #86
Closes #71
2022-06-27 20:18:24 +02:00
e9fdd20181 Updated unittests 2022-06-27 20:16:37 +02:00
8692686cb5 Added dev-deps support to new command 2022-06-27 20:07:52 +02:00
db29ad36fe Added dev-deps support to cpl install without package 2022-06-27 20:05:34 +02:00
0710b25317 Added dev-dependencies to uninstall command 2022-06-27 20:04:19 +02:00
cbd2964f42 Added dev-dependencies to install command 2022-06-27 20:02:01 +02:00
f51118f13c Merge pull request '2022.6.2 - Venv support' (#85) from 2022.6.2 into 2022.6
Reviewed-on: #85
Closes #51
2022-06-27 11:52:17 +02:00
323e363b42 Improved venv support to all related commands 2022-06-27 11:50:22 +02:00
e8a4fe6142 Added venv support to install command 2022-06-27 10:52:26 +02:00
587d9b359c Merge pull request '2022.6.17 - Unittests' (#84) from 2022.6.17 into 2022.6
Reviewed-on: #84
2022-06-27 10:03:54 +02:00
c2632253ac Added tests for update command 2022-06-27 09:10:21 +02:00
45be77dd10 Added tests for version command 2022-06-26 19:51:18 +02:00
78ffbcc33d Readded all test cases 2022-06-26 01:07:10 +02:00
d83d1a244e Fixed for start command [WIP] output is needed 2022-06-26 01:05:45 +02:00
fa002a50ac Fixed for start command 2022-06-26 00:41:25 +02:00
32507afae9 Added tests for start command 2022-06-26 00:39:16 +02:00
6de3bbdaf4 Added tests for run command 2022-06-26 00:15:05 +02:00
6e50d0cb22 Added tests for publish command 2022-06-23 23:47:29 +02:00
9e978f3ece Fixed tests for un/install commands 2022-06-23 23:39:41 +02:00
32478926c8 Added tests for build command 2022-06-23 21:49:44 +02:00
2925788d01 Added tests for uninstall command 2022-06-21 09:24:56 +02:00
c0789cf4f7 Added tests for install command 2022-06-21 08:56:26 +02:00
89d591ce0a Added project reference handling in cpl remove 2022-06-04 00:36:31 +02:00
77c560b40c Improved cpl remove test 2022-06-03 23:46:03 +02:00
dad4913bcd Added cpl remove test 2022-06-03 23:44:26 +02:00
9b56650d4b Added cpl add test 2022-06-03 23:35:07 +02:00
9fca2018e5 Build dev10 2022-05-27 18:57:12 +02:00
e5dd890931 Improved unittest for cpl new & Fixed subdirectory handling with cpl new 2022-05-27 18:57:00 +02:00
beadbf8e91 Improved set-version to ignore skipped deps 2022-05-27 18:26:32 +02:00
ff5f9b833d Improved unittest for cpl new 2022-05-27 18:07:12 +02:00
162f06001a Build dev8 & improved cpl new unittests 2022-05-26 23:27:32 +02:00
348fad24c7 Build dev8 & improved set-version change handling 2022-05-26 23:27:20 +02:00
f9748cdb76 Improved gitignore 2022-05-26 23:03:18 +02:00
56380763a9 Improved unittests 2022-05-26 23:01:50 +02:00
3a1630b687 Added force option to set-version 2022-05-26 23:01:23 +02:00
a593f34cde Build dev7 2022-05-26 23:00:55 +02:00
49cce5fa1a Extended cpl new options 2022-05-26 22:52:03 +02:00
df7bd06629 Fixed additional argument & flag bug 2022-05-26 22:51:29 +02:00
e0da77fd4b Added new test condition for cpl new 2022-05-26 22:24:19 +02:00
833dd83008 Improved unittests & added tests for cpl new 2022-05-26 22:21:16 +02:00
ce0ad4013f [WIP] Improved unittest 2022-05-26 21:42:43 +02:00
698f80adfe Build dev6 2022-05-26 21:42:28 +02:00
d0b0f4bfcb Fixed set-version 2022-05-26 21:41:42 +02:00
d23ea86ccf Added logic to answer questions of new command dialog by flag arguments 2022-05-26 21:18:57 +02:00
15d938b172 Fixed handing of unregistered console arguments 2022-05-26 21:01:41 +02:00
6c1d7a3b29 Removed prints from CLITestSuite 2022-05-26 16:29:07 +02:00
c28f551682 Added skip message to set-version 2022-05-26 16:26:55 +02:00
def92c78c8 Added logic to change version only for projects with changes 2022-05-26 16:25:15 +02:00
ddff9dec11 Fixed install command 2022-05-26 16:08:37 +02:00
9e0e85d646 Fixed install command 2022-05-26 16:06:56 +02:00
b05ca7e980 Set dev version 2022-05-26 16:03:14 +02:00
8f8a9f7dd7 Moved query unittests 2022-05-26 15:53:23 +02:00
df32978a31 Moved unittests 2022-05-26 15:49:52 +02:00
79b51cf8c5 Build dev4 & added unittest support to console 2022-05-26 15:41:47 +02:00
a72dd0dc2e Improved tests 2022-05-26 15:29:49 +02:00
d937c4c0e6 Added tests for generate command 2022-05-26 14:47:36 +02:00
46cceb0910 Registered CLI test cases 2022-05-26 13:59:46 +02:00
e74e39c189 Added CLI command test cases 2022-05-26 13:49:31 +02:00
c2706c7737 Added unittest projects 2022-05-26 13:37:15 +02:00
d0e66d24bd Added logic to generate test cases 2022-05-26 13:17:58 +02:00
c1a1849ad2 Added logic to create new unittest project 2022-05-26 13:12:35 +02:00
0675105731 Merge pull request '2022.6.16 - Build-Tools' (#83) from 2022.6.16 into 2022.6
Reviewed-on: #83
Closes #82
2022-05-26 12:13:45 +02:00
7ee0b951a8 Rebuild & improved workspace scripts 2022-05-25 19:59:38 +02:00
d8168f024c Added logic to write PipPath & build dev2 2022-05-25 19:53:05 +02:00
2654dc7c69 Merge remote-tracking branch 'origin/2022.6.16' into 2022.6.16 2022-05-25 19:38:56 +02:00
4224960837 First dev build 2022-05-25 19:38:49 +02:00
907c3a8fff First dev build 2022-05-25 19:38:38 +02:00
28505479ba Added new project 2022-05-25 19:30:11 +02:00
84d3abce3f Merge pull request '2022.6.15 - set-version' (#81) from 2022.6.15 into 2022.6
Reviewed-on: #81
Closes #80
2022-05-25 19:10:35 +02:00
9050dffc53 Renamed projects && build dev6 2022-05-25 19:07:29 +02:00
e0f69c9bdf Fixed old naming of cpl_core 2022-05-25 18:56:08 +02:00
bbd0a60f98 Added functionality to set dependencies for all projects in workspace 2022-05-25 18:54:21 +02:00
e23f4187fe Added logic to add internal pipes in ServiceCollection 2022-05-25 18:42:47 +02:00
15f200df3a Added version pipe 2022-05-25 18:40:01 +02:00
a1a3ad6fb5 Build dev4 2022-05-25 17:09:31 +02:00
d6677d53a3 Added empty lines to generate output 2022-05-25 17:08:03 +02:00
07e43b50d1 Fixed generate pipe argument 2022-05-25 17:07:22 +02:00
ac83555b24 Added logic to handle cpl deps 2022-05-25 17:04:18 +02:00
1ab358059c Added more pre-build scripts 2022-05-25 16:57:21 +02:00
5bf83c0d77 Build dev2 2022-05-25 16:56:24 +02:00
03ac00c6e3 Bugfixes for set-version & CustomScriptService 2022-05-25 16:51:52 +02:00
0122d8fc78 Merge remote-tracking branch 'origin/2022.6.15' into 2022.6.15 2022-05-25 16:43:52 +02:00
a66ce96dbf Added set-version logic && Fixed CustomScriptService to handle arguments 2022-05-25 16:43:43 +02:00
6da8e30446 Added set-version logic && Fixed CustomScriptService to handle arguments 2022-05-25 16:43:28 +02:00
539ed13be4 Bugfixes for run service 2022-05-25 16:06:44 +02:00
036a553f64 Dev build 2022.6.15.dev1 2022-05-25 15:12:36 +02:00
976a14584b Dev build 2022.6.15.dev1 2022-05-25 15:12:30 +02:00
ed69f52927 Fixed generate service 2022-05-25 15:11:42 +02:00
98847495e6 Merge pull request '2022.6.14 - Pre & Post build scripts' (#79) from 2022.6.14 into 2022.6
Reviewed-on: #79
Closes #77
2022-05-25 14:15:24 +02:00
40f132da33 Added workspace scripts 2022-05-25 14:14:26 +02:00
5feb44595a Fixed cpl run command 2022-05-25 14:00:38 +02:00
48c6941f1a Added run command & tools/set-version project 2022-05-25 13:43:16 +02:00
a8756d493a Fixed error with RemoveService 2022-05-25 13:19:12 +02:00
9f4077a073 Improved configuration 2022-05-25 13:11:41 +02:00
3e7a3d75c5 Merge pull request 'cpl@2022.6.13 - cpl run command' (#78) from 2022.6.13 into 2022.6
Reviewed-on: #78
Closes #76
2022-05-25 08:42:41 +02:00
477d2d87d3 Added run command 2022-05-25 08:41:35 +02:00
7a65dbe39b Readded logic to handle pre and post scripts from workspace 2022-05-24 22:28:38 +02:00
f83755ac77 Removed console output & build new dev version 2022-05-24 20:20:42 +02:00
a590cfd066 Bugfixes for start service 2022-05-24 20:12:59 +02:00
f317035342 Bugfixes for test application & added validators to cli 2022-05-24 19:20:55 +02:00
8900bdd446 Removed invalid import && build for rc1 2022-05-24 18:20:31 +02:00
35ecf158a2 Fixed loading by base_type 2022-05-24 18:13:39 +02:00
353c1d30ec Merge pull request '2022.6.9 - Singleton initialisierung' (#75) from 2022.6.9 into 2022.6
Reviewed-on: #75
Closes #70
2022-05-24 17:52:13 +02:00
1c94fb5bd1 Added logic to load singletons when requested not when registered 2022-05-24 17:51:17 +02:00
cf305aeebb Merge pull request '2022.6.12 - Alle Umgebungsvariablen' (#74) from 2022.6.12 into 2022.6
Reviewed-on: #74
Closes #73
2022-05-24 17:39:20 +02:00
90e97433e0 Added logic to load all environment variables by prefix 2022-05-24 17:37:31 +02:00
125a85a0af Merge pull request '2022.6.7 - Pipes' (#69) from 2022.6.7 into 2022.6
Reviewed-on: #69
Closes #60
2022-05-22 20:28:46 +02:00
cfb8838c73 Added default pipes 2022-05-22 20:27:58 +02:00
824d491ebc Dev build projects 2022-05-22 18:49:31 +02:00
d694c408c0 Added CLI logic to generate pipes 2022-05-22 18:48:33 +02:00
d1bb266d49 Added Pipes 2022-05-22 18:43:10 +02:00
419fcc3d29 Merge pull request '2022.6.5 - CLI Erweiterung' (#68) from 2022.6.5 into 2022.6
Reviewed-on: #68
Closes #54
2022-05-22 18:34:44 +02:00
24ab6a51c1 Refactored executable arguments 2022-05-22 18:33:07 +02:00
dec4a45d98 Added logic to add CLI commands from external packages 2022-05-22 18:32:34 +02:00
d11c56db03 Merge pull request 'cpl@2022.6.3 - Verbesserung der Parameter' (#67) from 2022.6.3 into 2022.6
Reviewed-on: #67
2022-05-22 17:38:21 +02:00
fc23315cc7 Build version 2022.6.3 2022-05-22 17:35:38 +02:00
1f503fe20d Build new version 2022-05-20 10:37:43 +02:00
4564f7ac0e Improved output & imports 2022-05-20 10:35:47 +02:00
7b823e1141 Added validator generation 2022-05-20 10:34:09 +02:00
dac3d9c6bb Added validators (closes #59) 2022-05-20 10:27:55 +02:00
ccca904cb8 Smaller output fixes 2022-05-20 09:17:51 +02:00
c66a81c0ec Dev build & migrated custom scripts 2022-05-20 09:12:28 +02:00
fb810e2943 Dev build & migrated custom scripts & add logic to prevent next executable 2022-05-20 09:10:29 +02:00
5cc663dedc Migrated generate command 2022-05-20 08:50:50 +02:00
593372699b BUild dev version 2022-05-20 08:44:32 +02:00
1899cb5b86 Added scripts to workspace 2022-05-19 20:49:48 +02:00
0a285f2d28 Improved help command 2022-05-19 20:23:21 +02:00
94c82e6701 Improved help command 2022-05-19 20:21:46 +02:00
0d37c86061 Removed console output 2022-05-19 20:05:22 +02:00
6c8e9ccd89 Migrated StartService to new argument parsing 2022-05-19 20:04:29 +02:00
e7cf545502 Migrated NewService to new argument parsing 2022-05-19 19:52:36 +02:00
44182eec86 Fixed value handling for variable arguments 2022-05-19 19:41:02 +02:00
0f5b1b7586 Improved argument handling 2022-05-19 19:37:32 +02:00
4fe073580a Migrated first commands to new argument parser 2022-05-19 18:12:47 +02:00
2fed654c16 Improved argument handling 2022-05-19 18:09:25 +02:00
172 changed files with 4175 additions and 844 deletions

3
.gitignore vendored
View File

@@ -135,3 +135,6 @@ dmypy.json
# IDE # IDE
.idea/ .idea/
PythonImportHelper-v2-Completion.json PythonImportHelper-v2-Completion.json
# cpl unittest stuff
unittests/test_*_playground

View File

@@ -1,13 +1,95 @@
{ {
"WorkspaceSettings": { "WorkspaceSettings": {
"DefaultProject": "cpl_cli", "DefaultProject": "cpl-cli",
"Projects": { "Projects": {
"cpl_core": "src/cpl_core/cpl_core.json", "cpl-core": "src/cpl_core/cpl-core.json",
"cpl_cli": "src/cpl_cli/cpl_cli.json", "cpl-cli": "src/cpl_cli/cpl-cli.json",
"cpl_query": "src/cpl_query/cpl_query.json" "cpl-query": "src/cpl_query/cpl-query.json",
"set-version": "tools/set_version/set-version.json",
"set-pip-urls": "tools/set_pip_urls/set-pip-urls.json",
"unittests": "unittests/unittests/unittests.json",
"unittests_cli": "unittests/unittests_cli/unittests_cli.json",
"unittests_core": "unittests/unittests_core/unittests_core.json",
"unittests_query": "unittests/unittests_query/unittests_query.json",
"unittests_shared": "unittests/unittests_shared/unittests_shared.json"
}, },
"Scripts": { "Scripts": {
"hello-world": "echo 'Hello World'" "hello-world": "echo 'Hello World'",
"sv": "cpl set-version",
"set-version": "cpl run set-version $ARGS; echo '';",
"spu": "cpl set-pip-urls",
"set-pip-urls": "cpl run set-pip-urls $ARGS; echo '';",
"docs-build": "echo 'Build Documentation'; cd docs/; sphinx-apidoc -o source/ ../src/cpl_core; sphinx-apidoc -o source/ ../src/cpl_query; make clean; make html; rm source/cpl_query.tests.rst;",
"db": "cpl build-docs",
"docs-open": "xdg-open $PWD/docs/build/html/index.html &",
"do": "cpl docs-open",
"test": "cpl run unittests",
"pre-build-all": "cpl sv $ARGS; cpl spu $ARGS;",
"build-all": "cpl build-cli; cpl build-core; cpl build-query; cpl build-set-pip-urls; cpl build-set-version",
"ba": "cpl build-all $ARGS",
"build-cli": "echo 'Build cpl-cli'; cd ./src/cpl_cli; cpl build; cd ../../;",
"build-core": "echo 'Build cpl-core'; cd ./src/cpl_core; cpl build; cd ../../;",
"build-query": "echo 'Build cpl-query'; cd ./src/cpl_query; cpl build; cd ../../;",
"build-set-pip-urls": "echo 'Build set-pip-urls'; cd ./tools/set_pip_urls; cpl build; cd ../../;",
"build-set-version": "echo 'Build set-version'; cd ./tools/set_version; cpl build; cd ../../;",
"pre-publish-all": "cpl sv $ARGS; cpl spu $ARGS;",
"publish-all": "cpl publish-cli; cpl publish-core; cpl publish-query;",
"pa": "cpl build-all $ARGS",
"publish-cli": "echo 'Publish cpl-cli'; cd ./src/cpl_cli; cpl publish; cd ../../;",
"publish-core": "echo 'Publish cpl-core'; cd ./src/cpl_core; cpl publish; cd ../../;",
"publish-query": "echo 'Publish cpl_query'; cd ./src/cpl_query; cpl publish; cd ../../;",
"upload-prod-cli": "echo 'PROD Upload cpl-cli'; cpl upl-prod-cli;",
"upl-prod-cli": "twine upload -r pip.sh-edraft.de dist/cpl-cli/publish/setup/*",
"upload-prod-core": "echo 'PROD Upload cpl-core'; cpl upl-prod-core;",
"upl-prod-core": "twine upload -r pip.sh-edraft.de dist/cpl-core/publish/setup/*",
"upload-prod-query": "echo 'PROD Upload cpl_query'; cpl upl-prod-query;",
"upl-prod-query": "twine upload -r pip.sh-edraft.de dist/cpl-query/publish/setup/*",
"upload-exp-cli": "echo 'EXP Upload cpl-cli'; cpl upl-exp-cli;",
"upl-exp-cli": "twine upload -r pip-exp.sh-edraft.de dist/cpl-cli/publish/setup/*",
"upload-exp-core": "echo 'EXP Upload cpl-core'; cpl upl-exp-core;",
"upl-exp-core": "twine upload -r pip-exp.sh-edraft.de dist/cpl-core/publish/setup/*",
"upload-exp-query": "echo 'EXP Upload cpl_query'; cpl upl-exp-query;",
"upl-exp-query": "twine upload -r pip-exp.sh-edraft.de dist/cpl-query/publish/setup/*",
"upload-dev-cli": "echo 'DEV Upload cpl-cli'; cpl upl-dev-cli;",
"upl-dev-cli": "twine upload -r pip-dev.sh-edraft.de dist/cpl-cli/publish/setup/*",
"upload-dev-core": "echo 'DEV Upload cpl-core'; cpl upl-dev-core;",
"upl-dev-core": "twine upload -r pip-dev.sh-edraft.de dist/cpl-core/publish/setup/*",
"upload-dev-query": "echo 'DEV Upload cpl_query'; cpl upl-dev-query;",
"upl-dev-query": "twine upload -r pip-dev.sh-edraft.de dist/cpl-query/publish/setup/*",
"pre-deploy-prod": "cpl sv $ARGS; cpl spu --environment=production;",
"deploy-prod": "cpl deploy-prod-cli; cpl deploy-prod-core; cpl deploy-prod-query;",
"dp": "cpl deploy-prod $ARGS",
"deploy-prod-cli": "cpl publish-cli; cpl upload-prod-cli",
"deploy-prod-core": "cpl publish-core; cpl upload-prod-core",
"deploy-prod-query": "cpl publish-query; cpl upload-prod-query",
"pre-deploy-exp": "cpl sv $ARGS; cpl spu --environment=staging;",
"deploy-exp": "cpl deploy-exp-cli; cpl deploy-exp-core; cpl deploy-exp-query;",
"de": "cpl deploy-exp $ARGS",
"deploy-exp-cli": "cpl publish-cli; cpl upload-exp-cli",
"deploy-exp-core": "cpl publish-core; cpl upload-exp-core",
"deploy-exp-query": "cpl publish-query; cpl upload-exp-query",
"pre-deploy-dev": "cpl sv $ARGS; cpl spu --environment=development;",
"deploy-dev": "cpl deploy-dev-cli; cpl deploy-dev-core; cpl deploy-dev-query;",
"dd": "cpl deploy-dev $ARGS",
"deploy-dev-cli": "cpl publish-cli; cpl upload-dev-cli",
"deploy-dev-core": "cpl publish-core; cpl upload-dev-core",
"deploy-dev-query": "cpl publish-query; cpl upload-dev-query",
"dev-install": "cpl di-core; cpl di-cli; cpl di-query;",
"di": "cpl dev-install",
"di-core": "pip install cpl-query --pre --upgrade --extra-index-url https://pip-dev.sh-edraft.de",
"di-cli": "pip install cpl-query --pre --upgrade --extra-index-url https://pip-dev.sh-edraft.de",
"di-query": "pip install cpl-query --pre --upgrade --extra-index-url https://pip-dev.sh-edraft.de"
} }
} }
} }

View File

@@ -7,7 +7,7 @@ if [ $1 == "-prod" ]; then
elif [ $1 == "-exp" ]; then elif [ $1 == "-exp" ]; then
twine upload -r pip-exp.sh-edraft.de dist/cpl-cli/publish/setup/* twine upload -r pip-exp.sh-edraft.de dist/cpl-cli/publish/setup/*
twine upload -r pip-exp.sh-edraft.de dist/cpl-core/publish/setup/* twine upload -r pip-exp.sh-edraft.de dist/cpl-core/publish/setup/*
twine upload -r pip-.sh-edraft.de dist/cpl-query/publish/setup/* twine upload -r pip-exp.sh-edraft.de dist/cpl-query/publish/setup/*
else else
twine upload -r pip-dev.sh-edraft.de dist/cpl-cli/publish/setup/* twine upload -r pip-dev.sh-edraft.de dist/cpl-cli/publish/setup/*

View File

@@ -15,18 +15,16 @@ __title__ = 'cpl_cli'
__author__ = 'Sven Heidemann' __author__ = 'Sven Heidemann'
__license__ = 'MIT' __license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de'
__version__ = '2022.6.3.dev2' __version__ = '2022.6.0rc1'
from collections import namedtuple from collections import namedtuple
# imports: # imports:
from .cli import CLI from .cli import CLI
from .command_abc import CommandABC from .command_abc import CommandABC
from .command_handler_service import CommandHandler
from .command_model import CommandModel
from .error import Error from .error import Error
from .main import main from .main import main
from .startup import Startup from .startup import Startup
VersionInfo = namedtuple('VersionInfo', 'major minor micro') VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='2022', minor='6', micro='3.dev2') version_info = VersionInfo(major='2022', minor='6', micro='0.rc1')

View File

@@ -15,11 +15,11 @@ __title__ = 'cpl_cli._templates'
__author__ = 'Sven Heidemann' __author__ = 'Sven Heidemann'
__license__ = 'MIT' __license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de'
__version__ = '2022.6.3.dev2' __version__ = '2022.6.0rc1'
from collections import namedtuple from collections import namedtuple
# imports: # imports:
VersionInfo = namedtuple('VersionInfo', 'major minor micro') VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='2022', minor='6', micro='3.dev2') version_info = VersionInfo(major='2022', minor='6', micro='0.rc1')

View File

@@ -15,11 +15,11 @@ __title__ = 'cpl_cli._templates.build'
__author__ = 'Sven Heidemann' __author__ = 'Sven Heidemann'
__license__ = 'MIT' __license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de'
__version__ = '2022.6.3.dev2' __version__ = '2022.6.0rc1'
from collections import namedtuple from collections import namedtuple
# imports: # imports:
VersionInfo = namedtuple('VersionInfo', 'major minor micro') VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='2022', minor='6', micro='3.dev2') version_info = VersionInfo(major='2022', minor='6', micro='0.rc1')

View File

@@ -15,11 +15,11 @@ __title__ = 'cpl_cli._templates.generate'
__author__ = 'Sven Heidemann' __author__ = 'Sven Heidemann'
__license__ = 'MIT' __license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de'
__version__ = '2022.6.3.dev2' __version__ = '2022.6.0rc1'
from collections import namedtuple from collections import namedtuple
# imports: # imports:
VersionInfo = namedtuple('VersionInfo', 'major minor micro') VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='2022', minor='6', micro='3.dev2') version_info = VersionInfo(major='2022', minor='6', micro='0.rc1')

View File

@@ -0,0 +1,40 @@
import textwrap
from string import Template
from cpl_core.utils.string import String
from cpl_cli._templates.template_file_abc import TemplateFileABC
class PipeTemplate(TemplateFileABC):
def __init__(self, name: str, schematic: str, schematic_upper: str, path: str):
TemplateFileABC.__init__(self)
self._name = f'{String.convert_to_snake_case(name)}_{schematic}.py'
self._class_name = f'{String.first_to_upper(name)}{schematic_upper}'
self._path = path
self._value = textwrap.dedent("""\
from cpl_core.pipes.pipe_abc import PipeABC
class $Name(PipeABC):
def __init__(self): pass
def transform(self, value: any, *args):
return value
""")
@property
def name(self) -> str:
return self._name
@property
def path(self) -> str:
return self._path
@property
def value(self) -> str:
return Template(self._value).substitute(
Name=self._class_name
)

View File

@@ -0,0 +1,41 @@
import textwrap
from string import Template
from cpl_core.utils.string import String
from cpl_cli._templates.template_file_abc import TemplateFileABC
class TestCaseTemplate(TemplateFileABC):
def __init__(self, name: str, schematic: str, schematic_upper: str, path: str):
TemplateFileABC.__init__(self)
self._name = f'{String.convert_to_snake_case(name)}_{schematic}.py'
self._class_name = f'{String.first_to_upper(name)}{schematic_upper}'
self._path = path
self._value = textwrap.dedent("""\
import unittest
class $Name(unittest.TestCase):
def setUp(self):
pass
def test_equal(self):
pass
""")
@property
def name(self) -> str:
return self._name
@property
def path(self) -> str:
return self._path
@property
def value(self) -> str:
return Template(self._value).substitute(
Name=self._class_name
)

View File

@@ -0,0 +1,41 @@
import textwrap
from string import Template
from cpl_core.utils.string import String
from cpl_cli._templates.template_file_abc import TemplateFileABC
class ValidatorTemplate(TemplateFileABC):
def __init__(self, name: str, schematic: str, schematic_upper: str, path: str):
TemplateFileABC.__init__(self)
self._name = f'{String.convert_to_snake_case(name)}_{schematic}.py'
self._class_name = f'{String.first_to_upper(name)}{schematic_upper}'
self._path = path
self._value = textwrap.dedent("""\
from cpl_core.configuration.validator_abc import ValidatorABC
class $Name(ValidatorABC):
def __init__(self):
ValidatorABC.__init__(self)
def validate(self) -> bool:
return True
""")
@property
def name(self) -> str:
return self._name
@property
def path(self) -> str:
return self._path
@property
def value(self) -> str:
return Template(self._value).substitute(
Name=self._class_name
)

View File

@@ -15,11 +15,11 @@ __title__ = 'cpl_cli._templates.new'
__author__ = 'Sven Heidemann' __author__ = 'Sven Heidemann'
__license__ = 'MIT' __license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de'
__version__ = '2022.6.3.dev2' __version__ = '2022.6.0rc1'
from collections import namedtuple from collections import namedtuple
# imports: # imports:
VersionInfo = namedtuple('VersionInfo', 'major minor micro') VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='2022', minor='6', micro='3.dev2') version_info = VersionInfo(major='2022', minor='6', micro='0.rc1')

View File

@@ -15,11 +15,11 @@ __title__ = 'cpl_cli._templates.new.console'
__author__ = 'Sven Heidemann' __author__ = 'Sven Heidemann'
__license__ = 'MIT' __license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de'
__version__ = '2022.6.3.dev2' __version__ = '2022.6.0rc1'
from collections import namedtuple from collections import namedtuple
# imports: # imports:
VersionInfo = namedtuple('VersionInfo', 'major minor micro') VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='2022', minor='6', micro='3.dev2') version_info = VersionInfo(major='2022', minor='6', micro='0.rc1')

View File

@@ -15,11 +15,11 @@ __title__ = 'cpl_cli._templates.new.console.source'
__author__ = 'Sven Heidemann' __author__ = 'Sven Heidemann'
__license__ = 'MIT' __license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de'
__version__ = '2022.6.3.dev2' __version__ = '2022.6.0rc1'
from collections import namedtuple from collections import namedtuple
# imports: # imports:
VersionInfo = namedtuple('VersionInfo', 'major minor micro') VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='2022', minor='6', micro='3.dev2') version_info = VersionInfo(major='2022', minor='6', micro='0.rc1')

View File

@@ -15,11 +15,11 @@ __title__ = 'cpl_cli._templates.new.console.source.name'
__author__ = 'Sven Heidemann' __author__ = 'Sven Heidemann'
__license__ = 'MIT' __license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de'
__version__ = '2022.6.3.dev2' __version__ = '2022.6.0rc1'
from collections import namedtuple from collections import namedtuple
# imports: # imports:
VersionInfo = namedtuple('VersionInfo', 'major minor micro') VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='2022', minor='6', micro='3.dev2') version_info = VersionInfo(major='2022', minor='6', micro='0.rc1')

View File

@@ -15,11 +15,11 @@ __title__ = 'cpl_cli._templates.new.console.source.tests'
__author__ = 'Sven Heidemann' __author__ = 'Sven Heidemann'
__license__ = 'MIT' __license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de'
__version__ = '2022.6.3.dev2' __version__ = '2022.6.0rc1'
from collections import namedtuple from collections import namedtuple
# imports: # imports:
VersionInfo = namedtuple('VersionInfo', 'major minor micro') VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='2022', minor='6', micro='3.dev2') version_info = VersionInfo(major='2022', minor='6', micro='0.rc1')

View File

@@ -15,11 +15,11 @@ __title__ = 'cpl_cli._templates.new.library'
__author__ = 'Sven Heidemann' __author__ = 'Sven Heidemann'
__license__ = 'MIT' __license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de'
__version__ = '2022.6.3.dev2' __version__ = '2022.6.0rc1'
from collections import namedtuple from collections import namedtuple
# imports: # imports:
VersionInfo = namedtuple('VersionInfo', 'major minor micro') VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='2022', minor='6', micro='3.dev2') version_info = VersionInfo(major='2022', minor='6', micro='0.rc1')

View File

@@ -15,11 +15,11 @@ __title__ = 'cpl_cli._templates.new.library.source'
__author__ = 'Sven Heidemann' __author__ = 'Sven Heidemann'
__license__ = 'MIT' __license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de'
__version__ = '2022.6.3.dev2' __version__ = '2022.6.0rc1'
from collections import namedtuple from collections import namedtuple
# imports: # imports:
VersionInfo = namedtuple('VersionInfo', 'major minor micro') VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='2022', minor='6', micro='3.dev2') version_info = VersionInfo(major='2022', minor='6', micro='0.rc1')

View File

@@ -15,11 +15,11 @@ __title__ = 'cpl_cli._templates.new.library.source.name'
__author__ = 'Sven Heidemann' __author__ = 'Sven Heidemann'
__license__ = 'MIT' __license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de'
__version__ = '2022.6.3.dev2' __version__ = '2022.6.0rc1'
from collections import namedtuple from collections import namedtuple
# imports: # imports:
VersionInfo = namedtuple('VersionInfo', 'major minor micro') VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='2022', minor='6', micro='3.dev2') version_info = VersionInfo(major='2022', minor='6', micro='0.rc1')

View File

@@ -15,11 +15,11 @@ __title__ = 'cpl_cli._templates.new.library.source.tests'
__author__ = 'Sven Heidemann' __author__ = 'Sven Heidemann'
__license__ = 'MIT' __license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de'
__version__ = '2022.6.3.dev2' __version__ = '2022.6.0rc1'
from collections import namedtuple from collections import namedtuple
# imports: # imports:
VersionInfo = namedtuple('VersionInfo', 'major minor micro') VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='2022', minor='6', micro='3.dev2') version_info = VersionInfo(major='2022', minor='6', micro='0.rc1')

View File

@@ -0,0 +1,25 @@
# -*- coding: utf-8 -*-
"""
cpl-cli sh-edraft Common Python library CLI
~~~~~~~~~~~~~~~~~~~
sh-edraft Common Python library Command Line Interface
:copyright: (c) 2020 - 2022 sh-edraft.de
:license: MIT, see LICENSE for more details.
"""
__title__ = 'cpl_cli._templates.new.unittest'
__author__ = 'Sven Heidemann'
__license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de'
__version__ = '2022.6.0rc1'
from collections import namedtuple
# imports:
VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='2022', minor='6', micro='0.rc1')

View File

@@ -0,0 +1,23 @@
from cpl_cli._templates.template_file_abc import TemplateFileABC
class LicenseTemplate(TemplateFileABC):
def __init__(self):
TemplateFileABC.__init__(self)
self._name = 'LICENSE'
self._path = ''
self._value = """"""
@property
def name(self) -> str:
return self._name
@property
def path(self) -> str:
return self._path
@property
def value(self) -> str:
return self._value

View File

@@ -0,0 +1,23 @@
from cpl_cli._templates.template_file_abc import TemplateFileABC
class ReadmeTemplate(TemplateFileABC):
def __init__(self):
TemplateFileABC.__init__(self)
self._name = 'README.md'
self._path = ''
self._value = """"""
@property
def name(self) -> str:
return self._name
@property
def path(self) -> str:
return self._path
@property
def value(self) -> str:
return self._value

View File

@@ -0,0 +1,25 @@
# -*- coding: utf-8 -*-
"""
cpl-cli sh-edraft Common Python library CLI
~~~~~~~~~~~~~~~~~~~
sh-edraft Common Python library Command Line Interface
:copyright: (c) 2020 - 2022 sh-edraft.de
:license: MIT, see LICENSE for more details.
"""
__title__ = 'cpl_cli._templates.new.unittest.source'
__author__ = 'Sven Heidemann'
__license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de'
__version__ = '2022.6.0rc1'
from collections import namedtuple
# imports:
VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='2022', minor='6', micro='0.rc1')

View File

@@ -0,0 +1,25 @@
# -*- coding: utf-8 -*-
"""
cpl-cli sh-edraft Common Python library CLI
~~~~~~~~~~~~~~~~~~~
sh-edraft Common Python library Command Line Interface
:copyright: (c) 2020 - 2022 sh-edraft.de
:license: MIT, see LICENSE for more details.
"""
__title__ = 'cpl_cli._templates.new.unittest.source.name'
__author__ = 'Sven Heidemann'
__license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de'
__version__ = '2022.6.0rc1'
from collections import namedtuple
# imports:
VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='2022', minor='6', micro='0.rc1')

View File

@@ -0,0 +1,74 @@
import textwrap
from cpl_cli._templates.template_file_abc import TemplateFileABC
class ApplicationTemplate(TemplateFileABC):
def __init__(self, name: str, path: str, use_async: bool):
TemplateFileABC.__init__(self)
self._name = 'application.py'
self._path = path
self._use_async = use_async
if self._use_async:
self._value = textwrap.dedent("""\
import unittest
from unittest import TestSuite
from cpl_core.application import ApplicationABC
from cpl_core.configuration import ConfigurationABC
from cpl_core.dependency_injection import ServiceProviderABC
from unittests.test_case import TestCase
class Application(ApplicationABC):
def __init__(self, config: ConfigurationABC, services: ServiceProviderABC):
ApplicationABC.__init__(self, config, services)
self._suite: TestSuite = unittest.TestSuite()
async def configure(self):
self._suite.addTest(TestCase('test_equal'))
async def main(self):
runner = unittest.TextTestRunner()
runner.run(self._suite)
""")
else:
self._value = textwrap.dedent("""\
import unittest
from unittest import TestSuite
from cpl_core.application import ApplicationABC
from cpl_core.configuration import ConfigurationABC
from cpl_core.dependency_injection import ServiceProviderABC
from unittests.test_case import TestCase
class Application(ApplicationABC):
def __init__(self, config: ConfigurationABC, services: ServiceProviderABC):
ApplicationABC.__init__(self, config, services)
self._suite: TestSuite = unittest.TestSuite()
def configure(self):
self._suite.addTest(TestCase('test_equal'))
def main(self):
runner = unittest.TextTestRunner()
runner.run(self._suite)
""")
@property
def name(self) -> str:
return self._name
@property
def path(self) -> str:
return self._path
@property
def value(self) -> str:
return self._value

View File

@@ -0,0 +1,27 @@
import textwrap
from cpl_cli._templates.template_file_abc import TemplateFileABC
class MainInitTemplate(TemplateFileABC):
def __init__(self, name: str, path: str):
TemplateFileABC.__init__(self)
self._name = '__init__.py'
self._path = path
self._value = textwrap.dedent("""\
# imports:
""")
@property
def name(self) -> str:
return self._name
@property
def path(self) -> str:
return self._path
@property
def value(self) -> str:
return self._value

View File

@@ -0,0 +1,63 @@
import textwrap
from cpl_core.utils.string import String
from cpl_cli._templates.template_file_abc import TemplateFileABC
class MainWithApplicationBaseTemplate(TemplateFileABC):
def __init__(self, name: str, path: str, use_async: bool):
TemplateFileABC.__init__(self)
name = String.convert_to_snake_case(name)
self._name = 'main.py'
self._path = path
import_pkg = f'{name}.'
if use_async:
self._value = textwrap.dedent(f"""\
import asyncio
from cpl_core.application import ApplicationBuilder
from {import_pkg}application import Application
async def main():
app_builder = ApplicationBuilder(Application)
app: Application = await app_builder.build_async()
await app.run_async()
if __name__ == '__main__':
ml = asyncio.get_event_loop()
ml.run_until_complete(main())
""")
else:
self._value = textwrap.dedent(f"""\
from cpl_core.application import ApplicationBuilder
from {import_pkg}application import Application
def main():
app_builder = ApplicationBuilder(Application)
app_builder.build().run()
if __name__ == '__main__':
main()
""")
@property
def name(self) -> str:
return self._name
@property
def path(self) -> str:
return self._path
@property
def value(self) -> str:
return self._value

View File

@@ -0,0 +1,52 @@
import textwrap
from cpl_cli._templates.template_file_abc import TemplateFileABC
class TestCaseTemplate(TemplateFileABC):
def __init__(self, name: str, path: str, use_async: bool):
TemplateFileABC.__init__(self)
self._name = 'test_case.py'
self._path = path
self._use_async = use_async
if self._use_async:
self._value = textwrap.dedent("""\
import unittest
class TestCase(unittest.TestCase):
async def setUp(self) -> None:
pass
async def test_equal(self):
self.assertEqual(True, True)
""")
else:
self._value = textwrap.dedent("""\
import unittest
class TestCase(unittest.TestCase):
def setUp(self) -> None:
pass
def test_equal(self):
self.assertEqual(True, True)
""")
@property
def name(self) -> str:
return self._name
@property
def path(self) -> str:
return self._path
@property
def value(self) -> str:
return self._value

View File

@@ -15,11 +15,11 @@ __title__ = 'cpl_cli._templates.publish'
__author__ = 'Sven Heidemann' __author__ = 'Sven Heidemann'
__license__ = 'MIT' __license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de'
__version__ = '2022.6.3.dev2' __version__ = '2022.6.0rc1'
from collections import namedtuple from collections import namedtuple
# imports: # imports:
VersionInfo = namedtuple('VersionInfo', 'major minor micro') VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='2022', minor='6', micro='3.dev2') version_info = VersionInfo(major='2022', minor='6', micro='0.rc1')

View File

@@ -1,5 +1,5 @@
{ {
"CLI": { "CLI": {
"PipPath": "https://pip.sh-edraft.de" "PipPath": "https://pip-exp.sh-edraft.de"
} }
} }

View File

@@ -1,28 +1,11 @@
import os
import sys import sys
from typing import Optional import traceback
from cpl_cli.error import Error
from cpl_core.application.application_abc import ApplicationABC from cpl_core.application.application_abc import ApplicationABC
from cpl_core.configuration.configuration_abc import ConfigurationABC from cpl_core.configuration.configuration_abc import ConfigurationABC
from cpl_core.console.console import Console from cpl_core.console.console import Console
from cpl_core.dependency_injection import ServiceProviderABC from cpl_core.dependency_injection.service_provider_abc import ServiceProviderABC
from cpl_cli.command.add_service import AddService
from cpl_cli.command.build_service import BuildService
from cpl_cli.command.custom_script_service import CustomScriptService
from cpl_cli.command.generate_service import GenerateService
from cpl_cli.command.install_service import InstallService
from cpl_cli.command.new_service import NewService
from cpl_cli.command.publish_service import PublishService
from cpl_cli.command.remove_service import RemoveService
from cpl_cli.command.start_service import StartService
from cpl_cli.command.uninstall_service import UninstallService
from cpl_cli.command.update_service import UpdateService
from cpl_cli.command_handler_service import CommandHandler
from cpl_cli.command_model import CommandModel
from cpl_cli.configuration.workspace_settings import WorkspaceSettings
from cpl_cli.error import Error
from cpl_cli.command.help_service import HelpService
from cpl_cli.command.version_service import VersionService
class CLI(ApplicationABC): class CLI(ApplicationABC):
@@ -33,33 +16,10 @@ class CLI(ApplicationABC):
""" """
ApplicationABC.__init__(self, config, services) ApplicationABC.__init__(self, config, services)
# self._command_handler: Optional[CommandHandler] = None
self._options: list[str] = [] self._options: list[str] = []
def configure(self): def configure(self):
pass pass
# self._command_handler: CommandHandler = self._services.get_service(CommandHandler)
#
# self._command_handler.add_command(CommandModel('add', ['a', 'a'], AddService, False, False, False))
# self._command_handler.add_command(CommandModel('build', ['b', 'B'], BuildService, False, True, True))
# self._command_handler.add_command(CommandModel('generate', ['g', 'G'], GenerateService, False, True, False))
# self._command_handler.add_command(CommandModel('help', ['h', 'H'], HelpService, False, False, False))
# self._command_handler.add_command(CommandModel('install', ['i', 'I'], InstallService, False, True, True))
# self._command_handler.add_command(CommandModel('new', ['n', 'N'], NewService, False, False, True))
# self._command_handler.add_command(CommandModel('publish', ['p', 'P'], PublishService, False, True, True))
# self._command_handler.add_command(CommandModel('remove', ['r', 'R'], RemoveService, True, True, False))
# self._command_handler.add_command(CommandModel('start', ['s', 'S'], StartService, False, True, True))
# self._command_handler.add_command(CommandModel('uninstall', ['ui', 'UI'], UninstallService, False, True, True))
# self._command_handler.add_command(CommandModel('update', ['u', 'U'], UpdateService, False, True, True))
# self._command_handler.add_command(CommandModel('version', ['v', 'V'], VersionService, False, False, False))
#
# if os.path.isfile(os.path.join(self._environment.working_directory, 'cpl-workspace.json')):
# workspace: Optional[WorkspaceSettings] = self._configuration.get_configuration(WorkspaceSettings)
# for script in workspace.scripts:
# self._command_handler.add_command(CommandModel(script, [], CustomScriptService, True, True, False))
#
# self._command_handler.add_command(CommandModel('--help', ['-h', '-H'], HelpService, False, False, False))
# self._options.append('--help')
def main(self): def main(self):
""" """
@@ -67,62 +27,21 @@ class CLI(ApplicationABC):
:return: :return:
""" """
try: try:
pass result = self._configuration.parse_console_arguments(self._services)
# command = None if result:
# args = [] Console.write_line()
# if len(self._configuration.additional_arguments) > 0: return
# is_option = False
# for opt in self._options: if len(self._configuration.additional_arguments) == 0:
# if opt in self._configuration.additional_arguments: Error.error('Expected command')
# is_option = True return
# command = opt
# args = self._configuration.additional_arguments unexpected_arguments = ', '.join(self._configuration.additional_arguments)
# args.remove(opt) Error.error(f'Unexpected argument(s): {unexpected_arguments}')
# Console.write_line()
# if not is_option:
# command = self._configuration.additional_arguments[0]
# if len(self._configuration.additional_arguments) > 1:
# args = self._configuration.additional_arguments[1:]
# else:
# for cmd in self._command_handler.commands:
# result = self._configuration.get_configuration(cmd.name)
# result_args: list[str] = self._configuration.get_configuration(f'{cmd.name}AdditionalArguments')
# is_option = False
# if result is None:
# continue
#
# for opt in self._options:
# if opt == result:
# is_option = True
# command = opt
#
# elif result_args is not None and opt in result_args:
# is_option = True
# command = opt
# result_args.remove(opt)
#
# if is_option:
# args.append(cmd.name)
# if result_args is not None:
# for arg in result_args:
# args.append(arg)
#
# elif result is not None:
# command = cmd.name
# args.append(result)
#
# for arg in result_args:
# args.append(arg)
#
# else:
# Error.error(f'Unexpected command')
# return
#
# if command is None:
# Error.error(f'Expected command')
# return
#
# self._command_handler.handle(command, args)
except KeyboardInterrupt: except KeyboardInterrupt:
Console.write_line() Console.write_line()
sys.exit() sys.exit()
except Exception as e:
Console.error(str(e), traceback.format_exc())
sys.exit()

View File

@@ -15,7 +15,7 @@ __title__ = 'cpl_cli.command'
__author__ = 'Sven Heidemann' __author__ = 'Sven Heidemann'
__license__ = 'MIT' __license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de'
__version__ = '2022.6.3.dev2' __version__ = '2022.6.0rc1'
from collections import namedtuple from collections import namedtuple
@@ -28,4 +28,4 @@ from .publish_service import PublishService
from .version_service import VersionService from .version_service import VersionService
VersionInfo = namedtuple('VersionInfo', 'major minor micro') VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='2022', minor='6', micro='3.dev2') version_info = VersionInfo(major='2022', minor='6', micro='0.rc1')

View File

@@ -23,6 +23,7 @@ class AddService(CommandABC):
self._config = config self._config = config
self._workspace = workspace self._workspace = workspace
self._is_simulation = False
@property @property
def help_message(self) -> str: def help_message(self) -> str:
@@ -35,8 +36,9 @@ class AddService(CommandABC):
target-project: Name of the project to be referenced target-project: Name of the project to be referenced
""") """)
@staticmethod def _edit_project_file(self, source: str, project_settings: ProjectSettings, build_settings: BuildSettings):
def _edit_project_file(source: str, project_settings: ProjectSettings, build_settings: BuildSettings): if self._is_simulation:
return
with open(source, 'w') as file: with open(source, 'w') as file:
file.write(json.dumps({ file.write(json.dumps({
ProjectSettings.__name__: SettingsHelper.get_project_settings_dict(project_settings), ProjectSettings.__name__: SettingsHelper.get_project_settings_dict(project_settings),
@@ -44,12 +46,17 @@ class AddService(CommandABC):
}, indent=2)) }, indent=2))
file.close() file.close()
def run(self, args: list[str]): def execute(self, args: list[str]):
""" """
Entry point of command Entry point of command
:param args: :param args:
:return: :return:
""" """
if 'simulate' in args:
args.remove('simulate')
Console.write_line('Running in simulation mode:')
self._is_simulation = True
if len(args) == 0: if len(args) == 0:
Console.error('Expected source and target project') Console.error('Expected source and target project')
return return
@@ -59,7 +66,7 @@ class AddService(CommandABC):
return return
elif len(args) > 2: elif len(args) > 2:
Console.error(f'Unexpected argument: {" ".join(args[2:])}') Console.error(f'Unexpected argument(s): {", ".join(args[2:])}')
return return
# file names # file names

View File

@@ -22,7 +22,7 @@ class BuildService(CommandABC):
Usage: cpl build Usage: cpl build
""") """)
def run(self, args: list[str]): def execute(self, args: list[str]):
""" """
Entry point of command Entry point of command
:param args: :param args:

View File

@@ -1,6 +1,7 @@
import os import os
import subprocess import subprocess
import sys
from cpl_core.environment import ApplicationEnvironmentABC
from cpl_core.configuration.configuration_abc import ConfigurationABC from cpl_core.configuration.configuration_abc import ConfigurationABC
from cpl_core.console.console import Console from cpl_core.console.console import Console
@@ -10,26 +11,40 @@ from cpl_cli.configuration.workspace_settings import WorkspaceSettings
class CustomScriptService(CommandABC): class CustomScriptService(CommandABC):
def __init__(self, config: ConfigurationABC, ws: WorkspaceSettings): def __init__(self, config: ConfigurationABC, env: ApplicationEnvironmentABC, ws: WorkspaceSettings):
""" """
Service for CLI scripts Service for CLI scripts
""" """
CommandABC.__init__(self) CommandABC.__init__(self)
self._config = config self._config = config
self._env = env
self._workspace = ws self._workspace = ws
@property @property
def help_message(self) -> str: def help_message(self) -> str:
return '' return ''
def run(self, args: list[str]): def execute(self, args: list[str]):
cmd = args[0] if len(args) > 0 else self._config.additional_arguments[0] cmd = self._config.get_configuration('ACTIVE_EXECUTABLE')
wd = self._config.get_configuration('PATH_WORKSPACE')
if wd is not None:
self._env.set_working_directory(wd)
for script in self._workspace.scripts: for script in self._workspace.scripts:
if script == cmd: if script != cmd:
command = self._workspace.scripts[script] continue
try:
subprocess.run(command, shell=True if os.name == 'posix' else None) command = ''
except Exception as e: external_args = self._config.get_configuration('ARGS')
Console.error(str(e)) if external_args is not None:
command += f'ARGS="{external_args}";'
command += self._workspace.scripts[script]
env_vars = os.environ
env_vars['CPL_ARGS'] = " ".join(args)
try:
subprocess.run(command, shell=True if os.name == 'posix' else None)
except Exception as e:
Console.error(str(e))

View File

@@ -2,19 +2,22 @@ import os
import sys import sys
import textwrap import textwrap
from cpl_core.configuration.configuration_abc import ConfigurationABC
from cpl_core.console.foreground_color_enum import ForegroundColorEnum
from cpl_core.console.console import Console
from cpl_core.utils.string import String
from cpl_cli.command_abc import CommandABC
from cpl_cli._templates.generate.init_template import InitTemplate
from cpl_cli._templates.generate.abc_template import ABCTemplate from cpl_cli._templates.generate.abc_template import ABCTemplate
from cpl_cli._templates.generate.class_template import ClassTemplate from cpl_cli._templates.generate.class_template import ClassTemplate
from cpl_cli._templates.generate.configmodel_template import ConfigModelTemplate from cpl_cli._templates.generate.configmodel_template import ConfigModelTemplate
from cpl_cli._templates.generate.enum_template import EnumTemplate from cpl_cli._templates.generate.enum_template import EnumTemplate
from cpl_cli._templates.generate.init_template import InitTemplate
from cpl_cli._templates.generate.pipe_template import PipeTemplate
from cpl_cli._templates.generate.service_template import ServiceTemplate from cpl_cli._templates.generate.service_template import ServiceTemplate
from cpl_cli._templates.generate.test_case_template import TestCaseTemplate
from cpl_cli._templates.generate.thread_template import ThreadTemplate from cpl_cli._templates.generate.thread_template import ThreadTemplate
from cpl_cli._templates.generate.validator_template import ValidatorTemplate
from cpl_cli._templates.template_file_abc import TemplateFileABC from cpl_cli._templates.template_file_abc import TemplateFileABC
from cpl_cli.command_abc import CommandABC
from cpl_core.configuration.configuration_abc import ConfigurationABC
from cpl_core.console.console import Console
from cpl_core.console.foreground_color_enum import ForegroundColorEnum
from cpl_core.utils.string import String
class GenerateService(CommandABC): class GenerateService(CommandABC):
@@ -32,13 +35,17 @@ class GenerateService(CommandABC):
"Template": ABCTemplate "Template": ABCTemplate
}, },
"class": { "class": {
"Upper": "", "Upper": "Class",
"Template": ClassTemplate "Template": ClassTemplate
}, },
"enum": { "enum": {
"Upper": "Enum", "Upper": "Enum",
"Template": EnumTemplate "Template": EnumTemplate
}, },
"pipe": {
"Upper": "Pipe",
"Template": PipeTemplate
},
"service": { "service": {
"Upper": "Service", "Upper": "Service",
"Template": ServiceTemplate "Template": ServiceTemplate
@@ -47,9 +54,17 @@ class GenerateService(CommandABC):
"Upper": "Settings", "Upper": "Settings",
"Template": ConfigModelTemplate "Template": ConfigModelTemplate
}, },
"test_case": {
"Upper": "TestCase",
"Template": TestCaseTemplate
},
"thread": { "thread": {
"Upper": "Thread", "Upper": "Thread",
"Template": ThreadTemplate "Template": ThreadTemplate
},
"validator": {
"Upper": "Validator",
"Template": ValidatorTemplate
} }
} }
@@ -70,9 +85,12 @@ class GenerateService(CommandABC):
abc abc
class class
enum enum
pipe
service service
settings settings
test_case
thread thread
validator
""") """)
@staticmethod @staticmethod
@@ -88,8 +106,12 @@ class GenerateService(CommandABC):
'abc (a|A)', 'abc (a|A)',
'class (c|C)', 'class (c|C)',
'enum (e|E)', 'enum (e|E)',
'pipe (p|P)',
'service (s|S)', 'service (s|S)',
'settings (st|ST)' 'settings (st|ST)',
'test-case (tc|TC)',
'thread (t|T)',
'validator (v|V)'
] ]
Console.write_line('Available Schematics:') Console.write_line('Available Schematics:')
for name in schematics: for name in schematics:
@@ -122,7 +144,7 @@ class GenerateService(CommandABC):
rel_path = '/'.join(parts[:-1]) rel_path = '/'.join(parts[:-1])
class_name = parts[len(parts) - 1] class_name = parts[len(parts) - 1]
if 'src' not in rel_path: if 'src' not in rel_path and not os.path.exists(os.path.join(self._env.working_directory, rel_path)):
rel_path = f'src/{rel_path}' rel_path = f'src/{rel_path}'
template = template(class_name, schematic, self._schematics[schematic]["Upper"], rel_path) template = template(class_name, schematic, self._schematics[schematic]["Upper"], rel_path)
@@ -145,7 +167,7 @@ class GenerateService(CommandABC):
) )
if os.path.isfile(file_path): if os.path.isfile(file_path):
Console.error(f'{String.first_to_upper(schematic)} already exists!') Console.error(f'{String.first_to_upper(schematic)} already exists!\n')
sys.exit() sys.exit()
message = f'Creating {self._env.working_directory}/{template.path}/{template.name}' message = f'Creating {self._env.working_directory}/{template.path}/{template.name}'
@@ -161,18 +183,26 @@ class GenerateService(CommandABC):
spinner_foreground_color=ForegroundColorEnum.cyan spinner_foreground_color=ForegroundColorEnum.cyan
) )
def run(self, args: list[str]): def execute(self, args: list[str]):
""" """
Entry point of command Entry point of command
:param args: :param args:
:return: :return:
""" """
if len(args) == 0: schematic = None
value = None
for s in self._schematics:
value = self._config.get_configuration(s)
if value is not None:
schematic = s
break
if schematic is None:
self._help('Usage: cpl generate <schematic> [options]') self._help('Usage: cpl generate <schematic> [options]')
Console.write_line()
sys.exit() sys.exit()
schematic = args[0] name = value
name = self._config.get_configuration(schematic)
if name is None: if name is None:
name = Console.read(f'Name for the {args[0]}: ') name = Console.read(f'Name for the {args[0]}: ')
@@ -182,4 +212,5 @@ class GenerateService(CommandABC):
else: else:
self._help('Usage: cpl generate <schematic> [options]') self._help('Usage: cpl generate <schematic> [options]')
Console.write_line()
sys.exit() sys.exit()

View File

@@ -1,54 +1,38 @@
import sys
import textwrap import textwrap
from typing import Optional
from cpl_core.console.console import Console from cpl_core.console.console import Console
from cpl_core.console.foreground_color_enum import ForegroundColorEnum from cpl_core.console.foreground_color_enum import ForegroundColorEnum
from cpl_core.dependency_injection.service_provider_abc import ServiceProviderABC from cpl_core.dependency_injection.service_provider_abc import ServiceProviderABC
from cpl_cli.command_handler_service import CommandHandler
from cpl_cli.command_abc import CommandABC from cpl_cli.command_abc import CommandABC
class HelpService(CommandABC): class HelpService(CommandABC):
def __init__(self, services: ServiceProviderABC, cmd_handler: CommandHandler): def __init__(self, services: ServiceProviderABC):
""" """
Service for CLI command help Service for CLI command help
""" """
CommandABC.__init__(self) CommandABC.__init__(self)
self._services = services self._services = services
self._commands = cmd_handler.commands
@property @property
def help_message(self) -> str: def help_message(self) -> str:
return textwrap.dedent("""\ return textwrap.dedent("""\
Lists available command and their short descriptions. Lists available command and their short descriptions.
Usage: cpl help <command> Usage: cpl help
Arguments:
command The command to display the help message for
""") """)
def run(self, args: list[str]): def execute(self, args: list[str]):
""" """
Entry point of command Entry point of command
:param args: :param args:
:return: :return:
""" """
if len(args) > 0: if len(args) > 0:
command_name = args[0] Console.error(f'Unexpected argument(s): {", ".join(args)}')
command: Optional[CommandABC] = None sys.exit()
for cmd in self._commands:
if cmd.name == command_name or command_name in cmd.aliases:
command = self._services.get_service(cmd.command)
if command is None:
Console.error(f'Invalid argument: {command_name}')
return
Console.write_line(command.help_message)
return
Console.write_line('Available Commands:') Console.write_line('Available Commands:')
commands = [ commands = [
@@ -70,3 +54,4 @@ class HelpService(CommandABC):
Console.write(f'\n\t{name} ') Console.write(f'\n\t{name} ')
Console.set_foreground_color(ForegroundColorEnum.default) Console.set_foreground_color(ForegroundColorEnum.default)
Console.write(f'{description}') Console.write(f'{description}')
Console.write_line('\nRun \'cpl <command> --help\' for command specific information\'s\n')

View File

@@ -4,19 +4,20 @@ import subprocess
import textwrap import textwrap
import time import time
from packaging import version
from cpl_cli.cli_settings import CLISettings from cpl_cli.cli_settings import CLISettings
from cpl_cli.command_abc import CommandABC from cpl_cli.command_abc import CommandABC
from cpl_cli.configuration.build_settings import BuildSettings from cpl_cli.configuration.build_settings import BuildSettings
from cpl_cli.configuration.project_settings import ProjectSettings from cpl_cli.configuration.project_settings import ProjectSettings
from cpl_cli.configuration.settings_helper import SettingsHelper from cpl_cli.configuration.settings_helper import SettingsHelper
from cpl_cli.configuration.venv_helper_service import VenvHelper
from cpl_cli.error import Error from cpl_cli.error import Error
from cpl_core.configuration.configuration_abc import ConfigurationABC from cpl_core.configuration.configuration_abc import ConfigurationABC
from cpl_core.console.console import Console from cpl_core.console.console import Console
from cpl_core.console.foreground_color_enum import ForegroundColorEnum from cpl_core.console.foreground_color_enum import ForegroundColorEnum
from cpl_core.environment.application_environment_abc import \ from cpl_core.environment.application_environment_abc import ApplicationEnvironmentABC
ApplicationEnvironmentABC
from cpl_core.utils.pip import Pip from cpl_core.utils.pip import Pip
from packaging import version
class InstallService(CommandABC): class InstallService(CommandABC):
@@ -38,11 +39,12 @@ class InstallService(CommandABC):
self._build_settings = build_settings self._build_settings = build_settings
self._project_settings = project_settings self._project_settings = project_settings
self._cli_settings = cli_settings self._cli_settings = cli_settings
self._is_simulating = False
self._is_virtual = False
self._project_file = f'{self._config.get_configuration("ProjectName")}.json' self._is_simulation = False
self._is_virtual = False
self._is_dev = False
self._project_file = f'{self._project_settings.name}.json'
@property @property
def help_message(self) -> str: def help_message(self) -> str:
@@ -53,7 +55,7 @@ class InstallService(CommandABC):
Arguments: Arguments:
package The package to install package The package to install
""") """)
def _wait(self, t: int, *args, source: str = None, stdout=None, stderr=None): def _wait(self, t: int, *args, source: str = None, stdout=None, stderr=None):
time.sleep(t) time.sleep(t)
@@ -62,7 +64,6 @@ class InstallService(CommandABC):
Installs dependencies of CPl project Installs dependencies of CPl project
:return: :return:
""" """
if self._project_settings is None or self._build_settings is None: if self._project_settings is None or self._build_settings is None:
Error.error('The command requires to be run in an CPL project, but a project could not be found.') Error.error('The command requires to be run in an CPL project, but a project could not be found.')
return return
@@ -71,13 +72,22 @@ class InstallService(CommandABC):
Error.error(f'Found invalid dependencies in {self._project_file}.') Error.error(f'Found invalid dependencies in {self._project_file}.')
return return
if not self._is_virtual:
Pip.set_executable(self._project_settings.python_executable)
for dependency in self._project_settings.dependencies: for dependency in self._project_settings.dependencies:
Console.spinner( Console.spinner(
f'Installing: {dependency}', f'Installing: {dependency}',
Pip.install if not self._is_virtual else self._wait, dependency if not self._is_virtual else 2, Pip.install if not self._is_virtual else self._wait, dependency if not self._is_virtual else 2,
source=self._cli_settings.pip_path if 'sh_cpl' in dependency else None, source=self._cli_settings.pip_path if 'cpl-' in dependency else None,
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
text_foreground_color=ForegroundColorEnum.green,
spinner_foreground_color=ForegroundColorEnum.cyan
)
for dependency in self._project_settings.dev_dependencies:
Console.spinner(
f'Installing dev: {dependency}',
Pip.install if not self._is_virtual else self._wait, dependency if not self._is_virtual else 2,
source=self._cli_settings.pip_path if 'cpl-' in dependency else None,
stdout=subprocess.DEVNULL, stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL, stderr=subprocess.DEVNULL,
text_foreground_color=ForegroundColorEnum.green, text_foreground_color=ForegroundColorEnum.green,
@@ -94,9 +104,6 @@ class InstallService(CommandABC):
:return: :return:
""" """
is_already_in_project = False is_already_in_project = False
if not self._is_virtual:
Pip.set_executable(self._project_settings.python_executable)
if self._project_settings is None or self._build_settings is None: if self._project_settings is None or self._build_settings is None:
Error.error('The command requires to be run in an CPL project, but a project could not be found.') Error.error('The command requires to be run in an CPL project, but a project could not be found.')
return return
@@ -112,7 +119,11 @@ class InstallService(CommandABC):
package_version = package.split('==')[1] package_version = package.split('==')[1]
to_remove_list = [] to_remove_list = []
for dependency in self._project_settings.dependencies: deps = self._project_settings.dependencies
if self._is_dev:
deps = self._project_settings.dev_dependencies
for dependency in deps:
dependency_version = '' dependency_version = ''
if '==' in dependency: if '==' in dependency:
@@ -126,7 +137,10 @@ class InstallService(CommandABC):
is_already_in_project = True is_already_in_project = True
for to_remove in to_remove_list: for to_remove in to_remove_list:
self._project_settings.dependencies.remove(to_remove) if self._is_dev:
self._project_settings.dev_dependencies.remove(to_remove)
else:
self._project_settings.dependencies.remove(to_remove)
local_package = Pip.get_package(package) local_package = Pip.get_package(package)
if local_package is not None and local_package in self._project_settings.dependencies: if local_package is not None and local_package in self._project_settings.dependencies:
@@ -138,15 +152,15 @@ class InstallService(CommandABC):
return return
Console.spinner( Console.spinner(
f'Installing: {package}', f'Installing: {package}' if not self._is_dev else f'Installing dev: {package}',
Pip.install if not self._is_virtual else self._wait, package if not self._is_virtual else 2, Pip.install if not self._is_virtual else self._wait, package if not self._is_virtual else 2,
source=self._cli_settings.pip_path if 'sh_cpl' in package else None, source=self._cli_settings.pip_path if 'cpl-' in package or 'cpl_' in package else None,
stdout=subprocess.DEVNULL, stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL, stderr=subprocess.DEVNULL,
text_foreground_color=ForegroundColorEnum.green, text_foreground_color=ForegroundColorEnum.green,
spinner_foreground_color=ForegroundColorEnum.cyan spinner_foreground_color=ForegroundColorEnum.cyan
) )
if self._is_virtual: if self._is_virtual:
new_package = name new_package = name
else: else:
@@ -170,37 +184,49 @@ class InstallService(CommandABC):
if '\r' in new_name: if '\r' in new_name:
new_name = new_name.replace('\r', '') new_name = new_name.replace('\r', '')
self._project_settings.dependencies.append(new_name) if self._is_dev:
self._project_settings.dev_dependencies.append(new_name)
else:
self._project_settings.dependencies.append(new_name)
if not self._is_simulating: if not self._is_simulation:
config = { config = {
ProjectSettings.__name__: SettingsHelper.get_project_settings_dict(self._project_settings), ProjectSettings.__name__: SettingsHelper.get_project_settings_dict(self._project_settings),
BuildSettings.__name__: SettingsHelper.get_build_settings_dict(self._build_settings) BuildSettings.__name__: SettingsHelper.get_build_settings_dict(self._build_settings)
} }
with open(os.path.join(self._env.working_directory, self._project_file), 'w') as project_file: with open(os.path.join(self._env.working_directory, self._project_file), 'w') as project_file:
project_file.write(json.dumps(config, indent=2)) project_file.write(json.dumps(config, indent=2))
project_file.close() project_file.close()
Pip.reset_executable() Pip.reset_executable()
def run(self, args: list[str]): def execute(self, args: list[str]):
""" """
Entry point of command Entry point of command
:param args: :param args:
:return: :return:
""" """
if '--virtual' in args: if 'dev' in args:
self._is_dev = True
args.remove('dev')
if 'virtual' in args:
self._is_virtual = True self._is_virtual = True
args.remove('--virtual') args.remove('virtual')
Console.write_line('Running in virtual mode:') Console.write_line('Running in virtual mode:')
if '--simulate' in args: if 'simulate' in args:
self._is_virtual = True self._is_simulation = True
args.remove('--simulate') args.remove('simulate')
Console.write_line('Running in simulation mode:') Console.write_line('Running in simulation mode:')
VenvHelper.init_venv(self._is_virtual, self._env, self._project_settings)
if len(args) == 0: if len(args) == 0:
self._install_project() self._install_project()
else: else:
self._install_package(args[0]) self._install_package(args[0])
if not self._is_virtual:
Pip.reset_executable()

View File

@@ -5,7 +5,10 @@ from typing import Optional
from packaging import version from packaging import version
import cpl_cli
import cpl_core import cpl_core
from cpl_cli.configuration.venv_helper_service import VenvHelper
from cpl_cli.source_creator.unittest_builder import UnittestBuilder
from cpl_core.configuration.configuration_abc import ConfigurationABC from cpl_core.configuration.configuration_abc import ConfigurationABC
from cpl_core.console.foreground_color_enum import ForegroundColorEnum from cpl_core.console.foreground_color_enum import ForegroundColorEnum
@@ -35,18 +38,22 @@ class NewService(CommandABC):
self._config = configuration self._config = configuration
self._env = self._config.environment self._env = self._config.environment
self._workspace = self._config.get_configuration(WorkspaceSettings) self._workspace: WorkspaceSettings = self._config.get_configuration(WorkspaceSettings)
self._project: ProjectSettings = ProjectSettings() self._project: ProjectSettings = ProjectSettings()
self._project_dict = {} self._project_dict = {}
self._build: BuildSettings = BuildSettings() self._build: BuildSettings = BuildSettings()
self._build_dict = {} self._build_dict = {}
self._project_json = {} self._project_json = {}
self._command: str = '' self._name: str = ''
self._rel_path: str = ''
self._schematic: ProjectTypeEnum = ProjectTypeEnum.console
self._use_nothing: bool = False
self._use_application_api: bool = False self._use_application_api: bool = False
self._use_startup: bool = False self._use_startup: bool = False
self._use_service_providing: bool = False self._use_service_providing: bool = False
self._use_async: bool = False self._use_async: bool = False
self._use_venv: bool = False
@property @property
def help_message(self) -> str: def help_message(self) -> str:
@@ -80,9 +87,10 @@ class NewService(CommandABC):
for name in schematics: for name in schematics:
Console.write(f'\n\t{name} ') Console.write(f'\n\t{name} ')
def _create_project_settings(self, name: str): def _create_project_settings(self):
self._rel_path = os.path.dirname(self._name)
self._project_dict = { self._project_dict = {
ProjectSettingsNameEnum.name.value: name, ProjectSettingsNameEnum.name.value: os.path.basename(self._name),
ProjectSettingsNameEnum.version.value: { ProjectSettingsNameEnum.version.value: {
VersionSettingsNameEnum.major.value: '0', VersionSettingsNameEnum.major.value: '0',
VersionSettingsNameEnum.minor.value: '0', VersionSettingsNameEnum.minor.value: '0',
@@ -98,11 +106,14 @@ class NewService(CommandABC):
ProjectSettingsNameEnum.license_name.value: '', ProjectSettingsNameEnum.license_name.value: '',
ProjectSettingsNameEnum.license_description.value: '', ProjectSettingsNameEnum.license_description.value: '',
ProjectSettingsNameEnum.dependencies.value: [ ProjectSettingsNameEnum.dependencies.value: [
f'sh_cpl-core>={version.parse(cpl_core.__version__)}' f'cpl-core>={version.parse(cpl_core.__version__)}'
],
ProjectSettingsNameEnum.dev_dependencies.value: [
f'cpl-cli>={version.parse(cpl_cli.__version__)}'
], ],
ProjectSettingsNameEnum.python_version.value: f'>={sys.version.split(" ")[0]}', ProjectSettingsNameEnum.python_version.value: f'>={sys.version.split(" ")[0]}',
ProjectSettingsNameEnum.python_path.value: { ProjectSettingsNameEnum.python_path.value: {
sys.platform: '' sys.platform: '../../venv/bin/python' if self._use_venv else ''
}, },
ProjectSettingsNameEnum.classifiers.value: [] ProjectSettingsNameEnum.classifiers.value: []
} }
@@ -110,15 +121,11 @@ class NewService(CommandABC):
self._project.from_dict(self._project_dict) self._project.from_dict(self._project_dict)
def _create_build_settings(self): def _create_build_settings(self):
main = f'{String.convert_to_snake_case(self._project.name)}.main'
if self._command == ProjectTypeEnum.library.value:
main = f'{String.convert_to_snake_case(self._project.name)}.main'
self._build_dict = { self._build_dict = {
BuildSettingsNameEnum.project_type.value: self._command, BuildSettingsNameEnum.project_type.value: self._schematic,
BuildSettingsNameEnum.source_path.value: '', BuildSettingsNameEnum.source_path.value: '',
BuildSettingsNameEnum.output_path.value: '../../dist', BuildSettingsNameEnum.output_path.value: '../../dist',
BuildSettingsNameEnum.main.value: main, BuildSettingsNameEnum.main.value: f'{String.convert_to_snake_case(self._project.name)}.main',
BuildSettingsNameEnum.entry_point.value: self._project.name, BuildSettingsNameEnum.entry_point.value: self._project.name,
BuildSettingsNameEnum.include_package_data.value: False, BuildSettingsNameEnum.include_package_data.value: False,
BuildSettingsNameEnum.included.value: [], BuildSettingsNameEnum.included.value: [],
@@ -148,40 +155,38 @@ class NewService(CommandABC):
:return: :return:
""" """
if self._workspace is None: if self._workspace is None:
project_path = os.path.join(self._env.working_directory, self._project.name) project_path = os.path.join(self._env.working_directory, self._rel_path, self._project.name)
else: else:
project_path = os.path.join( project_path = os.path.join(self._env.working_directory, 'src', self._rel_path, String.convert_to_snake_case(self._project.name))
self._env.working_directory,
'src',
String.convert_to_snake_case(self._project.name)
)
if os.path.isdir(project_path) and len(os.listdir(project_path)) > 0: if os.path.isdir(project_path) and len(os.listdir(project_path)) > 0:
Console.write_line(project_path)
Console.error('Project path is not empty\n') Console.error('Project path is not empty\n')
return None return None
return project_path return project_path
def _get_project_information(self): def _get_project_information(self, is_unittest=False):
""" """
Gets project information's from user Gets project information's from user
:return: :return:
""" """
result = Console.read('Do you want to use application base? (y/n) ') if self._use_application_api or self._use_startup or self._use_service_providing or self._use_async or self._use_nothing:
if result.lower() == 'y': Console.set_foreground_color(ForegroundColorEnum.default)
self._use_application_api = True Console.write_line('Skipping question due to given flags')
return
result = Console.read('Do you want to use startup? (y/n) ') if not is_unittest:
if result.lower() == 'y': self._use_application_api = Console.read('Do you want to use application base? (y/n) ').lower() == 'y'
self._use_startup = True
else: if not is_unittest and self._use_application_api:
result = Console.read('Do you want to use service providing? (y/n) ') self._use_startup = Console.read('Do you want to use startup? (y/n) ').lower() == 'y'
if result.lower() == 'y':
self._use_service_providing = True if not is_unittest and not self._use_application_api:
self._use_service_providing = Console.read('Do you want to use service providing? (y/n) ').lower() == 'y'
result = Console.read('Do you want to use async? (y/n) ')
if result.lower() == 'y': if not self._use_async:
self._use_async = True self._use_async = Console.read('Do you want to use async? (y/n) ').lower() == 'y'
Console.set_foreground_color(ForegroundColorEnum.default) Console.set_foreground_color(ForegroundColorEnum.default)
@@ -191,9 +196,7 @@ class NewService(CommandABC):
:param args: :param args:
:return: :return:
""" """
name = self._config.get_configuration(self._command) self._create_project_settings()
self._create_project_settings(name)
self._create_build_settings() self._create_build_settings()
self._create_project_json() self._create_project_json()
path = self._get_project_path() path = self._get_project_path()
@@ -201,6 +204,9 @@ class NewService(CommandABC):
return return
self._get_project_information() self._get_project_information()
project_name = self._project.name
if self._rel_path != '':
project_name = f'{self._rel_path}/{project_name}'
try: try:
ConsoleBuilder.build( ConsoleBuilder.build(
path, path,
@@ -208,7 +214,36 @@ class NewService(CommandABC):
self._use_startup, self._use_startup,
self._use_service_providing, self._use_service_providing,
self._use_async, self._use_async,
self._project.name, project_name,
self._project_json,
self._workspace
)
except Exception as e:
Console.error('Could not create project', str(e))
def _unittest(self, args: list[str]):
"""
Generates new unittest project
:param args:
:return:
"""
self._create_project_settings()
self._create_build_settings()
self._create_project_json()
path = self._get_project_path()
if path is None:
return
self._get_project_information(is_unittest=True)
project_name = self._project.name
if self._rel_path != '':
project_name = f'{self._rel_path}/{project_name}'
try:
UnittestBuilder.build(
path,
self._use_application_api,
self._use_async,
project_name,
self._project_json, self._project_json,
self._workspace self._workspace
) )
@@ -221,9 +256,7 @@ class NewService(CommandABC):
:param args: :param args:
:return: :return:
""" """
name = self._config.get_configuration(self._command) self._create_project_settings()
self._create_project_settings(name)
self._create_build_settings() self._create_build_settings()
self._create_project_json() self._create_project_json()
path = self._get_project_path() path = self._get_project_path()
@@ -231,6 +264,9 @@ class NewService(CommandABC):
return return
self._get_project_information() self._get_project_information()
project_name = self._project.name
if self._rel_path != '':
project_name = f'{self._rel_path}/{project_name}'
try: try:
LibraryBuilder.build( LibraryBuilder.build(
path, path,
@@ -238,29 +274,89 @@ class NewService(CommandABC):
self._use_startup, self._use_startup,
self._use_service_providing, self._use_service_providing,
self._use_async, self._use_async,
self._project.name, project_name,
self._project_json, self._project_json,
self._workspace self._workspace
) )
except Exception as e: except Exception as e:
Console.error('Could not create project', str(e)) Console.error('Could not create project', str(e))
def run(self, args: list[str]): def _create_venv(self):
project = self._project.name
if self._workspace is not None:
project = self._workspace.default_project
if self._env.working_directory.endswith(project):
project = ''
VenvHelper.init_venv(
False,
self._env,
self._project,
explicit_path=os.path.join(self._env.working_directory, project, self._project.python_executable.replace('../', ''))
)
def execute(self, args: list[str]):
""" """
Entry point of command Entry point of command
:param args: :param args:
:return: :return:
""" """
if len(args) == 0: if 'nothing' in args:
self._help('Usage: cpl new <schematic> [options]') self._use_nothing = True
return self._use_async = False
self._use_application_api = False
self._use_startup = False
self._use_service_providing = False
if 'async' in args:
args.remove('async')
if 'application-base' in args:
args.remove('application-base')
if 'startup' in args:
args.remove('startup')
if 'service-providing' in args:
args.remove('service-providing')
self._command = str(args[0]).lower() if 'async' in args:
if self._command == ProjectTypeEnum.console.value: self._use_async = True
args.remove('async')
if 'application-base' in args:
self._use_application_api = True
args.remove('application-base')
if 'startup' in args:
self._use_startup = True
args.remove('startup')
if 'service-providing' in args:
self._use_service_providing = True
args.remove('service-providing')
if 'venv' in args:
self._use_venv = True
args.remove('venv')
console = self._config.get_configuration(ProjectTypeEnum.console.value)
library = self._config.get_configuration(ProjectTypeEnum.library.value)
unittest = self._config.get_configuration(ProjectTypeEnum.unittest.value)
if console is not None and library is None and unittest is None:
self._name = console
self._schematic = ProjectTypeEnum.console.value
self._console(args) self._console(args)
if self._use_venv:
self._create_venv()
elif self._command == ProjectTypeEnum.library.value: elif console is None and library is not None and unittest is None:
self._name = library
self._schematic = ProjectTypeEnum.library.value
self._library(args) self._library(args)
if self._use_venv:
self._create_venv()
elif console is None and library is None and unittest is not None:
self._name = unittest
self._schematic = ProjectTypeEnum.unittest.value
self._unittest(args)
if self._use_venv:
self._create_venv()
else: else:
self._help('Usage: cpl new <schematic> [options]') self._help('Usage: cpl new <schematic> [options]')

View File

@@ -22,7 +22,7 @@ class PublishService(CommandABC):
Usage: cpl publish Usage: cpl publish
""") """)
def run(self, args: list[str]): def execute(self, args: list[str]):
""" """
Entry point of command Entry point of command
:param args: :param args:

View File

@@ -3,12 +3,14 @@ import shutil
import json import json
import textwrap import textwrap
from cpl_cli.configuration.settings_helper import SettingsHelper
from cpl_core.configuration.configuration_abc import ConfigurationABC from cpl_core.configuration.configuration_abc import ConfigurationABC
from cpl_core.console.console import Console from cpl_core.console.console import Console
from cpl_core.console.foreground_color_enum import ForegroundColorEnum from cpl_core.console.foreground_color_enum import ForegroundColorEnum
from cpl_core.environment.application_environment_abc import ApplicationEnvironmentABC from cpl_core.environment.application_environment_abc import ApplicationEnvironmentABC
from cpl_cli.command_abc import CommandABC from cpl_cli.command_abc import CommandABC
from cpl_cli.configuration import WorkspaceSettings, WorkspaceSettingsNameEnum from cpl_cli.configuration import WorkspaceSettings, WorkspaceSettingsNameEnum, BuildSettingsNameEnum, ProjectSettings, BuildSettings
class RemoveService(CommandABC): class RemoveService(CommandABC):
@@ -25,6 +27,7 @@ class RemoveService(CommandABC):
self._env = env self._env = env
self._workspace: WorkspaceSettings = self._config.get_configuration(WorkspaceSettings) self._workspace: WorkspaceSettings = self._config.get_configuration(WorkspaceSettings)
self._is_simulation = False
@property @property
def help_message(self) -> str: def help_message(self) -> str:
@@ -36,8 +39,10 @@ class RemoveService(CommandABC):
project The name of the project to delete project The name of the project to delete
""") """)
@staticmethod def _create_file(self, file_name: str, content: dict):
def _create_file(file_name: str, content: dict): if self._is_simulation:
return
if not os.path.isabs(file_name): if not os.path.isabs(file_name):
file_name = os.path.abspath(file_name) file_name = os.path.abspath(file_name)
@@ -49,8 +54,9 @@ class RemoveService(CommandABC):
project_json.write(json.dumps(content, indent=2)) project_json.write(json.dumps(content, indent=2))
project_json.close() project_json.close()
@staticmethod def _remove_sources(self, path: str):
def _remove_sources(path: str): if self._is_simulation:
return
shutil.rmtree(path) shutil.rmtree(path)
def _create_workspace(self, path: str): def _create_workspace(self, path: str):
@@ -64,12 +70,61 @@ class RemoveService(CommandABC):
self._create_file(path, ws_dict) self._create_file(path, ws_dict)
def run(self, args: list[str]): def _get_project_settings(self, project: str) -> dict:
with open(os.path.join(os.getcwd(), self._workspace.projects[project]), 'r', encoding='utf-8') as cfg:
# load json
project_json = json.load(cfg)
cfg.close()
return project_json
def _write_project_settings(self, project: str, project_settings: dict, build_settings: dict):
with open(os.path.join(os.getcwd(), self._workspace.projects[project]), 'w', encoding='utf-8') as file:
file.write(json.dumps({
ProjectSettings.__name__: project_settings,
BuildSettings.__name__: build_settings
}, indent=2))
file.close()
def _find_deps_in_projects(self, project_name: str, rel_path: str):
for project in self._workspace.projects:
if project == project_name:
continue
project_settings = self._get_project_settings(project)
if BuildSettings.__name__ not in project_settings or BuildSettingsNameEnum.project_references.value not in project_settings[BuildSettings.__name__]:
continue
ref_to_delete = ''
for ref in project_settings[BuildSettings.__name__][BuildSettingsNameEnum.project_references.value]:
if os.path.basename(ref) == f'{project_name}.json':
ref_to_delete = ref
if ref_to_delete not in project_settings[BuildSettings.__name__][BuildSettingsNameEnum.project_references.value]:
continue
project_settings[BuildSettings.__name__][BuildSettingsNameEnum.project_references.value].remove(ref_to_delete)
Console.spinner(
f'Removing {project_name} from {project}',
self._write_project_settings,
project,
project_settings[ProjectSettings.__name__],
project_settings[BuildSettings.__name__],
text_foreground_color=ForegroundColorEnum.green,
spinner_foreground_color=ForegroundColorEnum.cyan
)
def execute(self, args: list[str]):
""" """
Entry point of command Entry point of command
:param args: :param args:
:return: :return:
""" """
if 'simulate' in args:
args.remove('simulate')
Console.write_line('Running in simulation mode:')
self._is_simulation = True
project_name = args[0] project_name = args[0]
if project_name not in self._workspace.projects: if project_name not in self._workspace.projects:
Console.error(f'Project {project_name} not found in workspace.') Console.error(f'Project {project_name} not found in workspace.')
@@ -79,15 +134,17 @@ class RemoveService(CommandABC):
Console.error(f'Project {project_name} is the default project.') Console.error(f'Project {project_name} is the default project.')
return return
src_path = os.path.abspath(os.path.dirname(self._workspace.projects[project_name])) src_path = os.path.dirname(self._workspace.projects[project_name])
Console.spinner( Console.spinner(
f'Removing {src_path}', f'Removing {src_path}',
self._remove_sources, self._remove_sources,
src_path, os.path.abspath(src_path),
text_foreground_color=ForegroundColorEnum.green, text_foreground_color=ForegroundColorEnum.green,
spinner_foreground_color=ForegroundColorEnum.cyan spinner_foreground_color=ForegroundColorEnum.cyan
) )
self._find_deps_in_projects(project_name, src_path)
del self._workspace.projects[project_name] del self._workspace.projects[project_name]
path = 'cpl-workspace.json' path = 'cpl-workspace.json'
Console.spinner( Console.spinner(

View File

@@ -0,0 +1,95 @@
import os
import sys
import textwrap
from cpl_cli import Error
from cpl_cli.command_abc import CommandABC
from cpl_cli.configuration import WorkspaceSettings
from cpl_cli.configuration.build_settings import BuildSettings
from cpl_cli.configuration.project_settings import ProjectSettings
from cpl_cli.live_server.start_executable import StartExecutable
from cpl_core.configuration import ConfigurationABC
from cpl_core.console.console import Console
from cpl_core.dependency_injection import ServiceProviderABC
from cpl_core.environment.application_environment_abc import ApplicationEnvironmentABC
class RunService(CommandABC):
def __init__(self,
config: ConfigurationABC,
env: ApplicationEnvironmentABC,
services: ServiceProviderABC,
project_settings: ProjectSettings,
build_settings: BuildSettings,
workspace: WorkspaceSettings
):
"""
Service for the CLI command start
:param config:
:param env:
:param services:
:param project_settings:
:param build_settings:
:param workspace:
"""
CommandABC.__init__(self)
self._config = config
self._env = env
self._services = services
self._project_settings = project_settings
self._build_settings = build_settings
self._workspace = workspace
self._src_dir = os.path.join(self._env.working_directory, self._build_settings.source_path)
@property
def help_message(self) -> str:
return textwrap.dedent("""\
Starts your application.
Usage: cpl run
""")
def _set_project_by_args(self, name: str):
if self._workspace is None:
Error.error('The command requires to be run in an CPL workspace, but a workspace could not be found.')
sys.exit()
if name not in self._workspace.projects:
Error.error(f'Project {name} not found in workspace')
sys.exit()
project_path = self._workspace.projects[name]
self._config.add_configuration(ProjectSettings, None)
self._config.add_configuration(BuildSettings, None)
working_directory = self._config.get_configuration('PATH_WORKSPACE')
if working_directory is not None:
self._env.set_working_directory(working_directory)
json_file = os.path.join(self._env.working_directory, project_path)
self._config.add_json_file(json_file, optional=True, output=False)
self._project_settings: ProjectSettings = self._config.get_configuration(ProjectSettings)
self._build_settings: BuildSettings = self._config.get_configuration(BuildSettings)
if self._project_settings is None or self._build_settings is None:
Error.error(f'Project {name} not found')
sys.exit()
self._src_dir = os.path.dirname(json_file)
def execute(self, args: list[str]):
"""
Entry point of command
:param args:
:return:
"""
if len(args) >= 1:
self._set_project_by_args(args[0])
args.remove(args[0])
start_service = StartExecutable(self._env, self._build_settings)
start_service.run(args, self._project_settings.python_executable, self._src_dir, output=False)
Console.write_line()

View File

@@ -22,7 +22,7 @@ class StartService(CommandABC):
Usage: cpl start Usage: cpl start
""") """)
def run(self, args: list[str]): def execute(self, args: list[str]):
""" """
Entry point of command Entry point of command
:param args: :param args:

View File

@@ -4,6 +4,7 @@ import subprocess
import textwrap import textwrap
import time import time
from cpl_cli.configuration.venv_helper_service import VenvHelper
from cpl_core.configuration.configuration_abc import ConfigurationABC from cpl_core.configuration.configuration_abc import ConfigurationABC
from cpl_core.console.console import Console from cpl_core.console.console import Console
from cpl_core.console.foreground_color_enum import ForegroundColorEnum from cpl_core.console.foreground_color_enum import ForegroundColorEnum
@@ -35,6 +36,9 @@ class UninstallService(CommandABC):
self._is_simulating = False self._is_simulating = False
self._is_virtual = False self._is_virtual = False
self._is_dev = False
self._project_file = f'{self._project_settings.name}.json'
@property @property
def help_message(self) -> str: def help_message(self) -> str:
@@ -49,7 +53,7 @@ class UninstallService(CommandABC):
def _wait(self, t: int, *args, source: str = None, stdout=None, stderr=None): def _wait(self, t: int, *args, source: str = None, stdout=None, stderr=None):
time.sleep(t) time.sleep(t)
def run(self, args: list[str]): def execute(self, args: list[str]):
""" """
Entry point of command Entry point of command
:param args: :param args:
@@ -59,8 +63,11 @@ class UninstallService(CommandABC):
Console.error(f'Expected package') Console.error(f'Expected package')
Console.error(f'Usage: cpl uninstall <package>') Console.error(f'Usage: cpl uninstall <package>')
return return
if 'dev' in args:
self._is_dev = True
args.remove('dev')
if '--virtual' in args: if '--virtual' in args:
self._is_virtual = True self._is_virtual = True
args.remove('--virtual') args.remove('--virtual')
@@ -71,8 +78,7 @@ class UninstallService(CommandABC):
args.remove('--simulate') args.remove('--simulate')
Console.write_line('Running in simulation mode:') Console.write_line('Running in simulation mode:')
if not self._is_virtual: VenvHelper.init_venv(self._is_virtual, self._env, self._project_settings)
Pip.set_executable(self._project_settings.python_executable)
package = args[0] package = args[0]
is_in_dependencies = False is_in_dependencies = False
@@ -82,7 +88,11 @@ class UninstallService(CommandABC):
else: else:
pip_package = package pip_package = package
for dependency in self._project_settings.dependencies: deps = self._project_settings.dependencies
if self._is_dev:
deps = self._project_settings.dev_dependencies
for dependency in deps:
if package in dependency: if package in dependency:
is_in_dependencies = True is_in_dependencies = True
package = dependency package = dependency
@@ -95,7 +105,7 @@ class UninstallService(CommandABC):
package = pip_package package = pip_package
Console.spinner( Console.spinner(
f'Uninstalling: {package}', f'Uninstalling: {package}' if not self._is_dev else f'Uninstalling dev: {package}',
Pip.uninstall if not self._is_virtual else self._wait, package if not self._is_virtual else 2, Pip.uninstall if not self._is_virtual else self._wait, package if not self._is_virtual else 2,
stdout=subprocess.DEVNULL, stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL, stderr=subprocess.DEVNULL,
@@ -103,14 +113,18 @@ class UninstallService(CommandABC):
spinner_foreground_color=ForegroundColorEnum.cyan spinner_foreground_color=ForegroundColorEnum.cyan
) )
if package in self._project_settings.dependencies: deps = self._project_settings.dependencies
self._project_settings.dependencies.remove(package) if self._is_dev:
deps = self._project_settings.dev_dependencies
if package in deps:
deps.remove(package)
if not self._is_simulating: if not self._is_simulating:
config = { config = {
ProjectSettings.__name__: SettingsHelper.get_project_settings_dict(self._project_settings), ProjectSettings.__name__: SettingsHelper.get_project_settings_dict(self._project_settings),
BuildSettings.__name__: SettingsHelper.get_build_settings_dict(self._build_settings) BuildSettings.__name__: SettingsHelper.get_build_settings_dict(self._build_settings)
} }
with open(os.path.join(self._env.working_directory, f'{self._config.get_configuration("ProjectName")}.json'), 'w') as project_file: with open(os.path.join(self._env.working_directory, self._project_file), 'w') as project_file:
project_file.write(json.dumps(config, indent=2)) project_file.write(json.dumps(config, indent=2))
project_file.close() project_file.close()

View File

@@ -3,6 +3,7 @@ import os
import subprocess import subprocess
import textwrap import textwrap
from cpl_cli.configuration.venv_helper_service import VenvHelper
from cpl_core.configuration.configuration_abc import ConfigurationABC from cpl_core.configuration.configuration_abc import ConfigurationABC
from cpl_core.console.console import Console from cpl_core.console.console import Console
from cpl_core.console.foreground_color_enum import ForegroundColorEnum from cpl_core.console.foreground_color_enum import ForegroundColorEnum
@@ -38,6 +39,9 @@ class UpdateService(CommandABC):
self._build_settings = build_settings self._build_settings = build_settings
self._project_settings = project_settings self._project_settings = project_settings
self._cli_settings = cli_settings self._cli_settings = cli_settings
self._is_simulation = False
self._project_file = f'{self._project_settings.name}.json'
@property @property
def help_message(self) -> str: def help_message(self) -> str:
@@ -72,7 +76,7 @@ class UpdateService(CommandABC):
'--upgrade', '--upgrade',
'--upgrade-strategy', '--upgrade-strategy',
'eager', 'eager',
source=self._cli_settings.pip_path if 'sh_cpl' in name else None, source=self._cli_settings.pip_path if 'cpl-' in name else None,
stdout=subprocess.DEVNULL, stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL stderr=subprocess.DEVNULL
) )
@@ -80,7 +84,7 @@ class UpdateService(CommandABC):
new_package = Pip.get_package(name) new_package = Pip.get_package(name)
if new_package is None: if new_package is None:
Console.error(f'Update for package {package} failed') Console.error(f'Update for package {package} failed')
return continue
self._project_json_update_dependency(package, new_package) self._project_json_update_dependency(package, new_package)
@@ -132,6 +136,9 @@ class UpdateService(CommandABC):
:param new_package: :param new_package:
:return: :return:
""" """
if self._is_simulation:
return
if old_package in self._project_settings.dependencies: if old_package in self._project_settings.dependencies:
index = self._project_settings.dependencies.index(old_package) index = self._project_settings.dependencies.index(old_package)
if '/' in new_package: if '/' in new_package:
@@ -147,18 +154,23 @@ class UpdateService(CommandABC):
BuildSettings.__name__: SettingsHelper.get_build_settings_dict(self._build_settings) BuildSettings.__name__: SettingsHelper.get_build_settings_dict(self._build_settings)
} }
with open(os.path.join(self._env.working_directory, f'{self._config.get_configuration("ProjectName")}.json'), with open(os.path.join(self._env.working_directory, self._project_file), 'w') as project:
'w') as project:
project.write(json.dumps(config, indent=2)) project.write(json.dumps(config, indent=2))
project.close() project.close()
def run(self, args: list[str]): def execute(self, args: list[str]):
""" """
Entry point of command Entry point of command
:param args: :param args:
:return: :return:
""" """
Pip.set_executable(self._project_settings.python_executable) if 'simulate' in args:
args.remove('simulate')
Console.write_line('Running in simulation mode:')
self._is_simulation = True
VenvHelper.init_venv(False, self._env, self._project_settings)
self._check_project_dependencies() self._check_project_dependencies()
self._check_outdated() self._check_outdated()
Pip.reset_executable() Pip.reset_executable()

View File

@@ -5,7 +5,6 @@ import pkg_resources
import textwrap import textwrap
import cpl_cli import cpl_cli
import cpl_core
from cpl_core.console.console import Console from cpl_core.console.console import Console
from cpl_core.console.foreground_color_enum import ForegroundColorEnum from cpl_core.console.foreground_color_enum import ForegroundColorEnum
from cpl_cli.command_abc import CommandABC from cpl_cli.command_abc import CommandABC
@@ -26,7 +25,7 @@ class VersionService(CommandABC):
Usage: cpl version Usage: cpl version
""") """)
def run(self, args: list[str]): def execute(self, args: list[str]):
""" """
Entry point of command Entry point of command
:param args: :param args:

View File

@@ -1,9 +1,10 @@
from abc import abstractmethod, ABC from abc import abstractmethod, ABC
from cpl_core.configuration.executable_argument import ExecutableArgument from cpl_core.configuration.argument_executable_abc import ArgumentExecutableABC
from cpl_core.console import Console
class CommandABC(ExecutableArgument): class CommandABC(ArgumentExecutableABC):
@abstractmethod @abstractmethod
def __init__(self): def __init__(self):
@@ -12,3 +13,13 @@ class CommandABC(ExecutableArgument):
@property @property
@abstractmethod @abstractmethod
def help_message(self) -> str: pass def help_message(self) -> str: pass
@abstractmethod
def execute(self, args: list[str]): pass
def run(self, args: list[str]):
if 'help' in args:
Console.write_line(self.help_message)
return
self.execute(args)

View File

@@ -1,137 +0,0 @@
import os
from abc import ABC
from typing import Optional
from cpl_core.configuration.configuration_abc import ConfigurationABC
from cpl_core.console.console import Console
from cpl_core.dependency_injection.service_provider_abc import ServiceProviderABC
from cpl_core.utils.string import String
from cpl_cli.command.custom_script_service import CustomScriptService
from cpl_cli.configuration.workspace_settings import WorkspaceSettings
from cpl_cli.error import Error
from cpl_cli.command_model import CommandModel
class CommandHandler(ABC):
def __init__(self, config: ConfigurationABC, services: ServiceProviderABC):
"""
Service to handle incoming commands and args
:param config:
:param services:
"""
ABC.__init__(self)
self._config = config
self._env = self._config.environment
self._services = services
self._commands: list[CommandModel] = []
@property
def commands(self) -> list[CommandModel]:
return self._commands
@staticmethod
def _project_not_found():
Error.error(
'The command requires to be run in an CPL project, but a project could not be found.'
)
def add_command(self, cmd: CommandModel):
self._commands.append(cmd)
def remove_command(self, cmd: CommandModel):
self._commands.remove(cmd)
def handle(self, cmd: str, args: list[str]):
"""
Handles incoming commands and args
:param cmd:
:param args:
:return:
"""
for command in self._commands:
if cmd == command.name or cmd in command.aliases:
error = None
project_name: Optional[str] = None
workspace: Optional[WorkspaceSettings] = None
if os.path.isfile(os.path.join(self._env.working_directory, 'cpl-workspace.json')):
workspace = self._config.get_configuration(WorkspaceSettings)
if command.is_project_needed:
name = os.path.basename(self._env.working_directory)
for r, d, f in os.walk(self._env.working_directory):
for file in f:
if file.endswith('.json'):
f_name = file.split('.json')[0]
if f_name == name or \
String.convert_to_camel_case(f_name).lower() == String.convert_to_camel_case(
name).lower():
project_name = f_name
break
if not command.is_workspace_needed and project_name is None and workspace is None:
self._project_not_found()
return
elif command.is_workspace_needed or project_name is None:
if workspace is None:
Error.error(
'The command requires to be run in an CPL workspace or project, '
'but a workspace or project could not be found.'
)
return
if project_name is None:
project_name = workspace.default_project
self._config.add_configuration('ProjectName', project_name)
project_json = f'{project_name}.json'
if workspace is not None:
if project_name not in workspace.projects:
Error.error(
f'Project {project_name} not found.'
)
return
project_json = workspace.projects[project_name]
if not os.path.isfile(os.path.join(self._env.working_directory, project_json)):
self._project_not_found()
return
project_json = os.path.join(self._env.working_directory, project_json)
if command.change_cwd:
self._env.set_working_directory(
os.path.join(self._env.working_directory, os.path.dirname(project_json))
)
self._config.add_json_file(project_json, optional=True, output=False)
# pre scripts
Console.write('\n')
self._handle_pre_or_post_scripts(True, workspace, command)
self._services.get_service(command.command).run(args)
# post scripts
Console.write('\n\n')
self._handle_pre_or_post_scripts(False, workspace, command)
Console.write('\n')
def _handle_pre_or_post_scripts(self, pre: bool, workspace: WorkspaceSettings, command: CommandModel):
script_type = 'pre-' if pre else 'post-'
if workspace is not None and len(workspace.scripts) > 0:
for script in workspace.scripts:
if script_type in script and script.split(script_type)[1] == command.name:
script_name = script
script_cmd = workspace.scripts[script]
if script_cmd in workspace.scripts:
script_name = workspace.scripts[script]
css: CustomScriptService = self._services.get_service(CustomScriptService)
if css is None:
continue
css.run([script_name])

View File

@@ -1,37 +0,0 @@
from cpl_cli.command_abc import CommandABC
class CommandModel:
def __init__(self, name: str, aliases: list[str], command: CommandABC, is_workspace_needed: bool,
is_project_needed: bool, change_cwd: bool):
self._name = name
self._aliases = aliases
self._command = command
self._is_workspace_needed = is_workspace_needed
self._is_project_needed = is_project_needed
self._change_cwd = change_cwd
@property
def name(self) -> str:
return self._name
@property
def aliases(self) -> list[str]:
return self._aliases
@property
def command(self) -> CommandABC:
return self._command
@property
def is_workspace_needed(self) -> bool:
return self._is_workspace_needed
@property
def is_project_needed(self) -> bool:
return self._is_project_needed
@property
def change_cwd(self) -> bool:
return self._change_cwd

View File

@@ -15,7 +15,7 @@ __title__ = 'cpl_cli.configuration'
__author__ = 'Sven Heidemann' __author__ = 'Sven Heidemann'
__license__ = 'MIT' __license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de'
__version__ = '2022.6.3.dev2' __version__ = '2022.6.0rc1'
from collections import namedtuple from collections import namedtuple
@@ -30,4 +30,4 @@ from .workspace_settings import WorkspaceSettings
from .workspace_settings_name_enum import WorkspaceSettingsNameEnum from .workspace_settings_name_enum import WorkspaceSettingsNameEnum
VersionInfo = namedtuple('VersionInfo', 'major minor micro') VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='2022', minor='6', micro='3.dev2') version_info = VersionInfo(major='2022', minor='6', micro='0.rc1')

View File

@@ -3,12 +3,12 @@ import sys
import traceback import traceback
from typing import Optional from typing import Optional
from cpl_cli.configuration.project_settings_name_enum import ProjectSettingsNameEnum
from cpl_cli.configuration.version_settings import VersionSettings
from cpl_cli.error import Error
from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC
from cpl_core.console.console import Console from cpl_core.console.console import Console
from cpl_core.console.foreground_color_enum import ForegroundColorEnum from cpl_core.console.foreground_color_enum import ForegroundColorEnum
from cpl_cli.configuration.version_settings import VersionSettings
from cpl_cli.configuration.project_settings_name_enum import ProjectSettingsNameEnum
from cpl_cli.error import Error
class ProjectSettings(ConfigurationModelABC): class ProjectSettings(ConfigurationModelABC):
@@ -28,6 +28,7 @@ class ProjectSettings(ConfigurationModelABC):
self._license_name: Optional[str] = None self._license_name: Optional[str] = None
self._license_description: Optional[str] = None self._license_description: Optional[str] = None
self._dependencies: Optional[list[str]] = None self._dependencies: Optional[list[str]] = None
self._dev_dependencies: Optional[list[str]] = None
self._python_version: Optional[str] = None self._python_version: Optional[str] = None
self._python_path: Optional[str] = None self._python_path: Optional[str] = None
self._python_executable: Optional[str] = None self._python_executable: Optional[str] = None
@@ -81,6 +82,10 @@ class ProjectSettings(ConfigurationModelABC):
def dependencies(self) -> list[str]: def dependencies(self) -> list[str]:
return self._dependencies return self._dependencies
@property
def dev_dependencies(self) -> list[str]:
return self._dev_dependencies
@property @property
def python_version(self) -> str: def python_version(self) -> str:
return self._python_version return self._python_version
@@ -111,16 +116,16 @@ class ProjectSettings(ConfigurationModelABC):
self._license_name = settings[ProjectSettingsNameEnum.license_name.value] self._license_name = settings[ProjectSettingsNameEnum.license_name.value]
self._license_description = settings[ProjectSettingsNameEnum.license_description.value] self._license_description = settings[ProjectSettingsNameEnum.license_description.value]
self._dependencies = settings[ProjectSettingsNameEnum.dependencies.value] self._dependencies = settings[ProjectSettingsNameEnum.dependencies.value]
if ProjectSettingsNameEnum.dev_dependencies.value not in settings:
settings[ProjectSettingsNameEnum.dev_dependencies.value] = []
self._dev_dependencies = settings[ProjectSettingsNameEnum.dev_dependencies.value]
self._python_version = settings[ProjectSettingsNameEnum.python_version.value] self._python_version = settings[ProjectSettingsNameEnum.python_version.value]
self._python_path = settings[ProjectSettingsNameEnum.python_path.value] self._python_path = settings[ProjectSettingsNameEnum.python_path.value]
if ProjectSettingsNameEnum.python_path.value in settings and \ if ProjectSettingsNameEnum.python_path.value in settings and sys.platform in settings[ProjectSettingsNameEnum.python_path.value]:
sys.platform in settings[ProjectSettingsNameEnum.python_path.value]:
path = settings[ProjectSettingsNameEnum.python_path.value][sys.platform] path = settings[ProjectSettingsNameEnum.python_path.value][sys.platform]
if not os.path.isfile(path) and not os.path.islink(path): if path == '' or path is None:
if path != '' and path is not None: Error.warn(f'{ProjectSettingsNameEnum.python_path.value} not found')
Error.warn(f'{ProjectSettingsNameEnum.python_path.value} not found')
path = sys.executable path = sys.executable
else: else:
path = sys.executable path = sys.executable
@@ -134,7 +139,6 @@ class ProjectSettings(ConfigurationModelABC):
except Exception as e: except Exception as e:
Console.set_foreground_color(ForegroundColorEnum.red) Console.set_foreground_color(ForegroundColorEnum.red)
Console.write_line( Console.write_line(f'[ ERROR ] [ {__name__} ]: Reading error in {ProjectSettings.__name__} settings')
f'[ ERROR ] [ {__name__} ]: Reading error in {ProjectSettings.__name__} settings')
Console.write_line(f'[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}') Console.write_line(f'[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}')
Console.set_foreground_color(ForegroundColorEnum.default) Console.set_foreground_color(ForegroundColorEnum.default)

View File

@@ -14,6 +14,7 @@ class ProjectSettingsNameEnum(Enum):
license_name = 'LicenseName' license_name = 'LicenseName'
license_description = 'LicenseDescription' license_description = 'LicenseDescription'
dependencies = 'Dependencies' dependencies = 'Dependencies'
dev_dependencies = 'DevDependencies'
python_version = 'PythonVersion' python_version = 'PythonVersion'
python_path = 'PythonPath' python_path = 'PythonPath'
classifiers = 'Classifiers' classifiers = 'Classifiers'

View File

@@ -5,3 +5,4 @@ class ProjectTypeEnum(Enum):
console = 'console' console = 'console'
library = 'library' library = 'library'
unittest = 'unittest'

View File

@@ -26,6 +26,7 @@ class SettingsHelper:
ProjectSettingsNameEnum.license_name.value: project.license_name, ProjectSettingsNameEnum.license_name.value: project.license_name,
ProjectSettingsNameEnum.license_description.value: project.license_description, ProjectSettingsNameEnum.license_description.value: project.license_description,
ProjectSettingsNameEnum.dependencies.value: project.dependencies, ProjectSettingsNameEnum.dependencies.value: project.dependencies,
ProjectSettingsNameEnum.dev_dependencies.value: project.dev_dependencies,
ProjectSettingsNameEnum.python_version.value: project.python_version, ProjectSettingsNameEnum.python_version.value: project.python_version,
ProjectSettingsNameEnum.python_path.value: project.python_path, ProjectSettingsNameEnum.python_path.value: project.python_path,
ProjectSettingsNameEnum.classifiers.value: project.classifiers ProjectSettingsNameEnum.classifiers.value: project.classifiers

View File

@@ -0,0 +1,43 @@
import os
import subprocess
import sys
from cpl_cli.configuration import ProjectSettings
from cpl_core.environment import ApplicationEnvironmentABC
from cpl_core.utils import Pip
from cpl_core.console import Console, ForegroundColorEnum
class VenvHelper:
@staticmethod
def init_venv(is_virtual: bool, env: ApplicationEnvironmentABC, project_settings: ProjectSettings, explicit_path=None):
if is_virtual:
return
venv_path = os.path.abspath(os.path.join(env.working_directory, project_settings.python_executable))
if explicit_path is not None:
venv_path = os.path.abspath(explicit_path)
if not os.path.exists(venv_path):
Console.spinner(
f'Creating venv: {venv_path}',
VenvHelper.create_venv,
venv_path,
text_foreground_color=ForegroundColorEnum.green,
spinner_foreground_color=ForegroundColorEnum.cyan
)
Pip.set_executable(venv_path)
@staticmethod
def create_venv(path):
subprocess.run(
[sys.executable, '-m', 'venv', os.path.abspath(os.path.join(path, '../../'))],
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
stdin=subprocess.DEVNULL
)

View File

@@ -4,7 +4,7 @@
"Version": { "Version": {
"Major": "2022", "Major": "2022",
"Minor": "6", "Minor": "6",
"Micro": "3.dev2" "Micro": "0.rc1"
}, },
"Author": "Sven Heidemann", "Author": "Sven Heidemann",
"AuthorEmail": "sven.heidemann@sh-edraft.de", "AuthorEmail": "sven.heidemann@sh-edraft.de",
@@ -16,10 +16,13 @@
"LicenseName": "MIT", "LicenseName": "MIT",
"LicenseDescription": "MIT, see LICENSE for more details.", "LicenseDescription": "MIT, see LICENSE for more details.",
"Dependencies": [ "Dependencies": [
"cpl-core>=2022.6.3.dev2" "cpl-core>=2022.6.0.rc1"
], ],
"DevDependencies": [],
"PythonVersion": ">=3.10", "PythonVersion": ">=3.10",
"PythonPath": {}, "PythonPath": {
"linux": "../../venv"
},
"Classifiers": [] "Classifiers": []
}, },
"BuildSettings": { "BuildSettings": {
@@ -42,8 +45,6 @@
"*.json" "*.json"
] ]
}, },
"ProjectReferences": [ "ProjectReferences": []
"../cpl_core/cpl_core.json"
]
} }
} }

View File

@@ -15,11 +15,11 @@ __title__ = 'cpl_cli.live_server'
__author__ = 'Sven Heidemann' __author__ = 'Sven Heidemann'
__license__ = 'MIT' __license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de'
__version__ = '2022.6.3.dev2' __version__ = '2022.6.0rc1'
from collections import namedtuple from collections import namedtuple
# imports: # imports:
VersionInfo = namedtuple('VersionInfo', 'major minor micro') VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='2022', minor='6', micro='3.dev2') version_info = VersionInfo(major='2022', minor='6', micro='0.rc1')

View File

@@ -35,8 +35,6 @@ class LiveServerThread(threading.Thread):
self._command = [] self._command = []
self._env_vars = os.environ self._env_vars = os.environ
self._set_venv()
@property @property
def command(self) -> list[str]: def command(self) -> list[str]:
return self._command return self._command
@@ -45,16 +43,6 @@ class LiveServerThread(threading.Thread):
def main(self) -> str: def main(self) -> str:
return self._main return self._main
def _set_venv(self):
if self._executable != sys.executable:
path = os.path.abspath(os.path.dirname(os.path.dirname(self._executable)))
if sys.platform == 'win32':
self._env_vars['PATH'] = f'{path}\\bin' + os.pathsep + os.environ.get('PATH', '')
else:
self._env_vars['PATH'] = f'{path}/bin' + os.pathsep + os.environ.get('PATH', '')
self._env_vars['VIRTUAL_ENV'] = path
def run(self): def run(self):
""" """
Starts the CPL project Starts the CPL project
@@ -88,7 +76,9 @@ class LiveServerThread(threading.Thread):
Console.set_foreground_color(ForegroundColorEnum.default) Console.set_foreground_color(ForegroundColorEnum.default)
self._command = [self._executable, self._main] self._command = [self._executable, self._main]
if len(self._args) > 0: # if len(self._args) > 0:
self._command.append(''.join(self._args)) # self._command.append(' '.join(self._args))
for arg in self._args:
self._command.append(arg)
subprocess.run(self._command, env=self._env_vars) subprocess.run(self._command, env=self._env_vars)

View File

@@ -0,0 +1,81 @@
import os
import subprocess
import sys
import threading
from datetime import datetime
from cpl_core.console.console import Console
from cpl_core.console.foreground_color_enum import ForegroundColorEnum
from cpl_core.environment.application_environment_abc import ApplicationEnvironmentABC
from cpl_cli.configuration import BuildSettings
class StartExecutable:
def __init__(self, env: ApplicationEnvironmentABC, build_settings: BuildSettings):
"""
Service to start the CPL project for the live development server
:param env:
:param build_settings:
"""
self._executable = None
self._env = env
self._build_settings = build_settings
self._main = ''
self._command = []
self._env_vars = os.environ
self._set_venv()
def _set_venv(self):
if self._executable is None or self._executable == sys.executable:
return
path = os.path.abspath(os.path.dirname(os.path.dirname(self._executable)))
if sys.platform == 'win32':
self._env_vars['PATH'] = f'{path}\\bin' + os.pathsep + os.environ.get('PATH', '')
else:
self._env_vars['PATH'] = f'{path}/bin' + os.pathsep + os.environ.get('PATH', '')
self._env_vars['VIRTUAL_ENV'] = path
def run(self, args: list[str], executable: str, path: str, output=True):
self._executable = os.path.abspath(executable)
main = self._build_settings.main
if '.' in self._build_settings.main:
length = len(self._build_settings.main.split('.')) - 1
main = self._build_settings.main.split('.')[length]
self._main = os.path.join(path, f'{main}.py')
if not os.path.isfile(self._main):
Console.error('Entry point main.py not found')
return
# set cwd to src/
self._env.set_working_directory(os.path.abspath(os.path.join(path)))
src_cwd = os.path.abspath(os.path.join(path, '../'))
if sys.platform == 'win32':
self._env_vars['PYTHONPATH'] = f'{src_cwd};' \
f'{os.path.join(self._env.working_directory, self._build_settings.source_path)}'
else:
self._env_vars['PYTHONPATH'] = f'{src_cwd}:' \
f'{os.path.join(self._env.working_directory, self._build_settings.source_path)}'
if output:
Console.set_foreground_color(ForegroundColorEnum.green)
Console.write_line('Read successfully')
Console.set_foreground_color(ForegroundColorEnum.cyan)
Console.write_line(f'Started at {datetime.now().strftime("%Y-%m-%d %H:%M:%S")}\n\n')
Console.set_foreground_color(ForegroundColorEnum.default)
self._command = [self._executable, self._main]
# if len(self._args) > 0:
# self._command.append(' '.join(self._args))
for arg in args:
self._command.append(arg)
subprocess.run(self._command, env=self._env_vars)

View File

@@ -1,13 +1,54 @@
from cpl_core.application.application_builder import ApplicationBuilder from typing import Type
import pkg_resources
from cpl_cli.cli import CLI from cpl_cli.cli import CLI
from cpl_cli.startup import Startup from cpl_cli.startup import Startup
from cpl_cli.startup_argument_extension import StartupArgumentExtension
from cpl_cli.startup_workspace_extension import StartupWorkspaceExtension
from cpl_core.application.application_builder import ApplicationBuilder
from cpl_core.application.startup_extension_abc import StartupExtensionABC
def get_startup_extensions() -> list[Type[StartupExtensionABC]]:
blacklisted_packages = ['cpl-cli']
startup_extensions = []
installed_packages = pkg_resources.working_set
for p in installed_packages:
package = str(p).split(' ')[0]
if not package.startswith('cpl-') or package in blacklisted_packages:
continue
package = package.replace('-', '_')
loaded_package = __import__(package)
if '__cli_startup_extension__' not in dir(loaded_package):
continue
startup_extensions.append(loaded_package.__cli_startup_extension__)
return startup_extensions
def main(): def main():
app_builder = ApplicationBuilder(CLI) app_builder = ApplicationBuilder(CLI)
app_builder.use_startup(Startup) app_builder.use_startup(Startup)
app_builder.use_extension(StartupWorkspaceExtension)
app_builder.use_extension(StartupArgumentExtension)
for extension in get_startup_extensions():
app_builder.use_extension(extension)
app_builder.build().run() app_builder.build().run()
if __name__ == '__main__': if __name__ == '__main__':
main() main()
# ((
# ( `)
# ; / ,
# / \/
# / |
# / ~/
# / ) ) ~ edraft
# ___// | /
# `--' \_~-,

View File

@@ -15,7 +15,7 @@ __title__ = 'cpl_cli.publish'
__author__ = 'Sven Heidemann' __author__ = 'Sven Heidemann'
__license__ = 'MIT' __license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de'
__version__ = '2022.6.3.dev2' __version__ = '2022.6.0rc1'
from collections import namedtuple from collections import namedtuple
@@ -24,4 +24,4 @@ from .publisher_abc import PublisherABC
from .publisher_service import PublisherService from .publisher_service import PublisherService
VersionInfo = namedtuple('VersionInfo', 'major minor micro') VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='2022', minor='6', micro='3.dev2') version_info = VersionInfo(major='2022', minor='6', micro='0.rc1')

View File

@@ -206,55 +206,57 @@ class PublisherService(PublisherABC):
:return: :return:
""" """
for file in self._included_files: for file in self._included_files:
if file.endswith('__init__.py'): if not file.endswith('__init__.py'):
template_content = '' continue
module_file_lines: list[str] = []
title = self._get_module_name_from_dirs(file) template_content = ''
if title == '': module_file_lines: list[str] = []
title = self._project_settings.name
module_py_lines: list[str] = [] title = self._get_module_name_from_dirs(file)
imports = '' if title == '':
title = self._project_settings.name
with open(file, 'r') as py_file: module_py_lines: list[str] = []
module_file_lines = py_file.readlines() imports = ''
py_file.close()
if len(module_file_lines) == 0: with open(file, 'r') as py_file:
imports = '# imports:' module_file_lines = py_file.readlines()
else: py_file.close()
is_started = False
for line in module_file_lines:
if line.__contains__('# imports'):
is_started = True
if (line.__contains__('from') or line.__contains__('import')) and is_started: if len(module_file_lines) == 0:
module_py_lines.append(line.replace('\n', '')) imports = '# imports:'
else:
is_started = False
for line in module_file_lines:
if line.__contains__('# imports'):
is_started = True
if len(module_py_lines) > 0: if ((line.__contains__('from') or line.__contains__('import')) and is_started) or line.startswith('__cli_startup_extension__'):
imports = '\n'.join(module_py_lines) module_py_lines.append(line.replace('\n', ''))
template_content = stringTemplate(InitTemplate.get_init_py()).substitute( if len(module_py_lines) > 0:
Name=self._project_settings.name, imports = '\n'.join(module_py_lines)
Description=self._project_settings.description,
LongDescription=self._project_settings.long_description,
CopyrightDate=self._project_settings.copyright_date,
CopyrightName=self._project_settings.copyright_name,
LicenseName=self._project_settings.license_name,
LicenseDescription=self._project_settings.license_description,
Title=title if title is not None and title != '' else self._project_settings.name,
Author=self._project_settings.author,
Version=version.parse(self._project_settings.version.to_str()),
Major=self._project_settings.version.major,
Minor=self._project_settings.version.minor,
Micro=self._project_settings.version.micro,
Imports=imports
)
with open(file, 'w+') as py_file: template_content = stringTemplate(InitTemplate.get_init_py()).substitute(
py_file.write(template_content) Name=self._project_settings.name,
py_file.close() Description=self._project_settings.description,
LongDescription=self._project_settings.long_description,
CopyrightDate=self._project_settings.copyright_date,
CopyrightName=self._project_settings.copyright_name,
LicenseName=self._project_settings.license_name,
LicenseDescription=self._project_settings.license_description,
Title=title if title is not None and title != '' else self._project_settings.name,
Author=self._project_settings.author,
Version=version.parse(self._project_settings.version.to_str()),
Major=self._project_settings.version.major,
Minor=self._project_settings.version.minor,
Micro=self._project_settings.version.micro,
Imports=imports
)
with open(file, 'w+') as py_file:
py_file.write(template_content)
py_file.close()
def _dist_files(self): def _dist_files(self):
""" """
@@ -424,7 +426,7 @@ class PublisherService(PublisherABC):
:return: :return:
""" """
self._env.set_working_directory(os.path.join(self._env.working_directory, '../')) self._env.set_working_directory(os.path.join(self._env.working_directory, '../'))
self.exclude(f'*/{self._config.get_configuration("ProjectName")}.json') self.exclude(f'*/{self._project_settings.name}.json')
self._output_path = os.path.abspath(os.path.join(self._output_path, self._project_settings.name, 'build')) self._output_path = os.path.abspath(os.path.join(self._output_path, self._project_settings.name, 'build'))
Console.spinner('Reading source files:', self._read_sources, text_foreground_color=ForegroundColorEnum.green, Console.spinner('Reading source files:', self._read_sources, text_foreground_color=ForegroundColorEnum.green,
@@ -434,6 +436,7 @@ class PublisherService(PublisherABC):
spinner_foreground_color=ForegroundColorEnum.blue) spinner_foreground_color=ForegroundColorEnum.blue)
Console.spinner('Building application:', self._dist_files, text_foreground_color=ForegroundColorEnum.green, Console.spinner('Building application:', self._dist_files, text_foreground_color=ForegroundColorEnum.green,
spinner_foreground_color=ForegroundColorEnum.blue) spinner_foreground_color=ForegroundColorEnum.blue)
Console.write_line()
def publish(self): def publish(self):
""" """
@@ -446,7 +449,7 @@ class PublisherService(PublisherABC):
:return: :return:
""" """
self._env.set_working_directory(os.path.join(self._env.working_directory, '../')) self._env.set_working_directory(os.path.join(self._env.working_directory, '../'))
self.exclude(f'*/{self._config.get_configuration("ProjectName")}.json') self.exclude(f'*/{self._project_settings.name}.json')
self._output_path = os.path.abspath(os.path.join(self._output_path, self._project_settings.name, 'publish')) self._output_path = os.path.abspath(os.path.join(self._output_path, self._project_settings.name, 'publish'))
Console.write_line('Build:') Console.write_line('Build:')
@@ -487,3 +490,4 @@ class PublisherService(PublisherABC):
text_foreground_color=ForegroundColorEnum.green, text_foreground_color=ForegroundColorEnum.green,
spinner_foreground_color=ForegroundColorEnum.blue spinner_foreground_color=ForegroundColorEnum.blue
) )
Console.write_line()

View File

@@ -15,11 +15,11 @@ __title__ = 'cpl_cli.source_creator'
__author__ = 'Sven Heidemann' __author__ = 'Sven Heidemann'
__license__ = 'MIT' __license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de'
__version__ = '2022.6.3.dev2' __version__ = '2022.6.0rc1'
from collections import namedtuple from collections import namedtuple
# imports: # imports:
VersionInfo = namedtuple('VersionInfo', 'major minor micro') VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='2022', minor='6', micro='3.dev2') version_info = VersionInfo(major='2022', minor='6', micro='0.rc1')

View File

@@ -0,0 +1,164 @@
import json
import os
from typing import Optional
from cpl_cli._templates.new.unittest.license import LicenseTemplate
from cpl_cli._templates.new.unittest.readme_py import ReadmeTemplate
from cpl_cli._templates.new.unittest.source.name.application import ApplicationTemplate
from cpl_cli._templates.new.unittest.source.name.init import MainInitTemplate
from cpl_cli._templates.new.unittest.source.name.main import MainWithApplicationBaseTemplate
from cpl_cli._templates.new.unittest.source.name.test_case import TestCaseTemplate
from cpl_cli._templates.template_file_abc import TemplateFileABC
from cpl_cli.configuration.workspace_settings import WorkspaceSettings
from cpl_cli.configuration.workspace_settings_name_enum import WorkspaceSettingsNameEnum
from cpl_cli.source_creator.template_builder import TemplateBuilder
from cpl_core.console.console import Console
from cpl_core.console.foreground_color_enum import ForegroundColorEnum
from cpl_core.utils.string import String
class UnittestBuilder:
def __init__(self):
pass
@staticmethod
def _create_file(file_name: str, content: dict):
if not os.path.isabs(file_name):
file_name = os.path.abspath(file_name)
path = os.path.dirname(file_name)
if not os.path.isdir(path):
os.makedirs(path)
with open(file_name, 'w') as project_json:
project_json.write(json.dumps(content, indent=2))
project_json.close()
@classmethod
def _create_workspace(cls, path: str, project_name, projects: dict, scripts: dict):
ws_dict = {
WorkspaceSettings.__name__: {
WorkspaceSettingsNameEnum.default_project.value: project_name,
WorkspaceSettingsNameEnum.projects.value: projects,
WorkspaceSettingsNameEnum.scripts.value: scripts
}
}
Console.spinner(
f'Creating {path}',
cls._create_file,
path,
ws_dict,
text_foreground_color=ForegroundColorEnum.green,
spinner_foreground_color=ForegroundColorEnum.cyan
)
@classmethod
def build(cls, project_path: str, use_application_api: bool,
use_async: bool, project_name: str, project_settings: dict, workspace: Optional[WorkspaceSettings]):
"""
Builds the console project files
:param project_path:
:param use_application_api:
:param use_async:
:param project_name:
:param project_settings:
:param workspace:
:return:
"""
pj_name = project_name
if '/' in pj_name:
pj_name = pj_name.split('/')[len(pj_name.split('/')) - 1]
project_name_snake = String.convert_to_snake_case(pj_name)
if workspace is None:
templates: list[TemplateFileABC] = [
LicenseTemplate(),
ReadmeTemplate(),
MainInitTemplate(project_name, os.path.join('src/', project_name_snake))
]
else:
project_path = os.path.join(
os.path.dirname(project_path),
project_name_snake
)
templates: list[TemplateFileABC] = [
MainInitTemplate('', '')
]
if not os.path.isdir(project_path):
os.makedirs(project_path)
py_src_rel_path = ''
src_name = project_name_snake
if workspace is None:
py_src_rel_path = f'src/{src_name}'
templates.append(ApplicationTemplate(src_name, py_src_rel_path, use_async))
templates.append(MainWithApplicationBaseTemplate(src_name, py_src_rel_path, use_async))
templates.append(TestCaseTemplate(src_name, py_src_rel_path, use_async))
src_rel_path = ''
if '/' in project_name:
old_pj_name = project_name
parts = project_name.split('/')
project_name = parts[len(parts) - 1]
src_rel_path = old_pj_name.split(project_name)[0]
proj_name = project_name
if src_rel_path.endswith('/'):
src_rel_path = src_rel_path[:len(src_rel_path) - 1]
if src_rel_path != '':
proj_name = f'{src_rel_path}/{project_name}'
if workspace is not None:
proj_name = project_name_snake
if src_rel_path != '':
project_file_path = f'{src_rel_path}/{project_name_snake}/{project_name}.json'
else:
project_file_path = f'{project_name_snake}/{project_name}.json'
if workspace is None:
src_path = f'src/{project_name_snake}'
workspace_file_path = f'{proj_name}/cpl-workspace.json'
project_file_rel_path = f'{src_path}/{project_name}.json'
project_file_path = f'{proj_name}/{src_path}/{project_name}.json'
cls._create_workspace(
workspace_file_path,
project_name,
{
project_name: project_file_rel_path
},
{}
)
else:
workspace.projects[project_name] = f'src/{project_file_path}'
cls._create_workspace('cpl-workspace.json', workspace.default_project, workspace.projects, workspace.scripts)
Console.spinner(
f'Creating {project_file_path}',
cls._create_file,
project_file_path if workspace is None else f'src/{project_file_path}',
project_settings,
text_foreground_color=ForegroundColorEnum.green,
spinner_foreground_color=ForegroundColorEnum.cyan
)
for template in templates:
divider = ''
if template.path != '' and not template.path.endswith('/'):
divider = '/'
Console.spinner(
f'Creating {proj_name}/{template.path}{divider}{template.name}',
TemplateBuilder.build,
project_path,
template,
text_foreground_color=ForegroundColorEnum.green,
spinner_foreground_color=ForegroundColorEnum.cyan
)

View File

@@ -1,32 +1,34 @@
import os import os
from typing import Optional
from cpl_core.application.startup_abc import StartupABC
from cpl_core.configuration.argument_type_enum import ArgumentTypeEnum
from cpl_core.configuration.configuration_abc import ConfigurationABC
from cpl_core.console import Console
from cpl_core.dependency_injection.service_collection_abc import ServiceCollectionABC
from cpl_core.dependency_injection.service_provider_abc import ServiceProviderABC
from cpl_cli.command.add_service import AddService from cpl_cli.command.add_service import AddService
from cpl_cli.command.build_service import BuildService from cpl_cli.command.build_service import BuildService
from cpl_cli.command.custom_script_service import CustomScriptService from cpl_cli.command.custom_script_service import CustomScriptService
from cpl_cli.command.generate_service import GenerateService from cpl_cli.command.generate_service import GenerateService
from cpl_cli.command.help_service import HelpService
from cpl_cli.command.install_service import InstallService from cpl_cli.command.install_service import InstallService
from cpl_cli.command.new_service import NewService from cpl_cli.command.new_service import NewService
from cpl_cli.command.publish_service import PublishService from cpl_cli.command.publish_service import PublishService
from cpl_cli.command.remove_service import RemoveService from cpl_cli.command.remove_service import RemoveService
from cpl_cli.command.run_service import RunService
from cpl_cli.command.start_service import StartService from cpl_cli.command.start_service import StartService
from cpl_cli.command.uninstall_service import UninstallService from cpl_cli.command.uninstall_service import UninstallService
from cpl_cli.command.update_service import UpdateService from cpl_cli.command.update_service import UpdateService
from cpl_cli.command_handler_service import CommandHandler
from cpl_cli.command.help_service import HelpService
from cpl_cli.command.version_service import VersionService from cpl_cli.command.version_service import VersionService
from cpl_cli.configuration.workspace_settings import WorkspaceSettings from cpl_cli.validators.project_validator import ProjectValidator
from cpl_cli.validators.workspace_validator import WorkspaceValidator
from cpl_core.console import Console
from cpl_cli.error import Error from cpl_cli.error import Error
from cpl_cli.live_server.live_server_service import LiveServerService from cpl_cli.live_server.live_server_service import LiveServerService
from cpl_cli.publish.publisher_service import PublisherService
from cpl_cli.publish.publisher_abc import PublisherABC from cpl_cli.publish.publisher_abc import PublisherABC
from cpl_core.environment import ApplicationEnvironment from cpl_cli.publish.publisher_service import PublisherService
from cpl_core.application.startup_abc import StartupABC
from cpl_core.configuration.configuration_abc import ConfigurationABC
from cpl_core.dependency_injection.service_collection_abc import ServiceCollectionABC
from cpl_core.dependency_injection.service_provider_abc import ServiceProviderABC
from cpl_core.environment.application_environment_abc import ApplicationEnvironmentABC
class Startup(StartupABC): class Startup(StartupABC):
@@ -34,59 +36,28 @@ class Startup(StartupABC):
def __init__(self): def __init__(self):
StartupABC.__init__(self) StartupABC.__init__(self)
def configure_configuration(self, configuration: ConfigurationABC, environment: ApplicationEnvironment) -> ConfigurationABC: def configure_configuration(self, configuration: ConfigurationABC, environment: ApplicationEnvironmentABC) -> ConfigurationABC:
environment.set_runtime_directory(os.path.dirname(__file__)) environment.set_runtime_directory(os.path.dirname(__file__))
configuration.argument_error_function = Error.error configuration.argument_error_function = Error.error
configuration.add_environment_variables('PYTHON_') configuration.add_environment_variables('PYTHON_')
configuration.add_environment_variables('CPL_') configuration.add_environment_variables('CPL_')
is_unittest = configuration.get_configuration('IS_UNITTEST')
if is_unittest == 'YES':
Console.disable()
configuration.add_json_file('appsettings.json', path=environment.runtime_directory, optional=False, output=False) configuration.add_json_file('appsettings.json', path=environment.runtime_directory, optional=False, output=False)
configuration.add_json_file('cpl-workspace.json', path=environment.working_directory, optional=True, output=False)
configuration.create_console_argument(ArgumentTypeEnum.Executable, '', 'add', ['a', 'A'], AddService) \
.add_console_argument(ArgumentTypeEnum.Flag, '--', 'simulate', ['s', 'S'])
configuration.create_console_argument(ArgumentTypeEnum.Executable, '', 'build', ['b', 'B'], BuildService)
configuration.create_console_argument(ArgumentTypeEnum.Executable, '', 'generate', ['g', 'G'], GenerateService) \
.add_console_argument(ArgumentTypeEnum.Variable, '', 'abc', ['a', 'A'], ' ') \
.add_console_argument(ArgumentTypeEnum.Variable, '', 'class', ['c', 'C'], ' ') \
.add_console_argument(ArgumentTypeEnum.Variable, '', 'enum', ['e', 'E'], ' ') \
.add_console_argument(ArgumentTypeEnum.Variable, '', 'service', ['s', 'S'], ' ') \
.add_console_argument(ArgumentTypeEnum.Variable, '', 'settings', ['st', 'ST'], ' ') \
.add_console_argument(ArgumentTypeEnum.Variable, '', 'thread', ['t', 't'], ' ')
configuration.create_console_argument(ArgumentTypeEnum.Executable, '', 'install', ['i', 'I'], InstallService) \
.add_console_argument(ArgumentTypeEnum.Flag, '--', 'virtual', ['v', 'V']) \
.add_console_argument(ArgumentTypeEnum.Flag, '--', 'simulate', ['s', 'S'])
configuration.create_console_argument(ArgumentTypeEnum.Executable, '', 'new', ['n', 'N'], NewService) \
.add_console_argument(ArgumentTypeEnum.Variable, '', 'console', ['c', 'C'], ' ') \
.add_console_argument(ArgumentTypeEnum.Variable, '', 'library', ['l', 'L'], ' ')
configuration.create_console_argument(ArgumentTypeEnum.Executable, '', 'publish', ['p', 'P'], PublishService)
configuration.create_console_argument(ArgumentTypeEnum.Executable, '', 'remove', ['r', 'R'], RemoveService) \
.add_console_argument(ArgumentTypeEnum.Flag, '--', 'simulate', ['s', 'S'])
configuration.create_console_argument(ArgumentTypeEnum.Executable, '', 'start', ['S', 'S'], StartService)
configuration.create_console_argument(ArgumentTypeEnum.Executable, '', 'uninstall', ['ui', 'UI'], UninstallService) \
.add_console_argument(ArgumentTypeEnum.Flag, '--', 'virtual', ['v', 'V']) \
.add_console_argument(ArgumentTypeEnum.Flag, '--', 'simulate', ['s', 'S'])
configuration.create_console_argument(ArgumentTypeEnum.Executable, '', 'update', ['u', 'U'], UpdateService)
configuration.create_console_argument(ArgumentTypeEnum.Executable, '', 'version', ['v', 'V'], VersionService)
configuration.for_each_argument(
lambda a: a.add_console_argument(ArgumentTypeEnum.Executable, '--', 'help', ['h', 'H'], HelpService)
)
configuration.create_console_argument(ArgumentTypeEnum.Executable, '', 'help', ['h', 'H'], HelpService)
workspace: Optional[WorkspaceSettings] = configuration.get_configuration(WorkspaceSettings)
if workspace is not None:
for script in workspace.scripts:
configuration.create_console_argument(ArgumentTypeEnum.Executable, '', script, [], CustomScriptService)
return configuration return configuration
def configure_services(self, services: ServiceCollectionABC, environment: ApplicationEnvironment) -> ServiceProviderABC: def configure_services(self, services: ServiceCollectionABC, environment: ApplicationEnvironmentABC) -> ServiceProviderABC:
# services.add_singleton(CommandHandler)
services.add_transient(PublisherABC, PublisherService) services.add_transient(PublisherABC, PublisherService)
services.add_transient(LiveServerService) services.add_transient(LiveServerService)
services.add_transient(WorkspaceValidator)
services.add_transient(ProjectValidator)
services.add_transient(AddService) services.add_transient(AddService)
services.add_transient(BuildService) services.add_transient(BuildService)
services.add_transient(CustomScriptService) services.add_transient(CustomScriptService)
@@ -96,6 +67,7 @@ class Startup(StartupABC):
services.add_transient(NewService) services.add_transient(NewService)
services.add_transient(PublishService) services.add_transient(PublishService)
services.add_transient(RemoveService) services.add_transient(RemoveService)
services.add_transient(RunService)
services.add_transient(StartService) services.add_transient(StartService)
services.add_transient(UninstallService) services.add_transient(UninstallService)
services.add_transient(UpdateService) services.add_transient(UpdateService)

View File

@@ -0,0 +1,73 @@
from cpl_cli.command.add_service import AddService
from cpl_cli.command.build_service import BuildService
from cpl_cli.command.generate_service import GenerateService
from cpl_cli.command.help_service import HelpService
from cpl_cli.command.install_service import InstallService
from cpl_cli.command.new_service import NewService
from cpl_cli.command.publish_service import PublishService
from cpl_cli.command.remove_service import RemoveService
from cpl_cli.command.run_service import RunService
from cpl_cli.command.start_service import StartService
from cpl_cli.command.uninstall_service import UninstallService
from cpl_cli.command.update_service import UpdateService
from cpl_cli.command.version_service import VersionService
from cpl_cli.validators.project_validator import ProjectValidator
from cpl_cli.validators.workspace_validator import WorkspaceValidator
from cpl_core.application.startup_extension_abc import StartupExtensionABC
from cpl_core.configuration.argument_type_enum import ArgumentTypeEnum
from cpl_core.configuration.configuration_abc import ConfigurationABC
from cpl_core.dependency_injection.service_collection_abc import ServiceCollectionABC
from cpl_core.environment.application_environment_abc import ApplicationEnvironmentABC
class StartupArgumentExtension(StartupExtensionABC):
def __init__(self):
pass
def configure_configuration(self, config: ConfigurationABC, env: ApplicationEnvironmentABC):
config.create_console_argument(ArgumentTypeEnum.Executable, '', 'add', ['a', 'A'], AddService, True, validators=[WorkspaceValidator]) \
.add_console_argument(ArgumentTypeEnum.Flag, '--', 'simulate', ['s', 'S'])
config.create_console_argument(ArgumentTypeEnum.Executable, '', 'build', ['b', 'B'], BuildService, True, validators=[ProjectValidator])
config.create_console_argument(ArgumentTypeEnum.Executable, '', 'generate', ['g', 'G'], GenerateService, True) \
.add_console_argument(ArgumentTypeEnum.Variable, '', 'abc', ['a', 'A'], ' ') \
.add_console_argument(ArgumentTypeEnum.Variable, '', 'class', ['c', 'C'], ' ') \
.add_console_argument(ArgumentTypeEnum.Variable, '', 'enum', ['e', 'E'], ' ') \
.add_console_argument(ArgumentTypeEnum.Variable, '', 'pipe', ['p', 'P'], ' ') \
.add_console_argument(ArgumentTypeEnum.Variable, '', 'service', ['s', 'S'], ' ') \
.add_console_argument(ArgumentTypeEnum.Variable, '', 'settings', ['st', 'ST'], ' ') \
.add_console_argument(ArgumentTypeEnum.Variable, '', 'test_case', ['tc', 'TC'], ' ') \
.add_console_argument(ArgumentTypeEnum.Variable, '', 'thread', ['t', 'T'], ' ') \
.add_console_argument(ArgumentTypeEnum.Variable, '', 'validator', ['v', 'V'], ' ')
config.create_console_argument(ArgumentTypeEnum.Executable, '', 'install', ['i', 'I'], InstallService, True, validators=[ProjectValidator]) \
.add_console_argument(ArgumentTypeEnum.Flag, '--', 'dev', ['d', 'D']) \
.add_console_argument(ArgumentTypeEnum.Flag, '--', 'virtual', ['v', 'V']) \
.add_console_argument(ArgumentTypeEnum.Flag, '--', 'simulate', ['s', 'S'])
config.create_console_argument(ArgumentTypeEnum.Executable, '', 'new', ['n', 'N'], NewService, True) \
.add_console_argument(ArgumentTypeEnum.Variable, '', 'console', ['c', 'C'], ' ') \
.add_console_argument(ArgumentTypeEnum.Variable, '', 'library', ['l', 'L'], ' ') \
.add_console_argument(ArgumentTypeEnum.Variable, '', 'unittest', ['ut', 'UT'], ' ') \
.add_console_argument(ArgumentTypeEnum.Flag, '--', 'async', ['a', 'A']) \
.add_console_argument(ArgumentTypeEnum.Flag, '--', 'application-base', ['ab', 'AB']) \
.add_console_argument(ArgumentTypeEnum.Flag, '--', 'startup', ['s', 'S']) \
.add_console_argument(ArgumentTypeEnum.Flag, '--', 'service-providing', ['sp', 'SP']) \
.add_console_argument(ArgumentTypeEnum.Flag, '--', 'nothing', ['n', 'N']) \
.add_console_argument(ArgumentTypeEnum.Flag, '--', 'venv', ['v', 'V'])
config.create_console_argument(ArgumentTypeEnum.Executable, '', 'publish', ['p', 'P'], PublishService, True, validators=[ProjectValidator])
config.create_console_argument(ArgumentTypeEnum.Executable, '', 'remove', ['r', 'R'], RemoveService, True, validators=[WorkspaceValidator]) \
.add_console_argument(ArgumentTypeEnum.Flag, '--', 'simulate', ['s', 'S'])
config.create_console_argument(ArgumentTypeEnum.Executable, '', 'run', [], RunService, True, validators=[ProjectValidator])
config.create_console_argument(ArgumentTypeEnum.Executable, '', 'start', ['s', 'S'], StartService, True, validators=[ProjectValidator])
config.create_console_argument(ArgumentTypeEnum.Executable, '', 'uninstall', ['ui', 'UI'], UninstallService, True, validators=[ProjectValidator]) \
.add_console_argument(ArgumentTypeEnum.Flag, '--', 'dev', ['d', 'D']) \
.add_console_argument(ArgumentTypeEnum.Flag, '--', 'virtual', ['v', 'V']) \
.add_console_argument(ArgumentTypeEnum.Flag, '--', 'simulate', ['s', 'S'])
config.create_console_argument(ArgumentTypeEnum.Executable, '', 'update', ['u', 'U'], UpdateService, True, validators=[ProjectValidator]) \
.add_console_argument(ArgumentTypeEnum.Flag, '--', 'simulate', ['s', 'S'])
config.create_console_argument(ArgumentTypeEnum.Executable, '', 'version', ['v', 'V'], VersionService, True)
config.for_each_argument(lambda a: a.add_console_argument(ArgumentTypeEnum.Flag, '--', 'help', ['h', 'H']))
config.create_console_argument(ArgumentTypeEnum.Executable, '', 'help', ['h', 'H'], HelpService)
def configure_services(self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC):
pass

View File

@@ -0,0 +1,55 @@
import os
from typing import Optional
from cpl_cli.command.custom_script_service import CustomScriptService
from cpl_cli.configuration.workspace_settings import WorkspaceSettings
from cpl_core.application.startup_extension_abc import StartupExtensionABC
from cpl_core.configuration.argument_type_enum import ArgumentTypeEnum
from cpl_core.configuration.configuration_abc import ConfigurationABC
from cpl_core.dependency_injection.service_collection_abc import ServiceCollectionABC
from cpl_core.environment.application_environment_abc import ApplicationEnvironmentABC
from cpl_core.utils.string import String
class StartupWorkspaceExtension(StartupExtensionABC):
def __init__(self):
pass
@staticmethod
def _search_project_json(working_directory: str) -> Optional[str]:
project_name = None
name = os.path.basename(working_directory)
for r, d, f in os.walk(working_directory):
for file in f:
if file.endswith('.json'):
f_name = file.split('.json')[0]
if f_name == name or String.convert_to_camel_case(f_name).lower() == String.convert_to_camel_case(name).lower():
project_name = f_name
break
return project_name
def _read_cpl_environment(self, config: ConfigurationABC, env: ApplicationEnvironmentABC):
workspace: Optional[WorkspaceSettings] = config.get_configuration(WorkspaceSettings)
config.add_configuration('PATH_WORKSPACE', env.working_directory)
if workspace is not None:
for script in workspace.scripts:
config.create_console_argument(ArgumentTypeEnum.Executable, '', script, [], CustomScriptService)
return
project = self._search_project_json(env.working_directory)
if project is not None:
project = f'{project}.json'
if project is None:
return
config.add_json_file(project, optional=True, output=False)
def configure_configuration(self, config: ConfigurationABC, env: ApplicationEnvironmentABC):
config.add_json_file('cpl-workspace.json', path=env.working_directory, optional=True, output=False)
self._read_cpl_environment(config, env)
def configure_services(self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC):
pass

View File

@@ -0,0 +1,25 @@
# -*- coding: utf-8 -*-
"""
cpl-cli sh-edraft Common Python library CLI
~~~~~~~~~~~~~~~~~~~
sh-edraft Common Python library Command Line Interface
:copyright: (c) 2020 - 2022 sh-edraft.de
:license: MIT, see LICENSE for more details.
"""
__title__ = 'cpl_cli.validators'
__author__ = 'Sven Heidemann'
__license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de'
__version__ = '2022.6.0rc1'
from collections import namedtuple
# imports:
VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='2022', minor='6', micro='0.rc1')

View File

@@ -0,0 +1,30 @@
import os
from cpl_cli import Error
from cpl_cli.configuration import WorkspaceSettings, ProjectSettings
from cpl_core.configuration import ConfigurationABC
from cpl_core.configuration.validator_abc import ValidatorABC
from cpl_core.environment import ApplicationEnvironmentABC
class ProjectValidator(ValidatorABC):
def __init__(self, config: ConfigurationABC, env: ApplicationEnvironmentABC, workspace: WorkspaceSettings, project: ProjectSettings):
self._config: ConfigurationABC = config
self._env: ApplicationEnvironmentABC = env
self._workspace: WorkspaceSettings = workspace
self._project: ProjectSettings = project
ValidatorABC.__init__(self)
def validate(self) -> bool:
if self._project is None and self._workspace is not None:
project = self._workspace.projects[self._workspace.default_project]
self._config.add_json_file(project, optional=True, output=False)
self._project = self._config.get_configuration(ProjectSettings)
self._env.set_working_directory(os.path.join(self._env.working_directory, os.path.dirname(project)))
result = self._project is not None or self._workspace is not None
if not result:
Error.error('The command requires to be run in an CPL project, but a project could not be found.')
return result

View File

@@ -0,0 +1,17 @@
from cpl_cli import Error
from cpl_cli.configuration import WorkspaceSettings
from cpl_core.configuration.validator_abc import ValidatorABC
class WorkspaceValidator(ValidatorABC):
def __init__(self, workspace: WorkspaceSettings):
self._workspace = workspace
ValidatorABC.__init__(self)
def validate(self) -> bool:
result = self._workspace is not None
if not result:
Error.error('The command requires to be run in an CPL workspace, but a workspace could not be found.')
return result

View File

@@ -15,11 +15,11 @@ __title__ = 'cpl_core'
__author__ = 'Sven Heidemann' __author__ = 'Sven Heidemann'
__license__ = 'MIT' __license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de'
__version__ = '2022.6.3.dev2' __version__ = '2022.6.0rc1'
from collections import namedtuple from collections import namedtuple
# imports: # imports:
VersionInfo = namedtuple('VersionInfo', 'major minor micro') VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='2022', minor='6', micro='3.dev2') version_info = VersionInfo(major='2022', minor='6', micro='0.rc1')

View File

@@ -15,7 +15,7 @@ __title__ = 'cpl_core.application'
__author__ = 'Sven Heidemann' __author__ = 'Sven Heidemann'
__license__ = 'MIT' __license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de'
__version__ = '2022.6.3.dev2' __version__ = '2022.6.0rc1'
from collections import namedtuple from collections import namedtuple
@@ -28,4 +28,4 @@ from .startup_abc import StartupABC
from .startup_extension_abc import StartupExtensionABC from .startup_extension_abc import StartupExtensionABC
VersionInfo = namedtuple('VersionInfo', 'major minor micro') VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='2022', minor='6', micro='3.dev2') version_info = VersionInfo(major='2022', minor='6', micro='0.rc1')

View File

@@ -4,7 +4,7 @@ from typing import Optional
from cpl_core.configuration.configuration_abc import ConfigurationABC from cpl_core.configuration.configuration_abc import ConfigurationABC
from cpl_core.console.console import Console from cpl_core.console.console import Console
from cpl_core.dependency_injection.service_provider_abc import ServiceProviderABC from cpl_core.dependency_injection.service_provider_abc import ServiceProviderABC
from cpl_core.environment import ApplicationEnvironmentABC from cpl_core.environment.application_environment_abc import ApplicationEnvironmentABC
class ApplicationABC(ABC): class ApplicationABC(ABC):

View File

@@ -10,7 +10,7 @@ from cpl_core.dependency_injection.service_collection import ServiceCollection
class ApplicationBuilder(ApplicationBuilderABC): class ApplicationBuilder(ApplicationBuilderABC):
r"""This is class is used to build a object of :class:`cpl_core.application.application_abc.ApplicationABC` r"""This is class is used to build an object of :class:`cpl_core.application.application_abc.ApplicationABC`
Parameter Parameter
--------- ---------
@@ -54,8 +54,6 @@ class ApplicationBuilder(ApplicationBuilderABC):
config = self._configuration config = self._configuration
services = self._services.build_service_provider() services = self._services.build_service_provider()
config.resolve_runnable_argument_types(services)
config.parse_console_arguments()
for ex in self._app_extensions: for ex in self._app_extensions:
extension = ex() extension = ex()

View File

@@ -15,7 +15,7 @@ __title__ = 'cpl_core.configuration'
__author__ = 'Sven Heidemann' __author__ = 'Sven Heidemann'
__license__ = 'MIT' __license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de'
__version__ = '2022.6.3.dev2' __version__ = '2022.6.0rc1'
from collections import namedtuple from collections import namedtuple
@@ -30,7 +30,8 @@ from .configuration_model_abc import ConfigurationModelABC
from .configuration_variable_name_enum import ConfigurationVariableNameEnum from .configuration_variable_name_enum import ConfigurationVariableNameEnum
from .executable_argument import ExecutableArgument from .executable_argument import ExecutableArgument
from .flag_argument import FlagArgument from .flag_argument import FlagArgument
from .validator_abc import ValidatorABC
from .variable_argument import VariableArgument from .variable_argument import VariableArgument
VersionInfo = namedtuple('VersionInfo', 'major minor micro') VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='2022', minor='6', micro='3.dev2') version_info = VersionInfo(major='2022', minor='6', micro='0.rc1')

View File

@@ -10,6 +10,7 @@ class ArgumentABC(ABC):
token: str, token: str,
name: str, name: str,
aliases: list[str], aliases: list[str],
prevent_next_executable: bool = False,
console_arguments: list['ArgumentABC'] = None console_arguments: list['ArgumentABC'] = None
): ):
r"""Representation of an console argument r"""Representation of an console argument
@@ -24,6 +25,7 @@ class ArgumentABC(ABC):
self._token = token self._token = token
self._name = name self._name = name
self._aliases = aliases self._aliases = aliases
self._prevent_next_executable = prevent_next_executable
self._console_arguments = console_arguments if console_arguments is not None else [] self._console_arguments = console_arguments if console_arguments is not None else []
@property @property
@@ -38,6 +40,10 @@ class ArgumentABC(ABC):
def aliases(self) -> list[str]: def aliases(self) -> list[str]:
return self._aliases return self._aliases
@property
def prevent_next_executable(self) -> bool:
return self._prevent_next_executable
@property @property
def console_arguments(self) -> list['ArgumentABC']: def console_arguments(self) -> list['ArgumentABC']:
return self._console_arguments return self._console_arguments

View File

@@ -7,4 +7,4 @@ class ArgumentExecutableABC(ABC):
def __init__(self): pass def __init__(self): pass
@abstractmethod @abstractmethod
def run(self, args: list[str]): pass def execute(self, args: list[str]): pass

View File

@@ -1,21 +1,24 @@
import json import json
import os import os
import sys import sys
import traceback
from collections.abc import Callable from collections.abc import Callable
from typing import Union, Type, Optional from typing import Union, Type, Optional
from cpl_core.configuration.argument_abc import ArgumentABC from cpl_core.configuration.argument_abc import ArgumentABC
from cpl_core.configuration.argument_builder import ArgumentBuilder from cpl_core.configuration.argument_builder import ArgumentBuilder
from cpl_core.configuration.argument_executable_abc import ArgumentExecutableABC
from cpl_core.configuration.argument_type_enum import ArgumentTypeEnum from cpl_core.configuration.argument_type_enum import ArgumentTypeEnum
from cpl_core.configuration.configuration_abc import ConfigurationABC from cpl_core.configuration.configuration_abc import ConfigurationABC
from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC
from cpl_core.configuration.configuration_variable_name_enum import ConfigurationVariableNameEnum from cpl_core.configuration.configuration_variable_name_enum import ConfigurationVariableNameEnum
from cpl_core.configuration.executable_argument import ExecutableArgument from cpl_core.configuration.executable_argument import ExecutableArgument
from cpl_core.configuration.flag_argument import FlagArgument from cpl_core.configuration.flag_argument import FlagArgument
from cpl_core.configuration.validator_abc import ValidatorABC
from cpl_core.configuration.variable_argument import VariableArgument from cpl_core.configuration.variable_argument import VariableArgument
from cpl_core.console.console import Console from cpl_core.console.console import Console
from cpl_core.console.foreground_color_enum import ForegroundColorEnum from cpl_core.console.foreground_color_enum import ForegroundColorEnum
from cpl_core.dependency_injection import ServiceProviderABC from cpl_core.dependency_injection.service_provider_abc import ServiceProviderABC
from cpl_core.environment.application_environment import ApplicationEnvironment from cpl_core.environment.application_environment import ApplicationEnvironment
from cpl_core.environment.application_environment_abc import ApplicationEnvironmentABC from cpl_core.environment.application_environment_abc import ApplicationEnvironmentABC
from cpl_core.environment.environment_name_enum import EnvironmentNameEnum from cpl_core.environment.environment_name_enum import EnvironmentNameEnum
@@ -53,6 +56,10 @@ class Configuration(ConfigurationABC):
def argument_error_function(self, argument_error_function: Callable): def argument_error_function(self, argument_error_function: Callable):
self._argument_error_function = argument_error_function self._argument_error_function = argument_error_function
@property
def arguments(self) -> list[ArgumentABC]:
return self._argument_types
@staticmethod @staticmethod
def _print_info(name: str, message: str): def _print_info(name: str, message: str):
r"""Prints an info message r"""Prints an info message
@@ -147,21 +154,46 @@ class Configuration(ConfigurationABC):
self._print_error(__name__, f'Cannot load config file: {file}! -> {e}') self._print_error(__name__, f'Cannot load config file: {file}! -> {e}')
return {} return {}
def _parse_arguments(self, call_stack: list[Callable], arg_list: list[str], args_types: list[ArgumentABC]): def _handle_pre_or_post_executables(self, pre: bool, argument: ExecutableArgument, services: ServiceProviderABC):
script_type = 'pre-' if pre else 'post-'
from cpl_cli.configuration.workspace_settings import WorkspaceSettings
workspace: Optional[WorkspaceSettings] = self.get_configuration(WorkspaceSettings)
if workspace is None or len(workspace.scripts) == 0:
return
for script in workspace.scripts:
if script_type not in script and not script.startswith(script_type):
continue
# split in two ifs to prevent exception
if script.split(script_type)[1] != argument.name:
continue
from cpl_cli.command.custom_script_service import CustomScriptService
css: CustomScriptService = services.get_service(CustomScriptService)
if css is None:
continue
Console.write_line()
self._set_variable('ACTIVE_EXECUTABLE', script)
css.run([])
def _parse_arguments(self, executables: list[ArgumentABC], arg_list: list[str], args_types: list[ArgumentABC]):
for i in range(0, len(arg_list)): for i in range(0, len(arg_list)):
arg_str = arg_list[i] arg_str = arg_list[i]
for arg in args_types: for n in range(0, len(args_types)):
arg = args_types[n]
arg_str_without_token = arg_str arg_str_without_token = arg_str
if arg.token != "" and arg.token in arg_str: if arg.token != "" and arg.token in arg_str:
arg_str_without_token = arg_str.split(arg.token)[1] arg_str_without_token = arg_str.split(arg.token)[1]
# executable # executable
if isinstance(arg, ExecutableArgument): if isinstance(arg, ExecutableArgument):
if arg_str.startswith(arg.token) \ if arg_str.startswith(arg.token) and arg_str_without_token == arg.name or arg_str_without_token in arg.aliases:
and arg_str_without_token == arg.name or arg_str_without_token in arg.aliases: executables.append(arg)
call_stack.append(arg.run) self._handled_args.append(arg_str)
self._parse_arguments(call_stack, arg_list[i + 1:], arg.console_arguments) self._parse_arguments(executables, arg_list[i + 1:], arg.console_arguments)
break
# variables # variables
elif isinstance(arg, VariableArgument): elif isinstance(arg, VariableArgument):
@@ -169,33 +201,35 @@ class Configuration(ConfigurationABC):
if arg.value_token in arg_str_without_value: if arg.value_token in arg_str_without_value:
arg_str_without_value = arg_str_without_token.split(arg.value_token)[0] arg_str_without_value = arg_str_without_token.split(arg.value_token)[0]
if arg_str.startswith(arg.token) \ if arg_str.startswith(arg.token) and arg_str_without_value == arg.name or arg_str_without_value in arg.aliases:
and arg_str_without_value == arg.name or arg_str_without_value in arg.aliases:
if arg.value_token != ' ': if arg.value_token != ' ':
value = arg_str_without_token.split(arg.value_token)[1] value = arg_str_without_token.split(arg.value_token)[1]
else: else:
value = arg_list[i + 1] value = arg_list[i + 1]
self._set_variable(arg.name, value) self._set_variable(arg.name, value)
self._parse_arguments(call_stack, arg_list[i + 1:], arg.console_arguments) self._handled_args.append(arg_str)
break self._handled_args.append(value)
self._parse_arguments(executables, arg_list[i + 1:], arg.console_arguments)
# flags # flags
elif isinstance(arg, FlagArgument): elif isinstance(arg, FlagArgument):
if arg_str.startswith(arg.token) \ if arg_str.startswith(arg.token) and arg_str_without_token == arg.name or arg_str_without_token in arg.aliases:
and arg_str_without_token == arg.name or arg_str_without_token in arg.aliases: if arg_str in self._additional_arguments:
self._additional_arguments.remove(arg_str)
self._additional_arguments.append(arg.name) self._additional_arguments.append(arg.name)
self._parse_arguments(call_stack, arg_list[i + 1:], arg.console_arguments) self._handled_args.append(arg_str)
break self._parse_arguments(executables, arg_list[i + 1:], arg.console_arguments)
# add left over values to args # add left over values to args
if arg_str not in self._additional_arguments: if arg_str not in self._additional_arguments and arg_str not in self._handled_args:
self._additional_arguments.append(arg_str) self._additional_arguments.append(arg_str)
def add_environment_variables(self, prefix: str): def add_environment_variables(self, prefix: str):
for variable in ConfigurationVariableNameEnum.to_list(): for env_var in os.environ.keys():
var_name = f'{prefix}{variable}' if not env_var.startswith(prefix):
if var_name in [key.upper() for key in os.environ.keys()]: continue
self._set_variable(variable, os.environ[var_name])
self._set_variable(env_var.replace(prefix, ''), os.environ[env_var])
def add_console_argument(self, argument: ArgumentABC): def add_console_argument(self, argument: ArgumentABC):
self._argument_types.append(argument) self._argument_types.append(argument)
@@ -233,12 +267,12 @@ class Configuration(ConfigurationABC):
configuration.from_dict(value) configuration.from_dict(value)
self.add_configuration(sub, configuration) self.add_configuration(sub, configuration)
def add_configuration(self, key_type: Union[str, type], value: ConfigurationModelABC): def add_configuration(self, key_type: Union[str, type], value: Union[str, ConfigurationModelABC]):
self._config[key_type] = value self._config[key_type] = value
def create_console_argument(self, arg_type: ArgumentTypeEnum, token: str, name: str, aliases: list[str], def create_console_argument(self, arg_type: ArgumentTypeEnum, token: str, name: str, aliases: list[str],
*args, **kwargs) -> ArgumentABC: *args, **kwargs) -> ArgumentABC:
argument = ArgumentBuilder.build_argument(arg_type, token, name, aliases, *args, *kwargs) argument = ArgumentBuilder.build_argument(arg_type, token, name, aliases, *args, **kwargs)
self._argument_types.append(argument) self._argument_types.append(argument)
return argument return argument
@@ -265,19 +299,47 @@ class Configuration(ConfigurationABC):
if config_model == search_type: if config_model == search_type:
return self._config[config_model] return self._config[config_model]
def parse_console_arguments(self, error: bool = None): def parse_console_arguments(self, services: ServiceProviderABC, error: bool = None) -> bool:
# sets environment variables as possible arguments as: --VAR=VALUE # sets environment variables as possible arguments as: --VAR=VALUE
for arg_name in ConfigurationVariableNameEnum.to_list(): for arg_name in ConfigurationVariableNameEnum.to_list():
self.add_console_argument(VariableArgument('--', str(arg_name).upper(), [str(arg_name).lower()], '=')) self.add_console_argument(VariableArgument('--', str(arg_name).upper(), [str(arg_name).lower()], '='))
arg_list = sys.argv[1:] success = False
call_stack = [] try:
self._parse_arguments(call_stack, arg_list, self._argument_types) arg_list = sys.argv[1:]
executables: list[ExecutableArgument] = []
self._parse_arguments(executables, arg_list, self._argument_types)
except Exception as e:
Console.error('An error occurred while parsing arguments.')
sys.exit()
for call in call_stack: try:
call(self._additional_arguments) prevent = False
for exe in executables:
if prevent:
continue
def resolve_runnable_argument_types(self, services: ServiceProviderABC): if exe.validators is not None:
for arg in self._argument_types: abort = False
if isinstance(arg, ExecutableArgument): for validator_type in exe.validators:
arg.set_executable(services.get_service(arg.executable_type)) validator: ValidatorABC = services.get_service(validator_type)
result = validator.validate()
abort = not result
if abort:
break
if abort:
sys.exit()
cmd: ArgumentExecutableABC = services.get_service(exe.executable_type)
self._handle_pre_or_post_executables(True, exe, services)
self._set_variable('ACTIVE_EXECUTABLE', exe.name)
cmd.execute(self._additional_arguments)
self._handle_pre_or_post_executables(False, exe, services)
prevent = exe.prevent_next_executable
success = True
except Exception as e:
Console.error('An error occurred while executing arguments.', traceback.format_exc())
sys.exit()
return success

View File

@@ -31,6 +31,10 @@ class ConfigurationABC(ABC):
@abstractmethod @abstractmethod
def argument_error_function(self, argument_error_function: Callable): pass def argument_error_function(self, argument_error_function: Callable): pass
@property
@abstractmethod
def arguments(self) -> list[ArgumentABC]: pass
@abstractmethod @abstractmethod
def add_environment_variables(self, prefix: str): def add_environment_variables(self, prefix: str):
r"""Reads the environment variables r"""Reads the environment variables
@@ -137,23 +141,16 @@ class ConfigurationABC(ABC):
pass pass
@abstractmethod @abstractmethod
def parse_console_arguments(self, error: bool = None): def parse_console_arguments(self, services: 'ServiceProviderABC', error: bool = None) -> bool:
r"""Reads the console arguments r"""Reads the console arguments
Parameter Parameter
--------- ---------
error: :class:`bool` error: :class:`bool`
Defines is invalid argument error will be shown or not Defines is invalid argument error will be shown or not
"""
pass Returns
-------
@abstractmethod Bool to specify if executables were executed or not.
def resolve_runnable_argument_types(self, services: 'ServiceProviderABC'):
r"""Gets all objects for given types of ConsoleArguments
Parameter
---------
services: :class:`cpl_core.dependency_injection.service_provider_abc.ServiceProviderABC`
Provides services
""" """
pass pass

View File

@@ -2,6 +2,7 @@ from typing import Type, Optional
from cpl_core.configuration.argument_executable_abc import ArgumentExecutableABC from cpl_core.configuration.argument_executable_abc import ArgumentExecutableABC
from cpl_core.configuration.argument_abc import ArgumentABC from cpl_core.configuration.argument_abc import ArgumentABC
from cpl_core.configuration.validator_abc import ValidatorABC
class ExecutableArgument(ArgumentABC): class ExecutableArgument(ArgumentABC):
@@ -11,13 +12,16 @@ class ExecutableArgument(ArgumentABC):
name: str, name: str,
aliases: list[str], aliases: list[str],
executable: Type[ArgumentExecutableABC], executable: Type[ArgumentExecutableABC],
prevent_next_executable: bool = False,
validators: list[Type[ValidatorABC]] = None,
console_arguments: list['ArgumentABC'] = None console_arguments: list['ArgumentABC'] = None
): ):
self._executable_type = executable self._executable_type = executable
self._validators = validators
self._executable: Optional[ArgumentExecutableABC] = None self._executable: Optional[ArgumentExecutableABC] = None
ArgumentABC.__init__(self, token, name, aliases, console_arguments) ArgumentABC.__init__(self, token, name, aliases, prevent_next_executable, console_arguments)
@property @property
def executable_type(self) -> type: def executable_type(self) -> type:
@@ -26,9 +30,13 @@ class ExecutableArgument(ArgumentABC):
def set_executable(self, executable: ArgumentExecutableABC): def set_executable(self, executable: ArgumentExecutableABC):
self._executable = executable self._executable = executable
@property
def validators(self) -> list[Type[ValidatorABC]]:
return self._validators
def run(self, args: list[str]): def run(self, args: list[str]):
r"""Executes runnable if exists r"""Executes runnable if exists
""" """
if self._executable is None: if self._executable is None:
return return
self._executable.run(args) self._executable.execute(args)

View File

@@ -7,7 +7,8 @@ class FlagArgument(ArgumentABC):
token: str, token: str,
name: str, name: str,
aliases: list[str], aliases: list[str],
prevent_next_executable: bool = False,
console_arguments: list['ArgumentABC'] = None console_arguments: list['ArgumentABC'] = None
): ):
ArgumentABC.__init__(self, token, name, aliases, console_arguments) ArgumentABC.__init__(self, token, name, aliases, prevent_next_executable, console_arguments)

View File

@@ -0,0 +1,10 @@
from abc import ABC, abstractmethod
class ValidatorABC(ABC):
@abstractmethod
def __init__(self): pass
@abstractmethod
def validate(self) -> bool: pass

View File

@@ -8,12 +8,13 @@ class VariableArgument(ArgumentABC):
name: str, name: str,
aliases: list[str], aliases: list[str],
value_token: str, value_token: str,
prevent_next_executable: bool = False,
console_arguments: list['ArgumentABC'] = None console_arguments: list['ArgumentABC'] = None
): ):
self._value_token = value_token self._value_token = value_token
self._value: str = '' self._value: str = ''
ArgumentABC.__init__(self, token, name, aliases, console_arguments) ArgumentABC.__init__(self, token, name, aliases, prevent_next_executable, console_arguments)
@property @property
def value_token(self) -> str: def value_token(self) -> str:

View File

@@ -15,7 +15,7 @@ __title__ = 'cpl_core.console'
__author__ = 'Sven Heidemann' __author__ = 'Sven Heidemann'
__license__ = 'MIT' __license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de'
__version__ = '2022.6.3.dev2' __version__ = '2022.6.0rc1'
from collections import namedtuple from collections import namedtuple
@@ -27,4 +27,4 @@ from .foreground_color_enum import ForegroundColorEnum
from .spinner_thread import SpinnerThread from .spinner_thread import SpinnerThread
VersionInfo = namedtuple('VersionInfo', 'major minor micro') VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='2022', minor='6', micro='3.dev2') version_info = VersionInfo(major='2022', minor='6', micro='0.rc1')

View File

@@ -456,17 +456,21 @@ class Console:
cls.write_line(message) cls.write_line(message)
cls.set_hold_back(True) cls.set_hold_back(True)
spinner = SpinnerThread(len(message), spinner_foreground_color, spinner_background_color) spinner = None
spinner.start() if not cls._disabled:
spinner = SpinnerThread(len(message), spinner_foreground_color, spinner_background_color)
spinner.start()
return_value = None return_value = None
try: try:
return_value = call(*args, **kwargs) return_value = call(*args, **kwargs)
except KeyboardInterrupt: except KeyboardInterrupt:
spinner.exit() if spinner is not None:
spinner.exit()
cls.close() cls.close()
spinner.stop_spinning() if spinner is not None:
spinner.stop_spinning()
cls.set_hold_back(False) cls.set_hold_back(False)
cls.set_foreground_color(ForegroundColorEnum.default) cls.set_foreground_color(ForegroundColorEnum.default)

View File

@@ -4,7 +4,7 @@
"Version": { "Version": {
"Major": "2022", "Major": "2022",
"Minor": "6", "Minor": "6",
"Micro": "3.dev1" "Micro": "0.rc1"
}, },
"Author": "Sven Heidemann", "Author": "Sven Heidemann",
"AuthorEmail": "sven.heidemann@sh-edraft.de", "AuthorEmail": "sven.heidemann@sh-edraft.de",
@@ -28,6 +28,7 @@
"watchdog==2.1.7", "watchdog==2.1.7",
"wheel==0.37.1" "wheel==0.37.1"
], ],
"DevDependencies": [],
"PythonVersion": ">=3.10", "PythonVersion": ">=3.10",
"PythonPath": {}, "PythonPath": {},
"Classifiers": [] "Classifiers": []

View File

@@ -15,7 +15,7 @@ __title__ = 'cpl_core.database'
__author__ = 'Sven Heidemann' __author__ = 'Sven Heidemann'
__license__ = 'MIT' __license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de'
__version__ = '2022.6.3.dev2' __version__ = '2022.6.0rc1'
from collections import namedtuple from collections import namedtuple
@@ -25,4 +25,4 @@ from .database_settings import DatabaseSettings
from .table_abc import TableABC from .table_abc import TableABC
VersionInfo = namedtuple('VersionInfo', 'major minor micro') VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='2022', minor='6', micro='3.dev2') version_info = VersionInfo(major='2022', minor='6', micro='0.rc1')

View File

@@ -15,7 +15,7 @@ __title__ = 'cpl_core.database.connection'
__author__ = 'Sven Heidemann' __author__ = 'Sven Heidemann'
__license__ = 'MIT' __license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de'
__version__ = '2022.6.3.dev2' __version__ = '2022.6.0rc1'
from collections import namedtuple from collections import namedtuple
@@ -24,4 +24,4 @@ from .database_connection import DatabaseConnection
from .database_connection_abc import DatabaseConnectionABC from .database_connection_abc import DatabaseConnectionABC
VersionInfo = namedtuple('VersionInfo', 'major minor micro') VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='2022', minor='6', micro='3.dev2') version_info = VersionInfo(major='2022', minor='6', micro='0.rc1')

View File

@@ -15,7 +15,7 @@ __title__ = 'cpl_core.database.context'
__author__ = 'Sven Heidemann' __author__ = 'Sven Heidemann'
__license__ = 'MIT' __license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de'
__version__ = '2022.6.3.dev2' __version__ = '2022.6.0rc1'
from collections import namedtuple from collections import namedtuple
@@ -24,4 +24,4 @@ from .database_context import DatabaseContext
from .database_context_abc import DatabaseContextABC from .database_context_abc import DatabaseContextABC
VersionInfo = namedtuple('VersionInfo', 'major minor micro') VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='2022', minor='6', micro='3.dev2') version_info = VersionInfo(major='2022', minor='6', micro='0.rc1')

View File

@@ -15,7 +15,7 @@ __title__ = 'cpl_core.dependency_injection'
__author__ = 'Sven Heidemann' __author__ = 'Sven Heidemann'
__license__ = 'MIT' __license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de'
__version__ = '2022.6.3.dev2' __version__ = '2022.6.0rc1'
from collections import namedtuple from collections import namedtuple
@@ -30,4 +30,4 @@ from .service_provider import ServiceProvider
from .service_provider_abc import ServiceProviderABC from .service_provider_abc import ServiceProviderABC
VersionInfo = namedtuple('VersionInfo', 'major minor micro') VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='2022', minor='6', micro='3.dev2') version_info = VersionInfo(major='2022', minor='6', micro='0.rc1')

View File

@@ -1,15 +1,17 @@
from typing import Union, Type, Callable, Optional from typing import Union, Type, Callable, Optional
from cpl_core.configuration.configuration_abc import ConfigurationABC from cpl_core.configuration.configuration_abc import ConfigurationABC
from cpl_core.database.database_settings import DatabaseSettings from cpl_core.console import Console
from cpl_core.database.context.database_context_abc import DatabaseContextABC from cpl_core.database.context.database_context_abc import DatabaseContextABC
from cpl_core.dependency_injection.service_provider_abc import ServiceProviderABC from cpl_core.database.database_settings import DatabaseSettings
from cpl_core.dependency_injection.service_collection_abc import ServiceCollectionABC from cpl_core.dependency_injection.service_collection_abc import ServiceCollectionABC
from cpl_core.dependency_injection.service_descriptor import ServiceDescriptor from cpl_core.dependency_injection.service_descriptor import ServiceDescriptor
from cpl_core.dependency_injection.service_lifetime_enum import ServiceLifetimeEnum from cpl_core.dependency_injection.service_lifetime_enum import ServiceLifetimeEnum
from cpl_core.dependency_injection.service_provider import ServiceProvider from cpl_core.dependency_injection.service_provider import ServiceProvider
from cpl_core.logging.logger_service import Logger from cpl_core.dependency_injection.service_provider_abc import ServiceProviderABC
from cpl_core.logging.logger_abc import LoggerABC from cpl_core.logging.logger_abc import LoggerABC
from cpl_core.logging.logger_service import Logger
from cpl_core.pipes.pipe_abc import PipeABC
class ServiceCollection(ServiceCollectionABC): class ServiceCollection(ServiceCollectionABC):
@@ -22,7 +24,7 @@ class ServiceCollection(ServiceCollectionABC):
self._database_context: Optional[DatabaseContextABC] = None self._database_context: Optional[DatabaseContextABC] = None
self._service_descriptors: list[ServiceDescriptor] = [] self._service_descriptors: list[ServiceDescriptor] = []
def _add_descriptor(self, service: Union[type, object], lifetime: ServiceLifetimeEnum): def _add_descriptor(self, service: Union[type, object], lifetime: ServiceLifetimeEnum, base_type: Callable = None):
found = False found = False
for descriptor in self._service_descriptors: for descriptor in self._service_descriptors:
if isinstance(service, descriptor.service_type): if isinstance(service, descriptor.service_type):
@@ -35,7 +37,15 @@ class ServiceCollection(ServiceCollectionABC):
raise Exception(f'Service of type {service_type} already exists') raise Exception(f'Service of type {service_type} already exists')
self._service_descriptors.append(ServiceDescriptor(service, lifetime)) self._service_descriptors.append(ServiceDescriptor(service, lifetime, base_type))
def _add_descriptor_by_lifetime(self, service_type: Type, lifetime: ServiceLifetimeEnum, service: Callable = None):
if service is not None:
self._add_descriptor(service, lifetime, service_type)
else:
self._add_descriptor(service_type, lifetime)
return self
def add_db_context(self, db_context_type: Type[DatabaseContextABC], db_settings: DatabaseSettings): def add_db_context(self, db_context_type: Type[DatabaseContextABC], db_settings: DatabaseSettings):
self.add_singleton(DatabaseContextABC, db_context_type) self.add_singleton(DatabaseContextABC, db_context_type)
@@ -45,35 +55,20 @@ class ServiceCollection(ServiceCollectionABC):
def add_logging(self): def add_logging(self):
self.add_singleton(LoggerABC, Logger) self.add_singleton(LoggerABC, Logger)
def add_pipes(self):
for pipe in PipeABC.__subclasses__():
self.add_transient(PipeABC, pipe)
def add_singleton(self, service_type: Union[type, object], service: Union[type, object] = None): def add_singleton(self, service_type: Union[type, object], service: Union[type, object] = None):
impl = None self._add_descriptor_by_lifetime(service_type, ServiceLifetimeEnum.singleton, service)
if service is not None:
if isinstance(service, type):
impl = self.build_service_provider().build_service(service)
self._add_descriptor(impl, ServiceLifetimeEnum.singleton)
else:
if isinstance(service_type, type):
impl = self.build_service_provider().build_service(service_type)
self._add_descriptor(impl, ServiceLifetimeEnum.singleton)
return self return self
def add_scoped(self, service_type: Type, service: Callable = None): def add_scoped(self, service_type: Type, service: Callable = None):
if service is not None: self._add_descriptor_by_lifetime(service_type, ServiceLifetimeEnum.scoped, service)
self._add_descriptor(service, ServiceLifetimeEnum.scoped)
else:
self._add_descriptor(service_type, ServiceLifetimeEnum.scoped)
return self return self
def add_transient(self, service_type: type, service: type = None): def add_transient(self, service_type: type, service: type = None):
if service is not None: self._add_descriptor_by_lifetime(service_type, ServiceLifetimeEnum.transient, service)
self._add_descriptor(service, ServiceLifetimeEnum.transient)
else:
self._add_descriptor(service_type, ServiceLifetimeEnum.transient)
return self return self
def build_service_provider(self) -> ServiceProviderABC: def build_service_provider(self) -> ServiceProviderABC:

View File

@@ -30,6 +30,11 @@ class ServiceCollectionABC(ABC):
r"""Adds the CPL internal logger""" r"""Adds the CPL internal logger"""
pass pass
@abstractmethod
def add_pipes(self):
r"""Adds the CPL internal pipes as transient"""
pass
@abstractmethod @abstractmethod
def add_transient(self, service_type: Type, service: Callable = None) -> 'ServiceCollectionABC': def add_transient(self, service_type: Type, service: Callable = None) -> 'ServiceCollectionABC':
r"""Adds a service with transient lifetime r"""Adds a service with transient lifetime

View File

@@ -1,5 +1,6 @@
from typing import Union, Optional from typing import Union, Optional
from cpl_core.console import Console
from cpl_core.dependency_injection.service_lifetime_enum import ServiceLifetimeEnum from cpl_core.dependency_injection.service_lifetime_enum import ServiceLifetimeEnum
@@ -14,7 +15,7 @@ class ServiceDescriptor:
Lifetime of the service Lifetime of the service
""" """
def __init__(self, implementation: Union[type, Optional[object]], lifetime: ServiceLifetimeEnum): def __init__(self, implementation: Union[type, Optional[object]], lifetime: ServiceLifetimeEnum, base_type=None):
self._service_type = implementation self._service_type = implementation
self._implementation = implementation self._implementation = implementation
@@ -25,10 +26,16 @@ class ServiceDescriptor:
else: else:
self._implementation = None self._implementation = None
self._base_type = base_type if base_type is not None else self._service_type
@property @property
def service_type(self) -> type: def service_type(self) -> type:
return self._service_type return self._service_type
@property
def base_type(self) -> type:
return self._base_type
@property @property
def implementation(self) -> Union[type, Optional[object]]: def implementation(self) -> Union[type, Optional[object]]:
return self._implementation return self._implementation

View File

@@ -4,6 +4,7 @@ from typing import Optional
from cpl_core.configuration.configuration_abc import ConfigurationABC from cpl_core.configuration.configuration_abc import ConfigurationABC
from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC
from cpl_core.console import Console
from cpl_core.database.context.database_context_abc import DatabaseContextABC from cpl_core.database.context.database_context_abc import DatabaseContextABC
from cpl_core.dependency_injection.scope_abc import ScopeABC from cpl_core.dependency_injection.scope_abc import ScopeABC
from cpl_core.dependency_injection.scope_builder import ScopeBuilder from cpl_core.dependency_injection.scope_builder import ScopeBuilder
@@ -36,7 +37,7 @@ class ServiceProvider(ServiceProviderABC):
def _find_service(self, service_type: type) -> Optional[ServiceDescriptor]: def _find_service(self, service_type: type) -> Optional[ServiceDescriptor]:
for descriptor in self._service_descriptors: for descriptor in self._service_descriptors:
if descriptor.service_type == service_type or issubclass(descriptor.service_type, service_type): if descriptor.service_type == service_type or issubclass(descriptor.base_type, service_type):
return descriptor return descriptor
return None return None

View File

@@ -15,7 +15,7 @@ __title__ = 'cpl_core.environment'
__author__ = 'Sven Heidemann' __author__ = 'Sven Heidemann'
__license__ = 'MIT' __license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de'
__version__ = '2022.6.3.dev2' __version__ = '2022.6.0rc1'
from collections import namedtuple from collections import namedtuple
@@ -25,4 +25,4 @@ from .environment_name_enum import EnvironmentNameEnum
from .application_environment import ApplicationEnvironment from .application_environment import ApplicationEnvironment
VersionInfo = namedtuple('VersionInfo', 'major minor micro') VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='2022', minor='6', micro='3.dev2') version_info = VersionInfo(major='2022', minor='6', micro='0.rc1')

View File

@@ -15,7 +15,7 @@ __title__ = 'cpl_core.logging'
__author__ = 'Sven Heidemann' __author__ = 'Sven Heidemann'
__license__ = 'MIT' __license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de'
__version__ = '2022.6.3.dev2' __version__ = '2022.6.0rc1'
from collections import namedtuple from collections import namedtuple
@@ -27,4 +27,4 @@ from .logging_settings import LoggingSettings
from .logging_settings_name_enum import LoggingSettingsNameEnum from .logging_settings_name_enum import LoggingSettingsNameEnum
VersionInfo = namedtuple('VersionInfo', 'major minor micro') VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='2022', minor='6', micro='3.dev2') version_info = VersionInfo(major='2022', minor='6', micro='0.rc1')

View File

@@ -15,7 +15,7 @@ __title__ = 'cpl_core.mailing'
__author__ = 'Sven Heidemann' __author__ = 'Sven Heidemann'
__license__ = 'MIT' __license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de' __copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de'
__version__ = '2022.6.3.dev2' __version__ = '2022.6.0rc1'
from collections import namedtuple from collections import namedtuple
@@ -27,4 +27,4 @@ from .email_client_settings import EMailClientSettings
from .email_client_settings_name_enum import EMailClientSettingsNameEnum from .email_client_settings_name_enum import EMailClientSettingsNameEnum
VersionInfo = namedtuple('VersionInfo', 'major minor micro') VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='2022', minor='6', micro='3.dev2') version_info = VersionInfo(major='2022', minor='6', micro='0.rc1')

View File

@@ -0,0 +1,32 @@
# -*- coding: utf-8 -*-
"""
cpl-core sh-edraft Common Python library
~~~~~~~~~~~~~~~~~~~
sh-edraft Common Python library
:copyright: (c) 2020 - 2022 sh-edraft.de
:license: MIT, see LICENSE for more details.
"""
__title__ = 'cpl_core.pipes'
__author__ = 'Sven Heidemann'
__license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2022 sh-edraft.de'
__version__ = '2022.6.0rc1'
from collections import namedtuple
# imports:
from .bool_pipe import BoolPipe
from .first_char_to_lower_pipe import FirstCharToLowerPipe
from .first_to_upper_pipe import FirstToUpperPipe
from .ip_address_pipe import IPAddressPipe
from .pipe_abc import PipeABC
from .to_camel_case_pipe import ToCamelCasePipe
from .to_snake_case_pipe import ToSnakeCasePipe
VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='2022', minor='6', micro='0.rc1')

View File

@@ -0,0 +1,9 @@
from cpl_core.pipes.pipe_abc import PipeABC
class BoolPipe(PipeABC):
def __init__(self): pass
def transform(self, value: bool, *args):
return 'True' if value else 'False'

View File

@@ -0,0 +1,20 @@
from cpl_core.pipes.pipe_abc import PipeABC
class FirstCharToLowerPipe(PipeABC):
def __init__(self): pass
def transform(self, value: any, *args):
r"""Converts first char to lower
Parameter
---------
value: :class:`str`
String to convert
Returns
-------
String with first char as lower
"""
return f'{value[0].lower()}{value[1:]}'

Some files were not shown because too many files have changed in this diff Show More