Example #1
0
    def setUp(self):
        # places
        self.pq_us = PlaceQuery('1200 Callowhill St, Philadelphia, PA 19107')
        self.pq_uk = PlaceQuery('32 Bond Road, Ste A, Surbiton, Surrey KT6')
        self.pq_uk_with_country_UK = PlaceQuery('32 Bond Road, Ste A, Surbiton, Surrey KT6', country='UK')
        self.pq_uk_with_country_GB = PlaceQuery('32 Bond Road, Ste A, Surbiton, Surrey KT6', country='GB')

        # candidates
        self.good = Candidate(match_addr='123 Any St', locator='address', score=85.3)
        self.better = Candidate(match_addr='123 Any St', locator='parcel', score=92)
        self.best = Candidate(match_addr='123 Any St', locator='rooftop', score=100)
        self.wolf_good = Candidate(match_addr='1200 Callowhill St', locator='address', score=76)
        self.wolf_better = Candidate(match_addr='1200 Callowhill St', locator='parcel', score=90)
        self.wolf_best = Candidate(match_addr='1200 Callowhill St', locator='rooftop',
                                   score=99.9, x=-75.158, y=39.959)
        self.wolf_340 = Candidate(match_addr='340 N 12th St', locator='rooftop',
                                  score=99.5, x=-75.158, y=39.959)  # same coords
        self.inky = Candidate(match_addr='324 N Broad St', locator='rooftop',
                              score=99.9, x=-75.163, y=39.959)  # same y
        self.capt_thomas = Candidate(match_addr='843 Callowhill St', locator='rooftop',
                                     score=99.9, x=-75.163, y=39.959)  # same y
        self.reading_term = Candidate(match_addr='1200 Arch St', locator='rooftop',
                                      score=99.9, x=-75.163, y=39.953)  # same x
        self.with_address_types = Candidate(match_addr='123 Any St', locator='address',
                                            entity_types=['address', 'place'])
        self.with_nonsense_types = Candidate(match_addr='123 Any St', locator='address',
                                             entity_types=['house', 'building'])

        self.locators_worse_to_better = ['address', 'parcel', 'rooftop']
Example #2
0
 def test_google_country_filter(self):
     candidates = self.g_google.get_candidates(PlaceQuery('York', country='US'))
     self.assertOneCandidate(candidates)
     self.assertEqual(candidates[0].match_region, 'PA')
     candidates = self.g_google_wo_postprocess.get_candidates(PlaceQuery('York', country='GB'))
     self.assertOneCandidate(candidates)
     self.assertEqual(candidates[0].match_country, 'GB')
Example #3
0
    def test_pro_streetnumber_ReplaceRangeWithNumber(self):
        """Test ReplaceRangeWithNumber preprocessor."""
        place_in = PlaceQuery('4452-54 Main Street, Philadelphia')  # Mom's Pizza in Manayunk
        place_out = ReplaceRangeWithNumber().process(place_in)
        query_exp = '4452 Main Street, Philadelphia'
        self.assertEqual_(place_out.query, query_exp)

        zip_plus_4 = '19127-1112'
        place_in = PlaceQuery(zip_plus_4)  # sets PlaceQuery.query to zip_plus_4 on init
        place_out = ReplaceRangeWithNumber().process(place_in)
        self.assertEqual_(place_out.query, zip_plus_4)
Example #4
0
def geocode(request):
    """
    Endpoint to geocode a lat/lng pair

    Configuration for sources is pulled from the OMGEO_SETTINGS
    settings key
    """
    viewbox = _get_viewbox_from_request(request)

    address = request.REQUEST['address']

    pq = PlaceQuery(query=address, viewbox=viewbox)

    geocode_result = geocoder.geocode(pq)
    candidates = geocode_result.get('candidates', None)

    if not candidates or len(candidates) == 0:
        return _no_results_response(address)
    else:
        candidates = [_omgeo_candidate_to_dict(c) for c in candidates]

        if _contains_bbox(request):
            bbox = {
                'xmin': request.REQUEST['xmin'],
                'ymin': request.REQUEST['ymin'],
                'xmax': request.REQUEST['xmax'],
                'ymax': request.REQUEST['ymax']
            }

            candidates = [c for c in candidates if _in_bbox(bbox, c)]

            if len(candidates) == 0:
                return _no_results_response(address, inregion=True)

        return {'candidates': candidates}
Example #5
0
 def test_pro_CancelIfRegexInAttr_case_sensitive(self):
     """Test CancelIfRegexInAttr preprocessor using case-sensitive option."""
     place_in = PlaceQuery('PO Box 123, Philadelphia, PA')
     place_out = CancelIfRegexInAttr(regex="PO BOX", attrs=('query',),
                                     ignorecase=False).process(place_in)
     place_exp = place_in  # we should still have it because PO BOX does not match exactly
     self.assertEqual_(place_out, place_exp)
Example #6
0
def _geocode_without_magic_key(request, address):
    # See settings.OMGEO_SETTINGS for configuration
    viewbox = _get_viewbox_from_request(request)
    pq = PlaceQuery(query=address, viewbox=viewbox)
    geocode_result = geocoder.geocode(pq)

    candidates = geocode_result.get('candidates', None)

    if not candidates:
        return _no_results_response(address)
    else:
        candidates = [_omgeo_candidate_to_dict(c) for c in candidates]

        if _contains_bbox(request):
            # The geocoder favored results inside the bounding box but may have
            # returned results outside the bounding box, so filter those away.
            bbox = {
                'xmin': request.REQUEST['xmin'],
                'ymin': request.REQUEST['ymin'],
                'xmax': request.REQUEST['xmax'],
                'ymax': request.REQUEST['ymax']
            }

            candidates = [c for c in candidates if _in_bbox(bbox, c)]

            if len(candidates) == 0:
                return _no_results_response(address, inregion=True)

        return {'candidates': candidates}
Example #7
0
 def test_pro_parsing_ParseSingleLine(self):
     """Test ParseSingleLine preprocessor using single-line UK address."""
     place_in = PlaceQuery('32 Bond Road, Surbiton, Surrey KT6 7SH')
     place_out = ParseSingleLine().process(place_in)
     self.assertEqual_(place_out.address, '32 Bond Road')
     self.assertEqual_(place_out.city, 'Surbiton, Surrey')
     self.assertEqual_(place_out.postal, 'KT6 7SH')
Example #8
0
 def test_pro_CancelIfRegexInAttr(self):
     """Test CancelIfRegexInAttr preprocessor."""
     place_in = PlaceQuery('PO Box 123, Philadelphia, PA')
     place_out = CancelIfRegexInAttr(regex="po box",
                                     attrs=('query', )).process(place_in)
     place_exp = False
     self.assertEqual_(place_out, place_exp)
Example #9
0
 def test_pro_CancelIfRegexInAttr_unicode_args(self):
     """Test CancelIfRegexInAttr preprocessor using bytestring query and unicode regex/attrs."""
     place_in = PlaceQuery(u'PO Box 123, Lindström, MN'.encode("utf-8"))
     # Test all 3 combinations for completeness, but only test the result once since if they
     # fail it will be by raising exceptions
     place_out = CancelIfRegexInAttr(regex=u"po box", attrs=('query',)).process(place_in)
     place_out = CancelIfRegexInAttr(regex="po box", attrs=(u'query',)).process(place_in)
     place_out = CancelIfRegexInAttr(regex=u"po box", attrs=('query',)).process(place_in)
     place_exp = False
     self.assertEqual_(place_out, place_exp)
Example #10
0
 def test_geocode_nom(self):
     """
     Test 1200 Callowhill Street using Nominatim geocoder.
     Also check to make sure coordinate values are floats and not some other data type.
     """
     candidates = self.g_nom.get_candidates(PlaceQuery('1200 Callowhill St, Philadelphia, PA'))
     x_type = type(candidates[0].x)
     y_type = type(candidates[0].y)
     self.assertEqual(x_type == float, True, 'x coord is of type %s instead of float' % x_type)
     self.assertEqual(y_type == float, True, 'y coord is of type %s instead of float' % y_type)
     self.assertEqual(len(candidates) > 0, True, 'No candidates returned.')
Example #11
0
def geocode(request, format=None):
    query = request.GET.get('search', None)
    key = request.GET.get('key', None)
    if (not query):
        response = Response(data={'error': 'Search parameter is required.'},
                            status=400)
        return response
    pq = PlaceQuery(query=query, country='US', key=key)
    result = geocoder.geocode(pq)
    candidates = result['candidates']
    candidates = [_omgeo_candidate_to_dict(c) for c in candidates]
    return Response(candidates)
Example #12
0
    def geocode(self, pq, waterfall=None, force_stats_logging=False):
        """
        :arg PlaceQuery pq:  PlaceQuery object (required).
        :arg bool waterfall: Boolean set to True if all geocoders listed should
                             be used to find results, instead of stopping after
                             the first geocoding service with valid candidates
                             (defaults to self.waterfall).
        :arg bool force_stats_logging: Raise exception if stats logging fails (default False).
        :returns: Returns a dictionary including:
                   * candidates - list of Candidate objects
                   * upstream_response_info - list of UpstreamResponseInfo objects
        """

        start_time = time.time()
        waterfall = self.waterfall if waterfall is None else waterfall
        if type(pq) in (str, unicode):
            pq = PlaceQuery(pq)
        processed_pq = copy.copy(pq)

        for p in self._preprocessors:  # apply universal address preprocessing
            processed_pq = p.process(processed_pq)
            if processed_pq == False:
                return get_result(
                )  # universal preprocessor rejects PlaceQuery

        upstream_response_info_list = []
        processed_candidates = []
        for gs in self._sources:  # iterate through each GeocodeService
            candidates, upstream_response_info = gs.geocode(processed_pq)
            if upstream_response_info is not None:
                upstream_response_info_list.append(upstream_response_info)
            processed_candidates += candidates  # merge lists
            if waterfall is False and len(processed_candidates) > 0:
                break  # if >= 1 good candidate, don't go to next geocoder

        for p in self._postprocessors:  # apply univ. candidate postprocessing
            if processed_candidates == []:
                break
                # avoid post-processing empty list
            processed_candidates = p.process(processed_candidates)

        result = dict(candidates=processed_candidates,
                      upstream_response_info=upstream_response_info_list)
        stats_dict = self.convert_geocode_result_to_nested_dicts(result)
        stats_dict = dict(stats_dict, original_pq=pq.__dict__)
        try:
            stats_logger.info(stats_dict)
        except Exception as exception:
            logger.error('Encountered exception while logging stats %s:\n%s',
                         stats_dict, exception)
            if force_stats_logging:
                raise exception
        return result
Example #13
0
def _geocode_with_magic_key(address, key):
    # See settings.OMGEO_SETTINGS_FOR_MAGIC_KEY for configuration
    pq = PlaceQuery(query=address, key=key)
    geocode_result = geocoder_for_magic_key.geocode(pq)
    candidates = geocode_result.get('candidates', None)
    if candidates:
        # Address searches return many candidates. But the user already
        # chose a specific suggestion so we want the first candidate.
        # The exception is a "point of interest" search, where the user's
        # chosen suggestion may be a category like "Beaches" and you want to
        # see many candidates.
        if candidates[0].locator_type != 'POI':
            candidates = [candidates[0]]
        candidates = [_omgeo_candidate_to_dict(c) for c in candidates]
        return {'candidates': candidates}
    else:
        return _no_results_response(address)
Example #14
0
def geocode(request):
    """
    Search for specified address, returning candidates with lat/long
    """
    key = request.REQUEST.get('key')
    address = request.REQUEST.get('address').encode('utf-8')

    if key:
        # See settings.OMGEO_SETTINGS for configuration
        pq = PlaceQuery(query=address, key=key)
        geocode_result = geocoder.geocode(pq)
        candidates = geocode_result.get('candidates', None)
        if candidates:
            # There should only be one candidate since the user already chose a
            # specific suggestion and the front end filters out suggestions
            # that might result in more than one candidate (like "Beaches").
            match = candidates[0]
            return {'lat': match.y, 'lng': match.x}

    return _no_results_response(address)
Example #15
0
    def test_pro_CancelIfPOBox(self):
        """Test CancelIfPOBox preprocessor."""
        place_in = PlaceQuery('PO Box 123, Philadelphia, PA')
        place_out = CancelIfPOBox().process(place_in)
        self.assertEqual_(place_out, False)

        place_in = PlaceQuery(address='PO Box 123',
                              city='Philadelphia',
                              state='PA')
        place_out = CancelIfPOBox().process(place_in)
        self.assertEqual_(place_out, False)

        place_in = PlaceQuery(address='P.O Box 123',
                              city='Philadelphia',
                              state='PA')
        place_out = CancelIfPOBox().process(place_in)
        self.assertEqual_(place_out, False)

        place_in = PlaceQuery(address='P  O  box 123',
                              city='Philadelphia',
                              state='PA')
        place_out = CancelIfPOBox().process(place_in)
        self.assertEqual_(place_out, False)

        place_in = PlaceQuery(address='P.O. Box 123',
                              city='Philadelphia',
                              state='PA')
        place_out = CancelIfPOBox().process(place_in)
        self.assertEqual_(place_out, False)

        place_in = PlaceQuery(address='P.O. Box K',
                              city='New Stanton',
                              state='PA')
        place_out = CancelIfPOBox().process(place_in)
        self.assertEqual_(place_out, False)

        place_in = PlaceQuery(address='PO. Box K',
                              city='New Stanton',
                              state='PA')
        place_out = CancelIfPOBox().process(place_in)
        self.assertEqual_(place_out, False)

        place_in = PlaceQuery(address='P.O.B. 123',
                              city='Philadelphia',
                              state='PA')
        place_out = CancelIfPOBox().process(place_in)
        self.assertEqual_(place_out, False)

        place_in = PlaceQuery(address='P.O. BX123',
                              city='Philadelphia',
                              state='PA')
        place_out = CancelIfPOBox().process(place_in)
        self.assertEqual_(place_out, False)

        place_in = PlaceQuery(address='POB 123',
                              city='Philadelphia',
                              state='PA')
        place_out = CancelIfPOBox().process(place_in)
        self.assertEqual_(place_out, False)

        place_in = PlaceQuery('POBOX 123, Philadelphia, PA')
        place_out = CancelIfPOBox().process(place_in)
        self.assertEqual_(place_out, False)

        place_in = PlaceQuery(
            '1200 Callowhill St, PO Box 466, Philadelphia, PA')
        place_out = CancelIfPOBox().process(place_in)
        self.assertEqual_(
            place_out,
            place_in)  # should still geocode because we a physical address
Example #16
0
    def setUp(self):
        # Viewbox objects - callowhill is from BSS Spring Garden station to Wash. Sq.
        vb = {
            'callowhill': Viewbox(-75.162628, 39.962769, -75.150963, 39.956322)
        }
        # PlaceQuery objects
        self.pq = {  # North American Addresses:
            'azavea': PlaceQuery('340 N 12th St Ste 402 Philadelphia PA'),
            'ambiguous_azavea': PlaceQuery('340 12th St Ste 402 Philadelphia PA'),
            'zip_plus_4_in_postal_plus_country': PlaceQuery(postal='19127-1115', country='US'),
            'wolf': PlaceQuery('Wolf Building'),
            'wolf_philly': PlaceQuery('Wolf Building, Philadelphia PA'),
            'wolf_bounded': PlaceQuery('Wolf Building', bounded=True, viewbox=vb['callowhill']),
            'bounded_340_12th': PlaceQuery('340 12th St, Philadelphia PA',
                                           bounded=True, viewbox=vb['callowhill']),
            'alpha_774R_W_Central_Ave': PlaceQuery('774R W Central Ave Alpha NJ'),
            'alpha_774_W_Central_Ave_Rear': PlaceQuery('774 W Central Ave Rear, Alpha NJ'),
            '8_kirkbride': PlaceQuery('8 Kirkbride Rd 08822'),
            'george_washington': PlaceQuery('201 W Montmorency Blvd, George, Washington'),
            'pine_needles_dr': PlaceQuery('11761 pine needles providence forge'),
            'pine_needles_ct': PlaceQuery('5328 pine needles providence forge'),
            'pine_needles_terr': PlaceQuery('5359 pine needles providence forge'),
            'moorestown_hyphenated': PlaceQuery('111-113 W Main St Moorestown NJ'),
            'willow_street': PlaceQuery('2819F Willow Street Pike Willow Street PA'),
            'willow_street_parts': PlaceQuery(address='2819F Willow Street Pike',
                                              city='Willow Street', state='PA', country='US'),
            'quebec': PlaceQuery('756 Rue Berri Montreal QC', country='CA'),
            'quebec_accent': PlaceQuery('527 Ch. Beauséjour, Saint-Elzéar-de-Témiscouata QC'),
            'quebec_hyphenated': PlaceQuery('227-227A Rue Commerciale, Saint-Louis-du-Ha! Ha! QC'),
            'senado_mx': PlaceQuery('Paseo de la Reforma 135, Tabacalera, Cuauhtémoc, Distrito Federal, 06030'),
            'senado_mx_struct': PlaceQuery(address='Paseo de la Reforma 135', neighborhood='Tabacalera, Cuauhtémoc', subregion='', state='Distrito Federal', postal='06030', country='MX'),
            'robert_cheetham': PlaceQuery('Robert Cheetham, Philadelphia'),
            # European Addresses:
            'london_pieces': PlaceQuery(address='31 Maiden Lane', city='London', country='UK'),
            'london_one_line': PlaceQuery('31 Maiden Lane, London WC2E', country='UK'),
            'london_pieces_hyphenated': PlaceQuery(address='31-32 Maiden Lane', city='London',
                                                   country='UK'),
            'london_one_line_hyphenated': PlaceQuery('31-32 Maiden Lane London WC2E', country='UK'),
            # Oceanian Addresses:
            'karori': PlaceQuery('102 Karori Road Karori Wellington', country='NZ'),
        }

        if BING_MAPS_API_KEY is not None:
            bing_settings = dict(api_key=BING_MAPS_API_KEY)
            self.g_bing = Geocoder(
                [['omgeo.services.Bing', {
                    'settings': bing_settings
                }]])

        if MAPQUEST_API_KEY is not None:
            mapquest_settings = dict(api_key=MAPQUEST_API_KEY)
            self.g_mapquest = Geocoder(
                [['omgeo.services.MapQuest', {
                    'settings': mapquest_settings
                }]])
            self.g_mapquest_ssl = Geocoder([[
                'omgeo.services.MapQuestSSL', {
                    'settings': mapquest_settings
                }
            ]])

        if PELIAS_API_KEY is not None:
            pelias_settings = dict(api_key=PELIAS_API_KEY)
            self.g_pelias = Geocoder(
                [['omgeo.services.Pelias', {
                    'settings': pelias_settings
                }]])

        if GOOGLE_API_KEY is not None:
            self.g_google = Geocoder([[
                'omgeo.services.Google', {
                    'settings': {
                        'api_key': GOOGLE_API_KEY
                    }
                }
            ]])
            self.g_google_wo_postprocess = Geocoder([[
                'omgeo.services.Google', {
                    'settings': {
                        'api_key': GOOGLE_API_KEY
                    },
                    'postprocessors': []
                }
            ]])

        #: main geocoder used for tests, using default APIs
        self.g = Geocoder()

        # geocoders using individual services
        self.g_esri_wgs = Geocoder([['omgeo.services.EsriWGS', {}]])

        if ESRI_CLIENT_ID is not None and ESRI_CLIENT_SECRET is not None:
            self.g_esri_wgs_auth = Geocoder([[
                'omgeo.services.EsriWGS', {
                    'settings': {
                        'client_id': ESRI_CLIENT_ID,
                        'client_secret': ESRI_CLIENT_SECRET
                    }
                }
            ]])

        if MAPQUEST_API_KEY is not None:  # MapQuest's open Nominatime API now also requires a key
            self.g_nom = Geocoder([['omgeo.services.Nominatim', {}]])

        self.g_census = Geocoder([['omgeo.services.USCensus', {}]])

        ESRI_WGS_LOCATOR_MAP = {
            'PointAddress': 'rooftop',
            'StreetAddress': 'interpolation',
            'PostalExt': 'postal_specific',  # accept ZIP+4
            'Postal': 'postal'
        }
        ESRI_WGS_POSTPROCESSORS_POSTAL_OK = [
            AttrExclude(
                ['USA.Postal'], 'locator'
            ),  # accept postal from everywhere but US (need PostalExt)
            AttrFilter(
                ['PointAddress', 'StreetAddress', 'PostalExt', 'Postal'],
                'locator_type'),
            AttrSorter(
                ['PointAddress', 'StreetAddress', 'PostalExt', 'Postal'],
                'locator_type'),
            AttrRename('locator', ESRI_WGS_LOCATOR_MAP
                       ),  # after filter to avoid searching things we toss out
            UseHighScoreIfAtLeast(99.8),
            ScoreSorter(),
            GroupBy('match_addr'),
            GroupBy(('x', 'y')),
        ]
        GEOCODERS_POSTAL_OK = [[
            'omgeo.services.EsriWGS', {
                'postprocessors': ESRI_WGS_POSTPROCESSORS_POSTAL_OK
            }
        ]]
        self.g_esri_wgs_postal_ok = Geocoder(GEOCODERS_POSTAL_OK)

        #: geocoder with fast timeout
        self.impatient_geocoder = Geocoder(
            [['omgeo.services.EsriWGS', {
                'settings': {
                    'timeout': 0.001
                }
            }]])
Example #17
0
 def test_geocode_census(self):
     """Test Azavea's address using US Census geocoder."""
     candidates = self.g_census.get_candidates(
         PlaceQuery('1200 Callowhill St, Philadelphia, PA'))
     self.assertEqual(len(candidates) > 0, True, 'No candidates returned.')
Example #18
0
 def test_pro_CancelIfRegexInAttr_unicode_query(self):
     """Test CancelIfRegexInAttr preprocessor using unicode query and default regex/attrs."""
     place_in = PlaceQuery(u'PO Box 123, Lindström, MN')
     place_out = CancelIfRegexInAttr(regex="po box", attrs=('query',)).process(place_in)
     place_exp = False
     self.assertEqual_(place_out, place_exp)
Example #19
0
 def test_geocode_esri_eu_soap(self):
     """Test ESRI Europe SOAP geocoder"""
     candidates = self.g_esri_eu_soap.get_candidates(PlaceQuery(
         address='31 Maiden Lane', city='London', country='UK'))
     self.assertEqual(len(candidates) > 0, True, 'No candidates returned.')