1+ # -*- coding: utf-8 -*-
2+
3+ """
4+ heroku.api
5+ ~~~~~~~~~~
6+
7+ This module provides the basic API interface for Heroku.
8+ """
9+
10+ import requests
11+ from .compat import json
12+ from .helpers import is_collection
13+ from .structures import KeyedListResource
14+ from .models import *
15+
16+ GITHUB_URL = 'https://api.github.com'
17+
18+
19+ class GithubCore (object ):
20+ """The core Heroku class."""
21+ def __init__ (self ):
22+ super (GithubCore , self ).__init__ ()
23+
24+ #: The User's API Key.
25+ self ._api_key = None
26+ self ._api_key_verified = None
27+ self ._s = requests .session ()
28+ self ._github_url = GITHUB_URL
29+
30+ # We only want JSON back.
31+ self ._s .headers .update ({'Accept' : 'application/json' })
32+
33+ def __repr__ (self ):
34+ return '<heroku-core at 0x%x>' % (id (self ))
35+
36+ def login (self , username , password ):
37+ """Logs user into Heroku with given api_key."""
38+
39+ # Attach auth to session.
40+ self ._s .auth = (username .password )
41+
42+ return True
43+
44+ @property
45+ def is_authenticated (self ):
46+ if self ._api_key_verified is None :
47+ return self ._verify_api_key ()
48+ else :
49+ return self ._api_key_verified
50+
51+ def _url_for (self , * args ):
52+ args = map (str , args )
53+ return '/' .join ([self ._heroku_url ] + list (args ))
54+
55+ @staticmethod
56+ def _resource_serialize (o ):
57+ """Returns JSON serialization of given object."""
58+ return json .dumps (o )
59+
60+ @staticmethod
61+ def _resource_deserialize (s ):
62+ """Returns dict deserialization of a given JSON string."""
63+
64+ try :
65+ return json .loads (s )
66+ except ValueError :
67+ raise ResponseError ('The API Response was not valid.' )
68+
69+ def _http_resource (self , method , resource , params = None , data = None ):
70+ """Makes an HTTP request."""
71+
72+ if not is_collection (resource ):
73+ resource = [resource ]
74+
75+ url = self ._url_for (* resource )
76+ r = self ._s .request (method , url , params = params , data = data )
77+
78+ # TODO: check heroku's status codes
79+ r .raise_for_status ()
80+
81+ return r
82+
83+ def _get_resource (self , resource , obj , params = None , ** kwargs ):
84+ """Returns a mapped object from an HTTP resource."""
85+ r = self ._http_resource ('GET' , resource , params = params )
86+ item = self ._resource_deserialize (r .content )
87+
88+ return obj .new_from_dict (item , h = self , ** kwargs )
89+
90+ def _get_resources (self , resource , obj , params = None , map = None , ** kwargs ):
91+ """Returns a list of mapped objects from an HTTP resource."""
92+ r = self ._http_resource ('GET' , resource , params = params )
93+ d_items = self ._resource_deserialize (r .content )
94+
95+ items = [obj .new_from_dict (item , h = self , ** kwargs ) for item in d_items ]
96+
97+ if map is None :
98+ map = KeyedListResource
99+
100+ list_resource = map (items = items )
101+ list_resource ._h = self
102+ list_resource ._obj = obj
103+
104+ return list_resource
105+
106+
107+ class Github (GithubCore ):
108+ """The main Github class."""
109+
110+ def __init__ (self ):
111+ super (Github , self ).__init__ ()
112+
113+ def __repr__ (self ):
114+ return '<github-client at 0x%x>' % (id (self ))
115+
116+ # @property
117+ # def addons(self):
118+ # return self._get_resources(('addons'), Addon)
119+
120+ # @property
121+ # def apps(self):
122+ # return self._get_resources(('apps'), App)
123+
124+ # @property
125+ # def keys(self):
126+ # return self._get_resources(('user', 'keys'), Key, map=SSHKeyListResource)
127+
128+
129+ class ResponseError (ValueError ):
130+ """The API Response was unexpected."""
0 commit comments