Mercurial > repos > bcclaywell > argo_navis
comparison venv/lib/python2.7/site-packages/github/GithubObject.py @ 0:d67268158946 draft
planemo upload commit a3f181f5f126803c654b3a66dd4e83a48f7e203b
author | bcclaywell |
---|---|
date | Mon, 12 Oct 2015 17:43:33 -0400 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:d67268158946 |
---|---|
1 # -*- coding: utf-8 -*- | |
2 | |
3 # ########################## Copyrights and license ############################ | |
4 # # | |
5 # Copyright 2012 Vincent Jacques <vincent@vincent-jacques.net> # | |
6 # Copyright 2012 Zearin <zearin@gonk.net> # | |
7 # Copyright 2013 AKFish <akfish@gmail.com> # | |
8 # Copyright 2013 Vincent Jacques <vincent@vincent-jacques.net> # | |
9 # # | |
10 # This file is part of PyGithub. http://jacquev6.github.com/PyGithub/ # | |
11 # # | |
12 # PyGithub is free software: you can redistribute it and/or modify it under # | |
13 # the terms of the GNU Lesser General Public License as published by the Free # | |
14 # Software Foundation, either version 3 of the License, or (at your option) # | |
15 # any later version. # | |
16 # # | |
17 # PyGithub is distributed in the hope that it will be useful, but WITHOUT ANY # | |
18 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # | |
19 # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more # | |
20 # details. # | |
21 # # | |
22 # You should have received a copy of the GNU Lesser General Public License # | |
23 # along with PyGithub. If not, see <http://www.gnu.org/licenses/>. # | |
24 # # | |
25 # ############################################################################## | |
26 | |
27 import datetime | |
28 | |
29 import GithubException | |
30 import Consts | |
31 | |
32 | |
33 class _NotSetType: | |
34 def __repr__(self): | |
35 return "NotSet" | |
36 | |
37 value = None | |
38 NotSet = _NotSetType() | |
39 | |
40 | |
41 class _ValuedAttribute: | |
42 def __init__(self, value): | |
43 self.value = value | |
44 | |
45 | |
46 class _BadAttribute: | |
47 def __init__(self, value, expectedType, exception=None): | |
48 self.__value = value | |
49 self.__expectedType = expectedType | |
50 self.__exception = exception | |
51 | |
52 @property | |
53 def value(self): | |
54 raise GithubException.BadAttributeException(self.__value, self.__expectedType, self.__exception) | |
55 | |
56 | |
57 class GithubObject(object): | |
58 """ | |
59 Base class for all classes representing objects returned by the API. | |
60 """ | |
61 | |
62 ''' | |
63 A global debug flag to enable header validation by requester for all objects | |
64 ''' | |
65 CHECK_AFTER_INIT_FLAG = False | |
66 | |
67 @classmethod | |
68 def setCheckAfterInitFlag(cls, flag): | |
69 cls.CHECK_AFTER_INIT_FLAG = flag | |
70 | |
71 def __init__(self, requester, headers, attributes, completed): | |
72 self._requester = requester | |
73 self._initAttributes() | |
74 self._storeAndUseAttributes(headers, attributes) | |
75 | |
76 # Ask requester to do some checking, for debug and test purpose | |
77 # Since it's most handy to access and kinda all-knowing | |
78 if self.CHECK_AFTER_INIT_FLAG: # pragma no branch (Flag always set in tests) | |
79 requester.check_me(self) | |
80 | |
81 def _storeAndUseAttributes(self, headers, attributes): | |
82 # Make sure headers are assigned before calling _useAttributes | |
83 # (Some derived classes will use headers in _useAttributes) | |
84 self._headers = headers | |
85 self._rawData = attributes | |
86 self._useAttributes(attributes) | |
87 | |
88 @property | |
89 def raw_data(self): | |
90 """ | |
91 :type: dict | |
92 """ | |
93 self._completeIfNeeded() | |
94 return self._rawData | |
95 | |
96 @property | |
97 def raw_headers(self): | |
98 """ | |
99 :type: dict | |
100 """ | |
101 self._completeIfNeeded() | |
102 return self._headers | |
103 | |
104 @staticmethod | |
105 def _parentUrl(url): | |
106 return "/".join(url.split("/")[: -1]) | |
107 | |
108 @staticmethod | |
109 def __makeSimpleAttribute(value, type): | |
110 if value is None or isinstance(value, type): | |
111 return _ValuedAttribute(value) | |
112 else: | |
113 return _BadAttribute(value, type) | |
114 | |
115 @staticmethod | |
116 def __makeSimpleListAttribute(value, type): | |
117 if isinstance(value, list) and all(isinstance(element, type) for element in value): | |
118 return _ValuedAttribute(value) | |
119 else: | |
120 return _BadAttribute(value, [type]) | |
121 | |
122 @staticmethod | |
123 def __makeTransformedAttribute(value, type, transform): | |
124 if value is None: | |
125 return _ValuedAttribute(None) | |
126 elif isinstance(value, type): | |
127 try: | |
128 return _ValuedAttribute(transform(value)) | |
129 except Exception, e: | |
130 return _BadAttribute(value, type, e) | |
131 else: | |
132 return _BadAttribute(value, type) | |
133 | |
134 @staticmethod | |
135 def _makeStringAttribute(value): | |
136 return GithubObject.__makeSimpleAttribute(value, (str, unicode)) | |
137 | |
138 @staticmethod | |
139 def _makeIntAttribute(value): | |
140 return GithubObject.__makeSimpleAttribute(value, (int, long)) | |
141 | |
142 @staticmethod | |
143 def _makeBoolAttribute(value): | |
144 return GithubObject.__makeSimpleAttribute(value, bool) | |
145 | |
146 @staticmethod | |
147 def _makeDictAttribute(value): | |
148 return GithubObject.__makeSimpleAttribute(value, dict) | |
149 | |
150 @staticmethod | |
151 def _makeTimestampAttribute(value): | |
152 return GithubObject.__makeTransformedAttribute(value, (int, long), datetime.datetime.utcfromtimestamp) | |
153 | |
154 @staticmethod | |
155 def _makeDatetimeAttribute(value): | |
156 def parseDatetime(s): | |
157 if len(s) == 24: # pragma no branch (This branch was used only when creating a download) | |
158 # The Downloads API has been removed. I'm keeping this branch because I have no mean | |
159 # to check if it's really useless now. | |
160 return datetime.datetime.strptime(s, "%Y-%m-%dT%H:%M:%S.000Z") # pragma no cover (This branch was used only when creating a download) | |
161 elif len(s) == 25: | |
162 return datetime.datetime.strptime(s[:19], "%Y-%m-%dT%H:%M:%S") + (1 if s[19] == '-' else -1) * datetime.timedelta(hours=int(s[20:22]), minutes=int(s[23:25])) | |
163 else: | |
164 return datetime.datetime.strptime(s, "%Y-%m-%dT%H:%M:%SZ") | |
165 | |
166 return GithubObject.__makeTransformedAttribute(value, (str, unicode), parseDatetime) | |
167 | |
168 def _makeClassAttribute(self, klass, value): | |
169 return GithubObject.__makeTransformedAttribute(value, dict, lambda value: klass(self._requester, self._headers, value, completed=False)) | |
170 | |
171 @staticmethod | |
172 def _makeListOfStringsAttribute(value): | |
173 return GithubObject.__makeSimpleListAttribute(value, (str, unicode)) | |
174 | |
175 @staticmethod | |
176 def _makeListOfIntsAttribute(value): | |
177 return GithubObject.__makeSimpleListAttribute(value, int) | |
178 | |
179 @staticmethod | |
180 def _makeListOfListOfStringsAttribute(value): | |
181 return GithubObject.__makeSimpleListAttribute(value, list) | |
182 | |
183 def _makeListOfClassesAttribute(self, klass, value): | |
184 if isinstance(value, list) and all(isinstance(element, dict) for element in value): | |
185 return _ValuedAttribute([klass(self._requester, self._headers, element, completed=False) for element in value]) | |
186 else: | |
187 return _BadAttribute(value, [dict]) | |
188 | |
189 def _makeDictOfStringsToClassesAttribute(self, klass, value): | |
190 if isinstance(value, dict) and all(isinstance(key, (str, unicode)) and isinstance(element, dict) for key, element in value.iteritems()): | |
191 return _ValuedAttribute(dict((key, klass(self._requester, self._headers, element, completed=False)) for key, element in value.iteritems())) | |
192 else: | |
193 return _BadAttribute(value, {(str, unicode): dict}) | |
194 | |
195 @property | |
196 def etag(self): | |
197 ''' | |
198 :type: str | |
199 ''' | |
200 return self._headers.get(Consts.RES_ETAG) | |
201 | |
202 @property | |
203 def last_modified(self): | |
204 ''' | |
205 :type: str | |
206 ''' | |
207 return self._headers.get(Consts.RES_LAST_MODIFED) | |
208 | |
209 | |
210 class NonCompletableGithubObject(GithubObject): | |
211 def _completeIfNeeded(self): | |
212 pass | |
213 | |
214 | |
215 class CompletableGithubObject(GithubObject): | |
216 def __init__(self, requester, headers, attributes, completed): | |
217 GithubObject.__init__(self, requester, headers, attributes, completed) | |
218 self.__completed = completed | |
219 | |
220 def __eq__(self, other): | |
221 return other.__class__ is self.__class__ and other._url.value == self._url.value | |
222 | |
223 def __ne__(self, other): | |
224 return not self == other | |
225 | |
226 def _completeIfNotSet(self, value): | |
227 if value is NotSet: | |
228 self._completeIfNeeded() | |
229 | |
230 def _completeIfNeeded(self): | |
231 if not self.__completed: | |
232 self.__complete() | |
233 | |
234 def __complete(self): | |
235 headers, data = self._requester.requestJsonAndCheck( | |
236 "GET", | |
237 self._url.value | |
238 ) | |
239 self._storeAndUseAttributes(headers, data) | |
240 self.__completed = True | |
241 | |
242 def update(self): | |
243 ''' | |
244 Check and update the object with conditional request | |
245 :rtype: Boolean value indicating whether the object is changed | |
246 ''' | |
247 conditionalRequestHeader = dict() | |
248 if self.etag is not None: | |
249 conditionalRequestHeader[Consts.REQ_IF_NONE_MATCH] = self.etag | |
250 if self.last_modified is not None: | |
251 conditionalRequestHeader[Consts.REQ_IF_MODIFIED_SINCE] = self.last_modified | |
252 | |
253 status, responseHeaders, output = self._requester.requestJson( | |
254 "GET", | |
255 self._url.value, | |
256 headers=conditionalRequestHeader | |
257 ) | |
258 if status == 304: | |
259 return False | |
260 else: | |
261 headers, data = self._requester._Requester__check(status, responseHeaders, output) | |
262 self._storeAndUseAttributes(headers, data) | |
263 self.__completed = True | |
264 return True |