Make render_expression use the stack like mock_engine.

This commit is contained in:
Ryan Leckey
2013-10-23 00:25:40 -07:00
parent 3bba347237
commit 1a76f9868d
2 changed files with 30 additions and 8 deletions

View File

@@ -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):

View File

@@ -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