[MERGE] trunk
bzr revid: al@openerp.com-20140316183515-fthpvudn1rbmru4q
This commit is contained in:
commit
3168c3c1ca
|
@ -1273,11 +1273,6 @@ class CommonController(Controller):
|
||||||
""" Method used by client APIs to contact OpenERP. """
|
""" Method used by client APIs to contact OpenERP. """
|
||||||
return dispatch_rpc(service, method, args)
|
return dispatch_rpc(service, method, args)
|
||||||
|
|
||||||
@route('/gen_session_id', type='json', auth="none")
|
|
||||||
def gen_session_id(self):
|
|
||||||
nsession = root.session_store.new()
|
|
||||||
return nsession.sid
|
|
||||||
|
|
||||||
root = None
|
root = None
|
||||||
|
|
||||||
def wsgi_postload():
|
def wsgi_postload():
|
||||||
|
|
|
@ -1,12 +1,15 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
from contextlib import closing
|
||||||
import base64
|
from functools import wraps
|
||||||
import contextlib
|
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
import shutil
|
||||||
import threading
|
import threading
|
||||||
import traceback
|
import traceback
|
||||||
from contextlib import contextmanager, closing
|
import tempfile
|
||||||
|
import zipfile
|
||||||
|
|
||||||
|
import psycopg2
|
||||||
|
|
||||||
import openerp
|
import openerp
|
||||||
from openerp import SUPERUSER_ID
|
from openerp import SUPERUSER_ID
|
||||||
|
@ -28,7 +31,8 @@ def _initialize_db(id, db_name, demo, lang, user_password):
|
||||||
self_actions[id]['progress'] = 0
|
self_actions[id]['progress'] = 0
|
||||||
db = openerp.sql_db.db_connect(db_name)
|
db = openerp.sql_db.db_connect(db_name)
|
||||||
with closing(db.cursor()) as cr:
|
with closing(db.cursor()) as cr:
|
||||||
openerp.modules.db.initialize(cr) # TODO this should be removed as it is done by RegistryManager.new().
|
# TODO this should be removed as it is done by RegistryManager.new().
|
||||||
|
openerp.modules.db.initialize(cr)
|
||||||
openerp.tools.config['lang'] = lang
|
openerp.tools.config['lang'] = lang
|
||||||
cr.commit()
|
cr.commit()
|
||||||
|
|
||||||
|
@ -55,14 +59,13 @@ def _initialize_db(id, db_name, demo, lang, user_password):
|
||||||
self_actions[id]['traceback'] = traceback.format_exc()
|
self_actions[id]['traceback'] = traceback.format_exc()
|
||||||
|
|
||||||
def dispatch(method, params):
|
def dispatch(method, params):
|
||||||
if method in [ 'create', 'get_progress', 'drop', 'dump',
|
if method in ['create', 'get_progress', 'drop', 'dump', 'restore', 'rename',
|
||||||
'restore', 'rename',
|
'change_admin_password', 'migrate_databases',
|
||||||
'change_admin_password', 'migrate_databases',
|
'create_database', 'duplicate_database']:
|
||||||
'create_database', 'duplicate_database' ]:
|
|
||||||
passwd = params[0]
|
passwd = params[0]
|
||||||
params = params[1:]
|
params = params[1:]
|
||||||
security.check_super(passwd)
|
security.check_super(passwd)
|
||||||
elif method in [ 'db_exist', 'list', 'list_lang', 'server_version' ]:
|
elif method in ['db_exist', 'list', 'list_lang', 'server_version']:
|
||||||
# params = params
|
# params = params
|
||||||
# No security check for these methods
|
# No security check for these methods
|
||||||
pass
|
pass
|
||||||
|
@ -78,9 +81,9 @@ def _create_empty_database(name):
|
||||||
cr.execute("SELECT datname FROM pg_database WHERE datname = %s",
|
cr.execute("SELECT datname FROM pg_database WHERE datname = %s",
|
||||||
(name,))
|
(name,))
|
||||||
if cr.fetchall():
|
if cr.fetchall():
|
||||||
raise openerp.exceptions.Warning(" %s database already exists!" % name )
|
raise openerp.exceptions.Warning("database %r already exists!" % (name,))
|
||||||
else:
|
else:
|
||||||
cr.autocommit(True) # avoid transaction block
|
cr.autocommit(True) # avoid transaction block
|
||||||
cr.execute("""CREATE DATABASE "%s" ENCODING 'unicode' TEMPLATE "%s" """ % (name, chosen_template))
|
cr.execute("""CREATE DATABASE "%s" ENCODING 'unicode' TEMPLATE "%s" """ % (name, chosen_template))
|
||||||
|
|
||||||
def exp_create(db_name, demo, lang, user_password='admin'):
|
def exp_create(db_name, demo, lang, user_password='admin'):
|
||||||
|
@ -96,7 +99,7 @@ def exp_create(db_name, demo, lang, user_password='admin'):
|
||||||
|
|
||||||
_logger.info('CREATE DATABASE %s', db_name.lower())
|
_logger.info('CREATE DATABASE %s', db_name.lower())
|
||||||
create_thread = threading.Thread(target=_initialize_db,
|
create_thread = threading.Thread(target=_initialize_db,
|
||||||
args=(id, db_name, demo, lang, user_password))
|
args=(id, db_name, demo, lang, user_password))
|
||||||
create_thread.start()
|
create_thread.start()
|
||||||
self_actions[id]['thread'] = create_thread
|
self_actions[id]['thread'] = create_thread
|
||||||
return id
|
return id
|
||||||
|
@ -121,14 +124,14 @@ def exp_duplicate_database(db_original_name, db_name):
|
||||||
openerp.sql_db.close_db(db_original_name)
|
openerp.sql_db.close_db(db_original_name)
|
||||||
db = openerp.sql_db.db_connect('postgres')
|
db = openerp.sql_db.db_connect('postgres')
|
||||||
with closing(db.cursor()) as cr:
|
with closing(db.cursor()) as cr:
|
||||||
cr.autocommit(True) # avoid transaction block
|
cr.autocommit(True) # avoid transaction block
|
||||||
cr.execute("""CREATE DATABASE "%s" ENCODING 'unicode' TEMPLATE "%s" """ % (db_name, db_original_name))
|
cr.execute("""CREATE DATABASE "%s" ENCODING 'unicode' TEMPLATE "%s" """ % (db_name, db_original_name))
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def exp_get_progress(id):
|
def exp_get_progress(id):
|
||||||
if self_actions[id]['thread'].isAlive():
|
if self_actions[id]['thread'].isAlive():
|
||||||
# return openerp.modules.init_progress[db_name]
|
# return openerp.modules.init_progress[db_name]
|
||||||
return min(self_actions[id].get('progress', 0),0.95), []
|
return min(self_actions[id].get('progress', 0), 0.95), []
|
||||||
else:
|
else:
|
||||||
clean = self_actions[id]['clean']
|
clean = self_actions[id]['clean']
|
||||||
if clean:
|
if clean:
|
||||||
|
@ -140,9 +143,9 @@ def exp_get_progress(id):
|
||||||
self_actions.pop(id)
|
self_actions.pop(id)
|
||||||
return 1.0, users
|
return 1.0, users
|
||||||
else:
|
else:
|
||||||
e = self_actions[id]['exception'] # TODO this seems wrong: actions[id]['traceback'] is set, but not 'exception'.
|
a = self_actions.pop(id)
|
||||||
self_actions.pop(id)
|
exc, tb = a['exception'], a['traceback']
|
||||||
raise Exception, e
|
raise Exception, exc, tb
|
||||||
|
|
||||||
def exp_drop(db_name):
|
def exp_drop(db_name):
|
||||||
if db_name not in exp_list(True):
|
if db_name not in exp_list(True):
|
||||||
|
@ -152,18 +155,17 @@ def exp_drop(db_name):
|
||||||
|
|
||||||
db = openerp.sql_db.db_connect('postgres')
|
db = openerp.sql_db.db_connect('postgres')
|
||||||
with closing(db.cursor()) as cr:
|
with closing(db.cursor()) as cr:
|
||||||
cr.autocommit(True) # avoid transaction block
|
cr.autocommit(True) # avoid transaction block
|
||||||
# Try to terminate all other connections that might prevent
|
# Try to terminate all other connections that might prevent
|
||||||
# dropping the database
|
# dropping the database
|
||||||
try:
|
try:
|
||||||
|
|
||||||
# PostgreSQL 9.2 renamed pg_stat_activity.procpid to pid:
|
# PostgreSQL 9.2 renamed pg_stat_activity.procpid to pid:
|
||||||
# http://www.postgresql.org/docs/9.2/static/release-9-2.html#AEN110389
|
# http://www.postgresql.org/docs/9.2/static/release-9-2.html#AEN110389
|
||||||
pid_col = 'pid' if cr._cnx.server_version >= 90200 else 'procpid'
|
pid_col = 'pid' if cr._cnx.server_version >= 90200 else 'procpid'
|
||||||
|
|
||||||
cr.execute("""SELECT pg_terminate_backend(%(pid_col)s)
|
cr.execute("""SELECT pg_terminate_backend(%(pid_col)s)
|
||||||
FROM pg_stat_activity
|
FROM pg_stat_activity
|
||||||
WHERE datname = %%s AND
|
WHERE datname = %%s AND
|
||||||
%(pid_col)s != pg_backend_pid()""" % {'pid_col': pid_col},
|
%(pid_col)s != pg_backend_pid()""" % {'pid_col': pid_col},
|
||||||
(db_name,))
|
(db_name,))
|
||||||
except Exception:
|
except Exception:
|
||||||
|
@ -178,94 +180,140 @@ def exp_drop(db_name):
|
||||||
_logger.info('DROP DB: %s', db_name)
|
_logger.info('DROP DB: %s', db_name)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@contextlib.contextmanager
|
def _set_pg_password_in_environment(func):
|
||||||
def _set_pg_password_in_environment():
|
|
||||||
""" On systems where pg_restore/pg_dump require an explicit
|
""" On systems where pg_restore/pg_dump require an explicit
|
||||||
password (i.e. when not connecting via unix sockets, and most
|
password (i.e. when not connecting via unix sockets, and most
|
||||||
importantly on Windows), it is necessary to pass the PG user
|
importantly on Windows), it is necessary to pass the PG user
|
||||||
password in the environment or in a special .pgpass file.
|
password in the environment or in a special .pgpass file.
|
||||||
|
|
||||||
This context management method handles setting
|
This decorator handles setting
|
||||||
:envvar:`PGPASSWORD` if it is not already
|
:envvar:`PGPASSWORD` if it is not already
|
||||||
set, and removing it afterwards.
|
set, and removing it afterwards.
|
||||||
|
|
||||||
See also http://www.postgresql.org/docs/8.4/static/libpq-envars.html
|
See also http://www.postgresql.org/docs/8.4/static/libpq-envars.html
|
||||||
|
|
||||||
.. note:: This is not thread-safe, and should never be enabled for
|
.. note:: This is not thread-safe, and should never be enabled for
|
||||||
SaaS (giving SaaS users the super-admin password is not a good idea
|
SaaS (giving SaaS users the super-admin password is not a good idea
|
||||||
anyway)
|
anyway)
|
||||||
"""
|
"""
|
||||||
if os.environ.get('PGPASSWORD') or not openerp.tools.config['db_password']:
|
@wraps(func)
|
||||||
yield
|
def wrapper(*args, **kwargs):
|
||||||
else:
|
if os.environ.get('PGPASSWORD') or not openerp.tools.config['db_password']:
|
||||||
os.environ['PGPASSWORD'] = openerp.tools.config['db_password']
|
return func(*args, **kwargs)
|
||||||
try:
|
else:
|
||||||
yield
|
os.environ['PGPASSWORD'] = openerp.tools.config['db_password']
|
||||||
finally:
|
try:
|
||||||
del os.environ['PGPASSWORD']
|
return func(*args, **kwargs)
|
||||||
|
finally:
|
||||||
|
del os.environ['PGPASSWORD']
|
||||||
|
return wrapper
|
||||||
|
|
||||||
def exp_dump(db_name):
|
def exp_dump(db_name):
|
||||||
with _set_pg_password_in_environment():
|
with tempfile.TemporaryFile() as t:
|
||||||
cmd = ['pg_dump', '--format=c', '--no-owner']
|
dump_db(db_name, t)
|
||||||
|
t.seek(0)
|
||||||
|
return t.read().encode('base64')
|
||||||
|
|
||||||
|
@_set_pg_password_in_environment
|
||||||
|
def dump_db(db, stream):
|
||||||
|
"""Dump database `db` into file-like object `stream`"""
|
||||||
|
with openerp.tools.osutil.tempdir() as dump_dir:
|
||||||
|
registry = openerp.modules.registry.RegistryManager.get(db)
|
||||||
|
with registry.cursor() as cr:
|
||||||
|
filestore = registry['ir.attachment']._filestore(cr, SUPERUSER_ID)
|
||||||
|
if os.path.exists(filestore):
|
||||||
|
shutil.copytree(filestore, os.path.join(dump_dir, 'filestore'))
|
||||||
|
|
||||||
|
dump_file = os.path.join(dump_dir, 'dump.sql')
|
||||||
|
cmd = ['pg_dump', '--format=p', '--no-owner', '--file=' + dump_file]
|
||||||
if openerp.tools.config['db_user']:
|
if openerp.tools.config['db_user']:
|
||||||
cmd.append('--username=' + openerp.tools.config['db_user'])
|
cmd.append('--username=' + openerp.tools.config['db_user'])
|
||||||
if openerp.tools.config['db_host']:
|
if openerp.tools.config['db_host']:
|
||||||
cmd.append('--host=' + openerp.tools.config['db_host'])
|
cmd.append('--host=' + openerp.tools.config['db_host'])
|
||||||
if openerp.tools.config['db_port']:
|
if openerp.tools.config['db_port']:
|
||||||
cmd.append('--port=' + str(openerp.tools.config['db_port']))
|
cmd.append('--port=' + str(openerp.tools.config['db_port']))
|
||||||
cmd.append(db_name)
|
cmd.append(db)
|
||||||
|
|
||||||
stdin, stdout = openerp.tools.exec_pg_command_pipe(*tuple(cmd))
|
if openerp.tools.exec_pg_command(*cmd):
|
||||||
stdin.close()
|
_logger.error('DUMP DB: %s failed! Please verify the configuration of the database '
|
||||||
data = stdout.read()
|
'password on the server. You may need to create a .pgpass file for '
|
||||||
res = stdout.close()
|
'authentication, or specify `db_password` in the server configuration '
|
||||||
|
'file.', db)
|
||||||
|
raise Exception("Couldn't dump database")
|
||||||
|
|
||||||
if not data or res:
|
openerp.tools.osutil.zip_dir(dump_dir, stream, include_dir=False)
|
||||||
_logger.error(
|
|
||||||
'DUMP DB: %s failed! Please verify the configuration of the database password on the server. '
|
|
||||||
'You may need to create a .pgpass file for authentication, or specify `db_password` in the '
|
|
||||||
'server configuration file.\n %s', db_name, data)
|
|
||||||
raise Exception, "Couldn't dump database"
|
|
||||||
_logger.info('DUMP DB successful: %s', db_name)
|
|
||||||
|
|
||||||
return base64.encodestring(data)
|
_logger.info('DUMP DB successful: %s', db)
|
||||||
|
|
||||||
def exp_restore(db_name, data):
|
def exp_restore(db_name, data, copy=False):
|
||||||
with _set_pg_password_in_environment():
|
data_file = tempfile.NamedTemporaryFile(delete=False)
|
||||||
if exp_db_exist(db_name):
|
try:
|
||||||
_logger.warning('RESTORE DB: %s already exists', db_name)
|
data_file.write(data.decode('base64'))
|
||||||
raise Exception, "Database already exists"
|
data_file.close()
|
||||||
|
restore_db(db_name, data_file.name, copy=copy)
|
||||||
|
finally:
|
||||||
|
os.unlink(data_file.name)
|
||||||
|
return True
|
||||||
|
|
||||||
_create_empty_database(db_name)
|
@_set_pg_password_in_environment
|
||||||
|
def restore_db(db, dump_file, copy=False):
|
||||||
|
assert isinstance(db, basestring)
|
||||||
|
if exp_db_exist(db):
|
||||||
|
_logger.warning('RESTORE DB: %s already exists', db)
|
||||||
|
raise Exception("Database already exists")
|
||||||
|
|
||||||
cmd = ['pg_restore', '--no-owner']
|
_create_empty_database(db)
|
||||||
|
|
||||||
|
filestore_path = None
|
||||||
|
with openerp.tools.osutil.tempdir() as dump_dir:
|
||||||
|
if zipfile.is_zipfile(dump_file):
|
||||||
|
# v8 format
|
||||||
|
with zipfile.ZipFile(dump_file, 'r') as z:
|
||||||
|
# only extract known members!
|
||||||
|
filestore = [m for m in z.namelist() if m.startswith('filestore/')]
|
||||||
|
z.extractall(dump_dir, ['dump.sql'] + filestore)
|
||||||
|
|
||||||
|
if filestore:
|
||||||
|
filestore_path = os.path.join(dump_dir, 'filestore')
|
||||||
|
|
||||||
|
pg_cmd = 'psql'
|
||||||
|
pg_args = ['-q', '-f', os.path.join(dump_dir, 'dump.sql')]
|
||||||
|
|
||||||
|
else:
|
||||||
|
# <= 7.0 format (raw pg_dump output)
|
||||||
|
pg_cmd = 'pg_restore'
|
||||||
|
pg_args = ['--no-owner', dump_file]
|
||||||
|
|
||||||
|
args = []
|
||||||
if openerp.tools.config['db_user']:
|
if openerp.tools.config['db_user']:
|
||||||
cmd.append('--username=' + openerp.tools.config['db_user'])
|
args.append('--username=' + openerp.tools.config['db_user'])
|
||||||
if openerp.tools.config['db_host']:
|
if openerp.tools.config['db_host']:
|
||||||
cmd.append('--host=' + openerp.tools.config['db_host'])
|
args.append('--host=' + openerp.tools.config['db_host'])
|
||||||
if openerp.tools.config['db_port']:
|
if openerp.tools.config['db_port']:
|
||||||
cmd.append('--port=' + str(openerp.tools.config['db_port']))
|
args.append('--port=' + str(openerp.tools.config['db_port']))
|
||||||
cmd.append('--dbname=' + db_name)
|
args.append('--dbname=' + db)
|
||||||
args2 = tuple(cmd)
|
pg_args = args + pg_args
|
||||||
|
|
||||||
buf=base64.decodestring(data)
|
if openerp.tools.exec_pg_command(pg_cmd, *pg_args):
|
||||||
if os.name == "nt":
|
raise Exception("Couldn't restore database")
|
||||||
tmpfile = (os.environ['TMP'] or 'C:\\') + os.tmpnam()
|
|
||||||
file(tmpfile, 'wb').write(buf)
|
|
||||||
args2=list(args2)
|
|
||||||
args2.append(tmpfile)
|
|
||||||
args2=tuple(args2)
|
|
||||||
stdin, stdout = openerp.tools.exec_pg_command_pipe(*args2)
|
|
||||||
if not os.name == "nt":
|
|
||||||
stdin.write(base64.decodestring(data))
|
|
||||||
stdin.close()
|
|
||||||
res = stdout.close()
|
|
||||||
if res:
|
|
||||||
raise Exception, "Couldn't restore database"
|
|
||||||
_logger.info('RESTORE DB: %s', db_name)
|
|
||||||
|
|
||||||
return True
|
registry = openerp.modules.registry.RegistryManager.new(db)
|
||||||
|
with registry.cursor() as cr:
|
||||||
|
if copy:
|
||||||
|
# if it's a copy of a database, force generation of a new dbuuid
|
||||||
|
registry['ir.config_parameter'].init(cr, force=True)
|
||||||
|
if filestore_path:
|
||||||
|
filestore_dest = registry['ir.attachment']._filestore(cr, SUPERUSER_ID)
|
||||||
|
shutil.move(filestore_path, filestore_dest)
|
||||||
|
|
||||||
|
if openerp.tools.config['unaccent']:
|
||||||
|
try:
|
||||||
|
with cr.savepoint():
|
||||||
|
cr.execute("CREATE EXTENSION unaccent")
|
||||||
|
except psycopg2.Error:
|
||||||
|
pass
|
||||||
|
|
||||||
|
_logger.info('RESTORE DB: %s', db)
|
||||||
|
|
||||||
def exp_rename(old_name, new_name):
|
def exp_rename(old_name, new_name):
|
||||||
openerp.modules.registry.RegistryManager.delete(old_name)
|
openerp.modules.registry.RegistryManager.delete(old_name)
|
||||||
|
@ -273,7 +321,7 @@ def exp_rename(old_name, new_name):
|
||||||
|
|
||||||
db = openerp.sql_db.db_connect('postgres')
|
db = openerp.sql_db.db_connect('postgres')
|
||||||
with closing(db.cursor()) as cr:
|
with closing(db.cursor()) as cr:
|
||||||
cr.autocommit(True) # avoid transaction block
|
cr.autocommit(True) # avoid transaction block
|
||||||
try:
|
try:
|
||||||
cr.execute('ALTER DATABASE "%s" RENAME TO "%s"' % (old_name, new_name))
|
cr.execute('ALTER DATABASE "%s" RENAME TO "%s"' % (old_name, new_name))
|
||||||
_logger.info('RENAME DB: %s -> %s', old_name, new_name)
|
_logger.info('RENAME DB: %s -> %s', old_name, new_name)
|
||||||
|
@ -282,6 +330,7 @@ def exp_rename(old_name, new_name):
|
||||||
raise Exception("Couldn't rename database %s to %s: %s" % (old_name, new_name, e))
|
raise Exception("Couldn't rename database %s to %s: %s" % (old_name, new_name, e))
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@openerp.tools.mute_logger('openerp.sql_db')
|
||||||
def exp_db_exist(db_name):
|
def exp_db_exist(db_name):
|
||||||
## Not True: in fact, check if connection to database is possible. The database may exists
|
## Not True: in fact, check if connection to database is possible. The database may exists
|
||||||
return bool(openerp.sql_db.db_connect(db_name))
|
return bool(openerp.sql_db.db_connect(db_name))
|
||||||
|
|
|
@ -212,7 +212,8 @@ class HttpCase(TransactionCase):
|
||||||
# OSError, and no errno/strerror/filename, only a pair of
|
# OSError, and no errno/strerror/filename, only a pair of
|
||||||
# unnamed arguments (matching errno and strerror)
|
# unnamed arguments (matching errno and strerror)
|
||||||
err, _ = e.args
|
err, _ = e.args
|
||||||
if err == errno.EINTR: continue
|
if err == errno.EINTR:
|
||||||
|
continue
|
||||||
raise
|
raise
|
||||||
|
|
||||||
if ready:
|
if ready:
|
||||||
|
@ -224,24 +225,24 @@ class HttpCase(TransactionCase):
|
||||||
# process lines
|
# process lines
|
||||||
if '\n' in buf:
|
if '\n' in buf:
|
||||||
line, buf = buf.split('\n', 1)
|
line, buf = buf.split('\n', 1)
|
||||||
|
|
||||||
line = str(line)
|
line = str(line)
|
||||||
if 'CoreText' in line:
|
|
||||||
continue
|
# relay everything from console.log, even 'ok' or 'error...' lines
|
||||||
|
_logger.debug("phantomjs: %s", line)
|
||||||
|
|
||||||
if line == "ok":
|
if line == "ok":
|
||||||
break
|
break
|
||||||
if line.startswith("error"):
|
if line.startswith("error"):
|
||||||
line_ = line[6:]
|
line_ = self.line[6:]
|
||||||
try: line_ = json.loads(line_)
|
# when error occurs the execution stack may be sent as as JSON
|
||||||
except ValueError: pass
|
try:
|
||||||
|
line_ = json.loads(line_)
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
self.fail(line_ or "phantomjs test failed")
|
self.fail(line_ or "phantomjs test failed")
|
||||||
|
|
||||||
try: line = json.loads(line)
|
|
||||||
except ValueError: pass
|
|
||||||
_logger.info("phantomjs: %s", line)
|
|
||||||
|
|
||||||
def phantom_run(self, cmd, timeout):
|
def phantom_run(self, cmd, timeout):
|
||||||
_logger.debug('executing `%s`', ' '.join(cmd))
|
_logger.debug('phantom_run executing %s', ' '.join(cmd))
|
||||||
try:
|
try:
|
||||||
phantom = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
phantom = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||||
except OSError:
|
except OSError:
|
||||||
|
@ -252,6 +253,7 @@ class HttpCase(TransactionCase):
|
||||||
# kill phantomjs if phantom.exit() wasn't called in the test
|
# kill phantomjs if phantom.exit() wasn't called in the test
|
||||||
if phantom.poll() is None:
|
if phantom.poll() is None:
|
||||||
phantom.terminate()
|
phantom.terminate()
|
||||||
|
_logger.debug("phantom_run execution finished")
|
||||||
|
|
||||||
def phantom_jsfile(self, jsfile, timeout=30, **kw):
|
def phantom_jsfile(self, jsfile, timeout=30, **kw):
|
||||||
options = {
|
options = {
|
||||||
|
|
|
@ -113,20 +113,22 @@ function PhantomTest() {
|
||||||
console.log('loaded', url, status);
|
console.log('loaded', url, status);
|
||||||
// process ready
|
// process ready
|
||||||
waitFor(function() {
|
waitFor(function() {
|
||||||
console.log("waiting for: calling page evaluate");
|
console.log("PhantomTest.run: wait for condition: " + ready);
|
||||||
return self.page.evaluate(function (ready) {
|
return self.page.evaluate(function (ready) {
|
||||||
console.log("waiting for", ready);
|
|
||||||
var r = false;
|
var r = false;
|
||||||
try {
|
try {
|
||||||
console.log("waiting for: page evaluating ", ready);
|
console.log("page.evaluate eval expr:", ready);
|
||||||
r = !!eval(ready);
|
r = !!eval(ready);
|
||||||
} catch(ex) { }
|
} catch(ex) {
|
||||||
console.log("waiting for: returning from page evaluate");
|
}
|
||||||
|
console.log("page.evaluate eval result:", r);
|
||||||
return r;
|
return r;
|
||||||
}, ready);
|
}, ready);
|
||||||
// run test
|
// run test
|
||||||
}, function() {
|
}, function() {
|
||||||
|
console.log("PhantomTest.run: condition statified, executing: " + code);
|
||||||
self.page.evaluate(function (code) { return eval(code); }, code);
|
self.page.evaluate(function (code) { return eval(code); }, code);
|
||||||
|
console.log("PhantomTest.run: execution launched, waiting for console.log('ok')...");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -23,8 +23,12 @@
|
||||||
Some functions related to the os and os.path module
|
Some functions related to the os and os.path module
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
from contextlib import contextmanager
|
||||||
import os
|
import os
|
||||||
from os.path import join as opj
|
from os.path import join as opj
|
||||||
|
import shutil
|
||||||
|
import tempfile
|
||||||
|
import zipfile
|
||||||
|
|
||||||
if os.name == 'nt':
|
if os.name == 'nt':
|
||||||
import ctypes
|
import ctypes
|
||||||
|
@ -61,6 +65,30 @@ def walksymlinks(top, topdown=True, onerror=None):
|
||||||
if not topdown:
|
if not topdown:
|
||||||
yield dirpath, dirnames, filenames
|
yield dirpath, dirnames, filenames
|
||||||
|
|
||||||
|
@contextmanager
|
||||||
|
def tempdir():
|
||||||
|
tmpdir = tempfile.mkdtemp()
|
||||||
|
try:
|
||||||
|
yield tmpdir
|
||||||
|
finally:
|
||||||
|
shutil.rmtree(tmpdir)
|
||||||
|
|
||||||
|
def zip_dir(path, stream, include_dir=True): # TODO add ignore list
|
||||||
|
path = os.path.normpath(path)
|
||||||
|
len_prefix = len(os.path.dirname(path)) if include_dir else len(path)
|
||||||
|
if len_prefix:
|
||||||
|
len_prefix += 1
|
||||||
|
|
||||||
|
with zipfile.ZipFile(stream, 'w', compression=zipfile.ZIP_DEFLATED, allowZip64=True) as zipf:
|
||||||
|
for dirpath, dirnames, filenames in os.walk(path):
|
||||||
|
for fname in filenames:
|
||||||
|
bname, ext = os.path.splitext(fname)
|
||||||
|
ext = ext or bname
|
||||||
|
if ext not in ['.pyc', '.pyo', '.swp', '.DS_Store']:
|
||||||
|
path = os.path.normpath(os.path.join(dirpath, fname))
|
||||||
|
if os.path.isfile(path):
|
||||||
|
zipf.write(path, path[len_prefix:])
|
||||||
|
|
||||||
|
|
||||||
if os.name != 'nt':
|
if os.name != 'nt':
|
||||||
getppid = os.getppid
|
getppid = os.getppid
|
||||||
|
|
Loading…
Reference in New Issue