WIP: dev into master #184
14
.gitea/workflows/core_dev.yaml
Normal file
14
.gitea/workflows/core_dev.yaml
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
name: Build on push
|
||||||
|
run-name: Build on push
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- dev
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
prepare:
|
||||||
|
uses: ./.gitea/workflows/prepare.yaml
|
||||||
|
|
||||||
|
build:
|
||||||
|
needs: prepare
|
||||||
|
uses: ./.gitea/workflows/package.yaml
|
||||||
47
.gitea/workflows/package.yaml
Normal file
47
.gitea/workflows/package.yaml
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
name: Build Package
|
||||||
|
run-name: Build Python Package
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_call:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: [ runner ]
|
||||||
|
needs: prepare
|
||||||
|
container: git.sh-edraft.de/sh-edraft.de/act-runner:latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Clone Repository
|
||||||
|
uses: https://github.com/actions/checkout@v3
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.CI_ACCESS_TOKEN }}
|
||||||
|
|
||||||
|
- name: Download build version artifact
|
||||||
|
uses: actions/download-artifact@v3
|
||||||
|
with:
|
||||||
|
name: version
|
||||||
|
|
||||||
|
- name: Set version
|
||||||
|
run: |
|
||||||
|
sed -i -E "s/^version = \".*\"/version = \"$(cat version.txt)-dev\"/" pyproject.toml
|
||||||
|
|
||||||
|
- name: Install Dependencies
|
||||||
|
run: |
|
||||||
|
pip install build
|
||||||
|
|
||||||
|
- name: Build Package
|
||||||
|
run: |
|
||||||
|
python -m build --sdist --wheel --outdir dist
|
||||||
|
|
||||||
|
upload:
|
||||||
|
- name: Login to registry git.sh-edraft.de
|
||||||
|
uses: https://github.com/docker/login-action@v1
|
||||||
|
with:
|
||||||
|
registry: git.sh-edraft.de
|
||||||
|
username: ${{ secrets.CI_USERNAME }}
|
||||||
|
password: ${{ secrets.CI_ACCESS_TOKEN }}
|
||||||
|
|
||||||
|
- name: Push image
|
||||||
|
run: |
|
||||||
|
pip install twine
|
||||||
|
python -m twine upload --repository-url https://git.sh-edraft.de/api/packages/sh-edraft.de/pypi -u ${{ secrets.CI_USERNAME }} -p ${{ secrets.CI_ACCESS_TOKEN }} ./dist/*
|
||||||
43
.gitea/workflows/prepare.yaml
Normal file
43
.gitea/workflows/prepare.yaml
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
name: Prepare Build
|
||||||
|
run-name: Prepare Build Version
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_call:
|
||||||
|
outputs:
|
||||||
|
build_version:
|
||||||
|
value: ${{ jobs.prepare.outputs.build_version }}
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
prepare:
|
||||||
|
runs-on: [ runner ]
|
||||||
|
container: git.sh-edraft.de/sh-edraft.de/act-runner:latest
|
||||||
|
steps:
|
||||||
|
- name: Clone Repository
|
||||||
|
uses: https://github.com/actions/checkout@v3
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.CI_ACCESS_TOKEN }}
|
||||||
|
|
||||||
|
- name: Get Date and Build Number
|
||||||
|
run: |
|
||||||
|
git fetch --tags
|
||||||
|
git tag
|
||||||
|
DATE=$(date +'%Y.%m.%d')
|
||||||
|
TAG_COUNT=$(git tag -l "${DATE}.*" | wc -l)
|
||||||
|
BUILD_NUMBER=$(($TAG_COUNT + 1))
|
||||||
|
BUILD_VERSION="${DATE}.${BUILD_NUMBER}.dev1"
|
||||||
|
echo "$BUILD_VERSION" > version.txt
|
||||||
|
echo "VERSION $BUILD_VERSION"
|
||||||
|
|
||||||
|
- name: Create Git Tag for Build
|
||||||
|
run: |
|
||||||
|
git config user.name "ci"
|
||||||
|
git config user.email "dev@sh-edraft.de"
|
||||||
|
echo "tag $(cat version.txt)"
|
||||||
|
git tag $(cat version.txt)
|
||||||
|
git push origin --tags
|
||||||
|
|
||||||
|
- name: Upload build version artifact
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: version
|
||||||
|
path: version.txt
|
||||||
22
.gitea/workflows/publish.yaml
Normal file
22
.gitea/workflows/publish.yaml
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
name: Publish Package
|
||||||
|
run-name: Publish Python Package
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_call:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
upload:
|
||||||
|
runs-on: [ runner ]
|
||||||
|
container: git.sh-edraft.de/sh-edraft.de/act-runner:latest
|
||||||
|
steps:
|
||||||
|
- name: Login to registry git.sh-edraft.de
|
||||||
|
uses: https://github.com/docker/login-action@v1
|
||||||
|
with:
|
||||||
|
registry: git.sh-edraft.de
|
||||||
|
username: ${{ secrets.CI_USERNAME }}
|
||||||
|
password: ${{ secrets.CI_ACCESS_TOKEN }}
|
||||||
|
|
||||||
|
- name: Push image
|
||||||
|
run: |
|
||||||
|
pip install twine
|
||||||
|
python -m twine upload --repository-url https://git.sh-edraft.de/api/packages/sh-edraft.de/pypi -u ${{ secrets.CI_USERNAME }} -p ${{ secrets.CI_ACCESS_TOKEN }} ./dist/*
|
||||||
79
clean_init.py
Normal file
79
clean_init.py
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
import os
|
||||||
|
import re
|
||||||
|
|
||||||
|
def clean_init_files(root_dir='.'):
|
||||||
|
"""
|
||||||
|
Durchsucht rekursiv alle __init__.py Dateien und entfernt:
|
||||||
|
- Einzeilige Kommentare
|
||||||
|
- Mehrzeilige Kommentare/Docstrings
|
||||||
|
- Variablen, die mit __ beginnen und enden
|
||||||
|
- VersionInfo- und version_info-Zuweisungen
|
||||||
|
"""
|
||||||
|
# Regex-Pattern für zu entfernende Zeilen
|
||||||
|
comment_pattern = re.compile(r'^\s*#.*$')
|
||||||
|
dunder_pattern = re.compile(r'^\s*__\w+__\s*=.*$')
|
||||||
|
version_pattern = re.compile(r'^\s*(VersionInfo|version_info)\s*=.*$')
|
||||||
|
|
||||||
|
# Zu ignorierende Verzeichnisse
|
||||||
|
ignore_dirs = ['venv', '.venv', 'env', '.env']
|
||||||
|
|
||||||
|
# Zähle bearbeitete Dateien
|
||||||
|
processed_files = 0
|
||||||
|
|
||||||
|
for dirpath, dirnames, filenames in os.walk(root_dir):
|
||||||
|
# Ignoriere venv-Verzeichnisse
|
||||||
|
dirnames[:] = [d for d in dirnames if d not in ignore_dirs]
|
||||||
|
|
||||||
|
for filename in filenames:
|
||||||
|
if filename == '__init__.py':
|
||||||
|
file_path = os.path.join(dirpath, filename)
|
||||||
|
|
||||||
|
# Datei lesen
|
||||||
|
with open(file_path, 'r', encoding='utf-8') as f:
|
||||||
|
content = f.read()
|
||||||
|
|
||||||
|
# Mehrzeilige Kommentare entfernen
|
||||||
|
# Entferne Docstrings (''' oder """)
|
||||||
|
content = re.sub(r'(?:\'\'\'|""")[\s\S]*?(?:\'\'\'|""")', '', content)
|
||||||
|
|
||||||
|
# Verarbeite die Zeilen
|
||||||
|
lines = content.splitlines()
|
||||||
|
|
||||||
|
# Zu behaltende Zeilen filtern
|
||||||
|
filtered_lines = []
|
||||||
|
for line in lines:
|
||||||
|
if (not comment_pattern.match(line) and
|
||||||
|
not dunder_pattern.match(line) and
|
||||||
|
not version_pattern.match(line)):
|
||||||
|
filtered_lines.append(line)
|
||||||
|
|
||||||
|
# Leere aufeinanderfolgende Zeilen entfernen
|
||||||
|
clean_lines = []
|
||||||
|
prev_empty = False
|
||||||
|
for line in filtered_lines:
|
||||||
|
is_empty = line.strip() == ''
|
||||||
|
if not (is_empty and prev_empty):
|
||||||
|
clean_lines.append(line)
|
||||||
|
prev_empty = is_empty
|
||||||
|
|
||||||
|
# Entferne Leerzeilen am Anfang und Ende
|
||||||
|
while clean_lines and clean_lines[0].strip() == '':
|
||||||
|
clean_lines.pop(0)
|
||||||
|
while clean_lines and clean_lines[-1].strip() == '':
|
||||||
|
clean_lines.pop()
|
||||||
|
|
||||||
|
# Füge eine Leerzeile am Ende hinzu, wenn die Datei nicht leer ist
|
||||||
|
if clean_lines:
|
||||||
|
clean_lines.append('')
|
||||||
|
|
||||||
|
# Schreibe bereinigte Datei zurück
|
||||||
|
with open(file_path, 'w', encoding='utf-8') as f:
|
||||||
|
f.write('\n'.join(clean_lines))
|
||||||
|
|
||||||
|
processed_files += 1
|
||||||
|
print(f"Bereinigt: {file_path}")
|
||||||
|
|
||||||
|
print(f"\nAbgeschlossen: {processed_files} __init__.py Dateien bereinigt")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
clean_init_files()
|
||||||
@@ -1,151 +0,0 @@
|
|||||||
{
|
|
||||||
"WorkspaceSettings": {
|
|
||||||
"DefaultProject": "cpl-core",
|
|
||||||
"Projects": {
|
|
||||||
"cpl-cli": "src/cpl_cli/cpl-cli.json",
|
|
||||||
"cpl-core": "src/cpl_core/cpl-core.json",
|
|
||||||
"cpl-discord": "src/cpl_discord/cpl-discord.json",
|
|
||||||
"cpl-query": "src/cpl_query/cpl-query.json",
|
|
||||||
"cpl-translation": "src/cpl_translation/cpl-translation.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",
|
|
||||||
"unittests_translation": "unittests/unittests_translation/unittests_translation.json"
|
|
||||||
},
|
|
||||||
"Scripts": {
|
|
||||||
"hello-world": "echo 'Hello World'",
|
|
||||||
|
|
||||||
"format": "echo 'Formatting:'; black ./",
|
|
||||||
|
|
||||||
"sv": "cpl set-version",
|
|
||||||
"set-version": "cpl run set-version --dev $ARGS; echo '';",
|
|
||||||
|
|
||||||
"spu": "cpl set-pip-urls",
|
|
||||||
"set-pip-urls": "cpl run set-pip-urls --dev $ARGS; echo '';",
|
|
||||||
|
|
||||||
"docs-build": "cpl format; echo 'Build Documentation'; cpl db-core; cpl db-discord; cpl db-query; cpl db-translation; cd docs/; make clean; make html;",
|
|
||||||
"db-core": "cd docs/; sphinx-apidoc -o source/ ../src/cpl_core; cd ../",
|
|
||||||
"db-discord": "cd docs/; sphinx-apidoc -o source/ ../src/cpl_discord; cd ../",
|
|
||||||
"db-query": "cd docs/; sphinx-apidoc -o source/ ../src/cpl_query; cd ../",
|
|
||||||
"db-translation": "cd docs/; sphinx-apidoc -o source/ ../src/cpl_translation; cd ../",
|
|
||||||
"db": "cpl docs-build",
|
|
||||||
|
|
||||||
"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-discord; cpl build-query; cpl build-translation; 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-discord": "echo 'Build cpl-discord'; cd ./src/cpl_discord; cpl build; cd ../../;",
|
|
||||||
"build-query": "echo 'Build cpl-query'; cd ./src/cpl_query; cpl build; cd ../../;",
|
|
||||||
"build-translation": "echo 'Build cpl-translation'; cd ./src/cpl_translation; 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-discord; cpl publish-query; cpl publish-translation;",
|
|
||||||
"pa": "cpl publish-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-discord": "echo 'Publish cpl-discord'; cd ./src/cpl_discord; cpl publish; cd ../../;",
|
|
||||||
"publish-query": "echo 'Publish cpl-query'; cd ./src/cpl_query; cpl publish; cd ../../;",
|
|
||||||
"publish-translation": "echo 'Publish cpl-translation'; cd ./src/cpl_translation; 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-discord": "echo 'PROD Upload cpl-discord'; cpl upl-prod-discord;",
|
|
||||||
"upl-prod-discord": "twine upload -r pip.sh-edraft.de dist/cpl-discord/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-prod-translation": "echo 'PROD Upload cpl-translation'; cpl upl-prod-translation;",
|
|
||||||
"upl-prod-translation": "twine upload -r pip.sh-edraft.de dist/cpl-translation/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-discord": "echo 'EXP Upload cpl-discord'; cpl upl-exp-discord;",
|
|
||||||
"upl-exp-discord": "twine upload -r pip-exp.sh-edraft.de dist/cpl-discord/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-exp-translation": "echo 'EXP Upload cpl-translation'; cpl upl-exp-translation;",
|
|
||||||
"upl-exp-translation": "twine upload -r pip-exp.sh-edraft.de dist/cpl-translation/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-discord": "echo 'DEV Upload cpl-discord'; cpl upl-dev-discord;",
|
|
||||||
"upl-dev-discord": "twine upload -r pip-dev.sh-edraft.de dist/cpl-discord/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/*",
|
|
||||||
|
|
||||||
"upload-dev-translation": "echo 'DEV Upload cpl-translation'; cpl upl-dev-translation;",
|
|
||||||
"upl-dev-translation": "twine upload -r pip-dev.sh-edraft.de dist/cpl-translation/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-discord; cpl deploy-prod-query; cpl deploy-prod-translation;",
|
|
||||||
"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",
|
|
||||||
"deploy-prod-discord": "cpl publish-discord; cpl upload-prod-discord",
|
|
||||||
"deploy-prod-translation": "cpl publish-translation; cpl upload-prod-translation",
|
|
||||||
|
|
||||||
"pre-deploy-exp": "cpl sv $ARGS; cpl spu --environment=staging;",
|
|
||||||
"deploy-exp": "cpl deploy-exp-cli; cpl deploy-exp-core; cpl deploy-exp-discord; cpl deploy-exp-query; cpl deploy-exp-translation;",
|
|
||||||
"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-discord": "cpl publish-discord; cpl upload-exp-discord",
|
|
||||||
"deploy-exp-query": "cpl publish-query; cpl upload-exp-query",
|
|
||||||
"deploy-exp-translation": "cpl publish-translation; cpl upload-exp-translation",
|
|
||||||
|
|
||||||
"pre-deploy-dev": "cpl sv $ARGS; cpl spu --environment=development;",
|
|
||||||
"deploy-dev": "cpl deploy-dev-cli; cpl deploy-dev-core; cpl deploy-dev-discord; cpl deploy-dev-query; cpl deploy-dev-translation;",
|
|
||||||
"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-discord": "cpl publish-discord; cpl upload-dev-discord",
|
|
||||||
"deploy-dev-query": "cpl publish-query; cpl upload-dev-query",
|
|
||||||
"deploy-dev-translation": "cpl publish-query; cpl upload-dev-translation",
|
|
||||||
|
|
||||||
"dev-install": "cpl di-core; cpl di-cli; cpl di-query; cpl di-translation;",
|
|
||||||
"di": "cpl dev-install",
|
|
||||||
"di-core": "pip install cpl-core --pre --upgrade --extra-index-url https://pip-dev.sh-edraft.de",
|
|
||||||
"di-cli": "pip install cpl-cli --pre --upgrade --extra-index-url https://pip-dev.sh-edraft.de",
|
|
||||||
"di-discord": "pip install cpl-discord --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",
|
|
||||||
"di-translation": "pip install cpl-translation --pre --upgrade --extra-index-url https://pip-dev.sh-edraft.de",
|
|
||||||
|
|
||||||
"prod-install": "cpl pi-core; cpl pi-cli; cpl pi-query; cpl pi-translation;",
|
|
||||||
"pi": "cpl prod-install",
|
|
||||||
"pi-core": "pip install cpl-core --pre --upgrade --extra-index-url https://pip.sh-edraft.de",
|
|
||||||
"pi-cli": "pip install cpl-cli --pre --upgrade --extra-index-url https://pip.sh-edraft.de",
|
|
||||||
"pi-discord": "pip install cpl-discord --pre --upgrade --extra-index-url https://pip.sh-edraft.de",
|
|
||||||
"pi-query": "pip install cpl-query --pre --upgrade --extra-index-url https://pip.sh-edraft.de",
|
|
||||||
"pi-translation": "pip install cpl-translation --pre --upgrade --extra-index-url https://pip.sh-edraft.de"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
"""
|
|
||||||
cpl-cli CPL CLI
|
|
||||||
~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
CPL Command Line Interface
|
|
||||||
|
|
||||||
:copyright: (c) 2020 - 2024 sh-edraft.de
|
|
||||||
:license: MIT, see LICENSE for more details.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
__title__ = "cpl_cli"
|
|
||||||
__author__ = "Sven Heidemann"
|
|
||||||
__license__ = "MIT"
|
|
||||||
__copyright__ = "Copyright (c) 2020 - 2024 sh-edraft.de"
|
|
||||||
__version__ = "2024.10.0"
|
|
||||||
|
|
||||||
from collections import namedtuple
|
|
||||||
|
|
||||||
|
|
||||||
# imports:
|
|
||||||
|
|
||||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
|
||||||
version_info = VersionInfo(major="2024", minor="10", micro="0")
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
from cpl_cli.abc.project_type_abc import ProjectTypeABC
|
|
||||||
from cpl_cli.configuration import WorkspaceSettings
|
|
||||||
from cpl_core.utils import String
|
|
||||||
|
|
||||||
|
|
||||||
class Console(ProjectTypeABC):
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
base_path: str,
|
|
||||||
project_name: str,
|
|
||||||
workspace: WorkspaceSettings,
|
|
||||||
use_application_api: bool,
|
|
||||||
use_startup: bool,
|
|
||||||
use_service_providing: bool,
|
|
||||||
use_async: bool,
|
|
||||||
project_file_data: dict,
|
|
||||||
):
|
|
||||||
from project_file import ProjectFile
|
|
||||||
from project_file_appsettings import ProjectFileAppsettings
|
|
||||||
from project_file_code_application import ProjectFileApplication
|
|
||||||
from project_file_code_main import ProjectFileMain
|
|
||||||
from project_file_code_startup import ProjectFileStartup
|
|
||||||
from project_file_readme import ProjectFileReadme
|
|
||||||
from project_file_license import ProjectFileLicense
|
|
||||||
from schematic_init import Init
|
|
||||||
|
|
||||||
ProjectTypeABC.__init__(
|
|
||||||
self,
|
|
||||||
base_path,
|
|
||||||
project_name,
|
|
||||||
workspace,
|
|
||||||
use_application_api,
|
|
||||||
use_startup,
|
|
||||||
use_service_providing,
|
|
||||||
use_async,
|
|
||||||
project_file_data,
|
|
||||||
)
|
|
||||||
|
|
||||||
project_path = f'{base_path}{String.convert_to_snake_case(project_name.split("/")[-1])}/'
|
|
||||||
|
|
||||||
self.add_template(ProjectFile(project_name.split("/")[-1], project_path, project_file_data))
|
|
||||||
if workspace is None:
|
|
||||||
self.add_template(ProjectFileLicense(""))
|
|
||||||
self.add_template(ProjectFileReadme(""))
|
|
||||||
self.add_template(Init("", "init", f"{base_path}tests/"))
|
|
||||||
|
|
||||||
self.add_template(Init("", "init", project_path))
|
|
||||||
self.add_template(ProjectFileAppsettings(project_path))
|
|
||||||
|
|
||||||
if use_application_api:
|
|
||||||
self.add_template(
|
|
||||||
ProjectFileApplication(project_path, use_application_api, use_startup, use_service_providing, use_async)
|
|
||||||
)
|
|
||||||
|
|
||||||
if use_startup:
|
|
||||||
self.add_template(
|
|
||||||
ProjectFileStartup(project_path, use_application_api, use_startup, use_service_providing, use_async)
|
|
||||||
)
|
|
||||||
|
|
||||||
self.add_template(
|
|
||||||
ProjectFileMain(
|
|
||||||
project_name.split("/")[-1],
|
|
||||||
project_path,
|
|
||||||
use_application_api,
|
|
||||||
use_startup,
|
|
||||||
use_service_providing,
|
|
||||||
use_async,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
import json
|
|
||||||
|
|
||||||
from cpl_cli.abc.file_template_abc import FileTemplateABC
|
|
||||||
|
|
||||||
|
|
||||||
class ProjectFile(FileTemplateABC):
|
|
||||||
def __init__(self, name: str, path: str, code: dict):
|
|
||||||
FileTemplateABC.__init__(self, "", path, "{}")
|
|
||||||
self._name = f"{name}.json"
|
|
||||||
self._code = code
|
|
||||||
|
|
||||||
def get_code(self) -> str:
|
|
||||||
return json.dumps(self._code, indent=2)
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
import textwrap
|
|
||||||
|
|
||||||
from cpl_cli.abc.file_template_abc import FileTemplateABC
|
|
||||||
|
|
||||||
|
|
||||||
class ProjectFileAppsettings(FileTemplateABC):
|
|
||||||
def __init__(self, path: str):
|
|
||||||
FileTemplateABC.__init__(self, "", path, "{}")
|
|
||||||
self._name = "appsettings.json"
|
|
||||||
|
|
||||||
def get_code(self) -> str:
|
|
||||||
return textwrap.dedent(
|
|
||||||
"""\
|
|
||||||
{
|
|
||||||
"TimeFormatSettings": {
|
|
||||||
"DateFormat": "%Y-%m-%d",
|
|
||||||
"TimeFormat": "%H:%M:%S",
|
|
||||||
"DateTimeFormat": "%Y-%m-%d %H:%M:%S.%f",
|
|
||||||
"DateTimeLogFormat": "%Y-%m-%d_%H-%M-%S"
|
|
||||||
},
|
|
||||||
"LoggingSettings": {
|
|
||||||
"Path": "logs/",
|
|
||||||
"Filename": "log_$start_time.log",
|
|
||||||
"ConsoleLogLevel": "ERROR",
|
|
||||||
"FileLogLevel": "WARN"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
from cpl_cli.abc.code_file_template_abc import CodeFileTemplateABC
|
|
||||||
|
|
||||||
|
|
||||||
class ProjectFileApplication(CodeFileTemplateABC):
|
|
||||||
def __init__(
|
|
||||||
self, path: str, use_application_api: bool, use_startup: bool, use_service_providing: bool, use_async: bool
|
|
||||||
):
|
|
||||||
CodeFileTemplateABC.__init__(
|
|
||||||
self, "application", path, "", use_application_api, use_startup, use_service_providing, use_async
|
|
||||||
)
|
|
||||||
|
|
||||||
def get_code(self) -> str:
|
|
||||||
import textwrap
|
|
||||||
|
|
||||||
if self._use_async:
|
|
||||||
return textwrap.dedent(
|
|
||||||
"""\
|
|
||||||
from cpl_core.application import ApplicationABC
|
|
||||||
from cpl_core.configuration import ConfigurationABC
|
|
||||||
from cpl_core.console import Console
|
|
||||||
from cpl_core.dependency_injection import ServiceProviderABC
|
|
||||||
|
|
||||||
|
|
||||||
class Application(ApplicationABC):
|
|
||||||
|
|
||||||
def __init__(self, config: ConfigurationABC, services: ServiceProviderABC):
|
|
||||||
ApplicationABC.__init__(self, config, services)
|
|
||||||
|
|
||||||
async def configure(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
async def main(self):
|
|
||||||
Console.write_line('Hello World')
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
|
|
||||||
return textwrap.dedent(
|
|
||||||
"""\
|
|
||||||
from cpl_core.application import ApplicationABC
|
|
||||||
from cpl_core.configuration import ConfigurationABC
|
|
||||||
from cpl_core.console import Console
|
|
||||||
from cpl_core.dependency_injection import ServiceProviderABC
|
|
||||||
|
|
||||||
|
|
||||||
class Application(ApplicationABC):
|
|
||||||
|
|
||||||
def __init__(self, config: ConfigurationABC, services: ServiceProviderABC):
|
|
||||||
ApplicationABC.__init__(self, config, services)
|
|
||||||
|
|
||||||
def configure(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def main(self):
|
|
||||||
Console.write_line('Hello World')
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
@@ -1,107 +0,0 @@
|
|||||||
from cpl_cli.abc.code_file_template_abc import CodeFileTemplateABC
|
|
||||||
from cpl_core.utils import String
|
|
||||||
|
|
||||||
|
|
||||||
class ProjectFileMain(CodeFileTemplateABC):
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
name: str,
|
|
||||||
path: str,
|
|
||||||
use_application_api: bool,
|
|
||||||
use_startup: bool,
|
|
||||||
use_service_providing: bool,
|
|
||||||
use_async: bool,
|
|
||||||
):
|
|
||||||
CodeFileTemplateABC.__init__(
|
|
||||||
self, "main", path, "", use_application_api, use_startup, use_service_providing, use_async
|
|
||||||
)
|
|
||||||
|
|
||||||
import textwrap
|
|
||||||
|
|
||||||
import_pkg = f"{String.convert_to_snake_case(name)}."
|
|
||||||
|
|
||||||
self._main_with_application_host_and_startup = textwrap.dedent(
|
|
||||||
f"""\
|
|
||||||
{"import asyncio" if self._use_async else ''}
|
|
||||||
|
|
||||||
from cpl_core.application import ApplicationBuilder
|
|
||||||
|
|
||||||
from {import_pkg}application import Application
|
|
||||||
from {import_pkg}startup import Startup
|
|
||||||
|
|
||||||
|
|
||||||
{self._async()}def main():
|
|
||||||
app_builder = ApplicationBuilder(Application)
|
|
||||||
app_builder.use_startup(Startup)
|
|
||||||
{"app: Application = await app_builder.build_async()" if self._use_async else ""}
|
|
||||||
{"await app.run_async()" if self._use_async else "app_builder.build().run()"}
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
{"asyncio.run(main())" if self._use_async else "main()"}
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
self._main_with_application_base = textwrap.dedent(
|
|
||||||
f"""\
|
|
||||||
{"import asyncio" if self._use_async else ''}
|
|
||||||
|
|
||||||
from cpl_core.application import ApplicationBuilder
|
|
||||||
|
|
||||||
from {import_pkg}application import Application
|
|
||||||
|
|
||||||
|
|
||||||
{self._async()}def main():
|
|
||||||
app_builder = ApplicationBuilder(Application)
|
|
||||||
{"app: Application = await app_builder.build_async()" if self._use_async else ""}
|
|
||||||
{"await app.run_async()" if self._use_async else "app_builder.build().run()"}
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
{"asyncio.run(main())" if self._use_async else "main()"}
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
|
|
||||||
self._main_with_dependency_injection = textwrap.dedent(
|
|
||||||
f"""\
|
|
||||||
{"import asyncio" if self._use_async else ''}
|
|
||||||
|
|
||||||
from cpl_core.application import ApplicationBuilder
|
|
||||||
|
|
||||||
|
|
||||||
{self._async()}def configure_configuration() -> ConfigurationABC:
|
|
||||||
config = Configuration()
|
|
||||||
return config
|
|
||||||
|
|
||||||
|
|
||||||
{self._async()}def configure_services(config: ConfigurationABC) -> ServiceProviderABC:
|
|
||||||
services = ServiceCollection(config)
|
|
||||||
return services.build_service_provider()
|
|
||||||
|
|
||||||
|
|
||||||
{self._async()}def main():
|
|
||||||
config = {self._async()}configure_configuration()
|
|
||||||
provider = {self._async()}configure_services(config)
|
|
||||||
Console.write_line('Hello World')
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
{"asyncio.run(main())" if self._use_async else "main()"}
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
|
|
||||||
def _async(self) -> str:
|
|
||||||
if self._use_async:
|
|
||||||
return "async "
|
|
||||||
return ""
|
|
||||||
|
|
||||||
def get_code(self) -> str:
|
|
||||||
if self._use_application_api and self._use_startup:
|
|
||||||
return self._main_with_application_host_and_startup
|
|
||||||
|
|
||||||
if self._use_application_api:
|
|
||||||
return self._main_with_application_base
|
|
||||||
|
|
||||||
if self._use_service_providing:
|
|
||||||
return self._main_with_dependency_injection
|
|
||||||
|
|
||||||
return self._main_with_application_base
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
from cpl_cli.abc.code_file_template_abc import CodeFileTemplateABC
|
|
||||||
|
|
||||||
|
|
||||||
class ProjectFileStartup(CodeFileTemplateABC):
|
|
||||||
def __init__(
|
|
||||||
self, path: str, use_application_api: bool, use_startup: bool, use_service_providing: bool, use_async: bool
|
|
||||||
):
|
|
||||||
CodeFileTemplateABC.__init__(
|
|
||||||
self, "startup", path, "", use_application_api, use_startup, use_service_providing, use_async
|
|
||||||
)
|
|
||||||
|
|
||||||
def get_code(self) -> str:
|
|
||||||
import textwrap
|
|
||||||
|
|
||||||
return textwrap.dedent(
|
|
||||||
"""\
|
|
||||||
from cpl_core.application import StartupABC
|
|
||||||
from cpl_core.configuration import ConfigurationABC
|
|
||||||
from cpl_core.dependency_injection import ServiceProviderABC, ServiceCollectionABC
|
|
||||||
from cpl_core.environment import ApplicationEnvironment
|
|
||||||
|
|
||||||
|
|
||||||
class Startup(StartupABC):
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
StartupABC.__init__(self)
|
|
||||||
|
|
||||||
def configure_configuration(self, configuration: ConfigurationABC, environment: ApplicationEnvironment) -> ConfigurationABC:
|
|
||||||
return configuration
|
|
||||||
|
|
||||||
def configure_services(self, services: ServiceCollectionABC, environment: ApplicationEnvironment) -> ServiceProviderABC:
|
|
||||||
return services.build_service_provider()
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
@@ -1,66 +0,0 @@
|
|||||||
from cpl_cli.abc.code_file_template_abc import CodeFileTemplateABC
|
|
||||||
|
|
||||||
|
|
||||||
class ProjectFileTestApplication(CodeFileTemplateABC):
|
|
||||||
def __init__(
|
|
||||||
self, path: str, use_application_api: bool, use_startup: bool, use_service_providing: bool, use_async: bool
|
|
||||||
):
|
|
||||||
CodeFileTemplateABC.__init__(
|
|
||||||
self, "application", path, "", use_application_api, use_startup, use_service_providing, use_async
|
|
||||||
)
|
|
||||||
|
|
||||||
def get_code(self) -> str:
|
|
||||||
import textwrap
|
|
||||||
|
|
||||||
if self._use_async:
|
|
||||||
return 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)
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
|
|
||||||
return 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)
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
from cpl_cli.abc.code_file_template_abc import CodeFileTemplateABC
|
|
||||||
|
|
||||||
|
|
||||||
class ProjectFileTestCase(CodeFileTemplateABC):
|
|
||||||
def __init__(
|
|
||||||
self, path: str, use_application_api: bool, use_startup: bool, use_service_providing: bool, use_async: bool
|
|
||||||
):
|
|
||||||
CodeFileTemplateABC.__init__(
|
|
||||||
self, "test_case", path, "", use_application_api, use_startup, use_service_providing, use_async
|
|
||||||
)
|
|
||||||
|
|
||||||
def get_code(self) -> str:
|
|
||||||
import textwrap
|
|
||||||
|
|
||||||
if self._use_async:
|
|
||||||
return textwrap.dedent(
|
|
||||||
"""\
|
|
||||||
import unittest
|
|
||||||
|
|
||||||
|
|
||||||
class TestCase(unittest.TestCase):
|
|
||||||
|
|
||||||
async def setUp(self) -> None:
|
|
||||||
pass
|
|
||||||
|
|
||||||
async def test_equal(self):
|
|
||||||
self.assertEqual(True, True)
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
|
|
||||||
return textwrap.dedent(
|
|
||||||
"""\
|
|
||||||
import unittest
|
|
||||||
|
|
||||||
|
|
||||||
class TestCase(unittest.TestCase):
|
|
||||||
|
|
||||||
def setUp(self) -> None:
|
|
||||||
pass
|
|
||||||
|
|
||||||
def test_equal(self):
|
|
||||||
self.assertEqual(True, True)
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
from cpl_cli.abc.file_template_abc import FileTemplateABC
|
|
||||||
|
|
||||||
|
|
||||||
class ProjectFileLicense(FileTemplateABC):
|
|
||||||
def __init__(self, path: str):
|
|
||||||
FileTemplateABC.__init__(self, "", path, "")
|
|
||||||
self._name = "LICENSE"
|
|
||||||
|
|
||||||
def get_code(self) -> str:
|
|
||||||
return self._code
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
from cpl_cli.abc.file_template_abc import FileTemplateABC
|
|
||||||
|
|
||||||
|
|
||||||
class ProjectFileReadme(FileTemplateABC):
|
|
||||||
def __init__(self, path: str):
|
|
||||||
FileTemplateABC.__init__(self, "", path, "")
|
|
||||||
self._name = "README.md"
|
|
||||||
|
|
||||||
def get_code(self) -> str:
|
|
||||||
return self._code
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
import os
|
|
||||||
|
|
||||||
from cpl_cli.abc.project_type_abc import ProjectTypeABC
|
|
||||||
from cpl_cli.configuration import WorkspaceSettings
|
|
||||||
from cpl_core.utils import String
|
|
||||||
|
|
||||||
|
|
||||||
class Library(ProjectTypeABC):
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
base_path: str,
|
|
||||||
project_name: str,
|
|
||||||
workspace: WorkspaceSettings,
|
|
||||||
use_application_api: bool,
|
|
||||||
use_startup: bool,
|
|
||||||
use_service_providing: bool,
|
|
||||||
use_async: bool,
|
|
||||||
project_file_data: dict,
|
|
||||||
):
|
|
||||||
from project_file import ProjectFile
|
|
||||||
from project_file_readme import ProjectFileReadme
|
|
||||||
from project_file_license import ProjectFileLicense
|
|
||||||
from schematic_init import Init
|
|
||||||
from schematic_class import Class
|
|
||||||
|
|
||||||
ProjectTypeABC.__init__(
|
|
||||||
self,
|
|
||||||
base_path,
|
|
||||||
project_name,
|
|
||||||
workspace,
|
|
||||||
use_application_api,
|
|
||||||
use_startup,
|
|
||||||
use_service_providing,
|
|
||||||
use_async,
|
|
||||||
project_file_data,
|
|
||||||
)
|
|
||||||
|
|
||||||
project_path = f'{base_path}{String.convert_to_snake_case(project_name.split("/")[-1])}/'
|
|
||||||
|
|
||||||
self.add_template(ProjectFile(project_name.split("/")[-1], project_path, project_file_data))
|
|
||||||
if workspace is None:
|
|
||||||
self.add_template(ProjectFileLicense(""))
|
|
||||||
self.add_template(ProjectFileReadme(""))
|
|
||||||
|
|
||||||
self.add_template(Init("", "init", project_path))
|
|
||||||
self.add_template(Class("Class1", "class", project_path))
|
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
import os
|
|
||||||
|
|
||||||
from cpl_cli.abc.project_type_abc import ProjectTypeABC
|
|
||||||
from cpl_cli.configuration import WorkspaceSettings
|
|
||||||
from cpl_core.utils import String
|
|
||||||
|
|
||||||
|
|
||||||
class Unittest(ProjectTypeABC):
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
base_path: str,
|
|
||||||
project_name: str,
|
|
||||||
workspace: WorkspaceSettings,
|
|
||||||
use_application_api: bool,
|
|
||||||
use_startup: bool,
|
|
||||||
use_service_providing: bool,
|
|
||||||
use_async: bool,
|
|
||||||
project_file_data: dict,
|
|
||||||
):
|
|
||||||
from project_file import ProjectFile
|
|
||||||
from project_file_code_application import ProjectFileApplication
|
|
||||||
from project_file_code_main import ProjectFileMain
|
|
||||||
from project_file_code_test_case import ProjectFileTestCase
|
|
||||||
from project_file_readme import ProjectFileReadme
|
|
||||||
from project_file_license import ProjectFileLicense
|
|
||||||
from schematic_init import Init
|
|
||||||
|
|
||||||
ProjectTypeABC.__init__(
|
|
||||||
self,
|
|
||||||
base_path,
|
|
||||||
project_name,
|
|
||||||
workspace,
|
|
||||||
use_application_api,
|
|
||||||
use_startup,
|
|
||||||
use_service_providing,
|
|
||||||
use_async,
|
|
||||||
project_file_data,
|
|
||||||
)
|
|
||||||
|
|
||||||
project_path = f'{base_path}{String.convert_to_snake_case(project_name.split("/")[-1])}/'
|
|
||||||
|
|
||||||
self.add_template(ProjectFile(project_name.split("/")[-1], project_path, project_file_data))
|
|
||||||
if workspace is None:
|
|
||||||
self.add_template(ProjectFileLicense(""))
|
|
||||||
self.add_template(ProjectFileReadme(""))
|
|
||||||
self.add_template(Init("", "init", f"{base_path}tests/"))
|
|
||||||
|
|
||||||
self.add_template(Init("", "init", project_path))
|
|
||||||
self.add_template(
|
|
||||||
ProjectFileApplication(project_path, use_application_api, use_startup, use_service_providing, use_async)
|
|
||||||
)
|
|
||||||
self.add_template(
|
|
||||||
ProjectFileMain(
|
|
||||||
project_name.split("/")[-1],
|
|
||||||
project_path,
|
|
||||||
use_application_api,
|
|
||||||
use_startup,
|
|
||||||
use_service_providing,
|
|
||||||
use_async,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
self.add_template(
|
|
||||||
ProjectFileTestCase(project_path, use_application_api, use_startup, use_service_providing, use_async)
|
|
||||||
)
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
from cpl_cli.abc.generate_schematic_abc import GenerateSchematicABC
|
|
||||||
from cpl_core.utils import String
|
|
||||||
|
|
||||||
|
|
||||||
class ABC(GenerateSchematicABC):
|
|
||||||
def __init__(self, name: str, schematic: str, path: str):
|
|
||||||
GenerateSchematicABC.__init__(self, name, schematic, path)
|
|
||||||
self._class_name = name
|
|
||||||
if name != "":
|
|
||||||
self._class_name = f'{String.first_to_upper(name.replace(schematic, ""))}ABC'
|
|
||||||
|
|
||||||
def get_code(self) -> str:
|
|
||||||
code = """\
|
|
||||||
from abc import ABC, abstractmethod
|
|
||||||
|
|
||||||
|
|
||||||
class $Name(ABC):
|
|
||||||
|
|
||||||
@abstractmethod
|
|
||||||
def __init__(self): pass
|
|
||||||
"""
|
|
||||||
x = self.build_code_str(code, Name=self._class_name)
|
|
||||||
return x
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def register(cls):
|
|
||||||
GenerateSchematicABC.register(cls, "abc", ["a", "A"])
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
import textwrap
|
|
||||||
|
|
||||||
from cpl_cli.abc.generate_schematic_abc import GenerateSchematicABC
|
|
||||||
|
|
||||||
|
|
||||||
class Application(GenerateSchematicABC):
|
|
||||||
def __init__(self, *args: str):
|
|
||||||
GenerateSchematicABC.__init__(self, *args)
|
|
||||||
|
|
||||||
def get_code(self) -> str:
|
|
||||||
code = """\
|
|
||||||
from cpl_core.application import ApplicationABC
|
|
||||||
from cpl_core.configuration import ConfigurationABC
|
|
||||||
from cpl_core.console import Console
|
|
||||||
from cpl_core.dependency_injection import ServiceProviderABC
|
|
||||||
|
|
||||||
|
|
||||||
class $Name(ApplicationABC):
|
|
||||||
|
|
||||||
def __init__(self, config: ConfigurationABC, services: ServiceProviderABC):
|
|
||||||
ApplicationABC.__init__(self, config, services)
|
|
||||||
|
|
||||||
def configure(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def main(self):
|
|
||||||
Console.write_line('Hello World')
|
|
||||||
"""
|
|
||||||
x = self.build_code_str(code, Name=self._class_name)
|
|
||||||
return x
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def register(cls):
|
|
||||||
GenerateSchematicABC.register(cls, "application", ["app", "APP"])
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
import textwrap
|
|
||||||
|
|
||||||
from cpl_cli.abc.generate_schematic_abc import GenerateSchematicABC
|
|
||||||
from cpl_core.utils import String
|
|
||||||
|
|
||||||
|
|
||||||
class ApplicationExtension(GenerateSchematicABC):
|
|
||||||
def __init__(self, *args: str):
|
|
||||||
GenerateSchematicABC.__init__(self, *args)
|
|
||||||
|
|
||||||
def get_code(self) -> str:
|
|
||||||
code = """\
|
|
||||||
from cpl_core.application import ApplicationExtensionABC
|
|
||||||
from cpl_core.configuration import ConfigurationABC
|
|
||||||
from cpl_core.dependency_injection import ServiceProviderABC
|
|
||||||
|
|
||||||
|
|
||||||
class $Name(ApplicationExtensionABC):
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
ApplicationExtensionABC.__init__(self)
|
|
||||||
|
|
||||||
def run(self, config: ConfigurationABC, services: ServiceProviderABC):
|
|
||||||
pass
|
|
||||||
"""
|
|
||||||
x = self.build_code_str(code, Name=String.convert_to_camel_case(self._class_name))
|
|
||||||
return x
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def register(cls):
|
|
||||||
GenerateSchematicABC.register(cls, "application-extension", ["appex", "APPEX"])
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
from cpl_cli.abc.generate_schematic_abc import GenerateSchematicABC
|
|
||||||
from cpl_core.utils import String
|
|
||||||
|
|
||||||
|
|
||||||
class Class(GenerateSchematicABC):
|
|
||||||
def __init__(self, name: str, schematic: str, path: str):
|
|
||||||
GenerateSchematicABC.__init__(self, name, schematic, path)
|
|
||||||
self._name = f"{String.convert_to_snake_case(name)}.py"
|
|
||||||
self._class_name = f"{String.first_to_upper(name)}"
|
|
||||||
|
|
||||||
def get_code(self) -> str:
|
|
||||||
code = """\
|
|
||||||
class $Name:
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
pass
|
|
||||||
"""
|
|
||||||
x = self.build_code_str(code, Name=self._class_name)
|
|
||||||
return x
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def register(cls):
|
|
||||||
GenerateSchematicABC.register(cls, "class", ["c", "C"])
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
import textwrap
|
|
||||||
|
|
||||||
from cpl_cli.abc.generate_schematic_abc import GenerateSchematicABC
|
|
||||||
|
|
||||||
|
|
||||||
class ConfigModel(GenerateSchematicABC):
|
|
||||||
def __init__(self, *args: str):
|
|
||||||
GenerateSchematicABC.__init__(self, *args)
|
|
||||||
|
|
||||||
def get_code(self) -> str:
|
|
||||||
code = """\
|
|
||||||
import traceback
|
|
||||||
|
|
||||||
from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC
|
|
||||||
from cpl_core.console import Console
|
|
||||||
|
|
||||||
|
|
||||||
class $Name(ConfigurationModelABC):
|
|
||||||
|
|
||||||
def __init__(self, atr: str = None):
|
|
||||||
ConfigurationModelABC.__init__(self)
|
|
||||||
|
|
||||||
self._atr = atr
|
|
||||||
|
|
||||||
@property
|
|
||||||
def atr(self) -> str:
|
|
||||||
return self._atr
|
|
||||||
|
|
||||||
"""
|
|
||||||
x = self.build_code_str(code, Name=self._class_name)
|
|
||||||
return x
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def register(cls):
|
|
||||||
GenerateSchematicABC.register(cls, "settings", ["st", "ST"])
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
from cpl_cli.abc.generate_schematic_abc import GenerateSchematicABC
|
|
||||||
|
|
||||||
|
|
||||||
class Enum(GenerateSchematicABC):
|
|
||||||
def __init__(self, *args: str):
|
|
||||||
GenerateSchematicABC.__init__(self, *args)
|
|
||||||
|
|
||||||
def get_code(self) -> str:
|
|
||||||
import textwrap
|
|
||||||
|
|
||||||
code = textwrap.dedent(
|
|
||||||
"""\
|
|
||||||
from enum import Enum
|
|
||||||
|
|
||||||
|
|
||||||
class $Name(Enum):
|
|
||||||
|
|
||||||
atr = 0
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
return self.build_code_str(code, Name=self._class_name)
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def register(cls):
|
|
||||||
GenerateSchematicABC.register(cls, "enum", ["e", "E"])
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
import textwrap
|
|
||||||
|
|
||||||
from cpl_cli.abc.generate_schematic_abc import GenerateSchematicABC
|
|
||||||
|
|
||||||
|
|
||||||
class Init(GenerateSchematicABC):
|
|
||||||
def __init__(self, *args: str):
|
|
||||||
GenerateSchematicABC.__init__(self, *args)
|
|
||||||
self._name = f"__init__.py"
|
|
||||||
|
|
||||||
def get_code(self) -> str:
|
|
||||||
code = """\
|
|
||||||
# imports
|
|
||||||
"""
|
|
||||||
x = self.build_code_str(code, Name=self._class_name)
|
|
||||||
return x
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def register(cls):
|
|
||||||
GenerateSchematicABC.register(cls, "init", [])
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
import textwrap
|
|
||||||
|
|
||||||
from cpl_cli.abc.generate_schematic_abc import GenerateSchematicABC
|
|
||||||
|
|
||||||
|
|
||||||
class Pipe(GenerateSchematicABC):
|
|
||||||
def __init__(self, *args: str):
|
|
||||||
GenerateSchematicABC.__init__(self, *args)
|
|
||||||
|
|
||||||
def get_code(self) -> str:
|
|
||||||
code = """\
|
|
||||||
from cpl_core.pipes.pipe_abc import PipeABC
|
|
||||||
|
|
||||||
|
|
||||||
class $Name(PipeABC):
|
|
||||||
|
|
||||||
def __init__(self): pass
|
|
||||||
|
|
||||||
def transform(self, value: any, *args):
|
|
||||||
return value
|
|
||||||
"""
|
|
||||||
x = self.build_code_str(code, Name=self._class_name)
|
|
||||||
return x
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def register(cls):
|
|
||||||
GenerateSchematicABC.register(cls, "pipe", ["p", "P"])
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
from cpl_cli.abc.generate_schematic_abc import GenerateSchematicABC
|
|
||||||
from cpl_core.utils import String
|
|
||||||
|
|
||||||
|
|
||||||
class Schematic(GenerateSchematicABC):
|
|
||||||
def __init__(self, name: str, path: str, schematic: str):
|
|
||||||
GenerateSchematicABC.__init__(self, name, path, schematic)
|
|
||||||
self._name = f"schematic_{String.convert_to_snake_case(name)}.py"
|
|
||||||
self._path = ".cpl/"
|
|
||||||
self._class_name = String.convert_to_camel_case(name)
|
|
||||||
|
|
||||||
def get_code(self) -> str:
|
|
||||||
code = """\
|
|
||||||
from cpl_cli.abc.generate_schematic_abc import GenerateSchematicABC
|
|
||||||
|
|
||||||
|
|
||||||
class $Name(GenerateSchematicABC):
|
|
||||||
|
|
||||||
def __init__(self, *args: str):
|
|
||||||
GenerateSchematicABC.__init__(self, *args)
|
|
||||||
|
|
||||||
def get_code(self) -> str:
|
|
||||||
import textwrap
|
|
||||||
code = textwrap.dedent(\"\"\"\\
|
|
||||||
from enum import Enum
|
|
||||||
|
|
||||||
|
|
||||||
class $Name(Enum):
|
|
||||||
|
|
||||||
atr = 0
|
|
||||||
\"\"\")
|
|
||||||
return self.build_code_str(code, Name=self._class_name)
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def register(cls):
|
|
||||||
GenerateSchematicABC.register(
|
|
||||||
cls,
|
|
||||||
'$NameLower',
|
|
||||||
[]
|
|
||||||
)
|
|
||||||
"""
|
|
||||||
return self.build_code_str(code, Name=self._class_name, NameLower=self._class_name.lower())
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def register(cls):
|
|
||||||
GenerateSchematicABC.register(cls, "schematic", ["scheme", "SCHEME"])
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
import textwrap
|
|
||||||
|
|
||||||
from cpl_cli.abc.generate_schematic_abc import GenerateSchematicABC
|
|
||||||
|
|
||||||
|
|
||||||
class Service(GenerateSchematicABC):
|
|
||||||
def __init__(self, *args: str):
|
|
||||||
GenerateSchematicABC.__init__(self, *args)
|
|
||||||
|
|
||||||
def get_code(self) -> str:
|
|
||||||
code = """\
|
|
||||||
class $Name:
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
pass
|
|
||||||
"""
|
|
||||||
x = self.build_code_str(code, Name=self._class_name)
|
|
||||||
return x
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def register(cls):
|
|
||||||
GenerateSchematicABC.register(cls, "service", ["s", "S"])
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
import textwrap
|
|
||||||
|
|
||||||
from cpl_cli.abc.generate_schematic_abc import GenerateSchematicABC
|
|
||||||
|
|
||||||
|
|
||||||
class Startup(GenerateSchematicABC):
|
|
||||||
def __init__(self, *args: str):
|
|
||||||
GenerateSchematicABC.__init__(self, *args)
|
|
||||||
|
|
||||||
def get_code(self) -> str:
|
|
||||||
code = """\
|
|
||||||
from cpl_core.application import StartupABC
|
|
||||||
from cpl_core.configuration import ConfigurationABC
|
|
||||||
from cpl_core.dependency_injection import ServiceProviderABC, ServiceCollectionABC
|
|
||||||
from cpl_core.environment import ApplicationEnvironment
|
|
||||||
|
|
||||||
|
|
||||||
class $Name(StartupABC):
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
StartupABC.__init__(self)
|
|
||||||
|
|
||||||
def configure_configuration(self, configuration: ConfigurationABC, environment: ApplicationEnvironment) -> ConfigurationABC:
|
|
||||||
return configuration
|
|
||||||
|
|
||||||
def configure_services(self, services: ServiceCollectionABC, environment: ApplicationEnvironment) -> ServiceProviderABC:
|
|
||||||
return services.build_service_provider()
|
|
||||||
"""
|
|
||||||
x = self.build_code_str(code, Name=self._class_name)
|
|
||||||
return x
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def register(cls):
|
|
||||||
GenerateSchematicABC.register(cls, "startup", ["stup", "STUP"])
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
import textwrap
|
|
||||||
|
|
||||||
from cpl_cli.abc.generate_schematic_abc import GenerateSchematicABC
|
|
||||||
from cpl_core.utils import String
|
|
||||||
|
|
||||||
|
|
||||||
class StartupExtension(GenerateSchematicABC):
|
|
||||||
def __init__(self, *args: str):
|
|
||||||
GenerateSchematicABC.__init__(self, *args)
|
|
||||||
|
|
||||||
def get_code(self) -> str:
|
|
||||||
code = """\
|
|
||||||
from cpl_core.application.startup_extension_abc import StartupExtensionABC
|
|
||||||
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 $Name(StartupExtensionABC):
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def configure_configuration(self, config: ConfigurationABC, env: ApplicationEnvironmentABC):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def configure_services(self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC):
|
|
||||||
pass
|
|
||||||
"""
|
|
||||||
x = self.build_code_str(code, Name=String.convert_to_camel_case(self._class_name))
|
|
||||||
return x
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def register(cls):
|
|
||||||
GenerateSchematicABC.register(cls, "startup-extension", ["stupex", "STUPEX"])
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
import textwrap
|
|
||||||
|
|
||||||
from cpl_cli.abc.generate_schematic_abc import GenerateSchematicABC
|
|
||||||
from cpl_core.utils import String
|
|
||||||
|
|
||||||
|
|
||||||
class TestCase(GenerateSchematicABC):
|
|
||||||
def __init__(self, *args: str):
|
|
||||||
GenerateSchematicABC.__init__(self, *args)
|
|
||||||
|
|
||||||
def get_code(self) -> str:
|
|
||||||
code = """\
|
|
||||||
import unittest
|
|
||||||
|
|
||||||
|
|
||||||
class $Name(unittest.TestCase):
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def test_equal(self):
|
|
||||||
pass
|
|
||||||
"""
|
|
||||||
return self.build_code_str(code, Name=String.convert_to_camel_case(self._class_name))
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def register(cls):
|
|
||||||
GenerateSchematicABC.register(cls, "test-case", ["tc", "TC"])
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
import textwrap
|
|
||||||
|
|
||||||
from cpl_cli.abc.generate_schematic_abc import GenerateSchematicABC
|
|
||||||
|
|
||||||
|
|
||||||
class Thread(GenerateSchematicABC):
|
|
||||||
def __init__(self, *args: str):
|
|
||||||
GenerateSchematicABC.__init__(self, *args)
|
|
||||||
|
|
||||||
def get_code(self) -> str:
|
|
||||||
code = """\
|
|
||||||
import threading
|
|
||||||
|
|
||||||
|
|
||||||
class $Name(threading.Thread):
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
threading.Thread.__init__(self)
|
|
||||||
|
|
||||||
def run(self) -> None:
|
|
||||||
pass
|
|
||||||
"""
|
|
||||||
x = self.build_code_str(code, Name=self._class_name)
|
|
||||||
return x
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def register(cls):
|
|
||||||
GenerateSchematicABC.register(cls, "thread", ["t", "T"])
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
import textwrap
|
|
||||||
|
|
||||||
from cpl_cli.abc.generate_schematic_abc import GenerateSchematicABC
|
|
||||||
|
|
||||||
|
|
||||||
class Validator(GenerateSchematicABC):
|
|
||||||
def __init__(self, *args: str):
|
|
||||||
GenerateSchematicABC.__init__(self, *args)
|
|
||||||
|
|
||||||
def get_code(self) -> str:
|
|
||||||
code = """\
|
|
||||||
from cpl_core.configuration.validator_abc import ValidatorABC
|
|
||||||
|
|
||||||
|
|
||||||
class $Name(ValidatorABC):
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
ValidatorABC.__init__(self)
|
|
||||||
|
|
||||||
def validate(self) -> bool:
|
|
||||||
return True
|
|
||||||
"""
|
|
||||||
x = self.build_code_str(code, Name=self._class_name)
|
|
||||||
return x
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def register(cls):
|
|
||||||
GenerateSchematicABC.register(cls, "validator", ["v", "V"])
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
"""
|
|
||||||
cpl-cli CPL CLI
|
|
||||||
~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
CPL Command Line Interface
|
|
||||||
|
|
||||||
:copyright: (c) 2020 - 2024 sh-edraft.de
|
|
||||||
:license: MIT, see LICENSE for more details.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
__title__ = "cpl_cli"
|
|
||||||
__author__ = "Sven Heidemann"
|
|
||||||
__license__ = "MIT"
|
|
||||||
__copyright__ = "Copyright (c) 2020 - 2024 sh-edraft.de"
|
|
||||||
__version__ = "2024.10.0"
|
|
||||||
|
|
||||||
from collections import namedtuple
|
|
||||||
|
|
||||||
|
|
||||||
# imports:
|
|
||||||
from .cli import CLI
|
|
||||||
from .command_abc import CommandABC
|
|
||||||
from .error import Error
|
|
||||||
from .main import main
|
|
||||||
from .startup import Startup
|
|
||||||
|
|
||||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
|
||||||
version_info = VersionInfo(major="2024", minor="10", micro="0")
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
"""
|
|
||||||
cpl-cli CPL CLI
|
|
||||||
~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
CPL Command Line Interface
|
|
||||||
|
|
||||||
:copyright: (c) 2020 - 2024 sh-edraft.de
|
|
||||||
:license: MIT, see LICENSE for more details.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
__title__ = "cpl_cli._templates"
|
|
||||||
__author__ = "Sven Heidemann"
|
|
||||||
__license__ = "MIT"
|
|
||||||
__copyright__ = "Copyright (c) 2020 - 2024 sh-edraft.de"
|
|
||||||
__version__ = "2024.10.0"
|
|
||||||
|
|
||||||
from collections import namedtuple
|
|
||||||
|
|
||||||
|
|
||||||
# imports:
|
|
||||||
|
|
||||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
|
||||||
version_info = VersionInfo(major="2024", minor="10", micro="0")
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
"""
|
|
||||||
cpl-cli CPL CLI
|
|
||||||
~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
CPL Command Line Interface
|
|
||||||
|
|
||||||
:copyright: (c) 2020 - 2024 sh-edraft.de
|
|
||||||
:license: MIT, see LICENSE for more details.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
__title__ = "cpl_cli._templates.build"
|
|
||||||
__author__ = "Sven Heidemann"
|
|
||||||
__license__ = "MIT"
|
|
||||||
__copyright__ = "Copyright (c) 2020 - 2024 sh-edraft.de"
|
|
||||||
__version__ = "2024.10.0"
|
|
||||||
|
|
||||||
from collections import namedtuple
|
|
||||||
|
|
||||||
|
|
||||||
# imports:
|
|
||||||
|
|
||||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
|
||||||
version_info = VersionInfo(major="2024", minor="10", micro="0")
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
import textwrap
|
|
||||||
|
|
||||||
|
|
||||||
class InitTemplate:
|
|
||||||
@staticmethod
|
|
||||||
def get_init_py() -> str:
|
|
||||||
string = textwrap.dedent(
|
|
||||||
"""\
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
\"\"\"
|
|
||||||
$Name $Description
|
|
||||||
~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
$LongDescription
|
|
||||||
|
|
||||||
:copyright: (c) $CopyrightDate $CopyrightName
|
|
||||||
:license: $LicenseDescription
|
|
||||||
|
|
||||||
\"\"\"
|
|
||||||
|
|
||||||
__title__ = "$Title"
|
|
||||||
__author__ = "$Author"
|
|
||||||
__license__ = "$LicenseName"
|
|
||||||
__copyright__ = "Copyright (c) $CopyrightDate $CopyrightName"
|
|
||||||
__version__ = "$Version"
|
|
||||||
|
|
||||||
from collections import namedtuple
|
|
||||||
|
|
||||||
|
|
||||||
$Imports
|
|
||||||
|
|
||||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
|
||||||
version_info = VersionInfo(major="$Major", minor="$Minor", micro="$Micro")
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
|
|
||||||
return string
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
"""
|
|
||||||
cpl-cli CPL CLI
|
|
||||||
~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
CPL Command Line Interface
|
|
||||||
|
|
||||||
:copyright: (c) 2020 - 2024 sh-edraft.de
|
|
||||||
:license: MIT, see LICENSE for more details.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
__title__ = "cpl_cli._templates.publish"
|
|
||||||
__author__ = "Sven Heidemann"
|
|
||||||
__license__ = "MIT"
|
|
||||||
__copyright__ = "Copyright (c) 2020 - 2024 sh-edraft.de"
|
|
||||||
__version__ = "2024.10.0"
|
|
||||||
|
|
||||||
from collections import namedtuple
|
|
||||||
|
|
||||||
|
|
||||||
# imports:
|
|
||||||
|
|
||||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
|
||||||
version_info = VersionInfo(major="2024", minor="10", micro="0")
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
import textwrap
|
|
||||||
|
|
||||||
|
|
||||||
class SetupTemplate:
|
|
||||||
@staticmethod
|
|
||||||
def get_setup_py() -> str:
|
|
||||||
string = textwrap.dedent(
|
|
||||||
"""\
|
|
||||||
\"\"\"
|
|
||||||
This file is generated by CPL CLI
|
|
||||||
\"\"\"
|
|
||||||
|
|
||||||
import setuptools
|
|
||||||
|
|
||||||
setuptools.setup(
|
|
||||||
name='$Name',
|
|
||||||
version='$Version',
|
|
||||||
packages=$Packages,
|
|
||||||
url='$URL',
|
|
||||||
license='$LicenseName',
|
|
||||||
author='$Author',
|
|
||||||
author_email='$AuthorMail',
|
|
||||||
include_package_data=$IncludePackageData,
|
|
||||||
description='$Description',
|
|
||||||
python_requires='$PyRequires',
|
|
||||||
install_requires=$Dependencies,
|
|
||||||
entry_points=$EntryPoints,
|
|
||||||
package_data=$PackageData
|
|
||||||
)
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
|
|
||||||
return string
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
from abc import ABC, abstractmethod
|
|
||||||
|
|
||||||
|
|
||||||
class TemplateFileABC(ABC):
|
|
||||||
@abstractmethod
|
|
||||||
def __init__(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
@property
|
|
||||||
@abstractmethod
|
|
||||||
def name(self) -> str:
|
|
||||||
pass
|
|
||||||
|
|
||||||
@property
|
|
||||||
@abstractmethod
|
|
||||||
def path(self) -> str:
|
|
||||||
pass
|
|
||||||
|
|
||||||
@property
|
|
||||||
@abstractmethod
|
|
||||||
def value(self) -> str:
|
|
||||||
pass
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
"""
|
|
||||||
cpl-cli CPL CLI
|
|
||||||
~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
CPL Command Line Interface
|
|
||||||
|
|
||||||
:copyright: (c) 2020 - 2024 sh-edraft.de
|
|
||||||
:license: MIT, see LICENSE for more details.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
__title__ = "cpl_cli.abc"
|
|
||||||
__author__ = "Sven Heidemann"
|
|
||||||
__license__ = "MIT"
|
|
||||||
__copyright__ = "Copyright (c) 2020 - 2024 sh-edraft.de"
|
|
||||||
__version__ = "2024.10.0"
|
|
||||||
|
|
||||||
from collections import namedtuple
|
|
||||||
|
|
||||||
|
|
||||||
# imports
|
|
||||||
|
|
||||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
|
||||||
version_info = VersionInfo(major="2024", minor="10", micro="0")
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
from abc import ABC, abstractmethod
|
|
||||||
|
|
||||||
from cpl_cli.abc.file_template_abc import FileTemplateABC
|
|
||||||
from cpl_core.utils import String
|
|
||||||
|
|
||||||
|
|
||||||
class CodeFileTemplateABC(FileTemplateABC):
|
|
||||||
@abstractmethod
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
name: str,
|
|
||||||
path: str,
|
|
||||||
code: str,
|
|
||||||
use_application_api: bool,
|
|
||||||
use_startup: bool,
|
|
||||||
use_service_providing: bool,
|
|
||||||
use_async: bool,
|
|
||||||
):
|
|
||||||
FileTemplateABC.__init__(self, name, path, code)
|
|
||||||
self._use_application_api = use_application_api
|
|
||||||
self._use_startup = use_startup
|
|
||||||
self._use_service_providing = use_service_providing
|
|
||||||
self._use_async = use_async
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
from abc import ABC, abstractmethod
|
|
||||||
|
|
||||||
from cpl_core.utils import String
|
|
||||||
|
|
||||||
|
|
||||||
class FileTemplateABC(ABC):
|
|
||||||
@abstractmethod
|
|
||||||
def __init__(self, name: str, path: str, code: str):
|
|
||||||
self._name = f"{String.convert_to_snake_case(name)}.py"
|
|
||||||
self._path = path
|
|
||||||
self._code = code
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return f"<{type(self).__name__} {self._path}{self._name}>"
|
|
||||||
|
|
||||||
@property
|
|
||||||
def name(self) -> str:
|
|
||||||
return self._name
|
|
||||||
|
|
||||||
@property
|
|
||||||
def path(self) -> str:
|
|
||||||
return self._path
|
|
||||||
|
|
||||||
@path.setter
|
|
||||||
def path(self, value: str):
|
|
||||||
self._path = value
|
|
||||||
|
|
||||||
@property
|
|
||||||
def value(self) -> str:
|
|
||||||
return self.get_code()
|
|
||||||
|
|
||||||
@abstractmethod
|
|
||||||
def get_code(self) -> str:
|
|
||||||
pass
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
import textwrap
|
|
||||||
from abc import abstractmethod
|
|
||||||
from string import Template
|
|
||||||
|
|
||||||
from cpl_cli.abc.file_template_abc import FileTemplateABC
|
|
||||||
from cpl_cli.configuration.schematic_collection import SchematicCollection
|
|
||||||
from cpl_core.utils import String
|
|
||||||
|
|
||||||
|
|
||||||
class GenerateSchematicABC(FileTemplateABC):
|
|
||||||
def __init__(self, name: str, schematic: str, path: str):
|
|
||||||
FileTemplateABC.__init__(self, name, path, "")
|
|
||||||
self._name = f"{String.convert_to_snake_case(name)}_{schematic}.py"
|
|
||||||
if schematic in name.lower():
|
|
||||||
self._name = f"{String.convert_to_snake_case(name)}.py"
|
|
||||||
|
|
||||||
self._class_name = name
|
|
||||||
if name != "":
|
|
||||||
self._class_name = f"{String.first_to_upper(name)}{String.first_to_upper(schematic)}"
|
|
||||||
|
|
||||||
if schematic in name.lower():
|
|
||||||
self._class_name = f"{String.first_to_upper(name)}"
|
|
||||||
|
|
||||||
@property
|
|
||||||
def class_name(self) -> str:
|
|
||||||
return self._class_name
|
|
||||||
|
|
||||||
@abstractmethod
|
|
||||||
def get_code(self) -> str:
|
|
||||||
pass
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def build_code_str(cls, code: str, **kwargs) -> str:
|
|
||||||
text = textwrap.dedent(code)
|
|
||||||
return Template(text).substitute(**kwargs)
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
@abstractmethod
|
|
||||||
def register(cls, *args):
|
|
||||||
SchematicCollection.register(*args)
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
from abc import ABC, abstractmethod
|
|
||||||
from typing import Optional
|
|
||||||
|
|
||||||
from cpl_cli.abc.file_template_abc import FileTemplateABC
|
|
||||||
from cpl_cli.configuration import WorkspaceSettings
|
|
||||||
|
|
||||||
|
|
||||||
class ProjectTypeABC(ABC):
|
|
||||||
@abstractmethod
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
base_path: str,
|
|
||||||
project_name: str,
|
|
||||||
workspace: Optional[WorkspaceSettings],
|
|
||||||
use_application_api: bool,
|
|
||||||
use_startup: bool,
|
|
||||||
use_service_providing: bool,
|
|
||||||
use_async: bool,
|
|
||||||
project_file_data: dict,
|
|
||||||
):
|
|
||||||
self._templates: list[FileTemplateABC] = []
|
|
||||||
self._base_path = base_path
|
|
||||||
self._project_name = project_name
|
|
||||||
self._workspace = workspace
|
|
||||||
self._use_application_api = use_application_api
|
|
||||||
self._use_startup = use_startup
|
|
||||||
self._use_service_providing = use_service_providing
|
|
||||||
self._use_async = use_async
|
|
||||||
self._project_file_data = project_file_data
|
|
||||||
|
|
||||||
@property
|
|
||||||
def templates(self) -> list[FileTemplateABC]:
|
|
||||||
return self._templates
|
|
||||||
|
|
||||||
def add_template(self, t: FileTemplateABC):
|
|
||||||
self._templates.append(t)
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
{
|
|
||||||
"CLI": {
|
|
||||||
"PipPath": "https://pip.sh-edraft.de"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
import sys
|
|
||||||
import traceback
|
|
||||||
|
|
||||||
from cpl_cli.error import Error
|
|
||||||
from cpl_core.application.application_abc import ApplicationABC
|
|
||||||
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
|
|
||||||
|
|
||||||
|
|
||||||
class CLI(ApplicationABC):
|
|
||||||
def __init__(self, config: ConfigurationABC, services: ServiceProviderABC):
|
|
||||||
"""
|
|
||||||
CPL CLI
|
|
||||||
"""
|
|
||||||
ApplicationABC.__init__(self, config, services)
|
|
||||||
|
|
||||||
self._options: list[str] = []
|
|
||||||
|
|
||||||
def configure(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def main(self):
|
|
||||||
"""
|
|
||||||
Entry point of the CPL CLI
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
result = self._configuration.parse_console_arguments(self._services)
|
|
||||||
if result:
|
|
||||||
Console.write_line()
|
|
||||||
return
|
|
||||||
|
|
||||||
if len(self._configuration.additional_arguments) == 0:
|
|
||||||
Error.error("Expected command")
|
|
||||||
return
|
|
||||||
|
|
||||||
unexpected_arguments = ", ".join(self._configuration.additional_arguments)
|
|
||||||
Error.error(f"Unexpected argument(s): {unexpected_arguments}")
|
|
||||||
Console.write_line()
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
Console.write_line()
|
|
||||||
sys.exit()
|
|
||||||
except Exception as e:
|
|
||||||
Console.error(str(e), traceback.format_exc())
|
|
||||||
sys.exit()
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
from typing import Optional
|
|
||||||
|
|
||||||
from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC
|
|
||||||
|
|
||||||
|
|
||||||
class CLISettings(ConfigurationModelABC):
|
|
||||||
def __init__(self, pip_path: str = None):
|
|
||||||
ConfigurationModelABC.__init__(self)
|
|
||||||
|
|
||||||
self._pip_path: Optional[str] = pip_path
|
|
||||||
|
|
||||||
@property
|
|
||||||
def pip_path(self) -> str:
|
|
||||||
return self._pip_path
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
from enum import Enum
|
|
||||||
|
|
||||||
|
|
||||||
class CLISettingsNameEnum(Enum):
|
|
||||||
pip_path = "PipPath"
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
"""
|
|
||||||
cpl-cli CPL CLI
|
|
||||||
~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
CPL Command Line Interface
|
|
||||||
|
|
||||||
:copyright: (c) 2020 - 2024 sh-edraft.de
|
|
||||||
:license: MIT, see LICENSE for more details.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
__title__ = "cpl_cli.command"
|
|
||||||
__author__ = "Sven Heidemann"
|
|
||||||
__license__ = "MIT"
|
|
||||||
__copyright__ = "Copyright (c) 2020 - 2024 sh-edraft.de"
|
|
||||||
__version__ = "2024.10.0"
|
|
||||||
|
|
||||||
from collections import namedtuple
|
|
||||||
|
|
||||||
|
|
||||||
# imports:
|
|
||||||
from .build_service import BuildService
|
|
||||||
from .generate_service import GenerateService
|
|
||||||
from .help_service import HelpService
|
|
||||||
from .new_service import NewService
|
|
||||||
from .publish_service import PublishService
|
|
||||||
from .version_service import VersionService
|
|
||||||
|
|
||||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
|
||||||
version_info = VersionInfo(major="2024", minor="10", micro="0")
|
|
||||||
@@ -1,138 +0,0 @@
|
|||||||
import json
|
|
||||||
import os
|
|
||||||
import textwrap
|
|
||||||
from typing import Optional
|
|
||||||
|
|
||||||
from cpl_cli.command_abc import CommandABC
|
|
||||||
from cpl_cli.configuration.build_settings import BuildSettings
|
|
||||||
from cpl_cli.configuration.project_settings import ProjectSettings
|
|
||||||
from cpl_cli.configuration.settings_helper import SettingsHelper
|
|
||||||
from cpl_cli.configuration.workspace_settings import WorkspaceSettings
|
|
||||||
from cpl_core.configuration.configuration_abc import ConfigurationABC
|
|
||||||
from cpl_core.console.console import Console
|
|
||||||
from cpl_core.console.foreground_color_enum import ForegroundColorEnum
|
|
||||||
|
|
||||||
|
|
||||||
class AddService(CommandABC):
|
|
||||||
def __init__(self, config: ConfigurationABC, workspace: WorkspaceSettings):
|
|
||||||
"""
|
|
||||||
Service for CLI command add
|
|
||||||
"""
|
|
||||||
CommandABC.__init__(self)
|
|
||||||
|
|
||||||
self._config = config
|
|
||||||
self._workspace = workspace
|
|
||||||
self._is_simulation = False
|
|
||||||
|
|
||||||
@property
|
|
||||||
def help_message(self) -> str:
|
|
||||||
return textwrap.dedent(
|
|
||||||
"""\
|
|
||||||
Adds a project reference to given project.
|
|
||||||
Usage: cpl add <source-project> <target-project>
|
|
||||||
|
|
||||||
Arguments:
|
|
||||||
source-project: Name of the project to which the reference has to be
|
|
||||||
target-project: Name of the project to be referenced
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
|
|
||||||
def _edit_project_file(self, source: str, project_settings: ProjectSettings, build_settings: BuildSettings):
|
|
||||||
if self._is_simulation:
|
|
||||||
return
|
|
||||||
with open(source, "w") as file:
|
|
||||||
file.write(
|
|
||||||
json.dumps(
|
|
||||||
{
|
|
||||||
ProjectSettings.__name__: SettingsHelper.get_project_settings_dict(project_settings),
|
|
||||||
BuildSettings.__name__: SettingsHelper.get_build_settings_dict(build_settings),
|
|
||||||
},
|
|
||||||
indent=2,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
file.close()
|
|
||||||
|
|
||||||
def execute(self, args: list[str]):
|
|
||||||
"""
|
|
||||||
Entry point of command
|
|
||||||
:param args:
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
if "simulate" in args:
|
|
||||||
args.remove("simulate")
|
|
||||||
Console.write_line("Running in simulation mode:")
|
|
||||||
self._is_simulation = True
|
|
||||||
|
|
||||||
if len(args) == 0:
|
|
||||||
Console.error("Expected source and target project")
|
|
||||||
return
|
|
||||||
|
|
||||||
elif len(args) == 1:
|
|
||||||
Console.error("Expected target project")
|
|
||||||
return
|
|
||||||
|
|
||||||
elif len(args) > 2:
|
|
||||||
Console.error(f'Unexpected argument(s): {", ".join(args[2:])}')
|
|
||||||
return
|
|
||||||
|
|
||||||
# file names
|
|
||||||
source = args[0]
|
|
||||||
target = args[1]
|
|
||||||
# validation flags
|
|
||||||
is_invalid_source = False
|
|
||||||
is_invalid_target = source == target
|
|
||||||
|
|
||||||
if not is_invalid_target:
|
|
||||||
if self._workspace is None:
|
|
||||||
is_invalid_source = not os.path.isfile(source)
|
|
||||||
is_invalid_target = not os.path.isfile(target)
|
|
||||||
|
|
||||||
else:
|
|
||||||
if source not in self._workspace.projects:
|
|
||||||
is_invalid_source = True
|
|
||||||
|
|
||||||
else:
|
|
||||||
source = self._workspace.projects[source]
|
|
||||||
|
|
||||||
if target not in self._workspace.projects:
|
|
||||||
is_invalid_target = True
|
|
||||||
|
|
||||||
else:
|
|
||||||
target = self._workspace.projects[target]
|
|
||||||
|
|
||||||
# load project-name.json
|
|
||||||
self._config.add_json_file(source, optional=True, output=False)
|
|
||||||
project_settings: Optional[ProjectSettings] = self._config.get_configuration(ProjectSettings)
|
|
||||||
build_settings: Optional[BuildSettings] = self._config.get_configuration(BuildSettings)
|
|
||||||
|
|
||||||
if project_settings is None or build_settings is None:
|
|
||||||
is_invalid_source = True
|
|
||||||
|
|
||||||
if is_invalid_source:
|
|
||||||
Console.error(f"Invalid source: {source}")
|
|
||||||
return
|
|
||||||
|
|
||||||
if is_invalid_target or source == target or not os.path.isfile(target):
|
|
||||||
Console.error(f"Invalid target: {target}")
|
|
||||||
return
|
|
||||||
|
|
||||||
if self._workspace is None:
|
|
||||||
target = f"../{target}"
|
|
||||||
else:
|
|
||||||
target = target.replace("src", "..")
|
|
||||||
|
|
||||||
if target in build_settings.project_references:
|
|
||||||
Console.error(f"Project reference already exists.")
|
|
||||||
return
|
|
||||||
|
|
||||||
build_settings.project_references.append(target)
|
|
||||||
|
|
||||||
Console.spinner(
|
|
||||||
f"Editing {source}",
|
|
||||||
self._edit_project_file,
|
|
||||||
source,
|
|
||||||
project_settings,
|
|
||||||
build_settings,
|
|
||||||
text_foreground_color=ForegroundColorEnum.green,
|
|
||||||
spinner_foreground_color=ForegroundColorEnum.cyan,
|
|
||||||
)
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
import textwrap
|
|
||||||
|
|
||||||
from cpl_cli.command_abc import CommandABC
|
|
||||||
from cpl_cli.publish.publisher_abc import PublisherABC
|
|
||||||
|
|
||||||
|
|
||||||
class BuildService(CommandABC):
|
|
||||||
def __init__(self, publisher: PublisherABC):
|
|
||||||
"""
|
|
||||||
Service for the CLI command build
|
|
||||||
:param publisher:
|
|
||||||
"""
|
|
||||||
CommandABC.__init__(self)
|
|
||||||
|
|
||||||
self._publisher = publisher
|
|
||||||
|
|
||||||
@property
|
|
||||||
def help_message(self) -> str:
|
|
||||||
return textwrap.dedent(
|
|
||||||
"""\
|
|
||||||
Copies an python app into an output directory named build/ at the given output path. Must be executed within a CPL workspace or project directory
|
|
||||||
Usage: cpl build
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
|
|
||||||
def execute(self, args: list[str]):
|
|
||||||
"""
|
|
||||||
Entry point of command
|
|
||||||
:param args:
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
self._publisher.build()
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
import os
|
|
||||||
import subprocess
|
|
||||||
|
|
||||||
from cpl_core.environment import ApplicationEnvironmentABC
|
|
||||||
|
|
||||||
from cpl_core.configuration.configuration_abc import ConfigurationABC
|
|
||||||
from cpl_core.console.console import Console
|
|
||||||
from cpl_cli.command_abc import CommandABC
|
|
||||||
from cpl_cli.configuration.workspace_settings import WorkspaceSettings
|
|
||||||
|
|
||||||
|
|
||||||
class CustomScriptService(CommandABC):
|
|
||||||
def __init__(self, config: ConfigurationABC, env: ApplicationEnvironmentABC, ws: WorkspaceSettings):
|
|
||||||
"""
|
|
||||||
Service for CLI scripts
|
|
||||||
"""
|
|
||||||
CommandABC.__init__(self)
|
|
||||||
|
|
||||||
self._config = config
|
|
||||||
self._env = env
|
|
||||||
self._workspace = ws
|
|
||||||
|
|
||||||
@property
|
|
||||||
def help_message(self) -> str:
|
|
||||||
return ""
|
|
||||||
|
|
||||||
def execute(self, args: list[str]):
|
|
||||||
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:
|
|
||||||
if script != cmd:
|
|
||||||
continue
|
|
||||||
|
|
||||||
command = ""
|
|
||||||
external_args = self._config.get_configuration("ARGS")
|
|
||||||
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))
|
|
||||||
@@ -1,223 +0,0 @@
|
|||||||
import importlib
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
import textwrap
|
|
||||||
import traceback
|
|
||||||
|
|
||||||
from cpl_cli.abc.generate_schematic_abc import GenerateSchematicABC
|
|
||||||
from cpl_cli.command_abc import CommandABC
|
|
||||||
from cpl_cli.configuration import WorkspaceSettings
|
|
||||||
from cpl_cli.configuration.schematic_collection import SchematicCollection
|
|
||||||
from cpl_cli.helper.dependencies import Dependencies
|
|
||||||
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):
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
configuration: ConfigurationABC,
|
|
||||||
workspace: WorkspaceSettings,
|
|
||||||
):
|
|
||||||
"""
|
|
||||||
Service for the CLI command generate
|
|
||||||
:param configuration:
|
|
||||||
"""
|
|
||||||
CommandABC.__init__(self)
|
|
||||||
|
|
||||||
self._config = configuration
|
|
||||||
self._workspace = workspace
|
|
||||||
|
|
||||||
self._config = configuration
|
|
||||||
self._env = self._config.environment
|
|
||||||
self._schematics = {}
|
|
||||||
self._schematic_classes = set()
|
|
||||||
|
|
||||||
for package_name, version in Dependencies.get_cpl_packages():
|
|
||||||
if package_name == "cpl-cli":
|
|
||||||
continue
|
|
||||||
package = importlib.import_module(String.convert_to_snake_case(package_name))
|
|
||||||
self._read_custom_schematics_from_path(os.path.dirname(package.__file__))
|
|
||||||
|
|
||||||
self._read_custom_schematics_from_path(self._env.working_directory)
|
|
||||||
self._read_custom_schematics_from_path(self._env.runtime_directory)
|
|
||||||
|
|
||||||
if len(self._schematic_classes) == 0:
|
|
||||||
Console.error(f"No schematics found in template directory: .cpl")
|
|
||||||
sys.exit()
|
|
||||||
|
|
||||||
known_schematics = []
|
|
||||||
for schematic in self._schematic_classes:
|
|
||||||
known_schematics.append(schematic.__name__)
|
|
||||||
schematic.register()
|
|
||||||
|
|
||||||
self._schematics = SchematicCollection.get_schematics()
|
|
||||||
|
|
||||||
@property
|
|
||||||
def help_message(self) -> str:
|
|
||||||
schematics = []
|
|
||||||
for schematic in self._schematics:
|
|
||||||
aliases = "|".join(self._schematics[schematic]["Aliases"])
|
|
||||||
schematic_str = schematic
|
|
||||||
if len(aliases) > 0:
|
|
||||||
schematic_str = f"{schematic} ({aliases})"
|
|
||||||
|
|
||||||
schematics.append(schematic_str)
|
|
||||||
help_msg = textwrap.dedent(
|
|
||||||
"""\
|
|
||||||
Generate a file based on schematic.
|
|
||||||
Usage: cpl generate <schematic> <name>
|
|
||||||
|
|
||||||
Arguments:
|
|
||||||
schematic: The schematic to generate.
|
|
||||||
name: The name of the generated file
|
|
||||||
|
|
||||||
Schematics:"""
|
|
||||||
)
|
|
||||||
|
|
||||||
for schematic in schematics:
|
|
||||||
help_msg += f"\n {schematic}"
|
|
||||||
return help_msg
|
|
||||||
|
|
||||||
def _read_custom_schematics_from_path(self, path: str):
|
|
||||||
if not os.path.exists(os.path.join(path, ".cpl")):
|
|
||||||
return
|
|
||||||
|
|
||||||
sys.path.insert(0, os.path.join(path, ".cpl"))
|
|
||||||
for r, d, f in os.walk(os.path.join(path, ".cpl")):
|
|
||||||
for file in f:
|
|
||||||
if not file.startswith("schematic_") or not file.endswith(".py"):
|
|
||||||
continue
|
|
||||||
|
|
||||||
try:
|
|
||||||
exec(open(os.path.join(r, file), "r").read())
|
|
||||||
self._schematic_classes.update(GenerateSchematicABC.__subclasses__())
|
|
||||||
except Exception as e:
|
|
||||||
Console.error(str(e), traceback.format_exc())
|
|
||||||
sys.exit(-1)
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _create_file(file_path: str, value: str):
|
|
||||||
"""
|
|
||||||
Creates the given file with content
|
|
||||||
:param file_path:
|
|
||||||
:param value:
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
with open(file_path, "w") as template:
|
|
||||||
template.write(value)
|
|
||||||
template.close()
|
|
||||||
|
|
||||||
def _create_init_files(
|
|
||||||
self, file_path: str, template: GenerateSchematicABC, class_name: str, schematic: str, rel_path: str
|
|
||||||
):
|
|
||||||
if not os.path.isdir(os.path.dirname(file_path)):
|
|
||||||
os.makedirs(os.path.dirname(file_path))
|
|
||||||
directory = ""
|
|
||||||
for subdir in template.path.split("/"):
|
|
||||||
directory = os.path.join(directory, subdir)
|
|
||||||
if subdir == "src":
|
|
||||||
continue
|
|
||||||
|
|
||||||
file = self._schematics["init"]["Template"](class_name, "init", rel_path)
|
|
||||||
if os.path.exists(os.path.join(os.path.abspath(directory), file.name)):
|
|
||||||
continue
|
|
||||||
|
|
||||||
Console.spinner(
|
|
||||||
f"Creating {os.path.abspath(directory)}/{file.name}",
|
|
||||||
self._create_file,
|
|
||||||
os.path.join(os.path.abspath(directory), file.name),
|
|
||||||
file.get_code(),
|
|
||||||
text_foreground_color=ForegroundColorEnum.green,
|
|
||||||
spinner_foreground_color=ForegroundColorEnum.cyan,
|
|
||||||
)
|
|
||||||
|
|
||||||
def _generate(self, schematic: str, name: str, template: type):
|
|
||||||
"""
|
|
||||||
Generates files by given schematic, name and template
|
|
||||||
:param schematic:
|
|
||||||
:param name:
|
|
||||||
:param template:
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
class_name = name
|
|
||||||
rel_path = ""
|
|
||||||
if "/" in name:
|
|
||||||
parts = name.split("/")
|
|
||||||
rel_path = "/".join(parts[:-1])
|
|
||||||
class_name = parts[len(parts) - 1]
|
|
||||||
|
|
||||||
if self._workspace is not None and parts[0] in self._workspace.projects:
|
|
||||||
rel_path = os.path.join(os.path.dirname(self._workspace.projects[parts[0]]), *parts[1:-1])
|
|
||||||
|
|
||||||
template = template(class_name, String.convert_to_snake_case(schematic), rel_path)
|
|
||||||
|
|
||||||
file_path = os.path.join(self._env.working_directory, template.path, template.name)
|
|
||||||
self._create_init_files(file_path, template, class_name, schematic, rel_path)
|
|
||||||
|
|
||||||
if os.path.isfile(file_path):
|
|
||||||
Console.error(f"{String.first_to_upper(schematic)} already exists!\n")
|
|
||||||
sys.exit()
|
|
||||||
|
|
||||||
message = f"Creating {self._env.working_directory}/{template.path}/{template.name}"
|
|
||||||
if template.path == "":
|
|
||||||
message = f"Creating {self._env.working_directory}/{template.name}"
|
|
||||||
|
|
||||||
Console.spinner(
|
|
||||||
message,
|
|
||||||
self._create_file,
|
|
||||||
file_path,
|
|
||||||
template.get_code(),
|
|
||||||
text_foreground_color=ForegroundColorEnum.green,
|
|
||||||
spinner_foreground_color=ForegroundColorEnum.cyan,
|
|
||||||
)
|
|
||||||
|
|
||||||
def _get_schematic_by_alias(self, schematic: str) -> str:
|
|
||||||
for key in self._schematics:
|
|
||||||
if schematic in self._schematics[key]["Aliases"]:
|
|
||||||
return key
|
|
||||||
|
|
||||||
return schematic
|
|
||||||
|
|
||||||
def execute(self, args: list[str]):
|
|
||||||
"""
|
|
||||||
Entry point of command
|
|
||||||
:param args:
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
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
|
|
||||||
and len(args) >= 1
|
|
||||||
and (args[0] in self._schematics or self._get_schematic_by_alias(args[0]) != args[0])
|
|
||||||
):
|
|
||||||
schematic = self._get_schematic_by_alias(args[0])
|
|
||||||
self._config.add_configuration(schematic, args[1])
|
|
||||||
value = args[1]
|
|
||||||
|
|
||||||
if schematic is None:
|
|
||||||
Console.error(f"Schematic not found")
|
|
||||||
Console.write_line(self.help_message)
|
|
||||||
sys.exit()
|
|
||||||
|
|
||||||
name = value
|
|
||||||
if name is None:
|
|
||||||
name = Console.read(f"Name for the {args[0]}: ")
|
|
||||||
|
|
||||||
if schematic in self._schematics:
|
|
||||||
s = self._schematics[schematic]
|
|
||||||
self._generate(schematic, name, s["Template"])
|
|
||||||
|
|
||||||
else:
|
|
||||||
self._help("Usage: cpl generate <schematic> [options]")
|
|
||||||
Console.write_line()
|
|
||||||
sys.exit()
|
|
||||||
@@ -1,67 +0,0 @@
|
|||||||
import sys
|
|
||||||
import textwrap
|
|
||||||
|
|
||||||
from cpl_core.console.console import Console
|
|
||||||
from cpl_core.console.foreground_color_enum import ForegroundColorEnum
|
|
||||||
from cpl_core.dependency_injection.service_provider_abc import ServiceProviderABC
|
|
||||||
from cpl_cli.command_abc import CommandABC
|
|
||||||
|
|
||||||
|
|
||||||
class HelpService(CommandABC):
|
|
||||||
def __init__(self, services: ServiceProviderABC):
|
|
||||||
"""
|
|
||||||
Service for CLI command help
|
|
||||||
"""
|
|
||||||
CommandABC.__init__(self)
|
|
||||||
|
|
||||||
self._services = services
|
|
||||||
|
|
||||||
@property
|
|
||||||
def help_message(self) -> str:
|
|
||||||
return textwrap.dedent(
|
|
||||||
"""\
|
|
||||||
Lists available command and their short descriptions.
|
|
||||||
Usage: cpl help
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
|
|
||||||
def execute(self, args: list[str]):
|
|
||||||
"""
|
|
||||||
Entry point of command
|
|
||||||
:param args:
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
if len(args) > 0:
|
|
||||||
Console.error(f'Unexpected argument(s): {", ".join(args)}')
|
|
||||||
sys.exit()
|
|
||||||
|
|
||||||
Console.write_line("Available Commands:")
|
|
||||||
commands = [
|
|
||||||
["add (a|a)", "Adds a project reference to given project."],
|
|
||||||
[
|
|
||||||
"build (b|B)",
|
|
||||||
"Prepares files for publish into an output directory named dist/ at the given output path. Must be executed from within a workspace directory.",
|
|
||||||
],
|
|
||||||
["generate (g|G)", "Generate a new file."],
|
|
||||||
["help (h|H)", "Lists available command and their short descriptions."],
|
|
||||||
[
|
|
||||||
"install (i|I)",
|
|
||||||
"With argument installs packages to project, without argument installs project dependencies.",
|
|
||||||
],
|
|
||||||
["new (n|N)", "Creates new CPL project."],
|
|
||||||
[
|
|
||||||
"publish (p|P)",
|
|
||||||
"Prepares files for publish into an output directory named dist/ at the given output path and executes setup.py. Must be executed from within a library workspace directory.",
|
|
||||||
],
|
|
||||||
["remove (r|R)", "Removes a project from workspace."],
|
|
||||||
["start (s|S)", "Starts CPL project, restarting on file changes."],
|
|
||||||
["uninstall (ui|UI)", "Uninstalls packages from project."],
|
|
||||||
["update (u|u)", "Update CPL and project dependencies."],
|
|
||||||
["version (v|V)", "Outputs CPL CLI version."],
|
|
||||||
]
|
|
||||||
for name, description in commands:
|
|
||||||
Console.set_foreground_color(ForegroundColorEnum.blue)
|
|
||||||
Console.write(f"\n\t{name} ")
|
|
||||||
Console.set_foreground_color(ForegroundColorEnum.default)
|
|
||||||
Console.write(f"{description}")
|
|
||||||
Console.write_line("\nRun 'cpl <command> --help' for command specific information's\n")
|
|
||||||
@@ -1,281 +0,0 @@
|
|||||||
import json
|
|
||||||
import os
|
|
||||||
import subprocess
|
|
||||||
import textwrap
|
|
||||||
import time
|
|
||||||
|
|
||||||
from packaging import version
|
|
||||||
|
|
||||||
from cpl_cli.cli_settings import CLISettings
|
|
||||||
from cpl_cli.command_abc import CommandABC
|
|
||||||
from cpl_cli.configuration.build_settings import BuildSettings
|
|
||||||
from cpl_cli.configuration.project_settings import ProjectSettings
|
|
||||||
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_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.environment.application_environment_abc import ApplicationEnvironmentABC
|
|
||||||
from cpl_core.utils.pip import Pip
|
|
||||||
|
|
||||||
|
|
||||||
class InstallService(CommandABC):
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
config: ConfigurationABC,
|
|
||||||
env: ApplicationEnvironmentABC,
|
|
||||||
build_settings: BuildSettings,
|
|
||||||
project_settings: ProjectSettings,
|
|
||||||
cli_settings: CLISettings,
|
|
||||||
):
|
|
||||||
"""
|
|
||||||
Service for the CLI command install
|
|
||||||
:param config:
|
|
||||||
:param env:
|
|
||||||
:param build_settings:
|
|
||||||
:param project_settings:
|
|
||||||
:param cli_settings:
|
|
||||||
"""
|
|
||||||
CommandABC.__init__(self)
|
|
||||||
|
|
||||||
self._config = config
|
|
||||||
self._env = env
|
|
||||||
self._build_settings = build_settings
|
|
||||||
self._project_settings = project_settings
|
|
||||||
self._cli_settings = cli_settings
|
|
||||||
|
|
||||||
self._is_simulation = False
|
|
||||||
self._is_virtual = False
|
|
||||||
self._is_dev = False
|
|
||||||
|
|
||||||
self._project_file = f"{self._project_settings.name}.json"
|
|
||||||
|
|
||||||
@property
|
|
||||||
def help_message(self) -> str:
|
|
||||||
return textwrap.dedent(
|
|
||||||
"""\
|
|
||||||
Installs given package via pip
|
|
||||||
Usage: cpl install <package>
|
|
||||||
|
|
||||||
Arguments:
|
|
||||||
package The package to install
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
|
|
||||||
def _wait(self, t: int, *args, source: str = None, stdout=None, stderr=None):
|
|
||||||
time.sleep(t)
|
|
||||||
|
|
||||||
def _install_project(self):
|
|
||||||
"""
|
|
||||||
Installs dependencies of CPl project
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
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.")
|
|
||||||
return
|
|
||||||
|
|
||||||
if self._project_settings.dependencies is None:
|
|
||||||
Error.error(f"Found invalid dependencies in {self._project_file}.")
|
|
||||||
return
|
|
||||||
|
|
||||||
for dependency in self._project_settings.dependencies:
|
|
||||||
Console.spinner(
|
|
||||||
f"Installing: {dependency}",
|
|
||||||
Pip.install if not self._is_virtual else self._wait,
|
|
||||||
dependency if not self._is_virtual else 2,
|
|
||||||
"--upgrade",
|
|
||||||
source=self._cli_settings.pip_path,
|
|
||||||
stdout=subprocess.DEVNULL,
|
|
||||||
stderr=subprocess.DEVNULL,
|
|
||||||
text_foreground_color=ForegroundColorEnum.green,
|
|
||||||
spinner_foreground_color=ForegroundColorEnum.cyan,
|
|
||||||
)
|
|
||||||
local_package = Pip.get_package(dependency)
|
|
||||||
if local_package is None:
|
|
||||||
Error.warn(f"Installation of package {dependency} failed!")
|
|
||||||
return
|
|
||||||
|
|
||||||
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,
|
|
||||||
"--upgrade",
|
|
||||||
source=self._cli_settings.pip_path,
|
|
||||||
stdout=subprocess.DEVNULL,
|
|
||||||
stderr=subprocess.DEVNULL,
|
|
||||||
text_foreground_color=ForegroundColorEnum.green,
|
|
||||||
spinner_foreground_color=ForegroundColorEnum.cyan,
|
|
||||||
)
|
|
||||||
local_package = Pip.get_package(dependency)
|
|
||||||
if local_package is None:
|
|
||||||
Error.warn(f"Installation of package {dependency} failed!")
|
|
||||||
return
|
|
||||||
|
|
||||||
if not self._is_virtual:
|
|
||||||
Pip.reset_executable()
|
|
||||||
|
|
||||||
def _install_package(self, package: str):
|
|
||||||
"""
|
|
||||||
Installs given package
|
|
||||||
:param package:
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
is_already_in_project = False
|
|
||||||
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.")
|
|
||||||
return
|
|
||||||
|
|
||||||
if self._project_settings.dependencies is None:
|
|
||||||
Error.error(f"Found invalid dependencies in {self._project_file}.")
|
|
||||||
return
|
|
||||||
|
|
||||||
package_version = ""
|
|
||||||
name = package
|
|
||||||
if "==" in package:
|
|
||||||
name = package.split("==")[0]
|
|
||||||
package_version = package.split("==")[1]
|
|
||||||
elif ">=" in package:
|
|
||||||
name = package.split(">=")[0]
|
|
||||||
package_version = package.split(">=")[1]
|
|
||||||
elif "<=" in package:
|
|
||||||
name = package.split("<=")[0]
|
|
||||||
package_version = package.split("<=")[1]
|
|
||||||
|
|
||||||
to_remove_list = []
|
|
||||||
deps = self._project_settings.dependencies
|
|
||||||
if self._is_dev:
|
|
||||||
deps = self._project_settings.dev_dependencies
|
|
||||||
|
|
||||||
for dependency in deps:
|
|
||||||
dependency_version = ""
|
|
||||||
|
|
||||||
if "==" in dependency:
|
|
||||||
dependency_version = dependency.split("==")[1]
|
|
||||||
elif "<=" in dependency:
|
|
||||||
dependency_version = dependency.split("<=")[1]
|
|
||||||
elif ">=" in dependency:
|
|
||||||
dependency_version = dependency.split(">=")[1]
|
|
||||||
|
|
||||||
if name in dependency:
|
|
||||||
if package_version != "" and version.parse(package_version) != version.parse(dependency_version):
|
|
||||||
to_remove_list.append(dependency)
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
is_already_in_project = True
|
|
||||||
|
|
||||||
for to_remove in to_remove_list:
|
|
||||||
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)
|
|
||||||
if local_package is not None and local_package in self._project_settings.dependencies:
|
|
||||||
Error.warn(f"Package {local_package} is already installed.")
|
|
||||||
return
|
|
||||||
|
|
||||||
elif is_already_in_project:
|
|
||||||
Error.warn(f"Package {package} is already installed.")
|
|
||||||
return
|
|
||||||
|
|
||||||
Console.spinner(
|
|
||||||
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,
|
|
||||||
source=self._cli_settings.pip_path,
|
|
||||||
stdout=subprocess.DEVNULL,
|
|
||||||
stderr=subprocess.DEVNULL,
|
|
||||||
text_foreground_color=ForegroundColorEnum.green,
|
|
||||||
spinner_foreground_color=ForegroundColorEnum.cyan,
|
|
||||||
)
|
|
||||||
|
|
||||||
if self._is_virtual:
|
|
||||||
new_package = name
|
|
||||||
else:
|
|
||||||
new_package = Pip.get_package(name)
|
|
||||||
|
|
||||||
if (
|
|
||||||
new_package is None
|
|
||||||
or "==" in package
|
|
||||||
and version.parse(package.split("==")[1]) != version.parse(new_package.split("==")[1])
|
|
||||||
or "<=" in package
|
|
||||||
and version.parse(package.split("<=")[1]) != version.parse(new_package.split("<=")[1])
|
|
||||||
or ">=" in package
|
|
||||||
and version.parse(package.split(">=")[1]) != version.parse(new_package.split(">=")[1])
|
|
||||||
):
|
|
||||||
Console.error(f"Installation of package {package} failed")
|
|
||||||
return
|
|
||||||
|
|
||||||
if not is_already_in_project:
|
|
||||||
new_name = package
|
|
||||||
if "==" in new_package or ">=" in new_package or "<=" in new_package:
|
|
||||||
new_name = new_package
|
|
||||||
elif "==" in name or ">=" in name or "<=" in name:
|
|
||||||
new_name = name
|
|
||||||
|
|
||||||
if "/" in new_name:
|
|
||||||
new_name = new_name.split("/")[0]
|
|
||||||
|
|
||||||
if "\r" in new_name:
|
|
||||||
new_name = new_name.replace("\r", "")
|
|
||||||
|
|
||||||
if self._is_dev:
|
|
||||||
self._project_settings.dev_dependencies.append(new_name)
|
|
||||||
else:
|
|
||||||
self._project_settings.dependencies.append(new_name)
|
|
||||||
|
|
||||||
if not self._is_simulation:
|
|
||||||
config = {
|
|
||||||
ProjectSettings.__name__: SettingsHelper.get_project_settings_dict(self._project_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:
|
|
||||||
project_file.write(json.dumps(config, indent=2))
|
|
||||||
project_file.close()
|
|
||||||
|
|
||||||
Pip.reset_executable()
|
|
||||||
|
|
||||||
def execute(self, args: list[str]):
|
|
||||||
"""
|
|
||||||
Entry point of command
|
|
||||||
:param args:
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
if "dev" in args:
|
|
||||||
self._is_dev = True
|
|
||||||
args.remove("dev")
|
|
||||||
|
|
||||||
if "virtual" in args:
|
|
||||||
self._is_virtual = True
|
|
||||||
args.remove("virtual")
|
|
||||||
Console.write_line("Running in virtual mode:")
|
|
||||||
|
|
||||||
if "simulate" in args:
|
|
||||||
self._is_simulation = True
|
|
||||||
args.remove("simulate")
|
|
||||||
Console.write_line("Running in simulation mode:")
|
|
||||||
|
|
||||||
if "cpl-prod" in args:
|
|
||||||
args.remove("cpl-prod")
|
|
||||||
self._cli_settings.from_dict({"PipPath": "https://pip.sh-edraft.de"})
|
|
||||||
|
|
||||||
if "cpl-exp" in args:
|
|
||||||
args.remove("cpl-exp")
|
|
||||||
self._cli_settings.from_dict({"PipPath": "https://pip-exp.sh-edraft.de"})
|
|
||||||
|
|
||||||
if "cpl-dev" in args:
|
|
||||||
args.remove("cpl-dev")
|
|
||||||
self._cli_settings.from_dict({"PipPath": "https://pip-dev.sh-edraft.de"})
|
|
||||||
|
|
||||||
VenvHelper.init_venv(self._is_virtual, self._env, self._project_settings.python_executable)
|
|
||||||
|
|
||||||
if len(args) == 0:
|
|
||||||
self._install_project()
|
|
||||||
else:
|
|
||||||
self._install_package(args[0])
|
|
||||||
|
|
||||||
if not self._is_virtual:
|
|
||||||
Pip.reset_executable()
|
|
||||||
@@ -1,362 +0,0 @@
|
|||||||
import importlib
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
import textwrap
|
|
||||||
import traceback
|
|
||||||
from typing import Optional
|
|
||||||
|
|
||||||
from packaging import version
|
|
||||||
|
|
||||||
import cpl_cli
|
|
||||||
import cpl_core
|
|
||||||
from cpl_cli.abc.project_type_abc import ProjectTypeABC
|
|
||||||
from cpl_cli.command_abc import CommandABC
|
|
||||||
from cpl_cli.configuration import VersionSettings
|
|
||||||
from cpl_cli.configuration.build_settings import BuildSettings
|
|
||||||
from cpl_cli.configuration.project_settings import ProjectSettings
|
|
||||||
from cpl_cli.configuration.project_type_enum import ProjectTypeEnum
|
|
||||||
from cpl_cli.configuration.settings_helper import SettingsHelper
|
|
||||||
from cpl_cli.configuration.venv_helper_service import VenvHelper
|
|
||||||
from cpl_cli.configuration.workspace_settings import WorkspaceSettings
|
|
||||||
from cpl_cli.helper.dependencies import Dependencies
|
|
||||||
from cpl_cli.source_creator.template_builder import TemplateBuilder
|
|
||||||
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 NewService(CommandABC):
|
|
||||||
def __init__(self, configuration: ConfigurationABC):
|
|
||||||
"""
|
|
||||||
Service for the CLI command new
|
|
||||||
:param configuration:
|
|
||||||
"""
|
|
||||||
CommandABC.__init__(self)
|
|
||||||
|
|
||||||
self._config = configuration
|
|
||||||
self._env = self._config.environment
|
|
||||||
|
|
||||||
self._workspace: WorkspaceSettings = self._config.get_configuration(WorkspaceSettings)
|
|
||||||
self._project_dict = {}
|
|
||||||
self._build_dict = {}
|
|
||||||
self._project_name = ""
|
|
||||||
self._python_executable = ""
|
|
||||||
|
|
||||||
self._project_type_classes = set()
|
|
||||||
|
|
||||||
self._name: str = ""
|
|
||||||
self._rel_path: str = ""
|
|
||||||
self._project_type: ProjectTypeEnum = ProjectTypeEnum.console
|
|
||||||
self._use_nothing: bool = False
|
|
||||||
self._use_application_api: bool = False
|
|
||||||
self._use_startup: bool = False
|
|
||||||
self._use_service_providing: bool = False
|
|
||||||
self._use_async: bool = False
|
|
||||||
self._use_venv: bool = False
|
|
||||||
self._use_base: bool = False
|
|
||||||
|
|
||||||
@property
|
|
||||||
def help_message(self) -> str:
|
|
||||||
return textwrap.dedent(
|
|
||||||
"""\
|
|
||||||
Generates a workspace and initial project or add a project to workspace.
|
|
||||||
Usage: cpl new <type> <name>
|
|
||||||
|
|
||||||
Arguments:
|
|
||||||
type The project type of the initial project
|
|
||||||
name Name of the workspace or the project
|
|
||||||
|
|
||||||
Types:
|
|
||||||
console (c|C)
|
|
||||||
library (l|L)
|
|
||||||
unittest (ut|UT)
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
|
|
||||||
def _create_project_settings(self):
|
|
||||||
self._project_name = os.path.basename(self._name)
|
|
||||||
self._python_executable = ProjectSettings(
|
|
||||||
python_path={sys.platform: "../../venv/" if self._use_venv else ""}
|
|
||||||
).python_executable
|
|
||||||
self._rel_path = os.path.dirname(self._name)
|
|
||||||
self._project_dict = SettingsHelper.get_project_settings_dict(
|
|
||||||
ProjectSettings(
|
|
||||||
os.path.basename(self._name),
|
|
||||||
VersionSettings("0", "0", "0"),
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
[f"cpl-core>={version.parse(cpl_core.__version__)}"],
|
|
||||||
[f"cpl-cli>={version.parse(cpl_cli.__version__)}"],
|
|
||||||
f'>={sys.version.split(" ")[0]}',
|
|
||||||
{sys.platform: "../../venv/" if self._use_venv else ""},
|
|
||||||
None,
|
|
||||||
[],
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
def _create_build_settings(self, project_type: str):
|
|
||||||
self._build_dict = SettingsHelper.get_build_settings_dict(
|
|
||||||
BuildSettings(
|
|
||||||
ProjectTypeEnum[project_type],
|
|
||||||
"",
|
|
||||||
"../../dist",
|
|
||||||
f"{String.convert_to_snake_case(self._project_name)}.main",
|
|
||||||
self._project_name,
|
|
||||||
False,
|
|
||||||
[],
|
|
||||||
["*/__pycache__", "*/logs", "*/tests"],
|
|
||||||
{},
|
|
||||||
[],
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
def _create_project_json(self):
|
|
||||||
"""
|
|
||||||
Creates cpl.json content
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
self._project_json = {ProjectSettings.__name__: self._project_dict, BuildSettings.__name__: self._build_dict}
|
|
||||||
|
|
||||||
def _get_project_path(self) -> Optional[str]:
|
|
||||||
"""
|
|
||||||
Gets project path
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
if self._workspace is None:
|
|
||||||
project_path = os.path.join(self._env.working_directory, self._rel_path, self._project_name)
|
|
||||||
else:
|
|
||||||
base = "" if self._use_base else "src"
|
|
||||||
project_path = os.path.join(
|
|
||||||
self._env.working_directory, base, self._rel_path, String.convert_to_snake_case(self._project_name)
|
|
||||||
)
|
|
||||||
|
|
||||||
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")
|
|
||||||
return None
|
|
||||||
|
|
||||||
return project_path
|
|
||||||
|
|
||||||
def _get_project_information(self, project_type: str):
|
|
||||||
"""
|
|
||||||
Gets project information's from user
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
is_unittest = project_type == "unittest"
|
|
||||||
is_library = project_type == "library"
|
|
||||||
if is_library:
|
|
||||||
return
|
|
||||||
|
|
||||||
if (
|
|
||||||
self._use_application_api
|
|
||||||
or self._use_startup
|
|
||||||
or self._use_service_providing
|
|
||||||
or self._use_async
|
|
||||||
or self._use_nothing
|
|
||||||
):
|
|
||||||
Console.set_foreground_color(ForegroundColorEnum.default)
|
|
||||||
Console.write_line("Skipping question due to given flags")
|
|
||||||
return
|
|
||||||
|
|
||||||
if not is_unittest and not is_library:
|
|
||||||
self._use_application_api = Console.read("Do you want to use application base? (y/n) ").lower() == "y"
|
|
||||||
|
|
||||||
if not is_unittest and self._use_application_api:
|
|
||||||
self._use_startup = Console.read("Do you want to use startup? (y/n) ").lower() == "y"
|
|
||||||
|
|
||||||
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"
|
|
||||||
|
|
||||||
if not self._use_async:
|
|
||||||
self._use_async = Console.read("Do you want to use async? (y/n) ").lower() == "y"
|
|
||||||
|
|
||||||
Console.set_foreground_color(ForegroundColorEnum.default)
|
|
||||||
|
|
||||||
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 = ""
|
|
||||||
|
|
||||||
if self._workspace is None and self._use_base:
|
|
||||||
project = f"{self._rel_path}/{project}"
|
|
||||||
|
|
||||||
VenvHelper.init_venv(
|
|
||||||
False,
|
|
||||||
self._env,
|
|
||||||
self._python_executable,
|
|
||||||
explicit_path=os.path.join(
|
|
||||||
self._env.working_directory, project, self._python_executable.replace("../", "")
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
def _read_custom_project_types_from_path(self, path: str):
|
|
||||||
if not os.path.exists(os.path.join(path, ".cpl")):
|
|
||||||
return
|
|
||||||
|
|
||||||
sys.path.insert(0, os.path.join(path, ".cpl"))
|
|
||||||
for r, d, f in os.walk(os.path.join(path, ".cpl")):
|
|
||||||
for file in f:
|
|
||||||
if file.startswith("project_file_") or not file.startswith("project_") or not file.endswith(".py"):
|
|
||||||
continue
|
|
||||||
|
|
||||||
try:
|
|
||||||
exec(open(os.path.join(r, file), "r").read())
|
|
||||||
self._project_type_classes.update(ProjectTypeABC.__subclasses__())
|
|
||||||
except Exception as e:
|
|
||||||
Console.error(str(e), traceback.format_exc())
|
|
||||||
sys.exit(-1)
|
|
||||||
|
|
||||||
def _create_project(self, project_type: str):
|
|
||||||
for package_name in Dependencies.get_cpl_packages():
|
|
||||||
if package_name == "cpl-cli":
|
|
||||||
continue
|
|
||||||
package = importlib.import_module(String.convert_to_snake_case(package_name[0]))
|
|
||||||
self._read_custom_project_types_from_path(os.path.dirname(package.__file__))
|
|
||||||
|
|
||||||
self._read_custom_project_types_from_path(self._env.working_directory)
|
|
||||||
self._read_custom_project_types_from_path(self._env.runtime_directory)
|
|
||||||
|
|
||||||
if len(self._project_type_classes) == 0:
|
|
||||||
Console.error(f"No project types found in template directory: .cpl")
|
|
||||||
sys.exit()
|
|
||||||
|
|
||||||
project_class = None
|
|
||||||
known_project_types = []
|
|
||||||
for p in self._project_type_classes:
|
|
||||||
known_project_types.append(p.__name__)
|
|
||||||
if p.__name__.lower() != project_type and p.__name__.lower()[0] != project_type[0]:
|
|
||||||
continue
|
|
||||||
|
|
||||||
project_class = p
|
|
||||||
|
|
||||||
if project_class is None:
|
|
||||||
Console.error(f"Project type {project_type} not found in template directory: .cpl/")
|
|
||||||
sys.exit()
|
|
||||||
|
|
||||||
project_type = String.convert_to_snake_case(project_class.__name__)
|
|
||||||
self._create_project_settings()
|
|
||||||
self._create_build_settings(project_type)
|
|
||||||
self._create_project_json()
|
|
||||||
path = self._get_project_path()
|
|
||||||
if path is None:
|
|
||||||
return
|
|
||||||
|
|
||||||
self._get_project_information(project_type)
|
|
||||||
project_name = self._project_name
|
|
||||||
if self._rel_path != "":
|
|
||||||
project_name = f"{self._rel_path}/{project_name}"
|
|
||||||
|
|
||||||
base = "src/"
|
|
||||||
split_project_name = project_name.split("/")
|
|
||||||
if self._use_base and len(split_project_name) > 0:
|
|
||||||
base = f"{split_project_name[0]}/"
|
|
||||||
|
|
||||||
project = project_class(
|
|
||||||
base if self._workspace is not None else "src/",
|
|
||||||
project_name,
|
|
||||||
self._workspace,
|
|
||||||
self._use_application_api,
|
|
||||||
self._use_startup,
|
|
||||||
self._use_service_providing,
|
|
||||||
self._use_async,
|
|
||||||
self._project_json,
|
|
||||||
)
|
|
||||||
|
|
||||||
if self._workspace is None:
|
|
||||||
TemplateBuilder.create_workspace(
|
|
||||||
f"{project_name}/cpl-workspace.json",
|
|
||||||
project_name.split("/")[-1],
|
|
||||||
{
|
|
||||||
project_name: f'{base if self._workspace is not None else "src/"}{String.convert_to_snake_case(project_name)}/{project_name}.json'
|
|
||||||
},
|
|
||||||
{},
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
self._workspace.projects[
|
|
||||||
project_name
|
|
||||||
] = f'{base if self._workspace is not None else "src/"}{String.convert_to_snake_case(project_name)}/{project_name}.json'
|
|
||||||
TemplateBuilder.create_workspace(
|
|
||||||
"cpl-workspace.json", self._workspace.default_project, self._workspace.projects, self._workspace.scripts
|
|
||||||
)
|
|
||||||
|
|
||||||
for template in project.templates:
|
|
||||||
rel_base = "/".join(project_name.split("/")[:-1])
|
|
||||||
template_path_base = template.path.split("/")[0]
|
|
||||||
if not self._use_base and rel_base != "" and template_path_base != "" and template_path_base != rel_base:
|
|
||||||
template.path = template.path.replace(f"{template_path_base}/", f"{template_path_base}/{rel_base}/")
|
|
||||||
|
|
||||||
if template.name.endswith(f'{project_name.split("/")[-1]}.json'):
|
|
||||||
pass
|
|
||||||
|
|
||||||
file_path = os.path.join(project_name if self._workspace is None else "", template.path, template.name)
|
|
||||||
|
|
||||||
Console.spinner(
|
|
||||||
f"Creating {file_path}",
|
|
||||||
TemplateBuilder.build,
|
|
||||||
file_path,
|
|
||||||
template,
|
|
||||||
text_foreground_color=ForegroundColorEnum.green,
|
|
||||||
spinner_foreground_color=ForegroundColorEnum.cyan,
|
|
||||||
)
|
|
||||||
|
|
||||||
if self._use_venv:
|
|
||||||
self._create_venv()
|
|
||||||
|
|
||||||
def execute(self, args: list[str]):
|
|
||||||
"""
|
|
||||||
Entry point of command
|
|
||||||
:param args:
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
if "nothing" in args:
|
|
||||||
self._use_nothing = True
|
|
||||||
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")
|
|
||||||
|
|
||||||
if "async" in args:
|
|
||||||
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")
|
|
||||||
if "base" in args:
|
|
||||||
self._use_base = True
|
|
||||||
args.remove("base")
|
|
||||||
|
|
||||||
if len(args) <= 1:
|
|
||||||
Console.error(f"Project type not found")
|
|
||||||
Console.write_line(self.help_message)
|
|
||||||
return
|
|
||||||
|
|
||||||
self._name = args[1]
|
|
||||||
self._create_project(args[0])
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
import textwrap
|
|
||||||
|
|
||||||
from cpl_cli.command_abc import CommandABC
|
|
||||||
from cpl_cli.publish.publisher_abc import PublisherABC
|
|
||||||
|
|
||||||
|
|
||||||
class PublishService(CommandABC):
|
|
||||||
def __init__(self, publisher: PublisherABC):
|
|
||||||
"""
|
|
||||||
Service for the CLI command publish
|
|
||||||
:param publisher:
|
|
||||||
"""
|
|
||||||
CommandABC.__init__(self)
|
|
||||||
|
|
||||||
self._publisher = publisher
|
|
||||||
|
|
||||||
@property
|
|
||||||
def help_message(self) -> str:
|
|
||||||
return textwrap.dedent(
|
|
||||||
"""\
|
|
||||||
Prepares files for publish into an output directory named dist/ at the given output path and executes setup.py.
|
|
||||||
Usage: cpl publish
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
|
|
||||||
def execute(self, args: list[str]):
|
|
||||||
"""
|
|
||||||
Entry point of command
|
|
||||||
:param args:
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
self._publisher.publish()
|
|
||||||
@@ -1,172 +0,0 @@
|
|||||||
import os
|
|
||||||
import shutil
|
|
||||||
import json
|
|
||||||
import textwrap
|
|
||||||
|
|
||||||
from cpl_cli.configuration.settings_helper import SettingsHelper
|
|
||||||
|
|
||||||
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.environment.application_environment_abc import ApplicationEnvironmentABC
|
|
||||||
from cpl_cli.command_abc import CommandABC
|
|
||||||
from cpl_cli.configuration import (
|
|
||||||
WorkspaceSettings,
|
|
||||||
WorkspaceSettingsNameEnum,
|
|
||||||
BuildSettingsNameEnum,
|
|
||||||
ProjectSettings,
|
|
||||||
BuildSettings,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class RemoveService(CommandABC):
|
|
||||||
def __init__(self, config: ConfigurationABC, env: ApplicationEnvironmentABC):
|
|
||||||
"""
|
|
||||||
Service for CLI command remove
|
|
||||||
:param config:
|
|
||||||
:param env:
|
|
||||||
"""
|
|
||||||
CommandABC.__init__(self)
|
|
||||||
|
|
||||||
self._config = config
|
|
||||||
self._env = env
|
|
||||||
|
|
||||||
self._workspace: WorkspaceSettings = self._config.get_configuration(WorkspaceSettings)
|
|
||||||
self._is_simulation = False
|
|
||||||
|
|
||||||
@property
|
|
||||||
def help_message(self) -> str:
|
|
||||||
return textwrap.dedent(
|
|
||||||
"""\
|
|
||||||
Removes a project from workspace.
|
|
||||||
Usage: cpl remove <project>
|
|
||||||
|
|
||||||
Arguments:
|
|
||||||
project The name of the project to delete
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
|
|
||||||
def _create_file(self, file_name: str, content: dict):
|
|
||||||
if self._is_simulation:
|
|
||||||
return
|
|
||||||
|
|
||||||
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()
|
|
||||||
|
|
||||||
def _remove_sources(self, path: str):
|
|
||||||
if self._is_simulation:
|
|
||||||
return
|
|
||||||
shutil.rmtree(path)
|
|
||||||
|
|
||||||
def _create_workspace(self, path: str):
|
|
||||||
ws_dict = {
|
|
||||||
WorkspaceSettings.__name__: {
|
|
||||||
WorkspaceSettingsNameEnum.default_project.value: self._workspace.default_project,
|
|
||||||
WorkspaceSettingsNameEnum.projects.value: self._workspace.projects,
|
|
||||||
WorkspaceSettingsNameEnum.scripts.value: self._workspace.scripts,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self._create_file(path, ws_dict)
|
|
||||||
|
|
||||||
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
|
|
||||||
:param args:
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
if "simulate" in args:
|
|
||||||
args.remove("simulate")
|
|
||||||
Console.write_line("Running in simulation mode:")
|
|
||||||
self._is_simulation = True
|
|
||||||
|
|
||||||
project_name = args[0]
|
|
||||||
if project_name not in self._workspace.projects:
|
|
||||||
Console.error(f"Project {project_name} not found in workspace.")
|
|
||||||
return
|
|
||||||
|
|
||||||
if project_name == self._workspace.default_project:
|
|
||||||
Console.error(f"Project {project_name} is the default project.")
|
|
||||||
return
|
|
||||||
|
|
||||||
src_path = os.path.dirname(self._workspace.projects[project_name])
|
|
||||||
Console.spinner(
|
|
||||||
f"Removing {src_path}",
|
|
||||||
self._remove_sources,
|
|
||||||
os.path.abspath(src_path),
|
|
||||||
text_foreground_color=ForegroundColorEnum.green,
|
|
||||||
spinner_foreground_color=ForegroundColorEnum.cyan,
|
|
||||||
)
|
|
||||||
|
|
||||||
self._find_deps_in_projects(project_name, src_path)
|
|
||||||
|
|
||||||
del self._workspace.projects[project_name]
|
|
||||||
path = "cpl-workspace.json"
|
|
||||||
Console.spinner(
|
|
||||||
f"Changing {path}",
|
|
||||||
self._create_workspace,
|
|
||||||
path,
|
|
||||||
text_foreground_color=ForegroundColorEnum.green,
|
|
||||||
spinner_foreground_color=ForegroundColorEnum.cyan,
|
|
||||||
)
|
|
||||||
@@ -1,125 +0,0 @@
|
|||||||
import os
|
|
||||||
import sys
|
|
||||||
import textwrap
|
|
||||||
|
|
||||||
from cpl_cli.error import Error
|
|
||||||
from cpl_cli.command_abc import CommandABC
|
|
||||||
from cpl_cli.configuration.workspace_settings 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_cli.publish.publisher_service import PublisherService
|
|
||||||
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.environment.application_environment_abc import ApplicationEnvironmentABC
|
|
||||||
from cpl_core.utils.string import String
|
|
||||||
|
|
||||||
|
|
||||||
class RunService(CommandABC):
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
config: ConfigurationABC,
|
|
||||||
env: ApplicationEnvironmentABC,
|
|
||||||
services: ServiceProviderABC,
|
|
||||||
project_settings: ProjectSettings,
|
|
||||||
build_settings: BuildSettings,
|
|
||||||
workspace: WorkspaceSettings,
|
|
||||||
publisher: PublisherService,
|
|
||||||
):
|
|
||||||
"""
|
|
||||||
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._publisher = publisher
|
|
||||||
|
|
||||||
self._src_dir = os.path.join(self._env.working_directory, self._build_settings.source_path)
|
|
||||||
self._is_dev = False
|
|
||||||
|
|
||||||
@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 _build(self):
|
|
||||||
if self._is_dev:
|
|
||||||
return
|
|
||||||
|
|
||||||
self._env.set_working_directory(self._src_dir)
|
|
||||||
self._publisher.build()
|
|
||||||
self._env.set_working_directory(self._src_dir)
|
|
||||||
self._src_dir = os.path.abspath(
|
|
||||||
os.path.join(
|
|
||||||
self._src_dir,
|
|
||||||
self._build_settings.output_path,
|
|
||||||
self._project_settings.name,
|
|
||||||
"build",
|
|
||||||
String.convert_to_snake_case(self._project_settings.name),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
def execute(self, args: list[str]):
|
|
||||||
"""
|
|
||||||
Entry point of command
|
|
||||||
:param args:
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
if "dev" in args:
|
|
||||||
self._is_dev = True
|
|
||||||
args.remove("dev")
|
|
||||||
|
|
||||||
if len(args) >= 1:
|
|
||||||
self._set_project_by_args(args[0])
|
|
||||||
args.remove(args[0])
|
|
||||||
|
|
||||||
self._build()
|
|
||||||
|
|
||||||
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()
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
import textwrap
|
|
||||||
|
|
||||||
from cpl_cli.command_abc import CommandABC
|
|
||||||
from cpl_cli.live_server.live_server_service import LiveServerService
|
|
||||||
|
|
||||||
|
|
||||||
class StartService(CommandABC):
|
|
||||||
def __init__(self, live_server: LiveServerService):
|
|
||||||
"""
|
|
||||||
Service for the CLI command start
|
|
||||||
:param live_server:
|
|
||||||
"""
|
|
||||||
CommandABC.__init__(self)
|
|
||||||
|
|
||||||
self._live_server = live_server
|
|
||||||
|
|
||||||
@property
|
|
||||||
def help_message(self) -> str:
|
|
||||||
return textwrap.dedent(
|
|
||||||
"""\
|
|
||||||
Starts your application, restarting on file changes.
|
|
||||||
Usage: cpl start
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
|
|
||||||
def execute(self, args: list[str]):
|
|
||||||
"""
|
|
||||||
Entry point of command
|
|
||||||
:param args:
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
self._live_server.start(args)
|
|
||||||
@@ -1,140 +0,0 @@
|
|||||||
import json
|
|
||||||
import os
|
|
||||||
import subprocess
|
|
||||||
import textwrap
|
|
||||||
import time
|
|
||||||
|
|
||||||
from cpl_cli.configuration.venv_helper_service import VenvHelper
|
|
||||||
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.environment.application_environment_abc import ApplicationEnvironmentABC
|
|
||||||
from cpl_core.utils.pip import Pip
|
|
||||||
from cpl_cli.command_abc import CommandABC
|
|
||||||
from cpl_cli.configuration.build_settings import BuildSettings
|
|
||||||
from cpl_cli.configuration.project_settings import ProjectSettings
|
|
||||||
from cpl_cli.configuration.settings_helper import SettingsHelper
|
|
||||||
|
|
||||||
|
|
||||||
class UninstallService(CommandABC):
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
config: ConfigurationABC,
|
|
||||||
env: ApplicationEnvironmentABC,
|
|
||||||
build_settings: BuildSettings,
|
|
||||||
project_settings: ProjectSettings,
|
|
||||||
):
|
|
||||||
"""
|
|
||||||
Service for the CLI command uninstall
|
|
||||||
:param config:
|
|
||||||
:param env:
|
|
||||||
:param build_settings:
|
|
||||||
:param project_settings:
|
|
||||||
"""
|
|
||||||
CommandABC.__init__(self)
|
|
||||||
|
|
||||||
self._config = config
|
|
||||||
self._env = env
|
|
||||||
self._build_settings = build_settings
|
|
||||||
self._project_settings = project_settings
|
|
||||||
|
|
||||||
self._is_simulating = False
|
|
||||||
self._is_virtual = False
|
|
||||||
self._is_dev = False
|
|
||||||
|
|
||||||
self._project_file = f"{self._project_settings.name}.json"
|
|
||||||
|
|
||||||
@property
|
|
||||||
def help_message(self) -> str:
|
|
||||||
return textwrap.dedent(
|
|
||||||
"""\
|
|
||||||
Uninstalls given package via pip
|
|
||||||
Usage: cpl uninstall <package>
|
|
||||||
|
|
||||||
Arguments:
|
|
||||||
package The package to uninstall
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
|
|
||||||
def _wait(self, t: int, *args, source: str = None, stdout=None, stderr=None):
|
|
||||||
time.sleep(t)
|
|
||||||
|
|
||||||
def execute(self, args: list[str]):
|
|
||||||
"""
|
|
||||||
Entry point of command
|
|
||||||
:param args:
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
if len(args) == 0:
|
|
||||||
Console.error(f"Expected package")
|
|
||||||
Console.error(f"Usage: cpl uninstall <package>")
|
|
||||||
return
|
|
||||||
|
|
||||||
if "dev" in args:
|
|
||||||
self._is_dev = True
|
|
||||||
args.remove("dev")
|
|
||||||
|
|
||||||
if "--virtual" in args:
|
|
||||||
self._is_virtual = True
|
|
||||||
args.remove("--virtual")
|
|
||||||
Console.write_line("Running in virtual mode:")
|
|
||||||
|
|
||||||
if "--simulate" in args:
|
|
||||||
self._is_virtual = True
|
|
||||||
args.remove("--simulate")
|
|
||||||
Console.write_line("Running in simulation mode:")
|
|
||||||
|
|
||||||
VenvHelper.init_venv(self._is_virtual, self._env, self._project_settings.python_executable)
|
|
||||||
|
|
||||||
package = args[0]
|
|
||||||
is_in_dependencies = False
|
|
||||||
|
|
||||||
if not self._is_virtual:
|
|
||||||
pip_package = Pip.get_package(package)
|
|
||||||
else:
|
|
||||||
pip_package = package
|
|
||||||
|
|
||||||
deps = self._project_settings.dependencies
|
|
||||||
if self._is_dev:
|
|
||||||
deps = self._project_settings.dev_dependencies
|
|
||||||
|
|
||||||
for dependency in deps:
|
|
||||||
if package in dependency:
|
|
||||||
is_in_dependencies = True
|
|
||||||
package = dependency
|
|
||||||
|
|
||||||
if not is_in_dependencies and pip_package is None:
|
|
||||||
Console.error(f"Package {package} not found")
|
|
||||||
return
|
|
||||||
|
|
||||||
elif not is_in_dependencies and pip_package is not None:
|
|
||||||
package = pip_package
|
|
||||||
|
|
||||||
Console.spinner(
|
|
||||||
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,
|
|
||||||
stdout=subprocess.DEVNULL,
|
|
||||||
stderr=subprocess.DEVNULL,
|
|
||||||
text_foreground_color=ForegroundColorEnum.green,
|
|
||||||
spinner_foreground_color=ForegroundColorEnum.cyan,
|
|
||||||
)
|
|
||||||
|
|
||||||
deps = self._project_settings.dependencies
|
|
||||||
if self._is_dev:
|
|
||||||
deps = self._project_settings.dev_dependencies
|
|
||||||
|
|
||||||
if package in deps:
|
|
||||||
deps.remove(package)
|
|
||||||
if not self._is_simulating:
|
|
||||||
config = {
|
|
||||||
ProjectSettings.__name__: SettingsHelper.get_project_settings_dict(self._project_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:
|
|
||||||
project_file.write(json.dumps(config, indent=2))
|
|
||||||
project_file.close()
|
|
||||||
|
|
||||||
Console.write_line(f"Removed {package}")
|
|
||||||
if not self._is_virtual:
|
|
||||||
Pip.reset_executable()
|
|
||||||
@@ -1,228 +0,0 @@
|
|||||||
import json
|
|
||||||
import os
|
|
||||||
import subprocess
|
|
||||||
import textwrap
|
|
||||||
|
|
||||||
from cpl_cli.configuration.venv_helper_service import VenvHelper
|
|
||||||
from cpl_cli.migrations.base.migration_service_abc import MigrationServiceABC
|
|
||||||
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.environment.application_environment_abc import ApplicationEnvironmentABC
|
|
||||||
from cpl_core.utils.pip import Pip
|
|
||||||
from cpl_cli.cli_settings import CLISettings
|
|
||||||
from cpl_cli.command_abc import CommandABC
|
|
||||||
from cpl_cli.configuration import BuildSettings
|
|
||||||
from cpl_cli.configuration.project_settings import ProjectSettings
|
|
||||||
from cpl_cli.configuration.settings_helper import SettingsHelper
|
|
||||||
|
|
||||||
|
|
||||||
class UpdateService(CommandABC):
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
config: ConfigurationABC,
|
|
||||||
env: ApplicationEnvironmentABC,
|
|
||||||
build_settings: BuildSettings,
|
|
||||||
project_settings: ProjectSettings,
|
|
||||||
cli_settings: CLISettings,
|
|
||||||
migrations: MigrationServiceABC,
|
|
||||||
):
|
|
||||||
"""
|
|
||||||
Service for the CLI command update
|
|
||||||
:param config:
|
|
||||||
:param env:
|
|
||||||
:param build_settings:
|
|
||||||
:param project_settings:
|
|
||||||
:param cli_settings:
|
|
||||||
"""
|
|
||||||
CommandABC.__init__(self)
|
|
||||||
|
|
||||||
self._config = config
|
|
||||||
self._env = env
|
|
||||||
self._build_settings = build_settings
|
|
||||||
self._project_settings = project_settings
|
|
||||||
self._cli_settings = cli_settings
|
|
||||||
self._migrations = migrations
|
|
||||||
self._is_simulation = False
|
|
||||||
|
|
||||||
self._project_file = f"{self._project_settings.name}.json"
|
|
||||||
|
|
||||||
@property
|
|
||||||
def help_message(self) -> str:
|
|
||||||
return textwrap.dedent(
|
|
||||||
"""\
|
|
||||||
Updates the CPL and project dependencies.
|
|
||||||
Usage: cpl update
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
|
|
||||||
def _collect_project_dependencies(self) -> list[tuple]:
|
|
||||||
"""
|
|
||||||
Collects project dependencies
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
dependencies = []
|
|
||||||
for package in [*self._project_settings.dependencies, *self._project_settings.dev_dependencies]:
|
|
||||||
name = package
|
|
||||||
if "==" in package:
|
|
||||||
name = package.split("==")[0]
|
|
||||||
elif ">=" in package:
|
|
||||||
name = package.split(">=")[0]
|
|
||||||
elif "<=" in package:
|
|
||||||
name = package.split("<=")[0]
|
|
||||||
|
|
||||||
dependencies.append((package, name))
|
|
||||||
|
|
||||||
return dependencies
|
|
||||||
|
|
||||||
def _update_project_dependencies(self, dependencies):
|
|
||||||
"""
|
|
||||||
Updates project dependencies
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
for package, name in dependencies:
|
|
||||||
Pip.install(
|
|
||||||
name,
|
|
||||||
"--upgrade",
|
|
||||||
"--upgrade-strategy",
|
|
||||||
"eager",
|
|
||||||
source=self._cli_settings.pip_path,
|
|
||||||
stdout=subprocess.DEVNULL,
|
|
||||||
stderr=subprocess.DEVNULL,
|
|
||||||
)
|
|
||||||
|
|
||||||
new_package = Pip.get_package(name)
|
|
||||||
if new_package is None:
|
|
||||||
Console.error(f"Update for package {package} failed")
|
|
||||||
continue
|
|
||||||
|
|
||||||
self._project_json_update_dependency(package, new_package)
|
|
||||||
|
|
||||||
def _check_project_dependencies(self):
|
|
||||||
"""
|
|
||||||
Checks project dependencies for updates
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
dependencies = Console.spinner(
|
|
||||||
"Collecting installed dependencies",
|
|
||||||
self._collect_project_dependencies,
|
|
||||||
text_foreground_color=ForegroundColorEnum.green,
|
|
||||||
spinner_foreground_color=ForegroundColorEnum.cyan,
|
|
||||||
)
|
|
||||||
|
|
||||||
Console.spinner(
|
|
||||||
"Updating installed dependencies",
|
|
||||||
self._update_project_dependencies,
|
|
||||||
dependencies,
|
|
||||||
text_foreground_color=ForegroundColorEnum.green,
|
|
||||||
spinner_foreground_color=ForegroundColorEnum.cyan,
|
|
||||||
)
|
|
||||||
|
|
||||||
if "cpl-cli" in [y for x, y in dependencies]:
|
|
||||||
import cpl_cli
|
|
||||||
|
|
||||||
Console.spinner(
|
|
||||||
"Running migrations",
|
|
||||||
self._migrations.migrate_from,
|
|
||||||
cpl_cli.__version__,
|
|
||||||
text_foreground_color=ForegroundColorEnum.green,
|
|
||||||
spinner_foreground_color=ForegroundColorEnum.cyan,
|
|
||||||
)
|
|
||||||
|
|
||||||
Console.write_line(f"Found {len(self._project_settings.dependencies)} dependencies.")
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _check_outdated():
|
|
||||||
"""
|
|
||||||
Checks for outdated packages in project
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
table_str: bytes = Console.spinner(
|
|
||||||
"Analyzing for available package updates",
|
|
||||||
Pip.get_outdated,
|
|
||||||
text_foreground_color=ForegroundColorEnum.green,
|
|
||||||
spinner_foreground_color=ForegroundColorEnum.cyan,
|
|
||||||
)
|
|
||||||
|
|
||||||
table = str(table_str, "utf-8").split("\n")
|
|
||||||
if len(table) > 1 and table[0] != "":
|
|
||||||
Console.write_line("\tAvailable updates for packages:")
|
|
||||||
for row in table:
|
|
||||||
Console.write_line(f"\t{row}")
|
|
||||||
|
|
||||||
Console.set_foreground_color(ForegroundColorEnum.yellow)
|
|
||||||
Console.write_line(f"\tUpdate with {Pip.get_executable()} -m pip install --upgrade <package>")
|
|
||||||
Console.set_foreground_color(ForegroundColorEnum.default)
|
|
||||||
|
|
||||||
def _save_formatted_package_name_to_deps_collection(self, deps: [str], old_package: str, new_package: str):
|
|
||||||
if old_package not in deps:
|
|
||||||
return
|
|
||||||
|
|
||||||
initial_package = new_package
|
|
||||||
|
|
||||||
if "/" in new_package:
|
|
||||||
new_package = new_package.split("/")[0]
|
|
||||||
|
|
||||||
if "\r" in new_package:
|
|
||||||
new_package = new_package.replace("\r", "")
|
|
||||||
|
|
||||||
if new_package == old_package:
|
|
||||||
return
|
|
||||||
|
|
||||||
index = deps.index(old_package)
|
|
||||||
deps[index] = new_package
|
|
||||||
|
|
||||||
def _project_json_update_dependency(self, old_package: str, new_package: str):
|
|
||||||
"""
|
|
||||||
Writes new package version to project.json
|
|
||||||
:param old_package:
|
|
||||||
:param new_package:
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
if self._is_simulation:
|
|
||||||
return
|
|
||||||
|
|
||||||
self._save_formatted_package_name_to_deps_collection(
|
|
||||||
self._project_settings.dependencies, old_package, new_package
|
|
||||||
)
|
|
||||||
self._save_formatted_package_name_to_deps_collection(
|
|
||||||
self._project_settings.dev_dependencies, old_package, new_package
|
|
||||||
)
|
|
||||||
|
|
||||||
config = {
|
|
||||||
ProjectSettings.__name__: SettingsHelper.get_project_settings_dict(self._project_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:
|
|
||||||
project.write(json.dumps(config, indent=2))
|
|
||||||
project.close()
|
|
||||||
|
|
||||||
def execute(self, args: list[str]):
|
|
||||||
"""
|
|
||||||
Entry point of command
|
|
||||||
:param args:
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
if "simulate" in args:
|
|
||||||
args.remove("simulate")
|
|
||||||
Console.write_line("Running in simulation mode:")
|
|
||||||
self._is_simulation = True
|
|
||||||
|
|
||||||
if "cpl-prod" in args:
|
|
||||||
args.remove("cpl-prod")
|
|
||||||
self._cli_settings.from_dict({"PipPath": "https://pip.sh-edraft.de"})
|
|
||||||
|
|
||||||
if "cpl-exp" in args:
|
|
||||||
args.remove("cpl-exp")
|
|
||||||
self._cli_settings.from_dict({"PipPath": "https://pip-exp.sh-edraft.de"})
|
|
||||||
|
|
||||||
if "cpl-dev" in args:
|
|
||||||
args.remove("cpl-dev")
|
|
||||||
self._cli_settings.from_dict({"PipPath": "https://pip-dev.sh-edraft.de"})
|
|
||||||
|
|
||||||
VenvHelper.init_venv(False, self._env, self._project_settings.python_executable)
|
|
||||||
|
|
||||||
self._check_project_dependencies()
|
|
||||||
self._check_outdated()
|
|
||||||
Pip.reset_executable()
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
import pkgutil
|
|
||||||
import sys
|
|
||||||
import platform
|
|
||||||
import pkg_resources
|
|
||||||
import textwrap
|
|
||||||
|
|
||||||
import cpl_cli
|
|
||||||
from cpl_cli.helper.dependencies import Dependencies
|
|
||||||
from cpl_core.console.console import Console
|
|
||||||
from cpl_core.console.foreground_color_enum import ForegroundColorEnum
|
|
||||||
from cpl_cli.command_abc import CommandABC
|
|
||||||
|
|
||||||
|
|
||||||
class VersionService(CommandABC):
|
|
||||||
def __init__(self):
|
|
||||||
"""
|
|
||||||
Service for the CLI command version
|
|
||||||
"""
|
|
||||||
CommandABC.__init__(self)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def help_message(self) -> str:
|
|
||||||
return textwrap.dedent(
|
|
||||||
"""\
|
|
||||||
Lists the version of CPL, CPL CLI and all installed packages from pip.
|
|
||||||
Usage: cpl version
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
|
|
||||||
def execute(self, args: list[str]):
|
|
||||||
"""
|
|
||||||
Entry point of command
|
|
||||||
:param args:
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
Console.set_foreground_color(ForegroundColorEnum.yellow)
|
|
||||||
Console.banner("CPL CLI")
|
|
||||||
Console.set_foreground_color(ForegroundColorEnum.default)
|
|
||||||
if "__version__" in dir(cpl_cli):
|
|
||||||
Console.write_line(f"Common Python library CLI: ")
|
|
||||||
Console.write(cpl_cli.__version__)
|
|
||||||
|
|
||||||
Console.write_line(f"Python: ")
|
|
||||||
Console.write(f"{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}")
|
|
||||||
Console.write_line(f"OS: {platform.system()} {platform.processor()}")
|
|
||||||
Console.write_line("\nCPL packages:")
|
|
||||||
Console.table(["Name", "Version"], Dependencies.get_cpl_packages())
|
|
||||||
Console.write_line("\nPython packages:")
|
|
||||||
Console.table(["Name", "Version"], Dependencies.get_packages())
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
from abc import abstractmethod, ABC
|
|
||||||
|
|
||||||
from cpl_core.configuration.argument_executable_abc import ArgumentExecutableABC
|
|
||||||
from cpl_core.console import Console
|
|
||||||
|
|
||||||
|
|
||||||
class CommandABC(ArgumentExecutableABC):
|
|
||||||
@abstractmethod
|
|
||||||
def __init__(self):
|
|
||||||
ABC.__init__(self)
|
|
||||||
|
|
||||||
@property
|
|
||||||
@abstractmethod
|
|
||||||
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)
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
"""
|
|
||||||
cpl-cli CPL CLI
|
|
||||||
~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
CPL Command Line Interface
|
|
||||||
|
|
||||||
:copyright: (c) 2020 - 2024 sh-edraft.de
|
|
||||||
:license: MIT, see LICENSE for more details.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
__title__ = "cpl_cli.configuration"
|
|
||||||
__author__ = "Sven Heidemann"
|
|
||||||
__license__ = "MIT"
|
|
||||||
__copyright__ = "Copyright (c) 2020 - 2024 sh-edraft.de"
|
|
||||||
__version__ = "2024.10.0"
|
|
||||||
|
|
||||||
from collections import namedtuple
|
|
||||||
|
|
||||||
|
|
||||||
# imports:
|
|
||||||
from .build_settings import BuildSettings
|
|
||||||
from .build_settings_name_enum import BuildSettingsNameEnum
|
|
||||||
from .project_settings import ProjectSettings
|
|
||||||
from .project_settings_name_enum import ProjectSettingsNameEnum
|
|
||||||
from .version_settings import VersionSettings
|
|
||||||
from .version_settings_name_enum import VersionSettingsNameEnum
|
|
||||||
from .workspace_settings import WorkspaceSettings
|
|
||||||
from .workspace_settings_name_enum import WorkspaceSettingsNameEnum
|
|
||||||
|
|
||||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
|
||||||
version_info = VersionInfo(major="2024", minor="10", micro="0")
|
|
||||||
@@ -1,95 +0,0 @@
|
|||||||
import sys
|
|
||||||
import traceback
|
|
||||||
from typing import Optional
|
|
||||||
|
|
||||||
from cpl_cli.configuration.build_settings_name_enum import BuildSettingsNameEnum
|
|
||||||
from cpl_cli.configuration.project_type_enum import ProjectTypeEnum
|
|
||||||
from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC
|
|
||||||
from cpl_core.console.console import Console
|
|
||||||
from cpl_core.console.foreground_color_enum import ForegroundColorEnum
|
|
||||||
|
|
||||||
|
|
||||||
class BuildSettings(ConfigurationModelABC):
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
project_type: ProjectTypeEnum = None,
|
|
||||||
source_path: str = None,
|
|
||||||
output_path: str = None,
|
|
||||||
main: str = None,
|
|
||||||
entry_point: str = None,
|
|
||||||
include_package_data: bool = None,
|
|
||||||
included: list = None,
|
|
||||||
excluded: list = None,
|
|
||||||
package_data: dict = None,
|
|
||||||
project_references: list = None,
|
|
||||||
):
|
|
||||||
ConfigurationModelABC.__init__(self)
|
|
||||||
|
|
||||||
self._project_type: Optional[ProjectTypeEnum] = project_type
|
|
||||||
self._source_path: Optional[str] = source_path
|
|
||||||
self._output_path: Optional[str] = output_path
|
|
||||||
self._main: Optional[str] = main
|
|
||||||
self._entry_point: Optional[str] = entry_point
|
|
||||||
self._include_package_data: Optional[bool] = include_package_data
|
|
||||||
self._included: Optional[list[str]] = included
|
|
||||||
self._excluded: Optional[list[str]] = excluded
|
|
||||||
self._package_data: Optional[dict[str, list[str]]] = package_data
|
|
||||||
self._project_references: Optional[list[str]] = [] if project_references is None else project_references
|
|
||||||
|
|
||||||
if sys.platform == "win32":
|
|
||||||
self._source_path = str(self._source_path).replace("/", "\\")
|
|
||||||
self._output_path = str(self._output_path).replace("/", "\\")
|
|
||||||
|
|
||||||
# windows paths for excluded files
|
|
||||||
excluded = []
|
|
||||||
for ex in self._excluded:
|
|
||||||
excluded.append(str(ex).replace("/", "\\"))
|
|
||||||
|
|
||||||
self._excluded = excluded
|
|
||||||
|
|
||||||
# windows paths for included files
|
|
||||||
included = []
|
|
||||||
for inc in self._included:
|
|
||||||
included.append(str(inc).replace("/", "\\"))
|
|
||||||
|
|
||||||
self._included = included
|
|
||||||
|
|
||||||
@property
|
|
||||||
def project_type(self):
|
|
||||||
return self._project_type
|
|
||||||
|
|
||||||
@property
|
|
||||||
def source_path(self) -> str:
|
|
||||||
return self._source_path
|
|
||||||
|
|
||||||
@property
|
|
||||||
def output_path(self) -> str:
|
|
||||||
return self._output_path
|
|
||||||
|
|
||||||
@property
|
|
||||||
def main(self) -> str:
|
|
||||||
return self._main
|
|
||||||
|
|
||||||
@property
|
|
||||||
def entry_point(self) -> str:
|
|
||||||
return self._entry_point
|
|
||||||
|
|
||||||
@property
|
|
||||||
def include_package_data(self) -> bool:
|
|
||||||
return self._include_package_data
|
|
||||||
|
|
||||||
@property
|
|
||||||
def included(self) -> list[str]:
|
|
||||||
return self._included
|
|
||||||
|
|
||||||
@property
|
|
||||||
def excluded(self) -> list[str]:
|
|
||||||
return self._excluded
|
|
||||||
|
|
||||||
@property
|
|
||||||
def package_data(self) -> dict[str, list[str]]:
|
|
||||||
return self._package_data
|
|
||||||
|
|
||||||
@property
|
|
||||||
def project_references(self) -> list[str]:
|
|
||||||
return self._project_references
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
from enum import Enum
|
|
||||||
|
|
||||||
|
|
||||||
class BuildSettingsNameEnum(Enum):
|
|
||||||
project_type = "ProjectType"
|
|
||||||
source_path = "SourcePath"
|
|
||||||
output_path = "OutputPath"
|
|
||||||
main = "Main"
|
|
||||||
entry_point = "EntryPoint"
|
|
||||||
include_package_data = "IncludePackageData"
|
|
||||||
included = "Included"
|
|
||||||
excluded = "Excluded"
|
|
||||||
package_data = "PackageData"
|
|
||||||
project_references = "ProjectReferences"
|
|
||||||
@@ -1,132 +0,0 @@
|
|||||||
import os
|
|
||||||
import sys
|
|
||||||
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
|
|
||||||
|
|
||||||
|
|
||||||
class ProjectSettings(ConfigurationModelABC):
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
name: str = None,
|
|
||||||
version: VersionSettings = None,
|
|
||||||
author: str = None,
|
|
||||||
author_email: str = None,
|
|
||||||
description: str = None,
|
|
||||||
long_description: str = None,
|
|
||||||
url: str = None,
|
|
||||||
copyright_date: str = None,
|
|
||||||
copyright_name: str = None,
|
|
||||||
license_name: str = None,
|
|
||||||
license_description: str = None,
|
|
||||||
dependencies: list = None,
|
|
||||||
dev_dependencies: list = None,
|
|
||||||
python_version: str = None,
|
|
||||||
python_path: dict = None,
|
|
||||||
python_executable: str = None,
|
|
||||||
classifiers: list = None,
|
|
||||||
):
|
|
||||||
ConfigurationModelABC.__init__(self)
|
|
||||||
|
|
||||||
self._name: Optional[str] = name
|
|
||||||
self._version: Optional[VersionSettings] = version
|
|
||||||
self._author: Optional[str] = author
|
|
||||||
self._author_email: Optional[str] = author_email
|
|
||||||
self._description: Optional[str] = description
|
|
||||||
self._long_description: Optional[str] = long_description
|
|
||||||
self._url: Optional[str] = url
|
|
||||||
self._copyright_date: Optional[str] = copyright_date
|
|
||||||
self._copyright_name: Optional[str] = copyright_name
|
|
||||||
self._license_name: Optional[str] = license_name
|
|
||||||
self._license_description: Optional[str] = license_description
|
|
||||||
self._dependencies: Optional[list[str]] = [] if dependencies is None else dependencies
|
|
||||||
self._dev_dependencies: Optional[list[str]] = [] if dev_dependencies is None else dev_dependencies
|
|
||||||
self._python_version: Optional[str] = python_version
|
|
||||||
self._python_path: Optional[str] = python_path
|
|
||||||
self._python_executable: Optional[str] = python_executable
|
|
||||||
self._classifiers: Optional[list[str]] = [] if classifiers is None else classifiers
|
|
||||||
|
|
||||||
if python_path is not None and sys.platform in python_path:
|
|
||||||
path = f"{python_path[sys.platform]}"
|
|
||||||
|
|
||||||
if path == "" or path is None:
|
|
||||||
Error.warn(f"{ProjectSettingsNameEnum.python_path.value} not set")
|
|
||||||
path = sys.executable
|
|
||||||
else:
|
|
||||||
if not path.endswith("bin/python"):
|
|
||||||
path = os.path.join(path, "bin/python")
|
|
||||||
else:
|
|
||||||
path = sys.executable
|
|
||||||
|
|
||||||
self._python_executable = path
|
|
||||||
|
|
||||||
@property
|
|
||||||
def name(self):
|
|
||||||
return self._name
|
|
||||||
|
|
||||||
@property
|
|
||||||
def version(self) -> VersionSettings:
|
|
||||||
return self._version
|
|
||||||
|
|
||||||
@property
|
|
||||||
def author(self) -> str:
|
|
||||||
return self._author
|
|
||||||
|
|
||||||
@property
|
|
||||||
def author_email(self) -> str:
|
|
||||||
return self._author_email
|
|
||||||
|
|
||||||
@property
|
|
||||||
def description(self) -> str:
|
|
||||||
return self._description
|
|
||||||
|
|
||||||
@property
|
|
||||||
def long_description(self) -> str:
|
|
||||||
return self._long_description
|
|
||||||
|
|
||||||
@property
|
|
||||||
def url(self) -> str:
|
|
||||||
return self._url
|
|
||||||
|
|
||||||
@property
|
|
||||||
def copyright_date(self) -> str:
|
|
||||||
return self._copyright_date
|
|
||||||
|
|
||||||
@property
|
|
||||||
def copyright_name(self) -> str:
|
|
||||||
return self._copyright_name
|
|
||||||
|
|
||||||
@property
|
|
||||||
def license_name(self) -> str:
|
|
||||||
return self._license_name
|
|
||||||
|
|
||||||
@property
|
|
||||||
def license_description(self) -> str:
|
|
||||||
return self._license_description
|
|
||||||
|
|
||||||
@property
|
|
||||||
def dependencies(self) -> list[str]:
|
|
||||||
return self._dependencies
|
|
||||||
|
|
||||||
@property
|
|
||||||
def dev_dependencies(self) -> list[str]:
|
|
||||||
return self._dev_dependencies
|
|
||||||
|
|
||||||
@property
|
|
||||||
def python_version(self) -> str:
|
|
||||||
return self._python_version
|
|
||||||
|
|
||||||
@property
|
|
||||||
def python_path(self) -> str:
|
|
||||||
return self._python_path
|
|
||||||
|
|
||||||
@property
|
|
||||||
def python_executable(self) -> str:
|
|
||||||
return self._python_executable
|
|
||||||
|
|
||||||
@property
|
|
||||||
def classifiers(self) -> list[str]:
|
|
||||||
return self._classifiers
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
from enum import Enum
|
|
||||||
|
|
||||||
|
|
||||||
class ProjectSettingsNameEnum(Enum):
|
|
||||||
name = "Name"
|
|
||||||
version = "Version"
|
|
||||||
author = "Author"
|
|
||||||
author_email = "AuthorEmail"
|
|
||||||
description = "Description"
|
|
||||||
long_description = "LongDescription"
|
|
||||||
url = "URL"
|
|
||||||
copyright_date = "CopyrightDate"
|
|
||||||
copyright_name = "CopyrightName"
|
|
||||||
license_name = "LicenseName"
|
|
||||||
license_description = "LicenseDescription"
|
|
||||||
dependencies = "Dependencies"
|
|
||||||
dev_dependencies = "DevDependencies"
|
|
||||||
python_version = "PythonVersion"
|
|
||||||
python_path = "PythonPath"
|
|
||||||
classifiers = "Classifiers"
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
from enum import Enum
|
|
||||||
|
|
||||||
|
|
||||||
class ProjectTypeEnum(Enum):
|
|
||||||
console = "console"
|
|
||||||
library = "library"
|
|
||||||
unittest = "unittest"
|
|
||||||
discord_bot = "discord-bot"
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
from cpl_core.utils import String
|
|
||||||
|
|
||||||
|
|
||||||
class SchematicCollection:
|
|
||||||
_schematics: dict = {}
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def register(cls, template: type, schematic: str, aliases: list[str]):
|
|
||||||
cls._schematics[schematic] = {"Template": template, "Aliases": aliases}
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def get_schematics(cls) -> dict:
|
|
||||||
return cls._schematics
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
from cpl_cli.configuration.version_settings_name_enum import VersionSettingsNameEnum
|
|
||||||
from cpl_cli.configuration.build_settings import BuildSettings
|
|
||||||
from cpl_cli.configuration.build_settings_name_enum import BuildSettingsNameEnum
|
|
||||||
from cpl_cli.configuration.project_settings import ProjectSettings
|
|
||||||
from cpl_cli.configuration.project_settings_name_enum import ProjectSettingsNameEnum
|
|
||||||
|
|
||||||
|
|
||||||
class SettingsHelper:
|
|
||||||
@staticmethod
|
|
||||||
def get_project_settings_dict(project: ProjectSettings) -> dict:
|
|
||||||
return {
|
|
||||||
ProjectSettingsNameEnum.name.value: project.name,
|
|
||||||
ProjectSettingsNameEnum.version.value: {
|
|
||||||
VersionSettingsNameEnum.major.value: project.version.major,
|
|
||||||
VersionSettingsNameEnum.minor.value: project.version.minor,
|
|
||||||
VersionSettingsNameEnum.micro.value: project.version.micro,
|
|
||||||
},
|
|
||||||
ProjectSettingsNameEnum.author.value: project.author,
|
|
||||||
ProjectSettingsNameEnum.author_email.value: project.author_email,
|
|
||||||
ProjectSettingsNameEnum.description.value: project.description,
|
|
||||||
ProjectSettingsNameEnum.long_description.value: project.long_description,
|
|
||||||
ProjectSettingsNameEnum.url.value: project.url,
|
|
||||||
ProjectSettingsNameEnum.copyright_date.value: project.copyright_date,
|
|
||||||
ProjectSettingsNameEnum.copyright_name.value: project.copyright_name,
|
|
||||||
ProjectSettingsNameEnum.license_name.value: project.license_name,
|
|
||||||
ProjectSettingsNameEnum.license_description.value: project.license_description,
|
|
||||||
ProjectSettingsNameEnum.dependencies.value: project.dependencies,
|
|
||||||
ProjectSettingsNameEnum.dev_dependencies.value: project.dev_dependencies,
|
|
||||||
ProjectSettingsNameEnum.python_version.value: project.python_version,
|
|
||||||
ProjectSettingsNameEnum.python_path.value: project.python_path,
|
|
||||||
ProjectSettingsNameEnum.classifiers.value: project.classifiers,
|
|
||||||
}
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def get_build_settings_dict(build: BuildSettings) -> dict:
|
|
||||||
return {
|
|
||||||
BuildSettingsNameEnum.project_type.value: build.project_type.value,
|
|
||||||
BuildSettingsNameEnum.source_path.value: build.source_path,
|
|
||||||
BuildSettingsNameEnum.output_path.value: build.output_path,
|
|
||||||
BuildSettingsNameEnum.main.value: build.main,
|
|
||||||
BuildSettingsNameEnum.entry_point.value: build.entry_point,
|
|
||||||
BuildSettingsNameEnum.include_package_data.value: build.include_package_data,
|
|
||||||
BuildSettingsNameEnum.included.value: build.included,
|
|
||||||
BuildSettingsNameEnum.excluded.value: build.excluded,
|
|
||||||
BuildSettingsNameEnum.package_data.value: build.package_data,
|
|
||||||
BuildSettingsNameEnum.project_references.value: build.project_references,
|
|
||||||
}
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
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, python_executable: str, explicit_path=None):
|
|
||||||
if is_virtual:
|
|
||||||
return
|
|
||||||
|
|
||||||
venv_path = os.path.abspath(os.path.join(env.working_directory, 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(python_executable)
|
|
||||||
|
|
||||||
@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,
|
|
||||||
)
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
from typing import Optional
|
|
||||||
|
|
||||||
from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC
|
|
||||||
from cpl_cli.configuration.version_settings_name_enum import VersionSettingsNameEnum
|
|
||||||
|
|
||||||
|
|
||||||
class VersionSettings(ConfigurationModelABC):
|
|
||||||
def __init__(self, major: str = None, minor: str = None, micro: str = None):
|
|
||||||
ConfigurationModelABC.__init__(self)
|
|
||||||
|
|
||||||
self._major: Optional[str] = major
|
|
||||||
self._minor: Optional[str] = minor
|
|
||||||
self._micro: Optional[str] = micro if micro != "" else None
|
|
||||||
|
|
||||||
@property
|
|
||||||
def major(self) -> str:
|
|
||||||
return self._major
|
|
||||||
|
|
||||||
@property
|
|
||||||
def minor(self) -> str:
|
|
||||||
return self._minor
|
|
||||||
|
|
||||||
@property
|
|
||||||
def micro(self) -> str:
|
|
||||||
return self._micro
|
|
||||||
|
|
||||||
def to_str(self) -> str:
|
|
||||||
if self._micro is None:
|
|
||||||
return f"{self._major}.{self._minor}"
|
|
||||||
else:
|
|
||||||
return f"{self._major}.{self._minor}.{self._micro}"
|
|
||||||
|
|
||||||
def to_dict(self) -> dict:
|
|
||||||
version = {
|
|
||||||
VersionSettingsNameEnum.major.value: self._major,
|
|
||||||
VersionSettingsNameEnum.minor.value: self._minor,
|
|
||||||
}
|
|
||||||
|
|
||||||
if self._micro is not None:
|
|
||||||
version[VersionSettingsNameEnum.micro.value] = self._micro
|
|
||||||
|
|
||||||
return version
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
from enum import Enum
|
|
||||||
|
|
||||||
|
|
||||||
class VersionSettingsNameEnum(Enum):
|
|
||||||
major = "Major"
|
|
||||||
minor = "Minor"
|
|
||||||
micro = "Micro"
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
import traceback
|
|
||||||
from typing import Optional
|
|
||||||
|
|
||||||
from cpl_cli.configuration.workspace_settings_name_enum import WorkspaceSettingsNameEnum
|
|
||||||
from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC
|
|
||||||
from cpl_core.console import Console
|
|
||||||
|
|
||||||
|
|
||||||
class WorkspaceSettings(ConfigurationModelABC):
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
default_project: str = None,
|
|
||||||
projects: dict = None,
|
|
||||||
scripts: dict = None,
|
|
||||||
):
|
|
||||||
ConfigurationModelABC.__init__(self)
|
|
||||||
|
|
||||||
self._default_project: Optional[str] = default_project
|
|
||||||
self._projects: dict[str, str] = {} if projects is None else projects
|
|
||||||
self._scripts: dict[str, str] = {} if scripts is None else scripts
|
|
||||||
|
|
||||||
@property
|
|
||||||
def default_project(self) -> str:
|
|
||||||
return self._default_project
|
|
||||||
|
|
||||||
@property
|
|
||||||
def projects(self) -> dict[str, str]:
|
|
||||||
return self._projects
|
|
||||||
|
|
||||||
@property
|
|
||||||
def scripts(self):
|
|
||||||
return self._scripts
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
from enum import Enum
|
|
||||||
|
|
||||||
|
|
||||||
class WorkspaceSettingsNameEnum(Enum):
|
|
||||||
default_project = "DefaultProject"
|
|
||||||
projects = "Projects"
|
|
||||||
scripts = "Scripts"
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
{
|
|
||||||
"ProjectSettings": {
|
|
||||||
"Name": "cpl-cli",
|
|
||||||
"Version": {
|
|
||||||
"Major": "2024",
|
|
||||||
"Minor": "7",
|
|
||||||
"Micro": "0"
|
|
||||||
},
|
|
||||||
"Author": "Sven Heidemann",
|
|
||||||
"AuthorEmail": "sven.heidemann@sh-edraft.de",
|
|
||||||
"Description": "CPL CLI",
|
|
||||||
"LongDescription": "CPL Command Line Interface",
|
|
||||||
"URL": "https://www.sh-edraft.de",
|
|
||||||
"CopyrightDate": "2020 - 2024",
|
|
||||||
"CopyrightName": "sh-edraft.de",
|
|
||||||
"LicenseName": "MIT",
|
|
||||||
"LicenseDescription": "MIT, see LICENSE for more details.",
|
|
||||||
"Dependencies": [
|
|
||||||
"cpl-core>=2024.6.2024.07.0"
|
|
||||||
],
|
|
||||||
"DevDependencies": [],
|
|
||||||
"PythonVersion": ">=3.12",
|
|
||||||
"PythonPath": {
|
|
||||||
"linux": "../../venv"
|
|
||||||
},
|
|
||||||
"Classifiers": []
|
|
||||||
},
|
|
||||||
"BuildSettings": {
|
|
||||||
"ProjectType": "console",
|
|
||||||
"SourcePath": "",
|
|
||||||
"OutputPath": "../../dist",
|
|
||||||
"Main": "cpl_cli.main",
|
|
||||||
"EntryPoint": "cpl",
|
|
||||||
"IncludePackageData": true,
|
|
||||||
"Included": [
|
|
||||||
"*/_templates"
|
|
||||||
],
|
|
||||||
"Excluded": [
|
|
||||||
"*/__pycache__",
|
|
||||||
"*/logs",
|
|
||||||
"*/tests"
|
|
||||||
],
|
|
||||||
"PackageData": {
|
|
||||||
"cpl_cli": [
|
|
||||||
"*.json",
|
|
||||||
".cpl/*.py"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"ProjectReferences": []
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
from cpl_core.console.foreground_color_enum import ForegroundColorEnum
|
|
||||||
from cpl_core.console.console import Console
|
|
||||||
|
|
||||||
|
|
||||||
class Error:
|
|
||||||
@staticmethod
|
|
||||||
def error(message: str):
|
|
||||||
Console.error(message)
|
|
||||||
Console.error("Run 'cpl help'\n")
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def warn(message: str):
|
|
||||||
Console.set_foreground_color(ForegroundColorEnum.yellow)
|
|
||||||
Console.write_line(message, "\n")
|
|
||||||
Console.set_foreground_color(ForegroundColorEnum.default)
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
"""
|
|
||||||
cpl-cli CPL CLI
|
|
||||||
~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
CPL Command Line Interface
|
|
||||||
|
|
||||||
:copyright: (c) 2020 - 2024 sh-edraft.de
|
|
||||||
:license: MIT, see LICENSE for more details.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
__title__ = "cpl_cli.helper"
|
|
||||||
__author__ = "Sven Heidemann"
|
|
||||||
__license__ = "MIT"
|
|
||||||
__copyright__ = "Copyright (c) 2020 - 2024 sh-edraft.de"
|
|
||||||
__version__ = "2024.10.0"
|
|
||||||
|
|
||||||
from collections import namedtuple
|
|
||||||
|
|
||||||
|
|
||||||
# imports:
|
|
||||||
|
|
||||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
|
||||||
version_info = VersionInfo(major="2024", minor="10", micro="0")
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
import pkg_resources
|
|
||||||
|
|
||||||
|
|
||||||
class Dependencies:
|
|
||||||
_packages = []
|
|
||||||
_cpl_packages = []
|
|
||||||
|
|
||||||
_dependencies = dict(tuple(str(ws).split()) for ws in pkg_resources.working_set)
|
|
||||||
for p in _dependencies:
|
|
||||||
if str(p).startswith("cpl-"):
|
|
||||||
_cpl_packages.append([p, _dependencies[p]])
|
|
||||||
continue
|
|
||||||
|
|
||||||
_packages.append([p, _dependencies[p]])
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def get_cpl_packages(cls) -> list[list]:
|
|
||||||
return cls._cpl_packages
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def get_packages(cls) -> list[list]:
|
|
||||||
return cls._packages
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
"""
|
|
||||||
cpl-cli CPL CLI
|
|
||||||
~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
CPL Command Line Interface
|
|
||||||
|
|
||||||
:copyright: (c) 2020 - 2024 sh-edraft.de
|
|
||||||
:license: MIT, see LICENSE for more details.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
__title__ = "cpl_cli.live_server"
|
|
||||||
__author__ = "Sven Heidemann"
|
|
||||||
__license__ = "MIT"
|
|
||||||
__copyright__ = "Copyright (c) 2020 - 2024 sh-edraft.de"
|
|
||||||
__version__ = "2024.10.0"
|
|
||||||
|
|
||||||
from collections import namedtuple
|
|
||||||
|
|
||||||
|
|
||||||
# imports:
|
|
||||||
|
|
||||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
|
||||||
version_info = VersionInfo(major="2024", minor="10", micro="0")
|
|
||||||
@@ -1,129 +0,0 @@
|
|||||||
import os
|
|
||||||
import time
|
|
||||||
from contextlib import suppress
|
|
||||||
|
|
||||||
import psutil as psutil
|
|
||||||
from watchdog.events import FileSystemEventHandler
|
|
||||||
from watchdog.observers import Observer
|
|
||||||
|
|
||||||
from cpl_cli.publish import PublisherService
|
|
||||||
from cpl_core.console.console import Console
|
|
||||||
from cpl_core.environment.application_environment_abc import ApplicationEnvironmentABC
|
|
||||||
from cpl_cli.configuration.build_settings import BuildSettings
|
|
||||||
from cpl_cli.configuration.project_settings import ProjectSettings
|
|
||||||
from cpl_cli.live_server.live_server_thread import LiveServerThread
|
|
||||||
from cpl_core.utils import String
|
|
||||||
|
|
||||||
|
|
||||||
class LiveServerService(FileSystemEventHandler):
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
env: ApplicationEnvironmentABC,
|
|
||||||
project_settings: ProjectSettings,
|
|
||||||
build_settings: BuildSettings,
|
|
||||||
publisher: PublisherService,
|
|
||||||
):
|
|
||||||
"""
|
|
||||||
Service for the live development server
|
|
||||||
:param env:
|
|
||||||
:param project_settings:
|
|
||||||
:param build_settings:
|
|
||||||
"""
|
|
||||||
FileSystemEventHandler.__init__(self)
|
|
||||||
|
|
||||||
self._env = env
|
|
||||||
self._project_settings = project_settings
|
|
||||||
self._build_settings = build_settings
|
|
||||||
self._publisher = publisher
|
|
||||||
|
|
||||||
self._src_dir = os.path.join(self._env.working_directory, self._build_settings.source_path)
|
|
||||||
self._wd = self._src_dir
|
|
||||||
self._ls_thread = None
|
|
||||||
self._observer = None
|
|
||||||
|
|
||||||
self._args: list[str] = []
|
|
||||||
self._is_dev = False
|
|
||||||
|
|
||||||
def _start_observer(self):
|
|
||||||
"""
|
|
||||||
Starts the file changes observer
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
self._observer = Observer()
|
|
||||||
self._observer.schedule(self, path=os.path.abspath(os.path.join(self._src_dir, "../")), recursive=True)
|
|
||||||
self._observer.start()
|
|
||||||
|
|
||||||
def _restart(self):
|
|
||||||
"""
|
|
||||||
Restarts the CPL project
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
for proc in psutil.process_iter():
|
|
||||||
with suppress(Exception):
|
|
||||||
if proc.cmdline() == self._ls_thread.command:
|
|
||||||
proc.kill()
|
|
||||||
|
|
||||||
Console.write_line("Restart\n")
|
|
||||||
while self._ls_thread.is_alive():
|
|
||||||
time.sleep(1)
|
|
||||||
|
|
||||||
self._start()
|
|
||||||
|
|
||||||
def on_modified(self, event):
|
|
||||||
"""
|
|
||||||
Triggers when source file is modified
|
|
||||||
:param event:
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
if event.is_directory:
|
|
||||||
return None
|
|
||||||
|
|
||||||
# Event is modified, you can process it now
|
|
||||||
if str(event.src_path).endswith(".py"):
|
|
||||||
self._observer.stop()
|
|
||||||
self._restart()
|
|
||||||
|
|
||||||
def _start(self):
|
|
||||||
self._build()
|
|
||||||
self._start_observer()
|
|
||||||
self._ls_thread = LiveServerThread(
|
|
||||||
self._project_settings.python_executable, self._wd, self._args, self._env, self._build_settings
|
|
||||||
)
|
|
||||||
self._ls_thread.start()
|
|
||||||
self._ls_thread.join()
|
|
||||||
Console.close()
|
|
||||||
|
|
||||||
def _build(self):
|
|
||||||
if self._is_dev:
|
|
||||||
return
|
|
||||||
|
|
||||||
self._env.set_working_directory(self._src_dir)
|
|
||||||
self._publisher.build()
|
|
||||||
self._env.set_working_directory(self._src_dir)
|
|
||||||
self._wd = os.path.abspath(
|
|
||||||
os.path.join(
|
|
||||||
self._src_dir,
|
|
||||||
self._build_settings.output_path,
|
|
||||||
self._project_settings.name,
|
|
||||||
"build",
|
|
||||||
String.convert_to_snake_case(self._project_settings.name),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
def start(self, args: list[str]):
|
|
||||||
"""
|
|
||||||
Starts the CPL live development server
|
|
||||||
:param args:
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
if self._build_settings.main == "":
|
|
||||||
Console.error("Project has no entry point.")
|
|
||||||
return
|
|
||||||
|
|
||||||
if "dev" in args:
|
|
||||||
self._is_dev = True
|
|
||||||
args.remove("dev")
|
|
||||||
|
|
||||||
self._args = args
|
|
||||||
Console.write_line("** CPL live development server is running **")
|
|
||||||
self._start()
|
|
||||||
@@ -1,86 +0,0 @@
|
|||||||
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 LiveServerThread(threading.Thread):
|
|
||||||
def __init__(
|
|
||||||
self, executable: str, path: str, args: list[str], env: ApplicationEnvironmentABC, build_settings: BuildSettings
|
|
||||||
):
|
|
||||||
"""
|
|
||||||
Thread to start the CPL project for the live development server
|
|
||||||
:param executable:
|
|
||||||
:param path:
|
|
||||||
:param args:
|
|
||||||
:param env:
|
|
||||||
:param build_settings:
|
|
||||||
"""
|
|
||||||
threading.Thread.__init__(self)
|
|
||||||
|
|
||||||
self._executable = os.path.abspath(executable)
|
|
||||||
|
|
||||||
self._path = path
|
|
||||||
self._args = args
|
|
||||||
self._env = env
|
|
||||||
self._build_settings = build_settings
|
|
||||||
|
|
||||||
self._main = ""
|
|
||||||
self._command = []
|
|
||||||
self._env_vars = os.environ
|
|
||||||
|
|
||||||
@property
|
|
||||||
def command(self) -> list[str]:
|
|
||||||
return self._command
|
|
||||||
|
|
||||||
@property
|
|
||||||
def main(self) -> str:
|
|
||||||
return self._main
|
|
||||||
|
|
||||||
def run(self):
|
|
||||||
"""
|
|
||||||
Starts the CPL project
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
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(self._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(self._path)))
|
|
||||||
src_cwd = os.path.abspath(os.path.join(self._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)}"
|
|
||||||
)
|
|
||||||
|
|
||||||
Console.set_foreground_color(ForegroundColorEnum.green)
|
|
||||||
Console.write_line("Read successfully")
|
|
||||||
Console.set_foreground_color(ForegroundColorEnum.cyan)
|
|
||||||
now = datetime.now()
|
|
||||||
Console.write_line(f'Started at {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 self._args:
|
|
||||||
self._command.append(arg)
|
|
||||||
|
|
||||||
subprocess.run(self._command, env=self._env_vars)
|
|
||||||
@@ -1,84 +0,0 @@
|
|||||||
import os
|
|
||||||
import subprocess
|
|
||||||
import sys
|
|
||||||
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.build_settings 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(os.path.join(self._env.working_directory, executable))
|
|
||||||
if not os.path.exists(self._executable):
|
|
||||||
Console.error(f"Executable not found")
|
|
||||||
return
|
|
||||||
|
|
||||||
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)
|
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
import importlib.metadata
|
|
||||||
from typing import Type
|
|
||||||
|
|
||||||
from cpl_cli.cli import CLI
|
|
||||||
from cpl_cli.startup import Startup
|
|
||||||
from cpl_cli.startup_argument_extension import StartupArgumentExtension
|
|
||||||
from cpl_cli.startup_migration_extension import StartupMigrationExtension
|
|
||||||
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
|
|
||||||
from cpl_core.console import Console
|
|
||||||
|
|
||||||
|
|
||||||
def get_startup_extensions() -> list[Type[StartupExtensionABC]]:
|
|
||||||
blacklisted_packages = ["cpl-cli"]
|
|
||||||
startup_extensions = []
|
|
||||||
|
|
||||||
installed_packages = importlib.metadata.distributions()
|
|
||||||
for p in installed_packages:
|
|
||||||
if not p.name.startswith("cpl-") or p.name in blacklisted_packages:
|
|
||||||
continue
|
|
||||||
|
|
||||||
package = p.name.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():
|
|
||||||
app_builder = ApplicationBuilder(CLI)
|
|
||||||
app_builder.use_startup(Startup)
|
|
||||||
app_builder.use_extension(StartupWorkspaceExtension)
|
|
||||||
app_builder.use_extension(StartupArgumentExtension)
|
|
||||||
app_builder.use_extension(StartupMigrationExtension)
|
|
||||||
for extension in get_startup_extensions():
|
|
||||||
app_builder.use_extension(extension)
|
|
||||||
|
|
||||||
app_builder.build().run()
|
|
||||||
Console.write_line()
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
||||||
|
|
||||||
# ((
|
|
||||||
# ( `)
|
|
||||||
# ; / ,
|
|
||||||
# / \/
|
|
||||||
# / |
|
|
||||||
# / ~/
|
|
||||||
# / ) ) ~ edraft
|
|
||||||
# ___// | /
|
|
||||||
# `--' \_~-,
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
"""
|
|
||||||
cpl-cli CPL CLI
|
|
||||||
~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
CPL Command Line Interface
|
|
||||||
|
|
||||||
:copyright: (c) 2020 - 2024 sh-edraft.de
|
|
||||||
:license: MIT, see LICENSE for more details.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
__title__ = "cpl_cli.migrations"
|
|
||||||
__author__ = "Sven Heidemann"
|
|
||||||
__license__ = "MIT"
|
|
||||||
__copyright__ = "Copyright (c) 2020 - 2024 sh-edraft.de"
|
|
||||||
__version__ = "2024.10.0"
|
|
||||||
|
|
||||||
from collections import namedtuple
|
|
||||||
|
|
||||||
|
|
||||||
# imports
|
|
||||||
|
|
||||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
|
||||||
version_info = VersionInfo(major="2024", minor="10", micro="0")
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
"""
|
|
||||||
cpl-cli CPL CLI
|
|
||||||
~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
CPL Command Line Interface
|
|
||||||
|
|
||||||
:copyright: (c) 2020 - 2024 sh-edraft.de
|
|
||||||
:license: MIT, see LICENSE for more details.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
__title__ = "cpl_cli.migrations.base"
|
|
||||||
__author__ = "Sven Heidemann"
|
|
||||||
__license__ = "MIT"
|
|
||||||
__copyright__ = "Copyright (c) 2020 - 2024 sh-edraft.de"
|
|
||||||
__version__ = "2024.10.0"
|
|
||||||
|
|
||||||
from collections import namedtuple
|
|
||||||
|
|
||||||
|
|
||||||
# imports:
|
|
||||||
|
|
||||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
|
||||||
version_info = VersionInfo(major="2024", minor="10", micro="0")
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
from abc import ABC, abstractmethod
|
|
||||||
|
|
||||||
|
|
||||||
class MigrationABC(ABC):
|
|
||||||
@abstractmethod
|
|
||||||
def __init__(self, version: str):
|
|
||||||
self._version = version
|
|
||||||
|
|
||||||
@property
|
|
||||||
def version(self) -> str:
|
|
||||||
return self._version
|
|
||||||
|
|
||||||
@abstractmethod
|
|
||||||
def migrate(self):
|
|
||||||
pass
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
from abc import ABC, abstractmethod
|
|
||||||
|
|
||||||
|
|
||||||
class MigrationServiceABC(ABC):
|
|
||||||
@abstractmethod
|
|
||||||
def __init__(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
@abstractmethod
|
|
||||||
def migrate_from(self, version: str):
|
|
||||||
pass
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
from cpl_cli.migrations.base.migration_abc import MigrationABC
|
|
||||||
|
|
||||||
|
|
||||||
class Migration202210(MigrationABC):
|
|
||||||
def __init__(self):
|
|
||||||
MigrationABC.__init__(self, "2022.10")
|
|
||||||
|
|
||||||
def migrate(self):
|
|
||||||
# This migration could be deleted, but stays as an example.
|
|
||||||
pass
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
"""
|
|
||||||
cpl-cli CPL CLI
|
|
||||||
~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
CPL Command Line Interface
|
|
||||||
|
|
||||||
:copyright: (c) 2020 - 2024 sh-edraft.de
|
|
||||||
:license: MIT, see LICENSE for more details.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
__title__ = "cpl_cli.migrations.service"
|
|
||||||
__author__ = "Sven Heidemann"
|
|
||||||
__license__ = "MIT"
|
|
||||||
__copyright__ = "Copyright (c) 2020 - 2024 sh-edraft.de"
|
|
||||||
__version__ = "2024.10.0"
|
|
||||||
|
|
||||||
from collections import namedtuple
|
|
||||||
|
|
||||||
|
|
||||||
# imports:
|
|
||||||
|
|
||||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
|
||||||
version_info = VersionInfo(major="2024", minor="10", micro="0")
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
from packaging import version
|
|
||||||
|
|
||||||
from cpl_cli.migrations.base.migration_abc import MigrationABC
|
|
||||||
from cpl_cli.migrations.base.migration_service_abc import MigrationServiceABC
|
|
||||||
from cpl_core.dependency_injection import ServiceProviderABC
|
|
||||||
|
|
||||||
|
|
||||||
class MigrationService(MigrationServiceABC):
|
|
||||||
def __init__(self, services: ServiceProviderABC):
|
|
||||||
MigrationServiceABC.__init__(self)
|
|
||||||
|
|
||||||
self._services = services
|
|
||||||
|
|
||||||
def migrate_from(self, _v: str):
|
|
||||||
for migration_type in MigrationABC.__subclasses__():
|
|
||||||
migration: MigrationABC = self._services.get_service(migration_type)
|
|
||||||
if version.parse(migration.version) <= version.parse(_v):
|
|
||||||
continue
|
|
||||||
|
|
||||||
migration.migrate()
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
"""
|
|
||||||
cpl-cli CPL CLI
|
|
||||||
~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
CPL Command Line Interface
|
|
||||||
|
|
||||||
:copyright: (c) 2020 - 2024 sh-edraft.de
|
|
||||||
:license: MIT, see LICENSE for more details.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
__title__ = "cpl_cli.publish"
|
|
||||||
__author__ = "Sven Heidemann"
|
|
||||||
__license__ = "MIT"
|
|
||||||
__copyright__ = "Copyright (c) 2020 - 2024 sh-edraft.de"
|
|
||||||
__version__ = "2024.10.0"
|
|
||||||
|
|
||||||
from collections import namedtuple
|
|
||||||
|
|
||||||
|
|
||||||
# imports:
|
|
||||||
from .publisher_abc import PublisherABC
|
|
||||||
from .publisher_service import PublisherService
|
|
||||||
|
|
||||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
|
||||||
version_info = VersionInfo(major="2024", minor="10", micro="0")
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
from abc import abstractmethod, ABC
|
|
||||||
|
|
||||||
|
|
||||||
class PublisherABC(ABC):
|
|
||||||
@abstractmethod
|
|
||||||
def __init__(self):
|
|
||||||
ABC.__init__(self)
|
|
||||||
|
|
||||||
@property
|
|
||||||
@abstractmethod
|
|
||||||
def source_path(self) -> str:
|
|
||||||
pass
|
|
||||||
|
|
||||||
@property
|
|
||||||
@abstractmethod
|
|
||||||
def dist_path(self) -> str:
|
|
||||||
pass
|
|
||||||
|
|
||||||
@abstractmethod
|
|
||||||
def include(self, path: str):
|
|
||||||
pass
|
|
||||||
|
|
||||||
@abstractmethod
|
|
||||||
def exclude(self, path: str):
|
|
||||||
pass
|
|
||||||
|
|
||||||
@abstractmethod
|
|
||||||
def build(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
@abstractmethod
|
|
||||||
def publish(self):
|
|
||||||
pass
|
|
||||||
@@ -1,519 +0,0 @@
|
|||||||
import os
|
|
||||||
import shutil
|
|
||||||
import sys
|
|
||||||
from string import Template as stringTemplate
|
|
||||||
|
|
||||||
import setuptools
|
|
||||||
from packaging import version
|
|
||||||
from setuptools import sandbox
|
|
||||||
|
|
||||||
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.environment.application_environment_abc import ApplicationEnvironmentABC
|
|
||||||
from cpl_cli.configuration.build_settings import BuildSettings
|
|
||||||
from cpl_cli.configuration.project_settings import ProjectSettings
|
|
||||||
from cpl_cli.publish.publisher_abc import PublisherABC
|
|
||||||
from cpl_cli._templates.build.init_template import InitTemplate
|
|
||||||
from cpl_cli._templates.publish.setup_template import SetupTemplate
|
|
||||||
|
|
||||||
|
|
||||||
class PublisherService(PublisherABC):
|
|
||||||
def __init__(
|
|
||||||
self, config: ConfigurationABC, env: ApplicationEnvironmentABC, project: ProjectSettings, build: BuildSettings
|
|
||||||
):
|
|
||||||
"""
|
|
||||||
Service to build or publish files for distribution
|
|
||||||
:param config:
|
|
||||||
:param env:
|
|
||||||
:param project:
|
|
||||||
:param build:
|
|
||||||
"""
|
|
||||||
PublisherABC.__init__(self)
|
|
||||||
|
|
||||||
self._config = config
|
|
||||||
self._env = env
|
|
||||||
self._project_settings = project
|
|
||||||
self._build_settings = build
|
|
||||||
|
|
||||||
self._source_path = os.path.join(self._env.working_directory, self._build_settings.source_path)
|
|
||||||
self._output_path = os.path.join(self._env.working_directory, self._build_settings.output_path)
|
|
||||||
|
|
||||||
self._included_files: list[str] = []
|
|
||||||
self._included_dirs: list[str] = []
|
|
||||||
self._distributed_files: list[str] = []
|
|
||||||
|
|
||||||
self._path_mark = "/"
|
|
||||||
if sys.platform == "win32":
|
|
||||||
self._path_mark = "\\"
|
|
||||||
|
|
||||||
self._src_path_part = f"src{self._path_mark}"
|
|
||||||
|
|
||||||
@property
|
|
||||||
def source_path(self) -> str:
|
|
||||||
return self._source_path
|
|
||||||
|
|
||||||
@property
|
|
||||||
def dist_path(self) -> str:
|
|
||||||
return self._output_path
|
|
||||||
|
|
||||||
def _get_module_name_from_dirs(self, file: str) -> str:
|
|
||||||
"""
|
|
||||||
Extracts module name from directories
|
|
||||||
:param file:
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
if self._src_path_part in file:
|
|
||||||
file = file.split(self._src_path_part)[1].replace(self._src_path_part, "", 1)
|
|
||||||
|
|
||||||
dirs = os.path.dirname(file).split(self._path_mark)
|
|
||||||
for d in dirs:
|
|
||||||
if d.__contains__("."):
|
|
||||||
dirs.remove(d)
|
|
||||||
|
|
||||||
if len(dirs) == 0:
|
|
||||||
return os.path.basename(file)
|
|
||||||
else:
|
|
||||||
return ".".join(dirs)
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _delete_path(path: str):
|
|
||||||
"""
|
|
||||||
Deletes full path tree
|
|
||||||
:param path:
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
if os.path.isdir(path):
|
|
||||||
try:
|
|
||||||
shutil.rmtree(path)
|
|
||||||
except Exception as e:
|
|
||||||
Console.error(f"{e}")
|
|
||||||
sys.exit()
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _create_path(path: str):
|
|
||||||
"""
|
|
||||||
Creates full path tree
|
|
||||||
:param path:
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
if not os.path.isdir(path):
|
|
||||||
try:
|
|
||||||
os.makedirs(path)
|
|
||||||
except Exception as e:
|
|
||||||
Console.error(f"{e}")
|
|
||||||
sys.exit()
|
|
||||||
|
|
||||||
def _is_path_included(self, path: str) -> bool:
|
|
||||||
"""
|
|
||||||
Checks if the path is included
|
|
||||||
:param path:
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
for included in self._build_settings.included:
|
|
||||||
if included.startswith("*"):
|
|
||||||
included = included.replace("*", "")
|
|
||||||
|
|
||||||
if included in path and path not in self._build_settings.excluded:
|
|
||||||
return True
|
|
||||||
|
|
||||||
return False
|
|
||||||
|
|
||||||
def _is_path_excluded(self, path: str) -> bool:
|
|
||||||
"""
|
|
||||||
Checks if the path is excluded
|
|
||||||
:param path:
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
for excluded in self._build_settings.excluded:
|
|
||||||
if excluded.startswith("*"):
|
|
||||||
excluded = excluded.replace("*", "")
|
|
||||||
|
|
||||||
if excluded in path and not self._is_path_included(path):
|
|
||||||
return True
|
|
||||||
|
|
||||||
return False
|
|
||||||
|
|
||||||
def _is_file_excluded(self, file: str) -> bool:
|
|
||||||
"""
|
|
||||||
Checks if the file is excluded
|
|
||||||
:param file:
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
for excluded in self._build_settings.excluded:
|
|
||||||
if excluded.startswith("*"):
|
|
||||||
excluded = excluded.replace("*", "")
|
|
||||||
|
|
||||||
if excluded in file and not self._is_path_included(file):
|
|
||||||
return True
|
|
||||||
|
|
||||||
return False
|
|
||||||
|
|
||||||
def _read_sources_from_path(self, path: str):
|
|
||||||
"""
|
|
||||||
Reads all source files from given path
|
|
||||||
:param path:
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
for r, d, f in os.walk(path):
|
|
||||||
for file in f:
|
|
||||||
relative_path = os.path.relpath(r)
|
|
||||||
file_path = os.path.join(relative_path, os.path.relpath(file))
|
|
||||||
if self._is_file_excluded(file_path):
|
|
||||||
continue
|
|
||||||
|
|
||||||
if len(d) > 0:
|
|
||||||
for directory in d:
|
|
||||||
empty_dir = os.path.join(os.path.dirname(file_path), directory)
|
|
||||||
if len(os.listdir(empty_dir)) == 0:
|
|
||||||
self._included_dirs.append(empty_dir)
|
|
||||||
|
|
||||||
if not self._is_path_excluded(relative_path):
|
|
||||||
self._included_files.append(os.path.relpath(file_path))
|
|
||||||
|
|
||||||
def _read_sources(self):
|
|
||||||
"""
|
|
||||||
Reads all source files and save included files
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
for file in self._build_settings.included:
|
|
||||||
rel_path = os.path.relpath(file)
|
|
||||||
if os.path.isdir(rel_path):
|
|
||||||
for r, d, f in os.walk(rel_path):
|
|
||||||
for sub_file in f:
|
|
||||||
relative_path = os.path.relpath(r)
|
|
||||||
file_path = os.path.join(relative_path, os.path.relpath(sub_file))
|
|
||||||
|
|
||||||
self._included_files.append(os.path.relpath(file_path))
|
|
||||||
|
|
||||||
elif os.path.isfile(rel_path):
|
|
||||||
self._included_files.append(rel_path)
|
|
||||||
|
|
||||||
self._read_sources_from_path(self._source_path)
|
|
||||||
|
|
||||||
for project in self._build_settings.project_references:
|
|
||||||
project = os.path.abspath(os.path.join(self._source_path, project))
|
|
||||||
if not os.path.isfile(os.path.abspath(project)):
|
|
||||||
Console.error(f"Cannot import project: {project}")
|
|
||||||
return
|
|
||||||
|
|
||||||
self.exclude(f"*/{os.path.basename(project)}")
|
|
||||||
self._read_sources_from_path(os.path.dirname(project))
|
|
||||||
|
|
||||||
def _create_packages(self):
|
|
||||||
"""
|
|
||||||
Writes information from template to all included __init__.py
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
for file in self._included_files:
|
|
||||||
if not file.endswith("__init__.py"):
|
|
||||||
continue
|
|
||||||
|
|
||||||
template_content = ""
|
|
||||||
module_file_lines: list[str] = []
|
|
||||||
|
|
||||||
title = self._get_module_name_from_dirs(file)
|
|
||||||
if title == "":
|
|
||||||
title = self._project_settings.name
|
|
||||||
|
|
||||||
module_py_lines: list[str] = []
|
|
||||||
imports = ""
|
|
||||||
|
|
||||||
with open(file, "r") as py_file:
|
|
||||||
module_file_lines = py_file.readlines()
|
|
||||||
py_file.close()
|
|
||||||
|
|
||||||
if len(module_file_lines) == 0:
|
|
||||||
imports = "# imports:"
|
|
||||||
else:
|
|
||||||
is_started = False
|
|
||||||
build_ignore = False
|
|
||||||
for line in module_file_lines:
|
|
||||||
if line.__contains__("# imports"):
|
|
||||||
is_started = True
|
|
||||||
|
|
||||||
if line.__contains__("# build-ignore"):
|
|
||||||
build_ignore = True
|
|
||||||
|
|
||||||
if line.__contains__("# build-ignore-end") and is_started:
|
|
||||||
module_py_lines.append("# build-ignore-end".replace("\n", ""))
|
|
||||||
build_ignore = False
|
|
||||||
|
|
||||||
if (
|
|
||||||
((line.__contains__("from") or line.__contains__("import")) and is_started)
|
|
||||||
or line.startswith("__cli_startup_extension__")
|
|
||||||
or build_ignore
|
|
||||||
):
|
|
||||||
module_py_lines.append(line.replace("\n", ""))
|
|
||||||
|
|
||||||
if len(module_py_lines) > 0:
|
|
||||||
imports = "\n".join(module_py_lines)
|
|
||||||
|
|
||||||
template_content = stringTemplate(InitTemplate.get_init_py()).substitute(
|
|
||||||
Name=self._project_settings.name,
|
|
||||||
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):
|
|
||||||
"""
|
|
||||||
Copies all included source files to dist_path
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
build_path = os.path.join(self._output_path)
|
|
||||||
self._delete_path(build_path)
|
|
||||||
self._create_path(build_path)
|
|
||||||
|
|
||||||
for file in self._included_files:
|
|
||||||
dist_file = file
|
|
||||||
if self._src_path_part in dist_file:
|
|
||||||
dist_file = dist_file.replace(self._src_path_part, "", 1)
|
|
||||||
|
|
||||||
output_path = os.path.join(build_path, os.path.dirname(dist_file))
|
|
||||||
output_file = os.path.join(build_path, dist_file)
|
|
||||||
|
|
||||||
try:
|
|
||||||
if not os.path.isdir(output_path):
|
|
||||||
os.makedirs(output_path, exist_ok=True)
|
|
||||||
except Exception as e:
|
|
||||||
Console.error(__name__, f"Cannot create directories: {output_path} -> {e}")
|
|
||||||
return
|
|
||||||
|
|
||||||
try:
|
|
||||||
self._distributed_files.append(output_file)
|
|
||||||
shutil.copy(os.path.abspath(file), output_file)
|
|
||||||
except Exception as e:
|
|
||||||
Console.error(__name__, f"Cannot copy file: {file} to {output_path} -> {e}")
|
|
||||||
return
|
|
||||||
|
|
||||||
for empty_dir in self._included_dirs:
|
|
||||||
dist_dir = empty_dir
|
|
||||||
if self._src_path_part in dist_dir:
|
|
||||||
dist_dir = dist_dir.replace(self._src_path_part, "", 1)
|
|
||||||
|
|
||||||
output_path = os.path.join(build_path, dist_dir)
|
|
||||||
if not os.path.isdir(output_path):
|
|
||||||
os.makedirs(output_path)
|
|
||||||
|
|
||||||
def _clean_dist_files(self):
|
|
||||||
"""
|
|
||||||
Deletes all included source files from dist_path
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
paths: list[str] = []
|
|
||||||
for file in self._distributed_files:
|
|
||||||
paths.append(os.path.dirname(file))
|
|
||||||
|
|
||||||
if os.path.isfile(file):
|
|
||||||
os.remove(file)
|
|
||||||
|
|
||||||
for path in paths:
|
|
||||||
if path != self._output_path and os.path.isdir(path):
|
|
||||||
shutil.rmtree(path)
|
|
||||||
|
|
||||||
def _create_setup(self):
|
|
||||||
"""
|
|
||||||
Generates setup.py
|
|
||||||
|
|
||||||
Dependencies: ProjectSettings, BuildSettings
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
setup_file = os.path.join(self._output_path, "setup.py")
|
|
||||||
if os.path.isfile(setup_file):
|
|
||||||
os.remove(setup_file)
|
|
||||||
|
|
||||||
entry_points = {}
|
|
||||||
if self._build_settings.main != "":
|
|
||||||
main = None
|
|
||||||
try:
|
|
||||||
main_name = self._build_settings.main
|
|
||||||
|
|
||||||
if "." in self._build_settings.main:
|
|
||||||
length = len(self._build_settings.main.split("."))
|
|
||||||
main_name = self._build_settings.main.split(".")[length - 1]
|
|
||||||
|
|
||||||
sys.path.insert(0, os.path.join(self._source_path, "../"))
|
|
||||||
main_mod = __import__(self._build_settings.main)
|
|
||||||
main = getattr(main_mod, main_name)
|
|
||||||
except Exception as e:
|
|
||||||
Console.error("Could not find entry point", str(e))
|
|
||||||
return
|
|
||||||
|
|
||||||
if main is None or not callable(main) and not hasattr(main, "main"):
|
|
||||||
Console.error("Could not find entry point")
|
|
||||||
return
|
|
||||||
|
|
||||||
if callable(main):
|
|
||||||
mod_name = main.__module__
|
|
||||||
func_name = main.__name__
|
|
||||||
else:
|
|
||||||
mod_name = main.__name__
|
|
||||||
func_name = main.main.__name__
|
|
||||||
|
|
||||||
entry_points = {"console_scripts": [f"{self._build_settings.entry_point} = {mod_name}:{func_name}"]}
|
|
||||||
|
|
||||||
with open(setup_file, "w+") as setup_py:
|
|
||||||
setup_string = stringTemplate(SetupTemplate.get_setup_py()).substitute(
|
|
||||||
Name=self._project_settings.name,
|
|
||||||
Version=self._project_settings.version.to_str(),
|
|
||||||
Packages=setuptools.find_packages(where=self._output_path, exclude=self._build_settings.excluded),
|
|
||||||
URL=self._project_settings.url,
|
|
||||||
LicenseName=self._project_settings.license_name,
|
|
||||||
Author=self._project_settings.author,
|
|
||||||
AuthorMail=self._project_settings.author_email,
|
|
||||||
IncludePackageData=self._build_settings.include_package_data,
|
|
||||||
Description=self._project_settings.description,
|
|
||||||
PyRequires=self._project_settings.python_version,
|
|
||||||
Dependencies=self._project_settings.dependencies,
|
|
||||||
EntryPoints=entry_points,
|
|
||||||
PackageData=self._build_settings.package_data,
|
|
||||||
)
|
|
||||||
setup_py.write(setup_string)
|
|
||||||
setup_py.close()
|
|
||||||
|
|
||||||
def _run_setup(self):
|
|
||||||
"""
|
|
||||||
Starts setup.py
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
setup_py = os.path.join(self._output_path, "setup.py")
|
|
||||||
if not os.path.isfile(setup_py):
|
|
||||||
Console.error(__name__, f"setup.py not found in {self._output_path}")
|
|
||||||
return
|
|
||||||
|
|
||||||
try:
|
|
||||||
sandbox.run_setup(
|
|
||||||
os.path.abspath(setup_py),
|
|
||||||
[
|
|
||||||
"sdist",
|
|
||||||
f'--dist-dir={os.path.join(self._output_path, "setup")}',
|
|
||||||
"bdist_wheel",
|
|
||||||
f'--bdist-dir={os.path.join(self._output_path, "bdist")}',
|
|
||||||
f'--dist-dir={os.path.join(self._output_path, "setup")}',
|
|
||||||
],
|
|
||||||
)
|
|
||||||
os.remove(setup_py)
|
|
||||||
except Exception as e:
|
|
||||||
Console.error("Executing setup.py failed", str(e))
|
|
||||||
|
|
||||||
def include(self, path: str):
|
|
||||||
"""
|
|
||||||
Includes given path from sources
|
|
||||||
:param path:
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
self._build_settings.included.append(path)
|
|
||||||
|
|
||||||
def exclude(self, path: str):
|
|
||||||
"""
|
|
||||||
Excludes given path from sources
|
|
||||||
:param path:
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
self._build_settings.excluded.append(path)
|
|
||||||
|
|
||||||
def build(self):
|
|
||||||
"""
|
|
||||||
Build the CPL project to dist_path/build
|
|
||||||
|
|
||||||
1. Reads all included source files
|
|
||||||
2. Writes informations from template to all included __init__.py
|
|
||||||
3. Copies all included source files to dist_path/build
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
self._env.set_working_directory(
|
|
||||||
os.path.join(self._env.working_directory, "../")
|
|
||||||
) # probably causing some errors (#125)
|
|
||||||
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"))
|
|
||||||
|
|
||||||
Console.spinner(
|
|
||||||
"Reading source files:",
|
|
||||||
self._read_sources,
|
|
||||||
text_foreground_color=ForegroundColorEnum.green,
|
|
||||||
spinner_foreground_color=ForegroundColorEnum.blue,
|
|
||||||
)
|
|
||||||
Console.spinner(
|
|
||||||
"Creating internal packages:",
|
|
||||||
self._create_packages,
|
|
||||||
text_foreground_color=ForegroundColorEnum.green,
|
|
||||||
spinner_foreground_color=ForegroundColorEnum.blue,
|
|
||||||
)
|
|
||||||
Console.spinner(
|
|
||||||
"Building application:",
|
|
||||||
self._dist_files,
|
|
||||||
text_foreground_color=ForegroundColorEnum.green,
|
|
||||||
spinner_foreground_color=ForegroundColorEnum.blue,
|
|
||||||
)
|
|
||||||
Console.write_line()
|
|
||||||
|
|
||||||
def publish(self):
|
|
||||||
"""
|
|
||||||
Publishes the CPL project to dist_path/publish
|
|
||||||
|
|
||||||
1. Builds the project
|
|
||||||
2. Generates setup.py
|
|
||||||
3. Start setup.py
|
|
||||||
4. Remove all included source from dist_path/publish
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
self._env.set_working_directory(
|
|
||||||
os.path.join(self._env.working_directory, "../")
|
|
||||||
) # probably causing some errors (#125)
|
|
||||||
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"))
|
|
||||||
|
|
||||||
Console.write_line("Build:")
|
|
||||||
Console.spinner(
|
|
||||||
"Reading source files:",
|
|
||||||
self._read_sources,
|
|
||||||
text_foreground_color=ForegroundColorEnum.green,
|
|
||||||
spinner_foreground_color=ForegroundColorEnum.blue,
|
|
||||||
)
|
|
||||||
|
|
||||||
Console.spinner(
|
|
||||||
"Creating internal packages:",
|
|
||||||
self._create_packages,
|
|
||||||
text_foreground_color=ForegroundColorEnum.green,
|
|
||||||
spinner_foreground_color=ForegroundColorEnum.blue,
|
|
||||||
)
|
|
||||||
|
|
||||||
Console.spinner(
|
|
||||||
"Building application:",
|
|
||||||
self._dist_files,
|
|
||||||
text_foreground_color=ForegroundColorEnum.green,
|
|
||||||
spinner_foreground_color=ForegroundColorEnum.blue,
|
|
||||||
)
|
|
||||||
|
|
||||||
Console.write_line("\nPublish:")
|
|
||||||
Console.spinner(
|
|
||||||
"Generating setup.py:",
|
|
||||||
self._create_setup,
|
|
||||||
text_foreground_color=ForegroundColorEnum.green,
|
|
||||||
spinner_foreground_color=ForegroundColorEnum.blue,
|
|
||||||
)
|
|
||||||
|
|
||||||
Console.write_line("Running setup.py:\n")
|
|
||||||
self._run_setup()
|
|
||||||
Console.spinner(
|
|
||||||
"Cleaning dist path:",
|
|
||||||
self._clean_dist_files,
|
|
||||||
text_foreground_color=ForegroundColorEnum.green,
|
|
||||||
spinner_foreground_color=ForegroundColorEnum.blue,
|
|
||||||
)
|
|
||||||
Console.write_line()
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
"""
|
|
||||||
cpl-cli CPL CLI
|
|
||||||
~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
CPL Command Line Interface
|
|
||||||
|
|
||||||
:copyright: (c) 2020 - 2024 sh-edraft.de
|
|
||||||
:license: MIT, see LICENSE for more details.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
__title__ = "cpl_cli.source_creator"
|
|
||||||
__author__ = "Sven Heidemann"
|
|
||||||
__license__ = "MIT"
|
|
||||||
__copyright__ = "Copyright (c) 2020 - 2024 sh-edraft.de"
|
|
||||||
__version__ = "2024.10.0"
|
|
||||||
|
|
||||||
from collections import namedtuple
|
|
||||||
|
|
||||||
|
|
||||||
# imports:
|
|
||||||
|
|
||||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
|
||||||
version_info = VersionInfo(major="2024", minor="10", micro="0")
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
import json
|
|
||||||
import os
|
|
||||||
|
|
||||||
from cpl_cli.abc.file_template_abc import FileTemplateABC
|
|
||||||
from cpl_cli.configuration import WorkspaceSettings, WorkspaceSettingsNameEnum
|
|
||||||
from cpl_core.console import Console, ForegroundColorEnum
|
|
||||||
|
|
||||||
|
|
||||||
class TemplateBuilder:
|
|
||||||
@staticmethod
|
|
||||||
def build_cpl_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.build_cpl_file,
|
|
||||||
path,
|
|
||||||
ws_dict,
|
|
||||||
text_foreground_color=ForegroundColorEnum.green,
|
|
||||||
spinner_foreground_color=ForegroundColorEnum.cyan,
|
|
||||||
)
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def build(file_path: str, template: FileTemplateABC):
|
|
||||||
"""
|
|
||||||
Creates template
|
|
||||||
:param file_path:
|
|
||||||
:param template:
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
if not os.path.isdir(os.path.dirname(file_path)):
|
|
||||||
os.makedirs(os.path.dirname(file_path))
|
|
||||||
|
|
||||||
with open(file_path, "w") as file:
|
|
||||||
file.write(template.value)
|
|
||||||
file.close()
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user