diff --git a/CHANGELOG.md b/CHANGELOG.md index d8cc48c..c10255e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ # Change log +### 0.2.10 +- Removed `climb` tag generation from OSM normalizer + ### 0.2.9 - Retain existing `incline` and `climb` tags when converting OSW to OSM - Add `climb` tag when missing and `incline` is provided diff --git a/requirements.txt b/requirements.txt index 87a77c3..c752478 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,4 +4,5 @@ networkx~=3.2 shapely~=2.0.2 pyproj~=3.6.1 coverage~=7.5.1 -ogr2osm==1.2.0 \ No newline at end of file +ogr2osm==1.2.0 +python-osw-validation==0.2.13 \ No newline at end of file diff --git a/src/osm_osw_reformatter/serializer/osm/osm_normalizer.py b/src/osm_osw_reformatter/serializer/osm/osm_normalizer.py index dc9c790..3a51033 100644 --- a/src/osm_osw_reformatter/serializer/osm/osm_normalizer.py +++ b/src/osm_osw_reformatter/serializer/osm/osm_normalizer.py @@ -45,18 +45,17 @@ def filter_tags(self, tags): tags.pop('foot', '') # OSW fields with similar OSM field names + if 'climb' in tags: + if tags.get('highway') != 'steps' or tags['climb'] not in ('up', 'down'): + tags.pop('climb', '') + if 'incline' in tags: try: incline_val = float(str(tags['incline']).rstrip('%')) except (ValueError, TypeError): - incline_val = None + pass else: tags['incline'] = str(incline_val) - if 'climb' not in tags: - if incline_val > 0: - tags['climb'] = 'up' - elif incline_val < 0: - tags['climb'] = 'down' self._check_datatypes(tags) diff --git a/src/osm_osw_reformatter/version.py b/src/osm_osw_reformatter/version.py index cd9b137..e913eb4 100644 --- a/src/osm_osw_reformatter/version.py +++ b/src/osm_osw_reformatter/version.py @@ -1 +1 @@ -__version__ = '0.2.9' +__version__ = '0.2.10' diff --git a/tests/unit_tests/test_osm_compliance/__init__.py b/tests/unit_tests/test_osm_compliance/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/unit_tests/test_osm_compliance/test_osm_compliance.py b/tests/unit_tests/test_osm_compliance/test_osm_compliance.py new file mode 100644 index 0000000..8a90275 --- /dev/null +++ b/tests/unit_tests/test_osm_compliance/test_osm_compliance.py @@ -0,0 +1,38 @@ +import os +import json +import zipfile +import unittest +from python_osw_validation import OSWValidation + +from src.osm_osw_reformatter.osw2osm.osw2osm import OSW2OSM +from src.osm_osw_reformatter import Formatter + +ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +OUTPUT_DIR = os.path.join(os.path.dirname(os.path.dirname(ROOT_DIR)), 'output') +TEST_DATA_WITH_INCLINE_ZIP_FILE = os.path.join(ROOT_DIR, 'test_files/dataset_with_incline.zip') + + +class TestOSMCompliance(unittest.IsolatedAsyncioTestCase): + async def test_output_is_osm_compliant(self): + osw2osm = OSW2OSM(zip_file_path=TEST_DATA_WITH_INCLINE_ZIP_FILE, workdir=OUTPUT_DIR, prefix='compliance') + result = osw2osm.convert() + osm_file = result.generated_files + + formatter = Formatter(workdir=OUTPUT_DIR, file_path=osm_file, prefix='compliance') + res = await formatter.osm2osw() + osw_files = res.generated_files + + zip_path = os.path.join(OUTPUT_DIR, 'compliance_osw.zip') + with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as zipf: + for f in osw_files: + zipf.write(f, os.path.basename(f)) + + validator = OSWValidation(zipfile_path=zip_path) + result = validator.validate() + self.assertEqual(len(result.issues), 0, f'OSW Validation issues: {json.dumps(result.issues)}') + + os.remove(osm_file) + for f in osw_files: + os.remove(f) + os.remove(zip_path) + formatter.cleanup() diff --git a/tests/unit_tests/test_osw2osm/test_osw2osm.py b/tests/unit_tests/test_osw2osm/test_osw2osm.py index 10e4730..d862fcd 100644 --- a/tests/unit_tests/test_osw2osm/test_osw2osm.py +++ b/tests/unit_tests/test_osw2osm/test_osw2osm.py @@ -65,7 +65,7 @@ async def test_convert_error(self): result = osw2osm.convert() self.assertFalse(result.status) - def test_generated_file_contains_climb_tag(self): + def test_generated_file_does_not_contain_climb_tag(self): zip_file = TEST_DATA_WITH_INCLINE_ZIP_FILE osw2osm = OSW2OSM(zip_file_path=zip_file, workdir=OUTPUT_DIR, prefix='test') result = osw2osm.convert() @@ -73,7 +73,7 @@ def test_generated_file_contains_climb_tag(self): tree = ET.parse(xml_file_path) root = tree.getroot() - self.assertGreater(len(root.findall(".//tag[@k='climb']")), 0) + self.assertEqual(len(root.findall(".//tag[@k='climb']")), 0) os.remove(result.generated_files) @@ -89,7 +89,7 @@ def test_generated_file_contains_incline_tag(self): os.remove(result.generated_files) - def test_incline_tags_have_climb(self): + def test_incline_tags_do_not_have_climb(self): zip_file = TEST_DATA_WITH_INCLINE_ZIP_FILE osw2osm = OSW2OSM(zip_file_path=zip_file, workdir=OUTPUT_DIR, prefix='test') result = osw2osm.convert() @@ -101,7 +101,7 @@ def test_incline_tags_have_climb(self): for element in root.findall('.//way') + root.findall('.//node') + root.findall('.//relation'): tags = {tag.get('k'): tag.get('v') for tag in element.findall('tag')} if 'incline' in tags and float(tags.get('incline', 0) or 0) != 0: - self.assertIn('climb', tags) + self.assertNotIn('climb', tags) os.remove(result.generated_files) diff --git a/tests/unit_tests/test_serializer/test_osm_normalizer.py b/tests/unit_tests/test_serializer/test_osm_normalizer.py index d4ec17b..ec0a95e 100644 --- a/tests/unit_tests/test_serializer/test_osm_normalizer.py +++ b/tests/unit_tests/test_serializer/test_osm_normalizer.py @@ -55,34 +55,34 @@ class TestOSMNormalizeInclineField(unittest.TestCase): def setUp(self): self.normalizer = OSMNormalizer() - def test_retains_existing_incline_and_climb(self): + def test_removes_existing_climb_and_retains_incline(self): tags = {"highway": "footway", "incline": 0.014, "climb": "up"} normalizer = self.normalizer.filter_tags(tags) self.assertEqual(normalizer["incline"], "0.014") - self.assertEqual(normalizer["climb"], "up") + self.assertNotIn("climb", normalizer) - def test_derives_climb_from_positive_incline(self): + def test_does_not_add_climb_from_positive_incline(self): tags = {"highway": "footway", "incline": 0.014} normalizer = self.normalizer.filter_tags(tags) - self.assertEqual(normalizer["climb"], "up") + self.assertNotIn("climb", normalizer) self.assertEqual(normalizer["incline"], "0.014") - def test_derives_climb_from_negative_incline(self): + def test_does_not_add_climb_from_negative_incline(self): tags = {"highway": "footway", "incline": -0.014} normalizer = self.normalizer.filter_tags(tags) - self.assertEqual(normalizer["climb"], "down") + self.assertNotIn("climb", normalizer) self.assertEqual(normalizer["incline"], "-0.014") - def test_does_not_derive_climb_from_zero_incline(self): + def test_does_not_add_climb_from_zero_incline(self): tags = {"highway": "footway", "incline": 0} normalizer = self.normalizer.filter_tags(tags) self.assertEqual(normalizer["incline"], "0.0") self.assertNotIn("climb", normalizer) - def test_retains_climb_without_incline(self): + def test_removes_climb_without_incline(self): tags = {"highway": "footway", "climb": "down"} normalizer = self.normalizer.filter_tags(tags) - self.assertEqual(normalizer["climb"], "down") + self.assertNotIn("climb", normalizer) self.assertNotIn("incline", normalizer) def test_retains_non_numeric_incline_without_climb(self): @@ -90,3 +90,21 @@ def test_retains_non_numeric_incline_without_climb(self): normalizer = self.normalizer.filter_tags(tags) self.assertEqual(normalizer["incline"], "steep") self.assertNotIn("climb", normalizer) + + def test_retains_climb_when_highway_is_steps(self): + tags = {"highway": "steps", "climb": "up"} + normalizer = self.normalizer.filter_tags(tags) + self.assertIn("climb", normalizer) + self.assertEqual(normalizer["climb"], "up") + self.assertNotIn("incline", normalizer) + + def test_retains_climb_down_when_highway_is_steps(self): + tags = {"highway": "steps", "climb": "down"} + normalizer = self.normalizer.filter_tags(tags) + self.assertIn("climb", normalizer) + self.assertEqual(normalizer["climb"], "down") + + def test_discards_invalid_climb_when_highway_is_steps(self): + tags = {"highway": "steps", "climb": "sideways"} + normalizer = self.normalizer.filter_tags(tags) + self.assertNotIn("climb", normalizer)