Repository: tefra/xsdata
Pull request #841 (2023-07-25 17:28:49)

Fix imports ordering
## 📒 Description

> Write a brief description of your PR.


Resolves #xxxx

## 🔗 What I've Done

> Write a description of the steps taken to resolve the issue


## 💬 Comments

> A place to write any comments to the reviewer.
>

## 🛫 Checklist

- [ ] Updated docs
- [ ] Added unit-tests
- [ ] [Sample tests](https://github.com/tefra/xsdata-samples) pass
- [ ] [W3C tests](https://github.com/tefra/xsdata-w3c-tests) pass



Patch:
diff --git a/xsdata/formats/dataclass/filters.py b/xsdata/formats/dataclass/filters.py
index 56e6e19b..57c318cd 100644
--- a/xsdata/formats/dataclass/filters.py
+++ b/xsdata/formats/dataclass/filters.py
@@ -764,11 +764,8 @@ class Filters:
 
     def default_imports(self, output: str) -> str:
         """Generate the default imports for the given package output."""
-        result = []
-
-        if self.postponed_annotations:
-            result.append("from __future__ import annotations")
-
+        module_imports = set()
+        func_imports = set()
         for library, types in self.import_patterns.items():
             names = [
                 name
@@ -777,11 +774,15 @@ class Filters:
             ]
 
             if len(names) == 1 and names[0] == "__module__":
-                result.append(f"import {library}")
+                module_imports.add(f"import {library}")
             elif names:
-                result.append(f"from {library} import {', '.join(names)}")
+                func_imports.add(f"from {library} import {', '.join(names)}")
+
+        imports = sorted(module_imports) + sorted(func_imports)
+        if self.postponed_annotations:
+            imports.insert(0, "from __future__ import annotations")
 
-        return "\n".join(sorted(result))
+        return "\n".join(imports)
 
     @classmethod
     def build_import_patterns(cls) -> Dict[str, Dict]:


Test patch:
diff --git a/tests/formats/dataclass/test_filters.py b/tests/formats/dataclass/test_filters.py
index 32112d60..7c26011f 100644
--- a/tests/formats/dataclass/test_filters.py
+++ b/tests/formats/dataclass/test_filters.py
@@ -877,12 +877,21 @@ class FiltersTests(FactoryTestCase):
         self.assertEqual(expected, self.filters.default_imports(output))
 
     def test_default_imports_with_annotations(self):
-        config = GeneratorConfig()
-        config.output.postponed_annotations = True
-        filters = Filters(config)
+        self.filters.postponed_annotations = True
 
         expected = "from __future__ import annotations"
-        self.assertEqual(expected, filters.default_imports(""))
+        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 = dict(