Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support 400 Bad Request responses and release 0.0.10. #33

Merged
merged 3 commits into from
Jul 9, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
15 changes: 15 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,21 @@ Change Log
prawcore follows `semantic versioning <http://semver.org/>`_ with the exception
that deprecations will not be announced by a minor release.

0.0.10 (2016-07-10)
-------------------

**Added**

* Support 400 "Bad Request" HTTP responses used in some v1 endpoints.
* Support 204 "No Content" HTTP responses used in some v1 endpoints.

0.0.9 (2016-07-09)
------------------

**Added**

* Support 201 "Created" HTTP responses used in some v1 endpoints.


0.0.8 (2016-03-21)
------------------
Expand Down
2 changes: 1 addition & 1 deletion prawcore/const.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""Constants for the prawcore package."""

__version__ = '0.0.9'
__version__ = '0.0.10'

ACCESS_TOKEN_PATH = '/api/v1/access_token'
AUTHORIZATION_PATH = '/api/v1/authorize'
Expand Down
4 changes: 4 additions & 0 deletions prawcore/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ def __init__(self, response, error, description):
.format(error, description))


class BadRequest(RequestException):
"""Indicate invalid parameters for the request."""


class Forbidden(RequestException):
"""Indicate the authentication is not permitted for the request."""

Expand Down
4 changes: 3 additions & 1 deletion prawcore/sessions.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

from .auth import Authorizer
from .rate_limit import RateLimiter
from .exceptions import InvalidInvocation, Redirect
from .exceptions import BadRequest, InvalidInvocation, Redirect
from .util import authorization_error_class

log = logging.getLogger(__package__)
Expand Down Expand Up @@ -81,6 +81,8 @@ def request(self, method, path, params=None, data=None):

if response.status_code in (codes['forbidden'], codes['unauthorized']):
raise authorization_error_class(response)
elif response.status_code == codes['bad_request']:
raise BadRequest(response)
elif response.status_code == codes['found']:
raise Redirect(response)
elif response.status_code == codes['no_content']:
Expand Down
103 changes: 103 additions & 0 deletions tests/cassettes/Session_request__bad_request.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
{
"http_interactions": [
{
"recorded_at": "2016-07-09T23:09:27",
"request": {
"body": {
"encoding": "utf-8",
"string": "grant_type=password&password=<PASSWORD>&username=<USERNAME>"
},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate",
"Authorization": "Basic <BASIC_AUTH>",
"Connection": "keep-alive",
"Content-Length": "57",
"Content-Type": "application/x-www-form-urlencoded",
"Cookie": "loid=S1UX7gEWPLHZFXDMKZ; __cfduid=dd555eb868b1bcfd517d08fcb174c3afc1454806972",
"User-Agent": "prawcore:test (by /u/bboe) prawcore/0.0.9"
},
"method": "POST",
"uri": "https://www.reddit.com/api/v1/access_token"
},
"response": {
"body": {
"base64_string": "H4sIAAAAAAAAA6tWSkxOTi0uji/Jz07NU7JSUMqKTLKsTEoPC/Ay9S9ON3V0SUvPyDQIs0gsilTSUVACq4svqSxIBSlOSk0sSi0CiadWFGQWpRbHZ4IMMTYzMNBRUCpOzoco01KqBQCMctsQaQAAAA==",
"encoding": "UTF-8",
"string": ""
},
"headers": {
"CF-RAY": "2bff7190c8c9297b-DUB",
"Connection": "keep-alive",
"Content-Encoding": "gzip",
"Content-Type": "application/json; charset=UTF-8",
"Date": "Sat, 09 Jul 2016 23:09:27 GMT",
"Server": "cloudflare-nginx",
"Strict-Transport-Security": "max-age=15552000; includeSubDomains; preload",
"Transfer-Encoding": "chunked",
"X-Moose": "majestic",
"cache-control": "max-age=0, must-revalidate",
"x-content-type-options": "nosniff",
"x-frame-options": "SAMEORIGIN",
"x-xss-protection": "1; mode=block"
},
"status": {
"code": 200,
"message": "OK"
},
"url": "https://www.reddit.com/api/v1/access_token"
}
},
{
"recorded_at": "2016-07-09T23:09:27",
"request": {
"body": {
"encoding": "utf-8",
"string": "{\"note\": \"prawcore\"}"
},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate",
"Authorization": "bearer jYb9ybgVPJ5Osg5ADfghi0V8arY",
"Connection": "keep-alive",
"Content-Length": "20",
"Cookie": "loid=S1UX7gEWPLHZFXDMKZ; __cfduid=dd555eb868b1bcfd517d08fcb174c3afc1454806972",
"User-Agent": "prawcore:test (by /u/bboe) prawcore/0.0.9"
},
"method": "PUT",
"uri": "https://oauth.reddit.com/api/v1/me/friends/spez?raw_json=1"
},
"response": {
"body": {
"encoding": "UTF-8",
"string": "{\"fields\": [\"note\"], \"explanation\": \"you must have an active reddit gold subscription to do that\", \"message\": \"Bad Request\", \"reason\": \"GOLD_REQUIRED\"}"
},
"headers": {
"CF-RAY": "2bff719571a6299f-DUB",
"Connection": "keep-alive",
"Content-Length": "151",
"Content-Type": "application/json; charset=UTF-8",
"Date": "Sat, 09 Jul 2016 23:09:27 GMT",
"Server": "cloudflare-nginx",
"Strict-Transport-Security": "max-age=15552000; includeSubDomains; preload",
"X-Moose": "majestic",
"cache-control": "private, s-maxage=0, max-age=0, must-revalidate",
"expires": "-1",
"x-content-type-options": "nosniff",
"x-frame-options": "SAMEORIGIN",
"x-ratelimit-remaining": "597.0",
"x-ratelimit-reset": "33",
"x-ratelimit-used": "3",
"x-ua-compatible": "IE=edge",
"x-xss-protection": "1; mode=block"
},
"status": {
"code": 400,
"message": "Bad Request"
},
"url": "https://oauth.reddit.com/api/v1/me/friends/spez?raw_json=1"
}
}
],
"recorded_with": "betamax/0.7.1"
}
26 changes: 14 additions & 12 deletions tests/test_sessions.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,7 @@ def test_request__get(self):
self.assertEqual('Listing', response['kind'])

def test_request__post(self):
with Betamax(REQUESTOR).use_cassette(
'Session_request__post'):
with Betamax(REQUESTOR).use_cassette('Session_request__post'):
session = prawcore.Session(script_authorizer())
data = {'kind': 'self', 'sr': 'reddit_api_test', 'text': 'Test!',
'title': 'A Test from PRAWCORE.'}
Expand All @@ -67,39 +66,42 @@ def test_request__post(self):
response['json']['data']['url'])

def test_request__raw_json(self):
with Betamax(REQUESTOR).use_cassette(
'Session_request__raw_json'):
with Betamax(REQUESTOR).use_cassette('Session_request__raw_json'):
session = prawcore.Session(readonly_authorizer())
response = session.request('GET', ('/r/reddit_api_test/comments/'
'45xjdr/want_raw_json_test/'))
self.assertEqual('WANT_RAW_JSON test: < > &',
response[0]['data']['children'][0]['data']['title'])

def test_request__bad_request(self):
with Betamax(REQUESTOR).use_cassette('Session_request__bad_request'):
session = prawcore.Session(script_authorizer())
with self.assertRaises(prawcore.BadRequest) as context_manager:
session.request('PUT', '/api/v1/me/friends/spez',
data='{"note": "prawcore"}')
self.assertIn('reason', context_manager.exception.response.json())

def test_request__created(self):
with Betamax(REQUESTOR).use_cassette(
'Session_request__created'):
with Betamax(REQUESTOR).use_cassette('Session_request__created'):
session = prawcore.Session(script_authorizer())
response = session.request('PUT', '/api/v1/me/friends/spez',
data='{}')
self.assertIn('name', response)

def test_request__no_content(self):
with Betamax(REQUESTOR).use_cassette(
'Session_request__no_content'):
with Betamax(REQUESTOR).use_cassette('Session_request__no_content'):
session = prawcore.Session(script_authorizer())
response = session.request('DELETE', '/api/v1/me/friends/spez')
self.assertIsNone(response)

def test_request__forbidden(self):
with Betamax(REQUESTOR).use_cassette(
'Session_request__forbidden'):
with Betamax(REQUESTOR).use_cassette('Session_request__forbidden'):
session = prawcore.Session(script_authorizer())
self.assertRaises(prawcore.Forbidden, session.request,
'GET', '/user/spez/gilded/given')

def test_request__redirect(self):
with Betamax(REQUESTOR).use_cassette(
'Session_request__redirect'):
with Betamax(REQUESTOR).use_cassette('Session_request__redirect'):
session = prawcore.Session(readonly_authorizer())
with self.assertRaises(prawcore.Redirect) as context_manager:
session.request('GET', '/r/random')
Expand Down