]> git.ipfire.org Git - thirdparty/psycopg.git/commitdiff
style: add isort plugin to sort imports with the desired style
authorDaniele Varrazzo <daniele.varrazzo@gmail.com>
Wed, 12 Feb 2025 12:26:40 +0000 (13:26 +0100)
committerDaniele Varrazzo <daniele.varrazzo@gmail.com>
Thu, 13 Feb 2025 10:26:15 +0000 (11:26 +0100)
Sort imports by length, imported objects naturally.

.gitignore
tools/isort-psycopg/README.rst [new file with mode: 0644]
tools/isort-psycopg/isort_psycopg.py [new file with mode: 0644]
tools/isort-psycopg/pyproject.toml [new file with mode: 0644]

index f7ba03c710c0a483b46353ba317bc5a21fa9bd3a..7040b97519147909a4b24a34c0732b8590550b79 100644 (file)
@@ -23,3 +23,4 @@ wheelhouse/
 /psycopg_c/build/
 /psycopg_pool/build/
 /tools/build/pg_config_vcpkg_stub/build/
+/tools/isort-psycopg/build/
diff --git a/tools/isort-psycopg/README.rst b/tools/isort-psycopg/README.rst
new file mode 100644 (file)
index 0000000..fe85fc5
--- /dev/null
@@ -0,0 +1,27 @@
+Psycopg style isort
+===================
+
+This is an isort_ plugin to sort:
+
+- import in length order
+- import lists in natural order
+
+The effect is the same of specifying ``--length-sort`` but only for the module
+names. For example::
+
+    from ccc import aaaa, bbb, cc
+    from bbbb import ddd, ee
+    from aaaaa import fff, gg
+
+Example configuration::
+
+    [tool.isort]
+    profile = "black"
+    length_sort = true
+    multi_line_output = 9
+    sort_order = "psycopg"
+
+Note: because this is the first day I use isort at all, there is a chance that
+this plug-in is totally useless and the same can be done using isort features.
+
+.. _isort: https://pycqa.github.io/isort/
diff --git a/tools/isort-psycopg/isort_psycopg.py b/tools/isort-psycopg/isort_psycopg.py
new file mode 100644 (file)
index 0000000..ff54716
--- /dev/null
@@ -0,0 +1,42 @@
+"""isort function to sort module names by length, objects naturally."""
+
+from __future__ import annotations
+
+import re
+import inspect
+from typing import Any, Callable, Iterable
+
+from isort.sorting import naturally
+
+
+def psycosort(
+    to_sort: Iterable[str],
+    key: Callable[[str], Any] | None = None,
+    reverse: bool = False,
+) -> list[str]:
+    # Sniff whether we are sorting an import list (from module import a, b, c)
+    # or a list of modules.
+    # Tested with isort 6.0. It might break in the future!
+    is_from_import = any(
+        f for f in inspect.stack() if f.function == "_with_from_imports"
+    )
+
+    new_key: Callable[[str], Any] | None
+    if is_from_import:
+        if key:
+            old_key = key
+
+            def new_key(s: str) -> Any:
+                return drop_length(old_key(s))
+
+        else:
+            new_key = drop_length
+    else:
+        new_key = key
+
+    return naturally(to_sort, key=new_key, reverse=reverse)
+
+
+def drop_length(s: str) -> Any:
+    """Drop the length prefix from the objects sorted."""
+    return re.sub(r"\d+:", "", s) if s else s
diff --git a/tools/isort-psycopg/pyproject.toml b/tools/isort-psycopg/pyproject.toml
new file mode 100644 (file)
index 0000000..c024139
--- /dev/null
@@ -0,0 +1,22 @@
+[build-system]
+requires = ["setuptools", "wheel"]
+build-backend = "setuptools.build_meta"
+
+[project]
+name = "isort-psycopg"
+description = "isort plug-in to sort imports by module length first"
+# Note: to release a new version:
+# python -m build -o dist --wheel .
+# twine upload dist/isort_psycopg-*-py3-none-any.whl
+version = "0.0.1"
+
+[project.readme]
+file = "README.rst"
+content-type = "text/x-rst"
+
+[[project.authors]]
+name = "Daniele Varrazzo"
+email = "daniele.varrazzo@gmail.com"
+
+[project.entry-points."isort.sort_function"]
+psycopg = "isort_psycopg:psycosort"