File: _imports.py

package info (click to toggle)
python-libcst 1.4.0-1.2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 5,928 kB
  • sloc: python: 76,235; makefile: 10; sh: 2
file content (45 lines) | stat: -rw-r--r-- 1,630 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
# Copyright (c) Meta Platforms, Inc. and affiliates.
#
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.

from dataclasses import dataclass, replace
from typing import Optional

from libcst.helpers import get_absolute_module_from_package


@dataclass(frozen=True)
class ImportItem:
    """Representation of individual import items for codemods."""

    module_name: str
    obj_name: Optional[str] = None
    alias: Optional[str] = None
    relative: int = 0

    def __post_init__(self) -> None:
        if self.module_name is None:
            object.__setattr__(self, "module_name", "")
        elif self.module_name.startswith("."):
            mod = self.module_name.lstrip(".")
            rel = self.relative + len(self.module_name) - len(mod)
            object.__setattr__(self, "module_name", mod)
            object.__setattr__(self, "relative", rel)

    @property
    def module(self) -> str:
        return "." * self.relative + self.module_name

    def resolve_relative(self, package_name: Optional[str]) -> "ImportItem":
        """Return an ImportItem with an absolute module name if possible."""
        mod = self
        # `import ..a` -> `from .. import a`
        if mod.relative and mod.obj_name is None:
            mod = replace(mod, module_name="", obj_name=mod.module_name)
        if package_name is None:
            return mod
        m = get_absolute_module_from_package(
            package_name, mod.module_name or None, self.relative
        )
        return mod if m is None else replace(mod, module_name=m, relative=0)