1#!/usr/bin/env python
2"""Fetch the most recent GAE SDK and decompress it in the current directory.
3
4Usage:
5    fetch_gae_sdk.py [<dest_dir>]
6
7Current releases are listed here:
8    https://www.googleapis.com/storage/v1/b/appengine-sdks/o?prefix=featured
9"""
10from __future__ import print_function
11
12import json
13import os
14import StringIO
15import sys
16import urllib2
17import zipfile
18
19
20_SDK_URL = (
21    'https://www.googleapis.com/storage/v1/b/appengine-sdks/o?prefix=featured')
22
23
24def get_gae_versions():
25    try:
26        version_info_json = urllib2.urlopen(_SDK_URL).read()
27    except:
28        return {}
29    try:
30        version_info = json.loads(version_info_json)
31    except:
32        return {}
33    return version_info.get('items', {})
34
35
36def _version_tuple(v):
37    version_string = os.path.splitext(v['name'])[0].rpartition('_')[2]
38    return tuple(int(x) for x in version_string.split('.'))
39
40
41def get_sdk_urls(sdk_versions):
42    python_releases = [v for v in sdk_versions
43                       if v['name'].startswith('featured/google_appengine')]
44    current_releases = sorted(python_releases, key=_version_tuple,
45                              reverse=True)
46    return [release['mediaLink'] for release in current_releases]
47
48
49def main(argv):
50    if len(argv) > 2:
51        print('Usage: {0} [<destination_dir>]'.format(argv[0]))
52        return 1
53    dest_dir = argv[1] if len(argv) > 1 else '.'
54    if not os.path.exists(dest_dir):
55        os.makedirs(dest_dir)
56
57    if os.path.exists(os.path.join(dest_dir, 'google_appengine')):
58        print('GAE SDK already installed at {0}, exiting.'.format(dest_dir))
59        return 0
60
61    sdk_versions = get_gae_versions()
62    if not sdk_versions:
63        print('Error fetching GAE SDK version info')
64        return 1
65    sdk_urls = get_sdk_urls(sdk_versions)
66    for sdk_url in sdk_urls:
67        try:
68            sdk_contents = StringIO.StringIO(urllib2.urlopen(sdk_url).read())
69            break
70        except:
71            pass
72    else:
73        print('Could not read SDK from any of ', sdk_urls)
74        return 1
75    sdk_contents.seek(0)
76    try:
77        zip_contents = zipfile.ZipFile(sdk_contents)
78        zip_contents.extractall(dest_dir)
79    except:
80        print('Error extracting SDK contents')
81        return 1
82
83
84if __name__ == '__main__':
85    sys.exit(main(sys.argv[:]))
86