Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions examples/international_autocomplete_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from smartystreets_python_sdk import SharedCredentials, ClientBuilder, BasicAuthCredentials
from smartystreets_python_sdk.international_autocomplete import Lookup as InternationalAutocompleteLookup
from smartystreets_python_sdk.international_autocomplete import LanguageMode


def run():
Expand All @@ -27,6 +28,7 @@ def run():
lookup.country = "FRA"
lookup.max_group_results = 50
lookup.geolocation = True
lookup.language = LanguageMode.NATIVE

# Uncomment the below line to add a custom parameter
# lookup.add_custom_parameter("parameter", "value")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from .candidate import Candidate
from .lookup import Lookup
from .client import Client
from .language_mode import LanguageMode
8 changes: 8 additions & 0 deletions smartystreets_python_sdk/international_autocomplete/client.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from smartystreets_python_sdk import Request
from smartystreets_python_sdk.exceptions import SmartyException
from smartystreets_python_sdk.international_autocomplete import Candidate
from smartystreets_python_sdk.international_autocomplete.language_mode import LanguageMode


class Client:
Expand Down Expand Up @@ -45,6 +46,7 @@ def build_request(self, lookup):
self.add_parameter(request, 'geolocation', 'on')
self.add_parameter(request, 'include_only_locality', lookup.locality)
self.add_parameter(request, 'include_only_postal_code', lookup.postal_code)
self.add_parameter(request, 'language', self.normalized_language(lookup.language))

for parameter in lookup.custom_parameter_array:
self.add_parameter(request, parameter, lookup.custom_parameter_array[parameter])
Expand All @@ -59,3 +61,9 @@ def convert_candidates(candidate_dictionaries):
def add_parameter(request, key, value):
if value and value != 'none':
request.parameters[key] = value

@staticmethod
def normalized_language(language):
if language is None:
return None
return LanguageMode.from_value(language).value
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
from enum import Enum

from smartystreets_python_sdk.exceptions import UnprocessableEntityError


class LanguageMode(Enum):
"""
A closed set of valid Language values, the closest Python equivalent to an enum-constrained field.
"""
NATIVE = 'native'
LATIN = 'latin'

@staticmethod
def from_value(value):
"""
Resolves a LanguageMode instance or a raw value (eg. from user input or config) into a LanguageMode,
matching 'native'/'latin' regardless of case.
"""
if isinstance(value, LanguageMode):
return value

for mode in LanguageMode:
if str(value).lower() == mode.value:
return mode

raise UnprocessableEntityError(
"invalid Language value; must be unset, 'native', or 'latin' (case-insensitive)")
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
class Lookup:
def __init__(self, search=None, address_id=None, country=None, max_results=5, max_group_results=100,
geolocation=False, locality=None, postal_code=None):
geolocation=False, locality=None, postal_code=None, language=None):
"""
In addition to holding all the input data for this lookup, this class also will contain the result
of the lookup after it comes back from the API.
Expand All @@ -10,6 +10,7 @@ def __init__(self, search=None, address_id=None, country=None, max_results=5, ma
:param administrative_area: Limit the results to only the administrative area provided
:param locality: Limit the results to only the locality provided
:param postal_code: Limit the results to only the postal code provided
:param language: The output language, Native or Latin (defaults to the country's language)
"""
self.result = []

Expand All @@ -22,6 +23,7 @@ def __init__(self, search=None, address_id=None, country=None, max_results=5, ma
self.geolocation = geolocation
self.locality = locality
self.postal_code = postal_code
self.language = language

def add_custom_parameter(self, parameter, value):
self.custom_parameter_array[parameter] = value
58 changes: 57 additions & 1 deletion test/international_autocomplete/client_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

from smartystreets_python_sdk import Response, exceptions
from test.mocks import *
from smartystreets_python_sdk.international_autocomplete import Client, Lookup
from smartystreets_python_sdk.international_autocomplete import Client, LanguageMode, Lookup
from smartystreets_python_sdk.international_street import LanguageMode as StreetLanguageMode


class TestClient(unittest.TestCase):
Expand All @@ -29,6 +30,7 @@ def test_sending_fully_populated_lookup(self):
lookup.locality = '3'
lookup.postal_code = '4'
lookup.address_id = '5'
lookup.language = LanguageMode.NATIVE
lookup.add_custom_parameter('custom', '6')

client.send(lookup)
Expand All @@ -41,6 +43,7 @@ def test_sending_fully_populated_lookup(self):
self.assertEqual('3', sender.request.parameters['include_only_locality'])
self.assertEqual('4', sender.request.parameters['include_only_postal_code'])
self.assertEqual('/5', sender.request.url_components)
self.assertEqual(LanguageMode.NATIVE.value, sender.request.parameters['language'])
self.assertEqual('6', sender.request.parameters['custom'])

def test_sending_lookup_with_custom_max_group_results(self):
Expand All @@ -65,6 +68,59 @@ def test_sending_lookup_with_geolocation(self):

self.assertEqual('on', sender.request.parameters['geolocation'])

def test_sending_lookup_with_language(self):
sender = RequestCapturingSender()
serializer = FakeSerializer({})
client = Client(sender, serializer)
lookup = Lookup('1')
lookup.language = LanguageMode.NATIVE

client.send(lookup)

self.assertEqual(LanguageMode.NATIVE.value, sender.request.parameters['language'])

def test_sending_lookup_with_mixed_case_language_value(self):
sender = RequestCapturingSender()
serializer = FakeSerializer({})
client = Client(sender, serializer)
lookup = Lookup('1')
lookup.language = 'Latin'

client.send(lookup)

self.assertEqual('latin', sender.request.parameters['language'])

def test_mixed_case_language_not_mutated(self):
sender = RequestCapturingSender()
serializer = FakeSerializer({})
client = Client(sender, serializer)
lookup = Lookup('1')
lookup.language = 'Latin'

client.send(lookup)

self.assertEqual('Latin', lookup.language)

def test_rejects_invalid_mixed_case_language_value(self):
sender = MockSender(None)
client = Client(sender, None)
lookup = Lookup('1')
lookup.language = 'Klingon'

self.assertRaises(exceptions.UnprocessableEntityError, client.send, lookup)

def test_language_omitted_when_not_set(self):
sender = RequestCapturingSender()
serializer = FakeSerializer({})
client = Client(sender, serializer)

client.send(Lookup('1'))

self.assertNotIn('language', sender.request.parameters)

def test_language_mode_not_shared_with_international_street(self):
self.assertIsNot(LanguageMode, StreetLanguageMode)

def test_deserialize_called_with_response_body(self):
response = Response('Hello, World!', 0)

Expand Down
Loading