diff --git a/.gitignore b/.gitignore index b869b6c70..03121cfc0 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,4 @@ venv*/ build/ *.egg .env +.ipynb_checkpoints diff --git a/.travis.yml b/.travis.yml index 740427c4c..e869794ec 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,24 +1,34 @@ language: python -python: -- 2.6 -- 2.7 -- 3.2 -- 3.3 -- pypy -# command to run tests, e.g. python setup.py test before_script: -- pip install -r dev-requirements.txt +- pip install tox - pip install -U requests"$REQUESTS_VERSION" # test script -script: make travis +script: tox -e ${TOX_ENV} notifications: - on_success: change - on_failure: always + on_success: change + on_failure: always env: global: - TRAVIS_GH3="True" matrix: - - REQUESTS_VERSION="==2.0.1" - - REQUESTS_VERSION="" # Latest + - TOX_ENV=py26 REQUESTS_VERSION="==2.0.1" + - TOX_ENV=py27 REQUESTS_VERSION="==2.0.1" + - TOX_ENV=py32 REQUESTS_VERSION="==2.0.1" + - TOX_ENV=py33 REQUESTS_VERSION="==2.0.1" + - TOX_ENV=py34 REQUESTS_VERSION="==2.0.1" + - TOX_ENV=pypy REQUESTS_VERSION="==2.0.1" + - TOX_ENV=py26 REQUESTS_VERSION="" + - TOX_ENV=py27 REQUESTS_VERSION="" + - TOX_ENV=py32 REQUESTS_VERSION="" + - TOX_ENV=py33 REQUESTS_VERSION="" + - TOX_ENV=py34 REQUESTS_VERSION="" + - TOX_ENV=pypy REQUESTS_VERSION="" + - TOX_ENV=py27-flake8 + - TOX_ENV=py34-flake8 + - TOX_ENV=docstrings + +matrix: + allow_failures: + - env: TOX_ENV=docstrings diff --git a/AUTHORS.rst b/AUTHORS.rst index b0b87c04e..722de45c5 100644 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -58,3 +58,29 @@ Contributors - Vincent Driessen (@nvie) - Philip Chimento (@ptomato) + +- Benjamin Gilbert (@bgilbert) + +- Daniel Johnson (@danielj7) + +- David Moss (@damoss007) + +- John Barbuto (@jbarbuto) + +- Nikolay Bryskin (@nikicat) + +- Tomi Äijö (@tomiaijo) + +- jnothman (@jnothman) + +- Cameron Davidson-Pilon (@CamDavidsonPilon) + +- Alex Couper (@alexcouper) + +- Marc Abramowitz (@msabramo) + +- Adrian Moisey (@adrianmoisey) + +- Bryce Boe (@bboe) + +- Ryan Weald (@rweald) diff --git a/HISTORY.rst b/HISTORY.rst index 9d237b31d..46e1b5cb1 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -1,6 +1,94 @@ +.. vim: set tw=100 + History/Changelog ----------------- +.. include:: ./LATEST_VERSION_NOTES.rst + +0.9.3: 2014-11-04 +~~~~~~~~~~~~~~~~~ + +- Backport of ``PullRequest#create_review_comment`` by Adrian Moisey + +- Backport of ``PullRequest#review_comments`` by Adrian Moisey + +- Backport of a fix that allows authenticated users to download Release + Assets. Original bug reported by Eugene Fidelin in issue #288. + +- Documentation typo fix by Marc Abramowitz + +0.9.2: 2014-10-05 +~~~~~~~~~~~~~~~~~ + +- Updates for `new team management`_ API changes + + - Add ``Team#invite``, ``Team#membership_for``, and + ``Team#revoke_membership`` + + - Deprecate ``Team#add_member``, ``Team#remove_member``, and + ``Organization#add_member``. + + - Update payload handler for ``TeamAddEvent``. + +.. _new team management: + https://developer.github.com/changes/2014-09-23-one-more-week-before-the-add-team-member-api-breaking-change/ + +0.9.1: 2014-08-10 +~~~~~~~~~~~~~~~~~ + +- Correct Repository attribute ``fork_count`` should be ``forks_count`` + +0.9.0: 2014-05-04 +~~~~~~~~~~~~~~~~~ + +- Add Deployments API + +- Add Pages API + +- Add support so applications can revoke a `single authorization`_ or `all + authorizations`_ created by the application + +- Add the ability for users to ping_ hooks + +- Allow users to list a `Repository's collaborators`_ + +- Allow users to create an empty blob on a Repository + +- Update how users can list issues and pull requests. See: + http://developer.github.com/changes/2014-02-28-issue-and-pull-query-enhancements/ + This includes breaking changes to ``Repository#iter_pulls``. + +- Update methods to handle the `pagination changes`_. + +- Fix typo `stargarzers_url`_ + +- Add ``assets`` attribute to ``Release`` object. + +- Fix wrong argument to ``Organization#create_team`` (``permissions`` versus + ``permission``) + +- Fix Issue Search Result's representation and initialization + +- Fix Repository Search Result's initialization + +- Allow users to pass a two-factor authentication callback to + ``GitHub#authorize``. + +.. _single authorization: https://github3py.readthedocs.org/en/latest/github.html#github3.github.GitHub.revoke_authorization +.. _all authorizations: https://github3py.readthedocs.org/en/latest/github.html#github3.github.GitHub.revoke_authorizations +.. _ping: https://github3py.readthedocs.org/en/latest/repos.html?highlight=ping#github3.repos.hook.Hook.ping +.. _Repository's collaborators: https://github3py.readthedocs.org/en/latest/repos.html#github3.repos.repo.Repository.iter_collaborators +.. _pagination changes: https://developer.github.com/changes/2014-03-18-paginating-method-changes/ +.. _stargarzers_url: https://github.com/sigmavirus24/github3.py/pull/240 + +0.8.2: 2014-02-11 +~~~~~~~~~~~~~~~~~ + +- Fix bug in ``GitHub#search_users`` (and ``github3.search_users``). Thanks + @abesto + +- Expose the stargazers count for repositories. Thanks @seveas + 0.8.1: 2014-01-26 ~~~~~~~~~~~~~~~~~ diff --git a/LATEST_VERSION_NOTES.rst b/LATEST_VERSION_NOTES.rst new file mode 100644 index 000000000..0662c2542 --- /dev/null +++ b/LATEST_VERSION_NOTES.rst @@ -0,0 +1,367 @@ +.. vim: set tw=100 + +1.0.0a1: 2014-12-07 +~~~~~~~~~~~~~~~~~~~ + +1.0.0 is a huge release. It includes a great deal of changes to ``github3.py``. +It is suggested you read the following release notes *very* carefully. + +Breaking Changes +```````````````` + +- ``Organization#add_member`` has been changed. The second parameter has been + changed to ``team_id`` and now expects an integer. + +- ``Organization#add_repository`` has been changed. The second parameter has been + changed to ``team_id`` and now expects an integer. + +- All methods and functions starting with ``iter_`` have been renamed. + +========================================== ============================================== +Old name New name +========================================== ============================================== +``github3.iter_all_repos`` ``github3.all_repositories`` +``github3.iter_all_users`` ``github3.all_users`` +``github3.iter_events`` ``github3.all_events`` +``github3.iter_followers`` ``github3.followers_of`` +``github3.iter_following`` ``github3.followed_by`` +``github3.iter_repo_issues`` ``github3.issues_on`` +``github3.iter_orgs`` ``github3.organizations_with`` +``github3.iter_user_repos`` ``github3.repositories_by`` +``github3.iter_starred`` ``github3.starred_by`` +``github3.iter_subscriptions`` ``github3.subscriptions_for`` +``Deployment#iter_statuses`` ``Deployment#statuses`` +``Gist#iter_comments`` ``Gist#comments`` +``Gist#iter_commits`` ``Gist#commits`` +``Gist#iter_files`` ``Gist#files`` +``Gist#iter_forks`` ``Gist#forks`` +``GitHub#iter_all_repos`` ``GitHub#all_repositories`` +``GitHub#iter_all_users`` ``GitHub#all_users`` +``GitHub#iter_authorizations`` ``GitHub#authorizations`` +``GitHub#iter_emails`` ``GitHub#emails`` +``GitHub#iter_events`` ``GitHub#events`` +``GitHub#iter_followers`` ``GitHub#{followers,followers_of}`` +``GitHub#iter_following`` ``GitHub#{following,followed_by}`` +``GitHub#iter_gists`` ``GitHub#{gists,gists_by,public_gists}`` +``GitHub#iter_notifications`` ``GitHub#notifications`` +``GitHub#iter_org_issues`` ``GitHub#organization_issues`` +``GitHub#iter_issues`` ``GitHub#issues`` +``GitHub#iter_user_issues`` ``GitHub#user_issues`` +``GitHub#iter_repo_issues`` ``GitHub#issues_on`` +``GitHub#iter_keys`` ``GitHub#keys`` +``GitHub#iter_orgs`` ``GitHub#{organizations,organizations_with}`` +``GitHub#iter_repos`` ``GitHub#reposistories`` +``GitHub#iter_user_repos`` ``GitHub#repositories_by`` +``GitHub#iter_user_teams`` ``GitHub#user_teams`` +``Issue#iter_comments`` ``Issue#comments`` +``Issue#iter_events`` ``Issue#events`` +``Issue#iter_labels`` ``Issue#labels`` +``Milestone#iter_labels`` ``Milestone#labels`` +``Organization#iter_members`` ``Organization#members`` +``Organization#iter_public_members`` ``Organization#public_members`` +``Organization#iter_repos`` ``Organization#repositories`` +``Organization#iter_teams`` ``Organization#teams`` +``PullRequest#iter_comments`` ``PullRequest#review_comments`` +``PullRequest#iter_commits`` ``PullRequest#commits`` +``PullRequest#iter_files`` ``PullRequest#files`` +``PullRequest#iter_issue_comments`` ``PullRequest#issue_comments`` +``Team#iter_members`` ``Team#members`` +``Team#iter_repos`` ``Team#repositories`` +``Repository#iter_assignees`` ``Repository#assignees`` +``Repository#iter_branches`` ``Repository#branches`` +``Repository#iter_code_frequency`` ``Repository#code_frequency`` +``Repository#iter_collaborators`` ``Repository#collaborators`` +``Repository#iter_comments`` ``Repository#comments`` +``Repository#iter_comments_on_commit`` ``Repository#comments_on_commit`` +``Repository#iter_commit_activity`` ``Repository#commit_activity`` +``Repository#iter_commits`` ``Repository#commits`` +``Repository#iter_contributor_statistics`` ``Repository#contributor_statistics`` +``Repository#iter_contributors`` ``Repository#contributors`` +``Repository#iter_forks`` ``Repository#forks`` +``Repository#iter_hooks`` ``Repository#hooks`` +``Repository#iter_issues`` ``Repository#issues`` +``Repository#iter_issue_events`` ``Repository#issue_events`` +``Repository#iter_keys`` ``Repository#keys`` +``Repository#iter_labels`` ``Repository#labels`` +``Repository#iter_languages`` ``Repository#languages`` +``Repository#iter_milestones`` ``Repository#milestones`` +``Repository#iter_network_events`` ``Repository#network_events`` +``Repository#iter_notifications`` ``Repository#notifications`` +``Repository#iter_pages_builds`` ``Repository#pages_builds`` +``Repository#iter_pulls`` ``Repository#pull_requests`` +``Repository#iter_refs`` ``Repository#refs`` +``Repository#iter_releases`` ``Repository#releases`` +``Repository#iter_stargazers`` ``Repository#stargazers`` +``Repository#iter_subscribers`` ``Repository#subscribers`` +``Repository#iter_statuses`` ``Repository#statuses`` +``Repository#iter_tags`` ``Repository#tags`` +``Repository#iter_teams`` ``Repository#teams`` +``Repository#iter_teams`` ``Repository#teams`` +``User#iter_events`` ``User#events`` +``User#iter_followers`` ``User#followers`` +``User#iter_following`` ``User#following`` +``User#iter_keys`` ``User#keys`` +``User#iter_org_events`` ``User#organization_events`` +``User#iter_received_events`` ``User#received_events`` +``User#iter_orgs`` ``User#organizations`` +``User#iter_starred`` ``User#starred_repositories`` +``User#iter_subscriptions`` ``User#subscriptions`` +========================================== ============================================== + +- ``github3.login`` has been simplified and split into two functions: + + - ``github3.login`` serves the majority use case and only provides an + authenticated ``GitHub`` object. + + - ``github3.enterprise_login`` allows GitHub Enterprise users to log into + their service. + +- ``GitHub#iter_followers`` was split into two functions: + + - ``GitHub#followers_of`` which iterates over all of the followers of a user + whose username you provide + + - ``GitHub#followers`` which iterates over all of the followers of the + authenticated user + +- ``GitHub#iter_following`` was split into two functions: + + - ``GitHub#followed_by`` which iterates over all of the users followed by + the username you provide + + - ``GitHub#following`` which iterates over all of the users followed by the + authenticated user + +- ``GitHub#iter_gists`` was split into three functions: + + - ``GitHub#public_gists`` which iterates over all of the public gists on + GitHub + + - ``GitHub#gists_for`` which iterates over all the public gists of a + specific user + + - ``GitHub#gists`` which iterates over the authenticated users gists + +- ``GitHub#iter_orgs`` was split into two functions: + + - ``GitHub#organizations`` which iterates over the authenticated user's + organization memberships + + - ``GitHub#organizations_with`` which iterates over the given user's + organization memberships + +- ``GitHub#iter_subscriptions`` was split into two functions: + + - ``GitHub#subscriptions_for`` which iterates over an arbitrary user's + subscriptions + + - ``GitHub#subscriptions`` which iterates over the authenticated user's + subscriptions + +- ``GitHub#iter_starred`` was split into two functions: + + - ``GitHub#starred_by`` which iterates over an arbitrary user's stars + + - ``GitHub#starred`` which iterates over the authenticated user's stars + +- ``GitHub#user`` was split into two functions: + + - ``GitHub#user`` which retrieves an arbitrary user's information + + - ``GitHub#me`` which retrieves the authenticated user's information + +- ``GitHub#update_user`` has been renamed to ``GitHub#update_me`` and only + uses 1 API call now. It was renamed to reflect the addition of + ``GitHub#me``. + +- The legacy watching API has been removed: + + - ``GitHub#subscribe`` + + - ``GitHub#unsubscribe`` + + - ``GitHub#is_subscribed`` + +- ``GitHub#create_repo`` was renamed to ``GitHub#create_repository`` + +- ``GitHub#delete_key`` was removed. To delete a key retrieve it with + ``GitHub#key`` and then call ``Key#delete``. + +- ``Repository#set_subscription`` was split into two simpler functions + + - ``Repository#subscribe`` subscribes the authenticated user to the + repository's notifications + + - ``Repository#ignore`` ignores notifications from the repository for the + authenticated user + +- ``Repository#contents`` was split into two simpler functions + + - ``Repository#file_contents`` returns the contents of a file object + + - ``Repository#directory_contents`` returns the contents of files in a + directory. + +- ``Organization#add_repo`` and ``Team#add_repo`` have been renamed to + ``Organization#add_repository`` and ``Team#add_repository`` respectively. + +- ``Organization#create_repo`` has been renamed to + ``Organization#create_repository``. It no longer accepts ``has_downloads``. + It now accepts ``license_template``. + +- ``Organization#remove_repo`` has been renamed to + ``Organization#remove_repository``. It now accepts ``team_id`` instead of + ``team``. + +- ``github3.ratelimit_remaining`` was removed + +- ``GitHub`` instances can no longer be used as context managers + +- The pull request API has changed. + + - The ``links`` attribute now contains the raw ``_links`` attribute from the + API. + + - The ``merge_commit_sha`` attribute has been removed since it was deprecated + in the GitHub API. + + - To present a more consistent universal API, certain attributes have been + renamed. + +=============================== ========================== +Old name New attribute name +=============================== ========================== +``PullFile.additions`` ``additions_count`` +``PullFile.deletions`` ``deletions_count`` +``PullFile.changes`` ``changes_count`` +``PullRequest.additions`` ``additions_count`` +``PullRequest.comments`` ``comments_count`` +``PullRequest.commits`` ``commits_count`` +``PullRequest.deletions`` ``deletions_count`` +``PullRequest.review_comments`` ``review_comments_count`` +=============================== ========================== + +- The Gist API has changed. + + - The ``forks`` and ``files`` attributes that used to keep count of the + number of ``forks`` and ``files`` have been **removed**. + + - The ``comments`` attribute which provided the number of comments on a + gist, has been **renamed** to ``comments_count``. + + - The ``is_public`` method has been removed since it just returned the + ``Gist.public`` attribute. + +- Most instances of ``login`` as a parameter have been changed to ``username`` + for clarity and consistency. This affects the following methods: + + - ``github3.authorize`` + - ``github3.repositories_by`` + - ``github3.user`` + - ``GitHub`` + - ``GitHub#authorize`` + - ``GitHub#follow`` + - ``GitHub#is_following`` + - ``GitHub#is_starred`` + - ``GitHub#issue`` + - ``GitHub#followers_of`` + - ``GitHub#followed_by`` + - ``GitHub#gists_by`` + - ``GitHub#issues_on`` + - ``GitHub#organizations_with`` + - ``GitHub#starred_by`` + - ``GitHub#subscriptions_for`` + - ``GitHub#user`` + - ``GitHubEnterprise`` + - ``Issue#assign`` + - ``Organization#add_member`` + - ``Organization#is_member`` + - ``Organization#is_public_member`` + - ``Organization#remove_member`` + - ``Repository#add_collaborator`` + - ``Repository#is_assignee`` + - ``Repository#is_collaborator`` + - ``Repository#remove_collaborator`` + - ``Team#add_member`` + - ``Team#is_member`` + - ``User#is_assignee_on`` + - ``User#is_following`` + +- ``Repository.stargazers`` is now ``Repository.stargazers_count`` (conforming + with the attribute name returned by the API). + + +- The ``Issue`` API has changed in order to provide a more consistent attribute + API. ``Issue.comments`` is now ``Issue.comments_count`` and returns the + number of comments on an issue. + +- The ``Issue.labels`` attribute has also been renamed. It is now available from + ``Issue.original_labels``. This will provide the user with the list of + ``Label`` objects that was returned by the API. To retrieve an updated list + of labels, the user can now use ``Issue#labels``, e.g. + + :: + + i = github3.issue('sigmavirus24', 'github3.py', 30) + labels = list(i.labels()) + +- The ``Organization`` and ``User`` APIs have changed to become more + consistent with the rest of the library and GitHub API. The following + attribute names have been changed + +=============================== ========================== +Old name New attribute name +=============================== ========================== +``Organization.followers`` ``followers_count`` +``Organization.following`` ``following_count`` +``Organization.public_repos`` ``public_repos_count`` +``User.followers`` ``followers_count`` +``User.following`` ``following_count`` +``User.public_repos`` ``public_repos_count`` +=============================== ========================== + +- The ``Release.assets`` attribute has been renamed to + ``Release.original_assets``. To retrieve up-to-date assets, use the + ``Release#assets`` method. + +- The ``Authorization`` API has changed. The ``update`` method has been split + into three methods: ``add_scopes``, ``remove_scopes``, ``replace_scopes``. + This highlights the fact that ``Authorization#update`` used to require more + than one request. + +- ``Event#is_public`` has been removed. Simply check the event's ``public`` + attribute instead. + +- ``Repository#delete_file`` and ``Repository#update_file`` have been removed. + Simply delete or update a file using the Contents API. + +- ``Content#delete`` now returns a dictionary that matches the JSON returned + by the API. It contains the Contents and the Commit associated with the + deletion. + +- ``Content#update`` now returns a dictionary that matches the JSON returned + by the API. It contains the Contents and the Commit associated with the + deletion. + +- ``Issue.pull_request`` has been renamed to ``Issue.pull_request_urls`` + +New Features +```````````` + +- Most objects now have a ``session`` attribute. This is a subclass of a + ``Session`` object from ``requests``. This can now be used in conjunction + with a third-party caching mechanism. The suggested caching library is + ``cachecontrol``. + +- All object's ``url`` attribute are now available. + +- You can now retrieve a repository by its id with + ``GitHub#repository_with_id``. + +- You can call the ``pull_request`` method on an ``Issue`` now to retrieve the + associated pull request:: + + import github3 + + i = github3.issue('sigmavirus24', 'github3.py', 301) + pr = i.pull_request() diff --git a/MANIFEST.in b/MANIFEST.in index ff09b49a0..e347eaa1a 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,8 +1,14 @@ include README.rst include LICENSE include HISTORY.rst +include LATEST_VERSION_NOTES.rst include AUTHORS.rst +include CONTRIBUTING.rst +include tox.ini +include report_issue.py prune *.pyc -recursive-include github3/ -recursive-include docs/ +recursive-include docs *.rst *.py Makefile +recursive-include tests *.py *.json +recursive-include tests/json * +recursive-include images *.png prune docs/_build diff --git a/dev-requirements.txt b/dev-requirements.txt index 6ab032431..6ea91ae66 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -5,3 +5,4 @@ mock==1.0.1 pytest>=2.3.5 wheel==0.21.0 git+git://github.com/sigmavirus24/betamax +git+git://github.com/sigmavirus24/betamax_matchers diff --git a/docs/conf.py b/docs/conf.py index 0262cdbe8..3d1ec55c8 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -96,7 +96,7 @@ # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. -html_theme = 'nature' +#html_theme = 'nature' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the diff --git a/docs/examples/gist.rst b/docs/examples/gist.rst index 2153ea6a7..c137122d4 100644 --- a/docs/examples/gist.rst +++ b/docs/examples/gist.rst @@ -46,7 +46,7 @@ Creating an anonymous gist 'content': 'What... is the air-speed velocity of an unladen swallow?' } } - gist = create_gist('Answer this to cross the bridge', files, public=False) + gist = create_gist('Answer this to cross the bridge', files) comments = [c for c in gist.iter_comments()] # [] comment = gist.create_comment('Bogus. This will not work.') @@ -59,3 +59,5 @@ file type based on extension provided. ``'What... is the air-speed velocity of an unladen swallow?'`` is the file's content or body. ``'Answer this to cross the bridge'`` is the gists's description. While required by github3.py, it is allowed to be empty, e.g., ``''`` is accepted by GitHub. + +Note that anonymous gists are always public. diff --git a/docs/gists.rst b/docs/gists.rst index 79e207d54..f6a453d5f 100644 --- a/docs/gists.rst +++ b/docs/gists.rst @@ -17,20 +17,28 @@ classes should never be instantiated by the user (developer) directly. Gist Objects ------------ +.. module:: github3.gists.gist + .. autoclass:: github3.gists.gist.Gist :inherited-members: ------ +.. module:: github3.gists.comment + .. autoclass:: github3.gists.comment.GistComment :inherited-members: ------ +.. module:: github3.gists.file + .. autoclass:: github3.gists.file.GistFile :inherited-members: ------ +.. module:: github3.gists.history + .. autoclass:: github3.gists.history.GistHistory :inherited-members: diff --git a/docs/index.rst b/docs/index.rst index abf61e3f5..77dbff32d 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -23,10 +23,10 @@ Let's get information about a user:: # Ian Cordasco print(sigmavirus24.login) # sigmavirus24 - print(sigmavirus24.followers) + print(sigmavirus24.followers_count) # 4 - for f in gh.iter_followers(): + for f in gh.followers(): print(str(f)) kennethreitz = gh.user('kennethreitz') @@ -34,9 +34,9 @@ Let's get information about a user:: print(kennethreitz.name) print(kennethreitz.login) - print(kennethreitz.followers) + print(kennethreitz.followers_count) - followers = [str(f) for f in gh.iter_followers('kennethreitz')] + followers = [str(f) for f in gh.followers('kennethreitz')] More Examples ~~~~~~~~~~~~~ @@ -74,6 +74,7 @@ Modules github issues models + notifications orgs pulls repos @@ -147,16 +148,33 @@ Examples Running the Unittests ~~~~~~~~~~~~~~~~~~~~~ -:: +The tests are generally run using tox. Tox can be installed lke so:: - mkdir -p /path/to/virtualenv/github3.py - cd /path/to/virtualenv/github3.py - virtualenv . - cd /path/to/github3.py_repo/ - pip install -r dev-requirements.txt - # Or you could run make test-deps - make tests + pip install tox +We test against PyPy and the following versions of Python: + +- 2.6 +- 2.7 +- 3.2 +- 3.3 +- 3.4 + +If you simply run ``tox`` it will run tests against all of these versions of +python and run ``flake8`` against the codebase as well. If you want to run +against one specific version, you can do:: + + tox -e py34 + +And if you want to run tests against a specific file, you can do:: + + tox -e py34 -- tests/uni/test_github.py + +To run the tests, ``tox`` uses ``py.test`` so you can pass any options or +parameters to ``py.test`` after specifying ``--``. For example, you can get +more verbose output by doing:: + + tox -e py34 -- -vv .. toctree:: @@ -172,7 +190,16 @@ Contact .. _sigmavirus24: https://twitter.com/sigmavirus24 -.. include:: ../HISTORY.rst +Latest Version's Changes +------------------------ + +.. include:: ../LATEST_VERSION_NOTES.rst + +The full history of the project is available as well. + +.. toctree:: + + project_changelog Testimonials ------------ diff --git a/docs/issues.rst b/docs/issues.rst index 4334306a7..42d85598a 100644 --- a/docs/issues.rst +++ b/docs/issues.rst @@ -14,25 +14,35 @@ This part of the documentation covers the module which handles :class:`Issue Issue Objects ------------- +.. module:: github3.issues.issue + .. autoclass:: github3.issues.issue.Issue :inherited-members: ------ +.. module:: github3.issues.comment + .. autoclass:: github3.issues.comment.IssueComment :inherited-members: ------ +.. module:: github3.issues.event + .. autoclass:: github3.issues.event.IssueEvent :inherited-members: ------ +.. module:: github3.issues.milestone + .. autoclass:: github3.issues.milestone.Milestone :inherited-members: ------ +.. module:: github3.issues.label + .. autoclass:: github3.issues.label.Label :inherited-members: diff --git a/docs/notifications.rst b/docs/notifications.rst new file mode 100644 index 000000000..73b47c0df --- /dev/null +++ b/docs/notifications.rst @@ -0,0 +1,19 @@ +.. module:: github3 +.. module:: github3.notifications + +Notifications +============= + +This part of the documentation covers the :class:`Thread ` and +:class:`Subscription ` objects. + +Notification Objects +-------------------- + +.. autoclass:: Thread + :inherited-members: + +------ + +.. autoclass:: Subscription + :inherited-members: diff --git a/docs/project_changelog.rst b/docs/project_changelog.rst new file mode 100644 index 000000000..250649964 --- /dev/null +++ b/docs/project_changelog.rst @@ -0,0 +1 @@ +.. include:: ../HISTORY.rst diff --git a/docs/repos.rst b/docs/repos.rst index b72d47a9a..71a726ca9 100644 --- a/docs/repos.rst +++ b/docs/repos.rst @@ -6,9 +6,15 @@ Repository This part of the documentation covers: - :class:`Repository ` +- :class:`Asset ` - :class:`Branch ` - :class:`Contents ` +- :class:`Deployment ` +- :class:`DeploymentStatus ` - :class:`Hook ` +- :class:`PagesInfo ` +- :class:`PagesBuild ` +- :class:`Release ` - :class:`RepoTag ` - :class:`RepoComment ` - :class:`RepoCommit ` @@ -31,37 +37,79 @@ sections of the GitHub documentation. Repository Objects ------------------ +.. module:: github3.repos.repo + .. autoclass:: github3.repos.repo.Repository :inherited-members: --------- +.. module:: github3.repos.branch + .. autoclass:: github3.repos.branch.Branch :members: --------- +.. module:: github3.repos.contents + .. autoclass:: github3.repos.contents.Contents :members: --------- +.. module:: github3.repos.deployment + +.. autoclass:: github3.repos.deployment.Deployment + :members: + +--------- + +.. autoclass:: github3.repos.deployment.DeploymentStatus + :members: + +--------- + +.. module:: github3.repos.release + .. autoclass:: github3.repos.release.Release :members: +--------- + +.. autoclass:: github3.repos.release.Asset + :members: --------- +.. module:: github3.repos.hook + .. autoclass:: github3.repos.hook.Hook :members: --------- +.. module:: github3.repos.pages + +.. autoclass:: github3.repos.pages.PagesInfo + :members: + +--------- + +.. autoclass:: github3.repos.pages.PagesBuild + :members: + +--------- + +.. module:: github3.repos.tag + .. autoclass:: github3.repos.tag.RepoTag :members: --------- +.. module:: github3.repos.comment + More information about this class can be found in the official documentation about `comments `_. @@ -70,20 +118,28 @@ about `comments `_. --------- +.. module:: github3.repos.commit + .. autoclass:: github3.repos.commit.RepoCommit :members: --------- +.. module:: github3.repos.comparison + .. autoclass:: github3.repos.comparison.Comparison :members: --------- +.. module:: github3.repos.status + .. autoclass:: github3.repos.status.Status :members: --------- +.. module:: github3.repos.stats + .. autoclass:: github3.repos.stats.ContributorStats :members: diff --git a/example-notebooks/all_repositories.ipynb b/example-notebooks/all_repositories.ipynb new file mode 100644 index 000000000..fff062f78 --- /dev/null +++ b/example-notebooks/all_repositories.ipynb @@ -0,0 +1,132 @@ +{ + "metadata": { + "name": "", + "signature": "sha256:d7edf60ced4d549568da849ae1760941af6e0432378fa5832cdff325109ee570" + }, + "nbformat": 3, + "nbformat_minor": 0, + "worksheets": [ + { + "cells": [ + { + "cell_type": "heading", + "level": 1, + "metadata": {}, + "source": [ + "How to retrieve all of the public repositories on GitHub" + ] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "import github3" + ], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": 1 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "for repository in github3.all_repositories(number=50):\n", + " print('{0}, id: {0.id}, url: {0.html_url}'.format(repository))" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "mojombo/grit, id: 1, url: https://github.com/mojombo/grit\n", + "wycats/merb-core, id: 26, url: https://github.com/wycats/merb-core\n", + "rubinius/rubinius, id: 27, url: https://github.com/rubinius/rubinius\n", + "mojombo/god, id: 28, url: https://github.com/mojombo/god\n", + "vanpelt/jsawesome, id: 29, url: https://github.com/vanpelt/jsawesome\n", + "wycats/jspec, id: 31, url: https://github.com/wycats/jspec\n", + "defunkt/exception_logger, id: 35, url: https://github.com/defunkt/exception_logger\n", + "defunkt/ambition, id: 36, url: https://github.com/defunkt/ambition\n", + "technoweenie/restful-authentication, id: 42, url: https://github.com/technoweenie/restful-authentication\n", + "technoweenie/attachment_fu, id: 43, url: https://github.com/technoweenie/attachment_fu\n", + "topfunky/bong, id: 47, url: https://github.com/topfunky/bong\n", + "Caged/microsis, id: 48, url: https://github.com/Caged/microsis\n", + "anotherjesse/s3, id: 52, url: https://github.com/anotherjesse/s3\n", + "anotherjesse/taboo, id: 53, url: https://github.com/anotherjesse/taboo\n", + "anotherjesse/foxtracs, id: 54, url: https://github.com/anotherjesse/foxtracs\n", + "anotherjesse/fotomatic, id: 56, url: https://github.com/anotherjesse/fotomatic\n", + "mojombo/glowstick, id: 61, url: https://github.com/mojombo/glowstick\n", + "defunkt/starling, id: 63, url: https://github.com/defunkt/starling\n", + "wycats/merb-more, id: 65, url: https://github.com/wycats/merb-more\n", + "macournoyer/thin, id: 68, url: https://github.com/macournoyer/thin\n", + "jamesgolick/resource_controller, id: 71, url: https://github.com/jamesgolick/resource_controller\n", + "jamesgolick/markaby, id: 73, url: https://github.com/jamesgolick/markaby\n", + "jamesgolick/enum_field, id: 74, url: https://github.com/jamesgolick/enum_field\n", + "defunkt/subtlety, id: 75, url: https://github.com/defunkt/subtlety\n", + "defunkt/zippy, id: 92, url: https://github.com/defunkt/zippy\n", + "defunkt/cache_fu, id: 93, url: https://github.com/defunkt/cache_fu\n", + "KirinDave/phosphor, id: 95, url: https://github.com/KirinDave/phosphor\n", + "bmizerany/sinatra, id: 98, url: https://github.com/bmizerany/sinatra\n", + "jnewland/gsa-prototype, id: 102, url: https://github.com/jnewland/gsa-prototype\n", + "technoweenie/duplikate, id: 105, url: https://github.com/technoweenie/duplikate\n", + "jnewland/lazy_record, id: 118, url: https://github.com/jnewland/lazy_record\n", + "jnewland/gsa-feeds, id: 119, url: https://github.com/jnewland/gsa-feeds\n", + "jnewland/votigoto, id: 120, url: https://github.com/jnewland/votigoto\n", + "defunkt/mofo, id: 127, url: https://github.com/defunkt/mofo\n", + "jnewland/xhtmlize, id: 129, url: https://github.com/jnewland/xhtmlize\n", + "schacon/ruby-git, id: 130, url: https://github.com/schacon/ruby-git\n", + "ezmobius/bmhsearch, id: 131, url: https://github.com/ezmobius/bmhsearch\n", + "uggedal/mofo, id: 137, url: https://github.com/uggedal/mofo\n", + "mmower/simply_versioned, id: 139, url: https://github.com/mmower/simply_versioned\n", + "abhay/gchart, id: 140, url: https://github.com/abhay/gchart\n", + "benburkert/schemr, id: 141, url: https://github.com/benburkert/schemr\n", + "abhay/calais, id: 142, url: https://github.com/abhay/calais\n", + "mojombo/chronic, id: 144, url: https://github.com/mojombo/chronic\n", + "sr/git-wiki, id: 165, url: https://github.com/sr/git-wiki\n", + "automatthew/ambitious_activeldap, id: 176, url: https://github.com/automatthew/ambitious_activeldap\n", + "queso/signal-wiki, id: 177, url: https://github.com/queso/signal-wiki\n", + "drnic/ruby-on-rails-tmbundle, id: 179, url: https://github.com/drnic/ruby-on-rails-tmbundle\n", + "danwrong/low-pro-for-jquery, id: 185, url: https://github.com/danwrong/low-pro-for-jquery\n", + "wayneeseguin/merb-core, id: 186, url: https://github.com/wayneeseguin/merb-core\n", + "sr/dst, id: 190, url: https://github.com/sr/dst\n" + ] + } + ], + "prompt_number": 3 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If you omit the `number` parameter, github3.py will attempt to retrieve all of the public repositories available on GitHub. In order to iterate over all of them in a reasonable amount of time, you should authenticate like so:" + ] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "gh = github3.login('username', 'password')" + ], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": 4 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "for repository in gh.all_repositories():\n", + " print('{0} - id: {0.id}, url: {0.html_url}'.format(repository))" + ], + "language": "python", + "metadata": {}, + "outputs": [] + } + ], + "metadata": {} + } + ] +} \ No newline at end of file diff --git a/example-notebooks/contents-api.ipynb b/example-notebooks/contents-api.ipynb new file mode 100644 index 000000000..a71357553 --- /dev/null +++ b/example-notebooks/contents-api.ipynb @@ -0,0 +1,612 @@ +{ + "metadata": { + "name": "", + "signature": "sha256:2a5438fc20dfd72328eb42f08327a4c176de03fe0009f6a33ecd15f27d7f51df" + }, + "nbformat": 3, + "nbformat_minor": 0, + "worksheets": [ + { + "cells": [ + { + "cell_type": "heading", + "level": 1, + "metadata": {}, + "source": [ + "Contents API" + ] + }, + { + "cell_type": "heading", + "level": 2, + "metadata": {}, + "source": [ + "Retrieving a File's Contents" + ] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "import github3" + ], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": 1 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "repo = github3.repository('sigmavirus24', 'github3.py')" + ], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": 2 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "contents = repo.file_contents('github3/repos/contents.py')" + ], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": 3 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now that we have the contents of the file at `github3/repos/contents.py` we can get information about it. We can find the name, the SHA of the commit that most recently updated it, etc." + ] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "print(contents.name)" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "contents.py\n" + ] + } + ], + "prompt_number": 4 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "print(contents.sha)" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "ec9f27e0cc18a5440952ebb7dc9b3b9402b93702\n" + ] + } + ], + "prompt_number": 5 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can also get the contents of the file:" + ] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "print(contents.content)" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "IyAtKi0gY29kaW5nOiB1dGYtOCAtKi0KIiIiCmdpdGh1YjMucmVwb3MuY29u\n", + "dGVudHMKPT09PT09PT09PT09PT09PT09PT09PQoKVGhpcyBtb2R1bGUgY29u\n", + "dGFpbnMgdGhlIENvbnRlbnRzIG9iamVjdCBwZXJ0YWluaW5nIHRvIFJFQURN\n", + "RXMgYW5kIG90aGVyIGZpbGVzCnRoYXQgY2FuIGJlIGFjY2Vzc2VkIHZpYSB0\n", + "aGUgR2l0SHViIEFQSS4KCiIiIgpmcm9tIF9fZnV0dXJlX18gaW1wb3J0IHVu\n", + "aWNvZGVfbGl0ZXJhbHMKCmZyb20ganNvbiBpbXBvcnQgZHVtcHMKZnJvbSBi\n", + "YXNlNjQgaW1wb3J0IGI2NGRlY29kZSwgYjY0ZW5jb2RlCmZyb20gLi5naXQg\n", + "aW1wb3J0IENvbW1pdApmcm9tIC4ubW9kZWxzIGltcG9ydCBHaXRIdWJDb3Jl\n", + "CmZyb20gLi5kZWNvcmF0b3JzIGltcG9ydCByZXF1aXJlc19hdXRoCgoKY2xh\n", + "c3MgQ29udGVudHMoR2l0SHViQ29yZSk6CiAgICAiIiJUaGUgOmNsYXNzOmBD\n", + "b250ZW50cyA8Q29udGVudHM+YCBvYmplY3QuIEl0IGhvbGRzIHRoZSBpbmZv\n", + "cm1hdGlvbgogICAgY29uY2VybmluZyBhbnkgY29udGVudCBpbiBhIHJlcG9z\n", + "aXRvcnkgcmVxdWVzdGVkIHZpYSB0aGUgQVBJLgoKICAgIFR3byBjb250ZW50\n", + "IGluc3RhbmNlcyBjYW4gYmUgY2hlY2tlZCBsaWtlIHNvOjoKCiAgICAgICAg\n", + "YzEgPT0gYzIKICAgICAgICBjMSAhPSBjMgoKICAgIEFuZCBpcyBlcXVpdmFs\n", + "ZW50IHRvOjoKCiAgICAgICAgYzEuc2hhID09IGMyLnNoYQogICAgICAgIGMx\n", + "LnNoYSAhPSBjMi5zaGEKCiAgICBTZWUgYWxzbzogaHR0cDovL2RldmVsb3Bl\n", + "ci5naXRodWIuY29tL3YzL3JlcG9zL2NvbnRlbnRzLwogICAgIiIiCiAgICBk\n", + "ZWYgX3VwZGF0ZV9hdHRyaWJ1dGVzKHNlbGYsIGNvbnRlbnQpOgogICAgICAg\n", + "ICMgbGlua3MKICAgICAgICBzZWxmLl9hcGkgPSBjb250ZW50LmdldCgndXJs\n", + "JykKICAgICAgICAjOiBEaWN0aW9uYXJ5IG9mIGxpbmtzCiAgICAgICAgc2Vs\n", + "Zi5saW5rcyA9IGNvbnRlbnQuZ2V0KCdfbGlua3MnKQoKICAgICAgICAjOiBV\n", + "Ukwgb2YgdGhlIFJFQURNRSBvbiBnaXRodWIuY29tCiAgICAgICAgc2VsZi5o\n", + "dG1sX3VybCA9IGNvbnRlbnQuZ2V0KCdodG1sX3VybCcpCgogICAgICAgICM6\n", + "IFVSTCBmb3IgdGhlIGdpdCBhcGkgcGVydGFpbmluZyB0byB0aGUgUkVBRE1F\n", + "CiAgICAgICAgc2VsZi5naXRfdXJsID0gY29udGVudC5nZXQoJ2dpdF91cmwn\n", + "KQoKICAgICAgICAjOiBnaXQ6Ly8gVVJMIG9mIHRoZSBjb250ZW50IGlmIGl0\n", + "IGlzIGEgc3VibW9kdWxlCiAgICAgICAgc2VsZi5zdWJtb2R1bGVfZ2l0X3Vy\n", + "bCA9IGNvbnRlbnQuZ2V0KCdzdWJtb2R1bGVfZ2l0X3VybCcpCgogICAgICAg\n", + "ICMgc2hvdWxkIGFsd2F5cyBiZSAnYmFzZTY0JwogICAgICAgICM6IFJldHVy\n", + "bnMgZW5jb2RpbmcgdXNlZCBvbiB0aGUgY29udGVudC4KICAgICAgICBzZWxm\n", + "LmVuY29kaW5nID0gY29udGVudC5nZXQoJ2VuY29kaW5nJywgJycpCgogICAg\n", + "ICAgICMgY29udGVudCwgYmFzZTY0IGVuY29kZWQgYW5kIGRlY29kZWQKICAg\n", + "ICAgICAjOiBCYXNlNjQtZW5jb2RlZCBjb250ZW50IG9mIHRoZSBmaWxlLgog\n", + "ICAgICAgIHNlbGYuY29udGVudCA9IGNvbnRlbnQuZ2V0KCdjb250ZW50Jywg\n", + "JycpCgogICAgICAgICM6IERlY29kZWQgY29udGVudCBvZiB0aGUgZmlsZSBh\n", + "cyBhIGJ5dGVzIG9iamVjdC4gSWYgd2UgdHJ5IHRvIGRlY29kZQogICAgICAg\n", + "ICM6IHRvIGNoYXJhY3RlciBzZXQgZm9yIHlvdSwgd2UgbWlnaHQgZW5jb3Vu\n", + "dGVyIGFuIGV4Y2VwdGlvbiB3aGljaAogICAgICAgICM6IHdpbGwgcHJldmVu\n", + "dCB0aGUgb2JqZWN0IGZyb20gYmVpbmcgY3JlYXRlZC4gT24gcHl0aG9uMiB0\n", + "aGlzIGlzIHRoZQogICAgICAgICM6IHNhbWUgYXMgYSBzdHJpbmcsIGJ1dCBv\n", + "biBweXRob24zIHlvdSBzaG91bGQgY2FsbCB0aGUgZGVjb2RlIG1ldGhvZAog\n", + "ICAgICAgICM6IHdpdGggdGhlIGNoYXJhY3RlciBzZXQgeW91IHdpc2ggdG8g\n", + "dXNlLCBlLmcuLAogICAgICAgICM6IGBgY29udGVudC5kZWNvZGVkLmRlY29k\n", + "ZSgndXRmLTgnKWBgLgogICAgICAgICM6IC4uIHZlcnNpb25jaGFuZ2VkOjog\n", + "MC41LjIKICAgICAgICBzZWxmLmRlY29kZWQgPSAnJwogICAgICAgIGlmIHNl\n", + "bGYuZW5jb2RpbmcgPT0gJ2Jhc2U2NCcgYW5kIHNlbGYuY29udGVudDoKICAg\n", + "ICAgICAgICAgc2VsZi5kZWNvZGVkID0gYjY0ZGVjb2RlKHNlbGYuY29udGVu\n", + "dC5lbmNvZGUoKSkKCiAgICAgICAgIyBmaWxlIG5hbWUsIHBhdGgsIGFuZCBz\n", + "aXplCiAgICAgICAgIzogTmFtZSBvZiB0aGUgY29udGVudC4KICAgICAgICBz\n", + "ZWxmLm5hbWUgPSBjb250ZW50LmdldCgnbmFtZScsICcnKQogICAgICAgICM6\n", + "IFBhdGggdG8gdGhlIGNvbnRlbnQuCiAgICAgICAgc2VsZi5wYXRoID0gY29u\n", + "dGVudC5nZXQoJ3BhdGgnLCAnJykKICAgICAgICAjOiBTaXplIG9mIHRoZSBj\n", + "b250ZW50CiAgICAgICAgc2VsZi5zaXplID0gY29udGVudC5nZXQoJ3NpemUn\n", + "LCAwKQogICAgICAgICM6IFNIQSBzdHJpbmcuCiAgICAgICAgc2VsZi5zaGEg\n", + "PSBjb250ZW50LmdldCgnc2hhJywgJycpCiAgICAgICAgIzogVHlwZSBvZiBj\n", + "b250ZW50LiAoJ2ZpbGUnLCAnc3ltbGluaycsICdzdWJtb2R1bGUnKQogICAg\n", + "ICAgIHNlbGYudHlwZSA9IGNvbnRlbnQuZ2V0KCd0eXBlJywgJycpCiAgICAg\n", + "ICAgIzogVGFyZ2V0IHdpbGwgb25seSBiZSBzZXQgb2YgdHlwZSBpcyBhIHN5\n", + "bWxpbmsuIFRoaXMgaXMgd2hhdCB0aGUgbGluawogICAgICAgICM6IHBvaW50\n", + "cyB0bwogICAgICAgIHNlbGYudGFyZ2V0ID0gY29udGVudC5nZXQoJ3Rhcmdl\n", + "dCcsICcnKQoKICAgICAgICBzZWxmLl91bmlxID0gc2VsZi5zaGEKCiAgICBk\n", + "ZWYgX3JlcHIoc2VsZik6CiAgICAgICAgcmV0dXJuICc8Q29udGVudCBbezB9\n", + "XT4nLmZvcm1hdChzZWxmLnBhdGgpCgogICAgZGVmIF9fZXFfXyhzZWxmLCBv\n", + "dGhlcik6CiAgICAgICAgcmV0dXJuIHNlbGYuZGVjb2RlZCA9PSBvdGhlcgoK\n", + "ICAgIGRlZiBfX25lX18oc2VsZiwgb3RoZXIpOgogICAgICAgIHJldHVybiBz\n", + "ZWxmLnNoYSAhPSBvdGhlcgoKICAgIEByZXF1aXJlc19hdXRoCiAgICBkZWYg\n", + "ZGVsZXRlKHNlbGYsIG1lc3NhZ2UsIGNvbW1pdHRlcj1Ob25lLCBhdXRob3I9\n", + "Tm9uZSk6CiAgICAgICAgIiIiRGVsZXRlIHRoaXMgZmlsZS4KCiAgICAgICAg\n", + "OnBhcmFtIHN0ciBtZXNzYWdlOiAocmVxdWlyZWQpLCBjb21taXQgbWVzc2Fn\n", + "ZSB0byBkZXNjcmliZSB0aGUgcmVtb3ZhbAogICAgICAgIDpwYXJhbSBkaWN0\n", + "IGNvbW1pdHRlcjogKG9wdGlvbmFsKSwgaWYgbm8gaW5mb3JtYXRpb24gaXMg\n", + "Z2l2ZW4gdGhlCiAgICAgICAgICAgIGF1dGhlbnRpY2F0ZWQgdXNlcidzIGlu\n", + "Zm9ybWF0aW9uIHdpbGwgYmUgdXNlZC4gWW91IG11c3Qgc3BlY2lmeQogICAg\n", + "ICAgICAgICBib3RoIGEgbmFtZSBhbmQgZW1haWwuCiAgICAgICAgOnBhcmFt\n", + "IGRpY3QgYXV0aG9yOiAob3B0aW9uYWwpLCBpZiBvbWl0dGVkIHRoaXMgd2ls\n", + "bCBiZSBmaWxsZWQgaW4gd2l0aAogICAgICAgICAgICBjb21taXR0ZXIgaW5m\n", + "b3JtYXRpb24uIElmIHBhc3NlZCwgeW91IG11c3Qgc3BlY2lmeSBib3RoIGEg\n", + "bmFtZSBhbmQKICAgICAgICAgICAgZW1haWwuCiAgICAgICAgOnJldHVybnM6\n", + "IGRpY3Rpb25hcnkgb2YgbmV3IGNvbnRlbnQgYW5kIGFzc29jaWF0ZWQgY29t\n", + "bWl0CiAgICAgICAgOnJ0eXBlOiA6Y2xhc3M6YH5naXRodWIzLnJlcG9zLmNv\n", + "bnRlbnRzLkNvbnRlbnRzYCBhbmQKICAgICAgICAgICAgOmNsYXNzOmB+Z2l0\n", + "aHViMy5naXQuQ29tbWl0YAogICAgICAgICIiIgogICAgICAgIGpzb24gPSB7\n", + "fQogICAgICAgIGlmIG1lc3NhZ2U6CiAgICAgICAgICAgIGRhdGEgPSB7J21l\n", + "c3NhZ2UnOiBtZXNzYWdlLCAnc2hhJzogc2VsZi5zaGEsCiAgICAgICAgICAg\n", + "ICAgICAgICAgJ2NvbW1pdHRlcic6IHZhbGlkYXRlX2NvbW1taXR0ZXIoY29t\n", + "bWl0dGVyKSwKICAgICAgICAgICAgICAgICAgICAnYXV0aG9yJzogdmFsaWRh\n", + "dGVfY29tbW1pdHRlcihhdXRob3IpfQogICAgICAgICAgICBzZWxmLl9yZW1v\n", + "dmVfbm9uZShkYXRhKQogICAgICAgICAgICBqc29uID0gc2VsZi5fanNvbihz\n", + "ZWxmLl9kZWxldGUoc2VsZi5fYXBpLCBkYXRhPWR1bXBzKGRhdGEpKSwgMjAw\n", + "KQogICAgICAgICAgICBpZiAnY29tbWl0JyBpbiBqc29uOgogICAgICAgICAg\n", + "ICAgICAganNvblsnY29tbWl0J10gPSBDb21taXQoanNvblsnY29tbWl0J10s\n", + "IHNlbGYpCiAgICAgICAgICAgIGlmICdjb250ZW50JyBpbiBqc29uOgogICAg\n", + "ICAgICAgICAgICAganNvblsnY29udGVudCddID0gc2VsZi5faW5zdGFuY2Vf\n", + "b3JfbnVsbChDb250ZW50cywKICAgICAgICAgICAgICAgICAgICAgICAgICAg\n", + "ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAganNvblsnY29udGVudCdd\n", + "KQogICAgICAgIHJldHVybiBqc29uCgogICAgQHJlcXVpcmVzX2F1dGgKICAg\n", + "IGRlZiB1cGRhdGUoc2VsZiwgbWVzc2FnZSwgY29udGVudCwgY29tbWl0dGVy\n", + "PU5vbmUsIGF1dGhvcj1Ob25lKToKICAgICAgICAiIiJVcGRhdGUgdGhpcyBm\n", + "aWxlLgoKICAgICAgICA6cGFyYW0gc3RyIG1lc3NhZ2U6IChyZXF1aXJlZCks\n", + "IGNvbW1pdCBtZXNzYWdlIHRvIGRlc2NyaWJlIHRoZSB1cGRhdGUKICAgICAg\n", + "ICA6cGFyYW0gc3RyIGNvbnRlbnQ6IChyZXF1aXJlZCksIGNvbnRlbnQgdG8g\n", + "dXBkYXRlIHRoZSBmaWxlIHdpdGgKICAgICAgICA6cGFyYW0gZGljdCBjb21t\n", + "aXR0ZXI6IChvcHRpb25hbCksIGlmIG5vIGluZm9ybWF0aW9uIGlzIGdpdmVu\n", + "IHRoZQogICAgICAgICAgICBhdXRoZW50aWNhdGVkIHVzZXIncyBpbmZvcm1h\n", + "dGlvbiB3aWxsIGJlIHVzZWQuIFlvdSBtdXN0IHNwZWNpZnkKICAgICAgICAg\n", + "ICAgYm90aCBhIG5hbWUgYW5kIGVtYWlsLgogICAgICAgIDpwYXJhbSBkaWN0\n", + "IGF1dGhvcjogKG9wdGlvbmFsKSwgaWYgb21pdHRlZCB0aGlzIHdpbGwgYmUg\n", + "ZmlsbGVkIGluIHdpdGgKICAgICAgICAgICAgY29tbWl0dGVyIGluZm9ybWF0\n", + "aW9uLiBJZiBwYXNzZWQsIHlvdSBtdXN0IHNwZWNpZnkgYm90aCBhIG5hbWUg\n", + "YW5kCiAgICAgICAgICAgIGVtYWlsLgogICAgICAgIDpyZXR1cm5zOiBkaWN0\n", + "aW9uYXJ5IGNvbnRhaW5pbmcgdGhlIHVwZGF0ZWQgY29udGVudHMgb2JqZWN0\n", + "IGFuZCB0aGUKICAgICAgICAgICAgY29tbWl0IGluIHdoaWNoIGl0IHdhcyBj\n", + "aGFuZ2VkLgogICAgICAgIDpydHlwZTogZGljdGlvbmFyeSBvZiA6Y2xhc3M6\n", + "YH5naXRodWIzLnJlcG9zLmNvbnRlbnRzLkNvbnRlbnRzYCBhbmQKICAgICAg\n", + "ICAgICAgOmNsYXNzOmB+Z2l0aHViMy5naXQuQ29tbWl0YAogICAgICAgICIi\n", + "IgogICAgICAgIGlmIGNvbnRlbnQgYW5kIG5vdCBpc2luc3RhbmNlKGNvbnRl\n", + "bnQsIGJ5dGVzKToKICAgICAgICAgICAgcmFpc2UgVmFsdWVFcnJvciggICMg\n", + "KE5vIGNvdmVyYWdlKQogICAgICAgICAgICAgICAgJ2NvbnRlbnQgbXVzdCBi\n", + "ZSBhIGJ5dGVzIG9iamVjdCcpICAjIChObyBjb3ZlcmFnZSkKCiAgICAgICAg\n", + "anNvbiA9IE5vbmUKICAgICAgICBpZiBtZXNzYWdlIGFuZCBjb250ZW50Ogog\n", + "ICAgICAgICAgICBjb250ZW50ID0gYjY0ZW5jb2RlKGNvbnRlbnQpLmRlY29k\n", + "ZSgndXRmLTgnKQogICAgICAgICAgICBkYXRhID0geydtZXNzYWdlJzogbWVz\n", + "c2FnZSwgJ2NvbnRlbnQnOiBjb250ZW50LCAnc2hhJzogc2VsZi5zaGEsCiAg\n", + "ICAgICAgICAgICAgICAgICAgJ2NvbW1pdHRlcic6IHZhbGlkYXRlX2NvbW1t\n", + "aXR0ZXIoY29tbWl0dGVyKSwKICAgICAgICAgICAgICAgICAgICAnYXV0aG9y\n", + "JzogdmFsaWRhdGVfY29tbW1pdHRlcihhdXRob3IpfQogICAgICAgICAgICBz\n", + "ZWxmLl9yZW1vdmVfbm9uZShkYXRhKQogICAgICAgICAgICBqc29uID0gc2Vs\n", + "Zi5fanNvbihzZWxmLl9wdXQoc2VsZi5fYXBpLCBkYXRhPWR1bXBzKGRhdGEp\n", + "KSwgMjAwKQogICAgICAgICAgICBpZiAnY29udGVudCcgaW4ganNvbjoKICAg\n", + "ICAgICAgICAgICAgIHNlbGYuX3VwZGF0ZV9hdHRyaWJ1dGVzKGpzb25bJ2Nv\n", + "bnRlbnQnXSkKICAgICAgICAgICAgICAgIGpzb25bJ2NvbnRlbnQnXSA9IHNl\n", + "bGYKICAgICAgICAgICAgaWYgJ2NvbW1pdCcgaW4ganNvbjoKICAgICAgICAg\n", + "ICAgICAgIGpzb25bJ2NvbW1pdCddID0gQ29tbWl0KGpzb25bJ2NvbW1pdCdd\n", + "LCBzZWxmKQogICAgICAgIHJldHVybiBqc29uCgoKZGVmIHZhbGlkYXRlX2Nv\n", + "bW1taXR0ZXIoZCk6CiAgICBpZiBkIGFuZCBkLmdldCgnbmFtZScpIGFuZCBk\n", + "LmdldCgnZW1haWwnKToKICAgICAgICByZXR1cm4gZAogICAgcmV0dXJuIE5v\n", + "bmUK\n", + "\n" + ] + } + ], + "prompt_number": 6 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "But that's base64 encoded text. So github3.py provides the content decoded as well:" + ] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "print(contents.decoded)" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "# -*- coding: utf-8 -*-\n", + "\"\"\"\n", + "github3.repos.contents\n", + "======================\n", + "\n", + "This module contains the Contents object pertaining to READMEs and other files\n", + "that can be accessed via the GitHub API.\n", + "\n", + "\"\"\"\n", + "from __future__ import unicode_literals\n", + "\n", + "from json import dumps\n", + "from base64 import b64decode, b64encode\n", + "from ..git import Commit\n", + "from ..models import GitHubCore\n", + "from ..decorators import requires_auth\n", + "\n", + "\n", + "class Contents(GitHubCore):\n", + " \"\"\"The :class:`Contents ` object. It holds the information\n", + " concerning any content in a repository requested via the API.\n", + "\n", + " Two content instances can be checked like so::\n", + "\n", + " c1 == c2\n", + " c1 != c2\n", + "\n", + " And is equivalent to::\n", + "\n", + " c1.sha == c2.sha\n", + " c1.sha != c2.sha\n", + "\n", + " See also: http://developer.github.com/v3/repos/contents/\n", + " \"\"\"\n", + " def _update_attributes(self, content):\n", + " # links\n", + " self._api = content.get('url')\n", + " #: Dictionary of links\n", + " self.links = content.get('_links')\n", + "\n", + " #: URL of the README on github.com\n", + " self.html_url = content.get('html_url')\n", + "\n", + " #: URL for the git api pertaining to the README\n", + " self.git_url = content.get('git_url')\n", + "\n", + " #: git:// URL of the content if it is a submodule\n", + " self.submodule_git_url = content.get('submodule_git_url')\n", + "\n", + " # should always be 'base64'\n", + " #: Returns encoding used on the content.\n", + " self.encoding = content.get('encoding', '')\n", + "\n", + " # content, base64 encoded and decoded\n", + " #: Base64-encoded content of the file.\n", + " self.content = content.get('content', '')\n", + "\n", + " #: Decoded content of the file as a bytes object. If we try to decode\n", + " #: to character set for you, we might encounter an exception which\n", + " #: will prevent the object from being created. On python2 this is the\n", + " #: same as a string, but on python3 you should call the decode method\n", + " #: with the character set you wish to use, e.g.,\n", + " #: ``content.decoded.decode('utf-8')``.\n", + " #: .. versionchanged:: 0.5.2\n", + " self.decoded = ''\n", + " if self.encoding == 'base64' and self.content:\n", + " self.decoded = b64decode(self.content.encode())\n", + "\n", + " # file name, path, and size\n", + " #: Name of the content.\n", + " self.name = content.get('name', '')\n", + " #: Path to the content.\n", + " self.path = content.get('path', '')\n", + " #: Size of the content\n", + " self.size = content.get('size', 0)\n", + " #: SHA string.\n", + " self.sha = content.get('sha', '')\n", + " #: Type of content. ('file', 'symlink', 'submodule')\n", + " self.type = content.get('type', '')\n", + " #: Target will only be set of type is a symlink. This is what the link\n", + " #: points to\n", + " self.target = content.get('target', '')\n", + "\n", + " self._uniq = self.sha\n", + "\n", + " def _repr(self):\n", + " return ''.format(self.path)\n", + "\n", + " def __eq__(self, other):\n", + " return self.decoded == other\n", + "\n", + " def __ne__(self, other):\n", + " return self.sha != other\n", + "\n", + " @requires_auth\n", + " def delete(self, message, committer=None, author=None):\n", + " \"\"\"Delete this file.\n", + "\n", + " :param str message: (required), commit message to describe the removal\n", + " :param dict committer: (optional), if no information is given the\n", + " authenticated user's information will be used. You must specify\n", + " both a name and email.\n", + " :param dict author: (optional), if omitted this will be filled in with\n", + " committer information. If passed, you must specify both a name and\n", + " email.\n", + " :returns: dictionary of new content and associated commit\n", + " :rtype: :class:`~github3.repos.contents.Contents` and\n", + " :class:`~github3.git.Commit`\n", + " \"\"\"\n", + " json = {}\n", + " if message:\n", + " data = {'message': message, 'sha': self.sha,\n", + " 'committer': validate_commmitter(committer),\n", + " 'author': validate_commmitter(author)}\n", + " self._remove_none(data)\n", + " json = self._json(self._delete(self._api, data=dumps(data)), 200)\n", + " if 'commit' in json:\n", + " json['commit'] = Commit(json['commit'], self)\n", + " if 'content' in json:\n", + " json['content'] = self._instance_or_null(Contents,\n", + " json['content'])\n", + " return json\n", + "\n", + " @requires_auth\n", + " def update(self, message, content, committer=None, author=None):\n", + " \"\"\"Update this file.\n", + "\n", + " :param str message: (required), commit message to describe the update\n", + " :param str content: (required), content to update the file with\n", + " :param dict committer: (optional), if no information is given the\n", + " authenticated user's information will be used. You must specify\n", + " both a name and email.\n", + " :param dict author: (optional), if omitted this will be filled in with\n", + " committer information. If passed, you must specify both a name and\n", + " email.\n", + " :returns: dictionary containing the updated contents object and the\n", + " commit in which it was changed.\n", + " :rtype: dictionary of :class:`~github3.repos.contents.Contents` and\n", + " :class:`~github3.git.Commit`\n", + " \"\"\"\n", + " if content and not isinstance(content, bytes):\n", + " raise ValueError( # (No coverage)\n", + " 'content must be a bytes object') # (No coverage)\n", + "\n", + " json = None\n", + " if message and content:\n", + " content = b64encode(content).decode('utf-8')\n", + " data = {'message': message, 'content': content, 'sha': self.sha,\n", + " 'committer': validate_commmitter(committer),\n", + " 'author': validate_commmitter(author)}\n", + " self._remove_none(data)\n", + " json = self._json(self._put(self._api, data=dumps(data)), 200)\n", + " if 'content' in json:\n", + " self._update_attributes(json['content'])\n", + " json['content'] = self\n", + " if 'commit' in json:\n", + " json['commit'] = Commit(json['commit'], self)\n", + " return json\n", + "\n", + "\n", + "def validate_commmitter(d):\n", + " if d and d.get('name') and d.get('email'):\n", + " return d\n", + " return None\n", + "\n" + ] + } + ], + "prompt_number": 7 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "github3.py tries to preserve original names of data it receives so that users can access that easily and without having to guess. From here, (if we were logged in) we could easily update or even delete this file altogether." + ] + }, + { + "cell_type": "heading", + "level": 2, + "metadata": {}, + "source": [ + "Retrieving a directory's contents" + ] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "import github3" + ], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": 8 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "repo = github3.repository('sigmavirus24', 'github3.py')" + ], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": 9 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "dir_contents = repo.directory_contents('github3/search/')" + ], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": 10 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "dir_contents" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "metadata": {}, + "output_type": "pyout", + "prompt_number": 11, + "text": [ + "[(u'__init__.py', ),\n", + " (u'code.py', ),\n", + " (u'issue.py', ),\n", + " (u'repository.py', ),\n", + " (u'user.py', )]" + ] + } + ], + "prompt_number": 11 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "dc = dict(dir_contents)" + ], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": 12 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "dc['user.py'].decoded" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "metadata": {}, + "output_type": "pyout", + "prompt_number": 13, + "text": [ + "u''" + ] + } + ], + "prompt_number": 13 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In many instances when GitHub returns more than one instance of a resource, they don't return the entirety of each resource. Here's we have an example of this. The file bodies would be expensive to return for a directory with a lot of files, so GitHub omits them. We can still retrieve it. We just need to make another call to the API for the information." + ] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "dc['user.py'].refresh()\n", + "print(dc['user.py'].decoded)" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "# -*- coding: utf-8 -*-\n", + "from __future__ import unicode_literals\n", + "\n", + "from ..models import GitHubCore\n", + "from ..users import User\n", + "\n", + "\n", + "class UserSearchResult(GitHubCore):\n", + " def _update_attributes(self, data):\n", + " result = data.copy()\n", + " #: Score of this search result\n", + " self.score = result.pop('score')\n", + " #: Text matches\n", + " self.text_matches = result.pop('text_matches', [])\n", + " #: User object matching the search\n", + " self.user = User(result, self)\n", + "\n", + " def _repr(self):\n", + " return ''.format(self.user)\n", + "\n" + ] + } + ], + "prompt_number": 15 + } + ], + "metadata": {} + } + ] +} \ No newline at end of file diff --git a/example-notebooks/forking_repositories_by.ipynb b/example-notebooks/forking_repositories_by.ipynb new file mode 100644 index 000000000..a4fbc49db --- /dev/null +++ b/example-notebooks/forking_repositories_by.ipynb @@ -0,0 +1,176 @@ +{ + "metadata": { + "name": "", + "signature": "sha256:2d234b400db23a8a564289d081cd262369729acb74813177cd991585e0f66fe9" + }, + "nbformat": 3, + "nbformat_minor": 0, + "worksheets": [ + { + "cells": [ + { + "cell_type": "heading", + "level": 1, + "metadata": {}, + "source": [ + "Listing repositories by their owner" + ] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "import github3" + ], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": 1 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "for repository in github3.repositories_by('sigmavirus24'):\n", + " print('{0} created at {0.created_at}'.format(repository))" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "sigmavirus24/betamax created at 2013-07-16 03:23:22+00:00\n", + "sigmavirus24/betamax_matchers created at 2014-07-19 18:51:39+00:00\n", + "sigmavirus24/catapultpgh created at 2013-02-11 17:16:43+00:00\n", + "sigmavirus24/charade created at 2012-11-28 03:24:20+00:00\n", + "sigmavirus24/clint created at 2013-02-10 21:09:02+00:00\n", + "sigmavirus24/contrib-hub created at 2013-11-30 18:36:55+00:00\n", + "sigmavirus24/crequests created at 2013-01-24 22:54:17+00:00\n", + "sigmavirus24/curryer created at 2013-11-10 02:03:42+00:00\n", + "sigmavirus24/c_libs created at 2012-06-11 14:45:35+00:00\n", + "sigmavirus24/ddg created at 2012-12-16 22:11:35+00:00\n", + "sigmavirus24/developer.github.com created at 2012-05-27 04:19:17+00:00\n", + "sigmavirus24/dream-python created at 2014-08-13 15:55:44+00:00\n", + "sigmavirus24/elephant created at 2013-03-27 18:25:03+00:00\n", + "sigmavirus24/euler.hs created at 2013-10-19 01:19:03+00:00\n", + "sigmavirus24/expecter created at 2012-07-25 03:02:58+00:00\n", + "sigmavirus24/format-geojson.clj created at 2013-10-25 22:17:20+00:00\n", + "sigmavirus24/ghsync created at 2012-10-17 13:49:42+00:00\n", + "sigmavirus24/git-hub created at 2012-10-05 19:35:45+00:00\n", + "sigmavirus24/GITenberg created at 2012-09-25 21:07:30+00:00\n", + "sigmavirus24/github-cli created at 2012-07-05 14:58:47+00:00\n", + "sigmavirus24/github3.py created at 2012-03-13 19:58:53+00:00\n", + "sigmavirus24/GitPython created at 2012-11-28 16:27:22+00:00\n", + "sigmavirus24/grequests created at 2012-12-30 23:04:12+00:00\n", + "sigmavirus24/gtk-vikb created at 2012-07-16 23:18:15+00:00\n", + "sigmavirus24/heroku-buildpack-python created at 2013-01-19 18:09:35+00:00\n", + "sigmavirus24/http11 created at 2014-07-21 01:57:47+00:00\n", + "sigmavirus24/httpbin created at 2013-07-19 18:53:30+00:00\n", + "sigmavirus24/hyper created at 2014-02-20 16:02:48+00:00\n", + "sigmavirus24/issues.py created at 2012-02-25 21:32:31+00:00\n", + "sigmavirus24/LendingClubAutoInvestor created at 2013-05-08 14:56:33+00:00\n", + "sigmavirus24/libyaml created at 2013-12-01 18:27:17+00:00\n", + "sigmavirus24/lyahfgg created at 2013-07-31 02:47:36+00:00\n", + "sigmavirus24/madison_geojson created at 2013-10-25 20:40:41+00:00\n", + "sigmavirus24/mccabe created at 2014-04-18 18:30:26+00:00\n", + "sigmavirus24/mixfaster created at 2012-06-30 00:13:21+00:00\n", + "sigmavirus24/mixminion created at 2011-09-06 13:34:15+00:00\n", + "sigmavirus24/mock_github_api created at 2012-12-21 23:14:08+00:00\n", + "sigmavirus24/nothub created at 2013-01-29 18:00:15+00:00\n", + "sigmavirus24/No_Agenda_Bat_Sig created at 2010-11-05 03:18:10+00:00\n", + "sigmavirus24/octokit.rb created at 2013-12-12 02:32:30+00:00\n", + "sigmavirus24/ordinary created at 2013-06-15 18:09:48+00:00\n", + "sigmavirus24/patch-converter created at 2012-11-26 13:52:57+00:00\n", + "sigmavirus24/pelican created at 2012-06-14 14:25:45+00:00\n", + "sigmavirus24/pelican-themes created at 2012-06-14 13:51:35+00:00\n", + "sigmavirus24/pep8 created at 2012-09-06 14:13:14+00:00\n", + "sigmavirus24/pip created at 2014-01-07 14:27:24+00:00\n", + "sigmavirus24/polynomials.py created at 2013-04-10 03:12:06+00:00\n", + "sigmavirus24/PyF-ck created at 2013-05-01 22:14:11+00:00\n", + "sigmavirus24/pyflakes created at 2014-07-23 15:06:17+00:00\n", + "sigmavirus24/pyflakes-old created at 2013-01-28 00:25:27+00:00\n", + "sigmavirus24/python-guide created at 2012-06-15 18:00:03+00:00\n", + "sigmavirus24/python-interview-questions created at 2014-08-13 02:32:38+00:00\n", + "sigmavirus24/pyyaml created at 2013-12-01 18:29:02+00:00\n", + "sigmavirus24/rack created at 2014-07-13 00:51:30+00:00\n", + "sigmavirus24/recipes created at 2013-01-25 04:31:44+00:00\n", + "sigmavirus24/repl_fun created at 2013-03-30 15:13:42+00:00\n", + "sigmavirus24/requests created at 2012-06-15 13:47:06+00:00\n", + "sigmavirus24/requests-data-schemes created at 2013-01-07 04:49:50+00:00\n", + "sigmavirus24/requests-ntlm created at 2014-07-18 21:32:31+00:00\n", + "sigmavirus24/requests-toolbelt created at 2013-12-29 21:19:08+00:00\n", + "sigmavirus24/requests.rb created at 2013-02-01 02:52:28+00:00\n", + "sigmavirus24/rfc3986 created at 2014-06-25 14:25:11+00:00\n", + "sigmavirus24/shipit created at 2013-05-22 19:32:18+00:00\n", + "sigmavirus24/solarized-pygment created at 2013-01-13 23:36:54+00:00\n", + "sigmavirus24/sprunge.py created at 2012-06-09 14:19:26+00:00\n", + "sigmavirus24/subscribed created at 2012-10-07 03:40:31+00:00\n", + "sigmavirus24/Todo.txt-python created at 2012-09-16 19:31:58+00:00\n", + "sigmavirus24/update_firefox created at 2012-06-19 01:56:02+00:00\n", + "sigmavirus24/uritemplate created at 2013-05-14 16:52:08+00:00\n", + "sigmavirus24/urllib3 created at 2013-12-04 03:04:13+00:00\n", + "sigmavirus24/vcr created at 2013-09-18 03:15:42+00:00\n", + "sigmavirus24/vim-stopsign created at 2013-09-03 13:26:03+00:00\n", + "sigmavirus24/www.gittip.com created at 2013-01-16 13:15:38+00:00\n", + "sigmavirus24/x11-ssh-askpass created at 2011-09-08 15:25:05+00:00\n", + "sigmavirus24/zero created at 2013-09-15 02:17:30+00:00\n", + "sigmavirus24/zero_buffer created at 2014-07-31 18:46:36+00:00\n" + ] + } + ], + "prompt_number": 2 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You can also login and fork each of these repositories." + ] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "gh = github3.login('username', 'password')" + ], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": 3 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "for repository in gh.repositories_by('sigmavirus24'):\n", + " repository.create_fork()" + ], + "language": "python", + "metadata": {}, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If you wanted to fork an organization to you, you could do the following: " + ] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "for repository in gh.repositories_by('sigmavirus24'):\n", + " repository.create_fork('my-organization')" + ], + "language": "python", + "metadata": {}, + "outputs": [] + } + ], + "metadata": {} + } + ] +} \ No newline at end of file diff --git a/example-notebooks/issues.ipynb b/example-notebooks/issues.ipynb new file mode 100644 index 000000000..6b9302829 --- /dev/null +++ b/example-notebooks/issues.ipynb @@ -0,0 +1,241 @@ +{ + "metadata": { + "name": "", + "signature": "sha256:ed4e83114104bffcc56d1edfe91758409ac02198e3daf0df5518ba2420c3a6f0" + }, + "nbformat": 3, + "nbformat_minor": 0, + "worksheets": [ + { + "cells": [ + { + "cell_type": "heading", + "level": 1, + "metadata": {}, + "source": [ + "The Issues API in github3.py" + ] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "import github3" + ], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": 1 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "issue = github3.issue('sigmavirus24', 'github3.py', 187)" + ], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": 2 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "print(issue.comments_count)" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "3\n" + ] + } + ], + "prompt_number": 3 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "for label in issue.labels():\n", + " print(label)" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "Bug\n", + "Easy\n", + "Enhancement\n", + "Pair with Ian\n" + ] + } + ], + "prompt_number": 4 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "With an Issue object, we can retrieve a lot of information about the issue itself.\n", + "\n", + "We can also retrieve an issue's text (or body) in *three* ways:\n", + "\n", + "1. HTML\n", + "1. Plain text\n", + "1. Plain markdown" + ] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "print(issue.body_html)" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "

https://twitter.com/brian_curtin/status/420665317270900736 made me realize I never documented it at all.

\n", + "\n", + "

Also it needs to be added to the github3.login function. We need a few good examples to document it with.

\n" + ] + } + ], + "prompt_number": 5 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "print(issue.body_text)" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "https://twitter.com/brian_curtin/status/420665317270900736 made me realize I never documented it at all.\n", + "\n", + "Also it needs to be added to the github3.login function. We need a few good examples to document it with.\n" + ] + } + ], + "prompt_number": 6 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "print(issue.body)" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "https://twitter.com/brian_curtin/status/420665317270900736 made me realize I never documented it *at all*.\r\n", + "\r\n", + "Also it needs to be added to the `github3.login` function. We need a few good examples to document it with.\n" + ] + } + ], + "prompt_number": 10 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "print(issue.html_url)" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "https://github.com/sigmavirus24/github3.py/issues/187\n" + ] + } + ], + "prompt_number": 7 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "print('#{0.number}: \"{0.title}\" opened by {0.user}'.format(issue))" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "#187: \"Document two factor auth\" opened by sigmavirus24\n" + ] + } + ], + "prompt_number": 8 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "for comment in issue.comments():\n", + " print('\"{0.body_text}\" posted by {0.user}'.format(comment))\n", + " print('-' * 80)" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "\"Note to self: Don't merge without documentation :-p \n", + "\n", + "But I totally thought I had some REPL/iPython output from testing this when it was implemented that would have worked well for an example.\" posted by esacteksab\n", + "--------------------------------------------------------------------------------\n", + "\"On Tue, Jan 07, 2014 at 05:48:28PM -0800, Barry Morrison wrote:\n", + " Note to self: _Don't merge without documentation_ :-p\n", + "A thousand times this.\n", + " But I totally thought I had some REPL/iPython output from testing this when\n", + " it was implemented that would have worked well for an example.\n", + "I'll take it!\" posted by sigmavirus24\n", + "--------------------------------------------------------------------------------\n", + "\"Went back through my things. I don't have anything. :(\" posted by esacteksab\n", + "--------------------------------------------------------------------------------\n" + ] + } + ], + "prompt_number": 11 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "As you can see above [esacteksab](https://github.com/esacteksab) originally thought of using IPython notebooks to document github3.py" + ] + } + ], + "metadata": {} + } + ] +} diff --git a/example-notebooks/iterating_over_public_gists.ipynb b/example-notebooks/iterating_over_public_gists.ipynb new file mode 100644 index 000000000..96423e75c --- /dev/null +++ b/example-notebooks/iterating_over_public_gists.ipynb @@ -0,0 +1,132 @@ +{ + "metadata": { + "name": "", + "signature": "sha256:6aebb45445a1bc5b493ba1825ffdc9d557439c023767e0e1eb2503c915db0960" + }, + "nbformat": 3, + "nbformat_minor": 0, + "worksheets": [ + { + "cells": [ + { + "cell_type": "heading", + "level": 1, + "metadata": {}, + "source": [ + "An example of retrieving and iterating over public gists on GitHub" + ] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "import github3" + ], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": 1 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "for gist in github3.public_gists(number=50):\n", + " print('Gist {0.id} was created by {0.owner} on {0.created_at} and can be viewed at {0.html_url}'.format(gist))" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "Gist ac738b75a14615b88477 was created by adilakhter on 2014-08-17 19:20:24+00:00 and can be viewed at https://gist.github.com/ac738b75a14615b88477\n", + "Gist 0a9a309a9abcc6b5c4bf was created by openpanzer on 2014-08-17 19:20:10+00:00 and can be viewed at https://gist.github.com/0a9a309a9abcc6b5c4bf\n", + "Gist 7683f4f65b38f845db77 was created by rodoard on 2014-08-17 19:19:36+00:00 and can be viewed at https://gist.github.com/7683f4f65b38f845db77\n", + "Gist 9e0c32c8a14be8f5d5a6 was created by alexdgarland on 2014-08-17 19:18:18+00:00 and can be viewed at https://gist.github.com/9e0c32c8a14be8f5d5a6\n", + "Gist 0e7360f80a7c3e1314b1 was created by netsmertia on 2014-08-17 19:17:25+00:00 and can be viewed at https://gist.github.com/0e7360f80a7c3e1314b1\n", + "Gist 9d4801fea0a79a64d65f was created by johnjohnsp1 on 2014-08-17 19:16:57+00:00 and can be viewed at https://gist.github.com/9d4801fea0a79a64d65f\n", + "Gist 697b7c19baef76a7e255 was created by francescoagati on 2014-08-17 19:14:52+00:00 and can be viewed at https://gist.github.com/697b7c19baef76a7e255\n", + "Gist 2b3654bcc548ea46fd5a was created by jkhosla on 2014-08-17 19:14:37+00:00 and can be viewed at https://gist.github.com/2b3654bcc548ea46fd5a\n", + "Gist 52aef973e8cd3814273d was created by netsmertia on 2014-08-17 19:14:35+00:00 and can be viewed at https://gist.github.com/52aef973e8cd3814273d\n", + "Gist 0ebb15e96051435a8495 was created by ivycheung1208 on 2014-08-17 19:14:07+00:00 and can be viewed at https://gist.github.com/0ebb15e96051435a8495\n", + "Gist 3e5e5344a8f4d7497ccd was created by mitsuhiko on 2014-08-17 19:13:32+00:00 and can be viewed at https://gist.github.com/3e5e5344a8f4d7497ccd\n", + "Gist a5619a2de7ab2c207977 was created by asez73 on 2014-08-17 19:13:24+00:00 and can be viewed at https://gist.github.com/a5619a2de7ab2c207977\n", + "Gist 2a0ef712770ed207f046 was created by 1992chenlu on 2014-08-17 19:13:15+00:00 and can be viewed at https://gist.github.com/2a0ef712770ed207f046\n", + "Gist 81f1ea72ec368b282e12 was created by jdehlin on 2014-08-17 19:13:08+00:00 and can be viewed at https://gist.github.com/81f1ea72ec368b282e12\n", + "Gist 6c864bdfced90b81d0a4 was created by rodoard on 2014-08-17 19:12:48+00:00 and can be viewed at https://gist.github.com/6c864bdfced90b81d0a4\n", + "Gist b38bcc0d9882507c918d was created by intothev01d on 2014-08-17 19:12:18+00:00 and can be viewed at https://gist.github.com/b38bcc0d9882507c918d\n", + "Gist 300f20f2705ccfff121f was created by sfujiwara on 2014-08-17 19:12:03+00:00 and can be viewed at https://gist.github.com/300f20f2705ccfff121f\n", + "Gist cf20734ce190c295bce0 was created by rodoard on 2014-08-17 19:10:04+00:00 and can be viewed at https://gist.github.com/cf20734ce190c295bce0\n", + "Gist 3ef046deac453abe5281 was created by dior001 on 2014-08-17 19:09:35+00:00 and can be viewed at https://gist.github.com/3ef046deac453abe5281\n", + "Gist 30e1572599d409ea60ce was created by wilbyang on 2014-08-17 19:09:15+00:00 and can be viewed at https://gist.github.com/30e1572599d409ea60ce\n", + "Gist 67e992f23aeb0c56c8a6 was created by rodoard on 2014-08-17 19:07:53+00:00 and can be viewed at https://gist.github.com/67e992f23aeb0c56c8a6\n", + "Gist 3c5aca83fc49137db35d was created by openpanzer on 2014-08-17 19:07:52+00:00 and can be viewed at https://gist.github.com/3c5aca83fc49137db35d\n", + "Gist 57099359cefcbbb4c07f was created by Arexxk on 2014-08-17 19:07:42+00:00 and can be viewed at https://gist.github.com/57099359cefcbbb4c07f\n", + "Gist b4ca18b8868485ada245 was created by krushd on 2014-08-17 19:07:15+00:00 and can be viewed at https://gist.github.com/b4ca18b8868485ada245\n", + "Gist 06b688f9857475215d88 was created by sanjuthomas on 2014-08-17 19:06:49+00:00 and can be viewed at https://gist.github.com/06b688f9857475215d88\n", + "Gist aa929546abe78aa2be81 was created by sanjuthomas on 2014-08-17 19:05:39+00:00 and can be viewed at https://gist.github.com/aa929546abe78aa2be81\n", + "Gist 593a3e39950d6ccf6d28 was created by CHLibrarian on 2014-08-17 19:05:36+00:00 and can be viewed at https://gist.github.com/593a3e39950d6ccf6d28\n", + "Gist 07bb9aa25f2dec34c353 was created by CHLibrarian on 2014-08-17 19:04:57+00:00 and can be viewed at https://gist.github.com/07bb9aa25f2dec34c353\n", + "Gist 77445b12dccddf898869 was created by sheolseol on 2014-08-17 19:04:42+00:00 and can be viewed at https://gist.github.com/77445b12dccddf898869\n", + "Gist 8fd26b4887231d2b6de7 was created by sackio on 2014-08-17 19:04:30+00:00 and can be viewed at https://gist.github.com/8fd26b4887231d2b6de7\n", + "Gist 03e46b12816e092a1f21 was created by CHLibrarian on 2014-08-17 19:04:17+00:00 and can be viewed at https://gist.github.com/03e46b12816e092a1f21\n", + "Gist faaa524186cd804fc059 was created by ramntry on 2014-08-17 19:03:47+00:00 and can be viewed at https://gist.github.com/faaa524186cd804fc059\n", + "Gist 4f8322e21803a97058fe was created by grondilu on 2014-08-17 19:03:34+00:00 and can be viewed at https://gist.github.com/4f8322e21803a97058fe\n", + "Gist 20cf25445e5ac9bf0028 was created by sanjuthomas on 2014-08-17 19:03:10+00:00 and can be viewed at https://gist.github.com/20cf25445e5ac9bf0028\n", + "Gist beb09796768d42ce9523 was created by CHLibrarian on 2014-08-17 19:03:08+00:00 and can be viewed at https://gist.github.com/beb09796768d42ce9523\n", + "Gist 0ed95c271587870feb5b was created by jakelodwick on 2014-08-17 19:02:38+00:00 and can be viewed at https://gist.github.com/0ed95c271587870feb5b\n", + "Gist e22429a340cd28f2f626 was created by sanjuthomas on 2014-08-17 19:02:14+00:00 and can be viewed at https://gist.github.com/e22429a340cd28f2f626\n", + "Gist 5a62eddbe67dca0a45e2 was created by jakelodwick on 2014-08-17 19:01:46+00:00 and can be viewed at https://gist.github.com/5a62eddbe67dca0a45e2\n", + "Gist 3cbc187e86e302016fd3 was created by synthtech on 2014-08-17 19:01:25+00:00 and can be viewed at https://gist.github.com/3cbc187e86e302016fd3\n", + "Gist ef40230b822a2207c95b was created by sackio on 2014-08-17 19:00:04+00:00 and can be viewed at https://gist.github.com/ef40230b822a2207c95b\n", + "Gist 77df801086743a8159e7 was created by CHLibrarian on 2014-08-17 18:59:12+00:00 and can be viewed at https://gist.github.com/77df801086743a8159e7\n", + "Gist 0de978159530abcbba98 was created by sackio on 2014-08-17 18:59:05+00:00 and can be viewed at https://gist.github.com/0de978159530abcbba98\n", + "Gist fbc99df944d2fd369d10 was created by cythux on 2014-08-17 18:58:42+00:00 and can be viewed at https://gist.github.com/fbc99df944d2fd369d10\n", + "Gist 9ae1fe82f8c335af5160 was created by santiblanko on 2014-08-17 18:58:37+00:00 and can be viewed at https://gist.github.com/9ae1fe82f8c335af5160\n", + "Gist c241cb84f28250a77232 was created by pudquick on 2014-08-17 18:55:26+00:00 and can be viewed at https://gist.github.com/c241cb84f28250a77232\n", + "Gist 187815899d6c3b4cb36e was created by sackio on 2014-08-17 18:55:19+00:00 and can be viewed at https://gist.github.com/187815899d6c3b4cb36e\n", + "Gist 798fa78c90642eebb3b4 was created by prakhar1989 on 2014-08-17 18:55:08+00:00 and can be viewed at https://gist.github.com/798fa78c90642eebb3b4\n", + "Gist 0042d48fbb469ce4bd4c was created by Softsapiens on 2014-08-17 18:54:50+00:00 and can be viewed at https://gist.github.com/0042d48fbb469ce4bd4c\n", + "Gist 91fd537b432b96979459 was created by georgkreimer on 2014-08-17 18:54:11+00:00 and can be viewed at https://gist.github.com/91fd537b432b96979459\n", + "Gist 3a43e1ee0ae57fd4a3d7 was created by yagudaev on 2014-08-17 18:54:07+00:00 and can be viewed at https://gist.github.com/3a43e1ee0ae57fd4a3d7\n" + ] + } + ], + "prompt_number": 3 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If you omit the number argument, github3.py will attempt to iterate over all public gists on GitHub. Unfortunately with a ratelimit of 60 unauthenticated requests per hour you will not be able to list them quickly. "To increase your ratelimit you would have to do the following (or something similar)." + ] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "gh = github3.login('username', 'password')" + ], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": 4 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "for gist in gh.public_gists():\n", + " print('Gist {0.id} was created by {0.owner} on {0.created_at} and can be viewed at {0.html_url}'.format(gist))" + ], + "language": "python", + "metadata": {}, + "outputs": [] + } + ], + "metadata": {} + } + ] +} diff --git a/example-notebooks/managing_issues.ipynb b/example-notebooks/managing_issues.ipynb new file mode 100644 index 000000000..03316e802 --- /dev/null +++ b/example-notebooks/managing_issues.ipynb @@ -0,0 +1,403 @@ +{ + "metadata": { + "name": "", + "signature": "sha256:b8cf2efcee4cc8dbd7cc3243958fbb66c6b0bd59d6d977e1c84b98e3058a616a" + }, + "nbformat": 3, + "nbformat_minor": 0, + "worksheets": [ + { + "cells": [ + { + "cell_type": "heading", + "level": 1, + "metadata": {}, + "source": [ + "Creating, Editing, Closing, and Adding Labels to Issues" + ] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "import github3" + ], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": 1 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "import os" + ], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": 2 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "gh = github3.login(os.environ['GH_USERNAME'], os.environ['GH_PASSWORD'])" + ], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": 3 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now that we've created an authenticated client, let's fetch the repository we need to create our issue on." + ] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "r = gh.repository('github3py', 'fork_this')" + ], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": 4 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next we create the issue using the `create_issue` method on the `Repository` object. It only requires that you pass the first parameter, `title`, to give the issue a title. The next parameter is `body` and it allows you to provide a description of the bug." + ] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "i = r.create_issue('Here is a title', body='I ran into this bug using version 0.1-alpha the other day ...')" + ], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": 5 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "repr(i)" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "metadata": {}, + "output_type": "pyout", + "prompt_number": 6, + "text": [ + "''" + ] + } + ], + "prompt_number": 6 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "What if we accidentally created an invalid bug report? We can close it right from here!" + ] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "help(i.close)" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "Help on method close in module github3.issues.issue:\n", + "\n", + "close() method of github3.issues.issue.Issue instance\n", + " Close this issue.\n", + " \n", + " :returns: bool\n", + "\n" + ] + } + ], + "prompt_number": 7 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "i.close()" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "metadata": {}, + "output_type": "pyout", + "prompt_number": 8, + "text": [ + "True" + ] + } + ], + "prompt_number": 8 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "But actually, we were just able to reproduce the issue. Let's re-open it, then we'll add some more details to the description." + ] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "i.reopen()" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "metadata": {}, + "output_type": "pyout", + "prompt_number": 9, + "text": [ + "True" + ] + } + ], + "prompt_number": 9 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "body = i.body" + ], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": 10 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "i.edit(body=(body + 'I tried to call reopen on an open issue and then ...'))" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "metadata": {}, + "output_type": "pyout", + "prompt_number": 11, + "text": [ + "True" + ] + } + ], + "prompt_number": 11 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "print(i.body)" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "I ran into this bug using version 0.1-alpha the other day ...I tried to call reopen on an open issue and then ...\n" + ] + } + ], + "prompt_number": 12 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can even add comments" + ] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "comment = i.create_comment('Thanks for this bug report!')" + ], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": 13 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "repr(comment)" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "metadata": {}, + "output_type": "pyout", + "prompt_number": 14, + "text": [ + "''" + ] + } + ], + "prompt_number": 14 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Finally, if you're a collaborator on a repository, you can add labels or a milestone to an issue." + ] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "i.add_labels('enhancement', 'bug')" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "metadata": {}, + "output_type": "pyout", + "prompt_number": 15, + "text": [ + "[