<commit_before>import string
import time
import os
try:
    from IPython.core.magic import Magics, magics_class, cell_magic, line_magic, line_cell_magic
    from IPython.core.pylabtools import print_figure
except:
    from unittest import SkipTest
    raise SkipTest("IPython extension requires IPython >= 0.13")

from ..core import OrderedDict
from ..core.options import OptionTree, Options, OptionError, Store, save_options

from IPython.display import display, HTML

from ..operation import Compositor

#========#
# Magics #
#========#


try:
    import pyparsing
except ImportError:
    pyparsing = None
else:
    from holoviews.ipython.parser import CompositorSpec
    from holoviews.ipython.parser import OptsSpec


# Set to True to automatically run notebooks.
STORE_HISTORY = False


# ANSI color codes for the IPython pager
red   = '\x1b[1;31m%s\x1b[0m'
blue  = '\x1b[1;34m%s\x1b[0m'
green = '\x1b[1;32m%s\x1b[0m'
cyan = '\x1b[1;36m%s\x1b[0m'

# Corresponding HTML color codes
html_red = '#980f00'
html_blue = '#00008e'



class OptionsMagic(Magics):
    """
    Base class for magics that are used to specified collections of
    keyword options.
    """
    # Dictionary from keywords to allowed bounds/values
    allowed = {'charwidth'   : (0, float('inf'))}
    defaults = OrderedDict([('charwidth'   , 80)])  # Default keyword values.
    options =  OrderedDict(defaults.items()) # Current options


    @classmethod
    def get_options(cls, line, options):
        "Given a keyword specification line, validated and compute options"
        items = cls._extract_keywords(line, OrderedDict())
        for keyword in cls.defaults:
            if keyword in items:
                value = items[keyword]
                allowed = cls.allowed[keyword]
                if isinstance(allowed, set):  pass
                elif isinstance(allowed, list) and value not in allowed:
                    raise ValueError("Value %r for key %r not one of %s"
                                     % (value, keyword, allowed))
                elif isinstance(allowed, tuple):
                    if not (allowed[0] <= value <= allowed[1]):
                        info = (keyword,value)+allowed
                        raise ValueError("Value %r for key %r not between %s and %s" % info)
                options[keyword] = value
            else:
                options[keyword] = cls.defaults[keyword]
        return cls._validate(options)

    @classmethod
    def _validate(cls, options):
        "Allows subclasses to check options are valid."
        raise NotImplementedError("OptionsMagic is an abstract base class.")

    @classmethod
    def option_completer(cls, k,v):
        raw_line = v.text_until_cursor
        line = raw_line.replace('%output','')

        # Find the last element class mentioned
        completion_key = None
        tokens = [t for els in reversed(line.split('=')) for t in els.split()]

        for token in tokens:
            if token.strip() in cls.allowed:
                completion_key = token.strip()
                break
        values = [repr(el) for el in cls.allowed.get(completion_key, [])
                  if not isinstance(el, tuple)]

        return values + [el+'=' for el in cls.allowed.keys()]

    @classmethod
    def pprint(cls):
        """
        Pretty print the current view options with a maximum width of
        cls.pprint_width.
        """
        elements = ["%output"]
        lines, current, count = [], '', 0
        for k,v in cls.options.items():
            keyword = '%s=%r' % (k,v)
            if len(current) + len(keyword) > cls.options['charwidth']:
                print(('%output' if count==0 else '      ')  + current)
                count += 1
                current = keyword
            else:
                current += ' '+ keyword
        else:
            print(('%output' if count==0 else '      ')  + current)


    @classmethod
    def _extract_keywords(cls, line, items):
        """
        Given the keyword string, parse a dictionary of options.
        """
        unprocessed = list(reversed(line.split('=')))
        while unprocessed:
            chunk = unprocessed.pop()
            key = None
            if chunk.strip() in cls.allowed:
                key = chunk.strip()
            else:
                raise SyntaxError("Invalid keyword: %s" % chunk.strip())
            # The next chunk may end in a subsequent keyword
            value = unprocessed.pop().strip()
            if len(unprocessed) != 0:
                # Check if a new keyword has begun
                for option in cls.allowed:
                    if value.endswith(option):
                        value = value[:-len(option)].strip()
                        unprocessed.append(option)
                        break
                else:
                    raise SyntaxError("Invalid keyword: %s" % value.split()[-1])
            keyword = '%s=%s' % (key, value)
            try:
                items.update(eval('dict(%s)' % keyword))
            except:
                raise SyntaxError("Could not evaluate keyword: %s" % keyword)
        return items



@magics_class
class SaveOptsMagic(OptionsMagic):
    """
    Implements the %saveopts magic for automatically saving HoloViews
    output from notebooks.
    """
    save_options_dflts = [(k,v) for (k,v)
                          in save_options.get_param_values()
                          if k not in ['name', 'time']]

    allowed = dict({k:{v} for k,v in save_options_dflts},
                   **{'auto'     : [True, False],
                      'charwidth'   :  (0, float('inf'))})

    defaults = OrderedDict(save_options_dflts
                           + [('auto' , True),
                              ('charwidth'   , 80)])

    options =  OrderedDict(defaults.items()) # Current options

    def __init__(self, *args, **kwargs):
        super(SaveOptsMagic, self).__init__(*args, **kwargs)

    @classmethod
    def _validate(cls, options):
        formatter = options['formatter']
        save_options.validate_fields(save_options.parse_fields(formatter), 'filename')
        directory = options['directory']
        save_options.validate_fields(save_options.parse_fields(directory), 'directory')
        return options

    @classmethod
    def option_completer(cls, k,v):
        raw_line = v.text_until_cursor
        line = raw_line.replace('%output','')

        # Find the last element class mentioned
        completion_key = None
        tokens = [t for els in reversed(line.split('=')) for t in els.split()]

        for token in tokens:
            if token.strip() in cls.allowed:<commit_msg>Added refresh_defaults to update %saveopts when SaveOptions modified<commit_after>import string
import time
import os
try:
    from IPython.core.magic import Magics, magics_class, cell_magic, line_magic, line_cell_magic
    from IPython.core.pylabtools import print_figure
except:
    from unittest import SkipTest
    raise SkipTest("IPython extension requires IPython >= 0.13")

from ..core import OrderedDict
from ..core.options import OptionTree, Options, OptionError, Store, SaveOptions, save_options

from IPython.display import display, HTML

from ..operation import Compositor

#========#
# Magics #
#========#


try:
    import pyparsing
except ImportError:
    pyparsing = None
else:
    from holoviews.ipython.parser import CompositorSpec
    from holoviews.ipython.parser import OptsSpec


# Set to True to automatically run notebooks.
STORE_HISTORY = False


# ANSI color codes for the IPython pager
red   = '\x1b[1;31m%s\x1b[0m'
blue  = '\x1b[1;34m%s\x1b[0m'
green = '\x1b[1;32m%s\x1b[0m'
cyan = '\x1b[1;36m%s\x1b[0m'

# Corresponding HTML color codes
html_red = '#980f00'
html_blue = '#00008e'



class OptionsMagic(Magics):
    """
    Base class for magics that are used to specified collections of
    keyword options.
    """
    # Dictionary from keywords to allowed bounds/values
    allowed = {'charwidth'   : (0, float('inf'))}
    defaults = OrderedDict([('charwidth'   , 80)])  # Default keyword values.
    options =  OrderedDict(defaults.items()) # Current options


    @classmethod
    def get_options(cls, line, options):
        "Given a keyword specification line, validated and compute options"
        items = cls._extract_keywords(line, OrderedDict())
        for keyword in cls.defaults:
            if keyword in items:
                value = items[keyword]
                allowed = cls.allowed[keyword]
                if isinstance(allowed, set):  pass
                elif isinstance(allowed, list) and value not in allowed:
                    raise ValueError("Value %r for key %r not one of %s"
                                     % (value, keyword, allowed))
                elif isinstance(allowed, tuple):
                    if not (allowed[0] <= value <= allowed[1]):
                        info = (keyword,value)+allowed
                        raise ValueError("Value %r for key %r not between %s and %s" % info)
                options[keyword] = value
            else:
                options[keyword] = cls.defaults[keyword]
        return cls._validate(options)

    @classmethod
    def _validate(cls, options):
        "Allows subclasses to check options are valid."
        raise NotImplementedError("OptionsMagic is an abstract base class.")

    @classmethod
    def option_completer(cls, k,v):
        raw_line = v.text_until_cursor
        line = raw_line.replace('%output','')

        # Find the last element class mentioned
        completion_key = None
        tokens = [t for els in reversed(line.split('=')) for t in els.split()]

        for token in tokens:
            if token.strip() in cls.allowed:
                completion_key = token.strip()
                break
        values = [repr(el) for el in cls.allowed.get(completion_key, [])
                  if not isinstance(el, tuple)]

        return values + [el+'=' for el in cls.allowed.keys()]

    @classmethod
    def pprint(cls):
        """
        Pretty print the current view options with a maximum width of
        cls.pprint_width.
        """
        elements = ["%output"]
        lines, current, count = [], '', 0
        for k,v in cls.options.items():
            keyword = '%s=%r' % (k,v)
            if len(current) + len(keyword) > cls.options['charwidth']:
                print(('%output' if count==0 else '      ')  + current)
                count += 1
                current = keyword
            else:
                current += ' '+ keyword
        else:
            print(('%output' if count==0 else '      ')  + current)


    @classmethod
    def _extract_keywords(cls, line, items):
        """
        Given the keyword string, parse a dictionary of options.
        """
        unprocessed = list(reversed(line.split('=')))
        while unprocessed:
            chunk = unprocessed.pop()
            key = None
            if chunk.strip() in cls.allowed:
                key = chunk.strip()
            else:
                raise SyntaxError("Invalid keyword: %s" % chunk.strip())
            # The next chunk may end in a subsequent keyword
            value = unprocessed.pop().strip()
            if len(unprocessed) != 0:
                # Check if a new keyword has begun
                for option in cls.allowed:
                    if value.endswith(option):
                        value = value[:-len(option)].strip()
                        unprocessed.append(option)
                        break
                else:
                    raise SyntaxError("Invalid keyword: %s" % value.split()[-1])
            keyword = '%s=%s' % (key, value)
            try:
                items.update(eval('dict(%s)' % keyword))
            except:
                raise SyntaxError("Could not evaluate keyword: %s" % keyword)
        return items



@magics_class
class SaveOptsMagic(OptionsMagic):
    """
    Implements the %saveopts magic for automatically saving HoloViews
    output from notebooks.
    """


    def __init__(self, *args, **kwargs):
        super(SaveOptsMagic, self).__init__(*args, **kwargs)
        self.refresh_defaults()

    @classmethod
    def refresh_defaults(cls):
        """
        Sets the defaults and tab auto-completion based on the
        parameter defaults of the SaveOptions class.

        In the class parameter defaults of SaveOptions are customize,
        this method needs to be called in order to update the
        tab-completion behaviour appropriately.
        """
        dflts = [(k,p.default) for (k,p) in SaveOptions.params().items()
                 if k not in ['name', 'time']]
        cls.allowed = dict({k:{v} for k,v in dflts},
                           **{'auto'     : [True, False],
                              'charwidth'   :  (0, float('inf'))})
        cls.defaults = OrderedDict(dflts
                               + [('auto' , True),
                                  ('charwidth'   , 80)])
        cls.options =  OrderedDict(cls.defaults.items())


    @classmethod
    def _validate(cls, options):
        formatter = options['formatter']
        save_options.validate_fields(save_options.parse_fields(formatter), 'filename')
        directory = options['directory']
        save_options.validate_fields(save_options.parse_fields(directory), 'directory')
        return options

    @classmethod
    def option_completer(cls, k,v):
        raw_line = v.text_until_cursor
        line = raw_line.replace('%output','')

        # Find the last element class mentioned
        completion_key = None
        tokens = [t for els in reversed(line.split('=')) for t in els.split()]

        for token in tokens:
            if token.strip() in cls.allowed:
{'fraction_non_alphanumeric': 0.1067742404419247, 'fraction_numerical': 0.007413868294810292, 'mean_word_length': 2.031284423881912, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1524352', 'n_tokens_mistral': 3931, 'n_tokens_neox': 3754, 'n_words': 1109}