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/12/02 21:50:56 UTC

[incubator-superset] branch master updated: Use py3's f-strings instead of s.format(**locals()) (#6448)

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 cc3a625  Use py3's f-strings instead of s.format(**locals()) (#6448)
cc3a625 is described below

commit cc3a625a4bb6b0e581b30f3112315ff5a8ab6807
Author: Maxime Beauchemin <ma...@gmail.com>
AuthorDate: Sun Dec 2 13:50:49 2018 -0800

    Use py3's f-strings instead of s.format(**locals()) (#6448)
    
    * Use py3's f-strings instead of s.format(**locals())
    
    In light of the bug reported here
    https://github.com/apache/incubator-superset/issues/6347, which seems
    like an odd `.format()` issue in py3, I greped and replaced all
    instances of `.format(**locals())` using py3's f-strings
    
    * lint
    
    * fix tests
---
 superset/cli.py                     | 17 +++++++++--------
 superset/config.py                  |  2 +-
 superset/connectors/base/models.py  |  2 +-
 superset/connectors/druid/models.py |  8 ++++----
 superset/connectors/sqla/models.py  |  4 ++--
 superset/db_engine_specs.py         | 12 ++++++------
 superset/models/core.py             | 35 ++++++++++++++++++++++-------------
 superset/models/helpers.py          | 11 -----------
 superset/models/sql_lab.py          |  6 +++---
 superset/sql_parse.py               |  6 +++---
 superset/stats_logger.py            | 12 +++++++-----
 superset/views/core.py              | 15 ++++++---------
 tests/core_tests.py                 | 10 +++++-----
 tests/model_tests.py                |  8 ++++----
 14 files changed, 73 insertions(+), 75 deletions(-)

diff --git a/superset/cli.py b/superset/cli.py
index 1f36037..c6444b1 100755
--- a/superset/cli.py
+++ b/superset/cli.py
@@ -115,12 +115,13 @@ def runserver(debug, console_log, use_reloader, address, port, timeout, workers,
         addr_str = ' unix:{socket} ' if socket else' {address}:{port} '
         cmd = (
             'gunicorn '
-            '-w {workers} '
-            '--timeout {timeout} '
-            '-b ' + addr_str +
+            f'-w {workers} '
+            f'--timeout {timeout} '
+            f'-b {addr_str} '
             '--limit-request-line 0 '
             '--limit-request-field_size 0 '
-            'superset:app').format(**locals())
+            'superset:app'
+        )
         print(Fore.GREEN + 'Starting server with command: ')
         print(Fore.YELLOW + cmd)
         print(Style.RESET_ALL)
@@ -404,10 +405,10 @@ def flower(port, address):
     BROKER_URL = celery_app.conf.BROKER_URL
     cmd = (
         'celery flower '
-        '--broker={BROKER_URL} '
-        '--port={port} '
-        '--address={address} '
-    ).format(**locals())
+        f'--broker={BROKER_URL} '
+        f'--port={port} '
+        f'--address={address} '
+    )
     logging.info(
         "The 'superset flower' command is deprecated. Please use the 'celery "
         "flower' command instead.")
diff --git a/superset/config.py b/superset/config.py
index a9622db..73e5a2c 100644
--- a/superset/config.py
+++ b/superset/config.py
@@ -450,7 +450,7 @@ DB_CONNECTION_MUTATOR = None
 #
 #    def SQL_QUERY_MUTATOR(sql, username, security_manager):
 #        dttm = datetime.now().isoformat()
-#        return "-- [SQL LAB] {username} {dttm}\n sql"(**locals())
+#        return f"-- [SQL LAB] {username} {dttm}\n{sql}"
 SQL_QUERY_MUTATOR = None
 
 # When not using gunicorn, (nginx for instance), you may want to disable
diff --git a/superset/connectors/base/models.py b/superset/connectors/base/models.py
index 7f159a6..216ed9e 100644
--- a/superset/connectors/base/models.py
+++ b/superset/connectors/base/models.py
@@ -66,7 +66,7 @@ class BaseDatasource(AuditMixinNullable, ImportMixin):
     @property
     def uid(self):
         """Unique id across datasource types"""
-        return '{self.id}__{self.type}'.format(**locals())
+        return f'{self.id}__{self.type}'
 
     @property
     def column_names(self):
diff --git a/superset/connectors/druid/models.py b/superset/connectors/druid/models.py
index 40a4287..0972f78 100644
--- a/superset/connectors/druid/models.py
+++ b/superset/connectors/druid/models.py
@@ -116,7 +116,7 @@ class DruidCluster(Model, AuditMixinNullable, ImportMixin):
     def get_base_broker_url(self):
         base_url = self.get_base_url(
             self.broker_host, self.broker_port)
-        return '{base_url}/{self.broker_endpoint}'.format(**locals())
+        return f'{base_url}/{self.broker_endpoint}'
 
     def get_pydruid_client(self):
         cli = PyDruid(
@@ -525,7 +525,7 @@ class DruidDatasource(Model, BaseDatasource):
     @property
     def link(self):
         name = escape(self.datasource_name)
-        return Markup('<a href="{self.url}">{name}</a>').format(**locals())
+        return Markup(f'<a href="{self.url}">{name}</a>')
 
     @property
     def full_name(self):
@@ -549,9 +549,9 @@ class DruidDatasource(Model, BaseDatasource):
 
     @renders('datasource_name')
     def datasource_link(self):
-        url = '/superset/explore/{obj.type}/{obj.id}/'.format(obj=self)
+        url = f'/superset/explore/{self.type}/{self.id}/'
         name = escape(self.datasource_name)
-        return Markup('<a href="{url}">{name}</a>'.format(**locals()))
+        return Markup(f'<a href="{url}">{name}</a>')
 
     def get_metric_obj(self, metric_name):
         return [
diff --git a/superset/connectors/sqla/models.py b/superset/connectors/sqla/models.py
index 2ed2afd..cf22add 100644
--- a/superset/connectors/sqla/models.py
+++ b/superset/connectors/sqla/models.py
@@ -324,8 +324,8 @@ class SqlaTable(Model, BaseDatasource):
     @property
     def link(self):
         name = escape(self.name)
-        anchor = '<a target="_blank" href="{self.explore_url}">{name}</a>'
-        return Markup(anchor.format(**locals()))
+        anchor = f'<a target="_blank" href="{self.explore_url}">{name}</a>'
+        return Markup(anchor)
 
     @property
     def schema_perm(self):
diff --git a/superset/db_engine_specs.py b/superset/db_engine_specs.py
index 5722507..d409c87 100644
--- a/superset/db_engine_specs.py
+++ b/superset/db_engine_specs.py
@@ -848,15 +848,15 @@ class PrestoEngineSpec(BaseEngineSpec):
         if filters:
             l = []  # noqa: E741
             for field, value in filters.items():
-                l.append("{field} = '{value}'".format(**locals()))
+                l.append(f"{field} = '{value}'")
             where_clause = 'WHERE ' + ' AND '.join(l)
 
-        sql = textwrap.dedent("""\
+        sql = textwrap.dedent(f"""\
             SHOW PARTITIONS FROM {table_name}
             {where_clause}
             {order_by_clause}
             {limit_clause}
-        """).format(**locals())
+        """)
         return sql
 
     @classmethod
@@ -1070,10 +1070,10 @@ class HiveEngineSpec(PrestoEngineSpec):
         s3.upload_file(
             upload_path, bucket_path,
             os.path.join(upload_prefix, table_name, filename))
-        sql = """CREATE TABLE {full_table_name} ( {schema_definition} )
+        sql = f"""CREATE TABLE {full_table_name} ( {schema_definition} )
             ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' STORED AS
             TEXTFILE LOCATION '{location}'
-            tblproperties ('skip.header.line.count'='1')""".format(**locals())
+            tblproperties ('skip.header.line.count'='1')"""
         logging.info(form.con.data)
         engine = create_engine(form.con.data.sqlalchemy_uri_decrypted)
         engine.execute(sql)
@@ -1220,7 +1220,7 @@ class HiveEngineSpec(PrestoEngineSpec):
     @classmethod
     def _partition_query(
             cls, table_name, limit=0, order_by=None, filters=None):
-        return 'SHOW PARTITIONS {table_name}'.format(**locals())
+        return f'SHOW PARTITIONS {table_name}'
 
     @classmethod
     def modify_url_for_impersonation(cls, url, impersonate_user, username):
diff --git a/superset/models/core.py b/superset/models/core.py
index 712de78..1323eed 100644
--- a/superset/models/core.py
+++ b/superset/models/core.py
@@ -257,8 +257,7 @@ class Slice(Model, AuditMixinNullable, ImportMixin):
         form_data = {'slice_id': self.id}
         form_data.update(overrides)
         params = parse.quote(json.dumps(form_data))
-        return (
-            '{base_url}/?form_data={params}'.format(**locals()))
+        return f'{base_url}/?form_data={params}'
 
     @property
     def slice_url(self):
@@ -278,7 +277,7 @@ class Slice(Model, AuditMixinNullable, ImportMixin):
     def slice_link(self):
         url = self.slice_url
         name = escape(self.slice_name)
-        return Markup('<a href="{url}">{name}</a>'.format(**locals()))
+        return Markup(f'<a href="{url}">{name}</a>')
 
     def get_viz(self, force=False):
         """Creates :py:class:viz.BaseViz object from the url_params_multidict.
@@ -299,6 +298,17 @@ class Slice(Model, AuditMixinNullable, ImportMixin):
             force=force,
         )
 
+    @property
+    def icons(self):
+        return f"""
+        <a
+                href="{self.datasource_edit_url}"
+                data-toggle="tooltip"
+                title="{self.datasource}">
+            <i class="fa fa-database"></i>
+        </a>
+        """
+
     @classmethod
     def import_obj(cls, slc_to_import, slc_to_override, import_time=None):
         """Inserts or overrides slc in the database.
@@ -409,8 +419,7 @@ class Dashboard(Model, AuditMixinNullable, ImportMixin):
 
     def dashboard_link(self):
         title = escape(self.dashboard_title)
-        return Markup(
-            '<a href="{self.url}">{title}</a>'.format(**locals()))
+        return Markup(f'<a href="{self.url}">{title}</a>')
 
     @property
     def data(self):
@@ -1185,11 +1194,11 @@ class DatasourceAccessRequest(Model, AuditMixinNullable):
         for r in pv.role:
             if r.name in self.ROLES_BLACKLIST:
                 continue
+            # pylint: disable=no-member
             url = (
-                '/superset/approve?datasource_type={self.datasource_type}&'
-                'datasource_id={self.datasource_id}&'
-                'created_by={self.created_by.username}&role_to_grant={r.name}'
-                .format(**locals())
+                f'/superset/approve?datasource_type={self.datasource_type}&'
+                f'datasource_id={self.datasource_id}&'
+                f'created_by={self.created_by.username}&role_to_grant={r.name}'
             )
             href = '<a href="{}">Grant {} Role</a>'.format(url, r.name)
             action_list = action_list + '<li>' + href + '</li>'
@@ -1199,11 +1208,11 @@ class DatasourceAccessRequest(Model, AuditMixinNullable):
     def user_roles(self):
         action_list = ''
         for r in self.created_by.roles:  # pylint: disable=no-member
+            # pylint: disable=no-member
             url = (
-                '/superset/approve?datasource_type={self.datasource_type}&'
-                'datasource_id={self.datasource_id}&'
-                'created_by={self.created_by.username}&role_to_extend={r.name}'
-                .format(**locals())
+                f'/superset/approve?datasource_type={self.datasource_type}&'
+                f'datasource_id={self.datasource_id}&'
+                f'created_by={self.created_by.username}&role_to_extend={r.name}'
             )
             href = '<a href="{}">Extend {} Role</a>'.format(url, r.name)
             if r.name in self.ROLES_BLACKLIST:
diff --git a/superset/models/helpers.py b/superset/models/helpers.py
index d45ff83..f1cb1cd 100644
--- a/superset/models/helpers.py
+++ b/superset/models/helpers.py
@@ -277,17 +277,6 @@ class AuditMixinNullable(AuditMixin):
     def modified(self):
         return humanize.naturaltime(datetime.now() - self.changed_on)
 
-    @property
-    def icons(self):
-        return """
-        <a
-                href="{self.datasource_edit_url}"
-                data-toggle="tooltip"
-                title="{self.datasource}">
-            <i class="fa fa-database"></i>
-        </a>
-        """.format(**locals())
-
 
 class QueryResult(object):
 
diff --git a/superset/models/sql_lab.py b/superset/models/sql_lab.py
index 9d0c331..117f874 100644
--- a/superset/models/sql_lab.py
+++ b/superset/models/sql_lab.py
@@ -115,7 +115,7 @@ class Query(Model):
         tab = (self.tab_name.replace(' ', '_').lower()
                if self.tab_name else 'notab')
         tab = re.sub(r'\W+', '', tab)
-        return 'sqllab_{tab}_{ts}'.format(**locals())
+        return f'sqllab_{tab}_{ts}'
 
 
 class SavedQuery(Model, AuditMixinNullable):
@@ -140,8 +140,8 @@ class SavedQuery(Model, AuditMixinNullable):
 
     @property
     def pop_tab_link(self):
-        return Markup("""
+        return Markup(f"""
             <a href="/superset/sqllab?savedQueryId={self.id}">
                 <i class="fa fa-link"></i>
             </a>
-        """.format(**locals()))
+        """)
diff --git a/superset/sql_parse.py b/superset/sql_parse.py
index 2f54f77..80dba4c 100644
--- a/superset/sql_parse.py
+++ b/superset/sql_parse.py
@@ -100,9 +100,9 @@ class SupersetQuery(object):
         exec_sql = ''
         sql = self.stripped()
         if overwrite:
-            exec_sql = 'DROP TABLE IF EXISTS {table_name};\n'
-        exec_sql += 'CREATE TABLE {table_name} AS \n{sql}'
-        return exec_sql.format(**locals())
+            exec_sql = f'DROP TABLE IF EXISTS {table_name};\n'
+        exec_sql += f'CREATE TABLE {table_name} AS \n{sql}'
+        return exec_sql
 
     def __extract_from_token(self, token):
         if not hasattr(token, 'tokens'):
diff --git a/superset/stats_logger.py b/superset/stats_logger.py
index 098f53f..20f6c1f 100644
--- a/superset/stats_logger.py
+++ b/superset/stats_logger.py
@@ -43,13 +43,15 @@ class DummyStatsLogger(BaseStatsLogger):
 
     def timing(self, key, value):
         logging.debug((
-            Fore.CYAN + '[stats_logger] (timing) {key} | {value} ' +
-            Style.RESET_ALL).format(**locals()))
+            Fore.CYAN +
+            f'[stats_logger] (timing) {key} | {value} ' +
+            Style.RESET_ALL))
 
     def gauge(self, key, value):
         logging.debug((
-            Fore.CYAN + '[stats_logger] (gauge) '
-            '{key} | {value}' + Style.RESET_ALL).format(**locals()))
+            Fore.CYAN + '[stats_logger] (gauge) ' +
+            f'{key} | {value}' +
+            Style.RESET_ALL))
 
 
 try:
@@ -72,5 +74,5 @@ try:
             # pylint: disable=no-value-for-parameter
             self.client.gauge(key)
 
-except Exception as e:
+except Exception:
     pass
diff --git a/superset/views/core.py b/superset/views/core.py
index 33d31c1..7faa1e2 100755
--- a/superset/views/core.py
+++ b/superset/views/core.py
@@ -1275,9 +1275,8 @@ class Superset(BaseSupersetView):
                 'danger')
             return redirect(
                 'superset/request_access/?'
-                'datasource_type={datasource_type}&'
-                'datasource_id={datasource_id}&'
-                ''.format(**locals()))
+                f'datasource_type={datasource_type}&'
+                f'datasource_id={datasource_id}&')
 
         viz_type = form_data.get('viz_type')
         if not viz_type and datasource.default_endpoint:
@@ -2115,7 +2114,7 @@ class Superset(BaseSupersetView):
                         'danger')
                     return redirect(
                         'superset/request_access/?'
-                        'dashboard_id={dash.id}&'.format(**locals()))
+                        f'dashboard_id={dash.id}&')
 
         dash_edit_perm = check_ownership(dash, raise_if_false=False) and \
             security_manager.can_access('can_save_dash', 'Superset')
@@ -2522,11 +2521,10 @@ class Superset(BaseSupersetView):
                     start_time=utils.now_as_float())
             except Exception as e:
                 logging.exception(e)
-                msg = (
+                msg = _(
                     'Failed to start remote query on a worker. '
                     'Tell your administrator to verify the availability of '
-                    'the message queue.'
-                )
+                    'the message queue.')
                 query.status = QueryStatus.FAILED
                 query.error_message = msg
                 session.commit()
@@ -2542,8 +2540,7 @@ class Superset(BaseSupersetView):
         try:
             timeout = config.get('SQLLAB_TIMEOUT')
             timeout_msg = (
-                'The query exceeded the {timeout} seconds '
-                'timeout.').format(**locals())
+                f'The query exceeded the {timeout} seconds timeout.')
             with utils.timeout(seconds=timeout,
                                error_message=timeout_msg):
                 # pylint: disable=no-value-for-parameter
diff --git a/tests/core_tests.py b/tests/core_tests.py
index 2acd842..5b45cb8 100644
--- a/tests/core_tests.py
+++ b/tests/core_tests.py
@@ -273,7 +273,7 @@ class CoreTests(SupersetTestCase):
                 (slc.slice_name, 'explore_json', slc.explore_json_url),
             ]
         for name, method, url in urls:
-            logging.info('[{name}]/[{method}]: {url}'.format(**locals()))
+            logging.info(f'[{name}]/[{method}]: {url}')
             self.client.get(url)
 
     def test_tablemodelview_list(self):
@@ -319,8 +319,8 @@ class CoreTests(SupersetTestCase):
                 (slc.slice_name, 'slice_url', slc.slice_url),
             ]
         for name, method, url in urls:
-            print('[{name}]/[{method}]: {url}'.format(**locals()))
-            response = self.client.get(url)
+            print(f'[{name}]/[{method}]: {url}')
+            self.client.get(url)
 
     def test_doctests(self):
         modules = [utils, models, sql_lab]
@@ -478,8 +478,8 @@ class CoreTests(SupersetTestCase):
         self.login('admin')
         dbid = get_main_database(db.session).id
         self.get_json_resp(
-            '/superset/extra_table_metadata/{dbid}/'
-            'ab_permission_view/panoramix/'.format(**locals()))
+            f'/superset/extra_table_metadata/{dbid}/'
+            'ab_permission_view/panoramix/')
 
     def test_process_template(self):
         maindb = get_main_database(db.session)
diff --git a/tests/model_tests.py b/tests/model_tests.py
index 8d3c17c..0885f31 100644
--- a/tests/model_tests.py
+++ b/tests/model_tests.py
@@ -76,20 +76,20 @@ class DatabaseModelTestCase(SupersetTestCase):
         table_name = 'energy_usage'
         sql = main_db.select_star(
             table_name, show_cols=False, latest_partition=False)
-        expected = textwrap.dedent("""\
+        expected = textwrap.dedent(f"""\
         SELECT *
         FROM {table_name}
-        LIMIT 100""".format(**locals()))
+        LIMIT 100""")
         assert sql.startswith(expected)
 
         sql = main_db.select_star(
             table_name, show_cols=True, latest_partition=False)
-        expected = textwrap.dedent("""\
+        expected = textwrap.dedent(f"""\
         SELECT source,
                target,
                value
         FROM energy_usage
-        LIMIT 100""".format(**locals()))
+        LIMIT 100""")
         assert sql.startswith(expected)
 
     def test_grains_dict(self):