]> git.openstreetmap.org Git - nominatim.git/commitdiff
enable flake for Python tests
authorSarah Hoffmann <lonvia@denofr.de>
Sun, 9 Mar 2025 14:33:24 +0000 (15:33 +0100)
committerSarah Hoffmann <lonvia@denofr.de>
Sun, 9 Mar 2025 14:33:24 +0000 (15:33 +0100)
93 files changed:
.flake8
Makefile
test/python/api/conftest.py
test/python/api/fake_adaptor.py
test/python/api/query_processing/test_normalize.py
test/python/api/query_processing/test_split_japanese_phrases.py
test/python/api/search/test_api_search_query.py
test/python/api/search/test_db_search_builder.py
test/python/api/search/test_icu_query_analyzer.py
test/python/api/search/test_postcode_parser.py
test/python/api/search/test_query.py
test/python/api/search/test_query_analyzer_factory.py
test/python/api/search/test_search_country.py
test/python/api/search/test_search_near.py
test/python/api/search/test_search_places.py
test/python/api/search/test_search_poi.py
test/python/api/search/test_search_postcode.py
test/python/api/search/test_token_assignment.py
test/python/api/test_api_connection.py
test/python/api/test_api_deletable_v1.py
test/python/api/test_api_details.py
test/python/api/test_api_lookup.py
test/python/api/test_api_polygons_v1.py
test/python/api/test_api_reverse.py
test/python/api/test_api_search.py
test/python/api/test_api_status.py
test/python/api/test_api_types.py
test/python/api/test_export.py
test/python/api/test_helpers_v1.py
test/python/api/test_localization.py
test/python/api/test_result_formatting_v1.py
test/python/api/test_result_formatting_v1_reverse.py
test/python/api/test_results.py
test/python/api/test_server_glue_v1.py
test/python/api/test_warm.py
test/python/cli/conftest.py
test/python/cli/test_cli.py
test/python/cli/test_cmd_admin.py
test/python/cli/test_cmd_api.py
test/python/cli/test_cmd_import.py
test/python/cli/test_cmd_refresh.py
test/python/cli/test_cmd_replication.py
test/python/config/test_config.py
test/python/config/test_config_load_module.py
test/python/conftest.py
test/python/cursor.py
test/python/data/test_country_info.py
test/python/db/test_connection.py
test/python/db/test_properties.py
test/python/db/test_sql_preprocessor.py
test/python/db/test_status.py
test/python/db/test_utils.py
test/python/dummy_tokenizer.py
test/python/indexer/test_indexing.py
test/python/mock_icu_word_table.py
test/python/mocks.py
test/python/tokenizer/sanitizers/test_clean_housenumbers.py
test/python/tokenizer/sanitizers/test_clean_postcodes.py
test/python/tokenizer/sanitizers/test_clean_tiger_tags.py
test/python/tokenizer/sanitizers/test_delete_tags.py
test/python/tokenizer/sanitizers/test_sanitizer_config.py
test/python/tokenizer/sanitizers/test_split_name_list.py
test/python/tokenizer/sanitizers/test_strip_brace_terms.py
test/python/tokenizer/sanitizers/test_tag_analyzer_by_language.py
test/python/tokenizer/sanitizers/test_tag_japanese.py
test/python/tokenizer/test_factory.py
test/python/tokenizer/test_icu.py
test/python/tokenizer/test_icu_rule_loader.py
test/python/tokenizer/test_place_sanitizer.py
test/python/tokenizer/token_analysis/test_analysis_postcodes.py
test/python/tokenizer/token_analysis/test_generic.py
test/python/tokenizer/token_analysis/test_generic_mutation.py
test/python/tokenizer/token_analysis/test_simple_trie.py
test/python/tools/conftest.py
test/python/tools/test_add_osm_data.py
test/python/tools/test_admin.py
test/python/tools/test_check_database.py
test/python/tools/test_database_import.py
test/python/tools/test_exec_utils.py
test/python/tools/test_freeze.py
test/python/tools/test_import_special_phrases.py
test/python/tools/test_migration.py
test/python/tools/test_postcodes.py
test/python/tools/test_refresh.py
test/python/tools/test_refresh_address_levels.py
test/python/tools/test_refresh_create_functions.py
test/python/tools/test_refresh_wiki_data.py
test/python/tools/test_replication.py
test/python/tools/test_sp_csv_loader.py
test/python/tools/test_sp_wiki_loader.py
test/python/tools/test_tiger_data.py
test/python/utils/test_centroid.py
test/python/utils/test_json_writer.py

diff --git a/.flake8 b/.flake8
index 82d77ed37fffc613def880af5601bf7294983e5e..f3e0db567eb78ea0c7665fc86e3de1ce9a862018 100644 (file)
--- a/.flake8
+++ b/.flake8
@@ -6,3 +6,5 @@ extend-ignore =
     E711
 per-file-ignores =
     __init__.py: F401
+    test/python/utils/test_json_writer.py: E131
+    test/python/conftest.py: E402
index 9e914850b783400e9f2c1d0b6c6d9548b3678c14..72072a59778163b423e5dda70438b992993deba5 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -24,7 +24,7 @@ pytest:
        pytest test/python
 
 lint:
-       flake8 src
+       flake8 src test/python
 
 bdd:
        cd test/bdd; behave -DREMOVE_TEMPLATE=1
index 3ca0720b4da24f76a76b0f30e3084af5e87d2802..bde0afc41807daceb9dece48e17db937e5166b44 100644 (file)
@@ -2,14 +2,13 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 """
 Helper fixtures for API call tests.
 """
 import pytest
 import pytest_asyncio
-import time
 import datetime as dt
 
 import sqlalchemy as sa
@@ -20,27 +19,25 @@ from nominatim_api.search.query_analyzer_factory import make_query_analyzer
 from nominatim_db.tools import convert_sqlite
 import nominatim_api.logging as loglib
 
+
 class APITester:
 
     def __init__(self):
         self.api = napi.NominatimAPI()
         self.async_to_sync(self.api._async_api.setup_database())
 
-
     def async_to_sync(self, func):
         """ Run an asynchronous function until completion using the
             internal loop of the API.
         """
         return self.api._loop.run_until_complete(func)
 
-
     def add_data(self, table, data):
         """ Insert data into the given table.
         """
         sql = getattr(self.api._async_api._tables, table).insert()
         self.async_to_sync(self.exec_async(sql, data))
 
-
     def add_placex(self, **kw):
         name = kw.get('name')
         if isinstance(name, str):
@@ -50,30 +47,29 @@ class APITester:
         geometry = kw.get('geometry', 'POINT(%f %f)' % centroid)
 
         self.add_data('placex',
-                     {'place_id': kw.get('place_id', 1000),
-                      'osm_type': kw.get('osm_type', 'W'),
-                      'osm_id': kw.get('osm_id', 4),
-                      'class_': kw.get('class_', 'highway'),
-                      'type': kw.get('type', 'residential'),
-                      'name': name,
-                      'address': kw.get('address'),
-                      'extratags': kw.get('extratags'),
-                      'parent_place_id': kw.get('parent_place_id'),
-                      'linked_place_id': kw.get('linked_place_id'),
-                      'admin_level': kw.get('admin_level', 15),
-                      'country_code': kw.get('country_code'),
-                      'housenumber': kw.get('housenumber'),
-                      'postcode': kw.get('postcode'),
-                      'wikipedia': kw.get('wikipedia'),
-                      'rank_search': kw.get('rank_search', 30),
-                      'rank_address': kw.get('rank_address', 30),
-                      'importance': kw.get('importance'),
-                      'centroid': 'POINT(%f %f)' % centroid,
-                      'indexed_status': kw.get('indexed_status', 0),
-                      'indexed_date': kw.get('indexed_date',
-                                             dt.datetime(2022, 12, 7, 14, 14, 46, 0)),
-                      'geometry': geometry})
-
+                      {'place_id': kw.get('place_id', 1000),
+                       'osm_type': kw.get('osm_type', 'W'),
+                       'osm_id': kw.get('osm_id', 4),
+                       'class_': kw.get('class_', 'highway'),
+                       'type': kw.get('type', 'residential'),
+                       'name': name,
+                       'address': kw.get('address'),
+                       'extratags': kw.get('extratags'),
+                       'parent_place_id': kw.get('parent_place_id'),
+                       'linked_place_id': kw.get('linked_place_id'),
+                       'admin_level': kw.get('admin_level', 15),
+                       'country_code': kw.get('country_code'),
+                       'housenumber': kw.get('housenumber'),
+                       'postcode': kw.get('postcode'),
+                       'wikipedia': kw.get('wikipedia'),
+                       'rank_search': kw.get('rank_search', 30),
+                       'rank_address': kw.get('rank_address', 30),
+                       'importance': kw.get('importance'),
+                       'centroid': 'POINT(%f %f)' % centroid,
+                       'indexed_status': kw.get('indexed_status', 0),
+                       'indexed_date': kw.get('indexed_date',
+                                              dt.datetime(2022, 12, 7, 14, 14, 46, 0)),
+                       'geometry': geometry})
 
     def add_address_placex(self, object_id, **kw):
         self.add_placex(**kw)
@@ -85,46 +81,42 @@ class APITester:
                        'fromarea': kw.get('fromarea', False),
                        'isaddress': kw.get('isaddress', True)})
 
-
     def add_osmline(self, **kw):
         self.add_data('osmline',
-                     {'place_id': kw.get('place_id', 10000),
-                      'osm_id': kw.get('osm_id', 4004),
-                      'parent_place_id': kw.get('parent_place_id'),
-                      'indexed_date': kw.get('indexed_date',
-                                             dt.datetime(2022, 12, 7, 14, 14, 46, 0)),
-                      'startnumber': kw.get('startnumber', 2),
-                      'endnumber': kw.get('endnumber', 6),
-                      'step': kw.get('step', 2),
-                      'address': kw.get('address'),
-                      'postcode': kw.get('postcode'),
-                      'country_code': kw.get('country_code'),
-                      'linegeo': kw.get('geometry', 'LINESTRING(1.1 -0.2, 1.09 -0.22)')})
-
+                      {'place_id': kw.get('place_id', 10000),
+                       'osm_id': kw.get('osm_id', 4004),
+                       'parent_place_id': kw.get('parent_place_id'),
+                       'indexed_date': kw.get('indexed_date',
+                                              dt.datetime(2022, 12, 7, 14, 14, 46, 0)),
+                       'startnumber': kw.get('startnumber', 2),
+                       'endnumber': kw.get('endnumber', 6),
+                       'step': kw.get('step', 2),
+                       'address': kw.get('address'),
+                       'postcode': kw.get('postcode'),
+                       'country_code': kw.get('country_code'),
+                       'linegeo': kw.get('geometry', 'LINESTRING(1.1 -0.2, 1.09 -0.22)')})
 
     def add_tiger(self, **kw):
         self.add_data('tiger',
-                     {'place_id': kw.get('place_id', 30000),
-                      'parent_place_id': kw.get('parent_place_id'),
-                      'startnumber': kw.get('startnumber', 2),
-                      'endnumber': kw.get('endnumber', 6),
-                      'step': kw.get('step', 2),
-                      'postcode': kw.get('postcode'),
-                      'linegeo': kw.get('geometry', 'LINESTRING(1.1 -0.2, 1.09 -0.22)')})
-
+                      {'place_id': kw.get('place_id', 30000),
+                       'parent_place_id': kw.get('parent_place_id'),
+                       'startnumber': kw.get('startnumber', 2),
+                       'endnumber': kw.get('endnumber', 6),
+                       'step': kw.get('step', 2),
+                       'postcode': kw.get('postcode'),
+                       'linegeo': kw.get('geometry', 'LINESTRING(1.1 -0.2, 1.09 -0.22)')})
 
     def add_postcode(self, **kw):
         self.add_data('postcode',
-                     {'place_id': kw.get('place_id', 1000),
-                      'parent_place_id': kw.get('parent_place_id'),
-                      'country_code': kw.get('country_code'),
-                      'postcode': kw.get('postcode'),
-                      'rank_search': kw.get('rank_search', 20),
-                      'rank_address': kw.get('rank_address', 22),
-                      'indexed_date': kw.get('indexed_date',
-                                             dt.datetime(2022, 12, 7, 14, 14, 46, 0)),
-                      'geometry': kw.get('geometry', 'POINT(23 34)')})
-
+                      {'place_id': kw.get('place_id', 1000),
+                       'parent_place_id': kw.get('parent_place_id'),
+                       'country_code': kw.get('country_code'),
+                       'postcode': kw.get('postcode'),
+                       'rank_search': kw.get('rank_search', 20),
+                       'rank_address': kw.get('rank_address', 22),
+                       'indexed_date': kw.get('indexed_date',
+                                              dt.datetime(2022, 12, 7, 14, 14, 46, 0)),
+                       'geometry': kw.get('geometry', 'POINT(23 34)')})
 
     def add_country(self, country_code, geometry):
         self.add_data('country_grid',
@@ -132,14 +124,12 @@ class APITester:
                        'area': 0.1,
                        'geometry': geometry})
 
-
     def add_country_name(self, country_code, names, partition=0):
         self.add_data('country_name',
                       {'country_code': country_code,
                        'name': names,
                        'partition': partition})
 
-
     def add_search_name(self, place_id, **kw):
         centroid = kw.get('centroid', (23.0, 34.0))
         self.add_data('search_name',
@@ -152,7 +142,6 @@ class APITester:
                        'country_code': kw.get('country_code', 'xx'),
                        'centroid': 'POINT(%f %f)' % centroid})
 
-
     def add_class_type_table(self, cls, typ):
         self.async_to_sync(
             self.exec_async(sa.text(f"""CREATE TABLE place_classtype_{cls}_{typ}
@@ -160,7 +149,6 @@ class APITester:
                                              WHERE class = '{cls}' AND type = '{typ}')
                                      """)))
 
-
     def add_word_table(self, content):
         data = [dict(zip(['word_id', 'word_token', 'type', 'word', 'info'], c))
                 for c in content]
@@ -176,12 +164,10 @@ class APITester:
 
         self.async_to_sync(_do_sql())
 
-
     async def exec_async(self, sql, *args, **kwargs):
         async with self.api._async_api.begin() as conn:
             return await conn.execute(sql, *args, **kwargs)
 
-
     async def create_tables(self):
         async with self.api._async_api._engine.begin() as conn:
             await conn.run_sync(self.api._async_api._tables.meta.create_all)
@@ -212,11 +198,12 @@ def frontend(request, event_loop, tmp_path):
         db = str(tmp_path / 'test_nominatim_python_unittest.sqlite')
 
         def mkapi(apiobj, options={'reverse'}):
-            apiobj.add_data('properties',
-                        [{'property': 'tokenizer', 'value': 'icu'},
-                         {'property': 'tokenizer_import_normalisation', 'value': ':: lower();'},
-                         {'property': 'tokenizer_import_transliteration', 'value': "'1' > '/1/'; 'ä' > 'ä '"},
-                        ])
+            apiobj.add_data(
+                'properties',
+                [{'property': 'tokenizer', 'value': 'icu'},
+                 {'property': 'tokenizer_import_normalisation', 'value': ':: lower();'},
+                 {'property': 'tokenizer_import_transliteration',
+                  'value': "'1' > '/1/'; 'ä' > 'ä '"}])
 
             async def _do_sql():
                 async with apiobj.api._async_api.begin() as conn:
index 4b64c17d9a25fe9ee630dc10653fd27d5e17c779..a3a3bcf9f47db798ae9a6e44d6880b4edeed4a38 100644 (file)
@@ -2,7 +2,7 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 """
 Provides dummy implementations of ASGIAdaptor for testing.
@@ -13,6 +13,7 @@ import nominatim_api.v1.server_glue as glue
 from nominatim_api.v1.format import dispatch as formatting
 from nominatim_api.config import Configuration
 
+
 class FakeError(BaseException):
 
     def __init__(self, msg, status):
@@ -22,8 +23,10 @@ class FakeError(BaseException):
     def __str__(self):
         return f'{self.status} -- {self.msg}'
 
+
 FakeResponse = namedtuple('FakeResponse', ['status', 'output', 'content_type'])
 
+
 class FakeAdaptor(glue.ASGIAdaptor):
 
     def __init__(self, params=None, headers=None, config=None):
@@ -31,23 +34,18 @@ class FakeAdaptor(glue.ASGIAdaptor):
         self.headers = headers or {}
         self._config = config or Configuration(None)
 
-
     def get(self, name, default=None):
         return self.params.get(name, default)
 
-
     def get_header(self, name, default=None):
         return self.headers.get(name, default)
 
-
     def error(self, msg, status=400):
         return FakeError(msg, status)
 
-
     def create_response(self, status, output, num_results):
         return FakeResponse(status, output, self.content_type)
 
-
     def base_uri(self):
         return 'http://test'
 
@@ -56,5 +54,3 @@ class FakeAdaptor(glue.ASGIAdaptor):
 
     def formatting(self):
         return formatting
-
-
index 12a8de2a2e0ea15bf7dbedf01581173198112dc1..35f5fcd76e601ef046c36b8f8be98630d7479768 100644 (file)
@@ -2,21 +2,18 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 """
 Tests for normalizing search queries.
 """
-from pathlib import Path
-
-import pytest
-
 from icu import Transliterator
 
 import nominatim_api.search.query as qmod
 from nominatim_api.query_preprocessing.config import QueryConfig
 from nominatim_api.query_preprocessing import normalize
 
+
 def run_preprocessor_on(query, norm):
     normalizer = Transliterator.createFromRules("normalization", norm)
     proc = normalize.create(QueryConfig().set_normalizer(normalizer))
index 51d592e3a724ca55c57c623ad5687123a254658e..30f22e7bbac864bc95fa8f93a198baf21c9802eb 100644 (file)
@@ -7,16 +7,13 @@
 """
 Tests for japanese phrase splitting.
 """
-from pathlib import Path
-
 import pytest
 
-from icu import Transliterator
-
 import nominatim_api.search.query as qmod
 from nominatim_api.query_preprocessing.config import QueryConfig
 from nominatim_api.query_preprocessing import split_japanese_phrases
 
+
 def run_preprocessor_on(query):
     proc = split_japanese_phrases.create(QueryConfig().set_normalizer(None))
 
index 08a1f7aafb02ac3d8228f20382bf4b9461c07502..c9e8de93683f419ad7cd1b9b1d9a7d163d986070 100644 (file)
@@ -2,7 +2,7 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 """
 Tests for tokenized query data structures.
@@ -11,6 +11,7 @@ import pytest
 
 from nominatim_api.search import query
 
+
 class MyToken(query.Token):
 
     def get_category(self):
@@ -21,9 +22,11 @@ def mktoken(tid: int):
     return MyToken(penalty=3.0, token=tid, count=1, addr_count=1,
                    lookup_word='foo')
 
+
 @pytest.fixture
 def qnode():
-    return query.QueryNode(query.BREAK_PHRASE, query.PHRASE_ANY, 0.0 ,'', '')
+    return query.QueryNode(query.BREAK_PHRASE, query.PHRASE_ANY, 0.0, '', '')
+
 
 @pytest.mark.parametrize('ptype,ttype', [(query.PHRASE_ANY, 'W'),
                                          (query.PHRASE_AMENITY, 'Q'),
@@ -132,4 +135,3 @@ def test_query_struct_amenity_two_words():
     assert len(q.get_tokens(query.TokenRange(1, 2), query.TOKEN_PARTIAL)) == 1
     assert len(q.get_tokens(query.TokenRange(1, 2), query.TOKEN_NEAR_ITEM)) == 0
     assert len(q.get_tokens(query.TokenRange(1, 2), query.TOKEN_QUALIFIER)) == 1
-
index 49d5f303dee26378479d230dc574602a68245558..be34fbea070a2859de238bb563d5ca2e0033917c 100644 (file)
@@ -16,6 +16,7 @@ from nominatim_api.search.token_assignment import TokenAssignment
 from nominatim_api.types import SearchDetails
 import nominatim_api.search.db_searches as dbs
 
+
 class MyToken(Token):
     def get_category(self):
         return 'this', 'that'
@@ -36,7 +37,6 @@ def make_query(*args):
                                     token=tid, count=1, addr_count=1,
                                     lookup_word=word))
 
-
     return q
 
 
@@ -241,8 +241,7 @@ def test_name_and_address():
                    [(2, qmod.TOKEN_PARTIAL, [(2, 'b')]),
                     (2, qmod.TOKEN_WORD, [(101, 'b')])],
                    [(3, qmod.TOKEN_PARTIAL, [(3, 'c')]),
-                    (3, qmod.TOKEN_WORD, [(102, 'c')])]
-                  )
+                    (3, qmod.TOKEN_WORD, [(102, 'c')])])
     builder = SearchBuilder(q, SearchDetails())
 
     searches = list(builder.build(TokenAssignment(name=TokenRange(0, 1),
@@ -267,8 +266,7 @@ def test_name_and_complex_address():
                     (3, qmod.TOKEN_WORD, [(101, 'bc')])],
                    [(3, qmod.TOKEN_PARTIAL, [(3, 'c')])],
                    [(4, qmod.TOKEN_PARTIAL, [(4, 'd')]),
-                    (4, qmod.TOKEN_WORD, [(103, 'd')])]
-                  )
+                    (4, qmod.TOKEN_WORD, [(103, 'd')])])
     builder = SearchBuilder(q, SearchDetails())
 
     searches = list(builder.build(TokenAssignment(name=TokenRange(0, 1),
@@ -423,8 +421,8 @@ def test_infrequent_partials_in_name():
     assert len(search.lookups) == 2
     assert len(search.rankings) == 2
 
-    assert set((l.column, l.lookup_type.__name__) for l in search.lookups) == \
-            {('name_vector', 'LookupAll'), ('nameaddress_vector', 'Restrict')}
+    assert set((s.column, s.lookup_type.__name__) for s in search.lookups) == \
+        {('name_vector', 'LookupAll'), ('nameaddress_vector', 'Restrict')}
 
 
 def test_frequent_partials_in_name_and_address():
@@ -435,10 +433,10 @@ def test_frequent_partials_in_name_and_address():
     assert all(isinstance(s, dbs.PlaceSearch) for s in searches)
     searches.sort(key=lambda s: s.penalty)
 
-    assert set((l.column, l.lookup_type.__name__) for l in searches[0].lookups) == \
-            {('name_vector', 'LookupAny'), ('nameaddress_vector', 'Restrict')}
-    assert set((l.column, l.lookup_type.__name__) for l in searches[1].lookups) == \
-            {('nameaddress_vector', 'LookupAll'), ('name_vector', 'LookupAll')}
+    assert set((s.column, s.lookup_type.__name__) for s in searches[0].lookups) == \
+        {('name_vector', 'LookupAny'), ('nameaddress_vector', 'Restrict')}
+    assert set((s.column, s.lookup_type.__name__) for s in searches[1].lookups) == \
+        {('nameaddress_vector', 'LookupAll'), ('name_vector', 'LookupAll')}
 
 
 def test_too_frequent_partials_in_name_and_address():
@@ -449,5 +447,5 @@ def test_too_frequent_partials_in_name_and_address():
     assert all(isinstance(s, dbs.PlaceSearch) for s in searches)
     searches.sort(key=lambda s: s.penalty)
 
-    assert set((l.column, l.lookup_type.__name__) for l in searches[0].lookups) == \
-            {('name_vector', 'LookupAny'), ('nameaddress_vector', 'Restrict')}
+    assert set((s.column, s.lookup_type.__name__) for s in searches[0].lookups) == \
+        {('name_vector', 'LookupAny'), ('nameaddress_vector', 'Restrict')}
index fc200bca55baf9fff3ef31f576f8680a9e3316a3..725350266cf455baedc5a3e5e537fdae2fe6ea66 100644 (file)
@@ -2,7 +2,7 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 """
 Tests for query analyzer for ICU tokenizer.
@@ -16,7 +16,8 @@ import nominatim_api.search.query as qmod
 import nominatim_api.search.icu_tokenizer as tok
 from nominatim_api.logging import set_log_output, get_and_disable
 
-async def add_word(conn, word_id, word_token, wtype, word, info = None):
+
+async def add_word(conn, word_id, word_token, wtype, word, info=None):
     t = conn.t.meta.tables['word']
     await conn.execute(t.insert(), {'word_id': word_id,
                                     'word_token': word_token,
@@ -28,6 +29,7 @@ async def add_word(conn, word_id, word_token, wtype, word, info = None):
 def make_phrase(query):
     return [Phrase(qmod.PHRASE_ANY, s) for s in query.split(',')]
 
+
 @pytest_asyncio.fixture
 async def conn(table_factory):
     """ Create an asynchronous SQLAlchemy engine for the test DB.
@@ -102,8 +104,7 @@ async def test_splitting_in_transliteration(conn):
 
 @pytest.mark.asyncio
 @pytest.mark.parametrize('term,order', [('23456', ['P', 'H', 'W', 'w']),
-                                        ('3', ['H', 'W', 'w'])
-                                       ])
+                                        ('3', ['H', 'W', 'w'])])
 async def test_penalty_postcodes_and_housenumbers(conn, term, order):
     ana = await tok.create_query_analyzer(conn)
 
@@ -120,6 +121,7 @@ async def test_penalty_postcodes_and_housenumbers(conn, term, order):
 
     assert [t[1] for t in torder] == order
 
+
 @pytest.mark.asyncio
 async def test_category_words_only_at_beginning(conn):
     ana = await tok.create_query_analyzer(conn)
index 284aba5b932b3c96bb60187f003da3402fe18561..38638e075f53e1d816e0cafcd8d4813d8707966b 100644 (file)
@@ -16,6 +16,7 @@ import pytest
 from nominatim_api.search.postcode_parser import PostcodeParser
 from nominatim_api.search.query import QueryStruct, PHRASE_ANY, PHRASE_POSTCODE, PHRASE_STREET
 
+
 @pytest.fixture
 def pc_config(project_env):
     country_file = project_env.project_dir / 'country_settings.yaml'
@@ -55,6 +56,7 @@ ky:
 
     return project_env
 
+
 def mk_query(inp):
     query = QueryStruct([])
     phrase_split = re.split(r"([ ,:'-])", inp)
@@ -80,6 +82,7 @@ def test_simple_postcode(pc_config, query, pos):
 
     assert result == {(pos, pos + 1, '45325'), (pos, pos + 1, '453 25')}
 
+
 def test_contained_postcode(pc_config):
     parser = PostcodeParser(pc_config)
 
@@ -87,7 +90,6 @@ def test_contained_postcode(pc_config):
                                                   (0, 2, '12345 DX')}
 
 
-
 @pytest.mark.parametrize('query,frm,to', [('345987', 0, 1), ('345 987', 0, 2),
                                           ('Aina 345 987', 1, 3),
                                           ('Aina 23 345 987 ff', 2, 4)])
@@ -98,6 +100,7 @@ def test_postcode_with_space(pc_config, query, frm, to):
 
     assert result == {(frm, to, '345987')}
 
+
 def test_overlapping_postcode(pc_config):
     parser = PostcodeParser(pc_config)
 
@@ -131,6 +134,7 @@ def test_postcode_with_non_matching_country_prefix(pc_config):
 
     assert not parser.parse(mk_query('ky12233'))
 
+
 def test_postcode_inside_postcode_phrase(pc_config):
     parser = PostcodeParser(pc_config)
 
index bfed38df57f5b5993dd0cdf804ac79288cd81d46..09f25f8e273850b7bada2bb4af09a687c25e8129 100644 (file)
@@ -2,7 +2,7 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 """
 Test data types for search queries.
@@ -11,14 +11,15 @@ import pytest
 
 import nominatim_api.search.query as nq
 
+
 def test_token_range_equal():
     assert nq.TokenRange(2, 3) == nq.TokenRange(2, 3)
     assert not (nq.TokenRange(2, 3) != nq.TokenRange(2, 3))
 
 
 @pytest.mark.parametrize('lop,rop', [((1, 2), (3, 4)),
-                                    ((3, 4), (3, 5)),
-                                    ((10, 12), (11, 12))])
+                                     ((3, 4), (3, 5)),
+                                     ((10, 12), (11, 12))])
 def test_token_range_unequal(lop, rop):
     assert not (nq.TokenRange(*lop) == nq.TokenRange(*rop))
     assert nq.TokenRange(*lop) != nq.TokenRange(*rop)
@@ -28,17 +29,17 @@ def test_token_range_lt():
     assert nq.TokenRange(1, 3) < nq.TokenRange(10, 12)
     assert nq.TokenRange(5, 6) < nq.TokenRange(7, 8)
     assert nq.TokenRange(1, 4) < nq.TokenRange(4, 5)
-    assert not(nq.TokenRange(5, 6) < nq.TokenRange(5, 6))
-    assert not(nq.TokenRange(10, 11) < nq.TokenRange(4, 5))
+    assert not (nq.TokenRange(5, 6) < nq.TokenRange(5, 6))
+    assert not (nq.TokenRange(10, 11) < nq.TokenRange(4, 5))
 
 
 def test_token_rankge_gt():
     assert nq.TokenRange(3, 4) > nq.TokenRange(1, 2)
     assert nq.TokenRange(100, 200) > nq.TokenRange(10, 11)
     assert nq.TokenRange(10, 11) > nq.TokenRange(4, 10)
-    assert not(nq.TokenRange(5, 6) > nq.TokenRange(5, 6))
-    assert not(nq.TokenRange(1, 2) > nq.TokenRange(3, 4))
-    assert not(nq.TokenRange(4, 10) > nq.TokenRange(3, 5))
+    assert not (nq.TokenRange(5, 6) > nq.TokenRange(5, 6))
+    assert not (nq.TokenRange(1, 2) > nq.TokenRange(3, 4))
+    assert not (nq.TokenRange(4, 10) > nq.TokenRange(3, 5))
 
 
 def test_token_range_unimplemented_ops():
@@ -58,8 +59,7 @@ def test_query_extract_words():
     words = q.extract_words(base_penalty=1.0)
 
     assert set(words.keys()) \
-             == {'12', 'ab', 'hallo', '12 ab', 'ab 12', '12 ab 12'}
+        == {'12', 'ab', 'hallo', '12 ab', 'ab 12', '12 ab 12'}
     assert sorted(words['12']) == [nq.TokenRange(0, 1, 1.0), nq.TokenRange(2, 3, 1.0)]
     assert words['12 ab'] == [nq.TokenRange(0, 2, 1.1)]
     assert words['hallo'] == [nq.TokenRange(3, 4, 1.0)]
-
index 42220b55958116a5ab6f26448e6a8431539e486f..933bdd1f73340c7e3a0a3915810cd9ab09ae7f8d 100644 (file)
@@ -2,18 +2,17 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 """
 Tests for query analyzer creation.
 """
-from pathlib import Path
-
 import pytest
 
 from nominatim_api.search.query_analyzer_factory import make_query_analyzer
 from nominatim_api.search.icu_tokenizer import ICUQueryAnalyzer
 
+
 @pytest.mark.asyncio
 async def test_import_icu_tokenizer(table_factory, api):
     table_factory('nominatim_properties',
index 2109ecb0bb7fb5ff4cd54ed08e913e446c476a95..46875a2c8323c347c79d5afda3c1619bf96cb4c4 100644 (file)
@@ -2,7 +2,7 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 """
 Tests for running the country searcher.
@@ -48,6 +48,7 @@ def test_find_from_placex(apiobj, frontend):
     assert results[0].place_id == 55
     assert results[0].accuracy == 0.8
 
+
 def test_find_from_fallback_countries(apiobj, frontend):
     apiobj.add_country('ro', 'POLYGON((0 0, 0 1, 1 1, 1 0, 0 0))')
     apiobj.add_country_name('ro', {'name': 'România'})
@@ -87,7 +88,6 @@ class TestCountryParameters:
         apiobj.add_country('ro', 'POLYGON((0 0, 0 1, 1 1, 1 0, 0 0))')
         apiobj.add_country_name('ro', {'name': 'România'})
 
-
     @pytest.mark.parametrize('geom', [napi.GeometryFormat.GEOJSON,
                                       napi.GeometryFormat.KML,
                                       napi.GeometryFormat.SVG,
@@ -100,7 +100,6 @@ class TestCountryParameters:
         assert len(results) == 1
         assert geom.name.lower() in results[0].geometry
 
-
     @pytest.mark.parametrize('pid,rids', [(76, [55]), (55, [])])
     def test_exclude_place_id(self, apiobj, frontend, pid, rids):
         results = run_search(apiobj, frontend, 0.5, ['yw', 'ro'],
@@ -108,7 +107,6 @@ class TestCountryParameters:
 
         assert [r.place_id for r in results] == rids
 
-
     @pytest.mark.parametrize('viewbox,rids', [((9, 9, 11, 11), [55]),
                                               ((-10, -10, -3, -3), [])])
     def test_bounded_viewbox_in_placex(self, apiobj, frontend, viewbox, rids):
@@ -118,9 +116,8 @@ class TestCountryParameters:
 
         assert [r.place_id for r in results] == rids
 
-
     @pytest.mark.parametrize('viewbox,numres', [((0, 0, 1, 1), 1),
-                                              ((-10, -10, -3, -3), 0)])
+                                                ((-10, -10, -3, -3), 0)])
     def test_bounded_viewbox_in_fallback(self, apiobj, frontend, viewbox, numres):
         results = run_search(apiobj, frontend, 0.5, ['ro'],
                              details=SearchDetails.from_kwargs({'viewbox': viewbox,
index 43098ddd20e5af93ca3c5b4f76235f2d565c58fa..e9650168cbba62a7d9c875fe583776aa75137216 100644 (file)
@@ -2,7 +2,7 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 """
 Tests for running the near searcher.
@@ -12,8 +12,8 @@ import pytest
 import nominatim_api as napi
 from nominatim_api.types import SearchDetails
 from nominatim_api.search.db_searches import NearSearch, PlaceSearch
-from nominatim_api.search.db_search_fields import WeightedStrings, WeightedCategories,\
-                                                  FieldLookup, FieldRanking, RankedTokens
+from nominatim_api.search.db_search_fields import WeightedStrings, WeightedCategories, \
+                                                  FieldLookup
 from nominatim_api.search.db_search_lookups import LookupAll
 
 
@@ -80,7 +80,6 @@ class TestNearSearch:
         apiobj.add_search_name(101, names=[56], country_code='mx',
                                centroid=(-10.3, 56.9))
 
-
     def test_near_in_placex(self, apiobj, frontend):
         apiobj.add_placex(place_id=22, class_='amenity', type='bank',
                           centroid=(5.6001, 4.2994))
@@ -91,7 +90,6 @@ class TestNearSearch:
 
         assert [r.place_id for r in results] == [22]
 
-
     def test_multiple_types_near_in_placex(self, apiobj, frontend):
         apiobj.add_placex(place_id=22, class_='amenity', type='bank',
                           importance=0.002,
@@ -105,7 +103,6 @@ class TestNearSearch:
 
         assert [r.place_id for r in results] == [22, 23]
 
-
     def test_near_in_classtype(self, apiobj, frontend):
         apiobj.add_placex(place_id=22, class_='amenity', type='bank',
                           centroid=(5.6, 4.34))
@@ -118,7 +115,6 @@ class TestNearSearch:
 
         assert [r.place_id for r in results] == [22]
 
-
     @pytest.mark.parametrize('cc,rid', [('us', 22), ('mx', 23)])
     def test_restrict_by_country(self, apiobj, frontend, cc, rid):
         apiobj.add_placex(place_id=22, class_='amenity', type='bank',
@@ -138,7 +134,6 @@ class TestNearSearch:
 
         assert [r.place_id for r in results] == [rid]
 
-
     @pytest.mark.parametrize('excluded,rid', [(22, 122), (122, 22)])
     def test_exclude_place_by_id(self, apiobj, frontend, excluded, rid):
         apiobj.add_placex(place_id=22, class_='amenity', type='bank',
@@ -148,13 +143,11 @@ class TestNearSearch:
                           centroid=(5.6001, 4.2994),
                           country_code='us')
 
-
         results = run_search(apiobj, frontend, 0.1, [('amenity', 'bank')],
                              details=SearchDetails(excluded=[excluded]))
 
         assert [r.place_id for r in results] == [rid]
 
-
     @pytest.mark.parametrize('layer,rids', [(napi.DataLayer.POI, [22]),
                                             (napi.DataLayer.MANMADE, [])])
     def test_with_layer(self, apiobj, frontend, layer, rids):
index c6ff16b83e8a81a62c2107cd7868b0aeab5c9f00..ed0722c3c218821e733126cb18cc295a5be3f38b 100644 (file)
@@ -2,7 +2,7 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 """
 Tests for running the generic place searcher.
@@ -14,12 +14,13 @@ import pytest
 import nominatim_api as napi
 from nominatim_api.types import SearchDetails
 from nominatim_api.search.db_searches import PlaceSearch
-from nominatim_api.search.db_search_fields import WeightedStrings, WeightedCategories,\
+from nominatim_api.search.db_search_fields import WeightedStrings, WeightedCategories, \
                                                   FieldLookup, FieldRanking, RankedTokens
 from nominatim_api.search.db_search_lookups import LookupAll, LookupAny, Restrict
 
 APIOPTIONS = ['search']
 
+
 def run_search(apiobj, frontend, global_penalty, lookup, ranking, count=2,
                hnrs=[], pcs=[], ccodes=[], quals=[],
                details=SearchDetails()):
@@ -55,29 +56,27 @@ class TestNameOnlySearches:
     def fill_database(self, apiobj):
         apiobj.add_placex(place_id=100, country_code='us',
                           centroid=(5.6, 4.3))
-        apiobj.add_search_name(100, names=[1,2,10,11], country_code='us',
+        apiobj.add_search_name(100, names=[1, 2, 10, 11], country_code='us',
                                centroid=(5.6, 4.3))
         apiobj.add_placex(place_id=101, country_code='mx',
                           centroid=(-10.3, 56.9))
-        apiobj.add_search_name(101, names=[1,2,20,21], country_code='mx',
+        apiobj.add_search_name(101, names=[1, 2, 20, 21], country_code='mx',
                                centroid=(-10.3, 56.9))
 
-
     @pytest.mark.parametrize('lookup_type', [LookupAll, Restrict])
     @pytest.mark.parametrize('rank,res', [([10], [100, 101]),
                                           ([20], [101, 100])])
     def test_lookup_all_match(self, apiobj, frontend, lookup_type, rank, res):
-        lookup = FieldLookup('name_vector', [1,2], lookup_type)
+        lookup = FieldLookup('name_vector', [1, 2], lookup_type)
         ranking = FieldRanking('name_vector', 0.4, [RankedTokens(0.0, rank)])
 
         results = run_search(apiobj, frontend, 0.1, [lookup], [ranking])
 
         assert [r.place_id for r in results] == res
 
-
     @pytest.mark.parametrize('lookup_type', [LookupAll, Restrict])
     def test_lookup_all_partial_match(self, apiobj, frontend, lookup_type):
-        lookup = FieldLookup('name_vector', [1,20], lookup_type)
+        lookup = FieldLookup('name_vector', [1, 20], lookup_type)
         ranking = FieldRanking('name_vector', 0.4, [RankedTokens(0.0, [21])])
 
         results = run_search(apiobj, frontend, 0.1, [lookup], [ranking])
@@ -88,14 +87,13 @@ class TestNameOnlySearches:
     @pytest.mark.parametrize('rank,res', [([10], [100, 101]),
                                           ([20], [101, 100])])
     def test_lookup_any_match(self, apiobj, frontend, rank, res):
-        lookup = FieldLookup('name_vector', [11,21], LookupAny)
+        lookup = FieldLookup('name_vector', [11, 21], LookupAny)
         ranking = FieldRanking('name_vector', 0.4, [RankedTokens(0.0, rank)])
 
         results = run_search(apiobj, frontend, 0.1, [lookup], [ranking])
 
         assert [r.place_id for r in results] == res
 
-
     def test_lookup_any_partial_match(self, apiobj, frontend):
         lookup = FieldLookup('name_vector', [20], LookupAll)
         ranking = FieldRanking('name_vector', 0.4, [RankedTokens(0.0, [21])])
@@ -105,19 +103,17 @@ class TestNameOnlySearches:
         assert len(results) == 1
         assert results[0].place_id == 101
 
-
     @pytest.mark.parametrize('cc,res', [('us', 100), ('mx', 101)])
     def test_lookup_restrict_country(self, apiobj, frontend, cc, res):
-        lookup = FieldLookup('name_vector', [1,2], LookupAll)
+        lookup = FieldLookup('name_vector', [1, 2], LookupAll)
         ranking = FieldRanking('name_vector', 0.4, [RankedTokens(0.0, [10])])
 
         results = run_search(apiobj, frontend, 0.1, [lookup], [ranking], ccodes=[cc])
 
         assert [r.place_id for r in results] == [res]
 
-
     def test_lookup_restrict_placeid(self, apiobj, frontend):
-        lookup = FieldLookup('name_vector', [1,2], LookupAll)
+        lookup = FieldLookup('name_vector', [1, 2], LookupAll)
         ranking = FieldRanking('name_vector', 0.4, [RankedTokens(0.0, [10])])
 
         results = run_search(apiobj, frontend, 0.1, [lookup], [ranking],
@@ -125,7 +121,6 @@ class TestNameOnlySearches:
 
         assert [r.place_id for r in results] == [100]
 
-
     @pytest.mark.parametrize('geom', [napi.GeometryFormat.GEOJSON,
                                       napi.GeometryFormat.KML,
                                       napi.GeometryFormat.SVG,
@@ -139,7 +134,6 @@ class TestNameOnlySearches:
 
         assert geom.name.lower() in results[0].geometry
 
-
     @pytest.mark.parametrize('factor,npoints', [(0.0, 3), (1.0, 2)])
     def test_return_simplified_geometry(self, apiobj, frontend, factor, npoints):
         apiobj.add_placex(place_id=333, country_code='us',
@@ -162,7 +156,6 @@ class TestNameOnlySearches:
         assert result.place_id == 333
         assert len(geom['coordinates']) == npoints
 
-
     @pytest.mark.parametrize('viewbox', ['5.0,4.0,6.0,5.0', '5.7,4.0,6.0,5.0'])
     @pytest.mark.parametrize('wcount,rids', [(2, [100, 101]), (20000, [100])])
     def test_prefer_viewbox(self, apiobj, frontend, viewbox, wcount, rids):
@@ -177,18 +170,16 @@ class TestNameOnlySearches:
                              details=SearchDetails.from_kwargs({'viewbox': viewbox}))
         assert [r.place_id for r in results] == rids
 
-
     @pytest.mark.parametrize('viewbox', ['5.0,4.0,6.0,5.0', '5.55,4.27,5.62,4.31'])
     def test_force_viewbox(self, apiobj, frontend, viewbox):
         lookup = FieldLookup('name_vector', [1, 2], LookupAll)
 
-        details=SearchDetails.from_kwargs({'viewbox': viewbox,
-                                           'bounded_viewbox': True})
+        details = SearchDetails.from_kwargs({'viewbox': viewbox,
+                                             'bounded_viewbox': True})
 
         results = run_search(apiobj, frontend, 0.1, [lookup], [], details=details)
         assert [r.place_id for r in results] == [100]
 
-
     def test_prefer_near(self, apiobj, frontend):
         lookup = FieldLookup('name_vector', [1, 2], LookupAll)
         ranking = FieldRanking('name_vector', 0.4, [RankedTokens(0.0, [21])])
@@ -202,13 +193,12 @@ class TestNameOnlySearches:
         results.sort(key=lambda r: -r.importance)
         assert [r.place_id for r in results] == [100, 101]
 
-
     @pytest.mark.parametrize('radius', [0.09, 0.11])
     def test_force_near(self, apiobj, frontend, radius):
         lookup = FieldLookup('name_vector', [1, 2], LookupAll)
 
-        details=SearchDetails.from_kwargs({'near': '5.6,4.3',
-                                           'near_radius': radius})
+        details = SearchDetails.from_kwargs({'near': '5.6,4.3',
+                                             'near_radius': radius})
 
         results = run_search(apiobj, frontend, 0.1, [lookup], [], details=details)
 
@@ -228,7 +218,7 @@ class TestStreetWithHousenumber:
         apiobj.add_placex(place_id=1000, class_='highway', type='residential',
                           rank_search=26, rank_address=26,
                           country_code='es')
-        apiobj.add_search_name(1000, names=[1,2,10,11],
+        apiobj.add_search_name(1000, names=[1, 2, 10, 11],
                                search_rank=26, address_rank=26,
                                country_code='es')
         apiobj.add_placex(place_id=91, class_='place', type='house',
@@ -243,26 +233,24 @@ class TestStreetWithHousenumber:
         apiobj.add_placex(place_id=2000, class_='highway', type='residential',
                           rank_search=26, rank_address=26,
                           country_code='pt')
-        apiobj.add_search_name(2000, names=[1,2,20,21],
+        apiobj.add_search_name(2000, names=[1, 2, 20, 21],
                                search_rank=26, address_rank=26,
                                country_code='pt')
 
-
     @pytest.mark.parametrize('hnr,res', [('20', [91, 1]), ('20 a', [1]),
                                          ('21', [2]), ('22', [2, 92]),
                                          ('24', [93]), ('25', [])])
     def test_lookup_by_single_housenumber(self, apiobj, frontend, hnr, res):
-        lookup = FieldLookup('name_vector', [1,2], LookupAll)
+        lookup = FieldLookup('name_vector', [1, 2], LookupAll)
         ranking = FieldRanking('name_vector', 0.3, [RankedTokens(0.0, [10])])
 
         results = run_search(apiobj, frontend, 0.1, [lookup], [ranking], hnrs=[hnr])
 
         assert [r.place_id for r in results] == res + [1000, 2000]
 
-
     @pytest.mark.parametrize('cc,res', [('es', [2, 1000]), ('pt', [92, 2000])])
     def test_lookup_with_country_restriction(self, apiobj, frontend, cc, res):
-        lookup = FieldLookup('name_vector', [1,2], LookupAll)
+        lookup = FieldLookup('name_vector', [1, 2], LookupAll)
         ranking = FieldRanking('name_vector', 0.3, [RankedTokens(0.0, [10])])
 
         results = run_search(apiobj, frontend, 0.1, [lookup], [ranking], hnrs=['22'],
@@ -270,9 +258,8 @@ class TestStreetWithHousenumber:
 
         assert [r.place_id for r in results] == res
 
-
     def test_lookup_exclude_housenumber_placeid(self, apiobj, frontend):
-        lookup = FieldLookup('name_vector', [1,2], LookupAll)
+        lookup = FieldLookup('name_vector', [1, 2], LookupAll)
         ranking = FieldRanking('name_vector', 0.3, [RankedTokens(0.0, [10])])
 
         results = run_search(apiobj, frontend, 0.1, [lookup], [ranking], hnrs=['22'],
@@ -280,9 +267,8 @@ class TestStreetWithHousenumber:
 
         assert [r.place_id for r in results] == [2, 1000, 2000]
 
-
     def test_lookup_exclude_street_placeid(self, apiobj, frontend):
-        lookup = FieldLookup('name_vector', [1,2], LookupAll)
+        lookup = FieldLookup('name_vector', [1, 2], LookupAll)
         ranking = FieldRanking('name_vector', 0.3, [RankedTokens(0.0, [10])])
 
         results = run_search(apiobj, frontend, 0.1, [lookup], [ranking], hnrs=['22'],
@@ -290,9 +276,8 @@ class TestStreetWithHousenumber:
 
         assert [r.place_id for r in results] == [2, 92, 2000]
 
-
     def test_lookup_only_house_qualifier(self, apiobj, frontend):
-        lookup = FieldLookup('name_vector', [1,2], LookupAll)
+        lookup = FieldLookup('name_vector', [1, 2], LookupAll)
         ranking = FieldRanking('name_vector', 0.3, [RankedTokens(0.0, [10])])
 
         results = run_search(apiobj, frontend, 0.1, [lookup], [ranking], hnrs=['22'],
@@ -300,9 +285,8 @@ class TestStreetWithHousenumber:
 
         assert [r.place_id for r in results] == [2, 92]
 
-
     def test_lookup_only_street_qualifier(self, apiobj, frontend):
-        lookup = FieldLookup('name_vector', [1,2], LookupAll)
+        lookup = FieldLookup('name_vector', [1, 2], LookupAll)
         ranking = FieldRanking('name_vector', 0.3, [RankedTokens(0.0, [10])])
 
         results = run_search(apiobj, frontend, 0.1, [lookup], [ranking], hnrs=['22'],
@@ -310,10 +294,9 @@ class TestStreetWithHousenumber:
 
         assert [r.place_id for r in results] == [1000, 2000]
 
-
     @pytest.mark.parametrize('rank,found', [(26, True), (27, False), (30, False)])
     def test_lookup_min_rank(self, apiobj, frontend, rank, found):
-        lookup = FieldLookup('name_vector', [1,2], LookupAll)
+        lookup = FieldLookup('name_vector', [1, 2], LookupAll)
         ranking = FieldRanking('name_vector', 0.3, [RankedTokens(0.0, [10])])
 
         results = run_search(apiobj, frontend, 0.1, [lookup], [ranking], hnrs=['22'],
@@ -321,7 +304,6 @@ class TestStreetWithHousenumber:
 
         assert [r.place_id for r in results] == ([2, 92, 1000, 2000] if found else [2, 92])
 
-
     @pytest.mark.parametrize('geom', [napi.GeometryFormat.GEOJSON,
                                       napi.GeometryFormat.KML,
                                       napi.GeometryFormat.SVG,
@@ -343,7 +325,7 @@ def test_very_large_housenumber(apiobj, frontend):
     apiobj.add_placex(place_id=2000, class_='highway', type='residential',
                       rank_search=26, rank_address=26,
                       country_code='pt')
-    apiobj.add_search_name(2000, names=[1,2],
+    apiobj.add_search_name(2000, names=[1, 2],
                            search_rank=26, address_rank=26,
                            country_code='pt')
 
@@ -405,7 +387,6 @@ class TestInterpolations:
                            centroid=(10.0, 10.00001),
                            geometry='LINESTRING(9.995 10.00001, 10.005 10.00001)')
 
-
     @pytest.mark.parametrize('hnr,res', [('21', [992]), ('22', []), ('23', [991])])
     def test_lookup_housenumber(self, apiobj, frontend, hnr, res):
         lookup = FieldLookup('name_vector', [111], LookupAll)
@@ -414,7 +395,6 @@ class TestInterpolations:
 
         assert [r.place_id for r in results] == res + [990]
 
-
     @pytest.mark.parametrize('geom', [napi.GeometryFormat.GEOJSON,
                                       napi.GeometryFormat.KML,
                                       napi.GeometryFormat.SVG,
@@ -429,7 +409,6 @@ class TestInterpolations:
         assert geom.name.lower() in results[0].geometry
 
 
-
 class TestTiger:
 
     @pytest.fixture(autouse=True)
@@ -453,7 +432,6 @@ class TestTiger:
                          centroid=(10.0, 10.00001),
                          geometry='LINESTRING(9.995 10.00001, 10.005 10.00001)')
 
-
     @pytest.mark.parametrize('hnr,res', [('21', [992]), ('22', []), ('23', [991])])
     def test_lookup_housenumber(self, apiobj, frontend, hnr, res):
         lookup = FieldLookup('name_vector', [111], LookupAll)
@@ -462,7 +440,6 @@ class TestTiger:
 
         assert [r.place_id for r in results] == res + [990]
 
-
     @pytest.mark.parametrize('geom', [napi.GeometryFormat.GEOJSON,
                                       napi.GeometryFormat.KML,
                                       napi.GeometryFormat.SVG,
@@ -513,15 +490,15 @@ class TestLayersRank30:
                                importance=0.0005,
                                address_rank=0, search_rank=30)
 
-
-    @pytest.mark.parametrize('layer,res', [(napi.DataLayer.ADDRESS, [223]),
-                                           (napi.DataLayer.POI, [224]),
-                                           (napi.DataLayer.ADDRESS | napi.DataLayer.POI, [223, 224]),
-                                           (napi.DataLayer.MANMADE, [225]),
-                                           (napi.DataLayer.RAILWAY, [226]),
-                                           (napi.DataLayer.NATURAL, [227]),
-                                           (napi.DataLayer.MANMADE | napi.DataLayer.NATURAL, [225, 227]),
-                                           (napi.DataLayer.MANMADE | napi.DataLayer.RAILWAY, [225, 226])])
+    @pytest.mark.parametrize('layer,res',
+                             [(napi.DataLayer.ADDRESS, [223]),
+                              (napi.DataLayer.POI, [224]),
+                              (napi.DataLayer.ADDRESS | napi.DataLayer.POI, [223, 224]),
+                              (napi.DataLayer.MANMADE, [225]),
+                              (napi.DataLayer.RAILWAY, [226]),
+                              (napi.DataLayer.NATURAL, [227]),
+                              (napi.DataLayer.MANMADE | napi.DataLayer.NATURAL, [225, 227]),
+                              (napi.DataLayer.MANMADE | napi.DataLayer.RAILWAY, [225, 226])])
     def test_layers_rank30(self, apiobj, frontend, layer, res):
         lookup = FieldLookup('name_vector', [34], LookupAny)
 
index d4319a57db2a349897da06a8ed63a59eee837ad5..9387385eb6352d9f3ea9e94d34a6a066ce2d2449 100644 (file)
@@ -2,14 +2,13 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 """
 Tests for running the POI searcher.
 """
 import pytest
 
-import nominatim_api as napi
 from nominatim_api.types import SearchDetails
 from nominatim_api.search.db_searches import PoiSearch
 from nominatim_api.search.db_search_fields import WeightedStrings, WeightedCategories
@@ -84,14 +83,12 @@ class TestPoiSearchWithRestrictions:
         else:
             self.args = {'near': '34.3, 56.100021', 'near_radius': 0.001}
 
-
     def test_unrestricted(self, apiobj, frontend):
         results = run_search(apiobj, frontend, 0.1, [('highway', 'bus_stop')], [0.5],
                              details=SearchDetails.from_kwargs(self.args))
 
         assert [r.place_id for r in results] == [1, 2]
 
-
     def test_restict_country(self, apiobj, frontend):
         results = run_search(apiobj, frontend, 0.1, [('highway', 'bus_stop')], [0.5],
                              ccodes=['de', 'nz'],
@@ -99,7 +96,6 @@ class TestPoiSearchWithRestrictions:
 
         assert [r.place_id for r in results] == [2]
 
-
     def test_restrict_by_viewbox(self, apiobj, frontend):
         args = {'bounded_viewbox': True, 'viewbox': '34.299,56.0,34.3001,56.10001'}
         args.update(self.args)
index 369e15045e0fd4ecf11721e67ee342cb661ddef3..529fb409609a759c9a01c552bbcb285ba882fe38 100644 (file)
@@ -2,7 +2,7 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 """
 Tests for running the postcode searcher.
@@ -15,6 +15,7 @@ from nominatim_api.search.db_searches import PostcodeSearch
 from nominatim_api.search.db_search_fields import WeightedStrings, FieldLookup, \
                                                   FieldRanking, RankedTokens
 
+
 def run_search(apiobj, frontend, global_penalty, pcs, pc_penalties=None,
                ccodes=[], lookup=[], ranking=[], details=SearchDetails()):
     if pc_penalties is None:
@@ -85,26 +86,24 @@ class TestPostcodeSearchWithAddress:
         apiobj.add_placex(place_id=1000, class_='place', type='village',
                           rank_search=22, rank_address=22,
                           country_code='ch')
-        apiobj.add_search_name(1000, names=[1,2,10,11],
+        apiobj.add_search_name(1000, names=[1, 2, 10, 11],
                                search_rank=22, address_rank=22,
                                country_code='ch')
         apiobj.add_placex(place_id=2000, class_='place', type='village',
                           rank_search=22, rank_address=22,
                           country_code='pl')
-        apiobj.add_search_name(2000, names=[1,2,20,21],
+        apiobj.add_search_name(2000, names=[1, 2, 20, 21],
                                search_rank=22, address_rank=22,
                                country_code='pl')
 
-
     def test_lookup_both(self, apiobj, frontend):
-        lookup = FieldLookup('name_vector', [1,2], 'restrict')
+        lookup = FieldLookup('name_vector', [1, 2], 'restrict')
         ranking = FieldRanking('name_vector', 0.3, [RankedTokens(0.0, [10])])
 
         results = run_search(apiobj, frontend, 0.1, ['12345'], lookup=[lookup], ranking=[ranking])
 
         assert [r.place_id for r in results] == [100, 101]
 
-
     def test_restrict_by_name(self, apiobj, frontend):
         lookup = FieldLookup('name_vector', [10], 'restrict')
 
@@ -112,11 +111,10 @@ class TestPostcodeSearchWithAddress:
 
         assert [r.place_id for r in results] == [100]
 
-
     @pytest.mark.parametrize('coord,place_id', [((16.5, 5), 100),
                                                 ((-45.1, 7.004), 101)])
     def test_lookup_near(self, apiobj, frontend, coord, place_id):
-        lookup = FieldLookup('name_vector', [1,2], 'restrict')
+        lookup = FieldLookup('name_vector', [1, 2], 'restrict')
         ranking = FieldRanking('name_vector', 0.3, [RankedTokens(0.0, [10])])
 
         results = run_search(apiobj, frontend, 0.1, ['12345'],
@@ -126,7 +124,6 @@ class TestPostcodeSearchWithAddress:
 
         assert [r.place_id for r in results] == [place_id]
 
-
     @pytest.mark.parametrize('geom', [napi.GeometryFormat.GEOJSON,
                                       napi.GeometryFormat.KML,
                                       napi.GeometryFormat.SVG,
@@ -138,18 +135,16 @@ class TestPostcodeSearchWithAddress:
         assert results
         assert all(geom.name.lower() in r.geometry for r in results)
 
-
-    @pytest.mark.parametrize('viewbox, rids', [('-46,6,-44,8', [101,100]),
-                                               ('16,4,18,6', [100,101])])
+    @pytest.mark.parametrize('viewbox, rids', [('-46,6,-44,8', [101, 100]),
+                                               ('16,4,18,6', [100, 101])])
     def test_prefer_viewbox(self, apiobj, frontend, viewbox, rids):
         results = run_search(apiobj, frontend, 0.1, ['12345'],
                              details=SearchDetails.from_kwargs({'viewbox': viewbox}))
 
         assert [r.place_id for r in results] == rids
 
-
     @pytest.mark.parametrize('viewbox, rid', [('-46,6,-44,8', 101),
-                                               ('16,4,18,6', 100)])
+                                              ('16,4,18,6', 100)])
     def test_restrict_to_viewbox(self, apiobj, frontend, viewbox, rid):
         results = run_search(apiobj, frontend, 0.1, ['12345'],
                              details=SearchDetails.from_kwargs({'viewbox': viewbox,
@@ -157,7 +152,6 @@ class TestPostcodeSearchWithAddress:
 
         assert [r.place_id for r in results] == [rid]
 
-
     @pytest.mark.parametrize('coord,rids', [((17.05, 5), [100, 101]),
                                             ((-45, 7.1), [101, 100])])
     def test_prefer_near(self, apiobj, frontend, coord, rids):
@@ -166,7 +160,6 @@ class TestPostcodeSearchWithAddress:
 
         assert [r.place_id for r in results] == rids
 
-
     @pytest.mark.parametrize('pid,rid', [(100, 101), (101, 100)])
     def test_exclude(self, apiobj, frontend, pid, rid):
         results = run_search(apiobj, frontend, 0.1, ['12345'],
index fff8d471e246c8fdec6c72346a15c47c43d01fce..2ffba335de9e027c829ad84bfff7160267b25102 100644 (file)
@@ -2,7 +2,7 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 """
 Test for creation of token assignments from tokenized queries.
@@ -11,7 +11,10 @@ import pytest
 
 from nominatim_api.search.query import QueryStruct, Phrase, TokenRange, Token
 import nominatim_api.search.query as qmod
-from nominatim_api.search.token_assignment import yield_token_assignments, TokenAssignment, PENALTY_TOKENCHANGE
+from nominatim_api.search.token_assignment import (yield_token_assignments,
+                                                   TokenAssignment,
+                                                   PENALTY_TOKENCHANGE)
+
 
 class MyToken(Token):
     def get_category(self):
@@ -102,8 +105,7 @@ def test_multiple_simple_words(btype):
                       TokenAssignment(penalty=penalty, name=TokenRange(1, 3),
                                       address=[TokenRange(0, 1)]),
                       TokenAssignment(penalty=penalty, name=TokenRange(2, 3),
-                                      address=[TokenRange(0, 2)])
-                     )
+                                      address=[TokenRange(0, 2)]))
 
 
 def test_multiple_words_respect_phrase_break():
@@ -156,6 +158,7 @@ def test_housenumber_and_postcode():
                                       address=[TokenRange(0, 1), TokenRange(2, 3)],
                                       postcode=TokenRange(3, 4)))
 
+
 def test_postcode_and_housenumber():
     q = make_query((qmod.BREAK_START, qmod.PHRASE_ANY, [(1, qmod.TOKEN_PARTIAL)]),
                    (qmod.BREAK_WORD, qmod.PHRASE_ANY, [(2, qmod.TOKEN_POSTCODE)]),
@@ -211,11 +214,11 @@ def test_housenumber_many_phrases():
     check_assignments(yield_token_assignments(q),
                       TokenAssignment(penalty=0.1,
                                       name=TokenRange(4, 5),
-                                      housenumber=TokenRange(3, 4),\
+                                      housenumber=TokenRange(3, 4),
                                       address=[TokenRange(0, 1), TokenRange(1, 2),
                                                TokenRange(2, 3)]),
                       TokenAssignment(penalty=0.1,
-                                      housenumber=TokenRange(3, 4),\
+                                      housenumber=TokenRange(3, 4),
                                       address=[TokenRange(0, 1), TokenRange(1, 2),
                                                TokenRange(2, 3), TokenRange(4, 5)]))
 
@@ -299,7 +302,6 @@ def test_qualifier_at_beginning():
                    (qmod.BREAK_WORD, qmod.PHRASE_ANY, [(2, qmod.TOKEN_PARTIAL)]),
                    (qmod.BREAK_WORD, qmod.PHRASE_ANY, [(3, qmod.TOKEN_PARTIAL)]))
 
-
     check_assignments(yield_token_assignments(q),
                       TokenAssignment(penalty=0.1, name=TokenRange(1, 3),
                                       qualifier=TokenRange(0, 1)),
@@ -315,7 +317,6 @@ def test_qualifier_after_name():
                    (qmod.BREAK_WORD, qmod.PHRASE_ANY, [(4, qmod.TOKEN_PARTIAL)]),
                    (qmod.BREAK_WORD, qmod.PHRASE_ANY, [(5, qmod.TOKEN_PARTIAL)]))
 
-
     check_assignments(yield_token_assignments(q),
                       TokenAssignment(penalty=0.2, name=TokenRange(0, 2),
                                       qualifier=TokenRange(2, 3),
@@ -349,4 +350,3 @@ def test_qualifier_in_middle_of_phrase():
                    (qmod.BREAK_PHRASE, qmod.PHRASE_ANY, [(5, qmod.TOKEN_PARTIAL)]))
 
     check_assignments(yield_token_assignments(q))
-
index f62b0d9e346c8357fe9ff5690741bdada8114935..9b29411a027a51bb8267440610c1e24b76d5fae3 100644 (file)
@@ -2,12 +2,11 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 """
 Tests for enhanced connection class for API functions.
 """
-from pathlib import Path
 import pytest
 
 import sqlalchemy as sa
@@ -76,7 +75,7 @@ async def test_get_db_property_existing(api):
 
 
 @pytest.mark.asyncio
-async def test_get_db_property_existing(api):
+async def test_get_db_property_bad_name(api):
     async with api.begin() as conn:
         with pytest.raises(ValueError):
             await conn.get_db_property('dfkgjd.rijg')
index 9e1138869e8d632b322dce7d7306c7f9cd920f26..8ea4c9cd165949f6cca3146407254a5c93cc7978 100644 (file)
@@ -2,20 +2,20 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 """
 Tests for the deletable v1 API call.
 """
 import json
-from pathlib import Path
 
 import pytest
 
-from fake_adaptor import FakeAdaptor, FakeError, FakeResponse
+from fake_adaptor import FakeAdaptor
 
 import nominatim_api.v1.server_glue as glue
 
+
 class TestDeletableEndPoint:
 
     @pytest.fixture(autouse=True)
@@ -25,14 +25,13 @@ class TestDeletableEndPoint:
                       content=[(345, 'N', 'boundary', 'administrative'),
                                (781, 'R', 'landuse', 'wood'),
                                (781, 'R', 'landcover', 'grass')])
-        table_factory('placex',
-                      definition="""place_id bigint, osm_id bigint, osm_type char(1),
-                                    class text, type text, name HSTORE, country_code char(2)""",
-                      content=[(1, 345, 'N', 'boundary', 'administrative', {'old_name': 'Former'}, 'ab'),
-                               (2, 781, 'R', 'landuse', 'wood', {'name': 'Wood'}, 'cd'),
-                               (3, 781, 'R', 'landcover', 'grass', None, 'cd')])
-
-
+        table_factory(
+            'placex',
+            definition="""place_id bigint, osm_id bigint, osm_type char(1),
+                          class text, type text, name HSTORE, country_code char(2)""",
+            content=[(1, 345, 'N', 'boundary', 'administrative', {'old_name': 'Former'}, 'ab'),
+                     (2, 781, 'R', 'landuse', 'wood', {'name': 'Wood'}, 'cd'),
+                     (3, 781, 'R', 'landcover', 'grass', None, 'cd')])
 
     @pytest.mark.asyncio
     async def test_deletable(self, api):
index 7f405728b284536ce6d221c857b0bbc27c46bed0..4f6dd92b06a2c2354ed2c8dcc40b881ff45b08ef 100644 (file)
@@ -2,7 +2,7 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 """
 Tests for details API call.
@@ -13,23 +13,24 @@ import pytest
 
 import nominatim_api as napi
 
+
 @pytest.mark.parametrize('idobj', (napi.PlaceID(332), napi.OsmID('W', 4),
                                    napi.OsmID('W', 4, 'highway')))
 def test_lookup_in_placex(apiobj, frontend, idobj):
     import_date = dt.datetime(2022, 12, 7, 14, 14, 46, 0)
     apiobj.add_placex(place_id=332, osm_type='W', osm_id=4,
-                     class_='highway', type='residential',
-                     name={'name': 'Road'}, address={'city': 'Barrow'},
-                     extratags={'surface': 'paved'},
-                     parent_place_id=34, linked_place_id=55,
-                     admin_level=15, country_code='gb',
-                     housenumber='4',
-                     postcode='34425', wikipedia='en:Faa',
-                     rank_search=27, rank_address=26,
-                     importance=0.01,
-                     centroid=(23, 34),
-                     indexed_date=import_date,
-                     geometry='LINESTRING(23 34, 23.1 34, 23.1 34.1, 23 34)')
+                      class_='highway', type='residential',
+                      name={'name': 'Road'}, address={'city': 'Barrow'},
+                      extratags={'surface': 'paved'},
+                      parent_place_id=34, linked_place_id=55,
+                      admin_level=15, country_code='gb',
+                      housenumber='4',
+                      postcode='34425', wikipedia='en:Faa',
+                      rank_search=27, rank_address=26,
+                      importance=0.01,
+                      centroid=(23, 34),
+                      indexed_date=import_date,
+                      geometry='LINESTRING(23 34, 23.1 34, 23.1 34.1, 23 34)')
 
     api = frontend(apiobj, options={'details'})
     result = api.details(idobj)
@@ -73,12 +74,12 @@ def test_lookup_in_placex(apiobj, frontend, idobj):
 def test_lookup_in_placex_minimal_info(apiobj, frontend):
     import_date = dt.datetime(2022, 12, 7, 14, 14, 46, 0)
     apiobj.add_placex(place_id=332, osm_type='W', osm_id=4,
-                     class_='highway', type='residential',
-                     admin_level=15,
-                     rank_search=27, rank_address=26,
-                     centroid=(23, 34),
-                     indexed_date=import_date,
-                     geometry='LINESTRING(23 34, 23.1 34, 23.1 34.1, 23 34)')
+                      class_='highway', type='residential',
+                      admin_level=15,
+                      rank_search=27, rank_address=26,
+                      centroid=(23, 34),
+                      indexed_date=import_date,
+                      geometry='LINESTRING(23 34, 23.1 34, 23.1 34.1, 23 34)')
 
     api = frontend(apiobj, options={'details'})
     result = api.details(napi.PlaceID(332))
@@ -131,9 +132,9 @@ def test_lookup_in_placex_with_geometry(apiobj, frontend):
 
 def test_lookup_placex_with_address_details(apiobj, frontend):
     apiobj.add_placex(place_id=332, osm_type='W', osm_id=4,
-                     class_='highway', type='residential',  name='Street',
-                     country_code='pl',
-                     rank_search=27, rank_address=26)
+                      class_='highway', type='residential',  name='Street',
+                      country_code='pl',
+                      rank_search=27, rank_address=26)
     apiobj.add_address_placex(332, fromarea=False, isaddress=False,
                               distance=0.0034,
                               place_id=1000, osm_type='N', osm_id=3333,
@@ -178,9 +179,9 @@ def test_lookup_placex_with_address_details(apiobj, frontend):
 
 def test_lookup_place_with_linked_places_none_existing(apiobj, frontend):
     apiobj.add_placex(place_id=332, osm_type='W', osm_id=4,
-                     class_='highway', type='residential',  name='Street',
-                     country_code='pl', linked_place_id=45,
-                     rank_search=27, rank_address=26)
+                      class_='highway', type='residential',  name='Street',
+                      country_code='pl', linked_place_id=45,
+                      rank_search=27, rank_address=26)
 
     api = frontend(apiobj, options={'details'})
     result = api.details(napi.PlaceID(332), linked_places=True)
@@ -190,17 +191,17 @@ def test_lookup_place_with_linked_places_none_existing(apiobj, frontend):
 
 def test_lookup_place_with_linked_places_existing(apiobj, frontend):
     apiobj.add_placex(place_id=332, osm_type='W', osm_id=4,
-                     class_='highway', type='residential',  name='Street',
-                     country_code='pl', linked_place_id=45,
-                     rank_search=27, rank_address=26)
+                      class_='highway', type='residential',  name='Street',
+                      country_code='pl', linked_place_id=45,
+                      rank_search=27, rank_address=26)
     apiobj.add_placex(place_id=1001, osm_type='W', osm_id=5,
-                     class_='highway', type='residential',  name='Street',
-                     country_code='pl', linked_place_id=332,
-                     rank_search=27, rank_address=26)
+                      class_='highway', type='residential',  name='Street',
+                      country_code='pl', linked_place_id=332,
+                      rank_search=27, rank_address=26)
     apiobj.add_placex(place_id=1002, osm_type='W', osm_id=6,
-                     class_='highway', type='residential',  name='Street',
-                     country_code='pl', linked_place_id=332,
-                     rank_search=27, rank_address=26)
+                      class_='highway', type='residential',  name='Street',
+                      country_code='pl', linked_place_id=332,
+                      rank_search=27, rank_address=26)
 
     api = frontend(apiobj, options={'details'})
     result = api.details(napi.PlaceID(332), linked_places=True)
@@ -221,9 +222,9 @@ def test_lookup_place_with_linked_places_existing(apiobj, frontend):
 
 def test_lookup_place_with_parented_places_not_existing(apiobj, frontend):
     apiobj.add_placex(place_id=332, osm_type='W', osm_id=4,
-                     class_='highway', type='residential',  name='Street',
-                     country_code='pl', parent_place_id=45,
-                     rank_search=27, rank_address=26)
+                      class_='highway', type='residential',  name='Street',
+                      country_code='pl', parent_place_id=45,
+                      rank_search=27, rank_address=26)
 
     api = frontend(apiobj, options={'details'})
     result = api.details(napi.PlaceID(332), parented_places=True)
@@ -233,17 +234,17 @@ def test_lookup_place_with_parented_places_not_existing(apiobj, frontend):
 
 def test_lookup_place_with_parented_places_existing(apiobj, frontend):
     apiobj.add_placex(place_id=332, osm_type='W', osm_id=4,
-                     class_='highway', type='residential',  name='Street',
-                     country_code='pl', parent_place_id=45,
-                     rank_search=27, rank_address=26)
+                      class_='highway', type='residential',  name='Street',
+                      country_code='pl', parent_place_id=45,
+                      rank_search=27, rank_address=26)
     apiobj.add_placex(place_id=1001, osm_type='N', osm_id=5,
-                     class_='place', type='house', housenumber='23',
-                     country_code='pl', parent_place_id=332,
-                     rank_search=30, rank_address=30)
+                      class_='place', type='house', housenumber='23',
+                      country_code='pl', parent_place_id=332,
+                      rank_search=30, rank_address=30)
     apiobj.add_placex(place_id=1002, osm_type='W', osm_id=6,
-                     class_='highway', type='residential',  name='Street',
-                     country_code='pl', parent_place_id=332,
-                     rank_search=27, rank_address=26)
+                      class_='highway', type='residential',  name='Street',
+                      country_code='pl', parent_place_id=332,
+                      rank_search=27, rank_address=26)
 
     api = frontend(apiobj, options={'details'})
     result = api.details(napi.PlaceID(332), parented_places=True)
@@ -332,9 +333,9 @@ def test_lookup_osmline_with_address_details(apiobj, frontend):
                        startnumber=2, endnumber=4, step=1,
                        parent_place_id=332)
     apiobj.add_placex(place_id=332, osm_type='W', osm_id=4,
-                     class_='highway', type='residential',  name='Street',
-                     country_code='pl',
-                     rank_search=27, rank_address=26)
+                      class_='highway', type='residential',  name='Street',
+                      country_code='pl',
+                      rank_search=27, rank_address=26)
     apiobj.add_address_placex(332, fromarea=False, isaddress=False,
                               distance=0.0034,
                               place_id=1000, osm_type='N', osm_id=3333,
@@ -432,9 +433,9 @@ def test_lookup_tiger_with_address_details(apiobj, frontend):
                      startnumber=2, endnumber=4, step=1,
                      parent_place_id=332)
     apiobj.add_placex(place_id=332, osm_type='W', osm_id=4,
-                     class_='highway', type='residential',  name='Street',
-                     country_code='us',
-                     rank_search=27, rank_address=26)
+                      class_='highway', type='residential',  name='Street',
+                      country_code='us',
+                      rank_search=27, rank_address=26)
     apiobj.add_address_placex(332, fromarea=False, isaddress=False,
                               distance=0.0034,
                               place_id=1000, osm_type='N', osm_id=3333,
@@ -571,6 +572,7 @@ def test_lookup_postcode_with_address_details(apiobj, frontend):
                                 rank_address=4, distance=0.0)
            ]
 
+
 @pytest.mark.parametrize('objid', [napi.PlaceID(1736),
                                    napi.OsmID('W', 55),
                                    napi.OsmID('N', 55, 'amenity')])
@@ -583,8 +585,8 @@ def test_lookup_missing_object(apiobj, frontend, objid):
 
 
 @pytest.mark.parametrize('gtype', (napi.GeometryFormat.KML,
-                                    napi.GeometryFormat.SVG,
-                                    napi.GeometryFormat.TEXT))
+                                   napi.GeometryFormat.SVG,
+                                   napi.GeometryFormat.TEXT))
 def test_lookup_unsupported_geometry(apiobj, frontend, gtype):
     apiobj.add_placex(place_id=332)
 
index 4281cd6c924cfa2dd0b75de50439ace9a8a32190..a2660f51c1a5cb4598b6ec69001f8a2ef2910414 100644 (file)
@@ -2,7 +2,7 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 """
 Tests for lookup API call.
@@ -13,6 +13,7 @@ import pytest
 
 import nominatim_api as napi
 
+
 def test_lookup_empty_list(apiobj, frontend):
     api = frontend(apiobj, options={'details'})
     assert api.lookup([]) == []
@@ -28,17 +29,17 @@ def test_lookup_non_existing(apiobj, frontend):
                                    napi.OsmID('W', 4, 'highway')))
 def test_lookup_single_placex(apiobj, frontend, idobj):
     apiobj.add_placex(place_id=332, osm_type='W', osm_id=4,
-                     class_='highway', type='residential',
-                     name={'name': 'Road'}, address={'city': 'Barrow'},
-                     extratags={'surface': 'paved'},
-                     parent_place_id=34, linked_place_id=55,
-                     admin_level=15, country_code='gb',
-                     housenumber='4',
-                     postcode='34425', wikipedia='en:Faa',
-                     rank_search=27, rank_address=26,
-                     importance=0.01,
-                     centroid=(23, 34),
-                     geometry='LINESTRING(23 34, 23.1 34, 23.1 34.1, 23 34)')
+                      class_='highway', type='residential',
+                      name={'name': 'Road'}, address={'city': 'Barrow'},
+                      extratags={'surface': 'paved'},
+                      parent_place_id=34, linked_place_id=55,
+                      admin_level=15, country_code='gb',
+                      housenumber='4',
+                      postcode='34425', wikipedia='en:Faa',
+                      rank_search=27, rank_address=26,
+                      importance=0.01,
+                      centroid=(23, 34),
+                      geometry='LINESTRING(23 34, 23.1 34, 23.1 34.1, 23 34)')
 
     api = frontend(apiobj, options={'details'})
     result = api.lookup([idobj])
@@ -79,17 +80,17 @@ def test_lookup_single_placex(apiobj, frontend, idobj):
 
 def test_lookup_multiple_places(apiobj, frontend):
     apiobj.add_placex(place_id=332, osm_type='W', osm_id=4,
-                     class_='highway', type='residential',
-                     name={'name': 'Road'}, address={'city': 'Barrow'},
-                     extratags={'surface': 'paved'},
-                     parent_place_id=34, linked_place_id=55,
-                     admin_level=15, country_code='gb',
-                     housenumber='4',
-                     postcode='34425', wikipedia='en:Faa',
-                     rank_search=27, rank_address=26,
-                     importance=0.01,
-                     centroid=(23, 34),
-                     geometry='LINESTRING(23 34, 23.1 34, 23.1 34.1, 23 34)')
+                      class_='highway', type='residential',
+                      name={'name': 'Road'}, address={'city': 'Barrow'},
+                      extratags={'surface': 'paved'},
+                      parent_place_id=34, linked_place_id=55,
+                      admin_level=15, country_code='gb',
+                      housenumber='4',
+                      postcode='34425', wikipedia='en:Faa',
+                      rank_search=27, rank_address=26,
+                      importance=0.01,
+                      centroid=(23, 34),
+                      geometry='LINESTRING(23 34, 23.1 34, 23.1 34.1, 23 34)')
     apiobj.add_osmline(place_id=4924, osm_id=9928,
                        parent_place_id=12,
                        startnumber=1, endnumber=4, step=1,
@@ -97,7 +98,6 @@ def test_lookup_multiple_places(apiobj, frontend):
                        address={'city': 'Big'},
                        geometry='LINESTRING(23 34, 23 35)')
 
-
     api = frontend(apiobj, options={'details'})
     result = api.lookup((napi.OsmID('W', 1),
                          napi.OsmID('W', 4),
@@ -111,17 +111,17 @@ def test_lookup_multiple_places(apiobj, frontend):
 @pytest.mark.parametrize('gtype', list(napi.GeometryFormat))
 def test_simple_place_with_geometry(apiobj, frontend, gtype):
     apiobj.add_placex(place_id=332, osm_type='W', osm_id=4,
-                     class_='highway', type='residential',
-                     name={'name': 'Road'}, address={'city': 'Barrow'},
-                     extratags={'surface': 'paved'},
-                     parent_place_id=34, linked_place_id=55,
-                     admin_level=15, country_code='gb',
-                     housenumber='4',
-                     postcode='34425', wikipedia='en:Faa',
-                     rank_search=27, rank_address=26,
-                     importance=0.01,
-                     centroid=(23, 34),
-                     geometry='POLYGON((23 34, 23.1 34, 23.1 34.1, 23 34))')
+                      class_='highway', type='residential',
+                      name={'name': 'Road'}, address={'city': 'Barrow'},
+                      extratags={'surface': 'paved'},
+                      parent_place_id=34, linked_place_id=55,
+                      admin_level=15, country_code='gb',
+                      housenumber='4',
+                      postcode='34425', wikipedia='en:Faa',
+                      rank_search=27, rank_address=26,
+                      importance=0.01,
+                      centroid=(23, 34),
+                      geometry='POLYGON((23 34, 23.1 34, 23.1 34.1, 23 34))')
 
     api = frontend(apiobj, options={'details'})
     result = api.lookup([napi.OsmID('W', 4)], geometry_output=gtype)
@@ -137,17 +137,17 @@ def test_simple_place_with_geometry(apiobj, frontend, gtype):
 
 def test_simple_place_with_geometry_simplified(apiobj, frontend):
     apiobj.add_placex(place_id=332, osm_type='W', osm_id=4,
-                     class_='highway', type='residential',
-                     name={'name': 'Road'}, address={'city': 'Barrow'},
-                     extratags={'surface': 'paved'},
-                     parent_place_id=34, linked_place_id=55,
-                     admin_level=15, country_code='gb',
-                     housenumber='4',
-                     postcode='34425', wikipedia='en:Faa',
-                     rank_search=27, rank_address=26,
-                     importance=0.01,
-                     centroid=(23, 34),
-                     geometry='POLYGON((23 34, 22.999 34, 23.1 34, 23.1 34.1, 23 34))')
+                      class_='highway', type='residential',
+                      name={'name': 'Road'}, address={'city': 'Barrow'},
+                      extratags={'surface': 'paved'},
+                      parent_place_id=34, linked_place_id=55,
+                      admin_level=15, country_code='gb',
+                      housenumber='4',
+                      postcode='34425', wikipedia='en:Faa',
+                      rank_search=27, rank_address=26,
+                      importance=0.01,
+                      centroid=(23, 34),
+                      geometry='POLYGON((23 34, 22.999 34, 23.1 34, 23.1 34.1, 23 34))')
 
     api = frontend(apiobj, options={'details'})
     result = api.lookup([napi.OsmID('W', 4)],
@@ -159,5 +159,5 @@ def test_simple_place_with_geometry_simplified(apiobj, frontend):
 
     geom = json.loads(result[0].geometry['geojson'])
 
-    assert geom['type']  == 'Polygon'
+    assert geom['type'] == 'Polygon'
     assert geom['coordinates'] == [[[23, 34], [23.1, 34], [23.1, 34.1], [23, 34]]]
index ac2b4cb9fc09cc2e8662bb2d44a856fde6d0c33b..e4700a95e6599160a06408aa6cd23bbaddb19681 100644 (file)
@@ -2,21 +2,21 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 """
 Tests for the deletable v1 API call.
 """
 import json
 import datetime as dt
-from pathlib import Path
 
 import pytest
 
-from fake_adaptor import FakeAdaptor, FakeError, FakeResponse
+from fake_adaptor import FakeAdaptor
 
 import nominatim_api.v1.server_glue as glue
 
+
 class TestPolygonsEndPoint:
 
     @pytest.fixture(autouse=True)
@@ -35,13 +35,12 @@ class TestPolygonsEndPoint:
                                     errormessage text,
                                     prevgeometry geometry(Geometry,4326),
                                     newgeometry geometry(Geometry,4326)""",
-                    content=[(345, 'N', 'boundary', 'administrative',
-                              {'name': 'Foo'}, 'xx', self.recent,
-                              'some text', None, None),
-                             (781, 'R', 'landuse', 'wood',
-                              None, 'ds', self.now,
-                              'Area reduced by lots', None, None)])
-
+                      content=[(345, 'N', 'boundary', 'administrative',
+                               {'name': 'Foo'}, 'xx', self.recent,
+                               'some text', None, None),
+                               (781, 'R', 'landuse', 'wood',
+                                None, 'ds', self.now,
+                                'Area reduced by lots', None, None)])
 
     @pytest.mark.asyncio
     async def test_polygons_simple(self, api):
@@ -63,7 +62,6 @@ class TestPolygonsEndPoint:
                             'errormessage': 'Area reduced by lots',
                             'updated': self.now.isoformat(sep=' ', timespec='seconds')}]
 
-
     @pytest.mark.asyncio
     async def test_polygons_days(self, api):
         a = FakeAdaptor()
@@ -74,7 +72,6 @@ class TestPolygonsEndPoint:
 
         assert [r['osm_id'] for r in results] == [781]
 
-
     @pytest.mark.asyncio
     async def test_polygons_class(self, api):
         a = FakeAdaptor()
@@ -85,8 +82,6 @@ class TestPolygonsEndPoint:
 
         assert [r['osm_id'] for r in results] == [781]
 
-
-
     @pytest.mark.asyncio
     async def test_polygons_reduced(self, api):
         a = FakeAdaptor()
index ff7f402b72f000d9364d716752b992a5e7514b3d..91074ecb3ef8e7ccdd8b1288f4d027a60bc25775 100644 (file)
@@ -2,7 +2,7 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 """
 Tests for reverse API call.
@@ -18,6 +18,7 @@ import nominatim_api as napi
 
 API_OPTIONS = {'reverse'}
 
+
 def test_reverse_rank_30(apiobj, frontend):
     apiobj.add_placex(place_id=223, class_='place', type='house',
                       housenumber='1',
@@ -35,7 +36,7 @@ def test_reverse_rank_30(apiobj, frontend):
 def test_reverse_street(apiobj, frontend, country):
     apiobj.add_placex(place_id=990, class_='highway', type='service',
                       rank_search=27, rank_address=27,
-                      name = {'name': 'My Street'},
+                      name={'name': 'My Street'},
                       centroid=(10.0, 10.0),
                       country_code=country,
                       geometry='LINESTRING(9.995 10, 10.005 10)')
@@ -57,16 +58,17 @@ def test_reverse_ignore_unindexed(apiobj, frontend):
     assert result is None
 
 
-@pytest.mark.parametrize('y,layer,place_id', [(0.7, napi.DataLayer.ADDRESS, 223),
-                                              (0.70001, napi.DataLayer.POI, 224),
-                                              (0.7, napi.DataLayer.ADDRESS | napi.DataLayer.POI, 224),
-                                              (0.70001, napi.DataLayer.ADDRESS | napi.DataLayer.POI, 223),
-                                              (0.7, napi.DataLayer.MANMADE, 225),
-                                              (0.7, napi.DataLayer.RAILWAY, 226),
-                                              (0.7, napi.DataLayer.NATURAL, 227),
-                                              (0.70003, napi.DataLayer.MANMADE | napi.DataLayer.RAILWAY, 225),
-                                              (0.70003, napi.DataLayer.MANMADE | napi.DataLayer.NATURAL, 225),
-                                              (5, napi.DataLayer.ADDRESS, 229)])
+@pytest.mark.parametrize('y,layer,place_id',
+                         [(0.7, napi.DataLayer.ADDRESS, 223),
+                          (0.70001, napi.DataLayer.POI, 224),
+                          (0.7, napi.DataLayer.ADDRESS | napi.DataLayer.POI, 224),
+                          (0.70001, napi.DataLayer.ADDRESS | napi.DataLayer.POI, 223),
+                          (0.7, napi.DataLayer.MANMADE, 225),
+                          (0.7, napi.DataLayer.RAILWAY, 226),
+                          (0.7, napi.DataLayer.NATURAL, 227),
+                          (0.70003, napi.DataLayer.MANMADE | napi.DataLayer.RAILWAY, 225),
+                          (0.70003, napi.DataLayer.MANMADE | napi.DataLayer.NATURAL, 225),
+                          (5, napi.DataLayer.ADDRESS, 229)])
 def test_reverse_rank_30_layers(apiobj, frontend, y, layer, place_id):
     apiobj.add_placex(place_id=223, osm_type='N', class_='place', type='house',
                       housenumber='1',
@@ -108,14 +110,14 @@ def test_reverse_poi_layer_with_no_pois(apiobj, frontend):
 
     api = frontend(apiobj, options=API_OPTIONS)
     assert api.reverse((1.3, 0.70001), max_rank=29,
-                              layers=napi.DataLayer.POI) is None
+                       layers=napi.DataLayer.POI) is None
 
 
 @pytest.mark.parametrize('with_geom', [True, False])
 def test_reverse_housenumber_on_street(apiobj, frontend, with_geom):
     apiobj.add_placex(place_id=990, class_='highway', type='service',
                       rank_search=27, rank_address=27,
-                      name = {'name': 'My Street'},
+                      name={'name': 'My Street'},
                       centroid=(10.0, 10.0),
                       geometry='LINESTRING(9.995 10, 10.005 10)')
     apiobj.add_placex(place_id=991, class_='place', type='house',
@@ -125,7 +127,7 @@ def test_reverse_housenumber_on_street(apiobj, frontend, with_geom):
                       centroid=(10.0, 10.00001))
     apiobj.add_placex(place_id=1990, class_='highway', type='service',
                       rank_search=27, rank_address=27,
-                      name = {'name': 'Other Street'},
+                      name={'name': 'Other Street'},
                       centroid=(10.0, 1.0),
                       geometry='LINESTRING(9.995 1, 10.005 1)')
     apiobj.add_placex(place_id=1991, class_='place', type='house',
@@ -147,7 +149,7 @@ def test_reverse_housenumber_on_street(apiobj, frontend, with_geom):
 def test_reverse_housenumber_interpolation(apiobj, frontend, with_geom):
     apiobj.add_placex(place_id=990, class_='highway', type='service',
                       rank_search=27, rank_address=27,
-                      name = {'name': 'My Street'},
+                      name={'name': 'My Street'},
                       centroid=(10.0, 10.0),
                       geometry='LINESTRING(9.995 10, 10.005 10)')
     apiobj.add_placex(place_id=991, class_='place', type='house',
@@ -162,7 +164,7 @@ def test_reverse_housenumber_interpolation(apiobj, frontend, with_geom):
                        geometry='LINESTRING(9.995 10.00001, 10.005 10.00001)')
     apiobj.add_placex(place_id=1990, class_='highway', type='service',
                       rank_search=27, rank_address=27,
-                      name = {'name': 'Other Street'},
+                      name={'name': 'Other Street'},
                       centroid=(10.0, 20.0),
                       geometry='LINESTRING(9.995 20, 10.005 20)')
     apiobj.add_osmline(place_id=1992,
@@ -181,7 +183,7 @@ def test_reverse_housenumber_interpolation(apiobj, frontend, with_geom):
 def test_reverse_housenumber_point_interpolation(apiobj, frontend):
     apiobj.add_placex(place_id=990, class_='highway', type='service',
                       rank_search=27, rank_address=27,
-                      name = {'name': 'My Street'},
+                      name={'name': 'My Street'},
                       centroid=(10.0, 10.0),
                       geometry='LINESTRING(9.995 10, 10.005 10)')
     apiobj.add_osmline(place_id=992,
@@ -199,7 +201,7 @@ def test_reverse_housenumber_point_interpolation(apiobj, frontend):
 def test_reverse_tiger_number(apiobj, frontend):
     apiobj.add_placex(place_id=990, class_='highway', type='service',
                       rank_search=27, rank_address=27,
-                      name = {'name': 'My Street'},
+                      name={'name': 'My Street'},
                       centroid=(10.0, 10.0),
                       country_code='us',
                       geometry='LINESTRING(9.995 10, 10.005 10)')
@@ -217,7 +219,7 @@ def test_reverse_tiger_number(apiobj, frontend):
 def test_reverse_point_tiger(apiobj, frontend):
     apiobj.add_placex(place_id=990, class_='highway', type='service',
                       rank_search=27, rank_address=27,
-                      name = {'name': 'My Street'},
+                      name={'name': 'My Street'},
                       centroid=(10.0, 10.0),
                       country_code='us',
                       geometry='LINESTRING(9.995 10, 10.005 10)')
@@ -393,14 +395,15 @@ def test_reverse_interpolation_geometry(apiobj, frontend):
                        geometry='LINESTRING(9.995 10.00001, 10.005 10.00001)')
 
     api = frontend(apiobj, options=API_OPTIONS)
-    assert api.reverse((10.0, 10.0), geometry_output=napi.GeometryFormat.TEXT)\
-                     .geometry['text'] == 'POINT(10 10.00001)'
+    result = api.reverse((10.0, 10.0), geometry_output=napi.GeometryFormat.TEXT)
+
+    assert result.geometry['text'] == 'POINT(10 10.00001)'
 
 
 def test_reverse_tiger_geometry(apiobj, frontend):
     apiobj.add_placex(place_id=990, class_='highway', type='service',
                       rank_search=27, rank_address=27,
-                      name = {'name': 'My Street'},
+                      name={'name': 'My Street'},
                       centroid=(10.0, 10.0),
                       country_code='us',
                       geometry='LINESTRING(9.995 10, 10.005 10)')
@@ -411,7 +414,7 @@ def test_reverse_tiger_geometry(apiobj, frontend):
                      geometry='LINESTRING(9.995 10.00001, 10.005 10.00001)')
     apiobj.add_placex(place_id=1000, class_='highway', type='service',
                       rank_search=27, rank_address=27,
-                      name = {'name': 'My Street'},
+                      name={'name': 'My Street'},
                       centroid=(11.0, 11.0),
                       country_code='us',
                       geometry='LINESTRING(10.995 11, 11.005 11)')
@@ -426,8 +429,9 @@ def test_reverse_tiger_geometry(apiobj, frontend):
     params = {'geometry_output': napi.GeometryFormat.GEOJSON}
 
     output = api.reverse((10.0, 10.0), **params)
-    assert json.loads(output.geometry['geojson']) == {'coordinates': [10, 10.00001], 'type': 'Point'}
+    assert json.loads(output.geometry['geojson']) \
+        == {'coordinates': [10, 10.00001], 'type': 'Point'}
 
     output = api.reverse((11.0, 11.0), **params)
-    assert json.loads(output.geometry['geojson']) == {'coordinates': [11, 11.00001], 'type': 'Point'}
-
+    assert json.loads(output.geometry['geojson']) \
+        == {'coordinates': [11, 11.00001], 'type': 'Point'}
index 54138e24442056a4dab6027d95bcacb834101414..59a83aa99b69f362ee2ab8681ef89ea8d10db3dc 100644 (file)
@@ -2,7 +2,7 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 """
 Tests for search API calls.
@@ -10,17 +10,13 @@ Tests for search API calls.
 These tests make sure that all Python code is correct and executable.
 Functional tests can be found in the BDD test suite.
 """
-import json
-
 import pytest
 
-import sqlalchemy as sa
-
-import nominatim_api as napi
 import nominatim_api.logging as loglib
 
 API_OPTIONS = {'search'}
 
+
 @pytest.fixture(autouse=True)
 def setup_icu_tokenizer(apiobj):
     """ Setup the properties needed for using the ICU tokenizer.
@@ -28,8 +24,9 @@ def setup_icu_tokenizer(apiobj):
     apiobj.add_data('properties',
                     [{'property': 'tokenizer', 'value': 'icu'},
                      {'property': 'tokenizer_import_normalisation', 'value': ':: lower();'},
-                     {'property': 'tokenizer_import_transliteration', 'value': "'1' > '/1/'; 'ä' > 'ä '"},
-                    ])
+                     {'property': 'tokenizer_import_transliteration',
+                      'value': "'1' > '/1/'; 'ä' > 'ä '"},
+                     ])
 
 
 def test_search_no_content(apiobj, frontend):
@@ -64,7 +61,7 @@ def test_search_with_debug(apiobj, frontend, logtype):
 
     api = frontend(apiobj, options=API_OPTIONS)
     loglib.set_log_output(logtype)
-    results = api.search('TEST')
+    api.search('TEST')
 
     assert loglib.get_and_disable()
 
index 9341b52774f5cfe5c0170dff72e743e1a4be1685..a80c8710bb5bd34aeae38e8b402d91ac42384408 100644 (file)
@@ -2,18 +2,17 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 """
 Tests for the status API call.
 """
 import datetime as dt
-import pytest
 
-from nominatim_db.version import NominatimVersion
 from nominatim_api.version import NOMINATIM_API_VERSION
 import nominatim_api as napi
 
+
 def test_status_no_extra_info(apiobj, frontend):
     api = frontend(apiobj)
     result = api.status()
index fbb9b682f499943c503041c61c1ff4d82bddabe2..898b884da6ba57653f133c281b9e16612aff82b0 100644 (file)
@@ -2,7 +2,7 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 """
 Tests for loading of parameter dataclasses.
@@ -12,6 +12,7 @@ import pytest
 from nominatim_api.errors import UsageError
 import nominatim_api.types as typ
 
+
 def test_no_params_defaults():
     params = typ.LookupDetails.from_kwargs({})
 
@@ -24,7 +25,7 @@ def test_no_params_defaults():
                                  ('geometry_simplification', 'NaN')])
 def test_bad_format_reverse(k, v):
     with pytest.raises(UsageError):
-        params = typ.ReverseDetails.from_kwargs({k: v})
+        typ.ReverseDetails.from_kwargs({k: v})
 
 
 @pytest.mark.parametrize('rin,rout', [(-23, 0), (0, 0), (1, 1),
index b0da52ce0504704e7cb76c9736310381e390f56c..c94cb7fb57624b82ceeb4e07ad9929d3848544fd 100644 (file)
@@ -2,7 +2,7 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 """
 Tests for export CLI function.
@@ -11,12 +11,13 @@ import pytest
 
 import nominatim_db.cli
 
+
 @pytest.fixture
 def run_export(tmp_path, capsys):
     def _exec(args):
+        cli_args = ['export', '--project-dir', str(tmp_path)] + args
         assert 0 == nominatim_db.cli.nominatim(osm2pgsql_path='OSM2PGSQL NOT AVAILABLE',
-                                               cli_args=['export', '--project-dir', str(tmp_path)]
-                                                        + args)
+                                               cli_args=cli_args)
         return capsys.readouterr().out.split('\r\n')
 
     return _exec
@@ -25,9 +26,9 @@ def run_export(tmp_path, capsys):
 @pytest.fixture(autouse=True)
 def setup_database_with_context(apiobj):
     apiobj.add_placex(place_id=332, osm_type='W', osm_id=4,
-                     class_='highway', type='residential',  name='Street',
-                     country_code='pl', postcode='55674',
-                     rank_search=27, rank_address=26)
+                      class_='highway', type='residential',  name='Street',
+                      country_code='pl', postcode='55674',
+                      rank_search=27, rank_address=26)
     apiobj.add_address_placex(332, fromarea=False, isaddress=False,
                               distance=0.0034,
                               place_id=1000, osm_type='N', osm_id=3333,
index 3a6a9a0b05c4798c6eb4e3b498972e75b4847ad4..10f0921b884058dbeffaca1ee67dddd24bc4bb8b 100644 (file)
@@ -2,7 +2,7 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 """
 Tests for the helper functions for v1 API.
@@ -11,6 +11,7 @@ import pytest
 
 import nominatim_api.v1.helpers as helper
 
+
 @pytest.mark.parametrize('inp', ['',
                                  'abc',
                                  '12 23',
@@ -35,40 +36,42 @@ def test_extract_coords_with_text_before():
 def test_extract_coords_with_text_after():
     assert ('abc', 12.456, -78.90) == helper.extract_coords_from_query('-78.90, 12.456   abc')
 
+
 @pytest.mark.parametrize('inp', [' [12.456,-78.90] ', ' 12.456,-78.90 '])
 def test_extract_coords_with_spaces(inp):
     assert ('', -78.90, 12.456) == helper.extract_coords_from_query(inp)
 
+
 @pytest.mark.parametrize('inp', ['40 26.767 N 79 58.933 W',
-                     '40° 26.767′ N 79° 58.933′ W',
-                     "40° 26.767' N 79° 58.933' W",
-                     "40° 26.767'\n"
-                     "    N 79° 58.933' W",
-                     'N 40 26.767, W 79 58.933',
-                     'N 40°26.767′, W 79°58.933′',
-                     ' N 40°26.767′, W 79°58.933′',
-                     "N 40°26.767', W 79°58.933'",
-                     '40 26 46 N 79 58 56 W',
-                     '40° 26′ 46″ N 79° 58′ 56″ W',
-                     '40° 26′ 46.00″ N 79° 58′ 56.00″ W',
-                     '40°26′46″N 79°58′56″W',
-                     'N 40 26 46 W 79 58 56',
-                     'N 40° 26′ 46″, W 79° 58′ 56″',
-                     'N 40° 26\' 46", W 79° 58\' 56"',
-                     'N 40° 26\' 46", W 79° 58\' 56"',
-                     '40.446 -79.982',
-                     '40.446,-79.982',
-                     '40.446° N 79.982° W',
-                     'N 40.446° W 79.982°',
-                     '[40.446 -79.982]',
-                     '[40.446,\v-79.982]',
-                     '       40.446  ,   -79.982     ',
-                     '       40.446  ,   -79.982     ',
-                     '       40.446    ,   -79.982     ',
-                     '       40.446\v,   -79.982        '])
+                                 '40° 26.767′ N 79° 58.933′ W',
+                                 "40° 26.767' N 79° 58.933' W",
+                                 "40° 26.767'\n"
+                                 "    N 79° 58.933' W",
+                                 'N 40 26.767, W 79 58.933',
+                                 'N 40°26.767′, W 79°58.933′',
+                                 '     N 40°26.767′, W 79°58.933′',
+                                 "N 40°26.767', W 79°58.933'",
+
+                                 '40 26 46 N 79 58 56 W',
+                                 '40° 26′ 46″ N 79° 58′ 56″ W',
+                                 '40° 26′ 46.00″ N 79° 58′ 56.00″ W',
+                                 '40°26′46″N 79°58′56″W',
+                                 'N 40 26 46 W 79 58 56',
+                                 'N 40° 26′ 46″, W 79° 58′ 56″',
+                                 'N 40° 26\' 46", W 79° 58\' 56"',
+                                 'N 40° 26\' 46", W 79° 58\' 56"',
+
+                                 '40.446 -79.982',
+                                 '40.446,-79.982',
+                                 '40.446° N 79.982° W',
+                                 'N 40.446° W 79.982°',
+
+                                 '[40.446 -79.982]',
+                                 '[40.446,\v-79.982]',
+                                 '       40.446  ,   -79.982     ',
+                                 '       40.446  ,   -79.982     ',
+                                 '       40.446        ,   -79.982     ',
+                                 '       40.446\v,   -79.982    '])
 def test_extract_coords_formats(inp):
     query, x, y = helper.extract_coords_from_query(inp)
 
@@ -108,9 +111,11 @@ def test_extract_category_good(inp):
     assert cls == 'shop'
     assert typ == 'fish'
 
+
 def test_extract_category_only():
     assert helper.extract_category_from_query('[shop=market]') == ('', 'shop', 'market')
 
+
 @pytest.mark.parametrize('inp', ['house []', 'nothing', '[352]'])
-def  test_extract_category_no_match(inp):
+def test_extract_category_no_match(inp):
     assert helper.extract_category_from_query(inp) == (inp, None, None)
index 21fa72c81c9af0cb7326460be11f6461f3722d7c..0a30cdc110b1eac1d1ec825952c6982380162f64 100644 (file)
@@ -2,7 +2,7 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 """
 Test functions for adapting results to the user's locale.
@@ -11,34 +11,36 @@ import pytest
 
 from nominatim_api import Locales
 
+
 def test_display_name_empty_names():
-    l = Locales(['en', 'de'])
+    loc = Locales(['en', 'de'])
+
+    assert loc.display_name(None) == ''
+    assert loc.display_name({}) == ''
 
-    assert l.display_name(None) == ''
-    assert l.display_name({}) == ''
 
 def test_display_name_none_localized():
-    l = Locales()
+    loc = Locales()
 
-    assert l.display_name({}) == ''
-    assert l.display_name({'name:de': 'DE', 'name': 'ALL'}) == 'ALL'
-    assert l.display_name({'ref': '34', 'name:de': 'DE'}) == '34'
+    assert loc.display_name({}) == ''
+    assert loc.display_name({'name:de': 'DE', 'name': 'ALL'}) == 'ALL'
+    assert loc.display_name({'ref': '34', 'name:de': 'DE'}) == '34'
 
 
 def test_display_name_localized():
-    l = Locales(['en', 'de'])
+    loc = Locales(['en', 'de'])
 
-    assert l.display_name({}) == ''
-    assert l.display_name({'name:de': 'DE', 'name': 'ALL'}) == 'DE'
-    assert l.display_name({'ref': '34', 'name:de': 'DE'}) == 'DE'
+    assert loc.display_name({}) == ''
+    assert loc.display_name({'name:de': 'DE', 'name': 'ALL'}) == 'DE'
+    assert loc.display_name({'ref': '34', 'name:de': 'DE'}) == 'DE'
 
 
 def test_display_name_preference():
-    l = Locales(['en', 'de'])
+    loc = Locales(['en', 'de'])
 
-    assert l.display_name({}) == ''
-    assert l.display_name({'name:de': 'DE', 'name:en': 'EN'}) == 'EN'
-    assert l.display_name({'official_name:en': 'EN', 'name:de': 'DE'}) == 'DE'
+    assert loc.display_name({}) == ''
+    assert loc.display_name({'name:de': 'DE', 'name:en': 'EN'}) == 'EN'
+    assert loc.display_name({'official_name:en': 'EN', 'name:de': 'DE'}) == 'DE'
 
 
 @pytest.mark.parametrize('langstr,langlist',
index aaecab4539995121c0b5204b8eec1b6acb22dfec..406c76548e584b1e7ebe95a000947cdec763d293 100644 (file)
@@ -2,7 +2,7 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 """
 Tests for formatting results for the V1 API.
@@ -22,6 +22,7 @@ STATUS_FORMATS = {'text', 'json'}
 
 # StatusResult
 
+
 def test_status_format_list():
     assert set(v1_format.list_formats(napi.StatusResult)) == STATUS_FORMATS
 
@@ -36,11 +37,13 @@ def test_status_unsupported():
 
 
 def test_status_format_text():
-    assert v1_format.format_result(napi.StatusResult(0, 'message here'), 'text', {}) == 'OK'
+    assert v1_format.format_result(napi.StatusResult(0, 'message here'), 'text', {}) \
+        == 'OK'
 
 
-def test_status_format_text():
-    assert v1_format.format_result(napi.StatusResult(500, 'message here'), 'text', {}) == 'ERROR: message here'
+def test_status_format_error_text():
+    assert v1_format.format_result(napi.StatusResult(500, 'message here'), 'text', {}) \
+        == 'ERROR: message here'
 
 
 def test_status_format_json_minimal():
@@ -48,8 +51,9 @@ def test_status_format_json_minimal():
 
     result = v1_format.format_result(status, 'json', {})
 
-    assert result == \
-           f'{{"status":700,"message":"Bad format.","software_version":"{napi.__version__}"}}'
+    assert json.loads(result) == {'status': 700,
+                                  'message': 'Bad format.',
+                                  'software_version': napi.__version__}
 
 
 def test_status_format_json_full():
@@ -59,8 +63,11 @@ def test_status_format_json_full():
 
     result = v1_format.format_result(status, 'json', {})
 
-    assert result == \
-           f'{{"status":0,"message":"OK","data_updated":"2010-02-07T20:20:03+00:00","software_version":"{napi.__version__}","database_version":"5.6"}}'
+    assert json.loads(result) == {'status': 0,
+                                  'message': 'OK',
+                                  'data_updated': '2010-02-07T20:20:03+00:00',
+                                  'software_version': napi.__version__,
+                                  'database_version': '5.6'}
 
 
 # DetailedResult
@@ -86,7 +93,7 @@ def test_search_details_minimal():
             'extratags': {},
             'centroid': {'type': 'Point', 'coordinates': [1.0, 2.0]},
             'geometry': {'type': 'Point', 'coordinates': [1.0, 2.0]},
-           }
+            }
 
 
 def test_search_details_full():
@@ -110,7 +117,7 @@ def test_search_details_full():
                   rank_search=28,
                   importance=0.0443,
                   country_code='ll',
-                  indexed_date = import_date
+                  indexed_date=import_date
                   )
     search.localize(napi.Locales())
 
@@ -140,7 +147,7 @@ def test_search_details_full():
             'isarea': False,
             'centroid': {'type': 'Point', 'coordinates': [56.947, -87.44]},
             'geometry': {'type': 'Point', 'coordinates': [56.947, -87.44]},
-           }
+            }
 
 
 @pytest.mark.parametrize('gtype,isarea', [('ST_Point', False),
@@ -149,9 +156,9 @@ def test_search_details_full():
                                           ('ST_MultiPolygon', True)])
 def test_search_details_no_geometry(gtype, isarea):
     search = napi.DetailedResult(napi.SourceTable.PLACEX,
-                               ('place', 'thing'),
-                               napi.Point(1.0, 2.0),
-                               geometry={'type': gtype})
+                                 ('place', 'thing'),
+                                 napi.Point(1.0, 2.0),
+                                 geometry={'type': gtype})
 
     result = v1_format.format_result(search, 'json', {})
     js = json.loads(result)
@@ -161,16 +168,17 @@ def test_search_details_no_geometry(gtype, isarea):
 
 
 def test_search_details_with_geometry():
-    search = napi.DetailedResult(napi.SourceTable.PLACEX,
-                                 ('place', 'thing'),
-                                 napi.Point(1.0, 2.0),
-                                 geometry={'geojson': '{"type":"Point","coordinates":[56.947,-87.44]}'})
+    search = napi.DetailedResult(
+        napi.SourceTable.PLACEX,
+        ('place', 'thing'),
+        napi.Point(1.0, 2.0),
+        geometry={'geojson': '{"type":"Point","coordinates":[56.947,-87.44]}'})
 
     result = v1_format.format_result(search, 'json', {})
     js = json.loads(result)
 
     assert js['geometry'] == {'type': 'Point', 'coordinates': [56.947, -87.44]}
-    assert js['isarea'] == False
+    assert js['isarea'] is False
 
 
 def test_search_details_with_icon_available():
@@ -226,7 +234,7 @@ def test_search_details_with_address_minimal():
 @pytest.mark.parametrize('field,outfield', [('address_rows', 'address'),
                                             ('linked_rows', 'linked_places'),
                                             ('parented_rows', 'hierarchy')
-                                           ])
+                                            ])
 def test_search_details_with_further_infos(field, outfield):
     search = napi.DetailedResult(napi.SourceTable.PLACEX,
                                  ('place', 'thing'),
@@ -249,50 +257,49 @@ def test_search_details_with_further_infos(field, outfield):
     js = json.loads(result)
 
     assert js[outfield] == [{'localname': 'Trespass',
-                              'place_id': 3498,
-                              'osm_id': 442,
-                              'osm_type': 'R',
-                              'place_type': 'spec',
-                              'class': 'bnd',
-                              'type': 'note',
-                              'admin_level': 4,
-                              'rank_address': 10,
-                              'distance': 0.034,
-                              'isaddress': True}]
+                             'place_id': 3498,
+                             'osm_id': 442,
+                             'osm_type': 'R',
+                             'place_type': 'spec',
+                             'class': 'bnd',
+                             'type': 'note',
+                             'admin_level': 4,
+                             'rank_address': 10,
+                             'distance': 0.034,
+                             'isaddress': True}]
 
 
 def test_search_details_grouped_hierarchy():
     search = napi.DetailedResult(napi.SourceTable.PLACEX,
                                  ('place', 'thing'),
                                  napi.Point(1.0, 2.0),
-                                 parented_rows =
-                                     [napi.AddressLine(place_id=3498,
-                                             osm_object=('R', 442),
-                                             category=('bnd', 'note'),
-                                             names={'name': 'Trespass'},
-                                             extratags={'access': 'no',
-                                                        'place_type': 'spec'},
-                                             admin_level=4,
-                                             fromarea=True,
-                                             isaddress=True,
-                                             rank_address=10,
-                                             distance=0.034)
-                                     ])
+                                 parented_rows=[napi.AddressLine(
+                                    place_id=3498,
+                                    osm_object=('R', 442),
+                                    category=('bnd', 'note'),
+                                    names={'name': 'Trespass'},
+                                    extratags={'access': 'no',
+                                               'place_type': 'spec'},
+                                    admin_level=4,
+                                    fromarea=True,
+                                    isaddress=True,
+                                    rank_address=10,
+                                    distance=0.034)])
 
     result = v1_format.format_result(search, 'json', {'group_hierarchy': True})
     js = json.loads(result)
 
     assert js['hierarchy'] == {'note': [{'localname': 'Trespass',
-                              'place_id': 3498,
-                              'osm_id': 442,
-                              'osm_type': 'R',
-                              'place_type': 'spec',
-                              'class': 'bnd',
-                              'type': 'note',
-                              'admin_level': 4,
-                              'rank_address': 10,
-                              'distance': 0.034,
-                              'isaddress': True}]}
+                                         'place_id': 3498,
+                                         'osm_id': 442,
+                                         'osm_type': 'R',
+                                         'place_type': 'spec',
+                                         'class': 'bnd',
+                                         'type': 'note',
+                                         'admin_level': 4,
+                                         'rank_address': 10,
+                                         'distance': 0.034,
+                                         'isaddress': True}]}
 
 
 def test_search_details_keywords_name():
@@ -307,7 +314,7 @@ def test_search_details_keywords_name():
     js = json.loads(result)
 
     assert js['keywords'] == {'name': [{'id': 23, 'token': 'foo'},
-                                      {'id': 24, 'token': 'foo'}],
+                                       {'id': 24, 'token': 'foo'}],
                               'address': []}
 
 
@@ -323,6 +330,5 @@ def test_search_details_keywords_address():
     js = json.loads(result)
 
     assert js['keywords'] == {'address': [{'id': 23, 'token': 'foo'},
-                                      {'id': 24, 'token': 'foo'}],
+                                          {'id': 24, 'token': 'foo'}],
                               'name': []}
-
index 2c036a65ba254d9058961a78eb0cfb7f827a45f7..902f0e7939393b13434800a8106a8f3f2e9a1e4c 100644 (file)
@@ -2,7 +2,7 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 """
 Tests for formatting reverse results for the V1 API.
@@ -20,6 +20,7 @@ import nominatim_api as napi
 
 FORMATS = ['json', 'jsonv2', 'geojson', 'geocodejson', 'xml']
 
+
 @pytest.mark.parametrize('fmt', FORMATS)
 def test_format_reverse_minimal(fmt):
     reverse = napi.ReverseResult(napi.SourceTable.PLACEX,
@@ -104,8 +105,7 @@ def test_format_reverse_with_address(fmt):
     reverse.localize(napi.Locales())
 
     raw = v1_format.format_result(napi.ReverseResults([reverse]), fmt,
-                                 {'addressdetails': True})
-
+                                  {'addressdetails': True})
 
     if fmt == 'xml':
         root = ET.fromstring(raw)
@@ -168,7 +168,7 @@ def test_format_reverse_geocodejson_special_parts():
     reverse.localize(napi.Locales())
 
     raw = v1_format.format_result(napi.ReverseResults([reverse]), 'geocodejson',
-                                 {'addressdetails': True})
+                                  {'addressdetails': True})
 
     props = json.loads(raw)['features'][0]['properties']['geocoding']
     assert props['housenumber'] == '1'
@@ -184,8 +184,7 @@ def test_format_reverse_with_address_none(fmt):
                                  address_rows=napi.AddressLines())
 
     raw = v1_format.format_result(napi.ReverseResults([reverse]), fmt,
-                                 {'addressdetails': True})
-
+                                  {'addressdetails': True})
 
     if fmt == 'xml':
         root = ET.fromstring(raw)
@@ -211,10 +210,10 @@ def test_format_reverse_with_extratags(fmt):
     reverse = napi.ReverseResult(napi.SourceTable.PLACEX,
                                  ('place', 'thing'),
                                  napi.Point(1.0, 2.0),
-                                 extratags={'one': 'A', 'two':'B'})
+                                 extratags={'one': 'A', 'two': 'B'})
 
     raw = v1_format.format_result(napi.ReverseResults([reverse]), fmt,
-                                 {'extratags': True})
+                                  {'extratags': True})
 
     if fmt == 'xml':
         root = ET.fromstring(raw)
@@ -226,7 +225,7 @@ def test_format_reverse_with_extratags(fmt):
         else:
             extra = result['extratags']
 
-        assert extra == {'one': 'A', 'two':'B'}
+        assert extra == {'one': 'A', 'two': 'B'}
 
 
 @pytest.mark.parametrize('fmt', ['json', 'jsonv2', 'geojson', 'xml'])
@@ -236,7 +235,7 @@ def test_format_reverse_with_extratags_none(fmt):
                                  napi.Point(1.0, 2.0))
 
     raw = v1_format.format_result(napi.ReverseResults([reverse]), fmt,
-                                 {'extratags': True})
+                                  {'extratags': True})
 
     if fmt == 'xml':
         root = ET.fromstring(raw)
@@ -256,10 +255,10 @@ def test_format_reverse_with_namedetails_with_name(fmt):
     reverse = napi.ReverseResult(napi.SourceTable.PLACEX,
                                  ('place', 'thing'),
                                  napi.Point(1.0, 2.0),
-                                 names={'name': 'A', 'ref':'1'})
+                                 names={'name': 'A', 'ref': '1'})
 
     raw = v1_format.format_result(napi.ReverseResults([reverse]), fmt,
-                                 {'namedetails': True})
+                                  {'namedetails': True})
 
     if fmt == 'xml':
         root = ET.fromstring(raw)
@@ -271,7 +270,7 @@ def test_format_reverse_with_namedetails_with_name(fmt):
         else:
             extra = result['namedetails']
 
-        assert extra == {'name': 'A', 'ref':'1'}
+        assert extra == {'name': 'A', 'ref': '1'}
 
 
 @pytest.mark.parametrize('fmt', ['json', 'jsonv2', 'geojson', 'xml'])
@@ -281,7 +280,7 @@ def test_format_reverse_with_namedetails_without_name(fmt):
                                  napi.Point(1.0, 2.0))
 
     raw = v1_format.format_result(napi.ReverseResults([reverse]), fmt,
-                                 {'namedetails': True})
+                                  {'namedetails': True})
 
     if fmt == 'xml':
         root = ET.fromstring(raw)
@@ -303,7 +302,7 @@ def test_search_details_with_icon_available(fmt):
                                  napi.Point(1.0, 2.0))
 
     result = v1_format.format_result(napi.ReverseResults([reverse]), fmt,
-                                    {'icon_base_url': 'foo'})
+                                     {'icon_base_url': 'foo'})
 
     js = json.loads(result)
 
@@ -317,7 +316,6 @@ def test_search_details_with_icon_not_available(fmt):
                                  napi.Point(1.0, 2.0))
 
     result = v1_format.format_result(napi.ReverseResults([reverse]), fmt,
-                                    {'icon_base_url': 'foo'})
+                                     {'icon_base_url': 'foo'})
 
     assert 'icon' not in json.loads(result)
-
index f0bfa163cbcb8b41cdf3f90f8fd0d9f68f8809e6..8e9fbf684fc48d06090fbb5b6bb5c9724a6c1634 100644 (file)
@@ -2,7 +2,7 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 """
 Tests for result datatype helper functions.
@@ -11,16 +11,15 @@ import struct
 from binascii import hexlify
 
 import pytest
-import pytest_asyncio
-import sqlalchemy as sa
-
 
 from nominatim_api import SourceTable, DetailedResult, Point
 import nominatim_api.results as nresults
 
+
 def mkpoint(x, y):
     return hexlify(struct.pack("=biidd", 1, 0x20000001, 4326, x, y)).decode('utf-8')
 
+
 class FakeRow:
     def __init__(self, **kwargs):
         if 'parent_place_id' not in kwargs:
@@ -39,6 +38,7 @@ def test_minimal_detailed_result():
     assert res.lat == 0.5
     assert res.calculated_importance() == pytest.approx(0.00001)
 
+
 def test_detailed_result_custom_importance():
     res = DetailedResult(SourceTable.PLACEX,
                          ('amenity', 'post_box'),
index 6ea790c060b21c740c3ff2e985adeb4bf51ba3b5..8d9f09404bfb2cd92c703d136c33fa5784f36c9d 100644 (file)
@@ -2,7 +2,7 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 """
 Tests for the Python web frameworks adaptor, v1 API.
@@ -121,7 +121,6 @@ class TestAdaptorRaiseError:
 
         return excinfo.value
 
-
     def test_without_content_set(self):
         err = self.run_raise_error('TEST', 404)
 
@@ -129,7 +128,6 @@ class TestAdaptorRaiseError:
         assert err.msg == 'ERROR 404: TEST'
         assert err.status == 404
 
-
     def test_json(self):
         self.adaptor.content_type = 'application/json; charset=utf-8'
 
@@ -139,7 +137,6 @@ class TestAdaptorRaiseError:
         assert content['code'] == 501
         assert content['message'] == 'TEST'
 
-
     def test_xml(self):
         self.adaptor.content_type = 'text/xml; charset=utf-8'
 
@@ -235,7 +232,6 @@ class TestStatusEndpoint:
 
         monkeypatch.setattr(napi.NominatimAPIAsync, 'status', _status)
 
-
     @pytest.mark.asyncio
     async def test_status_without_params(self):
         a = FakeAdaptor()
@@ -247,7 +243,6 @@ class TestStatusEndpoint:
         assert resp.status == 200
         assert resp.content_type == 'text/plain; charset=utf-8'
 
-
     @pytest.mark.asyncio
     async def test_status_with_error(self):
         a = FakeAdaptor()
@@ -259,7 +254,6 @@ class TestStatusEndpoint:
         assert resp.status == 500
         assert resp.content_type == 'text/plain; charset=utf-8'
 
-
     @pytest.mark.asyncio
     async def test_status_json_with_error(self):
         a = FakeAdaptor(params={'format': 'json'})
@@ -271,7 +265,6 @@ class TestStatusEndpoint:
         assert resp.status == 200
         assert resp.content_type == 'application/json; charset=utf-8'
 
-
     @pytest.mark.asyncio
     async def test_status_bad_format(self):
         a = FakeAdaptor(params={'format': 'foo'})
@@ -298,7 +291,6 @@ class TestDetailsEndpoint:
 
         monkeypatch.setattr(napi.NominatimAPIAsync, 'details', _lookup)
 
-
     @pytest.mark.asyncio
     async def test_details_no_params(self):
         a = FakeAdaptor()
@@ -306,7 +298,6 @@ class TestDetailsEndpoint:
         with pytest.raises(FakeError, match='^400 -- .*Missing'):
             await glue.details_endpoint(napi.NominatimAPIAsync(), a)
 
-
     @pytest.mark.asyncio
     async def test_details_by_place_id(self):
         a = FakeAdaptor(params={'place_id': '4573'})
@@ -315,7 +306,6 @@ class TestDetailsEndpoint:
 
         assert self.lookup_args[0].place_id == 4573
 
-
     @pytest.mark.asyncio
     async def test_details_by_osm_id(self):
         a = FakeAdaptor(params={'osmtype': 'N', 'osmid': '45'})
@@ -326,7 +316,6 @@ class TestDetailsEndpoint:
         assert self.lookup_args[0].osm_id == 45
         assert self.lookup_args[0].osm_class is None
 
-
     @pytest.mark.asyncio
     async def test_details_with_debugging(self):
         a = FakeAdaptor(params={'osmtype': 'N', 'osmid': '45', 'debug': '1'})
@@ -337,7 +326,6 @@ class TestDetailsEndpoint:
         assert resp.content_type == 'text/html; charset=utf-8'
         assert content.tag == 'html'
 
-
     @pytest.mark.asyncio
     async def test_details_no_result(self):
         a = FakeAdaptor(params={'place_id': '4573'})
@@ -353,14 +341,14 @@ class TestReverseEndPoint:
     @pytest.fixture(autouse=True)
     def patch_reverse_func(self, monkeypatch):
         self.result = napi.ReverseResult(napi.SourceTable.PLACEX,
-                                          ('place', 'thing'),
-                                          napi.Point(1.0, 2.0))
+                                         ('place', 'thing'),
+                                         napi.Point(1.0, 2.0))
+
         async def _reverse(*args, **kwargs):
             return self.result
 
         monkeypatch.setattr(napi.NominatimAPIAsync, 'reverse', _reverse)
 
-
     @pytest.mark.asyncio
     @pytest.mark.parametrize('params', [{}, {'lat': '3.4'}, {'lon': '6.7'}])
     async def test_reverse_no_params(self, params):
@@ -371,19 +359,6 @@ class TestReverseEndPoint:
         with pytest.raises(FakeError, match='^400 -- (?s:.*)missing'):
             await glue.reverse_endpoint(napi.NominatimAPIAsync(), a)
 
-
-    @pytest.mark.asyncio
-    @pytest.mark.parametrize('params', [{'lat': '45.6', 'lon': '4563'}])
-    async def test_reverse_success(self, params):
-        a = FakeAdaptor()
-        a.params = params
-        a.params['format'] = 'json'
-
-        res = await glue.reverse_endpoint(napi.NominatimAPIAsync(), a)
-
-        assert res == ''
-
-
     @pytest.mark.asyncio
     async def test_reverse_success(self):
         a = FakeAdaptor()
@@ -392,7 +367,6 @@ class TestReverseEndPoint:
 
         assert await glue.reverse_endpoint(napi.NominatimAPIAsync(), a)
 
-
     @pytest.mark.asyncio
     async def test_reverse_from_search(self):
         a = FakeAdaptor()
@@ -413,12 +387,12 @@ class TestLookupEndpoint:
         self.results = [napi.SearchResult(napi.SourceTable.PLACEX,
                                           ('place', 'thing'),
                                           napi.Point(1.0, 2.0))]
+
         async def _lookup(*args, **kwargs):
             return napi.SearchResults(self.results)
 
         monkeypatch.setattr(napi.NominatimAPIAsync, 'lookup', _lookup)
 
-
     @pytest.mark.asyncio
     async def test_lookup_no_params(self):
         a = FakeAdaptor()
@@ -428,7 +402,6 @@ class TestLookupEndpoint:
 
         assert res.output == '[]'
 
-
     @pytest.mark.asyncio
     @pytest.mark.parametrize('param', ['w', 'bad', ''])
     async def test_lookup_bad_params(self, param):
@@ -440,7 +413,6 @@ class TestLookupEndpoint:
 
         assert len(json.loads(res.output)) == 1
 
-
     @pytest.mark.asyncio
     @pytest.mark.parametrize('param', ['p234234', '4563'])
     async def test_lookup_bad_osm_type(self, param):
@@ -452,7 +424,6 @@ class TestLookupEndpoint:
 
         assert len(json.loads(res.output)) == 1
 
-
     @pytest.mark.asyncio
     async def test_lookup_working(self):
         a = FakeAdaptor()
@@ -473,12 +444,12 @@ class TestSearchEndPointSearch:
         self.results = [napi.SearchResult(napi.SourceTable.PLACEX,
                                           ('place', 'thing'),
                                           napi.Point(1.0, 2.0))]
+
         async def _search(*args, **kwargs):
             return napi.SearchResults(self.results)
 
         monkeypatch.setattr(napi.NominatimAPIAsync, 'search', _search)
 
-
     @pytest.mark.asyncio
     async def test_search_free_text(self):
         a = FakeAdaptor()
@@ -488,7 +459,6 @@ class TestSearchEndPointSearch:
 
         assert len(json.loads(res.output)) == 1
 
-
     @pytest.mark.asyncio
     async def test_search_free_text_xml(self):
         a = FakeAdaptor()
@@ -500,7 +470,6 @@ class TestSearchEndPointSearch:
         assert res.status == 200
         assert res.output.index('something') > 0
 
-
     @pytest.mark.asyncio
     async def test_search_free_and_structured(self):
         a = FakeAdaptor()
@@ -508,8 +477,7 @@ class TestSearchEndPointSearch:
         a.params['city'] = 'ignored'
 
         with pytest.raises(FakeError, match='^400 -- .*cannot be used together'):
-            res = await glue.search_endpoint(napi.NominatimAPIAsync(), a)
-
+            await glue.search_endpoint(napi.NominatimAPIAsync(), a)
 
     @pytest.mark.asyncio
     @pytest.mark.parametrize('dedupe,numres', [(True, 1), (False, 2)])
@@ -532,12 +500,12 @@ class TestSearchEndPointSearchAddress:
         self.results = [napi.SearchResult(napi.SourceTable.PLACEX,
                                           ('place', 'thing'),
                                           napi.Point(1.0, 2.0))]
+
         async def _search(*args, **kwargs):
             return napi.SearchResults(self.results)
 
         monkeypatch.setattr(napi.NominatimAPIAsync, 'search_address', _search)
 
-
     @pytest.mark.asyncio
     async def test_search_structured(self):
         a = FakeAdaptor()
@@ -555,12 +523,12 @@ class TestSearchEndPointSearchCategory:
         self.results = [napi.SearchResult(napi.SourceTable.PLACEX,
                                           ('place', 'thing'),
                                           napi.Point(1.0, 2.0))]
+
         async def _search(*args, **kwargs):
             return napi.SearchResults(self.results)
 
         monkeypatch.setattr(napi.NominatimAPIAsync, 'search_category', _search)
 
-
     @pytest.mark.asyncio
     async def test_search_category(self):
         a = FakeAdaptor()
index f0c9986d302f9159c017ea72a7a12ac6197daa7c..94081d00051ff5df17695b2168dc058795d6e459 100644 (file)
@@ -2,7 +2,7 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 """
 Tests for warm-up CLI function.
@@ -11,6 +11,7 @@ import pytest
 
 import nominatim_db.cli
 
+
 @pytest.fixture(autouse=True)
 def setup_database_with_context(apiobj, table_factory):
     table_factory('word',
@@ -21,8 +22,9 @@ def setup_database_with_context(apiobj, table_factory):
     apiobj.add_data('properties',
                     [{'property': 'tokenizer', 'value': 'icu'},
                      {'property': 'tokenizer_import_normalisation', 'value': ':: lower();'},
-                     {'property': 'tokenizer_import_transliteration', 'value': "'1' > '/1/'; 'ä' > 'ä '"},
-                    ])
+                     {'property': 'tokenizer_import_transliteration',
+                      'value': "'1' > '/1/'; 'ä' > 'ä '"}
+                     ])
 
 
 @pytest.mark.parametrize('args', [['--search-only'], ['--reverse-only']])
index 84f2d6598ae8adad77efe389d64d3adb31e80604..921a3a322949bcec14d876a8895c6f4b2473c363 100644 (file)
@@ -2,12 +2,13 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 import pytest
 
 import nominatim_db.cli
 
+
 class MockParamCapture:
     """ Mock that records the parameters with which a function was called
         as well as the number of calls.
index d42df50a760066f972628817b830c67899dea04a..a538049e81c52a2056fb20c03fda05baf9e6c6d8 100644 (file)
@@ -2,7 +2,7 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 """
 Tests for command line interface wrapper.
@@ -11,7 +11,6 @@ These tests just check that the various command line parameters route to the
 correct functionality. They use a lot of monkeypatching to avoid executing
 the actual functions.
 """
-import importlib
 import pytest
 
 import nominatim_db.indexer.indexer
@@ -28,6 +27,7 @@ def test_cli_help(cli_call, capsys):
     captured = capsys.readouterr()
     assert captured.out.startswith('usage:')
 
+
 def test_cli_version(cli_call, capsys):
     """ Running nominatim tool --version prints a version string.
     """
@@ -46,7 +46,6 @@ class TestCliWithDb:
         # Make sure tools.freeze.is_frozen doesn't report database as frozen. Monkeypatching failed
         table_factory('place')
 
-
     @pytest.mark.parametrize("name,oid", [('file', 'foo.osm'), ('diff', 'foo.osc')])
     def test_cli_add_data_file_command(self, cli_call, mock_func_factory, name, oid):
         mock_run_legacy = mock_func_factory(nominatim_db.tools.add_osm_data, 'add_data_from_file')
@@ -54,7 +53,6 @@ class TestCliWithDb:
 
         assert mock_run_legacy.called == 1
 
-
     @pytest.mark.parametrize("name,oid", [('node', 12), ('way', 8), ('relation', 32)])
     def test_cli_add_data_object_command(self, cli_call, mock_func_factory, name, oid):
         mock_run_legacy = mock_func_factory(nominatim_db.tools.add_osm_data, 'add_osm_object')
@@ -62,8 +60,6 @@ class TestCliWithDb:
 
         assert mock_run_legacy.called == 1
 
-
-
     def test_cli_add_data_tiger_data(self, cli_call, cli_tokenizer_mock, async_mock_func_factory):
         mock = async_mock_func_factory(nominatim_db.tools.tiger_data, 'add_tiger_data')
 
@@ -80,7 +76,6 @@ class TestCliWithDb:
         assert mock_drop.called == 1
         assert mock_flatnode.called == 1
 
-
     @pytest.mark.parametrize("params,do_bnds,do_ranks", [
                               ([], 2, 2),
                               (['--boundaries-only'], 2, 0),
@@ -89,11 +84,14 @@ class TestCliWithDb:
     def test_index_command(self, monkeypatch, async_mock_func_factory, table_factory,
                            params, do_bnds, do_ranks):
         table_factory('import_status', 'indexed bool')
-        bnd_mock = async_mock_func_factory(nominatim_db.indexer.indexer.Indexer, 'index_boundaries')
-        rank_mock = async_mock_func_factory(nominatim_db.indexer.indexer.Indexer, 'index_by_rank')
-        postcode_mock = async_mock_func_factory(nominatim_db.indexer.indexer.Indexer, 'index_postcodes')
-
-        monkeypatch.setattr(nominatim_db.indexer.indexer.Indexer, 'has_pending', 
+        bnd_mock = async_mock_func_factory(nominatim_db.indexer.indexer.Indexer,
+                                           'index_boundaries')
+        rank_mock = async_mock_func_factory(nominatim_db.indexer.indexer.Indexer,
+                                            'index_by_rank')
+        postcode_mock = async_mock_func_factory(nominatim_db.indexer.indexer.Indexer,
+                                                'index_postcodes')
+
+        monkeypatch.setattr(nominatim_db.indexer.indexer.Indexer, 'has_pending',
                             [False, True].pop)
 
         assert self.call_nominatim('index', *params) == 0
@@ -102,7 +100,6 @@ class TestCliWithDb:
         assert rank_mock.called == do_ranks
         assert postcode_mock.called == do_ranks
 
-
     def test_special_phrases_wiki_command(self, mock_func_factory):
         func = mock_func_factory(nominatim_db.clicmd.special_phrases.SPImporter, 'import_phrases')
 
@@ -110,7 +107,6 @@ class TestCliWithDb:
 
         assert func.called == 1
 
-
     def test_special_phrases_csv_command(self, src_dir, mock_func_factory):
         func = mock_func_factory(nominatim_db.clicmd.special_phrases.SPImporter, 'import_phrases')
         testdata = src_dir / 'test' / 'testdb'
@@ -120,7 +116,6 @@ class TestCliWithDb:
 
         assert func.called == 1
 
-
     def test_special_phrases_csv_bad_file(self, src_dir):
         testdata = src_dir / 'something349053905.csv'
 
index 7b0b9cd466fd6cfa27dd947af8752312f5656f4f..9732d73405b3f1bcb6cfd4995406047fed92d9c1 100644 (file)
@@ -2,7 +2,7 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 """
 Test for the command line interface wrapper admin subcommand.
@@ -39,11 +39,13 @@ def test_admin_clean_deleted_relations(cli_call, mock_func_factory):
     assert cli_call('admin', '--clean-deleted', '1 month') == 0
     assert mock.called == 1
 
+
 def test_admin_clean_deleted_relations_no_age(cli_call, mock_func_factory):
-    mock = mock_func_factory(nominatim_db.tools.admin, 'clean_deleted_relations')
+    mock_func_factory(nominatim_db.tools.admin, 'clean_deleted_relations')
 
     assert cli_call('admin', '--clean-deleted') == 1
 
+
 class TestCliAdminWithDb:
 
     @pytest.fixture(autouse=True)
@@ -51,7 +53,6 @@ class TestCliAdminWithDb:
         self.call_nominatim = cli_call
         self.tokenizer_mock = cli_tokenizer_mock
 
-
     @pytest.mark.parametrize("func, params", [('analyse_indexing', ('--analyse-indexing', ))])
     def test_analyse_indexing(self, mock_func_factory, func, params):
         mock = mock_func_factory(nominatim_db.tools.admin, func)
index 1c0750d1dc1cf03630ccf51c9024bbec508562dc..541b680c4c65dacb0489823a4d195a6113f4b6f0 100644 (file)
@@ -2,7 +2,7 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 """
 Tests for API access commands of command-line interface wrapper.
@@ -10,9 +10,9 @@ Tests for API access commands of command-line interface wrapper.
 import json
 import pytest
 
-import nominatim_db.clicmd.api
 import nominatim_api as napi
 
+
 @pytest.mark.parametrize('call', ['search', 'reverse', 'lookup', 'details', 'status'])
 def test_list_format(cli_call, call):
     assert 0 == cli_call(call, '--list-formats')
@@ -30,13 +30,11 @@ class TestCliStatusCall:
         monkeypatch.setattr(napi.NominatimAPI, 'status',
                             lambda self: napi.StatusResult(200, 'OK'))
 
-
     def test_status_simple(self, cli_call, tmp_path):
         result = cli_call('status', '--project-dir', str(tmp_path))
 
         assert result == 0
 
-
     def test_status_json_format(self, cli_call, tmp_path, capsys):
         result = cli_call('status', '--project-dir', str(tmp_path),
                           '--format', 'json')
@@ -60,7 +58,6 @@ class TestCliDetailsCall:
                                         ('--way', '1'),
                                         ('--relation', '1'),
                                         ('--place_id', '10001')])
-
     def test_details_json_format(self, cli_call, tmp_path, capsys, params):
         result = cli_call('details', '--project-dir', str(tmp_path), *params)
 
@@ -75,15 +72,14 @@ class TestCliReverseCall:
     def setup_reverse_mock(self, monkeypatch):
         result = napi.ReverseResult(napi.SourceTable.PLACEX, ('place', 'thing'),
                                     napi.Point(1.0, -3.0),
-                                    names={'name':'Name', 'name:fr': 'Nom'},
-                                    extratags={'extra':'Extra'},
+                                    names={'name': 'Name', 'name:fr': 'Nom'},
+                                    extratags={'extra': 'Extra'},
                                     locale_name='Name',
                                     display_name='Name')
 
         monkeypatch.setattr(napi.NominatimAPI, 'reverse',
                             lambda *args, **kwargs: result)
 
-
     def test_reverse_simple(self, cli_call, tmp_path, capsys):
         result = cli_call('reverse', '--project-dir', str(tmp_path),
                           '--lat', '34', '--lon', '34')
@@ -96,7 +92,6 @@ class TestCliReverseCall:
         assert 'extratags' not in out
         assert 'namedetails' not in out
 
-
     @pytest.mark.parametrize('param,field', [('--addressdetails', 'address'),
                                              ('--extratags', 'extratags'),
                                              ('--namedetails', 'namedetails')])
@@ -109,7 +104,6 @@ class TestCliReverseCall:
         out = json.loads(capsys.readouterr().out)
         assert field in out
 
-
     def test_reverse_format(self, cli_call, tmp_path, capsys):
         result = cli_call('reverse', '--project-dir', str(tmp_path),
                           '--lat', '34', '--lon', '34', '--format', 'geojson')
@@ -125,11 +119,11 @@ class TestCliLookupCall:
     @pytest.fixture(autouse=True)
     def setup_lookup_mock(self, monkeypatch):
         result = napi.SearchResult(napi.SourceTable.PLACEX, ('place', 'thing'),
-                                    napi.Point(1.0, -3.0),
-                                    names={'name':'Name', 'name:fr': 'Nom'},
-                                    extratags={'extra':'Extra'},
-                                    locale_name='Name',
-                                    display_name='Name')
+                                   napi.Point(1.0, -3.0),
+                                   names={'name': 'Name', 'name:fr': 'Nom'},
+                                   extratags={'extra': 'Extra'},
+                                   locale_name='Name',
+                                   display_name='Name')
 
         monkeypatch.setattr(napi.NominatimAPI, 'lookup',
                             lambda *args, **kwargs: napi.SearchResults([result]))
@@ -150,19 +144,18 @@ class TestCliLookupCall:
 
 @pytest.mark.parametrize('endpoint, params', [('search', ('--query', 'Berlin')),
                                               ('search_address', ('--city', 'Berlin'))
-                                             ])
+                                              ])
 def test_search(cli_call, tmp_path, capsys, monkeypatch, endpoint, params):
     result = napi.SearchResult(napi.SourceTable.PLACEX, ('place', 'thing'),
                                napi.Point(1.0, -3.0),
-                               names={'name':'Name', 'name:fr': 'Nom'},
-                               extratags={'extra':'Extra'},
+                               names={'name': 'Name', 'name:fr': 'Nom'},
+                               extratags={'extra': 'Extra'},
                                locale_name='Name',
                                display_name='Name')
 
     monkeypatch.setattr(napi.NominatimAPI, endpoint,
                         lambda *args, **kwargs: napi.SearchResults([result]))
 
-
     result = cli_call('search', '--project-dir', str(tmp_path), *params)
 
     assert result == 0
index f833dde347d7b743fbda477b1a2b761b59c6ebf2..e4a86fe0be865bb6e3633f4fd38afb6f492d1f5d 100644 (file)
@@ -2,7 +2,7 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 """
 Tests for import command of the command-line interface wrapper.
@@ -24,15 +24,12 @@ class TestCliImportWithDb:
         self.call_nominatim = cli_call
         self.tokenizer_mock = cli_tokenizer_mock
 
-
     def test_import_missing_file(self):
         assert self.call_nominatim('import', '--osm-file', 'sfsafegwedgw.reh.erh') == 1
 
-
     def test_import_bad_file(self):
         assert self.call_nominatim('import', '--osm-file', '.') == 1
 
-
     @pytest.mark.parametrize('with_updates', [True, False])
     def test_import_full(self, mock_func_factory, async_mock_func_factory,
                          with_updates, place_table, property_table):
@@ -62,7 +59,6 @@ class TestCliImportWithDb:
 
         cf_mock = mock_func_factory(nominatim_db.tools.refresh, 'create_functions')
 
-
         assert self.call_nominatim(*params) == 0
         assert self.tokenizer_mock.finalize_import_called
 
@@ -71,7 +67,6 @@ class TestCliImportWithDb:
         for mock in mocks:
             assert mock.called == 1, "Mock '{}' not called".format(mock.func_name)
 
-
     def test_import_continue_load_data(self, mock_func_factory, async_mock_func_factory):
         mocks = [
             mock_func_factory(nominatim_db.tools.database_import, 'truncate_data_tables'),
@@ -89,7 +84,6 @@ class TestCliImportWithDb:
         for mock in mocks:
             assert mock.called == 1, "Mock '{}' not called".format(mock.func_name)
 
-
     def test_import_continue_indexing(self, mock_func_factory, async_mock_func_factory,
                                       placex_table, temp_db_conn):
         mocks = [
@@ -107,7 +101,6 @@ class TestCliImportWithDb:
         # Calling it again still works for the index
         assert self.call_nominatim('import', '--continue', 'indexing') == 0
 
-
     def test_import_continue_postprocess(self, mock_func_factory, async_mock_func_factory):
         mocks = [
             async_mock_func_factory(nominatim_db.tools.database_import, 'create_search_indices'),
index 9f3d7bb241e46b31e3f4a548722ad3b2c60ee5ad..8121946f775022c75d27c931c168ea3612d09047 100644 (file)
@@ -2,7 +2,7 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 """
 Tests for command line interface wrapper for refresk command.
@@ -13,6 +13,7 @@ import nominatim_db.tools.refresh
 import nominatim_db.tools.postcodes
 import nominatim_db.indexer.indexer
 
+
 class TestRefresh:
 
     @pytest.fixture(autouse=True)
@@ -20,7 +21,6 @@ class TestRefresh:
         self.call_nominatim = cli_call
         self.tokenizer_mock = cli_tokenizer_mock
 
-
     @pytest.mark.parametrize("command,func", [
                              ('address-levels', 'load_address_levels_from_config'),
                              ('wiki-data', 'import_wikipedia_articles'),
@@ -33,17 +33,14 @@ class TestRefresh:
         assert self.call_nominatim('refresh', '--' + command) == 0
         assert func_mock.called == 1
 
-
     def test_refresh_word_count(self):
         assert self.call_nominatim('refresh', '--word-count') == 0
         assert self.tokenizer_mock.update_statistics_called
 
-
     def test_refresh_word_tokens(self):
         assert self.call_nominatim('refresh', '--word-tokens') == 0
         assert self.tokenizer_mock.update_word_tokens_called
 
-
     def test_refresh_postcodes(self, async_mock_func_factory, mock_func_factory, place_table):
         func_mock = mock_func_factory(nominatim_db.tools.postcodes, 'update_postcodes')
         idx_mock = async_mock_func_factory(nominatim_db.indexer.indexer.Indexer, 'index_postcodes')
@@ -52,12 +49,10 @@ class TestRefresh:
         assert func_mock.called == 1
         assert idx_mock.called == 1
 
-
     def test_refresh_postcodes_no_place_table(self):
         # Do nothing without the place table
         assert self.call_nominatim('refresh', '--postcodes') == 0
 
-
     def test_refresh_create_functions(self, mock_func_factory):
         func_mock = mock_func_factory(nominatim_db.tools.refresh, 'create_functions')
 
@@ -65,17 +60,14 @@ class TestRefresh:
         assert func_mock.called == 1
         assert self.tokenizer_mock.update_sql_functions_called
 
-
     def test_refresh_wikidata_file_not_found(self, monkeypatch):
         monkeypatch.setenv('NOMINATIM_WIKIPEDIA_DATA_PATH', 'gjoiergjeroi345Q')
 
         assert self.call_nominatim('refresh', '--wiki-data') == 1
 
-
     def test_refresh_secondary_importance_file_not_found(self):
         assert self.call_nominatim('refresh', '--secondary-importance') == 1
 
-
     def test_refresh_secondary_importance_new_table(self, mock_func_factory):
         mocks = [mock_func_factory(nominatim_db.tools.refresh, 'import_secondary_importance'),
                  mock_func_factory(nominatim_db.tools.refresh, 'create_functions')]
@@ -84,7 +76,6 @@ class TestRefresh:
         assert mocks[0].called == 1
         assert mocks[1].called == 1
 
-
     def test_refresh_importance_computed_after_wiki_import(self, monkeypatch, mock_func_factory):
         calls = []
         monkeypatch.setattr(nominatim_db.tools.refresh, 'import_wikipedia_articles',
@@ -102,7 +93,8 @@ class TestRefresh:
                                         ('--data-object', 'N23', '--data-object', 'N24'),
                                         ('--data-area', 'R7723'),
                                         ('--data-area', 'r7723', '--data-area', 'r2'),
-                                        ('--data-area', 'R9284425', '--data-object', 'n1234567894567')])
+                                        ('--data-area', 'R9284425',
+                                         '--data-object', 'n1234567894567')])
     def test_refresh_objects(self, params, mock_func_factory):
         func_mock = mock_func_factory(nominatim_db.tools.refresh, 'invalidate_osm_object')
 
@@ -110,7 +102,6 @@ class TestRefresh:
 
         assert func_mock.called == len(params)/2
 
-
     @pytest.mark.parametrize('func', ('--data-object', '--data-area'))
     @pytest.mark.parametrize('param', ('234', 'a55', 'R 453', 'Rel'))
     def test_refresh_objects_bad_param(self, func, param, mock_func_factory):
index 21c6350d4e762c62f66de007cd147da95d347671..34aafa3ab1cae1453174e0018a07739c16b1449c 100644 (file)
@@ -18,6 +18,7 @@ import nominatim_db.tools.replication
 import nominatim_db.tools.refresh
 from nominatim_db.db import status
 
+
 @pytest.fixture
 def tokenizer_mock(monkeypatch):
     class DummyTokenizer:
@@ -40,7 +41,6 @@ def tokenizer_mock(monkeypatch):
     return tok
 
 
-
 @pytest.fixture
 def init_status(temp_db_conn, status_table):
     status.set_status(temp_db_conn, date=dt.datetime.now(dt.timezone.utc), seq=1)
@@ -62,16 +62,14 @@ class TestCliReplication:
     def setup_cli_call(self, cli_call, temp_db):
         self.call_nominatim = lambda *args: cli_call('replication', *args)
 
-
     @pytest.fixture(autouse=True)
     def setup_update_function(self, monkeypatch):
         def _mock_updates(states):
             monkeypatch.setattr(nominatim_db.tools.replication, 'update',
-                            lambda *args, **kwargs: states.pop())
+                                lambda *args, **kwargs: states.pop())
 
         self.update_states = _mock_updates
 
-
     @pytest.mark.parametrize("params,func", [
                              (('--init',), 'init_replication'),
                              (('--init', '--no-update-functions'), 'init_replication'),
@@ -88,20 +86,17 @@ class TestCliReplication:
         if params == ('--init',):
             assert umock.called == 1
 
-
     def test_replication_update_bad_interval(self, monkeypatch):
         monkeypatch.setenv('NOMINATIM_REPLICATION_UPDATE_INTERVAL', 'xx')
 
         assert self.call_nominatim() == 1
 
-
     def test_replication_update_bad_interval_for_geofabrik(self, monkeypatch):
         monkeypatch.setenv('NOMINATIM_REPLICATION_URL',
                            'https://download.geofabrik.de/europe/italy-updates')
 
         assert self.call_nominatim() == 1
 
-
     def test_replication_update_continuous_no_index(self):
         assert self.call_nominatim('--no-index') == 1
 
@@ -110,14 +105,12 @@ class TestCliReplication:
 
         assert str(update_mock.last_args[1]['osm2pgsql']).endswith('OSM2PGSQL NOT AVAILABLE')
 
-
     def test_replication_update_custom_osm2pgsql(self, monkeypatch, update_mock):
         monkeypatch.setenv('NOMINATIM_OSM2PGSQL_BINARY', '/secret/osm2pgsql')
         assert self.call_nominatim('--once', '--no-index') == 0
 
         assert str(update_mock.last_args[1]['osm2pgsql']) == '/secret/osm2pgsql'
 
-
     @pytest.mark.parametrize("update_interval", [60, 3600])
     def test_replication_catchup(self, placex_table, monkeypatch, index_mock, update_interval):
         monkeypatch.setenv('NOMINATIM_REPLICATION_UPDATE_INTERVAL', str(update_interval))
@@ -125,13 +118,11 @@ class TestCliReplication:
 
         assert self.call_nominatim('--catch-up') == 0
 
-
     def test_replication_update_custom_threads(self, update_mock):
         assert self.call_nominatim('--once', '--no-index', '--threads', '4') == 0
 
         assert update_mock.last_args[1]['threads'] == 4
 
-
     def test_replication_update_continuous(self, index_mock):
         self.update_states([nominatim_db.tools.replication.UpdateState.UP_TO_DATE,
                             nominatim_db.tools.replication.UpdateState.UP_TO_DATE])
@@ -141,7 +132,6 @@ class TestCliReplication:
 
         assert index_mock.called == 2
 
-
     def test_replication_update_continuous_no_change(self, mock_func_factory,
                                                      index_mock):
         self.update_states([nominatim_db.tools.replication.UpdateState.NO_CHANGES,
index 9f68fcb9a97e89b2d85058ef6ecccf4d745b3334..a0dbf476b9bf8ce4dbd81705be18704e230d68e5 100644 (file)
@@ -2,7 +2,7 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 """
 Test for loading dotenv configuration.
@@ -13,6 +13,7 @@ import pytest
 from nominatim_db.config import Configuration, flatten_config_list
 from nominatim_db.errors import UsageError
 
+
 @pytest.fixture
 def make_config():
     """ Create a configuration object from the given project directory.
@@ -22,6 +23,7 @@ def make_config():
 
     return _mk_config
 
+
 @pytest.fixture
 def make_config_path(tmp_path):
     """ Create a configuration object with project and config directories
@@ -108,7 +110,7 @@ def test_get_libpq_dsn_convert_php(make_config, monkeypatch):
 
 @pytest.mark.parametrize("val,expect", [('foo bar', "'foo bar'"),
                                         ("xy'z", "xy\\'z"),
-                                       ])
+                                        ])
 def test_get_libpq_dsn_convert_php_special_chars(make_config, monkeypatch, val, expect):
     config = make_config()
 
@@ -137,6 +139,7 @@ def test_get_bool(make_config, monkeypatch, value, result):
 
     assert config.get_bool('FOOBAR') == result
 
+
 def test_get_bool_empty(make_config):
     config = make_config()
 
@@ -303,7 +306,7 @@ def test_load_subconf_env_absolute_not_found(make_config_path, monkeypatch, tmp_
     (config.config_dir / 'test.yaml').write_text('cow: muh\ncat: miau\n')
 
     with pytest.raises(UsageError, match='Config file not found.'):
-        rules = config.load_sub_configuration('test.yaml', config='MY_CONFIG')
+        config.load_sub_configuration('test.yaml', config='MY_CONFIG')
 
 
 @pytest.mark.parametrize("location", ['project_dir', 'config_dir'])
@@ -326,7 +329,7 @@ def test_load_subconf_env_relative_not_found(make_config_path, monkeypatch):
     (config.config_dir / 'test.yaml').write_text('cow: muh\ncat: miau\n')
 
     with pytest.raises(UsageError, match='Config file not found.'):
-        rules = config.load_sub_configuration('test.yaml', config='MY_CONFIG')
+        config.load_sub_configuration('test.yaml', config='MY_CONFIG')
 
 
 def test_load_subconf_json(make_config_path):
@@ -338,6 +341,7 @@ def test_load_subconf_json(make_config_path):
 
     assert rules == dict(cow='muh', cat='miau')
 
+
 def test_load_subconf_not_found(make_config_path):
     config = make_config_path()
 
@@ -371,7 +375,7 @@ def test_load_subconf_include_relative(make_config_path, tmp_path, location):
     config = make_config_path()
 
     testfile = config.config_dir / 'test.yaml'
-    testfile.write_text(f'base: !include inc.yaml\n')
+    testfile.write_text('base: !include inc.yaml\n')
     (getattr(config, location) / 'inc.yaml').write_text('first: 1\nsecond: 2\n')
 
     rules = config.load_sub_configuration('test.yaml')
@@ -383,28 +387,28 @@ def test_load_subconf_include_bad_format(make_config_path):
     config = make_config_path()
 
     testfile = config.config_dir / 'test.yaml'
-    testfile.write_text(f'base: !include inc.txt\n')
+    testfile.write_text('base: !include inc.txt\n')
     (config.config_dir / 'inc.txt').write_text('first: 1\nsecond: 2\n')
 
     with pytest.raises(UsageError, match='Cannot handle config file format.'):
-        rules = config.load_sub_configuration('test.yaml')
+        config.load_sub_configuration('test.yaml')
 
 
 def test_load_subconf_include_not_found(make_config_path):
     config = make_config_path()
 
     testfile = config.config_dir / 'test.yaml'
-    testfile.write_text(f'base: !include inc.txt\n')
+    testfile.write_text('base: !include inc.txt\n')
 
     with pytest.raises(UsageError, match='Config file not found.'):
-        rules = config.load_sub_configuration('test.yaml')
+        config.load_sub_configuration('test.yaml')
 
 
 def test_load_subconf_include_recursive(make_config_path):
     config = make_config_path()
 
     testfile = config.config_dir / 'test.yaml'
-    testfile.write_text(f'base: !include inc.yaml\n')
+    testfile.write_text('base: !include inc.yaml\n')
     (config.config_dir / 'inc.yaml').write_text('- !include more.yaml\n- upper\n')
     (config.config_dir / 'more.yaml').write_text('- the end\n')
 
@@ -435,6 +439,6 @@ def test_flatten_config_list_nested():
         [[2, 3], [45, [56, 78], 66]],
         'end'
     ]
+
     assert flatten_config_list(content) == \
-               [34, {'first': '1st', 'second': '2nd'}, {},
-                2, 3, 45, 56, 78, 66, 'end']
+        [34, {'first': '1st', 'second': '2nd'}, {}, 2, 3, 45, 56, 78, 66, 'end']
index c29121802c2dd69291a97dd8042502a7dc159873..309bd1fc325850c1be2bf5254a5557a49d5bcf5b 100644 (file)
@@ -2,18 +2,18 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 """
 Test for loading extra Python modules.
 """
-from pathlib import Path
 import sys
 
 import pytest
 
 from nominatim_db.config import Configuration
 
+
 @pytest.fixture
 def test_config(src_dir, tmp_path):
     """ Create a configuration object with project and config directories
@@ -31,6 +31,7 @@ def test_load_default_module(test_config):
 
     assert isinstance(module.NOMINATIM_VERSION, tuple)
 
+
 def test_load_default_module_with_hyphen(test_config):
     module = test_config.load_plugin_module('place-info', 'nominatim_db.data')
 
index a25ff8ec5046766416be3bcb87091dff8ff90fd2..f95da39e4411fd68e8155ebef11643e0308bea4f 100644 (file)
@@ -2,7 +2,7 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 import itertools
 import sys
@@ -69,6 +69,7 @@ def temp_db_with_extensions(temp_db):
 
     return temp_db
 
+
 @pytest.fixture
 def temp_db_conn(temp_db):
     """ Connection to the test database.
@@ -100,8 +101,9 @@ def table_factory(temp_db_conn):
             if content:
                 sql = pysql.SQL("INSERT INTO {} VALUES ({})")\
                            .format(pysql.Identifier(name),
-                                   pysql.SQL(',').join([pysql.Placeholder() for _ in range(len(content[0]))]))
-                cur.executemany(sql , content)
+                                   pysql.SQL(',').join([pysql.Placeholder()
+                                                        for _ in range(len(content[0]))]))
+                cur.executemany(sql, content)
 
     return mk_table
 
@@ -178,6 +180,7 @@ def place_row(place_table, temp_db_cursor):
 
     return _insert
 
+
 @pytest.fixture
 def placex_table(temp_db_with_extensions, temp_db_conn):
     """ Create an empty version of the place table.
index b3fc260a2526d016ae2607e681e702baaddb591e..5dc93cd57e3bd66cf1c5d516d2258e1dc7f2c780 100644 (file)
@@ -2,13 +2,14 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 """
 Specialised psycopg cursor with shortcut functions useful for testing.
 """
 import psycopg
 
+
 class CursorForTesting(psycopg.Cursor):
     """ Extension to the DictCursor class that provides execution
         short-cuts that simplify writing assertions.
@@ -22,7 +23,6 @@ class CursorForTesting(psycopg.Cursor):
         assert self.rowcount == 1
         return self.fetchone()[0]
 
-
     def row_set(self, sql, params=None):
         """ Execute a query and return the result as a set of tuples.
             Fails when the SQL command returns duplicate rows.
@@ -34,7 +34,6 @@ class CursorForTesting(psycopg.Cursor):
 
         return result
 
-
     def table_exists(self, table):
         """ Check that a table with the given name exists in the database.
         """
@@ -42,7 +41,6 @@ class CursorForTesting(psycopg.Cursor):
                              WHERE tablename = %s""", (table, ))
         return num == 1
 
-
     def index_exists(self, table, index):
         """ Check that an indexwith the given name exists on the given table.
         """
@@ -51,7 +49,6 @@ class CursorForTesting(psycopg.Cursor):
                           (table, index))
         return num == 1
 
-
     def table_rows(self, table, where=None):
         """ Return the number of rows in the given table.
         """
index 14b306bb764d70717f5c572304a4634af330ba9e..a85b7bf92ac7b56c82fd1a2f2c8299b3f000a7a4 100644 (file)
@@ -2,7 +2,7 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 """
 Tests for function that handle country properties.
@@ -12,6 +12,7 @@ import pytest
 
 from nominatim_db.data import country_info
 
+
 @pytest.fixture
 def loaded_country(def_config):
     country_info.setup_country_config(def_config)
@@ -115,8 +116,8 @@ def test_setup_country_config_languages_not_loaded(env_with_country_config):
     info = country_info._CountryInfo()
     info.load(config)
     assert dict(info.items()) == {'de': {'partition': 3,
-                                  'languages': [],
-                                  'names': {'name': 'Deutschland'}}}
+                                         'languages': [],
+                                         'names': {'name': 'Deutschland'}}}
 
 
 def test_setup_country_config_name_not_loaded(env_with_country_config):
@@ -132,8 +133,7 @@ def test_setup_country_config_name_not_loaded(env_with_country_config):
 
     assert dict(info.items()) == {'de': {'partition': 3,
                                          'languages': ['de'],
-                                         'names': {}
-                                 }}
+                                         'names': {}}}
 
 
 def test_setup_country_config_names_not_loaded(env_with_country_config):
@@ -148,8 +148,7 @@ def test_setup_country_config_names_not_loaded(env_with_country_config):
 
     assert dict(info.items()) == {'de': {'partition': 3,
                                          'languages': ['de'],
-                                         'names': {}
-                                 }}
+                                         'names': {}}}
 
 
 def test_setup_country_config_special_character(env_with_country_config):
@@ -157,8 +156,8 @@ def test_setup_country_config_special_character(env_with_country_config):
                                      bq:
                                          partition: 250
                                          languages: nl
-                                         names: 
-                                             name: 
+                                         names:
+                                             name:
                                                  default: "\\N"
                                      """)
 
@@ -167,5 +166,4 @@ def test_setup_country_config_special_character(env_with_country_config):
 
     assert dict(info.items()) == {'bq': {'partition': 250,
                                          'languages': ['nl'],
-                                         'names': {'name': '\x85'}
-                                 }}
+                                         'names': {'name': '\x85'}}}
index a8b5d677ce22e43f8e9b8e69ff222dc08202e560..19b945fda58de90fbd418934f193880bf3b6702c 100644 (file)
@@ -2,7 +2,7 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 """
 Tests for specialised connection and cursor classes.
@@ -12,6 +12,7 @@ import psycopg
 
 import nominatim_db.db.connection as nc
 
+
 @pytest.fixture
 def db(dsn):
     with nc.connect(dsn) as conn:
@@ -36,6 +37,7 @@ def test_has_column(db, table_factory, name, result):
 
     assert nc.table_has_column(db, 'stuff', name) == result
 
+
 def test_connection_index_exists(db, table_factory, temp_db_cursor):
     assert not nc.index_exists(db, 'some_index')
 
@@ -76,6 +78,7 @@ def test_drop_table_non_existing_force(db):
     with pytest.raises(psycopg.ProgrammingError, match='.*does not exist.*'):
         nc.drop_tables(db, 'dfkjgjriogjigjgjrdghehtre', if_exists=False)
 
+
 def test_connection_server_version_tuple(db):
     ver = nc.server_version_tuple(db)
 
index e55bb973467611022791699aa6ad755955a4bdbb..84d7dae06d8b0bd62fdd2e2675edc69d4de13fa5 100644 (file)
@@ -2,7 +2,7 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 """
 Tests for property table manpulation.
@@ -11,6 +11,7 @@ import pytest
 
 from nominatim_db.db import properties
 
+
 @pytest.fixture
 def property_factory(property_table, temp_db_cursor):
     """ A function fixture that adds a property into the property table.
index 45109c70c759452f0c972964944c40e79a322ff1..f2fbbb2af52cad7ead0c62ece5412bdc8b5ddae0 100644 (file)
@@ -2,16 +2,17 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 """
 Tests for SQL preprocessing.
 """
 import pytest
-import pytest_asyncio
+import pytest_asyncio  # noqa
 
 from nominatim_db.db.sql_preprocessor import SQLPreprocessor
 
+
 @pytest.fixture
 def sql_factory(tmp_path):
     def _mk_sql(sql_body):
@@ -26,6 +27,7 @@ def sql_factory(tmp_path):
 
     return _mk_sql
 
+
 @pytest.mark.parametrize("expr,ret", [
     ("'a'", 'a'),
     ("'{{db.partitions|join}}'", '012'),
@@ -61,8 +63,7 @@ def test_load_file_with_params(sql_preprocessor, sql_factory, temp_db_conn, temp
 async def test_load_parallel_file(dsn, sql_preprocessor, tmp_path, temp_db_cursor):
     (tmp_path / 'test.sql').write_text("""
         CREATE TABLE foo (a TEXT);
-        CREATE TABLE foo2(a TEXT);""" + 
-        "\n---\nCREATE TABLE bar (b INT);")
+        CREATE TABLE foo2(a TEXT);""" + "\n---\nCREATE TABLE bar (b INT);")
 
     await sql_preprocessor.run_parallel_sql_file(dsn, 'test.sql', num_threads=4)
 
index 77135a8c7f943c13df96632aa9901e50b9aabed7..462b8e3db809a0e56dd580771fc5c4d6b92a5cd1 100644 (file)
@@ -2,7 +2,7 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 """
 Tests for status table manipulation.
@@ -19,7 +19,8 @@ OSM_NODE_DATA = """\
 <node id="45673" visible="true" version="1" changeset="2047" timestamp="2006-01-27T22:09:10Z" user="Foo" uid="111" lat="48.7586670" lon="8.1343060">
 </node>
 </osm>
-"""
+"""  # noqa
+
 
 def iso_date(date):
     return dt.datetime.strptime(date, nominatim_db.db.status.ISODATE_FORMAT)\
@@ -43,7 +44,8 @@ def test_compute_database_date_from_osm2pgsql(table_factory, temp_db_conn, offli
 def test_compute_database_date_from_osm2pgsql_nodata(table_factory, temp_db_conn):
     table_factory('osm2pgsql_properties', 'property TEXT, value TEXT')
 
-    with pytest.raises(UsageError, match='Cannot determine database date from data in offline mode'):
+    with pytest.raises(UsageError,
+                       match='Cannot determine database date from data in offline mode'):
         nominatim_db.db.status.compute_database_date(temp_db_conn, offline=True)
 
 
@@ -56,6 +58,7 @@ def test_compute_database_date_valid(monkeypatch, place_row, temp_db_conn):
     place_row(osm_type='N', osm_id=45673)
 
     requested_url = []
+
     def mock_url(url):
         requested_url.append(url)
         return OSM_NODE_DATA
@@ -72,6 +75,7 @@ def test_compute_database_broken_api(monkeypatch, place_row, temp_db_conn):
     place_row(osm_type='N', osm_id=45673)
 
     requested_url = []
+
     def mock_url(url):
         requested_url.append(url)
         return '<osm version="0.6" generator="OpenStre'
@@ -86,8 +90,7 @@ def test_set_status_empty_table(temp_db_conn, temp_db_cursor):
     date = dt.datetime.fromordinal(1000000).replace(tzinfo=dt.timezone.utc)
     nominatim_db.db.status.set_status(temp_db_conn, date=date)
 
-    assert temp_db_cursor.row_set("SELECT * FROM import_status") == \
-             {(date, None, True)}
+    assert temp_db_cursor.row_set("SELECT * FROM import_status") == {(date, None, True)}
 
 
 def test_set_status_filled_table(temp_db_conn, temp_db_cursor):
@@ -99,8 +102,7 @@ def test_set_status_filled_table(temp_db_conn, temp_db_cursor):
     date = dt.datetime.fromordinal(1000100).replace(tzinfo=dt.timezone.utc)
     nominatim_db.db.status.set_status(temp_db_conn, date=date, seq=456, indexed=False)
 
-    assert temp_db_cursor.row_set("SELECT * FROM import_status") == \
-             {(date, 456, False)}
+    assert temp_db_cursor.row_set("SELECT * FROM import_status") == {(date, 456, False)}
 
 
 def test_set_status_missing_date(temp_db_conn, temp_db_cursor):
@@ -111,8 +113,7 @@ def test_set_status_missing_date(temp_db_conn, temp_db_cursor):
 
     nominatim_db.db.status.set_status(temp_db_conn, date=None, seq=456, indexed=False)
 
-    assert temp_db_cursor.row_set("SELECT * FROM import_status") == \
-             {(date, 456, False)}
+    assert temp_db_cursor.row_set("SELECT * FROM import_status") == {(date, 456, False)}
 
 
 def test_get_status_empty_table(temp_db_conn):
@@ -123,8 +124,7 @@ def test_get_status_success(temp_db_conn):
     date = dt.datetime.fromordinal(1000000).replace(tzinfo=dt.timezone.utc)
     nominatim_db.db.status.set_status(temp_db_conn, date=date, seq=667, indexed=False)
 
-    assert nominatim_db.db.status.get_status(temp_db_conn) == \
-             (date, 667, False)
+    assert nominatim_db.db.status.get_status(temp_db_conn) == (date, 667, False)
 
 
 @pytest.mark.parametrize("old_state", [True, False])
index 7c46846dbdd4fb0ba5c2fc2ae436f7df76005411..2bc7d95934277859593b3fc7cfeb60366749f3e6 100644 (file)
@@ -2,18 +2,17 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 """
 Tests for DB utility functions in db.utils
 """
-import json
-
 import pytest
 
 import nominatim_db.db.utils as db_utils
 from nominatim_db.errors import UsageError
 
+
 def test_execute_file_success(dsn, temp_db_cursor, tmp_path):
     tmpfile = tmp_path / 'test.sql'
     tmpfile.write_text('CREATE TABLE test (id INT);\nINSERT INTO test VALUES(56);')
@@ -22,6 +21,7 @@ def test_execute_file_success(dsn, temp_db_cursor, tmp_path):
 
     assert temp_db_cursor.row_set('SELECT * FROM test') == {(56, )}
 
+
 def test_execute_file_bad_file(dsn, tmp_path):
     with pytest.raises(FileNotFoundError):
         db_utils.execute_file(dsn, tmp_path / 'test2.sql')
index 4739e3f0af831303f4860f601b802537e781d898..08554129257b74fbc43e526d4621deafac42f27f 100644 (file)
@@ -2,7 +2,7 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 """
 Tokenizer for testing.
@@ -10,11 +10,13 @@ Tokenizer for testing.
 from nominatim_db.data.place_info import PlaceInfo
 from nominatim_db.config import Configuration
 
+
 def create(dsn, data_dir):
     """ Create a new instance of the tokenizer provided by this module.
     """
     return DummyTokenizer(dsn, data_dir)
 
+
 class DummyTokenizer:
 
     def __init__(self, dsn, data_dir):
@@ -23,23 +25,19 @@ class DummyTokenizer:
         self.init_state = None
         self.analyser_cache = {}
 
-
     def init_new_db(self, *args, **kwargs):
         assert self.init_state is None
         self.init_state = "new"
 
-
     def init_from_project(self, config):
         assert isinstance(config, Configuration)
         assert self.init_state is None
         self.init_state = "loaded"
 
-
     @staticmethod
     def finalize_import(_):
         pass
 
-
     def name_analyzer(self):
         return DummyNameAnalyzer(self.analyser_cache)
 
@@ -52,12 +50,10 @@ class DummyNameAnalyzer:
     def __exit__(self, exc_type, exc_value, traceback):
         self.close()
 
-
     def __init__(self, cache):
         self.analyser_cache = cache
         cache['countries'] = []
 
-
     def close(self):
         pass
 
index fe65b69c4dff04d39ebb04ceb133a42bc2a21f82..79b76c60a62773638d8f75f5f1374f58de872c08 100644 (file)
@@ -2,18 +2,19 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 """
 Tests for running the indexing.
 """
 import itertools
 import pytest
-import pytest_asyncio
+import pytest_asyncio  # noqa
 
 from nominatim_db.indexer import indexer
 from nominatim_db.tokenizer import factory
 
+
 class IndexerTestDB:
 
     def __init__(self, conn):
@@ -232,6 +233,7 @@ async def test_index_partial_with_30(test_db, threads, test_tokenizer):
                     SELECT count(*) FROM placex
                       WHERE indexed_status = 0 AND rank_address between 1 and 27""") == 0
 
+
 @pytest.mark.parametrize("threads", [1, 15])
 @pytest.mark.asyncio
 async def test_index_boundaries(test_db, threads, test_tokenizer):
index e8b4390f5fc38c4c6c55c5417f3cc36373a8dc7b..b26025a05a285cd6be0aa4fba2acdb8c27c7ba8e 100644 (file)
@@ -2,7 +2,7 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 """
 Legacy word table for testing with functions to prefil and test contents
@@ -10,6 +10,7 @@ of the table.
 """
 from nominatim_db.db.connection import execute_scalar
 
+
 class MockIcuWordTable:
     """ A word table for testing using legacy word table structure.
     """
@@ -31,7 +32,6 @@ class MockIcuWordTable:
                         (word_id, word or word_token, word))
         self.conn.commit()
 
-
     def add_special(self, word_token, word, cls, typ, oper):
         with self.conn.cursor() as cur:
             cur.execute("""INSERT INTO word (word_token, type, word, info)
@@ -42,7 +42,6 @@ class MockIcuWordTable:
                         """, (word_token, word, cls, typ, oper))
         self.conn.commit()
 
-
     def add_country(self, country_code, word_token):
         with self.conn.cursor() as cur:
             cur.execute("""INSERT INTO word (word_token, type, word)
@@ -50,7 +49,6 @@ class MockIcuWordTable:
                         (word_token, country_code))
         self.conn.commit()
 
-
     def add_postcode(self, word_token, postcode):
         with self.conn.cursor() as cur:
             cur.execute("""INSERT INTO word (word_token, type, word)
@@ -58,7 +56,6 @@ class MockIcuWordTable:
                         """, (word_token, postcode))
         self.conn.commit()
 
-
     def add_housenumber(self, word_id, word_tokens, word=None):
         with self.conn.cursor() as cur:
             if isinstance(word_tokens, str):
@@ -71,24 +68,21 @@ class MockIcuWordTable:
                     word = word_tokens[0]
                 for token in word_tokens:
                     cur.execute("""INSERT INTO word (word_id, word_token, type, word, info)
-                                      VALUES (%s, %s, 'H', %s, jsonb_build_object('lookup', %s::text))
+                                      VALUES (%s, %s, 'H', %s,
+                                              jsonb_build_object('lookup', %s::text))
                                 """, (word_id, token, word, word_tokens[0]))
 
         self.conn.commit()
 
-
     def count(self):
         return execute_scalar(self.conn, "SELECT count(*) FROM word")
 
-
     def count_special(self):
         return execute_scalar(self.conn, "SELECT count(*) FROM word WHERE type = 'S'")
 
-
     def count_housenumbers(self):
         return execute_scalar(self.conn, "SELECT count(*) FROM word WHERE type = 'H'")
 
-
     def get_special(self):
         with self.conn.cursor() as cur:
             cur.execute("SELECT word_token, info, word FROM word WHERE type = 'S'")
@@ -97,7 +91,6 @@ class MockIcuWordTable:
             assert len(result) == cur.rowcount, "Word table has duplicates."
             return result
 
-
     def get_country(self):
         with self.conn.cursor() as cur:
             cur.execute("SELECT word, word_token FROM word WHERE type = 'C'")
@@ -105,15 +98,12 @@ class MockIcuWordTable:
             assert len(result) == cur.rowcount, "Word table has duplicates."
             return result
 
-
     def get_postcodes(self):
         with self.conn.cursor() as cur:
             cur.execute("SELECT word FROM word WHERE type = 'P'")
             return set((row[0] for row in cur))
 
-
     def get_partial_words(self):
         with self.conn.cursor() as cur:
             cur.execute("SELECT word_token, info FROM word WHERE type ='w'")
             return set(((row[0], row[1]['count']) for row in cur))
-
index cde0b7bb58e8fdab6208ca6cef05d10c179535ff..fb7f4fa1d6d8e7e42c8b1ab2854f72e9d1f4ac88 100644 (file)
@@ -2,7 +2,7 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 """
 Custom mocks for testing.
@@ -11,8 +11,6 @@ import itertools
 
 from nominatim_db.db import properties
 
-# This must always point to the mock word table for the default tokenizer.
-from mock_icu_word_table import MockIcuWordTable as MockWordTable
 
 class MockPlacexTable:
     """ A placex table for testing.
@@ -58,7 +56,8 @@ class MockPlacexTable:
                                                type, name, admin_level, address,
                                                housenumber, rank_search,
                                                extratags, geometry, country_code)
-                            VALUES(nextval('seq_place'), %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""",
+                            VALUES(nextval('seq_place'), %s, %s, %s, %s, %s, %s,
+                                   %s, %s, %s, %s, %s, %s)""",
                         (osm_type, osm_id or next(self.idseq), cls, typ, names,
                          admin_level, address, housenumber, rank_search,
                          extratags, 'SRID=4326;' + geom,
@@ -72,13 +71,11 @@ class MockPropertyTable:
     def __init__(self, conn):
         self.conn = conn
 
-
     def set(self, name, value):
         """ Set a property in the table to the given value.
         """
         properties.set_property(self.conn, name, value)
 
-
     def get(self, name):
         """ Set a property in the table to the given value.
         """
index 01fb162b8e78ae4b90b7ac6253ff43dd1212875d..2dd10c5631ad402431f5f0df7dd8af944a0748b6 100644 (file)
@@ -2,7 +2,7 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 """
 Tests for the sanitizer that normalizes housenumbers.
@@ -12,11 +12,12 @@ import pytest
 from nominatim_db.tokenizer.place_sanitizer import PlaceSanitizer
 from nominatim_db.data.place_info import PlaceInfo
 
+
 @pytest.fixture
 def sanitize(request, def_config):
     sanitizer_args = {'step': 'clean-housenumbers'}
     for mark in request.node.iter_markers(name="sanitizer_params"):
-        sanitizer_args.update({k.replace('_', '-') : v for k,v in mark.kwargs.items()})
+        sanitizer_args.update({k.replace('_', '-'): v for k, v in mark.kwargs.items()})
 
     def _run(**kwargs):
         place = PlaceInfo({'address': kwargs})
index 70cc5256640b9918535367d986818b082f67f747..242e9301a9bf34094702f4e95ac559526acef424 100644 (file)
@@ -2,7 +2,7 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 """
 Tests for the sanitizer that normalizes postcodes.
@@ -13,12 +13,13 @@ from nominatim_db.tokenizer.place_sanitizer import PlaceSanitizer
 from nominatim_db.data.place_info import PlaceInfo
 from nominatim_db.data import country_info
 
+
 @pytest.fixture
 def sanitize(def_config, request):
     country_info.setup_country_config(def_config)
     sanitizer_args = {'step': 'clean-postcodes'}
     for mark in request.node.iter_markers(name="sanitizer_params"):
-        sanitizer_args.update({k.replace('_', '-') : v for k,v in mark.kwargs.items()})
+        sanitizer_args.update({k.replace('_', '-'): v for k, v in mark.kwargs.items()})
 
     def _run(country=None, **kwargs):
         pi = {'address': kwargs}
index 4badb57f7b25f48b90315ba5402ecacadf6560d2..d245f4dff17f716e0baa8f47ec1d8c1e1c7bf258 100644 (file)
@@ -2,7 +2,7 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 """
 Tests for sanitizer that clean up TIGER tags.
@@ -12,16 +12,17 @@ import pytest
 from nominatim_db.tokenizer.place_sanitizer import PlaceSanitizer
 from nominatim_db.data.place_info import PlaceInfo
 
+
 class TestCleanTigerTags:
 
     @pytest.fixture(autouse=True)
     def setup_country(self, def_config):
         self.config = def_config
 
-
     def run_sanitizer_on(self, addr):
         place = PlaceInfo({'address': addr})
-        _, outaddr = PlaceSanitizer([{'step': 'clean-tiger-tags'}], self.config).process_names(place)
+        _, outaddr = PlaceSanitizer([{'step': 'clean-tiger-tags'}],
+                                    self.config).process_names(place)
 
         return sorted([(p.name, p.kind, p.suffix) for p in outaddr])
 
@@ -31,13 +32,11 @@ class TestCleanTigerTags:
         assert self.run_sanitizer_on({'tiger:county': inname})\
             == [(outname, 'county', 'tiger')]
 
-
     @pytest.mark.parametrize('name', ('Hamilton', 'Big, Road', ''))
     def test_badly_formatted(self, name):
         assert self.run_sanitizer_on({'tiger:county': name})\
             == [(name, 'county', 'tiger')]
 
-
     def test_unmatched(self):
         assert self.run_sanitizer_on({'tiger:country': 'US'})\
             == [('US', 'tiger', 'country')]
index f9688c0be14dad44eae47679f18169fe81de582c..9c8f2a90dea872f78737aea62451faaea25a98fe 100644 (file)
@@ -2,7 +2,7 @@
 #\r
 # This file is part of Nominatim. (https://nominatim.org)\r
 #\r
-# Copyright (C) 2024 by the Nominatim developer community.\r
+# Copyright (C) 2025 by the Nominatim developer community.\r
 # For a full list of authors see the git log.\r
 """\r
 Tests for the sanitizer that normalizes housenumbers.\r
@@ -22,18 +22,15 @@ class TestWithDefault:
     def run_sanitizer_on(self, type, **kwargs):\r
 \r
         place = PlaceInfo({type: {k.replace('_', ':'): v for k, v in kwargs.items()},\r
-                            'country_code': 'de', 'rank_address': 30})\r
+                          'country_code': 'de', 'rank_address': 30})\r
 \r
         sanitizer_args = {'step': 'delete-tags'}\r
 \r
         name, address = PlaceSanitizer([sanitizer_args],\r
-                                    self.config).process_names(place)\r
-\r
-        return {\r
-                'name': sorted([(p.name, p.kind, p.suffix or '') for p in name]),\r
-                'address': sorted([(p.name, p.kind, p.suffix or '') for p in address])\r
-            }\r
+                                       self.config).process_names(place)\r
 \r
+        return {'name': sorted([(p.name, p.kind, p.suffix or '') for p in name]),\r
+                'address': sorted([(p.name, p.kind, p.suffix or '') for p in address])}\r
 \r
     def test_on_name(self):\r
         res = self.run_sanitizer_on('name', name='foo', ref='bar', ref_abc='baz')\r
@@ -44,7 +41,7 @@ class TestWithDefault:
         res = self.run_sanitizer_on('address', name='foo', ref='bar', ref_abc='baz')\r
 \r
         assert res.get('address') == [('bar', 'ref', ''), ('baz', 'ref', 'abc'),\r
-                                        ('foo', 'name', '')]\r
+                                      ('foo', 'name', '')]\r
 \r
 \r
 class TestTypeField:\r
@@ -56,15 +53,13 @@ class TestTypeField:
     def run_sanitizer_on(self, type, **kwargs):\r
 \r
         place = PlaceInfo({'name': {k.replace('_', ':'): v for k, v in kwargs.items()},\r
-                            'country_code': 'de', 'rank_address': 30})\r
+                           'country_code': 'de', 'rank_address': 30})\r
 \r
-        sanitizer_args = {\r
-                        'step': 'delete-tags',\r
-                        'type': type,\r
-                    }\r
+        sanitizer_args = {'step': 'delete-tags',\r
+                          'type': type}\r
 \r
         name, _ = PlaceSanitizer([sanitizer_args],\r
-                                    self.config).process_names(place)\r
+                                 self.config).process_names(place)\r
 \r
         return sorted([(p.name, p.kind, p.suffix or '') for p in name])\r
 \r
@@ -77,7 +72,8 @@ class TestTypeField:
         res = self.run_sanitizer_on('address', name='foo', ref='bar', ref_abc='baz')\r
 \r
         assert res == [('bar', 'ref', ''), ('baz', 'ref', 'abc'),\r
-                        ('foo', 'name', '')]\r
+                       ('foo', 'name', '')]\r
+\r
 \r
 class TestFilterKind:\r
 \r
@@ -88,15 +84,13 @@ class TestFilterKind:
     def run_sanitizer_on(self, filt, **kwargs):\r
 \r
         place = PlaceInfo({'name': {k.replace('_', ':'): v for k, v in kwargs.items()},\r
-                            'country_code': 'de', 'rank_address': 30})\r
+                           'country_code': 'de', 'rank_address': 30})\r
 \r
-        sanitizer_args = {\r
-                        'step': 'delete-tags',\r
-                        'filter-kind': filt,\r
-                    }\r
+        sanitizer_args = {'step': 'delete-tags',\r
+                          'filter-kind': filt}\r
 \r
         name, _ = PlaceSanitizer([sanitizer_args],\r
-                                    self.config).process_names(place)\r
+                                 self.config).process_names(place)\r
 \r
         return sorted([(p.name, p.kind, p.suffix or '') for p in name])\r
 \r
@@ -106,7 +100,6 @@ class TestFilterKind:
 \r
         assert res == [('bar', 'ref', 'abc'), ('foo', 'ref', '')]\r
 \r
-\r
     def test_single_pattern(self):\r
         res = self.run_sanitizer_on(['.*name'],\r
                                     name_fr='foo', ref_fr='foo', namexx_fr='bar',\r
@@ -114,7 +107,6 @@ class TestFilterKind:
 \r
         assert res == [('bar', 'namexx', 'fr'), ('foo', 'ref', 'fr')]\r
 \r
-\r
     def test_multiple_patterns(self):\r
         res = self.run_sanitizer_on(['.*name', 'ref'],\r
                                     name_fr='foo', ref_fr='foo', oldref_fr='foo',\r
@@ -132,19 +124,16 @@ class TestRankAddress:
     def run_sanitizer_on(self, rank_addr, **kwargs):\r
 \r
         place = PlaceInfo({'name': {k.replace('_', ':'): v for k, v in kwargs.items()},\r
-                            'country_code': 'de', 'rank_address': 30})\r
+                           'country_code': 'de', 'rank_address': 30})\r
 \r
-        sanitizer_args = {\r
-                        'step': 'delete-tags',\r
-                        'rank_address': rank_addr\r
-                    }\r
+        sanitizer_args = {'step': 'delete-tags',\r
+                          'rank_address': rank_addr}\r
 \r
         name, _ = PlaceSanitizer([sanitizer_args],\r
-                                    self.config).process_names(place)\r
+                                 self.config).process_names(place)\r
 \r
         return sorted([(p.name, p.kind, p.suffix or '') for p in name])\r
 \r
-\r
     def test_single_rank(self):\r
         res = self.run_sanitizer_on('30', name='foo', ref='bar')\r
 \r
@@ -185,33 +174,29 @@ class TestSuffix:
     def run_sanitizer_on(self, suffix, **kwargs):\r
 \r
         place = PlaceInfo({'name': {k.replace('_', ':'): v for k, v in kwargs.items()},\r
-                            'country_code': 'de', 'rank_address': 30})\r
+                           'country_code': 'de', 'rank_address': 30})\r
 \r
-        sanitizer_args = {\r
-                        'step': 'delete-tags',\r
-                        'suffix': suffix,\r
-                    }\r
+        sanitizer_args = {'step': 'delete-tags',\r
+                          'suffix': suffix}\r
 \r
         name, _ = PlaceSanitizer([sanitizer_args],\r
-                                    self.config).process_names(place)\r
+                                 self.config).process_names(place)\r
 \r
         return sorted([(p.name, p.kind, p.suffix or '') for p in name])\r
 \r
-\r
     def test_single_suffix(self):\r
         res = self.run_sanitizer_on('abc', name='foo', name_abc='foo',\r
-                                 name_pqr='bar', ref='bar', ref_abc='baz')\r
+                                    name_pqr='bar', ref='bar', ref_abc='baz')\r
 \r
         assert res == [('bar', 'name', 'pqr'), ('bar', 'ref', ''), ('foo', 'name', '')]\r
 \r
     def test_multiple_suffix(self):\r
         res = self.run_sanitizer_on(['abc.*', 'pqr'], name='foo', name_abcxx='foo',\r
-                                 ref_pqr='bar', name_pqrxx='baz')\r
+                                    ref_pqr='bar', name_pqrxx='baz')\r
 \r
         assert res == [('baz', 'name', 'pqrxx'), ('foo', 'name', '')]\r
 \r
 \r
-\r
 class TestCountryCodes:\r
 \r
     @pytest.fixture(autouse=True)\r
@@ -221,19 +206,16 @@ class TestCountryCodes:
     def run_sanitizer_on(self, country_code, **kwargs):\r
 \r
         place = PlaceInfo({'name': {k.replace('_', ':'): v for k, v in kwargs.items()},\r
-                            'country_code': 'de', 'rank_address': 30})\r
+                           'country_code': 'de', 'rank_address': 30})\r
 \r
-        sanitizer_args = {\r
-                        'step': 'delete-tags',\r
-                        'country_code': country_code,\r
-                    }\r
+        sanitizer_args = {'step': 'delete-tags',\r
+                          'country_code': country_code}\r
 \r
         name, _ = PlaceSanitizer([sanitizer_args],\r
-                                    self.config).process_names(place)\r
+                                 self.config).process_names(place)\r
 \r
         return sorted([(p.name, p.kind) for p in name])\r
 \r
-\r
     def test_single_country_code_pass(self):\r
         res = self.run_sanitizer_on('de', name='foo', ref='bar')\r
 \r
@@ -259,6 +241,7 @@ class TestCountryCodes:
 \r
         assert res == [('bar', 'ref'), ('foo', 'name')]\r
 \r
+\r
 class TestAllParameters:\r
 \r
     @pytest.fixture(autouse=True)\r
@@ -268,7 +251,7 @@ class TestAllParameters:
     def run_sanitizer_on(self, country_code, rank_addr, suffix, **kwargs):\r
 \r
         place = PlaceInfo({'name': {k.replace('_', ':'): v for k, v in kwargs.items()},\r
-                            'country_code': 'de', 'rank_address': 30})\r
+                           'country_code': 'de', 'rank_address': 30})\r
 \r
         sanitizer_args = {\r
                         'step': 'delete-tags',\r
@@ -281,11 +264,10 @@ class TestAllParameters:
                     }\r
 \r
         name, _ = PlaceSanitizer([sanitizer_args],\r
-                                    self.config).process_names(place)\r
+                                 self.config).process_names(place)\r
 \r
         return sorted([(p.name, p.kind, p.suffix or '') for p in name])\r
 \r
-\r
     def test_string_arguments_pass(self):\r
         res = self.run_sanitizer_on('de', '25-30', r'[\s\S]*',\r
                                     name='foo', ref='foo', name_abc='bar', ref_abc='baz')\r
index 0497f21df70e9907348730b21ce22c5700c984d3..5dd2ec034ac441fbc512ea49e4e506337a8e3aee 100644 (file)
@@ -2,7 +2,7 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 """
 Tests for sanitizer configuration helper functions.
@@ -12,6 +12,7 @@ import pytest
 from nominatim_db.errors import UsageError
 from nominatim_db.tokenizer.sanitizers.config import SanitizerConfig
 
+
 def test_string_list_default_empty():
     assert SanitizerConfig().get_string_list('op') == []
 
@@ -53,7 +54,7 @@ def test_create_split_regex_no_params_unsplit(inp):
                                       ('ying;;yang', ['ying', 'yang']),
                                       (';a; ;c;d,', ['', 'a', '', 'c', 'd', '']),
                                       ('1,  3  ,5', ['1', '3', '5'])
-                                     ])
+                                      ])
 def test_create_split_regex_no_params_split(inp, outp):
     regex = SanitizerConfig().get_delimiter()
 
@@ -70,7 +71,7 @@ def test_create_split_regex_custom(delimiter):
 
 def test_create_split_regex_empty_delimiter():
     with pytest.raises(UsageError):
-        regex = SanitizerConfig({'delimiters': ''}).get_delimiter()
+        SanitizerConfig({'delimiters': ''}).get_delimiter()
 
 
 @pytest.mark.parametrize('inp', ('name', 'name:de', 'na\\me', '.*', ''))
@@ -96,12 +97,12 @@ def test_create_name_filter_no_param_default_fail_all(inp):
 
 def test_create_name_filter_no_param_default_invalid_string():
     with pytest.raises(ValueError):
-        filt = SanitizerConfig().get_filter('name', 'abc')
+        SanitizerConfig().get_filter('name', 'abc')
 
 
 def test_create_name_filter_no_param_default_empty_list():
     with pytest.raises(ValueError):
-        filt = SanitizerConfig().get_filter('name', [])
+        SanitizerConfig().get_filter('name', [])
 
 
 @pytest.mark.parametrize('kind', ('de', 'name:de', 'ende'))
@@ -121,7 +122,7 @@ def test_create_kind_filter_default_negetive(kind):
 @pytest.mark.parametrize('kind', ('lang', 'lang:de', 'langxx'))
 def test_create_kind_filter_custom_regex_positive(kind):
     filt = SanitizerConfig({'filter-kind': 'lang.*'}
-    ).get_filter('filter-kind', ['.*fr'])
+                           ).get_filter('filter-kind', ['.*fr'])
 
     assert filt(kind)
 
@@ -136,7 +137,7 @@ def test_create_kind_filter_custom_regex_negative(kind):
 @pytest.mark.parametrize('kind', ('name', 'fr', 'name:fr', 'frfr', '34'))
 def test_create_kind_filter_many_positive(kind):
     filt = SanitizerConfig({'filter-kind': ['.*fr', 'name', r'\d+']}
-    ).get_filter('filter-kind')
+                           ).get_filter('filter-kind')
 
     assert filt(kind)
 
@@ -144,6 +145,6 @@ def test_create_kind_filter_many_positive(kind):
 @pytest.mark.parametrize('kind', ('name:de', 'fridge', 'a34', '.*', '\\'))
 def test_create_kind_filter_many_negative(kind):
     filt = SanitizerConfig({'filter-kind': ['.*fr', 'name', r'\d+']}
-    ).get_filter('filter-kind')
+                           ).get_filter('filter-kind')
 
     assert not filt(kind)
index fbfd72da514e974b2523c7fc869ed3625af44f7f..ec4869b3495c3f56127a8e22c6f1db3050ada38d 100644 (file)
@@ -2,7 +2,7 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 """
 Tests for the sanitizer that splits multivalue lists.
@@ -14,20 +14,19 @@ from nominatim_db.data.place_info import PlaceInfo
 
 from nominatim_db.errors import UsageError
 
+
 class TestSplitName:
 
     @pytest.fixture(autouse=True)
     def setup_country(self, def_config):
         self.config = def_config
 
-
     def run_sanitizer_on(self, **kwargs):
         place = PlaceInfo({'name': kwargs})
         name, _ = PlaceSanitizer([{'step': 'split-name-list'}], self.config).process_names(place)
 
         return sorted([(p.name, p.kind, p.suffix) for p in name])
 
-
     def sanitize_with_delimiter(self, delimiter, name):
         place = PlaceInfo({'name': {'name': name}})
         san = PlaceSanitizer([{'step': 'split-name-list', 'delimiters': delimiter}],
@@ -36,12 +35,10 @@ class TestSplitName:
 
         return sorted([p.name for p in name])
 
-
     def test_simple(self):
         assert self.run_sanitizer_on(name='ABC') == [('ABC', 'name', None)]
         assert self.run_sanitizer_on(name='') == [('', 'name', None)]
 
-
     def test_splits(self):
         assert self.run_sanitizer_on(name='A;B;C') == [('A', 'name', None),
                                                        ('B', 'name', None),
@@ -49,7 +46,6 @@ class TestSplitName:
         assert self.run_sanitizer_on(short_name=' House, boat ') == [('House', 'short_name', None),
                                                                      ('boat', 'short_name', None)]
 
-
     def test_empty_fields(self):
         assert self.run_sanitizer_on(name='A;;B') == [('A', 'name', None),
                                                       ('B', 'name', None)]
@@ -58,14 +54,12 @@ class TestSplitName:
         assert self.run_sanitizer_on(name=' ;B') == [('B', 'name', None)]
         assert self.run_sanitizer_on(name='B,') == [('B', 'name', None)]
 
-
     def test_custom_delimiters(self):
         assert self.sanitize_with_delimiter(':', '12:45,3') == ['12', '45,3']
         assert self.sanitize_with_delimiter('\\', 'a;\\b!#@ \\') == ['a;', 'b!#@']
         assert self.sanitize_with_delimiter('[]', 'foo[to]be') == ['be', 'foo', 'to']
         assert self.sanitize_with_delimiter(' ', 'morning  sun') == ['morning', 'sun']
 
-
     def test_empty_delimiter_set(self):
         with pytest.raises(UsageError):
             self.sanitize_with_delimiter('', 'abc')
index 6a4cffcf3039d564b431bc0128ddf6f61697d416..6e891f9eb0ef29f27b64ca512657e3baf5b46f5e 100644 (file)
@@ -2,7 +2,7 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 """
 Tests for the sanitizer that handles braced suffixes.
@@ -12,6 +12,7 @@ import pytest
 from nominatim_db.tokenizer.place_sanitizer import PlaceSanitizer
 from nominatim_db.data.place_info import PlaceInfo
 
+
 class TestStripBrace:
 
     @pytest.fixture(autouse=True)
@@ -24,23 +25,19 @@ class TestStripBrace:
 
         return sorted([(p.name, p.kind, p.suffix) for p in name])
 
-
     def test_no_braces(self):
         assert self.run_sanitizer_on(name='foo', ref='23') == [('23', 'ref', None),
                                                                ('foo', 'name', None)]
 
-
     def test_simple_braces(self):
-        assert self.run_sanitizer_on(name='Halle (Saale)', ref='3')\
-          == [('3', 'ref', None), ('Halle', 'name', None), ('Halle (Saale)', 'name', None)]
-        assert self.run_sanitizer_on(name='ack ( bar')\
-          == [('ack', 'name', None), ('ack ( bar', 'name', None)]
-
+        assert self.run_sanitizer_on(name='Halle (Saale)', ref='3') \
+            == [('3', 'ref', None), ('Halle', 'name', None), ('Halle (Saale)', 'name', None)]
+        assert self.run_sanitizer_on(name='ack ( bar') \
+            == [('ack', 'name', None), ('ack ( bar', 'name', None)]
 
     def test_only_braces(self):
         assert self.run_sanitizer_on(name='(maybe)') == [('(maybe)', 'name', None)]
 
-
     def test_double_braces(self):
         assert self.run_sanitizer_on(name='a((b))') == [('a', 'name', None),
                                                         ('a((b))', 'name', None)]
index 2022e41002e1b58ffd4d7b1f4ce1447ee33ab4dd..8f1d05401f2f7b1382c11606dd04047008c2b115 100644 (file)
@@ -2,7 +2,7 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 """
 Tests for the sanitizer that enables language-dependent analyzers.
@@ -13,13 +13,13 @@ from nominatim_db.data.place_info import PlaceInfo
 from nominatim_db.tokenizer.place_sanitizer import PlaceSanitizer
 from nominatim_db.data.country_info import setup_country_config
 
+
 class TestWithDefaults:
 
     @pytest.fixture(autouse=True)
     def setup_country(self, def_config):
         self.config = def_config
 
-
     def run_sanitizer_on(self, country, **kwargs):
         place = PlaceInfo({'name': {k.replace('_', ':'): v for k, v in kwargs.items()},
                            'country_code': country})
@@ -28,19 +28,16 @@ class TestWithDefaults:
 
         return sorted([(p.name, p.kind, p.suffix, p.attr) for p in name])
 
-
     def test_no_names(self):
         assert self.run_sanitizer_on('de') == []
 
-
     def test_simple(self):
-        res = self.run_sanitizer_on('fr', name='Foo',name_de='Zoo', ref_abc='M')
+        res = self.run_sanitizer_on('fr', name='Foo', name_de='Zoo', ref_abc='M')
 
         assert res == [('Foo', 'name', None, {}),
                        ('M', 'ref', 'abc', {'analyzer': 'abc'}),
                        ('Zoo', 'name', 'de', {'analyzer': 'de'})]
 
-
     @pytest.mark.parametrize('suffix', ['DE', 'asbc'])
     def test_illegal_suffix(self, suffix):
         assert self.run_sanitizer_on('fr', **{'name_' + suffix: 'Foo'}) \
@@ -53,7 +50,6 @@ class TestFilterKind:
     def setup_country(self, def_config):
         self.config = def_config
 
-
     def run_sanitizer_on(self, filt, **kwargs):
         place = PlaceInfo({'name': {k.replace('_', ':'): v for k, v in kwargs.items()},
                            'country_code': 'de'})
@@ -63,17 +59,15 @@ class TestFilterKind:
 
         return sorted([(p.name, p.kind, p.suffix, p.attr) for p in name])
 
-
     def test_single_exact_name(self):
         res = self.run_sanitizer_on(['name'], name_fr='A', ref_fr='12',
-                                              shortname_fr='C', name='D')
+                                    shortname_fr='C', name='D')
 
         assert res == [('12', 'ref',  'fr', {}),
                        ('A',  'name', 'fr', {'analyzer': 'fr'}),
                        ('C',  'shortname', 'fr', {}),
                        ('D',  'name', None, {})]
 
-
     def test_single_pattern(self):
         res = self.run_sanitizer_on(['.*name'],
                                     name_fr='A', ref_fr='12', namexx_fr='B',
@@ -85,7 +79,6 @@ class TestFilterKind:
                        ('C',  'shortname', 'fr', {'analyzer': 'fr'}),
                        ('D',  'name', None, {})]
 
-
     def test_multiple_patterns(self):
         res = self.run_sanitizer_on(['.*name', 'ref'],
                                     name_fr='A', ref_fr='12', oldref_fr='X',
@@ -106,7 +99,6 @@ class TestDefaultCountry:
         setup_country_config(def_config)
         self.config = def_config
 
-
     def run_sanitizer_append(self, mode,  country, **kwargs):
         place = PlaceInfo({'name': {k.replace('_', ':'): v for k, v in kwargs.items()},
                            'country_code': country})
@@ -122,7 +114,6 @@ class TestDefaultCountry:
 
         return sorted([(p.name, p.attr.get('analyzer', '')) for p in name])
 
-
     def run_sanitizer_replace(self, mode,  country, **kwargs):
         place = PlaceInfo({'name': {k.replace('_', ':'): v for k, v in kwargs.items()},
                            'country_code': country})
@@ -138,7 +129,6 @@ class TestDefaultCountry:
 
         return sorted([(p.name, p.attr.get('analyzer', '')) for p in name])
 
-
     def test_missing_country(self):
         place = PlaceInfo({'name': {'name': 'something'}})
         name, _ = PlaceSanitizer([{'step': 'tag-analyzer-by-language',
@@ -151,59 +141,50 @@ class TestDefaultCountry:
         assert name[0].suffix is None
         assert 'analyzer' not in name[0].attr
 
-
     def test_mono_unknown_country(self):
         expect = [('XX', '')]
 
         assert self.run_sanitizer_replace('mono', 'xx', name='XX') == expect
         assert self.run_sanitizer_append('mono', 'xx', name='XX') == expect
 
-
     def test_mono_monoling_replace(self):
         res = self.run_sanitizer_replace('mono', 'de', name='Foo')
 
         assert res == [('Foo', 'de')]
 
-
     def test_mono_monoling_append(self):
         res = self.run_sanitizer_append('mono', 'de', name='Foo')
 
         assert res == [('Foo', ''), ('Foo', 'de')]
 
-
     def test_mono_multiling(self):
         expect = [('XX', '')]
 
         assert self.run_sanitizer_replace('mono', 'ch', name='XX') == expect
         assert self.run_sanitizer_append('mono', 'ch', name='XX') == expect
 
-
     def test_all_unknown_country(self):
         expect = [('XX', '')]
 
         assert self.run_sanitizer_replace('all', 'xx', name='XX') == expect
         assert self.run_sanitizer_append('all', 'xx', name='XX') == expect
 
-
     def test_all_monoling_replace(self):
         res = self.run_sanitizer_replace('all', 'de', name='Foo')
 
         assert res == [('Foo', 'de')]
 
-
     def test_all_monoling_append(self):
         res = self.run_sanitizer_append('all', 'de', name='Foo')
 
         assert res == [('Foo', ''), ('Foo', 'de')]
 
-
     def test_all_multiling_append(self):
         res = self.run_sanitizer_append('all', 'ch', name='XX')
 
         assert res == [('XX', ''),
                        ('XX', 'de'), ('XX', 'fr'), ('XX', 'it'), ('XX', 'rm')]
 
-
     def test_all_multiling_replace(self):
         res = self.run_sanitizer_replace('all', 'ch', name='XX')
 
@@ -216,7 +197,6 @@ class TestCountryWithWhitelist:
     def setup_country(self, def_config):
         self.config = def_config
 
-
     def run_sanitizer_on(self, mode,  country, **kwargs):
         place = PlaceInfo({'name': {k.replace('_', ':'): v for k, v in kwargs.items()},
                            'country_code': country})
@@ -233,21 +213,17 @@ class TestCountryWithWhitelist:
 
         return sorted([(p.name, p.attr.get('analyzer', '')) for p in name])
 
-
     def test_mono_monoling(self):
         assert self.run_sanitizer_on('mono', 'de', name='Foo') == [('Foo', 'de')]
         assert self.run_sanitizer_on('mono', 'pt', name='Foo') == [('Foo', '')]
 
-
     def test_mono_multiling(self):
         assert self.run_sanitizer_on('mono', 'ca', name='Foo') == [('Foo', '')]
 
-
     def test_all_monoling(self):
         assert self.run_sanitizer_on('all', 'de', name='Foo') == [('Foo', 'de')]
         assert self.run_sanitizer_on('all', 'pt', name='Foo') == [('Foo', '')]
 
-
     def test_all_multiling(self):
         assert self.run_sanitizer_on('all', 'ca', name='Foo') == [('Foo', 'fr')]
         assert self.run_sanitizer_on('all', 'ch', name='Foo') \
@@ -260,7 +236,6 @@ class TestWhiteList:
     def setup_country(self, def_config):
         self.config = def_config
 
-
     def run_sanitizer_on(self, whitelist, **kwargs):
         place = PlaceInfo({'name': {k.replace('_', ':'): v for k, v in kwargs.items()}})
         name, _ = PlaceSanitizer([{'step': 'tag-analyzer-by-language',
@@ -275,14 +250,11 @@ class TestWhiteList:
 
         return sorted([(p.name, p.attr.get('analyzer', '')) for p in name])
 
-
     def test_in_whitelist(self):
         assert self.run_sanitizer_on(['de', 'xx'], ref_xx='123') == [('123', 'xx')]
 
-
     def test_not_in_whitelist(self):
         assert self.run_sanitizer_on(['de', 'xx'], ref_yy='123') == [('123', '')]
 
-
     def test_empty_whitelist(self):
         assert self.run_sanitizer_on([], ref_yy='123') == [('123', '')]
index 08edbb564462a1ea9556b14616586220b2f748f0..6db7a3c35329c3b241f9a5a85c2e392d3cdc07c0 100644 (file)
@@ -2,86 +2,86 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
-from typing import Mapping, Optional, List
 import pytest
 
 from nominatim_db.data.place_info import PlaceInfo
-from nominatim_db.data.place_name import PlaceName
 from nominatim_db.tokenizer.place_sanitizer import PlaceSanitizer
 
+
 class TestTagJapanese:
     @pytest.fixture(autouse=True)
     def setup_country(self, def_config):
         self.config = def_config
 
-    def run_sanitizer_on(self,type, **kwargs):
+    def run_sanitizer_on(self, type, **kwargs):
         place = PlaceInfo({
             'address': kwargs,
             'country_code': 'jp'
         })
         sanitizer_args = {'step': 'tag-japanese'}
         _, address = PlaceSanitizer([sanitizer_args], self.config).process_names(place)
-        tmp_list = [(p.name,p.kind) for p in address]
+        tmp_list = [(p.name, p.kind) for p in address]
         return sorted(tmp_list)
 
     def test_on_address(self):
         res = self.run_sanitizer_on('address', name='foo', ref='bar', ref_abc='baz')
-        assert res == [('bar','ref'),('baz','ref_abc'),('foo','name')]
+        assert res == [('bar', 'ref'), ('baz', 'ref_abc'), ('foo', 'name')]
 
     def test_housenumber(self):
         res = self.run_sanitizer_on('address', housenumber='2')
-        assert res == [('2','housenumber')]
+        assert res == [('2', 'housenumber')]
 
     def test_blocknumber(self):
         res = self.run_sanitizer_on('address', block_number='6')
-        assert res == [('6','housenumber')]
+        assert res == [('6', 'housenumber')]
 
     def test_neighbourhood(self):
         res = self.run_sanitizer_on('address', neighbourhood='8')
-        assert res == [('8','place')]
+        assert res == [('8', 'place')]
 
     def test_quarter(self):
         res = self.run_sanitizer_on('address', quarter='kase')
-        assert res==[('kase','place')]
+        assert res == [('kase', 'place')]
 
     def test_housenumber_blocknumber(self):
         res = self.run_sanitizer_on('address', housenumber='2', block_number='6')
-        assert res == [('6-2','housenumber')]
+        assert res == [('6-2', 'housenumber')]
 
     def test_quarter_neighbourhood(self):
         res = self.run_sanitizer_on('address', quarter='kase', neighbourhood='8')
-        assert res == [('kase8','place')]
+        assert res == [('kase8', 'place')]
 
     def test_blocknumber_housenumber_quarter(self):
         res = self.run_sanitizer_on('address', block_number='6', housenumber='2', quarter='kase')
-        assert res == [('6-2','housenumber'),('kase','place')]
+        assert res == [('6-2', 'housenumber'), ('kase', 'place')]
 
     def test_blocknumber_housenumber_quarter_neighbourhood(self):
         res = self.run_sanitizer_on('address', block_number='6', housenumber='2', neighbourhood='8')
-        assert res == [('6-2','housenumber'),('8','place')]
+        assert res == [('6-2', 'housenumber'), ('8', 'place')]
 
     def test_blocknumber_quarter_neighbourhood(self):
-        res = self.run_sanitizer_on('address',block_number='6', quarter='kase', neighbourhood='8')
-        assert res == [('6','housenumber'),('kase8','place')]
+        res = self.run_sanitizer_on('address', block_number='6', quarter='kase', neighbourhood='8')
+        assert res == [('6', 'housenumber'), ('kase8', 'place')]
 
     def test_blocknumber_quarter(self):
-        res = self.run_sanitizer_on('address',block_number='6', quarter='kase')
-        assert res == [('6','housenumber'),('kase','place')]
+        res = self.run_sanitizer_on('address', block_number='6', quarter='kase')
+        assert res == [('6', 'housenumber'), ('kase', 'place')]
 
     def test_blocknumber_neighbourhood(self):
-        res = self.run_sanitizer_on('address',block_number='6', neighbourhood='8')
-        assert res == [('6','housenumber'),('8','place')]
+        res = self.run_sanitizer_on('address', block_number='6', neighbourhood='8')
+        assert res == [('6', 'housenumber'), ('8', 'place')]
 
     def test_housenumber_quarter_neighbourhood(self):
-        res = self.run_sanitizer_on('address',housenumber='2', quarter='kase', neighbourhood='8')
-        assert res == [('2','housenumber'),('kase8','place')]
+        res = self.run_sanitizer_on('address', housenumber='2', quarter='kase', neighbourhood='8')
+        assert res == [('2', 'housenumber'), ('kase8', 'place')]
 
     def test_housenumber_quarter(self):
-        res = self.run_sanitizer_on('address',housenumber='2', quarter='kase')
-        assert res == [('2','housenumber'),('kase','place')]
+        res = self.run_sanitizer_on('address', housenumber='2', quarter='kase')
+        assert res == [('2', 'housenumber'), ('kase', 'place')]
 
     def test_housenumber_blocknumber_neighbourhood_quarter(self):
-        res = self.run_sanitizer_on('address', block_number='6', housenumber='2', quarter='kase', neighbourhood='8')
-        assert res == [('6-2','housenumber'),('kase8','place')]
+        res = self.run_sanitizer_on('address', block_number='6', housenumber='2',
+                                    quarter='kase', neighbourhood='8')
+        assert res == [('6-2', 'housenumber'), ('kase8', 'place')]
index 632dea88f831561fe711f26a9e535e27b6310c05..4f8d2cfecf69f2a74f67e3bb3205d59d8a2cce3d 100644 (file)
@@ -2,7 +2,7 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 """
 Tests for creating new tokenizers.
@@ -27,7 +27,6 @@ class TestFactory:
     def init_env(self, project_env, property_table, tokenizer_mock):
         self.config = project_env
 
-
     def test_setup_dummy_tokenizer(self, temp_db_conn):
         tokenizer = factory.create_tokenizer(self.config)
 
@@ -37,7 +36,6 @@ class TestFactory:
 
         assert properties.get_property(temp_db_conn, 'tokenizer') == 'dummy'
 
-
     def test_setup_tokenizer_dir_exists(self):
         (self.config.project_dir / 'tokenizer').mkdir()
 
@@ -46,14 +44,12 @@ class TestFactory:
         assert isinstance(tokenizer, DummyTokenizer)
         assert tokenizer.init_state == "new"
 
-
     def test_setup_tokenizer_dir_failure(self):
         (self.config.project_dir / 'tokenizer').write_text("foo")
 
         with pytest.raises(UsageError):
             factory.create_tokenizer(self.config)
 
-
     def test_load_tokenizer(self):
         factory.create_tokenizer(self.config)
 
@@ -62,7 +58,6 @@ class TestFactory:
         assert isinstance(tokenizer, DummyTokenizer)
         assert tokenizer.init_state == "loaded"
 
-
     def test_load_repopulate_tokenizer_dir(self):
         factory.create_tokenizer(self.config)
 
@@ -71,7 +66,6 @@ class TestFactory:
         factory.get_tokenizer_for_db(self.config)
         assert (self.config.project_dir / 'tokenizer').exists()
 
-
     def test_load_missing_property(self, temp_db_cursor):
         factory.create_tokenizer(self.config)
 
index 06a3cd6ce7b81a3697c3d2006089e0f79126ae35..ce00281cff7e09e850fb4d5ee957fb687f65d809 100644 (file)
@@ -2,7 +2,7 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 """
 Tests for ICU tokenizer.
@@ -20,6 +20,7 @@ from nominatim_db.data.place_info import PlaceInfo
 
 from mock_icu_word_table import MockIcuWordTable
 
+
 @pytest.fixture
 def word_table(temp_db_conn):
     return MockIcuWordTable(temp_db_conn)
@@ -89,6 +90,7 @@ def analyzer(tokenizer_factory, test_config, monkeypatch,
 
     return _mk_analyser
 
+
 @pytest.fixture
 def sql_functions(temp_db_conn, def_config, src_dir):
     orig_sql = def_config.lib_dir.sql
@@ -152,19 +154,19 @@ LANGUAGE plpgsql;
                               """)
 
 
-
 def test_init_new(tokenizer_factory, test_config, db_prop):
     tok = tokenizer_factory()
     tok.init_new_db(test_config)
 
-    assert db_prop(nominatim_db.tokenizer.icu_rule_loader.DBCFG_IMPORT_NORM_RULES) \
-            .startswith(':: lower ();')
+    prop = db_prop(nominatim_db.tokenizer.icu_rule_loader.DBCFG_IMPORT_NORM_RULES)
+
+    assert prop.startswith(':: lower ();')
 
 
 def test_init_word_table(tokenizer_factory, test_config, place_row, temp_db_cursor):
-    place_row(names={'name' : 'Test Area', 'ref' : '52'})
-    place_row(names={'name' : 'No Area'})
-    place_row(names={'name' : 'Holzstrasse'})
+    place_row(names={'name': 'Test Area', 'ref': '52'})
+    place_row(names={'name': 'No Area'})
+    place_row(names={'name': 'Holzstrasse'})
 
     tok = tokenizer_factory()
     tok.init_new_db(test_config)
@@ -259,12 +261,10 @@ class TestPostcodes:
             self.analyzer = anl
             yield anl
 
-
     def process_postcode(self, cc, postcode):
         return self.analyzer.process_place(PlaceInfo({'country_code': cc,
                                                       'address': {'postcode': postcode}}))
 
-
     def test_update_postcodes_deleted(self, word_table):
         word_table.add_postcode(' 1234', '1234')
         word_table.add_postcode(' 5678', '5678')
@@ -273,20 +273,17 @@ class TestPostcodes:
 
         assert word_table.count() == 0
 
-
     def test_process_place_postcode_simple(self, word_table):
         info = self.process_postcode('de', '12345')
 
         assert info['postcode'] == '12345'
 
-
     def test_process_place_postcode_with_space(self, word_table):
         info = self.process_postcode('in', '123 567')
 
         assert info['postcode'] == '123567'
 
 
-
 def test_update_special_phrase_empty_table(analyzer, word_table):
     with analyzer() as anl:
         anl.update_special_phrases([
@@ -296,9 +293,9 @@ def test_update_special_phrase_empty_table(analyzer, word_table):
         ], True)
 
     assert word_table.get_special() \
-               == {('KÖNIG BEI', 'König bei', 'amenity', 'royal', 'near'),
-                   ('KÖNIGE', 'Könige', 'amenity', 'royal', None),
-                   ('STREET', 'street', 'highway', 'primary', 'in')}
+        == {('KÖNIG BEI', 'König bei', 'amenity', 'royal', 'near'),
+            ('KÖNIGE', 'Könige', 'amenity', 'royal', None),
+            ('STREET', 'street', 'highway', 'primary', 'in')}
 
 
 def test_update_special_phrase_delete_all(analyzer, word_table):
@@ -339,9 +336,9 @@ def test_update_special_phrase_modify(analyzer, word_table):
         ], True)
 
     assert word_table.get_special() \
-               == {('PRISON', 'prison', 'amenity', 'prison', 'in'),
-                   ('BAR', 'bar', 'highway', 'road', None),
-                   ('GARDEN', 'garden', 'leisure', 'garden', 'near')}
+        == {('PRISON', 'prison', 'amenity', 'prison', 'in'),
+            ('BAR', 'bar', 'highway', 'road', None),
+            ('GARDEN', 'garden', 'leisure', 'garden', 'near')}
 
 
 def test_add_country_names_new(analyzer, word_table):
@@ -370,7 +367,6 @@ class TestPlaceNames:
             self.analyzer = anl
             yield anl
 
-
     def expect_name_terms(self, info, *expected_terms):
         tokens = self.analyzer.get_word_token_info(expected_terms)
         for token in tokens:
@@ -378,34 +374,29 @@ class TestPlaceNames:
 
         assert eval(info['names']) == set((t[2] for t in tokens))
 
-
     def process_named_place(self, names):
         return self.analyzer.process_place(PlaceInfo({'name': names}))
 
-
     def test_simple_names(self):
         info = self.process_named_place({'name': 'Soft bAr', 'ref': '34'})
 
         self.expect_name_terms(info, '#Soft bAr', '#34', 'Soft', 'bAr', '34')
 
-
-    @pytest.mark.parametrize('sep', [',' , ';'])
+    @pytest.mark.parametrize('sep', [',', ';'])
     def test_names_with_separator(self, sep):
         info = self.process_named_place({'name': sep.join(('New York', 'Big Apple'))})
 
         self.expect_name_terms(info, '#New York', '#Big Apple',
                                      'new', 'york', 'big', 'apple')
 
-
     def test_full_names_with_bracket(self):
         info = self.process_named_place({'name': 'Houseboat (left)'})
 
         self.expect_name_terms(info, '#Houseboat (left)', '#Houseboat',
                                      'houseboat', 'left')
 
-
     def test_country_name(self, word_table):
-        place = PlaceInfo({'name' : {'name': 'Norge'},
+        place = PlaceInfo({'name': {'name': 'Norge'},
                            'country_code': 'no',
                            'rank_address': 4,
                            'class': 'boundary',
@@ -427,18 +418,15 @@ class TestPlaceAddress:
             self.analyzer = anl
             yield anl
 
-
     @pytest.fixture
     def getorcreate_hnr_id(self, temp_db_cursor):
         temp_db_cursor.execute("""CREATE OR REPLACE FUNCTION getorcreate_hnr_id(lookup_term TEXT)
                                   RETURNS INTEGER AS $$
                                     SELECT -nextval('seq_word')::INTEGER; $$ LANGUAGE SQL""")
 
-
     def process_address(self, **kwargs):
         return self.analyzer.process_place(PlaceInfo({'address': kwargs}))
 
-
     def name_token_set(self, *expected_terms):
         tokens = self.analyzer.get_word_token_info(expected_terms)
         for token in tokens:
@@ -446,14 +434,12 @@ class TestPlaceAddress:
 
         return set((t[2] for t in tokens))
 
-
     @pytest.mark.parametrize('pcode', ['12345', 'AB 123', '34-345'])
     def test_process_place_postcode(self, word_table, pcode):
         info = self.process_address(postcode=pcode)
 
         assert info['postcode'] == pcode
 
-
     @pytest.mark.parametrize('hnr', ['123a', '1', '101'])
     def test_process_place_housenumbers_simple(self, hnr, getorcreate_hnr_id):
         info = self.process_address(housenumber=hnr)
@@ -461,7 +447,6 @@ class TestPlaceAddress:
         assert info['hnr'] == hnr.upper()
         assert info['hnr_tokens'] == "{-1}"
 
-
     def test_process_place_housenumbers_duplicates(self, getorcreate_hnr_id):
         info = self.process_address(housenumber='134',
                                     conscriptionnumber='134',
@@ -470,7 +455,6 @@ class TestPlaceAddress:
         assert set(info['hnr'].split(';')) == set(('134', '99A'))
         assert info['hnr_tokens'] == "{-1,-2}"
 
-
     def test_process_place_housenumbers_cached(self, getorcreate_hnr_id):
         info = self.process_address(housenumber="45")
         assert info['hnr_tokens'] == "{-1}"
@@ -484,37 +468,32 @@ class TestPlaceAddress:
         info = self.process_address(housenumber="41")
         assert eval(info['hnr_tokens']) == {-3}
 
-
     def test_process_place_street(self):
-        self.analyzer.process_place(PlaceInfo({'name': {'name' : 'Grand Road'}}))
+        self.analyzer.process_place(PlaceInfo({'name': {'name': 'Grand Road'}}))
         info = self.process_address(street='Grand Road')
 
         assert eval(info['street']) == self.name_token_set('#Grand Road')
 
-
     def test_process_place_nonexisting_street(self):
         info = self.process_address(street='Grand Road')
 
         assert info['street'] == '{}'
 
-
     def test_process_place_multiple_street_tags(self):
-        self.analyzer.process_place(PlaceInfo({'name': {'name' : 'Grand Road',
+        self.analyzer.process_place(PlaceInfo({'name': {'name': 'Grand Road',
                                                         'ref': '05989'}}))
         info = self.process_address(**{'street': 'Grand Road',
-                                      'street:sym_ul': '05989'})
+                                       'street:sym_ul': '05989'})
 
         assert eval(info['street']) == self.name_token_set('#Grand Road', '#05989')
 
-
     def test_process_place_street_empty(self):
         info = self.process_address(street='🜵')
 
         assert info['street'] == '{}'
 
-
     def test_process_place_street_from_cache(self):
-        self.analyzer.process_place(PlaceInfo({'name': {'name' : 'Grand Road'}}))
+        self.analyzer.process_place(PlaceInfo({'name': {'name': 'Grand Road'}}))
         self.process_address(street='Grand Road')
 
         # request address again
@@ -522,25 +501,21 @@ class TestPlaceAddress:
 
         assert eval(info['street']) == self.name_token_set('#Grand Road')
 
-
     def test_process_place_place(self):
         info = self.process_address(place='Honu Lulu')
 
         assert eval(info['place']) == self.name_token_set('HONU', 'LULU', '#HONU LULU')
 
-
     def test_process_place_place_extra(self):
         info = self.process_address(**{'place:en': 'Honu Lulu'})
 
         assert 'place' not in info
 
-
     def test_process_place_place_empty(self):
         info = self.process_address(place='🜵')
 
         assert 'place' not in info
 
-
     def test_process_place_address_terms(self):
         info = self.process_address(country='de', city='Zwickau', state='Sachsen',
                                     suburb='Zwickau', street='Hauptstr',
@@ -549,19 +524,17 @@ class TestPlaceAddress:
         city = self.name_token_set('ZWICKAU', '#ZWICKAU')
         state = self.name_token_set('SACHSEN', '#SACHSEN')
 
-        result = {k: eval(v) for k,v in info['addr'].items()}
+        result = {k: eval(v) for k, v in info['addr'].items()}
 
         assert result == {'city': city, 'suburb': city, 'state': state}
 
-
     def test_process_place_multiple_address_terms(self):
         info = self.process_address(**{'city': 'Bruxelles', 'city:de': 'Brüssel'})
 
-        result = {k: eval(v) for k,v in info['addr'].items()}
+        result = {k: eval(v) for k, v in info['addr'].items()}
 
         assert result == {'city': self.name_token_set('Bruxelles', '#Bruxelles')}
 
-
     def test_process_place_address_terms_empty(self):
         info = self.process_address(country='de', city=' ', street='Hauptstr',
                                     full='right behind the church')
@@ -575,22 +548,21 @@ class TestPlaceHousenumberWithAnalyser:
     def setup(self, analyzer, sql_functions):
         hnr = {'step': 'clean-housenumbers',
                'filter-kind': ['housenumber', 'conscriptionnumber', 'streetnumber']}
-        with analyzer(trans=(":: upper()", "'🜵' > ' '"), sanitizers=[hnr], with_housenumber=True) as anl:
+        with analyzer(trans=(":: upper()", "'🜵' > ' '"), sanitizers=[hnr],
+                      with_housenumber=True) as anl:
             self.analyzer = anl
             yield anl
 
-
     @pytest.fixture
     def getorcreate_hnr_id(self, temp_db_cursor):
-        temp_db_cursor.execute("""CREATE OR REPLACE FUNCTION create_analyzed_hnr_id(norm_term TEXT, lookup_terms TEXT[])
-                                  RETURNS INTEGER AS $$
-                                    SELECT -nextval('seq_word')::INTEGER; $$ LANGUAGE SQL""")
-
+        temp_db_cursor.execute("""
+            CREATE OR REPLACE FUNCTION create_analyzed_hnr_id(norm_term TEXT, lookup_terms TEXT[])
+            RETURNS INTEGER AS $$
+                SELECT -nextval('seq_word')::INTEGER; $$ LANGUAGE SQL""")
 
     def process_address(self, **kwargs):
         return self.analyzer.process_place(PlaceInfo({'address': kwargs}))
 
-
     def name_token_set(self, *expected_terms):
         tokens = self.analyzer.get_word_token_info(expected_terms)
         for token in tokens:
@@ -598,7 +570,6 @@ class TestPlaceHousenumberWithAnalyser:
 
         return set((t[2] for t in tokens))
 
-
     @pytest.mark.parametrize('hnr', ['123 a', '1', '101'])
     def test_process_place_housenumbers_simple(self, hnr, getorcreate_hnr_id):
         info = self.process_address(housenumber=hnr)
@@ -606,7 +577,6 @@ class TestPlaceHousenumberWithAnalyser:
         assert info['hnr'] == hnr.upper()
         assert info['hnr_tokens'] == "{-1}"
 
-
     def test_process_place_housenumbers_duplicates(self, getorcreate_hnr_id):
         info = self.process_address(housenumber='134',
                                     conscriptionnumber='134',
@@ -615,7 +585,6 @@ class TestPlaceHousenumberWithAnalyser:
         assert set(info['hnr'].split(';')) == set(('134', '99 A'))
         assert info['hnr_tokens'] == "{-1,-2}"
 
-
     def test_process_place_housenumbers_cached(self, getorcreate_hnr_id):
         info = self.process_address(housenumber="45")
         assert info['hnr_tokens'] == "{-1}"
@@ -637,7 +606,6 @@ class TestUpdateWordTokens:
         table_factory('search_name', 'place_id BIGINT, name_vector INT[]')
         self.tok = tokenizer_factory()
 
-
     @pytest.fixture
     def search_entry(self, temp_db_cursor):
         place_id = itertools.count(1000)
@@ -648,7 +616,6 @@ class TestUpdateWordTokens:
 
         return _insert
 
-
     @pytest.fixture(params=['simple', 'analyzed'])
     def add_housenumber(self, request, word_table):
         if request.param == 'simple':
@@ -660,7 +627,6 @@ class TestUpdateWordTokens:
 
         return _make
 
-
     @pytest.mark.parametrize('hnr', ('1a', '1234567', '34 5'))
     def test_remove_unused_housenumbers(self, add_housenumber, word_table, hnr):
         word_table.add_housenumber(1000, hnr)
@@ -669,7 +635,6 @@ class TestUpdateWordTokens:
         self.tok.update_word_tokens()
         assert word_table.count_housenumbers() == 0
 
-
     def test_keep_unused_numeral_housenumbers(self, add_housenumber, word_table):
         add_housenumber(1000, '5432')
 
@@ -677,8 +642,8 @@ class TestUpdateWordTokens:
         self.tok.update_word_tokens()
         assert word_table.count_housenumbers() == 1
 
-
-    def test_keep_housenumbers_from_search_name_table(self, add_housenumber, word_table, search_entry):
+    def test_keep_housenumbers_from_search_name_table(self, add_housenumber,
+                                                      word_table, search_entry):
         add_housenumber(9999, '5432a')
         add_housenumber(9991, '9 a')
         search_entry(123, 9999, 34)
@@ -687,8 +652,8 @@ class TestUpdateWordTokens:
         self.tok.update_word_tokens()
         assert word_table.count_housenumbers() == 1
 
-
-    def test_keep_housenumbers_from_placex_table(self, add_housenumber, word_table, placex_table):
+    def test_keep_housenumbers_from_placex_table(self, add_housenumber, word_table,
+                                                 placex_table):
         add_housenumber(9999, '5432a')
         add_housenumber(9990, '34z')
         placex_table.add(housenumber='34z')
@@ -698,8 +663,8 @@ class TestUpdateWordTokens:
         self.tok.update_word_tokens()
         assert word_table.count_housenumbers() == 1
 
-
-    def test_keep_housenumbers_from_placex_table_hnr_list(self, add_housenumber, word_table, placex_table):
+    def test_keep_housenumbers_from_placex_table_hnr_list(self, add_housenumber,
+                                                          word_table, placex_table):
         add_housenumber(9991, '9 b')
         add_housenumber(9990, '34z')
         placex_table.add(housenumber='9 a;9 b;9 c')
index a3fae75815d4a1d0dad629b00a547c7d77efc1bb..f26b84c26fbac32ccd02b491b03c6c1e2a86a865 100644 (file)
@@ -2,7 +2,7 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 """
 Tests for converting a config file to ICU rules.
@@ -19,17 +19,16 @@ from icu import Transliterator
 
 CONFIG_SECTIONS = ('normalization', 'transliteration', 'token-analysis')
 
+
 class TestIcuRuleLoader:
 
     @pytest.fixture(autouse=True)
     def init_env(self, project_env):
         self.project_env = project_env
 
-
     def write_config(self, content):
         (self.project_env.project_dir / 'icu_tokenizer.yaml').write_text(dedent(content))
 
-
     def config_rules(self, *variants):
         content = dedent("""\
         normalization:
@@ -49,14 +48,12 @@ class TestIcuRuleLoader:
         content += '\n'.join(("             - " + s for s in variants)) + '\n'
         self.write_config(content)
 
-
     def get_replacements(self, *variants):
         self.config_rules(*variants)
         loader = ICURuleLoader(self.project_env)
         rules = loader.analysis[None].config['replacements']
 
-        return sorted((k, sorted(v)) for k,v in rules)
-
+        return sorted((k, sorted(v)) for k, v in rules)
 
     def test_empty_rule_set(self):
         self.write_config("""\
@@ -72,16 +69,14 @@ class TestIcuRuleLoader:
         assert rules.get_normalization_rules() == ''
         assert rules.get_transliteration_rules() == ''
 
-
     @pytest.mark.parametrize("section", CONFIG_SECTIONS)
     def test_missing_section(self, section):
-        rule_cfg = { s: [] for s in CONFIG_SECTIONS if s != section}
+        rule_cfg = {s: [] for s in CONFIG_SECTIONS if s != section}
         self.write_config(yaml.dump(rule_cfg))
 
         with pytest.raises(UsageError):
             ICURuleLoader(self.project_env)
 
-
     def test_get_search_rules(self):
         self.config_rules()
         loader = ICURuleLoader(self.project_env)
@@ -97,7 +92,6 @@ class TestIcuRuleLoader:
         assert trans.transliterate(" Αθήνα ") == " athēna "
         assert trans.transliterate(" проспект ") == " prospekt "
 
-
     def test_get_normalization_rules(self):
         self.config_rules()
         loader = ICURuleLoader(self.project_env)
@@ -106,7 +100,6 @@ class TestIcuRuleLoader:
 
         assert trans.transliterate(" проспект-Prospekt ") == " проспект prospekt "
 
-
     def test_get_transliteration_rules(self):
         self.config_rules()
         loader = ICURuleLoader(self.project_env)
@@ -115,7 +108,6 @@ class TestIcuRuleLoader:
 
         assert trans.transliterate(" проспект-Prospekt ") == " prospekt Prospekt "
 
-
     def test_transliteration_rules_from_file(self):
         self.write_config("""\
             normalization:
@@ -135,7 +127,6 @@ class TestIcuRuleLoader:
 
         assert trans.transliterate(" axxt ") == " byt "
 
-
     def test_search_rules(self):
         self.config_rules('~street => s,st', 'master => mstr')
         proc = ICURuleLoader(self.project_env).make_token_analysis()
@@ -144,7 +135,6 @@ class TestIcuRuleLoader:
         assert proc.search.transliterate('Earnes St').strip() == 'earnes st'
         assert proc.search.transliterate('Nostreet').strip() == 'nostreet'
 
-
     @pytest.mark.parametrize("variant", ['foo > bar', 'foo -> bar -> bar',
                                          '~foo~ -> bar', 'fo~ o -> bar'])
     def test_invalid_variant_description(self, variant):
@@ -157,25 +147,21 @@ class TestIcuRuleLoader:
 
         assert repl == [(' foo ', [' bar', ' foo'])]
 
-
     def test_replace_full(self):
         repl = self.get_replacements("foo => bar")
 
         assert repl == [(' foo ', [' bar'])]
 
-
     def test_add_suffix_no_decompose(self):
         repl = self.get_replacements("~berg |-> bg")
 
         assert repl == [(' berg ', [' berg', ' bg']),
                         ('berg ', ['berg', 'bg'])]
 
-
     def test_replace_suffix_no_decompose(self):
         repl = self.get_replacements("~berg |=> bg")
 
-        assert repl == [(' berg ', [' bg']),('berg ', ['bg'])]
-
+        assert repl == [(' berg ', [' bg']), ('berg ', ['bg'])]
 
     def test_add_suffix_decompose(self):
         repl = self.get_replacements("~berg -> bg")
@@ -183,26 +169,22 @@ class TestIcuRuleLoader:
         assert repl == [(' berg ', [' berg', ' bg', 'berg', 'bg']),
                         ('berg ', [' berg', ' bg', 'berg', 'bg'])]
 
-
     def test_replace_suffix_decompose(self):
         repl = self.get_replacements("~berg => bg")
 
         assert repl == [(' berg ', [' bg', 'bg']),
                         ('berg ', [' bg', 'bg'])]
 
-
     def test_add_prefix_no_compose(self):
         repl = self.get_replacements("hinter~ |-> hnt")
 
         assert repl == [(' hinter', [' hinter', ' hnt']),
                         (' hinter ', [' hinter', ' hnt'])]
 
-
     def test_replace_prefix_no_compose(self):
         repl = self.get_replacements("hinter~ |=> hnt")
 
-        assert repl ==  [(' hinter', [' hnt']), (' hinter ', [' hnt'])]
-
+        assert repl == [(' hinter', [' hnt']), (' hinter ', [' hnt'])]
 
     def test_add_prefix_compose(self):
         repl = self.get_replacements("hinter~-> h")
@@ -210,45 +192,38 @@ class TestIcuRuleLoader:
         assert repl == [(' hinter', [' h', ' h ', ' hinter', ' hinter ']),
                         (' hinter ', [' h', ' h', ' hinter', ' hinter'])]
 
-
     def test_replace_prefix_compose(self):
         repl = self.get_replacements("hinter~=> h")
 
         assert repl == [(' hinter', [' h', ' h ']),
                         (' hinter ', [' h', ' h'])]
 
-
     def test_add_beginning_only(self):
         repl = self.get_replacements("^Premier -> Pr")
 
         assert repl == [('^ premier ', ['^ pr', '^ premier'])]
 
-
     def test_replace_beginning_only(self):
         repl = self.get_replacements("^Premier => Pr")
 
         assert repl == [('^ premier ', ['^ pr'])]
 
-
     def test_add_final_only(self):
         repl = self.get_replacements("road$ -> rd")
 
         assert repl == [(' road ^', [' rd ^', ' road ^'])]
 
-
     def test_replace_final_only(self):
         repl = self.get_replacements("road$ => rd")
 
         assert repl == [(' road ^', [' rd ^'])]
 
-
     def test_decompose_only(self):
         repl = self.get_replacements("~foo -> foo")
 
         assert repl == [(' foo ', [' foo', 'foo']),
                         ('foo ', [' foo', 'foo'])]
 
-
     def test_add_suffix_decompose_end_only(self):
         repl = self.get_replacements("~berg |-> bg", "~berg$ -> bg")
 
@@ -257,7 +232,6 @@ class TestIcuRuleLoader:
                         ('berg ', ['berg', 'bg']),
                         ('berg ^', [' berg ^', ' bg ^', 'berg ^', 'bg ^'])]
 
-
     def test_replace_suffix_decompose_end_only(self):
         repl = self.get_replacements("~berg |=> bg", "~berg$ => bg")
 
@@ -266,7 +240,6 @@ class TestIcuRuleLoader:
                         ('berg ', ['bg']),
                         ('berg ^', [' bg ^', 'bg ^'])]
 
-
     def test_add_multiple_suffix(self):
         repl = self.get_replacements("~berg,~burg -> bg")
 
index 25844459f907f2801432e8eec1e0111fb676d894..fcf02bd3fe6fda4d584e32b0d15a78dea8097f05 100644 (file)
@@ -2,7 +2,7 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 """
 Tests for execution of the sanitztion step.
@@ -50,13 +50,13 @@ def test_placeinfo_has_attr():
 def test_sanitizer_default(def_config):
     san = sanitizer.PlaceSanitizer([{'step': 'split-name-list'}], def_config)
 
-    name, address =  san.process_names(PlaceInfo({'name': {'name:de:de': '1;2;3'},
-                                                  'address': {'street': 'Bald'}}))
+    name, address = san.process_names(PlaceInfo({'name': {'name:de:de': '1;2;3'},
+                                                 'address': {'street': 'Bald'}}))
 
     assert len(name) == 3
     assert all(isinstance(n, sanitizer.PlaceName) for n in name)
-    assert all(n.kind == 'name'  for n in name)
-    assert all(n.suffix == 'de:de'  for n in name)
+    assert all(n.kind == 'name' for n in name)
+    assert all(n.suffix == 'de:de' for n in name)
 
     assert len(address) == 1
     assert all(isinstance(n, sanitizer.PlaceName) for n in address)
@@ -66,7 +66,7 @@ def test_sanitizer_default(def_config):
 def test_sanitizer_empty_list(def_config, rules):
     san = sanitizer.PlaceSanitizer(rules, def_config)
 
-    name, address =  san.process_names(PlaceInfo({'name': {'name:de:de': '1;2;3'}}))
+    name, address = san.process_names(PlaceInfo({'name': {'name:de:de': '1;2;3'}}))
 
     assert len(name) == 1
     assert all(isinstance(n, sanitizer.PlaceName) for n in name)
@@ -74,4 +74,4 @@ def test_sanitizer_empty_list(def_config, rules):
 
 def test_sanitizer_missing_step_definition(def_config):
     with pytest.raises(UsageError):
-        san = sanitizer.PlaceSanitizer([{'id': 'split-name-list'}], def_config)
+        sanitizer.PlaceSanitizer([{'id': 'split-name-list'}], def_config)
index 870c8a5d76f81346d291a2cd348f4431e65fbb6f..1eb15a50d98c0d86f9e1171ca02edad761d4b7f2 100644 (file)
@@ -2,7 +2,7 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 """
 Tests for special postcode analysis and variant generation.
@@ -13,7 +13,6 @@ from icu import Transliterator
 
 import nominatim_db.tokenizer.token_analysis.postcodes as module
 from nominatim_db.data.place_name import PlaceName
-from nominatim_db.errors import UsageError
 
 DEFAULT_NORMALIZATION = """ :: NFD ();
                             '🜳' > ' ';
@@ -27,9 +26,10 @@ DEFAULT_TRANSLITERATION = """ ::  Latin ();
                               '🜵' > ' ';
                           """
 
+
 @pytest.fixture
 def analyser():
-    rules = { 'analyzer': 'postcodes'}
+    rules = {'analyzer': 'postcodes'}
     config = module.configure(rules, DEFAULT_NORMALIZATION)
 
     trans = Transliterator.createFromRules("test_trans", DEFAULT_TRANSLITERATION)
index 191f551f86debcef7d011a102b5adf60803030f6..02870f2445e7b798a7bc29ffa5aa794d2dd1a9a1 100644 (file)
@@ -2,7 +2,7 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 """
 Tests for import name normalisation and variant generation.
@@ -26,8 +26,9 @@ DEFAULT_TRANSLITERATION = """ ::  Latin ();
                               '🜵' > ' ';
                           """
 
+
 def make_analyser(*variants, variant_only=False):
-    rules = { 'analyzer': 'generic', 'variants': [{'words': variants}]}
+    rules = {'analyzer': 'generic', 'variants': [{'words': variants}]}
     if variant_only:
         rules['mode'] = 'variant-only'
     trans = Transliterator.createFromRules("test_trans", DEFAULT_TRANSLITERATION)
@@ -43,7 +44,7 @@ def get_normalized_variants(proc, name):
 
 
 def test_no_variants():
-    rules = { 'analyzer': 'generic' }
+    rules = {'analyzer': 'generic'}
     trans = Transliterator.createFromRules("test_trans", DEFAULT_TRANSLITERATION)
     norm = Transliterator.createFromRules("test_norm", DEFAULT_NORMALIZATION)
     config = module.configure(rules, norm, trans)
@@ -62,35 +63,36 @@ def test_variants_empty():
 
 
 VARIANT_TESTS = [
-(('~strasse,~straße -> str', '~weg => weg'), "hallo", {'hallo'}),
-(('weg => wg',), "holzweg", {'holzweg'}),
-(('weg -> wg',), "holzweg", {'holzweg'}),
-(('~weg => weg',), "holzweg", {'holz weg', 'holzweg'}),
-(('~weg -> weg',), "holzweg",  {'holz weg', 'holzweg'}),
-(('~weg => w',), "holzweg", {'holz w', 'holzw'}),
-(('~weg -> w',), "holzweg",  {'holz weg', 'holzweg', 'holz w', 'holzw'}),
-(('~weg => weg',), "Meier Weg", {'meier weg', 'meierweg'}),
-(('~weg -> weg',), "Meier Weg", {'meier weg', 'meierweg'}),
-(('~weg => w',), "Meier Weg", {'meier w', 'meierw'}),
-(('~weg -> w',), "Meier Weg", {'meier weg', 'meierweg', 'meier w', 'meierw'}),
-(('weg => wg',), "Meier Weg", {'meier wg'}),
-(('weg -> wg',), "Meier Weg", {'meier weg', 'meier wg'}),
-(('~strasse,~straße -> str', '~weg => weg'), "Bauwegstraße",
+    (('~strasse,~straße -> str', '~weg => weg'), "hallo", {'hallo'}),
+    (('weg => wg',), "holzweg", {'holzweg'}),
+    (('weg -> wg',), "holzweg", {'holzweg'}),
+    (('~weg => weg',), "holzweg", {'holz weg', 'holzweg'}),
+    (('~weg -> weg',), "holzweg",  {'holz weg', 'holzweg'}),
+    (('~weg => w',), "holzweg", {'holz w', 'holzw'}),
+    (('~weg -> w',), "holzweg",  {'holz weg', 'holzweg', 'holz w', 'holzw'}),
+    (('~weg => weg',), "Meier Weg", {'meier weg', 'meierweg'}),
+    (('~weg -> weg',), "Meier Weg", {'meier weg', 'meierweg'}),
+    (('~weg => w',), "Meier Weg", {'meier w', 'meierw'}),
+    (('~weg -> w',), "Meier Weg", {'meier weg', 'meierweg', 'meier w', 'meierw'}),
+    (('weg => wg',), "Meier Weg", {'meier wg'}),
+    (('weg -> wg',), "Meier Weg", {'meier weg', 'meier wg'}),
+    (('~strasse,~straße -> str', '~weg => weg'), "Bauwegstraße",
      {'bauweg straße', 'bauweg str', 'bauwegstraße', 'bauwegstr'}),
-(('am => a', 'bach => b'), "am bach", {'a b'}),
-(('am => a', '~bach => b'), "am bach", {'a b'}),
-(('am -> a', '~bach -> b'), "am bach", {'am bach', 'a bach', 'am b', 'a b'}),
-(('am -> a', '~bach -> b'), "ambach", {'ambach', 'am bach', 'amb', 'am b'}),
-(('saint -> s,st', 'street -> st'), "Saint Johns Street",
+    (('am => a', 'bach => b'), "am bach", {'a b'}),
+    (('am => a', '~bach => b'), "am bach", {'a b'}),
+    (('am -> a', '~bach -> b'), "am bach", {'am bach', 'a bach', 'am b', 'a b'}),
+    (('am -> a', '~bach -> b'), "ambach", {'ambach', 'am bach', 'amb', 'am b'}),
+    (('saint -> s,st', 'street -> st'), "Saint Johns Street",
      {'saint johns street', 's johns street', 'st johns street',
       'saint johns st', 's johns st', 'st johns st'}),
-(('river$ -> r',), "River Bend Road", {'river bend road'}),
-(('river$ -> r',), "Bent River", {'bent river', 'bent r'}),
-(('^north => n',), "North 2nd Street", {'n 2nd street'}),
-(('^north => n',), "Airport North", {'airport north'}),
-(('am -> a',), "am am am am am am am am", {'am am am am am am am am'}),
-(('am => a',), "am am am am am am am am", {'a a a a a a a a'})
-]
+    (('river$ -> r',), "River Bend Road", {'river bend road'}),
+    (('river$ -> r',), "Bent River", {'bent river', 'bent r'}),
+    (('^north => n',), "North 2nd Street", {'n 2nd street'}),
+    (('^north => n',), "Airport North", {'airport north'}),
+    (('am -> a',), "am am am am am am am am", {'am am am am am am am am'}),
+    (('am => a',), "am am am am am am am am", {'a a a a a a a a'})
+    ]
+
 
 @pytest.mark.parametrize("rules,name,variants", VARIANT_TESTS)
 def test_variants(rules, name, variants):
@@ -103,10 +105,11 @@ def test_variants(rules, name, variants):
 
 
 VARIANT_ONLY_TESTS = [
-(('weg => wg',), "hallo", set()),
-(('weg => wg',), "Meier Weg", {'meier wg'}),
-(('weg -> wg',), "Meier Weg", {'meier wg'}),
-]
+    (('weg => wg',), "hallo", set()),
+    (('weg => wg',), "Meier Weg", {'meier wg'}),
+    (('weg -> wg',), "Meier Weg", {'meier wg'}),
+    ]
+
 
 @pytest.mark.parametrize("rules,name,variants", VARIANT_ONLY_TESTS)
 def test_variants_only(rules, name, variants):
@@ -122,17 +125,15 @@ class TestGetReplacements:
 
     @staticmethod
     def configure_rules(*variants):
-        rules = { 'analyzer': 'generic', 'variants': [{'words': variants}]}
+        rules = {'analyzer': 'generic', 'variants': [{'words': variants}]}
         trans = Transliterator.createFromRules("test_trans", DEFAULT_TRANSLITERATION)
         norm = Transliterator.createFromRules("test_norm", DEFAULT_NORMALIZATION)
         return module.configure(rules, norm, trans)
 
-
     def get_replacements(self, *variants):
         config = self.configure_rules(*variants)
 
-        return sorted((k, sorted(v)) for k,v in config['replacements'])
-
+        return sorted((k, sorted(v)) for k, v in config['replacements'])
 
     @pytest.mark.parametrize("variant", ['foo > bar', 'foo -> bar -> bar',
                                          '~foo~ -> bar', 'fo~ o -> bar'])
@@ -140,38 +141,32 @@ class TestGetReplacements:
         with pytest.raises(UsageError):
             self.configure_rules(variant)
 
-
     @pytest.mark.parametrize("rule", ["!!! -> bar", "bar => !!!"])
     def test_ignore_unnormalizable_terms(self, rule):
         repl = self.get_replacements(rule)
 
         assert repl == []
 
-
     def test_add_full(self):
         repl = self.get_replacements("foo -> bar")
 
         assert repl == [(' foo ', [' bar', ' foo'])]
 
-
     def test_replace_full(self):
         repl = self.get_replacements("foo => bar")
 
         assert repl == [(' foo ', [' bar'])]
 
-
     def test_add_suffix_no_decompose(self):
         repl = self.get_replacements("~berg |-> bg")
 
         assert repl == [(' berg ', [' berg', ' bg']),
                         ('berg ', ['berg', 'bg'])]
 
-
     def test_replace_suffix_no_decompose(self):
         repl = self.get_replacements("~berg |=> bg")
 
-        assert repl == [(' berg ', [' bg']),('berg ', ['bg'])]
-
+        assert repl == [(' berg ', [' bg']), ('berg ', ['bg'])]
 
     def test_add_suffix_decompose(self):
         repl = self.get_replacements("~berg -> bg")
@@ -179,26 +174,22 @@ class TestGetReplacements:
         assert repl == [(' berg ', [' berg', ' bg', 'berg', 'bg']),
                         ('berg ', [' berg', ' bg', 'berg', 'bg'])]
 
-
     def test_replace_suffix_decompose(self):
         repl = self.get_replacements("~berg => bg")
 
         assert repl == [(' berg ', [' bg', 'bg']),
                         ('berg ', [' bg', 'bg'])]
 
-
     def test_add_prefix_no_compose(self):
         repl = self.get_replacements("hinter~ |-> hnt")
 
         assert repl == [(' hinter', [' hinter', ' hnt']),
                         (' hinter ', [' hinter', ' hnt'])]
 
-
     def test_replace_prefix_no_compose(self):
         repl = self.get_replacements("hinter~ |=> hnt")
 
-        assert repl ==  [(' hinter', [' hnt']), (' hinter ', [' hnt'])]
-
+        assert repl == [(' hinter', [' hnt']), (' hinter ', [' hnt'])]
 
     def test_add_prefix_compose(self):
         repl = self.get_replacements("hinter~-> h")
@@ -206,45 +197,38 @@ class TestGetReplacements:
         assert repl == [(' hinter', [' h', ' h ', ' hinter', ' hinter ']),
                         (' hinter ', [' h', ' h', ' hinter', ' hinter'])]
 
-
     def test_replace_prefix_compose(self):
         repl = self.get_replacements("hinter~=> h")
 
         assert repl == [(' hinter', [' h', ' h ']),
                         (' hinter ', [' h', ' h'])]
 
-
     def test_add_beginning_only(self):
         repl = self.get_replacements("^Premier -> Pr")
 
         assert repl == [('^ premier ', ['^ pr', '^ premier'])]
 
-
     def test_replace_beginning_only(self):
         repl = self.get_replacements("^Premier => Pr")
 
         assert repl == [('^ premier ', ['^ pr'])]
 
-
     def test_add_final_only(self):
         repl = self.get_replacements("road$ -> rd")
 
         assert repl == [(' road ^', [' rd ^', ' road ^'])]
 
-
     def test_replace_final_only(self):
         repl = self.get_replacements("road$ => rd")
 
         assert repl == [(' road ^', [' rd ^'])]
 
-
     def test_decompose_only(self):
         repl = self.get_replacements("~foo -> foo")
 
         assert repl == [(' foo ', [' foo', 'foo']),
                         ('foo ', [' foo', 'foo'])]
 
-
     def test_add_suffix_decompose_end_only(self):
         repl = self.get_replacements("~berg |-> bg", "~berg$ -> bg")
 
@@ -253,7 +237,6 @@ class TestGetReplacements:
                         ('berg ', ['berg', 'bg']),
                         ('berg ^', [' berg ^', ' bg ^', 'berg ^', 'bg ^'])]
 
-
     def test_replace_suffix_decompose_end_only(self):
         repl = self.get_replacements("~berg |=> bg", "~berg$ => bg")
 
@@ -262,7 +245,6 @@ class TestGetReplacements:
                         ('berg ', ['bg']),
                         ('berg ^', [' bg ^', 'bg ^'])]
 
-
     @pytest.mark.parametrize('rule', ["~berg,~burg -> bg",
                                       "~berg, ~burg -> bg",
                                       "~berg,,~burg -> bg"])
index 7d0db9258246cea0017dec0ada0418d9c508fd74..2ce2236a3c490762c965c42a75cdcc4344661c54 100644 (file)
@@ -2,7 +2,7 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 """
 Tests for generic token analysis, mutation part.
@@ -24,37 +24,34 @@ DEFAULT_TRANSLITERATION = """ ::  Latin ();
                               '🜵' > ' ';
                           """
 
+
 class TestMutationNoVariants:
 
     def make_analyser(self, *mutations):
-        rules = { 'analyzer': 'generic',
-                  'mutations': [ {'pattern': m[0], 'replacements': m[1]}
-                                 for m in mutations]
-                }
+        rules = {'analyzer': 'generic',
+                 'mutations': [{'pattern': m[0], 'replacements': m[1]}
+                               for m in mutations]
+                 }
         trans = Transliterator.createFromRules("test_trans", DEFAULT_TRANSLITERATION)
         norm = Transliterator.createFromRules("test_norm", DEFAULT_NORMALIZATION)
         config = module.configure(rules, norm, trans)
 
         self.analysis = module.create(norm, trans, config)
 
-
     def variants(self, name):
         norm = Transliterator.createFromRules("test_norm", DEFAULT_NORMALIZATION)
         return set(self.analysis.compute_variants(norm.transliterate(name).strip()))
 
-
     @pytest.mark.parametrize('pattern', ('(capture)', ['a list']))
     def test_bad_pattern(self, pattern):
         with pytest.raises(UsageError):
             self.make_analyser((pattern, ['b']))
 
-
     @pytest.mark.parametrize('replacements', (None, 'a string'))
     def test_bad_replacement(self, replacements):
         with pytest.raises(UsageError):
             self.make_analyser(('a', replacements))
 
-
     def test_simple_replacement(self):
         self.make_analyser(('a', ['b']))
 
@@ -62,27 +59,23 @@ class TestMutationNoVariants:
         assert self.variants('abba') == {'bbbb'}
         assert self.variants('2 aar') == {'2 bbr'}
 
-
     def test_multichar_replacement(self):
         self.make_analyser(('1 1', ['1 1 1']))
 
         assert self.variants('1 1456') == {'1 1 1456'}
         assert self.variants('1 1 1') == {'1 1 1 1'}
 
-
     def test_removement_replacement(self):
         self.make_analyser((' ', [' ', '']))
 
         assert self.variants('A 345') == {'a 345', 'a345'}
         assert self.variants('a g b') == {'a g b', 'ag b', 'a gb', 'agb'}
 
-
     def test_regex_pattern(self):
         self.make_analyser(('[^a-z]+', ['XXX', ' ']))
 
         assert self.variants('a-34n12') == {'aXXXnXXX', 'aXXXn', 'a nXXX', 'a n'}
 
-
     def test_multiple_mutations(self):
         self.make_analyser(('ä', ['ä', 'ae']), ('ö', ['ö', 'oe']))
 
index 0384a4567ad26d6074c0b84a898b5e252dcdab9c..6ce665802c0a6426d020251f317652fb49638809 100644 (file)
@@ -10,6 +10,7 @@ Tests for simplified trie structure.
 
 from nominatim_db.tokenizer.token_analysis.simple_trie import SimpleTrie
 
+
 def test_single_item_trie():
     t = SimpleTrie([('foob', 42)])
 
@@ -18,6 +19,7 @@ def test_single_item_trie():
     assert t.longest_prefix('foob') == (42, 4)
     assert t.longest_prefix('123foofoo', 3) == (None, 3)
 
+
 def test_complex_item_tree():
     t = SimpleTrie([('a', 1),
                     ('b', 2),
index 0098747e52537d97eb33c889fcbb0f600fb2967e..dc9346c8fbcb06e33db50afd3c49e8cc92a90edd 100644 (file)
@@ -2,10 +2,11 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 import pytest
 
+
 @pytest.fixture
 def osm2pgsql_options(temp_db, tmp_path):
     """ A standard set of options for osm2pgsql
index c5aaaaae9f9c77ee4a614f6de51b610702929b8e..38cf87c4b5c642c230a280e5f0aefd4be9876527 100644 (file)
@@ -2,7 +2,7 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 """
 Tests for functions to add additional data to the database.
@@ -13,6 +13,7 @@ import pytest
 
 from nominatim_db.tools import add_osm_data
 
+
 class CaptureGetUrl:
 
     def __init__(self, monkeypatch):
@@ -29,6 +30,7 @@ def setup_delete_postprocessing(temp_db_cursor):
     temp_db_cursor.execute("""CREATE OR REPLACE FUNCTION flush_deleted_places()
                               RETURNS INTEGER AS $$ SELECT 1 $$ LANGUAGE SQL""")
 
+
 def test_import_osm_file_simple(dsn, table_factory, osm2pgsql_options, capfd):
 
     assert add_osm_data.add_data_from_file(dsn, Path('change.osm'), osm2pgsql_options) == 0
index 1e1f0e294736c23826f94adbda5a380a8a12c8a8..e758bca2e3e28d4aa38d9422684aa5ace0e48ae2 100644 (file)
@@ -2,7 +2,7 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 """
 Tests for maintenance and analysis functions.
@@ -14,6 +14,7 @@ from nominatim_db.tools import admin
 from nominatim_db.tokenizer import factory
 from nominatim_db.db.sql_preprocessor import SQLPreprocessor
 
+
 @pytest.fixture(autouse=True)
 def create_placex_table(project_env, tokenizer_mock, temp_db_cursor, placex_table):
     """ All tests in this module require the placex table to be set up.
@@ -76,7 +77,8 @@ def test_analyse_indexing_with_osm_id(project_env, temp_db_cursor):
 class TestAdminCleanDeleted:
 
     @pytest.fixture(autouse=True)
-    def setup_polygon_delete(self, project_env, table_factory, place_table, osmline_table, temp_db_cursor, temp_db_conn, def_config, src_dir):
+    def setup_polygon_delete(self, project_env, table_factory, place_table,
+                             osmline_table, temp_db_cursor, temp_db_conn, def_config, src_dir):
         """ Set up place_force_delete function and related tables
         """
         self.project_env = project_env
@@ -87,12 +89,14 @@ class TestAdminCleanDeleted:
                       class TEXT NOT NULL,
                       type TEXT NOT NULL""",
                       ((100, 'N', 'boundary', 'administrative'),
-                      (145, 'N', 'boundary', 'administrative'),
-                      (175, 'R', 'landcover', 'grass')))
-        temp_db_cursor.execute("""INSERT INTO placex (place_id, osm_id, osm_type, class, type, indexed_date, indexed_status)
-                              VALUES(1, 100, 'N', 'boundary', 'administrative', current_date - INTERVAL '1 month', 1),
-                               (2, 145, 'N', 'boundary', 'administrative', current_date - INTERVAL '3 month', 1),
-                               (3, 175, 'R', 'landcover', 'grass', current_date - INTERVAL '3 months', 1)""")
+                       (145, 'N', 'boundary', 'administrative'),
+                       (175, 'R', 'landcover', 'grass')))
+        temp_db_cursor.execute("""
+            INSERT INTO placex (place_id, osm_id, osm_type, class, type,
+                                indexed_date, indexed_status)
+            VALUES(1, 100, 'N', 'boundary', 'administrative', current_date - INTERVAL '1 month', 1),
+                  (2, 145, 'N', 'boundary', 'administrative', current_date - INTERVAL '3 month', 1),
+                  (3, 175, 'R', 'landcover', 'grass', current_date - INTERVAL '3 months', 1)""")
         # set up tables and triggers for utils function
         table_factory('place_to_be_deleted',
                       """osm_id BIGINT,
@@ -116,33 +120,42 @@ class TestAdminCleanDeleted:
         sqlproc = SQLPreprocessor(temp_db_conn, def_config)
         sqlproc.run_sql_file(temp_db_conn, 'functions/utils.sql')
         def_config.lib_dir.sql = orig_sql
-        
 
     def test_admin_clean_deleted_no_records(self):
         admin.clean_deleted_relations(self.project_env, age='1 year')
-        assert self.temp_db_cursor.row_set('SELECT osm_id, osm_type, class, type, indexed_status FROM placex') == {(100, 'N', 'boundary', 'administrative', 1),
-                                                                                                                   (145, 'N', 'boundary', 'administrative', 1),
-                                                                                                                   (175, 'R', 'landcover', 'grass', 1)}
-        assert self.temp_db_cursor.table_rows('import_polygon_delete') == 3
 
+        rowset = self.temp_db_cursor.row_set(
+            'SELECT osm_id, osm_type, class, type, indexed_status FROM placex')
+
+        assert rowset == {(100, 'N', 'boundary', 'administrative', 1),
+                          (145, 'N', 'boundary', 'administrative', 1),
+                          (175, 'R', 'landcover', 'grass', 1)}
+        assert self.temp_db_cursor.table_rows('import_polygon_delete') == 3
 
     @pytest.mark.parametrize('test_age', ['T week', '1 welk', 'P1E'])
     def test_admin_clean_deleted_bad_age(self, test_age):
         with pytest.raises(UsageError):
-            admin.clean_deleted_relations(self.project_env, age = test_age)
-
+            admin.clean_deleted_relations(self.project_env, age=test_age)
 
     def test_admin_clean_deleted_partial(self):
-        admin.clean_deleted_relations(self.project_env, age = '2 months')
-        assert self.temp_db_cursor.row_set('SELECT osm_id, osm_type, class, type, indexed_status FROM placex') == {(100, 'N', 'boundary', 'administrative', 1),
-                                                                                                                   (145, 'N', 'boundary', 'administrative', 100),
-                                                                                                                   (175, 'R', 'landcover', 'grass', 100)}
+        admin.clean_deleted_relations(self.project_env, age='2 months')
+
+        rowset = self.temp_db_cursor.row_set(
+            'SELECT osm_id, osm_type, class, type, indexed_status FROM placex')
+
+        assert rowset == {(100, 'N', 'boundary', 'administrative', 1),
+                          (145, 'N', 'boundary', 'administrative', 100),
+                          (175, 'R', 'landcover', 'grass', 100)}
         assert self.temp_db_cursor.table_rows('import_polygon_delete') == 1
 
     @pytest.mark.parametrize('test_age', ['1 week', 'P3D', '5 hours'])
     def test_admin_clean_deleted(self, test_age):
-        admin.clean_deleted_relations(self.project_env, age = test_age)
-        assert self.temp_db_cursor.row_set('SELECT osm_id, osm_type, class, type, indexed_status FROM placex') == {(100, 'N', 'boundary', 'administrative', 100),
-                                                                                                                   (145, 'N', 'boundary', 'administrative', 100),
-                                                                                                                   (175, 'R', 'landcover', 'grass', 100)}
+        admin.clean_deleted_relations(self.project_env, age=test_age)
+
+        rowset = self.temp_db_cursor.row_set(
+            'SELECT osm_id, osm_type, class, type, indexed_status FROM placex')
+
+        assert rowset == {(100, 'N', 'boundary', 'administrative', 100),
+                          (145, 'N', 'boundary', 'administrative', 100),
+                          (175, 'R', 'landcover', 'grass', 100)}
         assert self.temp_db_cursor.table_rows('import_polygon_delete') == 0
index 886bd75b72842216d7e1173e2cf57f53cac6c400..66506f561e42ab432ca2e84a21ab97e71c64f4e7 100644 (file)
@@ -2,7 +2,7 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 """
 Tests for database integrity checks.
@@ -12,6 +12,7 @@ import pytest
 from nominatim_db.tools import check_database as chkdb
 import nominatim_db.version
 
+
 def test_check_database_unknown_db(def_config, monkeypatch):
     monkeypatch.setenv('NOMINATIM_DATABASE_DSN', 'pgsql:dbname=fjgkhughwgh2423gsags')
     assert chkdb.check_database(def_config) == 1
@@ -35,6 +36,7 @@ def test_check_database_version_good(property_table, temp_db_conn, def_config):
                        str(nominatim_db.version.NOMINATIM_VERSION))
     assert chkdb.check_database_version(temp_db_conn, def_config) == chkdb.CheckState.OK
 
+
 def test_check_database_version_bad(property_table, temp_db_conn, def_config):
     property_table.set('database_version', '3.9.9-9')
     assert chkdb.check_database_version(temp_db_conn, def_config) == chkdb.CheckState.FATAL
index df2042982c98f090dc24174e38064873c15b09b3..f8cea2cce8267dc64ddd5c1e19c612acb667ad5d 100644 (file)
@@ -2,7 +2,7 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 """
 Tests for functions to import a new database.
@@ -10,13 +10,14 @@ Tests for functions to import a new database.
 from pathlib import Path
 
 import pytest
-import pytest_asyncio
+import pytest_asyncio  # noqa
 import psycopg
 from psycopg import sql as pysql
 
 from nominatim_db.tools import database_import
 from nominatim_db.errors import UsageError
 
+
 class TestDatabaseSetup:
     DBNAME = 'test_nominatim_python_unittest'
 
@@ -31,18 +32,15 @@ class TestDatabaseSetup:
             with conn.cursor() as cur:
                 cur.execute(f'DROP DATABASE IF EXISTS {self.DBNAME}')
 
-
     @pytest.fixture
     def cursor(self):
         with psycopg.connect(dbname=self.DBNAME) as conn:
             with conn.cursor() as cur:
                 yield cur
 
-
     def conn(self):
         return psycopg.connect(dbname=self.DBNAME)
 
-
     def test_setup_skeleton(self):
         database_import.setup_database_skeleton(f'dbname={self.DBNAME}')
 
@@ -51,25 +49,21 @@ class TestDatabaseSetup:
             with conn.cursor() as cur:
                 cur.execute('CREATE TABLE t (h HSTORE, geom GEOMETRY(Geometry, 4326))')
 
-
     def test_unsupported_pg_version(self, monkeypatch):
         monkeypatch.setattr(database_import, 'POSTGRESQL_REQUIRED_VERSION', (100, 4))
 
         with pytest.raises(UsageError, match='PostgreSQL server is too old.'):
             database_import.setup_database_skeleton(f'dbname={self.DBNAME}')
 
-
     def test_create_db_explicit_ro_user(self):
         database_import.setup_database_skeleton(f'dbname={self.DBNAME}',
                                                 rouser='postgres')
 
-
     def test_create_db_missing_ro_user(self):
         with pytest.raises(UsageError, match='Missing read-only user.'):
             database_import.setup_database_skeleton(f'dbname={self.DBNAME}',
                                                     rouser='sdfwkjkjgdugu2;jgsafkljas;')
 
-
     def test_setup_extensions_old_postgis(self, monkeypatch):
         monkeypatch.setattr(database_import, 'POSTGIS_REQUIRED_VERSION', (50, 50))
 
@@ -173,7 +167,7 @@ def test_truncate_database_tables(temp_db_conn, temp_db_cursor, table_factory, w
 @pytest.mark.parametrize("threads", (1, 5))
 @pytest.mark.asyncio
 async def test_load_data(dsn, place_row, placex_table, osmline_table,
-                   temp_db_cursor, threads):
+                         temp_db_cursor, threads):
     for func in ('precompute_words', 'getorcreate_housenumber_id', 'make_standard_name'):
         temp_db_cursor.execute(pysql.SQL("""CREATE FUNCTION {} (src TEXT)
                                             RETURNS TEXT AS $$ SELECT 'a'::TEXT $$ LANGUAGE SQL
@@ -198,11 +192,9 @@ class TestSetupSQL:
 
         self.config = def_config
 
-
     def write_sql(self, fname, content):
         (self.config.lib_dir.sql / fname).write_text(content)
 
-
     @pytest.mark.parametrize("reverse", [True, False])
     def test_create_tables(self, temp_db_conn, temp_db_cursor, reverse):
         self.write_sql('tables.sql',
@@ -213,7 +205,6 @@ class TestSetupSQL:
 
         temp_db_cursor.scalar('SELECT test()') == reverse
 
-
     def test_create_table_triggers(self, temp_db_conn, temp_db_cursor):
         self.write_sql('table-triggers.sql',
                        """CREATE FUNCTION test() RETURNS TEXT
@@ -223,7 +214,6 @@ class TestSetupSQL:
 
         temp_db_cursor.scalar('SELECT test()') == 'a'
 
-
     def test_create_partition_tables(self, temp_db_conn, temp_db_cursor):
         self.write_sql('partition-tables.src.sql',
                        """CREATE FUNCTION test() RETURNS TEXT
@@ -233,7 +223,6 @@ class TestSetupSQL:
 
         temp_db_cursor.scalar('SELECT test()') == 'b'
 
-
     @pytest.mark.parametrize("drop", [True, False])
     @pytest.mark.asyncio
     async def test_create_search_indices(self, temp_db_conn, temp_db_cursor, drop):
index 666ef0b8b65e74d1418bd6d3c8807b2217306f35..216f1a40774f0ba7242f2f58d6ad6b913f135454 100644 (file)
@@ -2,19 +2,14 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 """
 Tests for tools.exec_utils module.
 """
-from pathlib import Path
-import subprocess
-
-import pytest
-
-from nominatim_db.config import Configuration
 import nominatim_db.tools.exec_utils as exec_utils
 
+
 def test_run_osm2pgsql(osm2pgsql_options):
     osm2pgsql_options['append'] = False
     osm2pgsql_options['import_file'] = 'foo.bar'
index f64850fb2e99312aade36ebbd404c4f23020a132..21e49b8dc63054fd2cd8a46d5131215b52ff5ce5 100644 (file)
@@ -2,7 +2,7 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 """
 Tests for freeze functions (removing unused database parts).
@@ -26,6 +26,7 @@ NOMINATIM_DROP_TABLES = [
     'wikipedia_article', 'wikipedia_redirect'
 ]
 
+
 def test_drop_tables(temp_db_conn, temp_db_cursor, table_factory):
     for table in NOMINATIM_RUNTIME_TABLES + NOMINATIM_DROP_TABLES:
         table_factory(table)
@@ -42,6 +43,7 @@ def test_drop_tables(temp_db_conn, temp_db_cursor, table_factory):
 
     assert freeze.is_frozen(temp_db_conn)
 
+
 def test_drop_flatnode_file_no_file():
     freeze.drop_flatnode_file(None)
 
index 0d33e6e0f30e4a0ab47bfb02a4cd63f2ad4c55a9..d8fe8946c9173ed12485fc12163862869056ec7c 100644 (file)
@@ -2,20 +2,17 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 """
     Tests for import special phrases methods
     of the class SPImporter.
 """
-from shutil import copyfile
 import pytest
 from nominatim_db.tools.special_phrases.sp_importer import SPImporter
 from nominatim_db.tools.special_phrases.sp_wiki_loader import SPWikiLoader
 from nominatim_db.tools.special_phrases.special_phrase import SpecialPhrase
-from nominatim_db.errors import UsageError
 
-from cursor import CursorForTesting
 
 @pytest.fixture
 def sp_importer(temp_db_conn, def_config, monkeypatch):
@@ -53,6 +50,7 @@ def test_fetch_existing_place_classtype_tables(sp_importer, table_factory):
     contained_table = sp_importer.table_phrases_to_delete.pop()
     assert contained_table == 'place_classtype_testclasstypetable'
 
+
 def test_check_sanity_class(sp_importer):
     """
         Check for _check_sanity() method.
@@ -65,6 +63,7 @@ def test_check_sanity_class(sp_importer):
 
     assert sp_importer._check_sanity(SpecialPhrase('en', 'class', 'type', ''))
 
+
 def test_load_white_and_black_lists(sp_importer):
     """
         Test that _load_white_and_black_lists() well return
@@ -93,6 +92,7 @@ def test_create_place_classtype_indexes(temp_db_with_extensions,
 
     assert check_placeid_and_centroid_indexes(temp_db_cursor, phrase_class, phrase_type)
 
+
 def test_create_place_classtype_table(temp_db_conn, temp_db_cursor, placex_table, sp_importer):
     """
         Test that _create_place_classtype_table() create
@@ -105,6 +105,7 @@ def test_create_place_classtype_table(temp_db_conn, temp_db_cursor, placex_table
 
     assert check_table_exist(temp_db_cursor, phrase_class, phrase_type)
 
+
 def test_grant_access_to_web_user(temp_db_conn, temp_db_cursor, table_factory,
                                   def_config, sp_importer):
     """
@@ -120,7 +121,9 @@ def test_grant_access_to_web_user(temp_db_conn, temp_db_cursor, table_factory,
     sp_importer._grant_access_to_webuser(phrase_class, phrase_type)
     temp_db_conn.commit()
 
-    assert check_grant_access(temp_db_cursor, def_config.DATABASE_WEBUSER, phrase_class, phrase_type)
+    assert check_grant_access(temp_db_cursor, def_config.DATABASE_WEBUSER,
+                              phrase_class, phrase_type)
+
 
 def test_create_place_classtype_table_and_indexes(
         temp_db_cursor, def_config, placex_table,
@@ -141,6 +144,7 @@ def test_create_place_classtype_table_and_indexes(
         assert check_placeid_and_centroid_indexes(temp_db_cursor, pair[0], pair[1])
         assert check_grant_access(temp_db_cursor, def_config.DATABASE_WEBUSER, pair[0], pair[1])
 
+
 def test_remove_non_existent_tables_from_db(sp_importer, default_phrases,
                                             temp_db_conn, temp_db_cursor):
     """
@@ -168,7 +172,7 @@ def test_remove_non_existent_tables_from_db(sp_importer, default_phrases,
     temp_db_conn.commit()
 
     assert temp_db_cursor.row_set(query_tables) \
-                 == {('place_classtype_testclasstypetable_to_keep', )}
+        == {('place_classtype_testclasstypetable_to_keep', )}
 
 
 @pytest.mark.parametrize("should_replace", [(True), (False)])
@@ -182,8 +186,8 @@ def test_import_phrases(monkeypatch, temp_db_cursor, def_config, sp_importer,
         It should also update the database well by deleting or preserving existing entries
         of the database.
     """
-    #Add some data to the database before execution in order to test
-    #what is deleted and what is preserved.
+    # Add some data to the database before execution in order to test
+    # what is deleted and what is preserved.
     table_factory('place_classtype_amenity_animal_shelter')
     table_factory('place_classtype_wrongclass_wrongtype')
 
@@ -209,6 +213,7 @@ def test_import_phrases(monkeypatch, temp_db_cursor, def_config, sp_importer,
     if should_replace:
         assert not temp_db_cursor.table_exists('place_classtype_wrongclass_wrongtype')
 
+
 def check_table_exist(temp_db_cursor, phrase_class, phrase_type):
     """
         Verify that the place_classtype table exists for the given
@@ -231,6 +236,7 @@ def check_grant_access(temp_db_cursor, user, phrase_class, phrase_type):
             AND privilege_type='SELECT'""".format(table_name, user))
     return temp_db_cursor.fetchone()
 
+
 def check_placeid_and_centroid_indexes(temp_db_cursor, phrase_class, phrase_type):
     """
         Check that the place_id index and centroid index exist for the
index 0b4d2ec6e18585afd6ee233dfa5c31eb06086d04..00f6a7d7ad11a749c00b106cca815f956645b09f 100644 (file)
@@ -2,7 +2,7 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 """
 Tests for migration functions
@@ -11,9 +11,9 @@ import pytest
 
 from nominatim_db.tools import migration
 from nominatim_db.errors import UsageError
-from nominatim_db.db.connection import server_version_tuple
 import nominatim_db.version
 
+
 class DummyTokenizer:
 
     def update_sql_functions(self, config):
@@ -49,6 +49,7 @@ def test_run_single_migration(temp_db_with_extensions, def_config, temp_db_curso
                        str(nominatim_db.version.NominatimVersion(*oldversion)))
 
     done = {'old': False, 'new': False}
+
     def _migration(**_):
         """ Dummy migration"""
         done['new'] = True
@@ -69,7 +70,7 @@ def test_run_single_migration(temp_db_with_extensions, def_config, temp_db_curso
     assert property_table.get('database_version') == str(nominatim_db.version.NOMINATIM_VERSION)
 
 
-###### Tests for specific migrations
+# Tests for specific migrations
 #
 # Each migration should come with two tests:
 #  1. Test that migration from old to new state works as expected.
index f035bb19affa5c1195cb8999f61897cdd68c00de..b03c9748441a69537859b404dc125db55411ff18 100644 (file)
@@ -2,7 +2,7 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 """
 Tests for functions to maintain the artificial postcode table.
@@ -15,6 +15,7 @@ from nominatim_db.tools import postcodes
 from nominatim_db.data import country_info
 import dummy_tokenizer
 
+
 class MockPostcodeTable:
     """ A location_postcode table for testing.
     """
@@ -35,7 +36,7 @@ class MockPostcodeTable:
                            RETURNS TEXT AS $$ BEGIN RETURN postcode; END; $$ LANGUAGE plpgsql;
 
                            CREATE OR REPLACE FUNCTION get_country_code(place geometry)
-                           RETURNS TEXT AS $$ BEGIN 
+                           RETURNS TEXT AS $$ BEGIN
                            RETURN null;
                            END; $$ LANGUAGE plpgsql;
                         """)
@@ -51,7 +52,6 @@ class MockPostcodeTable:
                         (country, postcode, x, y))
         self.conn.commit()
 
-
     @property
     def row_set(self):
         with self.conn.cursor() as cur:
@@ -180,7 +180,7 @@ def test_postcodes_extern(dsn, postcode_table, tmp_path,
                                       ('xx', 'CD 4511', -10, -5)}
 
 
-def test_postcodes_extern_bad_column(dsn, postcode_table, tmp_path, 
+def test_postcodes_extern_bad_column(dsn, postcode_table, tmp_path,
                                      insert_implicit_postcode, tokenizer):
     insert_implicit_postcode(1, 'xx', 'POINT(10 12)', dict(postcode='AB 4511'))
 
@@ -204,6 +204,7 @@ def test_postcodes_extern_bad_number(dsn, insert_implicit_postcode,
     assert postcode_table.row_set == {('xx', 'AB 4511', 10, 12),
                                       ('xx', 'CD 4511', -10, -5)}
 
+
 def test_can_compute(dsn, table_factory):
     assert not postcodes.can_compute(dsn)
     table_factory('place')
@@ -211,10 +212,10 @@ def test_can_compute(dsn, table_factory):
 
 
 def test_no_placex_entry(dsn, tmp_path, temp_db_cursor, place_row, postcode_table, tokenizer):
-    #Rewrite the get_country_code function to verify its execution.
+    # Rewrite the get_country_code function to verify its execution.
     temp_db_cursor.execute("""
         CREATE OR REPLACE FUNCTION get_country_code(place geometry)
-        RETURNS TEXT AS $$ BEGIN 
+        RETURNS TEXT AS $$ BEGIN
         RETURN 'yy';
         END; $$ LANGUAGE plpgsql;
     """)
@@ -224,11 +225,12 @@ def test_no_placex_entry(dsn, tmp_path, temp_db_cursor, place_row, postcode_tabl
     assert postcode_table.row_set == {('yy', 'AB 4511', 10, 12)}
 
 
-def test_discard_badly_formatted_postcodes(dsn, tmp_path, temp_db_cursor, place_row, postcode_table, tokenizer):
-    #Rewrite the get_country_code function to verify its execution.
+def test_discard_badly_formatted_postcodes(dsn, tmp_path, temp_db_cursor, place_row,
+                                           postcode_table, tokenizer):
+    # Rewrite the get_country_code function to verify its execution.
     temp_db_cursor.execute("""
         CREATE OR REPLACE FUNCTION get_country_code(place geometry)
-        RETURNS TEXT AS $$ BEGIN 
+        RETURNS TEXT AS $$ BEGIN
         RETURN 'fr';
         END; $$ LANGUAGE plpgsql;
     """)
index 8f73518000b966690c60959f7de119283532fcfe..95feef0de04e7c6e34b57e3296b82ac48cb05e09 100644 (file)
@@ -2,7 +2,7 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 """
 Test for various refresh functions.
@@ -12,7 +12,7 @@ from pathlib import Path
 import pytest
 
 from nominatim_db.tools import refresh
-from nominatim_db.db.connection import postgis_version_tuple
+
 
 def test_refresh_import_wikipedia_not_existing(dsn):
     assert refresh.import_wikipedia_articles(dsn, Path('.')) == 1
@@ -21,6 +21,7 @@ def test_refresh_import_wikipedia_not_existing(dsn):
 def test_refresh_import_secondary_importance_non_existing(dsn):
     assert refresh.import_secondary_importance(dsn, Path('.')) == 1
 
+
 def test_refresh_import_secondary_importance_testdb(dsn, src_dir, temp_db_conn, temp_db_cursor):
     temp_db_cursor.execute('CREATE EXTENSION postgis')
     temp_db_cursor.execute('CREATE EXTENSION postgis_raster')
index 6e094cdc1c0e03ad5e138bffc18412039acfd07a..f2bfdea6c4da47a68d5f38362d88069dc691fbe4 100644 (file)
@@ -2,23 +2,24 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 """
 Tests for function for importing address ranks.
 """
 import json
-from pathlib import Path
 
 import pytest
 
 from nominatim_db.tools.refresh import load_address_levels, load_address_levels_from_config
 
+
 def test_load_ranks_def_config(temp_db_conn, temp_db_cursor, def_config):
     load_address_levels_from_config(temp_db_conn, def_config)
 
     assert temp_db_cursor.table_rows('address_levels') > 0
 
+
 def test_load_ranks_from_project_dir(project_env, temp_db_conn, temp_db_cursor):
     test_file = project_env.project_dir / 'address-levels.json'
     test_file.write_text('[{"tags":{"place":{"sea":2}}}]')
@@ -43,14 +44,14 @@ def test_load_ranks_country(temp_db_conn, temp_db_cursor):
                           "tags": {"place": {"village": 15}}},
                          {"countries": ['uk', 'us'],
                           "tags": {"place": {"village": 16}}}
-                        ])
+                         ])
 
     assert temp_db_cursor.row_set('SELECT * FROM levels') == \
            set([(None, 'place', 'village', 14, 14),
                 ('de', 'place', 'village', 15, 15),
                 ('uk', 'place', 'village', 16, 16),
                 ('us', 'place', 'village', 16, 16),
-               ])
+                ])
 
 
 def test_load_ranks_default_value(temp_db_conn, temp_db_cursor):
@@ -58,33 +59,33 @@ def test_load_ranks_default_value(temp_db_conn, temp_db_cursor):
                         [{"tags": {"boundary": {"": 28}}},
                          {"countries": ['hu'],
                           "tags": {"boundary": {"": 29}}}
-                        ])
+                         ])
 
     assert temp_db_cursor.row_set('SELECT * FROM levels') == \
            set([(None, 'boundary', None, 28, 28),
                 ('hu', 'boundary', None, 29, 29),
-               ])
+                ])
 
 
 def test_load_ranks_multiple_keys(temp_db_conn, temp_db_cursor):
     load_address_levels(temp_db_conn, 'levels',
                         [{"tags": {"place": {"city": 14},
-                                   "boundary": {"administrative2" : 4}}
-                         }])
+                                   "boundary": {"administrative2": 4}}
+                          }])
 
     assert temp_db_cursor.row_set('SELECT * FROM levels') == \
            set([(None, 'place', 'city', 14, 14),
                 (None, 'boundary', 'administrative2', 4, 4),
-               ])
+                ])
 
 
 def test_load_ranks_address(temp_db_conn, temp_db_cursor):
     load_address_levels(temp_db_conn, 'levels',
                         [{"tags": {"place": {"city": 14,
-                                             "town" : [14, 13]}}
-                         }])
+                                             "town": [14, 13]}}
+                          }])
 
     assert temp_db_cursor.row_set('SELECT * FROM levels') == \
            set([(None, 'place', 'city', 14, 14),
                 (None, 'place', 'town', 14, 13),
-               ])
+                ])
index 984a161016fecd8f594a00d8a0b7b80010b708a5..bd8724d60138787eec910724642e78f88aea307a 100644 (file)
@@ -2,7 +2,7 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 """
 Tests for creating PL/pgSQL functions for Nominatim.
@@ -11,6 +11,7 @@ import pytest
 
 from nominatim_db.tools.refresh import create_functions
 
+
 class TestCreateFunctions:
     @pytest.fixture(autouse=True)
     def init_env(self, sql_preprocessor, temp_db_conn, def_config, tmp_path):
@@ -18,12 +19,10 @@ class TestCreateFunctions:
         self.config = def_config
         def_config.lib_dir.sql = tmp_path
 
-
     def write_functions(self, content):
         sqlfile = self.config.lib_dir.sql / 'functions.sql'
         sqlfile.write_text(content)
 
-
     def test_create_functions(self, temp_db_cursor):
         self.write_functions("""CREATE OR REPLACE FUNCTION test() RETURNS INTEGER
                               AS $$
@@ -37,7 +36,6 @@ class TestCreateFunctions:
 
         assert temp_db_cursor.scalar('SELECT test()') == 43
 
-
     @pytest.mark.parametrize("dbg,ret", ((True, 43), (False, 22)))
     def test_create_functions_with_template(self, temp_db_cursor, dbg, ret):
         self.write_functions("""CREATE OR REPLACE FUNCTION test() RETURNS INTEGER
index 997ba04dc43562938266a2b4809cb9647bda7b0c..046e91919e3a3f7e826df94ef0b254216971a4e7 100644 (file)
@@ -12,7 +12,10 @@ import csv
 
 import pytest
 
-from nominatim_db.tools.refresh import import_wikipedia_articles, recompute_importance, create_functions
+from nominatim_db.tools.refresh import (import_wikipedia_articles,
+                                        recompute_importance,
+                                        create_functions)
+
 
 @pytest.fixture
 def wiki_csv(tmp_path, sql_preprocessor):
@@ -25,7 +28,7 @@ def wiki_csv(tmp_path, sql_preprocessor):
             for lang, title, importance, wd in data:
                 writer.writerow({'language': lang, 'type': 'a',
                                  'title': title, 'importance': str(importance),
-                                 'wikidata_id' : wd})
+                                 'wikidata_id': wd})
         return tmp_path
 
     return _import
index 392ea0750b6f50c11c5006e4ef6eb09ceb7763f3..347899bdb0fc4f97c448c0d064ae0638f027f1dc 100644 (file)
@@ -2,7 +2,7 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 """
 Tests for replication functionality.
@@ -22,13 +22,15 @@ OSM_NODE_DATA = """\
 <node id="100" visible="true" version="1" changeset="2047" timestamp="2006-01-27T22:09:10Z" user="Foo" uid="111" lat="48.7586670" lon="8.1343060">
 </node>
 </osm>
-"""
+"""  # noqa
+
 
 @pytest.fixture(autouse=True)
 def setup_status_table(status_table):
     pass
 
-### init replication
+
+# init replication
 
 def test_init_replication_bad_base_url(monkeypatch, place_row, temp_db_conn):
     place_row(osm_type='N', osm_id=100)
@@ -50,13 +52,13 @@ def test_init_replication_success(monkeypatch, place_row, temp_db_conn, temp_db_
     nominatim_db.tools.replication.init_replication(temp_db_conn, 'https://test.io')
 
     expected_date = dt.datetime.strptime('2006-01-27T19:09:10', status.ISODATE_FORMAT)\
-                        .replace(tzinfo=dt.timezone.utc)
+                      .replace(tzinfo=dt.timezone.utc)
 
     assert temp_db_cursor.row_set("SELECT * FROM import_status") \
-             == {(expected_date, 234, True)}
+        == {(expected_date, 234, True)}
 
 
-### checking for updates
+# checking for updates
 
 def test_check_for_updates_empty_status_table(temp_db_conn):
     assert nominatim_db.tools.replication.check_for_updates(temp_db_conn, 'https://test.io') == 254
@@ -87,10 +89,11 @@ def test_check_for_updates_no_new_data(monkeypatch, temp_db_conn,
                         "get_state_info",
                         lambda self: OsmosisState(server_sequence, date))
 
-    assert nominatim_db.tools.replication.check_for_updates(temp_db_conn, 'https://test.io') == result
+    assert result == \
+        nominatim_db.tools.replication.check_for_updates(temp_db_conn, 'https://test.io')
 
 
-### updating
+# updating
 
 @pytest.fixture
 def update_options(tmpdir):
@@ -100,6 +103,7 @@ def update_options(tmpdir):
                 import_file=tmpdir / 'foo.osm',
                 max_diff_size=1)
 
+
 def test_update_empty_status_table(dsn):
     with pytest.raises(UsageError):
         nominatim_db.tools.replication.update(dsn, {})
@@ -109,7 +113,7 @@ def test_update_already_indexed(temp_db_conn, dsn):
     status.set_status(temp_db_conn, dt.datetime.now(dt.timezone.utc), seq=34, indexed=False)
 
     assert nominatim_db.tools.replication.update(dsn, dict(indexed_only=True)) \
-             == nominatim_db.tools.replication.UpdateState.MORE_PENDING
+        == nominatim_db.tools.replication.UpdateState.MORE_PENDING
 
 
 def test_update_no_data_no_sleep(monkeypatch, temp_db_conn, dsn, update_options):
@@ -124,7 +128,7 @@ def test_update_no_data_no_sleep(monkeypatch, temp_db_conn, dsn, update_options)
     monkeypatch.setattr(time, 'sleep', sleeptime.append)
 
     assert nominatim_db.tools.replication.update(dsn, update_options) \
-             == nominatim_db.tools.replication.UpdateState.NO_CHANGES
+        == nominatim_db.tools.replication.UpdateState.NO_CHANGES
 
     assert not sleeptime
 
@@ -141,7 +145,7 @@ def test_update_no_data_sleep(monkeypatch, temp_db_conn, dsn, update_options):
     monkeypatch.setattr(time, 'sleep', sleeptime.append)
 
     assert nominatim_db.tools.replication.update(dsn, update_options) \
-             == nominatim_db.tools.replication.UpdateState.NO_CHANGES
+        == nominatim_db.tools.replication.UpdateState.NO_CHANGES
 
     assert len(sleeptime) == 1
     assert sleeptime[0] < 3600
index 9d0ad9cc8e81c8782819fa2c54cd1bffdd0082fb..67d6eed575cdb50f5bddfd95fe01d72de5fe1eab 100644 (file)
@@ -2,7 +2,7 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 """
     Tests for methods of the SPCsvLoader class.
@@ -13,6 +13,7 @@ from nominatim_db.errors import UsageError
 from nominatim_db.tools.special_phrases.sp_csv_loader import SPCsvLoader
 from nominatim_db.tools.special_phrases.special_phrase import SpecialPhrase
 
+
 @pytest.fixture
 def sp_csv_loader(src_dir):
     """
index 5c37c32f42eb2eec91c3043096bf255c5db3ce58..b8e41cbe2f6c87cc9713a79ea3d0d5dc5c3559ff 100644 (file)
@@ -2,7 +2,7 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 """
     Tests for methods of the SPWikiLoader class.
@@ -36,22 +36,22 @@ def test_generate_phrases(sp_wiki_loader):
     """
     phrases = list(sp_wiki_loader.generate_phrases())
 
-    assert set((p.p_label, p.p_class, p.p_type, p.p_operator) for p in phrases) ==\
-              {('Zip Line', 'aerialway', 'zip_line', '-'),
-               ('Zip Lines', 'aerialway', 'zip_line', '-'),
-               ('Zip Line in', 'aerialway', 'zip_line', 'in'),
-               ('Zip Lines in', 'aerialway', 'zip_line', 'in'),
-               ('Zip Line near', 'aerialway', 'zip_line', 'near'),
-               ('Animal shelter', 'amenity', 'animal_shelter', '-'),
-               ('Animal shelters', 'amenity', 'animal_shelter', '-'),
-               ('Animal shelter in', 'amenity', 'animal_shelter', 'in'),
-               ('Animal shelters in', 'amenity', 'animal_shelter', 'in'),
-               ('Animal shelter near', 'amenity', 'animal_shelter', 'near'),
-               ('Animal shelters near', 'amenity', 'animal_shelter', 'near'),
-               ('Drinking Water near', 'amenity', 'drinking_water', 'near'),
-               ('Water', 'amenity', 'drinking_water', '-'),
-               ('Water in', 'amenity', 'drinking_water', 'in'),
-               ('Water near', 'amenity', 'drinking_water', 'near'),
-               ('Embassy', 'amenity', 'embassy', '-'),
-               ('Embassys', 'amenity', 'embassy', '-'),
-               ('Embassies', 'amenity', 'embassy', '-')}
+    assert set((p.p_label, p.p_class, p.p_type, p.p_operator) for p in phrases) == \
+        {('Zip Line', 'aerialway', 'zip_line', '-'),
+         ('Zip Lines', 'aerialway', 'zip_line', '-'),
+         ('Zip Line in', 'aerialway', 'zip_line', 'in'),
+         ('Zip Lines in', 'aerialway', 'zip_line', 'in'),
+         ('Zip Line near', 'aerialway', 'zip_line', 'near'),
+         ('Animal shelter', 'amenity', 'animal_shelter', '-'),
+         ('Animal shelters', 'amenity', 'animal_shelter', '-'),
+         ('Animal shelter in', 'amenity', 'animal_shelter', 'in'),
+         ('Animal shelters in', 'amenity', 'animal_shelter', 'in'),
+         ('Animal shelter near', 'amenity', 'animal_shelter', 'near'),
+         ('Animal shelters near', 'amenity', 'animal_shelter', 'near'),
+         ('Drinking Water near', 'amenity', 'drinking_water', 'near'),
+         ('Water', 'amenity', 'drinking_water', '-'),
+         ('Water in', 'amenity', 'drinking_water', 'in'),
+         ('Water near', 'amenity', 'drinking_water', 'near'),
+         ('Embassy', 'amenity', 'embassy', '-'),
+         ('Embassys', 'amenity', 'embassy', '-'),
+         ('Embassies', 'amenity', 'embassy', '-')}
index 5d65fafb3b5c4d272472269ece832ea7bb220be6..f7dfe32e6be4052cee2d4f4539a0ceba045f381f 100644 (file)
@@ -2,7 +2,7 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 """
 Test for tiger data function
@@ -11,12 +11,13 @@ import tarfile
 from textwrap import dedent
 
 import pytest
-import pytest_asyncio
+import pytest_asyncio  # noqa: F401
 
 from nominatim_db.db.connection import execute_scalar
 from nominatim_db.tools import tiger_data, freeze
 from nominatim_db.errors import UsageError
 
+
 class MockTigerTable:
 
     def __init__(self, conn):
@@ -40,6 +41,7 @@ class MockTigerTable:
             cur.execute("SELECT * FROM tiger LIMIT 1")
             return cur.fetchone()
 
+
 @pytest.fixture
 def tiger_table(def_config, temp_db_conn, sql_preprocessor,
                 temp_db_with_extensions, tmp_path):
@@ -87,7 +89,7 @@ async def test_add_tiger_data(def_config, src_dir, tiger_table, tokenizer_mock,
 
 @pytest.mark.asyncio
 async def test_add_tiger_data_database_frozen(def_config, temp_db_conn, tiger_table, tokenizer_mock,
-                                 tmp_path):
+                                              tmp_path):
     freeze.drop_update_tables(temp_db_conn)
 
     with pytest.raises(UsageError) as excinfo:
@@ -100,7 +102,7 @@ async def test_add_tiger_data_database_frozen(def_config, temp_db_conn, tiger_ta
 
 @pytest.mark.asyncio
 async def test_add_tiger_data_no_files(def_config, tiger_table, tokenizer_mock,
-                                 tmp_path):
+                                       tmp_path):
     await tiger_data.add_tiger_data(str(tmp_path), def_config, 1, tokenizer_mock())
 
     assert tiger_table.count() == 0
@@ -108,7 +110,7 @@ async def test_add_tiger_data_no_files(def_config, tiger_table, tokenizer_mock,
 
 @pytest.mark.asyncio
 async def test_add_tiger_data_bad_file(def_config, tiger_table, tokenizer_mock,
-                                 tmp_path):
+                                       tmp_path):
     sqlfile = tmp_path / '1010.csv'
     sqlfile.write_text("""Random text""")
 
@@ -119,7 +121,7 @@ async def test_add_tiger_data_bad_file(def_config, tiger_table, tokenizer_mock,
 
 @pytest.mark.asyncio
 async def test_add_tiger_data_hnr_nan(def_config, tiger_table, tokenizer_mock,
-                                csv_factory, tmp_path):
+                                      csv_factory, tmp_path):
     csv_factory('file1', hnr_from=99)
     csv_factory('file2', hnr_from='L12')
     csv_factory('file3', hnr_to='12.4')
@@ -133,7 +135,7 @@ async def test_add_tiger_data_hnr_nan(def_config, tiger_table, tokenizer_mock,
 @pytest.mark.parametrize("threads", (1, 5))
 @pytest.mark.asyncio
 async def test_add_tiger_data_tarfile(def_config, tiger_table, tokenizer_mock,
-                                tmp_path, src_dir, threads):
+                                      tmp_path, src_dir, threads):
     tar = tarfile.open(str(tmp_path / 'sample.tar.gz'), "w:gz")
     tar.add(str(src_dir / 'test' / 'testdb' / 'tiger' / '01001.csv'))
     tar.close()
@@ -146,7 +148,7 @@ async def test_add_tiger_data_tarfile(def_config, tiger_table, tokenizer_mock,
 
 @pytest.mark.asyncio
 async def test_add_tiger_data_bad_tarfile(def_config, tiger_table, tokenizer_mock,
-                                    tmp_path):
+                                          tmp_path):
     tarfile = tmp_path / 'sample.tar.gz'
     tarfile.write_text("""Random text""")
 
@@ -156,7 +158,7 @@ async def test_add_tiger_data_bad_tarfile(def_config, tiger_table, tokenizer_moc
 
 @pytest.mark.asyncio
 async def test_add_tiger_data_empty_tarfile(def_config, tiger_table, tokenizer_mock,
-                                      tmp_path):
+                                            tmp_path):
     tar = tarfile.open(str(tmp_path / 'sample.tar.gz'), "w:gz")
     tar.add(__file__)
     tar.close()
index bac0edb3c406fd9ab45b74fb4d0e410ddfc982b2..664d5cd7a7f7d39438ce5a387a60ab06db8bb43e 100644 (file)
@@ -2,7 +2,7 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 """
 Tests for centroid computation.
@@ -11,6 +11,7 @@ import pytest
 
 from nominatim_db.utils.centroid import PointsCentroid
 
+
 def test_empty_set():
     c = PointsCentroid()
 
@@ -18,7 +19,7 @@ def test_empty_set():
         c.centroid()
 
 
-@pytest.mark.parametrize("centroid", [(0,0), (-1, 3), [0.0000032, 88.4938]])
+@pytest.mark.parametrize("centroid", [(0, 0), (-1, 3), [0.0000032, 88.4938]])
 def test_one_point_centroid(centroid):
     c = PointsCentroid()
 
index 53e3f4d3073ca01bcc1ad0bdc89f90c4a8c92234..c0946f010c97f6507c429bca9d4a244efbdec0c6 100644 (file)
@@ -2,7 +2,7 @@
 #
 # This file is part of Nominatim. (https://nominatim.org)
 #
-# Copyright (C) 2024 by the Nominatim developer community.
+# Copyright (C) 2025 by the Nominatim developer community.
 # For a full list of authors see the git log.
 """
 Tests for the streaming JSON writer.
@@ -13,6 +13,7 @@ import pytest
 
 from nominatim_api.utils.json_writer import JsonWriter
 
+
 @pytest.mark.parametrize("inval,outstr", [(None, 'null'),
                                           (True, 'true'), (False, 'false'),
                                           (23, '23'), (0, '0'), (-1.3, '-1.3'),
@@ -71,6 +72,7 @@ def test_object_single_entry():
     assert writer() == '{"something":5}'
     json.loads(writer())
 
+
 def test_object_many_values():
     writer = JsonWriter()\
                 .start_object()\
@@ -82,6 +84,7 @@ def test_object_many_values():
     assert writer() == '{"foo":null,"bar":{},"baz":"b\\taz"}'
     json.loads(writer())
 
+
 def test_object_many_values_without_none():
     writer = JsonWriter()\
                 .start_object()\
@@ -89,7 +92,7 @@ def test_object_many_values_without_none():
                     .keyval_not_none('bar', None)\
                     .keyval_not_none('baz', '')\
                     .keyval_not_none('eve', False,
-                                     transform = lambda v: 'yes' if v else 'no')\
+                                     transform=lambda v: 'yes' if v else 'no')\
                 .end_object()
 
     assert writer() == '{"foo":0,"baz":"","eve":"no"}'