]> git.openstreetmap.org Git - nominatim.git/commitdiff
Merge pull request #3122 from miku0/sanitizer-final
authorSarah Hoffmann <lonvia@denofr.de>
Tue, 1 Aug 2023 08:38:58 +0000 (10:38 +0200)
committerGitHub <noreply@github.com>
Tue, 1 Aug 2023 08:38:58 +0000 (10:38 +0200)
Adds sanitizer for Japanese addresses to correspond to block address

docs/customize/Tokenizers.md
nominatim/tokenizer/sanitizers/tag_japanese.py [new file with mode: 0644]
settings/icu-rules/unicode-digits-to-decimal.yaml
settings/icu_tokenizer.yaml
test/bdd/db/query/japanese.feature [new file with mode: 0644]
test/python/tokenizer/sanitizers/test_tag_japanese.py [new file with mode: 0644]

index 11c27e38b903ae0683ace099f417ec16b1077bc8..6199ea4252469537a0c3953415cff05795735cdd 100644 (file)
@@ -229,6 +229,14 @@ The following is a list of sanitizers that are shipped with Nominatim.
     rendering:
         heading_level: 6
 
+#### tag-japanese
+
+::: nominatim.tokenizer.sanitizers.tag_japanese
+    selection:
+        members: False
+    rendering:
+        heading_level: 6
+
 #### Token Analysis
 
 Token analyzers take a full name and transform it into one or more normalized
diff --git a/nominatim/tokenizer/sanitizers/tag_japanese.py b/nominatim/tokenizer/sanitizers/tag_japanese.py
new file mode 100644 (file)
index 0000000..3663860
--- /dev/null
@@ -0,0 +1,117 @@
+# SPDX-License-Identifier: GPL-3.0-or-later
+#
+# This file is part of Nominatim. (https://nominatim.org)
+#
+# Copyright (C) 2022 by the Nominatim developer community.
+# For a full list of authors see the git log.
+"""
+This sanitizer maps OSM data to Japanese block addresses.
+It replaces blocknumber and housenumber with housenumber,
+and quarter and neighbourhood with place.
+"""
+
+
+from typing import Callable
+from typing import List, Optional
+
+from nominatim.tokenizer.sanitizers.base import ProcessInfo
+from nominatim.tokenizer.sanitizers.config import SanitizerConfig
+from nominatim.data.place_name import PlaceName
+
+def create(_: SanitizerConfig) -> Callable[[ProcessInfo], None]:
+    """Set up the sanitizer
+    """
+    return tag_japanese
+
+def reconbine_housenumber(
+    new_address: List[PlaceName],
+    tmp_housenumber: Optional[str],
+    tmp_blocknumber: Optional[str]
+) -> List[PlaceName]:
+    """ Recombine the tag of housenumber by using housenumber and blocknumber
+    """
+    if tmp_blocknumber and tmp_housenumber:
+        new_address.append(
+            PlaceName(
+                kind='housenumber',
+                name=f'{tmp_blocknumber}-{tmp_housenumber}',
+                suffix=''
+            )
+        )
+    elif tmp_blocknumber:
+        new_address.append(
+            PlaceName(
+                kind='housenumber',
+                name=tmp_blocknumber,
+                suffix=''
+            )
+        )
+    elif tmp_housenumber:
+        new_address.append(
+            PlaceName(
+                kind='housenumber',
+                name=tmp_housenumber,
+                suffix=''
+            )
+        )
+    return new_address
+
+def reconbine_place(
+    new_address: List[PlaceName],
+    tmp_neighbourhood: Optional[str],
+    tmp_quarter: Optional[str]
+) -> List[PlaceName]:
+    """ Recombine the tag of place by using neighbourhood and quarter
+    """
+    if tmp_neighbourhood and tmp_quarter:
+        new_address.append(
+            PlaceName(
+                kind='place',
+                name=f'{tmp_quarter}{tmp_neighbourhood}',
+                suffix=''
+            )
+        )
+    elif tmp_neighbourhood:
+        new_address.append(
+            PlaceName(
+                kind='place',
+                name=tmp_neighbourhood,
+                suffix=''
+            )
+        )
+    elif tmp_quarter:
+        new_address.append(
+            PlaceName(
+                kind='place',
+                name=tmp_quarter,
+                suffix=''
+            )
+        )
+    return new_address
+def tag_japanese(obj: ProcessInfo) -> None:
+    """Recombine kind of address
+    """
+    if obj.place.country_code != 'jp':
+        return
+    tmp_housenumber = None
+    tmp_blocknumber = None
+    tmp_neighbourhood = None
+    tmp_quarter = None
+
+    new_address = []
+    for item in obj.address:
+        if item.kind == 'housenumber':
+            tmp_housenumber = item.name
+        elif item.kind == 'block_number':
+            tmp_blocknumber = item.name
+        elif item.kind == 'neighbourhood':
+            tmp_neighbourhood = item.name
+        elif item.kind == 'quarter':
+            tmp_quarter = item.name
+        else:
+            new_address.append(item)
+
+    new_address = reconbine_housenumber(new_address, tmp_housenumber, tmp_blocknumber)
+    new_address = reconbine_place(new_address, tmp_neighbourhood, tmp_quarter)
+
+    obj.address = [item for item in new_address if item.name is not None]
index 55b3274a3a9b9f682982ceb464aff947495cef2c..db6c8420869849ac555a952bd027b32297bbe0e8 100644 (file)
@@ -1,14 +1,14 @@
-- "[๐žฅ๐’ ฿€๐–ญ๊ค€๐–ฉ ๐‘“๐‘‘๐‘‹ฐ๐‘„ถ๊ฉ๊˜ แฑ€แญแฎฐแ แŸ แฅ†เผ เป๊งฐแ‚แชแช€แง๐‘ต๊ฏฐแฑ๐‘ฑ๐‘œฐ๐‘›€๐‘™๐‘‡๊ง๊ฃเทฆ๐‘ฆ๏ผ๐Ÿถ๐Ÿ˜๐Ÿฌ๐ŸŽ๐Ÿขโ‚€โ“ฟโ“ชโฐ] > 0"
-- "[๐žฅ‘๐’ก฿๐–ญ‘๊ค๐–ฉก๐‘“‘๐‘‘‘๐‘‹ฑ๐‘„ท๊ฉ‘๊˜กแฑแญ‘แฎฑแ ‘แŸกแฅ‡เผกเป‘๊งฑแ‚‘แช‘แชแง‘๐‘ต‘๊ฏฑแฑ‘๐‘ฑ‘๐‘œฑ๐‘›๐‘™‘๐‘‡‘๊ง‘๊ฃ‘เทง๐‘ง๏ผ‘๐Ÿท๐Ÿ™๐Ÿญ๐Ÿ๐Ÿฃโ‚ยนโ‘ โ‘ดโ’ˆโถโž€โžŠโ“ต] > 1"
-- "[๐žฅ’๐’ข฿‚๐–ญ’๊ค‚๐–ฉข๐‘“’๐‘‘’๐‘‹ฒ๐‘„ธ๊ฉ’๊˜ขแฑ‚แญ’แฎฒแ ’แŸขแฅˆเผขเป’๊งฒแ‚’แช’แช‚แง’๐‘ต’๊ฏฒแฑ’๐‘ฑ’๐‘œฒ๐‘›‚๐‘™’๐‘‡’๊ง’๊ฃ’เทจ๐‘จ๏ผ’๐Ÿธ๐Ÿš๐Ÿฎ๐Ÿ๐Ÿคโ‚‚ยฒโ‘กโ‘ตโ’‰โทโžโž‹โ“ถ] > 2"
-- "[๐žฅ“๐’ฃ฿ƒ๐–ญ“๊คƒ๐–ฉฃ๐‘““๐‘‘“๐‘‹ณ๐‘„น๊ฉ“๊˜ฃแฑƒแญ“แฎณแ “แŸฃแฅ‰เผฃเป“๊งณแ‚“แช“แชƒแง“๐‘ต“๊ฏณแฑ“๐‘ฑ“๐‘œณ๐‘›ƒ๐‘™“๐‘‡“๊ง“๊ฃ“เทฉ๐‘ฉ๏ผ“๐Ÿน๐Ÿ›๐Ÿฏ๐Ÿ‘๐Ÿฅโ‚ƒยณโ‘ขโ‘ถโ’Šโธโž‚โžŒโ“ท] > 3"
-- "[๐žฅ”๐’ค฿„๐–ญ”๊ค„๐–ฉค๐‘“”๐‘‘”๐‘‹ด๐‘„บ๊ฉ”๊˜คแฑ„แญ”แฎดแ ”แŸคแฅŠเผคเป”๊งดแ‚”แช”แช„แง”๐‘ต”๊ฏดแฑ”๐‘ฑ”๐‘œด๐‘›„๐‘™”๐‘‡”๊ง”๊ฃ”เทช๐‘ช๏ผ”๐Ÿบ๐Ÿœ๐Ÿฐ๐Ÿ’๐Ÿฆโ‚„โดโ‘ฃโ‘ทโ’‹โนโžƒโžโ“ธ] > 4"
-- "[๐žฅ•๐’ฅ฿…๐–ญ•๊ค…๐–ฉฅ๐‘“•๐‘‘•๐‘‹ต๐‘„ป๊ฉ•๊˜ฅแฑ…แญ•แฎตแ •แŸฅแฅ‹เผฅเป•๊งตแ‚•แช•แช…แง•๐‘ต•๊ฏตแฑ•๐‘ฑ•๐‘œต๐‘›…๐‘™•๐‘‡•๊ง•๊ฃ•เทซ๐‘ซ๏ผ•๐Ÿป๐Ÿ๐Ÿฑ๐Ÿ“๐Ÿงโ‚…โตโ‘คโ‘ธโ’Œโบโž„โžŽโ“น] > 5"
-- "[๐žฅ–๐’ฆ฿†๐–ญ–๊ค†๐–ฉฆ๐‘“–๐‘‘–๐‘‹ถ๐‘„ผ๊ฉ–๊˜ฆแฑ†แญ–แฎถแ –แŸฆแฅŒเผฆเป–๊งถแ‚–แช–แช†แง–๐‘ต–๊ฏถแฑ–๐‘ฑ–๐‘œถ๐‘›†๐‘™–๐‘‡–๊ง–๊ฃ–เทฌ๐‘ฌ๏ผ–๐Ÿผ๐Ÿž๐Ÿฒ๐Ÿ”๐Ÿจโ‚†โถโ‘ฅโ‘นโ’โปโž…โžโ“บ] > 6"
-- "[๐žฅ—๐’ง฿‡๐–ญ—๊ค‡๐–ฉง๐‘“—๐‘‘—๐‘‹ท๐‘„ฝ๊ฉ—๊˜งแฑ‡แญ—แฎทแ —แŸงแฅเผงเป—๊งทแ‚—แช—แช‡แง—๐‘ต—๊ฏทแฑ—๐‘ฑ—๐‘œท๐‘›‡๐‘™—๐‘‡—๊ง—๊ฃ—เทญ๐‘ญ๏ผ—๐Ÿฝ๐ŸŸ๐Ÿณ๐Ÿ•๐Ÿฉโ‚‡โทโ‘ฆโ‘บโ’Žโผโž†โžโ“ป] > 7"
-- "[๐žฅ˜๐’จ฿ˆ๐–ญ˜๊คˆ๐–ฉจ๐‘“˜๐‘‘˜๐‘‹ธ๐‘„พ๊ฉ˜๊˜จแฑˆแญ˜แฎธแ ˜แŸจแฅŽเผจเป˜๊งธแ‚˜แช˜แชˆแง˜๐‘ต˜๊ฏธแฑ˜๐‘ฑ˜๐‘œธ๐‘›ˆ๐‘™˜๐‘‡˜๊ง˜๊ฃ˜เทฎ๐‘ฎ๏ผ˜๐Ÿพ๐Ÿ ๐Ÿด๐Ÿ–๐Ÿชโ‚ˆโธโ‘งโ‘ปโ’โฝโž‡โž‘โ“ผ] > 8"
-- "[๐žฅ™๐’ฉ฿‰๐–ญ™๊ค‰๐–ฉฉ๐‘“™๐‘‘™๐‘‹น๐‘„ฟ๊ฉ™๊˜ฉแฑ‰แญ™แฎนแ ™แŸฉแฅเผฉเป™๊งนแ‚™แช™แช‰แง™๐‘ต™๊ฏนแฑ™๐‘ฑ™๐‘œน๐‘›‰๐‘™™๐‘‡™๊ง™๊ฃ™เทฏ๐‘ฏ๏ผ™๐Ÿฟ๐Ÿก๐Ÿต๐Ÿ—๐Ÿซโ‚‰โนโ‘จโ‘ผโ’โพโžˆโž’โ“ฝ] > 9"
-- "[๐‘œบโ‘ฉโ‘ฝโ’‘โฟโž‰โž“โ“พ] > '10'"
+- "[๐žฅ๐’ ฿€๐–ญ๊ค€๐–ฉ ๐‘“๐‘‘๐‘‹ฐ๐‘„ถ๊ฉ๊˜ แฑ€แญแฎฐแ แŸ แฅ†เผ เป๊งฐแ‚แชแช€แง๐‘ต๊ฏฐแฑ๐‘ฑ๐‘œฐ๐‘›€๐‘™๐‘‡๊ง๊ฃเทฆ๐‘ฆ๏ผ๐Ÿถ๐Ÿ˜๐Ÿฌ๐ŸŽ๐Ÿขโ‚€โ“ฟโ“ชโฐ้›ถ] > 0"
+- "[๐žฅ‘๐’ก฿๐–ญ‘๊ค๐–ฉก๐‘“‘๐‘‘‘๐‘‹ฑ๐‘„ท๊ฉ‘๊˜กแฑแญ‘แฎฑแ ‘แŸกแฅ‡เผกเป‘๊งฑแ‚‘แช‘แชแง‘๐‘ต‘๊ฏฑแฑ‘๐‘ฑ‘๐‘œฑ๐‘›๐‘™‘๐‘‡‘๊ง‘๊ฃ‘เทง๐‘ง๏ผ‘๐Ÿท๐Ÿ™๐Ÿญ๐Ÿ๐Ÿฃโ‚ยนโ‘ โ‘ดโ’ˆโถโž€โžŠโ“ตไธ€] > 1"
+- "[๐žฅ’๐’ข฿‚๐–ญ’๊ค‚๐–ฉข๐‘“’๐‘‘’๐‘‹ฒ๐‘„ธ๊ฉ’๊˜ขแฑ‚แญ’แฎฒแ ’แŸขแฅˆเผขเป’๊งฒแ‚’แช’แช‚แง’๐‘ต’๊ฏฒแฑ’๐‘ฑ’๐‘œฒ๐‘›‚๐‘™’๐‘‡’๊ง’๊ฃ’เทจ๐‘จ๏ผ’๐Ÿธ๐Ÿš๐Ÿฎ๐Ÿ๐Ÿคโ‚‚ยฒโ‘กโ‘ตโ’‰โทโžโž‹โ“ถไบŒ] > 2"
+- "[๐žฅ“๐’ฃ฿ƒ๐–ญ“๊คƒ๐–ฉฃ๐‘““๐‘‘“๐‘‹ณ๐‘„น๊ฉ“๊˜ฃแฑƒแญ“แฎณแ “แŸฃแฅ‰เผฃเป“๊งณแ‚“แช“แชƒแง“๐‘ต“๊ฏณแฑ“๐‘ฑ“๐‘œณ๐‘›ƒ๐‘™“๐‘‡“๊ง“๊ฃ“เทฉ๐‘ฉ๏ผ“๐Ÿน๐Ÿ›๐Ÿฏ๐Ÿ‘๐Ÿฅโ‚ƒยณโ‘ขโ‘ถโ’Šโธโž‚โžŒโ“ทไธ‰] > 3"
+- "[๐žฅ”๐’ค฿„๐–ญ”๊ค„๐–ฉค๐‘“”๐‘‘”๐‘‹ด๐‘„บ๊ฉ”๊˜คแฑ„แญ”แฎดแ ”แŸคแฅŠเผคเป”๊งดแ‚”แช”แช„แง”๐‘ต”๊ฏดแฑ”๐‘ฑ”๐‘œด๐‘›„๐‘™”๐‘‡”๊ง”๊ฃ”เทช๐‘ช๏ผ”๐Ÿบ๐Ÿœ๐Ÿฐ๐Ÿ’๐Ÿฆโ‚„โดโ‘ฃโ‘ทโ’‹โนโžƒโžโ“ธๅ››] > 4"
+- "[๐žฅ•๐’ฅ฿…๐–ญ•๊ค…๐–ฉฅ๐‘“•๐‘‘•๐‘‹ต๐‘„ป๊ฉ•๊˜ฅแฑ…แญ•แฎตแ •แŸฅแฅ‹เผฅเป•๊งตแ‚•แช•แช…แง•๐‘ต•๊ฏตแฑ•๐‘ฑ•๐‘œต๐‘›…๐‘™•๐‘‡•๊ง•๊ฃ•เทซ๐‘ซ๏ผ•๐Ÿป๐Ÿ๐Ÿฑ๐Ÿ“๐Ÿงโ‚…โตโ‘คโ‘ธโ’Œโบโž„โžŽโ“นไบ”] > 5"
+- "[๐žฅ–๐’ฆ฿†๐–ญ–๊ค†๐–ฉฆ๐‘“–๐‘‘–๐‘‹ถ๐‘„ผ๊ฉ–๊˜ฆแฑ†แญ–แฎถแ –แŸฆแฅŒเผฆเป–๊งถแ‚–แช–แช†แง–๐‘ต–๊ฏถแฑ–๐‘ฑ–๐‘œถ๐‘›†๐‘™–๐‘‡–๊ง–๊ฃ–เทฌ๐‘ฌ๏ผ–๐Ÿผ๐Ÿž๐Ÿฒ๐Ÿ”๐Ÿจโ‚†โถโ‘ฅโ‘นโ’โปโž…โžโ“บๅ…ญ] > 6"
+- "[๐žฅ—๐’ง฿‡๐–ญ—๊ค‡๐–ฉง๐‘“—๐‘‘—๐‘‹ท๐‘„ฝ๊ฉ—๊˜งแฑ‡แญ—แฎทแ —แŸงแฅเผงเป—๊งทแ‚—แช—แช‡แง—๐‘ต—๊ฏทแฑ—๐‘ฑ—๐‘œท๐‘›‡๐‘™—๐‘‡—๊ง—๊ฃ—เทญ๐‘ญ๏ผ—๐Ÿฝ๐ŸŸ๐Ÿณ๐Ÿ•๐Ÿฉโ‚‡โทโ‘ฆโ‘บโ’Žโผโž†โžโ“ปไธƒ] > 7"
+- "[๐žฅ˜๐’จ฿ˆ๐–ญ˜๊คˆ๐–ฉจ๐‘“˜๐‘‘˜๐‘‹ธ๐‘„พ๊ฉ˜๊˜จแฑˆแญ˜แฎธแ ˜แŸจแฅŽเผจเป˜๊งธแ‚˜แช˜แชˆแง˜๐‘ต˜๊ฏธแฑ˜๐‘ฑ˜๐‘œธ๐‘›ˆ๐‘™˜๐‘‡˜๊ง˜๊ฃ˜เทฎ๐‘ฎ๏ผ˜๐Ÿพ๐Ÿ ๐Ÿด๐Ÿ–๐Ÿชโ‚ˆโธโ‘งโ‘ปโ’โฝโž‡โž‘โ“ผๅ…ซ] > 8"
+- "[๐žฅ™๐’ฉ฿‰๐–ญ™๊ค‰๐–ฉฉ๐‘“™๐‘‘™๐‘‹น๐‘„ฟ๊ฉ™๊˜ฉแฑ‰แญ™แฎนแ ™แŸฉแฅเผฉเป™๊งนแ‚™แช™แช‰แง™๐‘ต™๊ฏนแฑ™๐‘ฑ™๐‘œน๐‘›‰๐‘™™๐‘‡™๊ง™๊ฃ™เทฏ๐‘ฏ๏ผ™๐Ÿฟ๐Ÿก๐Ÿต๐Ÿ—๐Ÿซโ‚‰โนโ‘จโ‘ผโ’โพโžˆโž’โ“ฝไน] > 9"
+- "[๐‘œบโ‘ฉโ‘ฝโ’‘โฟโž‰โž“โ“พๅ] > '10'"
 - "[โ‘ชโ‘พโ’’โ“ซ] > '11'"
 - "[โ‘ซโ‘ฟโ’“โ“ฌ] > '12'"
 - "[โ‘ฌโ’€โ’”โ“ญ] > '13'"
index 1fa467befebfa4c5977103d6731064dd760791ff..c5a809c68319f3095f2d9b4bf06c6456ff4b2b05 100644 (file)
@@ -45,6 +45,7 @@ sanitizers:
       whitelist: [bg,ca,cs,da,de,el,en,es,et,eu,fi,fr,gl,hu,it,ja,mg,ms,nl,no,pl,pt,ro,ru,sk,sl,sv,tr,uk,vi]
       use-defaults: all
       mode: append
+    - step: tag-japanese
 token-analysis:
     - analyzer: generic
     - id: "@housenumber"
diff --git a/test/bdd/db/query/japanese.feature b/test/bdd/db/query/japanese.feature
new file mode 100644 (file)
index 0000000..4960c50
--- /dev/null
@@ -0,0 +1,30 @@
+@DB
+Feature: Searches in Japan
+    Test specifically for searches of Japanese addresses and in Japanese language.
+    @fail-legacy
+    Scenario: A block house-number is parented to the neighbourhood
+        Given the grid with origin JP
+          | 1 |   |   |   | 2 |
+          |   | 3 |   |   |   |
+          |   |   | 9 |   |   |
+          |   |   |   | 6 |   |
+        And the places
+          | osm | class   | type        | name       | geometry |
+          | W1  | highway | residential | ้›‰ๅญๆฉ‹้€šใ‚Š | 1,2      |
+        And the places
+          | osm | class   | type       | housenr | addr+block_number | addr+neighbourhood | geometry |
+          | N3  | amenity | restaurant | 2       | 6                 | 2ไธ็›ฎ              | 3        |
+        And the places
+          | osm | class | type          | name  | geometry |
+          | N9  | place | neighbourhood | 2ไธ็›ฎ | 9        |
+        And the places
+          | osm | class | type    | name | geometry |
+          | N6  | place | quarter | ๅŠ ็€ฌ | 6        |
+        When importing
+        Then placex contains
+          | object | parent_place_id |
+          | N3     | N9              |
+        When sending search query "2ไธ็›ฎ 6-2"
+        Then results contain
+          | osm |
+          | N3  |
diff --git a/test/python/tokenizer/sanitizers/test_tag_japanese.py b/test/python/tokenizer/sanitizers/test_tag_japanese.py
new file mode 100644 (file)
index 0000000..946f137
--- /dev/null
@@ -0,0 +1,80 @@
+from nominatim.data.place_info import PlaceInfo
+from nominatim.data.place_name import PlaceName
+from nominatim.tokenizer.place_sanitizer import PlaceSanitizer
+from typing import Mapping, Optional, List
+import pytest
+
+class TestTagJapanese:
+    @pytest.fixture(autouse=True)
+    def setup_country(self, def_config):
+        self.config = def_config
+
+    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]
+        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')]
+
+    def test_housenumber(self):
+        res = self.run_sanitizer_on('address', housenumber='2')
+        assert res == [('2','housenumber')]
+
+    def test_blocknumber(self):
+        res = self.run_sanitizer_on('address', block_number='6')
+        assert res == [('6','housenumber')]
+
+    def test_neighbourhood(self):
+        res = self.run_sanitizer_on('address', neighbourhood='8')
+        assert res == [('8','place')]
+
+    def test_quarter(self):
+        res = self.run_sanitizer_on('address', quarter='kase')
+        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')]
+
+    def test_quarter_neighbourhood(self):
+        res = self.run_sanitizer_on('address', quarter='kase', neighbourhood='8')
+        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')]
+
+    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')]
+
+    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')]
+
+    def test_blocknumber_quarter(self):
+        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')]
+
+    def test_housenumber_quarter_neighbourhood(self):
+        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')]
+
+    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')]