Skip to content

Commit

Permalink
Allow passing municipality by name to more tools
Browse files Browse the repository at this point in the history
  • Loading branch information
Martin Nyhus committed Jun 11, 2023
1 parent 6266a72 commit b0fb41d
Show file tree
Hide file tree
Showing 6 changed files with 136 additions and 3 deletions.
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ FLAKE8_FILES := \
tests/test_filter.py \
tests/test_find_lifecycle_updates.py \
tests/test_find_removed.py \
tests/test_shared.py \
;


Expand Down
4 changes: 3 additions & 1 deletion filter_buildings.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,13 @@ def main():
parser.add_argument('--municipality', required=True)
args = parser.parse_args()

muni_id = shared.handle_municipality_argument(args.municipality)

with open(args.input, 'r', encoding='utf-8') as file:
cadastral = shared.parse_cadastral_data(file.read())
print(f'Loaded {len(cadastral)} buildings')

osm_raw = shared.load_building_tags(args.municipality)
osm_raw = shared.load_building_tags(muni_id)
osm_refs = load_osm_refs(osm_raw)
print(f'Loaded {len(osm_refs)} unique references from OSM')

Expand Down
4 changes: 3 additions & 1 deletion find_lifecycle_updates.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,11 +76,13 @@ def main():
parser.add_argument('--municipality', required=True)
args = parser.parse_args()

muni_id = shared.handle_municipality_argument(args.municipality)

with open(args.input, 'r', encoding='utf-8') as file:
cadastral = shared.parse_cadastral_data(file.read())
print(f'Loaded {len(cadastral)} buildings')

osm_raw = shared.load_building_tags(args.municipality)
osm_raw = shared.load_building_tags(muni_id)
osm_buildings = json.loads(osm_raw)['elements']
osm_by_ref = osm_buildings_by_ref(osm_buildings)
print(f'Loaded {len(osm_buildings)} buildings from OSM')
Expand Down
4 changes: 3 additions & 1 deletion find_removed.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,13 @@ def main():
parser.add_argument('--municipality', required=True)
args = parser.parse_args()

muni_id = shared.handle_municipality_argument(args.municipality)

with open(args.input, 'r', encoding='utf-8') as file:
cadastral = shared.parse_cadastral_data(file.read())
print(f'Loaded {len(cadastral)} buildings')

osm_raw = shared.load_building_tags(args.municipality,
osm_raw = shared.load_building_tags(muni_id,
with_position=True)
osm_buildings = json.loads(osm_raw)['elements']
print(f'Loaded {len(osm_buildings)} buildings from OSM')
Expand Down
65 changes: 65 additions & 0 deletions shared.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,19 @@
import json
import re
import sys

import requests


class NoResults(Exception):
pass


class MultipleResults(Exception):
def __init__(self, *results):
self.results = list(results)


def parse_ref(raw_ref):
return {int(ref) for ref in raw_ref.split(';') if ref}

Expand Down Expand Up @@ -43,3 +54,57 @@ def format_geojson(features):
'features': features,
}
return json.dumps(geojson)


def load_municipalities():
url = ('https://ws.geonorge.no/kommuneinfo/v1/fylkerkommuner'
+ '?filtrer=fylkesnummer%2Cfylkesnavn%2Ckommuner.kommunenummer'
+ '%2Ckommuner.kommunenavnNorsk')
request = requests.get(url)

municipalities = {}
for county in request.json():
for municipality in county['kommuner']:
muni_number = municipality['kommunenummer']
muni_name = municipality['kommunenavnNorsk']
municipalities[muni_number] = muni_name

return municipalities


def resolve_municipality_id(municipalities, lookup_name):
result = None
for muni_id in municipalities:
muni_name = municipalities[muni_id]
if lookup_name.casefold() in muni_name.casefold():
current = {
'id': muni_id,
'name': muni_name,
}

if result is not None:
raise MultipleResults(result, current)
else:
result = current

if result is None:
raise NoResults

return result['id']


def handle_municipality_argument(municipality):
if re.match('[0-9]{4}', municipality):
return municipality

municipalities = load_municipalities()
try:
return resolve_municipality_id(
municipalities, municipality)
except NoResults:
sys.exit(f'Municipality {municipality} not found')
except MultipleResults as e:
sys.exit('Found multiple matching municipalities: {}'.format(
', '.join(
[f'{item["id"]}/{item["name"]}' for item in e.results]
)))
61 changes: 61 additions & 0 deletions tests/test_shared.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import unittest

import shared


class TestMuncipalityResolution(unittest.TestCase):
def setUp(self):
self.municipalities = {
'0301': 'Oslo',
# '0231': 'Skedsmo',
'3018': 'Våler',
'3030': 'Lillestrøm',
'3419': 'Våler',
'4215': 'Lillesand',
'4637': 'Hyllestad',
}

def _resolve(self, muni_name):
return shared.resolve_municipality_id(
self.municipalities,
muni_name)

def _assert_resolves_to(self, muni_name, muni_id):
self.assertEqual(muni_id, self._resolve(muni_name))

def test_resolve_municipality(self):
self._assert_resolves_to('Lillestrøm', '3030')

def test_resolve_zero_prefix(self):
self._assert_resolves_to('Oslo', '0301')

def test_resolve_duplicate_name(self):
with self.assertRaises(shared.MultipleResults) as cm:
self._resolve('Våler')

self.assertEqual(cm.exception.results, [
{'id': '3018', 'name': 'Våler'},
{'id': '3419', 'name': 'Våler'},
])

def test_resolve_missing(self):
with self.assertRaises(shared.NoResults):
self._resolve('Skedsmo')

def test_resolve_with_different_case(self):
self._assert_resolves_to('lILLESTRØM', '3030')

def test_resolve_using_prefix(self):
self._assert_resolves_to('Lillest', '3030')

def test_prefix_resolution_to_multiple_results(self):
with self.assertRaises(shared.MultipleResults) as cm:
self._resolve('Lilles')

self.assertEqual(cm.exception.results, [
{'id': '3030', 'name': 'Lillestrøm'},
{'id': '4215', 'name': 'Lillesand'},
])

def test_resolve_with_infix_match(self):
self._assert_resolves_to('llestr', '3030')

0 comments on commit b0fb41d

Please sign in to comment.