#!/usr/bin/env python
#
#   Download and extract the last Google App Engine SDK.
#

import argparse
import logging
import os
import re
import sys
from evelink.thirdparty.six.moves import urllib
from xml.etree import ElementTree as ET
from zipfile import ZipFile


# TODO: this feed no longer exists; figure out where (if anywhere) to grab url
GAE_FEED_URL = 'https://code.google.com/feeds/p/googleappengine/downloads/basic'
SDK_PATTERN = r'http://googleappengine.googlecode.com/files/google_appengine_(\d\.)+zip'
DEFAULT_URL = 'https://storage.googleapis.com/appengine-sdks/featured/google_appengine_1.9.40.zip'

_log = logging.getLogger('travis.prerun')
logging.basicConfig(level=logging.INFO)


def get_args_parser():
    """Build the command line argument parser

    """
    parser = argparse.ArgumentParser(
        description='Download and extract the last Google App Engine SDK to.'
    )
    parser.add_argument(
        'gae_lib_dst',
        nargs='?',
        default='/usr/local',
        help='directory to extract Google App Engine SDK '
            '(default to "/usr/local").'
    )
    return parser


def get_sdk_url(feed, pattern):
    try:
        _log.info("Fetching atom feed for GAE sdk releases...")
        f = urllib.request.urlopen(feed)
        tree = ET.fromstring(f.read())
    finally:
        f.close()

    ns = {'a': 'http://www.w3.org/2005/Atom'}
    for link in tree.findall("a:entry/a:link[@rel='direct']", namespaces=ns):
        url = link.get('href')
        if re.match(SDK_PATTERN, url):
            _log.info("Found last release: %s", url)
            return url
    raise ValueError("No download links found!")


def download_sdk(url):
    _log.info("downloading SDK from %s ...", url)
    return urllib.request.urlretrieve(url)[0]


def unzip(file, dst):
    _log.info("Extracting SDK to %s ...", dst)
    with ZipFile(file) as z:
        for name in z.namelist():
            if '/' in name and name[0] == '/':
                raise ValueError("a SDK archive member has an absolute path")
            if '..' in name:
                raise ValueError("Found two dots in a member of the SDK archive")
        z.extractall(dst)


def main(gae_lib_dst):
    if sys.version_info[0:2] != (2, 7,):
        _log.info("Python 2.7 is required to run AppEngine.")
        return

    try:
        url = get_sdk_url(GAE_FEED_URL, SDK_PATTERN)
        _log.info("Found GAE SDK url: %s", url)
    except Exception:
        url = DEFAULT_URL
        _log.info(
            "Failed finding GAE SDK url at %s; Will use default url (%s)",
            GAE_FEED_URL,
            url
        )

    try:
        if not os.path.exists(gae_lib_dst):
            _log.info("Creating %s directory", gae_lib_dst)
            os.makedirs(gae_lib_dst)

        sdk_path = download_sdk(url)
        unzip(sdk_path, gae_lib_dst)
        _log.info("GAE SDK available at %s/google_engine", gae_lib_dst)
    except Exception as e:
        _log.error("failed downloading the sdk: %s", str(e))


if __name__ == '__main__':
    parser = get_args_parser()
    args = parser.parse_args()
    main(args.gae_lib_dst)

@@ -93,16 +93,28 @@
 rgparse%0A
+import json%0A
 import l
@@ -208,164 +208,54 @@
 rom 
-xml.etree import ElementTree as ET%0Afrom zipfile import ZipFile%0A%0A%0A# TODO: this feed no longer exists; figure out where (if anywhere) to grab url%0AGAE_FEED_URL
+zipfile import ZipFile%0A%0A%0AGAE_SDK_DOWNLOAD_LIST
  = '
@@ -266,69 +266,83 @@
 s://
-code
+www
 .google
+apis
 .com/
-feeds/p/googleappengine/downloads/basic
+storage/v1/b/appengine-sdks/o?prefix=featured
 '%0ASDK_
+FILE_
 PATT
@@ -352,53 +352,20 @@
  = r
-'http://googleappengine.googlecod
 e.com
-/files/
+pile(r'
 goog
@@ -382,18 +382,23 @@
 ne_(
-%5Cd%5C.)+
+%5B0-9.%5D+)%5C.
 zip'
+)
 %0ADEF
@@ -1017,20 +1017,23 @@
 sdk_url(
-feed
+api_url
 , patter
@@ -1077,22 +1077,8 @@
 ing 
-atom feed for 
 GAE 
@@ -1134,12 +1134,15 @@
 pen(
-feed
+api_url
 )%0A  
@@ -1151,28 +1151,25 @@
     
-tree = ET.fromstring
+data = json.loads
 (f.r
@@ -1215,257 +1215,241 @@
     
-ns = %7B'a': 'http://www.w3.org/2005/Atom'%7D%0A    for link in tree.f
+medialinks = %5Bitem%5B'mediaLink'%5D for item 
 in
+ 
 da
-ll(%22a:entry/a:link%5B@rel='direct'%5D%22, namespaces=ns):%0A        url = link.get('href')%0A  
+ta%5B'items'%5D%5D%0A    python_sdks = %5Bi for i in medialinks if pattern.search(i)%5D%0A
     
-  
 if 
-re.match(SDK_PATTERN, url):%0A            _log.info(%22Found last release: %25s%22, url
+python_sdks:%0A      # lazy version sort%0A      python_sdks.sort(key=lambda x: x.split('.'), reverse=True
 )%0A
-      
     
@@ -1457,19 +1457,30 @@
  return 
-url
+python_sdks%5B0%5D
 %0A    rai
@@ -2225,21 +2225,35 @@
 GAE_
-FEED_URL, SDK
+SDK_DOWNLOAD_LIST, SDK_FILE
 _PAT
@@ -2326,17 +2326,44 @@
 xception
-:
+ as e:%0A        _log.error(e)
 %0A       
@@ -2495,16 +2495,25 @@
 GAE_
-FEED_URL
+SDK_DOWNLOAD_LIST
 ,%0A  

Update automatic download of GAE SDK