From eb0c460b11c8728d65f253c893fd7fe9fe89195f Mon Sep 17 00:00:00 2001 From: Bill Prin Date: Tue, 23 Aug 2016 11:35:56 -0700 Subject: [PATCH 1/5] Add Scipy example --- .gitignore | 1 + appengine/flexible/scipy/README.md | 3 + appengine/flexible/scipy/app.yaml | 6 ++ .../flexible/scipy/assets/google_logo.jpg | Bin 0 -> 21568 bytes .../scipy/assets/resized_google_logo.jpg | Bin 0 -> 8639 bytes .../fixtures/assets/resized_google_logo.jpg | Bin 0 -> 8639 bytes appengine/flexible/scipy/main.py | 53 ++++++++++++++++++ appengine/flexible/scipy/main_test.py | 35 ++++++++++++ appengine/flexible/scipy/requirements.txt | 4 ++ requirements-dev.txt | 1 + 10 files changed, 103 insertions(+) create mode 100644 appengine/flexible/scipy/README.md create mode 100644 appengine/flexible/scipy/app.yaml create mode 100644 appengine/flexible/scipy/assets/google_logo.jpg create mode 100644 appengine/flexible/scipy/assets/resized_google_logo.jpg create mode 100644 appengine/flexible/scipy/fixtures/assets/resized_google_logo.jpg create mode 100644 appengine/flexible/scipy/main.py create mode 100644 appengine/flexible/scipy/main_test.py create mode 100644 appengine/flexible/scipy/requirements.txt diff --git a/.gitignore b/.gitignore index 176a48ea6e7..ec89b62eeaf 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,4 @@ secrets.tar junit.xml credentials.dat .nox +appengine/flexible/scipy/assets/resized_google_logo.jpg \ No newline at end of file diff --git a/appengine/flexible/scipy/README.md b/appengine/flexible/scipy/README.md new file mode 100644 index 00000000000..8a5fb4ae6b8 --- /dev/null +++ b/appengine/flexible/scipy/README.md @@ -0,0 +1,3 @@ +# SciPy on App Engine Flexible + +This sample demonstrates using SciPy to resize an image on App Engine Flexible. diff --git a/appengine/flexible/scipy/app.yaml b/appengine/flexible/scipy/app.yaml new file mode 100644 index 00000000000..00539c11722 --- /dev/null +++ b/appengine/flexible/scipy/app.yaml @@ -0,0 +1,6 @@ +runtime: python +vm: true +entrypoint: gunicorn -b :$PORT main:app + +runtime_config: + python_version: 3 diff --git a/appengine/flexible/scipy/assets/google_logo.jpg b/appengine/flexible/scipy/assets/google_logo.jpg new file mode 100644 index 0000000000000000000000000000000000000000..5538eaed2bdfb5ccdb0f1082afb97a4d0cf1a465 GIT binary patch literal 21568 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 literal 0 HcmV?d00001 diff --git a/appengine/flexible/scipy/fixtures/assets/resized_google_logo.jpg b/appengine/flexible/scipy/fixtures/assets/resized_google_logo.jpg new file mode 100644 index 0000000000000000000000000000000000000000..971fb566e150e19fc8788bbb6f2b10ed75007e38 GIT binary patch literal 8639 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 literal 0 HcmV?d00001 diff --git a/appengine/flexible/scipy/main.py b/appengine/flexible/scipy/main.py new file mode 100644 index 00000000000..1802a9573ee --- /dev/null +++ b/appengine/flexible/scipy/main.py @@ -0,0 +1,53 @@ +# Copyright 2016 Google Inc. All Rights Reserved. +# +# 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 logging +import os + +from flask import Flask +from scipy.misc import imread +import scipy.misc + +app = Flask(__name__) + + +# [START scipy] +@app.route('/') +def resize(): + """Demonstrates using scipy to resize an image.""" + app_path = os.path.dirname(os.path.realpath(__file__)) + image_path = os.path.join(app_path, 'assets/google_logo.jpg') + img = imread(image_path) + img_tinted = scipy.misc.imresize(img, (300, 300)) + output_image_path = os.path.join( + app_path, 'assets/resized_google_logo.jpg') + # Write the tinted image back to disk + scipy.misc.imsave(output_image_path, img_tinted) + return "Image resized." +# [END scipy] + + +@app.errorhandler(500) +def server_error(e): + logging.exception('An error occurred during a request.') + return """ + An internal error occurred:
{}
+ See logs for full stacktrace. + """.format(e), 500 + + +if __name__ == '__main__': + # This is used when running locally. Gunicorn is used to run the + # application on Google App Engine. See entrypoint in app.yaml. + app.run(host='127.0.0.1', port=8080, debug=True) diff --git a/appengine/flexible/scipy/main_test.py b/appengine/flexible/scipy/main_test.py new file mode 100644 index 00000000000..7765f3bf450 --- /dev/null +++ b/appengine/flexible/scipy/main_test.py @@ -0,0 +1,35 @@ +# Copyright 2016 Google Inc. All Rights Reserved. +# +# 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 filecmp +import os + +import main + + +def test_index(): + main.app.testing = True + client = main.app.test_client() + test_path = os.path.dirname(os.path.realpath(__file__)) + asset_path = os.path.join( + test_path, 'assets/resized_google_logo.jpg') + fixtured_path = os.path.join( + test_path, 'fixtures/assets/resized_google_logo.jpg') + try: + os.remove(asset_path) + except OSError: + pass # if doesn't exist + r = client.get('/') + assert filecmp.cmp(asset_path, fixtured_path) + assert r.status_code == 200 diff --git a/appengine/flexible/scipy/requirements.txt b/appengine/flexible/scipy/requirements.txt new file mode 100644 index 00000000000..ed88c85aa90 --- /dev/null +++ b/appengine/flexible/scipy/requirements.txt @@ -0,0 +1,4 @@ +Flask==0.11.1 +gunicorn==19.6.0 +scipy==0.18.0 +Pillow==3.3.1 diff --git a/requirements-dev.txt b/requirements-dev.txt index ff23415e98a..d6141d603ff 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -40,6 +40,7 @@ requests==2.11.1 requests[security]==2.11.1 responses==0.5.1 rsa==3.4.2 +scipy==0.18.0 sendgrid==3.2.10 simplejson==3.8.2 six==1.10.0 From e7095773a10192430a628ebd63ae0d5ff0982423 Mon Sep 17 00:00:00 2001 From: Bill Prin Date: Tue, 23 Aug 2016 16:03:55 -0700 Subject: [PATCH 2/5] README fixups --- appengine/flexible/scipy/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appengine/flexible/scipy/README.md b/appengine/flexible/scipy/README.md index 8a5fb4ae6b8..4e979d65b01 100644 --- a/appengine/flexible/scipy/README.md +++ b/appengine/flexible/scipy/README.md @@ -1,3 +1,3 @@ # SciPy on App Engine Flexible -This sample demonstrates using SciPy to resize an image on App Engine Flexible. +This sample demonstrates how to use SciPy to resize an image on App Engine Flexible. From dd4816895b84197df0d2dca5cc613be41d867607 Mon Sep 17 00:00:00 2001 From: Bill Prin Date: Tue, 23 Aug 2016 17:25:22 -0700 Subject: [PATCH 3/5] To remove in squash --- appengine/flexible/scipy/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/appengine/flexible/scipy/README.md b/appengine/flexible/scipy/README.md index 4e979d65b01..4f0df036549 100644 --- a/appengine/flexible/scipy/README.md +++ b/appengine/flexible/scipy/README.md @@ -1,3 +1,4 @@ # SciPy on App Engine Flexible This sample demonstrates how to use SciPy to resize an image on App Engine Flexible. + From 0911a567e7715a76cde714b245787948ceaf4d5d Mon Sep 17 00:00:00 2001 From: Bill Prin Date: Wed, 24 Aug 2016 11:50:55 -0700 Subject: [PATCH 4/5] Fix import --- appengine/flexible/scipy/main.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/appengine/flexible/scipy/main.py b/appengine/flexible/scipy/main.py index 1802a9573ee..612042c19de 100644 --- a/appengine/flexible/scipy/main.py +++ b/appengine/flexible/scipy/main.py @@ -16,7 +16,6 @@ import os from flask import Flask -from scipy.misc import imread import scipy.misc app = Flask(__name__) @@ -28,7 +27,7 @@ def resize(): """Demonstrates using scipy to resize an image.""" app_path = os.path.dirname(os.path.realpath(__file__)) image_path = os.path.join(app_path, 'assets/google_logo.jpg') - img = imread(image_path) + img = scipy.misc.imread(image_path) img_tinted = scipy.misc.imresize(img, (300, 300)) output_image_path = os.path.join( app_path, 'assets/resized_google_logo.jpg') From 7204d5471356d7b97ae698595803eeec975bd46a Mon Sep 17 00:00:00 2001 From: Bill Prin Date: Wed, 24 Aug 2016 13:14:07 -0700 Subject: [PATCH 5/5] Fix gitignore --- .gitignore | 1 - appengine/flexible/scipy/.gitignore | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 appengine/flexible/scipy/.gitignore diff --git a/.gitignore b/.gitignore index ec89b62eeaf..176a48ea6e7 100644 --- a/.gitignore +++ b/.gitignore @@ -19,4 +19,3 @@ secrets.tar junit.xml credentials.dat .nox -appengine/flexible/scipy/assets/resized_google_logo.jpg \ No newline at end of file diff --git a/appengine/flexible/scipy/.gitignore b/appengine/flexible/scipy/.gitignore new file mode 100644 index 00000000000..de724cf6213 --- /dev/null +++ b/appengine/flexible/scipy/.gitignore @@ -0,0 +1 @@ +assets/resized_google_logo.jpg