def __init__(self, filename): if os.path.exists(filename): self.data = geojson.load(open(filename)) else: raise Exception( f"URBANopt GeoJSON file does not exist: {filename}") # load the shemas self.schemas = Schemas() # break up the file based on the various features self.buildings = [] for f in self.data.features: if f["properties"]["type"] == "Building": self.buildings.append(UrbanOptBuilding(f))
def __init__(self, filename, building_ids=None): """ :param filename: str, path to the GeoJSON file to parse :param building_ids: list[str | int] | None, optional, list of GeoJSON building IDs to parse from the file. If None or an empty list, parse all buildings. """ if not Path(filename).exists(): raise GeoJsonValidationError( f"URBANopt GeoJSON file does not exist: {filename}") with open(filename, "r") as f: self.data = geojson.load(f) self.schemas = Schemas() building_errors = {} self.buildings = [] for feature in self.data.features: if feature["properties"]["type"] == "Building": building = UrbanOptLoad(feature) if not building_ids or building.id in building_ids: errors = self.schemas.validate("building", building.feature.properties) if errors: building_errors[building.id] = errors else: self.buildings.append(building) if building_errors: formatted_errors = '' for building_id, errors in building_errors.items(): building_errors_bullets = ''.join( [f'\n * {error}' for error in errors]) formatted_errors += f'\n ID {building_id}:{building_errors_bullets}' message = f'GeoJSON file is not valid:{formatted_errors}' raise GeoJsonValidationError(message) if not self.buildings: raise GeoJsonValidationError( f'No valid buildings found in GeoJSON file: {filename}')
def test_validate_schema(self): s = Schemas() s.retrieve("building") # verify that the schema can validate an instance with simple parameters instance = { "id": "5a6b99ec37f4de7f94020090", "type": "Building", "name": "Medium Office", "footprint_area": 17059, "footprint_perimeter": 533, "building_type": "Office", "number_of_stories": 3, "system_type": "PTAC with hot water heat", "number_of_stories_above_ground": 3, "building_status": "Proposed", "floor_area": 51177, "year_built": 2010, } res = s.validate("building", instance) self.assertEqual(len(res), 0) # bad system_type instance["type"] = "MagicBuilding" res = s.validate("building", instance) self.assertIn("'MagicBuilding' is not one of ['Building']", res[0]) self.assertEqual(len(res), 1)
class UrbanOptGeoJson(object): """ Root class for parsing an URBANopt GeoJSON file. This class simply reads and parses URBANopt GeoJSON files. """ def __init__(self, filename): if os.path.exists(filename): self.data = geojson.load(open(filename)) else: raise Exception( f"URBANopt GeoJSON file does not exist: {filename}") # load the shemas self.schemas = Schemas() # break up the file based on the various features self.buildings = [] for f in self.data.features: if f["properties"]["type"] == "Building": self.buildings.append(UrbanOptBuilding(f)) def validate(self): """ Validate each of the properties object for each of the types :return: dict of lists, errors for each of the types """ validations = defaultdict(dict) validations["building"] = [] status = True # go through building properties for validation for b in self.buildings: val_res = self.schemas.validate("building", b.feature.properties) if len(val_res) > 0: status = False res = {"id": b.feature.properties["id"], "errors": val_res} validations["building"].append(res) return status, validations
def test_invalid_retrieve(self): s = Schemas() with self.assertRaises(Exception) as context: s.retrieve("judicate") self.assertEqual("Schema for judicate does not exist", str(context.exception))
def test_load_schemas(self): s = Schemas() data = s.retrieve("building") self.assertEqual(data["title"], "Building object")