File: plugin.py

package info (click to toggle)
python-lsp-isort 0.2.2%2Breally%2B0.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 84 kB
  • sloc: python: 289; makefile: 5
file content (124 lines) | stat: -rw-r--r-- 3,683 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
import logging
import os
from pathlib import Path
from typing import Any, Dict, Generator, Optional, TypedDict, Union

import isort
from pylsp import hookimpl
from pylsp.config.config import Config
from pylsp.workspace import Document

logger = logging.getLogger(__name__)


class Position(TypedDict):
    line: int
    character: int


class Range(TypedDict):
    start: Position
    end: Position


@hookimpl
def pylsp_settings() -> Dict[str, Any]:
    return {
        "plugins": {
            "isort": {
                "enabled": True,
            },
        },
    }


@hookimpl(hookwrapper=True)
def pylsp_format_document(config: Config, document: Document) -> Generator:
    outcome = yield
    _format(outcome, config, document)


@hookimpl(hookwrapper=True)
def pylsp_format_range(config: Config, document: Document, range: Range) -> Generator:
    outcome = yield
    _format(outcome, config, document, range)


def _format(
    outcome, config: Config, document: Document, range: Optional[Range] = None
) -> None:
    result = outcome.get_result()
    if result:
        text = result[0]["newText"]
        range = result[0]["range"]
    elif range:
        text = "".join(document.lines[range["start"]["line"] : range["end"]["line"]])
    else:
        text = document.source
        range = Range(
            start={"line": 0, "character": 0},
            end={"line": len(document.lines), "character": 0},
        )

    IGNORE_KEYS = {"enabled"}
    settings = config.plugin_settings("isort", document_path=document.path)
    settings = {k: v for k, v in settings.items() if k not in IGNORE_KEYS}
    new_text = run_isort(text, settings, file_path=document.path)

    if new_text != text:
        result = [{"range": range, "newText": new_text}]
        outcome.force_result(result)


def run_isort(
    text: str,
    settings: Optional[Dict[str, Any]] = None,
    file_path: Optional[Union[str, bytes, os.PathLike]] = None,
) -> str:
    config = isort_config(settings or {}, file_path)
    file_path = Path(os.fsdecode(file_path)) if file_path else None
    return isort.code(text, config=config, file_path=file_path)


def isort_config(
    settings: Dict[str, Any],
    target_path: Optional[Union[str, bytes, os.PathLike]] = None,
) -> isort.Config:
    config_kwargs = {}
    unsupported_kwargs = {}

    defined_args = set(getattr(isort.Config, "__dataclass_fields__", {}).keys())
    for key, value in settings.items():
        if key in defined_args:
            config_kwargs[key] = value
        else:
            unsupported_kwargs[key] = value

    if "settings_path" in settings:
        if os.path.isfile(settings["settings_path"]):
            config_kwargs["settings_file"] = os.path.abspath(settings["settings_path"])
            config_kwargs["settings_path"] = os.path.dirname(
                config_kwargs["settings_file"]
            )
        else:
            config_kwargs["settings_path"] = os.path.abspath(settings["settings_path"])
    elif target_path:
        settings_path = os.path.abspath(target_path)
        if not os.path.isdir(settings_path):
            settings_path = os.path.dirname(settings_path)

        _, found_settings = isort.settings._find_config(settings_path)
        if found_settings:
            logger.info(
                "Found a config file: `%s`, skipping given settings.",
                found_settings["source"],
            )
            config_kwargs = {}

        config_kwargs["settings_path"] = settings_path

    logger.debug("config_kwargs=%r", config_kwargs)
    if unsupported_kwargs:
        logger.info("unsupported_kwargs=%r", unsupported_kwargs)

    return isort.Config(**config_kwargs)