From 2431ad3a962e33c840e11b54963e46d73bc51730 Mon Sep 17 00:00:00 2001 From: Becky Smith Date: Mon, 13 Jan 2025 12:17:10 +0000 Subject: [PATCH] Reformat after ruff update to 2025 style guide ruff 0.9.0 shipped a new style guide that introduces some formatting changes https://astral.sh/blog/ruff-v0.9.0 Rule A005 (stdlib-module-shadowing) is no longer in preview as of v0.9.0, and now complains about our file_formats/csv.py now, so the csv module is now ignored in pyproject.toml https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md#090 --- ehrql/__main__.py | 2 +- ehrql/backends/tpp.py | 6 ++++-- ehrql/docs/__main__.py | 6 +++--- ehrql/docs/cli.py | 6 +++--- ehrql/renderers.py | 2 +- hooks/parent_snippets.py | 2 +- pyproject.toml | 2 ++ tests/conftest.py | 6 +++--- tests/generative/test_query_model.py | 6 +++--- tests/integration/file_formats/test_main.py | 10 ++-------- tests/integration/utils/test_mssql_log_utils.py | 2 +- tests/spec/test_specs.py | 12 ++++++------ tests/unit/test_renderers.py | 2 +- tests/unit/utils/test_sqlalchemy_query_utils.py | 5 +---- 14 files changed, 32 insertions(+), 37 deletions(-) diff --git a/ehrql/__main__.py b/ehrql/__main__.py index 51b1dbe52..b55701469 100644 --- a/ehrql/__main__.py +++ b/ehrql/__main__.py @@ -299,7 +299,7 @@ def add_create_dummy_tables(subparsers, environ, user_args): By default these will be CSV files. To generate files in other formats add `:` to the directory name e.g. - {backtick_join('my_outputs' + format_directory_extension(e) for e in FILE_FORMATS)} + {backtick_join("my_outputs" + format_directory_extension(e) for e in FILE_FORMATS)} """ ), type=valid_output_directory_with_csv_default, diff --git a/ehrql/backends/tpp.py b/ehrql/backends/tpp.py index 1e0770537..f77cfe3d4 100644 --- a/ehrql/backends/tpp.py +++ b/ehrql/backends/tpp.py @@ -513,10 +513,12 @@ def emergency_care_attendances(self): ec.EC_Ident AS id, ec.Arrival_Date AS arrival_date, ec.Discharge_Destination_SNOMED_CT COLLATE Latin1_General_BIN AS discharge_destination, - {", ".join( + { + ", ".join( f"diag.EC_Diagnosis_{i:02d} COLLATE Latin1_General_BIN AS diagnosis_{i:02d}" for i in range(1, 25) - )} + ) + } FROM EC{{table_suffix}} AS ec LEFT JOIN EC_Diagnosis{{table_suffix}} AS diag ON ec.EC_Ident = diag.EC_Ident diff --git a/ehrql/docs/__main__.py b/ehrql/docs/__main__.py index 5b84551f6..70b06bdd3 100644 --- a/ehrql/docs/__main__.py +++ b/ehrql/docs/__main__.py @@ -60,9 +60,9 @@ def render(docs_data, output_dir): reference_index = Path(__file__).parents[2] / "docs/reference/language.md" reference_index_text = reference_index.read_text() for filename in section_filenames: - assert ( - filename in reference_index_text - ), f"{filename} not included by {reference_index}" + assert filename in reference_index_text, ( + f"{filename} not included by {reference_index}" + ) def fix_whitespace(s): diff --git a/ehrql/docs/cli.py b/ehrql/docs/cli.py index b3d98b842..52e4e8bdd 100644 --- a/ehrql/docs/cli.py +++ b/ehrql/docs/cli.py @@ -91,9 +91,9 @@ def get_subcommands(parser): for action in parser._actions if isinstance(action, argparse._SubParsersAction) ] - assert ( - len(subparsers) == 1 - ), f"Expected exactly one subcommand parser, got: {subparsers}" + assert len(subparsers) == 1, ( + f"Expected exactly one subcommand parser, got: {subparsers}" + ) subparser = subparsers[0] return [ get_subcommand(action, subparser.choices[action.metavar]) diff --git a/ehrql/renderers.py b/ehrql/renderers.py index b5f5ebed7..cd5a206b6 100644 --- a/ehrql/renderers.py +++ b/ehrql/renderers.py @@ -55,7 +55,7 @@ def _truncate_html_table(table_repr: str, head: int | None, tail: int | None): rows = [row for row in rows.split("") if row] # compose an "ellipsis row" to mark the place of truncated rows td_count = rows[0].count("") - ellipsis_row = f"{'...'*td_count}" + ellipsis_row = f"{'...' * td_count}" # Build the list of rows we need to include, with ellipsis rows where necessary truncated_rows = [] diff --git a/hooks/parent_snippets.py b/hooks/parent_snippets.py index f174a68a8..961ba835a 100644 --- a/hooks/parent_snippets.py +++ b/hooks/parent_snippets.py @@ -27,6 +27,6 @@ def on_page_markdown(markdown, page, **kwargs): markdown = markdown.replace( parent_snippet, '\n\n!!! note "TO BE REPLACED IN FULL DOCS BUILD"\n\n\tThis snippet will be replaced in the main docs ' - f'with the parent file {parent_snippet.lstrip("!!! parent_snippet:")}', + f"with the parent file {parent_snippet.lstrip('!!! parent_snippet:')}", ) return markdown diff --git a/pyproject.toml b/pyproject.toml index e4bb4cfc0..50cca9150 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -104,4 +104,6 @@ extend-ignore = [ "E501", # line-too-long "UP032", # replace `.format` with f-string ] +flake8-builtins.builtins-allowed-modules = ["csv"] + isort.lines-after-imports = 2 diff --git a/tests/conftest.py b/tests/conftest.py index 3954162da..5a23b6f8c 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -299,9 +299,9 @@ def random_should_not_be_used(): """ prev_state = random.getstate() yield - assert ( - random.getstate() == prev_state - ), "Global random number generator was used in test." + assert random.getstate() == prev_state, ( + "Global random number generator was used in test." + ) @pytest.fixture diff --git a/tests/generative/test_query_model.py b/tests/generative/test_query_model.py index 05ddf0285..36a5b98de 100644 --- a/tests/generative/test_query_model.py +++ b/tests/generative/test_query_model.py @@ -217,9 +217,9 @@ def run_test(query_engines, data, population, variable, recorder): first_results = [pytest.approx(row, rel=1e-5) for row in first_results] for other_name, other_results in results.items(): - assert ( - first_results == other_results - ), f"Mismatch between {first_name} and {other_name}" + assert first_results == other_results, ( + f"Mismatch between {first_name} and {other_name}" + ) def setup_test(data, population, variable): diff --git a/tests/integration/file_formats/test_main.py b/tests/integration/file_formats/test_main.py index 48c5035da..d04c89ad1 100644 --- a/tests/integration/file_formats/test_main.py +++ b/tests/integration/file_formats/test_main.py @@ -132,9 +132,7 @@ def test_read_rows_validates_categories(test_file): # the schema but with CSV we can only validate individual values errors = { "dataset.arrow": ( - "Unexpected categories in column 'c'\n" - " Categories: A, B\n" - " Expected: X, Y" + "Unexpected categories in column 'c'\n Categories: A, B\n Expected: X, Y" ), "dataset.csv": "'A' not in valid categories: 'X', 'Y'", "dataset.csv.gz": "'A' not in valid categories: 'X', 'Y'", @@ -156,11 +154,7 @@ def test_read_rows_validates_categories_on_non_categorical_column(test_file): column_specs = TEST_FILE_SPECS.copy() column_specs["s"] = ColumnSpec(str, categories=("X", "Y")) - error = ( - "Unexpected categories in column 's'\n" - " Categories: a, b\n" - " Expected: X, Y" - ) + error = "Unexpected categories in column 's'\n Categories: a, b\n Expected: X, Y" with pytest.raises(FileValidationError, match=error): read_rows(test_file, column_specs) diff --git a/tests/integration/utils/test_mssql_log_utils.py b/tests/integration/utils/test_mssql_log_utils.py index 099e53eb3..5ef9d27d9 100644 --- a/tests/integration/utils/test_mssql_log_utils.py +++ b/tests/integration/utils/test_mssql_log_utils.py @@ -58,7 +58,7 @@ def log(event, **kwargs): assert results == [(1,), (3,)] - assert log_lines[0] == ("[info ] SQL:\n" " SELECT 1") + assert log_lines[0] == ("[info ] SQL:\n SELECT 1") assert log_lines[1] == ( "[info ] 0 seconds: exec_cpu_ms=0 exec_elapsed_ms=0 exec_cpu_ratio=0.0 parse_cpu_ms=0 parse_elapsed_ms=0\n" diff --git a/tests/spec/test_specs.py b/tests/spec/test_specs.py index ead4cb289..81e0d83b0 100644 --- a/tests/spec/test_specs.py +++ b/tests/spec/test_specs.py @@ -40,14 +40,14 @@ def test_build_section(): assert len(paragraphs) == 2 for paragraph in paragraphs: if paragraph["id"] == "1.1": - assert ( - paragraph["text"] == "this docstring should appear in the spec" - ), "paragraph text not found when docstring present" + assert paragraph["text"] == "this docstring should appear in the spec", ( + "paragraph text not found when docstring present" + ) continue if paragraph["id"] == "1.2": - assert ( - "text" not in paragraph - ), "paragraph text found when no docstring present" + assert "text" not in paragraph, ( + "paragraph text found when no docstring present" + ) continue assert False, "expected paragraph ids not found" diff --git a/tests/unit/test_renderers.py b/tests/unit/test_renderers.py index 1cdf06ff9..9d227d06f 100644 --- a/tests/unit/test_renderers.py +++ b/tests/unit/test_renderers.py @@ -256,7 +256,7 @@ def test_truncate_table_bad_html(): "" ) - expected = "\n" "\n" "..." + expected = "
\n\n..." truncated = truncate_table(bad_html, head=2, tail=None) assert truncated == expected, truncated diff --git a/tests/unit/utils/test_sqlalchemy_query_utils.py b/tests/unit/utils/test_sqlalchemy_query_utils.py index d35c43e6e..5b25a7de7 100644 --- a/tests/unit/utils/test_sqlalchemy_query_utils.py +++ b/tests/unit/utils/test_sqlalchemy_query_utils.py @@ -201,10 +201,7 @@ def test_generated_table_from_query(): ) table = GeneratedTable.from_query("some_table", query, schema="some_schema") assert str(sqlalchemy.schema.CreateTable(table)).strip() == ( - "CREATE TABLE some_schema.some_table (\n" - "\tnumber INTEGER, \n" - "\tstring VARCHAR\n" - ")" + "CREATE TABLE some_schema.some_table (\n\tnumber INTEGER, \n\tstring VARCHAR\n)" )