Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
import json
import logging
import os
import requests
import sys
import unittest
if sys.version_info.major < 3:
import backports.unittest_mock
backports.unittest_mock.install()
from unittest.mock import MagicMock, patch, call
import pdpyras
pdpyras.APISession.raise_if_http_error = True
class Session(object):
"""
Python reqeusts.Session mockery class
"""
request = None
headers = None
class Response(object):
"""Mock class for emulating requests.Response objects
Look for existing use of this class for examples on how to use.
"""
def __init__(self, code, text, method='GET', url=None):
super(Response, self).__init__()
def test_profiler_key(self):
sess = pdpyras.APISession('token')
self.assertEqual(
'post:users/{id}/contact_methods/{index}',
sess.profiler_key(
'POST',
'https://api.pagerduty.com/users/PCWKOPZ/contact_methods'
)
returns.append(Response(200, json.dumps({'user': user})))
request.side_effect = returns
r = sess.get('/users/P123456')
self.assertEqual(sess.max_network_attempts+1,
request.call_count)
self.assertEqual(sess.max_network_attempts, sleep.call_count)
self.assertTrue(r.ok)
request.reset_mock()
sleep.reset_mock()
# Now test handling a non-transient error:
raises = [pdpyras.RequestsError("D'oh!")]*(
sess.max_network_attempts-1)
raises.extend([pdpyras.Urllib3Error("D'oh!")]*2)
request.side_effect = raises
self.assertRaises(pdpyras.PDClientError, sess.get, '/users')
self.assertEqual(sess.max_network_attempts+1,
request.call_count)
self.assertEqual(sess.max_network_attempts, sleep.call_count)
# Test custom retry logic:
sess.retry[404] = 3
request.side_effect = [
Response(404, json.dumps({})),
Response(404, json.dumps({})),
Response(200, json.dumps({'user': user})),
]
r = sess.get('/users/P123456')
self.assertEqual(200, r.status_code)
# Test retry logic with too many 404s
sess.retry[404] = 1
request.side_effect = [
response.reset_mock()
response.ok = False
do_http_things.__name__ = 'rput' # just for instance
self.assertRaises(pdpyras.PDClientError,
pdpyras.resource_envelope(do_http_things), my_self, '/services')
reset_mocks()
# GET /: use a different envelope name
response.ok = True
users_array = [{"type":"user","email":"user@example.com",
"summary":"User McUserson"}]
response.json.return_value = {'users': users_array}
do_http_things.__name__ = 'rget'
dummy_session.url = 'https://api.pagerduty.com'
self.assertEqual(users_array,
pdpyras.resource_envelope(do_http_things)(dummy_session, '/users',
query='user'))
reset_mocks()
# Test request body JSON envelope stuff in post/put
# Response body validation
do_http_things.__name__ = 'rpost'
user_payload = {'email':'user@example.com', 'name':'User McUserson'}
self.assertRaises(
pdpyras.PDClientError,
pdpyras.resource_envelope(do_http_things),
dummy_session, '/users', json=user_payload
)
reset_mocks()
# Add type property; should work now and automatically pack the user
# object into a JSON object inside the envelope.
user_payload['type'] = 'user'
"summary":"User McUserson"}]
response.json.return_value = {'users': users_array}
do_http_things.__name__ = 'rget'
dummy_session.url = 'https://api.pagerduty.com'
self.assertEqual(users_array,
pdpyras.resource_envelope(do_http_things)(dummy_session, '/users',
query='user'))
reset_mocks()
# Test request body JSON envelope stuff in post/put
# Response body validation
do_http_things.__name__ = 'rpost'
user_payload = {'email':'user@example.com', 'name':'User McUserson'}
self.assertRaises(
pdpyras.PDClientError,
pdpyras.resource_envelope(do_http_things),
dummy_session, '/users', json=user_payload
)
reset_mocks()
# Add type property; should work now and automatically pack the user
# object into a JSON object inside the envelope.
user_payload['type'] = 'user'
do_http_things.__name__ = 'rpost'
response.ok = True
created_user = user_payload.copy()
created_user['id'] = 'P456XYZ'
response.json.return_value = {'user':created_user}
self.assertEqual(
created_user,
pdpyras.resource_envelope(do_http_things)(dummy_session, '/users',
json=user_payload)
)
pdpyras.PDClientError,
pdpyras.resource_envelope(do_http_things),
dummy_session, '/users', json=user_payload
)
reset_mocks()
# Add type property; should work now and automatically pack the user
# object into a JSON object inside the envelope.
user_payload['type'] = 'user'
do_http_things.__name__ = 'rpost'
response.ok = True
created_user = user_payload.copy()
created_user['id'] = 'P456XYZ'
response.json.return_value = {'user':created_user}
self.assertEqual(
created_user,
pdpyras.resource_envelope(do_http_things)(dummy_session, '/users',
json=user_payload)
)
do_http_things.assert_called_with(dummy_session, '/users',
json={'user':user_payload})
reset_mocks()
# Test auto-envelope functionality for multi-update
# TODO: This test is loosely coupled but somewhat naive. Tighten if need
# be.
incidents = [{'id':'PABC123'}, {'id':'PDEF456'}]
do_http_things.__name__ = 'rput'
response.ok = True
updated_incidents = copy.deepcopy(incidents)
response.json.return_value = {'incidents': updated_incidents}
self.assertEqual(
updated_incidents,
do_http_things.return_value = response
my_self = pdpyras.APISession('some_key')
self.debug(my_self)
dummy_session = MagicMock()
def reset_mocks():
do_http_things.reset_mock()
response.reset_mock()
do_http_things.return_value = response
dummy_session.reset_mock()
# OK response, good JSON: JSON-decode and unpack response
response.ok = True
response.json.return_value = {'service': {'name': 'value'}}
do_http_things.__name__ = 'rput' # just for instance
self.assertEqual(
pdpyras.resource_envelope(do_http_things)(my_self,
'/services/PTHINGY'),
{'name': 'value'}
)
reset_mocks()
# OK response, bad JSON: raise exception.
response.ok = True
do_http_things.__name__ = 'rput' # just for instance
response.json.side_effect = [ValueError('Bad JSON!')]
self.assertRaises(pdpyras.PDClientError,
pdpyras.resource_envelope(do_http_things), my_self, '/services')
reset_mocks()
# OK response, but ruh-roh we hit an anti-pattern (probably won't exist
# except maybe in beta/reverse-engineered endpoints; this design is thus
# anticipatory rather than practical). Raise exception.
)
do_http_things.assert_called_with(dummy_session, '/users',
json={'user':user_payload})
reset_mocks()
# Test auto-envelope functionality for multi-update
# TODO: This test is loosely coupled but somewhat naive. Tighten if need
# be.
incidents = [{'id':'PABC123'}, {'id':'PDEF456'}]
do_http_things.__name__ = 'rput'
response.ok = True
updated_incidents = copy.deepcopy(incidents)
response.json.return_value = {'incidents': updated_incidents}
self.assertEqual(
updated_incidents,
pdpyras.resource_envelope(do_http_things)(dummy_session,
'/incidents', json=incidents)
)
def test_tokenize_url_path(self):
cm_path = ('users', '{id}', 'contact_methods', '{index}')
cm_path_str = 'users/PABC123/contact_methods'
baseurl = 'https://rest.pd/'
self.assertEqual(cm_path, pdpyras.tokenize_url_path(cm_path_str))
self.assertEqual(cm_path, pdpyras.tokenize_url_path(baseurl+cm_path_str,
baseurl=baseurl))
self.assertRaises(ValueError, pdpyras.tokenize_url_path,
'/https://api.pagerduty.com/?')
self.assertRaises(ValueError, pdpyras.tokenize_url_path,
'https://api.pagerduty.com/')
self.assertRaises(ValueError, pdpyras.tokenize_url_path,
'https://api.pagerduty.com')
self.assertRaises(ValueError, pdpyras.tokenize_url_path,
'/')
self.assertRaises(ValueError, pdpyras.tokenize_url_path,
'/users/')
self.assertEqual(('users','{index}'),
pdpyras.tokenize_url_path('/users'))
def test_tokenize_url_path(self):
cm_path = ('users', '{id}', 'contact_methods', '{index}')
cm_path_str = 'users/PABC123/contact_methods'
baseurl = 'https://rest.pd/'
self.assertEqual(cm_path, pdpyras.tokenize_url_path(cm_path_str))
self.assertEqual(cm_path, pdpyras.tokenize_url_path(baseurl+cm_path_str,
baseurl=baseurl))
self.assertRaises(ValueError, pdpyras.tokenize_url_path,
'/https://api.pagerduty.com/?')
self.assertRaises(ValueError, pdpyras.tokenize_url_path,
'https://api.pagerduty.com/')
self.assertRaises(ValueError, pdpyras.tokenize_url_path,
'https://api.pagerduty.com')
self.assertRaises(ValueError, pdpyras.tokenize_url_path,
'/')
self.assertRaises(ValueError, pdpyras.tokenize_url_path,
'/users/')
self.assertEqual(('users','{index}'),
pdpyras.tokenize_url_path('/users'))