Skip to content

Commit

Permalink
Merge pull request #33 from praw-dev/badrequest
Browse files Browse the repository at this point in the history
Support 400 Bad Request responses and release 0.0.10.
  • Loading branch information
bboe committed Jul 9, 2016
2 parents 53d1df8 + 09e8836 commit 6ec88b4
Show file tree
Hide file tree
Showing 6 changed files with 140 additions and 14 deletions.
15 changes: 15 additions & 0 deletions CHANGES.rst
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
@@ -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
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
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
@@ -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
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

0 comments on commit 6ec88b4

Please sign in to comment.