def extract_supplementalData(self, content, cursor): rounding = traverse(content, 'supplementalData.currencyData.fractions.info') _simple_store('rounding', cursor, rounding, False, 'iso4217', ('digits', 'int'), ('rounding', 'int'), ('cashDigits', 'int'), ('cashRounding', 'int')) # This gets a bit more complex, as we need to store typecast, date-ranged data. _recreate(cursor, 'region', 'region', 'currency', 'start', 'end', ('tender', 'bool')) values = [] for region in traverse(content, 'supplementalData.currencyData.region'): for currency in (region['currency'] if isinstance( region['currency'], list) else [region['currency']]): values.append(( region['@iso3166'], currency['@iso4217'], to_date(currency.get('@from', None)), to_date(currency.get('@to', None)), to_bool(currency.get('@tender', True)), )) cursor.executemany("INSERT INTO region VALUES (?, ?, ?, ?, ?)", values)
def extract_supplementalData(self, content, cursor): # Prepare the data source and destination. containment = traverse(content, 'supplementalData.territoryContainment.group') languages = traverse(content, 'supplementalData.languageData.language') _recreate(cursor, 'containment', 'parent', 'child', 'intermediary') _recreate(cursor, 'containment_path', 'territory', 'path') _recreate(cursor, 'language', 'territory', 'language', 'script', ('secondary', 'bool')) # The containment of territories within eachother and within logical groupings, from UN data. values = [] mapping = {} for group in containment: if group.get('@status', None) == 'deprecated': continue members = group['@contains'].split() intermediary = (group.get('status', None) == 'grouping') or all( i.isnumeric() for i in members) for member in members: mapping[member] = group['@type'] values.append((group['@type'], member, intermediary)) cursor.executemany("INSERT INTO containment VALUES (?, ?, ?)", values) # A reverse mapping of these, to quickly look up a "breadcrumb" for display or navigation. values = [] for key in mapping: if key.isnumeric() or key == 'EU': continue parent = mapping[key] path = [] while parent: path.append(parent) parent = mapping.get(parent, None) if parent == '001': break values.append((key, ' '.join(path))) cursor.executemany("INSERT INTO containment_path VALUES (?, ?)", values) # languages typically associated with certain territories. values = [] for language in languages: if '@territories' not in language: continue for territory in language['@territories'].split(): for script in language['@scripts'].split( ) if '@scripts' in language else [None]: values.append((territory, language['@type'], script, language.get('@alt', None) == 'secondary')) cursor.executemany("INSERT INTO language VALUES (?, ?, ?, ?)", values)
def _lookup(self): module, _, name = self.where.rpartition(':') module = traverse(__import__(module), '.'.join(module.split('.')[1:]), separator='.') return module, name
def __call__(self, context): value = traverse(context, self.attribute, self.SENTINEL) # Retrieve the value. if value is self.SENTINEL: return self.default result = any(i == value for i in self.values) # We do this rather than "in" to support equality comparison. return self.grant if result else None
def __call__(self, context): value = traverse(context, self.attribute, self.SENTINEL) # Retrieve the value. if value is self.SENTINEL: return self.default result = any(i in value for i in self.values) return self.grant if result else None
def extract_telephoneCodeData(self, content, cursor): content = traverse( content, 'supplementalData.telephoneCodeData.codesByTerritory') _recreate(cursor, 'telephone_code', 'territory', 'code') values = [] for item in content: codes = item['telephoneCountryCode'] if not isinstance(codes, list): codes = [codes] for code in codes: values.append((item['@territory'], code['@code'])) cursor.executemany("INSERT INTO telephone_code VALUES (?, ?)", values)
def test_empty_traversal_returns_haystack(self): assert traverse(Recorder(), '')._traversal == []
def test_reference_callable(self): assert traverse(Recorder(), 'callable', executable=True)._traversal == ['!']
def test_simple_attribute_reference(self): assert traverse(Recorder(), 'foo')._traversal == ['.foo']
def test_simple_attribute_reference_nested(self): assert traverse(Recorder(), 'foo.bar')._traversal == ['.foo', '.bar']
def test_reference_numeric(self): assert traverse(Recorder(), '27')._traversal == ['[27i]']
def test_reference_default(self): assert traverse(Recorder(), 'canary', default=27) == 27
def test_reference_bad(self): with pytest.raises(LookupError): assert traverse(Recorder(), 'canary')
def test_reference_bogan(self): assert traverse(Recorder(), 'bogan')._traversal == ['[bogan]']