PyCascade is a Python Cascade client implementation, written in pure Python. Although Cascade supports both BBAuth and OAuth authorization models, PyCascade supports only OAuth, via the oauth library. Only the JSON variant of the API is currently supported.
To apply for an OAuth key that works with Cascade, check out the YDN OAuth documentation.
The primary use of PyCascade is as a Cascade client library. To use it, one
constructs a JSON11Client
instance and invokes the call()
method. The API
that PyCascade provides is based on Python primitives: all JSON datatypes to be
communicated over the wire should be handed to PyCascade as Python primitives;
likewise, all JSON datatypes coming back from the server are de-serialized into
Python primitives before being handed back to the PyCascade client application.
As a brief example, the following code snippet will construct a JSON11Client
and then use it to print a list of folders in a mailbox.
oaConsumer = oauth.OAuthConsumer(...)
oaToken = oauth.OAuthToken(...)
jc = JSON11Client(oaConsumer, oaToken)
result = jc.call(
'ListFolders',
params = [{}]
)
for f in result['result']['folder']:
print f['folderInfo']['name']
Note that the OAuthToken
here must be an access token, not a request token.
If the access token is stale, the PyCascade library will attempt to refresh it
for you.
The PyCascade library provides some easier-to-use higher level functions for
interacting with the Cascade OAuth implementation to interact with tokens. The
following list of metthods are all present in the cascade
module:
oauth_get_request_token()
oauth_get_access_token()
oauth_refresh_access_token()
In addition, it provides some methods to (de-)serialize OAuth tokens to and
from query strings. These query strings are compatible with those generated by
oauth.OAuthToken.from_string()
, but contain additional data that allows for
token refresh, etc.
oauth_token_to_query_string()
oauth_token_from_query_string()
The PyCacade library can also be invoked directly from the shell. This can be useful to bolt on Cascade client functionality to other scripts, or to do interactive testing / exploration of the Cascade service.
The trickest part of using this is getting the OAuth configuration correct. One
is required to specify the -k
and -s
options which indicate the OAuth
consumer key and secret, respectively. Beyond that, one must specify an OAuth
access token to use, which can be done in one of two ways: the -a
option,
which takes a token encoded as a query string via
cascade.oauth_token_to_query_string()
; or both of the
--oauth-access-token-key
and --oauth-access-token-secret
options.
The major benefits of using the -a
option is that token query strings can
contain information which allows for refresh and that it is less verbose. Note
that one can get a query-encoded access token by running the unit tests (below)
and retrieving the OAUTH_ACCESS_TOKEN
value from
cascade_unittest_settings.py
.
As a brief example, we call ListFolders
.
% echo "[{}]" | python ./cascade.py call \
-k 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' \
-s 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' \
-a 'xoauth_yahoo_guid=UDLAKKVZB3N4BVS7CMIDBIDRYI&oauth_token_secret=3800c4b46be3eceb26938eb3af0198c031661c80&xoauth_authorization_expires_on=2147483650&oauth_session_handle=ANCIPkvlhRw8XL_VsZpCU88oUzYLm2f6cFCoS2.zF1x79QU-&oauth_token=A%3DiDHi8nvCpwQlBW6HqXB2eZywDxmGID3d28CX4ArOd7tF0YgHJCqDY0H39t6VeuobybSL8kVW1GCX0XedzVoPe2R8cl5Bw_uTsEHeKP.qnEMQz.qO9RWzdvFS.qzGIoaX3w.wLZUDAckrHOT2jSdDab72iXURTkuFaDjAdO.SIa6qJLRPQJuD_4fMgL4h1553y9uuz_revFBB8iqd8VQDWJKh1mr.p41ovaMDp90VR4Bpnap1xfQ7yNT.x9psZrtcS32MQcekaz.L3Ax6bKhBRc__JqeU5LIA0HONuM0yTk01vtb.Wcu0U7_jTRH3VAeyymKENhIlcsx3gUmJ0h5OzeAHvH16BEEl4SHS4nff2POJqZ7RSbrowkrWtoXYLCb5epjFoHXlk45c2xKbEpUyNYKGoLjrTLloTlfv90X6uRt3VctcsLEw8e5_kHUOfhcM7aUqMGRcZdihoC5ts6I0wxmVkGzGqSSdRIhYnZXcvB5dj9On9HtXBoQ.XF2kQT4zErW81i6dEgUu4i6hOq.Pey_qBLRVWno8ffyj.QRhUvhk2y2BrczKDHnnsLxXSOjVjFKo62IObXGjO7FelxOUeSc3tKn0N7Ic_AAxDQgo.X2v8mkoZKH66rHspH06vVURTLMG7oADaDsfZSe6CmnkrcOU7DN.AivzOV16Yu1wkXjSfABfSovE.QcRG6QB3fckypZ7PBfbRhOwboo_txK0a6A6WhMKA2EGnRBhCj68UEW7aLIEac2wJXWkErEhhcU2Z75.62KYjZlbAUyBUQ--&xoauth_expires_on=1266426257' \
ListFolders
{
"result": {
"folder": [
{
"folderInfo": {
"name": "@B@Bulk",
"fid": "%40B%40Bulk"
},
"total": 0,
"unread": 0,
"isSystem": true,
"size": 0
},
{
"folderInfo": {
"name": "Draft",
"fid": "Draft"
},
"total": 0,
"unread": 0,
"isSystem": true,
"size": 0
},
{
"folderInfo": {
"name": "Inbox",
"fid": "Inbox"
},
"total": 20,
"unread": 13,
"isSystem": true,
"size": 185992
},
{
"folderInfo": {
"name": "Sent",
"fid": "Sent"
},
"total": 0,
"unread": 0,
"isSystem": true,
"size": 0
},
{
"folderInfo": {
"name": "Trash",
"fid": "Trash"
},
"total": 0,
"unread": 0,
"isSystem": true,
"size": 0
}
],
"numberOfFolders": 5
},
"error": null
}
The exit status for cascade.py call
is zero if the call succeeded, nonzero
otherwise.
PyCascade sports a handful of unit tests, which are executed by invoking
cascade.py unittest
from the shell, as follows:
% python ./cascade.py unittest
..
----------------------------------------------------------------------
Ran 2 tests in 1.005s
OK
Most of these unit tests require OAuth authentication. As we do not want to
commit these credentials to source control, a facility exists to generate
them by interviewing the invoker, and persisting the results in the
cascade_unittest_settings.py
module in the current working directory. The
consumer callback URL should have the same hostname as the one configured
with the OAuth key being used, but should result in a 404. The idea is that
we do not want the OAuth authorization flow to end up somewhere "real" -- we
just want to steal the query parameters that are generated as part of this
flow. Thus, the token callback URL is just the consumer callback URL with
some query parameters populated by the OAuth flow.
In the following example, http://www.yttrium.ws
is configured as the
application URL for our OAuth key. We synthesize a fictitious path with some
gook to ensure a 404.
% rm -f cascade_unittest_settings.py*
% python ./cascade.py
>>> generating cascade_unittest_settings.py
consumer key: 6epbh1bl4p2zdnhsn5bnikcu2n73apewat0hp166dzkit8n84pe6fjvruagjg3r3wh824cnp45av5pueag274xzayzb2awipnvci
consumer secret: x4jhpriqzwbaojwhkq2hhrkm2nagmuyd7yqawjmc
consumer callback URL: http://www.yttrium.ws/qqzzbb
>>> navigate to the following URL in your browser, then paste in the tokenc allback URL that results
https://api.login.yahoo.com/oauth/v2/request_auth?oauth_token=crw2ke7
token callback URL: http://www.yttrium.ws/qqzzbb?oauth_token=crw2ke7&oauth_verifier=o3caph
..
----------------------------------------------------------------------
Ran 2 tests in 1.005s
OK
PyCascade be run through an HTTP proxy by utilizing the built-in support that
urllib2
provides for proxies. In the following example, both HTTP and HTTPS
are sent through a proxy running on localhost
port 8888.
% export http_proxy='http://localhost:8888'
% export https_proxy='http://localhost:8888'
% python ./cascade.py unittest
...