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."""
103from __future__import unicode_literals
114
125from base64 import b64decode ,b64encode
136from json import dumps
147
8+ from ..import models
9+
1510from ..decorators import requires_auth
1611from ..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 isequivalent to::
23+ The body of the file. If this ispresent, 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
3786def _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' )
7090self .decoded = self .content
7191if self .encoding == 'base64' and self .content :
7292self .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
91105def _repr (self ):
92- return '<Content [{0}]>' .format (self .path )
106+ return '<Contents [{0}]>' .format (self .path )
93107
94108def __eq__ (self ,other ):
95109return self .decoded == other
@@ -101,17 +115,21 @@ def __ne__(self, other):
101115def 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 """
117135json = {}
@@ -133,19 +151,24 @@ def update(self, message, content, branch=None, committer=None,
133151author = 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 """
151174if content and not isinstance (content ,bytes ):
@@ -170,6 +193,11 @@ def update(self, message, content, branch=None, committer=None,
170193
171194
172195def 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+ """
173201if d and d .get ('name' )and d .get ('email' ):
174202return d
175203return None