forked from s_ranjbar/city_retrofit
Partial correction in persistence and geometry_helper.py
This commit is contained in:
parent
1c4920d0b0
commit
5fb361e74c
|
@ -12,6 +12,7 @@ import numpy as np
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
from trimesh import Trimesh
|
from trimesh import Trimesh
|
||||||
from trimesh import intersections
|
from trimesh import intersections
|
||||||
|
from typing import Dict
|
||||||
|
|
||||||
from hub.city_model_structure.attributes.polygon import Polygon
|
from hub.city_model_structure.attributes.polygon import Polygon
|
||||||
from hub.city_model_structure.attributes.polyhedron import Polyhedron
|
from hub.city_model_structure.attributes.polyhedron import Polyhedron
|
||||||
|
@ -25,10 +26,16 @@ class MapPoint:
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def x(self):
|
def x(self):
|
||||||
|
"""
|
||||||
|
Get X Coordinate
|
||||||
|
"""
|
||||||
return self._x
|
return self._x
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def y(self):
|
def y(self):
|
||||||
|
"""
|
||||||
|
Get Y Coordinate
|
||||||
|
"""
|
||||||
return self._y
|
return self._y
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
@ -57,6 +64,10 @@ class GeometryHelper:
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def factor():
|
def factor():
|
||||||
|
"""
|
||||||
|
Set minimap resolution
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
return 0.5
|
return 0.5
|
||||||
|
|
||||||
def __init__(self, delta=0, area_delta=0):
|
def __init__(self, delta=0, area_delta=0):
|
||||||
|
@ -65,15 +76,24 @@ class GeometryHelper:
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def coordinate_to_map_point(coordinate, city):
|
def coordinate_to_map_point(coordinate, city):
|
||||||
|
"""
|
||||||
|
Transform a real world coordinate to a minimap one
|
||||||
|
:param coordinate: real world coordinate
|
||||||
|
:param city: current city
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
factor = GeometryHelper.factor()
|
factor = GeometryHelper.factor()
|
||||||
return MapPoint(
|
return MapPoint(
|
||||||
((coordinate[0] - city.lower_corner[0]) * factor), ((coordinate[1] - city.lower_corner[1]) * factor)
|
((coordinate[0] - city.lower_corner[0]) * factor), ((coordinate[1] - city.lower_corner[1]) * factor)
|
||||||
)
|
)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def city_mapping(city, building_names=None, plot=False):
|
def city_mapping(city, building_names=None, plot=False) -> Dict:
|
||||||
"""
|
"""
|
||||||
Returns a shared_information dictionary
|
:param city: city to be mapped
|
||||||
|
:param building_names: list of building names to be mapped or None
|
||||||
|
:param plot: True if minimap image should be displayed
|
||||||
|
:return: shared_information dictionary
|
||||||
"""
|
"""
|
||||||
lines_information = {}
|
lines_information = {}
|
||||||
if building_names is None:
|
if building_names is None:
|
||||||
|
@ -182,7 +202,8 @@ class GeometryHelper:
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def segment_list_to_trimesh(lines) -> Trimesh:
|
def segment_list_to_trimesh(lines) -> Trimesh:
|
||||||
"""
|
"""
|
||||||
Transform a list of segments into a Trimesh
|
:param lines: lines
|
||||||
|
:return: Transform a list of segments into a Trimesh
|
||||||
"""
|
"""
|
||||||
# todo: trimesh has a method for this
|
# todo: trimesh has a method for this
|
||||||
line_points = [lines[0][0], lines[0][1]]
|
line_points = [lines[0][0], lines[0][1]]
|
||||||
|
@ -262,6 +283,9 @@ class GeometryHelper:
|
||||||
def get_location(latitude, longitude) -> Location:
|
def get_location(latitude, longitude) -> Location:
|
||||||
"""
|
"""
|
||||||
Get Location from latitude and longitude
|
Get Location from latitude and longitude
|
||||||
|
:param latitude: Latitude
|
||||||
|
:param longitude: Longitude
|
||||||
|
:return: Location
|
||||||
"""
|
"""
|
||||||
_data_path = Path(Path(__file__).parent.parent / 'data/geolocation/cities15000.txt').resolve()
|
_data_path = Path(Path(__file__).parent.parent / 'data/geolocation/cities15000.txt').resolve()
|
||||||
latitude = float(latitude)
|
latitude = float(latitude)
|
||||||
|
|
|
@ -36,7 +36,6 @@ class CityObject(Models):
|
||||||
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)
|
||||||
|
|
||||||
# def __init__(self, city_id, name, alias, object_type, year_of_construction, function, usage, volume, area):
|
|
||||||
def __init__(self, city_id, building: Building):
|
def __init__(self, city_id, building: Building):
|
||||||
self.city_id = city_id
|
self.city_id = city_id
|
||||||
self.name = building.name
|
self.name = building.name
|
||||||
|
@ -49,7 +48,6 @@ class CityObject(Models):
|
||||||
self.area = building.floor_area
|
self.area = building.floor_area
|
||||||
storeys = building.storeys_above_ground
|
storeys = building.storeys_above_ground
|
||||||
if storeys is None:
|
if storeys is None:
|
||||||
print(building.average_storey_height)
|
|
||||||
storeys = building.max_height / building.average_storey_height
|
storeys = building.max_height / building.average_storey_height
|
||||||
self.total_heating_area = building.floor_area * storeys
|
self.total_heating_area = building.floor_area * storeys
|
||||||
wall_area = 0
|
wall_area = 0
|
||||||
|
|
|
@ -5,12 +5,12 @@ Copyright © 2022 Concordia CERC group
|
||||||
Project Coder Guille Gutierrez Guillermo.GutierrezMorote@concordia.ca
|
Project Coder Guille Gutierrez Guillermo.GutierrezMorote@concordia.ca
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import logging
|
|
||||||
import datetime
|
import datetime
|
||||||
from typing import Union, Dict
|
import logging
|
||||||
|
|
||||||
from sqlalchemy import select
|
from sqlalchemy import select
|
||||||
from sqlalchemy.exc import SQLAlchemyError
|
from sqlalchemy.exc import SQLAlchemyError
|
||||||
|
|
||||||
from hub.persistence import Repository
|
from hub.persistence import Repository
|
||||||
from hub.persistence.models import Application as Model
|
from hub.persistence.models import Application as Model
|
||||||
|
|
||||||
|
@ -32,33 +32,33 @@ class Application(Repository):
|
||||||
cls._instance = super(Application, 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[Model, Dict]:
|
def insert(self, name: str, description: str, application_uuid: str):
|
||||||
"""
|
"""
|
||||||
Inserts a new application
|
Inserts a new application
|
||||||
:param name: Application name
|
:param name: Application name
|
||||||
:param description: Application description
|
:param description: Application description
|
||||||
:param application_uuid: Unique identifier for the application
|
:param application_uuid: Unique identifier for the application
|
||||||
:return: application and dictionary
|
:return: None
|
||||||
"""
|
"""
|
||||||
application = self.get_by_uuid(application_uuid)
|
application = self.get_by_uuid(application_uuid)
|
||||||
if application is None:
|
if application is not None:
|
||||||
try:
|
raise SQLAlchemyError('application already exists')
|
||||||
application = Model(name=name, description=description, application_uuid=application_uuid)
|
try:
|
||||||
|
application = Model(name=name, description=description, application_uuid=application_uuid)
|
||||||
|
self.session.add(application)
|
||||||
|
self.session.commit()
|
||||||
|
except SQLAlchemyError as err:
|
||||||
|
error_message = f'An error occurred while creating application: {err}'
|
||||||
|
logging.error(error_message)
|
||||||
|
raise SQLAlchemyError(error_message)
|
||||||
|
|
||||||
self.session.add(application)
|
def update(self, application_uuid: str, name: str, description: str):
|
||||||
self.session.commit()
|
|
||||||
return application
|
|
||||||
except SQLAlchemyError as err:
|
|
||||||
logging.error('An error occurred while creating application: %s', err)
|
|
||||||
return {'message': f'An error occurred while creating application {application_uuid}'}
|
|
||||||
|
|
||||||
def update(self, application_uuid: str, name: str, description: str) -> Union[Dict, None]:
|
|
||||||
"""
|
"""
|
||||||
Updates an application
|
Updates an application
|
||||||
:param application_uuid: the application uuid of the application to be updated
|
:param application_uuid: the application uuid of the application to be updated
|
||||||
:param name: the application name
|
:param name: the application name
|
||||||
:param description: the application description
|
:param description: the application description
|
||||||
:return:
|
:return: None
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
self.session.query(Model).filter(
|
self.session.query(Model).filter(
|
||||||
|
@ -66,9 +66,9 @@ class Application(Repository):
|
||||||
).update({'name': name, 'description': description, 'updated': datetime.datetime.utcnow()})
|
).update({'name': name, 'description': description, 'updated': datetime.datetime.utcnow()})
|
||||||
self.session.commit()
|
self.session.commit()
|
||||||
except SQLAlchemyError as err:
|
except SQLAlchemyError as err:
|
||||||
logging.error('Error while updating application %s', err)
|
error_message = f'Error while updating application {err}'
|
||||||
return {'message': 'Error occurred while updating application'}
|
logging.error(error_message)
|
||||||
return None
|
raise SQLAlchemyError(error_message)
|
||||||
|
|
||||||
def delete(self, application_uuid: str):
|
def delete(self, application_uuid: str):
|
||||||
"""
|
"""
|
||||||
|
@ -81,21 +81,27 @@ class Application(Repository):
|
||||||
self.session.flush()
|
self.session.flush()
|
||||||
self.session.commit()
|
self.session.commit()
|
||||||
except SQLAlchemyError as err:
|
except SQLAlchemyError as err:
|
||||||
logging.error('Error while deleting application: %s', err)
|
error_message = f'Error while deleting application {err}'
|
||||||
|
logging.error(error_message)
|
||||||
|
raise SQLAlchemyError(error_message)
|
||||||
|
|
||||||
def get_by_uuid(self, application_uuid: str) -> Union[Model, None]:
|
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 or None
|
:return: Application with the provided application_uuid
|
||||||
"""
|
"""
|
||||||
result_set = None
|
|
||||||
try:
|
try:
|
||||||
result_set = self.session.execute(select(Model).where(
|
result_set = self.session.execute(select(Model).where(
|
||||||
Model.application_uuid == application_uuid)
|
Model.application_uuid == application_uuid)
|
||||||
).first()
|
).first()
|
||||||
|
return result_set[0]
|
||||||
except SQLAlchemyError as err:
|
except SQLAlchemyError as err:
|
||||||
logging.error('Error while fetching application by application_uuid: %s', err)
|
error_message = f'Error while fetching application by application_uuid {err}'
|
||||||
if result_set is None:
|
logging.error(error_message)
|
||||||
return None
|
raise SQLAlchemyError(error_message)
|
||||||
return result_set[0]
|
except IndexError as err:
|
||||||
|
error_message = f'Error while fetching application, empty result {err}'
|
||||||
|
logging.error(error_message)
|
||||||
|
raise IndexError(error_message)
|
||||||
|
|
|
@ -4,9 +4,8 @@ SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||||
Copyright © 2022 Concordia CERC group
|
Copyright © 2022 Concordia CERC group
|
||||||
Project Coder Peter Yefi peteryefi@gmail.com
|
Project Coder Peter Yefi peteryefi@gmail.com
|
||||||
"""
|
"""
|
||||||
import logging
|
|
||||||
import datetime
|
import datetime
|
||||||
from typing import Union
|
import logging
|
||||||
|
|
||||||
from sqlalchemy import select
|
from sqlalchemy import select
|
||||||
from sqlalchemy.exc import SQLAlchemyError
|
from sqlalchemy.exc import SQLAlchemyError
|
||||||
|
@ -35,14 +34,14 @@ class City(Repository):
|
||||||
cls._instance = super(City, cls).__new__(cls)
|
cls._instance = super(City, cls).__new__(cls)
|
||||||
return cls._instance
|
return cls._instance
|
||||||
|
|
||||||
def insert(self, city: CityHub, pickle_path, application_id, user_id: int) -> Union[Model, None]:
|
def insert(self, city: CityHub, pickle_path, application_id, user_id: int):
|
||||||
"""
|
"""
|
||||||
Inserts a city
|
Inserts a city
|
||||||
:param city: The complete city instance
|
:param city: The complete city instance
|
||||||
:param pickle_path: Path to the pickle
|
:param pickle_path: Path to the pickle
|
||||||
:param application_id: Application id owning the instance
|
:param application_id: Application id owning the instance
|
||||||
:param user_id: User id owning the instance
|
:param user_id: User id owning the instance
|
||||||
:return: City and None
|
:return: None
|
||||||
"""
|
"""
|
||||||
city.save_compressed(pickle_path)
|
city.save_compressed(pickle_path)
|
||||||
try:
|
try:
|
||||||
|
@ -64,39 +63,43 @@ class City(Repository):
|
||||||
self.session.add(db_city_object)
|
self.session.add(db_city_object)
|
||||||
self.session.flush()
|
self.session.flush()
|
||||||
self.session.commit()
|
self.session.commit()
|
||||||
return db_city
|
|
||||||
except SQLAlchemyError as err:
|
except SQLAlchemyError as err:
|
||||||
logging.error('An error occurred while creating city: %s', err)
|
error_message = f'An error occurred while creating a city: {err}'
|
||||||
return None
|
logging.error(error_message)
|
||||||
|
raise SQLAlchemyError(error_message)
|
||||||
|
|
||||||
def update(self, city_id: int, city: CityHub):
|
def update(self, city_id: int, city: CityHub):
|
||||||
"""
|
"""
|
||||||
Updates a city name (other updates makes no sense)
|
Updates a city name (other updates makes no sense)
|
||||||
:param city_id: the id of the city to be updated
|
:param city_id: the id of the city to be updated
|
||||||
:param city: the city object
|
:param city: the city object
|
||||||
:return:
|
:return: None
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
now = datetime.datetime.utcnow()
|
now = datetime.datetime.utcnow()
|
||||||
self.session.query(Model).filter(Model.id == city_id).update({'name': city.name, 'updated': now})
|
self.session.query(Model).filter(Model.id == city_id).update({'name': city.name, 'updated': now})
|
||||||
self.session.commit()
|
self.session.commit()
|
||||||
except SQLAlchemyError as err:
|
except SQLAlchemyError as err:
|
||||||
logging.error('Error while updating city: %s', err)
|
error_message = f'Error while updating city {err}'
|
||||||
|
logging.error(error_message)
|
||||||
|
raise SQLAlchemyError(error_message)
|
||||||
|
|
||||||
def delete(self, city_id: int):
|
def delete(self, city_id: int):
|
||||||
"""
|
"""
|
||||||
Deletes a City with the id
|
Deletes a City with the id
|
||||||
:param city_id: the city id
|
:param city_id: the city id
|
||||||
:return: a city
|
:return: None
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
self.session.query(CityObject).filter(CityObject.city_id == city_id).delete()
|
self.session.query(CityObject).filter(CityObject.city_id == city_id).delete()
|
||||||
self.session.query(Model).filter(Model.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:
|
||||||
logging.error('Error while fetching city: %s', err)
|
error_message = f'Error while fetching city {err}'
|
||||||
|
logging.error(error_message)
|
||||||
|
raise SQLAlchemyError(error_message)
|
||||||
|
|
||||||
def get_by_user_id_application_id_and_name(self, user_id, application_id, city_name):
|
def get_by_user_id_application_id_and_name(self, user_id, application_id, city_name) -> Model:
|
||||||
"""
|
"""
|
||||||
Fetch city based on the user who created it
|
Fetch city based on the user who created it
|
||||||
:param user_id: the user id
|
:param user_id: the user id
|
||||||
|
@ -113,8 +116,9 @@ class City(Repository):
|
||||||
result_set = result_set[0]
|
result_set = result_set[0]
|
||||||
return result_set
|
return result_set
|
||||||
except SQLAlchemyError as err:
|
except SQLAlchemyError as err:
|
||||||
logging.error('Error while fetching city by name: %s', err)
|
error_message = f'Error while fetching city by name {err}'
|
||||||
return None
|
logging.error(error_message)
|
||||||
|
raise SQLAlchemyError(error_message)
|
||||||
|
|
||||||
def get_by_user_id_and_application_id(self, user_id, application_id) -> [Model]:
|
def get_by_user_id_and_application_id(self, user_id, application_id) -> [Model]:
|
||||||
"""
|
"""
|
||||||
|
@ -129,5 +133,6 @@ class City(Repository):
|
||||||
)
|
)
|
||||||
return [r[0] for r in result_set]
|
return [r[0] for r in result_set]
|
||||||
except SQLAlchemyError as err:
|
except SQLAlchemyError as err:
|
||||||
logging.error('Error while fetching city by name: %s', err)
|
error_message = f'Error while fetching city by name {err}'
|
||||||
return None
|
logging.error(error_message)
|
||||||
|
raise SQLAlchemyError(error_message)
|
||||||
|
|
|
@ -30,27 +30,27 @@ class CityObject(Repository):
|
||||||
cls._instance = super(CityObject, cls).__new__(cls)
|
cls._instance = super(CityObject, cls).__new__(cls)
|
||||||
return cls._instance
|
return cls._instance
|
||||||
|
|
||||||
def insert(self, city_id: int, building: Building) -> Union[Model, Dict]:
|
def insert(self, city_id: int, building: Building):
|
||||||
"""
|
"""
|
||||||
Inserts a new city object
|
Inserts a new city object
|
||||||
:param city_id: city id for the city owning this city object
|
:param city_id: city id for the city owning this city object
|
||||||
:param building: the city object (only building for now) to be inserted
|
:param building: the city object (only building for now) to be inserted
|
||||||
return CityObject model and dictionary
|
return None
|
||||||
"""
|
"""
|
||||||
city_object = self.get_by_name_and_city(building.name, city_id)
|
city_object = self.get_by_name_and_city(building.name, city_id)
|
||||||
if city_object is None:
|
if city_object is not None:
|
||||||
try:
|
raise SQLAlchemyError(f'A city_object named {building.name} already exists in that city')
|
||||||
city_object = Model(city_id=city_id,
|
try:
|
||||||
building=building)
|
city_object = Model(city_id=city_id,
|
||||||
self.session.add(city_object)
|
building=building)
|
||||||
self.session.flush()
|
self.session.add(city_object)
|
||||||
self.session.commit()
|
self.session.flush()
|
||||||
|
self.session.commit()
|
||||||
|
|
||||||
except SQLAlchemyError as err:
|
except SQLAlchemyError as err:
|
||||||
logging.error('An error occurred while creating city_object: %s', err)
|
error_message = f'An error occurred while creating city_object {err}'
|
||||||
else:
|
logging.error(error_message)
|
||||||
return {'message': f'A city_object named {building.name} already exists in that city'}
|
raise SQLAlchemyError(error_message)
|
||||||
return city_object
|
|
||||||
|
|
||||||
def update(self, city_id: int, building: Building) -> Union[Dict, None]:
|
def update(self, city_id: int, building: Building) -> Union[Dict, None]:
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -18,13 +18,11 @@ class TestCostsCatalog(TestCase):
|
||||||
self.assertIsNotNone(catalog, 'catalog is none')
|
self.assertIsNotNone(catalog, 'catalog is none')
|
||||||
content = catalog.entries()
|
content = catalog.entries()
|
||||||
self.assertTrue(len(content.archetypes) == 2)
|
self.assertTrue(len(content.archetypes) == 2)
|
||||||
print(catalog)
|
|
||||||
|
|
||||||
# retrieving all the entries should not raise any exceptions
|
# retrieving all the entries should not raise any exceptions
|
||||||
for category in catalog_categories:
|
for category in catalog_categories:
|
||||||
for value in catalog_categories[category]:
|
for value in catalog_categories[category]:
|
||||||
catalog.get_entry(value)
|
catalog.get_entry(value)
|
||||||
print(value)
|
|
||||||
|
|
||||||
with self.assertRaises(IndexError):
|
with self.assertRaises(IndexError):
|
||||||
catalog.get_entry('unknown')
|
catalog.get_entry('unknown')
|
||||||
|
|
|
@ -4,6 +4,7 @@ SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||||
Copyright © 2022 Concordia CERC group
|
Copyright © 2022 Concordia CERC group
|
||||||
Project Coder Peter Yefi peteryefi@gmail.com
|
Project Coder Peter Yefi peteryefi@gmail.com
|
||||||
"""
|
"""
|
||||||
|
import logging
|
||||||
import os
|
import os
|
||||||
import unittest
|
import unittest
|
||||||
from unittest import TestCase
|
from unittest import TestCase
|
||||||
|
@ -48,7 +49,7 @@ class Control:
|
||||||
connection = engine.connect()
|
connection = engine.connect()
|
||||||
connection.close()
|
connection.close()
|
||||||
except ProgrammingError:
|
except ProgrammingError:
|
||||||
print(f'Database does not exist. Nothing to delete')
|
logging.info('Database does not exist. Nothing to delete')
|
||||||
except sqlalchemy.exc.OperationalError as operational_error:
|
except sqlalchemy.exc.OperationalError as operational_error:
|
||||||
self._skip_test = True
|
self._skip_test = True
|
||||||
self._skip_reason = f'{operational_error}'
|
self._skip_reason = f'{operational_error}'
|
||||||
|
|
|
@ -86,7 +86,6 @@ class TestGeometryFactory(TestCase):
|
||||||
elif input_key == 'hft':
|
elif input_key == 'hft':
|
||||||
for building in city.buildings:
|
for building in city.buildings:
|
||||||
building.function = Dictionaries().hft_function_to_hub_function[building.function]
|
building.function = Dictionaries().hft_function_to_hub_function[building.function]
|
||||||
print(construction_key, usage_key)
|
|
||||||
ConstructionFactory(construction_key, city).enrich()
|
ConstructionFactory(construction_key, city).enrich()
|
||||||
UsageFactory(usage_key, city).enrich()
|
UsageFactory(usage_key, city).enrich()
|
||||||
|
|
||||||
|
|
|
@ -14,9 +14,6 @@ class TestSystemsCatalog(TestCase):
|
||||||
def test_montreal_custom_catalog(self):
|
def test_montreal_custom_catalog(self):
|
||||||
catalog = EnergySystemsCatalogFactory('montreal_custom').catalog
|
catalog = EnergySystemsCatalogFactory('montreal_custom').catalog
|
||||||
catalog_categories = catalog.names()
|
catalog_categories = catalog.names()
|
||||||
for archetype in catalog.entries('archetypes'):
|
|
||||||
for equipment in archetype.equipments:
|
|
||||||
print(equipment._equipment_id)
|
|
||||||
archetypes = catalog.names('archetypes')
|
archetypes = catalog.names('archetypes')
|
||||||
self.assertEqual(18, len(archetypes['archetypes']))
|
self.assertEqual(18, len(archetypes['archetypes']))
|
||||||
equipments = catalog.names('equipments')
|
equipments = catalog.names('equipments')
|
||||||
|
|
Loading…
Reference in New Issue
Block a user