Make render_expression use the stack like mock_engine.
This commit is contained in:
@@ -340,7 +340,7 @@ def mock_engine(engine, stream=None):
|
|||||||
six.exec_('del __mock', frame.f_globals, frame.f_locals)
|
six.exec_('del __mock', frame.f_globals, frame.f_locals)
|
||||||
|
|
||||||
|
|
||||||
def render_expression(expression, bind, context=None):
|
def render_expression(expression, bind, stream=None):
|
||||||
"""Generate a SQL expression from the passed python expression.
|
"""Generate a SQL expression from the passed python expression.
|
||||||
|
|
||||||
Only the global variable, `engine`, is available for use in the
|
Only the global variable, `engine`, is available for use in the
|
||||||
@@ -351,15 +351,36 @@ def render_expression(expression, bind, context=None):
|
|||||||
blindly pass user input to this function as it uses exec.
|
blindly pass user input to this function as it uses exec.
|
||||||
|
|
||||||
:param bind: A SQLAlchemy engine or bind URL.
|
:param bind: A SQLAlchemy engine or bind URL.
|
||||||
:param context: Dictionary of local variables for the expression.
|
:param stream: Render all DDL operations to the stream.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
stream = cStringIO()
|
# Create a stream if not present.
|
||||||
|
|
||||||
|
if stream is None:
|
||||||
|
stream = cStringIO()
|
||||||
|
|
||||||
engine = create_mock_engine(bind, stream)
|
engine = create_mock_engine(bind, stream)
|
||||||
|
|
||||||
six.exec_(expression, {'engine': engine}, context)
|
# Navigate the stack and find the calling frame that allows the
|
||||||
|
# expression to execuate.
|
||||||
|
|
||||||
return stream.getvalue()
|
for frame in inspect.stack()[1:]:
|
||||||
|
|
||||||
|
try:
|
||||||
|
frame = frame[0]
|
||||||
|
local = dict(frame.f_locals)
|
||||||
|
local['engine'] = engine
|
||||||
|
six.exec_(expression, frame.f_globals, local)
|
||||||
|
break
|
||||||
|
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
else:
|
||||||
|
|
||||||
|
raise ValueError('Not a valid python expression', engine)
|
||||||
|
|
||||||
|
return stream
|
||||||
|
|
||||||
|
|
||||||
def render_statement(statement, bind=None):
|
def render_statement(statement, bind=None):
|
||||||
|
@@ -102,9 +102,10 @@ class TestRender(TestCase):
|
|||||||
assert 'WHERE user.id = 3' in text
|
assert 'WHERE user.id = 3' in text
|
||||||
|
|
||||||
def test_render_ddl(self):
|
def test_render_ddl(self):
|
||||||
context = {'table': self.User.__table__}
|
expression = 'self.User.__table__.create(engine)'
|
||||||
expression = 'table.create(engine)'
|
stream = render_expression(expression, self.engine)
|
||||||
text = render_expression(expression, self.engine, context)
|
|
||||||
|
text = stream.getvalue()
|
||||||
|
|
||||||
assert 'CREATE TABLE user' in text
|
assert 'CREATE TABLE user' in text
|
||||||
assert 'PRIMARY KEY' in text
|
assert 'PRIMARY KEY' in text
|
||||||
|
Reference in New Issue
Block a user