diff --git a/appengine_main.py b/appengine_main.py index c3fd5928132..c9b3f5494cd 100644 --- a/appengine_main.py +++ b/appengine_main.py @@ -18,7 +18,6 @@ import os import webapp2 import logging -import traceback import devsitePage import devsiteIndex import devsiteHelper @@ -28,20 +27,24 @@ DEFAULT_LANG = 'en' DEVENV = os.environ['SERVER_SOFTWARE'].startswith('Dev') USE_MEMCACHE = not DEVENV +SOURCE_PATH = os.path.join(os.path.dirname(__file__), 'src/content/') class FlushMemCache(webapp2.RequestHandler): def get(self): memcache.flush_all() self.response.out.write('Flushed') + class HomePage(webapp2.RequestHandler): def get(self): self.redirect('/web/', permanent=True) + class DevSiteRedirect(webapp2.RequestHandler): def get(self, path): self.redirect('https://developers.google.com/' + path, permanent=True) + class Framebox(webapp2.RequestHandler): def get(self, path): response = None @@ -58,8 +61,15 @@ def get(self, path): logging.info('200 ' + memcacheKey) self.response.out.write(response) + class DevSitePages(webapp2.RequestHandler): def get(self, path): + + if path.endswith('.html') or path.endswith('.md'): + redirectTo = '/web/' + os.path.splitext(path)[0] + self.redirect(redirectTo, permanent=True) + return + response = None langQS = self.request.get('hl', None) langCookie = self.request.cookies.get('hl') @@ -82,8 +92,11 @@ def get(self, path): if response is None: try: - if path.endswith('/') or path == '': + if os.path.isdir(os.path.join(SOURCE_PATH, 'en', path)): response = devsiteIndex.getPage(path, lang) + if (response is None) and (path.startswith('showcase') or + path.startswith('shows') or path.startswith('updates')): + response = devsiteIndex.getDirIndex(path) else: response = devsitePage.getPage(path, lang) @@ -108,7 +121,7 @@ def get(self, path): response = render('gae/500.tpl', context) logging.exception('500 ' + fullPath) self.response.set_status(500) - + self.response.out.write(response) diff --git a/devsiteHelper.py b/devsiteHelper.py index ab5245d009e..1515e3db95e 100644 --- a/devsiteHelper.py +++ b/devsiteHelper.py @@ -6,15 +6,10 @@ import logging import textwrap import urllib2 - from datetime import date, datetime from google.appengine.api import memcache -from google.appengine.ext.webapp.template import render SOURCE_PATH = os.path.join(os.path.dirname(__file__), 'src/content/') -DEVENV = os.environ['SERVER_SOFTWARE'].startswith('Dev') -USE_MEMCACHE = not DEVENV - def slugify(str): # Very simply slugify @@ -34,8 +29,7 @@ def getFromMemCache(memcacheKey): def setMemCache(memcacheKey, value, length=3600): try: - if USE_MEMCACHE: - memcache.set(memcacheKey, value, length) + memcache.set(memcacheKey, value, length) except Exception as e: logging.exception('Unable to cache to MemCache') @@ -149,10 +143,6 @@ def parseBookYaml(pathToBook, lang='en'): Returns: A dictionary with the parsed book. """ - memcacheKey = 'bookYAML-' + pathToBook - result = getFromMemCache(memcacheKey) - if result: - return result try: result = {} upperTabs = [] @@ -160,7 +150,6 @@ def parseBookYaml(pathToBook, lang='en'): bookYaml = yaml.load(readFile(pathToBook, lang)) for upperTab in bookYaml['upper_tabs']: upperTabs.append(expandBook(upperTab)) - setMemCache(memcacheKey, result, 60) return result except Exception as e: logging.exception('Error in parseBookYaml') @@ -219,13 +208,8 @@ def getLowerTabs(bookYaml): def getLeftNav(requestPath, bookYaml, lang='en'): - # Returns the left nav. If it's already been generated and stored in - # memcache, return that, otherwise, read the file then recursively - # build the tree using buildLeftNav. - memcacheKey = 'leftNav-' + requestPath - result = getFromMemCache(memcacheKey) - if result: - return result + # Returns the left nav. Read the file then recursively, then build the + # tree using buildLeftNav. whoops = '

Whoops!

' whoops += '

An error occured while trying to parse and build the' whoops += ' left hand navigation. Check the error logs.' @@ -241,10 +225,9 @@ def getLeftNav(requestPath, bookYaml, lang='en'): result = '

\n' - setMemCache(memcacheKey, result) return result except Exception as e: - msg = ' - Unable to read or parse primary book.yaml: ' + pathToBook + msg = ' - Unable to read or parse primary book.yaml' logging.exception(msg) whoops += '

Exception occured.

' return whoops @@ -254,18 +237,6 @@ def buildLeftNav(bookYaml, lang='en'): # Recursively reads the book.yaml file and generates the navigation tree result = '' for item in bookYaml: - if 'include' in item: - ## TODO(petele): Remove this - ## leaving this in for a few weeks while I ensure it doesn't break - ## anything. - logging.error('***** INCLUDE - this should NOT happen.') - # try: - # include = readFile(item['include'], lang) - # include = yaml.load(include) - # result += buildLeftNav(include['toc']) - # except Exception as e: - # msg = ' - Unable to parsing embedded toc file: ' + item['include'] - # logging.exception(msg) if 'path' in item: result += '
  • \n' result += '\n' @@ -442,10 +413,7 @@ def getIncludeCode(include_tag, lang='en'): def getAnnouncementBanner(pathToProject, lang='en'): - memcacheKey = 'projectYAML-' + pathToProject - result = getFromMemCache(memcacheKey) - if result: - return result + result = '' try: project = yaml.load(readFile(pathToProject, lang)) if 'announcement' in project: @@ -461,10 +429,9 @@ def getAnnouncementBanner(pathToProject, lang='en'): result += '' else: logging.warn('Announcement in _project.yaml expired: not shown') - setMemCache(memcacheKey, result, 60) except Exception as e: logging.exception('Unable to get announcement from project.yaml') - return '' + result = '' return result @@ -497,7 +464,7 @@ def getFooterPromo(lang='en'): result += '
  • \n' - setMemCache(memcacheKey, result) + setMemCache(memcacheKey, result, 60) return result @@ -527,5 +494,5 @@ def getFooterLinkBox(lang='en'): result += linkItem['label'] + '' result += '' result += '' - setMemCache(memcacheKey, result) + setMemCache(memcacheKey, result, 60) return result diff --git a/devsiteIndex.py b/devsiteIndex.py index c7b2339908d..6a88a5e60fc 100644 --- a/devsiteIndex.py +++ b/devsiteIndex.py @@ -1,64 +1,49 @@ import os -import yaml import logging -import devsitePage import devsiteHelper -from google.appengine.ext.webapp.template import render +import devsiteParseMD +import devsiteParseHTML +import devsiteParseYAML SOURCE_PATH = os.path.join(os.path.dirname(__file__), 'src/content') def getPage(requestPath, lang): - response = None fileLocations = [ os.path.join(SOURCE_PATH, lang, requestPath, '_index.yaml'), os.path.join(SOURCE_PATH, 'en', requestPath, '_index.yaml'), os.path.join(SOURCE_PATH, lang, requestPath, 'index.md'), - os.path.join(SOURCE_PATH, 'en', requestPath, 'index.md') + os.path.join(SOURCE_PATH, 'en', requestPath, 'index.md'), + os.path.join(SOURCE_PATH, 'lang', requestPath, 'index.html'), + os.path.join(SOURCE_PATH, 'en', requestPath, 'index.html') ] for fileLocation in fileLocations: if os.path.isfile(fileLocation): - fileContent = open(fileLocation, 'r').read() - fileContent = fileContent.decode('utf8') - + content = open(fileLocation, 'r').read() + content = content.decode('utf8') if fileLocation.endswith('_index.yaml'): - response = generateYaml(lang, requestPath, fileContent) - break - + return devsiteParseYAML.parse(requestPath, fileLocation, content, lang) if fileLocation.endswith('index.md'): - # index.md are treated like other devsite pages, so just use the - # devsitePage rendering template. - requestPath = os.path.join(requestPath, 'index') - response = devsitePage.getPage(requestPath, lang) - break - - if response is None and os.environ['SERVER_SOFTWARE'].startswith('Dev'): - if (requestPath.startswith('showcase/') or - requestPath.startswith('shows/') or requestPath.startswith('updates/')): - content = '' - content += '

    Generated Listing Page

    \n' - content += '' - fileList = os.listdir(os.path.join(SOURCE_PATH, 'en', requestPath)) - for f in fileList: - if not f.startswith('_'): - p = '/web/' + requestPath + f.replace('.md', '') - line = '
  • ' - line += '' + p + '' - line += '
  • ' - content += line - - response = render('gae/article.tpl', { - 'title': 'Whoops! Missing index page!', - 'requestPath': requestPath, - 'leftNav': '', - 'content': content, - 'toc': '', - 'dateUpdated': 'now', - 'lang': 'en'} - ) - return response + return devsiteParseMD.parse(requestPath, fileLocation, content, lang) + if fileLocation.endswith('index.html'): + return devsiteParseHTML.parse(requestPath, fileLocation, content, lang) + return None + + +def getDirIndex(requestPath): + result = None + if os.environ['SERVER_SOFTWARE'].startswith('Dev'): + result = '' + result += '

    Generated Listing Page

    \n' + result += '' + fileList = os.listdir(os.path.join(SOURCE_PATH, 'en', requestPath)) + for f in fileList: + if not f.startswith('_'): + link = os.path.join('/web', requestPath, os.path.splitext(f)[0]) + result += '
  • ' + link + '
  • ' + return result def parseIndexYamlItems(yamlItems): @@ -68,10 +53,8 @@ def parseIndexYamlItems(yamlItems): itemClasses = ['devsite-landing-row-item'] descriptionClasses = ['devsite-landing-row-item-description'] link = None - if 'path' in yamlItem: link = '' - if 'icon' in yamlItem: if link: item += link @@ -87,7 +70,6 @@ def parseIndexYamlItems(yamlItems): descriptionClasses.append('devsite-landing-row-item-icon-description') if link: item += '' - if 'image_path' in yamlItem: imgClass = 'devsite-landing-row-item-image' if 'image_left' in yamlItem: @@ -96,7 +78,6 @@ def parseIndexYamlItems(yamlItems): item += 'class="' + imgClass + '">' elif not 'youtube_id' in yamlItem: itemClasses.append('devsite-landing-row-item-no-image') - if 'description' in yamlItem: item += '
    ' if 'heading' in yamlItem: @@ -104,7 +85,6 @@ def parseIndexYamlItems(yamlItems): item += link item += '

    ' item += yamlItem['heading'] + '

    ' - # item += '

    ' + yamlItem['heading'] + '

    ' if link: item += '' item += yamlItem['description'] @@ -119,10 +99,8 @@ def parseIndexYamlItems(yamlItems): item += '>' + button['label'] + '' item += '
    ' item += '' - if 'custom_html' in yamlItem: item += devsiteHelper.renderDevSiteContent(yamlItem['custom_html']) - if 'youtube_id' in yamlItem: item += '
    ' item += '' + item += '
    ' + + item += '' + item = item.replace('[[ITEM_CLASSES]]', ' '.join(itemClasses)) + item = item.replace('[[DESCRIPTION_CLASSES]]', ' '.join(descriptionClasses)) + + result += item + + return result + diff --git a/gae/article.tpl b/gae/article.tpl index 30206695ec8..912248d45dc 100644 --- a/gae/article.tpl +++ b/gae/article.tpl @@ -41,6 +41,9 @@ } {{ title }} + {% autoescape off %} + {{ head }} + {% endautoescape %}
    diff --git a/gae/home.tpl b/gae/home.tpl index 705076be39d..1bdebcb814e 100644 --- a/gae/home.tpl +++ b/gae/home.tpl @@ -32,6 +32,9 @@ margin-top: 48px; } + {% autoescape off %} + {{ head }} + {% endautoescape %}