First update towards cpl2
This commit is contained in:
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