blob: 5afdca6f00336f6d0fc7c9ac1eb2568f14e2d3d0 [file] [log] [blame]
#!/usr/bin/env python
#
# Copyright 2007 Google Inc.
#
# 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.
#
"""Invoke PHP after setting up the App Engine environment."""
import argparse
import os
import subprocess
import sys
import tempfile
import wsgiref.util
import google
from google.appengine.api import request_info
from google.appengine.datastore import datastore_stub_util
from google.appengine.tools.devappserver2 import api_server
from google.appengine.tools.devappserver2 import gcs_server
from google.appengine.tools.devappserver2.php import runtime
def _get_gcs_server():
server = gcs_server.GCSServer('localhost', 0)
server.start()
return server
class APIRequestInfo(request_info.RequestInfo):
"""Allows stubs to lookup state linked to the request making the API call."""
def __init__(self):
self._environ = {}
wsgiref.util.setup_testing_defaults(self._environ)
def get_request_url(self, request_id):
"""Returns the URL the request e.g. 'http://localhost:8080/foo?bar=baz'.
Args:
request_id: The string id of the request making the API call.
Returns:
The URL of the request as a string.
"""
return wsgiref.util.request_uri(self._environ)
def get_request_environ(self, request_id):
"""Returns a dict containing the WSGI environ for the request."""
return self._environ
def get_module(self, request_id):
"""Returns the name of the module serving this request.
Args:
request_id: The string id of the request making the API call.
Returns:
A str containing the module name.
"""
return 'default'
def get_version(self, request_id):
"""Returns the version of the module serving this request.
Args:
request_id: The string id of the request making the API call.
Returns:
A str containing the version.
"""
return '1'
def get_instance(self, request_id):
"""Returns the instance serving this request.
Args:
request_id: The string id of the request making the API call.
Returns:
An opaque representation of the instance serving this request. It should
only be passed to dispatcher methods expecting an instance.
"""
return object()
def get_dispatcher(self):
"""Returns the Dispatcher.
Returns:
The Dispatcher instance.
"""
return request_info._LocalFakeDispatcher()
def _get_api_server(app_id):
"""Return a configured and started api_server.APIServer."""
tmp_dir = tempfile.mkdtemp()
os.environ['APPLICATION_ID'] = app_id
api_server.setup_stubs(
request_data=APIRequestInfo(),
app_id=app_id,
application_root=os.getcwd(),
trusted=False,
appidentity_email_address=None,
appidentity_private_key_path=None,
blobstore_path=tmp_dir,
datastore_consistency=
datastore_stub_util.PseudoRandomHRConsistencyPolicy(),
datastore_path=':memory:',
datastore_require_indexes=False,
datastore_auto_id_policy=datastore_stub_util.SCATTERED,
images_host_prefix='http://localhost:8080',
logs_path=':memory:',
mail_smtp_host='',
mail_smtp_port=25,
mail_smtp_user='',
mail_smtp_password='',
mail_enable_sendmail=False,
mail_show_mail_body=False,
matcher_prospective_search_path=tmp_dir,
search_index_path=None,
taskqueue_auto_run_tasks=False,
taskqueue_default_http_server='http://localhost:8080',
user_login_url='/_ah/login?continue=%s',
user_logout_url='/_ah/login?continue=%s',
default_gcs_bucket_name=None)
server = api_server.APIServer('localhost', 0, app_id)
server.start()
return server
def _get_default_php_cli_path():
"""Returns the path to the siloed php cli binary or None if not present."""
default_php_executable_path = None
google_package_directory = os.path.dirname(google.__file__)
sdk_directory = os.path.dirname(google_package_directory)
if sys.platform == 'win32':
default_php_executable_path = os.path.abspath(
os.path.join(sdk_directory, 'php/php-5.4-Win32-VC9-x86/php.exe'))
elif sys.platform == 'darwin':
default_php_executable_path = os.path.abspath(
os.path.join(os.path.dirname(sdk_directory), 'php'))
if (default_php_executable_path and
os.path.exists(default_php_executable_path)):
return default_php_executable_path
return None
def _parse_path(value):
"""Returns the given path with ~ and environment variables expanded."""
return os.path.expanduser(os.path.expandvars(value))
def _create_command_line_parser():
"""Returns an argparse.ArgumentParser to parse command line arguments."""
parser = argparse.ArgumentParser(
usage='usage: %(prog)s [execution options] <script> [script_args]',
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument(
'script',
help='the path to the PHP script that should be executed')
parser.add_argument(
'script_args',
help='the command arguments that will be passed to the script',
nargs=argparse.REMAINDER)
execution_group = parser.add_argument_group('Execution Options')
php_cli_path = _get_default_php_cli_path()
execution_group.add_argument('--php_executable_path', metavar='PATH',
type=_parse_path,
default=php_cli_path,
required=php_cli_path is None,
help='path to the PHP executable')
return parser
def main():
parser = _create_command_line_parser()
options = parser.parse_args()
if not options.php_executable_path:
parser.error('--php_executable_path must be set')
elif not os.path.exists(options.php_executable_path):
parser.error('--php_executable_path=%s, %s does not exist' % (
options.php_executable_path, options.php_executable_path))
php_script = os.path.abspath(_parse_path(options.script))
if not os.path.exists(php_script):
parser.error('%s does not exist' % php_script)
api_srver = _get_api_server(app_id='dummy_app_id')
gcs_srver = _get_gcs_server()
include_paths = [runtime.SDK_PATH]
if sys.platform == 'win32':
include_path = 'include_path="%s"' % ';'.join(include_paths)
else:
include_path = 'include_path=%s' % ':'.join(include_paths)
php_args = [options.php_executable_path,
'-d', include_path,
'-f', runtime.SETUP_PHP_PATH,]
php_args.extend(options.script_args)
env = dict(HTTP_HOST='localhost:%d' % gcs_srver.port,
SERVER_SOFTWARE='Development/CLI',
REAL_SCRIPT_FILENAME=php_script,
REMOTE_API_HOST='localhost',
REMOTE_API_PORT=str(api_srver.port),
REMOTE_REQUEST_ID='51',
APPLICATION_ROOT=os.path.dirname(php_script))
if 'SYSTEMROOT' in os.environ:
env['SYSTEMROOT'] = os.environ['SYSTEMROOT']
php_process = subprocess.Popen(php_args, env=env)
script_return = php_process.wait()
api_srver.quit()
gcs_srver.quit()
sys.exit(script_return)
if __name__ == '__main__':
main()