Skip to content

Commit

Permalink
Merge pull request #124 from CiscoDevNet/v1.x
Browse files Browse the repository at this point in the history
v1.5
  • Loading branch information
cmlccie committed Jul 9, 2020
2 parents 704904a + 30c080a commit 1cea422
Show file tree
Hide file tree
Showing 8 changed files with 202 additions and 70 deletions.
8 changes: 8 additions & 0 deletions docs/user/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,14 @@ Exceptions
Warnings
========

.. autoexception:: webexteamssdkWarning()
:show-inheritance:
:members:

.. autoexception:: ApiWarning()
:show-inheritance:
:members:

.. autoexception:: RateLimitWarning()
:show-inheritance:
:members:
Expand Down
14 changes: 6 additions & 8 deletions webexteamssdk/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,14 @@
import logging

import webexteamssdk.models.cards as cards
from ._metadata import *
from ._version import get_versions
from ._metadata import (
__author__, __author_email__, __copyright__, __description__,
__download_url__, __license__, __title__, __url__, __version__,
)
from .api import WebexTeamsAPI
from .exceptions import (
AccessTokenError, ApiError, MalformedResponse, RateLimitError,
RateLimitWarning, webexteamssdkException,
AccessTokenError, ApiError, ApiWarning, MalformedResponse, RateLimitError,
RateLimitWarning, webexteamssdkException, webexteamssdkWarning,
)
from .models.dictionary import dict_data_factory
from .models.immutable import (
Expand All @@ -50,10 +52,6 @@
from .utils import WebexTeamsDateTime


__version__ = get_versions()['version']
del get_versions


# Initialize Package Logging
logger = logging.getLogger(__name__)
logger.addHandler(logging.NullHandler())
9 changes: 8 additions & 1 deletion webexteamssdk/_metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
SOFTWARE.
"""


__title__ = 'webexteamssdk'
__description__ = 'Community-developed Python SDK for the Webex Teams APIs'
__url__ = 'https://github.com/CiscoDevNet/webexteamssdk'
Expand All @@ -31,3 +30,11 @@
__author_email__ = 'chrlunsf@cisco.com'
__copyright__ = "Copyright (c) 2016-2019 Cisco Systems, Inc."
__license__ = "MIT"


# Only import the ._version module and compute the version when this module is
# imported.
if __name__ == "webexteamssdk._metadata":
from ._version import get_versions
__version__ = get_versions()['version']
del get_versions
21 changes: 19 additions & 2 deletions webexteamssdk/api/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
from .team_memberships import TeamMembershipsAPI
from .teams import TeamsAPI
from .webhooks import WebhooksAPI
import os


class WebexTeamsAPI(object):
Expand All @@ -69,7 +70,9 @@ def __init__(self, access_token=None, base_url=DEFAULT_BASE_URL,
client_secret=None,
oauth_code=None,
redirect_uri=None,
proxies=None):
proxies=None,
be_geo_id=None,
caller=None):
"""Create a new WebexTeamsAPI object.
An access token must be used when interacting with the Webex Teams API.
Expand Down Expand Up @@ -113,6 +116,12 @@ def __init__(self, access_token=None, base_url=DEFAULT_BASE_URL,
OAuth process.
proxies(dict): Dictionary of proxies passed on to the requests
session.
be_geo_id(basestring): Optional partner identifier for API usage
tracking. Defaults to checking for a BE_GEO_ID environment
variable.
caller(basestring): Optional identifier for API usage tracking.
Defaults to checking for a WEBEX_PYTHON_SDK_CALLER environment
variable.
Returns:
WebexTeamsAPI: A new WebexTeamsAPI object.
Expand All @@ -132,6 +141,8 @@ def __init__(self, access_token=None, base_url=DEFAULT_BASE_URL,
check_type(oauth_code, basestring, optional=True)
check_type(redirect_uri, basestring, optional=True)
check_type(proxies, dict, optional=True)
check_type(be_geo_id, basestring, optional=True)
check_type(caller, basestring, optional=True)

access_token = access_token or WEBEX_TEAMS_ACCESS_TOKEN

Expand All @@ -151,6 +162,10 @@ def __init__(self, access_token=None, base_url=DEFAULT_BASE_URL,
redirect_uri=redirect_uri
).access_token

# Set optional API metrics tracking variables from env vars if there
be_geo_id = be_geo_id or os.environ.get('BE_GEO_ID')
caller = caller or os.environ.get('WEBEX_PYTHON_SDK_CALLER')

# If an access token hasn't been provided as a parameter, environment
# variable, or obtained via an OAuth exchange raise an error.
if not access_token:
Expand All @@ -169,7 +184,9 @@ def __init__(self, access_token=None, base_url=DEFAULT_BASE_URL,
base_url=base_url,
single_request_timeout=single_request_timeout,
wait_on_rate_limit=wait_on_rate_limit,
proxies=proxies
proxies=proxies,
be_geo_id=be_geo_id,
caller=caller
)

# API wrappers
Expand Down
53 changes: 32 additions & 21 deletions webexteamssdk/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@ class webexteamssdkException(Exception):
pass


class webexteamssdkWarning(webexteamssdkException, Warning):
"""Base class for all webexteamssdk warnings."""
pass


class AccessTokenError(webexteamssdkException):
"""Raised when an incorrect Webex Teams Access Token has been provided."""
pass
Expand Down Expand Up @@ -73,6 +78,9 @@ def __init__(self, response):
self.status = self.response.reason
"""The HTTP status from the API response."""

self.description = RESPONSE_CODES.get(self.status_code)
"""A description of the HTTP Response Code from the API docs."""

self.details = None
"""The parsed JSON details from the API response."""
if "application/json" in \
Expand All @@ -85,24 +93,40 @@ def __init__(self, response):
self.message = self.details.get("message") if self.details else None
"""The error message from the parsed API response."""

self.description = RESPONSE_CODES.get(self.status_code)
"""A description of the HTTP Response Code from the API docs."""
self.tracking_id = (
self.details.get("trackingId") if self.details else None
or self.response.headers.get("trackingId")
)
"""The Webex Tracking ID from the response."""

super(ApiError, self).__init__(
"[{status_code}]{status} - {message}".format(
self.error_message = (
"[{status_code}]{status} - {detail}{tracking_id}".format(
status_code=self.status_code,
status=" " + self.status if self.status else "",
message=self.message or self.description or "Unknown Error",
detail=self.message or self.description or "Unknown Error",
tracking_id=" [Tracking ID: " + self.tracking_id + "]"
if self.tracking_id else "",
)
)

super(ApiError, self).__init__(self.error_message)

def __repr__(self):
return "<{exception_name} [{status_code}]>".format(
return "<{exception_name} [{status_code}]{status}>".format(
exception_name=self.__class__.__name__,
status_code=self.status_code,
status=" " + self.status if self.status else "",
)


class ApiWarning(webexteamssdkWarning, ApiError):
"""Warnings raised from API responses received from the Webex APIs.
Several data attributes are available for inspection.
"""
pass


class RateLimitError(ApiError):
"""Webex Teams Rate-Limit exceeded Error.
Expand All @@ -125,26 +149,13 @@ def __init__(self, response):
super(RateLimitError, self).__init__(response)


class RateLimitWarning(UserWarning):
class RateLimitWarning(ApiWarning, RateLimitError):
"""Webex Teams rate-limit exceeded warning.
Raised when a rate-limit exceeded message is received and the request will
be retried.
"""

def __init__(self, response):
assert isinstance(response, requests.Response)

# Extended warning attributes
self.retry_after = max(1, int(response.headers.get('Retry-After', 15)))
"""The `Retry-After` time period (in seconds) provided by Webex Teams.
Defaults to 15 seconds if the response `Retry-After` header isn't
present in the response headers, and defaults to a minimum wait time of
1 second if Webex Teams returns a `Retry-After` header of 0 seconds.
"""

super(RateLimitWarning, self).__init__()
pass


class MalformedResponse(webexteamssdkException):
Expand Down
4 changes: 2 additions & 2 deletions webexteamssdk/models/cards/actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ def __init__(self, data=None, title=None, iconURL=None):
self.iconURL = iconURL

super().__init__(
serializable_properties=['data'],
simple_properties=['title', 'iconURL', 'type'],
serializable_properties=[],
simple_properties=['data', 'title', 'iconURL', 'type'],
)


Expand Down
6 changes: 5 additions & 1 deletion webexteamssdk/models/cards/adaptive_card_component.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"""

import json
import enum


class AdaptiveCardComponent:
Expand Down Expand Up @@ -63,7 +64,10 @@ def to_dict(self):
property_value = getattr(self, property_name, None)

if property_value is not None:
serialized_data[property_name] = str(property_value)
if isinstance(property_value, enum.Enum):
property_value = str(property_value)

serialized_data[property_name] = property_value

# Recursively serialize sub-components
for property_name in self.serializable_properties:
Expand Down

0 comments on commit 1cea422

Please sign in to comment.