Skip to content

Commit 668d6ad

Browse files
committed
Change requests.Body to suppor required attributes
1 parent 67ebcdb commit 668d6ad

File tree

6 files changed

+89
-51
lines changed

6 files changed

+89
-51
lines changed

pygithub3/exceptions.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@
22
# -*- encoding: utf-8 -*-
33

44

5+
class InvalidBodySchema(Exception):
6+
""" Raised when the 'valids_body' attribute of Resource isn't in a
7+
valid form (required.issubsetof(schema))"""
8+
pass
9+
10+
511
class DoesNotExists(Exception):
612
""" Raised when `Request` factory can't find the subclass """
713
pass

pygithub3/requests/__init__.py

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,39 +8,47 @@
88
except ImportError:
99
import json
1010

11-
from pygithub3.exceptions import DoesNotExists, UriInvalid, ValidationError
11+
from pygithub3.exceptions import (DoesNotExists, UriInvalid, ValidationError,
12+
InvalidBodySchema)
1213
from pygithub3.resources.base import Raw
1314

1415
ABS_IMPORT_PREFIX = 'pygithub3.requests'
1516

1617

1718
class Body(object):
1819

19-
def __init__(self, content, schema):
20+
def __init__(self, content, schema, required):
2021
self.content = content
2122
self.schema = schema
23+
self.required = required
2224

2325
def dumps(self):
2426
if not self.content:
2527
return None
2628
return json.dumps(self.parse())
2729

2830
def parse(self):
29-
if not self.schema:
30-
return self.content
31-
if not hasattr(self.content, 'items'):
31+
if self.schema and not hasattr(self.content, 'items'):
3232
raise ValidationError("'%s' needs a content dictionary"
3333
% self.__class__.__name__)
34-
return {key: self.content[key] for key in self.schema
34+
parsed = {key: self.content[key] for key in self.schema
3535
if key in self.content}
36+
for attr_required in self.required:
37+
if attr_required not in parsed:
38+
raise ValidationError("'%s' attribute is required" %
39+
attr_required)
40+
if not parsed[attr_required]:
41+
raise ValidationError("'%s' attribute can't be empty" %
42+
attr_required)
43+
return parsed or self.content
3644

3745

3846
class Request(object):
3947
""" """
4048

4149
uri = ''
4250
resource = Raw
43-
body_schema = ()
51+
body_schema = {}
4452

4553
def __init__(self, **kwargs):
4654
""" """
@@ -50,14 +58,24 @@ def __init__(self, **kwargs):
5058

5159
def clean(self):
5260
self.uri = self.clean_uri() or self.uri
53-
self.body = Body(self.clean_body(), self.body_schema)
61+
self.body = Body(self.clean_body(), **self.clean_valid_body())
5462

5563
def clean_body(self):
5664
return self.body
5765

5866
def clean_uri(self):
5967
return None
6068

69+
def clean_valid_body(self):
70+
schema = set(self.body_schema.get('schema', ()))
71+
required = set(self.body_schema.get('required', ()))
72+
if not required.issubset(schema):
73+
raise InvalidBodySchema(
74+
"'%s:valid_body' attribute is invalid. "
75+
"'%s required' isn't a subset of '%s schema'" % (
76+
self.__class__.__name__, required, schema))
77+
return dict(schema=schema, required=required)
78+
6179
def __getattr__(self, name):
6280
return self.args.get(name)
6381

pygithub3/requests/users/keys.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,19 @@ class Add(Request):
2121

2222
resource = Key
2323
uri = 'user/keys'
24-
body_schema = ('title', 'key')
24+
body_schema = {
25+
'schema': ('title', 'key'),
26+
'required': ('title', 'key')
27+
}
2528

2629

2730
class Update(Request):
2831

2932
resource = Key
30-
body_schema = ('title', 'key')
33+
body_schema = {
34+
'schema': ('title', 'key'),
35+
'required': ('title', 'key')
36+
}
3137
uri = 'user/keys/{key_id}'
3238

3339

pygithub3/requests/users/user.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,11 @@ class Update(Request):
2121

2222
resource = User
2323
uri = 'user'
24-
body_schema = (
25-
'name', 'email', 'blog', 'company', 'location', 'hireable', 'bio')
24+
body_schema = {
25+
'schema': ('name', 'email', 'blog', 'company', 'location', 'hireable',
26+
'bio'),
27+
'required': (),
28+
}
2629

2730
def clean_body(self):
2831
if not self.body:

pygithub3/tests/requests/test_core.py

Lines changed: 36 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,12 @@
55
from mock import Mock
66

77
from pygithub3.requests import Factory, Body, json, Request
8-
from pygithub3.exceptions import UriInvalid, DoesNotExists, ValidationError
8+
from pygithub3.exceptions import (UriInvalid, DoesNotExists, ValidationError,
9+
InvalidBodySchema)
10+
from pygithub3.tests.utils.base import mock_json
911
from pygithub3.tests.utils.requests import (
10-
RequestWithArgs, RequestCleanedUri, RequestBodyWithSchema, mock_json,
11-
DummyRequest, RequestCleanedBody)
12+
RequestWithArgs, RequestCleanedUri, RequestBodyInvalidSchema, DummyRequest,
13+
RequestCleanedBody)
1214

1315
json.dumps = Mock(side_effect=mock_json)
1416
json.loads = Mock(side_effect=mock_json)
@@ -35,7 +37,7 @@ def test_BUILDER_builds_users(self):
3537
self.assertIsInstance(request, Request)
3638

3739

38-
class TestRequestUri(TestCase):
40+
class TestRequest(TestCase):
3941

4042
def test_SIMPLE_with_correct_args(self):
4143
request = RequestWithArgs(arg1='arg1', arg2='arg2')
@@ -51,47 +53,45 @@ def test_with_cleaned_uri(self):
5153
request = RequestCleanedUri(notmatters='test')
5254
self.assertEqual(str(request), 'URI')
5355

56+
def test_with_cleaned_body(self):
57+
self.assertRaises(ValidationError, RequestCleanedBody)
5458

55-
class TestRequestBody(TestCase):
56-
57-
def test_with_schema_with_valid(self):
58-
request = RequestBodyWithSchema(body=dict(
59-
arg1='only', fake='t', fake1='t'))
60-
self.assertEqual(request.get_body(), dict(arg1='only'))
61-
62-
def test_with_schema_with_invalid(self):
63-
request = RequestBodyWithSchema(body='invalid_data')
64-
self.assertRaises(ValidationError, request.get_body)
65-
66-
def test_with_schema_without_body(self):
67-
request = RequestBodyWithSchema()
68-
self.assertIsNone(request.get_body())
59+
def test_with_invalid_schema(self):
60+
self.assertRaises(InvalidBodySchema, RequestBodyInvalidSchema)
6961

70-
def test_without_schema(self):
62+
def test_body_without_schema(self):
7163
request = DummyRequest(body=dict(arg1='test'))
7264
self.assertEqual(request.get_body(), dict(arg1='test'))
65+
self.assertEqual(request.body.schema, set(()))
66+
self.assertEqual(request.body.required, set(()))
7367

74-
def test_without_schema_without_body(self):
68+
def test_without_body_and_without_schema(self):
7569
request = DummyRequest()
7670
self.assertIsNone(request.get_body())
7771

78-
def test_with_clean_body(self):
79-
self.assertRaises(ValidationError, RequestCleanedBody)
8072

73+
class TestRequestBody(TestCase):
74+
75+
def setUp(self):
76+
valid_body = dict(schema=('arg1', 'arg2'), required=('arg1', ))
77+
self.b = Body({}, **valid_body)
78+
79+
def test_with_required(self):
80+
self.b.content = dict(arg1='arg1')
81+
self.assertEqual(self.b.dumps(), dict(arg1='arg1'))
82+
83+
def test_without_required(self):
84+
self.b.content = dict(arg2='arg2')
85+
self.assertRaises(ValidationError, self.b.dumps)
86+
87+
def test_with_invalid(self):
88+
self.b.content = 'invalid'
89+
self.assertRaises(ValidationError, self.b.dumps)
8190

82-
class TestBodyParsers(TestCase):
91+
def test_without_body(self):
92+
self.b.content = None
93+
self.assertIsNone(self.b.dumps())
8394

8495
def test_only_valid_keys(self):
85-
body = Body(
86-
dict(arg1='arg1', arg2='arg2', arg3='arg3', arg4='arg4'),
87-
('arg1', 'arg3', 'arg4'))
88-
self.assertEqual(body.parse(), dict(arg1='arg1', arg3='arg3',
89-
arg4='arg4'))
90-
91-
def test_none(self):
92-
body = Body({}, ('arg1', 'arg2'))
93-
self.assertEqual(body.parse(), {})
94-
95-
def test_invalid_content(self):
96-
body = Body('invalid', ('arg1',))
97-
self.assertRaises(ValidationError, body.parse)
96+
self.b.content = dict(arg1='arg1', arg2='arg2', fake='test')
97+
self.assertEqual(self.b.dumps(), dict(arg1='arg1', arg2='arg2'))

pygithub3/tests/utils/requests.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#!/usr/bin/env python
22
# -*- encoding: utf-8 -*-
33

4-
from .base import Request, DummyResource, DummyRequest, mock_json
4+
from .base import Request, DummyResource, DummyRequest
55
from pygithub3.exceptions import ValidationError
66

77

@@ -19,9 +19,14 @@ def clean_uri(self):
1919
return 'URI'
2020

2121

22-
class RequestBodyWithSchema(Request):
22+
class RequestBodyInvalidSchema(Request):
23+
""" It's invalid because body_schema[required] isn't a subset of
24+
body_schema[schema] """
2325
uri = 'URI'
24-
body_schema = ('arg1', 'arg2')
26+
body_schema = {
27+
'schema': ('arg1', 'arg2'),
28+
'required': ('arg3', )
29+
}
2530

2631

2732
class RequestCleanedBody(Request):

0 commit comments

Comments
 (0)