Skip to content

Commit 5aa47f1

Browse files
committed
Update github3.repos.contents for consistency
1 parent fca45b0 commit 5aa47f1

File tree

6 files changed

+154
-105
lines changed

6 files changed

+154
-105
lines changed

github3/pulls.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@
99
from . import models
1010
from . import users
1111
from .repos import commit as rcommit
12+
from .repos import contents
1213
from .decorators import requires_auth
1314
from .issues import Issue
1415
from .issues.comment import IssueComment
15-
from .repos.contents import Contents
1616

1717

1818
class PullDestination(models.GitHubCore):
@@ -170,10 +170,10 @@ def contents(self):
170170
:returns:
171171
An object representing the contents of this file
172172
:rtype:
173-
:class:`Contents <github3.repos.contents.Contents>`
173+
:class:`~github3.repos.contents.Contents`
174174
"""
175175
json = self._json(self._get(self.contents_url), 200)
176-
return self._instance_or_null(Contents, json)
176+
return self._instance_or_null(contents.Contents, json)
177177

178178

179179
class _PullRequest(models.GitHubCore):

github3/repos/contents.py

+118-90
Original file line numberDiff line numberDiff line change
@@ -1,95 +1,109 @@
11
# -*- coding: utf-8 -*-
2-
"""
3-
github3.repos.contents
4-
======================
5-
6-
This module contains the Contents object pertaining to READMEs and other files
7-
that can be accessed via the GitHub API.
8-
9-
"""
2+
"""This module contains the Contents object."""
103
from __future__ import unicode_literals
114

125
from base64 import b64decode, b64encode
136
from json import dumps
147

8+
from .. import models
9+
1510
from ..decorators import requires_auth
1611
from ..git import Commit
17-
from ..models import GitHubCore
1812

1913

20-
class Contents(GitHubCore):
21-
"""The :class:`Contents <Contents>` object. It holds the information
22-
concerning any content in a repository requested via the API.
14+
class Contents(models.GitHubCore):
15+
"""A representation of file contents returned via the API.
16+
17+
See also: http://developer.github.com/v3/repos/contents/
2318
24-
Two content instances can be checked like so::
19+
This object has the following attributes:
2520
26-
c1 == c2
27-
c1 != c2
21+
.. attribute:: content
2822
29-
And is equivalent to::
23+
The body of the file. If this is present, it may be base64 encoded.
3024
31-
c1.sha == c2.sha
32-
c1.sha != c2.sha
25+
.. attribute:: encoding
3326
34-
See also: http://developer.github.com/v3/repos/contents/
27+
The encoding used on the :attr:`content` when returning the data from
28+
the API, e.g., ``base64``. If :attr:`content` is not present this will
29+
not be present either.
30+
31+
.. attribute:: decoded
32+
33+
.. note:: This is a computed attribute which isn't returned by the API.
34+
.. versionchanged:: 0.5.2
35+
36+
Decoded content of the file as a bytes object. If we try to decode
37+
to character set for you, we might encounter an exception which
38+
will prevent the object from being created. On python2 this is the
39+
same as a string, but on python3 you should call the decode method
40+
with the character set you wish to use, e.g.,
41+
``content.decoded.decode('utf-8')``.
42+
43+
.. attribute:: git_url
44+
45+
The URL for the Git API pertaining to this file.
46+
47+
.. attribute:: html_url
48+
49+
The URL to open this file in a browser.
50+
51+
.. attribute:: links
52+
53+
A dictionary of links returned about the contents and related
54+
resources.
55+
56+
.. attribute:: name
57+
58+
The name of the file.
59+
60+
.. attribute:: path
61+
62+
The path to this file.
63+
64+
.. attribute:: sha
65+
66+
The SHA1 of the contents of this file.
67+
68+
.. attribute:: size
69+
70+
The size of file in bytes.
71+
72+
.. attribute:: submodule_git_url
73+
74+
The URL of the git submodule (if this is a git submodule).
75+
76+
.. attribute:: target
77+
78+
If the file is a symlink, this will be present and provides the type
79+
of file that the symlink points to.
80+
81+
.. attribute:: type
82+
83+
Type of content, e.g., ``'file'``, ``'symlink'``, or ``'submodule'``.
3584
"""
3685

3786
def _update_attributes(self, content):
38-
# links
39-
self._api = self._get_attribute(content, 'url')
40-
41-
#: Dictionary of links
42-
self.links = self._get_attribute(content, '_links')
43-
44-
#: URL of the README on github.com
45-
self.html_url = self._get_attribute(content, 'html_url')
46-
47-
#: URL for the git api pertaining to the README
48-
self.git_url = self._get_attribute(content, 'git_url')
49-
50-
#: git:// URL of the content if it is a submodule
51-
self.submodule_git_url = self._get_attribute(
52-
content, 'submodule_git_url'
53-
)
54-
55-
# should always be 'base64'
56-
#: Returns encoding used on the content.
57-
self.encoding = self._get_attribute(content, 'encoding')
58-
59-
# content, base64 encoded and decoded
60-
#: Base64-encoded content of the file.
61-
self.content = self._get_attribute(content, 'content')
62-
63-
#: Decoded content of the file as a bytes object. If we try to decode
64-
#: to character set for you, we might encounter an exception which
65-
#: will prevent the object from being created. On python2 this is the
66-
#: same as a string, but on python3 you should call the decode method
67-
#: with the character set you wish to use, e.g.,
68-
#: ``content.decoded.decode('utf-8')``.
69-
#: .. versionchanged:: 0.5.2
87+
self._api = content['url']
88+
self.content = content.get('content')
89+
self.encoding = content.get('encoding')
7090
self.decoded = self.content
7191
if self.encoding == 'base64' and self.content:
7292
self.decoded = b64decode(self.content.encode())
73-
74-
# file name, path, and size
75-
#: Name of the content.
76-
self.name = self._get_attribute(content, 'name')
77-
#: Path to the content.
78-
self.path = self._get_attribute(content, 'path')
79-
#: Size of the content
80-
self.size = self._get_attribute(content, 'size')
81-
#: SHA string.
82-
self.sha = self._get_attribute(content, 'sha')
83-
#: Type of content. ('file', 'symlink', 'submodule')
84-
self.type = self._get_attribute(content, 'type')
85-
#: Target will only be set of type is a symlink. This is what the link
86-
#: points to
87-
self.target = self._get_attribute(content, 'target')
88-
89-
self._uniq = self.sha
93+
self.download_url = content['download_url']
94+
self.git_url = content['git_url']
95+
self.html_url = content['html_url']
96+
self.links = content['_links']
97+
self.name = content['name']
98+
self.path = content['path']
99+
self._uniq = self.sha = content['sha']
100+
self.size = content['size']
101+
self.submodule_git_url = content.get('submodule_git_url')
102+
self.target = content.get('target')
103+
self.type = content['type']
90104

91105
def _repr(self):
92-
return '<Content [{0}]>'.format(self.path)
106+
return '<Contents [{0}]>'.format(self.path)
93107

94108
def __eq__(self, other):
95109
return self.decoded == other
@@ -101,17 +115,21 @@ def __ne__(self, other):
101115
def delete(self, message, branch=None, committer=None, author=None):
102116
"""Delete this file.
103117
104-
:param str message: (required), commit message to describe the removal
105-
:param str branch: (optional), branch where the file exists.
118+
:param str message:
119+
(required), commit message to describe the removal
120+
:param str branch:
121+
(optional), branch where the file exists.
106122
Defaults to the default branch of the repository.
107-
:param dict committer: (optional), if no information is given the
108-
authenticated user's information will be used. You must specify
109-
both a name and email.
110-
:param dict author: (optional), if omitted this will be filled in with
111-
committer information. If passed, you must specify both a name and
112-
email.
113-
:returns: dictionary of new content and associated commit
114-
:rtype: :class:`~github3.repos.contents.Contents` and
123+
:param dict committer:
124+
(optional), if no information is given the authenticated user's
125+
information will be used. You must specify both a name and email.
126+
:param dict author:
127+
(optional), if omitted this will be filled in with committer
128+
information. If passed, you must specify both a name and email.
129+
:returns:
130+
dictionary of new content and associated commit
131+
:rtype:
132+
:class:`~github3.repos.contents.Contents` and
115133
:class:`~github3.git.Commit`
116134
"""
117135
json = {}
@@ -133,19 +151,24 @@ def update(self, message, content, branch=None, committer=None,
133151
author=None):
134152
"""Update this file.
135153
136-
:param str message: (required), commit message to describe the update
137-
:param str content: (required), content to update the file with
138-
:param str branch: (optional), branch where the file exists.
154+
:param str message:
155+
(required), commit message to describe the update
156+
:param str content:
157+
(required), content to update the file with
158+
:param str branch:
159+
(optional), branch where the file exists.
139160
Defaults to the default branch of the repository.
140-
:param dict committer: (optional), if no information is given the
141-
authenticated user's information will be used. You must specify
142-
both a name and email.
143-
:param dict author: (optional), if omitted this will be filled in with
144-
committer information. If passed, you must specify both a name and
145-
email.
146-
:returns: dictionary containing the updated contents object and the
161+
:param dict committer:
162+
(optional), if no information is given the authenticated user's
163+
information will be used. You must specify both a name and email.
164+
:param dict author:
165+
(optional), if omitted this will be filled in with committer
166+
information. If passed, you must specify both a name and email.
167+
:returns:
168+
dictionary containing the updated contents object and the
147169
commit in which it was changed.
148-
:rtype: dictionary of :class:`~github3.repos.contents.Contents` and
170+
:rtype:
171+
dictionary of :class:`~github3.repos.contents.Contents` and
149172
:class:`~github3.git.Commit`
150173
"""
151174
if content and not isinstance(content, bytes):
@@ -170,6 +193,11 @@ def update(self, message, content, branch=None, committer=None,
170193

171194

172195
def validate_commmitter(d):
196+
"""Validate that there are enough details in the dictionary.
197+
198+
When sending data to GitHub, we need to ensure we're sending the name and
199+
email for committer and author data.
200+
"""
173201
if d and d.get('name') and d.get('email'):
174202
return d
175203
return None

github3/repos/repo.py

+11-8
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,9 @@
2929
from ..utils import stream_response_to_file, timestamp_parameter
3030
from . import branch
3131
from . import commit
32+
from . import contents
3233
from .comment import RepoComment
3334
from .comparison import Comparison
34-
from .contents import Contents, validate_commmitter
3535
from .deployment import Deployment
3636
from .hook import Hook
3737
from .issue_import import ImportedIssue
@@ -530,7 +530,7 @@ def create_file(self, path, message, content, branch=None,
530530
committer information. If passed, you must specify both a name and
531531
email.
532532
:returns: {
533-
'content': :class:`Contents <github3.repos.contents.Contents>`:,
533+
'content': :class:`~github3.repos.contents.Contents`,
534534
'commit': :class:`Commit <github3.git.Commit>`}
535535
536536
"""
@@ -543,12 +543,14 @@ def create_file(self, path, message, content, branch=None,
543543
url = self._build_url('contents', path, base_url=self._api)
544544
content = b64encode(content).decode('utf-8')
545545
data = {'message': message, 'content': content, 'branch': branch,
546-
'committer': validate_commmitter(committer),
547-
'author': validate_commmitter(author)}
546+
'committer': contents.validate_commmitter(committer),
547+
'author': contents.validate_commmitter(author)}
548548
self._remove_none(data)
549549
json = self._json(self._put(url, data=dumps(data)), 201)
550550
if json and 'content' in json and 'commit' in json:
551-
json['content'] = Contents(json['content'], self)
551+
json['content'] = contents.Contents(
552+
json['content'], self
553+
)
552554
json['commit'] = Commit(json['commit'], self)
553555
return json
554556

@@ -952,7 +954,8 @@ def directory_contents(self, directory_path, ref=None, return_as=list):
952954
"""
953955
url = self._build_url('contents', directory_path, base_url=self._api)
954956
json = self._json(self._get(url, params={'ref': ref}), 200) or []
955-
return return_as((j.get('name'), Contents(j, self)) for j in json)
957+
return return_as((j.get('name'), contents.Contents(j, self))
958+
for j in json)
956959

957960
@requires_auth
958961
def edit(self, name, description=None, homepage=None, private=None,
@@ -1022,7 +1025,7 @@ def file_contents(self, path, ref=None):
10221025
"""
10231026
url = self._build_url('contents', path, base_url=self._api)
10241027
json = self._json(self._get(url, params={'ref': ref}), 200)
1025-
return self._instance_or_null(Contents, json)
1028+
return self._instance_or_null(contents.Contents, json)
10261029

10271030
def forks(self, sort='', number=-1, etag=None):
10281031
"""Iterate over forks of this repository.
@@ -1590,7 +1593,7 @@ def readme(self):
15901593
"""
15911594
url = self._build_url('readme', base_url=self._api)
15921595
json = self._json(self._get(url), 200)
1593-
return self._instance_or_null(Contents, json)
1596+
return self._instance_or_null(contents.Contents, json)
15941597

15951598
def ref(self, ref):
15961599
"""Get a reference pointed to by ``ref``.

tests/cassettes/PullFile_contents.json

+1-1
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)