summaryrefslogtreecommitdiff
path: root/examples/pygithub.py
blob: cf3622abb72f577266c4a9158b2c090b9bfa8782 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#!/usr/bin/env python
"""
An example of caching [GitHub API](https://docs.github.com/en/rest) requests with
[PyGithub](https://github.com/PyGithub/PyGithub).

This example demonstrates the following features:
* {ref}`patching`: PyGithub uses `requests`, but the session it uses is not easily accessible.
  In this case, using {py:func}`.install_cache` is the easiest approach.
* {ref}`URL Patterns <url-filtering>`: Since we're using patching, this example adds an optional
  safety measure to avoid unintentionally caching any non-Github requests elsewhere in your code.
* {ref}`cache-control`: The GitHub API provides `Cache-Control` headers, so we can use those to set
  expiration.
* {ref}`conditional-requests`: The GitHub API also supports conditional requests. Even after
  responses expire, we can still make use of the cache until the remote content actually changes.
* [Rate limiting](https://docs.github.com/en/rest/overview/resources-in-the-rest-api#rate-limiting):
  The GitHub API is rate-limited at 5000 requests per hour if authenticated, or only 60 requests per
  hour otherwise. This makes caching especially useful, because cache hits and `304 Not Modified`
  responses (from conditional requests) are not counted against the rate limit.
* {ref}`inspection`: After calling some PyGithub functions, we can take a look at the cache contents
  to see the actual API requests that were sent.
* {ref}`Security <default-filter-params>`: If you use a
  [personal access token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token),
  it will be sent to the GitHub API via the `Authorization` header. This is not something you want
  to store in the cache if your storage backend is unsecured, so `Authorization` and other common
  auth headers/params are redacted by default. This example shows how to verify this.
"""
from time import time

import requests
from github import Github

from requests_cache import DO_NOT_CACHE, get_cache, install_cache

# (Optional) Add an access token here, if you want higher rate limits and access to private repos
ACCESS_TOKEN = None

# Or add your own username here (if not using an access token)
MY_USERNAME = 'test-user'


install_cache(
    cache_control=True,
    urls_expire_after={
        '*.github.com': 360,  # Placeholder expiration; should be overridden by Cache-Control
        '*': DO_NOT_CACHE,  # Don't cache anything other than GitHub requests
    },
)


def get_user_info():
    """Display some info about your own resources on GitHub"""
    gh = Github(ACCESS_TOKEN)
    my_user = gh.get_user() if ACCESS_TOKEN else gh.get_user(MY_USERNAME)

    # Get links to all of your own repositories
    print('My repos:')
    for repo in my_user.get_repos():
        print(repo.html_url)

    # Get links to all of your own gists
    print('\nMy gists:')
    for gist in my_user.get_gists():
        print(gist.html_url)

    # Get organizations you belong to
    print('\nMy organizations:')
    for org in my_user.get_orgs():
        print(org.html_url)

    # Check how internet-famous you are
    print('\nMy followers:')
    for user in my_user.get_followers():
        print(user.login)

    # Check your API rate limit usage
    print(f'\nRate limit: {gh.rate_limiting}')


def test_non_github_requests():
    """Test that URL patterns are working, and that non-GitHub requests are not cached"""
    response = requests.get('https://httpbin.org/json')
    response = requests.get('https://httpbin.org/json')
    from_cache = getattr(response, 'from_cache', False)
    print(f'Non-GitHub requests cached: {from_cache}')
    assert not from_cache


def check_cache():
    """Check some information on cached requests"""
    # Show all the GitHub API URLs that PyGithub called
    print('\nCached URLs:')
    print('\n'.join(get_cache().urls()))

    # Make sure credentials were redacted from all responses in the cache
    response = requests.get('https://api.github.com/user/repos')
    print('\nExample cached request headers:')
    print(response.request.headers)
    for response in get_cache().responses.values():
        assert 'Authorization' not in response.request.headers


def main():
    # Send initial requests
    start = time()
    get_user_info()
    print(f'Elapsed: {time() - start:.2f} seconds')

    # Repeat the same requests and verify that your rate limit usage is unchanged
    start = time()
    get_user_info()
    print(f'Elapsed: {time() - start:.2f} seconds')

    test_non_github_requests()
    check_cache()


if __name__ == '__main__':
    main()