Added first version of database and orm
This commit is contained in:
parent
ee60be9880
commit
03ba1d1847
@ -1,16 +1,13 @@
|
|||||||
from abc import abstractmethod
|
from abc import abstractmethod, ABC
|
||||||
|
|
||||||
from sqlalchemy import engine
|
from sqlalchemy import engine
|
||||||
from sqlalchemy.orm import session
|
from sqlalchemy.orm import session
|
||||||
|
|
||||||
from sh_edraft.service.base.service_base import ServiceBase
|
|
||||||
|
|
||||||
|
class DatabaseConnectionBase(ABC):
|
||||||
class DatabaseConnectionBase(ServiceBase):
|
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def __init__(self):
|
def __init__(self): pass
|
||||||
ServiceBase.__init__(self)
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
|
@ -19,8 +19,6 @@ class DatabaseConnection(DatabaseConnectionBase):
|
|||||||
self._session: Optional[session] = None
|
self._session: Optional[session] = None
|
||||||
self._credentials: Optional[str] = None
|
self._credentials: Optional[str] = None
|
||||||
|
|
||||||
self.create()
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def engine(self) -> engine:
|
def engine(self) -> engine:
|
||||||
return self._engine
|
return self._engine
|
||||||
@ -29,8 +27,6 @@ class DatabaseConnection(DatabaseConnectionBase):
|
|||||||
def session(self) -> session:
|
def session(self) -> session:
|
||||||
return self._session
|
return self._session
|
||||||
|
|
||||||
def create(self): pass
|
|
||||||
|
|
||||||
def connect(self, connection_string: str):
|
def connect(self, connection_string: str):
|
||||||
try:
|
try:
|
||||||
self._engine = create_engine(connection_string)
|
self._engine = create_engine(connection_string)
|
||||||
|
3
src/sh_edraft/database/context/__init__.py
Normal file
3
src/sh_edraft/database/context/__init__.py
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# imports:
|
||||||
|
|
||||||
|
from .database_context import DatabaseContext
|
3
src/sh_edraft/database/context/base/__init__.py
Normal file
3
src/sh_edraft/database/context/base/__init__.py
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# imports:
|
||||||
|
|
||||||
|
from .database_context_base import DatabaseContextBase
|
27
src/sh_edraft/database/context/base/database_context_base.py
Normal file
27
src/sh_edraft/database/context/base/database_context_base.py
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
from abc import abstractmethod
|
||||||
|
|
||||||
|
from sqlalchemy import engine
|
||||||
|
from sqlalchemy.orm import session
|
||||||
|
|
||||||
|
from sh_edraft.service.base.service_base import ServiceBase
|
||||||
|
|
||||||
|
|
||||||
|
class DatabaseContextBase(ServiceBase):
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def __init__(self):
|
||||||
|
ServiceBase.__init__(self)
|
||||||
|
|
||||||
|
@property
|
||||||
|
@abstractmethod
|
||||||
|
def engine(self) -> engine: pass
|
||||||
|
|
||||||
|
@property
|
||||||
|
@abstractmethod
|
||||||
|
def session(self) -> session: pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def connect(self, connection_string: str): pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def _create_tables(self): pass
|
45
src/sh_edraft/database/context/database_context.py
Normal file
45
src/sh_edraft/database/context/database_context.py
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
from sqlalchemy import engine, Table
|
||||||
|
from sqlalchemy.orm import session
|
||||||
|
|
||||||
|
from sh_edraft.database.connection.database_connection import DatabaseConnection
|
||||||
|
from sh_edraft.database.connection.base.database_connection_base import DatabaseConnectionBase
|
||||||
|
from sh_edraft.database.context.base.database_context_base import DatabaseContextBase
|
||||||
|
from sh_edraft.database.model.dbmodel import DBModel
|
||||||
|
from sh_edraft.database.model.database_settings import DatabaseSettings
|
||||||
|
from sh_edraft.utils.console import Console
|
||||||
|
|
||||||
|
|
||||||
|
class DatabaseContext(DatabaseContextBase):
|
||||||
|
|
||||||
|
def __init__(self, database_settings: DatabaseSettings):
|
||||||
|
DatabaseContextBase.__init__(self)
|
||||||
|
|
||||||
|
self._db: DatabaseConnectionBase = DatabaseConnection(database_settings)
|
||||||
|
self._tables: list[Table] = []
|
||||||
|
|
||||||
|
@property
|
||||||
|
def engine(self) -> engine:
|
||||||
|
return self._db.engine
|
||||||
|
|
||||||
|
@property
|
||||||
|
def session(self) -> session:
|
||||||
|
return self._db.session
|
||||||
|
|
||||||
|
def create(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def connect(self, connection_string: str):
|
||||||
|
self._db.connect(connection_string)
|
||||||
|
self._create_tables()
|
||||||
|
|
||||||
|
def _create_tables(self):
|
||||||
|
try:
|
||||||
|
for subclass in DBModel.__subclasses__():
|
||||||
|
self._tables.append(subclass.__table__)
|
||||||
|
|
||||||
|
DBModel.metadata.drop_all(self._db.engine, self._tables)
|
||||||
|
DBModel.metadata.create_all(self._db.engine, self._tables, checkfirst=True)
|
||||||
|
Console.write_line(f'[{__name__}] Created tables', 'green')
|
||||||
|
except Exception as e:
|
||||||
|
Console.write_line(f'[{__name__}] Creating tables failed -> {e}', 'red')
|
||||||
|
exit()
|
@ -2,3 +2,4 @@
|
|||||||
|
|
||||||
from .database_settings import DatabaseSettings
|
from .database_settings import DatabaseSettings
|
||||||
from .database_settings_name import DatabaseSettingsName
|
from .database_settings_name import DatabaseSettingsName
|
||||||
|
from .dbmodel import DBModel
|
||||||
|
3
src/sh_edraft/database/model/dbmodel.py
Normal file
3
src/sh_edraft/database/model/dbmodel.py
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
from sqlalchemy.ext.declarative import declarative_base
|
||||||
|
|
||||||
|
DBModel: declarative_base = declarative_base()
|
@ -1,15 +1,21 @@
|
|||||||
from abc import abstractmethod
|
from abc import abstractmethod, ABC
|
||||||
from collections import Callable
|
from collections import Callable
|
||||||
from typing import Type
|
from typing import Type
|
||||||
|
|
||||||
|
from sh_edraft.database.context.base.database_context_base import DatabaseContextBase
|
||||||
from sh_edraft.service.base.service_base import ServiceBase
|
from sh_edraft.service.base.service_base import ServiceBase
|
||||||
|
|
||||||
|
|
||||||
class ServiceProviderBase(ServiceBase):
|
class ServiceProviderBase(ABC):
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def __init__(self):
|
def __init__(self): pass
|
||||||
ServiceBase.__init__(self)
|
|
||||||
|
@abstractmethod
|
||||||
|
def add_db_context(self, db_context: Type[DatabaseContextBase]): pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def get_db_context(self) -> Callable[DatabaseContextBase]: pass
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def add_transient(self, service_type: Type[ServiceBase], service: Type[ServiceBase]): pass
|
def add_transient(self, service_type: Type[ServiceBase], service: Type[ServiceBase]): pass
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
from collections import Callable
|
from collections import Callable
|
||||||
from inspect import signature, Parameter
|
from inspect import signature, Parameter
|
||||||
from typing import Type
|
from typing import Type, Optional
|
||||||
|
|
||||||
from sh_edraft.configuration.base.configuration_model_base import ConfigurationModelBase
|
from sh_edraft.configuration.base.configuration_model_base import ConfigurationModelBase
|
||||||
|
from sh_edraft.database.context.base.database_context_base import DatabaseContextBase
|
||||||
from sh_edraft.hosting.base.application_runtime_base import ApplicationRuntimeBase
|
from sh_edraft.hosting.base.application_runtime_base import ApplicationRuntimeBase
|
||||||
from sh_edraft.service.providing.base.service_provider_base import ServiceProviderBase
|
from sh_edraft.service.providing.base.service_provider_base import ServiceProviderBase
|
||||||
from sh_edraft.service.base.service_base import ServiceBase
|
from sh_edraft.service.base.service_base import ServiceBase
|
||||||
@ -13,6 +14,7 @@ class ServiceProvider(ServiceProviderBase):
|
|||||||
def __init__(self, app_runtime: ApplicationRuntimeBase):
|
def __init__(self, app_runtime: ApplicationRuntimeBase):
|
||||||
ServiceProviderBase.__init__(self)
|
ServiceProviderBase.__init__(self)
|
||||||
self._app_runtime: ApplicationRuntimeBase = app_runtime
|
self._app_runtime: ApplicationRuntimeBase = app_runtime
|
||||||
|
self._database_context: Optional[DatabaseContextBase] = None
|
||||||
|
|
||||||
self._transient_services: dict[Type[ServiceBase], Type[ServiceBase]] = {}
|
self._transient_services: dict[Type[ServiceBase], Type[ServiceBase]] = {}
|
||||||
self._scoped_services: dict[Type[ServiceBase], Type[ServiceBase]] = {}
|
self._scoped_services: dict[Type[ServiceBase], Type[ServiceBase]] = {}
|
||||||
@ -29,6 +31,9 @@ class ServiceProvider(ServiceProviderBase):
|
|||||||
if issubclass(parameter.annotation, ApplicationRuntimeBase):
|
if issubclass(parameter.annotation, ApplicationRuntimeBase):
|
||||||
params.append(self._app_runtime)
|
params.append(self._app_runtime)
|
||||||
|
|
||||||
|
elif issubclass(parameter.annotation, DatabaseContextBase):
|
||||||
|
params.append(self._database_context)
|
||||||
|
|
||||||
elif issubclass(parameter.annotation, ServiceBase):
|
elif issubclass(parameter.annotation, ServiceBase):
|
||||||
params.append(self.get_service(parameter.annotation))
|
params.append(self.get_service(parameter.annotation))
|
||||||
|
|
||||||
@ -37,6 +42,12 @@ class ServiceProvider(ServiceProviderBase):
|
|||||||
|
|
||||||
return service(*params)
|
return service(*params)
|
||||||
|
|
||||||
|
def add_db_context(self, db_context: Type[DatabaseContextBase]):
|
||||||
|
self._database_context = self._create_instance(db_context)
|
||||||
|
|
||||||
|
def get_db_context(self) -> Callable[DatabaseContextBase]:
|
||||||
|
return self._database_context
|
||||||
|
|
||||||
def add_transient(self, service_type: Type[ServiceBase], service: Type[ServiceBase]):
|
def add_transient(self, service_type: Type[ServiceBase], service: Type[ServiceBase]):
|
||||||
self._transient_services[service_type] = service
|
self._transient_services[service_type] = service
|
||||||
|
|
||||||
|
@ -21,6 +21,7 @@ from collections import namedtuple
|
|||||||
|
|
||||||
# imports:
|
# imports:
|
||||||
from .console import Console
|
from .console import Console
|
||||||
|
from .credential_manager import CredentialManager
|
||||||
|
|
||||||
VersionInfo = namedtuple('VersionInfo', 'major minor micro')
|
VersionInfo = namedtuple('VersionInfo', 'major minor micro')
|
||||||
version_info = VersionInfo(major=2020, minor=12, micro=5)
|
version_info = VersionInfo(major=2020, minor=12, micro=5)
|
||||||
|
0
src/tests_dev/db/__init__.py
Normal file
0
src/tests_dev/db/__init__.py
Normal file
14
src/tests_dev/db/city.py
Normal file
14
src/tests_dev/db/city.py
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
from sqlalchemy import Column, Integer, String
|
||||||
|
|
||||||
|
from sh_edraft.database.model import DBModel
|
||||||
|
|
||||||
|
|
||||||
|
class City(DBModel):
|
||||||
|
__tablename__ = 'Cities'
|
||||||
|
Id = Column(Integer, primary_key=True, nullable=False, autoincrement=True)
|
||||||
|
Name = Column(String(64), nullable=False)
|
||||||
|
ZIP = Column(String(5), nullable=False)
|
||||||
|
|
||||||
|
def __init__(self, name: str, zip_code: str):
|
||||||
|
self.Name = name
|
||||||
|
self.ZIP = zip_code
|
18
src/tests_dev/db/user.py
Normal file
18
src/tests_dev/db/user.py
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
from sqlalchemy import Column, Integer, String, ForeignKey
|
||||||
|
from sqlalchemy.orm import relationship
|
||||||
|
|
||||||
|
from sh_edraft.database.model import DBModel
|
||||||
|
from tests_dev.db.city import City as CityModel
|
||||||
|
|
||||||
|
|
||||||
|
class User(DBModel):
|
||||||
|
__tablename__ = 'Users'
|
||||||
|
Id = Column(Integer, primary_key=True, nullable=False, autoincrement=True)
|
||||||
|
Name = Column(String(64), nullable=False)
|
||||||
|
City_Id = Column(Integer, ForeignKey('Cities.Id'), nullable=False)
|
||||||
|
City = relationship("City")
|
||||||
|
|
||||||
|
def __init__(self, name: str, city: CityModel):
|
||||||
|
self.Name = name
|
||||||
|
self.City_Id = city.Id
|
||||||
|
self.City = city
|
23
src/tests_dev/db/user_repo.py
Normal file
23
src/tests_dev/db/user_repo.py
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
from sh_edraft.database.context.base import DatabaseContextBase
|
||||||
|
from tests_dev.db.city import City
|
||||||
|
from tests_dev.db.user import User
|
||||||
|
from tests_dev.db.user_repo_base import UserRepoBase
|
||||||
|
|
||||||
|
|
||||||
|
class UserRepo(UserRepoBase):
|
||||||
|
|
||||||
|
def __init__(self, db_context: DatabaseContextBase):
|
||||||
|
UserRepoBase.__init__(self)
|
||||||
|
|
||||||
|
self._session = db_context.session
|
||||||
|
self._user_query = db_context.session.query(User)
|
||||||
|
|
||||||
|
def create(self): pass
|
||||||
|
|
||||||
|
def add_test_user(self):
|
||||||
|
city = City('Haren', '49733')
|
||||||
|
city2 = City('Meppen', '49716')
|
||||||
|
self._session.add(city2)
|
||||||
|
user = User('TestUser', city)
|
||||||
|
self._session.add(user)
|
||||||
|
self._session.commit()
|
10
src/tests_dev/db/user_repo_base.py
Normal file
10
src/tests_dev/db/user_repo_base.py
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
from abc import abstractmethod
|
||||||
|
|
||||||
|
from sh_edraft.service.base import ServiceBase
|
||||||
|
|
||||||
|
|
||||||
|
class UserRepoBase(ServiceBase):
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def __init__(self):
|
||||||
|
ServiceBase.__init__(self)
|
@ -1,15 +1,17 @@
|
|||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from sh_edraft.configuration.base import ConfigurationBase
|
from sh_edraft.configuration.base import ConfigurationBase
|
||||||
from sh_edraft.database.connection import DatabaseConnection
|
from sh_edraft.database.context import DatabaseContext
|
||||||
from sh_edraft.database.connection.base import DatabaseConnectionBase
|
|
||||||
from sh_edraft.database.model import DatabaseSettings
|
from sh_edraft.database.model import DatabaseSettings
|
||||||
from sh_edraft.hosting import ApplicationHost
|
from sh_edraft.hosting import ApplicationHost
|
||||||
from sh_edraft.hosting.base import ApplicationBase
|
from sh_edraft.hosting.base import ApplicationBase
|
||||||
from sh_edraft.logging import Logger
|
from sh_edraft.logging import Logger
|
||||||
from sh_edraft.logging.base import LoggerBase
|
from sh_edraft.logging.base import LoggerBase
|
||||||
from sh_edraft.service.providing.base import ServiceProviderBase
|
from sh_edraft.service.providing.base import ServiceProviderBase
|
||||||
from sh_edraft.utils.credential_manager import CredentialManager
|
from sh_edraft.utils import CredentialManager
|
||||||
|
|
||||||
|
from tests_dev.db.user_repo import UserRepo
|
||||||
|
from tests_dev.db.user_repo_base import UserRepoBase
|
||||||
|
|
||||||
|
|
||||||
class Program(ApplicationBase):
|
class Program(ApplicationBase):
|
||||||
@ -38,10 +40,12 @@ class Program(ApplicationBase):
|
|||||||
def create_services(self):
|
def create_services(self):
|
||||||
# Create and connect to database
|
# Create and connect to database
|
||||||
db_settings: DatabaseSettings = self._configuration.get_configuration(DatabaseSettings)
|
db_settings: DatabaseSettings = self._configuration.get_configuration(DatabaseSettings)
|
||||||
self._services.add_singleton(DatabaseConnectionBase, DatabaseConnection)
|
self._services.add_db_context(DatabaseContext)
|
||||||
db: DatabaseConnectionBase = self._services.get_service(DatabaseConnectionBase)
|
db: DatabaseContext = self._services.get_db_context()
|
||||||
db.connect(CredentialManager.build_string(db_settings.connection_string, db_settings.credentials))
|
db.connect(CredentialManager.build_string(db_settings.connection_string, db_settings.credentials))
|
||||||
|
|
||||||
|
self._services.add_scoped(UserRepoBase, UserRepo)
|
||||||
|
|
||||||
# Add and create logger
|
# Add and create logger
|
||||||
self._services.add_singleton(LoggerBase, Logger)
|
self._services.add_singleton(LoggerBase, Logger)
|
||||||
self._logger = self._services.get_service(LoggerBase)
|
self._logger = self._services.get_service(LoggerBase)
|
||||||
@ -51,3 +55,4 @@ class Program(ApplicationBase):
|
|||||||
self._logger.debug(__name__, f'Host: {self._configuration.environment.host_name}')
|
self._logger.debug(__name__, f'Host: {self._configuration.environment.host_name}')
|
||||||
self._logger.debug(__name__, f'Environment: {self._configuration.environment.environment_name}')
|
self._logger.debug(__name__, f'Environment: {self._configuration.environment.environment_name}')
|
||||||
self._logger.debug(__name__, f'Customer: {self._configuration.environment.customer}')
|
self._logger.debug(__name__, f'Customer: {self._configuration.environment.customer}')
|
||||||
|
self._services.get_service(UserRepoBase).add_test_user()
|
||||||
|
Loading…
Reference in New Issue
Block a user