jageocoder 2.1.6__tar.gz → 2.1.7.dev2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {jageocoder-2.1.6 → jageocoder-2.1.7.dev2}/PKG-INFO +11 -4
- {jageocoder-2.1.6 → jageocoder-2.1.7.dev2}/README.md +9 -3
- {jageocoder-2.1.6 → jageocoder-2.1.7.dev2}/jageocoder/__init__.py +8 -2
- {jageocoder-2.1.6 → jageocoder-2.1.7.dev2}/jageocoder/address.py +43 -0
- {jageocoder-2.1.6 → jageocoder-2.1.7.dev2}/jageocoder/module.py +114 -0
- {jageocoder-2.1.6 → jageocoder-2.1.7.dev2}/jageocoder/node.py +39 -3
- {jageocoder-2.1.6 → jageocoder-2.1.7.dev2}/jageocoder/remote.py +93 -49
- {jageocoder-2.1.6 → jageocoder-2.1.7.dev2}/jageocoder/rtree.py +25 -5
- {jageocoder-2.1.6 → jageocoder-2.1.7.dev2}/jageocoder/tree.py +167 -427
- {jageocoder-2.1.6 → jageocoder-2.1.7.dev2}/pyproject.toml +2 -1
- jageocoder-2.1.6/jageocoder/aliases.json +0 -72
- {jageocoder-2.1.6 → jageocoder-2.1.7.dev2}/LICENSE +0 -0
- {jageocoder-2.1.6 → jageocoder-2.1.7.dev2}/jageocoder/__main__.py +0 -0
- {jageocoder-2.1.6 → jageocoder-2.1.7.dev2}/jageocoder/aza_master.py +0 -0
- {jageocoder-2.1.6 → jageocoder-2.1.7.dev2}/jageocoder/dataset.py +0 -0
- {jageocoder-2.1.6 → jageocoder-2.1.7.dev2}/jageocoder/exceptions.py +0 -0
- {jageocoder-2.1.6 → jageocoder-2.1.7.dev2}/jageocoder/itaiji.py +0 -0
- {jageocoder-2.1.6 → jageocoder-2.1.7.dev2}/jageocoder/itaiji_dic.json +0 -0
- {jageocoder-2.1.6 → jageocoder-2.1.7.dev2}/jageocoder/result.py +0 -0
- {jageocoder-2.1.6 → jageocoder-2.1.7.dev2}/jageocoder/strlib.py +0 -0
- {jageocoder-2.1.6 → jageocoder-2.1.7.dev2}/jageocoder/trie.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: jageocoder
|
|
3
|
-
Version: 2.1.
|
|
3
|
+
Version: 2.1.7.dev2
|
|
4
4
|
Summary: A Japanese-address geocoder for Python.
|
|
5
5
|
Home-page: https://github.com/t-sagara/jageocoder/
|
|
6
6
|
License: The MIT License
|
|
@@ -29,6 +29,7 @@ Requires-Dist: jaconv (>=0.3.4,<0.4.0)
|
|
|
29
29
|
Requires-Dist: marisa-trie (>=0.7.8)
|
|
30
30
|
Requires-Dist: portabletab (>=0.3.3)
|
|
31
31
|
Requires-Dist: pycapnp
|
|
32
|
+
Requires-Dist: requests
|
|
32
33
|
Requires-Dist: rtree (>=1.0.0,<2.0.0)
|
|
33
34
|
Requires-Dist: tqdm (>=4.00.0,<5.0.0)
|
|
34
35
|
Requires-Dist: urllib3 (>=2.0.6)
|
|
@@ -44,7 +45,7 @@ This is a Python port of the Japanese-address geocoder `DAMS` used in CSIS at th
|
|
|
44
45
|
|
|
45
46
|
# Getting Started
|
|
46
47
|
|
|
47
|
-
This package provides address-geocoding functionality for Python programs. The basic usage is to specify a dictionary with `init()` then call `search()` to get geocoding results.
|
|
48
|
+
This package provides address-geocoding and reverse-geocoding functionality for Python programs. The basic usage is to specify a dictionary with `init()` then call `search()` to get geocoding results.
|
|
48
49
|
|
|
49
50
|
```python
|
|
50
51
|
>>> import jageocoder
|
|
@@ -69,11 +70,11 @@ To use Jageocoder, you need to install the "Dictionary Database" on the same mac
|
|
|
69
70
|
|
|
70
71
|
### Install Dictionary Database
|
|
71
72
|
|
|
72
|
-
|
|
73
|
+
When a dictionary database is installed, large amounts of data can be processed at high speed. A database covering addresses in Japan requires 25 GB or more of storage.
|
|
73
74
|
|
|
74
75
|
- Download an address database file compatible with that version from [here](https://www.info-proto.com/static/jageocoder/latest/v2/)
|
|
75
76
|
|
|
76
|
-
|
|
77
|
+
jageocoder download-dictionary https://www.info-proto.com/static/jageocoder/latest/v2/jukyo_all_v21.zip
|
|
77
78
|
|
|
78
79
|
- Install the dictionary with `install-dictionary` command
|
|
79
80
|
|
|
@@ -299,6 +300,12 @@ the block number (○番) contained therein.
|
|
|
299
300
|
['10番', '11番', '1番', '2番', '3番', '4番', '5番', '6番', '7番', '8番', '9番']
|
|
300
301
|
```
|
|
301
302
|
|
|
303
|
+
# For developers
|
|
304
|
+
|
|
305
|
+
## Documentation
|
|
306
|
+
|
|
307
|
+
Tutorials and references are [here](https://jageocoder.readthedocs.io/ja/latest/).
|
|
308
|
+
|
|
302
309
|
## Create your own dictionary
|
|
303
310
|
|
|
304
311
|
Consider using [jageocoder-converter](https://github.com/t-sagara/jageocoder-converter).
|
|
@@ -6,7 +6,7 @@ This is a Python port of the Japanese-address geocoder `DAMS` used in CSIS at th
|
|
|
6
6
|
|
|
7
7
|
# Getting Started
|
|
8
8
|
|
|
9
|
-
This package provides address-geocoding functionality for Python programs. The basic usage is to specify a dictionary with `init()` then call `search()` to get geocoding results.
|
|
9
|
+
This package provides address-geocoding and reverse-geocoding functionality for Python programs. The basic usage is to specify a dictionary with `init()` then call `search()` to get geocoding results.
|
|
10
10
|
|
|
11
11
|
```python
|
|
12
12
|
>>> import jageocoder
|
|
@@ -31,11 +31,11 @@ To use Jageocoder, you need to install the "Dictionary Database" on the same mac
|
|
|
31
31
|
|
|
32
32
|
### Install Dictionary Database
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
When a dictionary database is installed, large amounts of data can be processed at high speed. A database covering addresses in Japan requires 25 GB or more of storage.
|
|
35
35
|
|
|
36
36
|
- Download an address database file compatible with that version from [here](https://www.info-proto.com/static/jageocoder/latest/v2/)
|
|
37
37
|
|
|
38
|
-
|
|
38
|
+
jageocoder download-dictionary https://www.info-proto.com/static/jageocoder/latest/v2/jukyo_all_v21.zip
|
|
39
39
|
|
|
40
40
|
- Install the dictionary with `install-dictionary` command
|
|
41
41
|
|
|
@@ -261,6 +261,12 @@ the block number (○番) contained therein.
|
|
|
261
261
|
['10番', '11番', '1番', '2番', '3番', '4番', '5番', '6番', '7番', '8番', '9番']
|
|
262
262
|
```
|
|
263
263
|
|
|
264
|
+
# For developers
|
|
265
|
+
|
|
266
|
+
## Documentation
|
|
267
|
+
|
|
268
|
+
Tutorials and references are [here](https://jageocoder.readthedocs.io/ja/latest/).
|
|
269
|
+
|
|
264
270
|
## Create your own dictionary
|
|
265
271
|
|
|
266
272
|
Consider using [jageocoder-converter](https://github.com/t-sagara/jageocoder-converter).
|
|
@@ -19,7 +19,7 @@ running the following steps.
|
|
|
19
19
|
>>> jageocoder.searchNode('<Japanese-address>')
|
|
20
20
|
"""
|
|
21
21
|
|
|
22
|
-
__version__ = '2.1.
|
|
22
|
+
__version__ = '2.1.7.dev2' # The package version
|
|
23
23
|
__dictionary_version__ = '20230927' # Compatible dictionary version
|
|
24
24
|
__author__ = 'Takeshi Sagara <sagara@info-proto.com>'
|
|
25
25
|
|
|
@@ -37,6 +37,10 @@ __all__ = [
|
|
|
37
37
|
'create_trie_index',
|
|
38
38
|
'search',
|
|
39
39
|
'searchNode',
|
|
40
|
+
'search_by_machiaza_id',
|
|
41
|
+
'search_by_postcode',
|
|
42
|
+
'search_by_citycode',
|
|
43
|
+
'search_by_prefcode',
|
|
40
44
|
'reverse',
|
|
41
45
|
'version',
|
|
42
46
|
'dictionary_version',
|
|
@@ -48,5 +52,7 @@ from jageocoder.module import init, free, is_initialized, \
|
|
|
48
52
|
get_db_dir, set_search_config, get_search_config, \
|
|
49
53
|
get_module_tree, download_dictionary, install_dictionary, \
|
|
50
54
|
uninstall_dictionary, create_trie_index, \
|
|
51
|
-
search, searchNode,
|
|
55
|
+
search, searchNode, search_by_machiaza_id, search_by_postcode, \
|
|
56
|
+
search_by_citycode, search_by_prefcode, reverse, \
|
|
57
|
+
version, dictionary_version, \
|
|
52
58
|
installed_dictionary_version, installed_dictionary_readme # noqa: F401
|
|
@@ -30,6 +30,49 @@ class AddressLevel(object):
|
|
|
30
30
|
BLOCK = 7
|
|
31
31
|
BLD = 8
|
|
32
32
|
|
|
33
|
+
@classmethod
|
|
34
|
+
def levelname(cls, level: int) -> str:
|
|
35
|
+
"""
|
|
36
|
+
Returns the Japanese notation of the address level.
|
|
37
|
+
|
|
38
|
+
Parameters
|
|
39
|
+
----------
|
|
40
|
+
level: int
|
|
41
|
+
The address level.
|
|
42
|
+
|
|
43
|
+
Returns
|
|
44
|
+
-------
|
|
45
|
+
str
|
|
46
|
+
"""
|
|
47
|
+
if level == cls.PREF:
|
|
48
|
+
return "都道府県"
|
|
49
|
+
|
|
50
|
+
if level == cls.COUNTY:
|
|
51
|
+
return "郡"
|
|
52
|
+
|
|
53
|
+
if level == cls.CITY:
|
|
54
|
+
return "市町村・特別区"
|
|
55
|
+
|
|
56
|
+
if level == cls.WARD:
|
|
57
|
+
return "政令市の区"
|
|
58
|
+
|
|
59
|
+
if level == cls.OAZA:
|
|
60
|
+
return "町域・大字"
|
|
61
|
+
|
|
62
|
+
if level == cls.AZA:
|
|
63
|
+
return "丁目・小字"
|
|
64
|
+
|
|
65
|
+
if level == cls.BLOCK:
|
|
66
|
+
return "街区・道路・地番"
|
|
67
|
+
|
|
68
|
+
if level == cls.BLD:
|
|
69
|
+
return "建物・枝番"
|
|
70
|
+
|
|
71
|
+
if level == cls.UNDEFINED:
|
|
72
|
+
return "未定義"
|
|
73
|
+
|
|
74
|
+
return "不明"
|
|
75
|
+
|
|
33
76
|
@classmethod
|
|
34
77
|
def guess(cls, name, parent, trigger):
|
|
35
78
|
"""
|
|
@@ -482,6 +482,120 @@ def reverse(
|
|
|
482
482
|
return _tree.reverse(x, y, level, as_dict)
|
|
483
483
|
|
|
484
484
|
|
|
485
|
+
def search_by_machiaza_id(
|
|
486
|
+
id: str
|
|
487
|
+
) -> list:
|
|
488
|
+
"""
|
|
489
|
+
Finds the corresponding address nodes from the "machiaza-id" of
|
|
490
|
+
the address base registry.
|
|
491
|
+
|
|
492
|
+
Parameters
|
|
493
|
+
----------
|
|
494
|
+
id: str
|
|
495
|
+
Machiaza-id.
|
|
496
|
+
|
|
497
|
+
Returns
|
|
498
|
+
-------
|
|
499
|
+
List[AddressNode]
|
|
500
|
+
|
|
501
|
+
Notes
|
|
502
|
+
-----
|
|
503
|
+
- If "id" is 12 characters, the first 5 characters are considered the JISX0402 code.
|
|
504
|
+
- If "id" is 13 characters, the first 6 characters are considered the lg-code.
|
|
505
|
+
- In either of the above cases, search for the address node whose machiaza-id
|
|
506
|
+
matches the rest 7 characters in the corresponding municipality.
|
|
507
|
+
- Otherwise, it searches for address nodes whose machiaza-id matches "id"
|
|
508
|
+
from all municipalities. In this case, aza_id must be 7 characters.
|
|
509
|
+
"""
|
|
510
|
+
if not is_initialized():
|
|
511
|
+
raise JageocoderError("Not initialized. Call 'init()' first.")
|
|
512
|
+
|
|
513
|
+
global _tree
|
|
514
|
+
return _tree.search_by_machiaza_id(id)
|
|
515
|
+
|
|
516
|
+
|
|
517
|
+
def search_by_postcode(
|
|
518
|
+
code: str
|
|
519
|
+
) -> list:
|
|
520
|
+
"""
|
|
521
|
+
Finds the corresponding address node from a postcode.
|
|
522
|
+
|
|
523
|
+
Parameters
|
|
524
|
+
----------
|
|
525
|
+
code: str
|
|
526
|
+
The postal code as defined by the Japan Post.
|
|
527
|
+
|
|
528
|
+
Returns
|
|
529
|
+
-------
|
|
530
|
+
List[AddressNode]
|
|
531
|
+
|
|
532
|
+
Notes
|
|
533
|
+
-----
|
|
534
|
+
- The "code" must be 7 characters.
|
|
535
|
+
"""
|
|
536
|
+
if not is_initialized():
|
|
537
|
+
raise JageocoderError("Not initialized. Call 'init()' first.")
|
|
538
|
+
|
|
539
|
+
global _tree
|
|
540
|
+
return _tree.search_by_postcode(code)
|
|
541
|
+
|
|
542
|
+
|
|
543
|
+
def search_by_prefcode(
|
|
544
|
+
code: str
|
|
545
|
+
) -> list:
|
|
546
|
+
"""
|
|
547
|
+
Finds the corresponding address nodes from the JISX0401 code
|
|
548
|
+
or the prefacture's local-government code.
|
|
549
|
+
|
|
550
|
+
Parameters
|
|
551
|
+
----------
|
|
552
|
+
code: str
|
|
553
|
+
Prefacture code as defined in JISX0401, of local government code defined by MIC.
|
|
554
|
+
|
|
555
|
+
Returns
|
|
556
|
+
-------
|
|
557
|
+
List[AddressNode]
|
|
558
|
+
|
|
559
|
+
Notes
|
|
560
|
+
-----
|
|
561
|
+
- If "code" is 2 characters, the code is considered the JISX0401 code.
|
|
562
|
+
- If "code" is 6 characters, the code is considered the local-govenment code.
|
|
563
|
+
"""
|
|
564
|
+
if not is_initialized():
|
|
565
|
+
raise JageocoderError("Not initialized. Call 'init()' first.")
|
|
566
|
+
|
|
567
|
+
global _tree
|
|
568
|
+
return _tree.search_by_prefcode(code)
|
|
569
|
+
|
|
570
|
+
|
|
571
|
+
def search_by_citycode(
|
|
572
|
+
code: str
|
|
573
|
+
) -> list:
|
|
574
|
+
"""
|
|
575
|
+
Finds the corresponding address nodes from the JISX0402 code
|
|
576
|
+
or the local-government code.
|
|
577
|
+
|
|
578
|
+
Parameters
|
|
579
|
+
----------
|
|
580
|
+
code: str
|
|
581
|
+
City code as defined in JISX0402, of local government code defined by MIC.
|
|
582
|
+
|
|
583
|
+
Returns
|
|
584
|
+
-------
|
|
585
|
+
List[AddressNode]
|
|
586
|
+
|
|
587
|
+
Notes
|
|
588
|
+
-----
|
|
589
|
+
- If "code" is 5 characters, the code is considered the JISX0402 code.
|
|
590
|
+
- If "code" is 6 characters, the code is considered the local-govenment code.
|
|
591
|
+
"""
|
|
592
|
+
if not is_initialized():
|
|
593
|
+
raise JageocoderError("Not initialized. Call 'init()' first.")
|
|
594
|
+
|
|
595
|
+
global _tree
|
|
596
|
+
return _tree.search_by_citycode(code)
|
|
597
|
+
|
|
598
|
+
|
|
485
599
|
def create_trie_index() -> None:
|
|
486
600
|
"""
|
|
487
601
|
Create the TRIE index from the database file.
|
|
@@ -212,10 +212,16 @@ class AddressNode(object):
|
|
|
212
212
|
def dataset(self):
|
|
213
213
|
"""
|
|
214
214
|
Get dataset record.
|
|
215
|
-
|
|
216
215
|
"""
|
|
217
216
|
return self.table.datasets.get(id=self.priority)
|
|
218
217
|
|
|
218
|
+
@property
|
|
219
|
+
def levelname(self) -> str:
|
|
220
|
+
"""
|
|
221
|
+
Get level by name.
|
|
222
|
+
"""
|
|
223
|
+
return AddressLevel.levelname(self.level)
|
|
224
|
+
|
|
219
225
|
@classmethod
|
|
220
226
|
def from_record(cls, record) -> AddressNode:
|
|
221
227
|
"""
|
|
@@ -1252,6 +1258,28 @@ class AddressNode(object):
|
|
|
1252
1258
|
}
|
|
1253
1259
|
}
|
|
1254
1260
|
|
|
1261
|
+
def to_json(self):
|
|
1262
|
+
"""
|
|
1263
|
+
Convert node to JSONable dict for data transfer.
|
|
1264
|
+
|
|
1265
|
+
Notes
|
|
1266
|
+
-----
|
|
1267
|
+
- Different from the 'as_dict' method, this method includes
|
|
1268
|
+
all attributes in the database, such as 'parent_id'.
|
|
1269
|
+
"""
|
|
1270
|
+
return {
|
|
1271
|
+
"id": self.id,
|
|
1272
|
+
"name": self.name,
|
|
1273
|
+
"name_index": self.name_index,
|
|
1274
|
+
"x": self.x,
|
|
1275
|
+
"y": self.y,
|
|
1276
|
+
"level": self.level,
|
|
1277
|
+
"priority": self.priority,
|
|
1278
|
+
"note": self.note,
|
|
1279
|
+
"parent_id": self.parent_id,
|
|
1280
|
+
"sibling_id": self.sibling_id,
|
|
1281
|
+
}
|
|
1282
|
+
|
|
1255
1283
|
def get_fullname(
|
|
1256
1284
|
self,
|
|
1257
1285
|
delimiter: Optional[str] = None,
|
|
@@ -1300,7 +1328,7 @@ class AddressNode(object):
|
|
|
1300
1328
|
|
|
1301
1329
|
return nodes
|
|
1302
1330
|
|
|
1303
|
-
def get_nodes_by_level(self):
|
|
1331
|
+
def get_nodes_by_level(self) -> List[AddressNode | None]:
|
|
1304
1332
|
"""
|
|
1305
1333
|
The method returns an array of this node and its upper nodes.
|
|
1306
1334
|
The Nth node of the array contains the node corresponding
|
|
@@ -1508,6 +1536,7 @@ class AddressNode(object):
|
|
|
1508
1536
|
def get_aza_names(
|
|
1509
1537
|
self,
|
|
1510
1538
|
tree: Optional[AddressTree] = None,
|
|
1539
|
+
levelname: Optional[bool] = False,
|
|
1511
1540
|
) -> list:
|
|
1512
1541
|
"""
|
|
1513
1542
|
Returns representation of Aza node containing this node.
|
|
@@ -1516,6 +1545,8 @@ class AddressNode(object):
|
|
|
1516
1545
|
----------
|
|
1517
1546
|
tree: AddressTree, optional
|
|
1518
1547
|
The tree containing this node.
|
|
1548
|
+
levelname: bool, optional
|
|
1549
|
+
If true, Returns the address level by name, not by number.
|
|
1519
1550
|
|
|
1520
1551
|
Returns
|
|
1521
1552
|
-------
|
|
@@ -1527,7 +1558,12 @@ class AddressNode(object):
|
|
|
1527
1558
|
"""
|
|
1528
1559
|
aza_record = self.get_aza_record(tree)
|
|
1529
1560
|
if aza_record:
|
|
1530
|
-
|
|
1561
|
+
results = json.loads(aza_record.names)
|
|
1562
|
+
if levelname:
|
|
1563
|
+
for i in range(len(results)):
|
|
1564
|
+
results[i][0] = AddressLevel.levelname(results[i][0])
|
|
1565
|
+
|
|
1566
|
+
return results
|
|
1531
1567
|
|
|
1532
1568
|
return []
|
|
1533
1569
|
|
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
from functools import lru_cache
|
|
2
2
|
import json
|
|
3
|
+
from logging import getLogger
|
|
3
4
|
import os
|
|
4
5
|
import requests
|
|
5
|
-
from typing import Any, List, Optional, Union
|
|
6
|
+
from typing import Any, List, NoReturn, Optional, Union
|
|
6
7
|
import uuid
|
|
7
8
|
|
|
8
9
|
from jageocoder.address import AddressLevel
|
|
9
10
|
from jageocoder.exceptions import RemoteTreeException
|
|
10
11
|
from jageocoder.node import AddressNode
|
|
11
12
|
from jageocoder.result import Result
|
|
12
|
-
from jageocoder.tree import LRU
|
|
13
|
+
from jageocoder.tree import AddressTree, LRU
|
|
13
14
|
|
|
14
15
|
|
|
16
|
+
logger = getLogger(__name__)
|
|
15
17
|
_session = None
|
|
16
18
|
|
|
17
19
|
|
|
@@ -28,8 +30,13 @@ def _json_request(
|
|
|
28
30
|
"id": str(uuid.uuid4()),
|
|
29
31
|
}
|
|
30
32
|
if _session is None:
|
|
33
|
+
logger.debug("Start a new HTTP session with the remote tree.")
|
|
31
34
|
_session = requests.Session()
|
|
32
35
|
|
|
36
|
+
logger.debug(
|
|
37
|
+
"Send JSON-RPC request ---\n" +
|
|
38
|
+
json.dumps(payload, indent=2, ensure_ascii=False)
|
|
39
|
+
)
|
|
33
40
|
response = _session.post(
|
|
34
41
|
url=url,
|
|
35
42
|
data=json.dumps(payload),
|
|
@@ -39,6 +46,11 @@ def _json_request(
|
|
|
39
46
|
if "error" in response:
|
|
40
47
|
raise RemoteTreeException(response["error"])
|
|
41
48
|
|
|
49
|
+
logger.debug(
|
|
50
|
+
"Receive JSON-RPC response ---\n" +
|
|
51
|
+
json.dumps(response["result"], indent=2, ensure_ascii=False)
|
|
52
|
+
)
|
|
53
|
+
|
|
42
54
|
return response["result"]
|
|
43
55
|
|
|
44
56
|
|
|
@@ -72,6 +84,7 @@ class RemoteNodeTable(object):
|
|
|
72
84
|
self.datasets = RemoteDataset(url=url)
|
|
73
85
|
self.cache = LRU()
|
|
74
86
|
self.server_signature = None
|
|
87
|
+
self.mode = 'r' # Always read only
|
|
75
88
|
|
|
76
89
|
def update_server_signature(self) -> str:
|
|
77
90
|
"""
|
|
@@ -97,7 +110,7 @@ class RemoteNodeTable(object):
|
|
|
97
110
|
|
|
98
111
|
def get_record(self, pos: int) -> AddressNode:
|
|
99
112
|
"""
|
|
100
|
-
Get the record at the specified position
|
|
113
|
+
Get the record at the specified position from the remote server
|
|
101
114
|
and convert it to AddressNode object.
|
|
102
115
|
|
|
103
116
|
Parameters
|
|
@@ -123,8 +136,56 @@ class RemoteNodeTable(object):
|
|
|
123
136
|
self.cache[pos] = node
|
|
124
137
|
return node
|
|
125
138
|
|
|
139
|
+
def search_records_on(
|
|
140
|
+
self,
|
|
141
|
+
attr: str,
|
|
142
|
+
value: str,
|
|
143
|
+
funcname: str = "get") -> list:
|
|
144
|
+
"""
|
|
145
|
+
Search value from the table on the specified attribute on the remote server.
|
|
146
|
+
|
|
147
|
+
Paramters
|
|
148
|
+
---------
|
|
149
|
+
attr: str
|
|
150
|
+
The name of target attribute.
|
|
151
|
+
value: str
|
|
152
|
+
The target value.
|
|
153
|
+
funcname: str
|
|
154
|
+
The name of search method.
|
|
155
|
+
- "get" searches for records that exactly match the value.
|
|
156
|
+
- "prefixes" searches for records that contained in the value.
|
|
157
|
+
- "keys" searches for records that containing the value.
|
|
158
|
+
|
|
159
|
+
Returns
|
|
160
|
+
-------
|
|
161
|
+
List[Record]
|
|
162
|
+
List of records.
|
|
163
|
+
|
|
164
|
+
Notes
|
|
165
|
+
-----
|
|
166
|
+
- TRIE index must be created on the column before searching.
|
|
167
|
+
- The TRIE index file will be automatically opened if it exists.
|
|
168
|
+
"""
|
|
169
|
+
rpc_result = _json_request(
|
|
170
|
+
url=self.url,
|
|
171
|
+
method="node.search_records_on",
|
|
172
|
+
params={
|
|
173
|
+
"attr": attr,
|
|
174
|
+
"value": value,
|
|
175
|
+
"funcname": funcname,
|
|
176
|
+
"server": self.server_signature
|
|
177
|
+
},
|
|
178
|
+
)
|
|
179
|
+
nodes = []
|
|
180
|
+
for record in rpc_result:
|
|
181
|
+
node = AddressNode(**record)
|
|
182
|
+
node.table = self
|
|
183
|
+
nodes.append(node)
|
|
184
|
+
|
|
185
|
+
return nodes
|
|
186
|
+
|
|
126
187
|
|
|
127
|
-
class RemoteTree(
|
|
188
|
+
class RemoteTree(AddressTree):
|
|
128
189
|
"""
|
|
129
190
|
The proxy class for remote server's address-tree structure.
|
|
130
191
|
|
|
@@ -206,58 +267,18 @@ class RemoteTree(object):
|
|
|
206
267
|
the new address is retrieved automatically.
|
|
207
268
|
"""
|
|
208
269
|
for k, v in kwargs.items():
|
|
270
|
+
self.validate_config(key=k, value=v)
|
|
209
271
|
self.config[k] = v
|
|
210
272
|
|
|
211
|
-
def get_config(
|
|
212
|
-
self,
|
|
213
|
-
keys: Union[str, List[str], None] = None
|
|
214
|
-
) -> dict:
|
|
215
|
-
"""
|
|
216
|
-
Get configurable parameter(s).
|
|
217
|
-
|
|
218
|
-
Parameters
|
|
219
|
-
----------
|
|
220
|
-
keys: str, List[str], optional
|
|
221
|
-
If a name of parameter is specified, return its value.
|
|
222
|
-
Otherwise, a dict of specified key and its value pairs
|
|
223
|
-
will be returned.
|
|
224
|
-
|
|
225
|
-
Returns
|
|
226
|
-
-------
|
|
227
|
-
Any, or dict.
|
|
228
|
-
"""
|
|
229
|
-
if keys is None:
|
|
230
|
-
return self.config
|
|
231
|
-
|
|
232
|
-
if isinstance(keys, str):
|
|
233
|
-
return self.config.get(keys)
|
|
234
|
-
|
|
235
|
-
results = {}
|
|
236
|
-
for key in keys:
|
|
237
|
-
if key in self.config:
|
|
238
|
-
results[key] = self.config[key]
|
|
239
|
-
|
|
240
|
-
return results
|
|
241
|
-
|
|
242
273
|
def _close(self) -> None:
|
|
243
274
|
if _session:
|
|
244
275
|
del _session
|
|
245
276
|
_session = None
|
|
246
277
|
|
|
247
|
-
def
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
Parameters
|
|
252
|
-
----------
|
|
253
|
-
node_id: int
|
|
254
|
-
The target node id.
|
|
255
|
-
|
|
256
|
-
Return
|
|
257
|
-
------
|
|
258
|
-
AddressNode
|
|
259
|
-
"""
|
|
260
|
-
return self.address_nodes.get_record(node_id)
|
|
278
|
+
def get_trie_nodes(self) -> NoReturn:
|
|
279
|
+
raise RemoteTreeException(
|
|
280
|
+
"This method is not available for RemoteTree."
|
|
281
|
+
)
|
|
261
282
|
|
|
262
283
|
def installed_dictionary_version(self) -> str:
|
|
263
284
|
return _json_request(
|
|
@@ -266,6 +287,13 @@ class RemoteTree(object):
|
|
|
266
287
|
params={},
|
|
267
288
|
)
|
|
268
289
|
|
|
290
|
+
def search_by_trie(
|
|
291
|
+
self, *args, **kwargs
|
|
292
|
+
) -> NoReturn:
|
|
293
|
+
raise RemoteTreeException(
|
|
294
|
+
"This method is not available for RemoteTree."
|
|
295
|
+
)
|
|
296
|
+
|
|
269
297
|
def searchNode(self, query: str) -> List[Result]:
|
|
270
298
|
"""
|
|
271
299
|
Searches for address nodes corresponding to an address notation
|
|
@@ -352,3 +380,19 @@ class RemoteTree(object):
|
|
|
352
380
|
results.append(r)
|
|
353
381
|
|
|
354
382
|
return results
|
|
383
|
+
|
|
384
|
+
def search_by_machiaza_id(self, id: str) -> List[AddressNode]:
|
|
385
|
+
self.address_nodes.update_server_signature()
|
|
386
|
+
return super().search_by_machiaza_id(id)
|
|
387
|
+
|
|
388
|
+
def search_by_postcode(self, code: str) -> List[AddressNode]:
|
|
389
|
+
self.address_nodes.update_server_signature()
|
|
390
|
+
return super().search_by_postcode(code)
|
|
391
|
+
|
|
392
|
+
def search_by_prefcode(self, code: str) -> List[AddressNode]:
|
|
393
|
+
self.address_nodes.update_server_signature()
|
|
394
|
+
return super().search_by_prefcode(code)
|
|
395
|
+
|
|
396
|
+
def search_by_citycode(self, code: str) -> List[AddressNode]:
|
|
397
|
+
self.address_nodes.update_server_signature()
|
|
398
|
+
return super().search_by_citycode(code)
|
|
@@ -324,8 +324,10 @@ class Index(object):
|
|
|
324
324
|
id += 1
|
|
325
325
|
continue
|
|
326
326
|
elif not node.has_valid_coordinate_values():
|
|
327
|
-
|
|
328
|
-
|
|
327
|
+
node = node.add_dummy_coordinates()
|
|
328
|
+
if not node.has_valid_coordinate_values():
|
|
329
|
+
id += 1
|
|
330
|
+
continue
|
|
329
331
|
|
|
330
332
|
file_idx.insert(
|
|
331
333
|
id=id,
|
|
@@ -442,6 +444,9 @@ class Index(object):
|
|
|
442
444
|
if node.id in ancestors:
|
|
443
445
|
continue
|
|
444
446
|
|
|
447
|
+
if not node.has_valid_coordinate_values():
|
|
448
|
+
node = node.add_dummy_coordinates()
|
|
449
|
+
|
|
445
450
|
nodes.append(node)
|
|
446
451
|
max_level = max(max_level, node.level)
|
|
447
452
|
# Ancestor nodes of registering node are excluded.
|
|
@@ -462,8 +467,10 @@ class Index(object):
|
|
|
462
467
|
child_id = child_node.parent.sibling_id
|
|
463
468
|
continue
|
|
464
469
|
elif not child_node.has_valid_coordinate_values():
|
|
465
|
-
|
|
466
|
-
|
|
470
|
+
child_node = child_node.add_dummy_coordinates()
|
|
471
|
+
if not child_node.has_valid_coordinate_values():
|
|
472
|
+
child_id += 1
|
|
473
|
+
continue
|
|
467
474
|
|
|
468
475
|
local_idx.insert(
|
|
469
476
|
id=child_id,
|
|
@@ -478,6 +485,9 @@ class Index(object):
|
|
|
478
485
|
if node.id in ancestors:
|
|
479
486
|
continue
|
|
480
487
|
|
|
488
|
+
if not node.has_valid_coordinate_values():
|
|
489
|
+
node = node.add_dummy_coordinates()
|
|
490
|
+
|
|
481
491
|
nodes.append(node)
|
|
482
492
|
# Ancestor nodes of registering node are excluded.
|
|
483
493
|
cur = node.parent
|
|
@@ -488,7 +498,17 @@ class Index(object):
|
|
|
488
498
|
|
|
489
499
|
# Select the 3 nodes that make the smallest triangle
|
|
490
500
|
# surrounding the target point
|
|
491
|
-
|
|
501
|
+
if len(nodes) == 0:
|
|
502
|
+
return []
|
|
503
|
+
|
|
504
|
+
if self.distance(x, y, nodes[0].x, nodes[0].y) < 1.0e-02:
|
|
505
|
+
# If the distance between the nearest point and the search point is
|
|
506
|
+
# less than 1 cm, it returns three points in order of distance.
|
|
507
|
+
# This is because the nearest point may not be included in
|
|
508
|
+
# the search results due to a calculation error.
|
|
509
|
+
nodes = nodes[0:3]
|
|
510
|
+
else:
|
|
511
|
+
nodes = DelaunayTriangle.select(x, y, nodes)
|
|
492
512
|
|
|
493
513
|
# Convert nodes to the dict format.
|
|
494
514
|
results = []
|