Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ability to access github Release Asset API. #525

Merged
merged 10 commits into from
Nov 27, 2017

Conversation

if "Content-Type" in headers:
mime_type = headers["Content-Type"]
else:
import mimetypes
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not import globally?

"application/zip")



Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cleanup unused blanklines to avoid introduce new PEP8 failures.

@ankona
Copy link
Author

ankona commented Feb 21, 2017

@nhomar I had 3 places where I'd imported locally (with no good reason). I moved all of them and removed the extra whitespace as well.

@kujenga
Copy link

kujenga commented Mar 14, 2017

@nhomar Is there anything else left on this PR? I'd like to use this functionality for a project I'm working on. Happy to help out if necessary/possible.

Thanks for the great work @THEHighlander!

Copy link
Author

@ankona ankona left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

modified per review notes

@NicoHood
Copy link

NicoHood commented Apr 2, 2017

Am I wrong or are the releases themselves also missing for this module?

I try to search for an existing release using the tag id:
https://api.github.com/repos/username/project/releases/tags/1.0.0

And then I want to upload release assets to this release or create it if it does not exist yet. But the docs have no result for "release", so is there any doc about this yet?

@ankona
Copy link
Author

ankona commented Apr 11, 2017

@nhomar is there anything else you'd like me to do here?

@petelopez
Copy link

@nhomar Can we get this PR accepted?

@petelopez
Copy link

@NicoHood Releases are present in some form but it's not documented or at least wasn't as of a couple of months ago. This PR includes additional functionality around the release API as it pertains to assets.

This file has been around forever but I agree, it wasn't in the docs: https://github.com/PyGithub/PyGithub/blob/master/github/GitRelease.py

@NicoHood NicoHood mentioned this pull request Apr 25, 2017
15 tasks
@NicoHood
Copy link

Maybe this project can help for now:
https://github.com/seletz/ghrelease

@NicoHood
Copy link

@THEHighlander I have problems uploading release assets. Listing works fine, uploading does not.

This is my code (excerpt):

       # Note for github issue: yes, i am verifying the release exists.
       self.release = self.githubrepo.get_release(self.config['tag'])

        # Upload assets
        for asset in self.newassets:
            assetpath = os.path.join(self.config['output'], asset)
            print(':: Uploading', assetpath)
            self.release.upload_asset(assetpath, "Testlabel", "application/x-xz")

The error:

:: Uploading /home/arch/hackallthethings/attiny/archive/attiny-1.2.27.tar.xz
Traceback (most recent call last):
  File "../gpgit/gpgit.py", line 841, in <module>
    sys.exit(main(sys.argv[1:]))
  File "../gpgit/gpgit.py", line 833, in main
    if not gpgit.run():
  File "../gpgit/gpgit.py", line 791, in run
    if step.run():
  File "../gpgit/gpgit.py", line 110, in run
    if substep.run():
  File "../gpgit/gpgit.py", line 87, in run
    return self.funct()
  File "../gpgit/gpgit.py", line 772, in step_5_1
    self.release.upload_asset(assetpath, "unit test artifact", "application/x-xz")
  File "/usr/lib/python3.6/site-packages/github/GitRelease.py", line 145, in upload_asset
    input=path
  File "/usr/lib/python3.6/site-packages/github/Requester.py", line 243, in requestBlob
    status, responseHeaders, output = self.__requestEncode(None, verb, url, parameters, headers, input, encode)
  File "/usr/lib/python3.6/site-packages/github/Requester.py", line 268, in __requestEncode
    status, responseHeaders, output = self.__requestRaw(cnx, verb, url, requestHeaders, encoded_input)
  File "/usr/lib/python3.6/site-packages/github/Requester.py", line 293, in __requestRaw
    requestHeaders
  File "/usr/lib/python3.6/http/client.py", line 1239, in request
    self._send_request(method, url, body, headers, encode_chunked)
  File "/usr/lib/python3.6/http/client.py", line 1285, in _send_request
    self.endheaders(body, encode_chunked=encode_chunked)
  File "/usr/lib/python3.6/http/client.py", line 1234, in endheaders
    self._send_output(message_body, encode_chunked=encode_chunked)
  File "/usr/lib/python3.6/http/client.py", line 1055, in _send_output
    for chunk in chunks:
  File "/usr/lib/python3.6/http/client.py", line 1010, in _read_readable
    datablock = readable.read(blocksize)
  File "/usr/lib/python3.6/codecs.py", line 321, in decode
    (result, consumed) = self._buffer_decode(data, self.errors, final)
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xfd in position 0: invalid start byte

@ankona
Copy link
Author

ankona commented May 12, 2017

@NicoHood I'll dig into it after work

@NicoHood
Copy link

@THEHighlander thanks! Any progress so far? I have no idea what causes this issue.

You can find the full sourcecode of my project here:
https://github.com/NicoHood/gpgit/tree/python

@ankona
Copy link
Author

ankona commented May 15, 2017

@NicoHood So far, I'm unable to reproduce your defect.

image

I made the mistake of first rebasing my local branch off of master and that did introduce a defect (the underlying request code kills off the correct host name for uploads). I'm going to stash these changes and try again with the code as it was during the PR.

Edit: I just realized you're using python 3.6 and I'm running locally using 2.7. I'll try that, too.

@NicoHood
Copy link

@THEHighlander Thanks for testing! I have merged your changes into master and created a new tag:
https://github.com/NicoHood/PyGithub/releases/tag/v1.34.1

Yes I am using python3 and that is possibly the reason why it crashes (UFT8 changes were made in python3)

@ankona
Copy link
Author

ankona commented May 16, 2017

@NicoHood I've found and fixed the encoding issue in python3. there were two issues:

  1. the response from http.client is a byte array
  2. opening/uploading the file as plain text
    i've run out of time for today, but i'll have the fix committed tomorrow.

@NicoHood
Copy link

@THEHighlander thanks for taking the time. The test now fails:


======================================================================
ERROR: testGetAsset (github.tests.GitRelease.Release)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/build/python-pygithub/src/PyGithub-1.34.2/build/lib/github/tests/GitRelease.py", line 97, in testGetAsset
    the_asset = the_repo.get_release_asset(asset_id)
  File "/build/python-pygithub/src/PyGithub-1.34.2/build/lib/github/Repository.py", line 2305, in get_release_asset
    return github.GitReleaseAsset.GitReleaseAsset(self._requester, {}, data, completed=True)
  File "/build/python-pygithub/src/PyGithub-1.34.2/build/lib/github/GithubObject.py", line 240, in __init__
    GithubObject.__init__(self, requester, headers, attributes, completed)
  File "/build/python-pygithub/src/PyGithub-1.34.2/build/lib/github/GithubObject.py", line 78, in __init__
    self._storeAndUseAttributes(headers, attributes)
  File "/build/python-pygithub/src/PyGithub-1.34.2/build/lib/github/GithubObject.py", line 90, in _storeAndUseAttributes
    self._useAttributes(attributes)
  File "/build/python-pygithub/src/PyGithub-1.34.2/build/lib/github/GitReleaseAsset.py", line 200, in _useAttributes
    self._url = self._makeStringAttribute(attributes["url"])
TypeError: string indices must be integers

======================================================================
FAIL: testUploadAsset (github.tests.GitRelease.Release)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/build/python-pygithub/src/PyGithub-1.34.2/build/lib/github/tests/GitRelease.py", line 125, in testUploadAsset
    "application/zip")
  File "/build/python-pygithub/src/PyGithub-1.34.2/build/lib/github/GitRelease.py", line 145, in upload_asset
    input=path
  File "/build/python-pygithub/src/PyGithub-1.34.2/build/lib/github/Requester.py", line 181, in requestBlobAndCheck
    return self.__check(*self.requestBlob(verb, url, parameters, headers, input))
  File "/build/python-pygithub/src/PyGithub-1.34.2/build/lib/github/Requester.py", line 247, in requestBlob
    return self.__requestEncode(None, verb, url, parameters, headers, input, encode)
  File "/build/python-pygithub/src/PyGithub-1.34.2/build/lib/github/Requester.py", line 270, in __requestEncode
    status, responseHeaders, output = self.__requestRaw(cnx, verb, url, requestHeaders, encoded_input)
  File "/build/python-pygithub/src/PyGithub-1.34.2/build/lib/github/Requester.py", line 295, in __requestRaw
    requestHeaders
  File "/build/python-pygithub/src/PyGithub-1.34.2/build/lib/github/tests/Framework.py", line 148, in request
    self.__testCase.assertEqual(self.__host, readLine(self.__file))
AssertionError: 'uploads.github.com' != 'api.github.com'
- uploads.github.com
? ^ ^^^^^
+ api.github.com
? ^ ^


----------------------------------------------------------------------
Ran 424 tests in 2.951s

FAILED (failures=1, errors=1)
Test failed: <unittest.runner.TextTestResult run=424 errors=1 failures=1>
error: Test failed: <unittest.runner.TextTestResult run=424 errors=1 failures=1>
==> ERROR: A failure occurred in check().
    Aborting...
==> ERROR: Build failed, check /var/lib/archbuild/extra-x86_64/arch/build

@ankona
Copy link
Author

ankona commented May 17, 2017

@NicoHood Yeah... I'm working it.

One down...

@ankona
Copy link
Author

ankona commented May 17, 2017

@NicoHood Ready

@NicoHood
Copy link

@THEHighlander Thanks for the help. Now I get a different error while using:

:: Uploading /data/gpgit/PyGithub-v1.34.3.tar.xz
Traceback (most recent call last):
  File "../gpgit/gpgit.py", line 916, in <module>
    sys.exit(main())
  File "../gpgit/gpgit.py", line 903, in main
    err_msg = gpgit.run()
  File "../gpgit/gpgit.py", line 837, in run
    err_msg = substep.funct()
  File "../gpgit/gpgit.py", line 676, in substep2
    self.release.upload_asset(assetpath, "Testlabel", "application/x-xz")
  File "/usr/lib/python3.6/site-packages/github/GitRelease.py", line 145, in upload_asset
    input=path
  File "/usr/lib/python3.6/site-packages/github/Requester.py", line 181, in requestBlobAndCheck
    return self.__check(*self.requestBlob(verb, url, parameters, headers, input))
  File "/usr/lib/python3.6/site-packages/github/Requester.py", line 186, in __check
    raise self.__createException(status, responseHeaders, output)
github.GithubException.GithubException: 400 {'message': 'Bad Content-Length: ', 'request_id': 'DEC0:6858:529B6F:55DEA0:591DB84B'}

I am using a hardcoded label and mimetype. I also have a question about that. Do I need to specify those and to which values does those default to? From what I can see in the source the mime type is auto guessed and the label is left out, am I right with this?

Checkout my tool to reproduce the error:
https://github.com/NicoHood/gpgit/tree/python

@ankona
Copy link
Author

ankona commented May 18, 2017

@NicoHood You're correct on both label & mime type.

Label is optional. If you provide one, it just appears as the text in the download link on the release page in github (e.g. <a href='filename.ext'>Label Here</a>, see screenshot above). If you don't provide it, the link just shows the raw file name.

The mime type is also technically optional, but it's better to provide it. You noticed that I'm using mimetypes.guess_type(input_file) to try to determine it if it's not provided, then just falling back to application/octet-stream if that fails.

I haven't seen the bad content length error in my tests. I'll get it figured out today.

@NicoHood
Copy link

@THEHighlander Thanks! Its finally working now. Thanks so much for your help and effort!

@nhomar Please merge this PR, its tested and really helpful.

@NicoHood
Copy link

NicoHood commented Aug 6, 2017

@jayfk Any chance to get a review from your side?

@xiapoy
Copy link

xiapoy commented Aug 27, 2017

+1

@matejak
Copy link

matejak commented Nov 22, 2017

Please merge this if it is ready, it is a really useful stuff.

@nhomar nhomar merged commit 5244964 into PyGithub:master Nov 27, 2017
def requestBlobAndCheck(self, verb, url, parameters=None, headers=None, input=None):
o = urlparse.urlparse(url)
self.__hostname = o.hostname
return self.__check(*self.requestBlob(verb, url, parameters, headers, input))

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldnt we change back the __hostname here? My subsequent api calls failed due to the host name assertion fails in requester..

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See fix in #771

@NicoHood
Copy link

NicoHood commented Jan 6, 2018

@jasonwhite @nhomar Thanks for merging. Can you please tag a new release, so its available on pypi and the linux distros?

You might also want to check the comment by @steven-hh-ding , maybe also @THEHighlander can do.

@rpatterson
Copy link

This functionality remains undocumented in the reference.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants