From 488539f636c97acedd47e4dcd450128f79bfa6a8 Mon Sep 17 00:00:00 2001 From: Neil Fraser Date: Thu, 19 Apr 2018 14:36:54 -0700 Subject: [PATCH] Update storage.py to use ndb instead of db. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Back-ports from Blockly Games: * db is old and busted, ndb is the new hotness (there’s no known difference, just pointless API churn). * Use SHA1 which is consistent, rather than Python’s hash() which has started changing between executions. This stops duplicate programs from being stored. * Restructure so that storage.py can be used as a library, with xmlToKey and keyToXml being callable by external programs. * Use print function compatible with Python 3. --- appengine/index_redirect.py | 3 ++- appengine/storage.py | 50 +++++++++++++++++++------------------ 2 files changed, 28 insertions(+), 25 deletions(-) diff --git a/appengine/index_redirect.py b/appengine/index_redirect.py index 286a8e87c..94cc26226 100644 --- a/appengine/index_redirect.py +++ b/appengine/index_redirect.py @@ -1,2 +1,3 @@ -print("Status: 302") +print("Status: 301") print("Location: /static/demos/index.html") +print("") diff --git a/appengine/storage.py b/appengine/storage.py index 4a572073f..122fe364d 100644 --- a/appengine/storage.py +++ b/appengine/storage.py @@ -22,35 +22,32 @@ limitations under the License. __author__ = "q.neutron@gmail.com (Quynh Neutron)" import cgi +import hashlib from random import randint -from google.appengine.ext import db from google.appengine.api import memcache -import logging +from google.appengine.ext import ndb -print "Content-Type: text/plain\n" def keyGen(): # Generate a random string of length KEY_LEN. KEY_LEN = 6 - CHARS = "abcdefghijkmnopqrstuvwxyz23456789" # Exclude l, 0, 1. + CHARS = "abcdefghijkmnopqrstuvwxyz23456789" # Exclude l, 0, 1. max_index = len(CHARS) - 1 return "".join([CHARS[randint(0, max_index)] for x in range(KEY_LEN)]) -class Xml(db.Model): +class Xml(ndb.Model): # A row in the database. - xml_hash = db.IntegerProperty() - xml_content = db.TextProperty() + xml_hash = ndb.IntegerProperty() + xml_content = ndb.TextProperty() -forms = cgi.FieldStorage() -if "xml" in forms: +def xmlToKey(xml_content): # Store XML and return a generated key. - xml_content = forms["xml"].value - xml_hash = hash(xml_content) - lookup_query = db.Query(Xml) - lookup_query.filter("xml_hash =", xml_hash) + xml_hash = long(hashlib.sha1(xml_content).hexdigest(), 16) + xml_hash = int(xml_hash % (2 ** 64) - (2 ** 63)) + lookup_query = Xml.query(Xml.xml_hash == xml_hash) lookup_result = lookup_query.get() if lookup_result: - xml_key = lookup_result.key().name() + xml_key = lookup_result.key.string_id() else: trials = 0 result = True @@ -59,27 +56,32 @@ if "xml" in forms: if trials == 100: raise Exception("Sorry, the generator failed to get a key for you.") xml_key = keyGen() - result = db.get(db.Key.from_path("Xml", xml_key)) - xml = db.Text(xml_content, encoding="utf_8") - row = Xml(key_name = xml_key, xml_hash = xml_hash, xml_content = xml) + result = Xml.get_by_id(xml_key) + row = Xml(id = xml_key, xml_hash = xml_hash, xml_content = xml_content) row.put() - print xml_key + return xml_key -if "key" in forms: +def keyToXml(key_provided): # Retrieve stored XML based on the provided key. - key_provided = forms["key"].value # Normalize the string. key_provided = key_provided.lower().strip() # Check memcache for a quick match. xml = memcache.get("XML_" + key_provided) if xml is None: # Check datastore for a definitive match. - result = db.get(db.Key.from_path("Xml", key_provided)) + result = Xml.get_by_id(key_provided) if not result: xml = "" else: xml = result.xml_content # Save to memcache for next hit. - if not memcache.add("XML_" + key_provided, xml, 3600): - logging.error("Memcache set failed.") - print xml.encode("utf-8") + memcache.add("XML_" + key_provided, xml, 3600) + return xml.encode("utf-8") + +if __name__ == "__main__": + print("Content-Type: text/plain\n") + forms = cgi.FieldStorage() + if "xml" in forms: + print(xmlToKey(forms["xml"].value)) + if "key" in forms: + print(keyToXml(forms["key"].value))