"""
###################################
census_geocoder/locations.py
###################################
Defines :class:`Location` and :class:`MatchedAddress` geographic entities.
"""
from validator_collection import validators, checkers
from census_geocoder import metaclasses, geographies, constants
[docs]class MatchedAddress(metaclasses.BaseEntity):
"""Represents a matched address returned by the US Census GeoCoder API."""
def __init__(self, **kwargs):
self._tigerline_side = None
self._tigerline_id = None
self._latitude = None
self._longitude = None
self._address = None
self._from_address = None
self._to_address = None
self._street = None
self._pre_type = None
self._pre_direction = None
self._pre_qualifier = None
self._suffix_type = None
self._suffix_direction = None
self._suffix_qualifier = None
self._city = None
self._state = None
self._zip_code = None
self._state_fips_code = None
self._county_fips_code = None
self._tract = None
self._block = None
self._geographies = None
for key in kwargs:
if hasattr(self, key):
setattr(self, key, kwargs.get(key, None))
[docs] def inspect(self, as_census_fields = False):
"""Produce a list of the matched address properties that have values.
:param as_census_fields: If ``True``, return property names as they appear in
Census databases or the output of the `Census Geocoder API`_. If ``False``,
return properties as they are defined on the **Census Geocoder** objects.
Defaults to ``False``.
:type as_census_fields: :class:`bool <python:bool>`
:rtype: :class:`list <python:list>` of :class:`str <python:str>`
"""
result = []
if self.address and as_census_fields:
result.append('matchedAddress')
elif self.address:
result.append('address')
if self.latitude and as_census_fields:
result.append('coordinates.y')
elif self.latitude:
result.append('latitude')
if self.longitude and as_census_fields:
result.append('coordinates.x')
elif self.longitude:
result.append('longitude')
if self.tigerline_id and as_census_fields:
result.append('tigerLine.tigerLineId')
elif self.tigerline_id:
result.append('tigerline_id')
if self.tigerline_side and as_census_fields:
result.append('tigerLine.side')
elif self.tigerline_side:
result.append('tigerline_side')
if self.from_address and as_census_fields:
result.append('addressComponents.fromAddress')
elif self.from_address:
result.append('from_address')
if self.to_address and as_census_fields:
result.append('addressComponents.toAddress')
elif self.to_address:
result.append('to_address')
if self.street and as_census_fields:
result.append('addressComponents.streetName')
elif self.street:
result.append('street')
if self.pre_type and as_census_fields:
result.append('addressComponents.preType')
elif self.pre_type:
result.append('pre_type')
if self.pre_direction and as_census_fields:
result.append('addressComponents.preDirection')
elif self.pre_direction:
result.append('pre_direction')
if self.pre_qualifier and as_census_fields:
result.append('addressComponents.preQualifier')
elif self.pre_qualifier:
result.append('pre_qualifier')
if self.suffix_type and as_census_fields:
result.append('addressComponents.suffixType')
elif self.suffix_type:
result.append('suffix_type')
if self.suffix_direction and as_census_fields:
result.append('addressComponents.suffixDirection')
elif self.suffix_direction:
result.append('suffix_direction')
if self.suffix_qualifier and as_census_fields:
result.append('addressComponents.suffixQualifier')
elif self.suffix_qualifier:
result.append('suffix_qualifier')
if self.city and as_census_fields:
result.append('addressComponents.city')
elif self.city:
result.append('city')
if self.state and as_census_fields:
result.append('addressComponents.state')
elif self.state:
result.append('state')
if self.zip_code and as_census_fields:
result.append('addressComponents.zip')
elif self.zip_code:
result.append('zip_code')
if self.geographies:
result.append('geographies')
return result
@property
def tigerline_id(self):
"""The TigerLine ID for the matched address.
:rtype: :class:`str <python:str>` / :obj:`None <python:None>`
"""
return self._tigerline_id
@tigerline_id.setter
def tigerline_id(self, value):
self._tigerline_id = validators.string(value, allow_empty = True)
@property
def tigerline_side(self):
"""The TigerLine side of the street for the matched address. Accepts either 'L' or
'R'.
:rtype: :class:`str <python:str>` / :obj:`None <python:None>`
"""
return self._tigerline_side
@tigerline_side.setter
def tigerline_side(self, value):
value = validators.string(value, allow_empty = True)
if value:
value = value.upper()
if value and value not in ['L', 'R']:
raise ValueError(
f'tigerline_side can only be None, "L", or "R". Was: {value}'
)
self._tigerline_side = value
@property
def longitude(self):
"""The longitude coordinate for the location.
:rtype: :class:`decimal <python:decimal.decimal>`
"""
return self._longitude
@longitude.setter
def longitude(self, value):
self._longitude = validators.decimal(value, allow_empty = True)
@property
def latitude(self):
"""The latitude coordinate for the location.
:rtype: :class:`decimal <python:decimal.decimal>`
"""
return self._latitude
@latitude.setter
def latitude(self, value):
self._latitude = validators.decimal(value, allow_empty = True)
@property
def address(self):
"""The canonical address that was matched for the :class:`Location`.
:rtype: :class:`str <python:str>` / :obj:`None <python:None>`
"""
return self._address
@address.setter
def address(self, value):
self._address = validators.string(value, allow_empty = True)
@property
def pre_type(self):
"""The canonical pre-type that was matched for the :class:`Location`.
:rtype: :class:`str <python:str>` / :obj:`None <python:None>`
"""
return self._pre_type
@pre_type.setter
def pre_type(self, value):
self._pre_type = validators.string(value, allow_empty = True)
@property
def suffix_type(self):
"""The canonical suffix-type that was matched for the :class:`Location`.
:rtype: :class:`str <python:str>` / :obj:`None <python:None>`
"""
return self._suffix_type
@suffix_type.setter
def suffix_type(self, value):
self._suffix_type = validators.string(value, allow_empty = True)
@property
def pre_qualifier(self):
"""The canonical pre-qualifier that was matched for the :class:`Location`.
:rqualifier: :class:`str <python:str>` / :obj:`None <python:None>`
"""
return self._pre_qualifier
@pre_qualifier.setter
def pre_qualifier(self, value):
self._pre_qualifier = validators.string(value, allow_empty = True)
@property
def suffix_qualifier(self):
"""The canonical suffix-qualifier that was matched for the :class:`Location`.
:rqualifier: :class:`str <python:str>` / :obj:`None <python:None>`
"""
return self._suffix_qualifier
@suffix_qualifier.setter
def suffix_qualifier(self, value):
self._suffix_qualifier = validators.string(value, allow_empty = True)
@property
def pre_direction(self):
"""The canonical pre-direction that was matched for the :class:`Location`.
:rdirection: :class:`str <python:str>` / :obj:`None <python:None>`
"""
return self._pre_direction
@pre_direction.setter
def pre_direction(self, value):
self._pre_direction = validators.string(value, allow_empty = True)
@property
def suffix_direction(self):
"""The canonical suffix-direction that was matched for the :class:`Location`.
:rdirection: :class:`str <python:str>` / :obj:`None <python:None>`
"""
return self._suffix_direction
@suffix_direction.setter
def suffix_direction(self, value):
self._suffix_direction = validators.string(value, allow_empty = True)
@property
def from_address(self):
"""The canonical lower-bound street number that was matched for the
:class:`Location`.
:rdirection: :class:`str <python:str>` / :obj:`None <python:None>`
"""
return self._from_address
@from_address.setter
def from_address(self, value):
self._from_address = validators.string(value, allow_empty = True)
@property
def to_address(self):
"""The canonical upper-bound street number that was matched for the
:class:`Location`.
:rdirection: :class:`str <python:str>` / :obj:`None <python:None>`
"""
return self._to_address
@to_address.setter
def to_address(self, value):
self._to_address = validators.string(value, allow_empty = True)
@property
def street(self):
"""The canonical street name that was matched for the :class:`Location`.
:rdirection: :class:`str <python:str>` / :obj:`None <python:None>`
"""
return self._street
@street.setter
def street(self, value):
self._street = validators.string(value, allow_empty = True)
@property
def city(self):
"""The canonical city name that was matched for the :class:`Location`.
:rdirection: :class:`str <python:str>` / :obj:`None <python:None>`
"""
return self._city
@city.setter
def city(self, value):
self._city = validators.string(value, allow_empty = True)
@property
def state(self):
"""The canonical state that was matched for the :class:`Location`.
:rdirection: :class:`str <python:str>` / :obj:`None <python:None>`
"""
return self._state
@state.setter
def state(self, value):
self._state = validators.string(value, allow_empty = True)
@property
def zip_code(self):
"""The canonical zip code that was matched for the :class:`Location`.
:rdirection: :class:`str <python:str>` / :obj:`None <python:None>`
"""
return self._zip_code
@zip_code.setter
def zip_code(self, value):
self._zip_code = validators.string(value, allow_empty = True)
@property
def geographies(self):
"""Collection of geographical areas that this address is part of.
:rtype: :class:`GeographyCollection` / :obj:`None <python:None>`
"""
if not self._geographies:
return []
return self._geographies
@geographies.setter
def geographies(self, value):
if value and not isinstance(value, geographies.GeographyCollection):
value = validators.dict(value, allow_empty = False)
geos = geographies.GeographyCollection.from_dict(value)
elif value:
geos = value
else:
geos = None
self._geographies = geos
@property
def state_fips_code(self):
"""State FIPS Code
:rtype: :class:`str <python:str>`
"""
return self._state_fips_code
@state_fips_code.setter
def state_fips_code(self, value):
self._state_fips_code = validators.string(value, allow_empty = True)
@property
def tract(self):
"""Census Tract Code
:rtype: :class:`str <python:str>`
"""
return self._tract
@tract.setter
def tract(self, value):
self._tract = validators.string(value, allow_empty = True)
@property
def block(self):
"""Census Block Code
:rtype: :class:`str <python:str>` / :obj:`None <python:None>`
"""
return self._block
@block.setter
def block(self, value):
self._block = validators.string(value, allow_empty = True)
@property
def county_fips_code(self):
"""County FIPS Code
:rtype: :class:`str <python:str>`
"""
return self._county_fips_code
@county_fips_code.setter
def county_fips_code(self, value):
self._county_fips_code = validators.string(value, allow_empty = True)
@property
def entity_type(self):
return 'address'
[docs] @classmethod
def from_csv_record(cls, csv_record):
"""Create an instance of the geographic entity from its CSV record.
:param csv_record: The list of columns for the CSV record.
:type csv_record: :class:`list <python:list>` of :class:`str <python:str>`
:returns: An instance of the geographic entity.
:rtype: :class:`GeographicEntity`
"""
csv_record = validators.iterable(csv_record, allow_empty = False)
one_line_address = csv_record[1]
matched_address = csv_record[4]
coordinates = csv_record[5].split(',')
longitude = coordinates[0]
latitude = coordinates[1]
tigerline_id = csv_record[6]
tigerline_side = csv_record[7]
kwargs = {
'address': matched_address,
'longitude': longitude,
'latitude': latitude,
'tigerline_id': tigerline_id,
'tigerline_side': tigerline_side
}
if len(csv_record) > 8:
kwargs['state_fips_code'] = csv_record[8]
kwargs['county_fips_code'] = csv_record[9]
kwargs['tract'] = csv_record[10]
kwargs['block'] = csv_record[11]
return cls(**kwargs)
[docs] @classmethod
def from_dict(cls, as_dict):
"""Create an instance of the geographic entity from its
:class:`dict <python:dict>` representation.
:param as_dict: The :class:`dict <python:dict>` representation of the geographic
entity.
:type as_dict: :class:`dict <python:dict>`
:returns: An instance of the geographic entity.
:rtype: :class:`GeographicEntity`
"""
as_dict = validators.dict(as_dict, allow_empty = False)
address = as_dict.get('result', {})\
.get('addressMatches', {})\
.get('matchedAddress', None)
longitude = as_dict.get('result', {})\
.get('addressMatches', {})\
.get('coordinates', {})\
.get('x', None)
latitude = as_dict.get('result', {})\
.get('addressMatches', {})\
.get('coordinates', {})\
.get('y', None)
tigerline_side = as_dict.get('result', {})\
.get('addressMatches', {})\
.get('tigerLine', {})\
.get('side', None)
tigerline_id = as_dict.get('result', {})\
.get('addressMatches', {})\
.get('tigerLine', {})\
.get('tigerLineId', None)
pre_type = as_dict.get('result', {})\
.get('addressMatches', {})\
.get('addressComponents', {})\
.get('preType', None)
suffix_type = as_dict.get('result', {})\
.get('addressMatches', {})\
.get('addressComponents', {})\
.get('suffixType', None)
pre_qualifier = as_dict.get('result', {})\
.get('addressMatches', {})\
.get('addressComponents', {})\
.get('preQualifier', None)
suffix_qualifier = as_dict.get('result', {})\
.get('addressMatches', {})\
.get('addressComponents', {})\
.get('suffixQualifier', None)
pre_direction = as_dict.get('result', {})\
.get('addressMatches', {})\
.get('addressComponents', {})\
.get('preDirection', None)
suffix_direction = as_dict.get('result', {})\
.get('addressMatches', {})\
.get('addressComponents', {})\
.get('suffixDirection', None)
from_address = as_dict.get('result', {})\
.get('addressMatches', {})\
.get('addressComponents', {})\
.get('fromAddress', None)
to_address = as_dict.get('result', {})\
.get('addressMatches', {})\
.get('addressComponents', {})\
.get('toAddress', None)
street = as_dict.get('result', {})\
.get('addressMatches', {})\
.get('addressComponents', {})\
.get('streetName', None)
city = as_dict.get('result', {})\
.get('addressMatches', {})\
.get('addressComponents', {})\
.get('city', None)
state = as_dict.get('result', {})\
.get('addressMatches', {})\
.get('addressComponents', {})\
.get('state', None)
zip_code = as_dict.get('result', {})\
.get('addressMatches', {})\
.get('addressComponents', {})\
.get('zip', None)
return cls(**{
'tigerline_id': tigerline_id,
'tigerline_side': tigerline_side,
'longitude': longitude,
'latitute': latitude,
'pre_type': pre_type,
'suffix_type': suffix_type,
'pre_qualifier': pre_qualifier,
'suffix_qualifier': suffix_qualifier,
'pre_direction': pre_direction,
'suffix_direction': suffix_direction,
'from_address': from_address,
'to_address': to_address,
'street': street,
'city': city,
'state': state,
'zip_code': zip_code,
'address': address
})
[docs] def to_dict(self):
"""Returns a :class:`dict <python:dict>` representation of the geographic entity.
.. note::
The :class:`dict <python:dict>` representation matches the JSON structure for
the US Census Geocoder API. This is a not-very-pythonic
:class:`dict <python:dict>` structure, but at least this ensures idempotency.
:returns: :class:`dict <python:dict>` representation of the entity.
:rtype: :class:`dict <python:dict>`
"""
result = {
'matchedAddress': self.address,
'coordinates': {
'x': self.longitude,
'y': self.latitude
},
'tigerLine': {
'tigerLineId': self.tigerline_id,
'side': self.tigerline_side
},
'addressComponents': {
'fromAddress': self.from_address,
'toAddress': self.to_address,
'preType': self.pre_type,
'preQualifier': self.pre_qualifier,
'preDirection': self.pre_direction,
'streetName': self.street,
'suffixType': self.suffix_type,
'suffixQualifier': self.suffix_qualifier,
'suffixDirection': self.suffix_direction,
'city': self.city,
'state': self.state,
'zip': self.zip_code
},
'geographies': [x.to_dict() for x in self.geographies]
}
return result
[docs]class Location(metaclasses.GeographicEntity):
"""Represents a specific location returned by the US Census Geocoder API."""
def __init__(self, **kwargs):
self._input_one_line = None
self._input_street = None
self._input_city = None
self._input_state = None
self._input_zip_code = None
self._benchmark_name = None
self._benchmark_description = None
self._benchmark_id = None
self._benchmark_is_default = False
self._vintage_name = None
self._vintage_description = None
self._vintage_id = None
self._vintage_is_default = False
self._matched_addresses = None
for key in kwargs:
if hasattr(self, key):
setattr(self, key, kwargs.get(key, None))
[docs] def inspect(self, as_census_fields = False):
"""Produce a list of the location's properties that have values.
:param as_census_fields: If ``True``, return property names as they appear in
Census databases or the output of the `Census Geocoder API`_. If ``False``,
return properties as they are defined on the **Census Geocoder** objects.
Defaults to ``False``.
:type as_census_fields: :class:`bool <python:bool>`
:rtype: :class:`list <python:list>` of :class:`str <python:str>`
"""
result = []
if self.input_one_line and as_census_fields:
result.append('input.address')
elif self.input_one_line:
result.append('input_one_line')
if self.input_street and as_census_fields:
result.append('input.address.street')
elif self.input_street:
result.append('input_street')
if self.input_city and as_census_fields:
result.append('input.address.city')
elif self.input_city:
result.append('input_city')
if self.input_state and as_census_fields:
result.append('input.address.state')
elif self.input_state:
result.append('input_state')
if self.input_zip_code and as_census_fields:
result.append('input.address.zip')
elif self.input_zip_code:
result.append('input_zip_code')
if self.benchmark_name and as_census_fields:
result.append('benchmark.benchmarkName')
elif self.benchmark_name:
result.append('benchmark_name')
if self.benchmark_description and as_census_fields:
result.append('benchmark.benchmarkDescription')
elif self.benchmark_description:
result.append('benchmark_description')
if self.benchmark_id and as_census_fields:
result.append('benchmark.id')
elif self.benchmark_id:
result.append('benchmark_id')
if as_census_fields:
result.append('benchmark.isDefault')
else:
result.append('benchmark_is_default')
if self.benchmark:
result.append('benchmark')
if self.vintage_name and as_census_fields:
result.append('vintage.vintageName')
elif self.vintage_name:
result.append('vintage_name')
if self.vintage_description and as_census_fields:
result.append('vintage.vintageDescription')
elif self.vintage_description:
result.append('vintage_description')
if self.vintage_id and as_census_fields:
result.append('vintage.id')
elif self.vintage_id:
result.append('vintage_id')
if as_census_fields:
result.append('vintage.isDefault')
else:
result.append('vintage_is_default')
if self.vintage:
result.append('vintage')
if self.matched_addresses and as_census_fields:
result.append('addressMatches')
elif self.matched_addresses:
result.append('matched_addresses')
return result
@property
def input_one_line(self):
"""The one-line address that was provided as input to get this :class:`Location`.
:rtype: :class:`str <python:str>` or :obj:`None <python:None>`
"""
return self._input_one_line
@input_one_line.setter
def input_one_line(self, value):
self._input_one_line = validators.string(value, allow_empty = True)
@property
def input_street(self):
"""The street address that was provided as input to get this :class:`Location`.
:rtype: :class:`str <python:str>` or :obj:`None <python:None>`
"""
return self._input_street
@input_street.setter
def input_street(self, value):
self._input_street = validators.string(value, allow_empty = True)
@property
def input_city(self):
"""The city that was provided as input to get this :class:`Location`.
:rtype: :class:`str <python:str>` or :obj:`None <python:None>`
"""
return self._input_city
@input_city.setter
def input_city(self, value):
self._input_city = validators.string(value, allow_empty = True)
@property
def input_state(self):
"""The state that was provided as input to get this :class:`Location`.
:rtype: :class:`str <python:str>` or :obj:`None <python:None>`
"""
return self._input_state
@input_state.setter
def input_state(self, value):
self._input_state = validators.string(value, allow_empty = True)
@property
def input_zip_code(self):
"""The zip code that was provided as input to get this :class:`Location`.
:rtype: :class:`str <python:str>` or :obj:`None <python:None>`
"""
return self._input_zip_code
@input_zip_code.setter
def input_zip_code(self, value):
self._input_zip_code = validators.string(value, allow_empty = True)
@property
def input_address(self):
"""Returns a :class:`dict <python:dict>` with the input address provided.
:rtype: :class:`dict <python:dict>`
"""
result = {}
if self.input_one_line:
result['address'] = self.input_one_line
if self.input_street:
result['street'] = self.input_street
if self.input_city:
result['city'] = self.input_city
if self.input_state:
result['state'] = self.input_state
if self.input_zip_code:
result['zip_code'] = self.zip_code
return result
@property
def benchmark_name(self):
"""The name of the :term:`benchmark` for which this data was returned.
:rtype: :class:`str <python:str>`
"""
return self._benchmark_name
@benchmark_name.setter
def benchmark_name(self, value):
self._benchmark_name = validators.string(value, allow_empty = True)
@property
def benchmark_description(self):
"""The description of the :term:`benchmark` for which this data was returned.
:rtype: :class:`str <python:str>`
"""
return self._benchmark_description
@benchmark_description.setter
def benchmark_description(self, value):
self._benchmark_description = validators.string(value, allow_empty = True)
@property
def benchmark_id(self):
"""The name of the :term:`benchmark` for which this data was returned.
:rtype: :class:`str <python:str>`
"""
return self._benchmark_id
@benchmark_id.setter
def benchmark_id(self, value):
self._benchmark_id = validators.string(value, allow_empty = True)
@property
def benchmark_is_default(self):
"""If ``True``, indicates that the default :term:`benchmark` has been applied.
:rtype: :class:`bool <python:bool>`
"""
return bool(self._benchmark_is_default)
@benchmark_is_default.setter
def benchmark_is_default(self, value):
self._benchmark_is_default = bool(value)
@property
def benchmark(self):
"""The short-hand value of the :term:`benchmark` for which this :class:`Location`
was calculated.
:rtype: :class:`str <python:str>` / :obj:`None <python:None>`
"""
for key in constants.BENCHMARKS:
if constants.BENCHMARKS.get(key, None) == self.benchmark_name:
return key
return None
@property
def vintage_name(self):
"""The name of the :term:`vintage` for which this data was returned.
:rtype: :class:`str <python:str>`
"""
return self._vintage_name
@vintage_name.setter
def vintage_name(self, value):
self._vintage_name = validators.string(value, allow_empty = True)
@property
def vintage_description(self):
"""The description of the :term:`vintage` for which this data was returned.
:rtype: :class:`str <python:str>`
"""
return self._vintage_description
@vintage_description.setter
def vintage_description(self, value):
self._vintage_description = validators.string(value, allow_empty = True)
@property
def vintage_id(self):
"""The name of the :term:`vintage` for which this data was returned.
:rtype: :class:`str <python:str>`
"""
return self._vintage_id
@vintage_id.setter
def vintage_id(self, value):
self._vintage_id = validators.string(value, allow_empty = True)
@property
def vintage_is_default(self):
"""If ``True``, indicates that the default :term:`vintage` has been applied.
:rtype: :class:`bool <python:bool>`
"""
return bool(self._vintage_is_default)
@vintage_is_default.setter
def vintage_is_default(self, value):
self._vintage_is_default = bool(value)
@property
def vintage(self):
"""The short-hand value of the :term:`vintage` for which this :class:`Location`
was calculated.
:rtype: :class:`str <python:str>` / :obj:`None <python:None>`
"""
for key in constants.VINTAGES:
if key == self.benchmark_name:
vintage_set = constants.VINTAGES.get(key, {})
for vintage_key in vintage_set:
if vintage_set.get(vintage_key, None) == self.vintage_name:
return vintage_key
return None
@property
def matched_addresses(self):
"""Collection of addresses that have been matched to the :class:`Location`.
:rtype: :class:`list <python:list>` of :class:`MatchedAddress` /
:obj:`None <python:None>`
"""
return self._matched_addresses
@matched_addresses.setter
def matched_addresses(self, value):
value = validators.iterable(value, allow_empty = True)
for item in value:
if checkers.is_type(item, 'MatchedAddress') is False:
raise ValueError(
f'item must be a MatchedAddress. Was: {item.__class__.__name__}'
)
self._matched_addresses = [x for x in value]
@property
def entity_type(self):
return 'locations'
[docs] @classmethod
def from_csv_record(cls, csv_record):
"""Create an instance of the geographic entity from its CSV record.
:param csv_record: The list of columns for the CSV record.
:type csv_record: :class:`list <python:list>` of :class:`str <python:str>`
:returns: An instance of the geographic entity.
:rtype: :class:`GeographicEntity`
"""
csv_record = validators.iterable(csv_record, allow_empty = False)
one_line_address = csv_record[1]
matched_address = csv_record[4]
coordinates = csv_record[5].split(',')
longitude = coordinates[0]
latitude = coordinates[1]
tigerline_id = csv_record[6]
tigerline_side = csv_record[7]
kwargs = {
'address': matched_address,
'longitude': longitude,
'latitude': latitude,
'tigerline_id': tigerline_id,
'tigerline_side': tigerline_side
}
if len(csv_record) > 8:
kwargs['state_fips_code'] = csv_record[8]
kwargs['county_fips_code'] = csv_record[9]
kwargs['tract'] = csv_record[10]
kwargs['block'] = csv_record[11]
matched_address = MatchedAddress(**kwargs)
return cls(input_one_line = one_line_address,
matched_addresses = [matched_address])
[docs] @classmethod
def from_dict(cls, as_dict):
"""Create an instance of the geographic entity from its
:class:`dict <python:dict>` representation.
:param as_dict: The :class:`dict <python:dict>` representation of the geographic
entity.
:type as_dict: :class:`dict <python:dict>`
:returns: An instance of the geographic entity.
:rtype: :class:`GeographicEntity`
"""
as_dict = validators.dict(as_dict, allow_empty = False)
input_one_line = as_dict.get('result', {})\
.get('input', {})\
.get('address', {})\
.get('address', None)
input_street = as_dict.get('result', {})\
.get('input', {})\
.get('address', {})\
.get('street', None)
input_city = as_dict.get('result', {})\
.get('input', {})\
.get('address', {})\
.get('city', None)
input_state = as_dict.get('result', {})\
.get('input', {})\
.get('address', {})\
.get('state', None)
input_zip_code = as_dict.get('result', {})\
.get('input', {})\
.get('address', {})\
.get('zip', None)
benchmark_name = as_dict.get('result', {})\
.get('input', {})\
.get('benchmark', {})\
.get('benchmarkName', None)
benchmark_id = as_dict.get('result', {})\
.get('input', {})\
.get('benchmark', {})\
.get('id', None)
benchmark_description = as_dict.get('result', {})\
.get('input', {})\
.get('benchmark', {})\
.get('benchmarkDescription', None)
benchmark_is_default = as_dict.get('result', {})\
.get('input', {})\
.get('benchmark', {})\
.get('isDefault', False)
vintage_name = as_dict.get('result', {})\
.get('input', {})\
.get('vintage', {})\
.get('vintageName', None)
vintage_id = as_dict.get('result', {})\
.get('input', {})\
.get('vintage', {})\
.get('id', None)
vintage_description = as_dict.get('result', {})\
.get('input', {})\
.get('vintage', {})\
.get('vintageDescription', None)
vintage_is_default = as_dict.get('result', {})\
.get('input', {})\
.get('vintage', {})\
.get('isDefault', False)
matched_addresses = as_dict.get('result', {})\
.get('addressMatches', [])
matched_addresses = [MatchedAddress.from_json(x) for x in matched_addresses]
geos = as_dict.get('result', {})\
.get('geographies', {})
result = cls(**{
'input_one_line': input_one_line,
'input_street': input_street,
'input_city': input_city,
'input_state': input_state,
'input_zip_code': input_zip_code,
'benchmark_name': benchmark_name,
'benchmark_description': benchmark_description,
'benchmark_is_default': benchmark_is_default,
'benchmark_id': benchmark_id,
'vintage_name': vintage_name,
'vintage_description': vintage_description,
'vintage_is_default': vintage_is_default,
'vintage_id': vintage_id,
'matched_addresses': matched_addresses
})
if geos:
geography_collection = geographies.GeographyCollection.from_dict(geos)
result.geographies = geography_collection
return result
[docs] def to_dict(self):
"""Returns a :class:`dict <python:dict>` representation of the geographic entity.
.. note::
The :class:`dict <python:dict>` representation matches the JSON structure for
the US Census Geocoder API. This is a not-very-pythonic
:class:`dict <python:dict>` structure, but at least this ensures idempotency.
:returns: :class:`dict <python:dict>` representation of the entity.
:rtype: :class:`dict <python:dict>`
"""
result = {
'input': {
'address': {},
'benchmark': {
'id': self.benchmark_id,
'benchmarkName': self.benchmark_name,
'benchmarkDescription': self.benchmark_description,
'isDefault': self.benchmark_is_default
},
'vintage': {
'id': self.vintage_id,
'vintageName': self.vintage_name,
'vintageDescription': self.vintage_description,
'isDefault': self.vintage_is_default
}
}
}
if self.input_one_line:
result['input']['address']['address'] = self.input_one_line
if self.input_street:
result['input']['address']['street'] = self.input_street
if self.input_city:
result['input']['address']['city'] = self.input_city
if self.input_state:
result['input']['address']['state'] = self.input_state
if self.input_zip_code:
result['input']['address']['zip'] = self.input_zip_code