-
Notifications
You must be signed in to change notification settings - Fork 115
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
18 changed files
with
323 additions
and
0 deletions.
There are no files selected for viewing
This file contains 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,16 @@ | ||
resource(name='pyproject', source='pyproject.toml') | ||
file(name='readme', source='README.md') | ||
|
||
files(sources=['tests/data/*']) | ||
|
||
python_distribution( | ||
name='vonage-number-insight', | ||
dependencies=[ | ||
':pyproject', | ||
':readme', | ||
'number_insight/src/vonage_number_insight', | ||
], | ||
provides=python_artifact(), | ||
generate_setup=False, | ||
repositories=['@pypi'], | ||
) |
This file contains 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,2 @@ | ||
# 1.0.0 | ||
- Initial upload |
This file contains 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,9 @@ | ||
# Vonage Number Insight Package | ||
|
||
This package contains the code to use [Vonage's Number Insight API](https://developer.vonage.com/en/number-insight/overview) in Python. This package includes methods to get information about phone numbers. It has 3 levels of insight, basic, standard, and advanced. | ||
|
||
## Usage | ||
|
||
It is recommended to use this as part of the main `vonage` package. The examples below assume you've created an instance of the `vonage.Vonage` class called `vonage_client`. | ||
|
||
### Make a Basic Number Insight Request |
This file contains 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,29 @@ | ||
[project] | ||
name = 'vonage-number-insight' | ||
version = '1.0.0' | ||
description = 'Vonage Number Insight package' | ||
readme = "README.md" | ||
authors = [{ name = "Vonage", email = "devrel@vonage.com" }] | ||
requires-python = ">=3.8" | ||
dependencies = [ | ||
"vonage-http-client>=1.3.0", | ||
"vonage-utils>=1.1.0", | ||
"pydantic>=2.6.1", | ||
] | ||
classifiers = [ | ||
"Programming Language :: Python", | ||
"Programming Language :: Python :: 3", | ||
"Programming Language :: Python :: 3.8", | ||
"Programming Language :: Python :: 3.9", | ||
"Programming Language :: Python :: 3.10", | ||
"Programming Language :: Python :: 3.11", | ||
"Programming Language :: Python :: 3.12", | ||
"License :: OSI Approved :: Apache Software License", | ||
] | ||
|
||
[project.urls] | ||
homepage = "https://github.com/Vonage/vonage-python-sdk" | ||
|
||
[build-system] | ||
requires = ["setuptools>=61.0", "wheel"] | ||
build-backend = "setuptools.build_meta" |
This file contains 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 @@ | ||
python_sources() |
This file contains 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 @@ | ||
from .number_insight import NumberInsight | ||
|
||
__all__ = ['NumberInsight'] |
Empty file.
This file contains 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,5 @@ | ||
from vonage_utils.errors import VonageError | ||
|
||
|
||
class NumberInsightError(VonageError): | ||
"""Indicates an error when using the Vonage Number Insight API.""" |
139 changes: 139 additions & 0 deletions
139
number_insight/src/vonage_number_insight/number_insight.py
This file contains 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,139 @@ | ||
from pydantic import validate_call | ||
from vonage_http_client.http_client import HttpClient | ||
|
||
from .errors import NumberInsightError | ||
from .requests import ( | ||
AdvancedAsyncInsightRequest, | ||
AdvancedSyncInsightRequest, | ||
BasicInsightRequest, | ||
StandardInsightRequest, | ||
) | ||
from .responses import ( | ||
AdvancedAsyncInsightResponse, | ||
AdvancedSyncInsightResponse, | ||
BasicInsightResponse, | ||
StandardInsightResponse, | ||
) | ||
|
||
|
||
class NumberInsight: | ||
"""Calls Vonage's Number Insight API.""" | ||
|
||
def __init__(self, http_client: HttpClient) -> None: | ||
self._http_client = http_client | ||
self._auth_type = 'body' | ||
|
||
@property | ||
def http_client(self) -> HttpClient: | ||
"""The HTTP client used to make requests to the Verify V2 API. | ||
Returns: | ||
HttpClient: The HTTP client used to make requests to the Verify V2 API. | ||
""" | ||
return self._http_client | ||
|
||
@validate_call | ||
def basic_number_insight(self, options: BasicInsightRequest) -> BasicInsightResponse: | ||
"""Get basic number insight information about a phone number. | ||
Args: | ||
Options (BasicInsightRequest): The options for the request. The `number` paramerter | ||
is required, and the `country_code` parameter is optional. | ||
Returns: | ||
BasicInsightResponse: The response object containing the basic number insight | ||
information about the phone number. | ||
""" | ||
response = self._http_client.get( | ||
self._http_client.api_host, | ||
'/ni/basic/json', | ||
params=options.model_dump(exclude_none=True), | ||
auth_type=self._auth_type, | ||
) | ||
self._check_for_error(response) | ||
|
||
return BasicInsightResponse(**response) | ||
|
||
@validate_call | ||
def standard_number_insight( | ||
self, options: StandardInsightRequest | ||
) -> StandardInsightResponse: | ||
"""Get standard number insight information about a phone number. | ||
Args: | ||
Options (StandardInsightRequest): The options for the request. The `number` paramerter | ||
is required, and the `country_code` and `cnam` parameters are optional. | ||
Returns: | ||
StandardInsightResponse: The response object containing the standard number insight | ||
information about the phone number. | ||
""" | ||
response = self._http_client.get( | ||
self._http_client.api_host, | ||
'/ni/standard/json', | ||
params=options.model_dump(exclude_none=True), | ||
auth_type=self._auth_type, | ||
) | ||
self._check_for_error(response) | ||
|
||
return StandardInsightResponse(**response) | ||
|
||
@validate_call | ||
def advanced_async_number_insight( | ||
self, options: AdvancedAsyncInsightRequest | ||
) -> AdvancedAsyncInsightResponse: | ||
"""Get advanced number insight information about a phone number asynchronously. | ||
Args: | ||
Options (AdvancedAsyncInsightRequest): The options for the request. You must provide values | ||
for the `callback` and `number` parameters. The `country_code` and `cnam` parameters | ||
are optional. | ||
Returns: | ||
AdvancedAsyncInsightResponse: The response object containing the advanced number insight | ||
information about the phone number. | ||
""" | ||
response = self._http_client.get( | ||
self._http_client.api_host, | ||
'/ni/advanced/async/json', | ||
params=options.model_dump(exclude_none=True), | ||
auth_type=self._auth_type, | ||
) | ||
|
||
return AdvancedAsyncInsightResponse(**response) | ||
|
||
@validate_call | ||
def advanced_sync_number_insight( | ||
self, options: AdvancedSyncInsightRequest | ||
) -> AdvancedSyncInsightResponse: | ||
"""Get advanced number insight information about a phone number synchronously. | ||
Args: | ||
Options (AdvancedSyncInsightRequest): The options for the request. The `number` parameter | ||
is required, and the `country_code`, `cnam`, and `real_time_data` parameters are optional. | ||
Returns: | ||
AdvancedSyncInsightResponse: The response object containing the advanced number insight | ||
information about the phone number. | ||
""" | ||
response = self._http_client.get( | ||
self._http_client.api_host, | ||
'/ni/advanced/json', | ||
params=options.model_dump(exclude_none=True), | ||
auth_type=self._auth_type, | ||
) | ||
|
||
return AdvancedSyncInsightResponse(**response) | ||
|
||
def _check_for_error(self, response: dict) -> None: | ||
"""Check for an error in the response from the Number Insight API. | ||
Args: | ||
response (dict): The response from the Number Insight API. | ||
Raises: | ||
NumberInsightError: If the response contains an error. | ||
""" | ||
if response['status'] != 0: | ||
error_message = f'Error with the following details: {response}' | ||
raise NumberInsightError(error_message) |
This file contains 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,21 @@ | ||
from typing import Optional | ||
|
||
from pydantic import BaseModel | ||
from vonage_utils.types import PhoneNumber | ||
|
||
|
||
class BasicInsightRequest(BaseModel): | ||
number: PhoneNumber | ||
country: Optional[str] = None | ||
|
||
|
||
class StandardInsightRequest(BasicInsightRequest): | ||
cnam: Optional[bool] = None | ||
|
||
|
||
class AdvancedAsyncInsightRequest(StandardInsightRequest): | ||
callback: str | ||
|
||
|
||
class AdvancedSyncInsightRequest(StandardInsightRequest): | ||
real_time_data: Optional[bool] = None |
This file contains 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,27 @@ | ||
from typing import Optional | ||
|
||
from pydantic import BaseModel | ||
|
||
|
||
class BasicInsightResponse(BaseModel): | ||
status: int = None | ||
status_message: str = None | ||
request_id: Optional[str] = None | ||
international_format_number: Optional[str] = None | ||
national_format_number: Optional[str] = None | ||
country_code: Optional[str] = None | ||
country_code_iso3: Optional[str] = None | ||
country_name: Optional[str] = None | ||
country_prefix: Optional[str] = None | ||
|
||
|
||
class StandardInsightResponse(BasicInsightResponse): | ||
... | ||
|
||
|
||
class AdvancedAsyncInsightResponse(BaseModel): | ||
... | ||
|
||
|
||
class AdvancedSyncInsightResponse(BaseModel): | ||
... |
This file contains 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 @@ | ||
python_tests(dependencies=['number_insight', 'testutils']) |
This file contains 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,11 @@ | ||
{ | ||
"status": 0, | ||
"status_message": "Success", | ||
"request_id": "7f4a8a16-aa89-4078-b0ae-7743da34aca5", | ||
"international_format_number": "12345678900", | ||
"national_format_number": "(234) 567-8900", | ||
"country_code": "US", | ||
"country_code_iso3": "USA", | ||
"country_name": "United States of America", | ||
"country_prefix": "1" | ||
} |
This file contains 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 @@ | ||
{ | ||
"status": 3, | ||
"status_message": "Invalid request :: Not valid number format detected [ 145645562 ]" | ||
} |
This file contains 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,50 @@ | ||
from os.path import abspath | ||
|
||
import responses | ||
from pytest import raises | ||
from vonage_http_client.http_client import HttpClient | ||
from vonage_number_insight.errors import NumberInsightError | ||
from vonage_number_insight.number_insight import NumberInsight | ||
from vonage_number_insight.requests import BasicInsightRequest | ||
|
||
from testutils import build_response, get_mock_api_key_auth | ||
|
||
path = abspath(__file__) | ||
|
||
|
||
number_insight = NumberInsight(HttpClient(get_mock_api_key_auth())) | ||
|
||
|
||
def test_http_client_property(): | ||
http_client = number_insight.http_client | ||
assert isinstance(http_client, HttpClient) | ||
|
||
|
||
@responses.activate | ||
def test_basic_insight(): | ||
build_response( | ||
path, | ||
'GET', | ||
'https://api.nexmo.com/ni/basic/json', | ||
'basic_insight.json', | ||
) | ||
options = BasicInsightRequest(number='12345678900', country_code='US') | ||
response = number_insight.basic_number_insight(options) | ||
assert response.status == 0 | ||
assert response.status_message == 'Success' | ||
|
||
|
||
@responses.activate | ||
def test_basic_insight_error(): | ||
build_response( | ||
path, | ||
'GET', | ||
'https://api.nexmo.com/ni/basic/json', | ||
'basic_insight_error.json', | ||
) | ||
|
||
with raises(NumberInsightError) as e: | ||
options = BasicInsightRequest(number='1234567890', country_code='US') | ||
number_insight.basic_number_insight(options) | ||
assert e.match('Invalid request :: Not valid number format detected') | ||
assert 0 |
This file contains 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 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 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