<filename>geocoder/canadapost.py<gh_stars>1000+
#!/usr/bin/python
# coding: utf8
from __future__ import absolute_import

import logging

from geocoder.base import OneResult, MultipleResultsQuery
from geocoder.keys import canadapost_key_getter


class CanadapostIdResult(OneResult):

    @property
    def ok(self):
        return bool(self.item_id)

    @property
    def item_id(self):
        return self.raw.get('Id')

    @property
    def next_action(self):
        return self.raw.get('Next')


class CanadapostIdQuery(MultipleResultsQuery):

    provider = 'canadapost'
    method = 'id'

    _URL = 'https://ws1.postescanada-canadapost.ca/AddressComplete/Interactive/Find/v2.10/json3ex.ws'
    _RESULT_CLASS = CanadapostIdResult
    _KEY_MANDATORY = False

    def _build_params(self, location, provider_key, **kwargs):
        if not provider_key:
            provider_key = canadapost_key_getter(**kwargs)

        return {
            'Key': provider_key,
            'LastId': kwargs.get('last_id', ''),
            'Country': kwargs.get('country', 'ca'),
            'SearchFor': 'Everything',
            'SearchTerm': location,
            'LanguagePreference': kwargs.get('language', 'en'),
            '$cache': 'true'
        }

    def _adapt_results(self, json_response):
        return json_response['Items']


class CanadapostResult(OneResult):

    @property
    def ok(self):
        return bool(self.postal)

    @property
    def quality(self):
        return self.raw.get('Type')

    @property
    def accuracy(self):
        return self.raw.get('DataLevel')

    @property
    def address(self):
        return self.raw.get('Line1')

    @property
    def postal(self):
        return self.raw.get('PostalCode')

    @property
    def housenumber(self):
        return self.raw.get('BuildingNumber')

    @property
    def street(self):
        return self.raw.get('Street')

    @property
    def city(self):
        return self.raw.get('City')

    @property
    def state(self):
        return self.raw.get('ProvinceName')

    @property
    def country(self):
        return self.raw.get('CountryName')

    @property
    def unit(self):
        return self.raw.get('SubBuilding')

    @property
    def domesticId(self):
        return self.raw.get('DomesticId')

    @property
    def label(self):
        return self.raw.get('Label')


class CanadapostQuery(MultipleResultsQuery):
    """
    Addres Complete API
    =======================
    The next generation of address finders, AddressComplete uses
    intelligent, fast searching to improve data accuracy and relevancy.
    Simply start typing a business name, address or Postal Code
    and AddressComplete will suggest results as you go.

    Params
    ------
    :param ``location``: Your search location you want geocoded.
    :param ``key``: (optional) API Key from CanadaPost Address Complete.
    :param ``language``: (default=en) Output language preference.
    :param ``country``: (default=ca) Geofenced query by country.

    API Reference
    -------------
    https://www.canadapost.ca/pca/
    """
    provider = 'canadapost'
    method = 'geocode'

    _URL = 'https://ws1.postescanada-canadapost.ca/AddressComplete/Interactive/RetrieveFormatted/v2.10/json3ex.ws'
    _RESULT_CLASS = CanadapostResult
    _KEY_MANDATORY = False

    def _build_params(self, location, provider_key, **kwargs):
        if not provider_key:
            provider_key = canadapost_key_getter(**kwargs)

        self.key = provider_key

        last_id = ''
        next_action = 'Find'
        while next_action == 'Find':
            ids = CanadapostIdQuery(location, key=provider_key, last_id=last_id, **kwargs)
            next_action = ids.next_action
            last_id = ids.item_id

        if not ids.item_id:
            raise ValueError("Could not get any Id for given location")

        return {
            'Key': provider_key,
            'Id': ids.item_id,
            'Source': '',
            'MaxResults': kwargs.get('maxRows', 1),
            'cache': 'true'
        }

    def _adapt_results(self, json_response):
        return json_response['Items']

    @property
    def canadapost_api_key(self):
        return self.key


if __name__ == '__main__':
    logging.basicConfig(level=logging.INFO)
    g = CanadapostQuery("453 Booth Street, ON")
    g.debug()
