Beispiel #1
0
class VLANS:
    '''
    Manage a bunch of VLANs, as a dictionary
    '''
    def __init__(self, vlans=None, delemiter=",", range_delemiter="-"):
        super().__init__()
        self._delemiter = delemiter
        self._range_delemiter = range_delemiter
        self._vlans = AttrDict()
        if vlans:
            self.__iadd__(vlans)

    def __add__(self, other):
        """
        Add two VLANS to each other
        """
        if not isinstance(other, VLANS):
            raise TypeError("Error: Can only handle object of VLANS()")
        tmp = self.copy()
        for vlan in other._vlans.values():
            tmp._vlans[vlan.id] = vlan
        return tmp

    def __iadd__(self, other):
        if isinstance(other, VLANS):
            for vlan in other._vlans.values():
                self._vlans[vlan.id] = vlan
        elif isinstance(other, VLAN):
            self._vlans[other.id] = other
        else:
            raise TypeError(
                "Error: Can only handle object of VLANS() or VLAN() got %s" %
                type(other))
        return self

    def __str__(self):
        return dict_to_vlan_str(self._vlans,
                                delemiter=self._delemiter,
                                range_delemiter=self._range_delemiter)

    def __repr__(self):
        s = ""
        for vlan in self._vlans.values():
            s += "(%s)" % vlan.to_str()
        return "VLANS(%s)" % s

    def __iter__(self):
        return iter(self.__dict__)

    def items(self):
        for item in self._vlans.items():
            yield item

    def keys(self):
        for item in self._vlans.keys():
            yield item

    def values(self):
        for item in self._vlans.values():
            yield item
Beispiel #2
0
class VLANS:
    '''
    Manage a bunch of VLANs, as a dictionary
    '''
    def __init__(self, vlans=None, delemiter=",", range_delemiter="-"):
        super().__init__()
        self._delemiter = delemiter
        self._range_delemiter = range_delemiter
        self._vlans = AttrDict()
        if vlans:
            self.__iadd__(vlans)

    def __add__(self, other):
        """
        Add two VLANS to each other
        """
        if not isinstance(other, VLANS):
            raise TypeError("Error: Can only handle object of VLANS()")
        tmp = self.copy()
        for vlan in other._vlans.values():
            tmp._vlans[vlan.id] = vlan
        return tmp

    def __iadd__(self, other):
        if isinstance(other, VLANS):
            for vlan in other._vlans.values():
                self._vlans[vlan.id] = vlan
        elif isinstance(other, VLAN):
            self._vlans[other.id] = other
        else:
            raise TypeError("Error: Can only handle object of VLANS() or VLAN() got %s" % type(other))
        return self

    def __str__(self):
        return dict_to_vlan_str(self._vlans,
                                delemiter=self._delemiter,
                                range_delemiter=self._range_delemiter)

    def __repr__(self):
        s = ""
        for vlan in self._vlans.values():
            s += "(%s)" % vlan.to_str()
        return "VLANS(%s)" % s

    def __iter__(self):
        return iter(self.__dict__)

    def items(self):
        for item in self._vlans.items():
            yield item

    def keys(self):
        for item in self._vlans.keys():
            yield item
            
    def values(self):
        for item in self._vlans.values():
            yield item
Beispiel #3
0
class HighlightRuleConfig(object):

    # def __init__(self, config):
    def __init__(self, config_file):
        self._config_file = config_file
        self.config = config.Config(
            self._config_file
        )
        self.flags = 0 if self.config.match.case_sensitive else re.IGNORECASE
        # import ipdb; ipdb.set_trace()
        self.rules = AttrDict([
            (label,
             HighlightRuleList(
                 self.highlight_config.get(label),
                 [ dict(subject=k, **(v or {})) for k, v in rule_dict.items() ],
                 config=self.config
             )
             )
            for label, rule_dict in self.label_config.items()
        ])
        self.RE_MAP = dict()

    @property
    def highlight_config(self):
        return self.config.get("highlight", {})

    @property
    def label_config(self):
        return self.config.get("label", {})

    @property
    def labels(self):
        return self.label_config.keys()

    def __getitem__(self, key):
        return self.rules[key]

    def add_rule(self, label, subject, group=None, patterns=None):
        targets = [subject] + (patterns if patterns else [])
        self.remove_rule(targets)
        rule = HighlightRule(subject, group=group, patterns=patterns)
        self.rules[label].append(rule)
        self.save()

    def remove_rule(self, targets):
        if not isinstance(targets, list):
            targets = [targets]
        self.rules = AttrDict([
            (label, HighlightRuleList(
                self.highlight_config.get(label),
                [
                    r for r in self.rules[label]
                    if r.subject not in targets
                    and not any(pattern in targets for pattern in r.patterns)
                ],
                config=self.config
            ))
            for label, rule_list in self.rules.items()
        ])

        self.save()

    def save(self):

        self.config.label = {
            label: {
                d.subject: {
                    k: v for k, v in d.items()
                    if k != "subject"
                } or None
                for d in [
                    rule.to_dict()
                    for rule in sorted(rule_list)
                ]
            }
            for label, rule_list in self.rules.items()
        }

        self.config.save()
        # temp_config = config.Config(
        #     self._config_file + ".new.yaml"
        # )
        # temp_config.update(self.config.tree)

        # temp_config.label = {
        #     label: {
        #         d.subject: {
        #             k: v for k, v in d.items()
        #             if k != "subject"
        #         } or None
        #         for d in [
        #             rule.to_dict()
        #             for rule in sorted(rule_list)
        #         ]
        #     }
        #     for label, rule_list in self.rules.items()
        # }
        # temp_config.save()

    def get_regex(self, rules):
        rules_set = frozenset(rules.items())
        if rules_set not in self.RE_MAP:
            pattern = '|'.join(
                f"{rules_list.pattern}"
                for label, rules_list in rules.items()
                if len(rules_list)
            )
            pattern_grouped = '|'.join(
                f"(?P<{label}>{rules_list.pattern})"
                for label, rules_list in rules.items()
                if len(rules_list)
            )
#             pattern_tokens = f"{pattern_grouped}|(?P<none>(?!{pattern})(.+?))"
            pattern_tokens = "|".join([
                p for p in [pattern_grouped, "(?P<none>(?!{pattern})(.+?))"]
                if len(p)
            ])
            self.RE_MAP[rules_set] = tuple(
                re.compile(p, self.flags)
                for p in [pattern, pattern_grouped, pattern_tokens]
            )
        return self.RE_MAP[rules_set]

    @property
    def pattern_rules(self):
        return self.get_regex(self.rules)[0]

    @property
    def pattern_rules_grouped(self):
        return self.get_regex(self.rules)[1]

    @property
    def pattern_rules_tokens(self):
        return self.get_regex(self.rules)[2]

    def search(self, text):
        return next(
            (
                match for match in (
                    rules.search(text)
                    for rules in self.rules.values()
                )
                if match
            ),
            None
        )

    def tokenize(self, text, candidates=[], aliases={}):

        for subject, alias_list in aliases.items():
            text = re.sub("|".join(
                (
                    alias
                    for alias in alias_list
                )
            ), subject, text)

        if candidates:
            rules = AttrDict([
                (label, HighlightRuleList(
                    self.highlight_config[label],
                    [
                        r for r in rule_list
                        if r.subject in candidates
                    ],
                    config=self.config
                ))
                for label, rule_list in self.rules.items()
            ])
        else:
            rules = self.rules

        (pattern, pattern_grouped, pattern_tokens) = self.get_regex(rules)

        tokens = (
            (match.lastgroup, match.group())
            for match in re.finditer(pattern_tokens, text)
        )

        out = []
        for k, g in groupby(tokens, lambda x: x[0] == "none"):
            if k:
                out.append(((None, None), "".join(item[1] for item in g)))
            else:
                (attr, text) = next(g)
                label, rule = self.rule_for_token(text)
                attr = rule.attr if (rule and rule.attr) else attr
                out.append(((label, attr), text))
        return out


    def apply(self, text, candidates=[], aliases={}):

        return [
            (attr, token) if attr else token
            for attr, token in [
                    (self.highlight_config.get(attr, attr), token)
                    for ( (label, attr), token) in self.tokenize(text, candidates=candidates, aliases=aliases)
                ]
        ]

    def get_tokens(self, text, candidates=[], aliases={}):
        return [
            token
            for (attr, token) in self.tokenize(text, candidates=candidates, aliases=aliases)
            if attr
        ]

    def rule_for_token(self, token):
        return next(
            (
                (label, rule) for label, rule in (
                    (label, rules.rule_for_token(token))
                    for label, rules in self.rules.items()
                )
                if rule
            ),
            (None, None)
        )
Beispiel #4
0
def main():

    data = AttrDict([('Adipisci eius dolore consectetur.', 34),
                     ('Aliquam consectetur velit dolore', 19),
                     ('Amet ipsum quaerat numquam.', 25),
                     ('Amet quisquam labore dolore.', 30),
                     ('Amet velit consectetur.', 20),
                     ('Consectetur consectetur aliquam voluptatem', 23),
                     ('Consectetur ipsum aliquam.', 28),
                     ('Consectetur sit neque est', 15),
                     ('Dolore voluptatem etincidunt sit', 40),
                     ('Dolorem porro tempora tempora.', 37),
                     ('Eius numquam dolor ipsum', 26),
                     ('Eius tempora etincidunt est', 12),
                     ('Est adipisci numquam adipisci', 7),
                     ('Est aliquam dolor.', 38),
                     ('Etincidunt amet quisquam.', 33),
                     ('Etincidunt consectetur velit.', 29),
                     ('Etincidunt dolore eius.', 45),
                     ('Etincidunt non amet.', 14),
                     ('Etincidunt velit adipisci labore', 6),
                     ('Ipsum magnam velit quiquia', 21),
                     ('Ipsum modi eius.', 3),
                     ('Labore voluptatem quiquia aliquam', 18),
                     ('Magnam etincidunt porro magnam', 39),
                     ('Magnam numquam amet.', 44),
                     ('Magnam quisquam sit amet.', 27),
                     ('Magnam voluptatem ipsum neque', 32),
                     ('Modi est ipsum adipisci', 2),
                     ('Neque eius voluptatem voluptatem', 42),
                     ('Neque quisquam ipsum.', 10),
                     ('Neque quisquam neque.', 48),
                     ('Non dolore voluptatem.', 41),
                     ('Non numquam consectetur voluptatem.', 35),
                     ('Numquam eius dolorem.', 43),
                     ('Numquam sed neque modi', 9),
                     ('Porro voluptatem quaerat voluptatem', 11),
                     ('Quaerat eius quiquia.', 17),
                     ('Quiquia aliquam etincidunt consectetur.', 0),
                     ('Quiquia ipsum sit.', 49),
                     ('Quiquia non dolore quiquia', 8),
                     ('Quisquam aliquam numquam dolore.', 1),
                     ('Quisquam dolorem voluptatem adipisci.', 22),
                     ('Sed magnam dolorem quisquam', 4),
                     ('Sed tempora modi est.', 16),
                     ('Sit aliquam dolorem.', 46), ('Sit modi dolor.', 31),
                     ('Sit quiquia quiquia non.', 5),
                     ('Sit quisquam numquam quaerat.', 36),
                     ('Tempora etincidunt quiquia dolor', 13),
                     ('Tempora velit etincidunt.', 24),
                     ('Velit dolor velit.', 47)])

    NORMAL_FG = 'light gray'
    NORMAL_BG = 'black'

    if os.environ.get("DEBUG"):
        logger.setLevel(logging.DEBUG)
        formatter = logging.Formatter(
            "%(asctime)s [%(levelname)8s] %(message)s",
            datefmt='%Y-%m-%d %H:%M:%S')
        fh = logging.FileHandler("dropdown.log")
        fh.setFormatter(formatter)
        logger.addHandler(fh)
    else:
        logger.addHandler(logging.NullHandler())

    entries = {
        "dropdown_text":
        PaletteEntry(
            foreground="light gray",
            background="dark blue",
            foreground_high="light gray",
            background_high="#003",
        ),
        "dropdown_focused":
        PaletteEntry(
            foreground="white",
            background="light blue",
            foreground_high="white",
            background_high="#009",
        ),
        "dropdown_highlight":
        PaletteEntry(
            foreground="yellow",
            background="light blue",
            foreground_high="yellow",
            background_high="#009",
        ),
        "dropdown_label":
        PaletteEntry(foreground="white", background="black"),
        "dropdown_prompt":
        PaletteEntry(foreground="light blue", background="black"),
    }

    entries = DataTable.get_palette_entries(user_entries=entries)
    palette = Palette("default", **entries)
    screen = urwid.raw_display.Screen()
    screen.set_terminal_properties(256)

    boxes = [
        TestDropdown(
            data,
            label="Foo",
            border=True,
            scrollbar=True,
            right_chars_top=u" \N{BLACK DOWN-POINTING TRIANGLE}",
            auto_complete=True,
        ),
        TestDropdown(
            data,
            border=False,
            margin=2,
            left_chars=u"\N{LIGHT LEFT TORTOISE SHELL BRACKET ORNAMENT}",
            right_chars=u"\N{LIGHT RIGHT TORTOISE SHELL BRACKET ORNAMENT}",
            auto_complete=True),
        TestDropdown(
            data,
            initial_value=list(data.values())[10],
            label="Foo",
            border=True,
            scrollbar=False,
            auto_complete=False,
        ),
        TestDropdown([], ),
    ]

    grid = urwid.GridFlow([urwid.Padding(b) for b in boxes], 60, 1, 1, "left")

    main = urwid.Frame(urwid.Filler(grid))

    def global_input(key):
        if key in ('q', 'Q'):
            raise urwid.ExitMainLoop()
        else:
            return False

    loop = urwid.MainLoop(main,
                          palette,
                          screen=screen,
                          unhandled_input=global_input,
                          pop_ups=True)
    loop.run()
Beispiel #5
0
class Dropdown(urwid.PopUpLauncher):
    # Based in part on SelectOne widget from
    # https://github.com/tuffy/python-audio-tools

    signals = ["change"]

    label = None
    empty_label = u"\N{EMPTY SET}"
    margin = 0

    def __init__(
        self,
        items=None,
        label=None,
        default=None,
        border=False,
        scrollbar=False,
        margin=None,
        left_chars=None,
        right_chars=None,
        left_chars_top=None,
        right_chars_top=None,
        auto_complete=False,
        max_height=10,
        # keymap = {}
    ):

        if items is not None:
            self._items = items
        if label is not None:
            self.label = label
        self.default = default

        self.border = border
        self.scrollbar = scrollbar
        self.auto_complete = auto_complete
        # self.keymap = keymap

        if margin:
            self.margin = margin

        if isinstance(self.items, list):
            if len(self.items):
                if isinstance(self.items[0], tuple):
                    self._items = AttrDict(self.items)
                else:
                    logger.debug(self.items)
                    self._items = AttrDict(
                        ((item, n) for n, item in enumerate(self.items)))
            else:
                self._items = AttrDict()
        else:
            self._items = self.items

        self.button = DropdownItem(
            u"",
            None,
            margin=self.margin,
            left_chars=left_chars_top if left_chars_top else left_chars,
            right_chars=right_chars_top if right_chars_top else right_chars)

        self.pop_up = DropdownDialog(
            self,
            self._items,
            self.default,
            label=self.label,
            border=self.border,
            margin=self.margin,
            left_chars=left_chars,
            right_chars=right_chars,
            auto_complete=self.auto_complete,
            scrollbar=scrollbar,
            max_height=max_height,
            # keymap = self.KEYMAP
        )

        urwid.connect_signal(self.pop_up, "select",
                             lambda souce, selection: self.select(selection))

        urwid.connect_signal(self.pop_up, "close",
                             lambda button: self.close_pop_up())

        if self.default is not None:
            try:
                if isinstance(self.default, str):
                    self.select_label(self.default)
                else:
                    raise StopIteration
            except StopIteration:
                try:
                    self.select_value(self.default)
                except StopIteration:
                    self.focus_position = 0

        if len(self):
            self.select(self.selection)
        else:
            self.button.set_label(("dropdown_text", self.empty_label))

        cols = [(self.button_width, self.button)]

        if self.label:
            cols[0:0] = [
                ("pack", urwid.Text([("dropdown_label", "%s: " % (self.label))
                                     ])),
            ]
        self.columns = urwid.Columns(cols, dividechars=0)

        w = self.columns
        if self.border:
            w = urwid.LineBox(self.columns)
        w = urwid.Padding(w, width=self.width)

        super(Dropdown, self).__init__(w)
        urwid.connect_signal(self.button, 'click',
                             lambda button: self.open_pop_up())

    @classmethod
    def get_palette_entries(cls):
        return {
            "dropdown_text":
            PaletteEntry(
                foreground="light gray",
                background="dark blue",
                foreground_high="light gray",
                background_high="#003",
            ),
            "dropdown_focused":
            PaletteEntry(
                foreground="white",
                background="light blue",
                foreground_high="white",
                background_high="#009",
            ),
            "dropdown_highlight":
            PaletteEntry(
                foreground="yellow",
                background="light blue",
                foreground_high="yellow",
                background_high="#009",
            ),
            "dropdown_label":
            PaletteEntry(foreground="white", background="black"),
            "dropdown_prompt":
            PaletteEntry(foreground="light blue", background="black")
        }

    @keymap_command()
    def complete_prefix(self):
        if not self.auto_complete:
            return
        self.open_pop_up()
        self.pop_up.complete_prefix()

    @keymap_command()
    def complete_substring(self):
        if not self.auto_complete:
            return
        self.open_pop_up()
        self.pop_up.complete_substring()

    def create_pop_up(self):
        # print("create")
        return self.pop_up

    @property
    def button_width(self):
        return self.pop_up.max_item_width + self.button.decoration_width

    @property
    def pop_up_width(self):
        w = self.button_width
        if self.border:
            w += 2
        return w

    @property
    def contents_width(self):
        # raise Exception(self.button.width)
        w = self.button_width
        if self.label:
            w += len(self.label) + 2
        return max(self.pop_up.width, w)

    @property
    def width(self):
        width = max(self.contents_width, self.pop_up.width)
        if self.border:
            width += 2
        return width

    @property
    def height(self):
        height = self.pop_up.height + 1
        return height

    def pack(self, size, focus=False):
        return (self.width, self.height)

    @property
    def page_size(self):
        return self.pop_up.height

    def open_pop_up(self):
        # print("open")
        super(Dropdown, self).open_pop_up()

    def close_pop_up(self):
        super(Dropdown, self).close_pop_up()

    def get_pop_up_parameters(self):
        return {
            'left': (len(self.label) + 2 if self.label else 0),
            'top': 0,
            'overlay_width': self.pop_up_width,
            'overlay_height': self.pop_up.height
        }

    @property
    def focus_position(self):
        return self.pop_up.focus_position

    @focus_position.setter
    def focus_position(self, pos):
        # self.select_index(pos)
        old_pos = self.focus_position
        self.pop_up.selected_button = self.pop_up.focus_position = pos
        self.select(self.selection)

    @property
    def items(self):
        return self._items

    @property
    def selection(self):
        return self.pop_up.selection

    def select_label(self, label, case_sensitive=False):

        old_value = self.value

        def f(x):
            return x

        if not case_sensitive:

            def f(x):
                return x.lower()

        index = next(
            itertools.dropwhile(lambda x: f(x[1]) != f(label),
                                enumerate((self._items.keys()))))[0]
        self.focus_position = index

    @property
    def items(self):
        return self._items

    @property
    def selection(self):
        return self.pop_up.selection

    def select_label(self, label, case_sensitive=False):

        old_value = self.value

        def f(x):
            return x

        if not case_sensitive:

            def f(x):
                return x.lower()

        index = next(
            itertools.dropwhile(lambda x: f(x[1]) != f(label),
                                enumerate((self._items.keys()))))[0]
        self.focus_position = index

    def select_value(self, value):

        index = next(
            itertools.dropwhile(lambda x: x[1] != value,
                                enumerate((self._items.values()))))[0]
        self.focus_position = index

    @property
    def labels(self):
        return self._items.keys()

    @property
    def values(self):
        return self._items.values()

    @property
    def selected_label(self):
        return self.selection.label

    @selected_label.setter
    def selected_label(self, label):
        return self.select_label(label)

    @property
    def selected_value(self):
        if not self.selection:
            return None
        return self.selection.value

    @selected_value.setter
    def selected_value(self, value):
        return self.select_value(value)

    @property
    def value(self):
        return self.selected_value

    @value.setter
    def value(self, value):
        old_value = self.value

        # try to set by value.  if not found, try to set by label
        try:
            self.selected_value = value
        except StopIteration:
            self.selected_label = value

    def cycle_prev(self):
        self.cycle(-1)

    @keymap_command("cycle")
    def cycle(self, n):
        pos = self.focus_position + n
        if pos > len(self) - 1:
            pos = len(self) - 1
        elif pos < 0:
            pos = 0
        # self.focus_position = pos
        self.focus_position = pos

    def select(self, button):
        logger.debug("select: %s" % (button))
        self.button.set_label(("dropdown_text", button.label))
        self.pop_up.dropdown_buttons.listbox.set_focus_valign("top")
        # if old_pos != pos:
        self._emit("change", self.selected_label, self.selected_value)

    # def set_items(self, items, selected_value):
    #     self._items = items
    #     self.make_selection([label for (label, value) in items if
    #                          value is selected_value][0],
    #                         selected_value)
    def __len__(self):
        return len(self.items)
Beispiel #6
0
class Dropdown(urwid.PopUpLauncher):
    # Based in part on SelectOne widget from
    # https://github.com/tuffy/python-audio-tools

    signals = ["change"]

    empty_label = u"\N{EMPTY SET}"
    margin = 0

    def __init__(self,
                 items=None,
                 initial_value=None,
                 label=None,
                 border=False,
                 scrollbar=False,
                 margin=None,
                 left_chars=None,
                 right_chars=None,
                 left_chars_top=None,
                 right_chars_top=None,
                 auto_complete=False,
                 keymap={}):

        # raise Exception(self.KEYMAP_SCOPE)
        if items is not None:
            self._items = items

        self.initial_value = initial_value
        self.label = label
        self.border = border
        self.scrollbar = scrollbar
        self.auto_complete = auto_complete
        # self.keymap = keymap

        if margin:
            self.margin = margin

        if isinstance(self.items, list):
            if len(self.items):
                if isinstance(items[0], tuple):
                    self.items = AttrDict(self.items)
                self._items = AttrDict(
                    ((item, n) for n, item in enumerate(self.items)))
            else:
                self._items = AttrDict()

        self.button = DropdownItem(
            u"",
            None,
            margin=self.margin,
            left_chars=left_chars_top if left_chars_top else left_chars,
            right_chars=right_chars_top if right_chars_top else right_chars)

        self.pop_up = DropdownDialog(
            self,
            self._items,
            self.initial_value,
            label=self.label,
            border=self.border,
            margin=self.margin,
            left_chars=left_chars,
            right_chars=right_chars,
            auto_complete=self.auto_complete,
            scrollbar=scrollbar,
            # keymap = self.KEYMAP
        )

        urwid.connect_signal(self.pop_up, "select",
                             lambda souce, selection: self.select(selection))

        urwid.connect_signal(self.pop_up, "close",
                             lambda button: self.close_pop_up())

        try:
            initial_index = next(v for v in self.items.values()
                                 if v == self.initial_value)
            self.focus_position = initial_index
        except StopIteration:
            initial_index = 0

        if len(self):
            self.select(self.selection)
        else:
            self.button.set_label(("dropdown_text", self.empty_label))

        cols = [(self.button_width, self.button)]

        if self.label:
            cols[0:0] = [
                ("pack", urwid.Text([("dropdown_label", "%s: " % (self.label))
                                     ])),
            ]
        self.columns = urwid.Columns(cols, dividechars=0)

        w = self.columns
        if self.border:
            w = urwid.LineBox(self.columns)
        w = urwid.Padding(w, width=self.width)

        super(Dropdown, self).__init__(w)
        urwid.connect_signal(self.button, 'click',
                             lambda button: self.open_pop_up())

    @keymap_command()
    def complete_prefix(self):
        if not self.auto_complete:
            return
        self.open_pop_up()
        self.pop_up.complete_prefix()

    @keymap_command()
    def complete_substring(self):
        if not self.auto_complete:
            return
        self.open_pop_up()
        self.pop_up.complete_substring()

    def create_pop_up(self):
        # print("create")
        return self.pop_up

    @property
    def button_width(self):
        return self.pop_up.max_item_width + self.button.decoration_width

    @property
    def pop_up_width(self):
        w = self.button_width
        if self.border:
            w += 2
        return w

    @property
    def contents_width(self):
        # raise Exception(self.button.width)
        w = self.button_width
        if self.label:
            w += len(self.label) + 2
        return max(self.pop_up.width, w)

    @property
    def width(self):
        width = max(self.contents_width, self.pop_up.width)
        if self.border:
            width += 2
        return width

    @property
    def height(self):
        height = self.pop_up.height + 1
        return height

    @property
    def page_size(self):
        return self.pop_up.height

    def open_pop_up(self):
        # print("open")
        super(Dropdown, self).open_pop_up()

    def close_pop_up(self):
        super(Dropdown, self).close_pop_up()

    def get_pop_up_parameters(self):
        return {
            'left': (len(self.label) + 2 if self.label else 0),
            'top': 0,
            'overlay_width': self.pop_up_width,
            'overlay_height': self.pop_up.height
        }

    @property
    def focus_position(self):
        return self.pop_up.focus_position

    @focus_position.setter
    def focus_position(self, pos):
        # self.select_index(pos)
        self.pop_up.selected_button = self.pop_up.focus_position = pos
        self.select(self.selection)

    @property
    def items(self):
        return self._items

    @property
    def selection(self):
        return self.pop_up.selection

    @property
    def selected_label(self):
        return self.selection.label

    @property
    def selected_value(self):
        return self.selection.value

    def cycle(self, n):
        pos = self.focus_position + n
        if pos > len(self) - 1:
            pos = len(self) - 1
        elif pos < 0:
            pos = 0
        # self.focus_position = pos
        self.focus_position = pos

    def select(self, button):
        logger.debug("select: %s" % (button))
        self.button.set_label(("dropdown_text", button.label))
        self.pop_up.dropdown_buttons.listbox.set_focus_valign("top")
        self._emit("change", button, button.value)

    # def set_items(self, items, selected_value):
    #     self._items = items
    #     self.make_selection([label for (label, value) in items if
    #                          value is selected_value][0],
    #                         selected_value)
    def __len__(self):
        return len(self.items)