Skip to content

Commit 58e9e91

Browse files
author
Takashi Matsuo
authored
[appengine] chore: remove gcp-devrel-py-tools (GoogleCloudPlatform#3474)
1 parent 68d7400 commit 58e9e91

File tree

22 files changed

+333
-20
lines changed

22 files changed

+333
-20
lines changed
Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,2 @@
11
pytest==4.6.9
2-
gcp-devrel-py-tools==0.0.15
32
responses==0.10.12
Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
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+
15+
"""
16+
Common testing tools for Google App Engine tests.
17+
"""
18+
19+
import os
20+
import sys
21+
import tempfile
22+
23+
import pytest
24+
import six
25+
26+
27+
def setup_sdk_imports():
28+
"""Sets up appengine SDK third-party imports."""
29+
if six.PY3:
30+
return
31+
32+
sdk_path = os.environ.get('GAE_SDK_PATH')
33+
34+
if not sdk_path:
35+
return
36+
37+
if os.path.exists(os.path.join(sdk_path, 'google_appengine')):
38+
sdk_path = os.path.join(sdk_path, 'google_appengine')
39+
40+
if 'google' in sys.modules:
41+
sys.modules['google'].__path__.append(
42+
os.path.join(sdk_path, 'google'))
43+
44+
# This sets up libraries packaged with the SDK, but puts them last in
45+
# sys.path to prevent clobbering newer versions
46+
sys.path.append(sdk_path)
47+
import dev_appserver
48+
sys.path.extend(dev_appserver.EXTRA_PATHS)
49+
50+
# Fixes timezone and other os-level items.
51+
import google.appengine.tools.os_compat
52+
(google.appengine.tools.os_compat)
53+
54+
55+
def import_appengine_config():
56+
"""Imports an application appengine_config.py. This is used to
57+
mimic the behavior of the runtime."""
58+
try:
59+
import appengine_config
60+
(appengine_config)
61+
except ImportError:
62+
pass
63+
64+
65+
def setup_testbed():
66+
"""Sets up the GAE testbed and enables common stubs."""
67+
from google.appengine.datastore import datastore_stub_util
68+
from google.appengine.ext import testbed as gaetestbed
69+
70+
# Setup the datastore and memcache stub.
71+
# First, create an instance of the Testbed class.
72+
tb = gaetestbed.Testbed()
73+
# Then activate the testbed, which prepares the service stubs for
74+
# use.
75+
tb.activate()
76+
# Create a consistency policy that will simulate the High
77+
# Replication consistency model.
78+
policy = datastore_stub_util.PseudoRandomHRConsistencyPolicy(
79+
probability=1.0)
80+
# Initialize the datastore stub with this policy.
81+
tb.init_datastore_v3_stub(
82+
datastore_file=tempfile.mkstemp()[1],
83+
consistency_policy=policy)
84+
tb.init_memcache_stub()
85+
86+
# Setup remaining stubs.
87+
tb.init_urlfetch_stub()
88+
tb.init_app_identity_stub()
89+
tb.init_blobstore_stub()
90+
tb.init_user_stub()
91+
tb.init_logservice_stub()
92+
# tb.init_taskqueue_stub(root_path='tests/resources')
93+
tb.init_taskqueue_stub()
94+
tb.taskqueue_stub = tb.get_stub(gaetestbed.TASKQUEUE_SERVICE_NAME)
95+
96+
return tb
97+
98+
99+
def run_taskqueue_tasks(testbed, app):
100+
"""Runs tasks that are queued in the GAE taskqueue."""
101+
from google.appengine.api import namespace_manager
102+
103+
tasks = testbed.taskqueue_stub.get_filtered_tasks()
104+
for task in tasks:
105+
namespace = task.headers.get('X-AppEngine-Current-Namespace', '')
106+
previous_namespace = namespace_manager.get_namespace()
107+
try:
108+
namespace_manager.set_namespace(namespace)
109+
app.post(
110+
task.url,
111+
task.extract_params(),
112+
headers=dict([
113+
(k, v) for k, v in task.headers.iteritems()
114+
if k.startswith('X-AppEngine')]))
115+
finally:
116+
namespace_manager.set_namespace(previous_namespace)
117+
118+
119+
# py.test helpers
120+
121+
@pytest.yield_fixture
122+
def testbed():
123+
"""py.test fixture for the GAE testbed."""
124+
testbed = setup_testbed()
125+
yield testbed
126+
testbed.deactivate()
127+
128+
129+
@pytest.fixture
130+
def login(testbed):
131+
"""py.test fixture for logging in GAE users."""
132+
def _login(email='user@example.com', id='123', is_admin=False):
133+
testbed.setup_env(
134+
user_email=email,
135+
user_id=id,
136+
user_is_admin='1' if is_admin else '0',
137+
overwrite=True)
138+
return _login
139+
140+
141+
@pytest.fixture
142+
def run_tasks(testbed):
143+
"""py.test fixture for running GAE tasks."""
144+
def _run_tasks(app):
145+
run_taskqueue_tasks(testbed, app)
146+
return _run_tasks
147+
148+
149+
def pytest_configure():
150+
"""conftest.py hook function for setting up SDK imports."""
151+
setup_sdk_imports()
152+
153+
154+
def pytest_runtest_call(item):
155+
"""conftest.py hook for setting up appengine configuration."""
156+
import_appengine_config()
Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,2 @@
11
pytest==4.6.9
2-
gcp-devrel-py-tools==0.0.15
32
WebTest==2.0.34
Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,2 @@
11
pytest==4.6.9
2-
gcp-devrel-py-tools==0.0.15
32
WebTest==2.0.34

appengine/standard/conftest.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
import os
1616

1717
# Import py.test hooks and fixtures for App Engine
18-
from gcp_devrel.testing.appengine import (
18+
from appengine_helper import (
1919
login,
2020
pytest_configure,
2121
pytest_runtest_call,
Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1 @@
11
pytest==4.6.9
2-
gcp-devrel-py-tools==0.0.15
Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
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+
15+
"""Fetches the most recent GAE SDK and extracts it to the given directory."""
16+
17+
from __future__ import print_function
18+
19+
import os
20+
import re
21+
import sys
22+
import zipfile
23+
24+
import requests
25+
26+
27+
if sys.version_info[0] == 2:
28+
from StringIO import StringIO
29+
elif sys.version_info[0] == 3:
30+
from io import StringIO
31+
32+
33+
SDK_RELEASES_URL = (
34+
'https://www.googleapis.com/storage/v1/b/appengine-sdks/o?prefix=featured')
35+
PYTHON_RELEASE_RE = re.compile(
36+
r'featured/google_appengine_(\d+?)\.(\d+?)\.(\d+?)\.zip')
37+
SDK_RELEASE_RE = re.compile(
38+
r'release: \"(\d+?)\.(\d+?)\.(\d+?)\"')
39+
40+
41+
def get_gae_versions():
42+
"""Gets a list of all of the available Python SDK versions, sorted with
43+
the newest last."""
44+
r = requests.get(SDK_RELEASES_URL)
45+
r.raise_for_status()
46+
47+
releases = r.json().get('items', {})
48+
49+
# We only care about the Python releases, which all are in the format
50+
# "featured/google_appengine_{version}.zip". We'll extract the version
51+
# number so we can sort the list by version, and finally get the download
52+
# URL.
53+
versions_and_urls = []
54+
for release in releases:
55+
match = PYTHON_RELEASE_RE.match(release['name'])
56+
57+
if not match:
58+
continue
59+
60+
versions_and_urls.append(
61+
([int(x) for x in match.groups()], release['mediaLink']))
62+
63+
return sorted(versions_and_urls, key=lambda x: x[0])
64+
65+
66+
def is_existing_up_to_date(destination, latest_version):
67+
"""Returns False if there is no existing install or if the existing install
68+
is out of date. Otherwise, returns True."""
69+
version_path = os.path.join(
70+
destination, 'google_appengine', 'VERSION')
71+
72+
if not os.path.exists(version_path):
73+
return False
74+
75+
with open(version_path, 'r') as f:
76+
version_line = f.readline()
77+
78+
match = SDK_RELEASE_RE.match(version_line)
79+
80+
if not match:
81+
print('Unable to parse version from:', version_line)
82+
return False
83+
84+
version = [int(x) for x in match.groups()]
85+
86+
return version >= latest_version
87+
88+
89+
def download_sdk(url):
90+
"""Downloads the SDK and returns a file-like object for the zip content."""
91+
r = requests.get(url)
92+
r.raise_for_status()
93+
return StringIO(r.content)
94+
95+
96+
def extract_zip(zip, destination):
97+
zip_contents = zipfile.ZipFile(zip)
98+
99+
if not os.path.exists(destination):
100+
os.makedirs(destination)
101+
102+
zip_contents.extractall(destination)
103+
104+
105+
def fixup_version(destination, version):
106+
"""Newer releases of the SDK do not have the version number set correctly
107+
in the VERSION file. Fix it up."""
108+
version_path = os.path.join(
109+
destination, 'google_appengine', 'VERSION')
110+
111+
with open(version_path, 'r') as f:
112+
version_data = f.read()
113+
114+
version_data = version_data.replace(
115+
'release: "0.0.0"',
116+
'release: "{}"'.format('.'.join(str(x) for x in version)))
117+
118+
with open(version_path, 'w') as f:
119+
f.write(version_data)
120+
121+
122+
def download_command(destination):
123+
"""Downloads and extracts the latest App Engine SDK to the given
124+
destination."""
125+
latest_two_versions = list(reversed(get_gae_versions()))[:2]
126+
127+
zip = None
128+
version_number = None
129+
130+
for version in latest_two_versions:
131+
if is_existing_up_to_date(destination, version[0]):
132+
print(
133+
'App Engine SDK already exists and is up to date '
134+
'at {}.'.format(destination))
135+
return
136+
137+
try:
138+
print('Downloading App Engine SDK {}'.format(
139+
'.'.join([str(x) for x in version[0]])))
140+
zip = download_sdk(version[1])
141+
version_number = version[0]
142+
break
143+
except Exception as e:
144+
print('Failed to download: {}'.format(e))
145+
continue
146+
147+
if not zip:
148+
return
149+
150+
print('Extracting SDK to {}'.format(destination))
151+
152+
extract_zip(zip, destination)
153+
fixup_version(destination, version_number)
154+
155+
print('App Engine SDK installed.')
156+
157+
158+
if __name__ == '__main__':
159+
if len(sys.argv) < 2:
160+
print("download-appengine-sdk.py dest")
161+
sys.exit(1)
162+
download_command(sys.argv[1])
Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,2 @@
11
pytest==4.6.9
2-
gcp-devrel-py-tools==0.0.15
32
mock==3.0.5
Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1 @@
11
pytest==4.6.9
2-
gcp-devrel-py-tools==0.0.15
Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,2 @@
11
pytest==4.6.9
2-
gcp-devrel-py-tools==0.0.15
32
mock==3.0.5

0 commit comments

Comments
 (0)