Skip to content

Commit

Permalink
Merge pull request #219 from Vonage/v3-release
Browse files Browse the repository at this point in the history
V3 release
  • Loading branch information
maxkahan committed Jul 27, 2022
2 parents 5f98d04 + 058b480 commit 9ffcb31
Show file tree
Hide file tree
Showing 39 changed files with 860 additions and 1,969 deletions.
2 changes: 1 addition & 1 deletion .bumpversion.cfg
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[bumpversion]
current_version = 2.8.0
current_version = 3.0.0
commit = True
tag = False

Expand Down
4 changes: 2 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ repos:
rev: v2.5.4
hooks:
- id: trailing-whitespace
language_version: python3.6
language_version: python3.7
- repo: https://github.com/ambv/black
rev: 18.6b4
hooks:
- id: black
language_version: python3.6
language_version: python3.7
19 changes: 18 additions & 1 deletion CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,22 @@
# 3.0.0

Breaking changes:
- Removed deprecated methods from `client.py` that are now available in specific modules related to each of the available Vonage APIs. E.g. to call the number insight API, the methods are now called in this way: `client.number_insight.get_basic_number_insight(...)`, or by instantiating the `NumberInsight` class directly: `ni = vonage.NumberInsight(client)`, `ni.get_basic_number_insight(...)` etc.
- Removed automatic client creation when instantiating an `sms`, `voice` or `verify` object. You can now use these APIs from a client instance you create (e.g. `client.sms.send_message()`) or pass in a client to the API class to create it (e.g. `sms = vonage.Sms(client)`), as has been the case since v2.7.0 of the SDK.
- Removed methods to call the Message Search API, which has been retired by Vonage.
- Removed deprecated voice and number insight methods from `voice.py` (`initiate_call, initiate_tts_call and initiate_tts_prompt_call`) and `number_insight.py` (`request_number_insight`).
- Deprecated the ApplicationV2 class and created an Application class with the same methods to bring the naming in line with other classes. This can be called from the client object with `client.application.create_application(...)` etc. or directly with `application = vonage.Application(client)`, `application.create_application(...)` etc.
- Deprecated old Pricing API methods `get_sms_pricing` and `get_voice_pricing`.
- Deprecated Redact class as it's a dev preview product that's unsupported in the SDK and will be removed in a later release.
- Renamed the `Account.delete_secret()` method to `revoke_secret()` to bring it in line with what is described in our documentation.

Enhancements:
- Added `get_all_countries_pricing` method to `Account` object.
- Added a `type` parameter for pricing calls, so `sms` or `voice` pricing can now be chosen.
- Added `max_retries`, `timeout`, `pool_connections` and `pool_maxsize` optional keyword arguments to the `Client` class, which can now be specified on instantiation and used in the API calls made with the client.

# 2.8.0
- Added Messages API v1.0 support. Messages API can now be used by calling the client.messages.send_message() method.
- Added Messages API v1.0 support. Messages API can now be used by calling the `client.messages.send_message()` method.

# 2.7.0
- Moved some client methods into their own classes: `account.py, application.py,
Expand Down
6 changes: 3 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
.PHONY: clean test build coverage install requirements release

clean:
rm -rf dist build

coverage:
pytest -v --cov
coverage html

test:
pytest -v

clean:
rm -rf dist build

build:
python -m build

Expand Down
61 changes: 54 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,16 @@ response = client.sms.send_message({
client.sms.submit_sms_conversion(response['message-id'])
```

### Update the default SMS webhook URLs for callbacks/delivery reciepts
```python
client.sms.update_default_sms_webhook({
'moCallBackUrl': 'new.url.vonage.com', # Default inbound sms webhook url
'drCallBackUrl': 'different.url.vonage.com' # Delivery receipt url
}})
```

The delivery receipt URL can be unset by sending an empty string.

## Messages API

The Messages API is an API that allows you to send messages via SMS, MMS, WhatsApp, Messenger and Viber. Call the API from your Python code by
Expand Down Expand Up @@ -458,6 +468,37 @@ client.number_insight.get_advanced_number_insight(number='447700900000')

Docs: [https://developer.nexmo.com/api/number-insight#getNumberInsightAdvanced](https://developer.nexmo.com/api/number-insight?utm_source=DEV_REL&utm_medium=github&utm_campaign=python-client-library#getNumberInsightAdvanced)

## Account API

### Get your account balance
```python
client.account.get_balance()
```

### Top up your account
This feature is only enabled when you enable auto-reload for your account in the dashboard.
```python
# trx is the reference from when auto-reload was enabled and money was added
client.account.topup(trx=transaction_reference)
```

## Pricing API

### Get pricing for a single country
```python
client.get_country_pricing(country_code='GB', type='sms') # Default type is sms
```

### Get pricing for all countries
```python
client.get_all_countries_pricing(type='sms') # Default type is sms, can be voice
```

### Get pricing for a specific dialling prefix
```python
client.get_country_pricing(prefix='44', type='sms')
```

## Managing Secrets

An API is provided to allow you to rotate your API secrets. You can create a new secret (up to a maximum of two secrets) and delete the existing one once all applications have been updated.
Expand All @@ -468,6 +509,12 @@ An API is provided to allow you to rotate your API secrets. You can create a new
secrets = client.account.list_secrets(API_KEY)
```

### Get information about a specific secret

```python
secrets = client.account.get_secret(API_KEY, secret_id)
```

### Create A New Secret

Create a new secret (the created dates will help you know which is which):
Expand All @@ -481,47 +528,47 @@ client.account.create_secret(API_KEY, 'awes0meNewSekret!!;');
Delete the old secret (any application still using these credentials will stop working):

```python
client.account.delete_secret(API_KEY, 'my-secret-id')
client.account.revoke_secret(API_KEY, 'my-secret-id')
```

## Application API

### Create an application

```python
response = client.application_v2.create_application({name='Example App', type='voice'})
response = client.application.create_application({name='Example App', type='voice'})
```

Docs: [https://developer.nexmo.com/api/application.v2#createApplication](https://developer.nexmo.com/api/application.v2#createApplication?utm_source=DEV_REL&utm_medium=github&utm_campaign=python-client-library#create-an-application)

### Retrieve a list of applications

```python
response = client.application_v2.list_applications()
response = client.application.list_applications()
```

Docs: [https://developer.nexmo.com/api/application.v2#listApplication](https://developer.nexmo.com/api/application.v2#listApplication?utm_source=DEV_REL&utm_medium=github&utm_campaign=python-client-library#retrieve-your-applications)

### Retrieve a single application

```python
response = client.application_v2.get_application(uuid)
response = client.application.get_application(uuid)
```

Docs: [https://developer.nexmo.com/api/application.v2#getApplication](https://developer.nexmo.com/api/application.v2#getApplication?utm_source=DEV_REL&utm_medium=github&utm_campaign=python-client-library#retrieve-an-application)

### Update an application

```python
response = client.application_v2.update_application(uuid, answer_method='POST')
response = client.application.update_application(uuid, answer_method='POST')
```

Docs: [https://developer.nexmo.com/api/application.v2#updateApplication](https://developer.nexmo.com/api/application.v2#updateApplication?utm_source=DEV_REL&utm_medium=github&utm_campaign=python-client-library#update-an-application)

### Delete an application

```python
response = client.application_v2.delete_application(uuid)
response = client.application.delete_application(uuid)
```

Docs: [https://developer.nexmo.com/api/application.v2#deleteApplication](https://developer.nexmo.com/api/application.v2#deleteApplication?utm_source=DEV_REL&utm_medium=github&utm_campaign=python-client-library#destroy-an-application)
Expand Down Expand Up @@ -608,7 +655,7 @@ The following is a list of Vonage APIs and whether the Python SDK provides suppo
| Number Insight API | General Availability ||
| Number Management API | General Availability ||
| Pricing API | General Availability ||
| Redact API | General Availability | |
| Redact API | Developer Preview | |
| Reports API | Beta ||
| SMS API | General Availability ||
| Verify API | General Availability ||
Expand Down
6 changes: 3 additions & 3 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,9 @@
# built documents.
#
# The short X.Y version.
version = "2.8.0"
version = "3.0.0"
# The full version, including alpha/beta/rc tags.
release = "2.8.0"
release = "3.0.0"

# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
Expand Down Expand Up @@ -143,7 +143,7 @@
# The name for this set of Sphinx documents.
# "<project> v<release> documentation" by default.
#
# html_title = u'Vonage v2.8.0'
# html_title = u'Vonage v3.0.0'

# A shorter title for the navigation bar. Default is the same as html_title.
#
Expand Down
6 changes: 5 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,8 @@ pytest==7.1.1
pytest-cov==3.0.0
responses==0.20.0
coveralls
glom==22.1.0
glom==22.1.0

bump2version
build
twine
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

setup(
name="vonage",
version="2.8.0",
version="3.0.0",
description="Vonage Server SDK for Python",
long_description=long_description,
long_description_content_type="text/markdown",
Expand Down
2 changes: 1 addition & 1 deletion src/vonage/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
from .client import *

__version__ = "2.8.0"
__version__ = "3.0.0"
83 changes: 67 additions & 16 deletions src/vonage/account.py
Original file line number Diff line number Diff line change
@@ -1,59 +1,110 @@
from .errors import PricingTypeError

from deprecated import deprecated
class Account:
account_auth_type = 'params'
pricing_auth_type = 'params'
secrets_auth_type = 'header'

allowed_pricing_types = {'sms', 'sms-transit', 'voice'}

def __init__(self, client):
self._client = client

def get_balance(self):
return self._client.get(self._client.host(), "/account/get-balance")
return self._client.get(self._client.host(), "/account/get-balance", auth_type=Account.account_auth_type)

def topup(self, params=None, **kwargs):
return self._client.post(self._client.host(), "/account/top-up", params or kwargs)
return self._client.post(
self._client.host(),
"/account/top-up",
params or kwargs,
auth_type=Account.account_auth_type,
body_is_json=False,
)

def get_country_pricing(self, country_code: str, type: str = 'sms'):
self._check_allowed_pricing_type(type)
return self._client.get(
self._client.host(),
f"/account/get-pricing/outbound/{type}",
{"country": country_code},
auth_type=Account.pricing_auth_type
)

def get_country_pricing(self, country_code):
def get_all_countries_pricing(self, type: str = 'sms'):
self._check_allowed_pricing_type(type)
return self._client.get(
self._client.host(), "/account/get-pricing/outbound", {"country": country_code}
self._client.host(), f"/account/get-full-pricing/outbound/{type}", auth_type=Account.pricing_auth_type
)

def get_prefix_pricing(self, prefix):
def get_prefix_pricing(self, prefix: str, type: str = 'sms'):
self._check_allowed_pricing_type(type)
return self._client.get(
self._client.host(), "/account/get-prefix-pricing/outbound", {"prefix": prefix}
self._client.host(),
f"/account/get-prefix-pricing/outbound/{type}",
{"prefix": prefix},
auth_type=Account.pricing_auth_type,
)

def get_sms_pricing(self, number):
@deprecated(version='3.0.0', reason='The "account/get-phone-pricing" endpoint is deprecated.')
def get_sms_pricing(self, number: str):
return self._client.get(
self._client.host(), "/account/get-phone-pricing/outbound/sms", {"phone": number}
self._client.host(),
"/account/get-phone-pricing/outbound/sms",
{"phone": number},
auth_type=Account.pricing_auth_type,
)

def get_voice_pricing(self, number):
@deprecated(version='3.0.0', reason='The "account/get-phone-pricing" endpoint is deprecated.')
def get_voice_pricing(self, number: str):
return self._client.get(
self._client.host(), "/account/get-phone-pricing/outbound/voice", {"phone": number}
self._client.host(),
"/account/get-phone-pricing/outbound/voice",
{"phone": number},
auth_type=Account.pricing_auth_type,
)

def update_default_sms_webhook(self, params=None, **kwargs):
return self._client.post(self._client.host(), "/account/settings", params or kwargs)
return self._client.post(
self._client.host(),
"/account/settings",
params or kwargs,
auth_type=Account.account_auth_type,
body_is_json=False,
)

def list_secrets(self, api_key):
return self._client.get(
self._client.api_host(),
f"/accounts/{api_key}/secrets",
header_auth=True,
auth_type=Account.secrets_auth_type,
)

def get_secret(self, api_key, secret_id):
return self._client.get(
self._client.api_host(),
f"/accounts/{api_key}/secrets/{secret_id}",
header_auth=True,
auth_type=Account.secrets_auth_type,
)

def create_secret(self, api_key, secret):
body = {"secret": secret}
return self._client._post_json(
self._client.api_host(), f"/accounts/{api_key}/secrets", body
return self._client.post(
self._client.api_host(),
f"/accounts/{api_key}/secrets",
body,
auth_type=Account.secrets_auth_type,
body_is_json=False,
)

def revoke_secret(self, api_key, secret_id):
return self._client.delete(
self._client.api_host(),
f"/accounts/{api_key}/secrets/{secret_id}",
header_auth=True,
auth_type=Account.secrets_auth_type,
)

def _check_allowed_pricing_type(self, type):
if type not in Account.allowed_pricing_types:
raise PricingTypeError('Invalid pricing type specified.')
Loading

0 comments on commit 9ffcb31

Please sign in to comment.