67 lines
3.4 KiB
Python
67 lines
3.4 KiB
Python
"""Versioned offline location paths. Administrative geography is not an ACL boundary."""
|
|
import json
|
|
from pathlib import Path
|
|
|
|
DATA = json.loads((Path(__file__).parent/'web/data/geography.json').read_text(encoding='utf8'))
|
|
|
|
|
|
def normalize(value, clean):
|
|
if not isinstance(value, dict):
|
|
raise ValueError('地域信息格式不正确')
|
|
mode = value.get('mode')
|
|
if mode not in ('china', 'world', 'custom'):
|
|
raise ValueError('请选择中国、世界或自定义地域')
|
|
result = dict(version=1, mode=mode, dataset=DATA['version'], body='地球', countryCode='', country='',
|
|
provinceCode='', cityCode='', districtCode='', province='', city='', district='', path='')
|
|
if mode == 'china':
|
|
result.update(countryCode='CN', country='中国')
|
|
children = DATA['china']
|
|
manual = False
|
|
for field in ('province', 'city', 'district'):
|
|
code = value.get(field+'Code', '')
|
|
if not isinstance(code, str): raise ValueError('地域编码格式不正确')
|
|
if manual:
|
|
result[field] = clean(value.get(field, ''), 100)
|
|
continue
|
|
if not code:
|
|
if any(value.get(k+'Code') for k in ('city','district') if ('province','city','district').index(k)>('province','city','district').index(field)):
|
|
raise ValueError('请先选择上级地区')
|
|
continue
|
|
item = next((x for x in children if x['code']==code), None)
|
|
if not item: raise ValueError('地区不属于所选上级,请重新选择')
|
|
result[field+'Code'], result[field] = item['code'], item['name']
|
|
manual = item.get('manual', False)
|
|
children = item.get('children', [])
|
|
elif mode == 'world':
|
|
code = value.get('countryCode', '')
|
|
if not isinstance(code, str) or code not in DATA['countries']: raise ValueError('请选择国家或地区')
|
|
if code == 'CN': raise ValueError('中国地区请使用中国分级选择')
|
|
result.update(countryCode=code, country=DATA['countries'][code])
|
|
for field in ('province','city','district'):
|
|
result[field] = clean(value.get(field, ''), 100)
|
|
else:
|
|
result['body'] = clean(value.get('body', '地球'), 100, True)
|
|
for field in ('country','province','city','district'):
|
|
result[field] = clean(value.get(field, ''), 100)
|
|
result['path'] = clean(value.get('path', ''), 1000)
|
|
return result
|
|
|
|
|
|
def apply(item, data, old, clean, problem, prefix=''):
|
|
key = prefix+'Geography' if prefix else 'geography'
|
|
if key not in data:
|
|
if key in (old or {}):
|
|
previous = old[key]
|
|
names = {f:prefix+f.title() if prefix else f for f in ('country','province','city','district')}
|
|
if any(k in data and data[k] != old.get(k,'') for k in names.values()):
|
|
# An older client can edit text but cannot keep now-inconsistent codes.
|
|
item[key] = normalize(dict(mode='custom',body=previous.get('body','地球'),
|
|
path=previous.get('path',''),**{f:data.get(k,old.get(k,'')) for f,k in names.items()}),clean)
|
|
else: item[key] = previous
|
|
return
|
|
try: result = normalize(data[key], clean)
|
|
except ValueError as error: raise problem(str(error))
|
|
item[key] = result
|
|
for field in ('country','province','city','district'):
|
|
item[prefix+field.title() if prefix else field] = result[field]
|