-
Notifications
You must be signed in to change notification settings - Fork 36
Add US Autocomplete (V2) API client #94
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
f629404
Add US Autocomplete (V2) API client
mae-smarty c446df8
Refactored source to enum
andrea-wait-smarty 715e357
Merge branch 'master' of github.com:smartystreets/smartystreets-pytho…
mae-smarty 204dcc1
add source
mae-smarty 0b4ef23
Change exclude to list of strings, rename prefer_geolocation.
andyjohnsonsmarty 9e4f6c2
Add add_exclude func.
andyjohnsonsmarty File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,79 @@ | ||
| import os | ||
|
|
||
| from smartystreets_python_sdk import SharedCredentials, BasicAuthCredentials, ClientBuilder | ||
| from smartystreets_python_sdk.us_autocomplete import Lookup as AutocompleteLookup, geolocation_type | ||
| from smartystreets_python_sdk.us_autocomplete.source import Source | ||
|
|
||
| # This example is for us-autocomplete (V2). It has the same name as a previous product | ||
| # which has been deprecated since 2022 which we refer to as US Autocomplete Basic. | ||
| # | ||
| # If you are still using US Autocomplete Basic, this SDK will not work. | ||
|
|
||
| def run(): | ||
| # key = "Your SmartyStreets Key here" | ||
| # hostname = "Your Hostname here" | ||
|
|
||
| # We recommend storing your secret keys in environment variables instead---it's safer! | ||
| # for client-side requests (browser/mobile), use this code: | ||
| # key = os.environ['SMARTY_AUTH_WEB'] | ||
| # hostname = os.environ['SMARTY_WEBSITE_DOMAIN'] | ||
| # | ||
| # credentials = SharedCredentials(key, hostname) | ||
|
|
||
| # for server-to-server requests, use this code: | ||
| auth_id = os.environ['SMARTY_AUTH_ID'] | ||
| auth_token = os.environ['SMARTY_AUTH_TOKEN'] | ||
|
|
||
| credentials = BasicAuthCredentials(auth_id, auth_token) | ||
|
|
||
| client = ClientBuilder(credentials).build_us_autocomplete_api_client() | ||
|
|
||
| lookup = AutocompleteLookup('1042 W Center') | ||
|
|
||
| # Uncomment the below line to add a custom parameter | ||
| # lookup.add_custom_parameter("parameter", "value") | ||
|
|
||
| client.send(lookup) | ||
|
|
||
| print('*** Result with no filter ***') | ||
| print() | ||
| for suggestion in lookup.result: | ||
| print(suggestion.street_line + " " + suggestion.city, suggestion.state, sep=", ") | ||
|
|
||
| # Documentation for input fields can be found at: | ||
| # https://www.smarty.com/docs/apis/us-autocomplete-v2/reference#http-request-input-fields | ||
|
|
||
| lookup.add_city_filter('Denver,Aurora,CO') | ||
| lookup.add_city_filter('Orem,UT') | ||
| lookup.add_state_preference('CO') | ||
| # lookup.selected = '1042 W Center St Apt A (24) Orem UT 84057' | ||
| lookup.max_results = 5 | ||
| lookup.prefer_geolocation = geolocation_type.NONE | ||
| lookup.prefer_ratio = 33 | ||
| lookup.source = Source.ALL | ||
|
|
||
| suggestions = client.send(lookup) # The client will also return the suggestions directly | ||
|
|
||
| print() | ||
| print('*** Result with some filters ***') | ||
| entry_id = '' | ||
| address_with_secondaries = '' | ||
| for suggestion in suggestions: | ||
| print(suggestion.street_line + " " + suggestion.city + ", " + suggestion.state) | ||
| if suggestion.entry_id: | ||
| address_with_secondaries = suggestion.street_line + " " + suggestion.city + " " + suggestion.state | ||
| entry_id = suggestion.entry_id | ||
|
|
||
| # Expand the secondaries of a result that has an entry_id by passing it back as the selected address. | ||
| if entry_id: | ||
| lookup.selected = entry_id | ||
| suggestions = client.send(lookup) | ||
|
|
||
| print() | ||
| print('*** Secondaries for: [' + address_with_secondaries + '] ***') | ||
| for suggestion in suggestions: | ||
| print(suggestion.street_line + " " + suggestion.city + ", " + suggestion.state) | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| run() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| from .suggestion import Suggestion | ||
| from .lookup import Lookup | ||
| from .client import Client | ||
| from .source import Source |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,70 @@ | ||
| from enum import Enum | ||
|
|
||
| from smartystreets_python_sdk import Request | ||
| from smartystreets_python_sdk.exceptions import SmartyException | ||
| from smartystreets_python_sdk.us_autocomplete import Suggestion, geolocation_type | ||
|
|
||
|
|
||
| class Client: | ||
| def __init__(self, sender, serializer): | ||
| """ | ||
| It is recommended to instantiate this class using ClientBuilder.build_us_autocomplete_api_client() | ||
| """ | ||
| self.sender = sender | ||
| self.serializer = serializer | ||
|
|
||
| def send(self, lookup): | ||
| """ | ||
| Sends a Lookup object to the US Autocomplete API and stores the result in the Lookup's result field. | ||
| """ | ||
| if not lookup or not lookup.search: | ||
| raise SmartyException('Send() must be passed a Lookup with the search field set.') | ||
|
|
||
| request = self.build_request(lookup) | ||
|
|
||
| response = self.sender.send(request) | ||
|
|
||
| if response.error: | ||
| raise response.error | ||
|
|
||
| result = self.serializer.deserialize(response.payload) | ||
| suggestions = self.convert_suggestions(result.get('suggestions') or []) | ||
| lookup.result = suggestions | ||
|
|
||
| return suggestions | ||
|
|
||
| def build_request(self, lookup): | ||
| request = Request() | ||
|
|
||
| self.add_parameter(request, 'search', lookup.search) | ||
| self.add_parameter(request, 'max_results', lookup.max_results) | ||
| self.add_parameter(request, 'include_only_cities', self.build_filter_string(lookup.city_filter)) | ||
| self.add_parameter(request, 'include_only_states', self.build_filter_string(lookup.state_filter)) | ||
| self.add_parameter(request, 'include_only_zip_codes', self.build_filter_string(lookup.zip_filter)) | ||
| self.add_parameter(request, 'exclude_states', self.build_filter_string(lookup.exclude_states)) | ||
| self.add_parameter(request, 'prefer_cities', self.build_filter_string(lookup.prefer_cities)) | ||
| self.add_parameter(request, 'prefer_states', self.build_filter_string(lookup.prefer_states)) | ||
| self.add_parameter(request, 'prefer_zip_codes', self.build_filter_string(lookup.prefer_zips)) | ||
| self.add_parameter(request, 'prefer_ratio', lookup.prefer_ratio) | ||
| self.add_parameter(request, 'prefer_geolocation', lookup.prefer_geolocation) | ||
| self.add_parameter(request, 'source', lookup.source) | ||
| self.add_parameter(request, 'selected', lookup.selected) | ||
| self.add_parameter(request, 'exclude', self.build_filter_string(lookup.exclude, ',')) | ||
|
|
||
| for parameter in lookup.custom_parameter_array: | ||
| self.add_parameter(request, parameter, lookup.custom_parameter_array[parameter]) | ||
|
|
||
| return request | ||
|
|
||
| @staticmethod | ||
| def build_filter_string(filter_list, separator=';'): | ||
| return separator.join(filter_list or []) or None | ||
|
|
||
| @staticmethod | ||
| def convert_suggestions(suggestion_dictionaries): | ||
| return [Suggestion(suggestion) for suggestion in suggestion_dictionaries] | ||
|
|
||
| @staticmethod | ||
| def add_parameter(request, key, value): | ||
| if value and value != 'none': | ||
| request.parameters[key] = value.value if isinstance(value, Enum) else value |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| CITY = 'city' | ||
|
|
||
| NONE = 'none' |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,83 @@ | ||
| from smartystreets_python_sdk.us_autocomplete import geolocation_type | ||
|
|
||
|
|
||
| class Lookup: | ||
| def __init__(self, search=None, max_results=None, city_filter=None, state_filter=None, zip_filter=None, | ||
| exclude_states=None, prefer_cities=None, prefer_states=None, prefer_zips=None, prefer_ratio=None, | ||
| prefer_geolocation=None, selected=None, exclude=None, source=None): | ||
|
|
||
| """ | ||
| In addition to holding all of the input data for this lookup, this class also will contain the result | ||
| of the lookup after it comes back from the API. | ||
|
|
||
| See "https://www.smarty.com/docs/apis/us-autocomplete-v2/reference#http-request-input-fields" | ||
|
|
||
| :param search: The part of the address that has already been typed (required) | ||
| :param max_results: Maximum number of address suggestions to return | ||
| :param city_filter: Limit the results to only those cities listed, as well as those in state_filter | ||
| :param state_filter: Limit the results to only those states listed, as well as those in city_filter | ||
| :param zip_filter: Limit the result to only those ZIP Codes listed. When this parameter is used, | ||
| no other _cities, _states parameters can be used | ||
| :param exclude_states: Exclude the following states from the results. When this parameter is used, | ||
| no other include_ parameters can be used | ||
| :param prefer_cities: Display suggestions with the listed cities and states at the top of the suggestion list | ||
| :param prefer_states: Display suggestions with the listed states at the top of the suggestion list | ||
| :param prefer_zips: Display suggestions with the listed ZIP Codes at the top of the suggestion list. | ||
| When this parameter is used, no other _cities or _state parameters can be used | ||
| :param prefer_ratio: Specifies the percentage of address suggestions that should be preferred | ||
| and will appear at the top of the suggestion list | ||
| :param prefer_geolocation: If omitted or set to city it uses the sender's IP address to determine location, | ||
| then automatically adds the city and state to the prefer_cities value. | ||
| This parameter takes precedence over other _include or exclude parameters, | ||
| meaning that if it is not set to none, you may see addresses from the customer's area | ||
| when you may not desire it | ||
| :param selected: Used by UI components to request a list of secondaries (up to 100) for the specified address | ||
| :param exclude: Removes the given partial address from the suggestion results | ||
| :param source: Include results from alternate data sources. Defaults to None (API default: postal). | ||
| Use Source.ALL to include non-postal addresses, Source.POSTAL to limit to postal only. | ||
| """ | ||
| self.result = [] | ||
| self.custom_parameter_array = {} | ||
| self.search = search | ||
| self.max_results = max_results | ||
| self.city_filter = city_filter or [] | ||
| self.state_filter = state_filter or [] | ||
| self.zip_filter = zip_filter or [] | ||
| self.exclude_states = exclude_states or [] | ||
| self.prefer_cities = prefer_cities or [] | ||
| self.prefer_states = prefer_states or [] | ||
| self.prefer_zips = prefer_zips or [] | ||
| self.prefer_ratio = prefer_ratio | ||
| self.prefer_geolocation = prefer_geolocation | ||
| self.selected = selected | ||
| self.exclude = exclude or [] | ||
| self.source = source | ||
|
|
||
| def add_city_filter(self, city): | ||
| self.city_filter.append(city) | ||
|
|
||
| def add_state_filter(self, state): | ||
| self.state_filter.append(state) | ||
|
|
||
| def add_zip_filter(self, zipcode): | ||
| self.prefer_geolocation = geolocation_type.NONE | ||
| self.zip_filter.append(zipcode) | ||
|
|
||
| def add_state_exclusion(self, state): | ||
| self.exclude_states.append(state) | ||
|
|
||
| def add_city_preference(self, city): | ||
| self.prefer_cities.append(city) | ||
|
|
||
| def add_state_preference(self, state): | ||
| self.prefer_states.append(state) | ||
|
|
||
| def add_zip_preference(self, zipcode): | ||
| self.prefer_geolocation = geolocation_type.NONE | ||
| self.prefer_zips.append(zipcode) | ||
|
|
||
| def add_exclude(self, exclude_type): | ||
| self.exclude.append(exclude_type) | ||
|
|
||
| def add_custom_parameter(self, parameter, value): | ||
| self.custom_parameter_array[parameter] = value |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| from enum import Enum | ||
|
|
||
|
|
||
| class Source(str, Enum): | ||
| ALL = "all" | ||
| POSTAL = "postal" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| class Suggestion: | ||
| def __init__(self, obj=None): | ||
| """ | ||
| See "https://www.smarty.com/docs/apis/us-autocomplete-v2/reference#http-response-status" | ||
| """ | ||
| self.smarty_key = obj.get('smarty_key', None) | ||
| self.entry_id = obj.get('entry_id', None) | ||
| self.street_line = obj.get('street_line', None) | ||
| self.secondary = obj.get('secondary', None) | ||
| self.city = obj.get('city', None) | ||
| self.state = obj.get('state', None) | ||
| self.zipcode = obj.get('zipcode', None) | ||
| self.entries = obj.get('entries', None) | ||
| self.source = obj.get('source', None) | ||
Empty file.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.