Skip to content

Commit ecad4a9

Browse files
author
Kenneth Reitz
committed
updates
1 parent e875a2c commit ecad4a9

File tree

4 files changed

+249
-0
lines changed

4 files changed

+249
-0
lines changed

github3/api.py

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,79 @@
1010
1111
"""
1212

13+
import urllib
14+
15+
16+
from .config import settings
17+
from .helpers import is_collection
18+
from .packages import omnijson as json
19+
20+
21+
class GithubCore(object):
22+
"""The main GitHub API Interface."""
23+
24+
def __init__(self):
25+
self.username = None
26+
self._auth = None
27+
28+
29+
@staticmethod
30+
def _resource_serialize(o):
31+
"""Returns JSON serialization of given object."""
32+
return json.dumps(o)
33+
34+
35+
@staticmethod
36+
def _resource_deserialize(s):
37+
"""Returns dict deserialization of a given JSON string."""
38+
39+
try:
40+
return json.loads(s)
41+
except ValueError:
42+
raise ResponseError('The API Response was not valid.')
43+
44+
45+
def _generate_url(self, resource, params):
46+
"""Generates Readability API Resource URL."""
47+
48+
if is_collection(resource):
49+
resource = map(str, resource)
50+
resource = '/'.join(resource)
51+
52+
if params:
53+
resource += '?%s' % (urllib.urlencode(params))
54+
55+
return settings.domain + '/' + resource
56+
57+
58+
class Github(GithubCore):
59+
"""The user-facing GitHub API Interface."""
60+
61+
def __init__(self):
62+
super(Github, self).__init__()
63+
64+
65+
# ----------
66+
# Exceptions
67+
# ----------
68+
69+
class APIError(Exception):
70+
"""There was an API Error."""
71+
72+
class PermissionsError(APIError):
73+
"""You do not have proper permission."""
74+
75+
class AuthenticationError(APIError):
76+
"""Authentication failed."""
77+
78+
class ResponseError(APIError):
79+
"""The API Response was unexpected."""
80+
81+
class MissingError(APIError):
82+
"""The Resource does not exist."""
83+
84+
class BadRequestError(APIError):
85+
"""The request could not be understood due to bad syntax. Check your request and try again."""
86+
87+
class ServerError(APIError):
88+
"""The server encountered an error and was unable to complete your request."""

github3/config.py

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
# -*- coding: utf-8 -*-
2+
3+
"""
4+
github3.config
5+
~~~~~~~~~~~~~~
6+
7+
This module provides the GitHub3 settings feature set.
8+
9+
:copyright: (c) 2011 by Kenneth Reitz.
10+
:license: ISC, see LICENSE for more details.
11+
"""
12+
13+
14+
class Settings(object):
15+
_singleton = dict()
16+
17+
# attributes with defaults
18+
__attrs__ = ('timeout',)
19+
20+
def __init__(self, **kwargs):
21+
super(Settings, self).__init__()
22+
23+
self.__dict__ = self._singleton
24+
25+
26+
def __call__(self, *args, **kwargs):
27+
# new instance of class to call
28+
r = self.__class__()
29+
30+
# cache previous settings for __exit__
31+
r.__cache = self.__dict__.copy()
32+
map(self.__cache.setdefault, self.__attrs__)
33+
34+
# set new settings
35+
self.__dict__.update(*args, **kwargs)
36+
37+
return r
38+
39+
40+
def __enter__(self):
41+
pass
42+
43+
44+
def __exit__(self, *args):
45+
46+
# restore cached copy
47+
self.__dict__.update(self.__cache.copy())
48+
del self.__cache
49+
50+
51+
def __getattribute__(self, key):
52+
if key in object.__getattribute__(self, '__attrs__'):
53+
try:
54+
return object.__getattribute__(self, key)
55+
except AttributeError:
56+
return None
57+
return object.__getattribute__(self, key)
58+
59+
60+
settings = Settings()
61+
settings.domain = 'https://api.github.com'

github3/core.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,20 @@
88
99
"""
1010

11+
import requests
12+
13+
from .api import Github, settings
14+
15+
16+
__version__ = '0.0.1'
17+
__license__ = 'ISC'
18+
__author__ = 'Kenneth Reitz'
19+
20+
21+
22+
def basic(username, password):
23+
pass
24+
25+
26+
def anon():
27+
pass

github3/helpers.py

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
# -*- coding: utf-8 -*-
2+
3+
"""
4+
github3.helpers
5+
~~~~~~~~~~~~~~~
6+
7+
This module provides various helper functions to the rest of the package.
8+
"""
9+
10+
11+
from datetime import datetime
12+
13+
from dateutil.parser import parse as parse_datetime
14+
15+
16+
def is_collection(obj):
17+
"""Tests if an object is a collection."""
18+
19+
col = getattr(obj, '__getitem__', False)
20+
val = False if (not col) else True
21+
22+
if isinstance(obj, basestring):
23+
val = False
24+
25+
return val
26+
27+
28+
def to_python(obj, in_dict, string_keys=None, date_keys=None, object_map=None, **kwargs):
29+
"""Extends a given object for API Consumption.
30+
31+
:param obj: Object to extend.
32+
:param in_dict: Dict to extract data from.
33+
:param string_keys: List of in_dict keys that will be extracted as strings.
34+
:param date_keys: List of in_dict keys that will be extrad as datetimes.
35+
:param object_map: Dict of {key, obj} map, for nested object results.
36+
"""
37+
38+
if string_keys:
39+
for in_key in string_keys:
40+
# print in_key
41+
obj.__dict__[in_key] = in_dict.get(in_key)
42+
43+
if date_keys:
44+
for in_key in date_keys:
45+
in_date = in_dict.get(in_key)
46+
try:
47+
out_date = datetime.strptime(in_date, '%Y-%m-%d %H:%M:%S')
48+
except TypeError:
49+
out_date = None
50+
51+
obj.__dict__[in_key] = out_date
52+
53+
if object_map:
54+
55+
for (k, v) in object_map.items():
56+
obj.__dict__[k] = v.new_from_dict(in_dict.get(k))
57+
58+
obj.__dict__.update(kwargs)
59+
60+
return obj
61+
62+
63+
def to_api(in_dict, int_keys=None, date_keys=None):
64+
"""Extends a given object for API Production."""
65+
66+
# Cast all int_keys to int()
67+
if int_keys:
68+
for in_key in int_keys:
69+
if (in_key in in_dict) and (in_dict.get(in_key, None) is not None):
70+
in_dict[in_key] = int(in_dict[in_key])
71+
72+
# Cast all date_keys to datetime.isoformat
73+
if date_keys:
74+
for in_key in date_keys:
75+
if (in_key in in_dict) and (in_dict.get(in_key, None) is not None):
76+
77+
_from = in_dict[in_key]
78+
79+
if isinstance(_from, basestring):
80+
dtime = parse_datetime(_from)
81+
82+
elif isinstance(_from, datetime):
83+
dtime = _from
84+
85+
in_dict[in_key] = dtime.isoformat()
86+
87+
elif (in_key in in_dict) and in_dict.get(in_key, None) is None:
88+
del in_dict[in_key]
89+
90+
# Remove all Nones
91+
for k, v in in_dict.items():
92+
if v is None:
93+
del in_dict[k]
94+
95+
return in_dict

0 commit comments

Comments
 (0)