Skip to content

Commit 8650e31

Browse files
Merge pull request #110 from rosette-api/RCB-622-param-fix
RCB-622: fix calling by map
2 parents 2580cf1 + 2df306d commit 8650e31

2 files changed

Lines changed: 102 additions & 39 deletions

File tree

rosette/api.py

Lines changed: 33 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ def __str__(self):
8686
return sst + ": " + self.message + ":\n " + self.response_message
8787

8888

89-
class _DocumentParamSetBase(object):
89+
class _RequestParametersBase(object):
9090

9191
def __init__(self, repertoire):
9292
self.__params = {}
@@ -135,7 +135,7 @@ def _byteify(value): # py 3 only
135135
return byte_array
136136

137137

138-
class DocumentParameters(_DocumentParamSetBase):
138+
class DocumentParameters(_RequestParametersBase):
139139
"""Parameter object for all operations requiring input other than
140140
translated_name.
141141
Two fields, C{content} and C{inputUri}, are set via
@@ -152,7 +152,7 @@ class DocumentParameters(_DocumentParamSetBase):
152152

153153
def __init__(self):
154154
"""Create a L{DocumentParameters} object."""
155-
_DocumentParamSetBase.__init__(
155+
_RequestParametersBase.__init__(
156156
self, ("content", "contentUri", "language", "profileId"))
157157
self.file_name = ""
158158
self.use_multipart = False
@@ -199,7 +199,7 @@ def load_document_string(self, content_as_string):
199199
self["content"] = content_as_string
200200

201201

202-
class NameTranslationParameters(_DocumentParamSetBase):
202+
class NameTranslationParameters(_RequestParametersBase):
203203
"""Parameter object for C{name-translation} endpoint.
204204
The following values may be set by the indexing (i.e.,C{ parms["name"]}) operator.
205205
The values are all strings (when not C{None}).
@@ -227,7 +227,7 @@ class NameTranslationParameters(_DocumentParamSetBase):
227227

228228
def __init__(self):
229229
self.use_multipart = False
230-
_DocumentParamSetBase.__init__(
230+
_RequestParametersBase.__init__(
231231
self,
232232
("name",
233233
"targetLanguage",
@@ -248,7 +248,7 @@ def validate(self):
248248
repr(option))
249249

250250

251-
class AddressSimilarityParameters(_DocumentParamSetBase):
251+
class AddressSimilarityParameters(_RequestParametersBase):
252252
"""Parameter object for C{address-similarity} endpoint.
253253
254254
C{address1} and C{address2} are required.
@@ -271,7 +271,7 @@ class AddressSimilarityParameters(_DocumentParamSetBase):
271271

272272
def __init__(self):
273273
self.use_multipart = False
274-
_DocumentParamSetBase.__init__(self, ("address1", "address2", "parameters"))
274+
_RequestParametersBase.__init__(self, ("address1", "address2", "parameters"))
275275

276276
def validate(self):
277277
"""Internal. Do not use."""
@@ -283,7 +283,7 @@ def validate(self):
283283
repr(option))
284284

285285

286-
class NameSimilarityParameters(_DocumentParamSetBase):
286+
class NameSimilarityParameters(_RequestParametersBase):
287287
"""Parameter object for C{name-similarity} endpoint.
288288
289289
C{name1} and C{name2} are required.
@@ -313,7 +313,7 @@ class NameSimilarityParameters(_DocumentParamSetBase):
313313

314314
def __init__(self):
315315
self.use_multipart = False
316-
_DocumentParamSetBase.__init__(self, ("name1", "name2", "parameters"))
316+
_RequestParametersBase.__init__(self, ("name1", "name2", "parameters"))
317317

318318
def validate(self):
319319
"""Internal. Do not use."""
@@ -325,7 +325,7 @@ def validate(self):
325325
repr(option))
326326

327327

328-
class NameDeduplicationParameters(_DocumentParamSetBase):
328+
class NameDeduplicationParameters(_RequestParametersBase):
329329
"""Parameter object for C{name-deduplication} endpoint.
330330
Required:
331331
C{names} A list of C{name} objects
@@ -334,7 +334,7 @@ class NameDeduplicationParameters(_DocumentParamSetBase):
334334

335335
def __init__(self):
336336
self.use_multipart = False
337-
_DocumentParamSetBase.__init__(self, ("names", "threshold"))
337+
_RequestParametersBase.__init__(self, ("names", "threshold"))
338338

339339
def validate(self):
340340
"""Internal. Do not use."""
@@ -438,7 +438,7 @@ def ping(self):
438438
response = self.api.get_http(url, headers=headers)
439439
return self.__finish_result(response, "ping")
440440

441-
def call(self, parameters):
441+
def call(self, parameters, paramtype=None):
442442
"""Invokes the endpoint to which this L{EndpointCaller} is bound.
443443
Passes data and metadata specified by C{parameters} to the server
444444
endpoint to which this L{EndpointCaller} object is bound. For all
@@ -455,24 +455,26 @@ def call(self, parameters):
455455
@param parameters: An object specifying the data,
456456
and possible metadata, to be processed by the endpoint. See the
457457
details for those object types.
458-
@type parameters: For C{name-translation}, L{NameTranslationParameters},
459-
otherwise L{DocumentParameters} or L{str}
458+
@type parameters: Parameters types or L{str} for document request.
459+
@param paramtype: Required parameters type.
460460
@return: A python dictionary expressing the result of the invocation.
461461
"""
462+
if paramtype and not isinstance(parameters, paramtype):
463+
raise RosetteException(
464+
"incompatible",
465+
"The parameters must be " + str(paramtype),
466+
self.suburl)
462467

463-
if not isinstance(parameters, _DocumentParamSetBase):
464-
if self.suburl != self.api.endpoints['NAME_SIMILARITY'] \
465-
and self.suburl != self.api.self.api.endpoints['NAME_TRANSLATION'] \
466-
and self.suburl != self.api.self.api.endpoints['NAME_DEDUPLICATION'] \
467-
and self.suburl != self.api.self.api.endpoints['ADDRESS_SIMILARITY']:
468-
text = parameters
469-
parameters = DocumentParameters()
470-
parameters['content'] = text
471-
else:
472-
raise RosetteException(
473-
"incompatible",
474-
"Text-only input only works for DocumentParameter endpoints",
475-
self.suburl)
468+
if type(parameters) == str:
469+
text = parameters
470+
parameters = DocumentParameters()
471+
parameters['content'] = text
472+
473+
if not paramtype and not isinstance(parameters, DocumentParameters):
474+
raise RosetteException(
475+
"incompatible",
476+
"The parameters must be string or DocumentParameters",
477+
self.suburl)
476478

477479
self.use_multipart = parameters.use_multipart
478480
url = self.service_url + self.suburl
@@ -915,7 +917,7 @@ def address_similarity(self, parameters):
915917
and possible metadata, to be processed by the name matcher.
916918
@type parameters: L{AddressSimilarityParameters}
917919
@return: A python dictionary containing the results of name matching."""
918-
return EndpointCaller(self, self.endpoints['ADDRESS_SIMILARITY']).call(parameters)
920+
return EndpointCaller(self, self.endpoints['ADDRESS_SIMILARITY']).call(parameters, AddressSimilarityParameters)
919921

920922
def name_translation(self, parameters):
921923
"""
@@ -925,7 +927,7 @@ def name_translation(self, parameters):
925927
and possible metadata, to be processed by the name translator.
926928
@type parameters: L{NameTranslationParameters}
927929
@return: A python dictionary containing the results of name translation."""
928-
return EndpointCaller(self, self.endpoints['NAME_TRANSLATION']).call(parameters)
930+
return EndpointCaller(self, self.endpoints['NAME_TRANSLATION']).call(parameters, NameTranslationParameters)
929931

930932
def translated_name(self, parameters):
931933
""" deprecated
@@ -944,7 +946,7 @@ def name_similarity(self, parameters):
944946
and possible metadata, to be processed by the name matcher.
945947
@type parameters: L{NameSimilarityParameters}
946948
@return: A python dictionary containing the results of name matching."""
947-
return EndpointCaller(self, self.endpoints['NAME_SIMILARITY']).call(parameters)
949+
return EndpointCaller(self, self.endpoints['NAME_SIMILARITY']).call(parameters, NameSimilarityParameters)
948950

949951
def matched_name(self, parameters):
950952
""" deprecated
@@ -962,7 +964,7 @@ def name_deduplication(self, parameters):
962964
as a threshold
963965
@type parameters: L{NameDeduplicationParameters}
964966
@return: A python dictionary containing the results of de-duplication"""
965-
return EndpointCaller(self, self.endpoints['NAME_DEDUPLICATION']).call(parameters)
967+
return EndpointCaller(self, self.endpoints['NAME_DEDUPLICATION']).call(parameters, NameDeduplicationParameters)
966968

967969
def text_embedding(self, parameters):
968970
""" deprecated

tests/test_rosette_api.py

Lines changed: 69 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,12 @@ def doc_params():
6565
params['content'] = 'Sample test string'
6666
return params
6767

68+
@pytest.fixture
69+
def doc_map():
70+
""" fixture for a simple map of doc request """
71+
return {'content': 'Simple test string'}
72+
73+
6874
# Of Note: httpretty provides a short hand decorator, @httpretty.activate, that wraps the decorated
6975
# function with httpretty.enable() and ends it with httpretty.disable(). However, when combined
7076
# with pytest fixtures, the passed in fixture arguments are ignored, resulting in a TypeError.
@@ -211,32 +217,40 @@ def test_the_max_pool_size(json_response, doc_params):
211217
# Test the language endpoint
212218

213219

214-
def test_the_language_endpoint(api, json_response, doc_params):
220+
def test_the_language_endpoint(api, json_response, doc_params, doc_map):
215221
"""Test language endpoint"""
216222
httpretty.enable()
217-
httpretty.register_uri(httpretty.POST, "https://api.rosette.com/rest/v1/info",
218-
body=json_response, status=200, content_type="application/json")
219223
httpretty.register_uri(httpretty.POST, "https://api.rosette.com/rest/v1/language",
220224
body=json_response, status=200, content_type="application/json")
221225

222226
result = api.language(doc_params)
223227
assert result["name"] == "Rosette"
228+
229+
with pytest.raises(RosetteException) as e_rosette:
230+
result = api.language(doc_map)
231+
assert e_rosette.value.status == 'incompatible'
232+
224233
httpretty.disable()
225234
httpretty.reset()
226235

227236
# Test the sentences endpoint
228237

229238

230-
def test_the_sentences_endpoint(api, json_response, doc_params):
239+
def test_the_sentences_endpoint(api, json_response, doc_params, doc_map):
231240
"""Test the sentences endpoint"""
232241
httpretty.enable()
233-
httpretty.register_uri(httpretty.POST, "https://api.rosette.com/rest/v1/info",
234-
body=json_response, status=200, content_type="application/json")
235242
httpretty.register_uri(httpretty.POST, "https://api.rosette.com/rest/v1/sentences",
236243
body=json_response, status=200, content_type="application/json")
237244

238245
result = api.sentences(doc_params)
239246
assert result["name"] == "Rosette"
247+
248+
with pytest.raises(RosetteException) as e_rosette:
249+
result = api.sentences(doc_map)
250+
251+
assert e_rosette.value.status == 'incompatible'
252+
253+
240254
httpretty.disable()
241255
httpretty.reset()
242256

@@ -246,8 +260,6 @@ def test_the_sentences_endpoint(api, json_response, doc_params):
246260
def test_the_tokens_endpoint(api, json_response, doc_params):
247261
"""Test the tokens endpoint"""
248262
httpretty.enable()
249-
httpretty.register_uri(httpretty.POST, "https://api.rosette.com/rest/v1/info",
250-
body=json_response, status=200, content_type="application/json")
251263
httpretty.register_uri(httpretty.POST, "https://api.rosette.com/rest/v1/tokens",
252264
body=json_response, status=200, content_type="application/json")
253265

@@ -403,6 +415,29 @@ def test_the_multipart_operation(api, json_response, doc_params, tmpdir):
403415
httpretty.disable()
404416
httpretty.reset()
405417

418+
419+
def test_incompatible_type(api, json_response):
420+
"""Test the name translation endpoint"""
421+
httpretty.enable()
422+
httpretty.register_uri(httpretty.POST, "https://api.rosette.com/rest/v1/info",
423+
body=json_response, status=200, content_type="application/json")
424+
httpretty.register_uri(httpretty.POST, "https://api.rosette.com/rest/v1/sentences",
425+
body=json_response, status=200, content_type="application/json")
426+
427+
params = NameTranslationParameters()
428+
params["name"] = "some data to translate"
429+
params["entityType"] = "PERSON"
430+
params["targetLanguage"] = "eng"
431+
params["targetScript"] = "Latn"
432+
433+
# oops, called sentences
434+
with pytest.raises(RosetteException) as e_rosette:
435+
api.sentences(params)
436+
437+
httpretty.disable()
438+
httpretty.reset()
439+
440+
406441
# Test the name translation endpoint
407442

408443

@@ -426,7 +461,33 @@ def test_the_name_translation_endpoint(api, json_response):
426461

427462
# Test the name similarity endpoint
428463

464+
def test_the_name_requests_with_text(api, json_response):
465+
"""Test the name similarity with text"""
466+
httpretty.enable()
467+
httpretty.register_uri(httpretty.POST, "https://api.rosette.com/rest/v1/info",
468+
body=json_response, status=200, content_type="application/json")
469+
httpretty.register_uri(httpretty.POST, "https://api.rosette.com/rest/v1/name-similarity",
470+
body=json_response, status=200, content_type="application/json")
471+
with pytest.raises(RosetteException) as e_rosette:
472+
result = api.name_similarity("should fail")
473+
assert e_rosette.value.status == 'incompatible'
474+
475+
with pytest.raises(RosetteException) as e_rosette:
476+
result = api.name_translation("should fail")
477+
assert e_rosette.value.status == 'incompatible'
478+
479+
with pytest.raises(RosetteException) as e_rosette:
480+
result = api.name_deduplication("should fail")
481+
assert e_rosette.value.status == 'incompatible'
482+
483+
with pytest.raises(RosetteException) as e_rosette:
484+
result = api.address_similarity("should fail")
485+
assert e_rosette.value.status == 'incompatible'
486+
487+
httpretty.disable()
488+
httpretty.reset()
429489

490+
430491
def test_the_name_similarity_single_parameters(api, json_response):
431492
"""Test the name similarity parameters"""
432493
httpretty.enable()

0 commit comments

Comments
 (0)