def verify_address(address: str, borough: str) -> AddressVerificationResult: ''' Attempt to verify the given address, returning the address, and whether it was actually verified. If the address was verified, the returned address may have changed. ''' search_text = get_geocoding_search_text(address, borough) features = geocoding.search(search_text) zipcode = '' if features is None: # Hmm, the geocoding service is unavailable. This # is unfortunate, but we don't want it to block # onboarding, so keep a note of it and let the # user continue. address_verified = False elif len(features) == 0: # The geocoding service is available, but the # address produces no results. raise forms.ValidationError('The address provided is invalid.') else: address_verified = True props = features[0].properties address = props.name zipcode = props.postalcode borough = BOROUGH_GID_TO_CHOICE[props.borough_gid] return AddressVerificationResult(address, borough, address_verified, zipcode)
def handle(self, *args, **options): features = geocoding.search(options['address']) if features is None: raise CommandError('Geocoding failed!') self.stdout.write("Geocoding results:\n\n") for feature in features: self.stdout.write(f"{feature.properties.label} " f"pad_bbl={feature.properties.pad_bbl}\n")
def update_geocoded_info(self): results = geocoding.search(self.address) if results: result = results[0] self.geocoded_address = result.properties.label longitude, latitude = result.geometry.coordinates self.geocoded_point = Point(longitude, latitude) else: self.geocoded_address = '' self.geocoded_point = None
def parse_address_or_bbl_or_bin(self, value: str) -> str: if BBL.safe_parse(value) or is_bin(value): return value features = geocoding.search(value) if not features: raise CommandError("Address not found!") props = features[0].properties self.stdout.write(f"Found BBL {props.pad_bbl} / BIN {props.pad_bin} ({props.label}).") self.stdout.write( f"Using the BIN (call this command separately with the BBL to use that instead)." ) return props.pad_bin
def lookup_addr_metadata(self): features = geocoding.search(self.full_address) if features: props = features[0].properties self.zipcode = props.postalcode self.pad_bbl = props.pad_bbl self.pad_bin = props.pad_bin elif self.__addr.has_changed(): # If the address has changed, we really don't want the existing # metadata to be there, because it will represent information # about their old address. self.zipcode = '' self.pad_bbl = '' self.pad_bin = '' self.__addr.set_to_unchanged() self.__addr_meta.set_to_unchanged()
def resolve_ddo_suggestions(self, info, address: str, borough: str): if not address.strip(): return None if not settings.WOW_DATABASE: logger.warning("Data-driven onboarding requires WoW integration.") return None features = geocoding.search(get_geocoding_search_text( address, borough)) if not features: return None props = features[0].properties row = cached_run_ddo_sql_query(props.pad_bbl) return DDOSuggestionsResult(full_address=props.label, bbl=props.pad_bbl, is_rtc_eligible=row['zipcode'] in RTC_ZIPCODES, **row)
def lookup_nycaddr_metadata(self): features = geocoding.search(self.full_nyc_address) if features: feature = features[0] props = feature.properties self.geocoded_address = f"{props.label} (via NYC GeoSearch)" self.zipcode = props.postalcode self.pad_bbl = props.pad_bbl self.pad_bin = props.pad_bin self.geometry = feature.geometry.dict() elif self.__nycaddr.has_changed(): # If the address has changed, we really don't want the existing # metadata to be there, because it will represent information # about their old address. self.geocoded_address = "" self.zipcode = "" self.pad_bbl = "" self.pad_bin = "" self.geometry = None self.__nycaddr.set_to_unchanged() self.__nycaddr_meta.set_to_unchanged()
def evaluate_address(request): if not (settings.NYCDB_DATABASE and settings.GEOCODING_SEARCH_URL): # https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/501 return make_json_error("NOT_IMPLEMENTED", 501) text = request.GET.get("text") if not text: return make_json_error("INVALID_TEXT", 400) result = geocoding.search(text) if result is None: # https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/502 return make_json_error("GEOCODING_UNAVAILABLE", 502) response: Dict[str, Any] = { "status": 200, "result": None, } if len(result) > 0: first = result[0].properties response["result"] = { **first.dict(), "predicted_housing_type": predict_housing_type(first.pad_bbl), } return JsonResponse(response, status=200)
def resolve_ddo_suggestions( self, info, address: str, borough: str) -> Optional[DDOSuggestionsResult]: if not address.strip(): return None if not settings.WOW_DATABASE: logger.warning("Data-driven onboarding requires WoW integration.") return None features = geocoding.search(get_geocoding_search_text( address, borough)) if not features: return None props = features[0].properties row = cached_run_ddo_sql_query(props.pad_bbl) if not row: return None normalized_row = normalize_complaint_category(row) return DDOSuggestionsResult( full_address=props.label, bbl=props.pad_bbl, is_rtc_eligible=normalized_row["zipcode"] in RTC_ZIPCODES, is_nycha_bbl=is_nycha_bbl(props.pad_bbl), **normalized_row, )
def test_search_promotes_results_in_same_borough(requests_mock): requests_mock.get(settings.GEOCODING_SEARCH_URL, json=EXAMPLE_SEARCH) results = geocoding.search("150 cody court, staten island") assert results[ 0].properties.label == "150 CODY COURT, Staten Island, New York, NY, USA"
def lookup_bbl_and_bin_and_full_address(address: str) -> Tuple[str, str, str]: features = geocoding.search(address) if not features: return ("", "", "") props = features[0].properties return (props.pad_bbl, props.pad_bin, props.label)
def test_search_works(requests_mock): requests_mock.get(settings.GEOCODING_SEARCH_URL, json=EXAMPLE_SEARCH) results = geocoding.search("150 court") assert results[ 0].properties.label == "150 COURT STREET, Brooklyn, New York, NY, USA"
def test_search_returns_none_on_500(requests_mock): requests_mock.get(settings.GEOCODING_SEARCH_URL, status_code=500) assert geocoding.search("150 court") is None
def run_check(self) -> bool: features = geocoding.search('150 court street, brooklyn') if features is None: return False return features[0].properties.pad_bbl == '3002920026'
def test_search_returns_none_on_request_exception(requests_mock): requests_mock.get(settings.GEOCODING_SEARCH_URL, exc=requests.exceptions.Timeout) assert geocoding.search("150 court") is None
def test_search_promotes_exact_matches(requests_mock): requests_mock.get(settings.GEOCODING_SEARCH_URL, json=EXAMPLE_SEARCH) results = geocoding.search("150 brightwatr court, brooklyn") assert results[ 0].properties.label == "150 BRIGHTWATR COURT, Brooklyn, New York, NY, USA"
def test_search_returns_none_on_bad_result_without_features(requests_mock): requests_mock.get(settings.GEOCODING_SEARCH_URL, json={"blarg": False}) assert geocoding.search("150 court") is None
def test_search_returns_none_on_feature_validation_errors(requests_mock): requests_mock.get(settings.GEOCODING_SEARCH_URL, json={"features": [{ "blah": 1 }]}) assert geocoding.search("150 court") is None