Initial commit: Email alerts application
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
__version_info__ = ("8", "10", "0")
|
||||
__version__ = ".".join(__version_info__)
|
||||
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,234 @@
|
||||
import os
|
||||
import platform
|
||||
from typing import Dict, List, MutableMapping, Optional, Tuple
|
||||
from urllib.parse import urlparse, urlunparse
|
||||
|
||||
from twilio import __version__
|
||||
from twilio.base.exceptions import TwilioException
|
||||
from twilio.http import HttpClient
|
||||
from twilio.http.http_client import TwilioHttpClient
|
||||
from twilio.http.response import Response
|
||||
|
||||
|
||||
class ClientBase(object):
|
||||
"""A client for accessing the Twilio API."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
username: Optional[str] = None,
|
||||
password: Optional[str] = None,
|
||||
account_sid: Optional[str] = None,
|
||||
region: Optional[str] = None,
|
||||
http_client: Optional[HttpClient] = None,
|
||||
environment: Optional[MutableMapping[str, str]] = None,
|
||||
edge: Optional[str] = None,
|
||||
user_agent_extensions: Optional[List[str]] = None,
|
||||
):
|
||||
"""
|
||||
Initializes the Twilio Client
|
||||
|
||||
:param username: Username to authenticate with
|
||||
:param password: Password to authenticate with
|
||||
:param account_sid: Account SID, defaults to Username
|
||||
:param region: Twilio Region to make requests to, defaults to 'us1' if an edge is provided
|
||||
:param http_client: HttpClient, defaults to TwilioHttpClient
|
||||
:param environment: Environment to look for auth details, defaults to os.environ
|
||||
:param edge: Twilio Edge to make requests to, defaults to None
|
||||
:param user_agent_extensions: Additions to the user agent string
|
||||
"""
|
||||
environment = environment or os.environ
|
||||
|
||||
self.username = username or environment.get("TWILIO_ACCOUNT_SID")
|
||||
""" :type : str """
|
||||
self.password = password or environment.get("TWILIO_AUTH_TOKEN")
|
||||
""" :type : str """
|
||||
self.edge = edge or environment.get("TWILIO_EDGE")
|
||||
""" :type : str """
|
||||
self.region = region or environment.get("TWILIO_REGION")
|
||||
""" :type : str """
|
||||
self.user_agent_extensions = user_agent_extensions or []
|
||||
""" :type : list[str] """
|
||||
|
||||
if not self.username or not self.password:
|
||||
raise TwilioException("Credentials are required to create a TwilioClient")
|
||||
|
||||
self.account_sid = account_sid or self.username
|
||||
""" :type : str """
|
||||
self.auth = (self.username, self.password)
|
||||
""" :type : tuple(str, str) """
|
||||
self.http_client: HttpClient = http_client or TwilioHttpClient()
|
||||
""" :type : HttpClient """
|
||||
|
||||
def request(
|
||||
self,
|
||||
method: str,
|
||||
uri: str,
|
||||
params: Optional[Dict[str, object]] = None,
|
||||
data: Optional[Dict[str, object]] = None,
|
||||
headers: Optional[Dict[str, str]] = None,
|
||||
auth: Optional[Tuple[str, str]] = None,
|
||||
timeout: Optional[float] = None,
|
||||
allow_redirects: bool = False,
|
||||
) -> Response:
|
||||
"""
|
||||
Makes a request to the Twilio API using the configured http client
|
||||
Authentication information is automatically added if none is provided
|
||||
|
||||
:param method: HTTP Method
|
||||
:param uri: Fully qualified url
|
||||
:param params: Query string parameters
|
||||
:param data: POST body data
|
||||
:param headers: HTTP Headers
|
||||
:param auth: Authentication
|
||||
:param timeout: Timeout in seconds
|
||||
:param allow_redirects: Should the client follow redirects
|
||||
|
||||
:returns: Response from the Twilio API
|
||||
"""
|
||||
auth = self.get_auth(auth)
|
||||
headers = self.get_headers(method, headers)
|
||||
uri = self.get_hostname(uri)
|
||||
|
||||
return self.http_client.request(
|
||||
method,
|
||||
uri,
|
||||
params=params,
|
||||
data=data,
|
||||
headers=headers,
|
||||
auth=auth,
|
||||
timeout=timeout,
|
||||
allow_redirects=allow_redirects,
|
||||
)
|
||||
|
||||
async def request_async(
|
||||
self,
|
||||
method: str,
|
||||
uri: str,
|
||||
params: Optional[Dict[str, object]] = None,
|
||||
data: Optional[Dict[str, object]] = None,
|
||||
headers: Optional[Dict[str, str]] = None,
|
||||
auth: Optional[Tuple[str, str]] = None,
|
||||
timeout: Optional[float] = None,
|
||||
allow_redirects: bool = False,
|
||||
) -> Response:
|
||||
"""
|
||||
Asynchronously makes a request to the Twilio API using the configured http client
|
||||
The configured http client must be an asynchronous http client
|
||||
Authentication information is automatically added if none is provided
|
||||
|
||||
:param method: HTTP Method
|
||||
:param uri: Fully qualified url
|
||||
:param params: Query string parameters
|
||||
:param data: POST body data
|
||||
:param headers: HTTP Headers
|
||||
:param auth: Authentication
|
||||
:param timeout: Timeout in seconds
|
||||
:param allow_redirects: Should the client follow redirects
|
||||
|
||||
:returns: Response from the Twilio API
|
||||
"""
|
||||
if not self.http_client.is_async:
|
||||
raise RuntimeError(
|
||||
"http_client must be asynchronous to support async API requests"
|
||||
)
|
||||
|
||||
auth = self.get_auth(auth)
|
||||
headers = self.get_headers(method, headers)
|
||||
uri = self.get_hostname(uri)
|
||||
|
||||
return await self.http_client.request(
|
||||
method,
|
||||
uri,
|
||||
params=params,
|
||||
data=data,
|
||||
headers=headers,
|
||||
auth=auth,
|
||||
timeout=timeout,
|
||||
allow_redirects=allow_redirects,
|
||||
)
|
||||
|
||||
def get_auth(self, auth: Optional[Tuple[str, str]]) -> Tuple[str, str]:
|
||||
"""
|
||||
Get the request authentication object
|
||||
:param auth: Authentication (username, password)
|
||||
:returns: The authentication object
|
||||
"""
|
||||
return auth or self.auth
|
||||
|
||||
def get_headers(
|
||||
self, method: str, headers: Optional[Dict[str, str]]
|
||||
) -> Dict[str, str]:
|
||||
"""
|
||||
Get the request headers including user-agent, extensions, encoding, content-type, MIME type
|
||||
:param method: HTTP method
|
||||
:param headers: HTTP headers
|
||||
:returns: HTTP headers
|
||||
"""
|
||||
headers = headers or {}
|
||||
|
||||
# Set User-Agent
|
||||
pkg_version = __version__
|
||||
os_name = platform.system()
|
||||
os_arch = platform.machine()
|
||||
python_version = platform.python_version()
|
||||
headers["User-Agent"] = "twilio-python/{} ({} {}) Python/{}".format(
|
||||
pkg_version,
|
||||
os_name,
|
||||
os_arch,
|
||||
python_version,
|
||||
)
|
||||
# Extensions
|
||||
for extension in self.user_agent_extensions:
|
||||
headers["User-Agent"] += " {}".format(extension)
|
||||
headers["X-Twilio-Client"] = "python-{}".format(__version__)
|
||||
|
||||
# Types, encodings, etc.
|
||||
headers["Accept-Charset"] = "utf-8"
|
||||
if method == "POST" and "Content-Type" not in headers:
|
||||
headers["Content-Type"] = "application/x-www-form-urlencoded"
|
||||
if "Accept" not in headers:
|
||||
headers["Accept"] = "application/json"
|
||||
|
||||
return headers
|
||||
|
||||
def get_hostname(self, uri: str) -> str:
|
||||
"""
|
||||
Determines the proper hostname given edge and region preferences
|
||||
via client configuration or uri.
|
||||
|
||||
:param uri: Fully qualified url
|
||||
|
||||
:returns: The final uri used to make the request
|
||||
"""
|
||||
if not self.edge and not self.region:
|
||||
return uri
|
||||
|
||||
parsed_url = urlparse(uri)
|
||||
pieces = parsed_url.netloc.split(".")
|
||||
prefix = pieces[0]
|
||||
suffix = ".".join(pieces[-2:])
|
||||
region = None
|
||||
edge = None
|
||||
if len(pieces) == 4:
|
||||
# product.region.twilio.com
|
||||
region = pieces[1]
|
||||
elif len(pieces) == 5:
|
||||
# product.edge.region.twilio.com
|
||||
edge = pieces[1]
|
||||
region = pieces[2]
|
||||
|
||||
edge = self.edge or edge
|
||||
region = self.region or region or (edge and "us1")
|
||||
|
||||
parsed_url = parsed_url._replace(
|
||||
netloc=".".join([part for part in [prefix, edge, region, suffix] if part])
|
||||
)
|
||||
return str(urlunparse(parsed_url))
|
||||
|
||||
def __repr__(self) -> str:
|
||||
"""
|
||||
Provide a friendly representation
|
||||
|
||||
:returns: Machine friendly representation
|
||||
"""
|
||||
return "<Twilio {}>".format(self.account_sid)
|
||||
@@ -0,0 +1,75 @@
|
||||
import datetime
|
||||
from decimal import BasicContext, Decimal
|
||||
from email.utils import parsedate
|
||||
from typing import Optional, Union
|
||||
|
||||
ISO8601_DATE_FORMAT = "%Y-%m-%d"
|
||||
ISO8601_DATETIME_FORMAT = "%Y-%m-%dT%H:%M:%SZ"
|
||||
|
||||
|
||||
def iso8601_date(s: str) -> Union[datetime.date, str]:
|
||||
"""
|
||||
Parses an ISO 8601 date string and returns a UTC date object or the string
|
||||
if the parsing failed.
|
||||
:param s: ISO 8601-formatted date string (2015-01-25)
|
||||
:return:
|
||||
"""
|
||||
try:
|
||||
return (
|
||||
datetime.datetime.strptime(s, ISO8601_DATE_FORMAT)
|
||||
.replace(tzinfo=datetime.timezone.utc)
|
||||
.date()
|
||||
)
|
||||
except (TypeError, ValueError):
|
||||
return s
|
||||
|
||||
|
||||
def iso8601_datetime(
|
||||
s: str,
|
||||
) -> Union[datetime.datetime, str]:
|
||||
"""
|
||||
Parses an ISO 8601 datetime string and returns a UTC datetime object,
|
||||
or the string if parsing failed.
|
||||
:param s: ISO 8601-formatted datetime string (2015-01-25T12:34:56Z)
|
||||
"""
|
||||
try:
|
||||
return datetime.datetime.strptime(s, ISO8601_DATETIME_FORMAT).replace(
|
||||
tzinfo=datetime.timezone.utc
|
||||
)
|
||||
except (TypeError, ValueError):
|
||||
return s
|
||||
|
||||
|
||||
def rfc2822_datetime(s: str) -> Optional[datetime.datetime]:
|
||||
"""
|
||||
Parses an RFC 2822 date string and returns a UTC datetime object,
|
||||
or the string if parsing failed.
|
||||
:param s: RFC 2822-formatted string date
|
||||
:return: datetime or str
|
||||
"""
|
||||
date_tuple = parsedate(s)
|
||||
if date_tuple is None:
|
||||
return None
|
||||
return datetime.datetime(*date_tuple[:6]).replace(tzinfo=datetime.timezone.utc)
|
||||
|
||||
|
||||
def decimal(d: Optional[str]) -> Union[Decimal, str]:
|
||||
"""
|
||||
Parses a decimal string into a Decimal
|
||||
:param d: decimal string
|
||||
"""
|
||||
if not d:
|
||||
return d
|
||||
return Decimal(d, BasicContext)
|
||||
|
||||
|
||||
def integer(i: str) -> Union[int, str]:
|
||||
"""
|
||||
Parses an integer string into an int
|
||||
:param i: integer string
|
||||
:return: int
|
||||
"""
|
||||
try:
|
||||
return int(i)
|
||||
except (TypeError, ValueError):
|
||||
return i
|
||||
@@ -0,0 +1,93 @@
|
||||
from typing import Dict, Optional, Tuple
|
||||
from twilio.http.response import Response
|
||||
from twilio.rest import Client
|
||||
|
||||
|
||||
class Domain(object):
|
||||
"""
|
||||
This represents at Twilio API subdomain.
|
||||
|
||||
Like, `api.twilio.com` or `lookups.twilio.com'.
|
||||
"""
|
||||
|
||||
def __init__(self, twilio: Client, base_url: str):
|
||||
self.twilio = twilio
|
||||
self.base_url = base_url
|
||||
|
||||
def absolute_url(self, uri: str) -> str:
|
||||
"""
|
||||
Converts a relative `uri` to an absolute url.
|
||||
:param string uri: The relative uri to make absolute.
|
||||
:return: An absolute url (based off this domain)
|
||||
"""
|
||||
return "{}/{}".format(self.base_url.strip("/"), uri.strip("/"))
|
||||
|
||||
def request(
|
||||
self,
|
||||
method: str,
|
||||
uri: str,
|
||||
params: Optional[Dict[str, object]] = None,
|
||||
data: Optional[Dict[str, object]] = None,
|
||||
headers: Optional[Dict[str, str]] = None,
|
||||
auth: Optional[Tuple[str, str]] = None,
|
||||
timeout: Optional[float] = None,
|
||||
allow_redirects: bool = False,
|
||||
) -> Response:
|
||||
"""
|
||||
Makes an HTTP request to this domain.
|
||||
:param method: The HTTP method.
|
||||
:param uri: The HTTP uri.
|
||||
:param params: Query parameters.
|
||||
:param data: The request body.
|
||||
:param headers: The HTTP headers.
|
||||
:param auth: Basic auth tuple of (username, password)
|
||||
:param timeout: The request timeout.
|
||||
:param allow_redirects: True if the client should follow HTTP
|
||||
redirects.
|
||||
"""
|
||||
url = self.absolute_url(uri)
|
||||
return self.twilio.request(
|
||||
method,
|
||||
url,
|
||||
params=params,
|
||||
data=data,
|
||||
headers=headers,
|
||||
auth=auth,
|
||||
timeout=timeout,
|
||||
allow_redirects=allow_redirects,
|
||||
)
|
||||
|
||||
async def request_async(
|
||||
self,
|
||||
method: str,
|
||||
uri: str,
|
||||
params: Optional[Dict[str, object]] = None,
|
||||
data: Optional[Dict[str, object]] = None,
|
||||
headers: Optional[Dict[str, str]] = None,
|
||||
auth: Optional[Tuple[str, str]] = None,
|
||||
timeout: Optional[float] = None,
|
||||
allow_redirects: bool = False,
|
||||
) -> Response:
|
||||
"""
|
||||
Makes an asynchronous HTTP request to this domain.
|
||||
:param method: The HTTP method.
|
||||
:param uri: The HTTP uri.
|
||||
:param params: Query parameters.
|
||||
:param data: The request body.
|
||||
:param headers: The HTTP headers.
|
||||
:param auth: Basic auth tuple of (username, password)
|
||||
:param timeout: The request timeout.
|
||||
:param allow_redirects: True if the client should follow HTTP
|
||||
redirects.
|
||||
"""
|
||||
url = self.absolute_url(uri)
|
||||
return await self.twilio.request_async(
|
||||
method,
|
||||
url,
|
||||
params=params,
|
||||
data=data,
|
||||
headers=headers,
|
||||
auth=auth,
|
||||
timeout=timeout,
|
||||
allow_redirects=allow_redirects,
|
||||
)
|
||||
@@ -0,0 +1,82 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import sys
|
||||
from typing import Optional
|
||||
|
||||
|
||||
class TwilioException(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class TwilioRestException(TwilioException):
|
||||
"""A generic 400 or 500 level exception from the Twilio API
|
||||
|
||||
:param int status: the HTTP status that was returned for the exception
|
||||
:param str uri: The URI that caused the exception
|
||||
:param str msg: A human-readable message for the error
|
||||
:param int|None code: A Twilio-specific error code for the error. This is
|
||||
not available for all errors.
|
||||
:param method: The HTTP method used to make the request
|
||||
:param details: Additional error details returned for the exception
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
status: int,
|
||||
uri: str,
|
||||
msg: str = "",
|
||||
code: Optional[int] = None,
|
||||
method: str = "GET",
|
||||
details: Optional[object] = None,
|
||||
):
|
||||
self.uri = uri
|
||||
self.status = status
|
||||
self.msg = msg
|
||||
self.code = code
|
||||
self.method = method
|
||||
self.details = details
|
||||
|
||||
def __str__(self) -> str:
|
||||
"""Try to pretty-print the exception, if this is going on screen."""
|
||||
|
||||
def red(words: str) -> str:
|
||||
return "\033[31m\033[49m%s\033[0m" % words
|
||||
|
||||
def white(words: str) -> str:
|
||||
return "\033[37m\033[49m%s\033[0m" % words
|
||||
|
||||
def blue(words: str) -> str:
|
||||
return "\033[34m\033[49m%s\033[0m" % words
|
||||
|
||||
def teal(words: str) -> str:
|
||||
return "\033[36m\033[49m%s\033[0m" % words
|
||||
|
||||
def get_uri(code: int) -> str:
|
||||
return "https://www.twilio.com/docs/errors/{0}".format(code)
|
||||
|
||||
# If it makes sense to print a human readable error message, try to
|
||||
# do it. The one problem is that someone might catch this error and
|
||||
# try to display the message from it to an end user.
|
||||
if hasattr(sys.stderr, "isatty") and sys.stderr.isatty():
|
||||
msg = (
|
||||
"\n{red_error} {request_was}\n\n{http_line}"
|
||||
"\n\n{twilio_returned}\n\n{message}\n".format(
|
||||
red_error=red("HTTP Error"),
|
||||
request_was=white("Your request was:"),
|
||||
http_line=teal("%s %s" % (self.method, self.uri)),
|
||||
twilio_returned=white("Twilio returned the following information:"),
|
||||
message=blue(str(self.msg)),
|
||||
)
|
||||
)
|
||||
if self.code:
|
||||
msg = "".join(
|
||||
[
|
||||
msg,
|
||||
"\n{more_info}\n\n{uri}\n\n".format(
|
||||
more_info=white("More information may be available here:"),
|
||||
uri=blue(get_uri(self.code)),
|
||||
),
|
||||
]
|
||||
)
|
||||
return msg
|
||||
else:
|
||||
return "HTTP {0} error: {1}".format(self.status, self.msg)
|
||||
@@ -0,0 +1,6 @@
|
||||
from twilio.base.version import Version
|
||||
|
||||
|
||||
class InstanceContext(object):
|
||||
def __init__(self, version: Version):
|
||||
self._version = version
|
||||
@@ -0,0 +1,6 @@
|
||||
from twilio.base.version import Version
|
||||
|
||||
|
||||
class InstanceResource(object):
|
||||
def __init__(self, version: Version):
|
||||
self._version = version
|
||||
@@ -0,0 +1,6 @@
|
||||
from twilio.base.version import Version
|
||||
|
||||
|
||||
class ListResource(object):
|
||||
def __init__(self, version: Version):
|
||||
self._version = version
|
||||
@@ -0,0 +1,47 @@
|
||||
import warnings
|
||||
import functools
|
||||
|
||||
|
||||
class ObsoleteException(Exception):
|
||||
"""Base class for warnings about obsolete features."""
|
||||
|
||||
|
||||
def obsolete_client(func):
|
||||
"""This is a decorator which can be used to mark Client classes as
|
||||
obsolete. It will result in an error being emitted when the class is
|
||||
instantiated."""
|
||||
|
||||
@functools.wraps(func)
|
||||
def new_func(*args, **kwargs):
|
||||
raise ObsoleteException(
|
||||
"{} has been removed from this version of the library. "
|
||||
"Please refer to current documentation for guidance.".format(func.__name__)
|
||||
)
|
||||
|
||||
return new_func
|
||||
|
||||
|
||||
def deprecated_method(new_func=None):
|
||||
"""
|
||||
This is a decorator which can be used to mark deprecated methods.
|
||||
It will report in a DeprecationWarning being emitted to stderr when the deprecated method is used.
|
||||
"""
|
||||
|
||||
def deprecated_method_wrapper(func):
|
||||
@functools.wraps(func)
|
||||
def wrapper(*args, **kwargs):
|
||||
msg = "Function method .{}() is deprecated".format(func.__name__)
|
||||
msg += (
|
||||
" in favor of .{}()".format(new_func)
|
||||
if isinstance(new_func, str)
|
||||
else ""
|
||||
)
|
||||
warnings.warn(msg, DeprecationWarning)
|
||||
return func(*args, **kwargs)
|
||||
|
||||
return wrapper
|
||||
|
||||
if callable(new_func):
|
||||
return deprecated_method_wrapper(new_func)
|
||||
|
||||
return deprecated_method_wrapper
|
||||
@@ -0,0 +1,171 @@
|
||||
import json
|
||||
from typing import Any, Dict, Optional
|
||||
|
||||
from twilio.base.exceptions import TwilioException
|
||||
from twilio.http.response import Response
|
||||
|
||||
|
||||
class Page(object):
|
||||
"""
|
||||
Represents a page of records in a collection.
|
||||
|
||||
A `Page` lets you iterate over its records and fetch the next and previous
|
||||
pages in the collection.
|
||||
"""
|
||||
|
||||
META_KEYS = {
|
||||
"end",
|
||||
"first_page_uri",
|
||||
"next_page_uri",
|
||||
"last_page_uri",
|
||||
"page",
|
||||
"page_size",
|
||||
"previous_page_uri",
|
||||
"total",
|
||||
"num_pages",
|
||||
"start",
|
||||
"uri",
|
||||
}
|
||||
|
||||
def __init__(self, version, response: Response, solution={}):
|
||||
payload = self.process_response(response)
|
||||
|
||||
self._version = version
|
||||
self._payload = payload
|
||||
self._solution = solution
|
||||
self._records = iter(self.load_page(payload))
|
||||
|
||||
def __iter__(self):
|
||||
"""
|
||||
A `Page` is a valid iterator.
|
||||
"""
|
||||
return self
|
||||
|
||||
def __next__(self):
|
||||
return self.next()
|
||||
|
||||
def next(self):
|
||||
"""
|
||||
Returns the next record in the `Page`.
|
||||
"""
|
||||
return self.get_instance(next(self._records))
|
||||
|
||||
@classmethod
|
||||
def process_response(cls, response: Response) -> Any:
|
||||
"""
|
||||
Load a JSON response.
|
||||
|
||||
:param response: The HTTP response.
|
||||
:return The JSON-loaded content.
|
||||
"""
|
||||
if response.status_code != 200:
|
||||
raise TwilioException("Unable to fetch page", response)
|
||||
|
||||
return json.loads(response.text)
|
||||
|
||||
def load_page(self, payload: Dict[str, Any]):
|
||||
"""
|
||||
Parses the collection of records out of a list payload.
|
||||
|
||||
:param payload: The JSON-loaded content.
|
||||
:return list: The list of records.
|
||||
"""
|
||||
if "meta" in payload and "key" in payload["meta"]:
|
||||
return payload[payload["meta"]["key"]]
|
||||
else:
|
||||
keys = set(payload.keys())
|
||||
key = keys - self.META_KEYS
|
||||
if len(key) == 1:
|
||||
return payload[key.pop()]
|
||||
|
||||
raise TwilioException("Page Records can not be deserialized")
|
||||
|
||||
@property
|
||||
def previous_page_url(self) -> Optional[str]:
|
||||
"""
|
||||
:return str: Returns a link to the previous_page_url or None if doesn't exist.
|
||||
"""
|
||||
if "meta" in self._payload and "previous_page_url" in self._payload["meta"]:
|
||||
return self._payload["meta"]["previous_page_url"]
|
||||
elif (
|
||||
"previous_page_uri" in self._payload and self._payload["previous_page_uri"]
|
||||
):
|
||||
return self._version.domain.absolute_url(self._payload["previous_page_uri"])
|
||||
|
||||
return None
|
||||
|
||||
@property
|
||||
def next_page_url(self) -> Optional[str]:
|
||||
"""
|
||||
:return str: Returns a link to the next_page_url or None if doesn't exist.
|
||||
"""
|
||||
if "meta" in self._payload and "next_page_url" in self._payload["meta"]:
|
||||
return self._payload["meta"]["next_page_url"]
|
||||
elif "next_page_uri" in self._payload and self._payload["next_page_uri"]:
|
||||
return self._version.domain.absolute_url(self._payload["next_page_uri"])
|
||||
|
||||
return None
|
||||
|
||||
def get_instance(self, payload: Dict[str, Any]) -> Any:
|
||||
"""
|
||||
:param dict payload: A JSON-loaded representation of an instance record.
|
||||
:return: A rich, resource-dependent object.
|
||||
"""
|
||||
raise TwilioException(
|
||||
"Page.get_instance() must be implemented in the derived class"
|
||||
)
|
||||
|
||||
def next_page(self) -> Optional["Page"]:
|
||||
"""
|
||||
Return the `Page` after this one.
|
||||
:return The next page.
|
||||
"""
|
||||
if not self.next_page_url:
|
||||
return None
|
||||
|
||||
response = self._version.domain.twilio.request("GET", self.next_page_url)
|
||||
cls = type(self)
|
||||
return cls(self._version, response, self._solution)
|
||||
|
||||
async def next_page_async(self) -> Optional["Page"]:
|
||||
"""
|
||||
Asynchronously return the `Page` after this one.
|
||||
:return The next page.
|
||||
"""
|
||||
if not self.next_page_url:
|
||||
return None
|
||||
|
||||
response = await self._version.domain.twilio.request_async(
|
||||
"GET", self.next_page_url
|
||||
)
|
||||
cls = type(self)
|
||||
return cls(self._version, response, self._solution)
|
||||
|
||||
def previous_page(self) -> Optional["Page"]:
|
||||
"""
|
||||
Return the `Page` before this one.
|
||||
:return The previous page.
|
||||
"""
|
||||
if not self.previous_page_url:
|
||||
return None
|
||||
|
||||
response = self._version.domain.twilio.request("GET", self.previous_page_url)
|
||||
cls = type(self)
|
||||
return cls(self._version, response, self._solution)
|
||||
|
||||
async def previous_page_async(self) -> Optional["Page"]:
|
||||
"""
|
||||
Asynchronously return the `Page` before this one.
|
||||
:return The previous page.
|
||||
"""
|
||||
if not self.previous_page_url:
|
||||
return None
|
||||
|
||||
response = await self._version.domain.twilio.request_async(
|
||||
"GET", self.previous_page_url
|
||||
)
|
||||
cls = type(self)
|
||||
return cls(self._version, response, self._solution)
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return "<Page>"
|
||||
@@ -0,0 +1,80 @@
|
||||
import datetime
|
||||
import json
|
||||
|
||||
from twilio.base import values
|
||||
|
||||
|
||||
def iso8601_date(d):
|
||||
"""
|
||||
Return a string representation of a date that the Twilio API understands
|
||||
Format is YYYY-MM-DD. Returns None if d is not a string, datetime, or date
|
||||
"""
|
||||
if d == values.unset:
|
||||
return d
|
||||
elif isinstance(d, datetime.datetime):
|
||||
return str(d.date())
|
||||
elif isinstance(d, datetime.date):
|
||||
return str(d)
|
||||
elif isinstance(d, str):
|
||||
return d
|
||||
|
||||
|
||||
def iso8601_datetime(d):
|
||||
"""
|
||||
Return a string representation of a date that the Twilio API understands
|
||||
Format is YYYY-MM-DD. Returns None if d is not a string, datetime, or date
|
||||
"""
|
||||
if d == values.unset:
|
||||
return d
|
||||
elif isinstance(d, datetime.datetime) or isinstance(d, datetime.date):
|
||||
return d.strftime("%Y-%m-%dT%H:%M:%SZ")
|
||||
elif isinstance(d, str):
|
||||
return d
|
||||
|
||||
|
||||
def prefixed_collapsible_map(m, prefix):
|
||||
"""
|
||||
Return a dict of params corresponding to those in m with the added prefix
|
||||
"""
|
||||
if m == values.unset:
|
||||
return {}
|
||||
|
||||
def flatten_dict(d, result=None, prv_keys=None):
|
||||
if result is None:
|
||||
result = {}
|
||||
|
||||
if prv_keys is None:
|
||||
prv_keys = []
|
||||
|
||||
for k, v in d.items():
|
||||
if isinstance(v, dict):
|
||||
flatten_dict(v, result, prv_keys + [k])
|
||||
else:
|
||||
result[".".join(prv_keys + [k])] = v
|
||||
|
||||
return result
|
||||
|
||||
if isinstance(m, dict):
|
||||
flattened = flatten_dict(m)
|
||||
return {"{}.{}".format(prefix, k): v for k, v in flattened.items()}
|
||||
|
||||
return {}
|
||||
|
||||
|
||||
def object(obj):
|
||||
"""
|
||||
Return a jsonified string represenation of obj if obj is jsonifiable else
|
||||
return obj untouched
|
||||
"""
|
||||
if isinstance(obj, dict) or isinstance(obj, list):
|
||||
return json.dumps(obj)
|
||||
return obj
|
||||
|
||||
|
||||
def map(lst, serialize_func):
|
||||
"""
|
||||
Applies serialize_func to every element in lst
|
||||
"""
|
||||
if not isinstance(lst, list):
|
||||
return lst
|
||||
return [serialize_func(e) for e in lst]
|
||||
@@ -0,0 +1,13 @@
|
||||
from typing import Dict
|
||||
|
||||
unset = object()
|
||||
|
||||
|
||||
def of(d: Dict[str, object]) -> Dict[str, object]:
|
||||
"""
|
||||
Remove unset values from a dict.
|
||||
|
||||
:param d: A dict to strip.
|
||||
:return A dict with unset values removed.
|
||||
"""
|
||||
return {k: v for k, v in d.items() if v != unset}
|
||||
@@ -0,0 +1,492 @@
|
||||
import json
|
||||
from typing import Any, AsyncIterator, Dict, Iterator, Optional, Tuple
|
||||
|
||||
from twilio.base import values
|
||||
from twilio.base.domain import Domain
|
||||
from twilio.base.exceptions import TwilioRestException
|
||||
from twilio.base.page import Page
|
||||
from twilio.http.response import Response
|
||||
|
||||
|
||||
class Version(object):
|
||||
"""
|
||||
Represents an API version.
|
||||
"""
|
||||
|
||||
def __init__(self, domain: Domain, version: str):
|
||||
self.domain = domain
|
||||
self.version = version
|
||||
|
||||
def absolute_url(self, uri: str) -> str:
|
||||
"""
|
||||
Turns a relative uri into an absolute url.
|
||||
"""
|
||||
return self.domain.absolute_url(self.relative_uri(uri))
|
||||
|
||||
def relative_uri(self, uri: str) -> str:
|
||||
"""
|
||||
Turns a relative uri into a versioned relative uri.
|
||||
"""
|
||||
return "{}/{}".format(self.version.strip("/"), uri.strip("/"))
|
||||
|
||||
def request(
|
||||
self,
|
||||
method: str,
|
||||
uri: str,
|
||||
params: Optional[Dict[str, object]] = None,
|
||||
data: Optional[Dict[str, object]] = None,
|
||||
headers: Optional[Dict[str, str]] = None,
|
||||
auth: Optional[Tuple[str, str]] = None,
|
||||
timeout: Optional[float] = None,
|
||||
allow_redirects: bool = False,
|
||||
) -> Response:
|
||||
"""
|
||||
Make an HTTP request.
|
||||
"""
|
||||
url = self.relative_uri(uri)
|
||||
return self.domain.request(
|
||||
method,
|
||||
url,
|
||||
params=params,
|
||||
data=data,
|
||||
headers=headers,
|
||||
auth=auth,
|
||||
timeout=timeout,
|
||||
allow_redirects=allow_redirects,
|
||||
)
|
||||
|
||||
async def request_async(
|
||||
self,
|
||||
method: str,
|
||||
uri: str,
|
||||
params: Optional[Dict[str, object]] = None,
|
||||
data: Optional[Dict[str, object]] = None,
|
||||
headers: Optional[Dict[str, str]] = None,
|
||||
auth: Optional[Tuple[str, str]] = None,
|
||||
timeout: Optional[float] = None,
|
||||
allow_redirects: bool = False,
|
||||
) -> Response:
|
||||
"""
|
||||
Make an asynchronous HTTP request
|
||||
"""
|
||||
url = self.relative_uri(uri)
|
||||
return await self.domain.request_async(
|
||||
method,
|
||||
url,
|
||||
params=params,
|
||||
data=data,
|
||||
headers=headers,
|
||||
auth=auth,
|
||||
timeout=timeout,
|
||||
allow_redirects=allow_redirects,
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def exception(
|
||||
cls, method: str, uri: str, response: Response, message: str
|
||||
) -> TwilioRestException:
|
||||
"""
|
||||
Wraps an exceptional response in a `TwilioRestException`.
|
||||
"""
|
||||
# noinspection PyBroadException
|
||||
try:
|
||||
error_payload = json.loads(response.text)
|
||||
if "message" in error_payload:
|
||||
message = "{}: {}".format(message, error_payload["message"])
|
||||
details = error_payload.get("details")
|
||||
code = error_payload.get("code", response.status_code)
|
||||
return TwilioRestException(
|
||||
response.status_code, uri, message, code, method, details
|
||||
)
|
||||
except Exception:
|
||||
return TwilioRestException(
|
||||
response.status_code, uri, message, response.status_code, method
|
||||
)
|
||||
|
||||
def _parse_fetch(self, method: str, uri: str, response: Response) -> Any:
|
||||
"""
|
||||
Parses fetch response JSON
|
||||
"""
|
||||
# Note that 3XX response codes are allowed for fetches.
|
||||
if response.status_code < 200 or response.status_code >= 400:
|
||||
raise self.exception(method, uri, response, "Unable to fetch record")
|
||||
|
||||
return json.loads(response.text)
|
||||
|
||||
def fetch(
|
||||
self,
|
||||
method: str,
|
||||
uri: str,
|
||||
params: Optional[Dict[str, object]] = None,
|
||||
data: Optional[Dict[str, object]] = None,
|
||||
headers: Optional[Dict[str, str]] = None,
|
||||
auth: Optional[Tuple[str, str]] = None,
|
||||
timeout: Optional[float] = None,
|
||||
allow_redirects: bool = False,
|
||||
) -> Any:
|
||||
"""
|
||||
Fetch a resource instance.
|
||||
"""
|
||||
response = self.request(
|
||||
method,
|
||||
uri,
|
||||
params=params,
|
||||
data=data,
|
||||
headers=headers,
|
||||
auth=auth,
|
||||
timeout=timeout,
|
||||
allow_redirects=allow_redirects,
|
||||
)
|
||||
|
||||
return self._parse_fetch(method, uri, response)
|
||||
|
||||
async def fetch_async(
|
||||
self,
|
||||
method: str,
|
||||
uri: str,
|
||||
params: Optional[Dict[str, object]] = None,
|
||||
data: Optional[Dict[str, object]] = None,
|
||||
headers: Optional[Dict[str, str]] = None,
|
||||
auth: Optional[Tuple[str, str]] = None,
|
||||
timeout: Optional[float] = None,
|
||||
allow_redirects: bool = False,
|
||||
) -> Any:
|
||||
"""
|
||||
Asynchronously fetch a resource instance.
|
||||
"""
|
||||
response = await self.request_async(
|
||||
method,
|
||||
uri,
|
||||
params=params,
|
||||
data=data,
|
||||
headers=headers,
|
||||
auth=auth,
|
||||
timeout=timeout,
|
||||
allow_redirects=allow_redirects,
|
||||
)
|
||||
|
||||
return self._parse_fetch(method, uri, response)
|
||||
|
||||
def _parse_update(self, method: str, uri: str, response: Response) -> Any:
|
||||
"""
|
||||
Parses update response JSON
|
||||
"""
|
||||
if response.status_code < 200 or response.status_code >= 300:
|
||||
raise self.exception(method, uri, response, "Unable to update record")
|
||||
|
||||
return json.loads(response.text)
|
||||
|
||||
def update(
|
||||
self,
|
||||
method: str,
|
||||
uri: str,
|
||||
params: Optional[Dict[str, object]] = None,
|
||||
data: Optional[Dict[str, object]] = None,
|
||||
headers: Optional[Dict[str, str]] = None,
|
||||
auth: Optional[Tuple[str, str]] = None,
|
||||
timeout: Optional[float] = None,
|
||||
allow_redirects: bool = False,
|
||||
) -> Any:
|
||||
"""
|
||||
Update a resource instance.
|
||||
"""
|
||||
response = self.request(
|
||||
method,
|
||||
uri,
|
||||
params=params,
|
||||
data=data,
|
||||
headers=headers,
|
||||
auth=auth,
|
||||
timeout=timeout,
|
||||
allow_redirects=allow_redirects,
|
||||
)
|
||||
|
||||
return self._parse_update(method, uri, response)
|
||||
|
||||
async def update_async(
|
||||
self,
|
||||
method: str,
|
||||
uri: str,
|
||||
params: Optional[Dict[str, object]] = None,
|
||||
data: Optional[Dict[str, object]] = None,
|
||||
headers: Optional[Dict[str, str]] = None,
|
||||
auth: Optional[Tuple[str, str]] = None,
|
||||
timeout: Optional[float] = None,
|
||||
allow_redirects: bool = False,
|
||||
) -> Any:
|
||||
"""
|
||||
Asynchronously update a resource instance.
|
||||
"""
|
||||
response = await self.request_async(
|
||||
method,
|
||||
uri,
|
||||
params=params,
|
||||
data=data,
|
||||
headers=headers,
|
||||
auth=auth,
|
||||
timeout=timeout,
|
||||
allow_redirects=allow_redirects,
|
||||
)
|
||||
|
||||
return self._parse_update(method, uri, response)
|
||||
|
||||
def _parse_delete(self, method: str, uri: str, response: Response) -> bool:
|
||||
"""
|
||||
Parses delete response JSON
|
||||
"""
|
||||
if response.status_code < 200 or response.status_code >= 300:
|
||||
raise self.exception(method, uri, response, "Unable to delete record")
|
||||
|
||||
return response.status_code == 204
|
||||
|
||||
def delete(
|
||||
self,
|
||||
method: str,
|
||||
uri: str,
|
||||
params: Optional[Dict[str, object]] = None,
|
||||
data: Optional[Dict[str, object]] = None,
|
||||
headers: Optional[Dict[str, str]] = None,
|
||||
auth: Optional[Tuple[str, str]] = None,
|
||||
timeout: Optional[float] = None,
|
||||
allow_redirects: bool = False,
|
||||
) -> bool:
|
||||
"""
|
||||
Delete a resource.
|
||||
"""
|
||||
response = self.request(
|
||||
method,
|
||||
uri,
|
||||
params=params,
|
||||
data=data,
|
||||
headers=headers,
|
||||
auth=auth,
|
||||
timeout=timeout,
|
||||
allow_redirects=allow_redirects,
|
||||
)
|
||||
|
||||
return self._parse_delete(method, uri, response)
|
||||
|
||||
async def delete_async(
|
||||
self,
|
||||
method: str,
|
||||
uri: str,
|
||||
params: Optional[Dict[str, object]] = None,
|
||||
data: Optional[Dict[str, object]] = None,
|
||||
headers: Optional[Dict[str, str]] = None,
|
||||
auth: Optional[Tuple[str, str]] = None,
|
||||
timeout: Optional[float] = None,
|
||||
allow_redirects: bool = False,
|
||||
) -> bool:
|
||||
"""
|
||||
Asynchronously delete a resource.
|
||||
"""
|
||||
response = await self.request_async(
|
||||
method,
|
||||
uri,
|
||||
params=params,
|
||||
data=data,
|
||||
headers=headers,
|
||||
auth=auth,
|
||||
timeout=timeout,
|
||||
allow_redirects=allow_redirects,
|
||||
)
|
||||
|
||||
return self._parse_delete(method, uri, response)
|
||||
|
||||
def read_limits(
|
||||
self, limit: Optional[int] = None, page_size: Optional[int] = None
|
||||
) -> Dict[str, object]:
|
||||
"""
|
||||
Takes a limit on the max number of records to read and a max page_size
|
||||
and calculates the max number of pages to read.
|
||||
|
||||
:param limit: Max number of records to read.
|
||||
:param page_size: Max page size.
|
||||
:return A dictionary of paging limits.
|
||||
"""
|
||||
if limit is not None and page_size is None:
|
||||
page_size = limit
|
||||
|
||||
return {
|
||||
"limit": limit or values.unset,
|
||||
"page_size": page_size or values.unset,
|
||||
}
|
||||
|
||||
def page(
|
||||
self,
|
||||
method: str,
|
||||
uri: str,
|
||||
params: Optional[Dict[str, object]] = None,
|
||||
data: Optional[Dict[str, object]] = None,
|
||||
headers: Optional[Dict[str, str]] = None,
|
||||
auth: Optional[Tuple[str, str]] = None,
|
||||
timeout: Optional[float] = None,
|
||||
allow_redirects: bool = False,
|
||||
) -> Response:
|
||||
"""
|
||||
Makes an HTTP request.
|
||||
"""
|
||||
return self.request(
|
||||
method,
|
||||
uri,
|
||||
params=params,
|
||||
data=data,
|
||||
headers=headers,
|
||||
auth=auth,
|
||||
timeout=timeout,
|
||||
allow_redirects=allow_redirects,
|
||||
)
|
||||
|
||||
async def page_async(
|
||||
self,
|
||||
method: str,
|
||||
uri: str,
|
||||
params: Optional[Dict[str, object]] = None,
|
||||
data: Optional[Dict[str, object]] = None,
|
||||
headers: Optional[Dict[str, str]] = None,
|
||||
auth: Optional[Tuple[str, str]] = None,
|
||||
timeout: Optional[float] = None,
|
||||
allow_redirects: bool = False,
|
||||
) -> Response:
|
||||
"""
|
||||
Makes an asynchronous HTTP request.
|
||||
"""
|
||||
return await self.request_async(
|
||||
method,
|
||||
uri,
|
||||
params=params,
|
||||
data=data,
|
||||
headers=headers,
|
||||
auth=auth,
|
||||
timeout=timeout,
|
||||
allow_redirects=allow_redirects,
|
||||
)
|
||||
|
||||
def stream(
|
||||
self,
|
||||
page: Optional[Page],
|
||||
limit: Optional[int] = None,
|
||||
page_limit: Optional[int] = None,
|
||||
) -> Iterator[Any]:
|
||||
"""
|
||||
Generates records one a time from a page, stopping at prescribed limits.
|
||||
|
||||
:param page: The page to stream.
|
||||
:param limit: The max number of records to read.
|
||||
:param page_limit: The max number of pages to read.
|
||||
"""
|
||||
current_record = 1
|
||||
current_page = 1
|
||||
|
||||
while page is not None:
|
||||
for record in page:
|
||||
yield record
|
||||
current_record += 1
|
||||
if limit and limit is not values.unset and limit < current_record:
|
||||
return
|
||||
|
||||
current_page += 1
|
||||
if (
|
||||
page_limit
|
||||
and page_limit is not values.unset
|
||||
and page_limit < current_page
|
||||
):
|
||||
return
|
||||
|
||||
page = page.next_page()
|
||||
|
||||
async def stream_async(
|
||||
self,
|
||||
page: Optional[Page],
|
||||
limit: Optional[int] = None,
|
||||
page_limit: Optional[int] = None,
|
||||
) -> AsyncIterator[Any]:
|
||||
"""
|
||||
Generates records one a time from a page, stopping at prescribed limits.
|
||||
|
||||
:param page: The page to stream.
|
||||
:param limit: The max number of records to read.
|
||||
:param page_limit: The max number of pages to read.
|
||||
"""
|
||||
current_record = 1
|
||||
current_page = 1
|
||||
|
||||
while page is not None:
|
||||
for record in page:
|
||||
yield record
|
||||
current_record += 1
|
||||
if limit and limit is not values.unset and limit < current_record:
|
||||
return
|
||||
|
||||
current_page += 1
|
||||
if (
|
||||
page_limit
|
||||
and page_limit is not values.unset
|
||||
and page_limit < current_page
|
||||
):
|
||||
return
|
||||
|
||||
page = await page.next_page_async()
|
||||
|
||||
def _parse_create(self, method: str, uri: str, response: Response) -> Any:
|
||||
"""
|
||||
Parse create response JSON
|
||||
"""
|
||||
if response.status_code < 200 or response.status_code >= 300:
|
||||
raise self.exception(method, uri, response, "Unable to create record")
|
||||
|
||||
return json.loads(response.text)
|
||||
|
||||
def create(
|
||||
self,
|
||||
method: str,
|
||||
uri: str,
|
||||
params: Optional[Dict[str, object]] = None,
|
||||
data: Optional[Dict[str, object]] = None,
|
||||
headers: Optional[Dict[str, str]] = None,
|
||||
auth: Optional[Tuple[str, str]] = None,
|
||||
timeout: Optional[float] = None,
|
||||
allow_redirects: bool = False,
|
||||
) -> Any:
|
||||
"""
|
||||
Create a resource instance.
|
||||
"""
|
||||
response = self.request(
|
||||
method,
|
||||
uri,
|
||||
params=params,
|
||||
data=data,
|
||||
headers=headers,
|
||||
auth=auth,
|
||||
timeout=timeout,
|
||||
allow_redirects=allow_redirects,
|
||||
)
|
||||
|
||||
return self._parse_create(method, uri, response)
|
||||
|
||||
async def create_async(
|
||||
self,
|
||||
method: str,
|
||||
uri: str,
|
||||
params: Optional[Dict[str, object]] = None,
|
||||
data: Optional[Dict[str, object]] = None,
|
||||
headers: Optional[Dict[str, str]] = None,
|
||||
auth: Optional[Tuple[str, str]] = None,
|
||||
timeout: Optional[float] = None,
|
||||
allow_redirects: bool = False,
|
||||
) -> Any:
|
||||
"""
|
||||
Asynchronously create a resource instance.
|
||||
"""
|
||||
response = await self.request_async(
|
||||
method,
|
||||
uri,
|
||||
params=params,
|
||||
data=data,
|
||||
headers=headers,
|
||||
auth=auth,
|
||||
timeout=timeout,
|
||||
allow_redirects=allow_redirects,
|
||||
)
|
||||
|
||||
return self._parse_create(method, uri, response)
|
||||
@@ -0,0 +1,104 @@
|
||||
from logging import Logger
|
||||
from typing import Any, Dict, Optional, Tuple
|
||||
from urllib.parse import urlencode
|
||||
|
||||
from requests import Response
|
||||
|
||||
from twilio.base.exceptions import TwilioException
|
||||
from twilio.http.request import Request as TwilioRequest
|
||||
from twilio.http.response import Response as TwilioResponse
|
||||
|
||||
|
||||
class HttpClient(object):
|
||||
def __init__(self, logger: Logger, is_async: bool, timeout: Optional[float] = None):
|
||||
"""
|
||||
Constructor for the abstract HTTP client
|
||||
|
||||
:param logger
|
||||
:param is_async: Whether the client supports async request calls.
|
||||
:param timeout: Timeout for the requests.
|
||||
Timeout should never be zero (0) or less.
|
||||
"""
|
||||
self.logger = logger
|
||||
self.is_async = is_async
|
||||
|
||||
if timeout is not None and timeout <= 0:
|
||||
raise ValueError(timeout)
|
||||
self.timeout = timeout
|
||||
|
||||
self._test_only_last_request: Optional[TwilioRequest] = None
|
||||
self._test_only_last_response: Optional[TwilioResponse] = None
|
||||
|
||||
"""
|
||||
An abstract class representing an HTTP client.
|
||||
"""
|
||||
|
||||
def request(
|
||||
self,
|
||||
method: str,
|
||||
uri: str,
|
||||
params: Optional[Dict[str, object]] = None,
|
||||
data: Optional[Dict[str, object]] = None,
|
||||
headers: Optional[Dict[str, str]] = None,
|
||||
auth: Optional[Tuple[str, str]] = None,
|
||||
timeout: Optional[float] = None,
|
||||
allow_redirects: bool = False,
|
||||
) -> TwilioResponse:
|
||||
"""
|
||||
Make an HTTP request.
|
||||
"""
|
||||
raise TwilioException("HttpClient is an abstract class")
|
||||
|
||||
def log_request(self, kwargs: Dict[str, Any]) -> None:
|
||||
"""
|
||||
Logs the HTTP request
|
||||
"""
|
||||
self.logger.info("-- BEGIN Twilio API Request --")
|
||||
|
||||
if kwargs["params"]:
|
||||
self.logger.info(
|
||||
"{} Request: {}?{}".format(
|
||||
kwargs["method"], kwargs["url"], urlencode(kwargs["params"])
|
||||
)
|
||||
)
|
||||
self.logger.info("Query Params: {}".format(kwargs["params"]))
|
||||
else:
|
||||
self.logger.info("{} Request: {}".format(kwargs["method"], kwargs["url"]))
|
||||
|
||||
if kwargs["headers"]:
|
||||
self.logger.info("Headers:")
|
||||
for key, value in kwargs["headers"].items():
|
||||
# Do not log authorization headers
|
||||
if "authorization" not in key.lower():
|
||||
self.logger.info("{} : {}".format(key, value))
|
||||
|
||||
self.logger.info("-- END Twilio API Request --")
|
||||
|
||||
def log_response(self, status_code: int, response: Response) -> None:
|
||||
"""
|
||||
Logs the HTTP response
|
||||
"""
|
||||
self.logger.info("Response Status Code: {}".format(status_code))
|
||||
self.logger.info("Response Headers: {}".format(response.headers))
|
||||
|
||||
|
||||
class AsyncHttpClient(HttpClient):
|
||||
"""
|
||||
An abstract class representing an asynchronous HTTP client.
|
||||
"""
|
||||
|
||||
async def request(
|
||||
self,
|
||||
method: str,
|
||||
uri: str,
|
||||
params: Optional[Dict[str, object]] = None,
|
||||
data: Optional[Dict[str, object]] = None,
|
||||
headers: Optional[Dict[str, str]] = None,
|
||||
auth: Optional[Tuple[str, str]] = None,
|
||||
timeout: Optional[float] = None,
|
||||
allow_redirects: bool = False,
|
||||
) -> TwilioResponse:
|
||||
"""
|
||||
Make an asynchronous HTTP request.
|
||||
"""
|
||||
raise TwilioException("AsyncHttpClient is an abstract class")
|
||||
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
@@ -0,0 +1,135 @@
|
||||
import logging
|
||||
from typing import Dict, Optional, Tuple
|
||||
|
||||
from aiohttp import BasicAuth, ClientSession
|
||||
from aiohttp_retry import ExponentialRetry, RetryClient
|
||||
|
||||
from twilio.http import AsyncHttpClient
|
||||
from twilio.http.request import Request as TwilioRequest
|
||||
from twilio.http.response import Response
|
||||
|
||||
_logger = logging.getLogger("twilio.async_http_client")
|
||||
|
||||
|
||||
class AsyncTwilioHttpClient(AsyncHttpClient):
|
||||
"""
|
||||
General purpose asynchronous HTTP Client for interacting with the Twilio API
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
pool_connections: bool = True,
|
||||
trace_configs=None,
|
||||
timeout: Optional[float] = None,
|
||||
logger: logging.Logger = _logger,
|
||||
proxy_url: Optional[str] = None,
|
||||
max_retries: Optional[int] = None,
|
||||
):
|
||||
"""
|
||||
Constructor for the AsyncTwilioHttpClient
|
||||
|
||||
:param pool_connections: Creates a client session for making requests from.
|
||||
:param trace_configs: Configuration used to trace request lifecycle events. See aiohttp library TraceConfig
|
||||
documentation for more info.
|
||||
:param timeout: Timeout for the requests (seconds)
|
||||
:param logger
|
||||
:param proxy_url: Proxy URL
|
||||
:param max_retries: Maximum number of retries each request should attempt
|
||||
"""
|
||||
super().__init__(logger, True, timeout)
|
||||
self.proxy_url = proxy_url
|
||||
self.trace_configs = trace_configs
|
||||
self.session = (
|
||||
ClientSession(trace_configs=self.trace_configs)
|
||||
if pool_connections
|
||||
else None
|
||||
)
|
||||
if max_retries is not None:
|
||||
retry_options = ExponentialRetry(attempts=max_retries)
|
||||
self.session = RetryClient(
|
||||
client_session=self.session, retry_options=retry_options
|
||||
)
|
||||
|
||||
async def request(
|
||||
self,
|
||||
method: str,
|
||||
url: str,
|
||||
params: Optional[Dict[str, object]] = None,
|
||||
data: Optional[Dict[str, object]] = None,
|
||||
headers: Optional[Dict[str, str]] = None,
|
||||
auth: Optional[Tuple[str, str]] = None,
|
||||
timeout: Optional[float] = None,
|
||||
allow_redirects: bool = False,
|
||||
) -> Response:
|
||||
"""
|
||||
Make an asynchronous HTTP Request with parameters provided.
|
||||
|
||||
:param method: The HTTP method to use
|
||||
:param url: The URL to request
|
||||
:param params: Query parameters to append to the URL
|
||||
:param data: Parameters to go in the body of the HTTP request
|
||||
:param headers: HTTP Headers to send with the request
|
||||
:param auth: Basic Auth arguments (username, password entries)
|
||||
:param timeout: Socket/Read timeout for the request. Overrides the timeout if set on the client.
|
||||
:param allow_redirects: Whether or not to allow redirects
|
||||
See the requests documentation for explanation of all these parameters
|
||||
|
||||
:return: An http response
|
||||
"""
|
||||
if timeout is not None and timeout <= 0:
|
||||
raise ValueError(timeout)
|
||||
|
||||
basic_auth = None
|
||||
if auth is not None:
|
||||
basic_auth = BasicAuth(login=auth[0], password=auth[1])
|
||||
|
||||
kwargs = {
|
||||
"method": method.upper(),
|
||||
"url": url,
|
||||
"params": params,
|
||||
"data": data,
|
||||
"headers": headers,
|
||||
"auth": basic_auth,
|
||||
"timeout": timeout,
|
||||
"allow_redirects": allow_redirects,
|
||||
}
|
||||
|
||||
self.log_request(kwargs)
|
||||
self._test_only_last_response = None
|
||||
|
||||
temp = False
|
||||
session = None
|
||||
if self.session:
|
||||
session = self.session
|
||||
else:
|
||||
session = ClientSession()
|
||||
temp = True
|
||||
self._test_only_last_request = TwilioRequest(**kwargs)
|
||||
response = await session.request(**kwargs)
|
||||
self.log_response(response.status, response)
|
||||
self._test_only_last_response = Response(
|
||||
response.status, await response.text(), response.headers
|
||||
)
|
||||
if temp:
|
||||
await session.close()
|
||||
return self._test_only_last_response
|
||||
|
||||
async def close(self):
|
||||
"""
|
||||
Closes the HTTP client session
|
||||
"""
|
||||
if self.session:
|
||||
await self.session.close()
|
||||
|
||||
async def __aenter__(self):
|
||||
"""
|
||||
Async context manager setup
|
||||
"""
|
||||
return self
|
||||
|
||||
async def __aexit__(self, *excinfo):
|
||||
"""
|
||||
Async context manager exit
|
||||
"""
|
||||
if self.session:
|
||||
await self.session.close()
|
||||
@@ -0,0 +1,114 @@
|
||||
import logging
|
||||
from typing import Dict, Optional, Tuple
|
||||
|
||||
from requests import Request, Session, hooks
|
||||
from requests.adapters import HTTPAdapter
|
||||
|
||||
from twilio.http import HttpClient
|
||||
from twilio.http.request import Request as TwilioRequest
|
||||
from twilio.http.response import Response
|
||||
|
||||
_logger = logging.getLogger("twilio.http_client")
|
||||
|
||||
|
||||
class TwilioHttpClient(HttpClient):
|
||||
"""
|
||||
General purpose HTTP Client for interacting with the Twilio API
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
pool_connections: bool = True,
|
||||
request_hooks: Optional[Dict[str, object]] = None,
|
||||
timeout: Optional[float] = None,
|
||||
logger: logging.Logger = _logger,
|
||||
proxy: Optional[Dict[str, str]] = None,
|
||||
max_retries: Optional[int] = None,
|
||||
):
|
||||
"""
|
||||
Constructor for the TwilioHttpClient
|
||||
|
||||
:param pool_connections
|
||||
:param request_hooks
|
||||
:param timeout: Timeout for the requests.
|
||||
Timeout should never be zero (0) or less.
|
||||
:param logger
|
||||
:param proxy: Http proxy for the requests session
|
||||
:param max_retries: Maximum number of retries each request should attempt
|
||||
"""
|
||||
super().__init__(logger, False, timeout)
|
||||
self.session = Session() if pool_connections else None
|
||||
if self.session and max_retries is not None:
|
||||
self.session.mount("https://", HTTPAdapter(max_retries=max_retries))
|
||||
|
||||
self.request_hooks = request_hooks or hooks.default_hooks()
|
||||
self.proxy = proxy if proxy else {}
|
||||
|
||||
def request(
|
||||
self,
|
||||
method: str,
|
||||
url: str,
|
||||
params: Optional[Dict[str, object]] = None,
|
||||
data: Optional[Dict[str, object]] = None,
|
||||
headers: Optional[Dict[str, str]] = None,
|
||||
auth: Optional[Tuple[str, str]] = None,
|
||||
timeout: Optional[float] = None,
|
||||
allow_redirects: bool = False,
|
||||
) -> Response:
|
||||
"""
|
||||
Make an HTTP Request with parameters provided.
|
||||
|
||||
:param method: The HTTP method to use
|
||||
:param url: The URL to request
|
||||
:param params: Query parameters to append to the URL
|
||||
:param data: Parameters to go in the body of the HTTP request
|
||||
:param headers: HTTP Headers to send with the request
|
||||
:param auth: Basic Auth arguments
|
||||
:param timeout: Socket/Read timeout for the request
|
||||
:param allow_redirects: Whether or not to allow redirects
|
||||
See the requests documentation for explanation of all these parameters
|
||||
|
||||
:return: An http response
|
||||
"""
|
||||
if timeout is None:
|
||||
timeout = self.timeout
|
||||
elif timeout <= 0:
|
||||
raise ValueError(timeout)
|
||||
|
||||
kwargs = {
|
||||
"method": method.upper(),
|
||||
"url": url,
|
||||
"params": params,
|
||||
"data": data,
|
||||
"headers": headers,
|
||||
"auth": auth,
|
||||
"hooks": self.request_hooks,
|
||||
}
|
||||
|
||||
self.log_request(kwargs)
|
||||
|
||||
self._test_only_last_response = None
|
||||
session = self.session or Session()
|
||||
request = Request(**kwargs)
|
||||
self._test_only_last_request = TwilioRequest(**kwargs)
|
||||
|
||||
prepped_request = session.prepare_request(request)
|
||||
|
||||
settings = session.merge_environment_settings(
|
||||
prepped_request.url, self.proxy, None, None, None
|
||||
)
|
||||
|
||||
response = session.send(
|
||||
prepped_request,
|
||||
allow_redirects=allow_redirects,
|
||||
timeout=timeout,
|
||||
**settings
|
||||
)
|
||||
|
||||
self.log_response(response.status_code, response)
|
||||
|
||||
self._test_only_last_response = Response(
|
||||
int(response.status_code), response.text, response.headers
|
||||
)
|
||||
|
||||
return self._test_only_last_response
|
||||
@@ -0,0 +1,91 @@
|
||||
from enum import Enum
|
||||
from typing import Any, Dict, Tuple, Union
|
||||
from urllib.parse import urlencode
|
||||
|
||||
|
||||
class Match(Enum):
|
||||
ANY = "*"
|
||||
|
||||
|
||||
class Request(object):
|
||||
"""
|
||||
An HTTP request.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
method: Union[str, Match] = Match.ANY,
|
||||
url: Union[str, Match] = Match.ANY,
|
||||
auth: Union[Tuple[str, str], Match] = Match.ANY,
|
||||
params: Union[Dict[str, str], Match] = Match.ANY,
|
||||
data: Union[Dict[str, str], Match] = Match.ANY,
|
||||
headers: Union[Dict[str, str], Match] = Match.ANY,
|
||||
**kwargs: Any
|
||||
):
|
||||
self.method = method
|
||||
if method and method is not Match.ANY:
|
||||
self.method = method.upper()
|
||||
self.url = url
|
||||
self.auth = auth
|
||||
self.params = params
|
||||
self.data = data
|
||||
self.headers = headers
|
||||
|
||||
@classmethod
|
||||
def attribute_equal(cls, lhs, rhs) -> bool:
|
||||
if lhs == Match.ANY or rhs == Match.ANY:
|
||||
# ANY matches everything
|
||||
return True
|
||||
|
||||
lhs = lhs or None
|
||||
rhs = rhs or None
|
||||
|
||||
return lhs == rhs
|
||||
|
||||
def __eq__(self, other) -> bool:
|
||||
if not isinstance(other, Request):
|
||||
return False
|
||||
|
||||
return (
|
||||
self.attribute_equal(self.method, other.method)
|
||||
and self.attribute_equal(self.url, other.url)
|
||||
and self.attribute_equal(self.auth, other.auth)
|
||||
and self.attribute_equal(self.params, other.params)
|
||||
and self.attribute_equal(self.data, other.data)
|
||||
and self.attribute_equal(self.headers, other.headers)
|
||||
)
|
||||
|
||||
def __str__(self) -> str:
|
||||
auth = ""
|
||||
if self.auth and self.auth != Match.ANY:
|
||||
auth = "{} ".format(self.auth)
|
||||
|
||||
params = ""
|
||||
if self.params and self.params != Match.ANY:
|
||||
params = "?{}".format(urlencode(self.params, doseq=True))
|
||||
|
||||
data = ""
|
||||
if self.data and self.data != Match.ANY:
|
||||
if self.method == "GET":
|
||||
data = "\n -G"
|
||||
data += "\n{}".format(
|
||||
"\n".join(' -d "{}={}"'.format(k, v) for k, v in self.data.items())
|
||||
)
|
||||
|
||||
headers = ""
|
||||
if self.headers and self.headers != Match.ANY:
|
||||
headers = "\n{}".format(
|
||||
"\n".join(' -H "{}: {}"'.format(k, v) for k, v in self.headers.items())
|
||||
)
|
||||
|
||||
return "{auth}{method} {url}{params}{data}{headers}".format(
|
||||
auth=auth,
|
||||
method=self.method,
|
||||
url=self.url,
|
||||
params=params,
|
||||
data=data,
|
||||
headers=headers,
|
||||
)
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return str(self)
|
||||
@@ -0,0 +1,22 @@
|
||||
from typing import Any, Optional
|
||||
|
||||
|
||||
class Response(object):
|
||||
def __init__(
|
||||
self,
|
||||
status_code: int,
|
||||
text: str,
|
||||
headers: Optional[Any] = None,
|
||||
):
|
||||
self.content = text
|
||||
self.headers = headers
|
||||
self.cached = False
|
||||
self.status_code = status_code
|
||||
self.ok = self.status_code < 400
|
||||
|
||||
@property
|
||||
def text(self) -> str:
|
||||
return self.content
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return "HTTP {} {}".format(self.status_code, self.content)
|
||||
@@ -0,0 +1,138 @@
|
||||
from collections import namedtuple
|
||||
|
||||
from requests import Request, Session
|
||||
|
||||
from twilio.base.exceptions import TwilioRestException
|
||||
from urllib.parse import urlparse
|
||||
from twilio.http import HttpClient
|
||||
from twilio.http.response import Response
|
||||
from twilio.jwt.validation import ClientValidationJwt
|
||||
|
||||
|
||||
ValidationPayload = namedtuple(
|
||||
"ValidationPayload",
|
||||
["method", "path", "query_string", "all_headers", "signed_headers", "body"],
|
||||
)
|
||||
|
||||
|
||||
class ValidationClient(HttpClient):
|
||||
__SIGNED_HEADERS = ["authorization", "host"]
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
account_sid,
|
||||
api_key_sid,
|
||||
credential_sid,
|
||||
private_key,
|
||||
pool_connections=True,
|
||||
):
|
||||
"""
|
||||
Build a ValidationClient which signs requests with private_key and allows Twilio to
|
||||
validate request has not been tampered with.
|
||||
|
||||
:param str account_sid: A Twilio Account Sid starting with 'AC'
|
||||
:param str api_key_sid: A Twilio API Key Sid starting with 'SK'
|
||||
:param str credential_sid: A Credential Sid starting with 'CR',
|
||||
corresponds to public key Twilio will use to verify the JWT.
|
||||
:param str private_key: The private key used to sign the Client Validation JWT.
|
||||
"""
|
||||
self.account_sid = account_sid
|
||||
self.credential_sid = credential_sid
|
||||
self.api_key_sid = api_key_sid
|
||||
self.private_key = private_key
|
||||
self.session = Session() if pool_connections else None
|
||||
|
||||
def request(
|
||||
self,
|
||||
method,
|
||||
url,
|
||||
params=None,
|
||||
data=None,
|
||||
headers=None,
|
||||
auth=None,
|
||||
timeout=None,
|
||||
allow_redirects=False,
|
||||
):
|
||||
"""
|
||||
Make a signed HTTP Request
|
||||
|
||||
:param str method: The HTTP method to use
|
||||
:param str url: The URL to request
|
||||
:param dict params: Query parameters to append to the URL
|
||||
:param dict data: Parameters to go in the body of the HTTP request
|
||||
:param dict headers: HTTP Headers to send with the request
|
||||
:param tuple auth: Basic Auth arguments
|
||||
:param float timeout: Socket/Read timeout for the request
|
||||
:param boolean allow_redirects: Whether or not to allow redirects
|
||||
See the requests documentation for explanation of all these parameters
|
||||
|
||||
:return: An http response
|
||||
:rtype: A :class:`Response <twilio.rest.http.response.Response>` object
|
||||
"""
|
||||
session = self.session or Session()
|
||||
request = Request(
|
||||
method.upper(), url, params=params, data=data, headers=headers, auth=auth
|
||||
)
|
||||
prepared_request = session.prepare_request(request)
|
||||
|
||||
if (
|
||||
"Host" not in prepared_request.headers
|
||||
and "host" not in prepared_request.headers
|
||||
):
|
||||
prepared_request.headers["Host"] = self._get_host(prepared_request)
|
||||
|
||||
validation_payload = self._build_validation_payload(prepared_request)
|
||||
jwt = ClientValidationJwt(
|
||||
self.account_sid,
|
||||
self.api_key_sid,
|
||||
self.credential_sid,
|
||||
self.private_key,
|
||||
validation_payload,
|
||||
)
|
||||
prepared_request.headers["Twilio-Client-Validation"] = jwt.to_jwt()
|
||||
|
||||
response = session.send(
|
||||
prepared_request,
|
||||
allow_redirects=allow_redirects,
|
||||
timeout=timeout,
|
||||
)
|
||||
|
||||
return Response(int(response.status_code), response.text)
|
||||
|
||||
def _build_validation_payload(self, request):
|
||||
"""
|
||||
Extract relevant information from request to build a ClientValidationJWT
|
||||
:param PreparedRequest request: request we will extract information from.
|
||||
:return: ValidationPayload
|
||||
"""
|
||||
parsed = urlparse(request.url)
|
||||
path = parsed.path
|
||||
query_string = parsed.query or ""
|
||||
|
||||
return ValidationPayload(
|
||||
method=request.method,
|
||||
path=path,
|
||||
query_string=query_string,
|
||||
all_headers=request.headers,
|
||||
signed_headers=ValidationClient.__SIGNED_HEADERS,
|
||||
body=request.body or "",
|
||||
)
|
||||
|
||||
def _get_host(self, request):
|
||||
"""Pull the Host out of the request"""
|
||||
parsed = urlparse(request.url)
|
||||
return str(parsed.netloc)
|
||||
|
||||
def validate_ssl_certificate(self, client):
|
||||
"""
|
||||
Validate that a request to the new SSL certificate is successful
|
||||
:return: null on success, raise TwilioRestException if the request fails
|
||||
"""
|
||||
response = client.request("GET", "https://tls-test.twilio.com:443")
|
||||
|
||||
if response.status_code < 200 or response.status_code >= 300:
|
||||
raise TwilioRestException(
|
||||
response.status_code,
|
||||
"https://tls-test.twilio.com:443",
|
||||
"Failed to validate SSL certificate",
|
||||
)
|
||||
@@ -0,0 +1,161 @@
|
||||
import jwt as jwt_lib
|
||||
import time
|
||||
|
||||
|
||||
__all__ = ["Jwt", "JwtDecodeError"]
|
||||
|
||||
|
||||
class JwtDecodeError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class Jwt(object):
|
||||
"""Base class for building a Json Web Token"""
|
||||
|
||||
GENERATE = object()
|
||||
ALGORITHM = "HS256"
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
secret_key,
|
||||
issuer,
|
||||
subject=None,
|
||||
algorithm=None,
|
||||
nbf=GENERATE,
|
||||
ttl=3600,
|
||||
valid_until=None,
|
||||
):
|
||||
self.secret_key = secret_key
|
||||
""":type str: The secret used to encode the JWT"""
|
||||
self.issuer = issuer
|
||||
""":type str: The issuer of this JWT"""
|
||||
self.subject = subject
|
||||
""":type str: The subject of this JWT, omitted from payload by default"""
|
||||
self.algorithm = algorithm or self.ALGORITHM
|
||||
""":type str: The algorithm used to encode the JWT, defaults to 'HS256'"""
|
||||
self.nbf = nbf
|
||||
""":type int: Time in secs since epoch before which this JWT is invalid. Defaults to now."""
|
||||
self.ttl = ttl
|
||||
""":type int: Time to live of the JWT in seconds, defaults to 1 hour"""
|
||||
self.valid_until = valid_until
|
||||
""":type int: Time in secs since epoch this JWT is valid for. Overrides ttl if provided."""
|
||||
|
||||
self.__decoded_payload = None
|
||||
self.__decoded_headers = None
|
||||
|
||||
def _generate_payload(self):
|
||||
""":rtype: dict the payload of the JWT to send"""
|
||||
raise NotImplementedError("Subclass must provide a payload.")
|
||||
|
||||
def _generate_headers(self):
|
||||
""":rtype dict: Additional headers to include in the JWT, defaults to an empty dict"""
|
||||
return {}
|
||||
|
||||
@classmethod
|
||||
def _from_jwt(cls, headers, payload, key=None):
|
||||
"""
|
||||
Class specific implementation of from_jwt which should take jwt components and return
|
||||
and instance of this Class with jwt information loaded.
|
||||
:return: Jwt object containing the headers, payload and key
|
||||
"""
|
||||
jwt = Jwt(
|
||||
secret_key=key,
|
||||
issuer=payload.get("iss", None),
|
||||
subject=payload.get("sub", None),
|
||||
algorithm=headers.get("alg", None),
|
||||
valid_until=payload.get("exp", None),
|
||||
nbf=payload.get("nbf", None),
|
||||
)
|
||||
jwt.__decoded_payload = payload
|
||||
jwt.__decoded_headers = headers
|
||||
return jwt
|
||||
|
||||
@property
|
||||
def payload(self):
|
||||
if self.__decoded_payload:
|
||||
return self.__decoded_payload
|
||||
|
||||
payload = self._generate_payload().copy()
|
||||
payload["iss"] = self.issuer
|
||||
payload["exp"] = int(time.time()) + self.ttl
|
||||
if self.nbf is not None:
|
||||
if self.nbf == self.GENERATE:
|
||||
payload["nbf"] = int(time.time())
|
||||
else:
|
||||
payload["nbf"] = self.nbf
|
||||
if self.valid_until:
|
||||
payload["exp"] = self.valid_until
|
||||
if self.subject:
|
||||
payload["sub"] = self.subject
|
||||
|
||||
return payload
|
||||
|
||||
@property
|
||||
def headers(self):
|
||||
if self.__decoded_headers:
|
||||
return self.__decoded_headers
|
||||
|
||||
headers = self._generate_headers().copy()
|
||||
headers["typ"] = "JWT"
|
||||
headers["alg"] = self.algorithm
|
||||
return headers
|
||||
|
||||
def to_jwt(self, ttl=None):
|
||||
"""
|
||||
Encode this JWT object into a JWT string
|
||||
:param int ttl: override the ttl configured in the constructor
|
||||
:rtype: str The JWT string
|
||||
"""
|
||||
|
||||
if not self.secret_key:
|
||||
raise ValueError("JWT does not have a signing key configured.")
|
||||
|
||||
headers = self.headers.copy()
|
||||
|
||||
payload = self.payload.copy()
|
||||
if ttl:
|
||||
payload["exp"] = int(time.time()) + ttl
|
||||
|
||||
return jwt_lib.encode(
|
||||
payload, self.secret_key, algorithm=self.algorithm, headers=headers
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def from_jwt(cls, jwt, key=""):
|
||||
"""
|
||||
Decode a JWT string into a Jwt object
|
||||
:param str jwt: JWT string
|
||||
:param Optional[str] key: key used to verify JWT signature, if not provided then validation
|
||||
is skipped.
|
||||
:raises JwtDecodeError if decoding JWT fails for any reason.
|
||||
:return: A DecodedJwt object containing the jwt information.
|
||||
"""
|
||||
verify = True if key else False
|
||||
|
||||
try:
|
||||
headers = jwt_lib.get_unverified_header(jwt)
|
||||
|
||||
alg = headers.get("alg")
|
||||
if alg != cls.ALGORITHM:
|
||||
raise ValueError(
|
||||
f"Incorrect decoding algorithm {alg}, "
|
||||
f"expecting {cls.ALGORITHM}."
|
||||
)
|
||||
|
||||
payload = jwt_lib.decode(
|
||||
jwt,
|
||||
key,
|
||||
algorithms=[cls.ALGORITHM],
|
||||
options={
|
||||
"verify_signature": verify,
|
||||
"verify_exp": True,
|
||||
"verify_nbf": True,
|
||||
},
|
||||
)
|
||||
except Exception as e:
|
||||
raise JwtDecodeError(getattr(e, "message", str(e)))
|
||||
|
||||
return cls._from_jwt(headers, payload, key)
|
||||
|
||||
def __str__(self):
|
||||
return "<JWT {}>".format(self.to_jwt())
|
||||
Binary file not shown.
@@ -0,0 +1,81 @@
|
||||
import time
|
||||
|
||||
from twilio.jwt import Jwt
|
||||
|
||||
|
||||
class AccessTokenGrant(object):
|
||||
"""A Grant giving access to a Twilio Resource"""
|
||||
|
||||
@property
|
||||
def key(self):
|
||||
""":rtype str Grant's twilio specific key"""
|
||||
raise NotImplementedError("Grant must have a key property.")
|
||||
|
||||
def to_payload(self):
|
||||
""":return: dict something"""
|
||||
raise NotImplementedError("Grant must implement to_payload.")
|
||||
|
||||
def __str__(self):
|
||||
return "<{} {}>".format(self.__class__.__name__, self.to_payload())
|
||||
|
||||
|
||||
class AccessToken(Jwt):
|
||||
"""Access Token containing one or more AccessTokenGrants used to access Twilio Resources"""
|
||||
|
||||
ALGORITHM = "HS256"
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
account_sid,
|
||||
signing_key_sid,
|
||||
secret,
|
||||
grants=None,
|
||||
identity=None,
|
||||
nbf=Jwt.GENERATE,
|
||||
ttl=3600,
|
||||
valid_until=None,
|
||||
region=None,
|
||||
):
|
||||
grants = grants or []
|
||||
if any(not isinstance(g, AccessTokenGrant) for g in grants):
|
||||
raise ValueError("Grants must be instances of AccessTokenGrant.")
|
||||
|
||||
self.account_sid = account_sid
|
||||
self.signing_key_sid = signing_key_sid
|
||||
self.identity = identity
|
||||
self.region = region
|
||||
self.grants = grants
|
||||
super(AccessToken, self).__init__(
|
||||
secret_key=secret,
|
||||
algorithm=self.ALGORITHM,
|
||||
issuer=signing_key_sid,
|
||||
subject=self.account_sid,
|
||||
nbf=nbf,
|
||||
ttl=ttl,
|
||||
valid_until=valid_until,
|
||||
)
|
||||
|
||||
def add_grant(self, grant):
|
||||
"""Add a grant to this AccessToken"""
|
||||
if not isinstance(grant, AccessTokenGrant):
|
||||
raise ValueError("Grant must be an instance of AccessTokenGrant.")
|
||||
self.grants.append(grant)
|
||||
|
||||
def _generate_headers(self):
|
||||
headers = {"cty": "twilio-fpa;v=1"}
|
||||
if self.region and isinstance(self.region, str):
|
||||
headers["twr"] = self.region
|
||||
return headers
|
||||
|
||||
def _generate_payload(self):
|
||||
now = int(time.time())
|
||||
payload = {
|
||||
"jti": "{}-{}".format(self.signing_key_sid, now),
|
||||
"grants": {grant.key: grant.to_payload() for grant in self.grants},
|
||||
}
|
||||
if self.identity:
|
||||
payload["grants"]["identity"] = self.identity
|
||||
return payload
|
||||
|
||||
def __str__(self):
|
||||
return "<{} {}>".format(self.__class__.__name__, self.to_jwt())
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
@@ -0,0 +1,183 @@
|
||||
from twilio.jwt.access_token import AccessTokenGrant
|
||||
import warnings
|
||||
import functools
|
||||
|
||||
|
||||
def deprecated(func):
|
||||
"""This is a decorator which can be used to mark functions
|
||||
as deprecated. It will result in a warning being emitted
|
||||
when the function is used."""
|
||||
|
||||
@functools.wraps(func)
|
||||
def new_func(*args, **kwargs):
|
||||
warnings.simplefilter("always", DeprecationWarning)
|
||||
warnings.warn(
|
||||
"Call to deprecated function {}.".format(func.__name__),
|
||||
category=DeprecationWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
warnings.simplefilter("default", DeprecationWarning)
|
||||
return func(*args, **kwargs)
|
||||
|
||||
return new_func
|
||||
|
||||
|
||||
class ChatGrant(AccessTokenGrant):
|
||||
"""Grant to access Twilio Chat"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
service_sid=None,
|
||||
endpoint_id=None,
|
||||
deployment_role_sid=None,
|
||||
push_credential_sid=None,
|
||||
):
|
||||
self.service_sid = service_sid
|
||||
self.endpoint_id = endpoint_id
|
||||
self.deployment_role_sid = deployment_role_sid
|
||||
self.push_credential_sid = push_credential_sid
|
||||
|
||||
@property
|
||||
def key(self):
|
||||
return "chat"
|
||||
|
||||
def to_payload(self):
|
||||
grant = {}
|
||||
if self.service_sid:
|
||||
grant["service_sid"] = self.service_sid
|
||||
if self.endpoint_id:
|
||||
grant["endpoint_id"] = self.endpoint_id
|
||||
if self.deployment_role_sid:
|
||||
grant["deployment_role_sid"] = self.deployment_role_sid
|
||||
if self.push_credential_sid:
|
||||
grant["push_credential_sid"] = self.push_credential_sid
|
||||
|
||||
return grant
|
||||
|
||||
|
||||
class SyncGrant(AccessTokenGrant):
|
||||
"""Grant to access Twilio Sync"""
|
||||
|
||||
def __init__(self, service_sid=None, endpoint_id=None):
|
||||
self.service_sid = service_sid
|
||||
self.endpoint_id = endpoint_id
|
||||
|
||||
@property
|
||||
def key(self):
|
||||
return "data_sync"
|
||||
|
||||
def to_payload(self):
|
||||
grant = {}
|
||||
if self.service_sid:
|
||||
grant["service_sid"] = self.service_sid
|
||||
if self.endpoint_id:
|
||||
grant["endpoint_id"] = self.endpoint_id
|
||||
|
||||
return grant
|
||||
|
||||
|
||||
class VoiceGrant(AccessTokenGrant):
|
||||
"""Grant to access Twilio Programmable Voice"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
incoming_allow=None,
|
||||
outgoing_application_sid=None,
|
||||
outgoing_application_params=None,
|
||||
push_credential_sid=None,
|
||||
endpoint_id=None,
|
||||
):
|
||||
self.incoming_allow = incoming_allow
|
||||
""" :type : bool """
|
||||
self.outgoing_application_sid = outgoing_application_sid
|
||||
""" :type : str """
|
||||
self.outgoing_application_params = outgoing_application_params
|
||||
""" :type : dict """
|
||||
self.push_credential_sid = push_credential_sid
|
||||
""" :type : str """
|
||||
self.endpoint_id = endpoint_id
|
||||
""" :type : str """
|
||||
|
||||
@property
|
||||
def key(self):
|
||||
return "voice"
|
||||
|
||||
def to_payload(self):
|
||||
grant = {}
|
||||
if self.incoming_allow is True:
|
||||
grant["incoming"] = {}
|
||||
grant["incoming"]["allow"] = True
|
||||
|
||||
if self.outgoing_application_sid:
|
||||
grant["outgoing"] = {}
|
||||
grant["outgoing"]["application_sid"] = self.outgoing_application_sid
|
||||
|
||||
if self.outgoing_application_params:
|
||||
grant["outgoing"]["params"] = self.outgoing_application_params
|
||||
|
||||
if self.push_credential_sid:
|
||||
grant["push_credential_sid"] = self.push_credential_sid
|
||||
|
||||
if self.endpoint_id:
|
||||
grant["endpoint_id"] = self.endpoint_id
|
||||
|
||||
return grant
|
||||
|
||||
|
||||
class VideoGrant(AccessTokenGrant):
|
||||
"""Grant to access Twilio Video"""
|
||||
|
||||
def __init__(self, room=None):
|
||||
self.room = room
|
||||
|
||||
@property
|
||||
def key(self):
|
||||
return "video"
|
||||
|
||||
def to_payload(self):
|
||||
grant = {}
|
||||
if self.room:
|
||||
grant["room"] = self.room
|
||||
|
||||
return grant
|
||||
|
||||
|
||||
class TaskRouterGrant(AccessTokenGrant):
|
||||
"""Grant to access Twilio TaskRouter"""
|
||||
|
||||
def __init__(self, workspace_sid=None, worker_sid=None, role=None):
|
||||
self.workspace_sid = workspace_sid
|
||||
self.worker_sid = worker_sid
|
||||
self.role = role
|
||||
|
||||
@property
|
||||
def key(self):
|
||||
return "task_router"
|
||||
|
||||
def to_payload(self):
|
||||
grant = {}
|
||||
if self.workspace_sid:
|
||||
grant["workspace_sid"] = self.workspace_sid
|
||||
if self.worker_sid:
|
||||
grant["worker_sid"] = self.worker_sid
|
||||
if self.role:
|
||||
grant["role"] = self.role
|
||||
|
||||
return grant
|
||||
|
||||
|
||||
class PlaybackGrant(AccessTokenGrant):
|
||||
"""Grant to access Twilio Live stream"""
|
||||
|
||||
def __init__(self, grant=None):
|
||||
"""Initialize a PlaybackGrant with a grant retrieved from the Twilio API."""
|
||||
self.grant = grant
|
||||
|
||||
@property
|
||||
def key(self):
|
||||
"""Return the grant's key."""
|
||||
return "player"
|
||||
|
||||
def to_payload(self):
|
||||
"""Return the grant."""
|
||||
return self.grant
|
||||
@@ -0,0 +1,117 @@
|
||||
from twilio.jwt import Jwt
|
||||
|
||||
from urllib.parse import urlencode
|
||||
|
||||
|
||||
class ClientCapabilityToken(Jwt):
|
||||
"""A token to control permissions with Twilio Client"""
|
||||
|
||||
ALGORITHM = "HS256"
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
account_sid,
|
||||
auth_token,
|
||||
nbf=Jwt.GENERATE,
|
||||
ttl=3600,
|
||||
valid_until=None,
|
||||
**kwargs
|
||||
):
|
||||
"""
|
||||
:param str account_sid: The account sid to which this token is granted access.
|
||||
:param str auth_token: The secret key used to sign the token. Note, this auth token is not
|
||||
visible to the user of the token.
|
||||
:param int nbf: Time in secs from epic before which this token is considered invalid.
|
||||
:param int ttl: the amount of time in seconds from generation that this token is valid for.
|
||||
:param kwargs:
|
||||
|
||||
|
||||
:returns: A new CapabilityToken with zero permissions
|
||||
"""
|
||||
super(ClientCapabilityToken, self).__init__(
|
||||
algorithm=self.ALGORITHM,
|
||||
secret_key=auth_token,
|
||||
issuer=account_sid,
|
||||
nbf=nbf,
|
||||
ttl=ttl,
|
||||
valid_until=None,
|
||||
)
|
||||
|
||||
self.account_sid = account_sid
|
||||
self.auth_token = auth_token
|
||||
self.client_name = None
|
||||
self.capabilities = {}
|
||||
|
||||
if "allow_client_outgoing" in kwargs:
|
||||
self.allow_client_outgoing(**kwargs["allow_client_outgoing"])
|
||||
if "allow_client_incoming" in kwargs:
|
||||
self.allow_client_incoming(**kwargs["allow_client_incoming"])
|
||||
if "allow_event_stream" in kwargs:
|
||||
self.allow_event_stream(**kwargs["allow_event_stream"])
|
||||
|
||||
def allow_client_outgoing(self, application_sid, **kwargs):
|
||||
"""
|
||||
Allow the user of this token to make outgoing connections. Keyword arguments are passed
|
||||
to the application.
|
||||
|
||||
:param str application_sid: Application to contact
|
||||
"""
|
||||
scope = ScopeURI("client", "outgoing", {"appSid": application_sid})
|
||||
if kwargs:
|
||||
scope.add_param("appParams", urlencode(kwargs, doseq=True))
|
||||
|
||||
self.capabilities["outgoing"] = scope
|
||||
|
||||
def allow_client_incoming(self, client_name):
|
||||
"""
|
||||
Allow the user of this token to accept incoming connections.
|
||||
|
||||
:param str client_name: Client name to accept calls from
|
||||
"""
|
||||
self.client_name = client_name
|
||||
self.capabilities["incoming"] = ScopeURI(
|
||||
"client", "incoming", {"clientName": client_name}
|
||||
)
|
||||
|
||||
def allow_event_stream(self, **kwargs):
|
||||
"""
|
||||
Allow the user of this token to access their event stream.
|
||||
"""
|
||||
scope = ScopeURI("stream", "subscribe", {"path": "/2010-04-01/Events"})
|
||||
if kwargs:
|
||||
scope.add_param("params", urlencode(kwargs, doseq=True))
|
||||
|
||||
self.capabilities["events"] = scope
|
||||
|
||||
def _generate_payload(self):
|
||||
if "outgoing" in self.capabilities and self.client_name is not None:
|
||||
self.capabilities["outgoing"].add_param("clientName", self.client_name)
|
||||
|
||||
scope_uris = [
|
||||
scope_uri.to_payload() for scope_uri in self.capabilities.values()
|
||||
]
|
||||
return {"scope": " ".join(scope_uris)}
|
||||
|
||||
|
||||
class ScopeURI(object):
|
||||
"""A single capability granted to Twilio Client and scoped to a service"""
|
||||
|
||||
def __init__(self, service, privilege, params=None):
|
||||
self.service = service
|
||||
self.privilege = privilege
|
||||
self.params = params or {}
|
||||
|
||||
def add_param(self, key, value):
|
||||
self.params[key] = value
|
||||
|
||||
def to_payload(self):
|
||||
if self.params:
|
||||
sorted_params = sorted([(k, v) for k, v in self.params.items()])
|
||||
encoded_params = urlencode(sorted_params)
|
||||
param_string = "?{}".format(encoded_params)
|
||||
else:
|
||||
param_string = ""
|
||||
return "scope:{}:{}{}".format(self.service, self.privilege, param_string)
|
||||
|
||||
def __str__(self):
|
||||
return "<ScopeURI {}>".format(self.to_payload())
|
||||
BIN
Binary file not shown.
@@ -0,0 +1,142 @@
|
||||
from twilio.jwt import Jwt
|
||||
|
||||
|
||||
class TaskRouterCapabilityToken(Jwt):
|
||||
VERSION = "v1"
|
||||
DOMAIN = "https://taskrouter.twilio.com"
|
||||
EVENTS_BASE_URL = "https://event-bridge.twilio.com/v1/wschannels"
|
||||
ALGORITHM = "HS256"
|
||||
|
||||
def __init__(self, account_sid, auth_token, workspace_sid, channel_id, **kwargs):
|
||||
"""
|
||||
:param str account_sid: Twilio account sid
|
||||
:param str auth_token: Twilio auth token used to sign the JWT
|
||||
:param str workspace_sid: TaskRouter workspace sid
|
||||
:param str channel_id: TaskRouter channel sid
|
||||
:param kwargs:
|
||||
:param bool allow_web_sockets: shortcut to calling allow_web_sockets, defaults to True
|
||||
:param bool allow_fetch_self: shortcut to calling allow_fetch_self, defaults to True
|
||||
:param bool allow_update_self: shortcut to calling allow_update_self, defaults to False
|
||||
:param bool allow_delete_self: shortcut to calling allow_delete_self, defaults to False
|
||||
:param bool allow_fetch_subresources: shortcut to calling allow_fetch_subresources,
|
||||
defaults to False
|
||||
:param bool allow_update_subresources: shortcut to calling allow_update_subresources,
|
||||
defaults to False
|
||||
:param bool allow_delete_subresources: shortcut to calling allow_delete_subresources,
|
||||
defaults to False
|
||||
:returns a new TaskRouterCapabilityToken with capabilities set depending on kwargs.
|
||||
"""
|
||||
super(TaskRouterCapabilityToken, self).__init__(
|
||||
secret_key=auth_token,
|
||||
issuer=account_sid,
|
||||
algorithm=self.ALGORITHM,
|
||||
nbf=kwargs.get("nbf", Jwt.GENERATE),
|
||||
ttl=kwargs.get("ttl", 3600),
|
||||
valid_until=kwargs.get("valid_until", None),
|
||||
)
|
||||
|
||||
self._validate_inputs(account_sid, workspace_sid, channel_id)
|
||||
|
||||
self.account_sid = account_sid
|
||||
self.auth_token = auth_token
|
||||
self.workspace_sid = workspace_sid
|
||||
self.channel_id = channel_id
|
||||
self.policies = []
|
||||
|
||||
if kwargs.get("allow_web_sockets", True):
|
||||
self.allow_web_sockets()
|
||||
if kwargs.get("allow_fetch_self", True):
|
||||
self.allow_fetch_self()
|
||||
if kwargs.get("allow_update_self", False):
|
||||
self.allow_update_self()
|
||||
if kwargs.get("allow_delete_self", False):
|
||||
self.allow_delete_self()
|
||||
if kwargs.get("allow_fetch_subresources", False):
|
||||
self.allow_fetch_subresources()
|
||||
if kwargs.get("allow_delete_subresources", False):
|
||||
self.allow_delete_subresources()
|
||||
if kwargs.get("allow_update_subresources", False):
|
||||
self.allow_update_subresources()
|
||||
|
||||
@property
|
||||
def workspace_url(self):
|
||||
return "{}/{}/Workspaces/{}".format(
|
||||
self.DOMAIN, self.VERSION, self.workspace_sid
|
||||
)
|
||||
|
||||
@property
|
||||
def resource_url(self):
|
||||
raise NotImplementedError("Subclass must set its specific resource_url.")
|
||||
|
||||
@property
|
||||
def channel_prefix(self):
|
||||
raise NotImplementedError(
|
||||
"Subclass must set its specific channel_id sid prefix."
|
||||
)
|
||||
|
||||
def allow_fetch_self(self):
|
||||
self._make_policy(self.resource_url, "GET", True)
|
||||
|
||||
def allow_update_self(self):
|
||||
self._make_policy(self.resource_url, "POST", True)
|
||||
|
||||
def allow_delete_self(self):
|
||||
self._make_policy(self.resource_url, "DELETE", True)
|
||||
|
||||
def allow_fetch_subresources(self):
|
||||
self._make_policy(self.resource_url + "/**", "GET", True)
|
||||
|
||||
def allow_update_subresources(self):
|
||||
self._make_policy(self.resource_url + "/**", "POST", True)
|
||||
|
||||
def allow_delete_subresources(self):
|
||||
self._make_policy(self.resource_url + "/**", "DELETE", True)
|
||||
|
||||
def allow_web_sockets(self, channel_id=None):
|
||||
channel_id = channel_id or self.channel_id
|
||||
web_socket_url = "{}/{}/{}".format(
|
||||
self.EVENTS_BASE_URL, self.account_sid, channel_id
|
||||
)
|
||||
self._make_policy(web_socket_url, "GET", True)
|
||||
self._make_policy(web_socket_url, "POST", True)
|
||||
|
||||
def _generate_payload(self):
|
||||
payload = {
|
||||
"account_sid": self.account_sid,
|
||||
"workspace_sid": self.workspace_sid,
|
||||
"channel": self.channel_id,
|
||||
"version": self.VERSION,
|
||||
"friendly_name": self.channel_id,
|
||||
"policies": self.policies,
|
||||
}
|
||||
|
||||
if self.channel_id.startswith("WK"):
|
||||
payload["worker_sid"] = self.channel_id
|
||||
elif self.channel_id.startswith("WQ"):
|
||||
payload["taskqueue_sid"] = self.channel_id
|
||||
|
||||
return payload
|
||||
|
||||
def _make_policy(self, url, method, allowed, query_filter=None, post_filter=None):
|
||||
self.policies.append(
|
||||
{
|
||||
"url": url,
|
||||
"method": method.upper(),
|
||||
"allow": allowed,
|
||||
"query_filter": query_filter or {},
|
||||
"post_filter": post_filter or {},
|
||||
}
|
||||
)
|
||||
|
||||
def _validate_inputs(self, account_sid, workspace_sid, channel_id):
|
||||
if not account_sid or not account_sid.startswith("AC"):
|
||||
raise ValueError("Invalid account sid provided {}".format(account_sid))
|
||||
|
||||
if not workspace_sid or not workspace_sid.startswith("WS"):
|
||||
raise ValueError("Invalid workspace sid provided {}".format(workspace_sid))
|
||||
|
||||
if not channel_id or not channel_id.startswith(self.channel_prefix):
|
||||
raise ValueError("Invalid channel id provided {}".format(channel_id))
|
||||
|
||||
def __str__(self):
|
||||
return "<TaskRouterCapabilityToken {}>".format(self.to_jwt())
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
@@ -0,0 +1,116 @@
|
||||
from twilio.jwt.taskrouter import TaskRouterCapabilityToken
|
||||
|
||||
|
||||
class WorkerCapabilityToken(TaskRouterCapabilityToken):
|
||||
def __init__(
|
||||
self, account_sid, auth_token, workspace_sid, worker_sid, ttl=3600, **kwargs
|
||||
):
|
||||
"""
|
||||
:param kwargs:
|
||||
All kwarg parameters supported by TaskRouterCapabilityToken
|
||||
:param bool allow_fetch_activities: shortcut to calling allow_fetch_activities,
|
||||
defaults to True
|
||||
:param bool allow_fetch_reservations: shortcut to calling allow_fetch_reservations,
|
||||
defaults to True
|
||||
:param bool allow_fetch_worker_reservations: shortcut to calling allow_fetch_worker_reservations,
|
||||
defaults to True
|
||||
:param bool allow_update_activities: shortcut to calling allow_update_activities,
|
||||
defaults to False
|
||||
:param bool allow_update_reservations: shortcut to calling allow_update_reservations,
|
||||
defaults to False
|
||||
"""
|
||||
super(WorkerCapabilityToken, self).__init__(
|
||||
account_sid=account_sid,
|
||||
auth_token=auth_token,
|
||||
workspace_sid=workspace_sid,
|
||||
channel_id=worker_sid,
|
||||
ttl=ttl,
|
||||
**kwargs
|
||||
)
|
||||
|
||||
if kwargs.get("allow_fetch_activities", True):
|
||||
self.allow_fetch_activities()
|
||||
if kwargs.get("allow_fetch_reservations", True):
|
||||
self.allow_fetch_reservations()
|
||||
if kwargs.get("allow_fetch_worker_reservations", True):
|
||||
self.allow_fetch_worker_reservations()
|
||||
if kwargs.get("allow_update_activities", False):
|
||||
self.allow_update_activities()
|
||||
if kwargs.get("allow_update_reservations", False):
|
||||
self.allow_update_reservations()
|
||||
|
||||
@property
|
||||
def resource_url(self):
|
||||
return "{}/Workers/{}".format(self.workspace_url, self.channel_id)
|
||||
|
||||
@property
|
||||
def channel_prefix(self):
|
||||
return "WK"
|
||||
|
||||
def allow_fetch_activities(self):
|
||||
self._make_policy(self.workspace_url + "/Activities", "GET", True)
|
||||
|
||||
def allow_fetch_reservations(self):
|
||||
self._make_policy(self.workspace_url + "/Tasks/**", "GET", True)
|
||||
|
||||
def allow_fetch_worker_reservations(self):
|
||||
self._make_policy(self.resource_url + "/Reservations/**", "GET", True)
|
||||
|
||||
def allow_update_activities(self):
|
||||
post_filter = {"ActivitySid": {"required": True}}
|
||||
self._make_policy(self.resource_url, "POST", True, post_filter=post_filter)
|
||||
|
||||
def allow_update_reservations(self):
|
||||
self._make_policy(self.workspace_url + "/Tasks/**", "POST", True)
|
||||
self._make_policy(self.resource_url + "/Reservations/**", "POST", True)
|
||||
|
||||
def __str__(self):
|
||||
return "<WorkerCapabilityToken {}>".format(self.to_jwt())
|
||||
|
||||
|
||||
class TaskQueueCapabilityToken(TaskRouterCapabilityToken):
|
||||
def __init__(
|
||||
self, account_sid, auth_token, workspace_sid, task_queue_sid, ttl=3600, **kwargs
|
||||
):
|
||||
super(TaskQueueCapabilityToken, self).__init__(
|
||||
account_sid=account_sid,
|
||||
auth_token=auth_token,
|
||||
workspace_sid=workspace_sid,
|
||||
channel_id=task_queue_sid,
|
||||
ttl=ttl,
|
||||
**kwargs
|
||||
)
|
||||
|
||||
@property
|
||||
def resource_url(self):
|
||||
return "{}/TaskQueues/{}".format(self.workspace_url, self.channel_id)
|
||||
|
||||
@property
|
||||
def channel_prefix(self):
|
||||
return "WQ"
|
||||
|
||||
def __str__(self):
|
||||
return "<TaskQueueCapabilityToken {}>".format(self.to_jwt())
|
||||
|
||||
|
||||
class WorkspaceCapabilityToken(TaskRouterCapabilityToken):
|
||||
def __init__(self, account_sid, auth_token, workspace_sid, ttl=3600, **kwargs):
|
||||
super(WorkspaceCapabilityToken, self).__init__(
|
||||
account_sid=account_sid,
|
||||
auth_token=auth_token,
|
||||
workspace_sid=workspace_sid,
|
||||
channel_id=workspace_sid,
|
||||
ttl=ttl,
|
||||
**kwargs
|
||||
)
|
||||
|
||||
@property
|
||||
def resource_url(self):
|
||||
return self.workspace_url
|
||||
|
||||
@property
|
||||
def channel_prefix(self):
|
||||
return "WS"
|
||||
|
||||
def __str__(self):
|
||||
return "<WorkspaceCapabilityToken {}>".format(self.to_jwt())
|
||||
@@ -0,0 +1,92 @@
|
||||
from hashlib import sha256
|
||||
|
||||
from twilio.jwt import Jwt
|
||||
|
||||
|
||||
class ClientValidationJwt(Jwt):
|
||||
"""A JWT included on requests so that Twilio can verify request authenticity"""
|
||||
|
||||
__CTY = "twilio-pkrv;v=1"
|
||||
ALGORITHM = "RS256"
|
||||
|
||||
def __init__(
|
||||
self, account_sid, api_key_sid, credential_sid, private_key, validation_payload
|
||||
):
|
||||
"""
|
||||
Create a new ClientValidationJwt
|
||||
:param str account_sid: A Twilio Account Sid starting with 'AC'
|
||||
:param str api_key_sid: A Twilio API Key Sid starting with 'SK'
|
||||
:param str credential_sid: A Credential Sid starting with 'CR',
|
||||
public key Twilio will use to verify the JWT.
|
||||
:param str private_key: The private key used to sign the JWT.
|
||||
:param ValidationPayload validation_payload: information from the request to sign
|
||||
"""
|
||||
super(ClientValidationJwt, self).__init__(
|
||||
secret_key=private_key,
|
||||
issuer=api_key_sid,
|
||||
subject=account_sid,
|
||||
algorithm=self.ALGORITHM,
|
||||
ttl=300, # 5 minute ttl
|
||||
)
|
||||
self.credential_sid = credential_sid
|
||||
self.validation_payload = validation_payload
|
||||
|
||||
def _generate_headers(self):
|
||||
return {"cty": ClientValidationJwt.__CTY, "kid": self.credential_sid}
|
||||
|
||||
def _generate_payload(self):
|
||||
# Lowercase header keys, combine and sort headers with list values
|
||||
all_headers = {
|
||||
k.lower(): self._sort_and_join(v, ",")
|
||||
for k, v in self.validation_payload.all_headers.items()
|
||||
}
|
||||
# Names of headers we are signing in the jwt
|
||||
signed_headers = sorted(self.validation_payload.signed_headers)
|
||||
|
||||
# Stringify headers, only include headers in signed_headers
|
||||
headers_str = [
|
||||
"{}:{}".format(h, all_headers[h])
|
||||
for h in signed_headers
|
||||
if h in all_headers
|
||||
]
|
||||
headers_str = "\n".join(headers_str)
|
||||
|
||||
# Sort query string parameters
|
||||
query_string = self.validation_payload.query_string.split("&")
|
||||
query_string = self._sort_and_join(query_string, "&")
|
||||
|
||||
req_body_hash = self._hash(self.validation_payload.body) or ""
|
||||
|
||||
signed_headers_str = ";".join(signed_headers)
|
||||
|
||||
signed_payload = [
|
||||
self.validation_payload.method,
|
||||
self.validation_payload.path,
|
||||
query_string,
|
||||
]
|
||||
|
||||
if headers_str:
|
||||
signed_payload.append(headers_str)
|
||||
signed_payload.append("")
|
||||
signed_payload.append(signed_headers_str)
|
||||
signed_payload.append(req_body_hash)
|
||||
|
||||
signed_payload = "\n".join(signed_payload)
|
||||
|
||||
return {"hrh": signed_headers_str, "rqh": self._hash(signed_payload)}
|
||||
|
||||
@classmethod
|
||||
def _sort_and_join(cls, values, joiner):
|
||||
if isinstance(values, str):
|
||||
return values
|
||||
return joiner.join(sorted(values))
|
||||
|
||||
@classmethod
|
||||
def _hash(cls, input_str):
|
||||
if not input_str:
|
||||
return input_str
|
||||
|
||||
if not isinstance(input_str, bytes):
|
||||
input_str = input_str.encode("utf-8")
|
||||
|
||||
return sha256(input_str).hexdigest()
|
||||
BIN
Binary file not shown.
@@ -0,0 +1,137 @@
|
||||
import base64
|
||||
import hmac
|
||||
from hashlib import sha1, sha256
|
||||
|
||||
from urllib.parse import urlparse, parse_qs
|
||||
|
||||
|
||||
def compare(string1, string2):
|
||||
"""Compare two strings while protecting against timing attacks
|
||||
|
||||
:param str string1: the first string
|
||||
:param str string2: the second string
|
||||
|
||||
:returns: True if the strings are equal, False if not
|
||||
:rtype: :obj:`bool`
|
||||
"""
|
||||
if len(string1) != len(string2):
|
||||
return False
|
||||
result = True
|
||||
for c1, c2 in zip(string1, string2):
|
||||
result &= c1 == c2
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def remove_port(uri):
|
||||
"""Remove the port number from a URI
|
||||
|
||||
:param uri: parsed URI that Twilio requested on your server
|
||||
|
||||
:returns: full URI without a port number
|
||||
:rtype: str
|
||||
"""
|
||||
if not uri.port:
|
||||
return uri.geturl()
|
||||
|
||||
new_netloc = uri.netloc.split(":")[0]
|
||||
new_uri = uri._replace(netloc=new_netloc)
|
||||
|
||||
return new_uri.geturl()
|
||||
|
||||
|
||||
def add_port(uri):
|
||||
"""Add the port number to a URI
|
||||
|
||||
:param uri: parsed URI that Twilio requested on your server
|
||||
|
||||
:returns: full URI with a port number
|
||||
:rtype: str
|
||||
"""
|
||||
if uri.port:
|
||||
return uri.geturl()
|
||||
|
||||
port = 443 if uri.scheme == "https" else 80
|
||||
new_netloc = uri.netloc + ":" + str(port)
|
||||
new_uri = uri._replace(netloc=new_netloc)
|
||||
|
||||
return new_uri.geturl()
|
||||
|
||||
|
||||
class RequestValidator(object):
|
||||
def __init__(self, token):
|
||||
self.token = token.encode("utf-8")
|
||||
|
||||
def compute_signature(self, uri, params):
|
||||
"""Compute the signature for a given request
|
||||
|
||||
:param uri: full URI that Twilio requested on your server
|
||||
:param params: post vars that Twilio sent with the request
|
||||
|
||||
:returns: The computed signature
|
||||
"""
|
||||
s = uri
|
||||
if params:
|
||||
for param_name in sorted(set(params)):
|
||||
values = self.get_values(params, param_name)
|
||||
|
||||
for value in sorted(set(values)):
|
||||
s += param_name + value
|
||||
|
||||
# compute signature and compare signatures
|
||||
mac = hmac.new(self.token, s.encode("utf-8"), sha1)
|
||||
computed = base64.b64encode(mac.digest())
|
||||
computed = computed.decode("utf-8")
|
||||
|
||||
return computed.strip()
|
||||
|
||||
def get_values(self, param_dict, param_name):
|
||||
try:
|
||||
# Support MultiDict used by Flask.
|
||||
return param_dict.getall(param_name)
|
||||
except AttributeError:
|
||||
try:
|
||||
# Support QueryDict used by Django.
|
||||
return param_dict.getlist(param_name)
|
||||
except AttributeError:
|
||||
# Fallback to a standard dict.
|
||||
return [param_dict[param_name]]
|
||||
|
||||
def compute_hash(self, body):
|
||||
computed = sha256(body.encode("utf-8")).hexdigest()
|
||||
|
||||
return computed.strip()
|
||||
|
||||
def validate(self, uri, params, signature):
|
||||
"""Validate a request from Twilio
|
||||
|
||||
:param uri: full URI that Twilio requested on your server
|
||||
:param params: dictionary of POST variables or string of POST body for JSON requests
|
||||
:param signature: expected signature in HTTP X-Twilio-Signature header
|
||||
|
||||
:returns: True if the request passes validation, False if not
|
||||
"""
|
||||
if params is None:
|
||||
params = {}
|
||||
|
||||
parsed_uri = urlparse(uri)
|
||||
uri_with_port = add_port(parsed_uri)
|
||||
uri_without_port = remove_port(parsed_uri)
|
||||
|
||||
valid_body_hash = True # May not receive body hash, so default succeed
|
||||
|
||||
query = parse_qs(parsed_uri.query)
|
||||
if "bodySHA256" in query and isinstance(params, str):
|
||||
valid_body_hash = compare(self.compute_hash(params), query["bodySHA256"][0])
|
||||
params = {}
|
||||
|
||||
# check signature of uri with and without port,
|
||||
# since sig generation on back end is inconsistent
|
||||
valid_signature = compare(
|
||||
self.compute_signature(uri_without_port, params), signature
|
||||
)
|
||||
valid_signature_with_port = compare(
|
||||
self.compute_signature(uri_with_port, params), signature
|
||||
)
|
||||
|
||||
return valid_body_hash and (valid_signature or valid_signature_with_port)
|
||||
@@ -0,0 +1,724 @@
|
||||
r"""
|
||||
This code was generated by
|
||||
___ _ _ _ _ _ _ ____ ____ ____ _ ____ ____ _ _ ____ ____ ____ ___ __ __
|
||||
| | | | | | | | | __ | | |__| | __ | __ |___ |\ | |___ |__/ |__| | | | |__/
|
||||
| |_|_| | |___ | |__| |__| | | | |__] |___ | \| |___ | \ | | | |__| | \
|
||||
|
||||
NOTE: This class is auto generated by OpenAPI Generator.
|
||||
https://openapi-generator.tech
|
||||
Do not edit the class manually.
|
||||
"""
|
||||
from typing import TYPE_CHECKING, Optional
|
||||
|
||||
from twilio.base.client_base import ClientBase
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from twilio.rest.accounts import Accounts
|
||||
from twilio.rest.api import Api
|
||||
from twilio.rest.autopilot import Autopilot
|
||||
from twilio.rest.bulkexports import Bulkexports
|
||||
from twilio.rest.chat import Chat
|
||||
from twilio.rest.content import Content
|
||||
from twilio.rest.conversations import Conversations
|
||||
from twilio.rest.events import Events
|
||||
from twilio.rest.flex_api import FlexApi
|
||||
from twilio.rest.frontline_api import FrontlineApi
|
||||
from twilio.rest.insights import Insights
|
||||
from twilio.rest.intelligence import Intelligence
|
||||
from twilio.rest.ip_messaging import IpMessaging
|
||||
from twilio.rest.lookups import Lookups
|
||||
from twilio.rest.media import Media
|
||||
from twilio.rest.messaging import Messaging
|
||||
from twilio.rest.microvisor import Microvisor
|
||||
from twilio.rest.monitor import Monitor
|
||||
from twilio.rest.notify import Notify
|
||||
from twilio.rest.numbers import Numbers
|
||||
from twilio.rest.oauth import Oauth
|
||||
from twilio.rest.preview import Preview
|
||||
from twilio.rest.pricing import Pricing
|
||||
from twilio.rest.proxy import Proxy
|
||||
from twilio.rest.routes import Routes
|
||||
from twilio.rest.serverless import Serverless
|
||||
from twilio.rest.studio import Studio
|
||||
from twilio.rest.supersim import Supersim
|
||||
from twilio.rest.sync import Sync
|
||||
from twilio.rest.taskrouter import Taskrouter
|
||||
from twilio.rest.trunking import Trunking
|
||||
from twilio.rest.trusthub import Trusthub
|
||||
from twilio.rest.verify import Verify
|
||||
from twilio.rest.video import Video
|
||||
from twilio.rest.voice import Voice
|
||||
from twilio.rest.wireless import Wireless
|
||||
from twilio.rest.api.v2010.account.address import AddressList
|
||||
from twilio.rest.api.v2010.account.application import ApplicationList
|
||||
from twilio.rest.api.v2010.account.authorized_connect_app import (
|
||||
AuthorizedConnectAppList,
|
||||
)
|
||||
from twilio.rest.api.v2010.account.available_phone_number_country import (
|
||||
AvailablePhoneNumberCountryList,
|
||||
)
|
||||
from twilio.rest.api.v2010.account.balance import BalanceList
|
||||
from twilio.rest.api.v2010.account.call import CallList
|
||||
from twilio.rest.api.v2010.account.conference import ConferenceList
|
||||
from twilio.rest.api.v2010.account.connect_app import ConnectAppList
|
||||
from twilio.rest.api.v2010.account.incoming_phone_number import (
|
||||
IncomingPhoneNumberList,
|
||||
)
|
||||
from twilio.rest.api.v2010.account.key import KeyList
|
||||
from twilio.rest.api.v2010.account.new_key import NewKeyList
|
||||
from twilio.rest.api.v2010.account.message import MessageList
|
||||
from twilio.rest.api.v2010.account.signing_key import SigningKeyList
|
||||
from twilio.rest.api.v2010.account.new_signing_key import NewSigningKeyList
|
||||
from twilio.rest.api.v2010.account.notification import NotificationList
|
||||
from twilio.rest.api.v2010.account.outgoing_caller_id import OutgoingCallerIdList
|
||||
from twilio.rest.api.v2010.account.validation_request import ValidationRequestList
|
||||
from twilio.rest.api.v2010.account.queue import QueueList
|
||||
from twilio.rest.api.v2010.account.recording import RecordingList
|
||||
from twilio.rest.api.v2010.account.short_code import ShortCodeList
|
||||
from twilio.rest.api.v2010.account.sip import SipList
|
||||
from twilio.rest.api.v2010.account.token import TokenList
|
||||
from twilio.rest.api.v2010.account.transcription import TranscriptionList
|
||||
from twilio.rest.api.v2010.account.usage import UsageList
|
||||
|
||||
|
||||
class Client(ClientBase):
|
||||
"""A client for accessing the Twilio API."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
username=None,
|
||||
password=None,
|
||||
account_sid=None,
|
||||
region=None,
|
||||
http_client=None,
|
||||
environment=None,
|
||||
edge=None,
|
||||
user_agent_extensions=None,
|
||||
):
|
||||
"""
|
||||
Initializes the Twilio Client
|
||||
|
||||
:param str username: Username to authenticate with, either account_sid or api_key
|
||||
:param str password: Password to authenticate with, auth_token (if using account_sid) or api_secret (if using api_key)
|
||||
:param str account_sid: Account SID, required if using api_key to authenticate.
|
||||
:param str region: Twilio Region to make requests to, defaults to 'us1' if an edge is provided
|
||||
:param HttpClient http_client: HttpClient, defaults to TwilioHttpClient
|
||||
:param dict environment: Environment to look for auth details, defaults to os.environ
|
||||
:param str edge: Twilio Edge to make requests to, defaults to None
|
||||
:param list[str] user_agent_extensions: Additions to the user agent string
|
||||
|
||||
:returns: Twilio Client
|
||||
:rtype: twilio.rest.Client
|
||||
"""
|
||||
super().__init__(
|
||||
username,
|
||||
password,
|
||||
account_sid,
|
||||
region,
|
||||
http_client,
|
||||
environment,
|
||||
edge,
|
||||
user_agent_extensions,
|
||||
)
|
||||
|
||||
# Domains
|
||||
self._accounts: Optional["Accounts"] = None
|
||||
self._api: Optional["Api"] = None
|
||||
self._autopilot: Optional["Autopilot"] = None
|
||||
self._bulkexports: Optional["Bulkexports"] = None
|
||||
self._chat: Optional["Chat"] = None
|
||||
self._content: Optional["Content"] = None
|
||||
self._conversations: Optional["Conversations"] = None
|
||||
self._events: Optional["Events"] = None
|
||||
self._flex_api: Optional["FlexApi"] = None
|
||||
self._frontline_api: Optional["FrontlineApi"] = None
|
||||
self._insights: Optional["Insights"] = None
|
||||
self._intelligence: Optional["Intelligence"] = None
|
||||
self._ip_messaging: Optional["IpMessaging"] = None
|
||||
self._lookups: Optional["Lookups"] = None
|
||||
self._media: Optional["Media"] = None
|
||||
self._messaging: Optional["Messaging"] = None
|
||||
self._microvisor: Optional["Microvisor"] = None
|
||||
self._monitor: Optional["Monitor"] = None
|
||||
self._notify: Optional["Notify"] = None
|
||||
self._numbers: Optional["Numbers"] = None
|
||||
self._oauth: Optional["Oauth"] = None
|
||||
self._preview: Optional["Preview"] = None
|
||||
self._pricing: Optional["Pricing"] = None
|
||||
self._proxy: Optional["Proxy"] = None
|
||||
self._routes: Optional["Routes"] = None
|
||||
self._serverless: Optional["Serverless"] = None
|
||||
self._studio: Optional["Studio"] = None
|
||||
self._supersim: Optional["Supersim"] = None
|
||||
self._sync: Optional["Sync"] = None
|
||||
self._taskrouter: Optional["Taskrouter"] = None
|
||||
self._trunking: Optional["Trunking"] = None
|
||||
self._trusthub: Optional["Trusthub"] = None
|
||||
self._verify: Optional["Verify"] = None
|
||||
self._video: Optional["Video"] = None
|
||||
self._voice: Optional["Voice"] = None
|
||||
self._wireless: Optional["Wireless"] = None
|
||||
|
||||
@property
|
||||
def accounts(self) -> "Accounts":
|
||||
"""
|
||||
Access the Accounts Twilio Domain
|
||||
|
||||
:returns: Accounts Twilio Domain
|
||||
"""
|
||||
if self._accounts is None:
|
||||
from twilio.rest.accounts import Accounts
|
||||
|
||||
self._accounts = Accounts(self)
|
||||
return self._accounts
|
||||
|
||||
@property
|
||||
def api(self) -> "Api":
|
||||
"""
|
||||
Access the Api Twilio Domain
|
||||
|
||||
:returns: Api Twilio Domain
|
||||
"""
|
||||
if self._api is None:
|
||||
from twilio.rest.api import Api
|
||||
|
||||
self._api = Api(self)
|
||||
return self._api
|
||||
|
||||
@property
|
||||
def autopilot(self) -> "Autopilot":
|
||||
"""
|
||||
Access the Autopilot Twilio Domain
|
||||
|
||||
:returns: Autopilot Twilio Domain
|
||||
"""
|
||||
if self._autopilot is None:
|
||||
from twilio.rest.autopilot import Autopilot
|
||||
|
||||
self._autopilot = Autopilot(self)
|
||||
return self._autopilot
|
||||
|
||||
@property
|
||||
def bulkexports(self) -> "Bulkexports":
|
||||
"""
|
||||
Access the Bulkexports Twilio Domain
|
||||
|
||||
:returns: Bulkexports Twilio Domain
|
||||
"""
|
||||
if self._bulkexports is None:
|
||||
from twilio.rest.bulkexports import Bulkexports
|
||||
|
||||
self._bulkexports = Bulkexports(self)
|
||||
return self._bulkexports
|
||||
|
||||
@property
|
||||
def chat(self) -> "Chat":
|
||||
"""
|
||||
Access the Chat Twilio Domain
|
||||
|
||||
:returns: Chat Twilio Domain
|
||||
"""
|
||||
if self._chat is None:
|
||||
from twilio.rest.chat import Chat
|
||||
|
||||
self._chat = Chat(self)
|
||||
return self._chat
|
||||
|
||||
@property
|
||||
def content(self) -> "Content":
|
||||
"""
|
||||
Access the Content Twilio Domain
|
||||
|
||||
:returns: Content Twilio Domain
|
||||
"""
|
||||
if self._content is None:
|
||||
from twilio.rest.content import Content
|
||||
|
||||
self._content = Content(self)
|
||||
return self._content
|
||||
|
||||
@property
|
||||
def conversations(self) -> "Conversations":
|
||||
"""
|
||||
Access the Conversations Twilio Domain
|
||||
|
||||
:returns: Conversations Twilio Domain
|
||||
"""
|
||||
if self._conversations is None:
|
||||
from twilio.rest.conversations import Conversations
|
||||
|
||||
self._conversations = Conversations(self)
|
||||
return self._conversations
|
||||
|
||||
@property
|
||||
def events(self) -> "Events":
|
||||
"""
|
||||
Access the Events Twilio Domain
|
||||
|
||||
:returns: Events Twilio Domain
|
||||
"""
|
||||
if self._events is None:
|
||||
from twilio.rest.events import Events
|
||||
|
||||
self._events = Events(self)
|
||||
return self._events
|
||||
|
||||
@property
|
||||
def flex_api(self) -> "FlexApi":
|
||||
"""
|
||||
Access the FlexApi Twilio Domain
|
||||
|
||||
:returns: FlexApi Twilio Domain
|
||||
"""
|
||||
if self._flex_api is None:
|
||||
from twilio.rest.flex_api import FlexApi
|
||||
|
||||
self._flex_api = FlexApi(self)
|
||||
return self._flex_api
|
||||
|
||||
@property
|
||||
def frontline_api(self) -> "FrontlineApi":
|
||||
"""
|
||||
Access the FrontlineApi Twilio Domain
|
||||
|
||||
:returns: FrontlineApi Twilio Domain
|
||||
"""
|
||||
if self._frontline_api is None:
|
||||
from twilio.rest.frontline_api import FrontlineApi
|
||||
|
||||
self._frontline_api = FrontlineApi(self)
|
||||
return self._frontline_api
|
||||
|
||||
@property
|
||||
def insights(self) -> "Insights":
|
||||
"""
|
||||
Access the Insights Twilio Domain
|
||||
|
||||
:returns: Insights Twilio Domain
|
||||
"""
|
||||
if self._insights is None:
|
||||
from twilio.rest.insights import Insights
|
||||
|
||||
self._insights = Insights(self)
|
||||
return self._insights
|
||||
|
||||
@property
|
||||
def intelligence(self) -> "Intelligence":
|
||||
"""
|
||||
Access the Intelligence Twilio Domain
|
||||
|
||||
:returns: Intelligence Twilio Domain
|
||||
"""
|
||||
if self._intelligence is None:
|
||||
from twilio.rest.intelligence import Intelligence
|
||||
|
||||
self._intelligence = Intelligence(self)
|
||||
return self._intelligence
|
||||
|
||||
@property
|
||||
def ip_messaging(self) -> "IpMessaging":
|
||||
"""
|
||||
Access the IpMessaging Twilio Domain
|
||||
|
||||
:returns: IpMessaging Twilio Domain
|
||||
"""
|
||||
if self._ip_messaging is None:
|
||||
from twilio.rest.ip_messaging import IpMessaging
|
||||
|
||||
self._ip_messaging = IpMessaging(self)
|
||||
return self._ip_messaging
|
||||
|
||||
@property
|
||||
def lookups(self) -> "Lookups":
|
||||
"""
|
||||
Access the Lookups Twilio Domain
|
||||
|
||||
:returns: Lookups Twilio Domain
|
||||
"""
|
||||
if self._lookups is None:
|
||||
from twilio.rest.lookups import Lookups
|
||||
|
||||
self._lookups = Lookups(self)
|
||||
return self._lookups
|
||||
|
||||
@property
|
||||
def media(self) -> "Media":
|
||||
"""
|
||||
Access the Media Twilio Domain
|
||||
|
||||
:returns: Media Twilio Domain
|
||||
"""
|
||||
if self._media is None:
|
||||
from twilio.rest.media import Media
|
||||
|
||||
self._media = Media(self)
|
||||
return self._media
|
||||
|
||||
@property
|
||||
def messaging(self) -> "Messaging":
|
||||
"""
|
||||
Access the Messaging Twilio Domain
|
||||
|
||||
:returns: Messaging Twilio Domain
|
||||
"""
|
||||
if self._messaging is None:
|
||||
from twilio.rest.messaging import Messaging
|
||||
|
||||
self._messaging = Messaging(self)
|
||||
return self._messaging
|
||||
|
||||
@property
|
||||
def microvisor(self) -> "Microvisor":
|
||||
"""
|
||||
Access the Microvisor Twilio Domain
|
||||
|
||||
:returns: Microvisor Twilio Domain
|
||||
"""
|
||||
if self._microvisor is None:
|
||||
from twilio.rest.microvisor import Microvisor
|
||||
|
||||
self._microvisor = Microvisor(self)
|
||||
return self._microvisor
|
||||
|
||||
@property
|
||||
def monitor(self) -> "Monitor":
|
||||
"""
|
||||
Access the Monitor Twilio Domain
|
||||
|
||||
:returns: Monitor Twilio Domain
|
||||
"""
|
||||
if self._monitor is None:
|
||||
from twilio.rest.monitor import Monitor
|
||||
|
||||
self._monitor = Monitor(self)
|
||||
return self._monitor
|
||||
|
||||
@property
|
||||
def notify(self) -> "Notify":
|
||||
"""
|
||||
Access the Notify Twilio Domain
|
||||
|
||||
:returns: Notify Twilio Domain
|
||||
"""
|
||||
if self._notify is None:
|
||||
from twilio.rest.notify import Notify
|
||||
|
||||
self._notify = Notify(self)
|
||||
return self._notify
|
||||
|
||||
@property
|
||||
def numbers(self) -> "Numbers":
|
||||
"""
|
||||
Access the Numbers Twilio Domain
|
||||
|
||||
:returns: Numbers Twilio Domain
|
||||
"""
|
||||
if self._numbers is None:
|
||||
from twilio.rest.numbers import Numbers
|
||||
|
||||
self._numbers = Numbers(self)
|
||||
return self._numbers
|
||||
|
||||
@property
|
||||
def oauth(self) -> "Oauth":
|
||||
"""
|
||||
Access the Oauth Twilio Domain
|
||||
|
||||
:returns: Oauth Twilio Domain
|
||||
"""
|
||||
if self._oauth is None:
|
||||
from twilio.rest.oauth import Oauth
|
||||
|
||||
self._oauth = Oauth(self)
|
||||
return self._oauth
|
||||
|
||||
@property
|
||||
def preview(self) -> "Preview":
|
||||
"""
|
||||
Access the Preview Twilio Domain
|
||||
|
||||
:returns: Preview Twilio Domain
|
||||
"""
|
||||
if self._preview is None:
|
||||
from twilio.rest.preview import Preview
|
||||
|
||||
self._preview = Preview(self)
|
||||
return self._preview
|
||||
|
||||
@property
|
||||
def pricing(self) -> "Pricing":
|
||||
"""
|
||||
Access the Pricing Twilio Domain
|
||||
|
||||
:returns: Pricing Twilio Domain
|
||||
"""
|
||||
if self._pricing is None:
|
||||
from twilio.rest.pricing import Pricing
|
||||
|
||||
self._pricing = Pricing(self)
|
||||
return self._pricing
|
||||
|
||||
@property
|
||||
def proxy(self) -> "Proxy":
|
||||
"""
|
||||
Access the Proxy Twilio Domain
|
||||
|
||||
:returns: Proxy Twilio Domain
|
||||
"""
|
||||
if self._proxy is None:
|
||||
from twilio.rest.proxy import Proxy
|
||||
|
||||
self._proxy = Proxy(self)
|
||||
return self._proxy
|
||||
|
||||
@property
|
||||
def routes(self) -> "Routes":
|
||||
"""
|
||||
Access the Routes Twilio Domain
|
||||
|
||||
:returns: Routes Twilio Domain
|
||||
"""
|
||||
if self._routes is None:
|
||||
from twilio.rest.routes import Routes
|
||||
|
||||
self._routes = Routes(self)
|
||||
return self._routes
|
||||
|
||||
@property
|
||||
def serverless(self) -> "Serverless":
|
||||
"""
|
||||
Access the Serverless Twilio Domain
|
||||
|
||||
:returns: Serverless Twilio Domain
|
||||
"""
|
||||
if self._serverless is None:
|
||||
from twilio.rest.serverless import Serverless
|
||||
|
||||
self._serverless = Serverless(self)
|
||||
return self._serverless
|
||||
|
||||
@property
|
||||
def studio(self) -> "Studio":
|
||||
"""
|
||||
Access the Studio Twilio Domain
|
||||
|
||||
:returns: Studio Twilio Domain
|
||||
"""
|
||||
if self._studio is None:
|
||||
from twilio.rest.studio import Studio
|
||||
|
||||
self._studio = Studio(self)
|
||||
return self._studio
|
||||
|
||||
@property
|
||||
def supersim(self) -> "Supersim":
|
||||
"""
|
||||
Access the Supersim Twilio Domain
|
||||
|
||||
:returns: Supersim Twilio Domain
|
||||
"""
|
||||
if self._supersim is None:
|
||||
from twilio.rest.supersim import Supersim
|
||||
|
||||
self._supersim = Supersim(self)
|
||||
return self._supersim
|
||||
|
||||
@property
|
||||
def sync(self) -> "Sync":
|
||||
"""
|
||||
Access the Sync Twilio Domain
|
||||
|
||||
:returns: Sync Twilio Domain
|
||||
"""
|
||||
if self._sync is None:
|
||||
from twilio.rest.sync import Sync
|
||||
|
||||
self._sync = Sync(self)
|
||||
return self._sync
|
||||
|
||||
@property
|
||||
def taskrouter(self) -> "Taskrouter":
|
||||
"""
|
||||
Access the Taskrouter Twilio Domain
|
||||
|
||||
:returns: Taskrouter Twilio Domain
|
||||
"""
|
||||
if self._taskrouter is None:
|
||||
from twilio.rest.taskrouter import Taskrouter
|
||||
|
||||
self._taskrouter = Taskrouter(self)
|
||||
return self._taskrouter
|
||||
|
||||
@property
|
||||
def trunking(self) -> "Trunking":
|
||||
"""
|
||||
Access the Trunking Twilio Domain
|
||||
|
||||
:returns: Trunking Twilio Domain
|
||||
"""
|
||||
if self._trunking is None:
|
||||
from twilio.rest.trunking import Trunking
|
||||
|
||||
self._trunking = Trunking(self)
|
||||
return self._trunking
|
||||
|
||||
@property
|
||||
def trusthub(self) -> "Trusthub":
|
||||
"""
|
||||
Access the Trusthub Twilio Domain
|
||||
|
||||
:returns: Trusthub Twilio Domain
|
||||
"""
|
||||
if self._trusthub is None:
|
||||
from twilio.rest.trusthub import Trusthub
|
||||
|
||||
self._trusthub = Trusthub(self)
|
||||
return self._trusthub
|
||||
|
||||
@property
|
||||
def verify(self) -> "Verify":
|
||||
"""
|
||||
Access the Verify Twilio Domain
|
||||
|
||||
:returns: Verify Twilio Domain
|
||||
"""
|
||||
if self._verify is None:
|
||||
from twilio.rest.verify import Verify
|
||||
|
||||
self._verify = Verify(self)
|
||||
return self._verify
|
||||
|
||||
@property
|
||||
def video(self) -> "Video":
|
||||
"""
|
||||
Access the Video Twilio Domain
|
||||
|
||||
:returns: Video Twilio Domain
|
||||
"""
|
||||
if self._video is None:
|
||||
from twilio.rest.video import Video
|
||||
|
||||
self._video = Video(self)
|
||||
return self._video
|
||||
|
||||
@property
|
||||
def voice(self) -> "Voice":
|
||||
"""
|
||||
Access the Voice Twilio Domain
|
||||
|
||||
:returns: Voice Twilio Domain
|
||||
"""
|
||||
if self._voice is None:
|
||||
from twilio.rest.voice import Voice
|
||||
|
||||
self._voice = Voice(self)
|
||||
return self._voice
|
||||
|
||||
@property
|
||||
def wireless(self) -> "Wireless":
|
||||
"""
|
||||
Access the Wireless Twilio Domain
|
||||
|
||||
:returns: Wireless Twilio Domain
|
||||
"""
|
||||
if self._wireless is None:
|
||||
from twilio.rest.wireless import Wireless
|
||||
|
||||
self._wireless = Wireless(self)
|
||||
return self._wireless
|
||||
|
||||
@property
|
||||
def addresses(self) -> "AddressList":
|
||||
return self.api.account.addresses
|
||||
|
||||
@property
|
||||
def applications(self) -> "ApplicationList":
|
||||
return self.api.account.applications
|
||||
|
||||
@property
|
||||
def authorized_connect_apps(self) -> "AuthorizedConnectAppList":
|
||||
return self.api.account.authorized_connect_apps
|
||||
|
||||
@property
|
||||
def available_phone_numbers(self) -> "AvailablePhoneNumberCountryList":
|
||||
return self.api.account.available_phone_numbers
|
||||
|
||||
@property
|
||||
def balance(self) -> "BalanceList":
|
||||
return self.api.account.balance
|
||||
|
||||
@property
|
||||
def calls(self) -> "CallList":
|
||||
return self.api.account.calls
|
||||
|
||||
@property
|
||||
def conferences(self) -> "ConferenceList":
|
||||
return self.api.account.conferences
|
||||
|
||||
@property
|
||||
def connect_apps(self) -> "ConnectAppList":
|
||||
return self.api.account.connect_apps
|
||||
|
||||
@property
|
||||
def incoming_phone_numbers(self) -> "IncomingPhoneNumberList":
|
||||
return self.api.account.incoming_phone_numbers
|
||||
|
||||
@property
|
||||
def keys(self) -> "KeyList":
|
||||
return self.api.account.keys
|
||||
|
||||
@property
|
||||
def new_keys(self) -> "NewKeyList":
|
||||
return self.api.account.new_keys
|
||||
|
||||
@property
|
||||
def messages(self) -> "MessageList":
|
||||
return self.api.account.messages
|
||||
|
||||
@property
|
||||
def signing_keys(self) -> "SigningKeyList":
|
||||
return self.api.account.signing_keys
|
||||
|
||||
@property
|
||||
def new_signing_keys(self) -> "NewSigningKeyList":
|
||||
return self.api.account.new_signing_keys
|
||||
|
||||
@property
|
||||
def notifications(self) -> "NotificationList":
|
||||
return self.api.account.notifications
|
||||
|
||||
@property
|
||||
def outgoing_caller_ids(self) -> "OutgoingCallerIdList":
|
||||
return self.api.account.outgoing_caller_ids
|
||||
|
||||
@property
|
||||
def validation_requests(self) -> "ValidationRequestList":
|
||||
return self.api.account.validation_requests
|
||||
|
||||
@property
|
||||
def queues(self) -> "QueueList":
|
||||
return self.api.account.queues
|
||||
|
||||
@property
|
||||
def recordings(self) -> "RecordingList":
|
||||
return self.api.account.recordings
|
||||
|
||||
@property
|
||||
def short_codes(self) -> "ShortCodeList":
|
||||
return self.api.account.short_codes
|
||||
|
||||
@property
|
||||
def sip(self) -> "SipList":
|
||||
return self.api.account.sip
|
||||
|
||||
@property
|
||||
def tokens(self) -> "TokenList":
|
||||
return self.api.account.tokens
|
||||
|
||||
@property
|
||||
def transcriptions(self) -> "TranscriptionList":
|
||||
return self.api.account.transcriptions
|
||||
|
||||
@property
|
||||
def usage(self) -> "UsageList":
|
||||
return self.api.account.usage
|
||||
Binary file not shown.
@@ -0,0 +1,43 @@
|
||||
r"""
|
||||
This code was generated by
|
||||
___ _ _ _ _ _ _ ____ ____ ____ _ ____ ____ _ _ ____ ____ ____ ___ __ __
|
||||
| | | | | | | | | __ | | |__| | __ | __ |___ |\ | |___ |__/ |__| | | | |__/
|
||||
| |_|_| | |___ | |__| |__| | | | |__] |___ | \| |___ | \ | | | |__| | \
|
||||
|
||||
NOTE: This class is auto generated by OpenAPI Generator.
|
||||
https://openapi-generator.tech
|
||||
Do not edit the class manually.
|
||||
"""
|
||||
|
||||
from typing import Optional
|
||||
|
||||
from twilio.base.domain import Domain
|
||||
from twilio.rest import Client
|
||||
from twilio.rest.accounts.v1 import V1
|
||||
|
||||
|
||||
class AccountsBase(Domain):
|
||||
def __init__(self, twilio: Client):
|
||||
"""
|
||||
Initialize the Accounts Domain
|
||||
|
||||
:returns: Domain for Accounts
|
||||
"""
|
||||
super().__init__(twilio, "https://accounts.twilio.com")
|
||||
self._v1: Optional[V1] = None
|
||||
|
||||
@property
|
||||
def v1(self) -> V1:
|
||||
"""
|
||||
:returns: Versions v1 of Accounts
|
||||
"""
|
||||
if self._v1 is None:
|
||||
self._v1 = V1(self)
|
||||
return self._v1
|
||||
|
||||
def __repr__(self) -> str:
|
||||
"""
|
||||
Provide a friendly representation
|
||||
:returns: Machine friendly representation
|
||||
"""
|
||||
return "<Twilio.Accounts>"
|
||||
@@ -0,0 +1,35 @@
|
||||
from warnings import warn
|
||||
|
||||
from twilio.rest.accounts.AccountsBase import AccountsBase
|
||||
from twilio.rest.accounts.v1.auth_token_promotion import AuthTokenPromotionList
|
||||
from twilio.rest.accounts.v1.credential import CredentialList
|
||||
from twilio.rest.accounts.v1.secondary_auth_token import SecondaryAuthTokenList
|
||||
|
||||
|
||||
class Accounts(AccountsBase):
|
||||
@property
|
||||
def auth_token_promotion(self) -> AuthTokenPromotionList:
|
||||
warn(
|
||||
"auth_token_promotion is deprecated. Use v1.auth_token_promotion instead.",
|
||||
DeprecationWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
return self.v1.auth_token_promotion
|
||||
|
||||
@property
|
||||
def credentials(self) -> CredentialList:
|
||||
warn(
|
||||
"credentials is deprecated. Use v1.credentials instead.",
|
||||
DeprecationWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
return self.v1.credentials
|
||||
|
||||
@property
|
||||
def secondary_auth_token(self) -> SecondaryAuthTokenList:
|
||||
warn(
|
||||
"secondary_auth_token is deprecated. Use v1.secondary_auth_token instead.",
|
||||
DeprecationWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
return self.v1.secondary_auth_token
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
@@ -0,0 +1,66 @@
|
||||
r"""
|
||||
This code was generated by
|
||||
___ _ _ _ _ _ _ ____ ____ ____ _ ____ ____ _ _ ____ ____ ____ ___ __ __
|
||||
| | | | | | | | | __ | | |__| | __ | __ |___ |\ | |___ |__/ |__| | | | |__/
|
||||
| |_|_| | |___ | |__| |__| | | | |__] |___ | \| |___ | \ | | | |__| | \
|
||||
|
||||
Twilio - Accounts
|
||||
This is the public Twilio REST API.
|
||||
|
||||
NOTE: This class is auto generated by OpenAPI Generator.
|
||||
https://openapi-generator.tech
|
||||
Do not edit the class manually.
|
||||
"""
|
||||
|
||||
from typing import Optional
|
||||
from twilio.base.version import Version
|
||||
from twilio.base.domain import Domain
|
||||
from twilio.rest.accounts.v1.auth_token_promotion import AuthTokenPromotionList
|
||||
from twilio.rest.accounts.v1.credential import CredentialList
|
||||
from twilio.rest.accounts.v1.safelist import SafelistList
|
||||
from twilio.rest.accounts.v1.secondary_auth_token import SecondaryAuthTokenList
|
||||
|
||||
|
||||
class V1(Version):
|
||||
def __init__(self, domain: Domain):
|
||||
"""
|
||||
Initialize the V1 version of Accounts
|
||||
|
||||
:param domain: The Twilio.accounts domain
|
||||
"""
|
||||
super().__init__(domain, "v1")
|
||||
self._auth_token_promotion: Optional[AuthTokenPromotionList] = None
|
||||
self._credentials: Optional[CredentialList] = None
|
||||
self._safelist: Optional[SafelistList] = None
|
||||
self._secondary_auth_token: Optional[SecondaryAuthTokenList] = None
|
||||
|
||||
@property
|
||||
def auth_token_promotion(self) -> AuthTokenPromotionList:
|
||||
if self._auth_token_promotion is None:
|
||||
self._auth_token_promotion = AuthTokenPromotionList(self)
|
||||
return self._auth_token_promotion
|
||||
|
||||
@property
|
||||
def credentials(self) -> CredentialList:
|
||||
if self._credentials is None:
|
||||
self._credentials = CredentialList(self)
|
||||
return self._credentials
|
||||
|
||||
@property
|
||||
def safelist(self) -> SafelistList:
|
||||
if self._safelist is None:
|
||||
self._safelist = SafelistList(self)
|
||||
return self._safelist
|
||||
|
||||
@property
|
||||
def secondary_auth_token(self) -> SecondaryAuthTokenList:
|
||||
if self._secondary_auth_token is None:
|
||||
self._secondary_auth_token = SecondaryAuthTokenList(self)
|
||||
return self._secondary_auth_token
|
||||
|
||||
def __repr__(self) -> str:
|
||||
"""
|
||||
Provide a friendly representation
|
||||
:returns: Machine friendly representation
|
||||
"""
|
||||
return "<Twilio.Accounts.V1>"
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
@@ -0,0 +1,177 @@
|
||||
r"""
|
||||
This code was generated by
|
||||
___ _ _ _ _ _ _ ____ ____ ____ _ ____ ____ _ _ ____ ____ ____ ___ __ __
|
||||
| | | | | | | | | __ | | |__| | __ | __ |___ |\ | |___ |__/ |__| | | | |__/
|
||||
| |_|_| | |___ | |__| |__| | | | |__] |___ | \| |___ | \ | | | |__| | \
|
||||
|
||||
Twilio - Accounts
|
||||
This is the public Twilio REST API.
|
||||
|
||||
NOTE: This class is auto generated by OpenAPI Generator.
|
||||
https://openapi-generator.tech
|
||||
Do not edit the class manually.
|
||||
"""
|
||||
|
||||
|
||||
from datetime import datetime
|
||||
from typing import Any, Dict, Optional
|
||||
from twilio.base import deserialize, values
|
||||
from twilio.base.instance_context import InstanceContext
|
||||
from twilio.base.instance_resource import InstanceResource
|
||||
from twilio.base.list_resource import ListResource
|
||||
from twilio.base.version import Version
|
||||
|
||||
|
||||
class AuthTokenPromotionInstance(InstanceResource):
|
||||
|
||||
"""
|
||||
:ivar account_sid: The SID of the [Account](https://www.twilio.com/docs/iam/api/account) that the secondary Auth Token was created for.
|
||||
:ivar auth_token: The promoted Auth Token that must be used to authenticate future API requests.
|
||||
:ivar date_created: The date and time in UTC when the resource was created specified in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format.
|
||||
:ivar date_updated: The date and time in GMT when the resource was last updated specified in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format.
|
||||
:ivar url: The URI for this resource, relative to `https://accounts.twilio.com`
|
||||
"""
|
||||
|
||||
def __init__(self, version: Version, payload: Dict[str, Any]):
|
||||
super().__init__(version)
|
||||
|
||||
self.account_sid: Optional[str] = payload.get("account_sid")
|
||||
self.auth_token: Optional[str] = payload.get("auth_token")
|
||||
self.date_created: Optional[datetime] = deserialize.iso8601_datetime(
|
||||
payload.get("date_created")
|
||||
)
|
||||
self.date_updated: Optional[datetime] = deserialize.iso8601_datetime(
|
||||
payload.get("date_updated")
|
||||
)
|
||||
self.url: Optional[str] = payload.get("url")
|
||||
|
||||
self._context: Optional[AuthTokenPromotionContext] = None
|
||||
|
||||
@property
|
||||
def _proxy(self) -> "AuthTokenPromotionContext":
|
||||
"""
|
||||
Generate an instance context for the instance, the context is capable of
|
||||
performing various actions. All instance actions are proxied to the context
|
||||
|
||||
:returns: AuthTokenPromotionContext for this AuthTokenPromotionInstance
|
||||
"""
|
||||
if self._context is None:
|
||||
self._context = AuthTokenPromotionContext(
|
||||
self._version,
|
||||
)
|
||||
return self._context
|
||||
|
||||
def update(self) -> "AuthTokenPromotionInstance":
|
||||
"""
|
||||
Update the AuthTokenPromotionInstance
|
||||
|
||||
|
||||
:returns: The updated AuthTokenPromotionInstance
|
||||
"""
|
||||
return self._proxy.update()
|
||||
|
||||
async def update_async(self) -> "AuthTokenPromotionInstance":
|
||||
"""
|
||||
Asynchronous coroutine to update the AuthTokenPromotionInstance
|
||||
|
||||
|
||||
:returns: The updated AuthTokenPromotionInstance
|
||||
"""
|
||||
return await self._proxy.update_async()
|
||||
|
||||
def __repr__(self) -> str:
|
||||
"""
|
||||
Provide a friendly representation
|
||||
|
||||
:returns: Machine friendly representation
|
||||
"""
|
||||
|
||||
return "<Twilio.Accounts.V1.AuthTokenPromotionInstance>"
|
||||
|
||||
|
||||
class AuthTokenPromotionContext(InstanceContext):
|
||||
def __init__(self, version: Version):
|
||||
"""
|
||||
Initialize the AuthTokenPromotionContext
|
||||
|
||||
:param version: Version that contains the resource
|
||||
"""
|
||||
super().__init__(version)
|
||||
|
||||
self._uri = "/AuthTokens/Promote"
|
||||
|
||||
def update(self) -> AuthTokenPromotionInstance:
|
||||
"""
|
||||
Update the AuthTokenPromotionInstance
|
||||
|
||||
|
||||
:returns: The updated AuthTokenPromotionInstance
|
||||
"""
|
||||
data = values.of({})
|
||||
|
||||
payload = self._version.update(
|
||||
method="POST",
|
||||
uri=self._uri,
|
||||
data=data,
|
||||
)
|
||||
|
||||
return AuthTokenPromotionInstance(self._version, payload)
|
||||
|
||||
async def update_async(self) -> AuthTokenPromotionInstance:
|
||||
"""
|
||||
Asynchronous coroutine to update the AuthTokenPromotionInstance
|
||||
|
||||
|
||||
:returns: The updated AuthTokenPromotionInstance
|
||||
"""
|
||||
data = values.of({})
|
||||
|
||||
payload = await self._version.update_async(
|
||||
method="POST",
|
||||
uri=self._uri,
|
||||
data=data,
|
||||
)
|
||||
|
||||
return AuthTokenPromotionInstance(self._version, payload)
|
||||
|
||||
def __repr__(self) -> str:
|
||||
"""
|
||||
Provide a friendly representation
|
||||
|
||||
:returns: Machine friendly representation
|
||||
"""
|
||||
|
||||
return "<Twilio.Accounts.V1.AuthTokenPromotionContext>"
|
||||
|
||||
|
||||
class AuthTokenPromotionList(ListResource):
|
||||
def __init__(self, version: Version):
|
||||
"""
|
||||
Initialize the AuthTokenPromotionList
|
||||
|
||||
:param version: Version that contains the resource
|
||||
|
||||
"""
|
||||
super().__init__(version)
|
||||
|
||||
def get(self) -> AuthTokenPromotionContext:
|
||||
"""
|
||||
Constructs a AuthTokenPromotionContext
|
||||
|
||||
"""
|
||||
return AuthTokenPromotionContext(self._version)
|
||||
|
||||
def __call__(self) -> AuthTokenPromotionContext:
|
||||
"""
|
||||
Constructs a AuthTokenPromotionContext
|
||||
|
||||
"""
|
||||
return AuthTokenPromotionContext(self._version)
|
||||
|
||||
def __repr__(self) -> str:
|
||||
"""
|
||||
Provide a friendly representation
|
||||
|
||||
:returns: Machine friendly representation
|
||||
"""
|
||||
return "<Twilio.Accounts.V1.AuthTokenPromotionList>"
|
||||
@@ -0,0 +1,65 @@
|
||||
r"""
|
||||
This code was generated by
|
||||
___ _ _ _ _ _ _ ____ ____ ____ _ ____ ____ _ _ ____ ____ ____ ___ __ __
|
||||
| | | | | | | | | __ | | |__| | __ | __ |___ |\ | |___ |__/ |__| | | | |__/
|
||||
| |_|_| | |___ | |__| |__| | | | |__] |___ | \| |___ | \ | | | |__| | \
|
||||
|
||||
Twilio - Accounts
|
||||
This is the public Twilio REST API.
|
||||
|
||||
NOTE: This class is auto generated by OpenAPI Generator.
|
||||
https://openapi-generator.tech
|
||||
Do not edit the class manually.
|
||||
"""
|
||||
|
||||
|
||||
from typing import Optional
|
||||
|
||||
|
||||
from twilio.base.list_resource import ListResource
|
||||
from twilio.base.version import Version
|
||||
|
||||
from twilio.rest.accounts.v1.credential.aws import AwsList
|
||||
from twilio.rest.accounts.v1.credential.public_key import PublicKeyList
|
||||
|
||||
|
||||
class CredentialList(ListResource):
|
||||
def __init__(self, version: Version):
|
||||
"""
|
||||
Initialize the CredentialList
|
||||
|
||||
:param version: Version that contains the resource
|
||||
|
||||
"""
|
||||
super().__init__(version)
|
||||
|
||||
self._uri = "/Credentials"
|
||||
|
||||
self._aws: Optional[AwsList] = None
|
||||
self._public_key: Optional[PublicKeyList] = None
|
||||
|
||||
@property
|
||||
def aws(self) -> AwsList:
|
||||
"""
|
||||
Access the aws
|
||||
"""
|
||||
if self._aws is None:
|
||||
self._aws = AwsList(self._version)
|
||||
return self._aws
|
||||
|
||||
@property
|
||||
def public_key(self) -> PublicKeyList:
|
||||
"""
|
||||
Access the public_key
|
||||
"""
|
||||
if self._public_key is None:
|
||||
self._public_key = PublicKeyList(self._version)
|
||||
return self._public_key
|
||||
|
||||
def __repr__(self) -> str:
|
||||
"""
|
||||
Provide a friendly representation
|
||||
|
||||
:returns: Machine friendly representation
|
||||
"""
|
||||
return "<Twilio.Accounts.V1.CredentialList>"
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
@@ -0,0 +1,576 @@
|
||||
r"""
|
||||
This code was generated by
|
||||
___ _ _ _ _ _ _ ____ ____ ____ _ ____ ____ _ _ ____ ____ ____ ___ __ __
|
||||
| | | | | | | | | __ | | |__| | __ | __ |___ |\ | |___ |__/ |__| | | | |__/
|
||||
| |_|_| | |___ | |__| |__| | | | |__] |___ | \| |___ | \ | | | |__| | \
|
||||
|
||||
Twilio - Accounts
|
||||
This is the public Twilio REST API.
|
||||
|
||||
NOTE: This class is auto generated by OpenAPI Generator.
|
||||
https://openapi-generator.tech
|
||||
Do not edit the class manually.
|
||||
"""
|
||||
|
||||
|
||||
from datetime import datetime
|
||||
from typing import Any, Dict, List, Optional, Union, Iterator, AsyncIterator
|
||||
from twilio.base import deserialize, values
|
||||
from twilio.base.instance_context import InstanceContext
|
||||
from twilio.base.instance_resource import InstanceResource
|
||||
from twilio.base.list_resource import ListResource
|
||||
from twilio.base.version import Version
|
||||
from twilio.base.page import Page
|
||||
|
||||
|
||||
class AwsInstance(InstanceResource):
|
||||
|
||||
"""
|
||||
:ivar sid: The unique string that we created to identify the AWS resource.
|
||||
:ivar account_sid: The SID of the [Account](https://www.twilio.com/docs/iam/api/account) that created the AWS resource.
|
||||
:ivar friendly_name: The string that you assigned to describe the resource.
|
||||
:ivar date_created: The date and time in GMT when the resource was created specified in [RFC 2822](https://www.ietf.org/rfc/rfc2822.txt) format.
|
||||
:ivar date_updated: The date and time in GMT when the resource was last updated specified in [RFC 2822](https://www.ietf.org/rfc/rfc2822.txt) format.
|
||||
:ivar url: The URI for this resource, relative to `https://accounts.twilio.com`
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self, version: Version, payload: Dict[str, Any], sid: Optional[str] = None
|
||||
):
|
||||
super().__init__(version)
|
||||
|
||||
self.sid: Optional[str] = payload.get("sid")
|
||||
self.account_sid: Optional[str] = payload.get("account_sid")
|
||||
self.friendly_name: Optional[str] = payload.get("friendly_name")
|
||||
self.date_created: Optional[datetime] = deserialize.iso8601_datetime(
|
||||
payload.get("date_created")
|
||||
)
|
||||
self.date_updated: Optional[datetime] = deserialize.iso8601_datetime(
|
||||
payload.get("date_updated")
|
||||
)
|
||||
self.url: Optional[str] = payload.get("url")
|
||||
|
||||
self._solution = {
|
||||
"sid": sid or self.sid,
|
||||
}
|
||||
self._context: Optional[AwsContext] = None
|
||||
|
||||
@property
|
||||
def _proxy(self) -> "AwsContext":
|
||||
"""
|
||||
Generate an instance context for the instance, the context is capable of
|
||||
performing various actions. All instance actions are proxied to the context
|
||||
|
||||
:returns: AwsContext for this AwsInstance
|
||||
"""
|
||||
if self._context is None:
|
||||
self._context = AwsContext(
|
||||
self._version,
|
||||
sid=self._solution["sid"],
|
||||
)
|
||||
return self._context
|
||||
|
||||
def delete(self) -> bool:
|
||||
"""
|
||||
Deletes the AwsInstance
|
||||
|
||||
|
||||
:returns: True if delete succeeds, False otherwise
|
||||
"""
|
||||
return self._proxy.delete()
|
||||
|
||||
async def delete_async(self) -> bool:
|
||||
"""
|
||||
Asynchronous coroutine that deletes the AwsInstance
|
||||
|
||||
|
||||
:returns: True if delete succeeds, False otherwise
|
||||
"""
|
||||
return await self._proxy.delete_async()
|
||||
|
||||
def fetch(self) -> "AwsInstance":
|
||||
"""
|
||||
Fetch the AwsInstance
|
||||
|
||||
|
||||
:returns: The fetched AwsInstance
|
||||
"""
|
||||
return self._proxy.fetch()
|
||||
|
||||
async def fetch_async(self) -> "AwsInstance":
|
||||
"""
|
||||
Asynchronous coroutine to fetch the AwsInstance
|
||||
|
||||
|
||||
:returns: The fetched AwsInstance
|
||||
"""
|
||||
return await self._proxy.fetch_async()
|
||||
|
||||
def update(self, friendly_name: Union[str, object] = values.unset) -> "AwsInstance":
|
||||
"""
|
||||
Update the AwsInstance
|
||||
|
||||
:param friendly_name: A descriptive string that you create to describe the resource. It can be up to 64 characters long.
|
||||
|
||||
:returns: The updated AwsInstance
|
||||
"""
|
||||
return self._proxy.update(
|
||||
friendly_name=friendly_name,
|
||||
)
|
||||
|
||||
async def update_async(
|
||||
self, friendly_name: Union[str, object] = values.unset
|
||||
) -> "AwsInstance":
|
||||
"""
|
||||
Asynchronous coroutine to update the AwsInstance
|
||||
|
||||
:param friendly_name: A descriptive string that you create to describe the resource. It can be up to 64 characters long.
|
||||
|
||||
:returns: The updated AwsInstance
|
||||
"""
|
||||
return await self._proxy.update_async(
|
||||
friendly_name=friendly_name,
|
||||
)
|
||||
|
||||
def __repr__(self) -> str:
|
||||
"""
|
||||
Provide a friendly representation
|
||||
|
||||
:returns: Machine friendly representation
|
||||
"""
|
||||
context = " ".join("{}={}".format(k, v) for k, v in self._solution.items())
|
||||
return "<Twilio.Accounts.V1.AwsInstance {}>".format(context)
|
||||
|
||||
|
||||
class AwsContext(InstanceContext):
|
||||
def __init__(self, version: Version, sid: str):
|
||||
"""
|
||||
Initialize the AwsContext
|
||||
|
||||
:param version: Version that contains the resource
|
||||
:param sid: The Twilio-provided string that uniquely identifies the AWS resource to update.
|
||||
"""
|
||||
super().__init__(version)
|
||||
|
||||
# Path Solution
|
||||
self._solution = {
|
||||
"sid": sid,
|
||||
}
|
||||
self._uri = "/Credentials/AWS/{sid}".format(**self._solution)
|
||||
|
||||
def delete(self) -> bool:
|
||||
"""
|
||||
Deletes the AwsInstance
|
||||
|
||||
|
||||
:returns: True if delete succeeds, False otherwise
|
||||
"""
|
||||
return self._version.delete(
|
||||
method="DELETE",
|
||||
uri=self._uri,
|
||||
)
|
||||
|
||||
async def delete_async(self) -> bool:
|
||||
"""
|
||||
Asynchronous coroutine that deletes the AwsInstance
|
||||
|
||||
|
||||
:returns: True if delete succeeds, False otherwise
|
||||
"""
|
||||
return await self._version.delete_async(
|
||||
method="DELETE",
|
||||
uri=self._uri,
|
||||
)
|
||||
|
||||
def fetch(self) -> AwsInstance:
|
||||
"""
|
||||
Fetch the AwsInstance
|
||||
|
||||
|
||||
:returns: The fetched AwsInstance
|
||||
"""
|
||||
|
||||
payload = self._version.fetch(
|
||||
method="GET",
|
||||
uri=self._uri,
|
||||
)
|
||||
|
||||
return AwsInstance(
|
||||
self._version,
|
||||
payload,
|
||||
sid=self._solution["sid"],
|
||||
)
|
||||
|
||||
async def fetch_async(self) -> AwsInstance:
|
||||
"""
|
||||
Asynchronous coroutine to fetch the AwsInstance
|
||||
|
||||
|
||||
:returns: The fetched AwsInstance
|
||||
"""
|
||||
|
||||
payload = await self._version.fetch_async(
|
||||
method="GET",
|
||||
uri=self._uri,
|
||||
)
|
||||
|
||||
return AwsInstance(
|
||||
self._version,
|
||||
payload,
|
||||
sid=self._solution["sid"],
|
||||
)
|
||||
|
||||
def update(self, friendly_name: Union[str, object] = values.unset) -> AwsInstance:
|
||||
"""
|
||||
Update the AwsInstance
|
||||
|
||||
:param friendly_name: A descriptive string that you create to describe the resource. It can be up to 64 characters long.
|
||||
|
||||
:returns: The updated AwsInstance
|
||||
"""
|
||||
data = values.of(
|
||||
{
|
||||
"FriendlyName": friendly_name,
|
||||
}
|
||||
)
|
||||
|
||||
payload = self._version.update(
|
||||
method="POST",
|
||||
uri=self._uri,
|
||||
data=data,
|
||||
)
|
||||
|
||||
return AwsInstance(self._version, payload, sid=self._solution["sid"])
|
||||
|
||||
async def update_async(
|
||||
self, friendly_name: Union[str, object] = values.unset
|
||||
) -> AwsInstance:
|
||||
"""
|
||||
Asynchronous coroutine to update the AwsInstance
|
||||
|
||||
:param friendly_name: A descriptive string that you create to describe the resource. It can be up to 64 characters long.
|
||||
|
||||
:returns: The updated AwsInstance
|
||||
"""
|
||||
data = values.of(
|
||||
{
|
||||
"FriendlyName": friendly_name,
|
||||
}
|
||||
)
|
||||
|
||||
payload = await self._version.update_async(
|
||||
method="POST",
|
||||
uri=self._uri,
|
||||
data=data,
|
||||
)
|
||||
|
||||
return AwsInstance(self._version, payload, sid=self._solution["sid"])
|
||||
|
||||
def __repr__(self) -> str:
|
||||
"""
|
||||
Provide a friendly representation
|
||||
|
||||
:returns: Machine friendly representation
|
||||
"""
|
||||
context = " ".join("{}={}".format(k, v) for k, v in self._solution.items())
|
||||
return "<Twilio.Accounts.V1.AwsContext {}>".format(context)
|
||||
|
||||
|
||||
class AwsPage(Page):
|
||||
def get_instance(self, payload: Dict[str, Any]) -> AwsInstance:
|
||||
"""
|
||||
Build an instance of AwsInstance
|
||||
|
||||
:param payload: Payload response from the API
|
||||
"""
|
||||
return AwsInstance(self._version, payload)
|
||||
|
||||
def __repr__(self) -> str:
|
||||
"""
|
||||
Provide a friendly representation
|
||||
|
||||
:returns: Machine friendly representation
|
||||
"""
|
||||
return "<Twilio.Accounts.V1.AwsPage>"
|
||||
|
||||
|
||||
class AwsList(ListResource):
|
||||
def __init__(self, version: Version):
|
||||
"""
|
||||
Initialize the AwsList
|
||||
|
||||
:param version: Version that contains the resource
|
||||
|
||||
"""
|
||||
super().__init__(version)
|
||||
|
||||
self._uri = "/Credentials/AWS"
|
||||
|
||||
def create(
|
||||
self,
|
||||
credentials: str,
|
||||
friendly_name: Union[str, object] = values.unset,
|
||||
account_sid: Union[str, object] = values.unset,
|
||||
) -> AwsInstance:
|
||||
"""
|
||||
Create the AwsInstance
|
||||
|
||||
:param credentials: A string that contains the AWS access credentials in the format `<AWS_ACCESS_KEY_ID>:<AWS_SECRET_ACCESS_KEY>`. For example, `AKIAIOSFODNN7EXAMPLE:wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY`
|
||||
:param friendly_name: A descriptive string that you create to describe the resource. It can be up to 64 characters long.
|
||||
:param account_sid: The SID of the Subaccount that this Credential should be associated with. Must be a valid Subaccount of the account issuing the request.
|
||||
|
||||
:returns: The created AwsInstance
|
||||
"""
|
||||
data = values.of(
|
||||
{
|
||||
"Credentials": credentials,
|
||||
"FriendlyName": friendly_name,
|
||||
"AccountSid": account_sid,
|
||||
}
|
||||
)
|
||||
|
||||
payload = self._version.create(
|
||||
method="POST",
|
||||
uri=self._uri,
|
||||
data=data,
|
||||
)
|
||||
|
||||
return AwsInstance(self._version, payload)
|
||||
|
||||
async def create_async(
|
||||
self,
|
||||
credentials: str,
|
||||
friendly_name: Union[str, object] = values.unset,
|
||||
account_sid: Union[str, object] = values.unset,
|
||||
) -> AwsInstance:
|
||||
"""
|
||||
Asynchronously create the AwsInstance
|
||||
|
||||
:param credentials: A string that contains the AWS access credentials in the format `<AWS_ACCESS_KEY_ID>:<AWS_SECRET_ACCESS_KEY>`. For example, `AKIAIOSFODNN7EXAMPLE:wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY`
|
||||
:param friendly_name: A descriptive string that you create to describe the resource. It can be up to 64 characters long.
|
||||
:param account_sid: The SID of the Subaccount that this Credential should be associated with. Must be a valid Subaccount of the account issuing the request.
|
||||
|
||||
:returns: The created AwsInstance
|
||||
"""
|
||||
data = values.of(
|
||||
{
|
||||
"Credentials": credentials,
|
||||
"FriendlyName": friendly_name,
|
||||
"AccountSid": account_sid,
|
||||
}
|
||||
)
|
||||
|
||||
payload = await self._version.create_async(
|
||||
method="POST",
|
||||
uri=self._uri,
|
||||
data=data,
|
||||
)
|
||||
|
||||
return AwsInstance(self._version, payload)
|
||||
|
||||
def stream(
|
||||
self,
|
||||
limit: Optional[int] = None,
|
||||
page_size: Optional[int] = None,
|
||||
) -> Iterator[AwsInstance]:
|
||||
"""
|
||||
Streams AwsInstance records from the API as a generator stream.
|
||||
This operation lazily loads records as efficiently as possible until the limit
|
||||
is reached.
|
||||
The results are returned as a generator, so this operation is memory efficient.
|
||||
|
||||
:param limit: Upper limit for the number of records to return. stream()
|
||||
guarantees to never return more than limit. Default is no limit
|
||||
:param page_size: Number of records to fetch per request, when not set will use
|
||||
the default value of 50 records. If no page_size is defined
|
||||
but a limit is defined, stream() will attempt to read the
|
||||
limit with the most efficient page size, i.e. min(limit, 1000)
|
||||
|
||||
:returns: Generator that will yield up to limit results
|
||||
"""
|
||||
limits = self._version.read_limits(limit, page_size)
|
||||
page = self.page(page_size=limits["page_size"])
|
||||
|
||||
return self._version.stream(page, limits["limit"])
|
||||
|
||||
async def stream_async(
|
||||
self,
|
||||
limit: Optional[int] = None,
|
||||
page_size: Optional[int] = None,
|
||||
) -> AsyncIterator[AwsInstance]:
|
||||
"""
|
||||
Asynchronously streams AwsInstance records from the API as a generator stream.
|
||||
This operation lazily loads records as efficiently as possible until the limit
|
||||
is reached.
|
||||
The results are returned as a generator, so this operation is memory efficient.
|
||||
|
||||
:param limit: Upper limit for the number of records to return. stream()
|
||||
guarantees to never return more than limit. Default is no limit
|
||||
:param page_size: Number of records to fetch per request, when not set will use
|
||||
the default value of 50 records. If no page_size is defined
|
||||
but a limit is defined, stream() will attempt to read the
|
||||
limit with the most efficient page size, i.e. min(limit, 1000)
|
||||
|
||||
:returns: Generator that will yield up to limit results
|
||||
"""
|
||||
limits = self._version.read_limits(limit, page_size)
|
||||
page = await self.page_async(page_size=limits["page_size"])
|
||||
|
||||
return self._version.stream_async(page, limits["limit"])
|
||||
|
||||
def list(
|
||||
self,
|
||||
limit: Optional[int] = None,
|
||||
page_size: Optional[int] = None,
|
||||
) -> List[AwsInstance]:
|
||||
"""
|
||||
Lists AwsInstance records from the API as a list.
|
||||
Unlike stream(), this operation is eager and will load `limit` records into
|
||||
memory before returning.
|
||||
|
||||
:param limit: Upper limit for the number of records to return. list() guarantees
|
||||
never to return more than limit. Default is no limit
|
||||
:param page_size: Number of records to fetch per request, when not set will use
|
||||
the default value of 50 records. If no page_size is defined
|
||||
but a limit is defined, list() will attempt to read the limit
|
||||
with the most efficient page size, i.e. min(limit, 1000)
|
||||
|
||||
:returns: list that will contain up to limit results
|
||||
"""
|
||||
return list(
|
||||
self.stream(
|
||||
limit=limit,
|
||||
page_size=page_size,
|
||||
)
|
||||
)
|
||||
|
||||
async def list_async(
|
||||
self,
|
||||
limit: Optional[int] = None,
|
||||
page_size: Optional[int] = None,
|
||||
) -> List[AwsInstance]:
|
||||
"""
|
||||
Asynchronously lists AwsInstance records from the API as a list.
|
||||
Unlike stream(), this operation is eager and will load `limit` records into
|
||||
memory before returning.
|
||||
|
||||
:param limit: Upper limit for the number of records to return. list() guarantees
|
||||
never to return more than limit. Default is no limit
|
||||
:param page_size: Number of records to fetch per request, when not set will use
|
||||
the default value of 50 records. If no page_size is defined
|
||||
but a limit is defined, list() will attempt to read the limit
|
||||
with the most efficient page size, i.e. min(limit, 1000)
|
||||
|
||||
:returns: list that will contain up to limit results
|
||||
"""
|
||||
return [
|
||||
record
|
||||
async for record in await self.stream_async(
|
||||
limit=limit,
|
||||
page_size=page_size,
|
||||
)
|
||||
]
|
||||
|
||||
def page(
|
||||
self,
|
||||
page_token: Union[str, object] = values.unset,
|
||||
page_number: Union[int, object] = values.unset,
|
||||
page_size: Union[int, object] = values.unset,
|
||||
) -> AwsPage:
|
||||
"""
|
||||
Retrieve a single page of AwsInstance records from the API.
|
||||
Request is executed immediately
|
||||
|
||||
:param page_token: PageToken provided by the API
|
||||
:param page_number: Page Number, this value is simply for client state
|
||||
:param page_size: Number of records to return, defaults to 50
|
||||
|
||||
:returns: Page of AwsInstance
|
||||
"""
|
||||
data = values.of(
|
||||
{
|
||||
"PageToken": page_token,
|
||||
"Page": page_number,
|
||||
"PageSize": page_size,
|
||||
}
|
||||
)
|
||||
|
||||
response = self._version.page(method="GET", uri=self._uri, params=data)
|
||||
return AwsPage(self._version, response)
|
||||
|
||||
async def page_async(
|
||||
self,
|
||||
page_token: Union[str, object] = values.unset,
|
||||
page_number: Union[int, object] = values.unset,
|
||||
page_size: Union[int, object] = values.unset,
|
||||
) -> AwsPage:
|
||||
"""
|
||||
Asynchronously retrieve a single page of AwsInstance records from the API.
|
||||
Request is executed immediately
|
||||
|
||||
:param page_token: PageToken provided by the API
|
||||
:param page_number: Page Number, this value is simply for client state
|
||||
:param page_size: Number of records to return, defaults to 50
|
||||
|
||||
:returns: Page of AwsInstance
|
||||
"""
|
||||
data = values.of(
|
||||
{
|
||||
"PageToken": page_token,
|
||||
"Page": page_number,
|
||||
"PageSize": page_size,
|
||||
}
|
||||
)
|
||||
|
||||
response = await self._version.page_async(
|
||||
method="GET", uri=self._uri, params=data
|
||||
)
|
||||
return AwsPage(self._version, response)
|
||||
|
||||
def get_page(self, target_url: str) -> AwsPage:
|
||||
"""
|
||||
Retrieve a specific page of AwsInstance records from the API.
|
||||
Request is executed immediately
|
||||
|
||||
:param target_url: API-generated URL for the requested results page
|
||||
|
||||
:returns: Page of AwsInstance
|
||||
"""
|
||||
response = self._version.domain.twilio.request("GET", target_url)
|
||||
return AwsPage(self._version, response)
|
||||
|
||||
async def get_page_async(self, target_url: str) -> AwsPage:
|
||||
"""
|
||||
Asynchronously retrieve a specific page of AwsInstance records from the API.
|
||||
Request is executed immediately
|
||||
|
||||
:param target_url: API-generated URL for the requested results page
|
||||
|
||||
:returns: Page of AwsInstance
|
||||
"""
|
||||
response = await self._version.domain.twilio.request_async("GET", target_url)
|
||||
return AwsPage(self._version, response)
|
||||
|
||||
def get(self, sid: str) -> AwsContext:
|
||||
"""
|
||||
Constructs a AwsContext
|
||||
|
||||
:param sid: The Twilio-provided string that uniquely identifies the AWS resource to update.
|
||||
"""
|
||||
return AwsContext(self._version, sid=sid)
|
||||
|
||||
def __call__(self, sid: str) -> AwsContext:
|
||||
"""
|
||||
Constructs a AwsContext
|
||||
|
||||
:param sid: The Twilio-provided string that uniquely identifies the AWS resource to update.
|
||||
"""
|
||||
return AwsContext(self._version, sid=sid)
|
||||
|
||||
def __repr__(self) -> str:
|
||||
"""
|
||||
Provide a friendly representation
|
||||
|
||||
:returns: Machine friendly representation
|
||||
"""
|
||||
return "<Twilio.Accounts.V1.AwsList>"
|
||||
@@ -0,0 +1,580 @@
|
||||
r"""
|
||||
This code was generated by
|
||||
___ _ _ _ _ _ _ ____ ____ ____ _ ____ ____ _ _ ____ ____ ____ ___ __ __
|
||||
| | | | | | | | | __ | | |__| | __ | __ |___ |\ | |___ |__/ |__| | | | |__/
|
||||
| |_|_| | |___ | |__| |__| | | | |__] |___ | \| |___ | \ | | | |__| | \
|
||||
|
||||
Twilio - Accounts
|
||||
This is the public Twilio REST API.
|
||||
|
||||
NOTE: This class is auto generated by OpenAPI Generator.
|
||||
https://openapi-generator.tech
|
||||
Do not edit the class manually.
|
||||
"""
|
||||
|
||||
|
||||
from datetime import datetime
|
||||
from typing import Any, Dict, List, Optional, Union, Iterator, AsyncIterator
|
||||
from twilio.base import deserialize, values
|
||||
from twilio.base.instance_context import InstanceContext
|
||||
from twilio.base.instance_resource import InstanceResource
|
||||
from twilio.base.list_resource import ListResource
|
||||
from twilio.base.version import Version
|
||||
from twilio.base.page import Page
|
||||
|
||||
|
||||
class PublicKeyInstance(InstanceResource):
|
||||
|
||||
"""
|
||||
:ivar sid: The unique string that that we created to identify the PublicKey resource.
|
||||
:ivar account_sid: The SID of the [Account](https://www.twilio.com/docs/iam/api/account) that created the Credential that the PublicKey resource belongs to.
|
||||
:ivar friendly_name: The string that you assigned to describe the resource.
|
||||
:ivar date_created: The date and time in GMT when the resource was created specified in [RFC 2822](https://www.ietf.org/rfc/rfc2822.txt) format.
|
||||
:ivar date_updated: The date and time in GMT when the resource was last updated specified in [RFC 2822](https://www.ietf.org/rfc/rfc2822.txt) format.
|
||||
:ivar url: The URI for this resource, relative to `https://accounts.twilio.com`
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self, version: Version, payload: Dict[str, Any], sid: Optional[str] = None
|
||||
):
|
||||
super().__init__(version)
|
||||
|
||||
self.sid: Optional[str] = payload.get("sid")
|
||||
self.account_sid: Optional[str] = payload.get("account_sid")
|
||||
self.friendly_name: Optional[str] = payload.get("friendly_name")
|
||||
self.date_created: Optional[datetime] = deserialize.iso8601_datetime(
|
||||
payload.get("date_created")
|
||||
)
|
||||
self.date_updated: Optional[datetime] = deserialize.iso8601_datetime(
|
||||
payload.get("date_updated")
|
||||
)
|
||||
self.url: Optional[str] = payload.get("url")
|
||||
|
||||
self._solution = {
|
||||
"sid": sid or self.sid,
|
||||
}
|
||||
self._context: Optional[PublicKeyContext] = None
|
||||
|
||||
@property
|
||||
def _proxy(self) -> "PublicKeyContext":
|
||||
"""
|
||||
Generate an instance context for the instance, the context is capable of
|
||||
performing various actions. All instance actions are proxied to the context
|
||||
|
||||
:returns: PublicKeyContext for this PublicKeyInstance
|
||||
"""
|
||||
if self._context is None:
|
||||
self._context = PublicKeyContext(
|
||||
self._version,
|
||||
sid=self._solution["sid"],
|
||||
)
|
||||
return self._context
|
||||
|
||||
def delete(self) -> bool:
|
||||
"""
|
||||
Deletes the PublicKeyInstance
|
||||
|
||||
|
||||
:returns: True if delete succeeds, False otherwise
|
||||
"""
|
||||
return self._proxy.delete()
|
||||
|
||||
async def delete_async(self) -> bool:
|
||||
"""
|
||||
Asynchronous coroutine that deletes the PublicKeyInstance
|
||||
|
||||
|
||||
:returns: True if delete succeeds, False otherwise
|
||||
"""
|
||||
return await self._proxy.delete_async()
|
||||
|
||||
def fetch(self) -> "PublicKeyInstance":
|
||||
"""
|
||||
Fetch the PublicKeyInstance
|
||||
|
||||
|
||||
:returns: The fetched PublicKeyInstance
|
||||
"""
|
||||
return self._proxy.fetch()
|
||||
|
||||
async def fetch_async(self) -> "PublicKeyInstance":
|
||||
"""
|
||||
Asynchronous coroutine to fetch the PublicKeyInstance
|
||||
|
||||
|
||||
:returns: The fetched PublicKeyInstance
|
||||
"""
|
||||
return await self._proxy.fetch_async()
|
||||
|
||||
def update(
|
||||
self, friendly_name: Union[str, object] = values.unset
|
||||
) -> "PublicKeyInstance":
|
||||
"""
|
||||
Update the PublicKeyInstance
|
||||
|
||||
:param friendly_name: A descriptive string that you create to describe the resource. It can be up to 64 characters long.
|
||||
|
||||
:returns: The updated PublicKeyInstance
|
||||
"""
|
||||
return self._proxy.update(
|
||||
friendly_name=friendly_name,
|
||||
)
|
||||
|
||||
async def update_async(
|
||||
self, friendly_name: Union[str, object] = values.unset
|
||||
) -> "PublicKeyInstance":
|
||||
"""
|
||||
Asynchronous coroutine to update the PublicKeyInstance
|
||||
|
||||
:param friendly_name: A descriptive string that you create to describe the resource. It can be up to 64 characters long.
|
||||
|
||||
:returns: The updated PublicKeyInstance
|
||||
"""
|
||||
return await self._proxy.update_async(
|
||||
friendly_name=friendly_name,
|
||||
)
|
||||
|
||||
def __repr__(self) -> str:
|
||||
"""
|
||||
Provide a friendly representation
|
||||
|
||||
:returns: Machine friendly representation
|
||||
"""
|
||||
context = " ".join("{}={}".format(k, v) for k, v in self._solution.items())
|
||||
return "<Twilio.Accounts.V1.PublicKeyInstance {}>".format(context)
|
||||
|
||||
|
||||
class PublicKeyContext(InstanceContext):
|
||||
def __init__(self, version: Version, sid: str):
|
||||
"""
|
||||
Initialize the PublicKeyContext
|
||||
|
||||
:param version: Version that contains the resource
|
||||
:param sid: The Twilio-provided string that uniquely identifies the PublicKey resource to update.
|
||||
"""
|
||||
super().__init__(version)
|
||||
|
||||
# Path Solution
|
||||
self._solution = {
|
||||
"sid": sid,
|
||||
}
|
||||
self._uri = "/Credentials/PublicKeys/{sid}".format(**self._solution)
|
||||
|
||||
def delete(self) -> bool:
|
||||
"""
|
||||
Deletes the PublicKeyInstance
|
||||
|
||||
|
||||
:returns: True if delete succeeds, False otherwise
|
||||
"""
|
||||
return self._version.delete(
|
||||
method="DELETE",
|
||||
uri=self._uri,
|
||||
)
|
||||
|
||||
async def delete_async(self) -> bool:
|
||||
"""
|
||||
Asynchronous coroutine that deletes the PublicKeyInstance
|
||||
|
||||
|
||||
:returns: True if delete succeeds, False otherwise
|
||||
"""
|
||||
return await self._version.delete_async(
|
||||
method="DELETE",
|
||||
uri=self._uri,
|
||||
)
|
||||
|
||||
def fetch(self) -> PublicKeyInstance:
|
||||
"""
|
||||
Fetch the PublicKeyInstance
|
||||
|
||||
|
||||
:returns: The fetched PublicKeyInstance
|
||||
"""
|
||||
|
||||
payload = self._version.fetch(
|
||||
method="GET",
|
||||
uri=self._uri,
|
||||
)
|
||||
|
||||
return PublicKeyInstance(
|
||||
self._version,
|
||||
payload,
|
||||
sid=self._solution["sid"],
|
||||
)
|
||||
|
||||
async def fetch_async(self) -> PublicKeyInstance:
|
||||
"""
|
||||
Asynchronous coroutine to fetch the PublicKeyInstance
|
||||
|
||||
|
||||
:returns: The fetched PublicKeyInstance
|
||||
"""
|
||||
|
||||
payload = await self._version.fetch_async(
|
||||
method="GET",
|
||||
uri=self._uri,
|
||||
)
|
||||
|
||||
return PublicKeyInstance(
|
||||
self._version,
|
||||
payload,
|
||||
sid=self._solution["sid"],
|
||||
)
|
||||
|
||||
def update(
|
||||
self, friendly_name: Union[str, object] = values.unset
|
||||
) -> PublicKeyInstance:
|
||||
"""
|
||||
Update the PublicKeyInstance
|
||||
|
||||
:param friendly_name: A descriptive string that you create to describe the resource. It can be up to 64 characters long.
|
||||
|
||||
:returns: The updated PublicKeyInstance
|
||||
"""
|
||||
data = values.of(
|
||||
{
|
||||
"FriendlyName": friendly_name,
|
||||
}
|
||||
)
|
||||
|
||||
payload = self._version.update(
|
||||
method="POST",
|
||||
uri=self._uri,
|
||||
data=data,
|
||||
)
|
||||
|
||||
return PublicKeyInstance(self._version, payload, sid=self._solution["sid"])
|
||||
|
||||
async def update_async(
|
||||
self, friendly_name: Union[str, object] = values.unset
|
||||
) -> PublicKeyInstance:
|
||||
"""
|
||||
Asynchronous coroutine to update the PublicKeyInstance
|
||||
|
||||
:param friendly_name: A descriptive string that you create to describe the resource. It can be up to 64 characters long.
|
||||
|
||||
:returns: The updated PublicKeyInstance
|
||||
"""
|
||||
data = values.of(
|
||||
{
|
||||
"FriendlyName": friendly_name,
|
||||
}
|
||||
)
|
||||
|
||||
payload = await self._version.update_async(
|
||||
method="POST",
|
||||
uri=self._uri,
|
||||
data=data,
|
||||
)
|
||||
|
||||
return PublicKeyInstance(self._version, payload, sid=self._solution["sid"])
|
||||
|
||||
def __repr__(self) -> str:
|
||||
"""
|
||||
Provide a friendly representation
|
||||
|
||||
:returns: Machine friendly representation
|
||||
"""
|
||||
context = " ".join("{}={}".format(k, v) for k, v in self._solution.items())
|
||||
return "<Twilio.Accounts.V1.PublicKeyContext {}>".format(context)
|
||||
|
||||
|
||||
class PublicKeyPage(Page):
|
||||
def get_instance(self, payload: Dict[str, Any]) -> PublicKeyInstance:
|
||||
"""
|
||||
Build an instance of PublicKeyInstance
|
||||
|
||||
:param payload: Payload response from the API
|
||||
"""
|
||||
return PublicKeyInstance(self._version, payload)
|
||||
|
||||
def __repr__(self) -> str:
|
||||
"""
|
||||
Provide a friendly representation
|
||||
|
||||
:returns: Machine friendly representation
|
||||
"""
|
||||
return "<Twilio.Accounts.V1.PublicKeyPage>"
|
||||
|
||||
|
||||
class PublicKeyList(ListResource):
|
||||
def __init__(self, version: Version):
|
||||
"""
|
||||
Initialize the PublicKeyList
|
||||
|
||||
:param version: Version that contains the resource
|
||||
|
||||
"""
|
||||
super().__init__(version)
|
||||
|
||||
self._uri = "/Credentials/PublicKeys"
|
||||
|
||||
def create(
|
||||
self,
|
||||
public_key: str,
|
||||
friendly_name: Union[str, object] = values.unset,
|
||||
account_sid: Union[str, object] = values.unset,
|
||||
) -> PublicKeyInstance:
|
||||
"""
|
||||
Create the PublicKeyInstance
|
||||
|
||||
:param public_key: A URL encoded representation of the public key. For example, `-----BEGIN PUBLIC KEY-----MIIBIjANB.pa9xQIDAQAB-----END PUBLIC KEY-----`
|
||||
:param friendly_name: A descriptive string that you create to describe the resource. It can be up to 64 characters long.
|
||||
:param account_sid: The SID of the Subaccount that this Credential should be associated with. Must be a valid Subaccount of the account issuing the request
|
||||
|
||||
:returns: The created PublicKeyInstance
|
||||
"""
|
||||
data = values.of(
|
||||
{
|
||||
"PublicKey": public_key,
|
||||
"FriendlyName": friendly_name,
|
||||
"AccountSid": account_sid,
|
||||
}
|
||||
)
|
||||
|
||||
payload = self._version.create(
|
||||
method="POST",
|
||||
uri=self._uri,
|
||||
data=data,
|
||||
)
|
||||
|
||||
return PublicKeyInstance(self._version, payload)
|
||||
|
||||
async def create_async(
|
||||
self,
|
||||
public_key: str,
|
||||
friendly_name: Union[str, object] = values.unset,
|
||||
account_sid: Union[str, object] = values.unset,
|
||||
) -> PublicKeyInstance:
|
||||
"""
|
||||
Asynchronously create the PublicKeyInstance
|
||||
|
||||
:param public_key: A URL encoded representation of the public key. For example, `-----BEGIN PUBLIC KEY-----MIIBIjANB.pa9xQIDAQAB-----END PUBLIC KEY-----`
|
||||
:param friendly_name: A descriptive string that you create to describe the resource. It can be up to 64 characters long.
|
||||
:param account_sid: The SID of the Subaccount that this Credential should be associated with. Must be a valid Subaccount of the account issuing the request
|
||||
|
||||
:returns: The created PublicKeyInstance
|
||||
"""
|
||||
data = values.of(
|
||||
{
|
||||
"PublicKey": public_key,
|
||||
"FriendlyName": friendly_name,
|
||||
"AccountSid": account_sid,
|
||||
}
|
||||
)
|
||||
|
||||
payload = await self._version.create_async(
|
||||
method="POST",
|
||||
uri=self._uri,
|
||||
data=data,
|
||||
)
|
||||
|
||||
return PublicKeyInstance(self._version, payload)
|
||||
|
||||
def stream(
|
||||
self,
|
||||
limit: Optional[int] = None,
|
||||
page_size: Optional[int] = None,
|
||||
) -> Iterator[PublicKeyInstance]:
|
||||
"""
|
||||
Streams PublicKeyInstance records from the API as a generator stream.
|
||||
This operation lazily loads records as efficiently as possible until the limit
|
||||
is reached.
|
||||
The results are returned as a generator, so this operation is memory efficient.
|
||||
|
||||
:param limit: Upper limit for the number of records to return. stream()
|
||||
guarantees to never return more than limit. Default is no limit
|
||||
:param page_size: Number of records to fetch per request, when not set will use
|
||||
the default value of 50 records. If no page_size is defined
|
||||
but a limit is defined, stream() will attempt to read the
|
||||
limit with the most efficient page size, i.e. min(limit, 1000)
|
||||
|
||||
:returns: Generator that will yield up to limit results
|
||||
"""
|
||||
limits = self._version.read_limits(limit, page_size)
|
||||
page = self.page(page_size=limits["page_size"])
|
||||
|
||||
return self._version.stream(page, limits["limit"])
|
||||
|
||||
async def stream_async(
|
||||
self,
|
||||
limit: Optional[int] = None,
|
||||
page_size: Optional[int] = None,
|
||||
) -> AsyncIterator[PublicKeyInstance]:
|
||||
"""
|
||||
Asynchronously streams PublicKeyInstance records from the API as a generator stream.
|
||||
This operation lazily loads records as efficiently as possible until the limit
|
||||
is reached.
|
||||
The results are returned as a generator, so this operation is memory efficient.
|
||||
|
||||
:param limit: Upper limit for the number of records to return. stream()
|
||||
guarantees to never return more than limit. Default is no limit
|
||||
:param page_size: Number of records to fetch per request, when not set will use
|
||||
the default value of 50 records. If no page_size is defined
|
||||
but a limit is defined, stream() will attempt to read the
|
||||
limit with the most efficient page size, i.e. min(limit, 1000)
|
||||
|
||||
:returns: Generator that will yield up to limit results
|
||||
"""
|
||||
limits = self._version.read_limits(limit, page_size)
|
||||
page = await self.page_async(page_size=limits["page_size"])
|
||||
|
||||
return self._version.stream_async(page, limits["limit"])
|
||||
|
||||
def list(
|
||||
self,
|
||||
limit: Optional[int] = None,
|
||||
page_size: Optional[int] = None,
|
||||
) -> List[PublicKeyInstance]:
|
||||
"""
|
||||
Lists PublicKeyInstance records from the API as a list.
|
||||
Unlike stream(), this operation is eager and will load `limit` records into
|
||||
memory before returning.
|
||||
|
||||
:param limit: Upper limit for the number of records to return. list() guarantees
|
||||
never to return more than limit. Default is no limit
|
||||
:param page_size: Number of records to fetch per request, when not set will use
|
||||
the default value of 50 records. If no page_size is defined
|
||||
but a limit is defined, list() will attempt to read the limit
|
||||
with the most efficient page size, i.e. min(limit, 1000)
|
||||
|
||||
:returns: list that will contain up to limit results
|
||||
"""
|
||||
return list(
|
||||
self.stream(
|
||||
limit=limit,
|
||||
page_size=page_size,
|
||||
)
|
||||
)
|
||||
|
||||
async def list_async(
|
||||
self,
|
||||
limit: Optional[int] = None,
|
||||
page_size: Optional[int] = None,
|
||||
) -> List[PublicKeyInstance]:
|
||||
"""
|
||||
Asynchronously lists PublicKeyInstance records from the API as a list.
|
||||
Unlike stream(), this operation is eager and will load `limit` records into
|
||||
memory before returning.
|
||||
|
||||
:param limit: Upper limit for the number of records to return. list() guarantees
|
||||
never to return more than limit. Default is no limit
|
||||
:param page_size: Number of records to fetch per request, when not set will use
|
||||
the default value of 50 records. If no page_size is defined
|
||||
but a limit is defined, list() will attempt to read the limit
|
||||
with the most efficient page size, i.e. min(limit, 1000)
|
||||
|
||||
:returns: list that will contain up to limit results
|
||||
"""
|
||||
return [
|
||||
record
|
||||
async for record in await self.stream_async(
|
||||
limit=limit,
|
||||
page_size=page_size,
|
||||
)
|
||||
]
|
||||
|
||||
def page(
|
||||
self,
|
||||
page_token: Union[str, object] = values.unset,
|
||||
page_number: Union[int, object] = values.unset,
|
||||
page_size: Union[int, object] = values.unset,
|
||||
) -> PublicKeyPage:
|
||||
"""
|
||||
Retrieve a single page of PublicKeyInstance records from the API.
|
||||
Request is executed immediately
|
||||
|
||||
:param page_token: PageToken provided by the API
|
||||
:param page_number: Page Number, this value is simply for client state
|
||||
:param page_size: Number of records to return, defaults to 50
|
||||
|
||||
:returns: Page of PublicKeyInstance
|
||||
"""
|
||||
data = values.of(
|
||||
{
|
||||
"PageToken": page_token,
|
||||
"Page": page_number,
|
||||
"PageSize": page_size,
|
||||
}
|
||||
)
|
||||
|
||||
response = self._version.page(method="GET", uri=self._uri, params=data)
|
||||
return PublicKeyPage(self._version, response)
|
||||
|
||||
async def page_async(
|
||||
self,
|
||||
page_token: Union[str, object] = values.unset,
|
||||
page_number: Union[int, object] = values.unset,
|
||||
page_size: Union[int, object] = values.unset,
|
||||
) -> PublicKeyPage:
|
||||
"""
|
||||
Asynchronously retrieve a single page of PublicKeyInstance records from the API.
|
||||
Request is executed immediately
|
||||
|
||||
:param page_token: PageToken provided by the API
|
||||
:param page_number: Page Number, this value is simply for client state
|
||||
:param page_size: Number of records to return, defaults to 50
|
||||
|
||||
:returns: Page of PublicKeyInstance
|
||||
"""
|
||||
data = values.of(
|
||||
{
|
||||
"PageToken": page_token,
|
||||
"Page": page_number,
|
||||
"PageSize": page_size,
|
||||
}
|
||||
)
|
||||
|
||||
response = await self._version.page_async(
|
||||
method="GET", uri=self._uri, params=data
|
||||
)
|
||||
return PublicKeyPage(self._version, response)
|
||||
|
||||
def get_page(self, target_url: str) -> PublicKeyPage:
|
||||
"""
|
||||
Retrieve a specific page of PublicKeyInstance records from the API.
|
||||
Request is executed immediately
|
||||
|
||||
:param target_url: API-generated URL for the requested results page
|
||||
|
||||
:returns: Page of PublicKeyInstance
|
||||
"""
|
||||
response = self._version.domain.twilio.request("GET", target_url)
|
||||
return PublicKeyPage(self._version, response)
|
||||
|
||||
async def get_page_async(self, target_url: str) -> PublicKeyPage:
|
||||
"""
|
||||
Asynchronously retrieve a specific page of PublicKeyInstance records from the API.
|
||||
Request is executed immediately
|
||||
|
||||
:param target_url: API-generated URL for the requested results page
|
||||
|
||||
:returns: Page of PublicKeyInstance
|
||||
"""
|
||||
response = await self._version.domain.twilio.request_async("GET", target_url)
|
||||
return PublicKeyPage(self._version, response)
|
||||
|
||||
def get(self, sid: str) -> PublicKeyContext:
|
||||
"""
|
||||
Constructs a PublicKeyContext
|
||||
|
||||
:param sid: The Twilio-provided string that uniquely identifies the PublicKey resource to update.
|
||||
"""
|
||||
return PublicKeyContext(self._version, sid=sid)
|
||||
|
||||
def __call__(self, sid: str) -> PublicKeyContext:
|
||||
"""
|
||||
Constructs a PublicKeyContext
|
||||
|
||||
:param sid: The Twilio-provided string that uniquely identifies the PublicKey resource to update.
|
||||
"""
|
||||
return PublicKeyContext(self._version, sid=sid)
|
||||
|
||||
def __repr__(self) -> str:
|
||||
"""
|
||||
Provide a friendly representation
|
||||
|
||||
:returns: Machine friendly representation
|
||||
"""
|
||||
return "<Twilio.Accounts.V1.PublicKeyList>"
|
||||
@@ -0,0 +1,129 @@
|
||||
r"""
|
||||
This code was generated by
|
||||
___ _ _ _ _ _ _ ____ ____ ____ _ ____ ____ _ _ ____ ____ ____ ___ __ __
|
||||
| | | | | | | | | __ | | |__| | __ | __ |___ |\ | |___ |__/ |__| | | | |__/
|
||||
| |_|_| | |___ | |__| |__| | | | |__] |___ | \| |___ | \ | | | |__| | \
|
||||
|
||||
Twilio - Accounts
|
||||
This is the public Twilio REST API.
|
||||
|
||||
NOTE: This class is auto generated by OpenAPI Generator.
|
||||
https://openapi-generator.tech
|
||||
Do not edit the class manually.
|
||||
"""
|
||||
|
||||
|
||||
from typing import Any, Dict, Optional
|
||||
from twilio.base import values
|
||||
|
||||
from twilio.base.instance_resource import InstanceResource
|
||||
from twilio.base.list_resource import ListResource
|
||||
from twilio.base.version import Version
|
||||
|
||||
|
||||
class SafelistInstance(InstanceResource):
|
||||
|
||||
"""
|
||||
:ivar sid: The unique string that we created to identify the SafeList resource.
|
||||
:ivar phone_number: The phone number in SafeList.
|
||||
"""
|
||||
|
||||
def __init__(self, version: Version, payload: Dict[str, Any]):
|
||||
super().__init__(version)
|
||||
|
||||
self.sid: Optional[str] = payload.get("sid")
|
||||
self.phone_number: Optional[str] = payload.get("phone_number")
|
||||
|
||||
def __repr__(self) -> str:
|
||||
"""
|
||||
Provide a friendly representation
|
||||
|
||||
:returns: Machine friendly representation
|
||||
"""
|
||||
|
||||
return "<Twilio.Accounts.V1.SafelistInstance>"
|
||||
|
||||
|
||||
class SafelistList(ListResource):
|
||||
def __init__(self, version: Version):
|
||||
"""
|
||||
Initialize the SafelistList
|
||||
|
||||
:param version: Version that contains the resource
|
||||
|
||||
"""
|
||||
super().__init__(version)
|
||||
|
||||
self._uri = "/SafeList/Numbers"
|
||||
|
||||
def create(self, phone_number: str) -> SafelistInstance:
|
||||
"""
|
||||
Create the SafelistInstance
|
||||
|
||||
:param phone_number: The phone number to be added in SafeList. Phone numbers must be in [E.164 format](https://www.twilio.com/docs/glossary/what-e164).
|
||||
|
||||
:returns: The created SafelistInstance
|
||||
"""
|
||||
data = values.of(
|
||||
{
|
||||
"PhoneNumber": phone_number,
|
||||
}
|
||||
)
|
||||
|
||||
payload = self._version.create(
|
||||
method="POST",
|
||||
uri=self._uri,
|
||||
data=data,
|
||||
)
|
||||
|
||||
return SafelistInstance(self._version, payload)
|
||||
|
||||
async def create_async(self, phone_number: str) -> SafelistInstance:
|
||||
"""
|
||||
Asynchronously create the SafelistInstance
|
||||
|
||||
:param phone_number: The phone number to be added in SafeList. Phone numbers must be in [E.164 format](https://www.twilio.com/docs/glossary/what-e164).
|
||||
|
||||
:returns: The created SafelistInstance
|
||||
"""
|
||||
data = values.of(
|
||||
{
|
||||
"PhoneNumber": phone_number,
|
||||
}
|
||||
)
|
||||
|
||||
payload = await self._version.create_async(
|
||||
method="POST",
|
||||
uri=self._uri,
|
||||
data=data,
|
||||
)
|
||||
|
||||
return SafelistInstance(self._version, payload)
|
||||
|
||||
def fetch(self) -> SafelistInstance:
|
||||
"""
|
||||
Asynchronously fetch the SafelistInstance
|
||||
|
||||
:returns: The fetched SafelistInstance
|
||||
"""
|
||||
payload = self._version.fetch(method="GET", uri=self._uri)
|
||||
|
||||
return SafelistInstance(self._version, payload)
|
||||
|
||||
async def fetch_async(self) -> SafelistInstance:
|
||||
"""
|
||||
Asynchronously fetch the SafelistInstance
|
||||
|
||||
:returns: The fetched SafelistInstance
|
||||
"""
|
||||
payload = await self._version.fetch_async(method="GET", uri=self._uri)
|
||||
|
||||
return SafelistInstance(self._version, payload)
|
||||
|
||||
def __repr__(self) -> str:
|
||||
"""
|
||||
Provide a friendly representation
|
||||
|
||||
:returns: Machine friendly representation
|
||||
"""
|
||||
return "<Twilio.Accounts.V1.SafelistList>"
|
||||
@@ -0,0 +1,213 @@
|
||||
r"""
|
||||
This code was generated by
|
||||
___ _ _ _ _ _ _ ____ ____ ____ _ ____ ____ _ _ ____ ____ ____ ___ __ __
|
||||
| | | | | | | | | __ | | |__| | __ | __ |___ |\ | |___ |__/ |__| | | | |__/
|
||||
| |_|_| | |___ | |__| |__| | | | |__] |___ | \| |___ | \ | | | |__| | \
|
||||
|
||||
Twilio - Accounts
|
||||
This is the public Twilio REST API.
|
||||
|
||||
NOTE: This class is auto generated by OpenAPI Generator.
|
||||
https://openapi-generator.tech
|
||||
Do not edit the class manually.
|
||||
"""
|
||||
|
||||
|
||||
from datetime import datetime
|
||||
from typing import Any, Dict, Optional
|
||||
from twilio.base import deserialize, values
|
||||
from twilio.base.instance_context import InstanceContext
|
||||
from twilio.base.instance_resource import InstanceResource
|
||||
from twilio.base.list_resource import ListResource
|
||||
from twilio.base.version import Version
|
||||
|
||||
|
||||
class SecondaryAuthTokenInstance(InstanceResource):
|
||||
|
||||
"""
|
||||
:ivar account_sid: The SID of the [Account](https://www.twilio.com/docs/iam/api/account) that the secondary Auth Token was created for.
|
||||
:ivar date_created: The date and time in UTC when the resource was created specified in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format.
|
||||
:ivar date_updated: The date and time in UTC when the resource was last updated specified in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format.
|
||||
:ivar secondary_auth_token: The generated secondary Auth Token that can be used to authenticate future API requests.
|
||||
:ivar url: The URI for this resource, relative to `https://accounts.twilio.com`
|
||||
"""
|
||||
|
||||
def __init__(self, version: Version, payload: Dict[str, Any]):
|
||||
super().__init__(version)
|
||||
|
||||
self.account_sid: Optional[str] = payload.get("account_sid")
|
||||
self.date_created: Optional[datetime] = deserialize.iso8601_datetime(
|
||||
payload.get("date_created")
|
||||
)
|
||||
self.date_updated: Optional[datetime] = deserialize.iso8601_datetime(
|
||||
payload.get("date_updated")
|
||||
)
|
||||
self.secondary_auth_token: Optional[str] = payload.get("secondary_auth_token")
|
||||
self.url: Optional[str] = payload.get("url")
|
||||
|
||||
self._context: Optional[SecondaryAuthTokenContext] = None
|
||||
|
||||
@property
|
||||
def _proxy(self) -> "SecondaryAuthTokenContext":
|
||||
"""
|
||||
Generate an instance context for the instance, the context is capable of
|
||||
performing various actions. All instance actions are proxied to the context
|
||||
|
||||
:returns: SecondaryAuthTokenContext for this SecondaryAuthTokenInstance
|
||||
"""
|
||||
if self._context is None:
|
||||
self._context = SecondaryAuthTokenContext(
|
||||
self._version,
|
||||
)
|
||||
return self._context
|
||||
|
||||
def create(self) -> "SecondaryAuthTokenInstance":
|
||||
"""
|
||||
Create the SecondaryAuthTokenInstance
|
||||
|
||||
|
||||
:returns: The created SecondaryAuthTokenInstance
|
||||
"""
|
||||
return self._proxy.create()
|
||||
|
||||
async def create_async(self) -> "SecondaryAuthTokenInstance":
|
||||
"""
|
||||
Asynchronous coroutine to create the SecondaryAuthTokenInstance
|
||||
|
||||
|
||||
:returns: The created SecondaryAuthTokenInstance
|
||||
"""
|
||||
return await self._proxy.create_async()
|
||||
|
||||
def delete(self) -> bool:
|
||||
"""
|
||||
Deletes the SecondaryAuthTokenInstance
|
||||
|
||||
|
||||
:returns: True if delete succeeds, False otherwise
|
||||
"""
|
||||
return self._proxy.delete()
|
||||
|
||||
async def delete_async(self) -> bool:
|
||||
"""
|
||||
Asynchronous coroutine that deletes the SecondaryAuthTokenInstance
|
||||
|
||||
|
||||
:returns: True if delete succeeds, False otherwise
|
||||
"""
|
||||
return await self._proxy.delete_async()
|
||||
|
||||
def __repr__(self) -> str:
|
||||
"""
|
||||
Provide a friendly representation
|
||||
|
||||
:returns: Machine friendly representation
|
||||
"""
|
||||
|
||||
return "<Twilio.Accounts.V1.SecondaryAuthTokenInstance>"
|
||||
|
||||
|
||||
class SecondaryAuthTokenContext(InstanceContext):
|
||||
def __init__(self, version: Version):
|
||||
"""
|
||||
Initialize the SecondaryAuthTokenContext
|
||||
|
||||
:param version: Version that contains the resource
|
||||
"""
|
||||
super().__init__(version)
|
||||
|
||||
self._uri = "/AuthTokens/Secondary"
|
||||
|
||||
def create(self) -> SecondaryAuthTokenInstance:
|
||||
"""
|
||||
Create the SecondaryAuthTokenInstance
|
||||
|
||||
|
||||
:returns: The created SecondaryAuthTokenInstance
|
||||
"""
|
||||
data = values.of({})
|
||||
|
||||
payload = self._version.create(method="POST", uri=self._uri, data=data)
|
||||
|
||||
return SecondaryAuthTokenInstance(self._version, payload)
|
||||
|
||||
async def create_async(self) -> SecondaryAuthTokenInstance:
|
||||
"""
|
||||
Asynchronous coroutine to create the SecondaryAuthTokenInstance
|
||||
|
||||
|
||||
:returns: The created SecondaryAuthTokenInstance
|
||||
"""
|
||||
data = values.of({})
|
||||
|
||||
payload = await self._version.create_async(
|
||||
method="POST", uri=self._uri, data=data
|
||||
)
|
||||
|
||||
return SecondaryAuthTokenInstance(self._version, payload)
|
||||
|
||||
def delete(self) -> bool:
|
||||
"""
|
||||
Deletes the SecondaryAuthTokenInstance
|
||||
|
||||
|
||||
:returns: True if delete succeeds, False otherwise
|
||||
"""
|
||||
return self._version.delete(
|
||||
method="DELETE",
|
||||
uri=self._uri,
|
||||
)
|
||||
|
||||
async def delete_async(self) -> bool:
|
||||
"""
|
||||
Asynchronous coroutine that deletes the SecondaryAuthTokenInstance
|
||||
|
||||
|
||||
:returns: True if delete succeeds, False otherwise
|
||||
"""
|
||||
return await self._version.delete_async(
|
||||
method="DELETE",
|
||||
uri=self._uri,
|
||||
)
|
||||
|
||||
def __repr__(self) -> str:
|
||||
"""
|
||||
Provide a friendly representation
|
||||
|
||||
:returns: Machine friendly representation
|
||||
"""
|
||||
|
||||
return "<Twilio.Accounts.V1.SecondaryAuthTokenContext>"
|
||||
|
||||
|
||||
class SecondaryAuthTokenList(ListResource):
|
||||
def __init__(self, version: Version):
|
||||
"""
|
||||
Initialize the SecondaryAuthTokenList
|
||||
|
||||
:param version: Version that contains the resource
|
||||
|
||||
"""
|
||||
super().__init__(version)
|
||||
|
||||
def get(self) -> SecondaryAuthTokenContext:
|
||||
"""
|
||||
Constructs a SecondaryAuthTokenContext
|
||||
|
||||
"""
|
||||
return SecondaryAuthTokenContext(self._version)
|
||||
|
||||
def __call__(self) -> SecondaryAuthTokenContext:
|
||||
"""
|
||||
Constructs a SecondaryAuthTokenContext
|
||||
|
||||
"""
|
||||
return SecondaryAuthTokenContext(self._version)
|
||||
|
||||
def __repr__(self) -> str:
|
||||
"""
|
||||
Provide a friendly representation
|
||||
|
||||
:returns: Machine friendly representation
|
||||
"""
|
||||
return "<Twilio.Accounts.V1.SecondaryAuthTokenList>"
|
||||
@@ -0,0 +1,43 @@
|
||||
r"""
|
||||
This code was generated by
|
||||
___ _ _ _ _ _ _ ____ ____ ____ _ ____ ____ _ _ ____ ____ ____ ___ __ __
|
||||
| | | | | | | | | __ | | |__| | __ | __ |___ |\ | |___ |__/ |__| | | | |__/
|
||||
| |_|_| | |___ | |__| |__| | | | |__] |___ | \| |___ | \ | | | |__| | \
|
||||
|
||||
NOTE: This class is auto generated by OpenAPI Generator.
|
||||
https://openapi-generator.tech
|
||||
Do not edit the class manually.
|
||||
"""
|
||||
|
||||
from typing import Optional
|
||||
|
||||
from twilio.base.domain import Domain
|
||||
from twilio.rest import Client
|
||||
from twilio.rest.api.v2010 import V2010
|
||||
|
||||
|
||||
class ApiBase(Domain):
|
||||
def __init__(self, twilio: Client):
|
||||
"""
|
||||
Initialize the Api Domain
|
||||
|
||||
:returns: Domain for Api
|
||||
"""
|
||||
super().__init__(twilio, "https://api.twilio.com")
|
||||
self._v2010: Optional[V2010] = None
|
||||
|
||||
@property
|
||||
def v2010(self) -> V2010:
|
||||
"""
|
||||
:returns: Versions v2010 of Api
|
||||
"""
|
||||
if self._v2010 is None:
|
||||
self._v2010 = V2010(self)
|
||||
return self._v2010
|
||||
|
||||
def __repr__(self) -> str:
|
||||
"""
|
||||
Provide a friendly representation
|
||||
:returns: Machine friendly representation
|
||||
"""
|
||||
return "<Twilio.Api>"
|
||||
@@ -0,0 +1,258 @@
|
||||
from warnings import warn
|
||||
|
||||
from twilio.rest.api.ApiBase import ApiBase
|
||||
from twilio.rest.api.v2010.account import AccountContext, AccountList
|
||||
from twilio.rest.api.v2010.account.address import AddressList
|
||||
from twilio.rest.api.v2010.account.application import ApplicationList
|
||||
from twilio.rest.api.v2010.account.authorized_connect_app import (
|
||||
AuthorizedConnectAppList,
|
||||
)
|
||||
from twilio.rest.api.v2010.account.available_phone_number_country import (
|
||||
AvailablePhoneNumberCountryList,
|
||||
)
|
||||
from twilio.rest.api.v2010.account.balance import BalanceList
|
||||
from twilio.rest.api.v2010.account.call import CallList
|
||||
from twilio.rest.api.v2010.account.conference import ConferenceList
|
||||
from twilio.rest.api.v2010.account.connect_app import ConnectAppList
|
||||
from twilio.rest.api.v2010.account.incoming_phone_number import IncomingPhoneNumberList
|
||||
from twilio.rest.api.v2010.account.key import KeyList
|
||||
from twilio.rest.api.v2010.account.message import MessageList
|
||||
from twilio.rest.api.v2010.account.new_key import NewKeyList
|
||||
from twilio.rest.api.v2010.account.new_signing_key import NewSigningKeyList
|
||||
from twilio.rest.api.v2010.account.notification import NotificationList
|
||||
from twilio.rest.api.v2010.account.outgoing_caller_id import OutgoingCallerIdList
|
||||
from twilio.rest.api.v2010.account.queue import QueueList
|
||||
from twilio.rest.api.v2010.account.recording import RecordingList
|
||||
from twilio.rest.api.v2010.account.short_code import ShortCodeList
|
||||
from twilio.rest.api.v2010.account.signing_key import SigningKeyList
|
||||
from twilio.rest.api.v2010.account.sip import SipList
|
||||
from twilio.rest.api.v2010.account.token import TokenList
|
||||
from twilio.rest.api.v2010.account.transcription import TranscriptionList
|
||||
from twilio.rest.api.v2010.account.usage import UsageList
|
||||
from twilio.rest.api.v2010.account.validation_request import ValidationRequestList
|
||||
|
||||
|
||||
class Api(ApiBase):
|
||||
@property
|
||||
def account(self) -> AccountContext:
|
||||
return self.v2010.account
|
||||
|
||||
@property
|
||||
def accounts(self) -> AccountList:
|
||||
return self.v2010.accounts
|
||||
|
||||
@property
|
||||
def addresses(self) -> AddressList:
|
||||
warn(
|
||||
"addresses is deprecated. Use account.addresses instead.",
|
||||
DeprecationWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
return self.account.addresses
|
||||
|
||||
@property
|
||||
def applications(self) -> ApplicationList:
|
||||
warn(
|
||||
"applications is deprecated. Use account.applications instead.",
|
||||
DeprecationWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
return self.account.applications
|
||||
|
||||
@property
|
||||
def authorized_connect_apps(self) -> AuthorizedConnectAppList:
|
||||
warn(
|
||||
"authorized_connect_apps is deprecated. Use account.authorized_connect_apps instead.",
|
||||
DeprecationWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
return self.account.authorized_connect_apps
|
||||
|
||||
@property
|
||||
def available_phone_numbers(self) -> AvailablePhoneNumberCountryList:
|
||||
warn(
|
||||
"available_phone_numbers is deprecated. Use account.available_phone_numbers instead.",
|
||||
DeprecationWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
return self.account.available_phone_numbers
|
||||
|
||||
@property
|
||||
def balance(self) -> BalanceList:
|
||||
warn(
|
||||
"balance is deprecated. Use account.balance instead.",
|
||||
DeprecationWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
return self.account.balance
|
||||
|
||||
@property
|
||||
def calls(self) -> CallList:
|
||||
warn(
|
||||
"calls is deprecated. Use account.calls instead.",
|
||||
DeprecationWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
return self.account.calls
|
||||
|
||||
@property
|
||||
def conferences(self) -> ConferenceList:
|
||||
warn(
|
||||
"conferences is deprecated. Use account.conferences instead.",
|
||||
DeprecationWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
return self.account.conferences
|
||||
|
||||
@property
|
||||
def connect_apps(self) -> ConnectAppList:
|
||||
warn(
|
||||
"connect_apps is deprecated. Use account.connect_apps instead.",
|
||||
DeprecationWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
return self.account.connect_apps
|
||||
|
||||
@property
|
||||
def incoming_phone_numbers(self) -> IncomingPhoneNumberList:
|
||||
warn(
|
||||
"incoming_phone_numbers is deprecated. Use account.incoming_phone_numbers instead.",
|
||||
DeprecationWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
return self.account.incoming_phone_numbers
|
||||
|
||||
@property
|
||||
def keys(self) -> KeyList:
|
||||
warn(
|
||||
"keys is deprecated. Use account.keys instead.",
|
||||
DeprecationWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
return self.account.keys
|
||||
|
||||
@property
|
||||
def messages(self) -> MessageList:
|
||||
warn(
|
||||
"messages is deprecated. Use account.messages instead.",
|
||||
DeprecationWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
return self.account.messages
|
||||
|
||||
@property
|
||||
def new_keys(self) -> NewKeyList:
|
||||
warn(
|
||||
"new_keys is deprecated. Use account.new_keys instead.",
|
||||
DeprecationWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
return self.account.new_keys
|
||||
|
||||
@property
|
||||
def new_signing_keys(self) -> NewSigningKeyList:
|
||||
warn(
|
||||
"new_signing_keys is deprecated. Use account.new_signing_keys instead.",
|
||||
DeprecationWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
return self.account.new_signing_keys
|
||||
|
||||
@property
|
||||
def notifications(self) -> NotificationList:
|
||||
warn(
|
||||
"notifications is deprecated. Use account.notifications instead.",
|
||||
DeprecationWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
return self.account.notifications
|
||||
|
||||
@property
|
||||
def outgoing_caller_ids(self) -> OutgoingCallerIdList:
|
||||
warn(
|
||||
"outgoing_caller_ids is deprecated. Use account.outgoing_caller_ids instead.",
|
||||
DeprecationWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
return self.account.outgoing_caller_ids
|
||||
|
||||
@property
|
||||
def queues(self) -> QueueList:
|
||||
warn(
|
||||
"queues is deprecated. Use account.queues instead.",
|
||||
DeprecationWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
return self.account.queues
|
||||
|
||||
@property
|
||||
def recordings(self) -> RecordingList:
|
||||
warn(
|
||||
"recordings is deprecated. Use account.recordings instead.",
|
||||
DeprecationWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
return self.account.recordings
|
||||
|
||||
@property
|
||||
def signing_keys(self) -> SigningKeyList:
|
||||
warn(
|
||||
"signing_keys is deprecated. Use account.signing_keys instead.",
|
||||
DeprecationWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
return self.account.signing_keys
|
||||
|
||||
@property
|
||||
def sip(self) -> SipList:
|
||||
warn(
|
||||
"sip is deprecated. Use account.sip instead.",
|
||||
DeprecationWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
return self.account.sip
|
||||
|
||||
@property
|
||||
def short_codes(self) -> ShortCodeList:
|
||||
warn(
|
||||
"short_codes is deprecated. Use account.short_codes instead.",
|
||||
DeprecationWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
return self.account.short_codes
|
||||
|
||||
@property
|
||||
def tokens(self) -> TokenList:
|
||||
warn(
|
||||
"tokens is deprecated. Use account.tokens instead.",
|
||||
DeprecationWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
return self.account.tokens
|
||||
|
||||
@property
|
||||
def transcriptions(self) -> TranscriptionList:
|
||||
warn(
|
||||
"transcriptions is deprecated. Use account.transcriptions instead.",
|
||||
DeprecationWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
return self.account.transcriptions
|
||||
|
||||
@property
|
||||
def usage(self) -> UsageList:
|
||||
warn(
|
||||
"usage is deprecated. Use account.usage instead.",
|
||||
DeprecationWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
return self.account.usage
|
||||
|
||||
@property
|
||||
def validation_requests(self) -> ValidationRequestList:
|
||||
warn(
|
||||
"validation_requests is deprecated. Use account.validation_requests instead.",
|
||||
DeprecationWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
return self.account.validation_requests
|
||||
Binary file not shown.
BIN
Binary file not shown.
@@ -0,0 +1,58 @@
|
||||
r"""
|
||||
This code was generated by
|
||||
___ _ _ _ _ _ _ ____ ____ ____ _ ____ ____ _ _ ____ ____ ____ ___ __ __
|
||||
| | | | | | | | | __ | | |__| | __ | __ |___ |\ | |___ |__/ |__| | | | |__/
|
||||
| |_|_| | |___ | |__| |__| | | | |__] |___ | \| |___ | \ | | | |__| | \
|
||||
|
||||
Twilio - Api
|
||||
This is the public Twilio REST API.
|
||||
|
||||
NOTE: This class is auto generated by OpenAPI Generator.
|
||||
https://openapi-generator.tech
|
||||
Do not edit the class manually.
|
||||
"""
|
||||
|
||||
from typing import Optional
|
||||
from twilio.base.version import Version
|
||||
from twilio.base.domain import Domain
|
||||
from twilio.rest.api.v2010.account import AccountList
|
||||
from twilio.rest.api.v2010.account import AccountContext
|
||||
|
||||
|
||||
class V2010(Version):
|
||||
def __init__(self, domain: Domain):
|
||||
"""
|
||||
Initialize the V2010 version of Api
|
||||
|
||||
:param domain: The Twilio.api domain
|
||||
"""
|
||||
super().__init__(domain, "2010-04-01")
|
||||
self._accounts: Optional[AccountList] = None
|
||||
self._account: Optional[AccountContext] = None
|
||||
|
||||
@property
|
||||
def accounts(self) -> AccountList:
|
||||
if self._accounts is None:
|
||||
self._accounts = AccountList(self)
|
||||
return self._accounts
|
||||
|
||||
@property
|
||||
def account(self) -> AccountContext:
|
||||
if self._account is None:
|
||||
self._account = AccountContext(self, self.domain.twilio.account_sid)
|
||||
return self._account
|
||||
|
||||
@account.setter
|
||||
def account(self, value: AccountContext) -> None:
|
||||
"""
|
||||
Setter to override account
|
||||
:param value: value to use as account
|
||||
"""
|
||||
self._account = value
|
||||
|
||||
def __repr__(self) -> str:
|
||||
"""
|
||||
Provide a friendly representation
|
||||
:returns: Machine friendly representation
|
||||
"""
|
||||
return "<Twilio.Api.V2010>"
|
||||
BIN
Binary file not shown.
File diff suppressed because it is too large
Load Diff
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
@@ -0,0 +1,862 @@
|
||||
r"""
|
||||
This code was generated by
|
||||
___ _ _ _ _ _ _ ____ ____ ____ _ ____ ____ _ _ ____ ____ ____ ___ __ __
|
||||
| | | | | | | | | __ | | |__| | __ | __ |___ |\ | |___ |__/ |__| | | | |__/
|
||||
| |_|_| | |___ | |__| |__| | | | |__] |___ | \| |___ | \ | | | |__| | \
|
||||
|
||||
Twilio - Api
|
||||
This is the public Twilio REST API.
|
||||
|
||||
NOTE: This class is auto generated by OpenAPI Generator.
|
||||
https://openapi-generator.tech
|
||||
Do not edit the class manually.
|
||||
"""
|
||||
|
||||
|
||||
from datetime import datetime
|
||||
from typing import Any, Dict, List, Optional, Union, Iterator, AsyncIterator
|
||||
from twilio.base import deserialize, values
|
||||
from twilio.base.instance_context import InstanceContext
|
||||
from twilio.base.instance_resource import InstanceResource
|
||||
from twilio.base.list_resource import ListResource
|
||||
from twilio.base.version import Version
|
||||
from twilio.base.page import Page
|
||||
from twilio.rest.api.v2010.account.address.dependent_phone_number import (
|
||||
DependentPhoneNumberList,
|
||||
)
|
||||
|
||||
|
||||
class AddressInstance(InstanceResource):
|
||||
|
||||
"""
|
||||
:ivar account_sid: The SID of the [Account](https://www.twilio.com/docs/iam/api/account) that is responsible for the Address resource.
|
||||
:ivar city: The city in which the address is located.
|
||||
:ivar customer_name: The name associated with the address.This property has a maximum length of 16 4-byte characters, or 21 3-byte characters.
|
||||
:ivar date_created: The date and time in GMT that the resource was created specified in [RFC 2822](https://www.ietf.org/rfc/rfc2822.txt) format.
|
||||
:ivar date_updated: The date and time in GMT that the resource was last updated specified in [RFC 2822](https://www.ietf.org/rfc/rfc2822.txt) format.
|
||||
:ivar friendly_name: The string that you assigned to describe the resource.
|
||||
:ivar iso_country: The ISO country code of the address.
|
||||
:ivar postal_code: The postal code of the address.
|
||||
:ivar region: The state or region of the address.
|
||||
:ivar sid: The unique string that that we created to identify the Address resource.
|
||||
:ivar street: The number and street address of the address.
|
||||
:ivar uri: The URI of the resource, relative to `https://api.twilio.com`.
|
||||
:ivar emergency_enabled: Whether emergency calling has been enabled on this number.
|
||||
:ivar validated: Whether the address has been validated to comply with local regulation. In countries that require valid addresses, an invalid address will not be accepted. `true` indicates the Address has been validated. `false` indicate the country doesn't require validation or the Address is not valid.
|
||||
:ivar verified: Whether the address has been verified to comply with regulation. In countries that require valid addresses, an invalid address will not be accepted. `true` indicates the Address has been verified. `false` indicate the country doesn't require verified or the Address is not valid.
|
||||
:ivar street_secondary: The additional number and street address of the address.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
version: Version,
|
||||
payload: Dict[str, Any],
|
||||
account_sid: str,
|
||||
sid: Optional[str] = None,
|
||||
):
|
||||
super().__init__(version)
|
||||
|
||||
self.account_sid: Optional[str] = payload.get("account_sid")
|
||||
self.city: Optional[str] = payload.get("city")
|
||||
self.customer_name: Optional[str] = payload.get("customer_name")
|
||||
self.date_created: Optional[datetime] = deserialize.rfc2822_datetime(
|
||||
payload.get("date_created")
|
||||
)
|
||||
self.date_updated: Optional[datetime] = deserialize.rfc2822_datetime(
|
||||
payload.get("date_updated")
|
||||
)
|
||||
self.friendly_name: Optional[str] = payload.get("friendly_name")
|
||||
self.iso_country: Optional[str] = payload.get("iso_country")
|
||||
self.postal_code: Optional[str] = payload.get("postal_code")
|
||||
self.region: Optional[str] = payload.get("region")
|
||||
self.sid: Optional[str] = payload.get("sid")
|
||||
self.street: Optional[str] = payload.get("street")
|
||||
self.uri: Optional[str] = payload.get("uri")
|
||||
self.emergency_enabled: Optional[bool] = payload.get("emergency_enabled")
|
||||
self.validated: Optional[bool] = payload.get("validated")
|
||||
self.verified: Optional[bool] = payload.get("verified")
|
||||
self.street_secondary: Optional[str] = payload.get("street_secondary")
|
||||
|
||||
self._solution = {
|
||||
"account_sid": account_sid,
|
||||
"sid": sid or self.sid,
|
||||
}
|
||||
self._context: Optional[AddressContext] = None
|
||||
|
||||
@property
|
||||
def _proxy(self) -> "AddressContext":
|
||||
"""
|
||||
Generate an instance context for the instance, the context is capable of
|
||||
performing various actions. All instance actions are proxied to the context
|
||||
|
||||
:returns: AddressContext for this AddressInstance
|
||||
"""
|
||||
if self._context is None:
|
||||
self._context = AddressContext(
|
||||
self._version,
|
||||
account_sid=self._solution["account_sid"],
|
||||
sid=self._solution["sid"],
|
||||
)
|
||||
return self._context
|
||||
|
||||
def delete(self) -> bool:
|
||||
"""
|
||||
Deletes the AddressInstance
|
||||
|
||||
|
||||
:returns: True if delete succeeds, False otherwise
|
||||
"""
|
||||
return self._proxy.delete()
|
||||
|
||||
async def delete_async(self) -> bool:
|
||||
"""
|
||||
Asynchronous coroutine that deletes the AddressInstance
|
||||
|
||||
|
||||
:returns: True if delete succeeds, False otherwise
|
||||
"""
|
||||
return await self._proxy.delete_async()
|
||||
|
||||
def fetch(self) -> "AddressInstance":
|
||||
"""
|
||||
Fetch the AddressInstance
|
||||
|
||||
|
||||
:returns: The fetched AddressInstance
|
||||
"""
|
||||
return self._proxy.fetch()
|
||||
|
||||
async def fetch_async(self) -> "AddressInstance":
|
||||
"""
|
||||
Asynchronous coroutine to fetch the AddressInstance
|
||||
|
||||
|
||||
:returns: The fetched AddressInstance
|
||||
"""
|
||||
return await self._proxy.fetch_async()
|
||||
|
||||
def update(
|
||||
self,
|
||||
friendly_name: Union[str, object] = values.unset,
|
||||
customer_name: Union[str, object] = values.unset,
|
||||
street: Union[str, object] = values.unset,
|
||||
city: Union[str, object] = values.unset,
|
||||
region: Union[str, object] = values.unset,
|
||||
postal_code: Union[str, object] = values.unset,
|
||||
emergency_enabled: Union[bool, object] = values.unset,
|
||||
auto_correct_address: Union[bool, object] = values.unset,
|
||||
street_secondary: Union[str, object] = values.unset,
|
||||
) -> "AddressInstance":
|
||||
"""
|
||||
Update the AddressInstance
|
||||
|
||||
:param friendly_name: A descriptive string that you create to describe the address. It can be up to 64 characters long.
|
||||
:param customer_name: The name to associate with the address.
|
||||
:param street: The number and street address of the address.
|
||||
:param city: The city of the address.
|
||||
:param region: The state or region of the address.
|
||||
:param postal_code: The postal code of the address.
|
||||
:param emergency_enabled: Whether to enable emergency calling on the address. Can be: `true` or `false`.
|
||||
:param auto_correct_address: Whether we should automatically correct the address. Can be: `true` or `false` and the default is `true`. If empty or `true`, we will correct the address you provide if necessary. If `false`, we won't alter the address you provide.
|
||||
:param street_secondary: The additional number and street address of the address.
|
||||
|
||||
:returns: The updated AddressInstance
|
||||
"""
|
||||
return self._proxy.update(
|
||||
friendly_name=friendly_name,
|
||||
customer_name=customer_name,
|
||||
street=street,
|
||||
city=city,
|
||||
region=region,
|
||||
postal_code=postal_code,
|
||||
emergency_enabled=emergency_enabled,
|
||||
auto_correct_address=auto_correct_address,
|
||||
street_secondary=street_secondary,
|
||||
)
|
||||
|
||||
async def update_async(
|
||||
self,
|
||||
friendly_name: Union[str, object] = values.unset,
|
||||
customer_name: Union[str, object] = values.unset,
|
||||
street: Union[str, object] = values.unset,
|
||||
city: Union[str, object] = values.unset,
|
||||
region: Union[str, object] = values.unset,
|
||||
postal_code: Union[str, object] = values.unset,
|
||||
emergency_enabled: Union[bool, object] = values.unset,
|
||||
auto_correct_address: Union[bool, object] = values.unset,
|
||||
street_secondary: Union[str, object] = values.unset,
|
||||
) -> "AddressInstance":
|
||||
"""
|
||||
Asynchronous coroutine to update the AddressInstance
|
||||
|
||||
:param friendly_name: A descriptive string that you create to describe the address. It can be up to 64 characters long.
|
||||
:param customer_name: The name to associate with the address.
|
||||
:param street: The number and street address of the address.
|
||||
:param city: The city of the address.
|
||||
:param region: The state or region of the address.
|
||||
:param postal_code: The postal code of the address.
|
||||
:param emergency_enabled: Whether to enable emergency calling on the address. Can be: `true` or `false`.
|
||||
:param auto_correct_address: Whether we should automatically correct the address. Can be: `true` or `false` and the default is `true`. If empty or `true`, we will correct the address you provide if necessary. If `false`, we won't alter the address you provide.
|
||||
:param street_secondary: The additional number and street address of the address.
|
||||
|
||||
:returns: The updated AddressInstance
|
||||
"""
|
||||
return await self._proxy.update_async(
|
||||
friendly_name=friendly_name,
|
||||
customer_name=customer_name,
|
||||
street=street,
|
||||
city=city,
|
||||
region=region,
|
||||
postal_code=postal_code,
|
||||
emergency_enabled=emergency_enabled,
|
||||
auto_correct_address=auto_correct_address,
|
||||
street_secondary=street_secondary,
|
||||
)
|
||||
|
||||
@property
|
||||
def dependent_phone_numbers(self) -> DependentPhoneNumberList:
|
||||
"""
|
||||
Access the dependent_phone_numbers
|
||||
"""
|
||||
return self._proxy.dependent_phone_numbers
|
||||
|
||||
def __repr__(self) -> str:
|
||||
"""
|
||||
Provide a friendly representation
|
||||
|
||||
:returns: Machine friendly representation
|
||||
"""
|
||||
context = " ".join("{}={}".format(k, v) for k, v in self._solution.items())
|
||||
return "<Twilio.Api.V2010.AddressInstance {}>".format(context)
|
||||
|
||||
|
||||
class AddressContext(InstanceContext):
|
||||
def __init__(self, version: Version, account_sid: str, sid: str):
|
||||
"""
|
||||
Initialize the AddressContext
|
||||
|
||||
:param version: Version that contains the resource
|
||||
:param account_sid: The SID of the [Account](https://www.twilio.com/docs/iam/api/account) that is responsible for the Address resource to update.
|
||||
:param sid: The Twilio-provided string that uniquely identifies the Address resource to update.
|
||||
"""
|
||||
super().__init__(version)
|
||||
|
||||
# Path Solution
|
||||
self._solution = {
|
||||
"account_sid": account_sid,
|
||||
"sid": sid,
|
||||
}
|
||||
self._uri = "/Accounts/{account_sid}/Addresses/{sid}.json".format(
|
||||
**self._solution
|
||||
)
|
||||
|
||||
self._dependent_phone_numbers: Optional[DependentPhoneNumberList] = None
|
||||
|
||||
def delete(self) -> bool:
|
||||
"""
|
||||
Deletes the AddressInstance
|
||||
|
||||
|
||||
:returns: True if delete succeeds, False otherwise
|
||||
"""
|
||||
return self._version.delete(
|
||||
method="DELETE",
|
||||
uri=self._uri,
|
||||
)
|
||||
|
||||
async def delete_async(self) -> bool:
|
||||
"""
|
||||
Asynchronous coroutine that deletes the AddressInstance
|
||||
|
||||
|
||||
:returns: True if delete succeeds, False otherwise
|
||||
"""
|
||||
return await self._version.delete_async(
|
||||
method="DELETE",
|
||||
uri=self._uri,
|
||||
)
|
||||
|
||||
def fetch(self) -> AddressInstance:
|
||||
"""
|
||||
Fetch the AddressInstance
|
||||
|
||||
|
||||
:returns: The fetched AddressInstance
|
||||
"""
|
||||
|
||||
payload = self._version.fetch(
|
||||
method="GET",
|
||||
uri=self._uri,
|
||||
)
|
||||
|
||||
return AddressInstance(
|
||||
self._version,
|
||||
payload,
|
||||
account_sid=self._solution["account_sid"],
|
||||
sid=self._solution["sid"],
|
||||
)
|
||||
|
||||
async def fetch_async(self) -> AddressInstance:
|
||||
"""
|
||||
Asynchronous coroutine to fetch the AddressInstance
|
||||
|
||||
|
||||
:returns: The fetched AddressInstance
|
||||
"""
|
||||
|
||||
payload = await self._version.fetch_async(
|
||||
method="GET",
|
||||
uri=self._uri,
|
||||
)
|
||||
|
||||
return AddressInstance(
|
||||
self._version,
|
||||
payload,
|
||||
account_sid=self._solution["account_sid"],
|
||||
sid=self._solution["sid"],
|
||||
)
|
||||
|
||||
def update(
|
||||
self,
|
||||
friendly_name: Union[str, object] = values.unset,
|
||||
customer_name: Union[str, object] = values.unset,
|
||||
street: Union[str, object] = values.unset,
|
||||
city: Union[str, object] = values.unset,
|
||||
region: Union[str, object] = values.unset,
|
||||
postal_code: Union[str, object] = values.unset,
|
||||
emergency_enabled: Union[bool, object] = values.unset,
|
||||
auto_correct_address: Union[bool, object] = values.unset,
|
||||
street_secondary: Union[str, object] = values.unset,
|
||||
) -> AddressInstance:
|
||||
"""
|
||||
Update the AddressInstance
|
||||
|
||||
:param friendly_name: A descriptive string that you create to describe the address. It can be up to 64 characters long.
|
||||
:param customer_name: The name to associate with the address.
|
||||
:param street: The number and street address of the address.
|
||||
:param city: The city of the address.
|
||||
:param region: The state or region of the address.
|
||||
:param postal_code: The postal code of the address.
|
||||
:param emergency_enabled: Whether to enable emergency calling on the address. Can be: `true` or `false`.
|
||||
:param auto_correct_address: Whether we should automatically correct the address. Can be: `true` or `false` and the default is `true`. If empty or `true`, we will correct the address you provide if necessary. If `false`, we won't alter the address you provide.
|
||||
:param street_secondary: The additional number and street address of the address.
|
||||
|
||||
:returns: The updated AddressInstance
|
||||
"""
|
||||
data = values.of(
|
||||
{
|
||||
"FriendlyName": friendly_name,
|
||||
"CustomerName": customer_name,
|
||||
"Street": street,
|
||||
"City": city,
|
||||
"Region": region,
|
||||
"PostalCode": postal_code,
|
||||
"EmergencyEnabled": emergency_enabled,
|
||||
"AutoCorrectAddress": auto_correct_address,
|
||||
"StreetSecondary": street_secondary,
|
||||
}
|
||||
)
|
||||
|
||||
payload = self._version.update(
|
||||
method="POST",
|
||||
uri=self._uri,
|
||||
data=data,
|
||||
)
|
||||
|
||||
return AddressInstance(
|
||||
self._version,
|
||||
payload,
|
||||
account_sid=self._solution["account_sid"],
|
||||
sid=self._solution["sid"],
|
||||
)
|
||||
|
||||
async def update_async(
|
||||
self,
|
||||
friendly_name: Union[str, object] = values.unset,
|
||||
customer_name: Union[str, object] = values.unset,
|
||||
street: Union[str, object] = values.unset,
|
||||
city: Union[str, object] = values.unset,
|
||||
region: Union[str, object] = values.unset,
|
||||
postal_code: Union[str, object] = values.unset,
|
||||
emergency_enabled: Union[bool, object] = values.unset,
|
||||
auto_correct_address: Union[bool, object] = values.unset,
|
||||
street_secondary: Union[str, object] = values.unset,
|
||||
) -> AddressInstance:
|
||||
"""
|
||||
Asynchronous coroutine to update the AddressInstance
|
||||
|
||||
:param friendly_name: A descriptive string that you create to describe the address. It can be up to 64 characters long.
|
||||
:param customer_name: The name to associate with the address.
|
||||
:param street: The number and street address of the address.
|
||||
:param city: The city of the address.
|
||||
:param region: The state or region of the address.
|
||||
:param postal_code: The postal code of the address.
|
||||
:param emergency_enabled: Whether to enable emergency calling on the address. Can be: `true` or `false`.
|
||||
:param auto_correct_address: Whether we should automatically correct the address. Can be: `true` or `false` and the default is `true`. If empty or `true`, we will correct the address you provide if necessary. If `false`, we won't alter the address you provide.
|
||||
:param street_secondary: The additional number and street address of the address.
|
||||
|
||||
:returns: The updated AddressInstance
|
||||
"""
|
||||
data = values.of(
|
||||
{
|
||||
"FriendlyName": friendly_name,
|
||||
"CustomerName": customer_name,
|
||||
"Street": street,
|
||||
"City": city,
|
||||
"Region": region,
|
||||
"PostalCode": postal_code,
|
||||
"EmergencyEnabled": emergency_enabled,
|
||||
"AutoCorrectAddress": auto_correct_address,
|
||||
"StreetSecondary": street_secondary,
|
||||
}
|
||||
)
|
||||
|
||||
payload = await self._version.update_async(
|
||||
method="POST",
|
||||
uri=self._uri,
|
||||
data=data,
|
||||
)
|
||||
|
||||
return AddressInstance(
|
||||
self._version,
|
||||
payload,
|
||||
account_sid=self._solution["account_sid"],
|
||||
sid=self._solution["sid"],
|
||||
)
|
||||
|
||||
@property
|
||||
def dependent_phone_numbers(self) -> DependentPhoneNumberList:
|
||||
"""
|
||||
Access the dependent_phone_numbers
|
||||
"""
|
||||
if self._dependent_phone_numbers is None:
|
||||
self._dependent_phone_numbers = DependentPhoneNumberList(
|
||||
self._version,
|
||||
self._solution["account_sid"],
|
||||
self._solution["sid"],
|
||||
)
|
||||
return self._dependent_phone_numbers
|
||||
|
||||
def __repr__(self) -> str:
|
||||
"""
|
||||
Provide a friendly representation
|
||||
|
||||
:returns: Machine friendly representation
|
||||
"""
|
||||
context = " ".join("{}={}".format(k, v) for k, v in self._solution.items())
|
||||
return "<Twilio.Api.V2010.AddressContext {}>".format(context)
|
||||
|
||||
|
||||
class AddressPage(Page):
|
||||
def get_instance(self, payload: Dict[str, Any]) -> AddressInstance:
|
||||
"""
|
||||
Build an instance of AddressInstance
|
||||
|
||||
:param payload: Payload response from the API
|
||||
"""
|
||||
return AddressInstance(
|
||||
self._version, payload, account_sid=self._solution["account_sid"]
|
||||
)
|
||||
|
||||
def __repr__(self) -> str:
|
||||
"""
|
||||
Provide a friendly representation
|
||||
|
||||
:returns: Machine friendly representation
|
||||
"""
|
||||
return "<Twilio.Api.V2010.AddressPage>"
|
||||
|
||||
|
||||
class AddressList(ListResource):
|
||||
def __init__(self, version: Version, account_sid: str):
|
||||
"""
|
||||
Initialize the AddressList
|
||||
|
||||
:param version: Version that contains the resource
|
||||
:param account_sid: The SID of the [Account](https://www.twilio.com/docs/iam/api/account) that is responsible for the Address resource to read.
|
||||
|
||||
"""
|
||||
super().__init__(version)
|
||||
|
||||
# Path Solution
|
||||
self._solution = {
|
||||
"account_sid": account_sid,
|
||||
}
|
||||
self._uri = "/Accounts/{account_sid}/Addresses.json".format(**self._solution)
|
||||
|
||||
def create(
|
||||
self,
|
||||
customer_name: str,
|
||||
street: str,
|
||||
city: str,
|
||||
region: str,
|
||||
postal_code: str,
|
||||
iso_country: str,
|
||||
friendly_name: Union[str, object] = values.unset,
|
||||
emergency_enabled: Union[bool, object] = values.unset,
|
||||
auto_correct_address: Union[bool, object] = values.unset,
|
||||
street_secondary: Union[str, object] = values.unset,
|
||||
) -> AddressInstance:
|
||||
"""
|
||||
Create the AddressInstance
|
||||
|
||||
:param customer_name: The name to associate with the new address.
|
||||
:param street: The number and street address of the new address.
|
||||
:param city: The city of the new address.
|
||||
:param region: The state or region of the new address.
|
||||
:param postal_code: The postal code of the new address.
|
||||
:param iso_country: The ISO country code of the new address.
|
||||
:param friendly_name: A descriptive string that you create to describe the new address. It can be up to 64 characters long.
|
||||
:param emergency_enabled: Whether to enable emergency calling on the new address. Can be: `true` or `false`.
|
||||
:param auto_correct_address: Whether we should automatically correct the address. Can be: `true` or `false` and the default is `true`. If empty or `true`, we will correct the address you provide if necessary. If `false`, we won't alter the address you provide.
|
||||
:param street_secondary: The additional number and street address of the address.
|
||||
|
||||
:returns: The created AddressInstance
|
||||
"""
|
||||
data = values.of(
|
||||
{
|
||||
"CustomerName": customer_name,
|
||||
"Street": street,
|
||||
"City": city,
|
||||
"Region": region,
|
||||
"PostalCode": postal_code,
|
||||
"IsoCountry": iso_country,
|
||||
"FriendlyName": friendly_name,
|
||||
"EmergencyEnabled": emergency_enabled,
|
||||
"AutoCorrectAddress": auto_correct_address,
|
||||
"StreetSecondary": street_secondary,
|
||||
}
|
||||
)
|
||||
|
||||
payload = self._version.create(
|
||||
method="POST",
|
||||
uri=self._uri,
|
||||
data=data,
|
||||
)
|
||||
|
||||
return AddressInstance(
|
||||
self._version, payload, account_sid=self._solution["account_sid"]
|
||||
)
|
||||
|
||||
async def create_async(
|
||||
self,
|
||||
customer_name: str,
|
||||
street: str,
|
||||
city: str,
|
||||
region: str,
|
||||
postal_code: str,
|
||||
iso_country: str,
|
||||
friendly_name: Union[str, object] = values.unset,
|
||||
emergency_enabled: Union[bool, object] = values.unset,
|
||||
auto_correct_address: Union[bool, object] = values.unset,
|
||||
street_secondary: Union[str, object] = values.unset,
|
||||
) -> AddressInstance:
|
||||
"""
|
||||
Asynchronously create the AddressInstance
|
||||
|
||||
:param customer_name: The name to associate with the new address.
|
||||
:param street: The number and street address of the new address.
|
||||
:param city: The city of the new address.
|
||||
:param region: The state or region of the new address.
|
||||
:param postal_code: The postal code of the new address.
|
||||
:param iso_country: The ISO country code of the new address.
|
||||
:param friendly_name: A descriptive string that you create to describe the new address. It can be up to 64 characters long.
|
||||
:param emergency_enabled: Whether to enable emergency calling on the new address. Can be: `true` or `false`.
|
||||
:param auto_correct_address: Whether we should automatically correct the address. Can be: `true` or `false` and the default is `true`. If empty or `true`, we will correct the address you provide if necessary. If `false`, we won't alter the address you provide.
|
||||
:param street_secondary: The additional number and street address of the address.
|
||||
|
||||
:returns: The created AddressInstance
|
||||
"""
|
||||
data = values.of(
|
||||
{
|
||||
"CustomerName": customer_name,
|
||||
"Street": street,
|
||||
"City": city,
|
||||
"Region": region,
|
||||
"PostalCode": postal_code,
|
||||
"IsoCountry": iso_country,
|
||||
"FriendlyName": friendly_name,
|
||||
"EmergencyEnabled": emergency_enabled,
|
||||
"AutoCorrectAddress": auto_correct_address,
|
||||
"StreetSecondary": street_secondary,
|
||||
}
|
||||
)
|
||||
|
||||
payload = await self._version.create_async(
|
||||
method="POST",
|
||||
uri=self._uri,
|
||||
data=data,
|
||||
)
|
||||
|
||||
return AddressInstance(
|
||||
self._version, payload, account_sid=self._solution["account_sid"]
|
||||
)
|
||||
|
||||
def stream(
|
||||
self,
|
||||
customer_name: Union[str, object] = values.unset,
|
||||
friendly_name: Union[str, object] = values.unset,
|
||||
iso_country: Union[str, object] = values.unset,
|
||||
limit: Optional[int] = None,
|
||||
page_size: Optional[int] = None,
|
||||
) -> Iterator[AddressInstance]:
|
||||
"""
|
||||
Streams AddressInstance records from the API as a generator stream.
|
||||
This operation lazily loads records as efficiently as possible until the limit
|
||||
is reached.
|
||||
The results are returned as a generator, so this operation is memory efficient.
|
||||
|
||||
:param str customer_name: The `customer_name` of the Address resources to read.
|
||||
:param str friendly_name: The string that identifies the Address resources to read.
|
||||
:param str iso_country: The ISO country code of the Address resources to read.
|
||||
:param limit: Upper limit for the number of records to return. stream()
|
||||
guarantees to never return more than limit. Default is no limit
|
||||
:param page_size: Number of records to fetch per request, when not set will use
|
||||
the default value of 50 records. If no page_size is defined
|
||||
but a limit is defined, stream() will attempt to read the
|
||||
limit with the most efficient page size, i.e. min(limit, 1000)
|
||||
|
||||
:returns: Generator that will yield up to limit results
|
||||
"""
|
||||
limits = self._version.read_limits(limit, page_size)
|
||||
page = self.page(
|
||||
customer_name=customer_name,
|
||||
friendly_name=friendly_name,
|
||||
iso_country=iso_country,
|
||||
page_size=limits["page_size"],
|
||||
)
|
||||
|
||||
return self._version.stream(page, limits["limit"])
|
||||
|
||||
async def stream_async(
|
||||
self,
|
||||
customer_name: Union[str, object] = values.unset,
|
||||
friendly_name: Union[str, object] = values.unset,
|
||||
iso_country: Union[str, object] = values.unset,
|
||||
limit: Optional[int] = None,
|
||||
page_size: Optional[int] = None,
|
||||
) -> AsyncIterator[AddressInstance]:
|
||||
"""
|
||||
Asynchronously streams AddressInstance records from the API as a generator stream.
|
||||
This operation lazily loads records as efficiently as possible until the limit
|
||||
is reached.
|
||||
The results are returned as a generator, so this operation is memory efficient.
|
||||
|
||||
:param str customer_name: The `customer_name` of the Address resources to read.
|
||||
:param str friendly_name: The string that identifies the Address resources to read.
|
||||
:param str iso_country: The ISO country code of the Address resources to read.
|
||||
:param limit: Upper limit for the number of records to return. stream()
|
||||
guarantees to never return more than limit. Default is no limit
|
||||
:param page_size: Number of records to fetch per request, when not set will use
|
||||
the default value of 50 records. If no page_size is defined
|
||||
but a limit is defined, stream() will attempt to read the
|
||||
limit with the most efficient page size, i.e. min(limit, 1000)
|
||||
|
||||
:returns: Generator that will yield up to limit results
|
||||
"""
|
||||
limits = self._version.read_limits(limit, page_size)
|
||||
page = await self.page_async(
|
||||
customer_name=customer_name,
|
||||
friendly_name=friendly_name,
|
||||
iso_country=iso_country,
|
||||
page_size=limits["page_size"],
|
||||
)
|
||||
|
||||
return self._version.stream_async(page, limits["limit"])
|
||||
|
||||
def list(
|
||||
self,
|
||||
customer_name: Union[str, object] = values.unset,
|
||||
friendly_name: Union[str, object] = values.unset,
|
||||
iso_country: Union[str, object] = values.unset,
|
||||
limit: Optional[int] = None,
|
||||
page_size: Optional[int] = None,
|
||||
) -> List[AddressInstance]:
|
||||
"""
|
||||
Lists AddressInstance records from the API as a list.
|
||||
Unlike stream(), this operation is eager and will load `limit` records into
|
||||
memory before returning.
|
||||
|
||||
:param str customer_name: The `customer_name` of the Address resources to read.
|
||||
:param str friendly_name: The string that identifies the Address resources to read.
|
||||
:param str iso_country: The ISO country code of the Address resources to read.
|
||||
:param limit: Upper limit for the number of records to return. list() guarantees
|
||||
never to return more than limit. Default is no limit
|
||||
:param page_size: Number of records to fetch per request, when not set will use
|
||||
the default value of 50 records. If no page_size is defined
|
||||
but a limit is defined, list() will attempt to read the limit
|
||||
with the most efficient page size, i.e. min(limit, 1000)
|
||||
|
||||
:returns: list that will contain up to limit results
|
||||
"""
|
||||
return list(
|
||||
self.stream(
|
||||
customer_name=customer_name,
|
||||
friendly_name=friendly_name,
|
||||
iso_country=iso_country,
|
||||
limit=limit,
|
||||
page_size=page_size,
|
||||
)
|
||||
)
|
||||
|
||||
async def list_async(
|
||||
self,
|
||||
customer_name: Union[str, object] = values.unset,
|
||||
friendly_name: Union[str, object] = values.unset,
|
||||
iso_country: Union[str, object] = values.unset,
|
||||
limit: Optional[int] = None,
|
||||
page_size: Optional[int] = None,
|
||||
) -> List[AddressInstance]:
|
||||
"""
|
||||
Asynchronously lists AddressInstance records from the API as a list.
|
||||
Unlike stream(), this operation is eager and will load `limit` records into
|
||||
memory before returning.
|
||||
|
||||
:param str customer_name: The `customer_name` of the Address resources to read.
|
||||
:param str friendly_name: The string that identifies the Address resources to read.
|
||||
:param str iso_country: The ISO country code of the Address resources to read.
|
||||
:param limit: Upper limit for the number of records to return. list() guarantees
|
||||
never to return more than limit. Default is no limit
|
||||
:param page_size: Number of records to fetch per request, when not set will use
|
||||
the default value of 50 records. If no page_size is defined
|
||||
but a limit is defined, list() will attempt to read the limit
|
||||
with the most efficient page size, i.e. min(limit, 1000)
|
||||
|
||||
:returns: list that will contain up to limit results
|
||||
"""
|
||||
return [
|
||||
record
|
||||
async for record in await self.stream_async(
|
||||
customer_name=customer_name,
|
||||
friendly_name=friendly_name,
|
||||
iso_country=iso_country,
|
||||
limit=limit,
|
||||
page_size=page_size,
|
||||
)
|
||||
]
|
||||
|
||||
def page(
|
||||
self,
|
||||
customer_name: Union[str, object] = values.unset,
|
||||
friendly_name: Union[str, object] = values.unset,
|
||||
iso_country: Union[str, object] = values.unset,
|
||||
page_token: Union[str, object] = values.unset,
|
||||
page_number: Union[int, object] = values.unset,
|
||||
page_size: Union[int, object] = values.unset,
|
||||
) -> AddressPage:
|
||||
"""
|
||||
Retrieve a single page of AddressInstance records from the API.
|
||||
Request is executed immediately
|
||||
|
||||
:param customer_name: The `customer_name` of the Address resources to read.
|
||||
:param friendly_name: The string that identifies the Address resources to read.
|
||||
:param iso_country: The ISO country code of the Address resources to read.
|
||||
:param page_token: PageToken provided by the API
|
||||
:param page_number: Page Number, this value is simply for client state
|
||||
:param page_size: Number of records to return, defaults to 50
|
||||
|
||||
:returns: Page of AddressInstance
|
||||
"""
|
||||
data = values.of(
|
||||
{
|
||||
"CustomerName": customer_name,
|
||||
"FriendlyName": friendly_name,
|
||||
"IsoCountry": iso_country,
|
||||
"PageToken": page_token,
|
||||
"Page": page_number,
|
||||
"PageSize": page_size,
|
||||
}
|
||||
)
|
||||
|
||||
response = self._version.page(method="GET", uri=self._uri, params=data)
|
||||
return AddressPage(self._version, response, self._solution)
|
||||
|
||||
async def page_async(
|
||||
self,
|
||||
customer_name: Union[str, object] = values.unset,
|
||||
friendly_name: Union[str, object] = values.unset,
|
||||
iso_country: Union[str, object] = values.unset,
|
||||
page_token: Union[str, object] = values.unset,
|
||||
page_number: Union[int, object] = values.unset,
|
||||
page_size: Union[int, object] = values.unset,
|
||||
) -> AddressPage:
|
||||
"""
|
||||
Asynchronously retrieve a single page of AddressInstance records from the API.
|
||||
Request is executed immediately
|
||||
|
||||
:param customer_name: The `customer_name` of the Address resources to read.
|
||||
:param friendly_name: The string that identifies the Address resources to read.
|
||||
:param iso_country: The ISO country code of the Address resources to read.
|
||||
:param page_token: PageToken provided by the API
|
||||
:param page_number: Page Number, this value is simply for client state
|
||||
:param page_size: Number of records to return, defaults to 50
|
||||
|
||||
:returns: Page of AddressInstance
|
||||
"""
|
||||
data = values.of(
|
||||
{
|
||||
"CustomerName": customer_name,
|
||||
"FriendlyName": friendly_name,
|
||||
"IsoCountry": iso_country,
|
||||
"PageToken": page_token,
|
||||
"Page": page_number,
|
||||
"PageSize": page_size,
|
||||
}
|
||||
)
|
||||
|
||||
response = await self._version.page_async(
|
||||
method="GET", uri=self._uri, params=data
|
||||
)
|
||||
return AddressPage(self._version, response, self._solution)
|
||||
|
||||
def get_page(self, target_url: str) -> AddressPage:
|
||||
"""
|
||||
Retrieve a specific page of AddressInstance records from the API.
|
||||
Request is executed immediately
|
||||
|
||||
:param target_url: API-generated URL for the requested results page
|
||||
|
||||
:returns: Page of AddressInstance
|
||||
"""
|
||||
response = self._version.domain.twilio.request("GET", target_url)
|
||||
return AddressPage(self._version, response, self._solution)
|
||||
|
||||
async def get_page_async(self, target_url: str) -> AddressPage:
|
||||
"""
|
||||
Asynchronously retrieve a specific page of AddressInstance records from the API.
|
||||
Request is executed immediately
|
||||
|
||||
:param target_url: API-generated URL for the requested results page
|
||||
|
||||
:returns: Page of AddressInstance
|
||||
"""
|
||||
response = await self._version.domain.twilio.request_async("GET", target_url)
|
||||
return AddressPage(self._version, response, self._solution)
|
||||
|
||||
def get(self, sid: str) -> AddressContext:
|
||||
"""
|
||||
Constructs a AddressContext
|
||||
|
||||
:param sid: The Twilio-provided string that uniquely identifies the Address resource to update.
|
||||
"""
|
||||
return AddressContext(
|
||||
self._version, account_sid=self._solution["account_sid"], sid=sid
|
||||
)
|
||||
|
||||
def __call__(self, sid: str) -> AddressContext:
|
||||
"""
|
||||
Constructs a AddressContext
|
||||
|
||||
:param sid: The Twilio-provided string that uniquely identifies the Address resource to update.
|
||||
"""
|
||||
return AddressContext(
|
||||
self._version, account_sid=self._solution["account_sid"], sid=sid
|
||||
)
|
||||
|
||||
def __repr__(self) -> str:
|
||||
"""
|
||||
Provide a friendly representation
|
||||
|
||||
:returns: Machine friendly representation
|
||||
"""
|
||||
return "<Twilio.Api.V2010.AddressList>"
|
||||
BIN
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user