Skip to content

Commit c49af2c

Browse files
committed
Merge 'develop' into consistency-is-a-hobgoblin
2 parents 9981ea4 + 17d0fb9 commit c49af2c

25 files changed

+106
-60
lines changed

github3/events.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -154,15 +154,15 @@ def _update_attributes(self, event):
154154
event = copy.deepcopy(event)
155155

156156
#: :class:`User <github3.users.User>` object representing the actor.
157-
self.actor = self._class_attribute(event, 'actor', EventUser)
157+
self.actor = self._class_attribute(event, 'actor', EventUser, self)
158158
#: datetime object representing when the event was created.
159159
self.created_at = self._strptime_attribute(event, 'created_at')
160160

161161
#: Unique id of the event
162162
self.id = self._get_attribute(event, 'id')
163163

164164
#: List all possible types of Events
165-
self.org = self._class_attribute(event, 'org', EventOrganization)
165+
self.org = self._class_attribute(event, 'org', EventOrganization, self)
166166

167167
#: Event type https://developer.github.com/v3/activity/events/types/
168168
self.type = self._get_attribute(event, 'type')

github3/gists/gist.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,7 @@ class GistFork(GitHubCore):
314314
def _update_attributes(self, fork):
315315
self.created_at = self._strptime(fork['created_at'])
316316
self.id = fork['id']
317-
self.owner = users.ShortUser(fork['user'])
317+
self.owner = users.ShortUser(fork['user'], self)
318318
self.updated_at = self._strptime(fork['updated_at'])
319319
self.url = self._api = fork['url']
320320

github3/git.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ def _update_attributes(self, ref):
108108
self.ref = self._get_attribute(ref, 'ref')
109109

110110
#: :class:`GitObject <GitObject>` the reference points to
111-
self.object = self._class_attribute(ref, 'object', GitObject)
111+
self.object = self._class_attribute(ref, 'object', GitObject, self)
112112

113113
def _repr(self):
114114
return '<Reference [{0}]>'.format(self.ref)
@@ -173,7 +173,7 @@ def _update_attributes(self, tag):
173173
self.tagger = self._get_attribute(tag, 'tagger')
174174

175175
#: :class:`GitObject <GitObject>` for the tag
176-
self.object = self._class_attribute(tag, 'object', GitObject)
176+
self.object = self._class_attribute(tag, 'object', GitObject, self)
177177

178178
def _repr(self):
179179
return '<Tag [{0}]>'.format(self.tag)
@@ -193,7 +193,7 @@ def _update_attributes(self, tree):
193193
#: list of :class:`Hash <Hash>` objects
194194
self.tree = self._get_attribute(tree, 'tree', [])
195195
if self.tree:
196-
self.tree = [Hash(t) for t in self.tree]
196+
self.tree = [Hash(t, self) for t in self.tree]
197197

198198
def _repr(self):
199199
return '<Tree [{0}]>'.format(self.sha)

github3/github.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ class GitHub(GitHubCore):
5858
"""
5959

6060
def __init__(self, username='', password='', token=''):
61-
super(GitHub, self).__init__({})
61+
super(GitHub, self).__init__({}, self.new_session())
6262
if token:
6363
self.login(username, token=token)
6464
elif username and password:
@@ -81,7 +81,7 @@ def add_email_addresses(self, addresses=[]):
8181
if addresses:
8282
url = self._build_url('user', 'emails')
8383
json = self._json(self._post(url, data=addresses), 201)
84-
return [users.Email(email) for email in json] if json else []
84+
return [users.Email(email, self) for email in json] if json else []
8585

8686
def all_events(self, number=-1, etag=None):
8787
"""Iterate over public events.
@@ -1818,7 +1818,7 @@ class GitHubStatus(GitHubCore):
18181818
return the JSON objects returned by the API.
18191819
"""
18201820
def __init__(self):
1821-
super(GitHubStatus, self).__init__({})
1821+
super(GitHubStatus, self).__init__({}, self.new_session())
18221822
self.session.base_url = 'https://status.github.com'
18231823

18241824
def _repr(self):

github3/issues/issue.py

+6-5
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,11 @@ def _update_attributes(self, issue):
3434
#: was assigned to.
3535
self.assignee = issue['assignee']
3636
if self.assignee:
37-
self.assignee = users.ShortUser(self.assignee)
37+
self.assignee = users.ShortUser(self.assignee, self)
3838
self.assignees = issue['assignees']
3939
if self.assignees:
4040
self.assignees = [
41-
users.ShortUser(assignee) for assignee in self.assignees
41+
users.ShortUser(assignee, self) for assignee in self.assignees
4242
]
4343

4444
#: Body (description) of the issue.
@@ -107,7 +107,7 @@ def _update_attributes(self, issue):
107107
self.updated_at = self._strptime_attribute(issue, 'updated_at')
108108

109109
#: :class:`User <github3.users.User>` who opened the issue.
110-
self.user = users.ShortUser(issue['user'])
110+
self.user = users.ShortUser(issue['user'], self)
111111

112112
def _repr(self):
113113
return '<Issue [{r[0]}/{r[1]} #{n}]>'.format(r=self.repository,
@@ -147,7 +147,8 @@ def close(self):
147147
"""
148148
assignee = self.assignee.login if self.assignee else ''
149149
number = self.milestone.number if self.milestone else None
150-
labels = [str(l) for l in self.original_labels]
150+
labels = [l.name for l in self.original_labels]
151+
151152
return self.edit(self.title, self.body, assignee, 'closed',
152153
number, labels)
153154

@@ -389,4 +390,4 @@ def _update_attributes(self, issue):
389390
#: :class:`User <github3.users.User>` who closed the issue.
390391
self.closed_by = issue['closed_by']
391392
if self.closed_by:
392-
self.closed_by = users.ShortUser(self.closed_by)
393+
self.closed_by = users.ShortUser(self.closed_by, self)

github3/models.py

+11-8
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,12 @@ class GitHubCore(object):
3131
basic attributes and methods to other sub-classes that are very useful to
3232
have.
3333
"""
34+
_ratelimit_resource = 'core'
3435

35-
def __init__(self, json, session=None):
36+
def __init__(self, json, session):
3637
if hasattr(session, 'session'):
3738
# i.e. session is actually a GitHubCore instance
3839
session = session.session
39-
elif session is None:
40-
session = GitHubSession()
4140
self.session = session
4241

4342
# set a sane default
@@ -165,14 +164,14 @@ def __repr__(self):
165164
return repr_string
166165

167166
@classmethod
168-
def from_dict(cls, json_dict):
167+
def from_dict(cls, json_dict, session):
169168
"""Return an instance of this class formed from ``json_dict``."""
170-
return cls(json_dict)
169+
return cls(json_dict, session)
171170

172171
@classmethod
173-
def from_json(cls, json):
172+
def from_json(cls, json, session):
174173
"""Return an instance of this class formed from ``json``."""
175-
return cls(loads(json))
174+
return cls(loads(json), session)
176175

177176
def __eq__(self, other):
178177
return self._uniq == other._uniq
@@ -305,7 +304,7 @@ def ratelimit_remaining(self):
305304
:returns: int
306305
"""
307306
json = self._json(self._get(self._github_url + '/rate_limit'), 200)
308-
core = json.get('resources', {}).get('core', {})
307+
core = json.get('resources', {}).get(self._ratelimit_resource, {})
309308
self._remaining = core.get('remaining', 0)
310309
return self._remaining
311310

@@ -348,6 +347,10 @@ def refresh(self, conditional=False):
348347
self._update_attributes(json)
349348
return self
350349

350+
def new_session(self):
351+
"""Helper function to generate a new session"""
352+
return GitHubSession()
353+
351354

352355
class BaseComment(GitHubCore):
353356

github3/pulls.py

+1-7
Original file line numberDiff line numberDiff line change
@@ -62,15 +62,11 @@ class PullDestination(models.GitHubCore):
6262

6363
def _update_attributes(self, dest):
6464
from .repos.repo import ShortRepository
65-
#: Full reference string of the object
6665
self.ref = dest['ref']
67-
#: label of the destination
6866
self.label = dest['label']
69-
#: :class:`User <github3.users.User>` representing the owner
7067
self.user = dest.get('user')
7168
if self.user:
7269
self.user = users.ShortUser(self.user, self)
73-
#: SHA of the commit at the head
7470
self.sha = dest['sha']
7571
self._repo_name = ''
7672
self._repo_owner = ''
@@ -215,16 +211,14 @@ def _update_attributes(self, pull):
215211
self.patch_url = pull['patch_url']
216212
self.review_comment_urlt = URITemplate(pull['review_comment_url'])
217213
self.review_comments_url = pull['review_comments_url']
218-
219214
self.repository = None
220215
if self.base:
221216
self.repository = self.base.repository
222-
223217
self.state = pull['state']
224218
self.statuses_url = pull['statuses_url']
225219
self.title = pull['title']
226220
self.updated_at = self._strptime(pull['updated_at'])
227-
self.user = users.ShortUser(pull['user'])
221+
self.user = users.ShortUser(pull['user'], self)
228222

229223
def _repr(self):
230224
return '<Pull Request [#{0}]>'.format(self.number)

github3/repos/comparison.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ def _update_attributes(self, compare):
6969
#: objects.
7070
self.commits = self._get_attribute(compare, 'commits', [])
7171
if self.commits:
72-
self.commits = [RepoCommit(com) for com in self.commits]
72+
self.commits = [RepoCommit(com, self) for com in self.commits]
7373

7474
#: List of dicts describing the files modified.
7575
self.files = self._get_attribute(compare, 'files', [])

github3/repos/pages.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@ def _update_attributes(self, build):
3737
from .. import users
3838
#: :class:`User <github3.users.User>` representing who pushed the
3939
#: commit
40-
self.pusher = self._class_attribute(build, 'pusher', users.ShortUser)
40+
self.pusher = self._class_attribute(build, 'pusher', users.ShortUser,
41+
self)
4142

4243
#: SHA of the commit that triggered the build
4344
self.commit = self._get_attribute(build, 'commit')

github3/repos/release.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ def _update_attributes(self, release):
6565

6666
#: :class:`User <github3.users.ShortUser>` object representing the
6767
#: creator of the release
68-
self.author = users.ShortUser(release['author'])
68+
self.author = users.ShortUser(release['author'], self)
6969

7070
#: URLs to various attributes
7171
for urltype in ['assets_url', 'html_url', 'tarball_url',

github3/repos/status.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ def _update_attributes(self, status):
3131

3232
#: :class:`User <github3.users.User>` who created the object
3333
self.creator = self._class_attribute(
34-
status, 'creator', users.ShortUser
34+
status, 'creator', users.ShortUser, self
3535
)
3636

3737
#: Short description of the Status
@@ -74,7 +74,7 @@ def _update_attributes(self, combined_status):
7474
#: List of :class:`Status <github3.repos.status.Status>`
7575
#: objects.
7676
statuses = self._get_attribute(combined_status, 'statuses', [])
77-
self.statuses = [Status(s) for s in statuses]
77+
self.statuses = [Status(s, self) for s in statuses]
7878

7979
from . import repo
8080
#: Repository the combined status belongs too.

github3/structs.py

+1
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ class SearchIterator(GitHubIterator):
129129
class. For other members and methods, check its parent class.
130130
131131
"""
132+
_ratelimit_resource = 'search'
132133

133134
def __init__(self, count, url, cls, session, params=None, etag=None,
134135
headers=None):

github3/users.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -753,4 +753,4 @@ def _update_attributes(self, user):
753753
self.disk_usage = user['disk_usage']
754754
self.owned_private_repos_count = user['owned_private_repos']
755755
self.total_private_repos_count = user['total_private_repos']
756-
self.plan = Plan(user['plan'])
756+
self.plan = Plan(user['plan'], self)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"recorded_with": "betamax/0.8.0", "http_interactions": [{"response": {"body": {"base64_string": "H4sIAAAAAAAAA6tWKkotzi8tSk4tVrKqVkrOL0oF0TmZuZklSlZmBjpA+dzEzLzMvHQYtzgVKGNoamhmaWlibGhcq6NUnJpYlJyBpM8QVR+Ei6TPwNwcpC+9KLEgozAHSSOqPjAP3TqgvqLEEpJdWQsAyulOc+oAAAA=", "encoding": "utf-8", "string": ""}, "url": "https://api.github.com/rate_limit", "headers": {"Cache-Control": "no-cache", "Access-Control-Expose-Headers": "ETag, Link, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval", "Access-Control-Allow-Origin": "*", "Content-Security-Policy": "default-src 'none'", "X-GitHub-Media-Type": "github.v3; param=full; format=json", "Content-Encoding": "gzip", "X-Content-Type-Options": "nosniff", "X-RateLimit-Limit": "60", "X-RateLimit-Reset": "1516994313", "Content-Type": "application/json; charset=utf-8", "X-XSS-Protection": "1; mode=block", "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", "Date": "Fri, 26 Jan 2018 18:18:33 GMT", "X-Runtime-rack": "0.008218", "Transfer-Encoding": "chunked", "X-GitHub-Request-Id": "D196:12414:2B7A313:507FFAA:5A6B70F9", "Status": "200 OK", "Server": "GitHub.com", "X-Frame-Options": "deny", "X-RateLimit-Remaining": "60"}, "status": {"message": "OK", "code": 200}}, "recorded_at": "2018-01-26T18:18:33", "request": {"body": {"encoding": "utf-8", "string": ""}, "method": "GET", "uri": "https://api.github.com/rate_limit", "headers": {"Connection": "keep-alive", "Content-Type": "application/json", "User-Agent": "github3.py/1.0.0a4", "Accept-Charset": "utf-8", "Accept-Encoding": "gzip, deflate", "Accept": "application/vnd.github.v3.full+json"}}}, {"response": {"body": {"base64_string": "H4sIAAAAAAAAA6tWKkotzi8tSk4tVrKqVkrOL0oF0TmZuZklSlZmBjpA+dzEzLzMvHQYtzgVKGNoamhmaWlibGhcq6NUnJpYlJyBpM8QVR+Ei6TPwNwcpC+9KLEgozAHSSOqPjAP3TqgvqLEEpJdWQsAyulOc+oAAAA=", "encoding": "utf-8", "string": ""}, "url": "https://api.github.com/rate_limit", "headers": {"Cache-Control": "no-cache", "Access-Control-Expose-Headers": "ETag, Link, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval", "Access-Control-Allow-Origin": "*", "Content-Security-Policy": "default-src 'none'", "X-GitHub-Media-Type": "github.v3; param=full; format=json", "Content-Encoding": "gzip", "X-Content-Type-Options": "nosniff", "X-RateLimit-Limit": "60", "X-RateLimit-Reset": "1516994313", "Content-Type": "application/json; charset=utf-8", "X-XSS-Protection": "1; mode=block", "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", "Date": "Fri, 26 Jan 2018 18:18:33 GMT", "X-Runtime-rack": "0.010151", "Transfer-Encoding": "chunked", "X-GitHub-Request-Id": "D196:12414:2B7A31F:507FFBB:5A6B70F9", "Status": "200 OK", "Server": "GitHub.com", "X-Frame-Options": "deny", "X-RateLimit-Remaining": "60"}, "status": {"message": "OK", "code": 200}}, "recorded_at": "2018-01-26T18:18:33", "request": {"body": {"encoding": "utf-8", "string": ""}, "method": "GET", "uri": "https://api.github.com/rate_limit", "headers": {"Connection": "keep-alive", "Content-Type": "application/json", "User-Agent": "github3.py/1.0.0a4", "Accept-Charset": "utf-8", "Accept-Encoding": "gzip, deflate", "Accept": "application/vnd.github.v3.full+json"}}}]}

tests/integration/test_github_core.py

+28
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,31 @@ def test_ratelimit_remaining(self):
66
cassette_name = self.cassette_name('ratelimit_remaining')
77
with self.recorder.use_cassette(cassette_name):
88
assert self.gh.ratelimit_remaining > 0
9+
10+
def test_ratelimit_remaining_search(self):
11+
"""Test if search iterators return search ratelimit"""
12+
13+
def _get_ratelimit(resource):
14+
resources = self.gh.rate_limit().get('resources', {})
15+
rate_limit = resources.get(resource, {})
16+
return rate_limit.get('remaining', -1)
17+
18+
cassette_name = self.cassette_name('ratelimit_remaining_search')
19+
20+
# Run cassette to get correct remaining rate limit from responses.
21+
with self.recorder.use_cassette(cassette_name):
22+
correct_ratelimit_search = _get_ratelimit('search')
23+
correct_ratelimit_core = _get_ratelimit('core')
24+
25+
# Re-run cassette to test functions under test.
26+
with self.recorder.use_cassette(cassette_name):
27+
result_iterator = self.gh.search_code(
28+
'HTTPAdapter in:file language:python'
29+
' repo:kennethreitz/requests'
30+
)
31+
ratelimit_remaining_search = result_iterator.ratelimit_remaining
32+
ratelimit_remaining_core = self.gh.ratelimit_remaining
33+
34+
assert ratelimit_remaining_search != ratelimit_remaining_core
35+
assert ratelimit_remaining_core == correct_ratelimit_core
36+
assert ratelimit_remaining_search == correct_ratelimit_search

tests/unit/helper.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,8 @@ def create_instance_of_described_class(self):
8585
instance = self.described_class(self.example_data,
8686
self.session)
8787
elif self.example_data and not self.session:
88-
instance = self.described_class(self.example_data)
88+
session = self.create_session_mock()
89+
instance = self.described_class(self.example_data, session)
8990

9091
else:
9192
instance = self.described_class()

tests/unit/test_events.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ def test_org(self):
4040
json = self.instance.as_dict().copy()
4141
org = get_org_example_data()
4242
json['org'] = org
43-
event = github3.events.Event(json)
43+
event = github3.events.Event(json, self.session)
4444
assert isinstance(event.org, github3.events.EventOrganization)
4545

4646

tests/unit/test_gists.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,8 @@ class TestGistHistory(helper.UnitHelper):
200200
def test_equality(self):
201201
"""Show that two instances of a GistHistory are equal."""
202202
history = github3.gists.history.GistHistory(
203-
gist_history_example_data()
203+
gist_history_example_data(),
204+
self.session
204205
)
205206
assert self.instance == history
206207
history._uniq = 'foo'
@@ -222,7 +223,8 @@ class TestGistComment(helper.UnitHelper):
222223
def test_equality(self):
223224
"""Show that two instances of a GistComment are equal."""
224225
comment = github3.gists.comment.GistComment(
225-
gist_comment_example_data()
226+
gist_comment_example_data(),
227+
self.session
226228
)
227229
assert self.instance == comment
228230
comment._uniq = '1'

tests/unit/test_git.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,12 @@ class TestTree(UnitHelper):
2323

2424
def test_eq(self):
2525
"""Assert that two trees are equal."""
26-
tree = github3.git.Tree(get_example_data())
26+
tree = github3.git.Tree(get_example_data(), self.session)
2727
assert self.instance == tree
2828

2929
def test_ne(self):
3030
"""Assert that two trees are not equal."""
31-
tree = github3.git.Tree(get_example_data())
31+
tree = github3.git.Tree(get_example_data(), self.session)
3232
tree._json_data['truncated'] = True
3333
assert self.instance != tree
3434

0 commit comments

Comments
 (0)