Persistence refactory
This commit is contained in:
parent
5978757348
commit
672b9874f2
@ -1,6 +1,5 @@
|
|||||||
from .base_repo import BaseRepo
|
from .repository import Repository
|
||||||
from .repositories.city_repo import CityRepo
|
from .repositories.city import City
|
||||||
from .repositories.heat_pump_simulation_repo import HeatPumpSimulationRepo
|
|
||||||
from .db_setup import DBSetup
|
from .db_setup import DBSetup
|
||||||
from .repositories.user_repo import UserRepo
|
from .repositories.user import User
|
||||||
from .models.user import UserRoles
|
from .models.user import UserRoles
|
||||||
|
@ -13,10 +13,10 @@ from hub.hub_logger import logger
|
|||||||
Base = declarative_base()
|
Base = declarative_base()
|
||||||
|
|
||||||
|
|
||||||
class BaseConfiguration(object):
|
class Configuration:
|
||||||
|
"""
|
||||||
|
Configuration class to hold common persistence configuration
|
||||||
"""
|
"""
|
||||||
Base configuration class to hold common persistence configuration
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, db_name: str, dotenv_path: str, app_env='TEST'):
|
def __init__(self, db_name: str, dotenv_path: str, app_env='TEST'):
|
||||||
"""
|
"""
|
@ -1,13 +1,19 @@
|
|||||||
|
"""
|
||||||
|
Database setup
|
||||||
|
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||||
|
Copyright © 2022 Concordia CERC group
|
||||||
|
Project Coder Peter Yefi peteryefi@gmail.com
|
||||||
|
"""
|
||||||
|
|
||||||
from hub.persistence import BaseRepo
|
from hub.persistence import Repository
|
||||||
|
from hub.persistence.models import Application
|
||||||
from hub.persistence.models import City
|
from hub.persistence.models import City
|
||||||
from hub.persistence.models import HeatPumpSimulation
|
from hub.persistence.models import CityObject
|
||||||
from hub.persistence.models import User
|
from hub.persistence.models import User
|
||||||
from hub.persistence.models import UserRoles
|
from hub.persistence.models import UserRoles
|
||||||
from hub.persistence.models import Application
|
from hub.persistence.models import SimulationResults
|
||||||
from hub.persistence.models import UserApplications
|
from hub.persistence.repositories import User as UserRepository
|
||||||
from hub.persistence.repositories import UserRepo
|
from hub.persistence.repositories import Application as ApplicationRepository
|
||||||
from hub.persistence.repositories import ApplicationRepo
|
|
||||||
from hub.hub_logger import logger
|
from hub.hub_logger import logger
|
||||||
|
|
||||||
|
|
||||||
@ -20,14 +26,17 @@ class DBSetup:
|
|||||||
:param app_env:
|
:param app_env:
|
||||||
:param dotenv_path:
|
:param dotenv_path:
|
||||||
"""
|
"""
|
||||||
repo = BaseRepo(db_name=db_name, app_env=app_env, dotenv_path=dotenv_path)
|
repository = Repository(db_name=db_name, app_env=app_env, dotenv_path=dotenv_path)
|
||||||
User.__table__.create(bind=repo.engine, checkfirst=True)
|
|
||||||
City.__table__.create(bind=repo.engine, checkfirst=True)
|
# Create the tables using the models
|
||||||
Application.__table__.create(bind=repo.engine, checkfirst=True)
|
Application.__table__.create(bind=repository.engine, checkfirst=True)
|
||||||
UserApplications.__table__.create(bind=repo.engine, checkfirst=True)
|
City.__table__.create(bind=repository.engine, checkfirst=True)
|
||||||
HeatPumpSimulation.__table__.create(bind=repo.engine, checkfirst=True)
|
CityObject.__table__.create(bind=repository.engine, checkfirst=True)
|
||||||
self._user_repo = UserRepo(db_name=db_name, app_env=app_env, dotenv_path=dotenv_path)
|
SimulationResults.__table__.create(bind=repository.engine, checkfirst=True)
|
||||||
self._application_repo = ApplicationRepo(db_name=db_name, app_env=app_env, dotenv_path=dotenv_path)
|
User.__table__.create(bind=repository.engine, checkfirst=True)
|
||||||
|
|
||||||
|
self._user_repo = UserRepository(db_name=db_name, app_env=app_env, dotenv_path=dotenv_path)
|
||||||
|
self._application_repo = ApplicationRepository(db_name=db_name, app_env=app_env, dotenv_path=dotenv_path)
|
||||||
self._create_admin_user(self._user_repo, admin_password)
|
self._create_admin_user(self._user_repo, admin_password)
|
||||||
self._create_admin_app(self._application_repo, application_uuid)
|
self._create_admin_app(self._application_repo, application_uuid)
|
||||||
|
|
||||||
|
@ -1,8 +1,5 @@
|
|||||||
from .city import City
|
|
||||||
from .heat_pump_simulation import HeatPumpSimulation
|
|
||||||
from .heat_pump_simulation import SimulationTypes
|
|
||||||
from .heat_pump_simulation import HeatPumpTypes
|
|
||||||
from .user import User, UserRoles
|
|
||||||
from .user_applications import UserApplications
|
|
||||||
from .application import Application
|
from .application import Application
|
||||||
|
from .city import City
|
||||||
from .city_object import CityObject
|
from .city_object import CityObject
|
||||||
|
from .simulation_results import SimulationResults
|
||||||
|
from .user import User, UserRoles
|
||||||
|
@ -11,14 +11,12 @@ from sqlalchemy.dialects.postgresql import UUID
|
|||||||
from sqlalchemy import Column, Integer, String, Sequence
|
from sqlalchemy import Column, Integer, String, Sequence
|
||||||
from sqlalchemy import DateTime
|
from sqlalchemy import DateTime
|
||||||
|
|
||||||
from hub.persistence.db_config import Base
|
|
||||||
|
|
||||||
|
class Application:
|
||||||
class Application(Base):
|
|
||||||
"""
|
"""
|
||||||
A model representation of an application
|
A model representation of an application
|
||||||
"""
|
"""
|
||||||
__tablename__ = "application"
|
__table__ = "application"
|
||||||
id = Column(Integer, Sequence('application_id_seq'), primary_key=True)
|
id = Column(Integer, Sequence('application_id_seq'), primary_key=True)
|
||||||
name = Column(String, nullable=False)
|
name = Column(String, nullable=False)
|
||||||
description = Column(String, nullable=False)
|
description = Column(String, nullable=False)
|
||||||
|
@ -10,13 +10,11 @@ import datetime
|
|||||||
from sqlalchemy import Column, Integer, String, Sequence, ForeignKey
|
from sqlalchemy import Column, Integer, String, Sequence, ForeignKey
|
||||||
from sqlalchemy import DateTime, PickleType
|
from sqlalchemy import DateTime, PickleType
|
||||||
|
|
||||||
from hub.persistence.db_config import Base
|
|
||||||
|
|
||||||
|
class City:
|
||||||
class City(Base):
|
|
||||||
"""A model representation of a city
|
"""A model representation of a city
|
||||||
"""
|
"""
|
||||||
__tablename__ = "city"
|
__table__ = "city"
|
||||||
id = Column(Integer, Sequence('city_id_seq'), primary_key=True)
|
id = Column(Integer, Sequence('city_id_seq'), primary_key=True)
|
||||||
city = Column(PickleType, nullable=False)
|
city = Column(PickleType, nullable=False)
|
||||||
name = Column(String, nullable=False)
|
name = Column(String, nullable=False)
|
||||||
|
@ -10,14 +10,11 @@ import datetime
|
|||||||
from sqlalchemy import Column, Integer, String, Sequence, ForeignKey, Float
|
from sqlalchemy import Column, Integer, String, Sequence, ForeignKey, Float
|
||||||
from sqlalchemy import DateTime
|
from sqlalchemy import DateTime
|
||||||
|
|
||||||
from hub.persistence.db_config import Base
|
class CityObject:
|
||||||
|
|
||||||
|
|
||||||
class CityObject(Base):
|
|
||||||
"""
|
"""
|
||||||
A model representation of an application
|
A model representation of an application
|
||||||
"""
|
"""
|
||||||
__tablename__ = "city_object"
|
__table__ = "city_object"
|
||||||
id = Column(Integer, Sequence('application_id_seq'), primary_key=True)
|
id = Column(Integer, Sequence('application_id_seq'), primary_key=True)
|
||||||
city_id = Column(Integer, ForeignKey('city.id'), nullable=False)
|
city_id = Column(Integer, ForeignKey('city.id'), nullable=False)
|
||||||
name = Column(String, nullable=False)
|
name = Column(String, nullable=False)
|
||||||
@ -41,4 +38,3 @@ class CityObject(Base):
|
|||||||
self.usage = usage
|
self.usage = usage
|
||||||
self.volume = volume
|
self.volume = volume
|
||||||
self.area = area
|
self.area = area
|
||||||
|
|
||||||
|
@ -7,18 +7,15 @@ Project Coder Guille Gutierrez Guillermo.GutierrezMorote@concordia.ca
|
|||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
from sqlalchemy import Column, Integer, String, Sequence, ForeignKey, Float
|
from sqlalchemy import Column, Integer, String, Sequence, ForeignKey
|
||||||
from sqlalchemy import DateTime
|
from sqlalchemy import DateTime
|
||||||
from sqlalchemy.dialects.postgresql import JSONB
|
from sqlalchemy.dialects.postgresql import JSONB
|
||||||
|
|
||||||
from hub.persistence.db_config import Base
|
class SimulationResults:
|
||||||
|
|
||||||
|
|
||||||
class CityObject(Base):
|
|
||||||
"""
|
"""
|
||||||
A model representation of an application
|
A model representation of an application
|
||||||
"""
|
"""
|
||||||
__tablename__ = "simulation_results"
|
__table__ = "simulation_results"
|
||||||
id = Column(Integer, Sequence('application_id_seq'), primary_key=True)
|
id = Column(Integer, Sequence('application_id_seq'), primary_key=True)
|
||||||
city_id = Column(Integer, ForeignKey('city.id'), nullable=True)
|
city_id = Column(Integer, ForeignKey('city.id'), nullable=True)
|
||||||
city_object_id = Column(Integer, ForeignKey('city_object.id'), nullable=True)
|
city_object_id = Column(Integer, ForeignKey('city_object.id'), nullable=True)
|
||||||
|
@ -5,14 +5,11 @@ Copyright © 2022 Concordia CERC group
|
|||||||
Project Coder Peter Yefi peteryefi@gmail.com
|
Project Coder Peter Yefi peteryefi@gmail.com
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import datetime
|
||||||
|
import enum
|
||||||
|
|
||||||
from sqlalchemy import Column, Integer, String, Sequence
|
from sqlalchemy import Column, Integer, String, Sequence
|
||||||
from sqlalchemy import DateTime, Enum
|
from sqlalchemy import DateTime, Enum
|
||||||
from hub.persistence.db_config import Base
|
|
||||||
import datetime
|
|
||||||
from sqlalchemy.orm import validates
|
|
||||||
import re
|
|
||||||
import enum
|
|
||||||
from sqlalchemy.orm import relationship
|
|
||||||
|
|
||||||
|
|
||||||
class UserRoles(enum.Enum):
|
class UserRoles(enum.Enum):
|
||||||
@ -20,10 +17,11 @@ class UserRoles(enum.Enum):
|
|||||||
Hub_Reader = 'Hub_Reader'
|
Hub_Reader = 'Hub_Reader'
|
||||||
|
|
||||||
|
|
||||||
class User(Base):
|
class User:
|
||||||
"""A model representation of a city
|
|
||||||
"""
|
"""
|
||||||
__tablename__ = "user"
|
A model representation of a city
|
||||||
|
"""
|
||||||
|
__table__ = "user"
|
||||||
id = Column(Integer, Sequence('user_id_seq'), primary_key=True)
|
id = Column(Integer, Sequence('user_id_seq'), primary_key=True)
|
||||||
name = Column(String, nullable=False)
|
name = Column(String, nullable=False)
|
||||||
password = Column(String, nullable=False)
|
password = Column(String, nullable=False)
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
from .user_repo import UserRepo
|
from .user import User
|
||||||
from .application_repo import ApplicationRepo
|
from .application import Application
|
||||||
|
@ -12,11 +12,11 @@ from sqlalchemy import select
|
|||||||
from sqlalchemy.exc import SQLAlchemyError
|
from sqlalchemy.exc import SQLAlchemyError
|
||||||
|
|
||||||
from hub.hub_logger import logger
|
from hub.hub_logger import logger
|
||||||
from hub.persistence import BaseRepo
|
from hub.persistence import Repository
|
||||||
from hub.persistence.models import Application
|
from hub.persistence.models import Application as Model
|
||||||
|
|
||||||
|
|
||||||
class ApplicationRepo(BaseRepo):
|
class Application(Repository):
|
||||||
_instance = None
|
_instance = None
|
||||||
|
|
||||||
def __init__(self, db_name: str, dotenv_path: str, app_env: str):
|
def __init__(self, db_name: str, dotenv_path: str, app_env: str):
|
||||||
@ -27,14 +27,14 @@ class ApplicationRepo(BaseRepo):
|
|||||||
Implemented for a singleton pattern
|
Implemented for a singleton pattern
|
||||||
"""
|
"""
|
||||||
if cls._instance is None:
|
if cls._instance is None:
|
||||||
cls._instance = super(ApplicationRepo, cls).__new__(cls)
|
cls._instance = super(Application, cls).__new__(cls)
|
||||||
return cls._instance
|
return cls._instance
|
||||||
|
|
||||||
def insert(self, name: str, description: str, application_uuid: str) -> Union[Application, Dict]:
|
def insert(self, name: str, description: str, application_uuid: str) -> Union[Model, Dict]:
|
||||||
application = self.get_by_uuid(application_uuid)
|
application = self.get_by_uuid(application_uuid)
|
||||||
if application is None:
|
if application is None:
|
||||||
try:
|
try:
|
||||||
application = Application(name=name, description=description, application_uuid=application_uuid)
|
application = Model(name=name, description=description, application_uuid=application_uuid)
|
||||||
self.session.add(application)
|
self.session.add(application)
|
||||||
self.session.flush()
|
self.session.flush()
|
||||||
self.session.commit()
|
self.session.commit()
|
||||||
@ -53,21 +53,24 @@ class ApplicationRepo(BaseRepo):
|
|||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
self.session.query(Application).filter(Application.application_uuid == application_uuid) \
|
self.session.query(Model).filter(
|
||||||
.update({'name': name, 'description': description, 'updated': datetime.datetime.utcnow()})
|
Model.application_uuid == application_uuid
|
||||||
|
).update({'name': name, 'description': description, 'updated': datetime.datetime.utcnow()})
|
||||||
self.session.commit()
|
self.session.commit()
|
||||||
except SQLAlchemyError as err:
|
except SQLAlchemyError as err:
|
||||||
logger.error(f'Error while updating application: {err}')
|
logger.error(f'Error while updating application: {err}')
|
||||||
return {'err_msg': 'Error occurred while updating application'}
|
return {'err_msg': 'Error occurred while updating application'}
|
||||||
|
|
||||||
def get_by_uuid(self, application_uuid: str) -> [Application]:
|
def get_by_uuid(self, application_uuid: str) -> [Model]:
|
||||||
"""
|
"""
|
||||||
Fetch Application based on the application uuid
|
Fetch Application based on the application uuid
|
||||||
:param application_uuid: the application uuid
|
:param application_uuid: the application uuid
|
||||||
:return: [Application] with the provided application_uuid
|
:return: [Application] with the provided application_uuid
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
return self.session.execute(select(Application).where(Application.application_uuid == application_uuid)).first()
|
return self.session.execute(select(Model).where(
|
||||||
|
Model.application_uuid == application_uuid)
|
||||||
|
).first()
|
||||||
except SQLAlchemyError as err:
|
except SQLAlchemyError as err:
|
||||||
logger.error(f'Error while fetching application by application_uuid: {err}')
|
logger.error(f'Error while fetching application by application_uuid: {err}')
|
||||||
|
|
||||||
@ -78,7 +81,7 @@ class ApplicationRepo(BaseRepo):
|
|||||||
:return: None
|
:return: None
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
self.session.query(Application).filter(Application.application_uuid == application_uuid).delete()
|
self.session.query(Model).filter(Model.application_uuid == application_uuid).delete()
|
||||||
self.session.commit()
|
self.session.commit()
|
||||||
except SQLAlchemyError as err:
|
except SQLAlchemyError as err:
|
||||||
logger.error(f'Error while deleting application: {err}')
|
logger.error(f'Error while deleting application: {err}')
|
@ -12,14 +12,14 @@ from typing import Union, Dict
|
|||||||
from sqlalchemy import select
|
from sqlalchemy import select
|
||||||
from sqlalchemy.exc import SQLAlchemyError
|
from sqlalchemy.exc import SQLAlchemyError
|
||||||
|
|
||||||
from hub.city_model_structure.city import City
|
from hub.city_model_structure.city import City as CityHub
|
||||||
from hub.hub_logger import logger
|
from hub.hub_logger import logger
|
||||||
from hub.persistence import BaseRepo
|
from hub.persistence import Repository
|
||||||
from hub.persistence.models import City as DBCity
|
from hub.persistence.models import City as Model
|
||||||
from hub.version import __version__
|
from hub.version import __version__
|
||||||
|
|
||||||
|
|
||||||
class CityRepo(BaseRepo):
|
class City(Repository):
|
||||||
_instance = None
|
_instance = None
|
||||||
|
|
||||||
def __init__(self, db_name: str, dotenv_path: str, app_env: str):
|
def __init__(self, db_name: str, dotenv_path: str, app_env: str):
|
||||||
@ -30,10 +30,10 @@ class CityRepo(BaseRepo):
|
|||||||
Implemented for a singleton pattern
|
Implemented for a singleton pattern
|
||||||
"""
|
"""
|
||||||
if cls._instance is None:
|
if cls._instance is None:
|
||||||
cls._instance = super(CityRepo, cls).__new__(cls)
|
cls._instance = super(City, cls).__new__(cls)
|
||||||
return cls._instance
|
return cls._instance
|
||||||
|
|
||||||
def insert(self, city: City, application_id, user_id: int) -> Union[City, Dict]:
|
def insert(self, city: CityHub, application_id, user_id: int) -> Union[Model, Dict]:
|
||||||
"""
|
"""
|
||||||
Insert a city
|
Insert a city
|
||||||
:param city: The complete city instance
|
:param city: The complete city instance
|
||||||
@ -42,9 +42,14 @@ class CityRepo(BaseRepo):
|
|||||||
:return: City and Dictionary
|
:return: City and Dictionary
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
release = __version__
|
db_city = Model(
|
||||||
db_city = DBCity(pickle.dumps(city), city.name, city.level_of_detail, city.climate_file, application_id, user_id,
|
pickle.dumps(city),
|
||||||
release)
|
city.name,
|
||||||
|
city.level_of_detail,
|
||||||
|
city.climate_file,
|
||||||
|
application_id,
|
||||||
|
user_id,
|
||||||
|
__version__)
|
||||||
|
|
||||||
self.session.add(db_city)
|
self.session.add(db_city)
|
||||||
self.session.flush()
|
self.session.flush()
|
||||||
@ -53,18 +58,18 @@ class CityRepo(BaseRepo):
|
|||||||
except SQLAlchemyError as err:
|
except SQLAlchemyError as err:
|
||||||
logger.error(f'An error occurred while creating city: {err}')
|
logger.error(f'An error occurred while creating city: {err}')
|
||||||
|
|
||||||
def get_by_id(self, city_id: int) -> DBCity:
|
def get_by_id(self, city_id: int) -> Model:
|
||||||
"""
|
"""
|
||||||
Fetch a City based on the id
|
Fetch a City based on the id
|
||||||
:param city_id: the city id
|
:param city_id: the city id
|
||||||
:return: a city
|
:return: a city
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
return self.session.execute(select(DBCity).where(DBCity.id == city_id)).first()[0]
|
return self.session.execute(select(Model).where(Model.id == city_id)).first()[0]
|
||||||
except SQLAlchemyError as err:
|
except SQLAlchemyError as err:
|
||||||
logger.error(f'Error while fetching city: {err}')
|
logger.error(f'Error while fetching city: {err}')
|
||||||
|
|
||||||
def _get_by_hub_version(self, hub_release: str, city_name: str) -> City:
|
def _get_by_hub_version_and_name(self, hub_release: str, city_name: str) -> Model:
|
||||||
"""
|
"""
|
||||||
Fetch a City based on the name and hub project
|
Fetch a City based on the name and hub project
|
||||||
:param hub_release: the hub release
|
:param hub_release: the hub release
|
||||||
@ -72,55 +77,50 @@ class CityRepo(BaseRepo):
|
|||||||
:return: a city
|
:return: a city
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
return self.session.execute(select(DBCity)
|
return self.session.execute(select(Model)
|
||||||
.where(DBCity.hub_release == hub_release, DBCity.name == city_name)).first()
|
.where(Model.hub_release == hub_release, Model.name == city_name)
|
||||||
|
).first()
|
||||||
except SQLAlchemyError as err:
|
except SQLAlchemyError as err:
|
||||||
logger.error(f'Error while fetching city: {err}')
|
logger.error(f'Error while fetching city: {err}')
|
||||||
|
|
||||||
def update(self, city_id: int, city: City):
|
def get_by_name(self, city_name: str) -> [Model]:
|
||||||
"""
|
|
||||||
Updates a city
|
|
||||||
:param city_id: the id of the city to be updated
|
|
||||||
:param city: the city object
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
self.session.query(DBCity).filter(DBCity.id == city_id) \
|
|
||||||
.update({
|
|
||||||
'name': city.name, 'srs_name': city.srs_name, 'country_code': city.country_code, 'longitude': city.longitude,
|
|
||||||
'latitude': city.latitude, 'time_zone': city.time_zone, 'lower_corner': city.lower_corner.tolist(),
|
|
||||||
'upper_corner': city.upper_corner.tolist(), 'climate_reference_city': city.climate_reference_city,
|
|
||||||
'updated': datetime.datetime.utcnow()
|
|
||||||
})
|
|
||||||
|
|
||||||
self.session.commit()
|
|
||||||
except SQLAlchemyError as err:
|
|
||||||
logger.error(f'Error while updating city: {err}')
|
|
||||||
|
|
||||||
def get_by_name(self, city_name: str) -> [DBCity]:
|
|
||||||
"""
|
"""
|
||||||
Fetch city based on the name
|
Fetch city based on the name
|
||||||
:param city_name: the name of the building
|
:param city_name: the name of the building
|
||||||
:return: [ModelCity] with the provided name
|
:return: [ModelCity] with the provided name
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
result_set = self.session.execute(select(DBCity).where(DBCity.name == city_name))
|
result_set = self.session.execute(select(Model).where(Model.name == city_name))
|
||||||
return [building[0] for building in result_set]
|
return [building[0] for building in result_set]
|
||||||
except SQLAlchemyError as err:
|
except SQLAlchemyError as err:
|
||||||
logger.error(f'Error while fetching city by name: {err}')
|
logger.error(f'Error while fetching city by name: {err}')
|
||||||
|
|
||||||
def get_by_user(self, user_id: int) -> [DBCity]:
|
def get_by_user(self, user_id: int) -> [Model]:
|
||||||
"""
|
"""
|
||||||
Fetch city based on the user who created it
|
Fetch city based on the user who created it
|
||||||
:param user_id: the id of the user
|
:param user_id: the id of the user
|
||||||
:return: [ModelCity] with the provided name
|
:return: [ModelCity] with the provided name
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
result_set = self.session.execute(select(DBCity).where(DBCity.user_id == user_id))
|
result_set = self.session.execute(select(Model).where(Model.user_id == user_id))
|
||||||
return [building[0] for building in result_set]
|
return [building[0] for building in result_set]
|
||||||
except SQLAlchemyError as err:
|
except SQLAlchemyError as err:
|
||||||
logger.error(f'Error while fetching city by name: {err}')
|
logger.error(f'Error while fetching city by name: {err}')
|
||||||
|
|
||||||
|
def update(self, city_id: int, city: CityHub):
|
||||||
|
"""
|
||||||
|
Updates a city name (other updates makes no sense)
|
||||||
|
:param city_id: the id of the city to be updated
|
||||||
|
:param city: the city object
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
now = datetime.datetime.utcnow()
|
||||||
|
self.session.query(Model).filter(Model.id == city_id).update({'name': city.name,'updated': now})
|
||||||
|
self.session.commit()
|
||||||
|
except SQLAlchemyError as err:
|
||||||
|
logger.error(f'Error while updating city: {err}')
|
||||||
|
|
||||||
def delete_city(self, city_id: int):
|
def delete_city(self, city_id: int):
|
||||||
"""
|
"""
|
||||||
Deletes a City with the id
|
Deletes a City with the id
|
||||||
@ -128,7 +128,7 @@ class CityRepo(BaseRepo):
|
|||||||
:return: a city
|
:return: a city
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
self.session.query(DBCity).filter(DBCity.id == city_id).delete()
|
self.session.query(Model).filter(Model.id == city_id).delete()
|
||||||
self.session.commit()
|
self.session.commit()
|
||||||
except SQLAlchemyError as err:
|
except SQLAlchemyError as err:
|
||||||
logger.error(f'Error while fetching city: {err}')
|
logger.error(f'Error while fetching city: {err}')
|
0
hub/persistence/repositories/city_object.py
Normal file
0
hub/persistence/repositories/city_object.py
Normal file
@ -1,108 +0,0 @@
|
|||||||
"""
|
|
||||||
Heat pump simulation repository with database CRUD operations
|
|
||||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
|
||||||
Copyright © 2022 Concordia CERC group
|
|
||||||
Project Coder Peter Yefi peteryefi@gmail.com
|
|
||||||
"""
|
|
||||||
|
|
||||||
from hub.persistence import BaseRepo, CityRepo
|
|
||||||
from sqlalchemy.exc import SQLAlchemyError
|
|
||||||
from sqlalchemy import select
|
|
||||||
from hub.persistence.models import HeatPumpSimulation
|
|
||||||
from typing import Union, Dict
|
|
||||||
from hub.hub_logger import logger
|
|
||||||
|
|
||||||
|
|
||||||
class HeatPumpSimulationRepo(BaseRepo):
|
|
||||||
_instance = None
|
|
||||||
|
|
||||||
def __init__(self, db_name, dotenv_path, app_env):
|
|
||||||
super().__init__(db_name, dotenv_path, app_env)
|
|
||||||
self._city_repo = CityRepo(db_name, dotenv_path, app_env)
|
|
||||||
|
|
||||||
def __new__(cls, db_name, dotenv_path, app_env):
|
|
||||||
"""
|
|
||||||
Implemented for a singleton pattern
|
|
||||||
"""
|
|
||||||
if cls._instance is None:
|
|
||||||
cls._instance = super(HeatPumpSimulationRepo, cls).__new__(cls)
|
|
||||||
return cls._instance
|
|
||||||
|
|
||||||
def insert(self, hp_sim_data: Dict, city_id: int) -> Union[HeatPumpSimulation, Dict]:
|
|
||||||
"""
|
|
||||||
Inserts the results of heat pump simulation
|
|
||||||
:param hp_sim_data: dictionary with heatpump the simulation inputs and output
|
|
||||||
:param city_id: the city that was used in running the simulation
|
|
||||||
:return: HeatPumpSimulation
|
|
||||||
"""
|
|
||||||
|
|
||||||
city = self._city_repo.get_by_id(city_id)
|
|
||||||
if city is None:
|
|
||||||
return {'message': 'city not found in database'}
|
|
||||||
|
|
||||||
try:
|
|
||||||
hp_simulation = HeatPumpSimulation(city_id, hp_sim_data["HourlyElectricityDemand"],
|
|
||||||
hp_sim_data["DailyElectricityDemand"], hp_sim_data["MonthlyElectricityDemand"],
|
|
||||||
hp_sim_data["DailyFossilFuelConsumption"],
|
|
||||||
hp_sim_data["MonthlyFossilFuelConsumption"])
|
|
||||||
hp_simulation.city_id = city_id
|
|
||||||
hp_simulation.end_year = hp_sim_data["EndYear"]
|
|
||||||
hp_simulation.start_year = hp_sim_data["StartYear"]
|
|
||||||
hp_simulation.max_demand_storage_hour = hp_sim_data["HoursOfStorageAtMaxDemand"]
|
|
||||||
hp_simulation.max_hp_energy_input = hp_sim_data["MaximumHPEnergyInput"]
|
|
||||||
hp_simulation.building_supply_temp = hp_sim_data["BuildingSuppTemp"]
|
|
||||||
hp_simulation.temp_difference = hp_sim_data["TemperatureDifference"]
|
|
||||||
hp_simulation.fuel_lhv = hp_sim_data["FuelLHV"]
|
|
||||||
hp_simulation.fuel_price = hp_sim_data["FuelPrice"]
|
|
||||||
hp_simulation.fuel_efficiency = hp_sim_data["FuelEF"]
|
|
||||||
hp_simulation.fuel_density = hp_sim_data["FuelDensity"]
|
|
||||||
hp_simulation.hp_supply_temp = hp_sim_data["HPSupTemp"]
|
|
||||||
hp_simulation.simulation_type = hp_sim_data["SimulationType"]
|
|
||||||
hp_simulation.heat_pump_model = hp_sim_data["HeatPumpModel"]
|
|
||||||
hp_simulation.heat_pump_type = hp_sim_data["HeatPumpType"]
|
|
||||||
|
|
||||||
# Persist heat pump simulation data
|
|
||||||
self.session.add(hp_simulation)
|
|
||||||
self.session.flush()
|
|
||||||
self.session.commit()
|
|
||||||
return hp_simulation
|
|
||||||
except SQLAlchemyError as err:
|
|
||||||
logger.error(f'Error while saving heat pump simulation data: {err}')
|
|
||||||
except KeyError as err:
|
|
||||||
logger.error(f'A required field is missing in your heat pump simulation dictionary: {err}')
|
|
||||||
|
|
||||||
def get_by_id(self, hp_simulation_id: int) -> HeatPumpSimulation:
|
|
||||||
"""
|
|
||||||
Fetches heat pump simulation data
|
|
||||||
:param hp_simulation_id: the city id
|
|
||||||
:return: a HeatPumpSimulation
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
return self.session.execute(select(HeatPumpSimulation).where(HeatPumpSimulation.id == hp_simulation_id)).first()[
|
|
||||||
0]
|
|
||||||
except SQLAlchemyError as err:
|
|
||||||
logger.error(f'Error while fetching city: {err}')
|
|
||||||
|
|
||||||
def get_by_city(self, city_id: int) -> [HeatPumpSimulation]:
|
|
||||||
"""
|
|
||||||
Fetch heat pump simulation results by city
|
|
||||||
:param city_id: the name of the building
|
|
||||||
:return: [HeatPumpSimulation] with the provided name
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
result_set = self.session.execute(select(HeatPumpSimulation).where(HeatPumpSimulation.city_id == city_id))
|
|
||||||
return [sim_data[0] for sim_data in result_set]
|
|
||||||
except SQLAlchemyError as err:
|
|
||||||
logger.error(f'Error while fetching city by name: {err}')
|
|
||||||
|
|
||||||
def delete_hp_simulation(self, hp_simulation_id: int):
|
|
||||||
"""
|
|
||||||
Deletes a heat pump simulation results
|
|
||||||
:param hp_simulation_id: the heat pump simulation results id
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
self.session.query(HeatPumpSimulation).filter(HeatPumpSimulation.id == hp_simulation_id).delete()
|
|
||||||
self.session.commit()
|
|
||||||
except SQLAlchemyError as err:
|
|
||||||
logger.error(f'Error while fetching city: {err}')
|
|
@ -5,10 +5,10 @@ Copyright © 2022 Concordia CERC group
|
|||||||
Project Coder Peter Yefi peteryefi@gmail.com
|
Project Coder Peter Yefi peteryefi@gmail.com
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from hub.persistence import BaseRepo
|
from hub.persistence import Repository
|
||||||
from sqlalchemy.exc import SQLAlchemyError
|
from sqlalchemy.exc import SQLAlchemyError
|
||||||
from sqlalchemy import select
|
from sqlalchemy import select
|
||||||
from hub.persistence.models import User
|
from hub.persistence.models import User as Model
|
||||||
from hub.persistence.models import UserRoles
|
from hub.persistence.models import UserRoles
|
||||||
from hub.helpers.auth import Auth
|
from hub.helpers.auth import Auth
|
||||||
from typing import Union, Dict
|
from typing import Union, Dict
|
||||||
@ -16,7 +16,7 @@ from hub.hub_logger import logger
|
|||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
|
|
||||||
class UserRepo(BaseRepo):
|
class User(Repository):
|
||||||
_instance = None
|
_instance = None
|
||||||
|
|
||||||
def __init__(self, db_name: str, dotenv_path: str, app_env: str):
|
def __init__(self, db_name: str, dotenv_path: str, app_env: str):
|
||||||
@ -27,14 +27,14 @@ class UserRepo(BaseRepo):
|
|||||||
Implemented for a singleton pattern
|
Implemented for a singleton pattern
|
||||||
"""
|
"""
|
||||||
if cls._instance is None:
|
if cls._instance is None:
|
||||||
cls._instance = super(UserRepo, cls).__new__(cls)
|
cls._instance = super(User, cls).__new__(cls)
|
||||||
return cls._instance
|
return cls._instance
|
||||||
|
|
||||||
def insert(self, name: str, password: str, role: UserRoles, application_id: int) -> Union[User, Dict]:
|
def insert(self, name: str, password: str, role: UserRoles, application_id: int) -> Union[Model, Dict]:
|
||||||
user = self.get_by_name_and_application(name, application_id)
|
user = self.get_by_name_and_application(name, application_id)
|
||||||
if user is None:
|
if user is None:
|
||||||
try:
|
try:
|
||||||
user = User(name=name, password=Auth.hash_password(password), role=role, application_id=application_id)
|
user = Model(name=name, password=Auth.hash_password(password), role=role, application_id=application_id)
|
||||||
self.session.add(user)
|
self.session.add(user)
|
||||||
self.session.flush()
|
self.session.flush()
|
||||||
self.session.commit()
|
self.session.commit()
|
||||||
@ -42,38 +42,42 @@ class UserRepo(BaseRepo):
|
|||||||
except SQLAlchemyError as err:
|
except SQLAlchemyError as err:
|
||||||
logger.error(f'An error occurred while creating user: {err}')
|
logger.error(f'An error occurred while creating user: {err}')
|
||||||
else:
|
else:
|
||||||
return {'message': f'user with {email} email already exists'}
|
return {'message': f'user {name} already exists for that application'}
|
||||||
|
|
||||||
def update(self, user_id: int, name: str, email: str, password: str, role: UserRoles) -> Union[Dict, None]:
|
def update(self, user_id: int, name: str, password: str, role: UserRoles) -> Union[Dict, None]:
|
||||||
"""
|
"""
|
||||||
Updates a user
|
Updates a user
|
||||||
:param user_id: the id of the user to be updated
|
:param user_id: the id of the user to be updated
|
||||||
:param name: the name of the user
|
:param name: the name of the user
|
||||||
:param email: the email of the user
|
|
||||||
:param password: the password of the user
|
:param password: the password of the user
|
||||||
:param role: the role of the user
|
:param role: the role of the user
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
if Auth.validate_password(password):
|
self.session.query(Model).filter(Model.id == user_id).update({
|
||||||
self.session.query(User).filter(User.id == user_id) \
|
'name': name,
|
||||||
.update({'name': name, 'email': email, 'password': Auth.hash_password(password), 'role': role,
|
'password': Auth.hash_password(password),
|
||||||
'updated': datetime.datetime.utcnow()})
|
'role': role,
|
||||||
|
'updated': datetime.datetime.utcnow()
|
||||||
|
})
|
||||||
self.session.commit()
|
self.session.commit()
|
||||||
except SQLAlchemyError as err:
|
except SQLAlchemyError as err:
|
||||||
logger.error(f'Error while updating user: {err}')
|
logger.error(f'Error while updating user: {err}')
|
||||||
return {'err_msg': 'Error occurred while updated user'}
|
return {'err_msg': 'Error occurred while updated user'}
|
||||||
|
|
||||||
def get_by_email(self, email: str) -> [User]:
|
def get_by_name_and_application(self, name: str, application_id: int) -> [Model]:
|
||||||
"""
|
"""
|
||||||
Fetch user based on the email address
|
Fetch user based on the email address
|
||||||
:param email: the email of the user
|
:param name: User name
|
||||||
:return: [User] with the provided email
|
:param application_id: User application name
|
||||||
|
:return: [User] matching the search criteria
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
return self.session.execute(select(User).where(User.email == email)).first()
|
return self.session.execute(
|
||||||
|
select(Model).where(Model.name == name and Model.application_id == application_id)
|
||||||
|
).first()
|
||||||
except SQLAlchemyError as err:
|
except SQLAlchemyError as err:
|
||||||
logger.error(f'Error while fetching user by email: {err}')
|
logger.error(f'Error while fetching user by name and application: {err}')
|
||||||
|
|
||||||
def delete_user(self, user_id: int):
|
def delete_user(self, user_id: int):
|
||||||
"""
|
"""
|
||||||
@ -82,25 +86,27 @@ class UserRepo(BaseRepo):
|
|||||||
:return: None
|
:return: None
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
self.session.query(User).filter(User.id == user_id).delete()
|
self.session.query(Model).filter(Model.id == user_id).delete()
|
||||||
self.session.commit()
|
self.session.commit()
|
||||||
except SQLAlchemyError as err:
|
except SQLAlchemyError as err:
|
||||||
logger.error(f'Error while fetching user: {err}')
|
logger.error(f'Error while fetching user: {err}')
|
||||||
|
|
||||||
def get_user_by_email_and_password(self, email: str, password: str) -> [User]:
|
def get_user_by_name_application_and_password(self, name: str, password: str, application_id: int) -> [Model]:
|
||||||
"""
|
"""
|
||||||
Fetch user based on the email and password
|
Fetch user based on the email and password
|
||||||
:param email: the email of the user
|
:param name: User name
|
||||||
:param password: the password of the user
|
:param password: User password
|
||||||
|
:param application_id: User password
|
||||||
|
|
||||||
:return: [User] with the provided email and password
|
:return: [User] with the provided email and password
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
user = self.session.execute(select(User).where(User.email == email)).first()
|
user = self.session.execute(
|
||||||
|
select(Model).where(Model.name == name and Model.application_id == application_id)
|
||||||
|
).first()
|
||||||
if user:
|
if user:
|
||||||
if Auth.check_password(password, user[0].password):
|
if Auth.check_password(password, user[0].password):
|
||||||
return user
|
return user
|
||||||
else:
|
return {'message': 'invalid login information'}
|
||||||
return {'message': 'Wrong email/password combination'}
|
|
||||||
return {'message': 'user not found'}
|
|
||||||
except SQLAlchemyError as err:
|
except SQLAlchemyError as err:
|
||||||
logger.error(f'Error while fetching user by email: {err}')
|
logger.error(f'Error while fetching user by email: {err}')
|
@ -5,17 +5,17 @@ Copyright © 2022 Concordia CERC group
|
|||||||
Project Coder Peter Yefi peteryefi@gmail.com
|
Project Coder Peter Yefi peteryefi@gmail.com
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from hub.persistence.db_config import BaseConfiguration
|
from hub.persistence.configuration import Configuration
|
||||||
from sqlalchemy import create_engine
|
from sqlalchemy import create_engine
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
|
|
||||||
class BaseRepo:
|
class Repository:
|
||||||
|
|
||||||
def __init__(self, db_name, dotenv_path: str, app_env='TEST'):
|
def __init__(self, db_name, dotenv_path: str, app_env='TEST'):
|
||||||
try:
|
try:
|
||||||
self.config = BaseConfiguration(db_name, dotenv_path, app_env)
|
self.configuration = Configuration(db_name, dotenv_path, app_env)
|
||||||
self.engine = create_engine(self.config.conn_string())
|
self.engine = create_engine(self.configuration.conn_string())
|
||||||
self.session = Session(self.engine)
|
self.session = Session(self.engine)
|
||||||
except ValueError as err:
|
except ValueError as err:
|
||||||
print(f'Missing value for credentials: {err}')
|
print(f'Missing value for credentials: {err}')
|
5
setup.py
5
setup.py
@ -13,7 +13,10 @@ setup(
|
|||||||
description="CERC Hub consist in a set of classes (Central data model), importers and exporters to help researchers "
|
description="CERC Hub consist in a set of classes (Central data model), importers and exporters to help researchers "
|
||||||
"to create better and sustainable cities",
|
"to create better and sustainable cities",
|
||||||
long_description="CERC Hub consist in a set of classes (Central data model), importers and exporters to help "
|
long_description="CERC Hub consist in a set of classes (Central data model), importers and exporters to help "
|
||||||
"researchers to create better and sustainable cities",
|
"researchers to create better and sustainable cities.\n\nDevelop at Concordia university in canada "
|
||||||
|
"as part of the research group from the next generation cities institute our aim among others it's "
|
||||||
|
"to provide a comprehensive set of tools to help researchers and urban developers to make decisions "
|
||||||
|
"to improve the livability and efficiency of our cities",
|
||||||
classifiers=[
|
classifiers=[
|
||||||
"License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)",
|
"License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)",
|
||||||
"Programming Language :: Python",
|
"Programming Language :: Python",
|
||||||
|
Loading…
Reference in New Issue
Block a user