diff --git a/.gitignore b/.gitignore
index 686c336..eb9c60a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,3 +3,4 @@
/config.json
*.pyc
.idea
+lib
diff --git a/README.md b/README.md
index 0a6f8ab..ccf83ce 100644
--- a/README.md
+++ b/README.md
@@ -20,11 +20,55 @@
$ vagrant ssh
$ cd ~/vagrant
$ redis-server &
- $ python3 app.wsgi
+ $ python app.py
```
4. access
+## How to run on GAE local dev server (work in progress, as we did not migrate to GAE yet)
+
+GAE doesn't support Redis. So you need to use Memcache instead.
+
+1. setup
+
+ - Install [GAE Python SDK](https://cloud.google.com/appengine/downloads)
+
+
+2. In config.json,
+
+ Remove the "REDIS_INFO" section :
+
+ ```
+ "REDIS_INFO": {
+ ...
+ },
+ ```
+
+ and add the "MEMCACHE" section like below
+
+ ```
+ "MEMCACHE": {
+ "servers" : [
+ {
+ "host": "localhost",
+ "port": "11211"
+ }
+ ],
+ "debug": 0
+ },
+ ```
+
+3. start GAE local dev server
+
+ do not forget the last dot (.) in the command
+
+ ```
+ $ dev_appserver.py .
+ ```
+
+4. access
+
+
## i18n/l10n
### Extract translatable strings from templates
diff --git a/app.py b/app.py
index 7b68ede..9a64c29 100644
--- a/app.py
+++ b/app.py
@@ -38,14 +38,16 @@ def __init__(self, file):
with open(file, 'r') as f:
self.cfg = json.load(f)
- for section in ['OCTAV', 'REDIS_INFO', 'GITHUB', 'GOOGLE_MAP']:
+ for section in ['OCTAV', 'GITHUB', 'GOOGLE_MAP']:
if not self.cfg.get(section):
raise Exception( "missing section '" + section + "' in config file '" + file + "'" )
if self.cfg.get('OCTAV').get('BASE_URI'):
raise Exception(
'DEPRECATED: {"OCTAV":{"BASE_URI"}} in config.json is deprecated.\
- Please use {"OCTAV":{"endpoint"}} instead and remove {"OCTAV":{"BASE_URI"}}.'
- )
+ Please use {"OCTAV":{"endpoint"}} instead and remove {"OCTAV":{"BASE_URI"}}.')
+ if self.cfg.get('REDIS_INFO') and self.cfg.get('MEMCACHE'):
+ raise Exception( 'In config.json, do not specify both "REDIS_INFO" and "MEMCACHE". Use only either of them.' )
+
def section(self, name):
return self.cfg.get(name)
@@ -68,7 +70,12 @@ def googlemap_api_key(self):
octav = Octav(**cfg.section('OCTAV'))
-cache = cache.Redis(**cfg.section('REDIS_INFO'))
+if cfg.section('REDIS_INFO'):
+ cache = cache.Redis(**cfg.section('REDIS_INFO'))
+elif cfg.section('MEMCACHE'):
+ cache = cache.Memcache(**cfg.section('MEMCACHE'))
+else:
+ raise Exception( 'config.json must specify either of "REDIS_INFO" or "MEMCACHE"' )
twitter = oauth.Init('twitter',
base_url='https://api.twitter.com/1.1/',
diff --git a/app.yaml b/app.yaml
new file mode 100644
index 0000000..42ad914
--- /dev/null
+++ b/app.yaml
@@ -0,0 +1,13 @@
+application: confweb
+version: 1
+runtime: python27
+threadsafe: yes
+api_version: 1
+
+handlers:
+- url: .*
+ script: app.app
+
+libraries:
+- name: jinja2
+ version: latest
\ No newline at end of file
diff --git a/appengine_config.py b/appengine_config.py
index 56e77ad..fc28495 100644
--- a/appengine_config.py
+++ b/appengine_config.py
@@ -1,2 +1,12 @@
-import vendor
-vendor.add('lib')
\ No newline at end of file
+import os
+import sys
+
+from google.appengine.ext import vendor
+
+vendor.add('lib')
+
+# Fix for msvcrt import error https://github.com/gae-init/gae-init/pull/527
+# Otherwise, GAE local dev server fails at "import msvcrt" in "click" package
+if os.name == 'nt':
+ os.name = None
+ sys.platform = ''
\ No newline at end of file
diff --git a/cache.py b/cache.py
index 54d8c54..ccfb393 100644
--- a/cache.py
+++ b/cache.py
@@ -2,6 +2,11 @@
import pickle
import redis
+import os
+if os.getenv('SERVER_SOFTWARE', '').startswith('Google App Engine/') or os.getenv('SERVER_SOFTWARE', '').startswith('Development/'):
+ from google.appengine.api import memcache
+else:
+ import memcache
class Redis(object):
def __init__(self, host, port, db):
@@ -16,3 +21,37 @@ def get(self, key):
return None
return pickle.loads(thing)
+
+class Memcache:
+ def __init__(self, servers=[], debug=0):
+ if os.getenv('SERVER_SOFTWARE', '').startswith('Google App Engine/') or os.getenv('SERVER_SOFTWARE', '').startswith('Development/'):
+ print "GAE memcache used"
+ self.client = memcache
+ else:
+ def server_str(server):
+ host = server.get('host')
+ port = server.get('port')
+ if not host:
+ raise Exception("host missing in memcache servers settings" )
+ elif not port:
+ raise Exception("port missing in memcache servers settings" )
+ else:
+ return str( host + ':' + port )
+
+ if not servers:
+ raise Exception("servers missing in memcache settings")
+ else:
+ server_settings = map( server_str, servers )
+ print "Normal memcache used"
+ self.client = memcache.Client(server_settings, debug)
+
+ def set(self, key, val, expires=0):
+ self.client .set(key, val, expires)
+
+ def get(self, key):
+ thing = self.client .get(key)
+ if not thing:
+ return None
+
+ return thing
+
diff --git a/provision.mk b/provision.mk
index 0061e02..5b43b73 100644
--- a/provision.mk
+++ b/provision.mk
@@ -54,6 +54,7 @@ ubuntu-all:
ubuntu-root: \
ubuntu-apt \
ubuntu-redis \
+ ubuntu-memcached \
ubuntu-pip
ubuntu-user: \
@@ -75,6 +76,9 @@ ubuntu-apt:
ubuntu-redis:
apt-get install -y redis-server
+ubuntu-memcached:
+ apt-get install -y memcached
+
ubuntu-pip:
apt-get install -y python-pip
pip install -r /vagrant/requirements.txt
diff --git a/requirements.txt b/requirements.txt
index b4d89f4..cc61f6b 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -5,6 +5,7 @@ flask_oauth
jinja2
py-gfm
redis
+python-memcached
urllib3
wsgi-request-logger
werkzeug
diff --git a/vendor.py b/vendor.py
deleted file mode 100644
index 4609019..0000000
--- a/vendor.py
+++ /dev/null
@@ -1,71 +0,0 @@
-#
-# Copyright 2014 Jon Wayne Parrott, [proppy], Michael R. Bernstein
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-# Notes:
-# - Imported from https://github.com/jonparrott/Darth-Vendor/.
-# - Added license header.
-# - Renamed `darth.vendor` to `vendor.add` to match upcoming SDK interface.
-# - Renamed `position` param to `index` to match upcoming SDK interface.
-# - Removed funny arworks docstring.
-
-import site
-import os.path
-import sys
-
-
-def add(folder, index=1):
- """
- Adds the given folder to the python path. Supports namespaced packages.
- By default, packages in the given folder take precedence over site-packages
- and any previous path manipulations.
-
- Args:
- folder: Path to the folder containing packages, relative to ``os.getcwd()``
- position: Where in ``sys.path`` to insert the vendor packages. By default
- this is set to 1. It is inadvisable to set it to 0 as it will override
- any modules in the current working directory.
- """
-
- # Check if the path contains a virtualenv.
- site_dir = os.path.join(folder, 'lib', 'python' + sys.version[:3], 'site-packages')
- if os.path.exists(site_dir):
- folder = site_dir
- # Otherwise it's just a normal path, make it absolute.
- else:
- folder = os.path.join(os.path.dirname(__file__), folder)
-
- # Use site.addsitedir() because it appropriately reads .pth
- # files for namespaced packages. Unfortunately, there's not an
- # option to choose where addsitedir() puts its paths in sys.path
- # so we have to do a little bit of magic to make it play along.
-
- # We're going to grab the current sys.path and split it up into
- # the first entry and then the rest. Essentially turning
- # ['.', '/site-packages/x', 'site-packages/y']
- # into
- # ['.'] and ['/site-packages/x', 'site-packages/y']
- # The reason for this is we want '.' to remain at the top of the
- # list but we want our vendor files to override everything else.
- sys.path, remainder = sys.path[:1], sys.path[1:]
-
- # Now we call addsitedir which will append our vendor directories
- # to sys.path (which was truncated by the last step.)
- site.addsitedir(folder)
-
- # Finally, we'll add the paths we removed back.
- # The final product is something like this:
- # ['.', '/vendor-folder', /site-packages/x', 'site-packages/y']
- sys.path.extend(remainder)
\ No newline at end of file