summaryrefslogtreecommitdiff
path: root/reqoauth_test.py
blob: e1450e1456739df0254f5c1042653779900ec26e (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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
#import logging
#logging.basicConfig(level=logging.DEBUG)

import requests
from requests.auth import OAuth1
from urlparse import parse_qs

CONSUMER_KEY = u'sekrit'
CONSUMER_SECRET = u'123'
REQUEST_TOKEN_URL = 'https://testpypi.python.org/oauth/request_token'
AUTHORIZATION_URL = 'https://testpypi.python.org/oauth/authorise'
ACCESS_TOKEN_URL = 'https://testpypi.python.org/oauth/access_token'
RESOURCE_URL = 'https://testpypi.python.org/oauth/test'
CALLBACK_URL = 'http://spam.example/back'


def register():
    #### Step 1: Obtain a request token
    # We start asking for a request token, which will finally turn into an
    # access token, the one we need to operate on behalf of the user.
    auth = OAuth1(CONSUMER_KEY, CONSUMER_SECRET, signature_type='auth_header')
    response = requests.get(REQUEST_TOKEN_URL, auth=auth, verify=False)
    qs = parse_qs(response.text)
    REQUEST_TOKEN = unicode(qs['oauth_token'][0])
    REQUEST_SECRET = unicode(qs['oauth_token_secret'][0])


    #### Step 2: Redirect the user for getting authorization
    # In this step we give the user a link or open a web browser redirecting
    # him to an endpoint, passing the REQUEST_TOKEN we got in the previous step
    # as a url parameter. The user will get a dialog asking for authorization
    # for our application. PyPI will redirect the user back to the URL you
    # provide in CALLBACK_URL.
    import webbrowser
    webbrowser.open("%s?oauth_token=%s&oauth_callback=%s" % (AUTHORIZATION_URL,
        REQUEST_TOKEN, CALLBACK_URL))

    raw_input('[press enter when ready]')


    #### Step 3: Authenticate
    # Once we get user's authorization, we request a final access token, to
    # operate on behalf of the user. We build a new hook using previous request
    # token information achieved at step 1. The request token will have been
    # authorized at step 2.
    # This code is typically invoked in the page called at CALLBACK_URL.
    auth = OAuth1(CONSUMER_KEY, CONSUMER_SECRET, REQUEST_TOKEN, REQUEST_SECRET,
        signature_type='auth_header')
    response = requests.get(ACCESS_TOKEN_URL, auth=auth, verify=False)
    response = parse_qs(response.content)
    ACCESS_TOKEN = unicode(response['oauth_token'][0])
    ACCESS_SECRET = unicode(response['oauth_token_secret'][0])
    # The ACCESS_TOKEN and ACCESS_SECRET are the credentials we need to use for
    # handling user's oauth, so most likely you will want to persist them
    # somehow. These are the ones you should use for building a requests
    # session with a new hook. Beware that not all OAuth APIs provide unlimited
    # time credentials.

    print 'ACCESS TOKEN', ACCESS_TOKEN
    print 'ACCESS SECRET', ACCESS_SECRET

    ### Optional Step 4: Access a protected resource
    # Now we have an access token we may access the protected resources on
    # behalf of the user. In this case we access the test URL which will echo
    # back to us the authenticated user and any parameters we pass.
    auth = OAuth1(CONSUMER_KEY, CONSUMER_SECRET, ACCESS_TOKEN, ACCESS_SECRET,
        signature_type='auth_header')
    response = requests.get(RESOURCE_URL, params={'test': 'spam'}, auth=auth,
        verify=False)
    print response.text


def test(ACCESS_TOKEN, ACCESS_SECRET, **params):
    '''Access the test resource passing optional parameters.

    The test resource will echo back the authenticated user and any parameters
    we pass.
    '''
    RESOURCE_URL = 'https://testpypi.python.org/oauth/test'
    auth = OAuth1(CONSUMER_KEY, CONSUMER_SECRET, ACCESS_TOKEN, ACCESS_SECRET,
        signature_type='auth_header')
    client = SimpleOAuthClient(CONSUMER_KEY, CONSUMER_SECRET, access_token)
    response = requests.get(RESOURCE_URL, params=params, auth=auth,
        verify=False)
    return response.text


def flatten_params(params):
    '''Convert a dict to to a list of two-tuples of (k, v) where v is
    potentially each element from a list of values.

    Also ignore empty values as these confuse signature generation.
    '''
    flattened = []
    for k, v in params.items():
        if isinstance(v, list):
            for v in v:
                if v:
                    flattened.append((k, v))
        elif v:
            flattened.append((k, v))
    return [e for e in flattened if e[1]]


def release(ACCESS_TOKEN, ACCESS_SECRET, name, version, summary, **optional):
    '''Register a new package, or release of an existing package.

    The "optional" parameters match fields in PEP 345.

    The complete list of parameters are:

    Single value: description, keywords, home_page, author, author_email,
        maintainer, maintainer_email, license, requires_python

    Multiple values: requires, provides, obsoletes, requires_dist,
        provides_dist, obsoletes_dist, requires_external, project_url,
        classifiers.

    For parameters with multiple values, pass them as lists of strings.

    The API will default metadata_version to '1.2' for you. The other valid
    value is '1.0'.

    Two additional metadata fields are available specific to PyPI:

    1. _pypi_hidden: If set to '1' the relase will be hidden from listings and
       searches.
    2. bugtrack_url: This will be displayed on package pages.
    '''
    RESOURCE_URL = 'https://testpypi.python.org/oauth/add_release'
    auth = OAuth1(CONSUMER_KEY, CONSUMER_SECRET, ACCESS_TOKEN, ACCESS_SECRET,
        signature_type='auth_header')
    params = {u'name': name, u'version': version, u'summary': summary}
    params.update(optional)
    data = flatten_params(params)
    response = requests.post(RESOURCE_URL, data=data, auth=auth,
        verify=False)
    return response.text


def upload(ACCESS_TOKEN, ACCESS_SECRET, name, version, content,
        filename, filetype, **optional):
    '''Upload a file for a package release. If the release does not exist then
    it will be registered automatically.

    The name and version identify the package release to upload the file
    against. The content and filetype are specific to the file being uploaded.

    content - an readable file object
    filetype - one of the standard distutils file types ("sdist", "bdist_win",
        etc.)

    There are several optional parameters:

    pyversion - specify the 'N.N' Python version the distribution works with.
        This is not needed for source distributions but required otherwise.
    comment - use if there's multiple files for one distribution type.
    md5_digest - supply the MD5 digest of the file content to verify
        transmission
    gpg_signature - ASCII armored GPG signature for the file content
    protocol_version - defaults to "1" (currently the only valid value)

    Additionally the release parameters are as specified for release() above.
    '''
    RESOURCE_URL = 'https://testpypi.python.org/oauth/upload'
    auth = OAuth1(CONSUMER_KEY, CONSUMER_SECRET, ACCESS_TOKEN, ACCESS_SECRET,
        signature_type='auth_header')
    params = dict(name=name, version=version, filename=filename,
        filetype=filetype, protocol_version='1')
    params.update(optional)
    data = flatten_params(params)
    files = dict(content=(filename, content))
    response = requests.post(RESOURCE_URL, params=params, files=files,
        auth=auth, verify=False)
    return response.text

# TODO docupload

if __name__ == '__main__':
    #register()

    ACCESS_TOKEN = u'AJLks8p4zezH2ud9R7OQy98eRLXf8zut'
    ACCESS_SECRET = u'vSXBEWk5kn6wvVGivILPyBmtRitDvJq0cVcmBDk57eX2XCENvp2da3ou7v09TxrL'
    name = u'spam'
    version = u'3.3.1'
    summary = u'spam via OAuth'
    classifiers = [u'Topic :: Security', u'Environment :: Console']
    print 'REGISTERING', name, version
    print release(ACCESS_TOKEN, ACCESS_SECRET, name, version, summary,
      classifiers=classifiers)

    name = u'spam'
    version = u'3.3.1'
    filename = u'spam-3.3.1.tar.gz'
    filetype = u'sdist'
    content = open('/Users/richard/src/projects/spam/dist/' + filename, 'rb')
    #print 'UPLOADING', filename
    #print upload(ACCESS_TOKEN, ACCESS_SECRET, name, version, content,
        #filename, filetype)