2014-08-04 16:41:49 +02:00
|
|
|
#!/usr/bin/env python
|
2022-08-26 18:12:02 +02:00
|
|
|
# PYTHON_ARGCOMPLETE_OK
|
2015-01-08 13:17:22 +01:00
|
|
|
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
|
|
|
|
# this repository contains the full copyright notices and license terms.
|
2018-02-04 23:35:33 +01:00
|
|
|
from __future__ import print_function
|
2021-12-11 17:58:42 +01:00
|
|
|
|
2017-03-21 23:35:01 +01:00
|
|
|
import csv
|
|
|
|
|
import os
|
|
|
|
|
import sys
|
2021-12-11 17:58:42 +01:00
|
|
|
|
2018-02-04 23:35:33 +01:00
|
|
|
try:
|
2021-08-06 09:46:32 +02:00
|
|
|
from urllib.error import HTTPError
|
2021-12-11 17:58:42 +01:00
|
|
|
from urllib.request import urlopen
|
2018-02-04 23:35:33 +01:00
|
|
|
except ImportError:
|
2021-08-06 09:46:32 +02:00
|
|
|
from urllib2 import urlopen, HTTPError
|
2017-03-21 23:35:01 +01:00
|
|
|
|
2021-12-11 17:58:42 +01:00
|
|
|
import zipfile
|
2014-08-04 16:41:49 +02:00
|
|
|
from argparse import ArgumentParser
|
2021-07-22 00:05:32 +02:00
|
|
|
from io import BytesIO, TextIOWrapper
|
2014-08-04 16:41:49 +02:00
|
|
|
|
2022-08-26 18:12:02 +02:00
|
|
|
try:
|
|
|
|
|
import argcomplete
|
|
|
|
|
except ImportError:
|
|
|
|
|
argcomplete = None
|
|
|
|
|
|
2014-08-04 16:41:49 +02:00
|
|
|
try:
|
2023-07-22 19:36:08 +02:00
|
|
|
from tqdm import tqdm
|
2014-08-04 16:41:49 +02:00
|
|
|
except ImportError:
|
2023-07-22 19:36:08 +02:00
|
|
|
tqdm = None
|
2014-08-04 16:41:49 +02:00
|
|
|
|
2017-03-21 23:35:01 +01:00
|
|
|
try:
|
|
|
|
|
from proteus import Model, config
|
|
|
|
|
except ImportError:
|
|
|
|
|
prog = os.path.basename(sys.argv[0])
|
|
|
|
|
sys.exit("proteus must be installed to use %s" % prog)
|
2014-08-04 16:41:49 +02:00
|
|
|
|
|
|
|
|
|
2023-07-22 19:36:08 +02:00
|
|
|
def _progress(iterable, **kwargs):
|
|
|
|
|
if tqdm:
|
|
|
|
|
return tqdm(iterable, disable=None, **kwargs)
|
|
|
|
|
else:
|
|
|
|
|
return iterable
|
|
|
|
|
|
|
|
|
|
|
2014-08-04 16:41:49 +02:00
|
|
|
def clean(code):
|
|
|
|
|
sys.stderr.write('Cleaning')
|
2021-03-31 23:59:33 +02:00
|
|
|
PostalCode = Model.get('country.postal_code')
|
|
|
|
|
PostalCode._proxy.delete(
|
|
|
|
|
[c.id for c in PostalCode.find([('country.code', '=', code)])], {})
|
2018-02-04 23:35:33 +01:00
|
|
|
print('.', file=sys.stderr)
|
2014-08-04 16:41:49 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def fetch(code):
|
|
|
|
|
sys.stderr.write('Fetching')
|
2023-01-16 15:07:08 +01:00
|
|
|
url = 'https://downloads.tryton.org/geonames/%s.zip' % code
|
2021-08-06 09:46:32 +02:00
|
|
|
try:
|
|
|
|
|
responce = urlopen(url)
|
|
|
|
|
except HTTPError as e:
|
|
|
|
|
sys.exit("\nError downloading %s: %s" % (code, e.reason))
|
2014-08-04 16:41:49 +02:00
|
|
|
data = responce.read()
|
|
|
|
|
with zipfile.ZipFile(BytesIO(data)) as zf:
|
|
|
|
|
data = zf.read('%s.txt' % code)
|
2018-02-04 23:35:33 +01:00
|
|
|
print('.', file=sys.stderr)
|
2014-08-04 16:41:49 +02:00
|
|
|
return data
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def import_(data):
|
2021-03-31 23:59:33 +02:00
|
|
|
PostalCode = Model.get('country.postal_code')
|
2014-08-04 16:41:49 +02:00
|
|
|
Country = Model.get('country.country')
|
|
|
|
|
Subdivision = Model.get('country.subdivision')
|
2018-02-04 23:35:33 +01:00
|
|
|
print('Importing', file=sys.stderr)
|
2014-08-04 16:41:49 +02:00
|
|
|
|
|
|
|
|
def get_country(code):
|
|
|
|
|
country = countries.get(code)
|
|
|
|
|
if not country:
|
2021-08-06 09:46:32 +02:00
|
|
|
try:
|
|
|
|
|
country, = Country.find([('code', '=', code)])
|
|
|
|
|
except ValueError:
|
|
|
|
|
sys.exit("Error missing country with code %s" % code)
|
2014-08-04 16:41:49 +02:00
|
|
|
countries[code] = country
|
|
|
|
|
return country
|
|
|
|
|
countries = {}
|
|
|
|
|
|
|
|
|
|
def get_subdivision(country, code):
|
|
|
|
|
code = '%s-%s' % (country, code)
|
|
|
|
|
subdivision = subdivisions.get(code)
|
|
|
|
|
if not subdivision:
|
|
|
|
|
try:
|
|
|
|
|
subdivision, = Subdivision.find([('code', '=', code)])
|
|
|
|
|
except ValueError:
|
|
|
|
|
return
|
|
|
|
|
subdivisions[code] = subdivision
|
|
|
|
|
return subdivision
|
|
|
|
|
subdivisions = {}
|
|
|
|
|
|
2021-07-22 00:05:32 +02:00
|
|
|
f = TextIOWrapper(BytesIO(data), encoding='utf-8')
|
2021-03-31 23:59:33 +02:00
|
|
|
codes = []
|
2023-07-22 19:36:08 +02:00
|
|
|
for row in _progress(csv.DictReader(
|
|
|
|
|
f, fieldnames=_fieldnames, delimiter='\t'),
|
|
|
|
|
total=data.count(b'\n')):
|
2014-08-04 16:41:49 +02:00
|
|
|
country = get_country(row['country'])
|
2020-02-17 09:59:27 +01:00
|
|
|
for code in ['code1', 'code2', 'code3']:
|
|
|
|
|
subdivision = get_subdivision(row['country'], row[code])
|
|
|
|
|
if code == 'code1' or subdivision:
|
2021-03-31 23:59:33 +02:00
|
|
|
codes.append(
|
|
|
|
|
PostalCode(country=country, subdivision=subdivision,
|
|
|
|
|
postal_code=row['postal'], city=row['place']))
|
|
|
|
|
PostalCode.save(codes)
|
2014-08-04 16:41:49 +02:00
|
|
|
|
2018-06-26 19:11:47 +02:00
|
|
|
|
2014-08-04 16:41:49 +02:00
|
|
|
_fieldnames = ['country', 'postal', 'place', 'name1', 'code1',
|
|
|
|
|
'name2', 'code2', 'name3', 'code3', 'latitude', 'longitude', 'accuracy']
|
|
|
|
|
|
|
|
|
|
|
2015-01-29 12:34:15 +01:00
|
|
|
def main(database, codes, config_file=None):
|
|
|
|
|
config.set_trytond(database, config_file=config_file)
|
2019-10-14 00:13:00 +02:00
|
|
|
do_import(codes)
|
2014-08-04 16:41:49 +02:00
|
|
|
|
2019-10-14 00:13:00 +02:00
|
|
|
|
|
|
|
|
def do_import(codes):
|
2014-08-04 16:41:49 +02:00
|
|
|
for code in codes:
|
2018-02-04 23:35:33 +01:00
|
|
|
print(code, file=sys.stderr)
|
2014-08-04 16:41:49 +02:00
|
|
|
code = code.upper()
|
|
|
|
|
clean(code)
|
|
|
|
|
import_(fetch(code))
|
|
|
|
|
|
2018-06-26 19:11:47 +02:00
|
|
|
|
2019-10-14 00:13:00 +02:00
|
|
|
def run():
|
2014-08-04 16:41:49 +02:00
|
|
|
parser = ArgumentParser()
|
2020-07-09 10:38:50 +01:00
|
|
|
parser.add_argument('-d', '--database', dest='database', required=True)
|
2014-08-04 16:41:49 +02:00
|
|
|
parser.add_argument('-c', '--config', dest='config_file',
|
|
|
|
|
help='the trytond config file')
|
|
|
|
|
parser.add_argument('codes', nargs='+')
|
2022-08-26 18:12:02 +02:00
|
|
|
if argcomplete:
|
|
|
|
|
argcomplete.autocomplete(parser)
|
2014-08-04 16:41:49 +02:00
|
|
|
|
|
|
|
|
args = parser.parse_args()
|
2015-01-29 12:34:15 +01:00
|
|
|
main(args.database, args.codes, args.config_file)
|
2019-10-14 00:13:00 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
|
run()
|