Compare commits

..

10 Commits

Author SHA1 Message Date
5edabbf8c1 Removed docs from sources
All checks were successful
Build on push / prepare (push) Successful in 10s
Build on push / core (push) Successful in 17s
Build on push / query (push) Successful in 18s
Build on push / translation (push) Successful in 15s
Build on push / mail (push) Successful in 16s
2025-09-15 23:08:17 +02:00
62b6435470 Improved logging closes #180
All checks were successful
Build on push / prepare (push) Successful in 9s
Build on push / query (push) Successful in 17s
Build on push / core (push) Successful in 18s
Build on push / mail (push) Successful in 17s
Build on push / translation (push) Successful in 18s
2025-09-15 23:06:38 +02:00
d9d7802f33 Fixed translation build
All checks were successful
Build on push / prepare (push) Successful in 9s
Build on push / query (push) Successful in 19s
Build on push / core (push) Successful in 20s
Build on push / mail (push) Successful in 15s
Build on push / translation (push) Successful in 18s
2025-09-15 21:08:40 +02:00
25b4ca0696 Added cpl-mail
Some checks failed
Build on push / prepare (push) Successful in 9s
Build on push / core (push) Successful in 18s
Build on push / query (push) Successful in 25s
Build on push / translation (push) Failing after 8s
Build on push / mail (push) Successful in 14s
2025-09-15 20:56:07 +02:00
3b120370b8 Added cpl-mail
All checks were successful
Build on push / prepare (push) Successful in 9s
Build on push / translation (push) Successful in 20s
Build on push / mail (push) Successful in 21s
Build on push / query (push) Successful in 21s
Build on push / core (push) Successful in 21s
2025-09-15 18:38:34 +02:00
aac038ef63 Added cpl-mail
Some checks failed
Build on push / core (push) Failing after 9s
Build on push / mail (push) Has been cancelled
Build on push / translation (push) Has been cancelled
Build on push / prepare (push) Has been cancelled
Build on push / query (push) Has been cancelled
2025-09-15 18:35:36 +02:00
784632a0b4 Updated ci
Some checks failed
Build on push / core (push) Has been cancelled
Build on push / query (push) Has been cancelled
Build on push / translation (push) Has been cancelled
Build on push / prepare (push) Has been cancelled
2025-09-15 18:17:23 +02:00
4719c32457 Updated ci
Some checks failed
Build on push / prepare (push) Successful in 9s
Build on push / query (push) Failing after 18s
Build on push / core (push) Successful in 15s
2025-09-15 16:55:57 +02:00
516fa3fb7e Updated ci
Some checks failed
Build on push / prepare (push) Successful in 8s
Build on push / query (push) Successful in 18s
Build on push / core (push) Failing after 18s
2025-09-15 15:28:09 +02:00
2d2bb86720 First update towards cpl2
Some checks failed
Build on push / prepare (push) Failing after 6s
Build on push / build (push) Has been skipped
2025-09-15 15:02:47 +02:00
489 changed files with 1935 additions and 10731 deletions

View File

@@ -0,0 +1,41 @@
name: Build on push
run-name: Build on push
on:
push:
branches:
- dev
jobs:
prepare:
uses: ./.gitea/workflows/prepare.yaml
with:
version_suffix: 'dev'
secrets: inherit
core:
uses: ./.gitea/workflows/package.yaml
needs: [prepare]
with:
working_directory: src/cpl-core
secrets: inherit
query:
uses: ./.gitea/workflows/package.yaml
needs: [prepare]
with:
working_directory: src/cpl-query
secrets: inherit
translation:
uses: ./.gitea/workflows/package.yaml
needs: [ prepare, core ]
with:
working_directory: src/cpl-translation
secrets: inherit
mail:
uses: ./.gitea/workflows/package.yaml
needs: [ prepare, core ]
with:
working_directory: src/cpl-mail
secrets: inherit

View File

@@ -0,0 +1,39 @@
name: Build on push
run-name: Build on push
on:
push:
branches:
- master
jobs:
prepare:
uses: ./.gitea/workflows/prepare.yaml
secrets: inherit
core:
uses: ./.gitea/workflows/package.yaml
needs: [prepare]
with:
working_directory: src/cpl-core
secrets: inherit
query:
uses: ./.gitea/workflows/package.yaml
needs: [prepare]
with:
working_directory: src/cpl-query
secrets: inherit
translation:
uses: ./.gitea/workflows/package.yaml
needs: [ prepare, core ]
with:
working_directory: src/cpl-translation
secrets: inherit
mail:
uses: ./.gitea/workflows/package.yaml
needs: [ prepare, core ]
with:
working_directory: src/cpl-mail
secrets: inherit

View File

@@ -0,0 +1,65 @@
name: Build Package
run-name: Build Python Package
on:
workflow_call:
inputs:
version_suffix:
description: 'Suffix for version (z.B. "dev", "alpha", "beta")'
required: false
type: string
working_directory:
required: true
type: string
jobs:
build:
runs-on: [ runner ]
container: git.sh-edraft.de/sh-edraft.de/act-runner:latest
defaults:
run:
working-directory: ${{ inputs.working_directory }}
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 /workspace/sh-edraft.de/cpl/version.txt)\"/" pyproject.toml
echo "Set version to $(cat /workspace/sh-edraft.de/cpl/version.txt)"
cat pyproject.toml
- name: Set pip conf
run: |
cat > .pip.conf <<'EOF'
[global]
extra-index-url = https://git.sh-edraft.de/api/packages/sh-edraft.de/pypi/simple/
EOF
- name: Install Dependencies
run: |
export PIP_CONFIG_FILE=".pip.conf"
pip install build
- name: Build Package
run: |
python -m build --outdir dist
- 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/*

View File

@@ -0,0 +1,54 @@
name: Prepare Build
run-name: Prepare Build Version
on:
workflow_call:
inputs:
version_suffix:
description: 'Suffix for version (z.B. "dev", "alpha", "beta")'
required: false
type: string
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))
VERSION_SUFFIX=${{ inputs.version_suffix }}
if [ -n "$VERSION_SUFFIX" ] && [ "$VERSION_SUFFIX" = "dev" ]; then
BUILD_VERSION="${DATE}.dev${BUILD_NUMBER}"
elif [ -n "$VERSION_SUFFIX" ]; then
BUILD_VERSION="${DATE}.${BUILD_NUMBER}${VERSION_SUFFIX}"
else
BUILD_VERSION="${DATE}.${BUILD_NUMBER}"
fi
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

2
.pip.conf Normal file
View File

@@ -0,0 +1,2 @@
[global]
extra-index-url = https://git.sh-edraft.de/api/packages/sh-edraft.de/pypi/simple/

View File

@@ -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"
}
}
}

View File

@@ -0,0 +1 @@

View File

@@ -0,0 +1,6 @@
from .application_abc import ApplicationABC
from .application_builder import ApplicationBuilder
from .application_builder_abc import ApplicationBuilderABC
from .application_extension_abc import ApplicationExtensionABC
from .startup_abc import StartupABC
from .startup_extension_abc import StartupExtensionABC

View File

@@ -1,19 +1,19 @@
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from typing import Optional from typing import Optional
from cpl_core.configuration.configuration_abc import ConfigurationABC from cpl.core.configuration.configuration_abc import ConfigurationABC
from cpl_core.console.console import Console from cpl.core.console.console import Console
from cpl_core.dependency_injection.service_provider_abc import ServiceProviderABC from cpl.core.dependency_injection.service_provider_abc import ServiceProviderABC
from cpl_core.environment.application_environment_abc import ApplicationEnvironmentABC from cpl.core.environment.application_environment_abc import ApplicationEnvironmentABC
class ApplicationABC(ABC): class ApplicationABC(ABC):
r"""ABC for the Application class r"""ABC for the Application class
Parameters: Parameters:
config: :class:`cpl_core.configuration.configuration_abc.ConfigurationABC` config: :class:`cpl.core.configuration.configuration_abc.ConfigurationABC`
Contains object loaded from appsettings Contains object loaded from appsettings
services: :class:`cpl_core.dependency_injection.service_provider_abc.ServiceProviderABC` services: :class:`cpl.core.dependency_injection.service_provider_abc.ServiceProviderABC`
Contains instances of prepared objects Contains instances of prepared objects
""" """
@@ -49,14 +49,12 @@ class ApplicationABC(ABC):
def configure(self): def configure(self):
r"""Configure the application r"""Configure the application
Called by :class:`cpl_core.application.application_abc.ApplicationABC.run` Called by :class:`cpl.core.application.application_abc.ApplicationABC.run`
""" """
pass
@abstractmethod @abstractmethod
def main(self): def main(self):
r"""Custom entry point r"""Custom entry point
Called by :class:`cpl_core.application.application_abc.ApplicationABC.run` Called by :class:`cpl.core.application.application_abc.ApplicationABC.run`
""" """
pass

View File

@@ -0,0 +1,91 @@
from typing import Type, Optional, Callable, Union
from cpl.core.application.application_abc import ApplicationABC
from cpl.core.application.application_builder_abc import ApplicationBuilderABC
from cpl.core.application.application_extension_abc import ApplicationExtensionABC
from cpl.core.application.async_application_extension_abc import AsyncApplicationExtensionABC
from cpl.core.application.async_startup_abc import AsyncStartupABC
from cpl.core.application.async_startup_extension_abc import AsyncStartupExtensionABC
from cpl.core.application.startup_abc import StartupABC
from cpl.core.application.startup_extension_abc import StartupExtensionABC
from cpl.core.configuration.configuration import Configuration
from cpl.core.dependency_injection.service_collection import ServiceCollection
class ApplicationBuilder(ApplicationBuilderABC):
r"""This is class is used to build an object of :class:`cpl.core.application.application_abc.ApplicationABC`
Parameter:
app: Type[:class:`cpl.core.application.application_abc.ApplicationABC`]
Application to build
"""
def __init__(self, app: Type[ApplicationABC]):
ApplicationBuilderABC.__init__(self)
self._app = app
self._startup: Optional[StartupABC | AsyncStartupABC] = None
self._configuration = Configuration()
self._environment = self._configuration.environment
self._services = ServiceCollection(self._configuration)
self._app_extensions: list[Type[ApplicationExtensionABC | AsyncApplicationExtensionABC]] = []
self._startup_extensions: list[Type[StartupExtensionABC | AsyncStartupABC]] = []
def use_startup(self, startup: Type[StartupABC | AsyncStartupABC]) -> "ApplicationBuilder":
self._startup = startup()
return self
def use_extension(
self, extension: Type[ApplicationExtensionABC | AsyncApplicationExtensionABC | StartupExtensionABC | AsyncStartupExtensionABC]
) -> "ApplicationBuilder":
if (issubclass(extension, ApplicationExtensionABC) or issubclass(extension, AsyncApplicationExtensionABC)) and extension not in self._app_extensions:
self._app_extensions.append(extension)
elif (issubclass(extension, StartupExtensionABC) or issubclass(extension, AsyncStartupExtensionABC)) and extension not in self._startup_extensions:
self._startup_extensions.append(extension)
return self
def _build_startup(self):
for ex in self._startup_extensions:
extension = ex()
extension.configure_configuration(self._configuration, self._environment)
extension.configure_services(self._services, self._environment)
if self._startup is not None:
self._startup.configure_configuration(self._configuration, self._environment)
self._startup.configure_services(self._services, self._environment)
async def _build_async_startup(self):
for ex in self._startup_extensions:
extension = ex()
await extension.configure_configuration(self._configuration, self._environment)
await extension.configure_services(self._services, self._environment)
if self._startup is not None:
await self._startup.configure_configuration(self._configuration, self._environment)
await self._startup.configure_services(self._services, self._environment)
def build(self) -> ApplicationABC:
self._build_startup()
config = self._configuration
services = self._services.build_service_provider()
for ex in self._app_extensions:
extension = ex()
extension.run(config, services)
return self._app(config, services)
async def build_async(self) -> ApplicationABC:
await self._build_async_startup()
config = self._configuration
services = self._services.build_service_provider()
for ex in self._app_extensions:
extension = ex()
await extension.run(config, services)
return self._app(config, services)

View File

@@ -1,12 +1,12 @@
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from typing import Type from typing import Type
from cpl_core.application.application_abc import ApplicationABC from cpl.core.application.application_abc import ApplicationABC
from cpl_core.application.startup_abc import StartupABC from cpl.core.application.startup_abc import StartupABC
class ApplicationBuilderABC(ABC): class ApplicationBuilderABC(ABC):
r"""ABC for the :class:`cpl_core.application.application_builder.ApplicationBuilder`""" r"""ABC for the :class:`cpl.core.application.application_builder.ApplicationBuilder`"""
@abstractmethod @abstractmethod
def __init__(self, *args): def __init__(self, *args):
@@ -17,35 +17,31 @@ class ApplicationBuilderABC(ABC):
r"""Sets the custom startup class to use r"""Sets the custom startup class to use
Parameter: Parameter:
startup: Type[:class:`cpl_core.application.startup_abc.StartupABC`] startup: Type[:class:`cpl.core.application.startup_abc.StartupABC`]
Startup class to use Startup class to use
""" """
pass
@abstractmethod @abstractmethod
async def use_startup(self, startup: Type[StartupABC]): async def use_startup(self, startup: Type[StartupABC]):
r"""Sets the custom startup class to use async r"""Sets the custom startup class to use async
Parameter: Parameter:
startup: Type[:class:`cpl_core.application.startup_abc.StartupABC`] startup: Type[:class:`cpl.core.application.startup_abc.StartupABC`]
Startup class to use Startup class to use
""" """
pass
@abstractmethod @abstractmethod
def build(self) -> ApplicationABC: def build(self) -> ApplicationABC:
r"""Creates custom application object r"""Creates custom application object
Returns: Returns:
Object of :class:`cpl_core.application.application_abc.ApplicationABC` Object of :class:`cpl.core.application.application_abc.ApplicationABC`
""" """
pass
@abstractmethod @abstractmethod
async def build_async(self) -> ApplicationABC: async def build_async(self) -> ApplicationABC:
r"""Creates custom application object async r"""Creates custom application object async
Returns: Returns:
Object of :class:`cpl_core.application.application_abc.ApplicationABC` Object of :class:`cpl.core.application.application_abc.ApplicationABC`
""" """
pass

View File

@@ -1,7 +1,7 @@
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from cpl_core.configuration import ConfigurationABC from cpl.core.configuration import ConfigurationABC
from cpl_core.dependency_injection import ServiceProviderABC from cpl.core.dependency_injection import ServiceProviderABC
class ApplicationExtensionABC(ABC): class ApplicationExtensionABC(ABC):
@@ -12,7 +12,3 @@ class ApplicationExtensionABC(ABC):
@abstractmethod @abstractmethod
def run(self, config: ConfigurationABC, services: ServiceProviderABC): def run(self, config: ConfigurationABC, services: ServiceProviderABC):
pass pass
@abstractmethod
async def run(self, config: ConfigurationABC, services: ServiceProviderABC):
pass

View File

@@ -0,0 +1,14 @@
from abc import ABC, abstractmethod
from cpl.core.configuration import ConfigurationABC
from cpl.core.dependency_injection import ServiceProviderABC
class AsyncApplicationExtensionABC(ABC):
@abstractmethod
def __init__(self):
pass
@abstractmethod
async def run(self, config: ConfigurationABC, services: ServiceProviderABC):
pass

View File

@@ -0,0 +1,32 @@
from abc import ABC, abstractmethod
from cpl.core.configuration.configuration_abc import ConfigurationABC
from cpl.core.dependency_injection.service_collection_abc import ServiceCollectionABC
from cpl.core.dependency_injection.service_provider_abc import ServiceProviderABC
from cpl.core.environment.application_environment_abc import ApplicationEnvironmentABC
class AsyncStartupABC(ABC):
r"""ABC for the startup class"""
@abstractmethod
def __init__(self):
pass
@abstractmethod
async def configure_configuration(self, config: ConfigurationABC, env: ApplicationEnvironmentABC):
r"""Creates configuration of application
Parameter:
config: :class:`cpl.core.configuration.configuration_abc.ConfigurationABC`
env: :class:`cpl.core.environment.application_environment_abc`
"""
@abstractmethod
async def configure_services(self, service: ServiceCollectionABC, env: ApplicationEnvironmentABC):
r"""Creates service provider
Parameter:
services: :class:`cpl.core.dependency_injection.service_collection_abc`
env: :class:`cpl.core.environment.application_environment_abc`
"""

View File

@@ -0,0 +1,31 @@
from abc import ABC, abstractmethod
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 AsyncStartupExtensionABC(ABC):
r"""ABC for startup extension classes"""
@abstractmethod
def __init__(self):
pass
@abstractmethod
async def configure_configuration(self, config: ConfigurationABC, env: ApplicationEnvironmentABC):
r"""Creates configuration of application
Parameter:
config: :class:`cpl.core.configuration.configuration_abc.ConfigurationABC`
env: :class:`cpl.core.environment.application_environment_abc`
"""
@abstractmethod
async def configure_services(self, service: ServiceCollectionABC, env: ApplicationEnvironmentABC):
r"""Creates service provider
Parameter:
services: :class:`cpl.core.dependency_injection.service_collection_abc`
env: :class:`cpl.core.environment.application_environment_abc`
"""

View File

@@ -0,0 +1,32 @@
from abc import ABC, abstractmethod
from cpl.core.configuration.configuration_abc import ConfigurationABC
from cpl.core.dependency_injection.service_collection_abc import ServiceCollectionABC
from cpl.core.dependency_injection.service_provider_abc import ServiceProviderABC
from cpl.core.environment.application_environment_abc import ApplicationEnvironmentABC
class StartupABC(ABC):
r"""ABC for the startup class"""
@abstractmethod
def __init__(self):
pass
@abstractmethod
def configure_configuration(self, config: ConfigurationABC, env: ApplicationEnvironmentABC):
r"""Creates configuration of application
Parameter:
config: :class:`cpl.core.configuration.configuration_abc.ConfigurationABC`
env: :class:`cpl.core.environment.application_environment_abc`
"""
@abstractmethod
def configure_services(self, service: ServiceCollectionABC, env: ApplicationEnvironmentABC):
r"""Creates service provider
Parameter:
services: :class:`cpl.core.dependency_injection.service_collection_abc`
env: :class:`cpl.core.environment.application_environment_abc`
"""

View File

@@ -1,8 +1,8 @@
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from cpl_core.configuration.configuration_abc import ConfigurationABC from cpl.core.configuration.configuration_abc import ConfigurationABC
from cpl_core.dependency_injection.service_collection_abc import ServiceCollectionABC from cpl.core.dependency_injection.service_collection_abc import ServiceCollectionABC
from cpl_core.environment.application_environment_abc import ApplicationEnvironmentABC from cpl.core.environment.application_environment_abc import ApplicationEnvironmentABC
class StartupExtensionABC(ABC): class StartupExtensionABC(ABC):
@@ -17,17 +17,15 @@ class StartupExtensionABC(ABC):
r"""Creates configuration of application r"""Creates configuration of application
Parameter: Parameter:
config: :class:`cpl_core.configuration.configuration_abc.ConfigurationABC` config: :class:`cpl.core.configuration.configuration_abc.ConfigurationABC`
env: :class:`cpl_core.environment.application_environment_abc` env: :class:`cpl.core.environment.application_environment_abc`
""" """
pass
@abstractmethod @abstractmethod
def configure_services(self, service: ServiceCollectionABC, env: ApplicationEnvironmentABC): def configure_services(self, service: ServiceCollectionABC, env: ApplicationEnvironmentABC):
r"""Creates service provider r"""Creates service provider
Parameter: Parameter:
services: :class:`cpl_core.dependency_injection.service_collection_abc` services: :class:`cpl.core.dependency_injection.service_collection_abc`
env: :class:`cpl_core.environment.application_environment_abc` env: :class:`cpl.core.environment.application_environment_abc`
""" """
pass

View File

@@ -1,26 +1,3 @@
# -*- coding: utf-8 -*-
"""
cpl-core CPL core
~~~~~~~~~~~~~~~~~~~
CPL core package
:copyright: (c) 2020 - 2024 sh-edraft.de
:license: MIT, see LICENSE for more details.
"""
__title__ = "cpl_core.configuration"
__author__ = "Sven Heidemann"
__license__ = "MIT"
__copyright__ = "Copyright (c) 2020 - 2024 sh-edraft.de"
__version__ = "2024.6.0"
from collections import namedtuple
# imports:
from .argument_abc import ArgumentABC from .argument_abc import ArgumentABC
from .argument_builder import ArgumentBuilder from .argument_builder import ArgumentBuilder
from .argument_executable_abc import ArgumentExecutableABC from .argument_executable_abc import ArgumentExecutableABC
@@ -33,6 +10,3 @@ from .executable_argument import ExecutableArgument
from .flag_argument import FlagArgument from .flag_argument import FlagArgument
from .validator_abc import ValidatorABC from .validator_abc import ValidatorABC
from .variable_argument import VariableArgument from .variable_argument import VariableArgument
VersionInfo = namedtuple("VersionInfo", "major minor micro")
version_info = VersionInfo(major="2024", minor="6", micro="0")

View File

@@ -1,6 +1,6 @@
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from cpl_core.configuration.argument_type_enum import ArgumentTypeEnum from cpl.core.configuration.argument_type_enum import ArgumentTypeEnum
class ArgumentABC(ABC): class ArgumentABC(ABC):
@@ -19,7 +19,7 @@ class ArgumentABC(ABC):
token: :class:`str` token: :class:`str`
name: :class:`str` name: :class:`str`
aliases: list[:class:`str`] aliases: list[:class:`str`]
console_arguments: List[:class:`cpl_core.configuration.console_argument.ConsoleArgument`] console_arguments: List[:class:`cpl.core.configuration.console_argument.ConsoleArgument`]
""" """
self._token = token self._token = token
self._name = name self._name = name
@@ -55,9 +55,9 @@ class ArgumentABC(ABC):
Specifies the specific type of the argument Specifies the specific type of the argument
Returns: Returns:
self :class:`cpl_core.configuration.console_argument.ConsoleArgument` not created argument! self :class:`cpl.core.configuration.console_argument.ConsoleArgument` not created argument!
""" """
from cpl_core.configuration.argument_builder import ArgumentBuilder from cpl.core.configuration.argument_builder import ArgumentBuilder
argument = ArgumentBuilder.build_argument(arg_type, *args, *kwargs) argument = ArgumentBuilder.build_argument(arg_type, *args, *kwargs)
self._console_arguments.append(argument) self._console_arguments.append(argument)

View File

@@ -1,10 +1,10 @@
from typing import Union from typing import Union
from cpl_core.configuration.argument_type_enum import ArgumentTypeEnum from cpl.core.configuration.argument_type_enum import ArgumentTypeEnum
from cpl_core.configuration.executable_argument import ExecutableArgument from cpl.core.configuration.executable_argument import ExecutableArgument
from cpl_core.configuration.flag_argument import FlagArgument from cpl.core.configuration.flag_argument import FlagArgument
from cpl_core.configuration.variable_argument import VariableArgument from cpl.core.configuration.variable_argument import VariableArgument
from cpl_core.console import Console from cpl.core.console import Console
class ArgumentBuilder: class ArgumentBuilder:

View File

@@ -3,29 +3,27 @@ import os
import sys import sys
import traceback import traceback
from collections.abc import Callable from collections.abc import Callable
from typing import Union, Type, Optional from typing import Union, Optional
from cpl_core.configuration.argument_abc import ArgumentABC from cpl.core.configuration.argument_abc import ArgumentABC
from cpl_core.configuration.argument_builder import ArgumentBuilder from cpl.core.configuration.argument_builder import ArgumentBuilder
from cpl_core.configuration.argument_executable_abc import ArgumentExecutableABC from cpl.core.configuration.argument_type_enum import ArgumentTypeEnum
from cpl_core.configuration.argument_type_enum import ArgumentTypeEnum from cpl.core.configuration.configuration_abc import ConfigurationABC
from cpl_core.configuration.configuration_abc import ConfigurationABC from cpl.core.configuration.configuration_model_abc import ConfigurationModelABC
from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC from cpl.core.configuration.configuration_variable_name_enum import (
from cpl_core.configuration.configuration_variable_name_enum import (
ConfigurationVariableNameEnum, ConfigurationVariableNameEnum,
) )
from cpl_core.configuration.executable_argument import ExecutableArgument from cpl.core.configuration.executable_argument import ExecutableArgument
from cpl_core.configuration.flag_argument import FlagArgument from cpl.core.configuration.flag_argument import FlagArgument
from cpl_core.configuration.validator_abc import ValidatorABC from cpl.core.configuration.variable_argument import VariableArgument
from cpl_core.configuration.variable_argument import VariableArgument from cpl.core.console.console import Console
from cpl_core.console.console import Console from cpl.core.console.foreground_color_enum import ForegroundColorEnum
from cpl_core.console.foreground_color_enum import ForegroundColorEnum from cpl.core.dependency_injection.service_provider_abc import ServiceProviderABC
from cpl_core.dependency_injection.service_provider_abc import ServiceProviderABC from cpl.core.environment.application_environment import ApplicationEnvironment
from cpl_core.environment.application_environment import ApplicationEnvironment from cpl.core.environment.application_environment_abc import ApplicationEnvironmentABC
from cpl_core.environment.application_environment_abc import ApplicationEnvironmentABC from cpl.core.environment.environment_name_enum import EnvironmentNameEnum
from cpl_core.environment.environment_name_enum import EnvironmentNameEnum from cpl.core.typing import T, R
from cpl_core.type import T, R from cpl.core.utils.json_processor import JSONProcessor
from cpl_core.utils.json_processor import JSONProcessor
class Configuration(ConfigurationABC): class Configuration(ConfigurationABC):
@@ -64,7 +62,7 @@ class Configuration(ConfigurationABC):
return self._argument_types return self._argument_types
@staticmethod @staticmethod
def _print_info(name: str, message: str): def _print_info(message: str):
r"""Prints an info message r"""Prints an info message
Parameter: Parameter:
@@ -74,11 +72,11 @@ class Configuration(ConfigurationABC):
Info message Info message
""" """
Console.set_foreground_color(ForegroundColorEnum.green) Console.set_foreground_color(ForegroundColorEnum.green)
Console.write_line(f"[{name}] {message}") Console.write_line(f"[CONF] {message}")
Console.set_foreground_color(ForegroundColorEnum.default) Console.set_foreground_color(ForegroundColorEnum.default)
@staticmethod @staticmethod
def _print_warn(name: str, message: str): def _print_warn(message: str):
r"""Prints a warning r"""Prints a warning
Parameter: Parameter:
@@ -88,11 +86,11 @@ class Configuration(ConfigurationABC):
Warning message Warning message
""" """
Console.set_foreground_color(ForegroundColorEnum.yellow) Console.set_foreground_color(ForegroundColorEnum.yellow)
Console.write_line(f"[{name}] {message}") Console.write_line(f"[CONF] {message}")
Console.set_foreground_color(ForegroundColorEnum.default) Console.set_foreground_color(ForegroundColorEnum.default)
@staticmethod @staticmethod
def _print_error(name: str, message: str): def _print_error(message: str):
r"""Prints an error r"""Prints an error
Parameter: Parameter:
@@ -102,7 +100,7 @@ class Configuration(ConfigurationABC):
Error message Error message
""" """
Console.set_foreground_color(ForegroundColorEnum.red) Console.set_foreground_color(ForegroundColorEnum.red)
Console.write_line(f"[{name}] {message}") Console.write_line(f"[CONF] {message}")
Console.set_foreground_color(ForegroundColorEnum.default) Console.set_foreground_color(ForegroundColorEnum.default)
def _set_variable(self, name: str, value: any): def _set_variable(self, name: str, value: any):
@@ -144,40 +142,13 @@ class Configuration(ConfigurationABC):
# load json # load json
json_cfg = json.load(cfg) json_cfg = json.load(cfg)
if output: if output:
self._print_info(__name__, f"Loaded config file: {file}") self._print_info(f"Loaded config file: {file}")
return json_cfg return json_cfg
except Exception as e: except Exception as e:
self._print_error(__name__, f"Cannot load config file: {file}! -> {e}") self._print_error(f"Cannot load config file: {file}! -> {e}")
return {} return {}
def _handle_pre_or_post_executables(self, pre: bool, argument: ExecutableArgument, services: ServiceProviderABC):
script_type = "pre-" if pre else "post-"
from cpl_cli.configuration.workspace_settings import WorkspaceSettings
workspace: Optional[WorkspaceSettings] = self.get_configuration(WorkspaceSettings)
if workspace is None or len(workspace.scripts) == 0:
return
for script in workspace.scripts:
if script_type not in script and not script.startswith(script_type):
continue
# split in two ifs to prevent exception
if script.split(script_type)[1] != argument.name:
continue
from cpl_cli.command.custom_script_service import CustomScriptService
css: CustomScriptService = services.get_service(CustomScriptService)
if css is None:
continue
Console.write_line()
self._set_variable("ACTIVE_EXECUTABLE", script)
css.run(self._additional_arguments)
def _parse_arguments( def _parse_arguments(
self, self,
executables: list[ArgumentABC], executables: list[ArgumentABC],
@@ -266,7 +237,7 @@ class Configuration(ConfigurationABC):
if not os.path.isfile(file_path): if not os.path.isfile(file_path):
if optional is not True: if optional is not True:
if output: if output:
self._print_error(__name__, f"File not found: {file_path}") self._print_error(f"File not found: {file_path}")
sys.exit() sys.exit()
@@ -344,7 +315,7 @@ class Configuration(ConfigurationABC):
arg_list = sys.argv[1:] arg_list = sys.argv[1:]
executables: list[ExecutableArgument] = [] executables: list[ExecutableArgument] = []
self._parse_arguments(executables, arg_list, self._argument_types) self._parse_arguments(executables, arg_list, self._argument_types)
except Exception as e: except Exception:
Console.error("An error occurred while parsing arguments.", traceback.format_exc()) Console.error("An error occurred while parsing arguments.", traceback.format_exc())
sys.exit() sys.exit()
@@ -380,7 +351,7 @@ class Configuration(ConfigurationABC):
self._handle_pre_or_post_executables(False, exe, services) self._handle_pre_or_post_executables(False, exe, services)
prevent = exe.prevent_next_executable prevent = exe.prevent_next_executable
success = True success = True
except Exception as e: except Exception:
Console.error("An error occurred while executing arguments.", traceback.format_exc()) Console.error("An error occurred while executing arguments.", traceback.format_exc())
sys.exit() sys.exit()

View File

@@ -1,19 +1,17 @@
from abc import abstractmethod, ABC from abc import abstractmethod, ABC
from collections.abc import Callable from collections.abc import Callable
from typing import Type, Union, Optional from typing import Optional
from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC from cpl.core.configuration.argument_abc import ArgumentABC
from cpl_core.configuration.argument_abc import ArgumentABC from cpl.core.configuration.argument_type_enum import ArgumentTypeEnum
from cpl_core.configuration.argument_type_enum import ArgumentTypeEnum from cpl.core.environment.application_environment_abc import ApplicationEnvironmentABC
from cpl_core.environment.application_environment_abc import ApplicationEnvironmentABC from cpl.core.typing import T, R
from cpl_core.type import T, R
class ConfigurationABC(ABC): class ConfigurationABC(ABC):
@abstractmethod @abstractmethod
def __init__(self): def __init__(self):
r"""ABC for the :class:`cpl_core.configuration.configuration.Configuration`""" r"""ABC for the :class:`cpl.core.configuration.configuration.Configuration`"""
pass
@property @property
@abstractmethod @abstractmethod
@@ -48,17 +46,15 @@ class ConfigurationABC(ABC):
prefix: :class:`str` prefix: :class:`str`
Prefix of the variables Prefix of the variables
""" """
pass
@abstractmethod @abstractmethod
def add_console_argument(self, argument: ArgumentABC): def add_console_argument(self, argument: ArgumentABC):
r"""Adds console argument to known console arguments r"""Adds console argument to known console arguments
Parameter: Parameter:
argument: :class:`cpl_core.configuration.console_argument.ConsoleArgumentABC` argument: :class:`cpl.core.configuration.console_argument.ConsoleArgumentABC`
Specifies the console argument Specifies the console argument
""" """
pass
@abstractmethod @abstractmethod
def add_json_file(self, name: str, optional: bool = None, output: bool = True, path: str = None): def add_json_file(self, name: str, optional: bool = None, output: bool = True, path: str = None):
@@ -74,19 +70,17 @@ class ConfigurationABC(ABC):
path: :class:`str` path: :class:`str`
Path in which the file should be stored Path in which the file should be stored
""" """
pass
@abstractmethod @abstractmethod
def add_configuration(self, key_type: T, value: any): def add_configuration(self, key_type: T, value: any):
r"""Add configuration object r"""Add configuration object
Parameter: Parameter:
key_type: :class:`cpl_core.type.T` key_type: :class:`cpl.core.type.T`
Type of the value Type of the value
value: any value: any
Object of the value Object of the value
""" """
pass
@abstractmethod @abstractmethod
def create_console_argument( def create_console_argument(
@@ -105,13 +99,12 @@ class ConfigurationABC(ABC):
Specifies were the value begins Specifies were the value begins
is_value_token_optional :class:`bool` is_value_token_optional :class:`bool`
Specifies if values are optional Specifies if values are optional
runnable: :class:`cpl_core.configuration.console_argument.ConsoleArgumentABC` runnable: :class:`cpl.core.configuration.console_argument.ConsoleArgumentABC`
Specifies class to run when called if value is not None Specifies class to run when called if value is not None
Returns: Returns:
Object of :class:`cpl_core.configuration.console_argument.ConsoleArgumentABC` Object of :class:`cpl.core.configuration.console_argument.ConsoleArgumentABC`
""" """
pass
@abstractmethod @abstractmethod
def for_each_argument(self, call: Callable): def for_each_argument(self, call: Callable):
@@ -121,20 +114,18 @@ class ConfigurationABC(ABC):
call: :class:`Callable` call: :class:`Callable`
Call for each argument Call for each argument
""" """
pass
@abstractmethod @abstractmethod
def get_configuration(self, search_type: T) -> Optional[R]: def get_configuration(self, search_type: T) -> Optional[R]:
r"""Returns value from configuration by given type r"""Returns value from configuration by given type
Parameter: Parameter:
search_type: :class:`cpl_core.type.T` search_type: :class:`cpl.core.type.T`
Type to search for Type to search for
Returns: Returns:
Object of Union[:class:`str`, :class:`cpl_core.configuration.configuration_model_abc.ConfigurationModelABC`] Object of Union[:class:`str`, :class:`cpl.core.configuration.configuration_model_abc.ConfigurationModelABC`]
""" """
pass
@abstractmethod @abstractmethod
def parse_console_arguments(self, services: "ServiceProviderABC", error: bool = None) -> bool: def parse_console_arguments(self, services: "ServiceProviderABC", error: bool = None) -> bool:
@@ -147,4 +138,3 @@ class ConfigurationABC(ABC):
Returns: Returns:
Bool to specify if executables were executed or not. Bool to specify if executables were executed or not.
""" """
pass

View File

@@ -10,7 +10,6 @@ class ConfigurationModelABC(ABC):
@abstractmethod @abstractmethod
def __init__(self): def __init__(self):
r"""ABC for settings representation""" r"""ABC for settings representation"""
pass
@base_func @base_func
def from_dict(self, settings: dict): def from_dict(self, settings: dict):
@@ -20,4 +19,3 @@ class ConfigurationModelABC(ABC):
Parameter: Parameter:
settings: :class:`dict` settings: :class:`dict`
""" """
pass

View File

@@ -1,8 +1,8 @@
from typing import Type, Optional from typing import Type, Optional
from cpl_core.configuration.argument_executable_abc import ArgumentExecutableABC from cpl.core.configuration.argument_executable_abc import ArgumentExecutableABC
from cpl_core.configuration.argument_abc import ArgumentABC from cpl.core.configuration.argument_abc import ArgumentABC
from cpl_core.configuration.validator_abc import ValidatorABC from cpl.core.configuration.validator_abc import ValidatorABC
class ExecutableArgument(ArgumentABC): class ExecutableArgument(ArgumentABC):

View File

@@ -1,4 +1,4 @@
from cpl_core.configuration.argument_abc import ArgumentABC from cpl.core.configuration.argument_abc import ArgumentABC
class FlagArgument(ArgumentABC): class FlagArgument(ArgumentABC):

View File

@@ -1,4 +1,4 @@
from cpl_core.configuration.argument_abc import ArgumentABC from cpl.core.configuration.argument_abc import ArgumentABC
class VariableArgument(ArgumentABC): class VariableArgument(ArgumentABC):

View File

@@ -0,0 +1,5 @@
from .background_color_enum import BackgroundColorEnum
from .console import Console
from .console_call import ConsoleCall
from .foreground_color_enum import ForegroundColorEnum
from .spinner_thread import SpinnerThread

View File

@@ -9,14 +9,15 @@ import colorama
from tabulate import tabulate from tabulate import tabulate
from termcolor import colored from termcolor import colored
from cpl_core.console.background_color_enum import BackgroundColorEnum from cpl.core.console.background_color_enum import BackgroundColorEnum
from cpl_core.console.console_call import ConsoleCall from cpl.core.console.console_call import ConsoleCall
from cpl_core.console.foreground_color_enum import ForegroundColorEnum from cpl.core.console.foreground_color_enum import ForegroundColorEnum
from cpl_core.console.spinner_thread import SpinnerThread from cpl.core.console.spinner_thread import SpinnerThread
class Console: class Console:
r"""Useful functions for handling with input and output""" r"""Useful functions for handling with input and output"""
colorama.init() colorama.init()
_is_first_write = True _is_first_write = True
@@ -61,7 +62,7 @@ class Console:
r"""Sets the background color r"""Sets the background color
Parameter: Parameter:
color: Union[:class:`cpl_core.console.background_color_enum.BackgroundColorEnum`, :class:`str`] color: Union[:class:`cpl.core.console.background_color_enum.BackgroundColorEnum`, :class:`str`]
Background color of the console Background color of the console
""" """
if type(color) is str: if type(color) is str:
@@ -74,7 +75,7 @@ class Console:
r"""Sets the foreground color r"""Sets the foreground color
Parameter: Parameter:
color: Union[:class:`cpl_core.console.background_color_enum.BackgroundColorEnum`, :class:`str`] color: Union[:class:`cpl.core.console.background_color_enum.BackgroundColorEnum`, :class:`str`]
Foreground color of the console Foreground color of the console
""" """
if type(color) is str: if type(color) is str:
@@ -365,17 +366,17 @@ class Console:
Message or header of the selection Message or header of the selection
options: List[:class:`str`] options: List[:class:`str`]
Selectable options Selectable options
header_foreground_color: Union[:class:`str`, :class:`cpl_core.console.foreground_color_enum.ForegroundColorEnum`] header_foreground_color: Union[:class:`str`, :class:`cpl.core.console.foreground_color_enum.ForegroundColorEnum`]
Foreground color of the header Foreground color of the header
header_background_color: Union[:class:`str`, :class:`cpl_core.console.background_color_enum.BackgroundColorEnum`] header_background_color: Union[:class:`str`, :class:`cpl.core.console.background_color_enum.BackgroundColorEnum`]
Background color of the header Background color of the header
option_foreground_color: Union[:class:`str`, :class:`cpl_core.console.foreground_color_enum.ForegroundColorEnum`] option_foreground_color: Union[:class:`str`, :class:`cpl.core.console.foreground_color_enum.ForegroundColorEnum`]
Foreground color of the options Foreground color of the options
option_background_color: Union[:class:`str`, :class:`cpl_core.console.background_color_enum.BackgroundColorEnum`] option_background_color: Union[:class:`str`, :class:`cpl.core.console.background_color_enum.BackgroundColorEnum`]
Background color of the options Background color of the options
cursor_foreground_color: Union[:class:`str`, :class:`cpl_core.console.foreground_color_enum.ForegroundColorEnum`] cursor_foreground_color: Union[:class:`str`, :class:`cpl.core.console.foreground_color_enum.ForegroundColorEnum`]
Foreground color of the cursor Foreground color of the cursor
cursor_background_color: Union[:class:`str`, :class:`cpl_core.console.background_color_enum.BackgroundColorEnum`] cursor_background_color: Union[:class:`str`, :class:`cpl.core.console.background_color_enum.BackgroundColorEnum`]
Background color of the cursor Background color of the cursor
Returns: Returns:
@@ -429,13 +430,13 @@ class Console:
Function to call Function to call
args: :class:`list` args: :class:`list`
Arguments of the function Arguments of the function
text_foreground_color: Union[:class:`str`, :class:`cpl_core.console.foreground_color_enum.ForegroundColorEnum`] text_foreground_color: Union[:class:`str`, :class:`cpl.core.console.foreground_color_enum.ForegroundColorEnum`]
Foreground color of the text Foreground color of the text
spinner_foreground_color: Union[:class:`str`, :class:`cpl_core.console.foreground_color_enum.ForegroundColorEnum`] spinner_foreground_color: Union[:class:`str`, :class:`cpl.core.console.foreground_color_enum.ForegroundColorEnum`]
Foreground color of the spinner Foreground color of the spinner
text_background_color: Union[:class:`str`, :class:`cpl_core.console.background_color_enum.BackgroundColorEnum`] text_background_color: Union[:class:`str`, :class:`cpl.core.console.background_color_enum.BackgroundColorEnum`]
Background color of the text Background color of the text
spinner_background_color: Union[:class:`str`, :class:`cpl_core.console.background_color_enum.BackgroundColorEnum`] spinner_background_color: Union[:class:`str`, :class:`cpl.core.console.background_color_enum.BackgroundColorEnum`]
Background color of the spinner Background color of the spinner
kwargs: :class:`dict` kwargs: :class:`dict`
Keyword arguments of the call Keyword arguments of the call

View File

@@ -5,8 +5,8 @@ import time
from termcolor import colored from termcolor import colored
from cpl_core.console.background_color_enum import BackgroundColorEnum from cpl.core.console.background_color_enum import BackgroundColorEnum
from cpl_core.console.foreground_color_enum import ForegroundColorEnum from cpl.core.console.foreground_color_enum import ForegroundColorEnum
class SpinnerThread(threading.Thread): class SpinnerThread(threading.Thread):
@@ -15,9 +15,9 @@ class SpinnerThread(threading.Thread):
Parameter: Parameter:
msg_len: :class:`int` msg_len: :class:`int`
Length of the message Length of the message
foreground_color: :class:`cpl_core.console.foreground_color.ForegroundColorEnum` foreground_color: :class:`cpl.core.console.foreground_color.ForegroundColorEnum`
Foreground color of the spinner Foreground color of the spinner
background_color: :class:`cpl_core.console.background_color.BackgroundColorEnum` background_color: :class:`cpl.core.console.background_color.BackgroundColorEnum`
Background color of the spinner Background color of the spinner
""" """

View File

@@ -0,0 +1,3 @@
from .database_settings_name_enum import DatabaseSettingsNameEnum
from .database_settings import DatabaseSettings
from .table_abc import TableABC

View File

@@ -0,0 +1,2 @@
from .database_connection import DatabaseConnection
from .database_connection_abc import DatabaseConnectionABC

View File

@@ -4,9 +4,9 @@ import mysql.connector as sql
from mysql.connector.abstracts import MySQLConnectionAbstract from mysql.connector.abstracts import MySQLConnectionAbstract
from mysql.connector.cursor import MySQLCursorBuffered from mysql.connector.cursor import MySQLCursorBuffered
from cpl_core.database.connection.database_connection_abc import DatabaseConnectionABC from cpl.core.database.connection.database_connection_abc import DatabaseConnectionABC
from cpl_core.database.database_settings import DatabaseSettings from cpl.core.database.database_settings import DatabaseSettings
from cpl_core.utils.credential_manager import CredentialManager from cpl.core.utils.credential_manager import CredentialManager
class DatabaseConnection(DatabaseConnectionABC): class DatabaseConnection(DatabaseConnectionABC):

View File

@@ -1,12 +1,12 @@
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from cpl_core.database.database_settings import DatabaseSettings from cpl.core.database.database_settings import DatabaseSettings
from mysql.connector.abstracts import MySQLConnectionAbstract from mysql.connector.abstracts import MySQLConnectionAbstract
from mysql.connector.cursor import MySQLCursorBuffered from mysql.connector.cursor import MySQLCursorBuffered
class DatabaseConnectionABC(ABC): class DatabaseConnectionABC(ABC):
r"""ABC for the :class:`cpl_core.database.connection.database_connection.DatabaseConnection`""" r"""ABC for the :class:`cpl.core.database.connection.database_connection.DatabaseConnection`"""
@abstractmethod @abstractmethod
def __init__(self): def __init__(self):
@@ -30,4 +30,3 @@ class DatabaseConnectionABC(ABC):
connection_string: :class:`str` connection_string: :class:`str`
Database connection string, see: https://docs.sqlalchemy.org/en/14/core/engines.html Database connection string, see: https://docs.sqlalchemy.org/en/14/core/engines.html
""" """
pass

View File

@@ -0,0 +1,2 @@
from .database_context import DatabaseContext
from .database_context_abc import DatabaseContextABC

View File

@@ -1,12 +1,10 @@
from typing import Optional from typing import Optional
import mysql
from cpl_core.database.connection.database_connection import DatabaseConnection from cpl.core.database.connection.database_connection import DatabaseConnection
from cpl_core.database.connection.database_connection_abc import DatabaseConnectionABC from cpl.core.database.connection.database_connection_abc import DatabaseConnectionABC
from cpl_core.database.context.database_context_abc import DatabaseContextABC from cpl.core.database.context.database_context_abc import DatabaseContextABC
from cpl_core.database.database_settings import DatabaseSettings from cpl.core.database.database_settings import DatabaseSettings
from cpl_core.database.table_abc import TableABC
from mysql.connector.cursor import MySQLCursorBuffered from mysql.connector.cursor import MySQLCursorBuffered
@@ -14,7 +12,7 @@ class DatabaseContext(DatabaseContextABC):
r"""Representation of the database context r"""Representation of the database context
Parameter: Parameter:
database_settings: :class:`cpl_core.database.database_settings.DatabaseSettings` database_settings: :class:`cpl.core.database.database_settings.DatabaseSettings`
""" """
def __init__(self): def __init__(self):
@@ -31,7 +29,7 @@ class DatabaseContext(DatabaseContextABC):
def _ping_and_reconnect(self): def _ping_and_reconnect(self):
try: try:
self._db.server.ping(reconnect=True, attempts=3, delay=5) self._db.server.ping(reconnect=True, attempts=3, delay=5)
except Exception as err: except Exception:
# reconnect your cursor as you did in __init__ or wherever # reconnect your cursor as you did in __init__ or wherever
if self._settings is None: if self._settings is None:
raise Exception("Call DatabaseContext.connect first") raise Exception("Call DatabaseContext.connect first")

View File

@@ -1,11 +1,11 @@
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from cpl_core.database.database_settings import DatabaseSettings from cpl.core.database.database_settings import DatabaseSettings
from mysql.connector.cursor import MySQLCursorBuffered from mysql.connector.cursor import MySQLCursorBuffered
class DatabaseContextABC(ABC): class DatabaseContextABC(ABC):
r"""ABC for the :class:`cpl_core.database.context.database_context.DatabaseContext`""" r"""ABC for the :class:`cpl.core.database.context.database_context.DatabaseContext`"""
@abstractmethod @abstractmethod
def __init__(self, *args): def __init__(self, *args):
@@ -21,14 +21,12 @@ class DatabaseContextABC(ABC):
r"""Connects to a database by connection settings r"""Connects to a database by connection settings
Parameter: Parameter:
database_settings :class:`cpl_core.database.database_settings.DatabaseSettings` database_settings :class:`cpl.core.database.database_settings.DatabaseSettings`
""" """
pass
@abstractmethod @abstractmethod
def save_changes(self): def save_changes(self):
r"""Saves changes of the database""" r"""Saves changes of the database"""
pass
@abstractmethod @abstractmethod
def select(self, statement: str) -> list[tuple]: def select(self, statement: str) -> list[tuple]:
@@ -40,4 +38,3 @@ class DatabaseContextABC(ABC):
Returns: Returns:
list: Fetched list of selected elements list: Fetched list of selected elements
""" """
pass

View File

@@ -1,6 +1,6 @@
from typing import Optional from typing import Optional
from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC from cpl.core.configuration.configuration_model_abc import ConfigurationModelABC
class DatabaseSettings(ConfigurationModelABC): class DatabaseSettings(ConfigurationModelABC):

View File

@@ -0,0 +1,8 @@
from cpl.core.log import Logger
from cpl.core.typing import Source
class DBLogger(Logger):
def __init__(self, source: Source):
Logger.__init__(self, source, "db")

View File

@@ -0,0 +1,8 @@
from .scope import Scope
from .scope_abc import ScopeABC
from .service_collection import ServiceCollection
from .service_collection_abc import ServiceCollectionABC
from .service_descriptor import ServiceDescriptor
from .service_lifetime_enum import ServiceLifetimeEnum
from .service_provider import ServiceProvider
from .service_provider_abc import ServiceProviderABC

View File

@@ -1,6 +1,5 @@
from cpl_core.console.console import Console from cpl.core.dependency_injection.scope_abc import ScopeABC
from cpl_core.dependency_injection.scope_abc import ScopeABC from cpl.core.dependency_injection.service_provider_abc import ServiceProviderABC
from cpl_core.dependency_injection.service_provider_abc import ServiceProviderABC
class Scope(ScopeABC): class Scope(ScopeABC):

View File

@@ -2,7 +2,7 @@ from abc import ABC, abstractmethod
class ScopeABC(ABC): class ScopeABC(ABC):
r"""ABC for the class :class:`cpl_core.dependency_injection.scope.Scope`""" r"""ABC for the class :class:`cpl.core.dependency_injection.scope.Scope`"""
def __init__(self): def __init__(self):
pass pass
@@ -13,11 +13,9 @@ class ScopeABC(ABC):
r"""Returns to service provider of scope r"""Returns to service provider of scope
Returns: Returns:
Object of type :class:`cpl_core.dependency_injection.service_provider_abc.ServiceProviderABC` Object of type :class:`cpl.core.dependency_injection.service_provider_abc.ServiceProviderABC`
""" """
pass
@abstractmethod @abstractmethod
def dispose(self): def dispose(self):
r"""Sets service_provider to None""" r"""Sets service_provider to None"""
pass

View File

@@ -1,10 +1,10 @@
from cpl_core.dependency_injection.scope import Scope from cpl.core.dependency_injection.scope import Scope
from cpl_core.dependency_injection.scope_abc import ScopeABC from cpl.core.dependency_injection.scope_abc import ScopeABC
from cpl_core.dependency_injection.service_provider_abc import ServiceProviderABC from cpl.core.dependency_injection.service_provider_abc import ServiceProviderABC
class ScopeBuilder: class ScopeBuilder:
r"""Class to build :class:`cpl_core.dependency_injection.scope.Scope`""" r"""Class to build :class:`cpl.core.dependency_injection.scope.Scope`"""
def __init__(self, service_provider: ServiceProviderABC) -> None: def __init__(self, service_provider: ServiceProviderABC) -> None:
self._service_provider = service_provider self._service_provider = service_provider
@@ -13,6 +13,6 @@ class ScopeBuilder:
r"""Returns scope r"""Returns scope
Returns: Returns:
Object of type :class:`cpl_core.dependency_injection.scope.Scope` Object of type :class:`cpl.core.dependency_injection.scope.Scope`
""" """
return Scope(self._service_provider) return Scope(self._service_provider)

View File

@@ -1,17 +1,17 @@
from typing import Union, Type, Callable, Optional from typing import Union, Type, Callable, Optional
from cpl_core.configuration.configuration_abc import ConfigurationABC from cpl.core.configuration.configuration_abc import ConfigurationABC
from cpl_core.database.context.database_context_abc import DatabaseContextABC from cpl.core.database.context.database_context_abc import DatabaseContextABC
from cpl_core.database.database_settings import DatabaseSettings from cpl.core.database.database_settings import DatabaseSettings
from cpl_core.dependency_injection.service_collection_abc import ServiceCollectionABC from cpl.core.dependency_injection.service_collection_abc import ServiceCollectionABC
from cpl_core.dependency_injection.service_descriptor import ServiceDescriptor from cpl.core.dependency_injection.service_descriptor import ServiceDescriptor
from cpl_core.dependency_injection.service_lifetime_enum import ServiceLifetimeEnum from cpl.core.dependency_injection.service_lifetime_enum import ServiceLifetimeEnum
from cpl_core.dependency_injection.service_provider import ServiceProvider from cpl.core.dependency_injection.service_provider import ServiceProvider
from cpl_core.dependency_injection.service_provider_abc import ServiceProviderABC from cpl.core.dependency_injection.service_provider_abc import ServiceProviderABC
from cpl_core.logging.logger_abc import LoggerABC from cpl.core.log.logger import Logger
from cpl_core.logging.logger_service import Logger from cpl.core.log.logger_abc import LoggerABC
from cpl_core.pipes.pipe_abc import PipeABC from cpl.core.pipes.pipe_abc import PipeABC
from cpl_core.type import T from cpl.core.typing import T, Service
class ServiceCollection(ServiceCollectionABC): class ServiceCollection(ServiceCollectionABC):
@@ -53,7 +53,7 @@ class ServiceCollection(ServiceCollectionABC):
self._database_context.connect(db_settings) self._database_context.connect(db_settings)
def add_logging(self): def add_logging(self):
self.add_singleton(LoggerABC, Logger) self.add_transient(LoggerABC, Logger)
return self return self
def add_pipes(self): def add_pipes(self):
@@ -61,15 +61,15 @@ class ServiceCollection(ServiceCollectionABC):
self.add_transient(PipeABC, pipe) self.add_transient(PipeABC, pipe)
return self return self
def add_singleton(self, service_type: T, service: T = None): def add_singleton(self, service_type: T, service: Service = None):
self._add_descriptor_by_lifetime(service_type, ServiceLifetimeEnum.singleton, service) self._add_descriptor_by_lifetime(service_type, ServiceLifetimeEnum.singleton, service)
return self return self
def add_scoped(self, service_type: T, service: T = None): def add_scoped(self, service_type: T, service: Service = None):
self._add_descriptor_by_lifetime(service_type, ServiceLifetimeEnum.scoped, service) self._add_descriptor_by_lifetime(service_type, ServiceLifetimeEnum.scoped, service)
return self return self
def add_transient(self, service_type: T, service: T = None): def add_transient(self, service_type: T, service: Service = None):
self._add_descriptor_by_lifetime(service_type, ServiceLifetimeEnum.transient, service) self._add_descriptor_by_lifetime(service_type, ServiceLifetimeEnum.transient, service)
return self return self

View File

@@ -1,15 +1,14 @@
from abc import abstractmethod, ABC from abc import abstractmethod, ABC
from collections.abc import Callable
from typing import Type from typing import Type
from cpl_core.database.database_settings import DatabaseSettings from cpl.core.database.context.database_context_abc import DatabaseContextABC
from cpl_core.database.context.database_context_abc import DatabaseContextABC from cpl.core.database.database_settings import DatabaseSettings
from cpl_core.dependency_injection.service_provider_abc import ServiceProviderABC from cpl.core.dependency_injection.service_provider_abc import ServiceProviderABC
from cpl_core.type import T from cpl.core.typing import T, Source
class ServiceCollectionABC(ABC): class ServiceCollectionABC(ABC):
r"""ABC for the class :class:`cpl_core.dependency_injection.service_collection.ServiceCollection`""" r"""ABC for the class :class:`cpl.core.dependency_injection.service_collection.ServiceCollection`"""
@abstractmethod @abstractmethod
def __init__(self): def __init__(self):
@@ -20,30 +19,25 @@ class ServiceCollectionABC(ABC):
r"""Adds database context r"""Adds database context
Parameter: Parameter:
db_context: Type[:class:`cpl_core.database.context.database_context_abc.DatabaseContextABC`] db_context: Type[:class:`cpl.core.database.context.database_context_abc.DatabaseContextABC`]
Database context Database context
""" """
pass
@abstractmethod @abstractmethod
def add_logging(self): def add_logging(self):
r"""Adds the CPL internal logger""" r"""Adds the CPL internal logger"""
pass
@abstractmethod @abstractmethod
def add_pipes(self): def add_pipes(self):
r"""Adds the CPL internal pipes as transient""" r"""Adds the CPL internal pipes as transient"""
pass
def add_discord(self):
r"""Adds the CPL discord"""
raise NotImplementedError("You should install and use the cpl-discord package")
pass
def add_translation(self): def add_translation(self):
r"""Adds the CPL translation""" r"""Adds the CPL translation"""
raise NotImplementedError("You should install and use the cpl-translation package") raise NotImplementedError("You should install and use the cpl-translation package")
pass
def add_mail(self):
r"""Adds the CPL mail"""
raise NotImplementedError("You should install and use the cpl-mail package")
@abstractmethod @abstractmethod
def add_transient(self, service_type: T, service: T = None) -> "ServiceCollectionABC": def add_transient(self, service_type: T, service: T = None) -> "ServiceCollectionABC":
@@ -56,9 +50,8 @@ class ServiceCollectionABC(ABC):
Object of the service Object of the service
Returns: Returns:
self: :class:`cpl_core.dependency_injection.service_collection_abc.ServiceCollectionABC` self: :class:`cpl.core.dependency_injection.service_collection_abc.ServiceCollectionABC`
""" """
pass
@abstractmethod @abstractmethod
def add_scoped(self, service_type: T, service: T = None) -> "ServiceCollectionABC": def add_scoped(self, service_type: T, service: T = None) -> "ServiceCollectionABC":
@@ -71,9 +64,8 @@ class ServiceCollectionABC(ABC):
Object of the service Object of the service
Returns: Returns:
self: :class:`cpl_core.dependency_injection.service_collection_abc.ServiceCollectionABC` self: :class:`cpl.core.dependency_injection.service_collection_abc.ServiceCollectionABC`
""" """
pass
@abstractmethod @abstractmethod
def add_singleton(self, service_type: T, service: T = None) -> "ServiceCollectionABC": def add_singleton(self, service_type: T, service: T = None) -> "ServiceCollectionABC":
@@ -86,15 +78,13 @@ class ServiceCollectionABC(ABC):
Object of the service Object of the service
Returns: Returns:
self: :class:`cpl_core.dependency_injection.service_collection_abc.ServiceCollectionABC` self: :class:`cpl.core.dependency_injection.service_collection_abc.ServiceCollectionABC`
""" """
pass
@abstractmethod @abstractmethod
def build_service_provider(self) -> ServiceProviderABC: def build_service_provider(self) -> ServiceProviderABC:
r"""Creates instance of the service provider r"""Creates instance of the service provider
Returns: Returns:
Object of type :class:`cpl_core.dependency_injection.service_provider_abc.ServiceProviderABC` Object of type :class:`cpl.core.dependency_injection.service_provider_abc.ServiceProviderABC`
""" """
pass

View File

@@ -1,7 +1,6 @@
from typing import Union, Optional from typing import Union, Optional
from cpl_core.console import Console from cpl.core.dependency_injection.service_lifetime_enum import ServiceLifetimeEnum
from cpl_core.dependency_injection.service_lifetime_enum import ServiceLifetimeEnum
class ServiceDescriptor: class ServiceDescriptor:
@@ -10,7 +9,7 @@ class ServiceDescriptor:
Parameter: Parameter:
implementation: Union[:class:`type`, Optional[:class:`object`]] implementation: Union[:class:`type`, Optional[:class:`object`]]
Object or type of service Object or type of service
lifetime: :class:`cpl_core.dependency_injection.service_lifetime_enum.ServiceLifetimeEnum` lifetime: :class:`cpl.core.dependency_injection.service_lifetime_enum.ServiceLifetimeEnum`
Lifetime of the service Lifetime of the service
""" """

View File

@@ -3,16 +3,16 @@ import typing
from inspect import signature, Parameter, Signature from inspect import signature, Parameter, Signature
from typing import Optional from typing import Optional
from cpl_core.configuration.configuration_abc import ConfigurationABC from cpl.core.configuration.configuration_abc import ConfigurationABC
from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC from cpl.core.configuration.configuration_model_abc import ConfigurationModelABC
from cpl_core.database.context.database_context_abc import DatabaseContextABC from cpl.core.database.context.database_context_abc import DatabaseContextABC
from cpl_core.dependency_injection.scope_abc import ScopeABC from cpl.core.dependency_injection.scope_abc import ScopeABC
from cpl_core.dependency_injection.scope_builder import ScopeBuilder from cpl.core.dependency_injection.scope_builder import ScopeBuilder
from cpl_core.dependency_injection.service_descriptor import ServiceDescriptor from cpl.core.dependency_injection.service_descriptor import ServiceDescriptor
from cpl_core.dependency_injection.service_lifetime_enum import ServiceLifetimeEnum from cpl.core.dependency_injection.service_lifetime_enum import ServiceLifetimeEnum
from cpl_core.dependency_injection.service_provider_abc import ServiceProviderABC from cpl.core.dependency_injection.service_provider_abc import ServiceProviderABC
from cpl_core.environment.application_environment_abc import ApplicationEnvironmentABC from cpl.core.environment.application_environment_abc import ApplicationEnvironmentABC
from cpl_core.type import T, R from cpl.core.typing import T, R, Source
class ServiceProvider(ServiceProviderABC): class ServiceProvider(ServiceProviderABC):
@@ -20,11 +20,11 @@ class ServiceProvider(ServiceProviderABC):
Parameter Parameter
--------- ---------
service_descriptors: list[:class:`cpl_core.dependency_injection.service_descriptor.ServiceDescriptor`] service_descriptors: list[:class:`cpl.core.dependency_injection.service_descriptor.ServiceDescriptor`]
Descriptor of the service Descriptor of the service
config: :class:`cpl_core.configuration.configuration_abc.ConfigurationABC` config: :class:`cpl.core.configuration.configuration_abc.ConfigurationABC`
CPL Configuration CPL Configuration
db_context: Optional[:class:`cpl_core.database.context.database_context_abc.DatabaseContextABC`] db_context: Optional[:class:`cpl.core.database.context.database_context_abc.DatabaseContextABC`]
Database representation Database representation
""" """
@@ -48,7 +48,7 @@ class ServiceProvider(ServiceProviderABC):
return None return None
def _get_service(self, parameter: Parameter) -> Optional[object]: def _get_service(self, parameter: Parameter, origin_service_type: type = None) -> Optional[object]:
for descriptor in self._service_descriptors: for descriptor in self._service_descriptors:
if descriptor.service_type == parameter.annotation or issubclass( if descriptor.service_type == parameter.annotation or issubclass(
descriptor.service_type, parameter.annotation descriptor.service_type, parameter.annotation
@@ -56,7 +56,7 @@ class ServiceProvider(ServiceProviderABC):
if descriptor.implementation is not None: if descriptor.implementation is not None:
return descriptor.implementation return descriptor.implementation
implementation = self.build_service(descriptor.service_type) implementation = self._build_service(descriptor.service_type, origin_service_type=origin_service_type)
if descriptor.lifetime == ServiceLifetimeEnum.singleton: if descriptor.lifetime == ServiceLifetimeEnum.singleton:
descriptor.implementation = implementation descriptor.implementation = implementation
@@ -64,7 +64,7 @@ class ServiceProvider(ServiceProviderABC):
# raise Exception(f'Service {parameter.annotation} not found') # raise Exception(f'Service {parameter.annotation} not found')
def _get_services(self, t: type, *args, **kwargs) -> list[Optional[object]]: def _get_services(self, t: type, *args, service_type: type = None, **kwargs) -> list[Optional[object]]:
implementations = [] implementations = []
for descriptor in self._service_descriptors: for descriptor in self._service_descriptors:
if descriptor.service_type == t or issubclass(descriptor.service_type, t): if descriptor.service_type == t or issubclass(descriptor.service_type, t):
@@ -72,7 +72,7 @@ class ServiceProvider(ServiceProviderABC):
implementations.append(descriptor.implementation) implementations.append(descriptor.implementation)
continue continue
implementation = self.build_service(descriptor.service_type, *args, **kwargs) implementation = self._build_service(descriptor.service_type, *args, service_type, **kwargs)
if descriptor.lifetime == ServiceLifetimeEnum.singleton: if descriptor.lifetime == ServiceLifetimeEnum.singleton:
descriptor.implementation = implementation descriptor.implementation = implementation
@@ -80,13 +80,16 @@ class ServiceProvider(ServiceProviderABC):
return implementations return implementations
def build_by_signature(self, sig: Signature) -> list[R]: def _build_by_signature(self, sig: Signature, origin_service_type: type) -> list[R]:
params = [] params = []
for param in sig.parameters.items(): for param in sig.parameters.items():
parameter = param[1] parameter = param[1]
if parameter.name != "self" and parameter.annotation != Parameter.empty: if parameter.name != "self" and parameter.annotation != Parameter.empty:
if typing.get_origin(parameter.annotation) == list: if typing.get_origin(parameter.annotation) == list:
params.append(self._get_services(typing.get_args(parameter.annotation)[0])) params.append(self._get_services(typing.get_args(parameter.annotation)[0], origin_service_type))
elif parameter.annotation == Source:
params.append(origin_service_type.__name__)
elif issubclass(parameter.annotation, ServiceProviderABC): elif issubclass(parameter.annotation, ServiceProviderABC):
params.append(self) params.append(self)
@@ -104,11 +107,15 @@ class ServiceProvider(ServiceProviderABC):
params.append(self._configuration) params.append(self._configuration)
else: else:
params.append(self._get_service(parameter)) params.append(self._get_service(parameter, origin_service_type))
return params return params
def build_service(self, service_type: type, *args, **kwargs) -> object: def _build_service(self, service_type: type, *args, origin_service_type: type = None, **kwargs) -> object:
if origin_service_type is None:
origin_service_type = service_type
for descriptor in self._service_descriptors: for descriptor in self._service_descriptors:
if descriptor.service_type == service_type or issubclass(descriptor.service_type, service_type): if descriptor.service_type == service_type or issubclass(descriptor.service_type, service_type):
if descriptor.implementation is not None: if descriptor.implementation is not None:
@@ -119,7 +126,7 @@ class ServiceProvider(ServiceProviderABC):
break break
sig = signature(service_type.__init__) sig = signature(service_type.__init__)
params = self.build_by_signature(sig) params = self._build_by_signature(sig, origin_service_type)
return service_type(*params, *args, **kwargs) return service_type(*params, *args, **kwargs)
@@ -147,7 +154,7 @@ class ServiceProvider(ServiceProviderABC):
if result.implementation is not None: if result.implementation is not None:
return result.implementation return result.implementation
implementation = self.build_service(service_type, *args, **kwargs) implementation = self._build_service(service_type, *args, **kwargs)
if ( if (
result.lifetime == ServiceLifetimeEnum.singleton result.lifetime == ServiceLifetimeEnum.singleton
or result.lifetime == ServiceLifetimeEnum.scoped or result.lifetime == ServiceLifetimeEnum.scoped

View File

@@ -1,14 +1,14 @@
import functools import functools
from abc import abstractmethod, ABC from abc import abstractmethod, ABC
from inspect import Signature, signature from inspect import Signature, signature
from typing import Optional, Type from typing import Optional
from cpl_core.dependency_injection.scope_abc import ScopeABC from cpl.core.dependency_injection.scope_abc import ScopeABC
from cpl_core.type import T, R from cpl.core.typing import T, R
class ServiceProviderABC(ABC): class ServiceProviderABC(ABC):
r"""ABC for the class :class:`cpl_core.dependency_injection.service_provider.ServiceProvider`""" r"""ABC for the class :class:`cpl.core.dependency_injection.service_provider.ServiceProvider`"""
_provider: Optional["ServiceProviderABC"] = None _provider: Optional["ServiceProviderABC"] = None
@@ -21,11 +21,11 @@ class ServiceProviderABC(ABC):
cls._provider = provider cls._provider = provider
@abstractmethod @abstractmethod
def build_by_signature(self, sig: Signature) -> list[R]: def _build_by_signature(self, sig: Signature, origin_service_type: type) -> list[R]:
pass pass
@abstractmethod @abstractmethod
def build_service(self, service_type: type, *args, **kwargs) -> object: def _build_service(self, service_type: type, *args, **kwargs) -> object:
r"""Creates instance of given type r"""Creates instance of given type
Parameter Parameter
@@ -37,7 +37,6 @@ class ServiceProviderABC(ABC):
------- -------
Object of the given type Object of the given type
""" """
pass
@abstractmethod @abstractmethod
def set_scope(self, scope: ScopeABC): def set_scope(self, scope: ScopeABC):
@@ -45,10 +44,9 @@ class ServiceProviderABC(ABC):
Parameter Parameter
--------- ---------
Object of type :class:`cpl_core.dependency_injection.scope_abc.ScopeABC` Object of type :class:`cpl.core.dependency_injection.scope_abc.ScopeABC`
Service scope Service scope
""" """
pass
@abstractmethod @abstractmethod
def create_scope(self) -> ScopeABC: def create_scope(self) -> ScopeABC:
@@ -56,9 +54,8 @@ class ServiceProviderABC(ABC):
Returns Returns
------- -------
Object of type :class:`cpl_core.dependency_injection.scope_abc.ScopeABC` Object of type :class:`cpl.core.dependency_injection.scope_abc.ScopeABC`
""" """
pass
@abstractmethod @abstractmethod
def get_service(self, instance_type: T, *args, **kwargs) -> Optional[R]: def get_service(self, instance_type: T, *args, **kwargs) -> Optional[R]:
@@ -66,14 +63,13 @@ class ServiceProviderABC(ABC):
Parameter Parameter
--------- ---------
instance_type: :class:`cpl_core.type.T` instance_type: :class:`cpl.core.type.T`
The type of the searched instance The type of the searched instance
Returns Returns
------- -------
Object of type Optional[:class:`cpl_core.type.T`] Object of type Optional[:class:`cpl.core.type.T`]
""" """
pass
@abstractmethod @abstractmethod
def get_services(self, service_type: T, *args, **kwargs) -> list[Optional[R]]: def get_services(self, service_type: T, *args, **kwargs) -> list[Optional[R]]:
@@ -81,14 +77,13 @@ class ServiceProviderABC(ABC):
Parameter Parameter
--------- ---------
service_type: :class:`cpl_core.type.T` service_type: :class:`cpl.core.type.T`
The type of the searched instance The type of the searched instance
Returns Returns
------- -------
Object of type list[Optional[:class:`cpl_core.type.T`] Object of type list[Optional[:class:`cpl.core.type.T`]
""" """
pass
@classmethod @classmethod
def inject(cls, f=None): def inject(cls, f=None):
@@ -110,7 +105,7 @@ class ServiceProviderABC(ABC):
if cls._provider is None: if cls._provider is None:
raise Exception(f"{cls.__name__} not build!") raise Exception(f"{cls.__name__} not build!")
injection = [x for x in cls._provider.build_by_signature(signature(f)) if x is not None] injection = [x for x in cls._provider._build_by_signature(signature(f)) if x is not None]
return f(*args, *injection, **kwargs) return f(*args, *injection, **kwargs)
return inner return inner

View File

@@ -0,0 +1,3 @@
from .application_environment_abc import ApplicationEnvironmentABC
from .environment_name_enum import EnvironmentNameEnum
from .application_environment import ApplicationEnvironment

View File

@@ -3,15 +3,15 @@ from datetime import datetime
from socket import gethostname from socket import gethostname
from typing import Optional from typing import Optional
from cpl_core.environment.application_environment_abc import ApplicationEnvironmentABC from cpl.core.environment.application_environment_abc import ApplicationEnvironmentABC
from cpl_core.environment.environment_name_enum import EnvironmentNameEnum from cpl.core.environment.environment_name_enum import EnvironmentNameEnum
class ApplicationEnvironment(ApplicationEnvironmentABC): class ApplicationEnvironment(ApplicationEnvironmentABC):
r"""Represents environment of the application r"""Represents environment of the application
Parameter: Parameter:
name: :class:`cpl_core.environment.environment_name_enum.EnvironmentNameEnum` name: :class:`cpl.core.environment.environment_name_enum.EnvironmentNameEnum`
""" """
def __init__(self, name: EnvironmentNameEnum = EnvironmentNameEnum.production): def __init__(self, name: EnvironmentNameEnum = EnvironmentNameEnum.production):

View File

@@ -3,7 +3,7 @@ from datetime import datetime
class ApplicationEnvironmentABC(ABC): class ApplicationEnvironmentABC(ABC):
r"""ABC of the class :class:`cpl_core.environment.application_environment.ApplicationEnvironment`""" r"""ABC of the class :class:`cpl.core.environment.application_environment.ApplicationEnvironment`"""
@abstractmethod @abstractmethod
def __init__(self): def __init__(self):
@@ -87,7 +87,6 @@ class ApplicationEnvironmentABC(ABC):
runtime_directory: :class:`str` runtime_directory: :class:`str`
Path of the runtime directory Path of the runtime directory
""" """
pass
@abstractmethod @abstractmethod
def set_working_directory(self, working_directory: str): def set_working_directory(self, working_directory: str):
@@ -97,4 +96,3 @@ class ApplicationEnvironmentABC(ABC):
working_directory: :class:`str` working_directory: :class:`str`
Path of the current working directory Path of the current working directory
""" """
pass

View File

@@ -0,0 +1,32 @@
import os
from typing import Optional, Type
from cpl.core.typing import T
from cpl.core.utils.get_value import get_value
class Environment:
_environment = "production"
@classmethod
def get_environment(cls):
return cls._environment
@classmethod
def set_environment(cls, environment: str):
if environment not in ["development", "staging", "production"]:
raise ValueError("Invalid environment")
Environment._environment = environment
@staticmethod
def get(key: str, cast_type: Type[T], default: Optional[T] = None) -> Optional[T]:
"""
Get an environment variable and cast it to a specified type.
:param str key: The name of the environment variable.
:param Type[T] cast_type: A callable to cast the variable's value.
:param Optional[T] default: The default value to return if the variable is not found. Defaults to None.The default value to return if the variable is not found. Defaults to None.
:return: The casted value, or None if the variable is not found.
:rtype: Optional[T]
"""
return get_value(dict(os.environ), key, cast_type, default)

View File

@@ -0,0 +1,4 @@
from .logger import Logger
from .logger_abc import LoggerABC
from .log_level_enum import LogLevelEnum
from .logging_settings import LogSettings

View File

@@ -0,0 +1,94 @@
import multiprocessing
import os
from datetime import datetime
from typing import Self
from cpl.core.console import Console
from cpl.core.log.log_level_enum import LogLevelEnum
class LogWriter:
_instance = None
# ANSI color codes for different log levels
_COLORS = {
LogLevelEnum.trace: "\033[37m", # Light Gray
LogLevelEnum.debug: "\033[94m", # Blue
LogLevelEnum.info: "\033[92m", # Green
LogLevelEnum.warning: "\033[93m", # Yellow
LogLevelEnum.error: "\033[91m", # Red
LogLevelEnum.fatal: "\033[95m", # Magenta
}
def __init__(self, file_prefix: str, level: LogLevelEnum = LogLevelEnum.info):
self._file_prefix = file_prefix
self._level = level
self._queue = multiprocessing.Queue()
self._process = multiprocessing.Process(target=self._log_worker, daemon=True)
self._create_log_dir()
self._process.start()
@property
def level(self) -> LogLevelEnum:
return self._level
@level.setter
def level(self, value: LogLevelEnum):
assert isinstance(value, LogLevelEnum), "Log level must be an instance of LogLevelEnum"
self._level = value
@classmethod
def get_instance(cls, file_prefix: str, level: LogLevelEnum = LogLevelEnum.info) -> Self:
if cls._instance is None:
cls._instance = LogWriter(file_prefix, level)
return cls._instance
@staticmethod
def _create_log_dir():
if os.path.exists("logs"):
return
os.makedirs("logs")
def _log_worker(self):
"""Worker process that writes log messages from the queue to the file."""
while True:
content = self._queue.get()
if content is None: # Shutdown signal
break
self._write_log_to_file(content)
Console.write_line(
f"{self._COLORS.get(self._level, '\033[0m')}{content}\033[0m"
)
@property
def log_file(self):
return f"logs/{self._file_prefix}_{datetime.now().strftime('%Y-%m-%d')}.log"
def _ensure_file_size(self):
log_file = self.log_file
if not os.path.exists(log_file) or os.path.getsize(log_file) <= 0.5 * 1024 * 1024:
return
# if exists and size is greater than 300MB, create a new file
os.rename(
log_file,
f"{log_file.split('.log')[0]}_{datetime.now().strftime('%H-%M-%S')}.log",
)
def _write_log_to_file(self, content: str):
self._ensure_file_size()
with open(self.log_file, "a") as log_file:
log_file.write(content + "\n")
log_file.close()
def log(self, content: str):
"""Enqueue log message without blocking main app."""
self._queue.put(content)
def close(self):
"""Gracefully stop the logging process."""
self._queue.put(None)
self._process.join()

View File

@@ -0,0 +1,11 @@
from enum import Enum
class LogLevelEnum(Enum):
off = "OFF" # Nothing
trace = "TRC" # Detailed app information's
debug = "DEB" # Detailed app state
info = "INF" # Normal information's
warning = "WAR" # Error that can later be fatal
error = "ERR" # Non fatal error
fatal = "FAT" # Error that cause exit

View File

@@ -0,0 +1,78 @@
import os
import traceback
from datetime import datetime
from cpl.core.console import Console
from cpl.core.log._log_writer import LogWriter
from cpl.core.log.log_level_enum import LogLevelEnum
from cpl.core.log.logger_abc import LoggerABC
from cpl.core.typing import Messages, Source
class Logger(LoggerABC):
_level = LogLevelEnum.info
_levels = [x for x in LogLevelEnum]
def __init__(self, source: Source, file_prefix: str = None):
LoggerABC.__init__(self)
assert source is not None and source != "", "Source cannot be None or empty"
self._source = source
if file_prefix is None:
file_prefix = "app"
self._file_prefix = file_prefix
self._writer = LogWriter.get_instance(self._file_prefix)
@classmethod
def set_level(cls, level: LogLevelEnum):
if level in cls._levels:
cls._level = level
else:
raise ValueError(f"Invalid log level: {level}")
def _log(self, level: LogLevelEnum, *messages: Messages):
try:
if self._levels.index(level) < self._levels.index(self._level):
return
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f")
formatted_message = self._format_message(level.value, timestamp, *messages)
self._writer.log(formatted_message)
except Exception as e:
print(f"Error while logging: {e} -> {traceback.format_exc()}")
def _format_message(self, level: str, timestamp, *messages: Messages) -> str:
if isinstance(messages, tuple):
messages = list(messages)
if not isinstance(messages, list):
messages = [messages]
messages = [str(message) for message in messages if message is not None]
return f"<{timestamp}> [{level.upper():^3}] [{self._file_prefix}] - [{self._source}]: {' '.join(messages)}"
def header(self, string: str):
self._log(LogLevelEnum.info, string)
def trace(self, *messages: Messages):
self._log(LogLevelEnum.trace, *messages)
def debug(self, *messages: Messages):
self._log(LogLevelEnum.debug, *messages)
def info(self, *messages: Messages):
self._log(LogLevelEnum.info, *messages)
def warning(self, *messages: Messages):
self._log(LogLevelEnum.warning, *messages)
def error(self, message, e: Exception = None):
self._log(LogLevelEnum.error, message, f"{e} -> {traceback.format_exc()}" if e else None)
def fatal(self, message, e: Exception = None, prevent_quit: bool = False):
self._log(LogLevelEnum.fatal, message, f"{e} -> {traceback.format_exc()}" if e else None)
if not prevent_quit:
exit(-1)

View File

@@ -1,12 +1,18 @@
from abc import abstractmethod, ABC from abc import abstractmethod, ABC
from cpl.core.typing import Messages
class LoggerABC(ABC): class LoggerABC(ABC):
r"""ABC for :class:`cpl_core.logging.logger_service.Logger`""" r"""ABC for :class:`cpl.core.log.logger_service.Logger`"""
@abstractmethod @abstractmethod
def __init__(self): def set_level(self, level: str):
ABC.__init__(self) pass
@abstractmethod
def _format_message(self, level: str, timestamp, *messages: Messages) -> str:
pass
@abstractmethod @abstractmethod
def header(self, string: str): def header(self, string: str):
@@ -16,10 +22,9 @@ class LoggerABC(ABC):
string: :class:`str` string: :class:`str`
String to write as header String to write as header
""" """
pass
@abstractmethod @abstractmethod
def trace(self, name: str, message: str): def trace(self, *messages: Messages):
r"""Writes a trace message r"""Writes a trace message
Parameter: Parameter:
@@ -28,10 +33,9 @@ class LoggerABC(ABC):
message: :class:`str` message: :class:`str`
Message string Message string
""" """
pass
@abstractmethod @abstractmethod
def debug(self, name: str, message: str): def debug(self, *messages: Messages):
r"""Writes a debug message r"""Writes a debug message
Parameter: Parameter:
@@ -40,10 +44,9 @@ class LoggerABC(ABC):
message: :class:`str` message: :class:`str`
Message string Message string
""" """
pass
@abstractmethod @abstractmethod
def info(self, name: str, message: str): def info(self, *messages: Messages):
r"""Writes an information r"""Writes an information
Parameter: Parameter:
@@ -52,10 +55,9 @@ class LoggerABC(ABC):
message: :class:`str` message: :class:`str`
Message string Message string
""" """
pass
@abstractmethod @abstractmethod
def warn(self, name: str, message: str): def warning(self, *messages: Messages):
r"""Writes an warning r"""Writes an warning
Parameter: Parameter:
@@ -64,10 +66,9 @@ class LoggerABC(ABC):
message: :class:`str` message: :class:`str`
Message string Message string
""" """
pass
@abstractmethod @abstractmethod
def error(self, name: str, message: str, ex: Exception = None): def error(self, messages: str, e: Exception = None):
r"""Writes an error r"""Writes an error
Parameter: Parameter:
@@ -78,10 +79,9 @@ class LoggerABC(ABC):
ex: :class:`Exception` ex: :class:`Exception`
Thrown exception Thrown exception
""" """
pass
@abstractmethod @abstractmethod
def fatal(self, name: str, message: str, ex: Exception = None): def fatal(self, messages: str, e: Exception = None):
r"""Writes an error and ends the program r"""Writes an error and ends the program
Parameter: Parameter:
@@ -92,4 +92,3 @@ class LoggerABC(ABC):
ex: :class:`Exception` ex: :class:`Exception`
Thrown exception Thrown exception
""" """
pass

View File

@@ -1,28 +1,24 @@
import traceback
from typing import Optional from typing import Optional
from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC from cpl.core.configuration.configuration_model_abc import ConfigurationModelABC
from cpl_core.console.console import Console from cpl.core.log.log_level_enum import LogLevelEnum
from cpl_core.console.foreground_color_enum import ForegroundColorEnum
from cpl_core.logging.logging_level_enum import LoggingLevelEnum
from cpl_core.logging.logging_settings_name_enum import LoggingSettingsNameEnum
class LoggingSettings(ConfigurationModelABC): class LogSettings(ConfigurationModelABC):
r"""Representation of logging settings""" r"""Representation of logging settings"""
def __init__( def __init__(
self, self,
path: str = None, path: str = None,
filename: str = None, filename: str = None,
console_log_level: LoggingLevelEnum = None, console_log_level: LogLevelEnum = None,
file_log_level: LoggingLevelEnum = None, file_log_level: LogLevelEnum = None,
): ):
ConfigurationModelABC.__init__(self) ConfigurationModelABC.__init__(self)
self._path: Optional[str] = path self._path: Optional[str] = path
self._filename: Optional[str] = filename self._filename: Optional[str] = filename
self._console: Optional[LoggingLevelEnum] = console_log_level self._console: Optional[LogLevelEnum] = console_log_level
self._level: Optional[LoggingLevelEnum] = file_log_level self._level: Optional[LogLevelEnum] = file_log_level
@property @property
def path(self) -> str: def path(self) -> str:
@@ -41,17 +37,17 @@ class LoggingSettings(ConfigurationModelABC):
self._filename = filename self._filename = filename
@property @property
def console(self) -> LoggingLevelEnum: def console(self) -> LogLevelEnum:
return self._console return self._console
@console.setter @console.setter
def console(self, console: LoggingLevelEnum) -> None: def console(self, console: LogLevelEnum) -> None:
self._console = console self._console = console
@property @property
def level(self) -> LoggingLevelEnum: def level(self) -> LogLevelEnum:
return self._level return self._level
@level.setter @level.setter
def level(self, level: LoggingLevelEnum) -> None: def level(self, level: LogLevelEnum) -> None:
self._level = level self._level = level

View File

@@ -0,0 +1,3 @@
from .bool_pipe import BoolPipe
from .ip_address_pipe import IPAddressPipe
from .pipe_abc import PipeABC

View File

@@ -1,4 +1,4 @@
from cpl_core.pipes.pipe_abc import PipeABC from cpl.core.pipes.pipe_abc import PipeABC
class BoolPipe(PipeABC): class BoolPipe(PipeABC):

View File

@@ -1,4 +1,4 @@
from cpl_core.pipes.pipe_abc import PipeABC from cpl.core.pipes.pipe_abc import PipeABC
class IPAddressPipe(PipeABC): class IPAddressPipe(PipeABC):

View File

@@ -1,5 +1,5 @@
from cpl_cli.configuration import VersionSettingsNameEnum from cpl_cli.configuration import VersionSettingsNameEnum
from cpl_core.pipes.pipe_abc import PipeABC from cpl.core.pipes.pipe_abc import PipeABC
class VersionPipe(PipeABC): class VersionPipe(PipeABC):

View File

@@ -0,0 +1,2 @@
from .time_format_settings import TimeFormatSettings
from .time_format_settings_names_enum import TimeFormatSettingsNamesEnum

View File

@@ -1,10 +1,6 @@
import traceback
from typing import Optional from typing import Optional
from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC from cpl.core.configuration.configuration_model_abc import ConfigurationModelABC
from cpl_core.console.console import Console
from cpl_core.console.foreground_color_enum import ForegroundColorEnum
from cpl_core.time.time_format_settings_names_enum import TimeFormatSettingsNamesEnum
class TimeFormatSettings(ConfigurationModelABC): class TimeFormatSettings(ConfigurationModelABC):

View File

@@ -0,0 +1,9 @@
from typing import TypeVar, Any
T = TypeVar("T")
R = TypeVar("R")
Service = TypeVar("Service")
Source = TypeVar("Source")
Messages = list[Any] | Any

View File

@@ -0,0 +1,3 @@
from .credential_manager import CredentialManager
from .string import String
from .pip import Pip

View File

@@ -0,0 +1,63 @@
from typing import Type, Optional
from cpl.core.typing import T
def get_value(
source: dict,
key: str,
cast_type: Type[T],
default: Optional[T] = None,
list_delimiter: str = ",",
) -> Optional[T]:
"""
Get value from source dictionary and cast it to a specified type.
:param dict source: The source dictionary.
:param str key: The name of the environment variable.
:param Type[T] cast_type: A callable to cast the variable's value.
:param Optional[T] default: The default value to return if the variable is not found. Defaults to None.
:param str list_delimiter: The delimiter to split the value into a list. Defaults to ",".
:return: The casted value, or None if the key is not found.
:rtype: Optional[T]
"""
if key not in source:
return default
value = source[key]
if isinstance(
value,
cast_type if not hasattr(cast_type, "__origin__") else cast_type.__origin__,
):
# Handle list[int] case explicitly
if hasattr(cast_type, "__origin__") and cast_type.__origin__ == list:
subtype = cast_type.__args__[0] if hasattr(cast_type, "__args__") else None
if subtype is not None:
return [subtype(item) for item in value]
return value
try:
if cast_type == bool:
return value.lower() in ["true", "1"]
if (
cast_type if not hasattr(cast_type, "__origin__") else cast_type.__origin__
) == list:
if (
not (value.startswith("[") and value.endswith("]"))
and list_delimiter not in value
):
raise ValueError(
"List values must be enclosed in square brackets or use a delimiter."
)
if value.startswith("[") and value.endswith("]"):
value = value[1:-1]
value = value.split(list_delimiter)
subtype = cast_type.__args__[0] if hasattr(cast_type, "__args__") else None
return [subtype(item) if subtype is not None else item for item in value]
return cast_type(value)
except (ValueError, TypeError):
return default

View File

@@ -1,7 +1,7 @@
import enum import enum
from inspect import signature, Parameter from inspect import signature, Parameter
from cpl_core.utils import String from cpl.core.utils import String
class JSONProcessor: class JSONProcessor:

View File

@@ -4,11 +4,10 @@ import sys
from contextlib import suppress from contextlib import suppress
from typing import Optional from typing import Optional
from cpl_core.console import Console
class Pip: class Pip:
r"""Executes pip commands""" r"""Executes pip commands"""
_executable = sys.executable _executable = sys.executable
_env = os.environ _env = os.environ

View File

@@ -0,0 +1,29 @@
[build-system]
requires = ["setuptools>=70.1.0", "wheel>=0.43.0"]
build-backend = "setuptools.build_meta"
[project]
name = "cpl-core"
version = "2024.7.0"
description = "CPL core"
readme = "CPL core package"
requires-python = ">=3.12"
license = "MIT"
authors = [
{ name = "Sven Heidemann", email = "sven.heidemann@sh-edraft.de" }
]
keywords = ["cpl", "core", "backend", "shared", "library"]
dynamic = ["dependencies", "optional-dependencies"]
[project.urls]
Homepage = "https://www.sh-edraft.de"
[tool.setuptools.packages.find]
where = ["."]
include = ["cpl*"]
[tool.setuptools.dynamic]
dependencies = { file = ["requirements.txt"] }
optional-dependencies.dev = { file = ["requirements.dev.txt"] }

View File

@@ -0,0 +1 @@
black==25.1.0

View File

@@ -0,0 +1,5 @@
art==6.5
colorama==0.4.6
tabulate==0.9.0
termcolor==3.1.0
mysql-connector-python==9.4.0

View File

@@ -0,0 +1,26 @@
from .abc.email_client_abc import EMailClientABC
from .email_client import EMailClient
from .email_client_settings import EMailClientSettings
from .email_client_settings_name_enum import EMailClientSettingsNameEnum
from .email_model import EMail
from .mail_logger import MailLogger
def add_mail(self):
from cpl.core.console import Console
from cpl.core.log import LoggerABC
try:
self.add_singleton(EMailClientABC, EMailClient)
self.add_transient(LoggerABC, MailLogger)
except ImportError as e:
Console.error("cpl-translation is not installed", str(e))
def init():
from cpl.core.dependency_injection import ServiceCollection
ServiceCollection.add_mail = add_mail
init()

View File

@@ -1,10 +1,10 @@
from abc import abstractmethod, ABC from abc import abstractmethod, ABC
from cpl_core.mailing.email import EMail from cpl.mail.email_model import EMail
class EMailClientABC(ABC): class EMailClientABC(ABC):
"""ABC of :class:`cpl_core.mailing.email_client_service.EMailClient`""" """ABC of :class:`cpl.mail.email_client_service.EMailClient`"""
@abstractmethod @abstractmethod
def __init__(self): def __init__(self):
@@ -13,14 +13,12 @@ class EMailClientABC(ABC):
@abstractmethod @abstractmethod
def connect(self): def connect(self):
r"""Connects to server""" r"""Connects to server"""
pass
@abstractmethod @abstractmethod
def send_mail(self, email: EMail): def send_mail(self, email: EMail):
r"""Sends email r"""Sends email
Parameter: Parameter:
email: :class:`cpl_core.mailing.email.EMail` email: :class:`cpl.mail.email.EMail`
Object of the E-Mail to send Object of the E-Mail to send
""" """
pass

View File

@@ -0,0 +1,88 @@
import ssl
from smtplib import SMTP
from typing import Optional
from cpl.core.environment.application_environment_abc import ApplicationEnvironmentABC
from cpl.core.utils.credential_manager import CredentialManager
from cpl.mail.abc.email_client_abc import EMailClientABC
from cpl.mail.email_client_settings import EMailClientSettings
from cpl.mail.email_model import EMail
from cpl.mail.mail_logger import MailLogger
class EMailClient(EMailClientABC):
r"""Service to send emails
Parameter:
environment: :class:`cpl.core.environment.application_environment_abc.ApplicationEnvironmentABC`
Environment of the application
logger: :class:`cpl.core.log.logger_abc.LoggerABC`
The logger to use
mail_settings: :class:`cpl.mail.email_client_settings.EMailClientSettings`
Settings for mailing
"""
def __init__(self, environment: ApplicationEnvironmentABC, logger: MailLogger, mail_settings: EMailClientSettings):
EMailClientABC.__init__(self)
self._environment = environment
self._mail_settings = mail_settings
self._logger = logger
self._server: Optional[SMTP] = None
self.create()
def create(self):
r"""Creates connection"""
self._logger.trace(f"Started {__name__}.create")
self.connect()
self._logger.trace(f"Stopped {__name__}.create")
def connect(self):
self._logger.trace(f"Started {__name__}.connect")
try:
self._logger.debug(f"Try to connect to {self._mail_settings.host}:{self._mail_settings.port}")
self._server = SMTP(self._mail_settings.host, self._mail_settings.port)
self._logger.info(f"Connected to {self._mail_settings.host}:{self._mail_settings.port}")
self._logger.debug("Try to start tls")
self._server.starttls(context=ssl.create_default_context())
self._logger.info("Started tls")
except Exception as e:
self._logger.error("Cannot connect to mail server", e)
self._logger.trace(f"Stopped {__name__}.connect")
def login(self):
r"""Login to server"""
self._logger.trace(f"Started {__name__}.login")
try:
self._logger.debug(
__name__,
f"Try to login {self._mail_settings.user_name}@{self._mail_settings.host}:{self._mail_settings.port}",
)
self._server.login(
self._mail_settings.user_name, CredentialManager.decrypt(self._mail_settings.credentials)
)
self._logger.info(
__name__,
f"Logged on as {self._mail_settings.user_name} to {self._mail_settings.host}:{self._mail_settings.port}",
)
except Exception as e:
self._logger.error("Cannot login to mail server", e)
self._logger.trace(f"Stopped {__name__}.login")
def send_mail(self, email: EMail):
self._logger.trace(f"Started {__name__}.send_mail")
try:
self.login()
self._logger.debug(f"Try to send email to {email.receiver_list}")
self._server.sendmail(
self._mail_settings.user_name, email.receiver_list, email.get_content(self._mail_settings.user_name)
)
self._logger.info(f"Sent email to {email.receiver_list}")
except Exception as e:
self._logger.error(f"Cannot send mail to {email.receiver_list}", e)
self._logger.trace(f"Stopped {__name__}.send_mail")

View File

@@ -1,4 +1,4 @@
from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC from cpl.core.configuration.configuration_model_abc import ConfigurationModelABC
class EMailClientSettings(ConfigurationModelABC): class EMailClientSettings(ConfigurationModelABC):

View File

@@ -0,0 +1,8 @@
from cpl.core.log.logger import Logger
from cpl.core.typing import Source
class MailLogger(Logger):
def __init__(self, source: Source):
Logger.__init__(self, source, "mail")

View File

@@ -0,0 +1,29 @@
[build-system]
requires = ["setuptools>=70.1.0", "wheel>=0.43.0"]
build-backend = "setuptools.build_meta"
[project]
name = "cpl-mail"
version = "2024.7.0"
description = "CPL mail"
readme = "CPL mail package"
requires-python = ">=3.12"
license = { text = "MIT" }
authors = [
{ name = "Sven Heidemann", email = "sven.heidemann@sh-edraft.de" }
]
keywords = ["cpl", "mail", "backend", "shared", "library"]
dynamic = ["dependencies", "optional-dependencies"]
[project.urls]
Homepage = "https://www.sh-edraft.de"
[tool.setuptools.packages.find]
where = ["."]
include = ["cpl*"]
[tool.setuptools.dynamic]
dependencies = { file = ["requirements.txt"] }
optional-dependencies.dev = { file = ["requirements.dev.txt"] }

View File

@@ -0,0 +1 @@
black==25.1.0

View File

@@ -0,0 +1 @@
cpl-core

View File

@@ -0,0 +1 @@

View File

@@ -0,0 +1,5 @@
from .default_lambda import default_lambda
from .ordered_queryable import OrderedQueryable
from .sequence import Sequence
from .ordered_queryable_abc import OrderedQueryableABC
from .queryable_abc import QueryableABC

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