<commit_before>from angr.errors import AngrNoPluginError

import logging
l = logging.getLogger(name=__name__)


class PluginHub(object):
    """
    A plugin hub is an object which contains many plugins, as well as the notion of a "preset", or a
    backer that can provide default implementations of plugins which cater to a certain
    circumstance.

    Objects in angr like the SimState, the Analyses hub, the SimEngine selector, etc all use this
    model to unify their mechanisms for automatically collecting and selecting components to use. If
    you're familiar with design patterns this is a configurable Strategy Pattern.

    Each PluginHub subclass should have a corresponding Plugin subclass, and perhaps a PluginPreset
    subclass if it wants its presets to be able to specify anything more interesting than a list of
    defaults.
    """

    def __init__(self):
        super(PluginHub, self).__init__()
        self._active_plugins = {}
        self._active_preset = None
        self._provided_by_preset = []

    #
    #   Class methods for registration
    #

    _presets = None # not a dict so different subclasses don't share instances

    @classmethod
    def register_default(cls, name, plugin_cls, preset='default'):
        if cls._presets is None or preset not in cls._presets:
            l.error("Preset %s does not exist yet...", preset)
            return
        cls._presets[preset].add_default_plugin(name, plugin_cls)

    @classmethod
    def register_preset(cls, name, preset):
        """
        Register a preset instance with the class of the hub it corresponds to. This allows individual plugin objects to
        automatically register themselves with a preset by using a classmethod of their own with only the name of the
        preset to register with.
        """
        if cls._presets is None:
            cls._presets = {}
        cls._presets[name] = preset

    #
    #   Python magic methods
    #

    def __getstate__(self):
        return self._active_plugins, self._active_preset, self._provided_by_preset

    def __setstate__(self, s):
        plugins, preset, provided = s
        self._active_preset = preset
        self._active_plugins = {}
        self._provided_by_preset = provided

        for name, plugin in plugins.items():
            if name not in self._active_plugins:
                self.register_plugin(name, plugin)

    def __getattr__(self, name):
        try:
            return self.get_plugin(name)
        except AngrNoPluginError:
            raise AttributeError(name)

    def __dir__(self):
        out = set(self.__dict__)
        out.update(self._active_plugins)
        if self.has_plugin_preset:
            out.update(self._active_preset.list_default_plugins())

        q = [type(self)]
        while q:
            cls = q.pop(0)
            out.update(cls.__dict__)
            for base in cls.__bases__:
                if base is not object:
                    q.append(base)

        return sorted(out)

    #
    #   Methods for managing the current plugin preset
    #

    @property
    def plugin_preset(self):
        """
        Get the current active plugin preset
        """
        return self._active_preset

    @property
    def has_plugin_preset(self):
        """
        Check whether or not there is a plugin preset in use on this hub right now
        """
        return self._active_preset is not None

    def use_plugin_preset(self, preset):
        """
        Apply a preset to the hub. If there was a previously active preset, discard it.

        Preset can be either the string name of a preset or a PluginPreset instance.
        """
        if isinstance(preset, str):
            try:
                preset = self._presets[preset]
            except (AttributeError, KeyError):
                raise AngrNoPluginError("There is no preset named %s" % preset)

        elif not isinstance(preset, PluginPreset):
            raise ValueError("Argument must be an instance of PluginPreset: %s" % preset)

        if self._active_preset:
            l.warning("Overriding active preset %s with %s", self._active_preset, preset)
            self.discard_plugin_preset()

        preset.activate(self)
        self._active_preset = preset

    def discard_plugin_preset(self):
        """
        Discard the current active preset. Will release any active plugins that could have come from the old preset.
        """
        if self.has_plugin_preset:
            for name, plugin in self._active_plugins.items():
                if id(plugin) in self._provided_by_preset:
                    self.release_plugin(name)
            self._active_preset.deactivate(self)
        self._active_preset = None

    #
    #   Methods for managing the current active plugins
    #

    def get_plugin(self, name):
        """
        Get the plugin named ``name``. If no such plugin is currently active, try to activate a new
        one using the current preset.
        """
        if name in self._active_plugins:
            return self._active_plugins[name]

        elif self.has_plugin_preset:
            plugin_cls = self._active_preset.request_plugin(name)
            plugin = self._init_plugin(plugin_cls)<commit_msg>Fix a dictionary modification error in discard_plugin_preset. (#1468)<commit_after>from angr.errors import AngrNoPluginError

import logging
l = logging.getLogger(name=__name__)


class PluginHub(object):
    """
    A plugin hub is an object which contains many plugins, as well as the notion of a "preset", or a
    backer that can provide default implementations of plugins which cater to a certain
    circumstance.

    Objects in angr like the SimState, the Analyses hub, the SimEngine selector, etc all use this
    model to unify their mechanisms for automatically collecting and selecting components to use. If
    you're familiar with design patterns this is a configurable Strategy Pattern.

    Each PluginHub subclass should have a corresponding Plugin subclass, and perhaps a PluginPreset
    subclass if it wants its presets to be able to specify anything more interesting than a list of
    defaults.
    """

    def __init__(self):
        super(PluginHub, self).__init__()
        self._active_plugins = {}
        self._active_preset = None
        self._provided_by_preset = []

    #
    #   Class methods for registration
    #

    _presets = None # not a dict so different subclasses don't share instances

    @classmethod
    def register_default(cls, name, plugin_cls, preset='default'):
        if cls._presets is None or preset not in cls._presets:
            l.error("Preset %s does not exist yet...", preset)
            return
        cls._presets[preset].add_default_plugin(name, plugin_cls)

    @classmethod
    def register_preset(cls, name, preset):
        """
        Register a preset instance with the class of the hub it corresponds to. This allows individual plugin objects to
        automatically register themselves with a preset by using a classmethod of their own with only the name of the
        preset to register with.
        """
        if cls._presets is None:
            cls._presets = {}
        cls._presets[name] = preset

    #
    #   Python magic methods
    #

    def __getstate__(self):
        return self._active_plugins, self._active_preset, self._provided_by_preset

    def __setstate__(self, s):
        plugins, preset, provided = s
        self._active_preset = preset
        self._active_plugins = {}
        self._provided_by_preset = provided

        for name, plugin in plugins.items():
            if name not in self._active_plugins:
                self.register_plugin(name, plugin)

    def __getattr__(self, name):
        try:
            return self.get_plugin(name)
        except AngrNoPluginError:
            raise AttributeError(name)

    def __dir__(self):
        out = set(self.__dict__)
        out.update(self._active_plugins)
        if self.has_plugin_preset:
            out.update(self._active_preset.list_default_plugins())

        q = [type(self)]
        while q:
            cls = q.pop(0)
            out.update(cls.__dict__)
            for base in cls.__bases__:
                if base is not object:
                    q.append(base)

        return sorted(out)

    #
    #   Methods for managing the current plugin preset
    #

    @property
    def plugin_preset(self):
        """
        Get the current active plugin preset
        """
        return self._active_preset

    @property
    def has_plugin_preset(self):
        """
        Check whether or not there is a plugin preset in use on this hub right now
        """
        return self._active_preset is not None

    def use_plugin_preset(self, preset):
        """
        Apply a preset to the hub. If there was a previously active preset, discard it.

        Preset can be either the string name of a preset or a PluginPreset instance.
        """
        if isinstance(preset, str):
            try:
                preset = self._presets[preset]
            except (AttributeError, KeyError):
                raise AngrNoPluginError("There is no preset named %s" % preset)

        elif not isinstance(preset, PluginPreset):
            raise ValueError("Argument must be an instance of PluginPreset: %s" % preset)

        if self._active_preset:
            l.warning("Overriding active preset %s with %s", self._active_preset, preset)
            self.discard_plugin_preset()

        preset.activate(self)
        self._active_preset = preset

    def discard_plugin_preset(self):
        """
        Discard the current active preset. Will release any active plugins that could have come from the old preset.
        """
        if self.has_plugin_preset:
            for name, plugin in list(self._active_plugins.items()):
                if id(plugin) in self._provided_by_preset:
                    self.release_plugin(name)
            self._active_preset.deactivate(self)
        self._active_preset = None

    #
    #   Methods for managing the current active plugins
    #

    def get_plugin(self, name):
        """
        Get the plugin named ``name``. If no such plugin is currently active, try to activate a new
        one using the current preset.
        """
        if name in self._active_plugins:
            return self._active_plugins[name]

        elif self.has_plugin_preset:
            plugin_cls = self._active_preset.request_plugin(name)
            plugin = self._init_plugin(plugin_cls)
{'fraction_non_alphanumeric': 0.0681560015145778, 'fraction_numerical': 0.0005679666792881485, 'mean_word_length': 2.269885484370164, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, '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': '3176702', 'n_tokens_mistral': 2902, 'n_tokens_neox': 2789, 'n_words': 980}