mirror of
https://github.com/google/blockly.git
synced 2025-12-15 13:50:08 +01:00
‘Upgrade’ from Python 2.7 to Python 3.7
Python is a non-issue. But App Engine took the opportunity to change everything.
This commit is contained in:
23
appengine/.gcloudignore
Normal file
23
appengine/.gcloudignore
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
# Do not upload these files.
|
||||||
|
.*
|
||||||
|
deploy
|
||||||
|
*.soy
|
||||||
|
static/appengine/
|
||||||
|
static/closure/
|
||||||
|
static/demos/plane/soy/*.jar
|
||||||
|
static/demos/plane/xlf/
|
||||||
|
static/externs/
|
||||||
|
static/i18n/
|
||||||
|
static/msg/json/
|
||||||
|
static/node_modules/
|
||||||
|
static/package/
|
||||||
|
static/theme_scripts/
|
||||||
|
static/typings/
|
||||||
|
|
||||||
|
static/build.py
|
||||||
|
static/gulpfile.js
|
||||||
|
static/jsconfig.json
|
||||||
|
static/LICENSE
|
||||||
|
static/package-lock.json
|
||||||
|
static/package.json
|
||||||
|
static/README.md
|
||||||
@@ -1,8 +1,4 @@
|
|||||||
application: blockly-demo
|
runtime: python37
|
||||||
version: 20200123
|
|
||||||
runtime: python27
|
|
||||||
api_version: 1
|
|
||||||
threadsafe: no
|
|
||||||
|
|
||||||
handlers:
|
handlers:
|
||||||
# Redirect obsolete URLs.
|
# Redirect obsolete URLs.
|
||||||
@@ -19,29 +15,15 @@ handlers:
|
|||||||
static_files: redirect.html
|
static_files: redirect.html
|
||||||
upload: redirect.html
|
upload: redirect.html
|
||||||
|
|
||||||
|
|
||||||
# Storage API.
|
|
||||||
- url: /storage
|
|
||||||
script: storage.py
|
|
||||||
secure: always
|
|
||||||
- url: /storage\.js
|
|
||||||
static_files: storage.js
|
|
||||||
upload: storage\.js
|
|
||||||
secure: always
|
|
||||||
|
|
||||||
# Blockly files.
|
# Blockly files.
|
||||||
- url: /static
|
- url: /static
|
||||||
static_dir: static
|
static_dir: static
|
||||||
secure: always
|
secure: always
|
||||||
|
|
||||||
# Closure library for uncompressed Blockly.
|
# Storage API.
|
||||||
- url: /closure-library
|
- url: /storage\.js
|
||||||
static_dir: closure-library
|
static_files: storage.js
|
||||||
secure: always
|
upload: storage\.js
|
||||||
|
|
||||||
# Redirect for root directory.
|
|
||||||
- url: /
|
|
||||||
script: index_redirect.py
|
|
||||||
secure: always
|
secure: always
|
||||||
|
|
||||||
# Favicon.
|
# Favicon.
|
||||||
@@ -64,24 +46,8 @@ handlers:
|
|||||||
upload: robots\.txt
|
upload: robots\.txt
|
||||||
secure: always
|
secure: always
|
||||||
|
|
||||||
|
# Dynamic content.
|
||||||
skip_files:
|
- url: /.*
|
||||||
# App Engine default patterns.
|
script: auto
|
||||||
- ^(.*/)?#.*#$
|
secure: always
|
||||||
- ^(.*/)?.*~$
|
|
||||||
- ^(.*/)?.*\.py[co]$
|
|
||||||
- ^(.*/)?.*/RCS/.*$
|
|
||||||
- ^(.*/)?\..*$
|
|
||||||
# Custom skip patterns.
|
|
||||||
- ^static/appengine/.*$
|
|
||||||
- ^static/demos/plane/soy/.+\.jar$
|
|
||||||
- ^static/demos/plane/template.soy$
|
|
||||||
- ^static/demos/plane/xlf/.*$
|
|
||||||
- ^static/i18n/.*$
|
|
||||||
- ^static/msg/json/.*$
|
|
||||||
- ^.+\.soy$
|
|
||||||
- ^closure-library/.*_test.html$
|
|
||||||
- ^closure-library/.*_test.js$
|
|
||||||
- ^closure-library/closure/bin/.*$
|
|
||||||
- ^closure-library/doc/.*$
|
|
||||||
- ^closure-library/scripts/.*$
|
|
||||||
16
appengine/deploy
Executable file
16
appengine/deploy
Executable file
@@ -0,0 +1,16 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Script to deploy on GAE.
|
||||||
|
|
||||||
|
APP=./app.yaml
|
||||||
|
if ! [ -f $APP ] ; then
|
||||||
|
echo $APP not found 1>&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
PROJECT=blockly-demo
|
||||||
|
VERSION=37
|
||||||
|
|
||||||
|
echo 'Beginning deployment...'
|
||||||
|
gcloud app deploy --project $PROJECT --version $VERSION --no-promote
|
||||||
|
echo 'Deployment finished.'
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
print("Status: 301")
|
|
||||||
print("Location: /static/demos/index.html")
|
|
||||||
print("")
|
|
||||||
43
appengine/main.py
Normal file
43
appengine/main.py
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
"""
|
||||||
|
Copyright 2020 Google LLC
|
||||||
|
|
||||||
|
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.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import cgi
|
||||||
|
import storage
|
||||||
|
from google.cloud import ndb
|
||||||
|
|
||||||
|
|
||||||
|
# Datastore model.
|
||||||
|
class Grid(ndb.Model):
|
||||||
|
data = ndb.StringProperty(required=True)
|
||||||
|
|
||||||
|
|
||||||
|
# Route to requested handler.
|
||||||
|
def app(environ, start_response):
|
||||||
|
if environ["PATH_INFO"] == "/":
|
||||||
|
return redirect(environ, start_response)
|
||||||
|
if environ["PATH_INFO"] == "/storage.py":
|
||||||
|
return storage.app(environ, start_response)
|
||||||
|
start_response("404 Not Found", [])
|
||||||
|
return [b"Page not found."]
|
||||||
|
|
||||||
|
|
||||||
|
# Redirect for root directory.
|
||||||
|
def redirect(environ, start_response):
|
||||||
|
headers = [
|
||||||
|
("Location", "static/demos/index.html")
|
||||||
|
]
|
||||||
|
start_response("301 Found", headers)
|
||||||
|
return []
|
||||||
1
appengine/requirements.txt
Normal file
1
appengine/requirements.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
google-cloud-ndb
|
||||||
@@ -23,8 +23,7 @@ __author__ = "q.neutron@gmail.com (Quynh Neutron)"
|
|||||||
import cgi
|
import cgi
|
||||||
import hashlib
|
import hashlib
|
||||||
from random import randint
|
from random import randint
|
||||||
from google.appengine.api import memcache
|
from google.cloud import ndb
|
||||||
from google.appengine.ext import ndb
|
|
||||||
|
|
||||||
|
|
||||||
def keyGen():
|
def keyGen():
|
||||||
@@ -41,46 +40,52 @@ class Xml(ndb.Model):
|
|||||||
|
|
||||||
def xmlToKey(xml_content):
|
def xmlToKey(xml_content):
|
||||||
# Store XML and return a generated key.
|
# Store XML and return a generated key.
|
||||||
xml_hash = long(hashlib.sha1(xml_content).hexdigest(), 16)
|
xml_hash = int(hashlib.sha1(xml_content.encode("utf-8")).hexdigest(), 16)
|
||||||
xml_hash = int(xml_hash % (2 ** 64) - (2 ** 63))
|
xml_hash = int(xml_hash % (2 ** 64) - (2 ** 63))
|
||||||
lookup_query = Xml.query(Xml.xml_hash == xml_hash)
|
lookup_query = Xml.query(Xml.xml_hash == xml_hash)
|
||||||
lookup_result = lookup_query.get()
|
client = ndb.Client()
|
||||||
if lookup_result:
|
with client.context():
|
||||||
xml_key = lookup_result.key.string_id()
|
lookup_result = lookup_query.get()
|
||||||
else:
|
if lookup_result:
|
||||||
trials = 0
|
xml_key = lookup_result.key.string_id()
|
||||||
result = True
|
else:
|
||||||
while result:
|
trials = 0
|
||||||
trials += 1
|
result = True
|
||||||
if trials == 100:
|
while result:
|
||||||
raise Exception("Sorry, the generator failed to get a key for you.")
|
trials += 1
|
||||||
xml_key = keyGen()
|
if trials == 100:
|
||||||
result = Xml.get_by_id(xml_key)
|
raise Exception("Sorry, the generator failed to get a key for you.")
|
||||||
row = Xml(id = xml_key, xml_hash = xml_hash, xml_content = xml_content)
|
xml_key = keyGen()
|
||||||
row.put()
|
result = Xml.get_by_id(xml_key)
|
||||||
|
row = Xml(id = xml_key, xml_hash = xml_hash, xml_content = xml_content)
|
||||||
|
row.put()
|
||||||
return xml_key
|
return xml_key
|
||||||
|
|
||||||
def keyToXml(key_provided):
|
def keyToXml(key_provided):
|
||||||
# Retrieve stored XML based on the provided key.
|
# Retrieve stored XML based on the provided key.
|
||||||
# Normalize the string.
|
# Normalize the string.
|
||||||
key_provided = key_provided.lower().strip()
|
key_provided = key_provided.lower().strip()
|
||||||
# Check memcache for a quick match.
|
# Check datastore for a match.
|
||||||
xml = memcache.get("XML_" + key_provided)
|
client = ndb.Client()
|
||||||
if xml is None:
|
with client.context():
|
||||||
# Check datastore for a definitive match.
|
|
||||||
result = Xml.get_by_id(key_provided)
|
result = Xml.get_by_id(key_provided)
|
||||||
if not result:
|
if not result:
|
||||||
xml = ""
|
xml = ""
|
||||||
else:
|
else:
|
||||||
xml = result.xml_content
|
xml = result.xml_content
|
||||||
# Save to memcache for next hit.
|
return xml
|
||||||
memcache.add("XML_" + key_provided, xml, 3600)
|
|
||||||
return xml.encode("utf-8")
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
def app(environ, start_response):
|
||||||
print("Content-Type: text/plain\n")
|
forms = cgi.FieldStorage(fp=environ['wsgi.input'], environ=environ)
|
||||||
forms = cgi.FieldStorage()
|
|
||||||
if "xml" in forms:
|
if "xml" in forms:
|
||||||
print(xmlToKey(forms["xml"].value))
|
out = xmlToKey(forms["xml"].value)
|
||||||
if "key" in forms:
|
elif "key" in forms:
|
||||||
print(keyToXml(forms["key"].value))
|
out = keyToXml(forms["key"].value)
|
||||||
|
else:
|
||||||
|
out = ""
|
||||||
|
|
||||||
|
headers = [
|
||||||
|
("Content-Type", "text/plain")
|
||||||
|
]
|
||||||
|
start_response("200 OK", headers)
|
||||||
|
return [out.encode("utf-8")]
|
||||||
|
|||||||
Reference in New Issue
Block a user