diff options
author | monster <monster@ydb.tech> | 2022-07-07 14:41:37 +0300 |
---|---|---|
committer | monster <monster@ydb.tech> | 2022-07-07 14:41:37 +0300 |
commit | 06e5c21a835c0e923506c4ff27929f34e00761c2 (patch) | |
tree | 75efcbc6854ef9bd476eb8bf00cc5c900da436a2 /contrib/python/prompt-toolkit/py3/prompt_toolkit/styles/style.py | |
parent | 03f024c4412e3aa613bb543cf1660176320ba8f4 (diff) | |
download | ydb-06e5c21a835c0e923506c4ff27929f34e00761c2.tar.gz |
fix ya.make
Diffstat (limited to 'contrib/python/prompt-toolkit/py3/prompt_toolkit/styles/style.py')
-rw-r--r-- | contrib/python/prompt-toolkit/py3/prompt_toolkit/styles/style.py | 399 |
1 files changed, 0 insertions, 399 deletions
diff --git a/contrib/python/prompt-toolkit/py3/prompt_toolkit/styles/style.py b/contrib/python/prompt-toolkit/py3/prompt_toolkit/styles/style.py deleted file mode 100644 index 6e4bd1f43c..0000000000 --- a/contrib/python/prompt-toolkit/py3/prompt_toolkit/styles/style.py +++ /dev/null @@ -1,399 +0,0 @@ -""" -Tool for creating styles from a dictionary. -""" -import itertools -import re -import sys -from enum import Enum -from typing import Dict, Hashable, List, Set, Tuple, TypeVar - -from prompt_toolkit.cache import SimpleCache - -from .base import ( - ANSI_COLOR_NAMES, - ANSI_COLOR_NAMES_ALIASES, - DEFAULT_ATTRS, - Attrs, - BaseStyle, -) -from .named_colors import NAMED_COLORS - -__all__ = [ - "Style", - "parse_color", - "Priority", - "merge_styles", -] - -_named_colors_lowercase = {k.lower(): v.lstrip("#") for k, v in NAMED_COLORS.items()} - - -def parse_color(text: str) -> str: - """ - Parse/validate color format. - - Like in Pygments, but also support the ANSI color names. - (These will map to the colors of the 16 color palette.) - """ - # ANSI color names. - if text in ANSI_COLOR_NAMES: - return text - if text in ANSI_COLOR_NAMES_ALIASES: - return ANSI_COLOR_NAMES_ALIASES[text] - - # 140 named colors. - try: - # Replace by 'hex' value. - return _named_colors_lowercase[text.lower()] - except KeyError: - pass - - # Hex codes. - if text[0:1] == "#": - col = text[1:] - - # Keep this for backwards-compatibility (Pygments does it). - # I don't like the '#' prefix for named colors. - if col in ANSI_COLOR_NAMES: - return col - elif col in ANSI_COLOR_NAMES_ALIASES: - return ANSI_COLOR_NAMES_ALIASES[col] - - # 6 digit hex color. - elif len(col) == 6: - return col - - # 3 digit hex color. - elif len(col) == 3: - return col[0] * 2 + col[1] * 2 + col[2] * 2 - - # Default. - elif text in ("", "default"): - return text - - raise ValueError("Wrong color format %r" % text) - - -# Attributes, when they are not filled in by a style. None means that we take -# the value from the parent. -_EMPTY_ATTRS = Attrs( - color=None, - bgcolor=None, - bold=None, - underline=None, - strike=None, - italic=None, - blink=None, - reverse=None, - hidden=None, -) - - -def _expand_classname(classname: str) -> List[str]: - """ - Split a single class name at the `.` operator, and build a list of classes. - - E.g. 'a.b.c' becomes ['a', 'a.b', 'a.b.c'] - """ - result = [] - parts = classname.split(".") - - for i in range(1, len(parts) + 1): - result.append(".".join(parts[:i]).lower()) - - return result - - -def _parse_style_str(style_str: str) -> Attrs: - """ - Take a style string, e.g. 'bg:red #88ff00 class:title' - and return a `Attrs` instance. - """ - # Start from default Attrs. - if "noinherit" in style_str: - attrs = DEFAULT_ATTRS - else: - attrs = _EMPTY_ATTRS - - # Now update with the given attributes. - for part in style_str.split(): - if part == "noinherit": - pass - elif part == "bold": - attrs = attrs._replace(bold=True) - elif part == "nobold": - attrs = attrs._replace(bold=False) - elif part == "italic": - attrs = attrs._replace(italic=True) - elif part == "noitalic": - attrs = attrs._replace(italic=False) - elif part == "underline": - attrs = attrs._replace(underline=True) - elif part == "nounderline": - attrs = attrs._replace(underline=False) - elif part == "strike": - attrs = attrs._replace(strike=True) - elif part == "nostrike": - attrs = attrs._replace(strike=False) - - # prompt_toolkit extensions. Not in Pygments. - elif part == "blink": - attrs = attrs._replace(blink=True) - elif part == "noblink": - attrs = attrs._replace(blink=False) - elif part == "reverse": - attrs = attrs._replace(reverse=True) - elif part == "noreverse": - attrs = attrs._replace(reverse=False) - elif part == "hidden": - attrs = attrs._replace(hidden=True) - elif part == "nohidden": - attrs = attrs._replace(hidden=False) - - # Pygments properties that we ignore. - elif part in ("roman", "sans", "mono"): - pass - elif part.startswith("border:"): - pass - - # Ignore pieces in between square brackets. This is internal stuff. - # Like '[transparent]' or '[set-cursor-position]'. - elif part.startswith("[") and part.endswith("]"): - pass - - # Colors. - elif part.startswith("bg:"): - attrs = attrs._replace(bgcolor=parse_color(part[3:])) - elif part.startswith("fg:"): # The 'fg:' prefix is optional. - attrs = attrs._replace(color=parse_color(part[3:])) - else: - attrs = attrs._replace(color=parse_color(part)) - - return attrs - - -CLASS_NAMES_RE = re.compile(r"^[a-z0-9.\s_-]*$") # This one can't contain a comma! - - -class Priority(Enum): - """ - The priority of the rules, when a style is created from a dictionary. - - In a `Style`, rules that are defined later will always override previous - defined rules, however in a dictionary, the key order was arbitrary before - Python 3.6. This means that the style could change at random between rules. - - We have two options: - - - `DICT_KEY_ORDER`: This means, iterate through the dictionary, and take - the key/value pairs in order as they come. This is a good option if you - have Python >3.6. Rules at the end will override rules at the beginning. - - `MOST_PRECISE`: keys that are defined with most precision will get higher - priority. (More precise means: more elements.) - """ - - DICT_KEY_ORDER = "KEY_ORDER" - MOST_PRECISE = "MOST_PRECISE" - - -# We don't support Python versions older than 3.6 anymore, so we can always -# depend on dictionary ordering. This is the default. -default_priority = Priority.DICT_KEY_ORDER - - -class Style(BaseStyle): - """ - Create a ``Style`` instance from a list of style rules. - - The `style_rules` is supposed to be a list of ('classnames', 'style') tuples. - The classnames are a whitespace separated string of class names and the - style string is just like a Pygments style definition, but with a few - additions: it supports 'reverse' and 'blink'. - - Later rules always override previous rules. - - Usage:: - - Style([ - ('title', '#ff0000 bold underline'), - ('something-else', 'reverse'), - ('class1 class2', 'reverse'), - ]) - - The ``from_dict`` classmethod is similar, but takes a dictionary as input. - """ - - def __init__(self, style_rules: List[Tuple[str, str]]) -> None: - class_names_and_attrs = [] - - # Loop through the rules in the order they were defined. - # Rules that are defined later get priority. - for class_names, style_str in style_rules: - assert CLASS_NAMES_RE.match(class_names), repr(class_names) - - # The order of the class names doesn't matter. - # (But the order of rules does matter.) - class_names_set = frozenset(class_names.lower().split()) - attrs = _parse_style_str(style_str) - - class_names_and_attrs.append((class_names_set, attrs)) - - self._style_rules = style_rules - self.class_names_and_attrs = class_names_and_attrs - - @property - def style_rules(self) -> List[Tuple[str, str]]: - return self._style_rules - - @classmethod - def from_dict( - cls, style_dict: Dict[str, str], priority: Priority = default_priority - ) -> "Style": - """ - :param style_dict: Style dictionary. - :param priority: `Priority` value. - """ - if priority == Priority.MOST_PRECISE: - - def key(item: Tuple[str, str]) -> int: - # Split on '.' and whitespace. Count elements. - return sum(len(i.split(".")) for i in item[0].split()) - - return cls(sorted(style_dict.items(), key=key)) - else: - return cls(list(style_dict.items())) - - def get_attrs_for_style_str( - self, style_str: str, default: Attrs = DEFAULT_ATTRS - ) -> Attrs: - """ - Get `Attrs` for the given style string. - """ - list_of_attrs = [default] - class_names: Set[str] = set() - - # Apply default styling. - for names, attr in self.class_names_and_attrs: - if not names: - list_of_attrs.append(attr) - - # Go from left to right through the style string. Things on the right - # take precedence. - for part in style_str.split(): - # This part represents a class. - # Do lookup of this class name in the style definition, as well - # as all class combinations that we have so far. - if part.startswith("class:"): - # Expand all class names (comma separated list). - new_class_names = [] - for p in part[6:].lower().split(","): - new_class_names.extend(_expand_classname(p)) - - for new_name in new_class_names: - # Build a set of all possible class combinations to be applied. - combos = set() - combos.add(frozenset([new_name])) - - for count in range(1, len(class_names) + 1): - for c2 in itertools.combinations(class_names, count): - combos.add(frozenset(c2 + (new_name,))) - - # Apply the styles that match these class names. - for names, attr in self.class_names_and_attrs: - if names in combos: - list_of_attrs.append(attr) - - class_names.add(new_name) - - # Process inline style. - else: - inline_attrs = _parse_style_str(part) - list_of_attrs.append(inline_attrs) - - return _merge_attrs(list_of_attrs) - - def invalidation_hash(self) -> Hashable: - return id(self.class_names_and_attrs) - - -_T = TypeVar("_T") - - -def _merge_attrs(list_of_attrs: List[Attrs]) -> Attrs: - """ - Take a list of :class:`.Attrs` instances and merge them into one. - Every `Attr` in the list can override the styling of the previous one. So, - the last one has highest priority. - """ - - def _or(*values: _T) -> _T: - "Take first not-None value, starting at the end." - for v in values[::-1]: - if v is not None: - return v - raise ValueError # Should not happen, there's always one non-null value. - - return Attrs( - color=_or("", *[a.color for a in list_of_attrs]), - bgcolor=_or("", *[a.bgcolor for a in list_of_attrs]), - bold=_or(False, *[a.bold for a in list_of_attrs]), - underline=_or(False, *[a.underline for a in list_of_attrs]), - strike=_or(False, *[a.strike for a in list_of_attrs]), - italic=_or(False, *[a.italic for a in list_of_attrs]), - blink=_or(False, *[a.blink for a in list_of_attrs]), - reverse=_or(False, *[a.reverse for a in list_of_attrs]), - hidden=_or(False, *[a.hidden for a in list_of_attrs]), - ) - - -def merge_styles(styles: List[BaseStyle]) -> "_MergedStyle": - """ - Merge multiple `Style` objects. - """ - styles = [s for s in styles if s is not None] - return _MergedStyle(styles) - - -class _MergedStyle(BaseStyle): - """ - Merge multiple `Style` objects into one. - This is supposed to ensure consistency: if any of the given styles changes, - then this style will be updated. - """ - - # NOTE: previously, we used an algorithm where we did not generate the - # combined style. Instead this was a proxy that called one style - # after the other, passing the outcome of the previous style as the - # default for the next one. This did not work, because that way, the - # priorities like described in the `Style` class don't work. - # 'class:aborted' was for instance never displayed in gray, because - # the next style specified a default color for any text. (The - # explicit styling of class:aborted should have taken priority, - # because it was more precise.) - def __init__(self, styles: List[BaseStyle]) -> None: - self.styles = styles - self._style: SimpleCache[Hashable, Style] = SimpleCache(maxsize=1) - - @property - def _merged_style(self) -> Style: - "The `Style` object that has the other styles merged together." - - def get() -> Style: - return Style(self.style_rules) - - return self._style.get(self.invalidation_hash(), get) - - @property - def style_rules(self) -> List[Tuple[str, str]]: - style_rules = [] - for s in self.styles: - style_rules.extend(s.style_rules) - return style_rules - - def get_attrs_for_style_str( - self, style_str: str, default: Attrs = DEFAULT_ATTRS - ) -> Attrs: - return self._merged_style.get_attrs_for_style_str(style_str, default) - - def invalidation_hash(self) -> Hashable: - return tuple(s.invalidation_hash() for s in self.styles) |