Compare commits

..

4 Commits

Author SHA1 Message Date
d05d947d54 Import cleanup
All checks were successful
Test before pr merge / test-lint (pull_request) Successful in 6s
Build on push / prepare (push) Successful in 12s
Build on push / core (push) Successful in 18s
Build on push / query (push) Successful in 17s
Build on push / dependency (push) Successful in 17s
Build on push / application (push) Successful in 15s
Build on push / translation (push) Successful in 18s
Build on push / mail (push) Successful in 18s
Build on push / database (push) Successful in 20s
Build on push / auth (push) Successful in 17s
Build on push / api (push) Successful in 13s
2025-09-26 00:03:12 +02:00
0529269747 Fixed formatting
All checks were successful
Test before pr merge / test-lint (pull_request) Successful in 6s
Build on push / prepare (push) Successful in 9s
Build on push / core (push) Successful in 19s
Build on push / query (push) Successful in 19s
Build on push / dependency (push) Successful in 14s
Build on push / mail (push) Successful in 16s
Build on push / application (push) Successful in 19s
Build on push / database (push) Successful in 20s
Build on push / translation (push) Successful in 20s
Build on push / auth (push) Successful in 14s
Build on push / api (push) Successful in 15s
2025-09-25 10:37:29 +02:00
e3e1703ff8 Fixed versioning
Some checks failed
Test before pr merge / test-lint (pull_request) Failing after 6s
Build on push / prepare (push) Successful in 9s
Build on push / query (push) Successful in 19s
Build on push / core (push) Successful in 19s
Build on push / dependency (push) Successful in 14s
Build on push / api (push) Has been cancelled
Build on push / auth (push) Has been cancelled
Build on push / application (push) Has been cancelled
Build on push / mail (push) Has been cancelled
Build on push / translation (push) Has been cancelled
Build on push / database (push) Has been cancelled
2025-09-25 10:36:36 +02:00
cf4aa8291f Minor DI fixes & cleanup
Some checks failed
Test before pr merge / test-lint (pull_request) Failing after 6s
Build on push / prepare (push) Successful in 9s
Build on push / core (push) Successful in 19s
Build on push / query (push) Successful in 27s
Build on push / dependency (push) Successful in 18s
Build on push / application (push) Successful in 15s
Build on push / database (push) Successful in 20s
Build on push / translation (push) Successful in 19s
Build on push / mail (push) Successful in 20s
Build on push / auth (push) Successful in 14s
Build on push / api (push) Successful in 14s
2025-09-25 10:29:40 +02:00
44 changed files with 130 additions and 105 deletions

View File

@@ -25,7 +25,11 @@ jobs:
git tag git tag
DATE=$(date +'%Y.%m.%d') DATE=$(date +'%Y.%m.%d')
TAG_COUNT=$(git tag -l "${DATE}.*" | wc -l) TAG_COUNT=$(git tag -l "${DATE}.*" | wc -l)
BUILD_NUMBER=$(($TAG_COUNT + 1)) if [ "$TAG_COUNT" -eq 0 ]; then
BUILD_NUMBER=0
else
BUILD_NUMBER=$(($TAG_COUNT + 1))
fi
VERSION_SUFFIX=${{ inputs.version_suffix }} VERSION_SUFFIX=${{ inputs.version_suffix }}
if [ -n "$VERSION_SUFFIX" ] && [ "$VERSION_SUFFIX" = "dev" ]; then if [ -n "$VERSION_SUFFIX" ] && [ "$VERSION_SUFFIX" = "dev" ]; then

View File

@@ -1,9 +1,8 @@
from starlette.responses import JSONResponse from starlette.responses import JSONResponse
from cpl import api from cpl.api.api_module import ApiModule
from cpl.api.application.web_app import WebApp from cpl.api.application.web_app import WebApp
from cpl.api_module import ApiModule from cpl.application.application_builder import ApplicationBuilder
from cpl.application import ApplicationBuilder
from cpl.auth.permission.permissions import Permissions from cpl.auth.permission.permissions import Permissions
from cpl.auth.schema import AuthUser, Role from cpl.auth.schema import AuthUser, Role
from cpl.core.configuration import Configuration from cpl.core.configuration import Configuration

View File

@@ -1,11 +1,14 @@
from cpl import auth from cpl import auth
from cpl.application.abc.startup_abc import StartupABC from cpl.application.abc.startup_abc import StartupABC
from cpl.auth import permission from cpl.auth import permission
from cpl.auth.auth_module import AuthModule
from cpl.auth.permission.permission_module import PermissionsModule
from cpl.core.configuration import Configuration from cpl.core.configuration import Configuration
from cpl.core.environment import Environment from cpl.core.environment import Environment
from cpl.core.log import Logger, LoggerABC from cpl.core.log import Logger, LoggerABC
from cpl.database import mysql from cpl.database import mysql
from cpl.database.abc.data_access_object_abc import DataAccessObjectABC from cpl.database.abc.data_access_object_abc import DataAccessObjectABC
from cpl.database.mysql.mysql_module import MySQLModule
from cpl.dependency import ServiceCollection from cpl.dependency import ServiceCollection
from model.city_dao import CityDao from model.city_dao import CityDao
from model.user_dao import UserDao from model.user_dao import UserDao
@@ -21,9 +24,9 @@ class Startup(StartupABC):
@staticmethod @staticmethod
async def configure_services(services: ServiceCollection): async def configure_services(services: ServiceCollection):
services.add_module(mysql) services.add_module(MySQLModule)
services.add_module(auth) services.add_module(AuthModule)
services.add_module(permission) services.add_module(PermissionsModule)
services.add_transient(DataAccessObjectABC, UserDao) services.add_transient(DataAccessObjectABC, UserDao)
services.add_transient(DataAccessObjectABC, CityDao) services.add_transient(DataAccessObjectABC, CityDao)

View File

@@ -1,11 +1,10 @@
from cpl.application.abc import ApplicationABC from cpl.application.abc import ApplicationABC
from cpl.core.console.console import Console from cpl.core.console.console import Console
from cpl.dependency import ServiceProvider from cpl.dependency import ServiceProvider
from di.static_test import StaticTest from test_abc import TestABC
from di.test_abc import TestABC from test_service import TestService
from di.test_service import TestService from di_tester_service import DITesterService
from di.di_tester_service import DITesterService from tester import Tester
from di.tester import Tester
class Application(ApplicationABC): class Application(ApplicationABC):
@@ -39,7 +38,8 @@ class Application(ApplicationABC):
Console.write_line("Global") Console.write_line("Global")
self._part_of_scoped() self._part_of_scoped()
StaticTest.test() #from static_test import StaticTest
#StaticTest.test()
self._services.get_service(Tester) self._services.get_service(Tester)
Console.write_line(self._services.get_services(TestABC)) Console.write_line(self._services.get_services(TestABC))

View File

@@ -1,5 +1,5 @@
from cpl.core.console.console import Console from cpl.core.console.console import Console
from di.test_service import TestService from test_service import TestService
class DITesterService: class DITesterService:

View File

@@ -1,7 +1,7 @@
from cpl.application import ApplicationBuilder from cpl.application import ApplicationBuilder
from di.application import Application from application import Application
from di.startup import Startup from startup import Startup
def main(): def main():

View File

@@ -1,11 +1,11 @@
from cpl.application.abc import StartupABC from cpl.application.abc import StartupABC
from cpl.dependency import ServiceProvider, ServiceCollection from cpl.dependency import ServiceProvider, ServiceCollection
from di.di_tester_service import DITesterService from di_tester_service import DITesterService
from di.test1_service import Test1Service from test1_service import Test1Service
from di.test2_service import Test2Service from test2_service import Test2Service
from di.test_abc import TestABC from test_abc import TestABC
from di.test_service import TestService from test_service import TestService
from di.tester import Tester from tester import Tester
class Startup(StartupABC): class Startup(StartupABC):

View File

@@ -1,6 +1,6 @@
from cpl.dependency import ServiceProvider, ServiceProvider from cpl.dependency import ServiceProvider, ServiceProvider
from cpl.dependency.inject import inject from cpl.dependency.inject import inject
from di.test_service import TestService from test_service import TestService
class StaticTest: class StaticTest:

View File

@@ -1,7 +1,7 @@
import string import string
from cpl.core.console.console import Console from cpl.core.console.console import Console
from cpl.core.utils.string import String from cpl.core.utils.string import String
from di.test_abc import TestABC from test_abc import TestABC
class Test1Service(TestABC): class Test1Service(TestABC):

View File

@@ -1,7 +1,7 @@
import string import string
from cpl.core.console.console import Console from cpl.core.console.console import Console
from cpl.core.utils.string import String from cpl.core.utils.string import String
from di.test_abc import TestABC from test_abc import TestABC
class Test2Service(TestABC): class Test2Service(TestABC):

View File

@@ -1,8 +1,7 @@
from cpl.core.console.console import Console from cpl.core.console.console import Console
from di.test_abc import TestABC from test_abc import TestABC
class Tester: class Tester:
def __init__(self, t1: TestABC, t2: TestABC, t3: list[TestABC]): def __init__(self, t1: TestABC, t2: TestABC, t3: TestABC, t: list[TestABC]):
Console.write_line("Tester:") Console.write_line("Tester:", t, t1, t2, t3)
Console.write_line(t1, t2, t3)

View File

@@ -48,9 +48,9 @@ def t_benchmark(data: list):
def main(): def main():
N = 10_000_000 N = 1_000_000
data = list(range(N)) data = list(range(N))
#t_benchmark(data) t_benchmark(data)
Console.write_line() Console.write_line()
_default() _default()

View File

@@ -1,4 +1,4 @@
from .error import APIError, AlreadyExists, EndpointNotImplemented, Forbidden, NotFound, Unauthorized from .error import APIError, AlreadyExists, EndpointNotImplemented, Forbidden, NotFound, Unauthorized
from .logger import APILogger from .logger import APILogger
from .settings import ApiSettings from .settings import ApiSettings
from .api_module import ApiModule

View File

@@ -1,11 +1,6 @@
from cpl.api.registry.policy import PolicyRegistry
from cpl.api.registry.route import RouteRegistry
from cpl.auth.auth_module import AuthModule from cpl.auth.auth_module import AuthModule
from cpl.auth.permission.permission_module import PermissionsModule from cpl.auth.permission.permission_module import PermissionsModule
from cpl.core.errors import dependency_error
from cpl.database.database_module import DatabaseModule from cpl.database.database_module import DatabaseModule
from cpl.database.model.server_type import ServerType, ServerTypes
from cpl.database.mysql.mysql_module import MySQLModule
from cpl.dependency.module import Module, TModule from cpl.dependency.module import Module, TModule
@@ -17,6 +12,9 @@ class ApiModule(Module):
@staticmethod @staticmethod
def register(collection: "ServiceCollection"): def register(collection: "ServiceCollection"):
from cpl.api.registry.policy import PolicyRegistry
from cpl.api.registry.route import RouteRegistry
collection.add_module(DatabaseModule) collection.add_module(DatabaseModule)
collection.add_module(AuthModule) collection.add_module(AuthModule)

View File

@@ -25,7 +25,7 @@ from cpl.api.registry.route import RouteRegistry
from cpl.api.router import Router from cpl.api.router import Router
from cpl.api.settings import ApiSettings from cpl.api.settings import ApiSettings
from cpl.api.typing import HTTPMethods, PartialMiddleware, PolicyResolver from cpl.api.typing import HTTPMethods, PartialMiddleware, PolicyResolver
from cpl.api_module import ApiModule from cpl.api.api_module import ApiModule
from cpl.application.abc.application_abc import ApplicationABC from cpl.application.abc.application_abc import ApplicationABC
from cpl.auth.auth_module import AuthModule from cpl.auth.auth_module import AuthModule
from cpl.auth.permission.permission_module import PermissionsModule from cpl.auth.permission.permission_module import PermissionsModule

View File

@@ -1,2 +1,2 @@
from .application_builder import ApplicationBuilder from .application_builder import ApplicationBuilder
from .host import Host from .host import Host

View File

@@ -83,6 +83,7 @@ class ApplicationBuilder(Generic[TApp]):
for extension in self._app_extensions: for extension in self._app_extensions:
Host.run(extension.run, self.service_provider) Host.run(extension.run, self.service_provider)
use_root_provider(self._services.build())
app = self._app(self.service_provider) app = self._app(self.service_provider)
self.validate_app_required_modules(app) self.validate_app_required_modules(app)
return app return app

View File

@@ -77,4 +77,4 @@ class Host:
if asyncio.iscoroutinefunction(func): if asyncio.iscoroutinefunction(func):
return cls.get_loop().run_until_complete(func(*args, **kwargs)) return cls.get_loop().run_until_complete(func(*args, **kwargs))
return func(*args, **kwargs) return func(*args, **kwargs)

View File

@@ -7,6 +7,7 @@ from cpl.auth.keycloak.keycloak_admin import KeycloakAdmin as _KeycloakAdmin
from cpl.auth.keycloak.keycloak_client import KeycloakClient as _KeycloakClient from cpl.auth.keycloak.keycloak_client import KeycloakClient as _KeycloakClient
from .keycloak_settings import KeycloakSettings from .keycloak_settings import KeycloakSettings
from .logger import AuthLogger from .logger import AuthLogger
from .auth_module import AuthModule
def _with_permissions(self: _ApplicationABC, *permissions: Type[Enum]) -> _ApplicationABC: def _with_permissions(self: _ApplicationABC, *permissions: Type[Enum]) -> _ApplicationABC:
@@ -17,5 +18,4 @@ def _with_permissions(self: _ApplicationABC, *permissions: Type[Enum]) -> _Appli
return self return self
_ApplicationABC.extend(_ApplicationABC.with_permissions, _with_permissions) _ApplicationABC.extend(_ApplicationABC.with_permissions, _with_permissions)

View File

@@ -1,19 +1,10 @@
import os import os
from cpl.auth.keycloak.keycloak_admin import KeycloakAdmin as _KeycloakAdmin
from cpl.auth.keycloak.keycloak_client import KeycloakClient as _KeycloakClient
from cpl.database.database_module import DatabaseModule from cpl.database.database_module import DatabaseModule
from cpl.database.model.server_type import ServerType, ServerTypes from cpl.database.model.server_type import ServerType, ServerTypes
from cpl.database.service.migration_service import MigrationService from cpl.database.service.migration_service import MigrationService
from cpl.dependency.module import Module, TModule from cpl.dependency.module import Module, TModule
from cpl.dependency.service_collection import ServiceCollection from cpl.dependency.service_collection import ServiceCollection
from .schema._administration.api_key_dao import ApiKeyDao
from .schema._administration.auth_user_dao import AuthUserDao
from .schema._permission.api_key_permission_dao import ApiKeyPermissionDao
from .schema._permission.permission_dao import PermissionDao
from .schema._permission.role_dao import RoleDao
from .schema._permission.role_permission_dao import RolePermissionDao
from .schema._permission.role_user_dao import RoleUserDao
class AuthModule(Module): class AuthModule(Module):
@@ -23,8 +14,18 @@ class AuthModule(Module):
@staticmethod @staticmethod
def register(collection: ServiceCollection): def register(collection: ServiceCollection):
collection.add_singleton(_KeycloakClient) from cpl.auth.keycloak.keycloak_admin import KeycloakAdmin
collection.add_singleton(_KeycloakAdmin) from cpl.auth.keycloak.keycloak_client import KeycloakClient
from .schema._administration.api_key_dao import ApiKeyDao
from .schema._administration.auth_user_dao import AuthUserDao
from .schema._permission.api_key_permission_dao import ApiKeyPermissionDao
from .schema._permission.permission_dao import PermissionDao
from .schema._permission.role_dao import RoleDao
from .schema._permission.role_permission_dao import RolePermissionDao
from .schema._permission.role_user_dao import RoleUserDao
collection.add_singleton(KeycloakClient)
collection.add_singleton(KeycloakAdmin)
collection.add_singleton(AuthUserDao) collection.add_singleton(AuthUserDao)
collection.add_singleton(ApiKeyDao) collection.add_singleton(ApiKeyDao)

View File

@@ -0,0 +1,4 @@
from .permission_module import PermissionsModule
from .permission_seeder import PermissionSeeder
from .permissions import Permissions
from .permissions_registry import PermissionsRegistry

View File

@@ -1,8 +1,8 @@
from cpl.auth.auth_module import AuthModule
from cpl.auth.permission.permission_seeder import PermissionSeeder from cpl.auth.permission.permission_seeder import PermissionSeeder
from cpl.auth.permission.permissions import Permissions from cpl.auth.permission.permissions import Permissions
from cpl.auth.permission.permissions_registry import PermissionsRegistry from cpl.auth.permission.permissions_registry import PermissionsRegistry
from cpl.database.abc.data_seeder_abc import DataSeederABC from cpl.database.abc.data_seeder_abc import DataSeederABC
from cpl.database.model.server_type import ServerType, ServerTypes
from cpl.dependency.module import Module, TModule from cpl.dependency.module import Module, TModule
from cpl.dependency.service_collection import ServiceCollection from cpl.dependency.service_collection import ServiceCollection
@@ -12,21 +12,7 @@ class PermissionsModule(Module):
def dependencies() -> list[TModule]: def dependencies() -> list[TModule]:
from cpl.database.database_module import DatabaseModule from cpl.database.database_module import DatabaseModule
r = [DatabaseModule] return [DatabaseModule, AuthModule]
match ServerType.server_type:
case ServerTypes.POSTGRES:
from cpl.database.postgres.postgres_module import PostgresModule
r.append(PostgresModule)
case ServerTypes.MYSQL:
from cpl.database.mysql.mysql_module import MySQLModule
r.append(MySQLModule)
case _:
raise Exception(f"Unsupported database type: {ServerType.server_type}")
return r
@staticmethod @staticmethod
def register(collection: ServiceCollection): def register(collection: ServiceCollection):

View File

@@ -14,6 +14,7 @@ def dependency_error(src: str, package_name: str, e: ImportError = None) -> None
exit(1) exit(1)
def module_dependency_error(src: str, module: str, e: ImportError = None) -> None: def module_dependency_error(src: str, module: str, e: ImportError = None) -> None:
Console.error(f"'{module}' is required to use feature: {src}. Please initialize it with `add_module({module})`.") Console.error(f"'{module}' is required to use feature: {src}. Please initialize it with `add_module({module})`.")
tb = traceback.format_exc() tb = traceback.format_exc()
@@ -23,4 +24,4 @@ def module_dependency_error(src: str, module: str, e: ImportError = None) -> Non
elif e is not None: elif e is not None:
Console.write_line("->", str(e)) Console.write_line("->", str(e))
exit(1) exit(1)

View File

@@ -3,7 +3,9 @@ import os
from cpl.application.abc import ApplicationABC as _ApplicationABC from cpl.application.abc import ApplicationABC as _ApplicationABC
from . import mysql as _mysql from . import mysql as _mysql
from . import postgres as _postgres from . import postgres as _postgres
from .database_module import DatabaseModule
from .table_manager import TableManager from .table_manager import TableManager
from .logger import DBLogger
def _with_migrations(self: _ApplicationABC, *paths: str | list[str]) -> _ApplicationABC: def _with_migrations(self: _ApplicationABC, *paths: str | list[str]) -> _ApplicationABC:

View File

@@ -1,4 +1,6 @@
from .connection_abc import ConnectionABC from .connection_abc import ConnectionABC
from .data_access_object_abc import DataAccessObjectABC
from .data_seeder_abc import DataSeederABC
from .db_context_abc import DBContextABC from .db_context_abc import DBContextABC
from .db_join_model_abc import DbJoinModelABC from .db_join_model_abc import DbJoinModelABC
from .db_model_abc import DbModelABC from .db_model_abc import DbModelABC

View File

@@ -14,7 +14,7 @@ from cpl.database.logger import DBLogger
from cpl.database.model.server_type import ServerType, ServerTypes from cpl.database.model.server_type import ServerType, ServerTypes
from cpl.database.postgres.sql_select_builder import SQLSelectBuilder from cpl.database.postgres.sql_select_builder import SQLSelectBuilder
from cpl.database.typing import T_DBM, Attribute, AttributeFilters, AttributeSorts from cpl.database.typing import T_DBM, Attribute, AttributeFilters, AttributeSorts
from cpl.dependency import get_provider from cpl.dependency.context import get_provider
class DataAccessObjectABC(ABC, Generic[T_DBM]): class DataAccessObjectABC(ABC, Generic[T_DBM]):

View File

@@ -2,7 +2,7 @@ from abc import abstractmethod
from datetime import datetime from datetime import datetime
from typing import Type from typing import Type
from cpl.database import TableManager from cpl.database.table_manager import TableManager
from cpl.database.abc.data_access_object_abc import DataAccessObjectABC from cpl.database.abc.data_access_object_abc import DataAccessObjectABC
from cpl.database.abc.db_model_abc import DbModelABC from cpl.database.abc.db_model_abc import DbModelABC

View File

@@ -1,8 +1,5 @@
from cpl.core.errors import module_dependency_error from cpl.core.errors import module_dependency_error
from cpl.database.model.server_type import ServerType from cpl.database.model.server_type import ServerType
from cpl.database.schema.executed_migration_dao import ExecutedMigrationDao
from cpl.database.service.migration_service import MigrationService
from cpl.database.service.seeder_service import SeederService
from cpl.dependency.module import Module, TModule from cpl.dependency.module import Module, TModule
from cpl.dependency.service_collection import ServiceCollection from cpl.dependency.service_collection import ServiceCollection
@@ -17,6 +14,10 @@ class DatabaseModule(Module):
@staticmethod @staticmethod
def register(collection: ServiceCollection): def register(collection: ServiceCollection):
from cpl.database.schema import ExecutedMigrationDao
from cpl.database.service.migration_service import MigrationService
from cpl.database.service.seeder_service import SeederService
collection.add_singleton(ExecutedMigrationDao) collection.add_singleton(ExecutedMigrationDao)
collection.add_singleton(MigrationService) collection.add_singleton(MigrationService)
collection.add_singleton(SeederService) collection.add_singleton(SeederService)

View File

@@ -0,0 +1,4 @@
from .connection import DatabaseConnection
from .db_context import DBContext
from .mysql_module import MySQLModule
from .mysql_pool import MySQLPool

View File

@@ -1,7 +1,5 @@
from cpl.core.configuration.configuration import Configuration from cpl.core.configuration.configuration import Configuration
from cpl.database.abc.db_context_abc import DBContextABC
from cpl.database.model.server_type import ServerTypes, ServerType from cpl.database.model.server_type import ServerTypes, ServerType
from cpl.database.mysql.db_context import DBContext
from cpl.dependency.module import Module, TModule from cpl.dependency.module import Module, TModule
from cpl.dependency.service_collection import ServiceCollection from cpl.dependency.service_collection import ServiceCollection
@@ -13,6 +11,9 @@ class MySQLModule(Module):
@staticmethod @staticmethod
def register(collection: ServiceCollection): def register(collection: ServiceCollection):
from cpl.database.abc.db_context_abc import DBContextABC
from cpl.database.mysql.db_context import DBContext
ServerType.set_server_type(ServerTypes(ServerTypes.MYSQL.value)) ServerType.set_server_type(ServerTypes(ServerTypes.MYSQL.value))
Configuration.set("DB_DEFAULT_PORT", 3306) Configuration.set("DB_DEFAULT_PORT", 3306)

View File

@@ -0,0 +1,4 @@
from .db_context import DBContext
from .postgres_module import PostgresModule
from .postgres_pool import PostgresPool
from .sql_select_builder import SQLSelectBuilder

View File

@@ -1,8 +1,6 @@
from cpl.core.configuration.configuration import Configuration from cpl.core.configuration.configuration import Configuration
from cpl.database.abc.db_context_abc import DBContextABC
from cpl.database.database_module import DatabaseModule from cpl.database.database_module import DatabaseModule
from cpl.database.model.server_type import ServerTypes, ServerType from cpl.database.model.server_type import ServerTypes, ServerType
from cpl.database.postgres.db_context import DBContext
from cpl.dependency.module import Module, TModule from cpl.dependency.module import Module, TModule
from cpl.dependency.service_collection import ServiceCollection from cpl.dependency.service_collection import ServiceCollection
@@ -14,6 +12,9 @@ class PostgresModule(Module):
@staticmethod @staticmethod
def register(collection: ServiceCollection): def register(collection: ServiceCollection):
from cpl.database.abc.db_context_abc import DBContextABC
from cpl.database.postgres.db_context import DBContext
ServerType.set_server_type(ServerTypes(ServerTypes.POSTGRES.value)) ServerType.set_server_type(ServerTypes(ServerTypes.POSTGRES.value))
Configuration.set("DB_DEFAULT_PORT", 5432) Configuration.set("DB_DEFAULT_PORT", 5432)

View File

@@ -0,0 +1,2 @@
from .executed_migration import ExecutedMigration
from .executed_migration_dao import ExecutedMigrationDao

View File

@@ -1,4 +1,4 @@
from cpl.database import TableManager from cpl.database.table_manager import TableManager
from cpl.database.abc.data_access_object_abc import DataAccessObjectABC from cpl.database.abc.data_access_object_abc import DataAccessObjectABC
from cpl.database.schema.executed_migration import ExecutedMigration from cpl.database.schema.executed_migration import ExecutedMigration

View File

@@ -1,9 +1,9 @@
import glob import glob
import os import os
from cpl.database.abc import DBContextABC from cpl.database.abc.db_context_abc import DBContextABC
from cpl.database.logger import DBLogger from cpl.database.logger import DBLogger
from cpl.database.model import Migration from cpl.database.model.migration import Migration
from cpl.database.model.server_type import ServerType, ServerTypes from cpl.database.model.server_type import ServerType, ServerTypes
from cpl.database.schema.executed_migration import ExecutedMigration from cpl.database.schema.executed_migration import ExecutedMigration
from cpl.database.schema.executed_migration_dao import ExecutedMigrationDao from cpl.database.schema.executed_migration_dao import ExecutedMigrationDao

View File

@@ -2,7 +2,7 @@ import contextvars
from contextlib import contextmanager from contextlib import contextmanager
_current_provider = contextvars.ContextVar("current_provider") _current_provider = contextvars.ContextVar("current_provider", default=None)
def use_root_provider(provider: "ServiceProvider"): def use_root_provider(provider: "ServiceProvider"):

View File

@@ -1,2 +1,2 @@
from .hosted_service import HostedService from .hosted_service import HostedService
from .startup_task import StartupTask from .startup_task import StartupTask

View File

@@ -6,4 +6,4 @@ class HostedService(ABC):
async def start(self): ... async def start(self): ...
@abstractmethod @abstractmethod
async def stop(self): ... async def stop(self): ...

View File

@@ -3,6 +3,7 @@ from typing import Type
TModule = Type["Module"] TModule = Type["Module"]
class Module(ABC): class Module(ABC):
@staticmethod @staticmethod

View File

@@ -23,6 +23,11 @@ class ServiceProvider:
type_args = list(typing.get_args(service_type)) type_args = list(typing.get_args(service_type))
for descriptor in self._service_descriptors: for descriptor in self._service_descriptors:
if typing.get_origin(service_type) is None and (
descriptor.service_type == service_type or issubclass(descriptor.base_type, service_type)
):
return descriptor
descriptor_base_type = typing.get_origin(descriptor.base_type) or descriptor.base_type descriptor_base_type = typing.get_origin(descriptor.base_type) or descriptor.base_type
descriptor_type_args = list(typing.get_args(descriptor.base_type)) descriptor_type_args = list(typing.get_args(descriptor.base_type))
@@ -48,7 +53,7 @@ class ServiceProvider:
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, origin_service_type=origin_service_type) implementation = self._build_service(descriptor, origin_service_type=origin_service_type)
if descriptor.lifetime in (ServiceLifetimeEnum.singleton, ServiceLifetimeEnum.scoped): if descriptor.lifetime in (ServiceLifetimeEnum.singleton, ServiceLifetimeEnum.scoped):
descriptor.implementation = implementation descriptor.implementation = implementation
@@ -62,9 +67,7 @@ class ServiceProvider:
implementations.append(descriptor.implementation) implementations.append(descriptor.implementation)
continue continue
implementation = self._build_service( implementation = self._build_service(descriptor, *args, origin_service_type=service_type, **kwargs)
descriptor.service_type, *args, origin_service_type=service_type, **kwargs
)
if descriptor.lifetime in (ServiceLifetimeEnum.singleton, ServiceLifetimeEnum.scoped): if descriptor.lifetime in (ServiceLifetimeEnum.singleton, ServiceLifetimeEnum.scoped):
descriptor.implementation = implementation descriptor.implementation = implementation
@@ -78,7 +81,9 @@ class ServiceProvider:
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], origin_service_type)) params.append(
self._get_services(typing.get_args(parameter.annotation)[0], service_type=origin_service_type)
)
elif parameter.annotation == Source: elif parameter.annotation == Source:
params.append(origin_service_type.__name__) params.append(origin_service_type.__name__)
@@ -101,18 +106,17 @@ class ServiceProvider:
return params return params
def _build_service(self, service_type: type, *args, origin_service_type: type = None, **kwargs) -> object: def _build_service(
self, descriptor: ServiceDescriptor, *args, origin_service_type: type = None, **kwargs
) -> object:
if descriptor.implementation is not None:
service_type = type(descriptor.implementation)
else:
service_type = descriptor.service_type
if origin_service_type is None: if origin_service_type is None:
origin_service_type = service_type origin_service_type = service_type
for descriptor in self._service_descriptors:
if descriptor.service_type == service_type or issubclass(descriptor.service_type, service_type):
if descriptor.implementation is not None:
service_type = type(descriptor.implementation)
else:
service_type = descriptor.service_type
break
sig = signature(service_type.__init__) sig = signature(service_type.__init__)
params = self._build_by_signature(sig, origin_service_type) params = self._build_by_signature(sig, origin_service_type)
return service_type(*params, *args, **kwargs) return service_type(*params, *args, **kwargs)
@@ -131,7 +135,11 @@ class ServiceProvider:
yield scoped_provider yield scoped_provider
def get_hosted_services(self) -> list[Optional[T]]: def get_hosted_services(self) -> list[Optional[T]]:
hosted_services = [self.get_service(d.service_type) for d in self._service_descriptors if d.lifetime == ServiceLifetimeEnum.hosted] hosted_services = [
self.get_service(d.service_type)
for d in self._service_descriptors
if d.lifetime == ServiceLifetimeEnum.hosted
]
return hosted_services return hosted_services
def get_service(self, service_type: Type[T], *args, **kwargs) -> Optional[T]: def get_service(self, service_type: Type[T], *args, **kwargs) -> Optional[T]:
@@ -142,7 +150,7 @@ class ServiceProvider:
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(result, *args, **kwargs)
if result.lifetime == ServiceLifetimeEnum.singleton: if result.lifetime == ServiceLifetimeEnum.singleton:
result.implementation = implementation result.implementation = implementation

View File

@@ -3,6 +3,7 @@ from .abc.email_client_abc import EMailClientABC
from .email_client import EMailClient from .email_client import EMailClient
from .email_client_settings import EMailClientSettings from .email_client_settings import EMailClientSettings
from .email_model import EMail from .email_model import EMail
from .mail_module import MailModule
from .logger import MailLogger from .logger import MailLogger

View File

@@ -1,7 +1,5 @@
from cpl.dependency import ServiceCollection from cpl.dependency import ServiceCollection
from cpl.dependency.module import Module, TModule from cpl.dependency.module import Module, TModule
from cpl.mail.email_client import EMailClient
from cpl.mail.abc.email_client_abc import EMailClientABC
class MailModule(Module): class MailModule(Module):
@@ -9,7 +7,9 @@ class MailModule(Module):
def dependencies() -> list[TModule]: def dependencies() -> list[TModule]:
return [] return []
@staticmethod @staticmethod
def register(collection: ServiceCollection): def register(collection: ServiceCollection):
collection.add_singleton(EMailClientABC, EMailClient) from cpl.mail.abc.email_client_abc import EMailClientABC
from cpl.mail.email_client import EMailClient
collection.add_singleton(EMailClientABC, EMailClient)

View File

@@ -1,5 +1,6 @@
from cpl.dependency import ServiceCollection as _ServiceCollection from cpl.dependency import ServiceCollection as _ServiceCollection
from .translate_pipe import TranslatePipe from .translate_pipe import TranslatePipe
from .translation_module import TranslationModule
from .translation_service import TranslationService from .translation_service import TranslationService
from .translation_service_abc import TranslationServiceABC from .translation_service_abc import TranslationServiceABC
from .translation_settings import TranslationSettings from .translation_settings import TranslationSettings

View File

@@ -1,6 +1,5 @@
from cpl.dependency import ServiceCollection from cpl.dependency import ServiceCollection
from cpl.dependency.module import Module, TModule from cpl.dependency.module import Module, TModule
from cpl.translation.translation_service import TranslationService
from cpl.translation.translation_service_abc import TranslationServiceABC from cpl.translation.translation_service_abc import TranslationServiceABC
@@ -11,4 +10,6 @@ class TranslationModule(Module):
@staticmethod @staticmethod
def register(collection: ServiceCollection): def register(collection: ServiceCollection):
from cpl.translation.translation_service import TranslationService
collection.add_singleton(TranslationServiceABC, TranslationService) collection.add_singleton(TranslationServiceABC, TranslationService)