diff --git a/CHANGELOG.md b/CHANGELOG.md index 5289316..2edc308 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Change log +### 0.2.13 +- Added default `version="1"` attribute to all nodes, ways, and relations generated during OSW→OSM conversion. +- Introduced unit test coverage to verify version attributes are written for all OSM elements. + ### 0.2.12 - Updated OSMTaggedNodeParser to apply the OSW node and point filters with normalization before adding loose tagged nodes, ensuring non-compliant features like crossings are no longer emitted. - Extended serializer tests to cover the new tagged-node behavior, confirming that compliant kerb features are retained while schema-invalid crossings are skipped. @@ -92,4 +96,4 @@ - Added unit test cases - Added README.md file - Added CHANGELOG.md file -- Added test.pypi pipeline \ No newline at end of file +- Added test.pypi pipeline diff --git a/src/osm_osw_reformatter/osw2osm/osw2osm.py b/src/osm_osw_reformatter/osw2osm/osw2osm.py index 8bfa2fb..505164b 100644 --- a/src/osm_osw_reformatter/osw2osm/osw2osm.py +++ b/src/osm_osw_reformatter/osw2osm/osw2osm.py @@ -1,5 +1,6 @@ import gc import ogr2osm +from xml.etree import ElementTree as ET from pathlib import Path from ..helpers.osw import OSWHelper from ..helpers.response import Response @@ -32,6 +33,7 @@ def convert(self) -> Response: # Instantiate either ogr2osm.OsmDataWriter or ogr2osm.PbfDataWriter data_writer = ogr2osm.OsmDataWriter(output_file, suppress_empty_tags=True) osm_data.output(data_writer) + self._ensure_version_attribute(output_file) del translation_object del datasource @@ -46,3 +48,19 @@ def convert(self) -> Response: finally: gc.collect() return resp + + @staticmethod + def _ensure_version_attribute(osm_xml_path: Path) -> None: + """Ensure nodes, ways, and relations include a version attribute.""" + try: + tree = ET.parse(osm_xml_path) + except Exception: + return + + root = tree.getroot() + for tag in ('node', 'way', 'relation'): + for element in root.findall(f'.//{tag}'): + if not element.get('version'): + element.set('version', '1') + + tree.write(osm_xml_path, encoding='utf-8', xml_declaration=True) diff --git a/src/osm_osw_reformatter/version.py b/src/osm_osw_reformatter/version.py index 51e2f03..a53c568 100644 --- a/src/osm_osw_reformatter/version.py +++ b/src/osm_osw_reformatter/version.py @@ -1 +1 @@ -__version__ = '0.2.12' +__version__ = '0.2.13' diff --git a/tests/unit_tests/test_osw2osm/test_osw2osm.py b/tests/unit_tests/test_osw2osm/test_osw2osm.py index f877fec..c46eb48 100644 --- a/tests/unit_tests/test_osw2osm/test_osw2osm.py +++ b/tests/unit_tests/test_osw2osm/test_osw2osm.py @@ -152,6 +152,19 @@ def test_invalid_incline_values_are_excluded(self): os.remove(result.generated_files) os.remove(zip_file) + def test_osm_elements_have_version_attribute(self): + zip_file = TEST_WIDTH_ZIP_FILE + osw2osm = OSW2OSM(zip_file_path=zip_file, workdir=OUTPUT_DIR, prefix='version') + result = osw2osm.convert() + + tree = ET.parse(result.generated_files) + root = tree.getroot() + + for element in root.findall('.//node') + root.findall('.//way') + root.findall('.//relation'): + self.assertEqual(element.get('version'), '1') + + os.remove(result.generated_files) + if __name__ == '__main__': unittest.main()