Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
container.py182 linesDownload Raw Back to widget
1from __future__ import annotations2 3import abc4import enum5import typing6 7from .constants import Sizing, WHSettings8 9if typing.TYPE_CHECKING:10    from collections.abc import Iterable, Iterator11 12    from .widget import Widget13 14 15# Ideally, we would like to use an IntFlag coupled with enum.auto().16# However, doing many bitwise operations (which happens when nesting too many17# widgets ...) on IntFlag is orders of magnitude slower than doing the same18# operations on IntEnum.19class _ContainerElementSizingFlag(enum.IntEnum):20    # fmt: off21    NONE      = 0b00000022    BOX       = 0b00000123    FLOW      = 0b00001024    FIXED     = 0b00010025    WH_WEIGHT = 0b00100026    WH_PACK   = 0b01000027    WH_GIVEN  = 0b10000028    # fmt: on29 30    @staticmethod31    def reverse_flag(bitfield: int) -> tuple[frozenset[Sizing], WHSettings | None]:32        """Get flag in public API format."""33        sizing: set[Sizing] = set()34 35        if bitfield & _ContainerElementSizingFlag.BOX:36            sizing.add(Sizing.BOX)37        if bitfield & _ContainerElementSizingFlag.FLOW:38            sizing.add(Sizing.FLOW)39        if bitfield & _ContainerElementSizingFlag.FIXED:40            sizing.add(Sizing.FIXED)41 42        if bitfield & _ContainerElementSizingFlag.WH_WEIGHT:43            return frozenset(sizing), WHSettings.WEIGHT44        if bitfield & _ContainerElementSizingFlag.WH_PACK:45            return frozenset(sizing), WHSettings.PACK46        if bitfield & _ContainerElementSizingFlag.WH_GIVEN:47            return frozenset(sizing), WHSettings.GIVEN48        return frozenset(sizing), None49 50    @staticmethod51    def log_string(bitfield: int) -> str:52        """Get desctiprion in public API format."""53        sizing, render = _ContainerElementSizingFlag.reverse_flag(bitfield)54        render_string = f" {render.upper()}" if render else ""55        return "|".join(sorted(mode.upper() for mode in sizing)) + render_string56 57 58class WidgetContainerMixin:59    """60    Mixin class for widget containers implementing common container methods61    """62 63    def __getitem__(self, position) -> Widget:64        """65        Container short-cut for self.contents[position][0].base_widget66        which means "give me the child widget at position without any67        widget decorations".68 69        This allows for concise traversal of nested container widgets70        such as:71 72            my_widget[position0][position1][position2] ...73        """74        return self.contents[position][0].base_widget75 76    def get_focus_path(self) -> list[int | str]:77        """78        Return the .focus_position values starting from this container79        and proceeding along each child widget until reaching a leaf80        (non-container) widget.81        """82        out = []83        w = self84        while True:85            try:86                p = w.focus_position87            except IndexError:88                return out89            out.append(p)90            w = w.focus.base_widget91 92    def set_focus_path(self, positions: Iterable[int | str]) -> None:93        """94        Set the .focus_position property starting from this container95        widget and proceeding along newly focused child widgets.  Any96        failed assignment due do incompatible position types or invalid97        positions will raise an IndexError.98 99        This method may be used to restore a particular widget to the100        focus by passing in the value returned from an earlier call to101        get_focus_path().102 103        positions -- sequence of positions104        """105        w: Widget = self106        for p in positions:107            if p != w.focus_position:108                w.focus_position = p  # modifies w.focus109            w = w.focus.base_widget  # type: ignore[assignment]110 111    def get_focus_widgets(self) -> list[Widget]:112        """113        Return the .focus values starting from this container114        and proceeding along each child widget until reaching a leaf115        (non-container) widget.116 117        Note that the list does not contain the topmost container widget118        (i.e., on which this method is called), but does include the119        lowest leaf widget.120        """121        out = []122        w = self123        while (w := w.base_widget.focus) is not None:124            out.append(w)125 126        return out127 128    @property129    @abc.abstractmethod130    def focus(self) -> Widget:131        """132        Read-only property returning the child widget in focus for133        container widgets.  This default implementation134        always returns ``None``, indicating that this widget has no children.135        """136 137 138class WidgetContainerListContentsMixin:139    """140    Mixin class for widget containers whose positions are indexes into141    a list available as self.contents.142    """143 144    def __iter__(self) -> Iterator[int]:145        """146        Return an iterable of positions for this container from first147        to last.148        """149        return iter(range(len(self.contents)))150 151    def __reversed__(self) -> Iterator[int]:152        """153        Return an iterable of positions for this container from last154        to first.155        """156        return iter(range(len(self.contents) - 1, -1, -1))157 158    def __len__(self) -> int:159        return len(self.contents)160 161    @property162    @abc.abstractmethod163    def contents(self) -> list[tuple[Widget, typing.Any]]:164        """The contents of container as a list of (widget, options)"""165 166    @contents.setter167    def contents(self, new_contents: list[tuple[Widget, typing.Any]]) -> None:168        """The contents of container as a list of (widget, options)"""169 170    @property171    @abc.abstractmethod172    def focus_position(self) -> int | None:173        """174        index of child widget in focus.175        """176 177    @focus_position.setter178    def focus_position(self, position: int) -> None:179        """180        index of child widget in focus.181        """182 
codekingpro/portable-devtools · Team Ai