"""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]