<commit_before>#!/usr/bin/python
#
# Urwid basic widget classes
#    Copyright (C) 2004-2012  <NAME>
#
#    This library is free software; you can redistribute it and/or
#    modify it under the terms of the GNU Lesser General Public
#    License as published by the Free Software Foundation; either
#    version 2.1 of the License, or (at your option) any later version.
#
#    This library is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
#    Lesser General Public License for more details.
#
#    You should have received a copy of the GNU Lesser General Public
#    License along with this library; if not, write to the Free Software
#    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
# Urwid web site: http://excess.org/urwid/

from operator import attrgetter

from urwid.util import (MetaSuper, decompose_tagmarkup, calc_width,
    is_wide_char, move_prev_char, move_next_char)
from urwid.text_layout import calc_pos, calc_coords, shift_line
from urwid import signals
from urwid import text_layout
from urwid.canvas import (CanvasCache, CompositeCanvas, SolidCanvas,
    apply_text_layout)
from urwid.command_map import (command_map, CURSOR_LEFT, CURSOR_RIGHT,
    CURSOR_UP, CURSOR_DOWN, CURSOR_MAX_LEFT, CURSOR_MAX_RIGHT)
from urwid.split_repr import split_repr, remove_defaults, python3_repr


# define some names for these constants to avoid misspellings in the source
# and to document the constant strings we are using

# Widget sizing methods

FLOW = 'flow'
BOX = 'box'
FIXED = 'fixed'

# Text alignment modes
LEFT = 'left'
RIGHT = 'right'
CENTER = 'center'

# Filler alignment
TOP = 'top'
MIDDLE = 'middle'
BOTTOM = 'bottom'

# Text wrapping modes
SPACE = 'space'
ANY = 'any'
CLIP = 'clip'

# Width and Height settings
PACK = 'pack'
GIVEN = 'given'
RELATIVE = 'relative'
RELATIVE_100 = (RELATIVE, 100)
WEIGHT = 'weight'


class WidgetMeta(MetaSuper, signals.MetaSignals):
    """
    Bases: :class:`MetaSuper`, :class:`MetaSignals`

    Automatic caching of render and rows methods.

    Class variable *no_cache* is a list of names of methods to not cache
    automatically.  Valid method names for *no_cache* are ``'render'`` and
    ``'rows'``.

    Class variable *ignore_focus* if defined and set to ``True`` indicates
    that the canvas this widget renders is not affected by the focus
    parameter, so it may be ignored when caching.
    """
    def __init__(cls, name, bases, d):
        no_cache = d.get("no_cache", [])

        super(WidgetMeta, cls).__init__(name, bases, d)

        if "render" in d:
            if "render" not in no_cache:
                render_fn = cache_widget_render(cls)
            else:
                render_fn = nocache_widget_render(cls)
            cls.render = render_fn

        if "rows" in d and "rows" not in no_cache:
            cls.rows = cache_widget_rows(cls)
        if "no_cache" in d:
            del cls.no_cache
        if "ignore_focus" in d:
            del cls.ignore_focus

class WidgetError(Exception):
    pass

def validate_size(widget, size, canv):
    """
    Raise a WidgetError if a canv does not match size size.
    """
    if (size and size[1:] != (0,) and size[0] != canv.cols()) or \
        (len(size)>1 and size[1] != canv.rows()):
        raise WidgetError("Widget %r rendered (%d x %d) canvas"
            " when passed size %r!" % (widget, canv.cols(),
            canv.rows(), size))

def update_wrapper(new_fn, fn):
    """
    Copy as much of the function detail from fn to new_fn
    as we can.
    """
    try:
        new_fn.__name__ = fn.__name__
        new_fn.__dict__.update(fn.__dict__)
        new_fn.__doc__ = fn.__doc__
        new_fn.__module__ = fn.__module__
    except TypeError:
        pass # python2.3 ignore read-only attributes


def cache_widget_render(cls):
    """
    Return a function that wraps the cls.render() method
    and fetches and stores canvases with CanvasCache.
    """
    ignore_focus = bool(getattr(cls, "ignore_focus", False))
    fn = cls.render
    def cached_render(self, size, focus=False):
        focus = focus and not ignore_focus
        canv = CanvasCache.fetch(self, cls, size, focus)
        if canv:
            return canv

        canv = fn(self, size, focus=focus)
        validate_size(self, size, canv)
        if canv.widget_info:
            canv = CompositeCanvas(canv)
        canv.finalize(self, size, focus)
        CanvasCache.store(cls, canv)
        return canv
    cached_render.original_fn = fn
    update_wrapper(cached_render, fn)
    return cached_render

def nocache_widget_render(cls):
    """
    Return a function that wraps the cls.render() method
    and finalizes the canvas that it returns.
    """
    fn = cls.render
    if hasattr(fn, "original_fn"):
        fn = fn.original_fn
    def finalize_render(self, size, focus=False):
        canv = fn(self, size, focus=focus)
        if canv.widget_info:
            canv = CompositeCanvas(canv)
        validate_size(self, size, canv)
        canv.finalize(self, size, focus)
        return canv
    finalize_render.original_fn = fn
    update_wrapper(finalize_render, fn)
    return finalize_render

def nocache_widget_render_instance(self):
    """
    Return a function that wraps the cls.render() method
    and finalizes the canvas that it returns, but does not 
    cache the canvas.
    """
    fn = self.render.original_fn
    def finalize_render(size, focus=False):
        canv = fn(self, size, focus=focus)
        if canv.widget_info:
            canv = CompositeCanvas(canv)
        canv.finalize(self, size, focus)
        return canv
    finalize_render.original_fn = fn
    update_wrapper(finalize_render, fn)
    return finalize_render

def cache_widget_rows(cls):
    """
    Return a function that wraps the cls.rows() method
    and returns rows from the CanvasCache if available.
    """
    ignore_focus = bool(getattr(cls, "ignore_focus", False))
    fn = cls.rows
    def cached_rows(self, size, focus=False):
        focus = focus and not ignore_focus
        canv = CanvasCache.fetch(self, cls, size, focus)
        if canv:
            return canv.rows()

        return fn(self, size, focus)
    update_wrapper(cached_rows, fn)
    return cached_rows


class Widget(object):
    """
    Widget base class

    .. attribute:: __metaclass__
       :annotation: = urwid.WidgetMeta

       See :class:`urwid.WidgetMeta` definition

    .. attribute:: _selectable
       :annotation: = False

       The default :meth:`.selectable` method returns this
       value.

    .. attribute:: _sizing
       :annotation: = frozenset(['flow', 'box', 'fixed'])

       The default :meth:`.sizing` method returns this value.

    .. attribute:: _command_map
       :annotation: = urwid.command_map

       A shared :class:`CommandMap` instance. May be redefined
       in subclasses or widget instances.

    .. method:: render(size, focus=False)

       .. note::

          This method is not implemented in :class:`.Widget` but
          must be implemented by any concrete subclass

       :param size: One of the following,
                    *maxcol* and *maxrow* are integers > 0:

                    (*maxcol*, *maxrow*)
                      for box sizing -- the parent chooses the exact
                      size of this widget

                    (*maxcol*,)
                      for flow sizing -- the parent chooses only the
                      number of columns for this widget

                    ()
                      for fixed sizing -- this widget is a fixed size
                      which can't be adjusted by the parent
       :type size: widget size
       :param focus: set to ``True`` if this widget or one of its children
                     is in focus
       :type focus: bool

       :returns: A :class:`Canvas` subclass instance containing the
                 rendered content of this widget

       :class:`Text` widgets return a :class:`TextCanvas` (arbitrary text and
       display attributes), :class:`SolidFill` widgets return a
       :class:`SolidCanvas` (a single character repeated across
       the whole surface) and container widgets return a
       :class:`CompositeCanvas` (one or more other canvases
       arranged arbitrarily).

       If *focus* is ``False``, the returned canvas may not have a cursor
       position set.

       There is some metaclass magic defined in the :class:`Widget`
       metaclass :class:`WidgetMeta` that causes the
       result of this method to be cached by :class:`CanvasCache`.
       Later calls will automatically look up the value in the cache first.

       As a small optimization the class variable :attr:`ignore_focus`
       may be defined and set to ``True`` if this widget renders the same
       canvas regardless of the value of the *focus* parameter.

       Any time the content of a widget changes it should call
       :meth:`_invalidate` to remove any cached canvases, or the widget
       may render the cached canvas instead of creating a new one.


    .. method:: rows(size, focus=False)

       .. note::

          This method is not implemented in :class:`.Widget` but
          must be implemented by any flow widget.  See :meth:`.sizing`.

       See :meth:`Widget.render` for parameter details.

       :returns: The number of rows required for this widget given a number
                 of columns in *size*

       This is the method flow widgets use to communicate their size to other
       widgets without having to render a canvas. This should be a quick
       calculation as this function may be called a number of times in normal
       operation. If your implementation may take a long time you should add
       your own caching here.

       There is some metaclass magic defined in the :class:`Widget`
       metaclass :class:`WidgetMeta` that causes the
       result of this function to be retrieved from any
       canvas cached by :class:`CanvasCache`, so if your widget
       has been rendered you may not receive calls to this function. The class
       variable :attr:`ignore_focus` may be defined and set to ``True`` if this
       widget renders the same size regardless of the value of the *focus*
       parameter.


    .. method:: keypress(size, key)

       .. note::

          This method is not implemented in :class:`.Widget` but
          must be implemented by any selectable widget.
          See :meth:`.selectable`.

       :param size: See :meth:`Widget.render` for details
       :type size: widget size
       :param key: a single keystroke value; see :ref:`keyboard-input`
       :type key: bytes or unicode

       :returns: ``None`` if *key* was handled by this widget or
                 *key* (the same value passed) if *key* was not handled
                 by this widget

       Container widgets will typically call the :meth:`keypress` method on
       whichever of their children is set as the focus.

       The standard widgets use :attr:`_command_map` to
       determine what action should be performed for a given *key*. You may
       modify these values to your liking globally, at some level in the
       widget hierarchy or on individual widgets. See :class:`CommandMap`
       for the defaults.

       In your own widgets you may use whatever logic you like: filtering or
       translating keys, selectively passing along events etc.



    .. method:: mouse_event(size, event, button, col, row, focus)

       .. note::

          This method is not implemented in :class:`.Widget` but
          may be implemented by a subclass.  Not implementing this
          method is equivalent to having a method that always returns
          ``False``.

       :param size: See :meth:`Widget.render` for details.
       :type size: widget size
       :param event: Values such as ``'mouse press'``, ``'ctrl mouse press'``,
                     ``'mouse relase'``, ``'meta mouse release'``,
                     ``'mouse drag'``; see :ref:`mouse-input`
       :type event: mouse event
       :param button: 1 through 5 for press events, often 0 for release events
                      (which button was released is often not known)
       :type button: int
       :param col: Column of the event, 0 is the left edge of this widget
       :type col: int<commit_msg>DOC: TYPO: Update widget.py<commit_after>#!/usr/bin/python
#
# Urwid basic widget classes
#    Copyright (C) 2004-2012  <NAME>
#
#    This library is free software; you can redistribute it and/or
#    modify it under the terms of the GNU Lesser General Public
#    License as published by the Free Software Foundation; either
#    version 2.1 of the License, or (at your option) any later version.
#
#    This library is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
#    Lesser General Public License for more details.
#
#    You should have received a copy of the GNU Lesser General Public
#    License along with this library; if not, write to the Free Software
#    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
# Urwid web site: http://excess.org/urwid/

from operator import attrgetter

from urwid.util import (MetaSuper, decompose_tagmarkup, calc_width,
    is_wide_char, move_prev_char, move_next_char)
from urwid.text_layout import calc_pos, calc_coords, shift_line
from urwid import signals
from urwid import text_layout
from urwid.canvas import (CanvasCache, CompositeCanvas, SolidCanvas,
    apply_text_layout)
from urwid.command_map import (command_map, CURSOR_LEFT, CURSOR_RIGHT,
    CURSOR_UP, CURSOR_DOWN, CURSOR_MAX_LEFT, CURSOR_MAX_RIGHT)
from urwid.split_repr import split_repr, remove_defaults, python3_repr


# define some names for these constants to avoid misspellings in the source
# and to document the constant strings we are using

# Widget sizing methods

FLOW = 'flow'
BOX = 'box'
FIXED = 'fixed'

# Text alignment modes
LEFT = 'left'
RIGHT = 'right'
CENTER = 'center'

# Filler alignment
TOP = 'top'
MIDDLE = 'middle'
BOTTOM = 'bottom'

# Text wrapping modes
SPACE = 'space'
ANY = 'any'
CLIP = 'clip'

# Width and Height settings
PACK = 'pack'
GIVEN = 'given'
RELATIVE = 'relative'
RELATIVE_100 = (RELATIVE, 100)
WEIGHT = 'weight'


class WidgetMeta(MetaSuper, signals.MetaSignals):
    """
    Bases: :class:`MetaSuper`, :class:`MetaSignals`

    Automatic caching of render and rows methods.

    Class variable *no_cache* is a list of names of methods to not cache
    automatically.  Valid method names for *no_cache* are ``'render'`` and
    ``'rows'``.

    Class variable *ignore_focus* if defined and set to ``True`` indicates
    that the canvas this widget renders is not affected by the focus
    parameter, so it may be ignored when caching.
    """
    def __init__(cls, name, bases, d):
        no_cache = d.get("no_cache", [])

        super(WidgetMeta, cls).__init__(name, bases, d)

        if "render" in d:
            if "render" not in no_cache:
                render_fn = cache_widget_render(cls)
            else:
                render_fn = nocache_widget_render(cls)
            cls.render = render_fn

        if "rows" in d and "rows" not in no_cache:
            cls.rows = cache_widget_rows(cls)
        if "no_cache" in d:
            del cls.no_cache
        if "ignore_focus" in d:
            del cls.ignore_focus

class WidgetError(Exception):
    pass

def validate_size(widget, size, canv):
    """
    Raise a WidgetError if a canv does not match size size.
    """
    if (size and size[1:] != (0,) and size[0] != canv.cols()) or \
        (len(size)>1 and size[1] != canv.rows()):
        raise WidgetError("Widget %r rendered (%d x %d) canvas"
            " when passed size %r!" % (widget, canv.cols(),
            canv.rows(), size))

def update_wrapper(new_fn, fn):
    """
    Copy as much of the function detail from fn to new_fn
    as we can.
    """
    try:
        new_fn.__name__ = fn.__name__
        new_fn.__dict__.update(fn.__dict__)
        new_fn.__doc__ = fn.__doc__
        new_fn.__module__ = fn.__module__
    except TypeError:
        pass # python2.3 ignore read-only attributes


def cache_widget_render(cls):
    """
    Return a function that wraps the cls.render() method
    and fetches and stores canvases with CanvasCache.
    """
    ignore_focus = bool(getattr(cls, "ignore_focus", False))
    fn = cls.render
    def cached_render(self, size, focus=False):
        focus = focus and not ignore_focus
        canv = CanvasCache.fetch(self, cls, size, focus)
        if canv:
            return canv

        canv = fn(self, size, focus=focus)
        validate_size(self, size, canv)
        if canv.widget_info:
            canv = CompositeCanvas(canv)
        canv.finalize(self, size, focus)
        CanvasCache.store(cls, canv)
        return canv
    cached_render.original_fn = fn
    update_wrapper(cached_render, fn)
    return cached_render

def nocache_widget_render(cls):
    """
    Return a function that wraps the cls.render() method
    and finalizes the canvas that it returns.
    """
    fn = cls.render
    if hasattr(fn, "original_fn"):
        fn = fn.original_fn
    def finalize_render(self, size, focus=False):
        canv = fn(self, size, focus=focus)
        if canv.widget_info:
            canv = CompositeCanvas(canv)
        validate_size(self, size, canv)
        canv.finalize(self, size, focus)
        return canv
    finalize_render.original_fn = fn
    update_wrapper(finalize_render, fn)
    return finalize_render

def nocache_widget_render_instance(self):
    """
    Return a function that wraps the cls.render() method
    and finalizes the canvas that it returns, but does not 
    cache the canvas.
    """
    fn = self.render.original_fn
    def finalize_render(size, focus=False):
        canv = fn(self, size, focus=focus)
        if canv.widget_info:
            canv = CompositeCanvas(canv)
        canv.finalize(self, size, focus)
        return canv
    finalize_render.original_fn = fn
    update_wrapper(finalize_render, fn)
    return finalize_render

def cache_widget_rows(cls):
    """
    Return a function that wraps the cls.rows() method
    and returns rows from the CanvasCache if available.
    """
    ignore_focus = bool(getattr(cls, "ignore_focus", False))
    fn = cls.rows
    def cached_rows(self, size, focus=False):
        focus = focus and not ignore_focus
        canv = CanvasCache.fetch(self, cls, size, focus)
        if canv:
            return canv.rows()

        return fn(self, size, focus)
    update_wrapper(cached_rows, fn)
    return cached_rows


class Widget(object):
    """
    Widget base class

    .. attribute:: __metaclass__
       :annotation: = urwid.WidgetMeta

       See :class:`urwid.WidgetMeta` definition

    .. attribute:: _selectable
       :annotation: = False

       The default :meth:`.selectable` method returns this
       value.

    .. attribute:: _sizing
       :annotation: = frozenset(['flow', 'box', 'fixed'])

       The default :meth:`.sizing` method returns this value.

    .. attribute:: _command_map
       :annotation: = urwid.command_map

       A shared :class:`CommandMap` instance. May be redefined
       in subclasses or widget instances.

    .. method:: render(size, focus=False)

       .. note::

          This method is not implemented in :class:`.Widget` but
          must be implemented by any concrete subclass

       :param size: One of the following,
                    *maxcol* and *maxrow* are integers > 0:

                    (*maxcol*, *maxrow*)
                      for box sizing -- the parent chooses the exact
                      size of this widget

                    (*maxcol*,)
                      for flow sizing -- the parent chooses only the
                      number of columns for this widget

                    ()
                      for fixed sizing -- this widget is a fixed size
                      which can't be adjusted by the parent
       :type size: widget size
       :param focus: set to ``True`` if this widget or one of its children
                     is in focus
       :type focus: bool

       :returns: A :class:`Canvas` subclass instance containing the
                 rendered content of this widget

       :class:`Text` widgets return a :class:`TextCanvas` (arbitrary text and
       display attributes), :class:`SolidFill` widgets return a
       :class:`SolidCanvas` (a single character repeated across
       the whole surface) and container widgets return a
       :class:`CompositeCanvas` (one or more other canvases
       arranged arbitrarily).

       If *focus* is ``False``, the returned canvas may not have a cursor
       position set.

       There is some metaclass magic defined in the :class:`Widget`
       metaclass :class:`WidgetMeta` that causes the
       result of this method to be cached by :class:`CanvasCache`.
       Later calls will automatically look up the value in the cache first.

       As a small optimization the class variable :attr:`ignore_focus`
       may be defined and set to ``True`` if this widget renders the same
       canvas regardless of the value of the *focus* parameter.

       Any time the content of a widget changes it should call
       :meth:`_invalidate` to remove any cached canvases, or the widget
       may render the cached canvas instead of creating a new one.


    .. method:: rows(size, focus=False)

       .. note::

          This method is not implemented in :class:`.Widget` but
          must be implemented by any flow widget.  See :meth:`.sizing`.

       See :meth:`Widget.render` for parameter details.

       :returns: The number of rows required for this widget given a number
                 of columns in *size*

       This is the method flow widgets use to communicate their size to other
       widgets without having to render a canvas. This should be a quick
       calculation as this function may be called a number of times in normal
       operation. If your implementation may take a long time you should add
       your own caching here.

       There is some metaclass magic defined in the :class:`Widget`
       metaclass :class:`WidgetMeta` that causes the
       result of this function to be retrieved from any
       canvas cached by :class:`CanvasCache`, so if your widget
       has been rendered you may not receive calls to this function. The class
       variable :attr:`ignore_focus` may be defined and set to ``True`` if this
       widget renders the same size regardless of the value of the *focus*
       parameter.


    .. method:: keypress(size, key)

       .. note::

          This method is not implemented in :class:`.Widget` but
          must be implemented by any selectable widget.
          See :meth:`.selectable`.

       :param size: See :meth:`Widget.render` for details
       :type size: widget size
       :param key: a single keystroke value; see :ref:`keyboard-input`
       :type key: bytes or unicode

       :returns: ``None`` if *key* was handled by this widget or
                 *key* (the same value passed) if *key* was not handled
                 by this widget

       Container widgets will typically call the :meth:`keypress` method on
       whichever of their children is set as the focus.

       The standard widgets use :attr:`_command_map` to
       determine what action should be performed for a given *key*. You may
       modify these values to your liking globally, at some level in the
       widget hierarchy or on individual widgets. See :class:`CommandMap`
       for the defaults.

       In your own widgets you may use whatever logic you like: filtering or
       translating keys, selectively passing along events etc.



    .. method:: mouse_event(size, event, button, col, row, focus)

       .. note::

          This method is not implemented in :class:`.Widget` but
          may be implemented by a subclass.  Not implementing this
          method is equivalent to having a method that always returns
          ``False``.

       :param size: See :meth:`Widget.render` for details.
       :type size: widget size
       :param event: Values such as ``'mouse press'``, ``'ctrl mouse press'``,
                     ``'mouse release'``, ``'meta mouse release'``,
                     ``'mouse drag'``; see :ref:`mouse-input`
       :type event: mouse event
       :param button: 1 through 5 for press events, often 0 for release events
                      (which button was released is often not known)
       :type button: int
       :param col: Column of the event, 0 is the left edge of this widget
       :type col: int
{'fraction_non_alphanumeric': 0.08026152180016846, 'fraction_numerical': 0.0034495206770687094, 'mean_word_length': 2.524954050615015, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7081541', 'n_tokens_mistral': 7064, 'n_tokens_neox': 6798, 'n_words': 2774}