From: Alessio Bogon Date: Sun, 1 Sep 2019 12:43:37 +0000 (+0200) Subject: Improve warning message X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=63e81ee12aa18ff01ce8ccde8eea0f258c2d95d7;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git Improve warning message --- diff --git a/lib/sqlalchemy/ext/linter.py b/lib/sqlalchemy/ext/linter.py index 160731745d..6a96a62f03 100644 --- a/lib/sqlalchemy/ext/linter.py +++ b/lib/sqlalchemy/ext/linter.py @@ -7,6 +7,10 @@ from sqlalchemy.sql import visitors from sqlalchemy.sql.expression import Select +def _indent(text, indent): + return "\n".join(indent + line for line in text.split("\n")) + + def before_execute_hook(conn, clauseelement, multiparams, params): if isinstance(clauseelement, Select): lint(clauseelement) @@ -93,14 +97,14 @@ def warn_for_unmatching_froms(query): # type: (Select) -> None froms, start_with = find_unmatching_froms(query) if froms: - util.warn( - 'for stmt %s FROM elements %s are not joined up to FROM element "%r"' - % ( - id(query), # defeat the warnings filter - ", ".join('"%r"' % f for f in froms), - start_with, - ) + template = '''Query\n{query}\nhas FROM elements:\n{froms}\nthat are not joined up to FROM element\n{start}''' + indent = ' ' + message = template.format( + query=_indent(str(query), indent), + froms=_indent('\n'.join(str(from_) for from_ in froms), indent + '* '), + start=_indent(str(start_with), indent + '* '), ) + util.warn(message) def lint(query): diff --git a/test/ext/test_linter.py b/test/ext/test_linter.py index 763090b091..b8bc76f892 100644 --- a/test/ext/test_linter.py +++ b/test/ext/test_linter.py @@ -3,9 +3,10 @@ from sqlalchemy.ext import linter from sqlalchemy.ext.linter import find_unmatching_froms from sqlalchemy.testing import fixtures, expect_warnings from sqlalchemy.testing.schema import Table, Column +from sqlalchemy.testing.mock import patch -class TestFinder(fixtures.TablesTest): +class TestFindUnmatchingFroms(fixtures.TablesTest): @classmethod def define_tables(cls, metadata): Table("table_a", metadata, Column("col_a", Integer, primary_key=True)) @@ -194,18 +195,25 @@ class TestLinter(fixtures.TablesTest): def test_integration(self): query = ( - select([self.a]) + select([self.a.c.col_a]) .where(self.b.c.col_b == 5) ) - # TODO: - # - make it a unit by mocking or spying "find_unmatching_froms" - # - Make error string proper - with expect_warnings( - r"for stmt .* FROM elements .*table_.*col_.* " - r"are not joined up to FROM element .*table_.*col_.*" - ): - with testing.db.connect() as conn: - conn.execute(query) + + def deterministic_find_unmatching_froms(query): + return find_unmatching_froms(query, start_with=self.a) + + with patch( + 'sqlalchemy.ext.linter.find_unmatching_froms', + autospec=True, + side_effect=deterministic_find_unmatching_froms, + ) as m: + with expect_warnings( + r"Query.*Select table_a\.col_a.*has FROM elements.*table_b.*" + r"that are not joined up to FROM element.*table_a.*" + ): + with testing.db.connect() as conn: + conn.execute(query) + m.assert_called_once_with(query) def teardown(self): event.remove(testing.db, 'before_execute', linter.before_execute_hook)