You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@superset.apache.org by ma...@apache.org on 2018/05/10 17:32:34 UTC

[incubator-superset] branch master updated: [sql lab] Use context manager for sqllab sessions (#4927)

This is an automated email from the ASF dual-hosted git repository.

maximebeauchemin pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-superset.git


The following commit(s) were added to refs/heads/master by this push:
     new 8591319  [sql lab] Use context manager for sqllab sessions (#4927)
8591319 is described below

commit 8591319bde7db14ac358eae979dfefcbf450db91
Author: grafke <gr...@users.noreply.github.com>
AuthorDate: Thu May 10 19:32:31 2018 +0200

    [sql lab] Use context manager for sqllab sessions (#4927)
    
    * use session context manager
    
    * contextlib2 added to requirements.txt
    
    * Fixing error: Import statements are in the wrong order. from contextlib2 import contextmanager should be before import sqlalchemy
    
    * Fixing return inside generator
    
    * fixed C812 missing trailing comma
    
    * E501 line too long
    
    * fixed E127 continuation line over-indented for visual indent
    
    * E722 do not use bare except
    
    * reorganized imports
    
    * added context manager contextlib2.contextmanager
    
    * fixed import ordering
---
 .pylintrc           |  2 +-
 requirements.txt    |  1 +
 superset/sql_lab.py | 61 +++++++++++++++++++++++++++++++----------------------
 3 files changed, 38 insertions(+), 26 deletions(-)

diff --git a/.pylintrc b/.pylintrc
index 6e213c4..0f97106 100644
--- a/.pylintrc
+++ b/.pylintrc
@@ -292,7 +292,7 @@ generated-members=
 # List of decorators that produce context managers, such as
 # contextlib.contextmanager. Add to this list to register other decorators that
 # produce valid context managers.
-contextmanager-decorators=contextlib.contextmanager
+contextmanager-decorators=contextlib.contextmanager,contextlib2.contextmanager
 
 
 [VARIABLES]
diff --git a/requirements.txt b/requirements.txt
index e3bceee..05dca9d 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -37,3 +37,4 @@ thrift==0.11.0
 thrift-sasl==0.3.0
 unicodecsv==0.14.1
 unidecode==1.0.22
+contextlib2==0.5.5
\ No newline at end of file
diff --git a/superset/sql_lab.py b/superset/sql_lab.py
index 750da1f..856ea48 100644
--- a/superset/sql_lab.py
+++ b/superset/sql_lab.py
@@ -1,9 +1,6 @@
 # -*- coding: utf-8 -*-
 # pylint: disable=C,R,W
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-from __future__ import unicode_literals
+from __future__ import absolute_import, division, print_function, unicode_literals
 
 from datetime import datetime
 import json
@@ -12,6 +9,7 @@ from time import sleep
 import uuid
 
 from celery.exceptions import SoftTimeLimitExceeded
+from contextlib2 import contextmanager
 import numpy as np
 import pandas as pd
 import sqlalchemy
@@ -75,16 +73,28 @@ def get_query(query_id, session, retry_count=5):
     return query
 
 
-def get_session(nullpool):
+@contextmanager
+def session_scope(nullpool):
+    """Provide a transactional scope around a series of operations."""
     if nullpool:
         engine = sqlalchemy.create_engine(
             app.config.get('SQLALCHEMY_DATABASE_URI'), poolclass=NullPool)
         session_class = sessionmaker()
         session_class.configure(bind=engine)
-        return session_class()
-    session = db.session()
-    session.commit()  # HACK
-    return session
+        session = session_class()
+    else:
+        session = db.session()
+        session.commit()  # HACK
+
+    try:
+        yield session
+        session.commit()
+    except Exception as e:
+        session.rollback()
+        logging.exception(e)
+        raise
+    finally:
+        session.close()
 
 
 def convert_results_to_df(cursor_description, data):
@@ -109,30 +119,31 @@ def convert_results_to_df(cursor_description, data):
 
 @celery_app.task(bind=True, soft_time_limit=SQLLAB_TIMEOUT)
 def get_sql_results(
-        ctask, query_id, rendered_query, return_results=True, store_results=False,
+    ctask, query_id, rendered_query, return_results=True, store_results=False,
         user_name=None):
     """Executes the sql query returns the results."""
-    try:
-        return execute_sql(
-            ctask, query_id, rendered_query, return_results, store_results, user_name)
-    except Exception as e:
-        logging.exception(e)
-        stats_logger.incr('error_sqllab_unhandled')
-        sesh = get_session(not ctask.request.called_directly)
-        query = get_query(query_id, sesh)
-        query.error_message = str(e)
-        query.status = QueryStatus.FAILED
-        query.tmp_table_name = None
-        sesh.commit()
-        raise
+    with session_scope(not ctask.request.called_directly) as session:
+
+        try:
+            return execute_sql(
+                ctask, query_id, rendered_query, return_results, store_results, user_name,
+                session=session)
+        except Exception as e:
+            logging.exception(e)
+            stats_logger.incr('error_sqllab_unhandled')
+            query = get_query(query_id, session)
+            query.error_message = str(e)
+            query.status = QueryStatus.FAILED
+            query.tmp_table_name = None
+            session.commit()
+            raise
 
 
 def execute_sql(
     ctask, query_id, rendered_query, return_results=True, store_results=False,
-    user_name=None,
+    user_name=None, session=None,
 ):
     """Executes the sql query returns the results."""
-    session = get_session(not ctask.request.called_directly)
 
     query = get_query(query_id, session)
     payload = dict(query_id=query_id)

-- 
To stop receiving notification emails like this one, please contact
maximebeauchemin@apache.org.