Skip to content
This repository was archived by the owner on Oct 1, 2025. It is now read-only.

Commit a2e0916

Browse files
committed
initial checkin
1 parent 3623895 commit a2e0916

File tree

71 files changed

+439
-1047
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

71 files changed

+439
-1047
lines changed

README.md

Lines changed: 59 additions & 41 deletions
Large diffs are not rendered by default.

step0-webapp2-gaendb-py2/app.yaml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,17 @@
1+
# Copyright 2020 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
115
runtime: python27
216
threadsafe: yes
317
api_version: 1

step0-webapp2-gaendb-py2/main.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# you may not use this file except in compliance with the License.
55
# You may obtain a copy of the License at
66
#
7-
# http://apache.org/licenses/LICENSE-2.0
7+
# http://www.apache.org/licenses/LICENSE-2.0
88
#
99
# Unless required by applicable law or agreed to in writing, software
1010
# distributed under the License is distributed on an "AS IS" BASIS,

step1-flask-gaendb-py2/README.md

Lines changed: 3 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -202,81 +202,6 @@ AFTER:
202202

203203
---
204204

205-
## Summary
206-
207-
For the sample app in this tutorial, the overall contextual set of `diff`s look like this:
208-
209-
$ diff -c step[01]*
210-
Only in step1-flask-gaendb-py2: README.md
211-
Only in step1-flask-gaendb-py2: appengine_config.py
212-
Only in step0-webapp2-gaendb-py2: index.html
213-
diff -c step0-webapp2-gaendb-py2/main.py step1-flask-gaendb-py2/main.py
214-
*** step0-webapp2-gaendb-py2/main.py 2020-07-29 13:56:27.000000000 -0700
215-
--- step1-flask-gaendb-py2/main.py 2020-07-25 13:58:18.000000000 -0700
216-
***************
217-
*** 1,7 ****
218-
! import os
219-
! import webapp2
220-
from google.appengine.ext import ndb
221-
! from google.appengine.ext.webapp import template
222-
223-
class Visit(ndb.Model):
224-
visitor = ndb.StringProperty()
225-
--- 1,7 ----
226-
! from flask import Flask, render_template, request
227-
from google.appengine.ext import ndb
228-
!
229-
! app = Flask(__name__)
230-
231-
class Visit(ndb.Model):
232-
visitor = ndb.StringProperty()
233-
***************
234-
*** 14,26 ****
235-
return (v.to_dict() for v in Visit.query().order(
236-
-Visit.timestamp).fetch_page(limit)[0])
237-
238-
! class MainHandler(webapp2.RequestHandler):
239-
! def get(self):
240-
! store_visit(self.request.remote_addr, self.request.user_agent)
241-
! visits = fetch_visits(10) or () # empty sequence if None
242-
! tmpl = os.path.join(os.path.dirname(__file__), 'index.html')
243-
! self.response.out.write(template.render(tmpl, {'visits': visits}))
244-
!
245-
! app = webapp2.WSGIApplication([
246-
! ('/', MainHandler),
247-
! ], debug=True)
248-
--- 14,21 ----
249-
return (v.to_dict() for v in Visit.query().order(
250-
-Visit.timestamp).fetch_page(limit)[0])
251-
252-
! @app.route('/')
253-
! def root():
254-
! store_visit(request.remote_addr, request.user_agent)
255-
! visits = fetch_visits(10) or () # empty sequence if None
256-
! return render_template('index.html', visits=visits)
257-
Only in step1-flask-gaendb-py2: requirements.txt
258-
Only in step1-flask-gaendb-py2: templates
259-
260-
The `diff` for the index HTML file isn't shown above as it changed folders, but here is an explcit contextual `diff`:
261-
262-
$ diff -c step0*/index.html step1*/templates/index.html
263-
*** step0-webapp2-gaendb-py2/index.html 2020-08-05 00:12:42.000000000 -0700
264-
--- step1-flask-gaendb-py2/templates/index.html 2020-08-05 00:13:06.000000000 -0700
265-
***************
266-
*** 8,14 ****
267-
<h3>Last 10 visits</h3>
268-
<ul>
269-
{% for visit in visits %}
270-
! <li>{{ visit.timestamp.ctime }} from {{ visit.visitor }}</li>
271-
{% endfor %}
272-
</ul>
273-
274-
--- 8,14 ----
275-
<h3>Last 10 visits</h3>
276-
<ul>
277-
{% for visit in visits %}
278-
! <li>{{ visit.timestamp.ctime() }} from {{ visit.visitor }}</li>
279-
{% endfor %}
280-
</ul>
281-
282-
In the next step, we will migrate from App Engine NDB to Google Cloud NDB, a key step because after you complete *that*, you can either stop there or be presented with a variety of options to choose from.
205+
## Next
206+
207+
[**Step 2:**](/step2-flask-cloudndb-py2) The next tutorial involves migrating from App Engine NDB to Google Cloud NDB, a key step because after you switch to the Cloud library, many options become available to you.

step1-flask-gaendb-py2/app.yaml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,17 @@
1+
# Copyright 2020 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
115
runtime: python27
216
threadsafe: yes
317
api_version: 1

step1-flask-gaendb-py2/appengine_config.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# you may not use this file except in compliance with the License.
55
# You may obtain a copy of the License at
66
#
7-
# http://apache.org/licenses/LICENSE-2.0
7+
# http://www.apache.org/licenses/LICENSE-2.0
88
#
99
# Unless required by applicable law or agreed to in writing, software
1010
# distributed under the License is distributed on an "AS IS" BASIS,

step1-flask-gaendb-py2/main.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# you may not use this file except in compliance with the License.
55
# You may obtain a copy of the License at
66
#
7-
# http://apache.org/licenses/LICENSE-2.0
7+
# http://www.apache.org/licenses/LICENSE-2.0
88
#
99
# Unless required by applicable law or agreed to in writing, software
1010
# distributed under the License is distributed on an "AS IS" BASIS,

step2-flask-cloudndb-py2/README.md

Lines changed: 8 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ App Engine services have blossomed into their own products, and App Engine's Dat
1818
1. Update `requirements.txt` to include the Cloud NDB library (`google-cloud-ndb`).
1919
1. Update `app.yaml` to reference a pair of 3rd-party bundled packages: `grpcio` and `setuptools`
2020
1. Update `appengine_config.py` to use the `pkg_resources` tool (which comes with `setuptools`) so App Engine can access [3rd-party libraries already available on Google servers](https://cloud.google.com/appengine/docs/standard/python/tools/built-in-libraries-27) so users don't have to list them in `requirements.txt` nor `pip install` them.
21+
1. Similarly, [gRPC](http://grpc.io) is used by all [*Google Cloud* client libraries](https://cloud.google.com/apis/docs/cloud-client-libraries), and `grpcio` is the gRPC package for Python and thus required.
2122
1. Switch application code to use the Cloud NDB client library
2223

2324
### Configuration
@@ -155,99 +156,10 @@ def fetch_visits(limit):
155156

156157
---
157158

158-
## Summary
159-
160-
For this migration step, here are the contextual `diff`s:
161-
162-
$ diff -c step[12]*py2
163-
diff -c step1-flask-gaendb-py2/app.yaml step2-flask-cloudndb-py2/app.yaml
164-
*** step1-flask-gaendb-py2/app.yaml 2020-07-25 14:10:53.000000000 -0700
165-
--- step2-flask-cloudndb-py2/app.yaml 2020-08-05 00:09:42.000000000 -0700
166-
***************
167-
*** 5,7 ****
168-
--- 5,13 ----
169-
handlers:
170-
- url: /.*
171-
script: main.app
172-
+
173-
+ libraries:
174-
+ - name: grpcio
175-
+ version: 1.0.0
176-
+ - name: setuptools
177-
+ version: 36.6.0
178-
diff -c step1-flask-gaendb-py2/appengine_config.py step2-flask-cloudndb-py2/appengine_config.py
179-
*** step1-flask-gaendb-py2/appengine_config.py 2020-07-24 23:09:45.000000000 -0700
180-
--- step2-flask-cloudndb-py2/appengine_config.py 2020-07-24 22:50:57.000000000 -0700
181-
***************
182-
*** 1,6 ****
183-
--- 1,9 ----
184-
+ import pkg_resources
185-
from google.appengine.ext import vendor
186-
187-
# Set PATH to your libraries folder.
188-
PATH = 'lib'
189-
# Add libraries installed in the PATH folder.
190-
vendor.add(PATH)
191-
+ # Add libraries to pkg_resources working set to find the distribution.
192-
+ pkg_resources.working_set.add_entry(PATH)
193-
diff -c step1-flask-gaendb-py2/main.py step2-flask-cloudndb-py2/main.py
194-
*** step1-flask-gaendb-py2/main.py 2020-07-25 13:58:18.000000000 -0700
195-
--- step2-flask-cloudndb-py2/main.py 2020-07-25 14:00:56.000000000 -0700
196-
***************
197-
*** 1,18 ****
198-
from flask import Flask, render_template, request
199-
! from google.appengine.ext import ndb
200-
201-
app = Flask(__name__)
202-
203-
class Visit(ndb.Model):
204-
visitor = ndb.StringProperty()
205-
timestamp = ndb.DateTimeProperty(auto_now_add=True)
206-
207-
def store_visit(remote_addr, user_agent):
208-
! Visit(visitor='{}: {}'.format(remote_addr, user_agent)).put()
209-
210-
def fetch_visits(limit):
211-
! return (v.to_dict() for v in Visit.query().order(
212-
! -Visit.timestamp).fetch_page(limit)[0])
213-
214-
@app.route('/')
215-
def root():
216-
--- 1,21 ----
217-
from flask import Flask, render_template, request
218-
! from google.cloud import ndb
219-
220-
app = Flask(__name__)
221-
+ ds_client = ndb.Client()
222-
223-
class Visit(ndb.Model):
224-
visitor = ndb.StringProperty()
225-
timestamp = ndb.DateTimeProperty(auto_now_add=True)
226-
227-
def store_visit(remote_addr, user_agent):
228-
! with ds_client.context():
229-
! Visit(visitor='{}: {}'.format(remote_addr, user_agent)).put()
230-
231-
def fetch_visits(limit):
232-
! with ds_client.context():
233-
! return (v.to_dict() for v in Visit.query().order(
234-
! -Visit.timestamp).fetch_page(limit)[0])
235-
236-
@app.route('/')
237-
def root():
238-
diff -c step1-flask-gaendb-py2/requirements.txt step2-flask-cloudndb-py2/requirements.txt
239-
*** step1-flask-gaendb-py2/requirements.txt 2020-07-24 19:27:45.000000000 -0700
240-
--- step2-flask-cloudndb-py2/requirements.txt 2020-07-24 21:59:58.000000000 -0700
241-
***************
242-
*** 1 ****
243-
--- 1,2 ----
244-
Flask
245-
+ google-cloud-ndb
246-
Common subdirectories: step1-flask-gaendb-py2/templates and step2-flask-cloudndb-py2/templates
247-
248-
From here, you have some flexibility as to your next move. You can...
249-
250-
- Continue to use NDB but migrate your app to a container executing serverlessly on Cloud Run (see `step2a-flask-cloudndb-py2-cloudrun`)
251-
- Port your app to Python 3 (see `step2-flask-cloudndb-py3`)
252-
- Combine both of the above steps (migrate to Python 3 *and* Cloud Run; no example provided but extrapolate from above)
253-
- Further modernize Datastore access from Cloud NDB to the (official) Cloud Datastore library (how users *outside of* App Engine access Cloud Datastore) (see `step3-flask-datastore-py2`)
159+
## Next
160+
161+
From here, there's flexibility as to your next move. Choose any of these options:
162+
163+
- [**Step 2:**](/step2-flask-cloudndb-py3) Port your app to Python 3 to get you on the next generation App Engine runtime as Python 2 has reached its end-of-life.
164+
- [**Step 4:**](/step4-cloudndb-cloudrun-py2) Continue to use NDB but migrate your app to a container executing serverlessly on Cloud Run.
165+
- [**Step 3:**](/step3-flask-datastore-py2) Further modernize Datastore access from Cloud NDB to the (official) Cloud Datastore library (how users *outside of* App Engine access Cloud Datastore).

step2-flask-cloudndb-py2/app.yaml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,17 @@
1+
# Copyright 2020 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
115
runtime: python27
216
threadsafe: yes
317
api_version: 1

step2-flask-cloudndb-py2/appengine_config.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# you may not use this file except in compliance with the License.
55
# You may obtain a copy of the License at
66
#
7-
# http://apache.org/licenses/LICENSE-2.0
7+
# http://www.apache.org/licenses/LICENSE-2.0
88
#
99
# Unless required by applicable law or agreed to in writing, software
1010
# distributed under the License is distributed on an "AS IS" BASIS,

0 commit comments

Comments
 (0)