forked from s_ranjbar/city_retrofit
Merge remote-tracking branch 'origin/db_persistence'
# Conflicts: # helpers/enrich_city.py
This commit is contained in:
commit
6c54e82ea3
|
@ -31,6 +31,13 @@ class DBFactory:
|
||||||
"""
|
"""
|
||||||
return self._city_repo.get_by_name(city_name)
|
return self._city_repo.get_by_name(city_name)
|
||||||
|
|
||||||
|
def get_city_by_user(self, user_id):
|
||||||
|
"""
|
||||||
|
Retrieve cities created by user
|
||||||
|
:param user_id: the id of the user
|
||||||
|
"""
|
||||||
|
return self._city_repo.get_by_user(user_id)
|
||||||
|
|
||||||
def get_hp_simulation(self, hp_sim_id: int):
|
def get_hp_simulation(self, hp_sim_id: int):
|
||||||
"""
|
"""
|
||||||
Retrieve a single heat pump simulation from postgres
|
Retrieve a single heat pump simulation from postgres
|
||||||
|
|
|
@ -9,6 +9,7 @@ from typing import List, Union, Dict
|
||||||
import yaml
|
import yaml
|
||||||
from string import Template
|
from string import Template
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
|
from hub_logger import logger
|
||||||
|
|
||||||
|
|
||||||
class HeatPumpExport:
|
class HeatPumpExport:
|
||||||
|
@ -56,13 +57,15 @@ class HeatPumpExport:
|
||||||
insel_file_handler.write(insel_template)
|
insel_file_handler.write(insel_template)
|
||||||
# Now run insel
|
# Now run insel
|
||||||
self._delete_existing_output_files()
|
self._delete_existing_output_files()
|
||||||
os.system('/usr/local/bin/insel {}'.format(insel_file))
|
logger.info(f'Running Insel with user input: {user_input} and coefficients {capacity_coeff}')
|
||||||
|
os.system('insel {}'.format(insel_file))
|
||||||
# Writer headers to csv output files generated by insel
|
# Writer headers to csv output files generated by insel
|
||||||
self._write_insel_output_headers()
|
self._write_insel_output_headers()
|
||||||
# User output
|
# User output
|
||||||
return self._get_user_out_put()
|
return self._get_user_out_put()
|
||||||
except IOError as err:
|
except IOError as err:
|
||||||
print("I/O exception: {}".format(err))
|
print("I/O exception: {}".format(err))
|
||||||
|
logger.error(f'An I/O error occurred while running insel: {err}')
|
||||||
finally:
|
finally:
|
||||||
insel_file_handler.close()
|
insel_file_handler.close()
|
||||||
insel_template_handler.close()
|
insel_template_handler.close()
|
||||||
|
|
0
helpers/enrich_city.py
Normal file
0
helpers/enrich_city.py
Normal file
|
@ -12,6 +12,7 @@ from catalog_factories.construction_catalog_factory import ConstructionCatalogFa
|
||||||
from city_model_structure.building_demand.layer import Layer
|
from city_model_structure.building_demand.layer import Layer
|
||||||
from city_model_structure.building_demand.material import Material
|
from city_model_structure.building_demand.material import Material
|
||||||
from imports.construction.helpers.construction_helper import ConstructionHelper
|
from imports.construction.helpers.construction_helper import ConstructionHelper
|
||||||
|
from hub_logger import logger
|
||||||
|
|
||||||
|
|
||||||
class UsPhysicsParameters(NrelPhysicsInterface):
|
class UsPhysicsParameters(NrelPhysicsInterface):
|
||||||
|
@ -34,9 +35,14 @@ class UsPhysicsParameters(NrelPhysicsInterface):
|
||||||
try:
|
try:
|
||||||
archetype = self._search_archetype(building.function, building.year_of_construction, self._climate_zone)
|
archetype = self._search_archetype(building.function, building.year_of_construction, self._climate_zone)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
|
|
||||||
|
logger.error(f'Building {building.name} has unknown archetype for building function: {building.function} '
|
||||||
|
f'and building year of construction: {building.year_of_construction} '
|
||||||
|
f'and climate zone reference norm {self._climate_zone}\n')
|
||||||
sys.stderr.write(f'Building {building.name} has unknown archetype for building function: {building.function} '
|
sys.stderr.write(f'Building {building.name} has unknown archetype for building function: {building.function} '
|
||||||
f'and building year of construction: {building.year_of_construction} '
|
f'and building year of construction: {building.year_of_construction} '
|
||||||
f'and climate zone reference norm {self._climate_zone}\n')
|
f'and climate zone reference norm {self._climate_zone}\n')
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
# if building has no thermal zones defined from geometry, and the building will be divided in storeys,
|
# if building has no thermal zones defined from geometry, and the building will be divided in storeys,
|
||||||
|
|
|
@ -19,11 +19,11 @@ class DBFactory:
|
||||||
self._city_repo = CityRepo(db_name=db_name, dotenv_path=dotenv_path, app_env=app_env)
|
self._city_repo = CityRepo(db_name=db_name, dotenv_path=dotenv_path, app_env=app_env)
|
||||||
self._hp_simulation_repo = HeatPumpSimulationRepo(db_name=db_name, dotenv_path=dotenv_path, app_env=app_env)
|
self._hp_simulation_repo = HeatPumpSimulationRepo(db_name=db_name, dotenv_path=dotenv_path, app_env=app_env)
|
||||||
|
|
||||||
def persist_city(self):
|
def persist_city(self, user_id: int):
|
||||||
"""
|
"""
|
||||||
Persist city into postgres database
|
Persist city into postgres database
|
||||||
"""
|
"""
|
||||||
return self._city_repo.insert(self._city)
|
return self._city_repo.insert(self._city, user_id)
|
||||||
|
|
||||||
def update_city(self, city_id, city):
|
def update_city(self, city_id, city):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -17,9 +17,9 @@ class DBSetup:
|
||||||
:param dotenv_path:
|
:param dotenv_path:
|
||||||
"""
|
"""
|
||||||
repo = BaseRepo(db_name=db_name, app_env=app_env, dotenv_path=dotenv_path)
|
repo = BaseRepo(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)
|
City.__table__.create(bind=repo.engine, checkfirst=True)
|
||||||
HeatPumpSimulation.__table__.create(bind=repo.engine, checkfirst=True)
|
HeatPumpSimulation.__table__.create(bind=repo.engine, checkfirst=True)
|
||||||
User.__table__.create(bind=repo.engine, checkfirst=True)
|
|
||||||
self._user_repo = UserRepo(db_name=db_name, app_env=app_env, dotenv_path=dotenv_path)
|
self._user_repo = UserRepo(db_name=db_name, app_env=app_env, dotenv_path=dotenv_path)
|
||||||
self._create_admin_user(self._user_repo)
|
self._create_admin_user(self._user_repo)
|
||||||
|
|
||||||
|
@ -29,9 +29,8 @@ class DBSetup:
|
||||||
print('Creating default admin user...')
|
print('Creating default admin user...')
|
||||||
user = user_repo.insert('Administrator', email, password, UserRoles.Admin)
|
user = user_repo.insert('Administrator', email, password, UserRoles.Admin)
|
||||||
if type(user) is dict:
|
if type(user) is dict:
|
||||||
print(user)
|
|
||||||
logger.info(user)
|
logger.info(user)
|
||||||
else:
|
else:
|
||||||
print(f'Created Admin user with email: {email}, password: {password} and role: {UserRoles.Admin}')
|
print(f'Created Admin user with email: {email}, password: {password} and role: {UserRoles.Admin.value}')
|
||||||
logger.info(f'Created Admin user with email: {email}, password: {password} and role: {UserRoles.Admin}')
|
logger.info(f'Created Admin user with email: {email}, password: {password} and role: {UserRoles.Admin.value}')
|
||||||
print('Remember to change the admin default password and email address with the UserFactory')
|
print('Remember to change the admin default password and email address with the UserFactory')
|
||||||
|
|
|
@ -5,10 +5,11 @@ Copyright © 2022 Concordia CERC group
|
||||||
Project Coder Peter Yefi peteryefi@gmail.com
|
Project Coder Peter Yefi peteryefi@gmail.com
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from sqlalchemy import Column, Integer, String, Sequence
|
from sqlalchemy import Column, Integer, String, Sequence, ForeignKey
|
||||||
from sqlalchemy import DateTime, PickleType, Float
|
from sqlalchemy import DateTime, PickleType, Float
|
||||||
from persistence.db_config import Base
|
from persistence.db_config import Base
|
||||||
from sqlalchemy.dialects.postgresql import JSONB
|
from sqlalchemy.dialects.postgresql import JSONB
|
||||||
|
from sqlalchemy.orm import relationship
|
||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
|
|
||||||
|
@ -29,10 +30,14 @@ class City(Base):
|
||||||
upper_corner = Column(JSONB, nullable=False)
|
upper_corner = Column(JSONB, nullable=False)
|
||||||
hub_release = Column(String, nullable=False)
|
hub_release = Column(String, nullable=False)
|
||||||
city_version = Column(Integer, nullable=False)
|
city_version = Column(Integer, nullable=False)
|
||||||
|
user_id = Column(Integer, ForeignKey('user.id'))
|
||||||
|
user = relationship("User", back_populates="cities")
|
||||||
created = Column(DateTime, default=datetime.datetime.utcnow)
|
created = Column(DateTime, default=datetime.datetime.utcnow)
|
||||||
|
updated = Column(DateTime, default=datetime.datetime.utcnow)
|
||||||
|
|
||||||
def __init__(self, city, name, srs_name, country_code, l_corner, u_corner):
|
def __init__(self, city, name, srs_name, country_code, l_corner, u_corner, user_id):
|
||||||
self.city = city
|
self.city = city
|
||||||
|
self.user_id = user_id
|
||||||
self.name = name
|
self.name = name
|
||||||
self.srs_name = srs_name
|
self.srs_name = srs_name
|
||||||
self.country_code = country_code
|
self.country_code = country_code
|
||||||
|
|
|
@ -12,11 +12,12 @@ import datetime
|
||||||
from sqlalchemy.orm import validates
|
from sqlalchemy.orm import validates
|
||||||
import re
|
import re
|
||||||
import enum
|
import enum
|
||||||
|
from sqlalchemy.orm import relationship
|
||||||
|
|
||||||
|
|
||||||
class UserRoles(enum.Enum):
|
class UserRoles(enum.Enum):
|
||||||
Admin = 'ADMIN'
|
Admin = 'Admin'
|
||||||
HubReader = 'HUB_READER'
|
Hub_Reader = 'Hub_Reader'
|
||||||
|
|
||||||
|
|
||||||
class User(Base):
|
class User(Base):
|
||||||
|
@ -27,7 +28,8 @@ class User(Base):
|
||||||
name = Column(String, nullable=False)
|
name = Column(String, nullable=False)
|
||||||
email = Column(String, nullable=False, unique=True)
|
email = Column(String, nullable=False, unique=True)
|
||||||
password = Column(String, nullable=False)
|
password = Column(String, nullable=False)
|
||||||
role = Column(Enum(UserRoles), nullable=False, default=UserRoles.HubReader)
|
role = Column(Enum(UserRoles), nullable=False, default=UserRoles.Hub_Reader)
|
||||||
|
cities = relationship("City", back_populates="user")
|
||||||
created = Column(DateTime, default=datetime.datetime.utcnow)
|
created = Column(DateTime, default=datetime.datetime.utcnow)
|
||||||
updated = Column(DateTime, default=datetime.datetime.utcnow)
|
updated = Column(DateTime, default=datetime.datetime.utcnow)
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@ import requests
|
||||||
from urllib3.exceptions import HTTPError
|
from urllib3.exceptions import HTTPError
|
||||||
from typing import Union, Dict
|
from typing import Union, Dict
|
||||||
from hub_logger import logger
|
from hub_logger import logger
|
||||||
|
import datetime
|
||||||
|
|
||||||
|
|
||||||
class CityRepo(BaseRepo):
|
class CityRepo(BaseRepo):
|
||||||
|
@ -31,9 +32,9 @@ class CityRepo(BaseRepo):
|
||||||
cls._instance = super(CityRepo, cls).__new__(cls)
|
cls._instance = super(CityRepo, cls).__new__(cls)
|
||||||
return cls._instance
|
return cls._instance
|
||||||
|
|
||||||
def insert(self, city: City) -> Union[City, Dict]:
|
def insert(self, city: City, user_id: int) -> Union[City, Dict]:
|
||||||
db_city = DBCity(pickle.dumps(city), city.name, city.srs_name, city.country_code, city.lower_corner,
|
db_city = DBCity(pickle.dumps(city), city.name, city.srs_name, city.country_code, city.lower_corner,
|
||||||
city.upper_corner)
|
city.upper_corner, user_id)
|
||||||
db_city.climate_reference_city = city.climate_reference_city
|
db_city.climate_reference_city = city.climate_reference_city
|
||||||
db_city.longitude = city.longitude
|
db_city.longitude = city.longitude
|
||||||
db_city.latitude = city.latitude
|
db_city.latitude = city.latitude
|
||||||
|
@ -107,6 +108,7 @@ class CityRepo(BaseRepo):
|
||||||
'name': city.name, 'srs_name': city.srs_name, 'country_code': city.country_code, 'longitude': city.longitude,
|
'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(),
|
'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,
|
'upper_corner': city.upper_corner.tolist(), 'climate_reference_city': city.climate_reference_city,
|
||||||
|
'updated': datetime.datetime.utcnow()
|
||||||
})
|
})
|
||||||
|
|
||||||
self.session.commit()
|
self.session.commit()
|
||||||
|
@ -125,6 +127,18 @@ class CityRepo(BaseRepo):
|
||||||
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]:
|
||||||
|
"""
|
||||||
|
Fetch city based on the user who created it
|
||||||
|
:param user_id: the id of the user
|
||||||
|
:return: [ModelCity] with the provided name
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
result_set = self.session.execute(select(DBCity).where(DBCity.user_id == user_id))
|
||||||
|
return [building[0] for building in result_set]
|
||||||
|
except SQLAlchemyError as err:
|
||||||
|
logger.error(f'Error while fetching city by name: {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
|
||||||
|
|
|
@ -13,6 +13,7 @@ from persistence.models import UserRoles
|
||||||
from helpers.auth import Auth
|
from helpers.auth import Auth
|
||||||
from typing import Union, Dict
|
from typing import Union, Dict
|
||||||
from hub_logger import logger
|
from hub_logger import logger
|
||||||
|
import datetime
|
||||||
|
|
||||||
|
|
||||||
class UserRepo(BaseRepo):
|
class UserRepo(BaseRepo):
|
||||||
|
@ -44,7 +45,7 @@ class UserRepo(BaseRepo):
|
||||||
else:
|
else:
|
||||||
return {'message': f'user with {email} email already exists'}
|
return {'message': f'user with {email} email already exists'}
|
||||||
|
|
||||||
def update(self, user_id: int, name: str, email: str, password: str, role: UserRoles):
|
def update(self, user_id: int, name: str, email: 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
|
||||||
|
@ -57,10 +58,12 @@ class UserRepo(BaseRepo):
|
||||||
try:
|
try:
|
||||||
if Auth.validate_password(password):
|
if Auth.validate_password(password):
|
||||||
self.session.query(User).filter(User.id == user_id) \
|
self.session.query(User).filter(User.id == user_id) \
|
||||||
.update({'name': name, 'email': email, 'password': Auth.hash_password(password), 'role': role})
|
.update({'name': name, 'email': email, 'password': Auth.hash_password(password), '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 occured while updated user'}
|
||||||
|
|
||||||
def get_by_email(self, email: str) -> [User]:
|
def get_by_email(self, email: str) -> [User]:
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -7,10 +7,12 @@ Project Coder Peter Yefi peteryefi@gmail.com
|
||||||
from unittest import TestCase
|
from unittest import TestCase
|
||||||
from imports.geometry_factory import GeometryFactory
|
from imports.geometry_factory import GeometryFactory
|
||||||
from imports.db_factory import DBFactory
|
from imports.db_factory import DBFactory
|
||||||
|
from imports.user_factory import UserFactory
|
||||||
from exports.db_factory import DBFactory as ExportDBFactory
|
from exports.db_factory import DBFactory as ExportDBFactory
|
||||||
from persistence.base_repo import BaseRepo
|
from persistence.base_repo import BaseRepo
|
||||||
from sqlalchemy import create_engine
|
from sqlalchemy import create_engine
|
||||||
from persistence.models import City
|
from persistence.models import City
|
||||||
|
from persistence.models import User, UserRoles
|
||||||
from pickle import loads
|
from pickle import loads
|
||||||
from sqlalchemy.exc import ProgrammingError
|
from sqlalchemy.exc import ProgrammingError
|
||||||
|
|
||||||
|
@ -43,16 +45,18 @@ class TestDBFactory(TestCase):
|
||||||
cnn.execute('commit')
|
cnn.execute('commit')
|
||||||
cnn.execute("CREATE DATABASE test_db")
|
cnn.execute("CREATE DATABASE test_db")
|
||||||
cnn.close()
|
cnn.close()
|
||||||
|
User.__table__.create(bind=repo.engine, checkfirst=True)
|
||||||
City.__table__.create(bind=repo.engine, checkfirst=True)
|
City.__table__.create(bind=repo.engine, checkfirst=True)
|
||||||
|
|
||||||
city_file = "../unittests/tests_data/C40_Final.gml"
|
city_file = "../unittests/tests_data/C40_Final.gml"
|
||||||
cls.city = GeometryFactory('citygml', city_file).city
|
cls.city = GeometryFactory('citygml', city_file).city
|
||||||
cls._db_factory = DBFactory(city=cls.city, db_name='test_db', app_env='TEST', dotenv_path='../.env')
|
cls._db_factory = DBFactory(city=cls.city, db_name='test_db', app_env='TEST', dotenv_path='../.env')
|
||||||
cls._export_db_factory = ExportDBFactory(db_name='test_db', app_env='TEST', dotenv_path='../.env')
|
cls._export_db_factory = ExportDBFactory(db_name='test_db', app_env='TEST', dotenv_path='../.env')
|
||||||
|
user_factory = UserFactory(db_name='test_db', app_env='TEST', dotenv_path='../.env')
|
||||||
|
cls._user = user_factory.create_user("Admin", "admin@hub.com", "Admin@123", UserRoles.Admin)
|
||||||
|
|
||||||
def test_save_city(self):
|
def test_save_city(self):
|
||||||
saved_city = self._db_factory.persist_city()
|
saved_city = self._db_factory.persist_city(self._user.id)
|
||||||
self.assertEqual(saved_city.name, 'Montréal')
|
self.assertEqual(saved_city.name, 'Montréal')
|
||||||
pickled_city = loads(saved_city.city)
|
pickled_city = loads(saved_city.city)
|
||||||
self.assertEqual(len(pickled_city.buildings), 10)
|
self.assertEqual(len(pickled_city.buildings), 10)
|
||||||
|
@ -60,27 +64,33 @@ class TestDBFactory(TestCase):
|
||||||
self._db_factory.delete_city(saved_city.id)
|
self._db_factory.delete_city(saved_city.id)
|
||||||
|
|
||||||
def test_save_same_city_with_same_hub_version(self):
|
def test_save_same_city_with_same_hub_version(self):
|
||||||
first_city = self._db_factory.persist_city()
|
first_city = self._db_factory.persist_city(self._user.id)
|
||||||
second_city = self._db_factory.persist_city()
|
second_city = self._db_factory.persist_city(self._user.id)
|
||||||
self.assertEqual(second_city['message'], f'Same version of {self.city.name} exist')
|
self.assertEqual(second_city['message'], f'Same version of {self.city.name} exist')
|
||||||
self.assertEqual(first_city.name, 'Montréal')
|
self.assertEqual(first_city.name, 'Montréal')
|
||||||
self.assertEqual(first_city.country_code, 'ca')
|
self.assertEqual(first_city.country_code, 'ca')
|
||||||
self._db_factory.delete_city(first_city.id)
|
self._db_factory.delete_city(first_city.id)
|
||||||
|
|
||||||
def test_get_city_by_name(self):
|
def test_get_city_by_name(self):
|
||||||
city = self._db_factory.persist_city()
|
city = self._db_factory.persist_city(self._user.id)
|
||||||
retrieved_city = self._export_db_factory.get_city_by_name(city.name)
|
retrieved_city = self._export_db_factory.get_city_by_name(city.name)
|
||||||
self.assertEqual(retrieved_city[0].lower_corner[0], 610610.7547462888)
|
self.assertEqual(retrieved_city[0].lower_corner[0], 610610.7547462888)
|
||||||
self._db_factory.delete_city(city.id)
|
self._db_factory.delete_city(city.id)
|
||||||
|
|
||||||
|
def test_get_city_by_user(self):
|
||||||
|
city = self._db_factory.persist_city(self._user.id)
|
||||||
|
retrieved_city = self._export_db_factory.get_city_by_user(self._user.id)
|
||||||
|
self.assertEqual(retrieved_city[0].user_id, self._user.id)
|
||||||
|
self._db_factory.delete_city(city.id)
|
||||||
|
|
||||||
def test_get_city_by_id(self):
|
def test_get_city_by_id(self):
|
||||||
city = self._db_factory.persist_city()
|
city = self._db_factory.persist_city(self._user.id)
|
||||||
retrieved_city = self._export_db_factory.get_city(city.id)
|
retrieved_city = self._export_db_factory.get_city(city.id)
|
||||||
self.assertEqual(retrieved_city.upper_corner[0], 610818.6731258357)
|
self.assertEqual(retrieved_city.upper_corner[0], 610818.6731258357)
|
||||||
self._db_factory.delete_city(city.id)
|
self._db_factory.delete_city(city.id)
|
||||||
|
|
||||||
def test_get_update_city(self):
|
def test_get_update_city(self):
|
||||||
city = self._db_factory.persist_city()
|
city = self._db_factory.persist_city(self._user.id)
|
||||||
self.city.longitude = 1.43589
|
self.city.longitude = 1.43589
|
||||||
self.city.latitude = -9.38928339
|
self.city.latitude = -9.38928339
|
||||||
self._db_factory.update_city(city.id, self.city)
|
self._db_factory.update_city(city.id, self.city)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user