<commit_before>"""Object specification for creating messages in MCL.

.. codeauthor:: <NAME> <<EMAIL>>
.. codeauthor:: <NAME> <<EMAIL>>
.. sectionauthor:: <NAME> <<EMAIL>>

"""
import json
import msgpack
import datetime
from sets import Set


# Globally track Message() definitions. The meta-class _RegisterMeta() inserts
# Message() definitions into _MESSAGES when Message() objects are subclassed.
_MESSAGES = list()


class _RegisterMeta(type):
    """Meta-class for globally registering Message() objects.

    :py:class:`._RegisterMeta` is a simple meta-class that maintains a global
    register of :py:class:`.Message` sub-classes. :py:class:`.Message`
    subclasses are added to the register when they are defined. During this
    process :py:class:`._RegisterMeta` also checks to see if a
    :py:class:`.Message` object with the same name has already been defined.

    Note that the list of :py:class:`.Message` sub-classes can be acquired by
    calling::

        messages = Message.__subclasses__()

    The reason the :py:class:`._RegisterMeta` is preferred is that it can
    provide error checking at the time of definition. Note that subclasses
    cannot easily be removed from the list returned by
    ``Message.__subclasses__()``. By using this meta-class,
    :py:class:`.Message` objects can be removed from the global register via
    other methods (see :py:func:`.remove_message_object`).

    """

    def __init__(cls, name, bases, clsdict):

        # Do not allow Message() objects with the name Message() to be added.
        if name == 'Message' and len(_MESSAGES) > 0:
            msg = 'Cannot redefine the base Message() object.'
            raise Exception(msg)

        # Add new Message() definitions.
        elif name != 'Message':

            # Check that a message with the same name does not exist.
            if name in [message.__name__ for message in _MESSAGES]:
                msg = "A Message() with the name '%s' already exists."
                raise Exception(msg % name)

            # Store message definition.
            _MESSAGES.append(cls)

        super(_RegisterMeta, cls).__init__(name, bases, clsdict)


class Message(dict):
    """Base class based on dict that is used for message passing.
    Has a set of mandatory fields that must be present.
    Additional fields will be serialised if present, but are not
    required."""

    __metaclass__ = _RegisterMeta

    def __init__(self, mandatory_items, *args, **kwargs):

        self.__mandatory_items = mandatory_items

        # If no inputs were passed into the constructor, initialise the object
        # with empty fields.
        if not args and not kwargs:
            empty = [None] * len(self.__mandatory_items)
            kwargs = dict(zip(self.__mandatory_items, empty))

        # Initialise message object with items.<commit_msg>message: _RegisterMeta() more documentation added<commit_after>"""Object specification for creating messages in MCL.

.. codeauthor:: <NAME> <<EMAIL>>
.. codeauthor:: <NAME> <<EMAIL>>
.. sectionauthor:: <NAME> <<EMAIL>>

"""
import json
import msgpack
import datetime
from sets import Set


# Globally track Message() definitions. The meta-class _RegisterMeta() inserts
# Message() definitions into _MESSAGES when Message() objects are subclassed.
_MESSAGES = list()


class _RegisterMeta(type):
    """Meta-class for globally registering Message() objects.

    :py:class:`._RegisterMeta` is a simple meta-class that maintains a global
    register of :py:class:`.Message` sub-classes. :py:class:`.Message`
    subclasses are added to the register when they are defined. During this
    process :py:class:`._RegisterMeta` also checks to see if a
    :py:class:`.Message` object with the same name has already been defined.

    Note that the list of :py:class:`.Message` sub-classes can be acquired by
    calling::

        messages = Message.__subclasses__()

    The reason the :py:class:`._RegisterMeta` is preferred is that it can
    provide error checking at the time of definition. Note that subclasses
    cannot easily be removed from the list returned by
    ``Message.__subclasses__()``. By using this meta-class,
    :py:class:`.Message` objects can be removed from the global register via
    other methods (see :py:func:`.remove_message_object`).

    Args:
      cls (class): is the class being instantiated.
      name (string): is the name of the new class.
      bases (tuple): base classes of the new class.
      dct (dict): dictionary mapping the class attribute names to objects.

    """

    def __init__(cls, name, bases, dct):

        # Do not allow Message() objects with the name Message() to be added.
        if name == 'Message' and len(_MESSAGES) > 0:
            msg = 'Cannot redefine the base Message() object.'
            raise Exception(msg)

        # Add new Message() definitions.
        elif name != 'Message':

            # Check that a message with the same name does not exist.
            if name in [message.__name__ for message in _MESSAGES]:
                msg = "A Message() with the name '%s' already exists."
                raise Exception(msg % name)

            # Store message definition.
            _MESSAGES.append(cls)

        super(_RegisterMeta, cls).__init__(name, bases, dct)


class Message(dict):
    """Base class based on dict that is used for message passing.
    Has a set of mandatory fields that must be present.
    Additional fields will be serialised if present, but are not
    required."""

    __metaclass__ = _RegisterMeta

    def __init__(self, mandatory_items, *args, **kwargs):

        self.__mandatory_items = mandatory_items

        # If no inputs were passed into the constructor, initialise the object
        # with empty fields.
        if not args and not kwargs:
            empty = [None] * len(self.__mandatory_items)
            kwargs = dict(zip(self.__mandatory_items, empty))

        # Initialise message object with items.
{'fraction_non_alphanumeric': 0.0911062906724512, 'fraction_numerical': 0.0003337226764558652, 'mean_word_length': 2.9827242524916944, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 23, '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': '1323403', 'n_tokens_mistral': 1598, 'n_tokens_neox': 1536, 'n_words': 666}