From ca4b3cf2a699e8e86324932a4491bce54c3b93bf Mon Sep 17 00:00:00 2001 From: Christodoulos Tsoulloftas Date: Sat, 9 Mar 2024 21:11:14 +0200 Subject: [PATCH] feat: Use ruff isort during codegen --- .pre-commit-config.yaml | 4 +-- tests/fixtures/annotations/model.py | 2 ++ tests/fixtures/annotations/units.py | 1 + tests/fixtures/artists/metadata.py | 1 + tests/fixtures/books/__init__.py | 2 +- tests/fixtures/books/books.py | 1 + .../docstrings/accessible/__init__.py | 2 +- tests/fixtures/docstrings/blank/__init__.py | 2 +- tests/fixtures/docstrings/google/__init__.py | 2 +- tests/fixtures/docstrings/numpy/__init__.py | 2 +- tests/fixtures/docstrings/rst/__init__.py | 2 +- tests/fixtures/hello/__init__.py | 4 +-- tests/fixtures/primer/__init__.py | 4 +-- tests/fixtures/primer/order.py | 1 + tests/fixtures/series/__init__.py | 2 +- tests/fixtures/series/series.py | 1 + tests/formats/dataclass/test_filters.py | 11 ------- tests/formats/dataclass/test_generator.py | 33 +++++++++---------- xsdata/formats/dataclass/filters.py | 12 +++---- xsdata/formats/dataclass/generator.py | 16 ++++++++- xsdata/formats/dataclass/ruff.toml | 8 +++++ xsdata/models/datatype.py | 14 +++----- 22 files changed, 69 insertions(+), 58 deletions(-) create mode 100644 xsdata/formats/dataclass/ruff.toml diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 5dfd4af19..440420793 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -8,13 +8,13 @@ repos: - id: end-of-file-fixer - id: debug-statements - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.3.0 + rev: v0.3.2 hooks: - id: ruff args: [ --fix, --show-fixes ] - id: ruff-format - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.8.0 + rev: v1.9.0 hooks: - id: mypy files: ^(xsdata/) diff --git a/tests/fixtures/annotations/model.py b/tests/fixtures/annotations/model.py index b0f602b99..31f2d8fe2 100644 --- a/tests/fixtures/annotations/model.py +++ b/tests/fixtures/annotations/model.py @@ -1,6 +1,8 @@ from __future__ import annotations + from dataclasses import dataclass, field from typing import Optional + from tests.fixtures.annotations.units import unit __NAMESPACE__ = "http://domain.org/schema/model" diff --git a/tests/fixtures/annotations/units.py b/tests/fixtures/annotations/units.py index 587edcb73..bd3878da4 100644 --- a/tests/fixtures/annotations/units.py +++ b/tests/fixtures/annotations/units.py @@ -1,4 +1,5 @@ from __future__ import annotations + from enum import Enum __NAMESPACE__ = "http://domain.org/schema/model/units" diff --git a/tests/fixtures/artists/metadata.py b/tests/fixtures/artists/metadata.py index b2e4eecd2..87d01e423 100644 --- a/tests/fixtures/artists/metadata.py +++ b/tests/fixtures/artists/metadata.py @@ -1,5 +1,6 @@ from dataclasses import dataclass, field from typing import List, Optional, Union + from xsdata.models.datatype import XmlDate, XmlPeriod __NAMESPACE__ = "http://musicbrainz.org/ns/mmd-2.0#" diff --git a/tests/fixtures/books/__init__.py b/tests/fixtures/books/__init__.py index eee06db4e..4105a7ee2 100644 --- a/tests/fixtures/books/__init__.py +++ b/tests/fixtures/books/__init__.py @@ -1,7 +1,7 @@ from tests.fixtures.books.books import ( BookForm, - BooksForm, Books, + BooksForm, ) __all__ = [ diff --git a/tests/fixtures/books/books.py b/tests/fixtures/books/books.py index ffdbc4d7e..e4d55ac4c 100644 --- a/tests/fixtures/books/books.py +++ b/tests/fixtures/books/books.py @@ -1,5 +1,6 @@ from dataclasses import dataclass, field from typing import List, Optional + from xsdata.models.datatype import XmlDate __NAMESPACE__ = "urn:books" diff --git a/tests/fixtures/docstrings/accessible/__init__.py b/tests/fixtures/docstrings/accessible/__init__.py index be8130bea..fbfc13f13 100644 --- a/tests/fixtures/docstrings/accessible/__init__.py +++ b/tests/fixtures/docstrings/accessible/__init__.py @@ -2,9 +2,9 @@ DoubleQuotesDescription, DoubleQuotesSummary, Root, - RootEnum, RootB, RootD, + RootEnum, ) __all__ = [ diff --git a/tests/fixtures/docstrings/blank/__init__.py b/tests/fixtures/docstrings/blank/__init__.py index e03953a24..3e461f44a 100644 --- a/tests/fixtures/docstrings/blank/__init__.py +++ b/tests/fixtures/docstrings/blank/__init__.py @@ -2,9 +2,9 @@ DoubleQuotesDescription, DoubleQuotesSummary, Root, - RootEnum, RootB, RootD, + RootEnum, ) __all__ = [ diff --git a/tests/fixtures/docstrings/google/__init__.py b/tests/fixtures/docstrings/google/__init__.py index 1e38b8ac3..251c983ef 100644 --- a/tests/fixtures/docstrings/google/__init__.py +++ b/tests/fixtures/docstrings/google/__init__.py @@ -2,9 +2,9 @@ DoubleQuotesDescription, DoubleQuotesSummary, Root, - RootEnum, RootB, RootD, + RootEnum, ) __all__ = [ diff --git a/tests/fixtures/docstrings/numpy/__init__.py b/tests/fixtures/docstrings/numpy/__init__.py index 0341b60a7..68253f90c 100644 --- a/tests/fixtures/docstrings/numpy/__init__.py +++ b/tests/fixtures/docstrings/numpy/__init__.py @@ -2,9 +2,9 @@ DoubleQuotesDescription, DoubleQuotesSummary, Root, - RootEnum, RootB, RootD, + RootEnum, ) __all__ = [ diff --git a/tests/fixtures/docstrings/rst/__init__.py b/tests/fixtures/docstrings/rst/__init__.py index c3e80341c..8656be37b 100644 --- a/tests/fixtures/docstrings/rst/__init__.py +++ b/tests/fixtures/docstrings/rst/__init__.py @@ -2,9 +2,9 @@ DoubleQuotesDescription, DoubleQuotesSummary, Root, - RootEnum, RootB, RootD, + RootEnum, ) __all__ = [ diff --git a/tests/fixtures/hello/__init__.py b/tests/fixtures/hello/__init__.py index b28d62d27..ed238d198 100644 --- a/tests/fixtures/hello/__init__.py +++ b/tests/fixtures/hello/__init__.py @@ -1,11 +1,11 @@ from tests.fixtures.hello.hello import ( + GetHelloAsString, + GetHelloAsStringResponse, HelloByeError, HelloError, HelloGetHelloAsString, HelloGetHelloAsStringInput, HelloGetHelloAsStringOutput, - GetHelloAsString, - GetHelloAsStringResponse, ) __all__ = [ diff --git a/tests/fixtures/primer/__init__.py b/tests/fixtures/primer/__init__.py index bfc280297..b03d8ce56 100644 --- a/tests/fixtures/primer/__init__.py +++ b/tests/fixtures/primer/__init__.py @@ -1,9 +1,9 @@ from tests.fixtures.primer.order import ( + Comment, Items, + PurchaseOrder, PurchaseOrderType, Usaddress, - Comment, - PurchaseOrder, ) __all__ = [ diff --git a/tests/fixtures/primer/order.py b/tests/fixtures/primer/order.py index c200987ce..1495572ac 100644 --- a/tests/fixtures/primer/order.py +++ b/tests/fixtures/primer/order.py @@ -1,6 +1,7 @@ from dataclasses import dataclass, field from decimal import Decimal from typing import List, Optional + from xsdata.models.datatype import XmlDate diff --git a/tests/fixtures/series/__init__.py b/tests/fixtures/series/__init__.py index 378fc158a..1d5a7207a 100644 --- a/tests/fixtures/series/__init__.py +++ b/tests/fixtures/series/__init__.py @@ -1,8 +1,8 @@ from tests.fixtures.series.series import ( - Links, Country, Externals, Image, + Links, Network, Previousepisode, Rating, diff --git a/tests/fixtures/series/series.py b/tests/fixtures/series/series.py index 53d876e57..cff7c716a 100644 --- a/tests/fixtures/series/series.py +++ b/tests/fixtures/series/series.py @@ -1,5 +1,6 @@ from dataclasses import dataclass, field from typing import List, Optional + from xsdata.models.datatype import XmlDate diff --git a/tests/formats/dataclass/test_filters.py b/tests/formats/dataclass/test_filters.py index 293fd6996..4b54920ac 100644 --- a/tests/formats/dataclass/test_filters.py +++ b/tests/formats/dataclass/test_filters.py @@ -899,17 +899,6 @@ def test_default_imports_with_annotations(self): expected = "from __future__ import annotations" self.assertEqual(expected, self.filters.default_imports("")) - def test_default_imports_ordering(self): - self.filters.postponed_annotations = True - self.filters.import_patterns["attrs"] = {"__module__": ["@attrs.s"]} - - expected = ( - "from __future__ import annotations\n" - "import attrs\n" - "from dataclasses import dataclass" - ) - self.assertEqual(expected, self.filters.default_imports("@dataclass @attrs.s")) - def test_format_metadata(self): data = { "num": 1, diff --git a/tests/formats/dataclass/test_generator.py b/tests/formats/dataclass/test_generator.py index 187894f41..bceabdfd7 100644 --- a/tests/formats/dataclass/test_generator.py +++ b/tests/formats/dataclass/test_generator.py @@ -68,23 +68,22 @@ def test_render_package(self): random.shuffle(classes) actual = self.generator.render_package(classes, "foo.tests", Path.cwd()) - expected = "\n".join( - [ - "from foo.bar import A as BarA", - "from foo.tests import (", - " A as TestsA,", - " B,", - " C,", - ")", - "", - "__all__ = [", - ' "BarA",', - ' "TestsA",', - ' "B",', - ' "C",', - "]", - "", - ] + expected = ( + "from foo.bar import A as BarA\n" + "from foo.tests import (\n" + " A as TestsA,\n" + ")\n" + "from foo.tests import (\n" + " B,\n" + " C,\n" + ")\n" + "\n" + "__all__ = [\n" + ' "BarA",\n' + ' "TestsA",\n' + ' "B",\n' + ' "C",\n' + "]\n" ) self.assertEqual(expected, actual) diff --git a/xsdata/formats/dataclass/filters.py b/xsdata/formats/dataclass/filters.py index b5e1de7ac..f51110c20 100644 --- a/xsdata/formats/dataclass/filters.py +++ b/xsdata/formats/dataclass/filters.py @@ -843,8 +843,7 @@ def constant_value(self, attr: Attr) -> str: def default_imports(self, output: str) -> str: """Generate the default imports for the given package output.""" - module_imports = set() - func_imports = set() + imports = [] for library, types in self.import_patterns.items(): names = [ name @@ -853,15 +852,14 @@ def default_imports(self, output: str) -> str: ] if len(names) == 1 and names[0] == "__module__": - module_imports.add(f"import {library}") + imports.append(f"import {library}") elif names: - func_imports.add(f"from {library} import {', '.join(names)}") + imports.append(f"from {library} import {', '.join(names)}") - imports = sorted(module_imports) + sorted(func_imports) if self.postponed_annotations: - imports.insert(0, "from __future__ import annotations") + imports.append("from __future__ import annotations") - return "\n".join(imports) + return "\n".join(collections.unique_sequence(imports)) def _get_iterable_format(self): fmt = "Tuple[{}, ...]" if self.format.frozen else "List[{}]" diff --git a/xsdata/formats/dataclass/generator.py b/xsdata/formats/dataclass/generator.py index d5fce1cb6..eaf23f8df 100644 --- a/xsdata/formats/dataclass/generator.py +++ b/xsdata/formats/dataclass/generator.py @@ -24,7 +24,7 @@ class DataclassGenerator(AbstractGenerator): filters: The template filters instance """ - __slots__ = ("env", "filters") + __slots__ = ("env", "filters", "ruff_config") package_template = "package.jinja2" module_template = "module.jinja2" @@ -39,6 +39,7 @@ def __init__(self, config: GeneratorConfig): self.env = Environment(loader=loader, autoescape=False) self.filters = self.init_filters(config) self.filters.register(self.env) + self.ruff_config = Path(__file__).parent / "ruff.toml" @classmethod def get_template_paths(cls) -> List[str]: @@ -227,6 +228,19 @@ def ruff_code(self, src_code: str, file_path: Path) -> str: "--line-length", str(self.config.output.max_line_length), ], + [ + "ruff", + "checks", + "--stdin-filename", + str(file_path), + "--line-length", + str(self.config.output.max_line_length), + "--config", + str(self.ruff_config), + "--fix", + "--unsafe-fixes", + "--exit-zero", + ], ] try: src_code_encoded = src_code.encode() diff --git a/xsdata/formats/dataclass/ruff.toml b/xsdata/formats/dataclass/ruff.toml new file mode 100644 index 000000000..edbced33c --- /dev/null +++ b/xsdata/formats/dataclass/ruff.toml @@ -0,0 +1,8 @@ +exclude = [ +] + +[lint] +select = ["I"] + +# Allow fix for all enabled rules (when `--fix`) is provided. +fixable = ["ALL"] diff --git a/xsdata/models/datatype.py b/xsdata/models/datatype.py index 36688c3a1..703b65f5a 100644 --- a/xsdata/models/datatype.py +++ b/xsdata/models/datatype.py @@ -283,11 +283,9 @@ def __str__(self) -> str: - 2001-10-26T21:32:52.126 - -2001-10-26T21:32:52.126Z """ - return "{}T{}{}".format( - format_date(self.year, self.month, self.day), - format_time(self.hour, self.minute, self.second, self.fractional_second), - format_offset(self.offset), - ) + date = format_date(self.year, self.month, self.day) + time = format_time(self.hour, self.minute, self.second, self.fractional_second) + return f"{date}T{time}{format_offset(self.offset)}" def __repr__(self) -> str: """Return the instance string representation.""" @@ -433,10 +431,8 @@ def __str__(self) -> str: - 21:32:52.126789 - 21:32:52.126Z """ - return "{}{}".format( - format_time(self.hour, self.minute, self.second, self.fractional_second), - format_offset(self.offset), - ) + time = format_time(self.hour, self.minute, self.second, self.fractional_second) + return f"{time}{format_offset(self.offset)}" def __repr__(self) -> str: """Return the instance string representation."""