Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit7a1b0ee

Browse files
committed
Merge branch 'pr/219' into develop
2 parents710181f +bce2a7c commit7a1b0ee

File tree

15 files changed

+281
-69
lines changed

15 files changed

+281
-69
lines changed

‎docs/repos.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,13 @@ Repository
66
This part of the documentation covers:
77

88
-:class:`Repository <github3.repos.repo.Repository>`
9+
-:class:`Asset <github3.repos.release.Asset>`
910
-:class:`Branch <github3.repos.branch.Branch>`
1011
-:class:`Contents <github3.repos.contents.Contents>`
1112
-:class:`Deployment <github3.repos.deployment.Deployment>`
1213
-:class:`DeploymentStatus <github3.repos.deployment.DeploymentStatus>`
1314
-:class:`Hook <github3.repos.hook.Hook>`
15+
-:class:`Release <github3.repos.release.Release>`
1416
-:class:`RepoTag <github3.repos.tag.RepoTag>`
1517
-:class:`RepoComment <github3.repos.comment.RepoComment>`
1618
-:class:`RepoCommit <github3.repos.commit.RepoCommit>`
@@ -61,6 +63,10 @@ Repository Objects
6163
..autoclass::github3.repos.release.Release
6264
:members:
6365

66+
---------
67+
68+
..autoclass::github3.repos.release.Asset
69+
:members:
6470

6571
---------
6672

‎github3/repos/release.py

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
fromgithub3.decoratorsimportrequires_auth
66
fromgithub3.modelsimportGitHubCore,GitHubError
7+
fromgithub3.utilsimportstream_response_to_file
78
fromuritemplateimportURITemplate
89

910

@@ -144,6 +145,9 @@ def __init__(self, asset, session=None):
144145
self.created_at=self._strptime(asset.get('created_at'))
145146
#: Number of times the asset was downloaded
146147
self.download_count=asset.get('download_count')
148+
#: URL to download the asset.
149+
#: Request headers must include ``Accept: application/octet-stream``.
150+
self.download_url=self._api
147151
#: GitHub id of the asset
148152
self.id=asset.get('id')
149153
#: Short description of the asset
@@ -160,6 +164,36 @@ def __init__(self, asset, session=None):
160164
def_repr(self):
161165
return'<Asset [{0}]>'.format(self.name)
162166

167+
defdownload(self,path=''):
168+
"""Download the data for this asset.
169+
170+
:param path: (optional), path where the file should be saved
171+
to, default is the filename provided in the headers and will be
172+
written in the current directory.
173+
it can take a file-like object as well
174+
:type path: str, file
175+
:returns: bool -- True if successful, False otherwise
176+
"""
177+
headers= {
178+
'Accept':'application/octet-stream'
179+
}
180+
resp=self._get(self._api,allow_redirects=False,stream=True,
181+
headers=headers)
182+
ifresp.status_code==302:
183+
# Amazon S3 will reject the redirected request unless we omit
184+
# certain request headers
185+
headers.update({
186+
'Authorization':None,
187+
'Content-Type':None,
188+
})
189+
resp=self._get(resp.headers['location'],stream=True,
190+
headers=headers)
191+
192+
ifself._boolean(resp,200,404):
193+
stream_response_to_file(resp,path)
194+
returnTrue
195+
returnFalse
196+
163197
defedit(self,name,label=None):
164198
"""Edit this asset.
165199
@@ -173,7 +207,7 @@ def edit(self, name, label=None):
173207
self._remove_none(edit_data)
174208
r=self._patch(
175209
self._api,
176-
data=edit_data,
210+
data=json.dumps(edit_data),
177211
headers=Release.CUSTOM_HEADERS
178212
)
179213
successful=self._boolean(r,200,404)

‎github3/repos/repo.py

Lines changed: 4 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111

1212
fromjsonimportdumps
1313
frombase64importb64encode
14-
fromcollectionsimportCallable
1514
fromgithub3.decoratorsimportrequires_auth
1615
fromgithub3.eventsimportEvent
1716
fromgithub3.gitimportBlob,Commit,Reference,Tag,Tree
@@ -35,7 +34,7 @@
3534
fromgithub3.repos.releaseimportRelease,Asset
3635
fromgithub3.repos.tagimportRepoTag
3736
fromgithub3.usersimportUser,Key
38-
fromgithub3.utilsimporttimestamp_parameter
37+
fromgithub3.utilsimportstream_response_to_file,timestamp_parameter
3938
fromuritemplateimportURITemplate
4039

4140

@@ -323,33 +322,14 @@ def archive(self, format, path='', ref='master'):
323322
324323
"""
325324
resp=None
326-
written=False
327325
ifformatin ('tarball','zipball'):
328326
url=self._build_url(format,ref,base_url=self._api)
329327
resp=self._get(url,allow_redirects=True,stream=True)
330328

331-
pre_opened=False
332329
ifrespandself._boolean(resp,200,404):
333-
fd=None
334-
ifpath:
335-
ifisinstance(getattr(path,'write',None),Callable):
336-
pre_opened=True
337-
fd=path
338-
else:
339-
fd=open(path,'wb')
340-
else:
341-
header=resp.headers['content-disposition']
342-
i=header.find('filename=')+len('filename=')
343-
fd=open(header[i:],'wb')
344-
345-
forchunkinresp.iter_content(chunk_size=512):
346-
fd.write(chunk)
347-
348-
ifnotpre_opened:
349-
fd.close()
350-
351-
written=True
352-
returnwritten
330+
stream_response_to_file(resp,path)
331+
returnTrue
332+
returnFalse
353333

354334
defasset(self,id):
355335
"""Returns a single Asset.

‎github3/utils.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# -*- coding: utf-8 -*-
2+
fromcollectionsimportCallable
23
fromdatetimeimportdatetime
34
fromrequests.compatimportbasestring
45
importre
@@ -27,3 +28,24 @@ def timestamp_parameter(timestamp, allow_none=True):
2728
returntimestamp
2829

2930
raiseValueError("Cannot accept type %s for timestamp"%type(timestamp))
31+
32+
33+
defstream_response_to_file(response,path=None):
34+
pre_opened=False
35+
fd=None
36+
ifpath:
37+
ifisinstance(getattr(path,'write',None),Callable):
38+
pre_opened=True
39+
fd=path
40+
else:
41+
fd=open(path,'wb')
42+
else:
43+
header=response.headers['content-disposition']
44+
i=header.find('filename=')+len('filename=')
45+
fd=open(header[i:],'wb')
46+
47+
forchunkinresponse.iter_content(chunk_size=512):
48+
fd.write(chunk)
49+
50+
ifnotpre_opened:
51+
fd.close()

‎tests/cassettes/Asset_download.json

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.

‎tests/cassettes/Asset_edit.json

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.

‎tests/integration/test_repos_release.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
importgithub3
2+
importos
3+
importtempfile
24

35
from .helperimportIntegrationHelper
46

@@ -53,3 +55,40 @@ def test_upload_asset(self):
5355
)
5456
assertisinstance(asset,github3.repos.release.Asset)
5557
release.delete()
58+
59+
60+
classTestAsset(IntegrationHelper):
61+
deftest_download(self):
62+
"""Test the ability to download an asset."""
63+
cassette_name=self.cassette_name('download')
64+
withself.recorder.use_cassette(cassette_name,
65+
preserve_exact_body_bytes=True):
66+
repository=self.gh.repository('sigmavirus24','github3.py')
67+
release=repository.release(76677)
68+
asset=next(release.iter_assets())
69+
_,filename=tempfile.mkstemp()
70+
asset.download(filename)
71+
72+
withopen(filename)asfd:
73+
assertlen(fd.read(1024))>0
74+
75+
os.unlink(filename)
76+
77+
deftest_edit(self):
78+
"""Test the ability to edit an existing asset."""
79+
self.basic_login()
80+
cassette_name=self.cassette_name('edit')
81+
withself.recorder.use_cassette(cassette_name,
82+
preserve_exact_body_bytes=True):
83+
repository=self.gh.repository('github3py','github3.py')
84+
release=repository.create_release(
85+
'0.8.0.pre','develop','0.8.0 fake release with upload',
86+
'To be deleted'
87+
)
88+
withopen(__file__)asfd:
89+
asset=release.upload_asset(
90+
'text/plain','test_repos_release.py',fd.read()
91+
)
92+
assertisinstance(asset,github3.repos.release.Asset)
93+
assertasset.edit('A new name for this asset')isTrue
94+
release.delete()

‎tests/json/asset

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"url":"https://api.github.com/repos/sigmavirus24/github3.py/releases/assets/37945","id":37945,"name":"github3.py-0.7.1.tar.gz","label":"github3.py-0.7.1.tar.gz","uploader":{"login":"sigmavirus24","id":240830,"avatar_url":"https://avatars.githubusercontent.com/u/240830?","gravatar_id":"c148356d89f925e692178bee1d93acf7","url":"https://api.github.com/users/sigmavirus24","html_url":"https://github.com/sigmavirus24","followers_url":"https://api.github.com/users/sigmavirus24/followers","following_url":"https://api.github.com/users/sigmavirus24/following{/other_user}","gists_url":"https://api.github.com/users/sigmavirus24/gists{/gist_id}","starred_url":"https://api.github.com/users/sigmavirus24/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/sigmavirus24/subscriptions","organizations_url":"https://api.github.com/users/sigmavirus24/orgs","repos_url":"https://api.github.com/users/sigmavirus24/repos","events_url":"https://api.github.com/users/sigmavirus24/events{/privacy}","received_events_url":"https://api.github.com/users/sigmavirus24/received_events","type":"User","site_admin":false},"content_type":"application/x-gzip","state":"uploaded","size":85516,"download_count":2,"created_at":"2013-11-15T22:35:55Z","updated_at":"2013-11-15T22:35:59Z"}

‎tests/json/download

Lines changed: 0 additions & 1 deletion
This file was deleted.

‎tests/json/refresh_fixtures.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
'commit_activity',
1515
'contributor_statistics',
1616
'create_content',
17-
'download',
1817
'emails',
1918
'event',
2019
'language',

‎tests/json/release

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"url":"https://api.github.com/repos/sigmavirus24/github3.py/releases/76677","assets_url":"https://api.github.com/repos/sigmavirus24/github3.py/releases/76677/assets","upload_url":"https://uploads.github.com/repos/sigmavirus24/github3.py/releases/76677/assets{?name}","html_url":"https://github.com/sigmavirus24/github3.py/releases/tag/v0.7.1","id":76677,"tag_name":"v0.7.1","target_commitish":"develop","name":"","draft":false,"author":{"login":"sigmavirus24","id":240830,"avatar_url":"https://avatars.githubusercontent.com/u/240830?","gravatar_id":"c148356d89f925e692178bee1d93acf7","url":"https://api.github.com/users/sigmavirus24","html_url":"https://github.com/sigmavirus24","followers_url":"https://api.github.com/users/sigmavirus24/followers","following_url":"https://api.github.com/users/sigmavirus24/following{/other_user}","gists_url":"https://api.github.com/users/sigmavirus24/gists{/gist_id}","starred_url":"https://api.github.com/users/sigmavirus24/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/sigmavirus24/subscriptions","organizations_url":"https://api.github.com/users/sigmavirus24/orgs","repos_url":"https://api.github.com/users/sigmavirus24/repos","events_url":"https://api.github.com/users/sigmavirus24/events{/privacy}","received_events_url":"https://api.github.com/users/sigmavirus24/received_events","type":"User","site_admin":false},"prerelease":false,"created_at":"2013-10-01T00:05:04Z","published_at":"2013-10-26T02:25:22Z","assets":[{"url":"https://api.github.com/repos/sigmavirus24/github3.py/releases/assets/37944","id":37944,"name":"github3.py-0.7.1-py2.py3-none-any.whl","label":"github3.py-0.7.1-py2.py3-none-any.whl","uploader":{"login":"sigmavirus24","id":240830,"avatar_url":"https://avatars.githubusercontent.com/u/240830?","gravatar_id":"c148356d89f925e692178bee1d93acf7","url":"https://api.github.com/users/sigmavirus24","html_url":"https://github.com/sigmavirus24","followers_url":"https://api.github.com/users/sigmavirus24/followers","following_url":"https://api.github.com/users/sigmavirus24/following{/other_user}","gists_url":"https://api.github.com/users/sigmavirus24/gists{/gist_id}","starred_url":"https://api.github.com/users/sigmavirus24/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/sigmavirus24/subscriptions","organizations_url":"https://api.github.com/users/sigmavirus24/orgs","repos_url":"https://api.github.com/users/sigmavirus24/repos","events_url":"https://api.github.com/users/sigmavirus24/events{/privacy}","received_events_url":"https://api.github.com/users/sigmavirus24/received_events","type":"User","site_admin":false},"content_type":"application/octet-stream","state":"uploaded","size":117140,"download_count":1,"created_at":"2013-11-15T22:35:21Z","updated_at":"2013-11-15T22:35:59Z"},{"url":"https://api.github.com/repos/sigmavirus24/github3.py/releases/assets/37945","id":37945,"name":"github3.py-0.7.1.tar.gz","label":"github3.py-0.7.1.tar.gz","uploader":{"login":"sigmavirus24","id":240830,"avatar_url":"https://avatars.githubusercontent.com/u/240830?","gravatar_id":"c148356d89f925e692178bee1d93acf7","url":"https://api.github.com/users/sigmavirus24","html_url":"https://github.com/sigmavirus24","followers_url":"https://api.github.com/users/sigmavirus24/followers","following_url":"https://api.github.com/users/sigmavirus24/following{/other_user}","gists_url":"https://api.github.com/users/sigmavirus24/gists{/gist_id}","starred_url":"https://api.github.com/users/sigmavirus24/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/sigmavirus24/subscriptions","organizations_url":"https://api.github.com/users/sigmavirus24/orgs","repos_url":"https://api.github.com/users/sigmavirus24/repos","events_url":"https://api.github.com/users/sigmavirus24/events{/privacy}","received_events_url":"https://api.github.com/users/sigmavirus24/received_events","type":"User","site_admin":false},"content_type":"application/x-gzip","state":"uploaded","size":85516,"download_count":2,"created_at":"2013-11-15T22:35:55Z","updated_at":"2013-11-15T22:35:59Z"}],"tarball_url":"https://api.github.com/repos/sigmavirus24/github3.py/tarball/v0.7.1","zipball_url":"https://api.github.com/repos/sigmavirus24/github3.py/zipball/v0.7.1","body_html":"<ul>\n<li><p>Add dependency on <a href=\"https://github.com/sigmavirus24/uritemplate\">uritemplate.py</a> to add URITemplates to different classes.<br><br>\nSee the documentation for attributes which are templates.</p></li>\n<li><p>Fixed issue trying to parse <code>html_url</code> on Pull Requests courtesy of <br><a href=\"https://github.com/rogerhu\" class=\"user-mention\">@rogerhu</a>.</p></li>\n<li><p>Remove <code>expecter</code> as a test dependency courtesy of <a href=\"https://github.com/esacteksab\" class=\"user-mention\">@esacteksab</a>.</p></li>\n<li><p>Fixed issue <a href=\"https://github.com/sigmavirus24/github3.py/issues/141\" class=\"issue-link\" title=\"Handle ReleaseEvent\">#141</a> trying to find an Event that doesn't exist.</p></li>\n</ul>","body_text":"Add dependency on uritemplate.py to add URITemplates to different classes.\nSee the documentation for attributes which are templates.\nFixed issue trying to parse html_url on Pull Requests courtesy of @rogerhu.\nRemove expecter as a test dependency courtesy of @esacteksab.\nFixed issue #141 trying to find an Event that doesn't exist.","body":"- Add dependency on [uritemplate.py][_] to add URITemplates to different classes. \r\n See the documentation for attributes which are templates.\r\n\r\n- Fixed issue trying to parse ``html_url`` on Pull Requests courtesy of \r\n @rogerhu.\r\n\r\n- Remove ``expecter`` as a test dependency courtesy of @esacteksab.\r\n\r\n- Fixed issue #141 trying to find an Event that doesn't exist.\r\n\r\n[_]: https://github.com/sigmavirus24/uritemplate"}

‎tests/test_repos.py

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1400,3 +1400,82 @@ def test_patch(self):
14001400

14011401
assertself.comp.patch().startswith(b'archive_data')
14021402
self.mock_assertions()
1403+
1404+
1405+
classTestAsset(BaseCase):
1406+
def__init__(self,methodName='runTest'):
1407+
super(TestAsset,self).__init__(methodName)
1408+
self.asset=repos.release.Asset(load('asset'))
1409+
self.api= ("https://api.github.com/repos/sigmavirus24/github3.py/"
1410+
"releases/assets/37945")
1411+
1412+
deftest_repr(self):
1413+
assertrepr(self.asset)=='<Asset [github3.py-0.7.1.tar.gz]>'
1414+
1415+
deftest_download(self):
1416+
headers= {'content-disposition':'filename=foo'}
1417+
self.response('archive',200,**headers)
1418+
self.get(self.api)
1419+
self.conf.update({
1420+
'stream':True,
1421+
'allow_redirects':False,
1422+
'headers': {'Accept':'application/octet-stream'}
1423+
})
1424+
1425+
# 200, to default location
1426+
assertos.path.isfile('foo')isFalse
1427+
assertself.asset.download()
1428+
assertos.path.isfile('foo')
1429+
os.unlink('foo')
1430+
self.mock_assertions()
1431+
1432+
self.request.return_value.raw.seek(0)
1433+
self.request.return_value._content_consumed=False
1434+
1435+
# 200, to path
1436+
assertos.path.isfile('path_to_file')isFalse
1437+
assertself.asset.download('path_to_file')
1438+
assertos.path.isfile('path_to_file')
1439+
os.unlink('path_to_file')
1440+
self.mock_assertions()
1441+
1442+
self.request.return_value.raw.seek(0)
1443+
self.request.return_value._content_consumed=False
1444+
1445+
# 200, to file-like object
1446+
o=mock_open()
1447+
withpatch('{0}.open'.format(__name__),o,create=True):
1448+
withopen('download','wb+')asfd:
1449+
self.asset.download(fd)
1450+
o.assert_called_once_with('download','wb+')
1451+
fd=o()
1452+
fd.write.assert_called_once_with(b'archive_data')
1453+
self.mock_assertions()
1454+
1455+
self.request.return_value.raw.seek(0)
1456+
self.request.return_value._content_consumed=False
1457+
1458+
# 302, to file-like object
1459+
r=self.request.return_value
1460+
target='http://github.s3.example.com/foo'
1461+
self.response('',302,location=target)
1462+
self.get(target)
1463+
self.request.side_effect= [self.request.return_value,r]
1464+
self.conf['headers'].update({
1465+
'Authorization':None,
1466+
'Content-Type':None,
1467+
})
1468+
delself.conf['allow_redirects']
1469+
o=mock_open()
1470+
withpatch('{0}.open'.format(__name__),o,create=True):
1471+
withopen('download','wb+')asfd:
1472+
self.asset.download(fd)
1473+
o.assert_called_once_with('download','wb+')
1474+
fd=o()
1475+
fd.write.assert_called_once_with(b'archive_data')
1476+
self.mock_assertions()
1477+
1478+
# 404
1479+
self.response('',404)
1480+
self.request.side_effect=None
1481+
assertself.asset.download()isFalse

‎tests/test_utils.py

Lines changed: 0 additions & 40 deletions
This file was deleted.

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp