<commit_before>"""
Tests for L{eliot._parse}.
"""

from __future__ import unicode_literals

from unittest import TestCase
from itertools import chain

from six import text_type as unicode, assertCountEqual
from six.moves import zip_longest

from hypothesis import strategies as st, given, assume

from pyrsistent import PClass, field, pvector_field

from .. import start_action, Message
from ..testing import MemoryLogger
from .._parse import Task, Parser
from .._message import (
    WrittenMessage, MESSAGE_TYPE_FIELD, TASK_LEVEL_FIELD, TASK_UUID_FIELD,
)
from .._action import FAILED_STATUS, ACTION_STATUS_FIELD, WrittenAction
from .strategies import labels


class ActionStructure(PClass):
    """
    A tree structure used to generate/compare to Eliot trees.

    Individual messages are encoded as a unicode string; actions are
    encoded as a L{ActionStructure} instance.
    """
    type = field(type=(unicode, None.__class__))
    children = pvector_field(object)  # XXX ("StubAction", unicode))
    failed = field(type=bool)

    @classmethod
    def from_written(cls, written):
        """
        Create an L{ActionStructure} or L{unicode} from a L{WrittenAction} or
        L{WrittenMessage}.
        """
        if isinstance(written, WrittenMessage):
            return written.as_dict()[MESSAGE_TYPE_FIELD]
        else:  # WrittenAction
            if not written.end_message:
                raise AssertionError("Missing end message.")
            return cls(
                type=written.action_type,
                failed=(written.end_message.contents[ACTION_STATUS_FIELD] ==
                        FAILED_STATUS),
                children=[cls.from_written(o) for o in written.children])

    @classmethod
    def to_eliot(cls, structure_or_message, logger):
        """
        Given a L{ActionStructure} or L{unicode}, generate appropriate
        structured Eliot log mesages to given L{MemoryLogger}.
        """
        if isinstance(structure_or_message, cls):
            action = structure_or_message
            try:
                with start_action(logger, action_type=action.type):
                    for child in action.children:
                        cls.to_eliot(child, logger)
                    if structure_or_message.failed:
                        raise RuntimeError("Make the eliot action fail.")
            except RuntimeError:
                pass
        else:
            Message.new(message_type=structure_or_message).write(logger)
        return logger.messages


@st.composite
def action_structures(draw):
    """
    A Hypothesis strategy that creates a tree of L{ActionStructure} and
    L{unicode}.
    """
    tree = draw(st.recursive(labels, st.lists, max_leaves=50))

    def to_structure(tree_or_message):
        if isinstance(tree_or_message, list):<commit_msg>Shrink size of trees.<commit_after>"""
Tests for L{eliot._parse}.
"""

from __future__ import unicode_literals

from unittest import TestCase
from itertools import chain

from six import text_type as unicode, assertCountEqual
from six.moves import zip_longest

from hypothesis import strategies as st, given, assume

from pyrsistent import PClass, field, pvector_field

from .. import start_action, Message
from ..testing import MemoryLogger
from .._parse import Task, Parser
from .._message import (
    WrittenMessage, MESSAGE_TYPE_FIELD, TASK_LEVEL_FIELD, TASK_UUID_FIELD,
)
from .._action import FAILED_STATUS, ACTION_STATUS_FIELD, WrittenAction
from .strategies import labels


class ActionStructure(PClass):
    """
    A tree structure used to generate/compare to Eliot trees.

    Individual messages are encoded as a unicode string; actions are
    encoded as a L{ActionStructure} instance.
    """
    type = field(type=(unicode, None.__class__))
    children = pvector_field(object)  # XXX ("StubAction", unicode))
    failed = field(type=bool)

    @classmethod
    def from_written(cls, written):
        """
        Create an L{ActionStructure} or L{unicode} from a L{WrittenAction} or
        L{WrittenMessage}.
        """
        if isinstance(written, WrittenMessage):
            return written.as_dict()[MESSAGE_TYPE_FIELD]
        else:  # WrittenAction
            if not written.end_message:
                raise AssertionError("Missing end message.")
            return cls(
                type=written.action_type,
                failed=(written.end_message.contents[ACTION_STATUS_FIELD] ==
                        FAILED_STATUS),
                children=[cls.from_written(o) for o in written.children])

    @classmethod
    def to_eliot(cls, structure_or_message, logger):
        """
        Given a L{ActionStructure} or L{unicode}, generate appropriate
        structured Eliot log mesages to given L{MemoryLogger}.
        """
        if isinstance(structure_or_message, cls):
            action = structure_or_message
            try:
                with start_action(logger, action_type=action.type):
                    for child in action.children:
                        cls.to_eliot(child, logger)
                    if structure_or_message.failed:
                        raise RuntimeError("Make the eliot action fail.")
            except RuntimeError:
                pass
        else:
            Message.new(message_type=structure_or_message).write(logger)
        return logger.messages


@st.composite
def action_structures(draw):
    """
    A Hypothesis strategy that creates a tree of L{ActionStructure} and
    L{unicode}.
    """
    tree = draw(st.recursive(labels, st.lists, max_leaves=20))

    def to_structure(tree_or_message):
        if isinstance(tree_or_message, list):
{'fraction_non_alphanumeric': 0.07962570621468927, 'fraction_numerical': 0.0007062146892655367, 'mean_word_length': 2.657198192382182, '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': '5664039', 'n_tokens_mistral': 1552, 'n_tokens_neox': 1485, 'n_words': 436}