From 6481a8650042b8bceecdae28a92154ed350e9c8e Mon Sep 17 00:00:00 2001 From: superdiana Date: Mon, 11 Jan 2021 12:16:39 -0500 Subject: [PATCH] rminor release for enum34 bug fix --- CONTRIBUTING.md | 12 +- opentok/archives.py | 65 +- opentok/broadcast.py | 17 +- opentok/endpoints.py | 105 +- opentok/exceptions.py | 20 +- opentok/opentok.py | 777 ++++-------- opentok/session.py | 46 +- opentok/sip_call.py | 7 +- opentok/stream.py | 16 +- opentok/streamlist.py | 9 +- opentok/version.py | 2 +- sample/Archiving/archiving.py | 64 +- sample/HelloWorld/helloworld.py | 12 +- tests/helpers.py | 17 +- tests/test_archive.py | 182 ++- tests/test_archive_api.py | 2006 +++++++++++++------------------ tests/test_broadcast.py | 435 +++---- tests/test_custom_jwt_claims.py | 30 - tests/test_force_disconnect.py | 53 +- tests/test_getter_setter.py | 22 - tests/test_http_options.py | 19 +- tests/test_initialization.py | 19 +- tests/test_session.py | 23 +- tests/test_session_creation.py | 281 ++--- tests/test_signal.py | 107 +- tests/test_sip_call.py | 132 +- tests/test_stream.py | 229 ++-- tests/test_token_generation.py | 54 +- tests/validate_jwt.py | 21 +- 29 files changed, 1806 insertions(+), 2976 deletions(-) delete mode 100644 tests/test_custom_jwt_claims.py delete mode 100644 tests/test_getter_setter.py diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 97f51c2..1328186 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,6 +1,6 @@ # Contributing Guidelines -For anyone looking to get involved in this project, we are glad to hear from you. Here are a few types of contributions +For anyone looking to get involved to this project, we are glad to hear from you. Here are a few types of contributions that we would be interested in hearing about. * Bug fixes @@ -12,12 +12,14 @@ that we would be interested in hearing about. - If you'd like to accomplish something in the library that it doesn't already do, describe the problem in a new Github Issue. - Issues that have been identified as a feature request will be labelled `enhancement`. - - If you'd like to implement the new feature, please wait for feedback from the project maintainers before spending too much time writing the code. In some cases, `enhancement`s may not align well with the project objectives at the time. + - If you'd like to implement the new feature, please wait for feedback from the project maintainers before spending + too much time writing the code. In some cases, `enhancement`s may not align well with the project objectives at + the time. * Tests, Documentation, Miscellaneous - If you think the test coverage could be improved, the documentation could be clearer, you've got an alternative - implementation of something that may have more advantages or any other change we would still be glad to hear about + implementation of something that may have more advantages, or any other change we would still be glad hear about it. - - If it's a trivial change, go ahead and send a Pull Request with the changes you have in mind + - If its a trivial change, go ahead and send a Pull Request with the changes you have in mind - If not, open a Github Issue to discuss the idea first. ## Requirements @@ -35,7 +37,7 @@ continue to add more commits to the branch you have sent the Pull Request from. 1. Fork this repository on GitHub. 1. Clone/fetch your fork to your local development machine. -1. Create a new branch (e.g. `issue-12`, `feat.add_foo`, etc.) and check it out. +1. Create a new branch (e.g. `issue-12`, `feat.add_foo`, etc) and check it out. 1. Make your changes and commit them. (Did the tests pass?) 1. Push your new branch to your fork. (e.g. `git push myname issue-12`) 1. Open a Pull Request from your new branch to the original fork's `master` branch. diff --git a/opentok/archives.py b/opentok/archives.py index 3a72774..36ac331 100644 --- a/opentok/archives.py +++ b/opentok/archives.py @@ -3,30 +3,22 @@ import json import pytz from enum import Enum - if PY3: from datetime import timezone # compat from six.moves import map -dthandler = ( - lambda obj: obj.isoformat() - if isinstance(obj, datetime) or isinstance(obj, date) - else None -) - +dthandler = lambda obj: obj.isoformat() if isinstance(obj, datetime) or isinstance(obj, date) else None class OutputModes(Enum): """List of valid settings for the output_mode parameter of the OpenTok.start_archive() method.""" - - composed = u("composed") + composed = u('composed') """All streams in the archive are recorded to a single (composed) file.""" - individual = u("individual") + individual = u('individual') """Each stream in the archive is recorded to an individual file.""" - class Archive(object): """Represents an archive of an OpenTok session. @@ -95,26 +87,22 @@ class Archive(object): def __init__(self, sdk, values): self.sdk = sdk - self.id = values.get("id") - self.name = values.get("name") - self.status = values.get("status") - self.session_id = values.get("sessionId") - self.partner_id = values.get("partnerId") + self.id = values.get('id') + self.name = values.get('name') + self.status = values.get('status') + self.session_id = values.get('sessionId') + self.partner_id = values.get('partnerId') if PY2: - self.created_at = datetime.fromtimestamp( - values.get("createdAt") / 1000, pytz.UTC - ) + self.created_at = datetime.fromtimestamp(values.get('createdAt') / 1000, pytz.UTC) if PY3: - self.created_at = datetime.fromtimestamp( - values.get("createdAt") // 1000, timezone.utc - ) - self.size = values.get("size") - self.duration = values.get("duration") - self.has_audio = values.get("hasAudio") - self.has_video = values.get("hasVideo") - self.output_mode = OutputModes[values.get("outputMode", "composed")] - self.url = values.get("url") - self.resolution = values.get("resolution") + self.created_at = datetime.fromtimestamp(values.get('createdAt') // 1000, timezone.utc) + self.size = values.get('size') + self.duration = values.get('duration') + self.has_audio = values.get('hasAudio') + self.has_video = values.get('hasVideo') + self.output_mode = OutputModes[values.get('outputMode', 'composed')] + self.url = values.get('url') + self.resolution = values.get('resolution') def stop(self): """ @@ -124,7 +112,7 @@ def stop(self): disconnected from the session being archived. """ temp_archive = self.sdk.stop_archive(self.id) - for k, v in iteritems(temp_archive.attrs()): + for k,v in iteritems(temp_archive.attrs()): setattr(self, k, v) def delete(self): @@ -142,7 +130,7 @@ def attrs(self): """ Returns a dictionary of the archive's attributes. """ - return dict((k, v) for k, v in iteritems(self.__dict__) if k != "sdk") + return dict((k, v) for k, v in iteritems(self.__dict__) if k is not "sdk") def json(self): """ @@ -150,18 +138,21 @@ def json(self): """ return json.dumps(self.attrs(), default=dthandler, indent=4) - class ArchiveList(object): + def __init__(self, sdk, values): - self.count = values.get("count") - self.items = list(map(lambda x: Archive(sdk, x), values.get("items", []))) + self.count = values.get('count') + self.items = list(map(lambda x: Archive(sdk, x), values.get('items', []))) def __iter__(self): for x in self.items: yield x def attrs(self): - return {"count": self.count, "items": map(Archive.attrs, self.items)} + return { + 'count': self.count, + 'items': map(Archive.attrs, self.items) + } def json(self): return json.dumps(self.attrs(), default=dthandler, indent=4) @@ -170,9 +161,7 @@ def __getitem__(self, key): return self.items.get(key) def __setitem__(self, key, item): - raise ArchiveError( - u("Cannot set item {0} for key {1} in Archive object").format(item, key) - ) + raise ArchiveError(u('Cannot set item {0} for key {1} in Archive object').format(item, key)) def __len__(self): return len(self.items) diff --git a/opentok/broadcast.py b/opentok/broadcast.py index 764672b..4ccea11 100644 --- a/opentok/broadcast.py +++ b/opentok/broadcast.py @@ -1,20 +1,19 @@ import json - class Broadcast(object): """ Represents a live streaming broadcast """ def __init__(self, kwargs): - self.id = kwargs.get("id") - self.sessionId = kwargs.get("sessionId") - self.projectId = kwargs.get("projectId") - self.createdAt = kwargs.get("createdAt") - self.updatedAt = kwargs.get("updatedAt") - self.resolution = kwargs.get("resolution") - self.status = kwargs.get("status") - self.broadcastUrls = kwargs.get("broadcastUrls") + self.id = kwargs.get('id') + self.sessionId = kwargs.get('sessionId') + self.projectId = kwargs.get('projectId') + self.createdAt = kwargs.get('createdAt') + self.updatedAt = kwargs.get('updatedAt') + self.resolution = kwargs.get('resolution') + self.status = kwargs.get('status') + self.broadcastUrls = kwargs.get('broadcastUrls') def json(self): """ diff --git a/opentok/endpoints.py b/opentok/endpoints.py index 47ace0b..d05f37b 100644 --- a/opentok/endpoints.py +++ b/opentok/endpoints.py @@ -1,132 +1,69 @@ -import warnings - - class Endpoints(object): """ For internal use. Class that provides the endpoint urls """ - def __init__(self, api_url, api_key): self.api_url = api_url self.api_key = api_key - def get_session_url(self): - url = self.api_url + "/session/create" - return url - def session_url(self): - warnings.warn( - "endpoints.session_url is deprecated (use endpoints.get_session_url instead).", - DeprecationWarning, - stacklevel=2, - ) - - return self.get_session_url() - - def get_archive_url(self, archive_id=None): - url = self.api_url + "/v2/project/" + self.api_key + "/archive" - if archive_id: - url = url + "/" + archive_id + url = self.api_url + '/session/create' return url def archive_url(self, archive_id=None): - warnings.warn( - "endpoints.archive_url is deprecated (use endpoints.get_archive_url instead).", - DeprecationWarning, - stacklevel=2, - ) - return self.get_archive_url(archive_id) + url = self.api_url + '/v2/project/' + self.api_key + '/archive' + if archive_id: + url = url + '/' + archive_id + return url - def get_signaling_url(self, session_id, connection_id=None): - url = self.api_url + "/v2/project/" + self.api_key + "/session/" + session_id + def signaling_url(self, session_id, connection_id=None): + url = self.api_url + '/v2/project/' + self.api_key + '/session/' + session_id if connection_id: - url += "/connection/" + connection_id + url += '/connection/' + connection_id - url += "/signal" + url += '/signal' return url - def signaling_url(self, session_id, connection_id=None): - warnings.warn( - "endpoints.signaling_url is deprecated (use endpoints.get_signaling_url instead).", - DeprecationWarning, - stacklevel=2, - ) - return self.get_signaling_url(session_id, connection_id) - def get_stream_url(self, session_id, stream_id=None): """ this method returns the url to get streams information """ - url = ( - self.api_url - + "/v2/project/" - + self.api_key - + "/session/" - + session_id - + "/stream" - ) + url = self.api_url + '/v2/project/' + self.api_key + '/session/' + session_id + '/stream' if stream_id: - url = url + "/" + stream_id + url = url + '/' + stream_id return url - def broadcast_url(self, broadcast_id=None, stop=False, layout=False): - warnings.warn( - "endpoints.broadcast_url is deprecated (use endpoints.get_broadcast_url instead).", - DeprecationWarning, - stacklevel=2, - ) - return self.get_broadcast_url(broadcast_id, stop, layout) - def force_disconnect_url(self, session_id, connection_id): """ this method returns the force disconnect url endpoint """ url = ( - self.api_url - + "/v2/project/" - + self.api_key - + "/session/" - + session_id - + "/connection/" - + connection_id + self.api_url + '/v2/project/' + self.api_key + '/session/' + + session_id + '/connection/' + connection_id ) return url def set_archive_layout_url(self, archive_id): """ this method returns the url to set the archive layout """ - url = ( - self.api_url - + "/v2/project/" - + self.api_key - + "/archive/" - + archive_id - + "/layout" - ) + url = self.api_url + '/v2/project/' + self.api_key + '/archive/' + archive_id + '/layout' return url def dial_url(self): """ this method returns the url to initialize a SIP call """ - url = self.api_url + "/v2/project/" + self.api_key + "/dial" + url = self.api_url + '/v2/project/' + self.api_key + '/dial' return url def set_stream_class_lists_url(self, session_id): """ this method returns the url to set the stream class list """ - url = ( - self.api_url - + "/v2/project/" - + self.api_key - + "/session/" - + session_id - + "/stream" - ) + url = self.api_url + '/v2/project/' + self.api_key + '/session/' + session_id + '/stream' return url - def get_broadcast_url(self, broadcast_id=None, stop=False, layout=False): + def broadcast_url(self, broadcast_id=None, stop=False, layout=False): """ this method returns urls for working with broadcast """ - url = self.api_url + "/v2/project/" + self.api_key + "/broadcast" + url = self.api_url + '/v2/project/' + self.api_key + '/broadcast' if broadcast_id: - url = url + "/" + broadcast_id + url = url + '/' + broadcast_id if stop: - url = url + "/stop" + url = url + '/stop' if layout: - url = url + "/layout" + url = url + '/layout' return url diff --git a/opentok/exceptions.py b/opentok/exceptions.py index 80cd5d9..b757eaa 100644 --- a/opentok/exceptions.py +++ b/opentok/exceptions.py @@ -1,6 +1,6 @@ class OpenTokException(Exception): - """Defines exceptions thrown by the OpenTok SDK.""" - + """Defines exceptions thrown by the OpenTok SDK. + """ pass @@ -8,7 +8,6 @@ class RequestError(OpenTokException): """Indicates an error during the request. Most likely an error connecting to the OpenTok API servers. (HTTP 500 error). """ - pass @@ -16,7 +15,6 @@ class AuthError(OpenTokException): """Indicates that the problem was likely with credentials. Check your API key and API secret and try again. """ - pass @@ -24,7 +22,6 @@ class NotFoundError(OpenTokException): """Indicates that the element requested was not found. Check the parameters of the request. """ - pass @@ -32,53 +29,41 @@ class ArchiveError(OpenTokException): """Indicates that there was a archive specific problem, probably the status of the requested archive is invalid. """ - pass - class SignalingError(OpenTokException): """Indicates that there was a signaling specific problem, one of the parameter is invalid or the type|data string doesn't have a correct size""" - pass - class GetStreamError(OpenTokException): """Indicates that the data in the request is invalid, or the session_id or stream_id are invalid""" - pass - class ForceDisconnectError(OpenTokException): """ Indicates that there was a force disconnect specific problem: One of the arguments is invalid or the client specified by the connectionId property is not connected to the session """ - pass - class SipDialError(OpenTokException): """ Indicates that there was a SIP dial specific problem: The Session ID passed in is invalid or you attempt to start a SIP call for a session that does not use the OpenTok Media Router. """ - pass - class SetStreamClassError(OpenTokException): """ Indicates that there is invalid data in the JSON request. It may also indicate that invalid layout options have been passed """ - pass - class BroadcastError(OpenTokException): """ Indicates that data in your request data is invalid JSON. It may also indicate @@ -86,5 +71,4 @@ class BroadcastError(OpenTokException): simultaneous RTMP streams for an OpenTok session. Or you specified and invalid resolution. Or The broadcast has already started for the session """ - pass diff --git a/opentok/opentok.py b/opentok/opentok.py index ad907bf..f7f43a9 100644 --- a/opentok/opentok.py +++ b/opentok/opentok.py @@ -1,20 +1,17 @@ from datetime import datetime # generate_token -import calendar # generate_token -import base64 # generate_token -import random # generate_token -import time # generate_token -import hmac # _sign_string -import hashlib # _sign_string -import requests # create_session, archiving -import json # archiving -import platform # user-agent -from socket import inet_aton # create_session -import xml.dom.minidom as xmldom # create_session -from jose import jwt # _create_jwt_auth_header -import random # _create_jwt_auth_header -import logging # logging -import warnings # Native. Used for notifying deprecations - +import calendar # generate_token +import base64 # generate_token +import random # generate_token +import time # generate_token +import hmac # _sign_string +import hashlib # _sign_string +import requests # create_session, archiving +import json # archiving +import platform # user-agent +from socket import inet_aton # create_session +import xml.dom.minidom as xmldom # create_session +from jose import jwt # _create_jwt_auth_header +import random # _create_jwt_auth_header # compat from six.moves.urllib.parse import urlencode @@ -40,72 +37,51 @@ ForceDisconnectError, SipDialError, SetStreamClassError, - BroadcastError, + BroadcastError ) - class Roles(Enum): """List of valid roles for a token.""" - - subscriber = u("subscriber") + subscriber = u('subscriber') """A subscriber can only subscribe to streams.""" - publisher = u("publisher") + publisher = u('publisher') """A publisher can publish streams, subscribe to streams, and signal""" - moderator = u("moderator") + moderator = u('moderator') """In addition to the privileges granted to a publisher, in clients using the OpenTok.js 2.2 library, a moderator can call the `forceUnpublish()` and `forceDisconnect()` method of the Session object. """ - class MediaModes(Enum): """List of valid settings for the mediaMode parameter of the OpenTok.create_session() method.""" - - routed = u("disabled") + routed = u('disabled') """The session will transmit streams using the OpenTok Media Server.""" - relayed = u("enabled") + relayed = u('enabled') """The session will attempt to transmit streams directly between clients. If two clients cannot send and receive each others' streams, due to firewalls on the clients' networks, their streams will be relayed using the OpenTok TURN Server.""" - class ArchiveModes(Enum): """List of valid settings for the archive_mode parameter of the OpenTok.create_Session() method.""" - - manual = u("manual") + manual = u('manual') """The session will be manually archived.""" - always = u("always") + always = u('always') """The session will be automatically archived.""" - -logger = logging.getLogger("opentok") - - class OpenTok(object): """Use this SDK to create tokens and interface with the server-side portion of the Opentok API. """ - - TOKEN_SENTINEL = "T1==" + TOKEN_SENTINEL = 'T1==' """For internal use.""" - def __init__( - self, - api_key, - api_secret, - api_url="https://api.opentok.com", - timeout=None, - app_version=None, - ): + def __init__(self, api_key, api_secret, api_url='https://api.opentok.com', timeout=None): self.api_key = str(api_key) self.api_secret = api_secret self.timeout = timeout self._proxies = None self.endpoints = Endpoints(api_url, self.api_key) - self._app_version = __version__ if app_version == None else app_version - # JWT custom claims - Default values - self._jwt_livetime = 3 # In minutes @property def proxies(self): @@ -115,30 +91,8 @@ def proxies(self): def proxies(self, proxies): self._proxies = proxies - @property - def app_version(self): - return self._app_version - - @app_version.setter - def app_version(self, value): - self._app_version = value - - @property - def jwt_livetime(self): - return self._jwt_livetime - - @jwt_livetime.setter - def jwt_livetime(self, minutes): - self._jwt_livetime = minutes - - def generate_token( - self, - session_id, - role=Roles.publisher, - expire_time=None, - data=None, - initial_layout_class_list=[], - ): + def generate_token(self, session_id, role=Roles.publisher, expire_time=None, data=None, + initial_layout_class_list=[]): """ Generates a token for a given session. @@ -187,110 +141,67 @@ def generate_token( try: expire_time = int(expire_time) except (ValueError, TypeError): - raise OpenTokException( - u("Cannot generate token, invalid expire time {0}").format( - expire_time - ) - ) + raise OpenTokException(u('Cannot generate token, invalid expire time {0}').format(expire_time)) else: - expire_time = int(time.time()) + (60 * 60 * 24) # 1 day + expire_time = int(time.time()) + (60*60*24) # 1 day # validations if not text_type(session_id): - raise OpenTokException( - u("Cannot generate token, session_id was not valid {0}").format( - session_id - ) - ) + raise OpenTokException(u('Cannot generate token, session_id was not valid {0}').format(session_id)) if not isinstance(role, Roles): - raise OpenTokException( - u("Cannot generate token, {0} is not a valid role").format(role) - ) + raise OpenTokException(u('Cannot generate token, {0} is not a valid role').format(role)) now = int(time.time()) if expire_time < now: - raise OpenTokException( - u("Cannot generate token, expire_time is not in the future {0}").format( - expire_time - ) - ) - if expire_time > now + (60 * 60 * 24 * 30): # 30 days - raise OpenTokException( - u( - "Cannot generate token, expire_time is not in the next 30 days {0}" - ).format(expire_time) - ) + raise OpenTokException(u('Cannot generate token, expire_time is not in the future {0}').format(expire_time)) + if expire_time > now + (60*60*24*30): # 30 days + raise OpenTokException(u('Cannot generate token, expire_time is not in the next 30 days {0}').format(expire_time)) if data and len(data) > 1000: - raise OpenTokException( - u("Cannot generate token, data must be less than 1000 characters") - ) - if initial_layout_class_list and not all( - text_type(c) for c in initial_layout_class_list - ): - raise OpenTokException( - u( - "Cannot generate token, all items in initial_layout_class_list must be strings" - ) - ) - initial_layout_class_list_serialized = u(" ").join(initial_layout_class_list) + raise OpenTokException(u('Cannot generate token, data must be less than 1000 characters')) + if initial_layout_class_list and not all(text_type(c) for c in initial_layout_class_list): + raise OpenTokException(u('Cannot generate token, all items in initial_layout_class_list must be strings')) + initial_layout_class_list_serialized = u(' ').join(initial_layout_class_list) if len(initial_layout_class_list_serialized) > 1000: - raise OpenTokException( - u( - "Cannot generate token, initial_layout_class_list must be less than 1000 characters" - ) - ) + raise OpenTokException(u('Cannot generate token, initial_layout_class_list must be less than 1000 characters')) # decode session id to verify api_key sub_session_id = session_id[2:] - sub_session_id_bytes = sub_session_id.encode("utf-8") - sub_session_id_bytes_padded = sub_session_id_bytes + ( - b("=") * (-len(sub_session_id_bytes) % 4) - ) + sub_session_id_bytes = sub_session_id.encode('utf-8') + sub_session_id_bytes_padded = sub_session_id_bytes + (b('=') * (-len(sub_session_id_bytes) % 4)) try: - decoded_session_id = base64.b64decode(sub_session_id_bytes_padded, b("-_")) - parts = decoded_session_id.decode("utf-8").split(u("~")) + decoded_session_id = base64.b64decode(sub_session_id_bytes_padded, b('-_')) + parts = decoded_session_id.decode('utf-8').split(u('~')) except Exception as e: - raise OpenTokException( - u("Cannot generate token, the session_id {0} was not valid").format( - session_id - ) - ) + raise OpenTokException(u('Cannot generate token, the session_id {0} was not valid').format(session_id)) if self.api_key not in parts: - raise OpenTokException( - u( - "Cannot generate token, the session_id {0} does not belong to the api_key {1}" - ).format(session_id, self.api_key) - ) + raise OpenTokException(u('Cannot generate token, the session_id {0} does not belong to the api_key {1}').format(session_id, self.api_key)) data_params = dict( - session_id=session_id, - create_time=now, - expire_time=expire_time, - role=role.value, - nonce=random.randint(0, 999999), - initial_layout_class_list=initial_layout_class_list_serialized, + session_id = session_id, + create_time = now, + expire_time = expire_time, + role = role.value, + nonce = random.randint(0,999999), + initial_layout_class_list = initial_layout_class_list_serialized ) if data: - data_params["connection_data"] = data + data_params['connection_data'] = data data_string = urlencode(data_params, True) sig = self._sign_string(data_string, self.api_secret) - decoded_base64_bytes = u("partner_id={api_key}&sig={sig}:{payload}").format( - api_key=self.api_key, sig=sig, payload=data_string + decoded_base64_bytes = u('partner_id={api_key}&sig={sig}:{payload}').format( + api_key = self.api_key, + sig = sig, + payload = data_string ) if PY3: - decoded_base64_bytes = decoded_base64_bytes.encode("utf-8") - token = u("{sentinal}{base64_data}").format( - sentinal=self.TOKEN_SENTINEL, - base64_data=base64.b64encode(decoded_base64_bytes).decode(), + decoded_base64_bytes = decoded_base64_bytes.encode('utf-8') + token = u('{sentinal}{base64_data}').format( + sentinal = self.TOKEN_SENTINEL, + base64_data = base64.b64encode(decoded_base64_bytes).decode() ) return token - def create_session( - self, - location=None, - media_mode=MediaModes.relayed, - archive_mode=ArchiveModes.manual, - ): + def create_session(self, location=None, media_mode=MediaModes.relayed, archive_mode=ArchiveModes.manual): """ Creates a new OpenTok session and returns the session ID, which uniquely identifies the session. @@ -354,128 +265,58 @@ def create_session( # build options options = {} if not isinstance(media_mode, MediaModes): - raise OpenTokException( - u("Cannot create session, {0} is not a valid media mode").format( - media_mode - ) - ) + raise OpenTokException(u('Cannot create session, {0} is not a valid media mode').format(media_mode)) if not isinstance(archive_mode, ArchiveModes): - raise OpenTokException( - u("Cannot create session, {0} is not a valid archive mode").format( - archive_mode - ) - ) + raise OpenTokException(u('Cannot create session, {0} is not a valid archive mode').format(archive_mode)) if archive_mode == ArchiveModes.always and media_mode != MediaModes.routed: - raise OpenTokException( - u( - "A session with always archive mode must also have the routed media mode." - ) - ) - options[u("p2p.preference")] = media_mode.value - options[u("archiveMode")] = archive_mode.value + raise OpenTokException(u('A session with always archive mode must also have the routed media mode.')) + options[u('p2p.preference')] = media_mode.value + options[u('archiveMode')] = archive_mode.value if location: # validate IP address try: inet_aton(location) except: - raise OpenTokException( - u( - "Cannot create session. Location must be either None or a valid IPv4 address {0}" - ).format(location) - ) - options[u("location")] = location + raise OpenTokException(u('Cannot create session. Location must be either None or a valid IPv4 address {0}').format(location)) + options[u('location')] = location try: - logger.debug( - "POST to %r with params %r, headers %r, proxies %r", - self.endpoints.session_url(), - options, - self.headers(), - self.proxies, - ) - response = requests.post( - self.endpoints.get_session_url(), - data=options, - headers=self.get_headers(), - proxies=self.proxies, - timeout=self.timeout, - ) - response.encoding = "utf-8" + response = requests.post(self.endpoints.session_url(), data=options, headers=self.headers(), proxies=self.proxies, timeout=self.timeout) + response.encoding = 'utf-8' if response.status_code == 403: - raise AuthError("Failed to create session, invalid credentials") + raise AuthError('Failed to create session, invalid credentials') if not response.content: raise RequestError() - dom = xmldom.parseString(response.content.decode("utf-8")) + dom = xmldom.parseString(response.content) except Exception as e: - raise RequestError("Failed to create session: %s" % str(e)) + raise RequestError('Failed to create session: %s' % str(e)) try: - error = dom.getElementsByTagName("error") + error = dom.getElementsByTagName('error') if error: error = error[0] - raise AuthError( - "Failed to create session (code=%s): %s" - % ( - error.attributes["code"].value, - error.firstChild.attributes["message"].value, - ) - ) - - session_id = ( - dom.getElementsByTagName("session_id")[0].childNodes[0].nodeValue - ) - return Session( - self, - session_id, - location=location, - media_mode=media_mode, - archive_mode=archive_mode, - ) + raise AuthError('Failed to create session (code=%s): %s' % (error.attributes['code'].value, error.firstChild.attributes['message'].value)) + + session_id = dom.getElementsByTagName('session_id')[0].childNodes[0].nodeValue + return Session(self, session_id, location=location, media_mode=media_mode, archive_mode=archive_mode) except Exception as e: - raise OpenTokException("Failed to generate session: %s" % str(e)) + raise OpenTokException('Failed to generate session: %s' % str(e)) - def get_headers(self): + def headers(self): """For internal use.""" return { - "User-Agent": "OpenTok-Python-SDK/" - + self.app_version - + " python/" - + platform.python_version(), - "X-OPENTOK-AUTH": self._create_jwt_auth_header(), + 'User-Agent': 'OpenTok-Python-SDK/' + __version__ + ' ' + platform.python_version(), + 'X-OPENTOK-AUTH': self._create_jwt_auth_header() } - def headers(self): - warnings.warn( - "opentok.headers is deprecated (use opentok.get_headers instead).", - DeprecationWarning, - stacklevel=2, - ) - return self.get_headers() - - def get_json_headers(self): + def json_headers(self): """For internal use.""" - result = self.get_headers() - result["Content-Type"] = "application/json" + result = self.headers() + result['Content-Type'] = 'application/json' return result - def json_headers(self): - warnings.warn( - "opentok.json_headers is deprecated (use opentok.get_json_headers instead).", - DeprecationWarning, - stacklevel=2, - ) - return self.get_json_headers() - - def start_archive( - self, - session_id, - has_audio=True, - has_video=True, - name=None, - output_mode=OutputModes.composed, - resolution=None, - ): + def start_archive(self, session_id, has_audio=True, has_video=True, name=None, output_mode=OutputModes.composed, resolution=None): """ Starts archiving an OpenTok session. @@ -511,43 +352,21 @@ def start_archive( including the archive ID. """ if not isinstance(output_mode, OutputModes): - raise OpenTokException( - u("Cannot start archive, {0} is not a valid output mode").format( - output_mode - ) - ) + raise OpenTokException(u('Cannot start archive, {0} is not a valid output mode').format(output_mode)) - if resolution and output_mode == OutputModes.individual: - raise OpenTokException( - u( - "Invalid parameters: Resolution cannot be supplied for individual output mode." - ) - ) - payload = { - "name": name, - "sessionId": session_id, - "hasAudio": has_audio, - "hasVideo": has_video, - "outputMode": output_mode.value, - "resolution": resolution, + if resolution and output_mode == OutputModes.individual: + raise OpenTokException(u('Invalid parameters: Resolution cannot be supplied for individual output mode.')) + + payload = {'name': name, + 'sessionId': session_id, + 'hasAudio': has_audio, + 'hasVideo': has_video, + 'outputMode': output_mode.value, + 'resolution': resolution, } - logger.debug( - "POST to %r with params %r, headers %r, proxies %r", - self.endpoints.archive_url(), - json.dumps(payload), - self.json_headers(), - self.proxies, - ) - - response = requests.post( - self.endpoints.get_archive_url(), - data=json.dumps(payload), - headers=self.get_json_headers(), - proxies=self.proxies, - timeout=self.timeout, - ) + response = requests.post(self.endpoints.archive_url(), data=json.dumps(payload), headers=self.json_headers(), proxies=self.proxies, timeout=self.timeout) if response.status_code < 300: return Archive(self, response.json()) @@ -580,19 +399,7 @@ def stop_archive(self, archive_id): :rtype: The Archive object corresponding to the archive being stopped. """ - logger.debug( - "POST to %r with headers %r, proxies %r", - self.endpoints.archive_url(archive_id) + "/stop", - self.json_headers(), - self.proxies, - ) - - response = requests.post( - self.endpoints.get_archive_url(archive_id) + "/stop", - headers=self.get_json_headers(), - proxies=self.proxies, - timeout=self.timeout, - ) + response = requests.post(self.endpoints.archive_url(archive_id) + '/stop', headers=self.json_headers(), proxies=self.proxies, timeout=self.timeout) if response.status_code < 300: return Archive(self, response.json()) @@ -615,19 +422,7 @@ def delete_archive(self, archive_id): :param String archive_id: The archive ID of the archive to be deleted. """ - logger.debug( - "DELETE to %r with headers %r, proxies %r", - self.endpoints.archive_url(archive_id), - self.json_headers(), - self.proxies, - ) - - response = requests.delete( - self.endpoints.get_archive_url(archive_id), - headers=self.get_json_headers(), - proxies=self.proxies, - timeout=self.timeout, - ) + response = requests.delete(self.endpoints.archive_url(archive_id), headers=self.json_headers(), proxies=self.proxies, timeout=self.timeout) if response.status_code < 300: pass @@ -645,19 +440,7 @@ def get_archive(self, archive_id): :rtype: The Archive object. """ - logger.debug( - "GET to %r with headers %r, proxies %r", - self.endpoints.archive_url(archive_id), - self.json_headers(), - self.proxies, - ) - - response = requests.get( - self.endpoints.get_archive_url(archive_id), - headers=self.get_json_headers(), - proxies=self.proxies, - timeout=self.timeout, - ) + response = requests.get(self.endpoints.archive_url(archive_id), headers=self.json_headers(), proxies=self.proxies, timeout=self.timeout) if response.status_code < 300: return Archive(self, response.json()) @@ -683,26 +466,16 @@ def get_archives(self, offset=None, count=None, session_id=None): """ params = {} if offset is not None: - params["offset"] = offset + params['offset'] = offset if count is not None: - params["count"] = count + params['count'] = count if session_id is not None: - params["sessionId"] = session_id + params['sessionId'] = session_id - endpoint = self.endpoints.get_archive_url() + "?" + urlencode(params) - - logger.debug( - "GET to %r with headers %r, proxies %r", - endpoint, - self.json_headers(), - self.proxies, - ) + endpoint = self.endpoints.archive_url() + "?" + urlencode(params) response = requests.get( - endpoint, - headers=self.get_json_headers(), - proxies=self.proxies, - timeout=self.timeout, + endpoint, headers=self.json_headers(), proxies=self.proxies, timeout=self.timeout ) if response.status_code < 300: @@ -721,7 +494,7 @@ def list_archives(self, offset=None, count=None, session_id=None): """ return self.get_archives(offset, count, session_id) - def send_signal(self, session_id, payload, connection_id=None): + def signal(self, session_id, payload, connection_id=None): """ Send signals to all participants in an active OpenTok session or to a specific client connected to that session. @@ -736,50 +509,26 @@ def send_signal(self, session_id, payload, connection_id=None): the signal is sent to the specified client. Otherwise, the signal is sent to all clients connected to the session """ - logger.debug( - "POST to %r with params %r, headers %r, proxies %r", - self.endpoints.signaling_url(session_id, connection_id), - json.dumps(payload), - self.json_headers(), - self.proxies, - ) - response = requests.post( - self.endpoints.get_signaling_url(session_id, connection_id), + self.endpoints.signaling_url(session_id, connection_id), data=json.dumps(payload), - headers=self.get_json_headers(), + headers=self.json_headers(), proxies=self.proxies, - timeout=self.timeout, + timeout=self.timeout ) if response.status_code == 204: pass elif response.status_code == 400: - raise SignalingError( - "One of the signal properties - data, type, sessionId or connectionId - is invalid." - ) + raise SignalingError('One of the signal properties - data, type, sessionId or connectionId - is invalid.') elif response.status_code == 403: - raise AuthError( - "You are not authorized to send the signal. Check your authentication credentials." - ) + raise AuthError('You are not authorized to send the signal. Check your authentication credentials.') elif response.status_code == 404: - raise SignalingError( - "The client specified by the connectionId property is not connected to the session." - ) + raise SignalingError('The client specified by the connectionId property is not connected to the session.') elif response.status_code == 413: - raise SignalingError( - "The type string exceeds the maximum length (128 bytes), or the data string exceeds the maximum size (8 kB)." - ) + raise SignalingError('The type string exceeds the maximum length (128 bytes), or the data string exceeds the maximum size (8 kB).') else: - raise RequestError("An unexpected error occurred", response.status_code) - - def signal(self, session_id, payload, connection_id=None): - warnings.warn( - "opentok.signal is deprecated (use opentok.send_signal instead).", - DeprecationWarning, - stacklevel=2, - ) - self.send_signal(session_id, payload, connection_id) + raise RequestError('An unexpected error occurred', response.status_code) def get_stream(self, session_id, stream_id): """ @@ -791,33 +540,20 @@ def get_stream(self, session_id, stream_id): -layoutClassList: It's an array of the layout classes for the stream """ endpoint = self.endpoints.get_stream_url(session_id, stream_id) - - logger.debug( - "GET to %r with headers %r, proxies %r", - endpoint, - self.json_headers(), - self.proxies, - ) - response = requests.get( - endpoint, - headers=self.get_json_headers(), - proxies=self.proxies, - timeout=self.timeout, + endpoint, headers=self.json_headers(), proxies=self.proxies, timeout=self.timeout ) if response.status_code == 200: return Stream(response.json()) elif response.status_code == 400: - raise GetStreamError( - "Invalid request. This response may indicate that data in your request data is invalid JSON. Or it may indicate that you do not pass in a session ID or you passed in an invalid stream ID." - ) + raise GetStreamError('Invalid request. This response may indicate that data in your request data is invalid JSON. Or it may indicate that you do not pass in a session ID or you passed in an invalid stream ID.') elif response.status_code == 403: - raise AuthError("You passed in an invalid OpenTok API key or JWT token.") + raise AuthError('You passed in an invalid OpenTok API key or JWT token.') elif response.status_code == 408: - raise GetStreamError("You passed in an invalid stream ID.") + raise GetStreamError('You passed in an invalid stream ID.') else: - raise RequestError("An unexpected error occurred", response.status_code) + raise RequestError('An unexpected error occurred', response.status_code) def list_streams(self, session_id): """ @@ -829,30 +565,18 @@ def list_streams(self, session_id): """ endpoint = self.endpoints.get_stream_url(session_id) - logger.debug( - "GET to %r with headers %r, proxies %r", - endpoint, - self.json_headers(), - self.proxies, - ) - response = requests.get( - endpoint, - headers=self.get_json_headers(), - proxies=self.proxies, - timeout=self.timeout, + endpoint, headers=self.json_headers(), proxies=self.proxies, timeout=self.timeout ) if response.status_code == 200: return StreamList(response.json()) elif response.status_code == 400: - raise GetStreamError( - "Invalid request. This response may indicate that data in your request data is invalid JSON. Or it may indicate that you do not pass in a session ID or you passed in an invalid stream ID." - ) + raise GetStreamError('Invalid request. This response may indicate that data in your request data is invalid JSON. Or it may indicate that you do not pass in a session ID or you passed in an invalid stream ID.') elif response.status_code == 403: - raise AuthError("You passed in an invalid OpenTok API key or JWT token.") + raise AuthError('You passed in an invalid OpenTok API key or JWT token.') else: - raise RequestError("An unexpected error occurred", response.status_code) + raise RequestError('An unexpected error occurred', response.status_code) def force_disconnect(self, session_id, connection_id): """ @@ -864,37 +588,20 @@ def force_disconnect(self, session_id, connection_id): :param String connection_id: The connection ID of the client that will be disconnected """ endpoint = self.endpoints.force_disconnect_url(session_id, connection_id) - - logger.debug( - "DELETE to %r with headers %r, proxies %r", - endpoint, - self.json_headers(), - self.proxies, - ) - response = requests.delete( - endpoint, - headers=self.get_json_headers(), - proxies=self.proxies, - timeout=self.timeout, + endpoint, headers=self.json_headers(), proxies=self.proxies, timeout=self.timeout ) if response.status_code == 204: pass elif response.status_code == 400: - raise ForceDisconnectError( - "One of the arguments - sessionId or connectionId - is invalid." - ) + raise ForceDisconnectError('One of the arguments - sessionId or connectionId - is invalid.') elif response.status_code == 403: - raise AuthError( - "You are not authorized to forceDisconnect, check your authentication credentials." - ) + raise AuthError('You are not authorized to forceDisconnect, check your authentication credentials.') elif response.status_code == 404: - raise ForceDisconnectError( - "The client specified by the connectionId property is not connected to the session." - ) + raise ForceDisconnectError('The client specified by the connectionId property is not connected to the session.') else: - raise RequestError("An unexpected error occurred", response.status_code) + raise RequestError('An unexpected error occurred', response.status_code) def set_archive_layout(self, archive_id, layout_type, stylesheet=None): """ @@ -909,41 +616,30 @@ def set_archive_layout(self, archive_id, layout_type, stylesheet=None): Specify this only if you set the type property to 'custom' """ payload = { - "type": layout_type, + 'type': layout_type, } - if layout_type == "custom": + if layout_type == 'custom': if stylesheet is not None: - payload["stylesheet"] = stylesheet + payload['stylesheet'] = stylesheet endpoint = self.endpoints.set_archive_layout_url(archive_id) - - logger.debug( - "PUT to %r with params %r, headers %r, proxies %r", - endpoint, - json.dumps(payload), - self.json_headers(), - self.proxies, - ) - response = requests.put( endpoint, data=json.dumps(payload), - headers=self.get_json_headers(), + headers=self.json_headers(), proxies=self.proxies, - timeout=self.timeout, + timeout=self.timeout ) if response.status_code == 200: pass elif response.status_code == 400: - raise ArchiveError( - "Invalid request. This response may indicate that data in your request data is invalid JSON. It may also indicate that you passed in invalid layout options." - ) + raise ArchiveError('Invalid request. This response may indicate that data in your request data is invalid JSON. It may also indicate that you passed in invalid layout options.') elif response.status_code == 403: - raise AuthError("Authentication error.") + raise AuthError('Authentication error.') else: - raise RequestError("OpenTok server error.", response.status_code) + raise RequestError('OpenTok server error.', response.status_code) def dial(self, session_id, token, sip_uri, options=[]): """ @@ -982,53 +678,49 @@ def dial(self, session_id, token, sip_uri, options=[]): :rtype: A SipCall object, which contains data of the SIP call: id, connectionId and streamId """ - payload = {"sessionId": session_id, "token": token, "sip": {"uri": sip_uri}} + payload = { + 'sessionId': session_id, + 'token': token, + 'sip': { + 'uri': sip_uri + } + } - if "from" in options: - payload["sip"]["from"] = options["from"] + if 'from' in options: + payload['sip']['from'] = options['from'] - if "headers" in options: - payload["sip"]["headers"] = options["headers"] + if 'headers' in options: + payload['sip']['headers'] = options['headers'] - if "auth" in options: - payload["sip"]["auth"] = options["auth"] + if 'auth' in options: + payload['sip']['auth'] = options['auth'] - if "secure" in options: - payload["sip"]["secure"] = options["secure"] + if 'secure' in options: + payload['sip']['secure'] = options['secure'] endpoint = self.endpoints.dial_url() - - logger.debug( - "POST to %r with params %r, headers %r, proxies %r", - endpoint, - json.dumps(payload), - self.json_headers(), - self.proxies, - ) - response = requests.post( endpoint, data=json.dumps(payload), - headers=self.get_json_headers(), + headers=self.json_headers(), proxies=self.proxies, - timeout=self.timeout, + timeout=self.timeout ) if response.status_code == 200: return SipCall(response.json()) elif response.status_code == 400: - raise SipDialError("Invalid request. Invalid session ID.") + raise SipDialError('Invalid request. Invalid session ID.') elif response.status_code == 403: - raise AuthError("Authentication error.") + raise AuthError('Authentication error.') elif response.status_code == 404: - raise SipDialError("The session does not exist.") + raise SipDialError('The session does not exist.') elif response.status_code == 409: raise SipDialError( - "You attempted to start a SIP call for a session that " - "does not use the OpenTok Media Router." - ) + 'You attempted to start a SIP call for a session that ' + 'does not use the OpenTok Media Router.') else: - raise RequestError("OpenTok server error.", response.status_code) + raise RequestError('OpenTok server error.', response.status_code) def set_stream_class_lists(self, session_id, payload): """ @@ -1048,37 +740,28 @@ class names (Strings) to apply to the stream. For example: {'id': '307dc941-0450-4c09-975c-705740d08970', 'layoutClassList': ['bottom']} ] """ - items_payload = {"items": payload} + items_payload = {'items': payload} endpoint = self.endpoints.set_stream_class_lists_url(session_id) - - logger.debug( - "PUT to %r with params %r, headers %r, proxies %r", - endpoint, - json.dumps(items_payload), - self.json_headers(), - self.proxies, - ) - response = requests.put( endpoint, data=json.dumps(items_payload), - headers=self.get_json_headers(), + headers=self.json_headers(), proxies=self.proxies, - timeout=self.timeout, + timeout=self.timeout ) if response.status_code == 200: pass elif response.status_code == 400: raise SetStreamClassError( - "Invalid request. This response may indicate that data in your request data " - "is invalid JSON. It may also indicate that you passed in invalid layout options." + 'Invalid request. This response may indicate that data in your request data ' + 'is invalid JSON. It may also indicate that you passed in invalid layout options.' ) elif response.status_code == 403: - raise AuthError("Authentication error.") + raise AuthError('Authentication error.') else: - raise RequestError("OpenTok server error.", response.status_code) + raise RequestError('OpenTok server error.', response.status_code) def start_broadcast(self, session_id, options): """ @@ -1118,43 +801,35 @@ def start_broadcast(self, session_id, options): :rtype A Broadcast object, which contains information of the broadcast: id, sessionId projectId, createdAt, updatedAt, resolution, status and broadcastUrls """ - payload = {"sessionId": session_id} + payload = { + 'sessionId': session_id + } payload.update(options) endpoint = self.endpoints.broadcast_url() - - logger.debug( - "POST to %r with params %r, headers %r, proxies %r", - endpoint, - json.dumps(payload), - self.json_headers(), - self.proxies, - ) - response = requests.post( endpoint, data=json.dumps(payload), - headers=self.get_json_headers(), + headers=self.json_headers(), proxies=self.proxies, - timeout=self.timeout, + timeout=self.timeout ) if response.status_code == 200: return Broadcast(response.json()) elif response.status_code == 400: raise BroadcastError( - "Invalid request. This response may indicate that data in your request data is " - "invalid JSON. It may also indicate that you passed in invalid layout options. " - "Or you have exceeded the limit of five simultaneous RTMP streams for an OpenTok " - "session. Or you specified and invalid resolution." - ) + 'Invalid request. This response may indicate that data in your request data is ' + 'invalid JSON. It may also indicate that you passed in invalid layout options. ' + 'Or you have exceeded the limit of five simultaneous RTMP streams for an OpenTok ' + 'session. Or you specified and invalid resolution.') elif response.status_code == 403: - raise AuthError("Authentication error.") + raise AuthError('Authentication error.') elif response.status_code == 409: - raise BroadcastError("The broadcast has already started for the session.") + raise BroadcastError('The broadcast has already started for the session.') else: - raise RequestError("OpenTok server error.", response.status_code) + raise RequestError('OpenTok server error.', response.status_code) def stop_broadcast(self, broadcast_id): """ @@ -1165,39 +840,28 @@ def stop_broadcast(self, broadcast_id): :rtype A Broadcast object, which contains information of the broadcast: id, sessionId projectId, createdAt, updatedAt and resolution """ - endpoint = self.endpoints.broadcast_url(broadcast_id, stop=True) - - logger.debug( - "POST to %r with headers %r, proxies %r", - endpoint, - self.json_headers(), - self.proxies, - ) - response = requests.post( endpoint, - headers=self.get_json_headers(), + headers=self.json_headers(), proxies=self.proxies, - timeout=self.timeout, + timeout=self.timeout ) if response.status_code == 200: return Broadcast(response.json()) elif response.status_code == 400: raise BroadcastError( - "Invalid request. This response may indicate that data in your request " - "data is invalid JSON." - ) + 'Invalid request. This response may indicate that data in your request ' + 'data is invalid JSON.') elif response.status_code == 403: - raise AuthError("Authentication error.") + raise AuthError('Authentication error.') elif response.status_code == 409: raise BroadcastError( - "The broadcast (with the specified ID) was not found or it has already " - "stopped." - ) + 'The broadcast (with the specified ID) was not found or it has already ' + 'stopped.') else: - raise RequestError("OpenTok server error.", response.status_code) + raise RequestError('OpenTok server error.', response.status_code) def get_broadcast(self, broadcast_id): """ @@ -1208,36 +872,26 @@ def get_broadcast(self, broadcast_id): :rtype A Broadcast object, which contains information of the broadcast: id, sessionId projectId, createdAt, updatedAt, resolution, broadcastUrls and status """ - endpoint = self.endpoints.broadcast_url(broadcast_id) - - logger.debug( - "GET to %r with headers %r, proxies %r", - endpoint, - self.json_headers(), - self.proxies, - ) - response = requests.get( endpoint, - headers=self.get_json_headers(), + headers=self.json_headers(), proxies=self.proxies, - timeout=self.timeout, + timeout=self.timeout ) if response.status_code == 200: return Broadcast(response.json()) elif response.status_code == 400: raise BroadcastError( - "Invalid request. This response may indicate that data in your request " - "data is invalid JSON." - ) + 'Invalid request. This response may indicate that data in your request ' + 'data is invalid JSON.') elif response.status_code == 403: - raise AuthError("Authentication error.") + raise AuthError('Authentication error.') elif response.status_code == 409: - raise BroadcastError("No matching broadcast found (with the specified ID).") + raise BroadcastError('No matching broadcast found (with the specified ID).') else: - raise RequestError("OpenTok server error.", response.status_code) + raise RequestError('OpenTok server error.', response.status_code) def set_broadcast_layout(self, broadcast_id, layout_type, stylesheet=None): """ @@ -1252,56 +906,43 @@ def set_broadcast_layout(self, broadcast_id, layout_type, stylesheet=None): Specify this only if you set the type property to 'custom' """ payload = { - "type": layout_type, + 'type': layout_type, } - if layout_type == "custom": + if layout_type == 'custom': if stylesheet is not None: - payload["stylesheet"] = stylesheet + payload['stylesheet'] = stylesheet endpoint = self.endpoints.broadcast_url(broadcast_id, layout=True) - - logger.debug( - "PUT to %r with params %r, headers %r, proxies %r", - endpoint, - json.dumps(payload), - self.json_headers(), - self.proxies, - ) - response = requests.put( endpoint, data=json.dumps(payload), - headers=self.get_json_headers(), + headers=self.json_headers(), proxies=self.proxies, - timeout=self.timeout, + timeout=self.timeout ) if response.status_code == 200: pass elif response.status_code == 400: raise BroadcastError( - "Invalid request. This response may indicate that data in your request data is " - "invalid JSON. It may also indicate that you passed in invalid layout options." - ) + 'Invalid request. This response may indicate that data in your request data is ' + 'invalid JSON. It may also indicate that you passed in invalid layout options.') elif response.status_code == 403: - raise AuthError("Authentication error.") + raise AuthError('Authentication error.') else: - raise RequestError("OpenTok server error.", response.status_code) + raise RequestError('OpenTok server error.', response.status_code) def _sign_string(self, string, secret): - return hmac.new( - secret.encode("utf-8"), string.encode("utf-8"), hashlib.sha1 - ).hexdigest() + return hmac.new(secret.encode('utf-8'), string.encode('utf-8'), hashlib.sha1).hexdigest() def _create_jwt_auth_header(self): payload = { - "ist": "project", - "iss": self.api_key, - "iat": int(time.time()), # current time in unix time (seconds) - "exp": int(time.time()) - + (60 * self._jwt_livetime), # 3 minutes in the future (seconds) - "jti": "{0}".format(0, random.random()), - } - - return jwt.encode(payload, self.api_secret, algorithm="HS256") + 'ist': 'project', + 'iss': self.api_key, + 'iat': int(time.time()), # current time in unix time (seconds) + 'exp': int(time.time()) + (60*3), # 3 minutes in the future (seconds) + 'jti': '{0}'.format(0, random.random()) + } + + return jwt.encode(payload, self.api_secret, algorithm='HS256') diff --git a/opentok/session.py b/opentok/session.py index 3ccbe38..02d21c4 100644 --- a/opentok/session.py +++ b/opentok/session.py @@ -1,7 +1,6 @@ from six import text_type, u from .exceptions import OpenTokException - class Session(object): """ Represents an OpenTok session. @@ -11,14 +10,9 @@ class Session(object): :ivar String session_id: The session ID. """ - def __init__(self, sdk, session_id, **kwargs): if not text_type(session_id): - raise OpenTokException( - u("Cannot instantiate Session, session_id was not valid {0}").format( - session_id - ) - ) + raise OpenTokException(u('Cannot instantiate Session, session_id was not valid {0}').format(session_id)) self.session_id = session_id self.sdk = sdk for key, value in kwargs.items(): @@ -26,31 +20,31 @@ def __init__(self, sdk, session_id, **kwargs): def generate_token(self, **kwargs): """ - Generates a token for the session. + Generates a token for the session. - :param String role: The role for the token. Valid values are defined in the Role - class. + :param String role: The role for the token. Valid values are defined in the Role + class. - * `Roles.subscriber` -- A subscriber can only subscribe to streams. + * `Roles.subscriber` -- A subscriber can only subscribe to streams. - * `Roles.publisher` -- A publisher can publish streams, subscribe to - streams, and signal. (This is the default value if you do not specify a role.) + * `Roles.publisher` -- A publisher can publish streams, subscribe to + streams, and signal. (This is the default value if you do not specify a role.) - * `Roles.moderator` -- In addition to the privileges granted to a - publisher, in clients using the OpenTok.js 2.2 library, a moderator can call the - `forceUnpublish()` and `forceDisconnect()` method of the - Session object. + * `Roles.moderator` -- In addition to the privileges granted to a + publisher, in clients using the OpenTok.js 2.2 library, a moderator can call the + `forceUnpublish()` and `forceDisconnect()` method of the + Session object. - :param int expire_time: The expiration time of the token, in seconds since the UNIX epoch. - The maximum expiration time is 30 days after the creation time. The default expiration - time is 24 hours after the token creation time. + :param int expire_time: The expiration time of the token, in seconds since the UNIX epoch. + The maximum expiration time is 30 days after the creation time. The default expiration + time is 24 hours after the token creation time. - :param String data: A string containing connection metadata describing the - end-user. For example, you can pass the user ID, name, or other data describing the - end-user. The length of the string is limited to 1000 characters. This data cannot be - updated once it is set. + :param String data: A string containing connection metadata describing the + end-user. For example, you can pass the user ID, name, or other data describing the + end-user. The length of the string is limited to 1000 characters. This data cannot be + updated once it is set. - :rtype: - The token string. + :rtype: + The token string. """ return self.sdk.generate_token(self.session_id, **kwargs) diff --git a/opentok/sip_call.py b/opentok/sip_call.py index 2d36334..b3addc9 100644 --- a/opentok/sip_call.py +++ b/opentok/sip_call.py @@ -1,15 +1,14 @@ import json - class SipCall(object): """ Represents data from a SIP call """ def __init__(self, kwargs): - self.id = kwargs.get("id") - self.connectionId = kwargs.get("connectionId") - self.streamId = kwargs.get("streamId") + self.id = kwargs.get('id') + self.connectionId = kwargs.get('connectionId') + self.streamId = kwargs.get('streamId') def json(self): """ diff --git a/opentok/stream.py b/opentok/stream.py index 11cba0a..cfe28fc 100644 --- a/opentok/stream.py +++ b/opentok/stream.py @@ -2,26 +2,20 @@ from six import iteritems, PY2, PY3, u import json from six.moves import map - -dthandler = ( - lambda obj: obj.isoformat() - if isinstance(obj, datetime) or isinstance(obj, date) - else None -) +dthandler = lambda obj: obj.isoformat() if isinstance(obj, datetime) or isinstance(obj, date) else None from .exceptions import GetStreamError - class Stream(object): """ Represents an OpenTok stream """ def __init__(self, kwargs): - self.id = kwargs.get("id") - self.videoType = kwargs.get("videoType") - self.name = kwargs.get("name") - self.layoutClassList = kwargs.get("layoutClassList") + self.id = kwargs.get('id') + self.videoType = kwargs.get('videoType') + self.name = kwargs.get('name') + self.layoutClassList = kwargs.get('layoutClassList') def attrs(self): """ diff --git a/opentok/streamlist.py b/opentok/streamlist.py index 37740f7..0842415 100644 --- a/opentok/streamlist.py +++ b/opentok/streamlist.py @@ -3,15 +3,14 @@ from .opentok import Stream from .exceptions import GetStreamError - class StreamList(object): """ Represents a list of OpenTok stream objects """ def __init__(self, values): - self.count = values.get("count") - self.items = list(map(lambda x: Stream(x), values.get("items", []))) + self.count = values.get('count') + self.items = list(map(lambda x: Stream(x), values.get('items', []))) def __iter__(self): for x in self.items: @@ -24,9 +23,7 @@ def __getitem__(self, key): return self.items.get(key) def __setitem__(self, key, item): - raise GetStreamError( - u("Cannot set item {0} for key {1} in Archive object").format(item, key) - ) + raise GetStreamError(u('Cannot set item {0} for key {1} in Archive object').format(item, key)) def __len__(self): return len(self.items) \ No newline at end of file diff --git a/opentok/version.py b/opentok/version.py index 92e711a..fcea62a 100644 --- a/opentok/version.py +++ b/opentok/version.py @@ -1,2 +1,2 @@ # see: http://legacy.python.org/dev/peps/pep-0440/#public-version-identifiers -__version__ = "2.10.0" +__version__ = '2.10.0' diff --git a/sample/Archiving/archiving.py b/sample/Archiving/archiving.py index c656191..c06775f 100644 --- a/sample/Archiving/archiving.py +++ b/sample/Archiving/archiving.py @@ -4,96 +4,74 @@ import os, time try: - api_key = os.environ["API_KEY"] - api_secret = os.environ["API_SECRET"] + api_key = os.environ['API_KEY'] + api_secret = os.environ['API_SECRET'] except Exception: - raise Exception("You must define API_KEY and API_SECRET environment variables") + raise Exception('You must define API_KEY and API_SECRET environment variables') app = Flask(__name__) opentok = OpenTok(api_key, api_secret) session = opentok.create_session(media_mode=MediaModes.routed) - -@app.template_filter("datefmt") +@app.template_filter('datefmt') def datefmt(dt): return formatdate(time.mktime(dt.timetuple())) - @app.route("/") def index(): - return render_template("index.html") - + return render_template('index.html') @app.route("/host") def host(): key = api_key session_id = session.session_id token = opentok.generate_token(session_id) - return render_template("host.html", api_key=key, session_id=session_id, token=token) - + return render_template('host.html', api_key=key, session_id=session_id, token=token) @app.route("/participant") def participant(): key = api_key session_id = session.session_id token = opentok.generate_token(session_id) - return render_template( - "participant.html", api_key=key, session_id=session_id, token=token - ) - + return render_template('participant.html', api_key=key, session_id=session_id, token=token) @app.route("/history") def history(): - page = int(request.args.get("page", "1")) + page = int(request.args.get('page', '1')) offset = (page - 1) * 5 archives = opentok.get_archives(offset=offset, count=5) - show_previous = "/history?page=" + str(page - 1) if page > 1 else None - show_next = ( - "/history?page=" + str(page + 1) if archives.count > (offset + 5) else None - ) - - return render_template( - "history.html", - archives=archives, - show_previous=show_previous, - show_next=show_next, - ) + show_previous = '/history?page=' + str(page-1) if page > 1 else None + show_next = '/history?page=' + str(page+1) if archives.count > (offset + 5) else None + return render_template('history.html', archives=archives, show_previous=show_previous, + show_next=show_next) @app.route("/download/") def download(archive_id): archive = opentok.get_archive(archive_id) return redirect(archive.url) - -@app.route("/start", methods=["POST"]) +@app.route("/start", methods=['POST']) def start(): - has_audio = "hasAudio" in request.form.keys() - has_video = "hasVideo" in request.form.keys() - output_mode = OutputModes[request.form.get("outputMode")] - resolution = request.form.get("resolution") - archive = opentok.start_archive( - session.session_id, - name="Python Archiving Sample App", - has_audio=has_audio, - has_video=has_video, - output_mode=output_mode, - resolution=resolution, - ) + has_audio = 'hasAudio' in request.form.keys() + has_video = 'hasVideo' in request.form.keys() + output_mode = OutputModes[request.form.get('outputMode')] + resolution = request.form.get('resolution') + archive = opentok.start_archive(session.session_id, name="Python Archiving Sample App", + has_audio=has_audio, has_video=has_video, + output_mode=output_mode, resolution=resolution) return archive.json() - @app.route("/stop/") def stop(archive_id): archive = opentok.stop_archive(archive_id) return archive.json() - @app.route("/delete/") def delete(archive_id): opentok.delete_archive(archive_id) - return redirect(url_for("history")) + return redirect(url_for('history')) if __name__ == "__main__": diff --git a/sample/HelloWorld/helloworld.py b/sample/HelloWorld/helloworld.py index b5ffa80..92fe913 100644 --- a/sample/HelloWorld/helloworld.py +++ b/sample/HelloWorld/helloworld.py @@ -3,25 +3,21 @@ import os try: - api_key = os.environ["API_KEY"] - api_secret = os.environ["API_SECRET"] + api_key = os.environ['API_KEY'] + api_secret = os.environ['API_SECRET'] except Exception: - raise Exception("You must define API_KEY and API_SECRET environment variables") + raise Exception('You must define API_KEY and API_SECRET environment variables') app = Flask(__name__) opentok = OpenTok(api_key, api_secret) session = opentok.create_session() - @app.route("/") def hello(): key = api_key session_id = session.session_id token = opentok.generate_token(session_id) - return render_template( - "index.html", api_key=key, session_id=session_id, token=token - ) - + return render_template('index.html', api_key=key, session_id=session_id, token=token) if __name__ == "__main__": app.debug = True diff --git a/tests/helpers.py b/tests/helpers.py index 2e8180b..4672cd8 100644 --- a/tests/helpers.py +++ b/tests/helpers.py @@ -7,27 +7,22 @@ def token_decoder(token): token_data = {} - # remove sentinal + #remove sentinal encoded = token[4:] - decoded = base64.b64decode(encoded.encode("utf-8")) + decoded = base64.b64decode(encoded.encode('utf-8')) # decode the bytes object back to unicode with utf-8 encoding if PY3: decoded = decoded.decode() - parts = decoded.split(u(":")) + parts = decoded.split(u(':')) for decoded_part in iter(parts): token_data.update(parse_qs(decoded_part)) # TODO: probably a more elegent way for k in iter(token_data): token_data[k] = token_data[k][0] - token_data[u("data_string")] = parts[1] + token_data[u('data_string')] = parts[1] return token_data - def token_signature_validator(token, secret): decoded = token_decoder(token) - signature = hmac.new( - secret.encode(u("utf-8")), - decoded[u("data_string")].encode("utf-8"), - hashlib.sha1, - ).hexdigest() - return signature == decoded[u("sig")] + signature = hmac.new(secret.encode(u('utf-8')), decoded[u('data_string')].encode('utf-8'), hashlib.sha1).hexdigest() + return signature == decoded[u('sig')] diff --git a/tests/test_archive.py b/tests/test_archive.py index b2d34f0..fbeb5b7 100644 --- a/tests/test_archive.py +++ b/tests/test_archive.py @@ -11,130 +11,98 @@ from opentok import OpenTok, Archive, __version__, OutputModes - class OpenTokArchiveTest(unittest.TestCase): def setUp(self): - self.api_key = u("123456") - self.api_secret = u("1234567890abcdef1234567890abcdef1234567890") + self.api_key = u('123456') + self.api_secret = u('1234567890abcdef1234567890abcdef1234567890') self.opentok = OpenTok(self.api_key, self.api_secret) @httpretty.activate def test_stop_archive(self): - archive_id = u("ARCHIVEID") - archive = Archive( - self.opentok, - { - u("createdAt"): 1395183243556, - u("duration"): 0, - u("id"): archive_id, - u("name"): u(""), - u("partnerId"): 123456, - u("reason"): u(""), - u("sessionId"): u("SESSIONID"), - u("size"): 0, - u("status"): u("started"), - u("hasAudio"): True, - u("hasVideo"): True, - u("outputMode"): OutputModes.composed.value, - u("url"): None, - }, - ) - httpretty.register_uri( - httpretty.POST, - u("https://api.opentok.com/v2/project/{0}/archive/{1}/stop").format( - self.api_key, archive_id - ), - body=textwrap.dedent( - u( - """\ - { - "createdAt" : 1395183243556, - "duration" : 0, - "id" : "ARCHIVEID", - "name" : "", - "partnerId" : 123456, - "reason" : "", - "sessionId" : "SESSIONID", - "size" : 0, - "status" : "stopped", - "hasAudio": true, - "hasVideo": false, - "outputMode": "composed", - "url" : null - } - """ - ) - ), - status=200, - content_type=u("application/json"), - ) + archive_id = u('ARCHIVEID') + archive = Archive(self.opentok, { + u('createdAt'): 1395183243556, + u('duration'): 0, + u('id'): archive_id, + u('name'): u(''), + u('partnerId'): 123456, + u('reason'): u(''), + u('sessionId'): u('SESSIONID'), + u('size'): 0, + u('status'): u('started'), + u('hasAudio'): True, + u('hasVideo'): True, + u('outputMode'): OutputModes.composed.value, + u('url'): None, + }) + httpretty.register_uri(httpretty.POST, u('https://api.opentok.com/v2/project/{0}/archive/{1}/stop').format(self.api_key, archive_id), + body=textwrap.dedent(u("""\ + { + "createdAt" : 1395183243556, + "duration" : 0, + "id" : "ARCHIVEID", + "name" : "", + "partnerId" : 123456, + "reason" : "", + "sessionId" : "SESSIONID", + "size" : 0, + "status" : "stopped", + "hasAudio": true, + "hasVideo": false, + "outputMode": "composed", + "url" : null + }""")), + status=200, + content_type=u('application/json')) archive.stop() - validate_jwt_header(self, httpretty.last_request().headers[u("x-opentok-auth")]) - expect(httpretty.last_request().headers[u("user-agent")]).to( - contain(u("OpenTok-Python-SDK/") + __version__) - ) - expect(httpretty.last_request().headers[u("content-type")]).to( - equal(u("application/json")) - ) + validate_jwt_header(self, httpretty.last_request().headers[u('x-opentok-auth')]) + expect(httpretty.last_request().headers[u('user-agent')]).to(contain(u('OpenTok-Python-SDK/')+__version__)) + expect(httpretty.last_request().headers[u('content-type')]).to(equal(u('application/json'))) expect(archive).to(be_an(Archive)) - expect(archive).to(have_property(u("id"), archive_id)) - expect(archive).to(have_property(u("name"), u(""))) - expect(archive).to(have_property(u("status"), u("stopped"))) - expect(archive).to(have_property(u("session_id"), u("SESSIONID"))) - expect(archive).to(have_property(u("partner_id"), 123456)) + expect(archive).to(have_property(u('id'), archive_id)) + expect(archive).to(have_property(u('name'), u(''))) + expect(archive).to(have_property(u('status'), u('stopped'))) + expect(archive).to(have_property(u('session_id'), u('SESSIONID'))) + expect(archive).to(have_property(u('partner_id'), 123456)) if PY2: created_at = datetime.datetime.fromtimestamp(1395183243, pytz.UTC) if PY3: - created_at = datetime.datetime.fromtimestamp( - 1395183243, datetime.timezone.utc - ) - expect(archive).to(have_property(u("created_at"), created_at)) - expect(archive).to(have_property(u("size"), 0)) - expect(archive).to(have_property(u("duration"), 0)) - expect(archive).to(have_property(u("has_audio"), True)) - expect(archive).to(have_property(u("has_video"), False)) - expect(archive).to(have_property(u("output_mode"), OutputModes.composed)) - expect(archive).to(have_property(u("url"), None)) + created_at = datetime.datetime.fromtimestamp(1395183243, datetime.timezone.utc) + expect(archive).to(have_property(u('created_at'), created_at)) + expect(archive).to(have_property(u('size'), 0)) + expect(archive).to(have_property(u('duration'), 0)) + expect(archive).to(have_property(u('has_audio'), True)) + expect(archive).to(have_property(u('has_video'), False)) + expect(archive).to(have_property(u('output_mode'), OutputModes.composed)) + expect(archive).to(have_property(u('url'), None)) @httpretty.activate def test_delete_archive(self): - archive_id = u("ARCHIVEID") - archive = Archive( - self.opentok, - { - u("createdAt"): 1395183243556, - u("duration"): 0, - u("id"): archive_id, - u("name"): u(""), - u("partnerId"): 123456, - u("reason"): u(""), - u("sessionId"): u("SESSIONID"), - u("size"): 0, - u("status"): u("available"), - u("hasAudio"): True, - u("hasVideo"): True, - u("outputMode"): OutputModes.composed.value, - u("url"): None, - }, - ) - httpretty.register_uri( - httpretty.DELETE, - u("https://api.opentok.com/v2/project/{0}/archive/{1}").format( - self.api_key, archive_id - ), - body=u(""), - status=204, - ) + archive_id = u('ARCHIVEID') + archive = Archive(self.opentok, { + u('createdAt'): 1395183243556, + u('duration'): 0, + u('id'): archive_id, + u('name'): u(''), + u('partnerId'): 123456, + u('reason'): u(''), + u('sessionId'): u('SESSIONID'), + u('size'): 0, + u('status'): u('available'), + u('hasAudio'): True, + u('hasVideo'): True, + u('outputMode'): OutputModes.composed.value, + u('url'): None, + }) + httpretty.register_uri(httpretty.DELETE, u('https://api.opentok.com/v2/project/{0}/archive/{1}').format(self.api_key, archive_id), + body=u(''), + status=204) archive.delete() - validate_jwt_header(self, httpretty.last_request().headers[u("x-opentok-auth")]) - expect(httpretty.last_request().headers[u("user-agent")]).to( - contain(u("OpenTok-Python-SDK/") + __version__) - ) - expect(httpretty.last_request().headers[u("content-type")]).to( - equal(u("application/json")) - ) + validate_jwt_header(self, httpretty.last_request().headers[u('x-opentok-auth')]) + expect(httpretty.last_request().headers[u('user-agent')]).to(contain(u('OpenTok-Python-SDK/')+__version__)) + expect(httpretty.last_request().headers[u('content-type')]).to(equal(u('application/json'))) # TODO: test that the object is invalidated diff --git a/tests/test_archive_api.py b/tests/test_archive_api.py index 1b30880..79cb3cf 100644 --- a/tests/test_archive_api.py +++ b/tests/test_archive_api.py @@ -16,995 +16,775 @@ OutputModes, OpenTokException, __version__, - ArchiveError, + ArchiveError ) - class OpenTokArchiveApiTest(unittest.TestCase): def setUp(self): - self.api_key = u("123456") - self.api_secret = u("1234567890abcdef1234567890abcdef1234567890") - self.session_id = u("SESSIONID") + self.api_key = u('123456') + self.api_secret = u('1234567890abcdef1234567890abcdef1234567890') + self.session_id = u('SESSIONID') self.opentok = OpenTok(self.api_key, self.api_secret) @httpretty.activate def test_start_archive(self): - httpretty.register_uri( - httpretty.POST, - u("https://api.opentok.com/v2/project/{0}/archive").format(self.api_key), - body=textwrap.dedent( - u( - """\ - { - "createdAt" : 1395183243556, - "duration" : 0, - "id" : "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", - "name" : "", - "partnerId" : 123456, - "reason" : "", - "sessionId" : "SESSIONID", - "size" : 0, - "status" : "started", - "hasAudio": true, - "hasVideo": true, - "outputMode": "composed", - "url" : null - } - """ - ) - ), - status=200, - content_type=u("application/json"), - ) + httpretty.register_uri(httpretty.POST, u('https://api.opentok.com/v2/project/{0}/archive').format(self.api_key), + body=textwrap.dedent(u("""\ + { + "createdAt" : 1395183243556, + "duration" : 0, + "id" : "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", + "name" : "", + "partnerId" : 123456, + "reason" : "", + "sessionId" : "SESSIONID", + "size" : 0, + "status" : "started", + "hasAudio": true, + "hasVideo": true, + "outputMode": "composed", + "url" : null + }""")), + status=200, + content_type=u('application/json')) archive = self.opentok.start_archive(self.session_id) - validate_jwt_header(self, httpretty.last_request().headers[u("x-opentok-auth")]) - expect(httpretty.last_request().headers[u("user-agent")]).to( - contain(u("OpenTok-Python-SDK/") + __version__) - ) - expect(httpretty.last_request().headers[u("content-type")]).to( - equal(u("application/json")) - ) + validate_jwt_header(self, httpretty.last_request().headers[u('x-opentok-auth')]) + expect(httpretty.last_request().headers[u('user-agent')]).to(contain(u('OpenTok-Python-SDK/')+__version__)) + expect(httpretty.last_request().headers[u('content-type')]).to(equal(u('application/json'))) # non-deterministic json encoding. have to decode to test it properly if PY2: body = json.loads(httpretty.last_request().body) if PY3: - body = json.loads(httpretty.last_request().body.decode("utf-8")) - expect(body).to(have_key(u("name"), None)) - expect(body).to(have_key(u("sessionId"), u("SESSIONID"))) + body = json.loads(httpretty.last_request().body.decode('utf-8')) + expect(body).to(have_key(u('name'), None)) + expect(body).to(have_key(u('sessionId'), u('SESSIONID'))) expect(archive).to(be_an(Archive)) - expect(archive).to( - have_property(u("id"), u("30b3ebf1-ba36-4f5b-8def-6f70d9986fe9")) - ) - expect(archive).to(have_property(u("name"), u(""))) - expect(archive).to(have_property(u("status"), u("started"))) - expect(archive).to(have_property(u("session_id"), u("SESSIONID"))) - expect(archive).to(have_property(u("partner_id"), 123456)) + expect(archive).to(have_property(u('id'), u('30b3ebf1-ba36-4f5b-8def-6f70d9986fe9'))) + expect(archive).to(have_property(u('name'), u(''))) + expect(archive).to(have_property(u('status'), u('started'))) + expect(archive).to(have_property(u('session_id'), u('SESSIONID'))) + expect(archive).to(have_property(u('partner_id'), 123456)) if PY2: created_at = datetime.datetime.fromtimestamp(1395183243, pytz.UTC) if PY3: - created_at = datetime.datetime.fromtimestamp( - 1395183243, datetime.timezone.utc - ) - expect(archive).to(have_property(u("created_at"), created_at)) - expect(archive).to(have_property(u("size"), 0)) - expect(archive).to(have_property(u("duration"), 0)) - expect(archive).to(have_property(u("has_audio"), True)) - expect(archive).to(have_property(u("has_video"), True)) - expect(archive).to(have_property(u("url"), None)) + created_at = datetime.datetime.fromtimestamp(1395183243, datetime.timezone.utc) + expect(archive).to(have_property(u('created_at'), created_at)) + expect(archive).to(have_property(u('size'), 0)) + expect(archive).to(have_property(u('duration'), 0)) + expect(archive).to(have_property(u('has_audio'), True)) + expect(archive).to(have_property(u('has_video'), True)) + expect(archive).to(have_property(u('url'), None)) @httpretty.activate def test_start_archive_with_name(self): - httpretty.register_uri( - httpretty.POST, - u("https://api.opentok.com/v2/project/{0}/archive").format(self.api_key), - body=textwrap.dedent( - u( - """\ - { - "createdAt" : 1395183243556, - "duration" : 0, - "id" : "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", - "name" : "ARCHIVE NAME", - "partnerId" : 123456, - "reason" : "", - "sessionId" : "SESSIONID", - "size" : 0, - "status" : "started", - "hasAudio": true, - "hasVideo": true, - "outputMode": "composed", - "url" : null - } - """ - ) - ), - status=200, - content_type=u("application/json"), - ) - - archive = self.opentok.start_archive(self.session_id, name=u("ARCHIVE NAME")) - - validate_jwt_header(self, httpretty.last_request().headers[u("x-opentok-auth")]) - expect(httpretty.last_request().headers[u("user-agent")]).to( - contain(u("OpenTok-Python-SDK/") + __version__) - ) - expect(httpretty.last_request().headers[u("content-type")]).to( - equal(u("application/json")) - ) + httpretty.register_uri(httpretty.POST, u('https://api.opentok.com/v2/project/{0}/archive').format(self.api_key), + body=textwrap.dedent(u("""\ + { + "createdAt" : 1395183243556, + "duration" : 0, + "id" : "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", + "name" : "ARCHIVE NAME", + "partnerId" : 123456, + "reason" : "", + "sessionId" : "SESSIONID", + "size" : 0, + "status" : "started", + "hasAudio": true, + "hasVideo": true, + "outputMode": "composed", + "url" : null + }""")), + status=200, + content_type=u('application/json')) + + archive = self.opentok.start_archive(self.session_id, name=u('ARCHIVE NAME')) + + validate_jwt_header(self, httpretty.last_request().headers[u('x-opentok-auth')]) + expect(httpretty.last_request().headers[u('user-agent')]).to(contain(u('OpenTok-Python-SDK/')+__version__)) + expect(httpretty.last_request().headers[u('content-type')]).to(equal(u('application/json'))) # non-deterministic json encoding. have to decode to test it properly if PY2: body = json.loads(httpretty.last_request().body) if PY3: - body = json.loads(httpretty.last_request().body.decode("utf-8")) - expect(body).to(have_key(u("sessionId"), u("SESSIONID"))) - expect(body).to(have_key(u("name"), u("ARCHIVE NAME"))) + body = json.loads(httpretty.last_request().body.decode('utf-8')) + expect(body).to(have_key(u('sessionId'), u('SESSIONID'))) + expect(body).to(have_key(u('name'), u('ARCHIVE NAME'))) expect(archive).to(be_an(Archive)) - expect(archive).to( - have_property(u("id"), u("30b3ebf1-ba36-4f5b-8def-6f70d9986fe9")) - ) - expect(archive).to(have_property(u("name"), ("ARCHIVE NAME"))) - expect(archive).to(have_property(u("status"), u("started"))) - expect(archive).to(have_property(u("session_id"), u("SESSIONID"))) - expect(archive).to(have_property(u("partner_id"), 123456)) + expect(archive).to(have_property(u('id'), u('30b3ebf1-ba36-4f5b-8def-6f70d9986fe9'))) + expect(archive).to(have_property(u('name'), ('ARCHIVE NAME'))) + expect(archive).to(have_property(u('status'), u('started'))) + expect(archive).to(have_property(u('session_id'), u('SESSIONID'))) + expect(archive).to(have_property(u('partner_id'), 123456)) if PY2: created_at = datetime.datetime.fromtimestamp(1395183243, pytz.UTC) if PY3: - created_at = datetime.datetime.fromtimestamp( - 1395183243, datetime.timezone.utc - ) - expect(archive).to(have_property(u("created_at"), equal(created_at))) - expect(archive).to(have_property(u("size"), equal(0))) - expect(archive).to(have_property(u("duration"), equal(0))) - expect(archive).to(have_property(u("url"), equal(None))) + created_at = datetime.datetime.fromtimestamp(1395183243, datetime.timezone.utc) + expect(archive).to(have_property(u('created_at'), equal(created_at))) + expect(archive).to(have_property(u('size'), equal(0))) + expect(archive).to(have_property(u('duration'), equal(0))) + expect(archive).to(have_property(u('url'), equal(None))) @httpretty.activate def test_start_archive_with_640x480_resolution(self): - httpretty.register_uri( - httpretty.POST, - u("https://api.opentok.com/v2/project/{0}/archive").format(self.api_key), - body=textwrap.dedent( - u( - """\ - { - "createdAt" : 1395183243556, - "duration" : 0, - "id" : "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", - "name" : "ARCHIVE NAME", - "partnerId" : 123456, - "reason" : "", - "sessionId" : "SESSIONID", - "size" : 0, - "status" : "started", - "hasAudio": true, - "hasVideo": true, - "outputMode": "composed", - "url" : null, - "resolution": "640x480" - } - """ - ) - ), - status=200, - content_type=u("application/json"), - ) + httpretty.register_uri(httpretty.POST, u('https://api.opentok.com/v2/project/{0}/archive').format(self.api_key), + body=textwrap.dedent(u("""\ + { + "createdAt" : 1395183243556, + "duration" : 0, + "id" : "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", + "name" : "ARCHIVE NAME", + "partnerId" : 123456, + "reason" : "", + "sessionId" : "SESSIONID", + "size" : 0, + "status" : "started", + "hasAudio": true, + "hasVideo": true, + "outputMode": "composed", + "url" : null, + "resolution": "640x480" + }""")), + status=200, + content_type=u('application/json')) archive = self.opentok.start_archive(self.session_id, resolution="640x480") - validate_jwt_header(self, httpretty.last_request().headers[u("x-opentok-auth")]) - expect(httpretty.last_request().headers[u("user-agent")]).to( - contain(u("OpenTok-Python-SDK/") + __version__) - ) - expect(httpretty.last_request().headers[u("content-type")]).to( - equal(u("application/json")) - ) + validate_jwt_header(self, httpretty.last_request().headers[u('x-opentok-auth')]) + expect(httpretty.last_request().headers[u('user-agent')]).to(contain(u('OpenTok-Python-SDK/')+__version__)) + expect(httpretty.last_request().headers[u('content-type')]).to(equal(u('application/json'))) # non-deterministic json encoding. have to decode to test it properly if PY2: body = json.loads(httpretty.last_request().body) if PY3: - body = json.loads(httpretty.last_request().body.decode("utf-8")) - expect(body).to(have_key(u("sessionId"), u("SESSIONID"))) - expect(body).to(have_key(u("resolution"), u("640x480"))) + body = json.loads(httpretty.last_request().body.decode('utf-8')) + expect(body).to(have_key(u('sessionId'), u('SESSIONID'))) + expect(body).to(have_key(u('resolution'), u('640x480'))) expect(archive).to(be_an(Archive)) - expect(archive).to( - have_property(u("id"), u("30b3ebf1-ba36-4f5b-8def-6f70d9986fe9")) - ) - expect(archive).to(have_property(u("resolution"), "640x480")) - expect(archive).to(have_property(u("status"), u("started"))) - expect(archive).to(have_property(u("session_id"), u("SESSIONID"))) - expect(archive).to(have_property(u("partner_id"), 123456)) + expect(archive).to(have_property(u('id'), u('30b3ebf1-ba36-4f5b-8def-6f70d9986fe9'))) + expect(archive).to(have_property(u('resolution'), "640x480")) + expect(archive).to(have_property(u('status'), u('started'))) + expect(archive).to(have_property(u('session_id'), u('SESSIONID'))) + expect(archive).to(have_property(u('partner_id'), 123456)) if PY2: created_at = datetime.datetime.fromtimestamp(1395183243, pytz.UTC) if PY3: - created_at = datetime.datetime.fromtimestamp( - 1395183243, datetime.timezone.utc - ) - expect(archive).to(have_property(u("created_at"), equal(created_at))) - expect(archive).to(have_property(u("size"), equal(0))) - expect(archive).to(have_property(u("duration"), equal(0))) - expect(archive).to(have_property(u("url"), equal(None))) + created_at = datetime.datetime.fromtimestamp(1395183243, datetime.timezone.utc) + expect(archive).to(have_property(u('created_at'), equal(created_at))) + expect(archive).to(have_property(u('size'), equal(0))) + expect(archive).to(have_property(u('duration'), equal(0))) + expect(archive).to(have_property(u('url'), equal(None))) @httpretty.activate def test_start_archive_with_1280x720_resolution(self): - httpretty.register_uri( - httpretty.POST, - u("https://api.opentok.com/v2/project/{0}/archive").format(self.api_key), - body=textwrap.dedent( - u( - """\ - { - "createdAt" : 1395183243556, - "duration" : 0, - "id" : "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", - "name" : "ARCHIVE NAME", - "partnerId" : 123456, - "reason" : "", - "sessionId" : "SESSIONID", - "size" : 0, - "status" : "started", - "hasAudio": true, - "hasVideo": true, - "outputMode": "composed", - "url" : null, - "resolution": "1280x720" - } - """ - ) - ), - status=200, - content_type=u("application/json"), - ) + httpretty.register_uri(httpretty.POST, u('https://api.opentok.com/v2/project/{0}/archive').format(self.api_key), + body=textwrap.dedent(u("""\ + { + "createdAt" : 1395183243556, + "duration" : 0, + "id" : "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", + "name" : "ARCHIVE NAME", + "partnerId" : 123456, + "reason" : "", + "sessionId" : "SESSIONID", + "size" : 0, + "status" : "started", + "hasAudio": true, + "hasVideo": true, + "outputMode": "composed", + "url" : null, + "resolution": "1280x720" + }""")), + status=200, + content_type=u('application/json')) archive = self.opentok.start_archive(self.session_id, resolution="1280x720") - validate_jwt_header(self, httpretty.last_request().headers[u("x-opentok-auth")]) - expect(httpretty.last_request().headers[u("user-agent")]).to( - contain(u("OpenTok-Python-SDK/") + __version__) - ) - expect(httpretty.last_request().headers[u("content-type")]).to( - equal(u("application/json")) - ) + validate_jwt_header(self, httpretty.last_request().headers[u('x-opentok-auth')]) + expect(httpretty.last_request().headers[u('user-agent')]).to(contain(u('OpenTok-Python-SDK/')+__version__)) + expect(httpretty.last_request().headers[u('content-type')]).to(equal(u('application/json'))) # non-deterministic json encoding. have to decode to test it properly if PY2: body = json.loads(httpretty.last_request().body) if PY3: - body = json.loads(httpretty.last_request().body.decode("utf-8")) - expect(body).to(have_key(u("sessionId"), u("SESSIONID"))) - expect(body).to(have_key(u("resolution"), u("1280x720"))) + body = json.loads(httpretty.last_request().body.decode('utf-8')) + expect(body).to(have_key(u('sessionId'), u('SESSIONID'))) + expect(body).to(have_key(u('resolution'), u('1280x720'))) expect(archive).to(be_an(Archive)) - expect(archive).to( - have_property(u("id"), u("30b3ebf1-ba36-4f5b-8def-6f70d9986fe9")) - ) - expect(archive).to(have_property(u("resolution"), "1280x720")) - expect(archive).to(have_property(u("status"), u("started"))) - expect(archive).to(have_property(u("session_id"), u("SESSIONID"))) - expect(archive).to(have_property(u("partner_id"), 123456)) + expect(archive).to(have_property(u('id'), u('30b3ebf1-ba36-4f5b-8def-6f70d9986fe9'))) + expect(archive).to(have_property(u('resolution'), "1280x720")) + expect(archive).to(have_property(u('status'), u('started'))) + expect(archive).to(have_property(u('session_id'), u('SESSIONID'))) + expect(archive).to(have_property(u('partner_id'), 123456)) if PY2: created_at = datetime.datetime.fromtimestamp(1395183243, pytz.UTC) if PY3: - created_at = datetime.datetime.fromtimestamp( - 1395183243, datetime.timezone.utc - ) - expect(archive).to(have_property(u("created_at"), equal(created_at))) - expect(archive).to(have_property(u("size"), equal(0))) - expect(archive).to(have_property(u("duration"), equal(0))) - expect(archive).to(have_property(u("url"), equal(None))) + created_at = datetime.datetime.fromtimestamp(1395183243, datetime.timezone.utc) + expect(archive).to(have_property(u('created_at'), equal(created_at))) + expect(archive).to(have_property(u('size'), equal(0))) + expect(archive).to(have_property(u('duration'), equal(0))) + expect(archive).to(have_property(u('url'), equal(None))) def test_start_archive_individual_and_resolution_throws_error(self): - self.assertRaises( - OpenTokException, + self.assertRaises(OpenTokException, self.opentok.start_archive, session_id=self.session_id, output_mode=OutputModes.individual, - resolution="640x480", - ) + resolution="640x480") - self.assertRaises( - OpenTokException, + self.assertRaises(OpenTokException, self.opentok.start_archive, session_id=self.session_id, output_mode=OutputModes.individual, - resolution="1280x720", - ) + resolution="1280x720") @httpretty.activate def test_start_voice_archive(self): - httpretty.register_uri( - httpretty.POST, - u("https://api.opentok.com/v2/project/{0}/archive").format(self.api_key), - body=textwrap.dedent( - u( - """\ - { - "createdAt" : 1395183243556, - "duration" : 0, - "id" : "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", - "name" : "ARCHIVE NAME", - "partnerId" : 123456, - "reason" : "", - "sessionId" : "SESSIONID", - "size" : 0, - "status" : "started", - "hasAudio": true, - "hasVideo": false, - "outputMode": "composed", - "url" : null - } - """ - ) - ), - status=200, - content_type=u("application/json"), - ) - - archive = self.opentok.start_archive( - self.session_id, name=u("ARCHIVE NAME"), has_video=False - ) - - validate_jwt_header(self, httpretty.last_request().headers[u("x-opentok-auth")]) - expect(httpretty.last_request().headers[u("user-agent")]).to( - contain(u("OpenTok-Python-SDK/") + __version__) - ) - expect(httpretty.last_request().headers[u("content-type")]).to( - equal(u("application/json")) - ) + httpretty.register_uri(httpretty.POST, u('https://api.opentok.com/v2/project/{0}/archive').format(self.api_key), + body=textwrap.dedent(u("""\ + { + "createdAt" : 1395183243556, + "duration" : 0, + "id" : "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", + "name" : "ARCHIVE NAME", + "partnerId" : 123456, + "reason" : "", + "sessionId" : "SESSIONID", + "size" : 0, + "status" : "started", + "hasAudio": true, + "hasVideo": false, + "outputMode": "composed", + "url" : null + }""")), + status=200, + content_type=u('application/json')) + + archive = self.opentok.start_archive(self.session_id, name=u('ARCHIVE NAME'), has_video=False) + + validate_jwt_header(self, httpretty.last_request().headers[u('x-opentok-auth')]) + expect(httpretty.last_request().headers[u('user-agent')]).to(contain(u('OpenTok-Python-SDK/')+__version__)) + expect(httpretty.last_request().headers[u('content-type')]).to(equal(u('application/json'))) # non-deterministic json encoding. have to decode to test it properly if PY2: body = json.loads(httpretty.last_request().body) if PY3: - body = json.loads(httpretty.last_request().body.decode("utf-8")) - expect(body).to(have_key(u("sessionId"), u("SESSIONID"))) - expect(body).to(have_key(u("name"), u("ARCHIVE NAME"))) + body = json.loads(httpretty.last_request().body.decode('utf-8')) + expect(body).to(have_key(u('sessionId'), u('SESSIONID'))) + expect(body).to(have_key(u('name'), u('ARCHIVE NAME'))) expect(archive).to(be_an(Archive)) - expect(archive).to( - have_property(u("id"), u("30b3ebf1-ba36-4f5b-8def-6f70d9986fe9")) - ) - expect(archive).to(have_property(u("name"), ("ARCHIVE NAME"))) - expect(archive).to(have_property(u("status"), u("started"))) - expect(archive).to(have_property(u("session_id"), u("SESSIONID"))) - expect(archive).to(have_property(u("partner_id"), 123456)) + expect(archive).to(have_property(u('id'), u('30b3ebf1-ba36-4f5b-8def-6f70d9986fe9'))) + expect(archive).to(have_property(u('name'), ('ARCHIVE NAME'))) + expect(archive).to(have_property(u('status'), u('started'))) + expect(archive).to(have_property(u('session_id'), u('SESSIONID'))) + expect(archive).to(have_property(u('partner_id'), 123456)) if PY2: created_at = datetime.datetime.fromtimestamp(1395183243, pytz.UTC) if PY3: - created_at = datetime.datetime.fromtimestamp( - 1395183243, datetime.timezone.utc - ) - expect(archive).to(have_property(u("created_at"), created_at)) - expect(archive).to(have_property(u("size"), 0)) - expect(archive).to(have_property(u("duration"), 0)) - expect(archive).to(have_property(u("has_audio"), True)) - expect(archive).to(have_property(u("has_video"), False)) - expect(archive).to(have_property(u("url"), None)) + created_at = datetime.datetime.fromtimestamp(1395183243, datetime.timezone.utc) + expect(archive).to(have_property(u('created_at'), created_at)) + expect(archive).to(have_property(u('size'), 0)) + expect(archive).to(have_property(u('duration'), 0)) + expect(archive).to(have_property(u('has_audio'), True)) + expect(archive).to(have_property(u('has_video'), False)) + expect(archive).to(have_property(u('url'), None)) @httpretty.activate def test_start_individual_archive(self): - httpretty.register_uri( - httpretty.POST, - u("https://api.opentok.com/v2/project/{0}/archive").format(self.api_key), - body=textwrap.dedent( - u( - """\ - { - "createdAt" : 1395183243556, - "duration" : 0, - "id" : "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", - "name" : "ARCHIVE NAME", - "partnerId" : 123456, - "reason" : "", - "sessionId" : "SESSIONID", - "size" : 0, - "status" : "started", - "hasAudio": true, - "hasVideo": true, - "outputMode": "individual", - "url" : null - } - """ - ) - ), - status=200, - content_type=u("application/json"), - ) - - archive = self.opentok.start_archive( - self.session_id, name=u("ARCHIVE NAME"), output_mode=OutputModes.individual - ) - - validate_jwt_header(self, httpretty.last_request().headers[u("x-opentok-auth")]) - expect(httpretty.last_request().headers[u("user-agent")]).to( - contain(u("OpenTok-Python-SDK/") + __version__) - ) - expect(httpretty.last_request().headers[u("content-type")]).to( - equal(u("application/json")) - ) + httpretty.register_uri(httpretty.POST, u('https://api.opentok.com/v2/project/{0}/archive').format(self.api_key), + body=textwrap.dedent(u("""\ + { + "createdAt" : 1395183243556, + "duration" : 0, + "id" : "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", + "name" : "ARCHIVE NAME", + "partnerId" : 123456, + "reason" : "", + "sessionId" : "SESSIONID", + "size" : 0, + "status" : "started", + "hasAudio": true, + "hasVideo": true, + "outputMode": "individual", + "url" : null + }""")), + status=200, + content_type=u('application/json')) + + archive = self.opentok.start_archive(self.session_id, name=u('ARCHIVE NAME'), output_mode=OutputModes.individual) + + validate_jwt_header(self, httpretty.last_request().headers[u('x-opentok-auth')]) + expect(httpretty.last_request().headers[u('user-agent')]).to(contain(u('OpenTok-Python-SDK/')+__version__)) + expect(httpretty.last_request().headers[u('content-type')]).to(equal(u('application/json'))) # non-deterministic json encoding. have to decode to test it properly if PY2: body = json.loads(httpretty.last_request().body) if PY3: - body = json.loads(httpretty.last_request().body.decode("utf-8")) - expect(body).to(have_key(u("sessionId"), u("SESSIONID"))) - expect(body).to(have_key(u("name"), u("ARCHIVE NAME"))) + body = json.loads(httpretty.last_request().body.decode('utf-8')) + expect(body).to(have_key(u('sessionId'), u('SESSIONID'))) + expect(body).to(have_key(u('name'), u('ARCHIVE NAME'))) expect(archive).to(be_an(Archive)) - expect(archive).to( - have_property(u("id"), u("30b3ebf1-ba36-4f5b-8def-6f70d9986fe9")) - ) - expect(archive).to(have_property(u("name"), ("ARCHIVE NAME"))) - expect(archive).to(have_property(u("status"), u("started"))) - expect(archive).to(have_property(u("session_id"), u("SESSIONID"))) - expect(archive).to(have_property(u("partner_id"), 123456)) + expect(archive).to(have_property(u('id'), u('30b3ebf1-ba36-4f5b-8def-6f70d9986fe9'))) + expect(archive).to(have_property(u('name'), ('ARCHIVE NAME'))) + expect(archive).to(have_property(u('status'), u('started'))) + expect(archive).to(have_property(u('session_id'), u('SESSIONID'))) + expect(archive).to(have_property(u('partner_id'), 123456)) if PY2: created_at = datetime.datetime.fromtimestamp(1395183243, pytz.UTC) if PY3: - created_at = datetime.datetime.fromtimestamp( - 1395183243, datetime.timezone.utc - ) - expect(archive).to(have_property(u("created_at"), created_at)) - expect(archive).to(have_property(u("size"), 0)) - expect(archive).to(have_property(u("duration"), 0)) - expect(archive).to(have_property(u("has_audio"), True)) - expect(archive).to(have_property(u("has_video"), True)) - expect(archive).to(have_property(u("output_mode"), OutputModes.individual)) - expect(archive).to(have_property(u("url"), None)) + created_at = datetime.datetime.fromtimestamp(1395183243, datetime.timezone.utc) + expect(archive).to(have_property(u('created_at'), created_at)) + expect(archive).to(have_property(u('size'), 0)) + expect(archive).to(have_property(u('duration'), 0)) + expect(archive).to(have_property(u('has_audio'), True)) + expect(archive).to(have_property(u('has_video'), True)) + expect(archive).to(have_property(u('output_mode'), OutputModes.individual)) + expect(archive).to(have_property(u('url'), None)) @httpretty.activate def test_start_composed_archive(self): - httpretty.register_uri( - httpretty.POST, - u("https://api.opentok.com/v2/project/{0}/archive").format(self.api_key), - body=textwrap.dedent( - u( - """\ - { - "createdAt" : 1395183243556, - "duration" : 0, - "id" : "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", - "name" : "ARCHIVE NAME", - "partnerId" : 123456, - "reason" : "", - "sessionId" : "SESSIONID", - "size" : 0, - "status" : "started", - "hasAudio": true, - "hasVideo": true, - "outputMode": "composed", - "url" : null - } - """ - ) - ), - status=200, - content_type=u("application/json"), - ) - - archive = self.opentok.start_archive( - self.session_id, name=u("ARCHIVE NAME"), output_mode=OutputModes.composed - ) - - validate_jwt_header(self, httpretty.last_request().headers[u("x-opentok-auth")]) - expect(httpretty.last_request().headers[u("user-agent")]).to( - contain(u("OpenTok-Python-SDK/") + __version__) - ) - expect(httpretty.last_request().headers[u("content-type")]).to( - equal(u("application/json")) - ) + httpretty.register_uri(httpretty.POST, u('https://api.opentok.com/v2/project/{0}/archive').format(self.api_key), + body=textwrap.dedent(u("""\ + { + "createdAt" : 1395183243556, + "duration" : 0, + "id" : "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", + "name" : "ARCHIVE NAME", + "partnerId" : 123456, + "reason" : "", + "sessionId" : "SESSIONID", + "size" : 0, + "status" : "started", + "hasAudio": true, + "hasVideo": true, + "outputMode": "composed", + "url" : null + }""")), + status=200, + content_type=u('application/json')) + + archive = self.opentok.start_archive(self.session_id, name=u('ARCHIVE NAME'), output_mode=OutputModes.composed) + + validate_jwt_header(self, httpretty.last_request().headers[u('x-opentok-auth')]) + expect(httpretty.last_request().headers[u('user-agent')]).to(contain(u('OpenTok-Python-SDK/')+__version__)) + expect(httpretty.last_request().headers[u('content-type')]).to(equal(u('application/json'))) # non-deterministic json encoding. have to decode to test it properly if PY2: body = json.loads(httpretty.last_request().body) if PY3: - body = json.loads(httpretty.last_request().body.decode("utf-8")) - expect(body).to(have_key(u("sessionId"), u("SESSIONID"))) - expect(body).to(have_key(u("name"), u("ARCHIVE NAME"))) + body = json.loads(httpretty.last_request().body.decode('utf-8')) + expect(body).to(have_key(u('sessionId'), u('SESSIONID'))) + expect(body).to(have_key(u('name'), u('ARCHIVE NAME'))) expect(archive).to(be_an(Archive)) - expect(archive).to( - have_property(u("id"), u("30b3ebf1-ba36-4f5b-8def-6f70d9986fe9")) - ) - expect(archive).to(have_property(u("name"), ("ARCHIVE NAME"))) - expect(archive).to(have_property(u("status"), u("started"))) - expect(archive).to(have_property(u("session_id"), u("SESSIONID"))) - expect(archive).to(have_property(u("partner_id"), 123456)) + expect(archive).to(have_property(u('id'), u('30b3ebf1-ba36-4f5b-8def-6f70d9986fe9'))) + expect(archive).to(have_property(u('name'), ('ARCHIVE NAME'))) + expect(archive).to(have_property(u('status'), u('started'))) + expect(archive).to(have_property(u('session_id'), u('SESSIONID'))) + expect(archive).to(have_property(u('partner_id'), 123456)) if PY2: created_at = datetime.datetime.fromtimestamp(1395183243, pytz.UTC) if PY3: - created_at = datetime.datetime.fromtimestamp( - 1395183243, datetime.timezone.utc - ) - expect(archive).to(have_property(u("created_at"), created_at)) - expect(archive).to(have_property(u("size"), 0)) - expect(archive).to(have_property(u("duration"), 0)) - expect(archive).to(have_property(u("has_audio"), True)) - expect(archive).to(have_property(u("has_video"), True)) - expect(archive).to(have_property(u("output_mode"), OutputModes.composed)) - expect(archive).to(have_property(u("url"), None)) + created_at = datetime.datetime.fromtimestamp(1395183243, datetime.timezone.utc) + expect(archive).to(have_property(u('created_at'), created_at)) + expect(archive).to(have_property(u('size'), 0)) + expect(archive).to(have_property(u('duration'), 0)) + expect(archive).to(have_property(u('has_audio'), True)) + expect(archive).to(have_property(u('has_video'), True)) + expect(archive).to(have_property(u('output_mode'), OutputModes.composed)) + expect(archive).to(have_property(u('url'), None)) @httpretty.activate def test_stop_archive(self): - archive_id = u("30b3ebf1-ba36-4f5b-8def-6f70d9986fe9") - httpretty.register_uri( - httpretty.POST, - u("https://api.opentok.com/v2/project/{0}/archive/{1}/stop").format( - self.api_key, archive_id - ), - body=textwrap.dedent( - u( - """\ - { - "createdAt" : 1395183243000, - "duration" : 0, - "id" : "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", - "name" : "", - "partnerId" : 123456, - "reason" : "", - "sessionId" : "SESSIONID", - "size" : 0, - "status" : "stopped", - "hasAudio": true, - "hasVideo": true, - "outputMode": "composed", - "url" : null - } - """ - ) - ), - status=200, - content_type=u("application/json"), - ) + archive_id = u('30b3ebf1-ba36-4f5b-8def-6f70d9986fe9') + httpretty.register_uri(httpretty.POST, u('https://api.opentok.com/v2/project/{0}/archive/{1}/stop').format(self.api_key, archive_id), + body=textwrap.dedent(u("""\ + { + "createdAt" : 1395183243000, + "duration" : 0, + "id" : "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", + "name" : "", + "partnerId" : 123456, + "reason" : "", + "sessionId" : "SESSIONID", + "size" : 0, + "status" : "stopped", + "hasAudio": true, + "hasVideo": true, + "outputMode": "composed", + "url" : null + }""")), + status=200, + content_type=u('application/json')) archive = self.opentok.stop_archive(archive_id) - validate_jwt_header(self, httpretty.last_request().headers[u("x-opentok-auth")]) - expect(httpretty.last_request().headers[u("user-agent")]).to( - contain(u("OpenTok-Python-SDK/") + __version__) - ) - expect(httpretty.last_request().headers[u("content-type")]).to( - equal(u("application/json")) - ) + validate_jwt_header(self, httpretty.last_request().headers[u('x-opentok-auth')]) + expect(httpretty.last_request().headers[u('user-agent')]).to(contain(u('OpenTok-Python-SDK/')+__version__)) + expect(httpretty.last_request().headers[u('content-type')]).to(equal(u('application/json'))) expect(archive).to(be_an(Archive)) - expect(archive).to(have_property(u("id"), archive_id)) - expect(archive).to(have_property(u("name"), u(""))) - expect(archive).to(have_property(u("status"), u("stopped"))) - expect(archive).to(have_property(u("session_id"), u("SESSIONID"))) - expect(archive).to(have_property(u("partner_id"), 123456)) + expect(archive).to(have_property(u('id'), archive_id)) + expect(archive).to(have_property(u('name'), u(''))) + expect(archive).to(have_property(u('status'), u('stopped'))) + expect(archive).to(have_property(u('session_id'), u('SESSIONID'))) + expect(archive).to(have_property(u('partner_id'), 123456)) if PY2: created_at = datetime.datetime.fromtimestamp(1395183243, pytz.UTC) if PY3: - created_at = datetime.datetime.fromtimestamp( - 1395183243, datetime.timezone.utc - ) - expect(archive).to(have_property(u("created_at"), created_at)) - expect(archive).to(have_property(u("size"), 0)) - expect(archive).to(have_property(u("duration"), 0)) - expect(archive).to(have_property(u("url"), None)) + created_at = datetime.datetime.fromtimestamp(1395183243, datetime.timezone.utc) + expect(archive).to(have_property(u('created_at'), created_at)) + expect(archive).to(have_property(u('size'), 0)) + expect(archive).to(have_property(u('duration'), 0)) + expect(archive).to(have_property(u('url'), None)) @httpretty.activate def test_delete_archive(self): - archive_id = u("30b3ebf1-ba36-4f5b-8def-6f70d9986fe9") - httpretty.register_uri( - httpretty.DELETE, - u("https://api.opentok.com/v2/project/{0}/archive/{1}").format( - self.api_key, archive_id - ), - body=u(""), - status=204, - ) + archive_id = u('30b3ebf1-ba36-4f5b-8def-6f70d9986fe9') + httpretty.register_uri(httpretty.DELETE, u('https://api.opentok.com/v2/project/{0}/archive/{1}').format(self.api_key, archive_id), + body=u(''), + status=204) self.opentok.delete_archive(archive_id) - validate_jwt_header(self, httpretty.last_request().headers[u("x-opentok-auth")]) - expect(httpretty.last_request().headers[u("user-agent")]).to( - contain(u("OpenTok-Python-SDK/") + __version__) - ) - expect(httpretty.last_request().headers[u("content-type")]).to( - equal(u("application/json")) - ) + validate_jwt_header(self, httpretty.last_request().headers[u('x-opentok-auth')]) + expect(httpretty.last_request().headers[u('user-agent')]).to(contain(u('OpenTok-Python-SDK/')+__version__)) + expect(httpretty.last_request().headers[u('content-type')]).to(equal(u('application/json'))) @httpretty.activate def test_find_archive(self): - archive_id = u("f6e7ee58-d6cf-4a59-896b-6d56b158ec71") - httpretty.register_uri( - httpretty.GET, - u("https://api.opentok.com/v2/project/{0}/archive/{1}").format( - self.api_key, archive_id - ), - body=textwrap.dedent( - u( - """\ - { - "createdAt" : 1395187836000, - "duration" : 62, - "id" : "f6e7ee58-d6cf-4a59-896b-6d56b158ec71", - "name" : "", - "partnerId" : 123456, - "reason" : "", - "sessionId" : "SESSIONID", - "size" : 8347554, - "status" : "available", - "hasAudio": true, - "hasVideo": true, - "outputMode": "composed", - "url" : "http://tokbox.com.archive2.s3.amazonaws.com/123456%2Ff6e7ee58-d6cf-4a59-896b-6d56b158ec71%2Farchive.mp4?Expires=1395194362&AWSAccessKeyId=AKIAI6LQCPIXYVWCQV6Q&Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - } - """ - ) - ), - status=200, - content_type=u("application/json"), - ) + archive_id = u('f6e7ee58-d6cf-4a59-896b-6d56b158ec71') + httpretty.register_uri(httpretty.GET, u('https://api.opentok.com/v2/project/{0}/archive/{1}').format(self.api_key, archive_id), + body=textwrap.dedent(u("""\ + { + "createdAt" : 1395187836000, + "duration" : 62, + "id" : "f6e7ee58-d6cf-4a59-896b-6d56b158ec71", + "name" : "", + "partnerId" : 123456, + "reason" : "", + "sessionId" : "SESSIONID", + "size" : 8347554, + "status" : "available", + "hasAudio": true, + "hasVideo": true, + "outputMode": "composed", + "url" : "http://tokbox.com.archive2.s3.amazonaws.com/123456%2Ff6e7ee58-d6cf-4a59-896b-6d56b158ec71%2Farchive.mp4?Expires=1395194362&AWSAccessKeyId=AKIAI6LQCPIXYVWCQV6Q&Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }""")), + status=200, + content_type=u('application/json')) archive = self.opentok.get_archive(archive_id) - validate_jwt_header(self, httpretty.last_request().headers[u("x-opentok-auth")]) - expect(httpretty.last_request().headers[u("user-agent")]).to( - contain(u("OpenTok-Python-SDK/") + __version__) - ) - expect(httpretty.last_request().headers[u("content-type")]).to( - equal(u("application/json")) - ) + validate_jwt_header(self, httpretty.last_request().headers[u('x-opentok-auth')]) + expect(httpretty.last_request().headers[u('user-agent')]).to(contain(u('OpenTok-Python-SDK/')+__version__)) + expect(httpretty.last_request().headers[u('content-type')]).to(equal(u('application/json'))) expect(archive).to(be_an(Archive)) - expect(archive).to(have_property(u("id"), archive_id)) - expect(archive).to(have_property(u("name"), u(""))) - expect(archive).to(have_property(u("status"), u("available"))) - expect(archive).to(have_property(u("session_id"), u("SESSIONID"))) - expect(archive).to(have_property(u("partner_id"), 123456)) + expect(archive).to(have_property(u('id'), archive_id)) + expect(archive).to(have_property(u('name'), u(''))) + expect(archive).to(have_property(u('status'), u('available'))) + expect(archive).to(have_property(u('session_id'), u('SESSIONID'))) + expect(archive).to(have_property(u('partner_id'), 123456)) if PY2: created_at = datetime.datetime.fromtimestamp(1395187836, pytz.UTC) if PY3: - created_at = datetime.datetime.fromtimestamp( - 1395187836, datetime.timezone.utc - ) - expect(archive).to(have_property(u("created_at"), created_at)) - expect(archive).to(have_property(u("size"), 8347554)) - expect(archive).to(have_property(u("duration"), 62)) - expect(archive).to( - have_property( - u("url"), - u( - "http://tokbox.com.archive2.s3.amazonaws.com/123456%2Ff6e7ee58-d6cf-4a59-896b-6d56b158ec71%2Farchive.mp4?Expires=1395194362&AWSAccessKeyId=AKIAI6LQCPIXYVWCQV6Q&Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - ), - ) - ) + created_at = datetime.datetime.fromtimestamp(1395187836, datetime.timezone.utc) + expect(archive).to(have_property(u('created_at'), created_at)) + expect(archive).to(have_property(u('size'), 8347554)) + expect(archive).to(have_property(u('duration'), 62)) + expect(archive).to(have_property(u('url'), u('http://tokbox.com.archive2.s3.amazonaws.com/123456%2Ff6e7ee58-d6cf-4a59-896b-6d56b158ec71%2Farchive.mp4?Expires=1395194362&AWSAccessKeyId=AKIAI6LQCPIXYVWCQV6Q&Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'))) @httpretty.activate def test_find_archives(self): - httpretty.register_uri( - httpretty.GET, - u("https://api.opentok.com/v2/project/{0}/archive").format(self.api_key), - body=textwrap.dedent( - u( - """\ - { - "count" : 6, - "items" : [ { - "createdAt" : 1395187930000, - "duration" : 22, - "id" : "ef546c5a-4fd7-4e59-ab3d-f1cfb4148d1d", - "name" : "", - "partnerId" : 123456, - "reason" : "", - "sessionId" : "SESSIONID", - "size" : 2909274, - "status" : "available", - "hasAudio": true, - "hasVideo": true, - "outputMode": "composed", - "url" : "http://tokbox.com.archive2.s3.amazonaws.com/123456%2Fef546c5a-4fd7-4e59-ab3d-f1cfb4148d1d%2Farchive.mp4?Expires=1395188695&AWSAccessKeyId=AKIAI6LQCPIXYVWCQV6Q&Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - }, { - "createdAt" : 1395187910000, - "duration" : 14, - "id" : "5350f06f-0166-402e-bc27-09ba54948512", - "name" : "", - "partnerId" : 123456, - "reason" : "", - "sessionId" : "SESSIONID", - "size" : 1952651, - "status" : "available", - "hasAudio": true, - "hasVideo": true, - "outputMode": "composed", - "url" : "http://tokbox.com.archive2.s3.amazonaws.com/123456%2F5350f06f-0166-402e-bc27-09ba54948512%2Farchive.mp4?Expires=1395188695&AWSAccessKeyId=AKIAI6LQCPIXYVWCQV6Q&Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - }, { - "createdAt" : 1395187836000, - "duration" : 62, - "id" : "f6e7ee58-d6cf-4a59-896b-6d56b158ec71", - "name" : "", - "partnerId" : 123456, - "reason" : "", - "sessionId" : "SESSIONID", - "size" : 8347554, - "status" : "available", - "hasAudio": true, - "hasVideo": true, - "outputMode": "composed", - "url" : "http://tokbox.com.archive2.s3.amazonaws.com/123456%2Ff6e7ee58-d6cf-4a59-896b-6d56b158ec71%2Farchive.mp4?Expires=1395188695&AWSAccessKeyId=AKIAI6LQCPIXYVWCQV6Q&Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - }, { - "createdAt" : 1395183243000, - "duration" : 544, - "id" : "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", - "name" : "", - "partnerId" : 123456, - "reason" : "", - "sessionId" : "SESSIONID", - "size" : 78499758, - "status" : "available", - "hasAudio": true, - "hasVideo": true, - "outputMode": "composed", - "url" : "http://tokbox.com.archive2.s3.amazonaws.com/123456%2F30b3ebf1-ba36-4f5b-8def-6f70d9986fe9%2Farchive.mp4?Expires=1395188695&AWSAccessKeyId=AKIAI6LQCPIXYVWCQV6Q&Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - }, { - "createdAt" : 1394396753000, - "duration" : 24, - "id" : "b8f64de1-e218-4091-9544-4cbf369fc238", - "name" : "showtime again", - "partnerId" : 123456, - "reason" : "", - "sessionId" : "SESSIONID", - "size" : 2227849, - "status" : "available", - "hasAudio": true, - "hasVideo": true, - "outputMode": "composed", - "url" : "http://tokbox.com.archive2.s3.amazonaws.com/123456%2Fb8f64de1-e218-4091-9544-4cbf369fc238%2Farchive.mp4?Expires=1395188695&AWSAccessKeyId=AKIAI6LQCPIXYVWCQV6Q&Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - }, { - "createdAt" : 1394321113000, - "duration" : 1294, - "id" : "832641bf-5dbf-41a1-ad94-fea213e59a92", - "name" : "showtime", - "partnerId" : 123456, - "reason" : "", - "sessionId" : "SESSIONID", - "size" : 42165242, - "status" : "available", - "hasAudio": true, - "hasVideo": true, - "outputMode": "composed", - "url" : "http://tokbox.com.archive2.s3.amazonaws.com/123456%2F832641bf-5dbf-41a1-ad94-fea213e59a92%2Farchive.mp4?Expires=1395188695&AWSAccessKeyId=AKIAI6LQCPIXYVWCQV6Q&Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - } ] - } - """ - ) - ), - status=200, - content_type=u("application/json"), - ) + httpretty.register_uri(httpretty.GET, u('https://api.opentok.com/v2/project/{0}/archive').format(self.api_key), + body=textwrap.dedent(u("""\ + { + "count" : 6, + "items" : [ { + "createdAt" : 1395187930000, + "duration" : 22, + "id" : "ef546c5a-4fd7-4e59-ab3d-f1cfb4148d1d", + "name" : "", + "partnerId" : 123456, + "reason" : "", + "sessionId" : "SESSIONID", + "size" : 2909274, + "status" : "available", + "hasAudio": true, + "hasVideo": true, + "outputMode": "composed", + "url" : "http://tokbox.com.archive2.s3.amazonaws.com/123456%2Fef546c5a-4fd7-4e59-ab3d-f1cfb4148d1d%2Farchive.mp4?Expires=1395188695&AWSAccessKeyId=AKIAI6LQCPIXYVWCQV6Q&Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { + "createdAt" : 1395187910000, + "duration" : 14, + "id" : "5350f06f-0166-402e-bc27-09ba54948512", + "name" : "", + "partnerId" : 123456, + "reason" : "", + "sessionId" : "SESSIONID", + "size" : 1952651, + "status" : "available", + "hasAudio": true, + "hasVideo": true, + "outputMode": "composed", + "url" : "http://tokbox.com.archive2.s3.amazonaws.com/123456%2F5350f06f-0166-402e-bc27-09ba54948512%2Farchive.mp4?Expires=1395188695&AWSAccessKeyId=AKIAI6LQCPIXYVWCQV6Q&Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { + "createdAt" : 1395187836000, + "duration" : 62, + "id" : "f6e7ee58-d6cf-4a59-896b-6d56b158ec71", + "name" : "", + "partnerId" : 123456, + "reason" : "", + "sessionId" : "SESSIONID", + "size" : 8347554, + "status" : "available", + "hasAudio": true, + "hasVideo": true, + "outputMode": "composed", + "url" : "http://tokbox.com.archive2.s3.amazonaws.com/123456%2Ff6e7ee58-d6cf-4a59-896b-6d56b158ec71%2Farchive.mp4?Expires=1395188695&AWSAccessKeyId=AKIAI6LQCPIXYVWCQV6Q&Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { + "createdAt" : 1395183243000, + "duration" : 544, + "id" : "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", + "name" : "", + "partnerId" : 123456, + "reason" : "", + "sessionId" : "SESSIONID", + "size" : 78499758, + "status" : "available", + "hasAudio": true, + "hasVideo": true, + "outputMode": "composed", + "url" : "http://tokbox.com.archive2.s3.amazonaws.com/123456%2F30b3ebf1-ba36-4f5b-8def-6f70d9986fe9%2Farchive.mp4?Expires=1395188695&AWSAccessKeyId=AKIAI6LQCPIXYVWCQV6Q&Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { + "createdAt" : 1394396753000, + "duration" : 24, + "id" : "b8f64de1-e218-4091-9544-4cbf369fc238", + "name" : "showtime again", + "partnerId" : 123456, + "reason" : "", + "sessionId" : "SESSIONID", + "size" : 2227849, + "status" : "available", + "hasAudio": true, + "hasVideo": true, + "outputMode": "composed", + "url" : "http://tokbox.com.archive2.s3.amazonaws.com/123456%2Fb8f64de1-e218-4091-9544-4cbf369fc238%2Farchive.mp4?Expires=1395188695&AWSAccessKeyId=AKIAI6LQCPIXYVWCQV6Q&Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { + "createdAt" : 1394321113000, + "duration" : 1294, + "id" : "832641bf-5dbf-41a1-ad94-fea213e59a92", + "name" : "showtime", + "partnerId" : 123456, + "reason" : "", + "sessionId" : "SESSIONID", + "size" : 42165242, + "status" : "available", + "hasAudio": true, + "hasVideo": true, + "outputMode": "composed", + "url" : "http://tokbox.com.archive2.s3.amazonaws.com/123456%2F832641bf-5dbf-41a1-ad94-fea213e59a92%2Farchive.mp4?Expires=1395188695&AWSAccessKeyId=AKIAI6LQCPIXYVWCQV6Q&Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + } ] + }""")), + status=200, + content_type=u('application/json')) archive_list = self.opentok.get_archives() - validate_jwt_header(self, httpretty.last_request().headers[u("x-opentok-auth")]) - expect(httpretty.last_request().headers[u("user-agent")]).to( - contain(u("OpenTok-Python-SDK/") + __version__) - ) - expect(httpretty.last_request().headers[u("content-type")]).to( - equal(u("application/json")) - ) + validate_jwt_header(self, httpretty.last_request().headers[u('x-opentok-auth')]) + expect(httpretty.last_request().headers[u('user-agent')]).to(contain(u('OpenTok-Python-SDK/')+__version__)) + expect(httpretty.last_request().headers[u('content-type')]).to(equal(u('application/json'))) expect(archive_list).to(be_an(ArchiveList)) - expect(archive_list).to(have_property(u("count"), 6)) + expect(archive_list).to(have_property(u('count'), 6)) expect(list(archive_list.items)).to(have_length(6)) # TODO: we could inspect each item in the list @httpretty.activate def test_find_archives_with_offset(self): - httpretty.register_uri( - httpretty.GET, - u("https://api.opentok.com/v2/project/{0}/archive").format(self.api_key), - body=textwrap.dedent( - u( - """\ - { - "count" : 6, - "items" : [ { - "createdAt" : 1395183243000, - "duration" : 544, - "id" : "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", - "name" : "", - "partnerId" : 123456, - "reason" : "", - "sessionId" : "SESSIONID", - "size" : 78499758, - "status" : "available", - "hasAudio": true, - "hasVideo": true, - "url" : "http://tokbox.com.archive2.s3.amazonaws.com/123456%2F30b3ebf1-ba36-4f5b-8def-6f70d9986fe9%2Farchive.mp4?Expires=1395188695&AWSAccessKeyId=AKIAI6LQCPIXYVWCQV6Q&Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - }, { - "createdAt" : 1394396753000, - "duration" : 24, - "id" : "b8f64de1-e218-4091-9544-4cbf369fc238", - "name" : "showtime again", - "partnerId" : 123456, - "reason" : "", - "sessionId" : "SESSIONID", - "size" : 2227849, - "status" : "available", - "hasAudio": true, - "hasVideo": true, - "url" : "http://tokbox.com.archive2.s3.amazonaws.com/123456%2Fb8f64de1-e218-4091-9544-4cbf369fc238%2Farchive.mp4?Expires=1395188695&AWSAccessKeyId=AKIAI6LQCPIXYVWCQV6Q&Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - }, { - "createdAt" : 1394321113000, - "duration" : 1294, - "id" : "832641bf-5dbf-41a1-ad94-fea213e59a92", - "name" : "showtime", - "partnerId" : 123456, - "reason" : "", - "sessionId" : "SESSIONID", - "size" : 42165242, - "status" : "available", - "hasAudio": true, - "hasVideo": true, - "url" : "http://tokbox.com.archive2.s3.amazonaws.com/123456%2F832641bf-5dbf-41a1-ad94-fea213e59a92%2Farchive.mp4?Expires=1395188695&AWSAccessKeyId=AKIAI6LQCPIXYVWCQV6Q&Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - } ] - } - """ - ) - ), - status=200, - content_type=u("application/json"), - ) + httpretty.register_uri(httpretty.GET, u('https://api.opentok.com/v2/project/{0}/archive').format(self.api_key), + body=textwrap.dedent(u("""\ + { + "count" : 6, + "items" : [ { + "createdAt" : 1395183243000, + "duration" : 544, + "id" : "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", + "name" : "", + "partnerId" : 123456, + "reason" : "", + "sessionId" : "SESSIONID", + "size" : 78499758, + "status" : "available", + "hasAudio": true, + "hasVideo": true, + "url" : "http://tokbox.com.archive2.s3.amazonaws.com/123456%2F30b3ebf1-ba36-4f5b-8def-6f70d9986fe9%2Farchive.mp4?Expires=1395188695&AWSAccessKeyId=AKIAI6LQCPIXYVWCQV6Q&Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { + "createdAt" : 1394396753000, + "duration" : 24, + "id" : "b8f64de1-e218-4091-9544-4cbf369fc238", + "name" : "showtime again", + "partnerId" : 123456, + "reason" : "", + "sessionId" : "SESSIONID", + "size" : 2227849, + "status" : "available", + "hasAudio": true, + "hasVideo": true, + "url" : "http://tokbox.com.archive2.s3.amazonaws.com/123456%2Fb8f64de1-e218-4091-9544-4cbf369fc238%2Farchive.mp4?Expires=1395188695&AWSAccessKeyId=AKIAI6LQCPIXYVWCQV6Q&Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { + "createdAt" : 1394321113000, + "duration" : 1294, + "id" : "832641bf-5dbf-41a1-ad94-fea213e59a92", + "name" : "showtime", + "partnerId" : 123456, + "reason" : "", + "sessionId" : "SESSIONID", + "size" : 42165242, + "status" : "available", + "hasAudio": true, + "hasVideo": true, + "url" : "http://tokbox.com.archive2.s3.amazonaws.com/123456%2F832641bf-5dbf-41a1-ad94-fea213e59a92%2Farchive.mp4?Expires=1395188695&AWSAccessKeyId=AKIAI6LQCPIXYVWCQV6Q&Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + } ] + }""")), + status=200, + content_type=u('application/json')) archive_list = self.opentok.get_archives(offset=3) - validate_jwt_header(self, httpretty.last_request().headers[u("x-opentok-auth")]) - expect(httpretty.last_request().headers[u("user-agent")]).to( - contain(u("OpenTok-Python-SDK/") + __version__) - ) - expect(httpretty.last_request().headers[u("content-type")]).to( - equal(u("application/json")) - ) - expect(httpretty.last_request()).to( - have_property(u("querystring"), {u("offset"): [u("3")]}) - ) + validate_jwt_header(self, httpretty.last_request().headers[u('x-opentok-auth')]) + expect(httpretty.last_request().headers[u('user-agent')]).to(contain(u('OpenTok-Python-SDK/')+__version__)) + expect(httpretty.last_request().headers[u('content-type')]).to(equal(u('application/json'))) + expect(httpretty.last_request()).to(have_property(u('querystring'), { + u('offset'): [u('3')] + })) expect(archive_list).to(be_an(ArchiveList)) - expect(archive_list).to(have_property(u("count"), 6)) + expect(archive_list).to(have_property(u('count'), 6)) expect(list(archive_list.items)).to(have_length(3)) # TODO: we could inspect each item in the list @httpretty.activate def test_find_archives_with_count(self): - httpretty.register_uri( - httpretty.GET, - u("https://api.opentok.com/v2/project/{0}/archive").format(self.api_key), - body=textwrap.dedent( - u( - """\ - { - "count" : 6, - "items" : [ { - "createdAt" : 1395187930000, - "duration" : 22, - "id" : "ef546c5a-4fd7-4e59-ab3d-f1cfb4148d1d", - "name" : "", - "partnerId" : 123456, - "reason" : "", - "sessionId" : "SESSIONID", - "size" : 2909274, - "status" : "available", - "hasAudio": true, - "hasVideo": true, - "url" : "http://tokbox.com.archive2.s3.amazonaws.com/123456%2Fef546c5a-4fd7-4e59-ab3d-f1cfb4148d1d%2Farchive.mp4?Expires=1395188695&AWSAccessKeyId=AKIAI6LQCPIXYVWCQV6Q&Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - }, { - "createdAt" : 1395187910000, - "duration" : 14, - "id" : "5350f06f-0166-402e-bc27-09ba54948512", - "name" : "", - "partnerId" : 123456, - "reason" : "", - "sessionId" : "SESSIONID", - "size" : 1952651, - "status" : "available", - "hasAudio": true, - "hasVideo": true, - "url" : "http://tokbox.com.archive2.s3.amazonaws.com/123456%2F5350f06f-0166-402e-bc27-09ba54948512%2Farchive.mp4?Expires=1395188695&AWSAccessKeyId=AKIAI6LQCPIXYVWCQV6Q&Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - } ] - } - """ - ) - ), - status=200, - content_type=u("application/json"), - ) + httpretty.register_uri(httpretty.GET, u('https://api.opentok.com/v2/project/{0}/archive').format(self.api_key), + body=textwrap.dedent(u("""\ + { + "count" : 6, + "items" : [ { + "createdAt" : 1395187930000, + "duration" : 22, + "id" : "ef546c5a-4fd7-4e59-ab3d-f1cfb4148d1d", + "name" : "", + "partnerId" : 123456, + "reason" : "", + "sessionId" : "SESSIONID", + "size" : 2909274, + "status" : "available", + "hasAudio": true, + "hasVideo": true, + "url" : "http://tokbox.com.archive2.s3.amazonaws.com/123456%2Fef546c5a-4fd7-4e59-ab3d-f1cfb4148d1d%2Farchive.mp4?Expires=1395188695&AWSAccessKeyId=AKIAI6LQCPIXYVWCQV6Q&Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { + "createdAt" : 1395187910000, + "duration" : 14, + "id" : "5350f06f-0166-402e-bc27-09ba54948512", + "name" : "", + "partnerId" : 123456, + "reason" : "", + "sessionId" : "SESSIONID", + "size" : 1952651, + "status" : "available", + "hasAudio": true, + "hasVideo": true, + "url" : "http://tokbox.com.archive2.s3.amazonaws.com/123456%2F5350f06f-0166-402e-bc27-09ba54948512%2Farchive.mp4?Expires=1395188695&AWSAccessKeyId=AKIAI6LQCPIXYVWCQV6Q&Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + } ] + }""")), + status=200, + content_type=u('application/json')) archive_list = self.opentok.get_archives(count=2) - validate_jwt_header(self, httpretty.last_request().headers[u("x-opentok-auth")]) - expect(httpretty.last_request().headers[u("user-agent")]).to( - contain(u("OpenTok-Python-SDK/") + __version__) - ) - expect(httpretty.last_request().headers[u("content-type")]).to( - equal(u("application/json")) - ) - expect(httpretty.last_request()).to( - have_property(u("querystring"), {u("count"): [u("2")]}) - ) + validate_jwt_header(self, httpretty.last_request().headers[u('x-opentok-auth')]) + expect(httpretty.last_request().headers[u('user-agent')]).to(contain(u('OpenTok-Python-SDK/')+__version__)) + expect(httpretty.last_request().headers[u('content-type')]).to(equal(u('application/json'))) + expect(httpretty.last_request()).to(have_property(u('querystring'), { + u('count'): [u('2')] + })) expect(archive_list).to(be_an(ArchiveList)) - expect(archive_list).to(have_property(u("count"), 6)) + expect(archive_list).to(have_property(u('count'), 6)) expect(list(archive_list.items)).to(have_length(2)) # TODO: we could inspect each item in the list @httpretty.activate def test_find_archives_with_offset_and_count(self): - httpretty.register_uri( - httpretty.GET, - u("https://api.opentok.com/v2/project/{0}/archive").format(self.api_key), - body=textwrap.dedent( - u( - """\ - { - "count" : 6, - "items" : [ { - "createdAt" : 1395187836000, - "duration" : 62, - "id" : "f6e7ee58-d6cf-4a59-896b-6d56b158ec71", - "name" : "", - "partnerId" : 123456, - "reason" : "", - "sessionId" : "SESSIONID", - "size" : 8347554, - "status" : "available", - "hasAudio": true, - "hasVideo": true, - "url" : "http://tokbox.com.archive2.s3.amazonaws.com/123456%2Ff6e7ee58-d6cf-4a59-896b-6d56b158ec71%2Farchive.mp4?Expires=1395188695&AWSAccessKeyId=AKIAI6LQCPIXYVWCQV6Q&Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - }, { - "createdAt" : 1395183243000, - "duration" : 544, - "id" : "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", - "name" : "", - "partnerId" : 123456, - "reason" : "", - "sessionId" : "SESSIONID", - "size" : 78499758, - "status" : "available", - "hasAudio": true, - "hasVideo": true, - "url" : "http://tokbox.com.archive2.s3.amazonaws.com/123456%2F30b3ebf1-ba36-4f5b-8def-6f70d9986fe9%2Farchive.mp4?Expires=1395188695&AWSAccessKeyId=AKIAI6LQCPIXYVWCQV6Q&Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - }, { - "createdAt" : 1394396753000, - "duration" : 24, - "id" : "b8f64de1-e218-4091-9544-4cbf369fc238", - "name" : "showtime again", - "partnerId" : 123456, - "reason" : "", - "sessionId" : "SESSIONID", - "size" : 2227849, - "status" : "available", - "hasAudio": true, - "hasVideo": true, - "url" : "http://tokbox.com.archive2.s3.amazonaws.com/123456%2Fb8f64de1-e218-4091-9544-4cbf369fc238%2Farchive.mp4?Expires=1395188695&AWSAccessKeyId=AKIAI6LQCPIXYVWCQV6Q&Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - }, { - "createdAt" : 1394321113000, - "duration" : 1294, - "id" : "832641bf-5dbf-41a1-ad94-fea213e59a92", - "name" : "showtime", - "partnerId" : 123456, - "reason" : "", - "sessionId" : "SESSIONID", - "size" : 42165242, - "status" : "available", - "hasAudio": true, - "hasVideo": true, - "url" : "http://tokbox.com.archive2.s3.amazonaws.com/123456%2F832641bf-5dbf-41a1-ad94-fea213e59a92%2Farchive.mp4?Expires=1395188695&AWSAccessKeyId=AKIAI6LQCPIXYVWCQV6Q&Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - } ] - } - """ - ) - ), - status=200, - content_type=u("application/json"), - ) + httpretty.register_uri(httpretty.GET, u('https://api.opentok.com/v2/project/{0}/archive').format(self.api_key), + body=textwrap.dedent(u("""\ + { + "count" : 6, + "items" : [ { + "createdAt" : 1395187836000, + "duration" : 62, + "id" : "f6e7ee58-d6cf-4a59-896b-6d56b158ec71", + "name" : "", + "partnerId" : 123456, + "reason" : "", + "sessionId" : "SESSIONID", + "size" : 8347554, + "status" : "available", + "hasAudio": true, + "hasVideo": true, + "url" : "http://tokbox.com.archive2.s3.amazonaws.com/123456%2Ff6e7ee58-d6cf-4a59-896b-6d56b158ec71%2Farchive.mp4?Expires=1395188695&AWSAccessKeyId=AKIAI6LQCPIXYVWCQV6Q&Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { + "createdAt" : 1395183243000, + "duration" : 544, + "id" : "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", + "name" : "", + "partnerId" : 123456, + "reason" : "", + "sessionId" : "SESSIONID", + "size" : 78499758, + "status" : "available", + "hasAudio": true, + "hasVideo": true, + "url" : "http://tokbox.com.archive2.s3.amazonaws.com/123456%2F30b3ebf1-ba36-4f5b-8def-6f70d9986fe9%2Farchive.mp4?Expires=1395188695&AWSAccessKeyId=AKIAI6LQCPIXYVWCQV6Q&Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { + "createdAt" : 1394396753000, + "duration" : 24, + "id" : "b8f64de1-e218-4091-9544-4cbf369fc238", + "name" : "showtime again", + "partnerId" : 123456, + "reason" : "", + "sessionId" : "SESSIONID", + "size" : 2227849, + "status" : "available", + "hasAudio": true, + "hasVideo": true, + "url" : "http://tokbox.com.archive2.s3.amazonaws.com/123456%2Fb8f64de1-e218-4091-9544-4cbf369fc238%2Farchive.mp4?Expires=1395188695&AWSAccessKeyId=AKIAI6LQCPIXYVWCQV6Q&Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { + "createdAt" : 1394321113000, + "duration" : 1294, + "id" : "832641bf-5dbf-41a1-ad94-fea213e59a92", + "name" : "showtime", + "partnerId" : 123456, + "reason" : "", + "sessionId" : "SESSIONID", + "size" : 42165242, + "status" : "available", + "hasAudio": true, + "hasVideo": true, + "url" : "http://tokbox.com.archive2.s3.amazonaws.com/123456%2F832641bf-5dbf-41a1-ad94-fea213e59a92%2Farchive.mp4?Expires=1395188695&AWSAccessKeyId=AKIAI6LQCPIXYVWCQV6Q&Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + } ] + }""")), + status=200, + content_type=u('application/json')) archive_list = self.opentok.get_archives(count=4, offset=2) - validate_jwt_header(self, httpretty.last_request().headers[u("x-opentok-auth")]) - expect(httpretty.last_request().headers[u("user-agent")]).to( - contain(u("OpenTok-Python-SDK/") + __version__) - ) - expect(httpretty.last_request().headers[u("content-type")]).to( - equal(u("application/json")) - ) - expect(httpretty.last_request()).to( - have_property( - u("querystring"), {u("offset"): [u("2")], u("count"): [u("4")]} - ) - ) + validate_jwt_header(self, httpretty.last_request().headers[u('x-opentok-auth')]) + expect(httpretty.last_request().headers[u('user-agent')]).to(contain(u('OpenTok-Python-SDK/')+__version__)) + expect(httpretty.last_request().headers[u('content-type')]).to(equal(u('application/json'))) + expect(httpretty.last_request()).to(have_property(u('querystring'), { + u('offset'): [u('2')], + u('count'): [u('4')] + })) expect(archive_list).to(be_an(ArchiveList)) - expect(archive_list).to(have_property(u("count"), 6)) + expect(archive_list).to(have_property(u('count'), 6)) expect(list(archive_list.items)).to(have_length(4)) # TODO: we could inspect each item in the list @@ -1013,87 +793,78 @@ def test_find_archives_with_sessionid(self): """ Test get_archives method using session_id parameter """ httpretty.register_uri( httpretty.GET, - u("https://api.opentok.com/v2/project/{0}/archive").format(self.api_key), - body=textwrap.dedent( - u( - """\ - { - "count" : 4, - "items" : [ { - "createdAt" : 1395187836000, - "duration" : 62, - "id" : "f6e7ee58-d6cf-4a59-896b-6d56b158ec71", - "name" : "", - "partnerId" : 123456, - "reason" : "", - "sessionId" : "SESSIONID", - "size" : 8347554, - "status" : "available", - "hasAudio": true, - "hasVideo": true, - "url" : "http://tokbox.com.archive2.s3.amazonaws.com/123456%2Ff6e7ee58-d6cf-4a59-896b-6d56b158ec71%2Farchive.mp4?Expires=1395188695&AWSAccessKeyId=AKIAI6LQCPIXYVWCQV6Q&Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - }, { - "createdAt" : 1395183243000, - "duration" : 544, - "id" : "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", - "name" : "", - "partnerId" : 123456, - "reason" : "", - "sessionId" : "SESSIONID", - "size" : 78499758, - "status" : "available", - "hasAudio": true, - "hasVideo": true, - "url" : "http://tokbox.com.archive2.s3.amazonaws.com/123456%2F30b3ebf1-ba36-4f5b-8def-6f70d9986fe9%2Farchive.mp4?Expires=1395188695&AWSAccessKeyId=AKIAI6LQCPIXYVWCQV6Q&Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - }, { - "createdAt" : 1394396753000, - "duration" : 24, - "id" : "b8f64de1-e218-4091-9544-4cbf369fc238", - "name" : "showtime again", - "partnerId" : 123456, - "reason" : "", - "sessionId" : "SESSIONID", - "size" : 2227849, - "status" : "available", - "hasAudio": true, - "hasVideo": true, - "url" : "http://tokbox.com.archive2.s3.amazonaws.com/123456%2Fb8f64de1-e218-4091-9544-4cbf369fc238%2Farchive.mp4?Expires=1395188695&AWSAccessKeyId=AKIAI6LQCPIXYVWCQV6Q&Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - }, { - "createdAt" : 1394321113000, - "duration" : 1294, - "id" : "832641bf-5dbf-41a1-ad94-fea213e59a92", - "name" : "showtime", - "partnerId" : 123456, - "reason" : "", - "sessionId" : "SESSIONID", - "size" : 42165242, - "status" : "available", - "hasAudio": true, - "hasVideo": true, - "url" : "http://tokbox.com.archive2.s3.amazonaws.com/123456%2F832641bf-5dbf-41a1-ad94-fea213e59a92%2Farchive.mp4?Expires=1395188695&AWSAccessKeyId=AKIAI6LQCPIXYVWCQV6Q&Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - }] - } - """ - ) - ), + u('https://api.opentok.com/v2/project/{0}/archive').format(self.api_key), + body=textwrap.dedent(u("""\ + { + "count" : 4, + "items" : [ { + "createdAt" : 1395187836000, + "duration" : 62, + "id" : "f6e7ee58-d6cf-4a59-896b-6d56b158ec71", + "name" : "", + "partnerId" : 123456, + "reason" : "", + "sessionId" : "SESSIONID", + "size" : 8347554, + "status" : "available", + "hasAudio": true, + "hasVideo": true, + "url" : "http://tokbox.com.archive2.s3.amazonaws.com/123456%2Ff6e7ee58-d6cf-4a59-896b-6d56b158ec71%2Farchive.mp4?Expires=1395188695&AWSAccessKeyId=AKIAI6LQCPIXYVWCQV6Q&Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { + "createdAt" : 1395183243000, + "duration" : 544, + "id" : "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", + "name" : "", + "partnerId" : 123456, + "reason" : "", + "sessionId" : "SESSIONID", + "size" : 78499758, + "status" : "available", + "hasAudio": true, + "hasVideo": true, + "url" : "http://tokbox.com.archive2.s3.amazonaws.com/123456%2F30b3ebf1-ba36-4f5b-8def-6f70d9986fe9%2Farchive.mp4?Expires=1395188695&AWSAccessKeyId=AKIAI6LQCPIXYVWCQV6Q&Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { + "createdAt" : 1394396753000, + "duration" : 24, + "id" : "b8f64de1-e218-4091-9544-4cbf369fc238", + "name" : "showtime again", + "partnerId" : 123456, + "reason" : "", + "sessionId" : "SESSIONID", + "size" : 2227849, + "status" : "available", + "hasAudio": true, + "hasVideo": true, + "url" : "http://tokbox.com.archive2.s3.amazonaws.com/123456%2Fb8f64de1-e218-4091-9544-4cbf369fc238%2Farchive.mp4?Expires=1395188695&AWSAccessKeyId=AKIAI6LQCPIXYVWCQV6Q&Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { + "createdAt" : 1394321113000, + "duration" : 1294, + "id" : "832641bf-5dbf-41a1-ad94-fea213e59a92", + "name" : "showtime", + "partnerId" : 123456, + "reason" : "", + "sessionId" : "SESSIONID", + "size" : 42165242, + "status" : "available", + "hasAudio": true, + "hasVideo": true, + "url" : "http://tokbox.com.archive2.s3.amazonaws.com/123456%2F832641bf-5dbf-41a1-ad94-fea213e59a92%2Farchive.mp4?Expires=1395188695&AWSAccessKeyId=AKIAI6LQCPIXYVWCQV6Q&Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }] + }""")), status=200, - content_type=u("application/json"), - ) + content_type=u('application/json')) - archive_list = self.opentok.get_archives(session_id="SESSIONID") + archive_list = self.opentok.get_archives(session_id='SESSIONID') - validate_jwt_header(self, httpretty.last_request().headers[u("x-opentok-auth")]) - expect(httpretty.last_request().headers[u("user-agent")]).to( - contain(u("OpenTok-Python-SDK/") + __version__) - ) - expect(httpretty.last_request().headers[u("content-type")]).to( - equal(u("application/json")) - ) - expect(httpretty.last_request()).to( - have_property(u("querystring"), {u("sessionId"): [u("SESSIONID")]}) - ) + validate_jwt_header(self, httpretty.last_request().headers[u('x-opentok-auth')]) + expect(httpretty.last_request().headers[u('user-agent')]).to(contain( + u('OpenTok-Python-SDK/')+__version__)) + expect(httpretty.last_request().headers[u('content-type')]).to(equal(u('application/json'))) + expect(httpretty.last_request()).to(have_property(u('querystring'), { + u('sessionId'): [u('SESSIONID')] + })) expect(archive_list).to(be_an(ArchiveList)) - expect(archive_list).to(have_property(u("count"), 4)) + expect(archive_list).to(have_property(u('count'), 4)) expect(list(archive_list.items)).to(have_length(4)) @httpretty.activate @@ -1101,70 +872,54 @@ def test_find_archives_with_offset_count_sessionId(self): """ Test get_archives method using all parameters: offset, count and sessionId """ httpretty.register_uri( httpretty.GET, - u("https://api.opentok.com/v2/project/{0}/archive").format(self.api_key), - body=textwrap.dedent( - u( - """\ - { - "count" : 2, - "items" : [ { - "createdAt" : 1394396753000, - "duration" : 24, - "id" : "b8f64de1-e218-4091-9544-4cbf369fc238", - "name" : "showtime again", - "partnerId" : 123456, - "reason" : "", - "sessionId" : "SESSIONID", - "size" : 2227849, - "status" : "available", - "hasAudio": true, - "hasVideo": true, - "url" : "http://tokbox.com.archive2.s3.amazonaws.com/123456%2Fb8f64de1-e218-4091-9544-4cbf369fc238%2Farchive.mp4?Expires=1395188695&AWSAccessKeyId=AKIAI6LQCPIXYVWCQV6Q&Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - }, { - "createdAt" : 1394321113000, - "duration" : 1294, - "id" : "832641bf-5dbf-41a1-ad94-fea213e59a92", - "name" : "showtime", - "partnerId" : 123456, - "reason" : "", - "sessionId" : "SESSIONID", - "size" : 42165242, - "status" : "available", - "hasAudio": true, - "hasVideo": true, - "url" : "http://tokbox.com.archive2.s3.amazonaws.com/123456%2F832641bf-5dbf-41a1-ad94-fea213e59a92%2Farchive.mp4?Expires=1395188695&AWSAccessKeyId=AKIAI6LQCPIXYVWCQV6Q&Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - }] - } - """ - ) - ), - status=200, - content_type=u("application/json"), - ) - - archive_list = self.opentok.get_archives( - offset=2, count=2, session_id="SESSIONID" - ) - - validate_jwt_header(self, httpretty.last_request().headers[u("x-opentok-auth")]) - expect(httpretty.last_request().headers[u("user-agent")]).to( - contain(u("OpenTok-Python-SDK/") + __version__) - ) - expect(httpretty.last_request().headers[u("content-type")]).to( - equal(u("application/json")) - ) - expect(httpretty.last_request()).to( - have_property( - u("querystring"), + u('https://api.opentok.com/v2/project/{0}/archive').format(self.api_key), + body=textwrap.dedent(u("""\ { - u("offset"): [u("2")], - u("count"): [u("2")], - u("sessionId"): [u("SESSIONID")], - }, - ) - ) + "count" : 2, + "items" : [ { + "createdAt" : 1394396753000, + "duration" : 24, + "id" : "b8f64de1-e218-4091-9544-4cbf369fc238", + "name" : "showtime again", + "partnerId" : 123456, + "reason" : "", + "sessionId" : "SESSIONID", + "size" : 2227849, + "status" : "available", + "hasAudio": true, + "hasVideo": true, + "url" : "http://tokbox.com.archive2.s3.amazonaws.com/123456%2Fb8f64de1-e218-4091-9544-4cbf369fc238%2Farchive.mp4?Expires=1395188695&AWSAccessKeyId=AKIAI6LQCPIXYVWCQV6Q&Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { + "createdAt" : 1394321113000, + "duration" : 1294, + "id" : "832641bf-5dbf-41a1-ad94-fea213e59a92", + "name" : "showtime", + "partnerId" : 123456, + "reason" : "", + "sessionId" : "SESSIONID", + "size" : 42165242, + "status" : "available", + "hasAudio": true, + "hasVideo": true, + "url" : "http://tokbox.com.archive2.s3.amazonaws.com/123456%2F832641bf-5dbf-41a1-ad94-fea213e59a92%2Farchive.mp4?Expires=1395188695&AWSAccessKeyId=AKIAI6LQCPIXYVWCQV6Q&Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }] + }""")), + status=200, + content_type=u('application/json')) + + archive_list = self.opentok.get_archives(offset=2, count=2, session_id='SESSIONID') + + validate_jwt_header(self, httpretty.last_request().headers[u('x-opentok-auth')]) + expect(httpretty.last_request().headers[u('user-agent')]).to(contain( + u('OpenTok-Python-SDK/')+__version__)) + expect(httpretty.last_request().headers[u('content-type')]).to(equal(u('application/json'))) + expect(httpretty.last_request()).to(have_property(u('querystring'), { + u('offset'): [u('2')], + u('count'): [u('2')], + u('sessionId'): [u('SESSIONID')] + })) expect(archive_list).to(be_an(ArchiveList)) - expect(archive_list).to(have_property(u("count"), 2)) + expect(archive_list).to(have_property(u('count'), 2)) expect(list(archive_list.items)).to(have_length(2)) @httpretty.activate @@ -1172,178 +927,132 @@ def test_find_archives_alternative_method(self): """ Test list_archives method using all parameters: offset, count and sessionId """ httpretty.register_uri( httpretty.GET, - u("https://api.opentok.com/v2/project/{0}/archive").format(self.api_key), - body=textwrap.dedent( - u( - """\ - { - "count" : 2, - "items" : [ { - "createdAt" : 1394396753000, - "duration" : 24, - "id" : "b8f64de1-e218-4091-9544-4cbf369fc238", - "name" : "showtime again", - "partnerId" : 123456, - "reason" : "", - "sessionId" : "SESSIONID", - "size" : 2227849, - "status" : "available", - "hasAudio": true, - "hasVideo": true, - "url" : "http://tokbox.com.archive2.s3.amazonaws.com/123456%2Fb8f64de1-e218-4091-9544-4cbf369fc238%2Farchive.mp4?Expires=1395188695&AWSAccessKeyId=AKIAI6LQCPIXYVWCQV6Q&Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - }, { - "createdAt" : 1394321113000, - "duration" : 1294, - "id" : "832641bf-5dbf-41a1-ad94-fea213e59a92", - "name" : "showtime", - "partnerId" : 123456, - "reason" : "", - "sessionId" : "SESSIONID", - "size" : 42165242, - "status" : "available", - "hasAudio": true, - "hasVideo": true, - "url" : "http://tokbox.com.archive2.s3.amazonaws.com/123456%2F832641bf-5dbf-41a1-ad94-fea213e59a92%2Farchive.mp4?Expires=1395188695&AWSAccessKeyId=AKIAI6LQCPIXYVWCQV6Q&Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - }] - } - """ - ) - ), - status=200, - content_type=u("application/json"), - ) - - archive_list = self.opentok.list_archives( - offset=2, count=2, session_id="SESSIONID" - ) - - validate_jwt_header(self, httpretty.last_request().headers[u("x-opentok-auth")]) - expect(httpretty.last_request().headers[u("user-agent")]).to( - contain(u("OpenTok-Python-SDK/") + __version__) - ) - expect(httpretty.last_request().headers[u("content-type")]).to( - equal(u("application/json")) - ) - expect(httpretty.last_request()).to( - have_property( - u("querystring"), + u('https://api.opentok.com/v2/project/{0}/archive').format(self.api_key), + body=textwrap.dedent(u("""\ { - u("offset"): [u("2")], - u("count"): [u("2")], - u("sessionId"): [u("SESSIONID")], - }, - ) - ) + "count" : 2, + "items" : [ { + "createdAt" : 1394396753000, + "duration" : 24, + "id" : "b8f64de1-e218-4091-9544-4cbf369fc238", + "name" : "showtime again", + "partnerId" : 123456, + "reason" : "", + "sessionId" : "SESSIONID", + "size" : 2227849, + "status" : "available", + "hasAudio": true, + "hasVideo": true, + "url" : "http://tokbox.com.archive2.s3.amazonaws.com/123456%2Fb8f64de1-e218-4091-9544-4cbf369fc238%2Farchive.mp4?Expires=1395188695&AWSAccessKeyId=AKIAI6LQCPIXYVWCQV6Q&Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { + "createdAt" : 1394321113000, + "duration" : 1294, + "id" : "832641bf-5dbf-41a1-ad94-fea213e59a92", + "name" : "showtime", + "partnerId" : 123456, + "reason" : "", + "sessionId" : "SESSIONID", + "size" : 42165242, + "status" : "available", + "hasAudio": true, + "hasVideo": true, + "url" : "http://tokbox.com.archive2.s3.amazonaws.com/123456%2F832641bf-5dbf-41a1-ad94-fea213e59a92%2Farchive.mp4?Expires=1395188695&AWSAccessKeyId=AKIAI6LQCPIXYVWCQV6Q&Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }] + }""")), + status=200, + content_type=u('application/json')) + + archive_list = self.opentok.list_archives(offset=2, count=2, session_id='SESSIONID') + + validate_jwt_header(self, httpretty.last_request().headers[u('x-opentok-auth')]) + expect(httpretty.last_request().headers[u('user-agent')]).to(contain( + u('OpenTok-Python-SDK/')+__version__)) + expect(httpretty.last_request().headers[u('content-type')]).to(equal(u('application/json'))) + expect(httpretty.last_request()).to(have_property(u('querystring'), { + u('offset'): [u('2')], + u('count'): [u('2')], + u('sessionId'): [u('SESSIONID')] + })) expect(archive_list).to(be_an(ArchiveList)) - expect(archive_list).to(have_property(u("count"), 2)) + expect(archive_list).to(have_property(u('count'), 2)) expect(list(archive_list.items)).to(have_length(2)) @httpretty.activate def test_find_paused_archive(self): - archive_id = u("f6e7ee58-d6cf-4a59-896b-6d56b158ec71") - httpretty.register_uri( - httpretty.GET, - u("https://api.opentok.com/v2/project/{0}/archive/{1}").format( - self.api_key, archive_id - ), - body=textwrap.dedent( - u( - """\ - { - "createdAt" : 1395187836000, - "duration" : 62, - "id" : "f6e7ee58-d6cf-4a59-896b-6d56b158ec71", - "name" : "", - "partnerId" : 123456, - "reason" : "", - "sessionId" : "SESSIONID", - "size" : 8347554, - "status" : "paused", - "hasAudio": true, - "hasVideo": true, - "url" : null - } - """ - ) - ), - status=200, - content_type=u("application/json"), - ) + archive_id = u('f6e7ee58-d6cf-4a59-896b-6d56b158ec71') + httpretty.register_uri(httpretty.GET, u('https://api.opentok.com/v2/project/{0}/archive/{1}').format(self.api_key, archive_id), + body=textwrap.dedent(u("""\ + { + "createdAt" : 1395187836000, + "duration" : 62, + "id" : "f6e7ee58-d6cf-4a59-896b-6d56b158ec71", + "name" : "", + "partnerId" : 123456, + "reason" : "", + "sessionId" : "SESSIONID", + "size" : 8347554, + "status" : "paused", + "hasAudio": true, + "hasVideo": true, + "url" : null + }""")), + status=200, + content_type=u('application/json')) archive = self.opentok.get_archive(archive_id) expect(archive).to(be_an(Archive)) - expect(archive).to(have_property(u("status"), u("paused"))) + expect(archive).to(have_property(u('status'), u('paused'))) @httpretty.activate def test_find_expired_archive(self): - archive_id = u("f6e7ee58-d6cf-4a59-896b-6d56b158ec71") - httpretty.register_uri( - httpretty.GET, - u("https://api.opentok.com/v2/project/{0}/archive/{1}").format( - self.api_key, archive_id - ), - body=textwrap.dedent( - u( - """\ - { - "createdAt" : 1395187836000, - "duration" : 62, - "id" : "f6e7ee58-d6cf-4a59-896b-6d56b158ec71", - "name" : "", - "partnerId" : 123456, - "reason" : "", - "sessionId" : "SESSIONID", - "size" : 8347554, - "status" : "expired", - "hasAudio": true, - "hasVideo": true, - "url" : null - } - """ - ) - ), - status=200, - content_type=u("application/json"), - ) + archive_id = u('f6e7ee58-d6cf-4a59-896b-6d56b158ec71') + httpretty.register_uri(httpretty.GET, u('https://api.opentok.com/v2/project/{0}/archive/{1}').format(self.api_key, archive_id), + body=textwrap.dedent(u("""\ + { + "createdAt" : 1395187836000, + "duration" : 62, + "id" : "f6e7ee58-d6cf-4a59-896b-6d56b158ec71", + "name" : "", + "partnerId" : 123456, + "reason" : "", + "sessionId" : "SESSIONID", + "size" : 8347554, + "status" : "expired", + "hasAudio": true, + "hasVideo": true, + "url" : null + }""")), + status=200, + content_type=u('application/json')) archive = self.opentok.get_archive(archive_id) expect(archive).to(be_an(Archive)) - expect(archive).to(have_property(u("status"), u("expired"))) + expect(archive).to(have_property(u('status'), u('expired'))) @httpretty.activate def test_find_archive_with_unknown_properties(self): - archive_id = u("f6e7ee58-d6cf-4a59-896b-6d56b158ec71") - httpretty.register_uri( - httpretty.GET, - u("https://api.opentok.com/v2/project/{0}/archive/{1}").format( - self.api_key, archive_id - ), - body=textwrap.dedent( - u( - """\ - { - "createdAt" : 1395187836000, - "duration" : 62, - "id" : "f6e7ee58-d6cf-4a59-896b-6d56b158ec71", - "name" : "", - "partnerId" : 123456, - "reason" : "", - "sessionId" : "SESSIONID", - "size" : 8347554, - "status" : "expired", - "url" : null, - "hasAudio": true, - "hasVideo": true, - "notarealproperty" : "not a real value" - } - """ - ) - ), - status=200, - content_type=u("application/json"), - ) + archive_id = u('f6e7ee58-d6cf-4a59-896b-6d56b158ec71') + httpretty.register_uri(httpretty.GET, u('https://api.opentok.com/v2/project/{0}/archive/{1}').format(self.api_key, archive_id), + body=textwrap.dedent(u("""\ + { + "createdAt" : 1395187836000, + "duration" : 62, + "id" : "f6e7ee58-d6cf-4a59-896b-6d56b158ec71", + "name" : "", + "partnerId" : 123456, + "reason" : "", + "sessionId" : "SESSIONID", + "size" : 8347554, + "status" : "expired", + "url" : null, + "hasAudio": true, + "hasVideo": true, + "notarealproperty" : "not a real value" + }""")), + status=200, + content_type=u('application/json')) archive = self.opentok.get_archive(archive_id) @@ -1352,72 +1061,69 @@ def test_find_archive_with_unknown_properties(self): @httpretty.activate def test_set_archive_layout(self): """ Test set archive layout functionality """ - archive_id = u("f6e7ee58-d6cf-4a59-896b-6d56b158ec71") + archive_id = u('f6e7ee58-d6cf-4a59-896b-6d56b158ec71') httpretty.register_uri( httpretty.PUT, - u("https://api.opentok.com/v2/project/{0}/archive/{1}/layout").format( - self.api_key, archive_id + u('https://api.opentok.com/v2/project/{0}/archive/{1}/layout').format( + self.api_key, + archive_id ), status=200, - content_type=u("application/json"), + content_type=u('application/json') ) - self.opentok.set_archive_layout(archive_id, "horizontalPresentation") + self.opentok.set_archive_layout(archive_id, 'horizontalPresentation') - validate_jwt_header(self, httpretty.last_request().headers[u("x-opentok-auth")]) - expect(httpretty.last_request().headers[u("user-agent")]).to( - contain(u("OpenTok-Python-SDK/") + __version__) - ) - expect(httpretty.last_request().headers[u("content-type")]).to( - equal(u("application/json")) - ) + validate_jwt_header(self, httpretty.last_request().headers[u('x-opentok-auth')]) + expect(httpretty.last_request().headers[u('user-agent')]).to(contain( + u('OpenTok-Python-SDK/')+__version__)) + expect(httpretty.last_request().headers[u('content-type')]).to(equal(u('application/json'))) @httpretty.activate def test_set_custom_archive_layout(self): """ Test set a custom archive layout specifying the 'stylesheet' parameter """ - archive_id = u("f6e7ee58-d6cf-4a59-896b-6d56b158ec71") + archive_id = u('f6e7ee58-d6cf-4a59-896b-6d56b158ec71') httpretty.register_uri( httpretty.PUT, - u("https://api.opentok.com/v2/project/{0}/archive/{1}/layout").format( - self.api_key, archive_id + u('https://api.opentok.com/v2/project/{0}/archive/{1}/layout').format( + self.api_key, + archive_id ), status=200, - content_type=u("application/json"), + content_type=u('application/json') ) self.opentok.set_archive_layout( archive_id, - "custom", - "stream.instructor {position: absolute; width: 100%; height:50%;}", + 'custom', + 'stream.instructor {position: absolute; width: 100%; height:50%;}' ) - validate_jwt_header(self, httpretty.last_request().headers[u("x-opentok-auth")]) - expect(httpretty.last_request().headers[u("user-agent")]).to( - contain(u("OpenTok-Python-SDK/") + __version__) - ) - expect(httpretty.last_request().headers[u("content-type")]).to( - equal(u("application/json")) - ) + validate_jwt_header(self, httpretty.last_request().headers[u('x-opentok-auth')]) + expect(httpretty.last_request().headers[u('user-agent')]).to(contain( + u('OpenTok-Python-SDK/')+__version__)) + expect(httpretty.last_request().headers[u('content-type')]).to(equal(u('application/json'))) @httpretty.activate def test_set_archive_layout_throws_exception(self): """ Test invalid request in set archive layout """ - archive_id = u("f6e7ee58-d6cf-4a59-896b-6d56b158ec71") + archive_id = u('f6e7ee58-d6cf-4a59-896b-6d56b158ec71') httpretty.register_uri( httpretty.PUT, - u("https://api.opentok.com/v2/project/{0}/archive/{1}/layout").format( - self.api_key, archive_id + u('https://api.opentok.com/v2/project/{0}/archive/{1}/layout').format( + self.api_key, + archive_id ), status=400, - content_type=u("application/json"), + content_type=u('application/json') ) self.assertRaises( ArchiveError, self.opentok.set_archive_layout, archive_id, - "horizontalPresentation", + 'horizontalPresentation' ) diff --git a/tests/test_broadcast.py b/tests/test_broadcast.py index f85f416..816d711 100644 --- a/tests/test_broadcast.py +++ b/tests/test_broadcast.py @@ -7,13 +7,12 @@ from opentok import OpenTok, Broadcast, __version__, BroadcastError from .validate_jwt import validate_jwt_header - class OpenTokBroadcastTest(unittest.TestCase): def setUp(self): - self.api_key = u("123456") - self.api_secret = u("1234567890abcdef1234567890abcdef1234567890") + self.api_key = u('123456') + self.api_secret = u('1234567890abcdef1234567890abcdef1234567890') self.opentok = OpenTok(self.api_key, self.api_secret) - self.session_id = u("2_MX4xMDBfjE0Mzc2NzY1NDgwMTJ-TjMzfn4") + self.session_id = u('2_MX4xMDBfjE0Mzc2NzY1NDgwMTJ-TjMzfn4') @httpretty.activate def test_start_broadcast(self): @@ -22,85 +21,70 @@ def test_start_broadcast(self): """ httpretty.register_uri( httpretty.POST, - u("https://api.opentok.com/v2/project/{0}/broadcast").format(self.api_key), - body=textwrap.dedent( - u( - """\ - { - "id": "1748b7070a81464c9759c46ad10d3734", - "sessionId": "2_MX4xMDBfjE0Mzc2NzY1NDgwMTJ-TjMzfn4", - "projectId": 100, - "createdAt": 1437676551000, - "updatedAt": 1437676551000, - "resolution": "640x480", - "status": "started", - "broadcastUrls": { - "hls" : "http://server/fakepath/playlist.m3u8", - "rtmp": { - "foo": { - "serverUrl": "rtmp://myfooserver/myfooapp", - "streamName": "myfoostream" - }, - "bar": { - "serverUrl": "rtmp://mybarserver/mybarapp", - "streamName": "mybarstream" - } - } + u('https://api.opentok.com/v2/project/{0}/broadcast').format(self.api_key), + body=textwrap.dedent(u("""\ + { + "id": "1748b7070a81464c9759c46ad10d3734", + "sessionId": "2_MX4xMDBfjE0Mzc2NzY1NDgwMTJ-TjMzfn4", + "projectId": 100, + "createdAt": 1437676551000, + "updatedAt": 1437676551000, + "resolution": "640x480", + "status": "started", + "broadcastUrls": { + "hls" : "http://server/fakepath/playlist.m3u8", + "rtmp": { + "foo": { + "serverUrl": "rtmp://myfooserver/myfooapp", + "streamName": "myfoostream" + }, + "bar": { + "serverUrl": "rtmp://mybarserver/mybarapp", + "streamName": "mybarstream" } } - """ - ) - ), + } + }""")), status=200, - content_type=u("application/json"), + content_type=u('application/json') ) options = { - "layout": { - "type": "custom", - "stylesheet": "the layout stylesheet (only used with type == custom)", + 'layout': { + 'type': 'custom', + 'stylesheet': 'the layout stylesheet (only used with type == custom)' }, - "maxDuration": 5400, - "outputs": { - "hls": {}, - "rtmp": [ - { - "id": "foo", - "serverUrl": "rtmp://myfooserver/myfooapp", - "streamName": "myfoostream", - }, - { - "id": "bar", - "serverUrl": "rtmp://mybarserver/mybarapp", - "streamName": "mybarstream", - }, - ], + 'maxDuration': 5400, + 'outputs': { + 'hls': {}, + 'rtmp': [{ + 'id': 'foo', + 'serverUrl': 'rtmp://myfooserver/myfooapp', + 'streamName': 'myfoostream' + }, { + 'id': 'bar', + 'serverUrl': 'rtmp://mybarserver/mybarapp', + 'streamName': 'mybarstream' + }] }, - "resolution": "640x480", + 'resolution': '640x480' } broadcast = self.opentok.start_broadcast(self.session_id, options) - validate_jwt_header(self, httpretty.last_request().headers[u("x-opentok-auth")]) - expect(httpretty.last_request().headers[u("user-agent")]).to( - contain(u("OpenTok-Python-SDK/") + __version__) - ) - expect(httpretty.last_request().headers[u("content-type")]).to( - equal(u("application/json")) - ) + validate_jwt_header(self, httpretty.last_request().headers[u('x-opentok-auth')]) + expect(httpretty.last_request().headers[u('user-agent')]).to(contain( + u('OpenTok-Python-SDK/')+__version__)) + expect(httpretty.last_request().headers[u('content-type')]).to(equal(u('application/json'))) expect(broadcast).to(be_an(Broadcast)) - expect(broadcast).to( - have_property(u("id"), u("1748b7070a81464c9759c46ad10d3734")) - ) - expect(broadcast).to( - have_property(u("sessionId"), u("2_MX4xMDBfjE0Mzc2NzY1NDgwMTJ-TjMzfn4")) - ) - expect(broadcast).to(have_property(u("projectId"), 100)) - expect(broadcast).to(have_property(u("createdAt"), 1437676551000)) - expect(broadcast).to(have_property(u("updatedAt"), 1437676551000)) - expect(broadcast).to(have_property(u("resolution"), u("640x480"))) - expect(broadcast).to(have_property(u("status"), u("started"))) + expect(broadcast).to(have_property(u('id'), u('1748b7070a81464c9759c46ad10d3734'))) + expect(broadcast).to(have_property(u('sessionId'), u('2_MX4xMDBfjE0Mzc2NzY1NDgwMTJ-TjMzfn4'))) + expect(broadcast).to(have_property(u('projectId'), 100)) + expect(broadcast).to(have_property(u('createdAt'), 1437676551000)) + expect(broadcast).to(have_property(u('updatedAt'), 1437676551000)) + expect(broadcast).to(have_property(u('resolution'), u('640x480'))) + expect(broadcast).to(have_property(u('status'), u('started'))) expect(list(broadcast.broadcastUrls)).to(have_length(2)) - expect(list(broadcast.broadcastUrls["rtmp"])).to(have_length(2)) + expect(list(broadcast.broadcastUrls['rtmp'])).to(have_length(2)) @httpretty.activate def test_start_broadcast_only_one_rtmp(self): @@ -109,266 +93,231 @@ def test_start_broadcast_only_one_rtmp(self): """ httpretty.register_uri( httpretty.POST, - u("https://api.opentok.com/v2/project/{0}/broadcast").format(self.api_key), - body=textwrap.dedent( - u( - """\ - { - "id": "1748b7070a81464c9759c46ad10d3734", - "sessionId": "2_MX4xMDBfjE0Mzc2NzY1NDgwMTJ-TjMzfn4", - "projectId": 100, - "createdAt": 1437676551000, - "updatedAt": 1437676551000, - "resolution": "640x480", - "status": "started", - "broadcastUrls": { - "hls" : "http://server/fakepath/playlist.m3u8", - "rtmp": { - "foo": { - "serverUrl": "rtmp://myfooserver/myfooapp", - "streamName": "myfoostream" - }, - "bar": { - "serverUrl": "rtmp://mybarserver/mybarapp", - "streamName": "mybarstream" - } - } + u('https://api.opentok.com/v2/project/{0}/broadcast').format(self.api_key), + body=textwrap.dedent(u("""\ + { + "id": "1748b7070a81464c9759c46ad10d3734", + "sessionId": "2_MX4xMDBfjE0Mzc2NzY1NDgwMTJ-TjMzfn4", + "projectId": 100, + "createdAt": 1437676551000, + "updatedAt": 1437676551000, + "resolution": "640x480", + "status": "started", + "broadcastUrls": { + "hls" : "http://server/fakepath/playlist.m3u8", + "rtmp": { + "foo": { + "serverUrl": "rtmp://myfooserver/myfooapp", + "streamName": "myfoostream" + }, + "bar": { + "serverUrl": "rtmp://mybarserver/mybarapp", + "streamName": "mybarstream" } } - """ - ) - ), + } + }""")), status=200, - content_type=u("application/json"), + content_type=u('application/json') ) options = { - "sessionId": "2_MX4xMDBfjE0Mzc2NzY1NDgwMTJ", - "layout": { - "type": "custom", - "stylesheet": "the layout stylesheet (only used with type == custom)", + 'sessionId': '2_MX4xMDBfjE0Mzc2NzY1NDgwMTJ', + 'layout': { + 'type': 'custom', + 'stylesheet': 'the layout stylesheet (only used with type == custom)' }, - "maxDuration": 5400, - "outputs": { - "rtmp": { - "id": "my-id", - "serverUrl": "rtmp://myserver/myapp", - "streamName": "my-stream-name", + 'maxDuration': 5400, + 'outputs': { + 'rtmp': { + 'id': 'my-id', + 'serverUrl': 'rtmp://myserver/myapp', + 'streamName': 'my-stream-name' } }, - "resolution": "640x480", + 'resolution': '640x480' } broadcast = self.opentok.start_broadcast(self.session_id, options) - validate_jwt_header(self, httpretty.last_request().headers[u("x-opentok-auth")]) - expect(httpretty.last_request().headers[u("user-agent")]).to( - contain(u("OpenTok-Python-SDK/") + __version__) - ) - expect(httpretty.last_request().headers[u("content-type")]).to( - equal(u("application/json")) - ) + validate_jwt_header(self, httpretty.last_request().headers[u('x-opentok-auth')]) + expect(httpretty.last_request().headers[u('user-agent')]).to(contain( + u('OpenTok-Python-SDK/')+__version__)) + expect(httpretty.last_request().headers[u('content-type')]).to(equal(u('application/json'))) expect(broadcast).to(be_an(Broadcast)) - expect(broadcast).to( - have_property(u("id"), u("1748b7070a81464c9759c46ad10d3734")) - ) - expect(broadcast).to( - have_property(u("sessionId"), u("2_MX4xMDBfjE0Mzc2NzY1NDgwMTJ-TjMzfn4")) - ) - expect(broadcast).to(have_property(u("projectId"), 100)) - expect(broadcast).to(have_property(u("createdAt"), 1437676551000)) - expect(broadcast).to(have_property(u("updatedAt"), 1437676551000)) - expect(broadcast).to(have_property(u("resolution"), u("640x480"))) - expect(broadcast).to(have_property(u("status"), u("started"))) + expect(broadcast).to(have_property(u('id'), u('1748b7070a81464c9759c46ad10d3734'))) + expect(broadcast).to(have_property(u('sessionId'), u('2_MX4xMDBfjE0Mzc2NzY1NDgwMTJ-TjMzfn4'))) + expect(broadcast).to(have_property(u('projectId'), 100)) + expect(broadcast).to(have_property(u('createdAt'), 1437676551000)) + expect(broadcast).to(have_property(u('updatedAt'), 1437676551000)) + expect(broadcast).to(have_property(u('resolution'), u('640x480'))) + expect(broadcast).to(have_property(u('status'), u('started'))) expect(list(broadcast.broadcastUrls)).to(have_length(2)) - expect(list(broadcast.broadcastUrls["rtmp"])).to(have_length(2)) + expect(list(broadcast.broadcastUrls['rtmp'])).to(have_length(2)) @httpretty.activate def test_stop_broadcast(self): """ Test stop_broadcast() method """ - broadcast_id = u("1748b7070a81464c9759c46ad10d3734") + broadcast_id = u('1748b7070a81464c9759c46ad10d3734') httpretty.register_uri( httpretty.POST, - u("https://api.opentok.com/v2/project/{0}/broadcast/{1}/stop").format( - self.api_key, broadcast_id - ), - body=textwrap.dedent( - u( - """\ - { - "id": "1748b7070a81464c9759c46ad10d3734", - "sessionId": "2_MX4xMDBfjE0Mzc2NzY1NDgwMTJ-TjMzfn4", - "projectId": 100, - "createdAt": 1437676551000, - "updatedAt": 1437676551000, - "resolution": "640x480", - "broadcastUrls": null - } - """ - ) + u('https://api.opentok.com/v2/project/{0}/broadcast/{1}/stop').format( + self.api_key, + broadcast_id ), + body=textwrap.dedent(u("""\ + { + "id": "1748b7070a81464c9759c46ad10d3734", + "sessionId": "2_MX4xMDBfjE0Mzc2NzY1NDgwMTJ-TjMzfn4", + "projectId": 100, + "createdAt": 1437676551000, + "updatedAt": 1437676551000, + "resolution": "640x480", + "broadcastUrls": null + }""")), status=200, - content_type=u("application/json"), + content_type=u('application/json') ) broadcast = self.opentok.stop_broadcast(broadcast_id) - validate_jwt_header(self, httpretty.last_request().headers[u("x-opentok-auth")]) - expect(httpretty.last_request().headers[u("user-agent")]).to( - contain(u("OpenTok-Python-SDK/") + __version__) - ) - expect(httpretty.last_request().headers[u("content-type")]).to( - equal(u("application/json")) - ) + validate_jwt_header(self, httpretty.last_request().headers[u('x-opentok-auth')]) + expect(httpretty.last_request().headers[u('user-agent')]).to(contain( + u('OpenTok-Python-SDK/')+__version__)) + expect(httpretty.last_request().headers[u('content-type')]).to(equal(u('application/json'))) expect(broadcast).to(be_an(Broadcast)) - expect(broadcast).to( - have_property(u("id"), u("1748b7070a81464c9759c46ad10d3734")) - ) - expect(broadcast).to( - have_property(u("sessionId"), u("2_MX4xMDBfjE0Mzc2NzY1NDgwMTJ-TjMzfn4")) - ) - expect(broadcast).to(have_property(u("projectId"), 100)) - expect(broadcast).to(have_property(u("createdAt"), 1437676551000)) - expect(broadcast).to(have_property(u("updatedAt"), 1437676551000)) - expect(broadcast).to(have_property(u("resolution"), u("640x480"))) + expect(broadcast).to(have_property(u('id'), u('1748b7070a81464c9759c46ad10d3734'))) + expect(broadcast).to(have_property(u('sessionId'), u('2_MX4xMDBfjE0Mzc2NzY1NDgwMTJ-TjMzfn4'))) + expect(broadcast).to(have_property(u('projectId'), 100)) + expect(broadcast).to(have_property(u('createdAt'), 1437676551000)) + expect(broadcast).to(have_property(u('updatedAt'), 1437676551000)) + expect(broadcast).to(have_property(u('resolution'), u('640x480'))) @httpretty.activate def test_get_broadcast(self): """ Test get_broadcast() method """ - broadcast_id = u("1748b707-0a81-464c-9759-c46ad10d3734") + broadcast_id = u('1748b707-0a81-464c-9759-c46ad10d3734') httpretty.register_uri( httpretty.GET, - u("https://api.opentok.com/v2/project/{0}/broadcast/{1}").format( - self.api_key, broadcast_id + u('https://api.opentok.com/v2/project/{0}/broadcast/{1}').format( + self.api_key, + broadcast_id ), - body=textwrap.dedent( - u( - """\ - { - "id": "1748b707-0a81-464c-9759-c46ad10d3734", - "sessionId": "2_MX4xMDBfjE0Mzc2NzY1NDgwMTJ-TjMzfn4", - "projectId": 100, - "createdAt": 1437676551000, - "updatedAt": 1437676551000, - "resolution": "640x480", - "broadcastUrls": { - "hls" : "http://server/fakepath/playlist.m3u8", - "rtmp": { - "foo": { - "serverUrl": "rtmp://myfooserver/myfooapp", - "streamName": "myfoostream", - "status": "live" - }, - "bar": { - "serverUrl": "rtmp://mybarserver/mybarapp", - "streamName": "mybarstream", - "status": "live" - } - } + body=textwrap.dedent(u("""\ + { + "id": "1748b707-0a81-464c-9759-c46ad10d3734", + "sessionId": "2_MX4xMDBfjE0Mzc2NzY1NDgwMTJ-TjMzfn4", + "projectId": 100, + "createdAt": 1437676551000, + "updatedAt": 1437676551000, + "resolution": "640x480", + "broadcastUrls": { + "hls" : "http://server/fakepath/playlist.m3u8", + "rtmp": { + "foo": { + "serverUrl": "rtmp://myfooserver/myfooapp", + "streamName": "myfoostream", + "status": "live" }, - "status": "started" + "bar": { + "serverUrl": "rtmp://mybarserver/mybarapp", + "streamName": "mybarstream", + "status": "live" + } } - """ - ) - ), + }, + "status": "started" + }""")), status=200, - content_type=u("application/json"), + content_type=u('application/json') ) broadcast = self.opentok.get_broadcast(broadcast_id) - validate_jwt_header(self, httpretty.last_request().headers[u("x-opentok-auth")]) - expect(httpretty.last_request().headers[u("user-agent")]).to( - contain(u("OpenTok-Python-SDK/") + __version__) - ) - expect(httpretty.last_request().headers[u("content-type")]).to( - equal(u("application/json")) - ) + validate_jwt_header(self, httpretty.last_request().headers[u('x-opentok-auth')]) + expect(httpretty.last_request().headers[u('user-agent')]).to(contain( + u('OpenTok-Python-SDK/')+__version__)) + expect(httpretty.last_request().headers[u('content-type')]).to(equal(u('application/json'))) expect(broadcast).to(be_an(Broadcast)) - expect(broadcast).to(have_property(u("id"), broadcast_id)) - expect(broadcast).to( - have_property(u("sessionId"), u("2_MX4xMDBfjE0Mzc2NzY1NDgwMTJ-TjMzfn4")) - ) - expect(broadcast).to(have_property(u("projectId"), 100)) - expect(broadcast).to(have_property(u("createdAt"), 1437676551000)) - expect(broadcast).to(have_property(u("updatedAt"), 1437676551000)) - expect(broadcast).to(have_property(u("resolution"), u("640x480"))) - expect(broadcast).to(have_property(u("status"), u("started"))) + expect(broadcast).to(have_property(u('id'), broadcast_id)) + expect(broadcast).to(have_property(u('sessionId'), u('2_MX4xMDBfjE0Mzc2NzY1NDgwMTJ-TjMzfn4'))) + expect(broadcast).to(have_property(u('projectId'), 100)) + expect(broadcast).to(have_property(u('createdAt'), 1437676551000)) + expect(broadcast).to(have_property(u('updatedAt'), 1437676551000)) + expect(broadcast).to(have_property(u('resolution'), u('640x480'))) + expect(broadcast).to(have_property(u('status'), u('started'))) expect(list(broadcast.broadcastUrls)).to(have_length(2)) - expect(list(broadcast.broadcastUrls["rtmp"])).to(have_length(2)) + expect(list(broadcast.broadcastUrls['rtmp'])).to(have_length(2)) @httpretty.activate def test_set_broadcast_layout(self): """ Test set_broadcast_layout() functionality """ - broadcast_id = u("1748b707-0a81-464c-9759-c46ad10d3734") + broadcast_id = u('1748b707-0a81-464c-9759-c46ad10d3734') httpretty.register_uri( httpretty.PUT, - u("https://api.opentok.com/v2/project/{0}/broadcast/{1}/layout").format( - self.api_key, broadcast_id + u('https://api.opentok.com/v2/project/{0}/broadcast/{1}/layout').format( + self.api_key, + broadcast_id ), status=200, - content_type=u("application/json"), + content_type=u('application/json') ) - self.opentok.set_broadcast_layout(broadcast_id, "horizontalPresentation") + self.opentok.set_broadcast_layout(broadcast_id, 'horizontalPresentation') - validate_jwt_header(self, httpretty.last_request().headers[u("x-opentok-auth")]) - expect(httpretty.last_request().headers[u("user-agent")]).to( - contain(u("OpenTok-Python-SDK/") + __version__) - ) - expect(httpretty.last_request().headers[u("content-type")]).to( - equal(u("application/json")) - ) + validate_jwt_header(self, httpretty.last_request().headers[u('x-opentok-auth')]) + expect(httpretty.last_request().headers[u('user-agent')]).to(contain( + u('OpenTok-Python-SDK/')+__version__)) + expect(httpretty.last_request().headers[u('content-type')]).to(equal(u('application/json'))) @httpretty.activate def test_set_custom_broadcast_layout(self): """ Test set a custom broadcast layout specifying the 'stylesheet' parameter """ - broadcast_id = u("1748b707-0a81-464c-9759-c46ad10d3734") + broadcast_id = u('1748b707-0a81-464c-9759-c46ad10d3734') httpretty.register_uri( httpretty.PUT, - u("https://api.opentok.com/v2/project/{0}/broadcast/{1}/layout").format( - self.api_key, broadcast_id + u('https://api.opentok.com/v2/project/{0}/broadcast/{1}/layout').format( + self.api_key, + broadcast_id ), status=200, - content_type=u("application/json"), + content_type=u('application/json') ) self.opentok.set_broadcast_layout( broadcast_id, - "custom", - "stream.instructor {position: absolute; width: 100%; height:50%;}", + 'custom', + 'stream.instructor {position: absolute; width: 100%; height:50%;}' ) - validate_jwt_header(self, httpretty.last_request().headers[u("x-opentok-auth")]) - expect(httpretty.last_request().headers[u("user-agent")]).to( - contain(u("OpenTok-Python-SDK/") + __version__) - ) - expect(httpretty.last_request().headers[u("content-type")]).to( - equal(u("application/json")) - ) + validate_jwt_header(self, httpretty.last_request().headers[u('x-opentok-auth')]) + expect(httpretty.last_request().headers[u('user-agent')]).to(contain( + u('OpenTok-Python-SDK/')+__version__)) + expect(httpretty.last_request().headers[u('content-type')]).to(equal(u('application/json'))) @httpretty.activate def test_set_broadcast_layout_throws_exception(self): """ Test invalid request in set broadcast layout """ - broadcast_id = u("1748b707-0a81-464c-9759-c46ad10d3734") + broadcast_id = u('1748b707-0a81-464c-9759-c46ad10d3734') httpretty.register_uri( httpretty.PUT, - u("https://api.opentok.com/v2/project/{0}/broadcast/{1}/layout").format( - self.api_key, broadcast_id + u('https://api.opentok.com/v2/project/{0}/broadcast/{1}/layout').format( + self.api_key, + broadcast_id ), status=400, - content_type=u("application/json"), + content_type=u('application/json') ) self.assertRaises( BroadcastError, self.opentok.set_broadcast_layout, broadcast_id, - "horizontalPresentation", + 'horizontalPresentation' ) diff --git a/tests/test_custom_jwt_claims.py b/tests/test_custom_jwt_claims.py deleted file mode 100644 index 18fe8df..0000000 --- a/tests/test_custom_jwt_claims.py +++ /dev/null @@ -1,30 +0,0 @@ -import unittest -from six import text_type, u, b, PY2, PY3 -from nose.tools import raises -from expects import * - -from opentok import OpenTok, __version__ -import time -from jose import jwt - - -class JwtCustomClaimsTest(unittest.TestCase): - def setUp(self): - self.api_key = u("123456") - self.api_secret = u("1234567890abcdef1234567890abcdef1234567890") - self.session_id = u( - "1_MX4xMjM0NTZ-flNhdCBNYXIgMTUgMTQ6NDI6MjMgUERUIDIwMTR-MC40OTAxMzAyNX4" - ) - self.opentok = OpenTok(self.api_key, self.api_secret) - - def test_livetime_custom_claim(self): - self.opentok.jwt_livetime = 5 # Token will expire 5 minutes in the future - jwt_token = self.opentok._create_jwt_auth_header() - claims = jwt.decode(jwt_token, self.api_secret, algorithms=[u("HS256")]) - expect(claims).to(have_key(u("exp"))) - expect(int(claims[u("exp")])).to( - be_above(int(time.time()) + (60 * 4)) - ) # above of 4 min - expect(int(claims[u("exp")])).to( - be_below(int(time.time()) + (60 * 6)) - ) # below of 6 min diff --git a/tests/test_force_disconnect.py b/tests/test_force_disconnect.py index 7a3dc16..b135e6b 100644 --- a/tests/test_force_disconnect.py +++ b/tests/test_force_disconnect.py @@ -6,16 +6,15 @@ from opentok import OpenTok, __version__, AuthError, ForceDisconnectError from .validate_jwt import validate_jwt_header - class OpenTokForceDisconnectTest(unittest.TestCase): """" Class that contains test for force disconnect functionality """ def setUp(self): - self.api_key = u("123456") - self.api_secret = u("1234567890abcdef1234567890abcdef1234567890") + self.api_key = u('123456') + self.api_secret = u('1234567890abcdef1234567890abcdef1234567890') self.opentok = OpenTok(self.api_key, self.api_secret) - self.session_id = u("SESSIONID") - self.connection_id = u("CONNECTIONID") + self.session_id = u('SESSIONID') + self.connection_id = u('CONNECTIONID') @httpretty.activate def test_force_disconnect(self): @@ -23,22 +22,20 @@ def test_force_disconnect(self): httpretty.register_uri( httpretty.DELETE, - u( - "https://api.opentok.com/v2/project/{0}/session/{1}/connection/{2}" - ).format(self.api_key, self.session_id, self.connection_id), + u('https://api.opentok.com/v2/project/{0}/session/{1}/connection/{2}').format( + self.api_key, + self.session_id, + self.connection_id + ), status=204, - content_type=u("application/json"), + content_type=u('application/json') ) self.opentok.force_disconnect(self.session_id, self.connection_id) - validate_jwt_header(self, httpretty.last_request().headers[u("x-opentok-auth")]) - expect(httpretty.last_request().headers[u("user-agent")]).to( - contain(u("OpenTok-Python-SDK/") + __version__) - ) - expect(httpretty.last_request().headers[u("content-type")]).to( - equal(u("application/json")) - ) + validate_jwt_header(self, httpretty.last_request().headers[u('x-opentok-auth')]) + expect(httpretty.last_request().headers[u('user-agent')]).to(contain(u('OpenTok-Python-SDK/')+__version__)) + expect(httpretty.last_request().headers[u('content-type')]).to(equal(u('application/json'))) @httpretty.activate def test_throws_force_disconnect_exception(self): @@ -46,18 +43,20 @@ def test_throws_force_disconnect_exception(self): httpretty.register_uri( httpretty.DELETE, - u( - "https://api.opentok.com/v2/project/{0}/session/{1}/connection/{2}" - ).format(self.api_key, self.session_id, self.connection_id), + u('https://api.opentok.com/v2/project/{0}/session/{1}/connection/{2}').format( + self.api_key, + self.session_id, + self.connection_id + ), status=400, - content_type=u("application/json"), + content_type=u('application/json') ) self.assertRaises( ForceDisconnectError, self.opentok.force_disconnect, self.session_id, - self.connection_id, + self.connection_id ) @httpretty.activate @@ -66,16 +65,18 @@ def test_throws_auth_exception(self): httpretty.register_uri( httpretty.DELETE, - u( - "https://api.opentok.com/v2/project/{0}/session/{1}/connection/{2}" - ).format(self.api_key, self.session_id, self.connection_id), + u('https://api.opentok.com/v2/project/{0}/session/{1}/connection/{2}').format( + self.api_key, + self.session_id, + self.connection_id + ), status=403, - content_type=u("application/json"), + content_type=u('application/json') ) self.assertRaises( AuthError, self.opentok.force_disconnect, self.session_id, - self.connection_id, + self.connection_id ) diff --git a/tests/test_getter_setter.py b/tests/test_getter_setter.py deleted file mode 100644 index 9d71118..0000000 --- a/tests/test_getter_setter.py +++ /dev/null @@ -1,22 +0,0 @@ -import unittest -from six import text_type, u, b, PY2, PY3 -from nose.tools import raises -from expects import * - -from opentok import OpenTok, __version__ -import time - - -class GetterSetterTest(unittest.TestCase): - def setUp(self): - self.api_key = u("123456") - self.api_secret = u("1234567890abcdef1234567890abcdef1234567890") - self.session_id = u( - "1_MX4xMjM0NTZ-flNhdCBNYXIgMTUgMTQ6NDI6MjMgUERUIDIwMTR-MC40OTAxMzAyNX4" - ) - self.opentok = OpenTok(self.api_key, self.api_secret) - - def test_getset_jwt_livetime(self): - livetime = self.opentok.jwt_livetime - self.opentok.jwt_livetime = 5 - assert self.opentok.jwt_livetime is not livetime \ No newline at end of file diff --git a/tests/test_http_options.py b/tests/test_http_options.py index f49bbcd..1feff3c 100644 --- a/tests/test_http_options.py +++ b/tests/test_http_options.py @@ -6,23 +6,18 @@ from opentok import OpenTok, OpenTokException - def _raise_timeout(*args): - raise requests.Timeout("Timeout occurred") - + raise requests.Timeout('Timeout occurred') class OpenTokSessionCreationTest(unittest.TestCase): def setUp(self): - self.api_key = u("123456") - self.api_secret = u("1234567890abcdef1234567890abcdef1234567890") + self.api_key = u('123456') + self.api_secret = u('1234567890abcdef1234567890abcdef1234567890') httpretty.enable() - httpretty.register_uri( - httpretty.POST, - u("https://api.opentok.com/session/create"), - body=_raise_timeout, - status=200, - content_type=u("text/xml"), - ) + httpretty.register_uri(httpretty.POST, u('https://api.opentok.com/session/create'), + body=_raise_timeout, + status=200, + content_type=u('text/xml')) def tearDown(self): httpretty.disable() diff --git a/tests/test_initialization.py b/tests/test_initialization.py index f5c0a6c..4ee111f 100644 --- a/tests/test_initialization.py +++ b/tests/test_initialization.py @@ -2,17 +2,15 @@ # import urllib2 import unittest from nose.tools import raises - # from xml.dom.minidom import parseString -from opentok import OpenTok # , OpenTokException - +from opentok import OpenTok #, OpenTokException class OpenTokInitializationTest(unittest.TestCase): def setUp(self): - self.api_key = "123456" - self.api_secret = "1234567890abcdef1234567890abcdef1234567890" - self.api_url = "http://environment.example.com" + self.api_key = '123456' + self.api_secret = '1234567890abcdef1234567890abcdef1234567890' + self.api_url = 'http://environment.example.com' def test_intialization(self): opentok = OpenTok(self.api_key, self.api_secret) @@ -21,8 +19,8 @@ def test_intialization(self): def test_set_proxies(self): opentok = OpenTok(self.api_key, self.api_secret) - opentok.proxies = {"https": "https://foo.bar"} - self.assertEquals(opentok.proxies, {"https": "https://foo.bar"}) + opentok.proxies = {'https': 'https://foo.bar'} + self.assertEquals(opentok.proxies, {'https': 'https://foo.bar'}) @raises(TypeError) def test_initialization_without_required_params(self): @@ -40,6 +38,5 @@ def test_initialization_with_timeout(self): opentok = OpenTok(self.api_key, self.api_secret, timeout=5) assert isinstance(opentok, OpenTok) - -if __name__ == "__main__": - unittest.main() +if __name__ == '__main__': + unittest.main() diff --git a/tests/test_session.py b/tests/test_session.py index 0f6730a..68af88a 100644 --- a/tests/test_session.py +++ b/tests/test_session.py @@ -5,31 +5,24 @@ from opentok import OpenTok, Session, Roles, MediaModes from .helpers import token_decoder, token_signature_validator - class SessionTest(unittest.TestCase): def setUp(self): - self.api_key = u("123456") - self.api_secret = u("1234567890abcdef1234567890abcdef1234567890") - self.session_id = u( - "1_MX4xMjM0NTZ-flNhdCBNYXIgMTUgMTQ6NDI6MjMgUERUIDIwMTR-MC40OTAxMzAyNX4" - ) + self.api_key = u('123456') + self.api_secret = u('1234567890abcdef1234567890abcdef1234567890') + self.session_id = u('1_MX4xMjM0NTZ-flNhdCBNYXIgMTUgMTQ6NDI6MjMgUERUIDIwMTR-MC40OTAxMzAyNX4') self.opentok = OpenTok(self.api_key, self.api_secret) def test_generate_token(self): - session = Session( - self.opentok, self.session_id, media_mode=MediaModes.routed, location=None - ) + session = Session(self.opentok, self.session_id, media_mode=MediaModes.routed, location=None) token = session.generate_token() assert isinstance(token, text_type) - assert token_decoder(token)[u("session_id")] == self.session_id + assert token_decoder(token)[u('session_id')] == self.session_id assert token_signature_validator(token, self.api_secret) def test_generate_role_token(self): - session = Session( - self.opentok, self.session_id, media_mode=MediaModes.routed, location=None - ) + session = Session(self.opentok, self.session_id, media_mode=MediaModes.routed, location=None) token = session.generate_token(role=Roles.moderator) assert isinstance(token, text_type) - assert token_decoder(token)[u("session_id")] == self.session_id - assert token_decoder(token)[u("role")] == u("moderator") + assert token_decoder(token)[u('session_id')] == self.session_id + assert token_decoder(token)[u('role')] == u('moderator') assert token_signature_validator(token, self.api_secret) diff --git a/tests/test_session_creation.py b/tests/test_session_creation.py index b53f55f..4bd74b1 100644 --- a/tests/test_session_creation.py +++ b/tests/test_session_creation.py @@ -6,262 +6,137 @@ import httpretty from .validate_jwt import validate_jwt_header -from opentok import ( - OpenTok, - Session, - MediaModes, - ArchiveModes, - OpenTokException, - __version__, -) - +from opentok import OpenTok, Session, MediaModes, ArchiveModes, OpenTokException, __version__ class OpenTokSessionCreationTest(unittest.TestCase): def setUp(self): - self.api_key = u("123456") - self.api_secret = u("1234567890abcdef1234567890abcdef1234567890") + self.api_key = u('123456') + self.api_secret = u('1234567890abcdef1234567890abcdef1234567890') self.opentok = OpenTok(self.api_key, self.api_secret) @httpretty.activate def test_create_default_session(self): - httpretty.register_uri( - httpretty.POST, - u("https://api.opentok.com/session/create"), - body=u( - '1_MX4xMjM0NTZ-fk1vbiBNYXIgMTcgMDA6NDE6MzEgUERUIDIwMTR-MC42ODM3ODk1MzQ0OTQyODA4fg123456Mon Mar 17 00:41:31 PDT 2014' - ), - status=200, - content_type=u("text/xml"), - ) + httpretty.register_uri(httpretty.POST, u('https://api.opentok.com/session/create'), + body=u('1_MX4xMjM0NTZ-fk1vbiBNYXIgMTcgMDA6NDE6MzEgUERUIDIwMTR-MC42ODM3ODk1MzQ0OTQyODA4fg123456Mon Mar 17 00:41:31 PDT 2014'), + status=200, + content_type=u('text/xml')) session = self.opentok.create_session() - validate_jwt_header(self, httpretty.last_request().headers[u("x-opentok-auth")]) - expect(httpretty.last_request().headers[u("user-agent")]).to( - contain(u("OpenTok-Python-SDK/") + __version__) - ) + validate_jwt_header(self, httpretty.last_request().headers[u('x-opentok-auth')]) + expect(httpretty.last_request().headers[u('user-agent')]).to(contain(u('OpenTok-Python-SDK/')+__version__)) body = parse_qs(httpretty.last_request().body) - expect(body).to(have_key(b("p2p.preference"), [b("enabled")])) - expect(body).to(have_key(b("archiveMode"), [b("manual")])) + expect(body).to(have_key(b('p2p.preference'), [b('enabled')])) + expect(body).to(have_key(b('archiveMode'), [b('manual')])) expect(session).to(be_a(Session)) - expect(session).to( - have_property( - u("session_id"), - u( - "1_MX4xMjM0NTZ-fk1vbiBNYXIgMTcgMDA6NDE6MzEgUERUIDIwMTR-MC42ODM3ODk1MzQ0OTQyODA4fg" - ), - ) - ) - expect(session).to(have_property(u("media_mode"), MediaModes.relayed)) - expect(session).to(have_property(u("location"), None)) + expect(session).to(have_property(u('session_id'), u('1_MX4xMjM0NTZ-fk1vbiBNYXIgMTcgMDA6NDE6MzEgUERUIDIwMTR-MC42ODM3ODk1MzQ0OTQyODA4fg'))) + expect(session).to(have_property(u('media_mode'), MediaModes.relayed)) + expect(session).to(have_property(u('location'), None)) @httpretty.activate def test_create_routed_session(self): - httpretty.register_uri( - httpretty.POST, - u("https://api.opentok.com/session/create"), - body=u( - '1_MX4xMjM0NTZ-fk1vbiBNYXIgMTcgMDA6NDE6MzEgUERUIDIwMTR-MC42ODM3ODk1MzQ0OTQyODA4fg123456Mon Mar 17 00:41:31 PDT 2014' - ), - status=200, - content_type=u("text/xml"), - ) + httpretty.register_uri(httpretty.POST, u('https://api.opentok.com/session/create'), + body=u('1_MX4xMjM0NTZ-fk1vbiBNYXIgMTcgMDA6NDE6MzEgUERUIDIwMTR-MC42ODM3ODk1MzQ0OTQyODA4fg123456Mon Mar 17 00:41:31 PDT 2014'), + status=200, + content_type=u('text/xml')) session = self.opentok.create_session(media_mode=MediaModes.routed) - validate_jwt_header(self, httpretty.last_request().headers[u("x-opentok-auth")]) - expect(httpretty.last_request().headers[u("user-agent")]).to( - contain(u("OpenTok-Python-SDK/") + __version__) - ) + validate_jwt_header(self, httpretty.last_request().headers[u('x-opentok-auth')]) + expect(httpretty.last_request().headers[u('user-agent')]).to(contain(u('OpenTok-Python-SDK/')+__version__)) body = parse_qs(httpretty.last_request().body) - expect(body).to(have_key(b("p2p.preference"), [b("disabled")])) - expect(body).to(have_key(b("archiveMode"), [b("manual")])) + expect(body).to(have_key(b('p2p.preference'), [b('disabled')])) + expect(body).to(have_key(b('archiveMode'), [b('manual')])) expect(session).to(be_a(Session)) - expect(session).to( - have_property( - u("session_id"), - u( - "1_MX4xMjM0NTZ-fk1vbiBNYXIgMTcgMDA6NDE6MzEgUERUIDIwMTR-MC42ODM3ODk1MzQ0OTQyODA4fg" - ), - ) - ) - expect(session).to(have_property(u("media_mode"), MediaModes.routed)) - expect(session).to(have_property(u("location"), None)) - - @httpretty.activate - def test_failure_create_routed_session(self): - # Session creation fails when server doesn't returns a XML - httpretty.register_uri( - httpretty.POST, - u("https://api.opentok.com/session/create"), - body=u( - 'Page not found' - ), - status=200, - content_type=u("text/xml"), - ) - - self.assertRaises( - OpenTokException, self.opentok.create_session, media_mode=MediaModes.routed - ) + expect(session).to(have_property(u('session_id'), u('1_MX4xMjM0NTZ-fk1vbiBNYXIgMTcgMDA6NDE6MzEgUERUIDIwMTR-MC42ODM3ODk1MzQ0OTQyODA4fg'))) + expect(session).to(have_property(u('media_mode'), MediaModes.routed)) + expect(session).to(have_property(u('location'), None)) @httpretty.activate def test_create_session_with_location_hint(self): - httpretty.register_uri( - httpretty.POST, - u("https://api.opentok.com/session/create"), - body=u( - '1_MX4xMjM0NTZ-fk1vbiBNYXIgMTcgMDA6NDE6MzEgUERUIDIwMTR-MC42ODM3ODk1MzQ0OTQyODA4fg123456Mon Mar 17 00:41:31 PDT 2014' - ), - status=200, - content_type=u("text/xml"), - ) + httpretty.register_uri(httpretty.POST, u('https://api.opentok.com/session/create'), + body=u('1_MX4xMjM0NTZ-fk1vbiBNYXIgMTcgMDA6NDE6MzEgUERUIDIwMTR-MC42ODM3ODk1MzQ0OTQyODA4fg123456Mon Mar 17 00:41:31 PDT 2014'), + status=200, + content_type=u('text/xml')) - session = self.opentok.create_session(location="12.34.56.78") + session = self.opentok.create_session(location='12.34.56.78') - validate_jwt_header(self, httpretty.last_request().headers[u("x-opentok-auth")]) - expect(httpretty.last_request().headers[u("user-agent")]).to( - contain(u("OpenTok-Python-SDK/") + __version__) - ) + validate_jwt_header(self, httpretty.last_request().headers[u('x-opentok-auth')]) + expect(httpretty.last_request().headers[u('user-agent')]).to(contain(u('OpenTok-Python-SDK/')+__version__)) # ordering of keys is non-deterministic, must parse the body to see if it is correct body = parse_qs(httpretty.last_request().body) - expect(body).to(have_key(b("location"), [b("12.34.56.78")])) - expect(body).to(have_key(b("p2p.preference"), [b("enabled")])) + expect(body).to(have_key(b('location'), [b('12.34.56.78')])) + expect(body).to(have_key(b('p2p.preference'), [b('enabled')])) expect(session).to(be_a(Session)) - expect(session).to( - have_property( - u("session_id"), - u( - "1_MX4xMjM0NTZ-fk1vbiBNYXIgMTcgMDA6NDE6MzEgUERUIDIwMTR-MC42ODM3ODk1MzQ0OTQyODA4fg" - ), - ) - ) - expect(session).to(have_property(u("media_mode"), MediaModes.relayed)) - expect(session).to(have_property(u("location"), u("12.34.56.78"))) + expect(session).to(have_property(u('session_id'), u('1_MX4xMjM0NTZ-fk1vbiBNYXIgMTcgMDA6NDE6MzEgUERUIDIwMTR-MC42ODM3ODk1MzQ0OTQyODA4fg'))) + expect(session).to(have_property(u('media_mode'), MediaModes.relayed)) + expect(session).to(have_property(u('location'), u('12.34.56.78'))) @httpretty.activate def test_create_routed_session_with_location_hint(self): - httpretty.register_uri( - httpretty.POST, - u("https://api.opentok.com/session/create"), - body=u( - '1_MX4xMjM0NTZ-fk1vbiBNYXIgMTcgMDA6NDE6MzEgUERUIDIwMTR-MC42ODM3ODk1MzQ0OTQyODA4fg123456Mon Mar 17 00:41:31 PDT 2014' - ), - status=200, - content_type=u("text/xml"), - ) + httpretty.register_uri(httpretty.POST, u('https://api.opentok.com/session/create'), + body=u('1_MX4xMjM0NTZ-fk1vbiBNYXIgMTcgMDA6NDE6MzEgUERUIDIwMTR-MC42ODM3ODk1MzQ0OTQyODA4fg123456Mon Mar 17 00:41:31 PDT 2014'), + status=200, + content_type=u('text/xml')) - session = self.opentok.create_session( - location="12.34.56.78", media_mode=MediaModes.routed - ) + session = self.opentok.create_session(location='12.34.56.78', media_mode=MediaModes.routed) - validate_jwt_header(self, httpretty.last_request().headers[u("x-opentok-auth")]) - expect(httpretty.last_request().headers[u("user-agent")]).to( - contain(u("OpenTok-Python-SDK/") + __version__) - ) + validate_jwt_header(self, httpretty.last_request().headers[u('x-opentok-auth')]) + expect(httpretty.last_request().headers[u('user-agent')]).to(contain(u('OpenTok-Python-SDK/')+__version__)) # ordering of keys is non-deterministic, must parse the body to see if it is correct body = parse_qs(httpretty.last_request().body) - expect(body).to(have_key(b("location"), [b("12.34.56.78")])) - expect(body).to(have_key(b("p2p.preference"), [b("disabled")])) + expect(body).to(have_key(b('location'), [b('12.34.56.78')])) + expect(body).to(have_key(b('p2p.preference'), [b('disabled')])) expect(session).to(be_a(Session)) - expect(session).to( - have_property( - u("session_id"), - u( - "1_MX4xMjM0NTZ-fk1vbiBNYXIgMTcgMDA6NDE6MzEgUERUIDIwMTR-MC42ODM3ODk1MzQ0OTQyODA4fg" - ), - ) - ) - expect(session).to(have_property(u("media_mode"), MediaModes.routed)) - expect(session).to(have_property(u("location"), u("12.34.56.78"))) + expect(session).to(have_property(u('session_id'), u('1_MX4xMjM0NTZ-fk1vbiBNYXIgMTcgMDA6NDE6MzEgUERUIDIwMTR-MC42ODM3ODk1MzQ0OTQyODA4fg'))) + expect(session).to(have_property(u('media_mode'), MediaModes.routed)) + expect(session).to(have_property(u('location'), u('12.34.56.78'))) @httpretty.activate def test_create_manual_archive_mode_session(self): - httpretty.register_uri( - httpretty.POST, - u("https://api.opentok.com/session/create"), - body=u( - '1_MX4xMjM0NTZ-fk1vbiBNYXIgMTcgMDA6NDE6MzEgUERUIDIwMTR-MC42ODM3ODk1MzQ0OTQyODA4fg123456Mon Mar 17 00:41:31 PDT 2014' - ), - status=200, - content_type=u("text/xml"), - ) + httpretty.register_uri(httpretty.POST, u('https://api.opentok.com/session/create'), + body=u('1_MX4xMjM0NTZ-fk1vbiBNYXIgMTcgMDA6NDE6MzEgUERUIDIwMTR-MC42ODM3ODk1MzQ0OTQyODA4fg123456Mon Mar 17 00:41:31 PDT 2014'), + status=200, + content_type=u('text/xml')) - session = self.opentok.create_session( - media_mode=MediaModes.routed, archive_mode=ArchiveModes.manual - ) + session = self.opentok.create_session(media_mode=MediaModes.routed, archive_mode=ArchiveModes.manual) - validate_jwt_header(self, httpretty.last_request().headers[u("x-opentok-auth")]) - expect(httpretty.last_request().headers[u("user-agent")]).to( - contain(u("OpenTok-Python-SDK/") + __version__) - ) + validate_jwt_header(self, httpretty.last_request().headers[u('x-opentok-auth')]) + expect(httpretty.last_request().headers[u('user-agent')]).to(contain(u('OpenTok-Python-SDK/')+__version__)) body = parse_qs(httpretty.last_request().body) - expect(body).to(have_key(b("p2p.preference"), [b("disabled")])) - expect(body).to(have_key(b("archiveMode"), [b("manual")])) + expect(body).to(have_key(b('p2p.preference'), [b('disabled')])) + expect(body).to(have_key(b('archiveMode'), [b('manual')])) expect(session).to(be_a(Session)) - expect(session).to( - have_property( - u("session_id"), - u( - "1_MX4xMjM0NTZ-fk1vbiBNYXIgMTcgMDA6NDE6MzEgUERUIDIwMTR-MC42ODM3ODk1MzQ0OTQyODA4fg" - ), - ) - ) - expect(session).to(have_property(u("media_mode"), MediaModes.routed)) - expect(session).to(have_property(u("archive_mode"), ArchiveModes.manual)) + expect(session).to(have_property(u('session_id'), u('1_MX4xMjM0NTZ-fk1vbiBNYXIgMTcgMDA6NDE6MzEgUERUIDIwMTR-MC42ODM3ODk1MzQ0OTQyODA4fg'))) + expect(session).to(have_property(u('media_mode'), MediaModes.routed)) + expect(session).to(have_property(u('archive_mode'), ArchiveModes.manual)) @httpretty.activate def test_create_always_archive_mode_session(self): - httpretty.register_uri( - httpretty.POST, - u("https://api.opentok.com/session/create"), - body=u( - '1_MX4xMjM0NTZ-fk1vbiBNYXIgMTcgMDA6NDE6MzEgUERUIDIwMTR-MC42ODM3ODk1MzQ0OTQyODA4fg123456Mon Mar 17 00:41:31 PDT 2014' - ), - status=200, - content_type=u("text/xml"), - ) + httpretty.register_uri(httpretty.POST, u('https://api.opentok.com/session/create'), + body=u('1_MX4xMjM0NTZ-fk1vbiBNYXIgMTcgMDA6NDE6MzEgUERUIDIwMTR-MC42ODM3ODk1MzQ0OTQyODA4fg123456Mon Mar 17 00:41:31 PDT 2014'), + status=200, + content_type=u('text/xml')) - session = self.opentok.create_session( - media_mode=MediaModes.routed, archive_mode=ArchiveModes.always - ) + session = self.opentok.create_session(media_mode=MediaModes.routed, archive_mode=ArchiveModes.always) - validate_jwt_header(self, httpretty.last_request().headers[u("x-opentok-auth")]) - expect(httpretty.last_request().headers[u("user-agent")]).to( - contain(u("OpenTok-Python-SDK/") + __version__) - ) + validate_jwt_header(self, httpretty.last_request().headers[u('x-opentok-auth')]) + expect(httpretty.last_request().headers[u('user-agent')]).to(contain(u('OpenTok-Python-SDK/')+__version__)) body = parse_qs(httpretty.last_request().body) - expect(body).to(have_key(b("p2p.preference"), [b("disabled")])) - expect(body).to(have_key(b("archiveMode"), [b("always")])) + expect(body).to(have_key(b('p2p.preference'), [b('disabled')])) + expect(body).to(have_key(b('archiveMode'), [b('always')])) expect(session).to(be_a(Session)) - expect(session).to( - have_property( - u("session_id"), - u( - "1_MX4xMjM0NTZ-fk1vbiBNYXIgMTcgMDA6NDE6MzEgUERUIDIwMTR-MC42ODM3ODk1MzQ0OTQyODA4fg" - ), - ) - ) - expect(session).to(have_property(u("media_mode"), MediaModes.routed)) - expect(session).to(have_property(u("archive_mode"), ArchiveModes.always)) + expect(session).to(have_property(u('session_id'), u('1_MX4xMjM0NTZ-fk1vbiBNYXIgMTcgMDA6NDE6MzEgUERUIDIwMTR-MC42ODM3ODk1MzQ0OTQyODA4fg'))) + expect(session).to(have_property(u('media_mode'), MediaModes.routed)) + expect(session).to(have_property(u('archive_mode'), ArchiveModes.always)) @httpretty.activate def test_complains_about_always_archive_mode_and_relayed_session(self): - httpretty.register_uri( - httpretty.POST, - u("https://api.opentok.com/session/create"), - body=u( - '1_MX4xMjM0NTZ-fk1vbiBNYXIgMTcgMDA6NDE6MzEgUERUIDIwMTR-MC42ODM3ODk1MzQ0OTQyODA4fg123456Mon Mar 17 00:41:31 PDT 2014' - ), - status=200, - content_type=u("text/xml"), - ) - self.assertRaises( - OpenTokException, - self.opentok.create_session, - media_mode=MediaModes.relayed, - archive_mode=ArchiveModes.always, - ) + httpretty.register_uri(httpretty.POST, u('https://api.opentok.com/session/create'), + body=u('1_MX4xMjM0NTZ-fk1vbiBNYXIgMTcgMDA6NDE6MzEgUERUIDIwMTR-MC42ODM3ODk1MzQ0OTQyODA4fg123456Mon Mar 17 00:41:31 PDT 2014'), + status=200, + content_type=u('text/xml')) + self.assertRaises(OpenTokException, self.opentok.create_session, media_mode=MediaModes.relayed, archive_mode=ArchiveModes.always) # TODO: all the cases that throw exceptions # TODO: custom api_url requests diff --git a/tests/test_signal.py b/tests/test_signal.py index e359579..2b92a04 100644 --- a/tests/test_signal.py +++ b/tests/test_signal.py @@ -8,92 +8,69 @@ from .validate_jwt import validate_jwt_header - class OpenTokSignalTest(unittest.TestCase): def setUp(self): - self.api_key = u("123456") - self.api_secret = u("1234567890abcdef1234567890abcdef1234567890") + self.api_key = u('123456') + self.api_secret = u('1234567890abcdef1234567890abcdef1234567890') self.opentok = OpenTok(self.api_key, self.api_secret) - self.session_id = u("SESSIONID") + self.session_id = u('SESSIONID') @httpretty.activate def test_signal(self): - data = {u("type"): u("type test"), u("data"): u("test data")} + data = { + u('type'): u('type test'), + u('data'): u('test data') + } - httpretty.register_uri( - httpretty.POST, - u("https://api.opentok.com/v2/project/{0}/session/{1}/signal").format( - self.api_key, self.session_id - ), - body=textwrap.dedent( - u( - """\ - { - "type": "type test", - "data": "test data" - } - """ - ) - ), - status=204, - content_type=u("application/json"), - ) + httpretty.register_uri(httpretty.POST, u('https://api.opentok.com/v2/project/{0}/session/{1}/signal').format(self.api_key, self.session_id), + body=textwrap.dedent(u("""\ + { + "type": "type test", + "data": "test data" + }""")), + status=204, + content_type=u('application/json')) - self.opentok.send_signal(self.session_id, data) + self.opentok.signal(self.session_id, data) - validate_jwt_header(self, httpretty.last_request().headers[u("x-opentok-auth")]) - expect(httpretty.last_request().headers[u("user-agent")]).to( - contain(u("OpenTok-Python-SDK/") + __version__) - ) - expect(httpretty.last_request().headers[u("content-type")]).to( - equal(u("application/json")) - ) + validate_jwt_header(self, httpretty.last_request().headers[u('x-opentok-auth')]) + expect(httpretty.last_request().headers[u('user-agent')]).to(contain(u('OpenTok-Python-SDK/')+__version__)) + expect(httpretty.last_request().headers[u('content-type')]).to(equal(u('application/json'))) # non-deterministic json encoding. have to decode to test it properly if PY2: body = json.loads(httpretty.last_request().body) if PY3: - body = json.loads(httpretty.last_request().body.decode("utf-8")) - expect(body).to(have_key(u("type"), u("type test"))) - expect(body).to(have_key(u("data"), u("test data"))) + body = json.loads(httpretty.last_request().body.decode('utf-8')) + expect(body).to(have_key(u('type'), u('type test'))) + expect(body).to(have_key(u('data'), u('test data'))) @httpretty.activate def test_signal_with_connection_id(self): - data = {u("type"): u("type test"), u("data"): u("test data")} + data = { + u('type'): u('type test'), + u('data'): u('test data') + } - connection_id = u("da9cb410-e29b-4c2d-ab9e-fe65bf83fcaf") + connection_id = u('da9cb410-e29b-4c2d-ab9e-fe65bf83fcaf') - httpretty.register_uri( - httpretty.POST, - u( - "https://api.opentok.com/v2/project/{0}/session/{1}/connection/{2}/signal" - ).format(self.api_key, self.session_id, connection_id), - body=textwrap.dedent( - u( - """\ - { - "type": "type test", - "data": "test data" - } - """ - ) - ), - status=204, - content_type=u("application/json"), - ) + httpretty.register_uri(httpretty.POST, u('https://api.opentok.com/v2/project/{0}/session/{1}/connection/{2}/signal').format(self.api_key, self.session_id, connection_id), + body=textwrap.dedent(u("""\ + { + "type": "type test", + "data": "test data" + }""")), + status=204, + content_type=u('application/json')) - self.opentok.send_signal(self.session_id, data, connection_id) + self.opentok.signal(self.session_id, data, connection_id) - validate_jwt_header(self, httpretty.last_request().headers[u("x-opentok-auth")]) - expect(httpretty.last_request().headers[u("user-agent")]).to( - contain(u("OpenTok-Python-SDK/") + __version__) - ) - expect(httpretty.last_request().headers[u("content-type")]).to( - equal(u("application/json")) - ) + validate_jwt_header(self, httpretty.last_request().headers[u('x-opentok-auth')]) + expect(httpretty.last_request().headers[u('user-agent')]).to(contain(u('OpenTok-Python-SDK/')+__version__)) + expect(httpretty.last_request().headers[u('content-type')]).to(equal(u('application/json'))) # non-deterministic json encoding. have to decode to test it properly if PY2: body = json.loads(httpretty.last_request().body) if PY3: - body = json.loads(httpretty.last_request().body.decode("utf-8")) - expect(body).to(have_key(u("type"), u("type test"))) - expect(body).to(have_key(u("data"), u("test data"))) + body = json.loads(httpretty.last_request().body.decode('utf-8')) + expect(body).to(have_key(u('type'), u('type test'))) + expect(body).to(have_key(u('data'), u('test data'))) diff --git a/tests/test_sip_call.py b/tests/test_sip_call.py index 49475cc..f00ecac 100644 --- a/tests/test_sip_call.py +++ b/tests/test_sip_call.py @@ -8,115 +8,93 @@ from .validate_jwt import validate_jwt_header - class OpenTokSipCallTest(unittest.TestCase): def setUp(self): - self.api_key = u("123456") - self.api_secret = u("1234567890abcdef1234567890abcdef1234567890") + self.api_key = u('123456') + self.api_secret = u('1234567890abcdef1234567890abcdef1234567890') self.opentok = OpenTok(self.api_key, self.api_secret) - self.session_id = u("SESSIONID") - self.token = u("TOKEN") - self.sip_uri = u("sip:user@sip.partner.com;transport=tls") + self.session_id = u('SESSIONID') + self.token = u('TOKEN') + self.sip_uri = u('sip:user@sip.partner.com;transport=tls') @httpretty.activate def test_sip_call_with_required_parameters(self): """ Test dial() method using just the required parameters: session_id, token, sip_uri """ - sip_call = SipCall( - { - u("id"): u("b0a5a8c7-dc38-459f-a48d-a7f2008da853"), - u("connectionId"): u("e9f8c166-6c67-440d-994a-04fb6dfed007"), - u("streamId"): u("482bce73-f882-40fd-8ca5-cb74ff416036"), - } - ) + sip_call = SipCall({ + u('id'): u('b0a5a8c7-dc38-459f-a48d-a7f2008da853'), + u('connectionId'): u('e9f8c166-6c67-440d-994a-04fb6dfed007'), + u('streamId'): u('482bce73-f882-40fd-8ca5-cb74ff416036') + }) httpretty.register_uri( httpretty.POST, - u("https://api.opentok.com/v2/project/{0}/dial").format(self.api_key), - body=textwrap.dedent( - u( - """\ - { - "id": "b0a5a8c7-dc38-459f-a48d-a7f2008da853", - "connectionId": "e9f8c166-6c67-440d-994a-04fb6dfed007", - "streamId": "482bce73-f882-40fd-8ca5-cb74ff416036" - } - """ - ) - ), + u('https://api.opentok.com/v2/project/{0}/dial').format(self.api_key), + body=textwrap.dedent(u("""\ + { + "id": "b0a5a8c7-dc38-459f-a48d-a7f2008da853", + "connectionId": "e9f8c166-6c67-440d-994a-04fb6dfed007", + "streamId": "482bce73-f882-40fd-8ca5-cb74ff416036" + }""")), status=200, - content_type=u("application/json"), + content_type=u('application/json') ) sip_call_response = self.opentok.dial(self.session_id, self.token, self.sip_uri) - validate_jwt_header(self, httpretty.last_request().headers[u("x-opentok-auth")]) - expect(httpretty.last_request().headers[u("user-agent")]).to( - contain(u("OpenTok-Python-SDK/") + __version__) - ) - expect(httpretty.last_request().headers[u("content-type")]).to( - equal(u("application/json")) - ) + validate_jwt_header(self, httpretty.last_request().headers[u('x-opentok-auth')]) + expect(httpretty.last_request().headers[u('user-agent')]).to(contain( + u('OpenTok-Python-SDK/')+__version__)) + expect(httpretty.last_request().headers[u('content-type')]).to(equal(u('application/json'))) expect(sip_call_response).to(be_an(SipCall)) - expect(sip_call_response).to(have_property(u("id"), sip_call.id)) - expect(sip_call_response).to( - have_property(u("connectionId"), sip_call.connectionId) - ) - expect(sip_call_response).to(have_property(u("streamId"), sip_call.streamId)) + expect(sip_call_response).to(have_property(u('id'), sip_call.id)) + expect(sip_call_response).to(have_property(u('connectionId'), sip_call.connectionId)) + expect(sip_call_response).to(have_property(u('streamId'), sip_call.streamId)) @httpretty.activate def test_sip_call_with_aditional_options(self): """ Test dial() method with aditional options """ - sip_call = SipCall( - { - u("id"): u("b0a5a8c7-dc38-459f-a48d-a7f2008da853"), - u("connectionId"): u("e9f8c166-6c67-440d-994a-04fb6dfed007"), - u("streamId"): u("482bce73-f882-40fd-8ca5-cb74ff416036"), - } - ) + sip_call = SipCall({ + u('id'): u('b0a5a8c7-dc38-459f-a48d-a7f2008da853'), + u('connectionId'): u('e9f8c166-6c67-440d-994a-04fb6dfed007'), + u('streamId'): u('482bce73-f882-40fd-8ca5-cb74ff416036') + }) httpretty.register_uri( httpretty.POST, - u("https://api.opentok.com/v2/project/{0}/dial").format(self.api_key), - body=textwrap.dedent( - u( - """\ - { - "id": "b0a5a8c7-dc38-459f-a48d-a7f2008da853", - "connectionId": "e9f8c166-6c67-440d-994a-04fb6dfed007", - "streamId": "482bce73-f882-40fd-8ca5-cb74ff416036" - } - """ - ) - ), + u('https://api.opentok.com/v2/project/{0}/dial').format(self.api_key), + body=textwrap.dedent(u("""\ + { + "id": "b0a5a8c7-dc38-459f-a48d-a7f2008da853", + "connectionId": "e9f8c166-6c67-440d-994a-04fb6dfed007", + "streamId": "482bce73-f882-40fd-8ca5-cb74ff416036" + }""")), status=200, - content_type=u("application/json"), + content_type=u('application/json') ) # aditional options to establish the sip call options = { - "from": "from@example.com", - "headers": {"headerKey": "headerValue"}, - "auth": {"username": "username", "password": "password"}, - "secure": True, + 'from': 'from@example.com', + 'headers': { + 'headerKey': 'headerValue' + }, + 'auth': { + 'username': 'username', + 'password': 'password' + }, + 'secure': True } - sip_call_response = self.opentok.dial( - self.session_id, self.token, self.sip_uri, options - ) - validate_jwt_header(self, httpretty.last_request().headers[u("x-opentok-auth")]) - expect(httpretty.last_request().headers[u("user-agent")]).to( - contain(u("OpenTok-Python-SDK/") + __version__) - ) - expect(httpretty.last_request().headers[u("content-type")]).to( - equal(u("application/json")) - ) + sip_call_response = self.opentok.dial(self.session_id, self.token, self.sip_uri, options) + validate_jwt_header(self, httpretty.last_request().headers[u('x-opentok-auth')]) + expect(httpretty.last_request().headers[u('user-agent')]).to(contain( + u('OpenTok-Python-SDK/')+__version__)) + expect(httpretty.last_request().headers[u('content-type')]).to(equal(u('application/json'))) expect(sip_call_response).to(be_an(SipCall)) - expect(sip_call_response).to(have_property(u("id"), sip_call.id)) - expect(sip_call_response).to( - have_property(u("connectionId"), sip_call.connectionId) - ) - expect(sip_call_response).to(have_property(u("streamId"), sip_call.streamId)) + expect(sip_call_response).to(have_property(u('id'), sip_call.id)) + expect(sip_call_response).to(have_property(u('connectionId'), sip_call.connectionId)) + expect(sip_call_response).to(have_property(u('streamId'), sip_call.streamId)) diff --git a/tests/test_stream.py b/tests/test_stream.py index 07ada3d..0af97bf 100644 --- a/tests/test_stream.py +++ b/tests/test_stream.py @@ -8,212 +8,165 @@ from .validate_jwt import validate_jwt_header - class OpenTokStreamTest(unittest.TestCase): def setUp(self): - self.api_key = u("123456") - self.api_secret = u("1234567890abcdef1234567890abcdef1234567890") + self.api_key = u('123456') + self.api_secret = u('1234567890abcdef1234567890abcdef1234567890') self.opentok = OpenTok(self.api_key, self.api_secret) - self.session_id = u("SESSIONID") - self.stream_id = u("8b732909-0a06-46a2-8ea8-074e64d43422") + self.session_id = u('SESSIONID') + self.stream_id = u('8b732909-0a06-46a2-8ea8-074e64d43422') @httpretty.activate def test_get_stream(self): - stream = Stream( - { - u("id"): u("8b732909-0a06-46a2-8ea8-074e64d43422"), - u("videoType"): u("camera"), - u("name"): u(""), - u("layoutClassList"): ["full"], - } - ) + stream = Stream({ + u('id'): u('8b732909-0a06-46a2-8ea8-074e64d43422'), + u('videoType'): u('camera'), + u('name'): u(''), + u('layoutClassList'): ['full'] + }) httpretty.register_uri( httpretty.GET, - u("https://api.opentok.com/v2/project/{0}/session/{1}/stream/{2}").format( - self.api_key, self.session_id, self.stream_id - ), - body=textwrap.dedent( - u( - """\ - { - "id": "8b732909-0a06-46a2-8ea8-074e64d43422", - "videoType": "camera", - "name": "", - "layoutClassList": ["full"] - } - """ - ) - ), + u('https://api.opentok.com/v2/project/{0}/session/{1}/stream/{2}').format(self.api_key, self.session_id, self.stream_id), + body=textwrap.dedent(u("""\ + { + "id": "8b732909-0a06-46a2-8ea8-074e64d43422", + "videoType": "camera", + "name": "", + "layoutClassList": ["full"] + }""")), status=200, - content_type=u("application/json"), + content_type=u('application/json') ) stream_response = self.opentok.get_stream(self.session_id, self.stream_id) - validate_jwt_header(self, httpretty.last_request().headers[u("x-opentok-auth")]) - expect(httpretty.last_request().headers[u("user-agent")]).to( - contain(u("OpenTok-Python-SDK/") + __version__) - ) - expect(httpretty.last_request().headers[u("content-type")]).to( - equal(u("application/json")) - ) + validate_jwt_header(self, httpretty.last_request().headers[u('x-opentok-auth')]) + expect(httpretty.last_request().headers[u('user-agent')]).to(contain(u('OpenTok-Python-SDK/')+__version__)) + expect(httpretty.last_request().headers[u('content-type')]).to(equal(u('application/json'))) expect(stream_response).to(be_an(Stream)) - expect(stream_response).to(have_property(u("id"), stream.id)) - expect(stream_response).to(have_property(u("videoType"), stream.videoType)) - expect(stream_response).to(have_property(u("name"), stream.name)) - expect(stream_response).to( - have_property(u("layoutClassList"), stream.layoutClassList) - ) + expect(stream_response).to(have_property(u('id'), stream.id)) + expect(stream_response).to(have_property(u('videoType'), stream.videoType)) + expect(stream_response).to(have_property(u('name'), stream.name)) + expect(stream_response).to(have_property(u('layoutClassList'), stream.layoutClassList)) expect(list(stream_response.layoutClassList)).to(have_length(1)) @httpretty.activate def test_get_stream_with_name(self): - stream = Stream( - { - u("id"): u("8b732909-0a06-46a2-8ea8-074e64d43422"), - u("videoType"): u("camera"), - u("name"): u("stream name"), - u("layoutClassList"): ["full"], - } - ) + stream = Stream({ + u('id'): u('8b732909-0a06-46a2-8ea8-074e64d43422'), + u('videoType'): u('camera'), + u('name'): u('stream name'), + u('layoutClassList'): ['full'] + }) httpretty.register_uri( httpretty.GET, - u("https://api.opentok.com/v2/project/{0}/session/{1}/stream/{2}").format( - self.api_key, self.session_id, self.stream_id - ), - body=textwrap.dedent( - u( - """\ - { - "id": "8b732909-0a06-46a2-8ea8-074e64d43422", - "videoType": "camera", - "name": "stream name", - "layoutClassList": ["full"] - } - """ - ) - ), + u('https://api.opentok.com/v2/project/{0}/session/{1}/stream/{2}').format(self.api_key, self.session_id, self.stream_id), + body=textwrap.dedent(u("""\ + { + "id": "8b732909-0a06-46a2-8ea8-074e64d43422", + "videoType": "camera", + "name": "stream name", + "layoutClassList": ["full"] + }""")), status=200, - content_type=u("application/json"), + content_type=u('application/json') ) stream_response = self.opentok.get_stream(self.session_id, self.stream_id) - validate_jwt_header(self, httpretty.last_request().headers[u("x-opentok-auth")]) - expect(httpretty.last_request().headers[u("user-agent")]).to( - contain(u("OpenTok-Python-SDK/") + __version__) - ) - expect(httpretty.last_request().headers[u("content-type")]).to( - equal(u("application/json")) - ) + validate_jwt_header(self, httpretty.last_request().headers[u('x-opentok-auth')]) + expect(httpretty.last_request().headers[u('user-agent')]).to(contain(u('OpenTok-Python-SDK/')+__version__)) + expect(httpretty.last_request().headers[u('content-type')]).to(equal(u('application/json'))) expect(stream_response).to(be_an(Stream)) - expect(stream_response).to(have_property(u("id"), stream.id)) - expect(stream_response).to(have_property(u("videoType"), stream.videoType)) - expect(stream_response).to(have_property(u("name"), stream.name)) - expect(stream_response).to( - have_property(u("layoutClassList"), stream.layoutClassList) - ) + expect(stream_response).to(have_property(u('id'), stream.id)) + expect(stream_response).to(have_property(u('videoType'), stream.videoType)) + expect(stream_response).to(have_property(u('name'), stream.name)) + expect(stream_response).to(have_property(u('layoutClassList'), stream.layoutClassList)) expect(list(stream_response.layoutClassList)).to(have_length(1)) @httpretty.activate def test_get_stream_list(self): httpretty.register_uri( httpretty.GET, - u("https://api.opentok.com/v2/project/{0}/session/{1}/stream").format( - self.api_key, self.session_id - ), - body=textwrap.dedent( - u( - """\ + u('https://api.opentok.com/v2/project/{0}/session/{1}/stream').format(self.api_key, self.session_id), + body=textwrap.dedent(u("""\ + { + "count": 2, + "items": [ { - "count": 2, - "items": [ - { - "id": "8b732909-0a06-46a2-8ea8-074e64d43422", - "videoType": "camera", - "name": "stream1", - "layoutClassList": ["full"] - }, - { - "id": "7b732909-0a06-46a2-8ea8-074e64d43423", - "videoType": "camera", - "name": "stream2", - "layoutClassList": ["full"] - } - ] + "id": "8b732909-0a06-46a2-8ea8-074e64d43422", + "videoType": "camera", + "name": "stream1", + "layoutClassList": ["full"] + }, + { + "id": "7b732909-0a06-46a2-8ea8-074e64d43423", + "videoType": "camera", + "name": "stream2", + "layoutClassList": ["full"] } - """ - ) - ), + ] + }""")), status=200, - content_type=u("application/json"), + content_type=u('application/json') ) stream_list = self.opentok.list_streams(self.session_id) - validate_jwt_header(self, httpretty.last_request().headers[u("x-opentok-auth")]) - expect(httpretty.last_request().headers[u("user-agent")]).to( - contain(u("OpenTok-Python-SDK/") + __version__) - ) - expect(httpretty.last_request().headers[u("content-type")]).to( - equal(u("application/json")) - ) + validate_jwt_header(self, httpretty.last_request().headers[u('x-opentok-auth')]) + expect(httpretty.last_request().headers[u('user-agent')]).to(contain(u('OpenTok-Python-SDK/')+__version__)) + expect(httpretty.last_request().headers[u('content-type')]).to(equal(u('application/json'))) expect(stream_list).to(be_an(StreamList)) - expect(stream_list).to(have_property(u("count"), 2)) + expect(stream_list).to(have_property(u('count'), 2)) expect(list(stream_list.items)).to(have_length(2)) @httpretty.activate def test_set_stream_class_lists(self): """ Test set stream class functionality """ payload = [ - { - "id": "7b09ec3c-26f9-43d7-8197-f608f13d4fb6", - "layoutClassList": ["focus"], - }, - {"id": "567bc941-6ea0-4c69-97fc-70a740b68976", "layoutClassList": ["top"]}, - { - "id": "307dc941-0450-4c09-975c-705740d08970", - "layoutClassList": ["bottom"], - }, + {'id': '7b09ec3c-26f9-43d7-8197-f608f13d4fb6', 'layoutClassList': ['focus']}, + {'id': '567bc941-6ea0-4c69-97fc-70a740b68976', 'layoutClassList': ['top']}, + {'id': '307dc941-0450-4c09-975c-705740d08970', 'layoutClassList': ['bottom']} ] httpretty.register_uri( httpretty.PUT, - u("https://api.opentok.com/v2/project/{0}/session/{1}/stream").format( - self.api_key, self.session_id + u('https://api.opentok.com/v2/project/{0}/session/{1}/stream').format( + self.api_key, + self.session_id ), status=200, - content_type=u("application/json"), + content_type=u('application/json') ) self.opentok.set_stream_class_lists(self.session_id, payload) - validate_jwt_header(self, httpretty.last_request().headers[u("x-opentok-auth")]) - expect(httpretty.last_request().headers[u("user-agent")]).to( - contain(u("OpenTok-Python-SDK/") + __version__) - ) - expect(httpretty.last_request().headers[u("content-type")]).to( - equal(u("application/json")) - ) + validate_jwt_header(self, httpretty.last_request().headers[u('x-opentok-auth')]) + expect(httpretty.last_request().headers[u('user-agent')]).to(contain( + u('OpenTok-Python-SDK/')+__version__)) + expect(httpretty.last_request().headers[u('content-type')]).to(equal(u('application/json'))) @httpretty.activate def test_set_stream_class_lists_throws_exception(self): """ Test invalid request in set stream class list """ - - # invalid payload - payload = [{"id": "7b09ec3c-26f9-43d7-8197-f608f13d4fb6"}] + + #invalid payload + payload = [ + {'id': '7b09ec3c-26f9-43d7-8197-f608f13d4fb6'} + ] httpretty.register_uri( httpretty.PUT, - u("https://api.opentok.com/v2/project/{0}/session/{1}/stream").format( - self.api_key, self.session_id + u('https://api.opentok.com/v2/project/{0}/session/{1}/stream').format( + self.api_key, + self.session_id ), status=400, - content_type=u("application/json"), + content_type=u('application/json') ) self.assertRaises( SetStreamClassError, self.opentok.set_stream_class_lists, self.session_id, - payload, + payload ) diff --git a/tests/test_token_generation.py b/tests/test_token_generation.py index ba9b3b5..ef9a3de 100644 --- a/tests/test_token_generation.py +++ b/tests/test_token_generation.py @@ -10,30 +10,27 @@ from .helpers import token_decoder, token_signature_validator - class OpenTokTokenGenerationTest(unittest.TestCase): def setUp(self): - self.api_key = u("123456") - self.api_secret = u("1234567890abcdef1234567890abcdef1234567890") - self.session_id = u( - "1_MX4xMjM0NTZ-flNhdCBNYXIgMTUgMTQ6NDI6MjMgUERUIDIwMTR-MC40OTAxMzAyNX4" - ) + self.api_key = u('123456') + self.api_secret = u('1234567890abcdef1234567890abcdef1234567890') + self.session_id = u('1_MX4xMjM0NTZ-flNhdCBNYXIgMTUgMTQ6NDI6MjMgUERUIDIwMTR-MC40OTAxMzAyNX4') self.opentok = OpenTok(self.api_key, self.api_secret) def test_generate_plain_token(self): token = self.opentok.generate_token(self.session_id) assert isinstance(token, text_type) - assert token_decoder(token)[u("session_id")] == self.session_id + assert token_decoder(token)[u('session_id')] == self.session_id assert token_signature_validator(token, self.api_secret) def test_generate_role_token(self): token = self.opentok.generate_token(self.session_id, Roles.moderator) assert isinstance(token, text_type) - assert token_decoder(token)[u("role")] == Roles.moderator.value + assert token_decoder(token)[u('role')] == Roles.moderator.value assert token_signature_validator(token, self.api_secret) token = self.opentok.generate_token(self.session_id, role=Roles.moderator) assert isinstance(token, text_type) - assert token_decoder(token)[u("role")] == Roles.moderator.value + assert token_decoder(token)[u('role')] == Roles.moderator.value assert token_signature_validator(token, self.api_secret) def test_generate_expires_token(self): @@ -41,52 +38,43 @@ def test_generate_expires_token(self): expire_time = int(time.time()) + 100 token = self.opentok.generate_token(self.session_id, expire_time=expire_time) assert isinstance(token, text_type) - assert token_decoder(token)[u("expire_time")] == text_type(expire_time) + assert token_decoder(token)[u('expire_time')] == text_type(expire_time) assert token_signature_validator(token, self.api_secret) # anything that can be coerced into an integer is also valid expire_time = text_type(int(time.time()) + 100) token = self.opentok.generate_token(self.session_id, expire_time=expire_time) assert isinstance(token, text_type) - assert token_decoder(token)[u("expire_time")] == expire_time + assert token_decoder(token)[u('expire_time')] == expire_time assert token_signature_validator(token, self.api_secret) # a datetime object is also valid if PY2: - expire_time = datetime.datetime.fromtimestamp( - time.time(), pytz.UTC - ) + datetime.timedelta(days=1) + expire_time = datetime.datetime.fromtimestamp(time.time(), pytz.UTC) + datetime.timedelta(days=1) if PY3: - expire_time = datetime.datetime.fromtimestamp( - time.time(), datetime.timezone.utc - ) + datetime.timedelta(days=1) + expire_time = datetime.datetime.fromtimestamp(time.time(), datetime.timezone.utc) + datetime.timedelta(days=1) token = self.opentok.generate_token(self.session_id, expire_time=expire_time) assert isinstance(token, text_type) - assert token_decoder(token)[u("expire_time")] == text_type( - calendar.timegm(expire_time.utctimetuple()) - ) + assert token_decoder(token)[u('expire_time')] == text_type(calendar.timegm(expire_time.utctimetuple())) assert token_signature_validator(token, self.api_secret) + def test_generate_data_token(self): - data = u("name=Johnny") + data = u('name=Johnny') token = self.opentok.generate_token(self.session_id, data=data) assert isinstance(token, text_type) - assert token_decoder(token)[u("connection_data")] == data + assert token_decoder(token)[u('connection_data')] == data assert token_signature_validator(token, self.api_secret) def test_generate_initial_layout_class_list(self): - initial_layout_class_list = [u("focus"), u("small")] - token = self.opentok.generate_token( - self.session_id, initial_layout_class_list=initial_layout_class_list - ) + initial_layout_class_list = [u('focus'), u('small')]; + token = self.opentok.generate_token(self.session_id, initial_layout_class_list=initial_layout_class_list) assert isinstance(token, text_type) - assert sorted( - token_decoder(token)[u("initial_layout_class_list")].split(u(" ")) - ) == sorted(initial_layout_class_list) + assert sorted(token_decoder(token)[u('initial_layout_class_list')].split(u(' '))) == sorted(initial_layout_class_list) assert token_signature_validator(token, self.api_secret) def test_generate_no_data_token(self): token = self.opentok.generate_token(self.session_id) assert isinstance(token, text_type) - assert u("connection_data") not in token_decoder(token) + assert u('connection_data') not in token_decoder(token) assert token_signature_validator(token, self.api_secret) @raises(TypeError) @@ -99,14 +87,12 @@ def test_does_not_generate_token_without_session(self): @raises(OpenTokException) def test_does_not_generate_token_invalid_session(self): - token = self.opentok.generate_token(u("NOT A REAL SESSIONID")) + token = self.opentok.generate_token(u('NOT A REAL SESSIONID')) @raises(OpenTokException) def test_does_not_generate_token_without_api_key_match(self): # this session_id has the wrong api_key - session_id = u( - "1_MX42NTQzMjF-flNhdCBNYXIgMTUgMTQ6NDI6MjMgUERUIDIwMTR-MC40OTAxMzAyNX4" - ) + session_id = u('1_MX42NTQzMjF-flNhdCBNYXIgMTUgMTQ6NDI6MjMgUERUIDIwMTR-MC40OTAxMzAyNX4') token = self.opentok.generate_token(session_id) # TODO: all the things that raise OpenTokException diff --git a/tests/validate_jwt.py b/tests/validate_jwt.py index e9ddc1b..1a03987 100644 --- a/tests/validate_jwt.py +++ b/tests/validate_jwt.py @@ -3,16 +3,15 @@ from jose import jwt import time - def validate_jwt_header(self, jsonwebtoken): - claims = jwt.decode(jsonwebtoken, self.api_secret, algorithms=[u("HS256")]) - expect(claims).to(have_key(u("iss"))) - expect(claims[u("iss")]).to(equal(self.api_key)) - expect(claims).to(have_key(u("ist"))) - expect(claims[u("ist")]).to(equal(u("project"))) - expect(claims).to(have_key(u("exp"))) - expect(float(claims[u("exp")])).to(be_above(float(time.time()))) + claims = jwt.decode(jsonwebtoken, self.api_secret, algorithms=[u('HS256')]) + expect(claims).to(have_key(u('iss'))) + expect(claims[u('iss')]).to(equal(self.api_key)) + expect(claims).to(have_key(u('ist'))) + expect(claims[u('ist')]).to(equal(u('project'))) + expect(claims).to(have_key(u('exp'))) + expect(float(claims[u('exp')])).to(be_above(float(time.time()))) # todo: add test to check for anvil failure code if exp time is greater than anvil expects - expect(claims).to(have_key(u("jti"))) - expect(float(claims[u("jti")])).to(be_above_or_equal(float(0))) - expect(float(claims[u("jti")])).to(be_below(float(1))) + expect(claims).to(have_key(u('jti'))) + expect(float(claims[u('jti')])).to(be_above_or_equal(float(0))) + expect(float(claims[u('jti')])).to(be_below(float(1)))