<commit_before># SPDX-License-Identifier: Apache-2.0
#
# Copyright (C) 2021, ARM Limited and contributors.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

"""
Fuzzing API to build random constrained values.

.. note:: The following example shows a direct use of the :class:`Gen` monad,
    but be aware that :mod:`lisa.wlgen.rta` API allows mixing both :class:`Gen`
    and RTA DSL into the same coroutine function.

**Example**::

    import operator
    import functools

    from lisa.platforms.platinfo import PlatformInfo
    from lisa.wlgen.rta import RTAPhase, RTAConf, PeriodicWload
    from lisa.fuzz import GenMonad, Choice, Int, Float, retry_until

    # The function must be decorated with GenMonad.do() so that "await" gains its
    # special meaning.
    @GenMonad.do
    async def make_task(duration=None):
        # Draw a value from an iterable.
        period = await Choice([16e-3, 8e-3])
        nr = await Choice(range(1, 4))
        duration = duration or (await Float(1, 2))

        # Arbitrary properties can be enforced. If they are not satisfied, the
        # function will run again until the condition is true.
        await retry_until(0 < nr <= 2)

        phase = functools.reduce(
            operator.add,
            [
                RTAPhase(
                    prop_wload=PeriodicWload(
                        duty_cycle_pct=await Choice(range(100)),
                        period=period,
                        duration=duration,
                    ),
                )
                for i in range(nr)
            ]
        )

        return phase

    @GenMonad.do
    async def make_profile(plat_info, **kwargs):
        nr_tasks = await Int(1, plat_info['cpus-count'])

        profile = {}
        for i in range(nr_tasks):
            profile[f'task{i}'] = await make_task(**kwargs)
        return profile


    def main():
        plat_info = PlatformInfo.from_yaml_map('./doc/traces/plat_info.yml')

        # Display a few randomly generated tasks
        for _ in range(2):
            # When called, profile_gen() will create a random profiles
            profile_gen = make_profile(plat_info, duration=1)

            # seed (or rng) can be fixed for reproducible results
            # profile = profile_gen(seed=1)
            profile = profile_gen(seed=None)

            conf = RTAConf.from_profile(profile, plat_info=plat_info)
            print(conf.json)

    main()
"""

import random
import functools
import itertools
import inspect
import logging
from operator import attrgetter, itemgetter
from collections.abc import Iterable, Mapping

from lisa.monad import StateDiscard
from lisa.utils import Loggable, deprecate


class RetryException(Exception):
    """
    Exception raised to signify to :class:`lisa.fuzz.Gen` to retry the random
    draw.

    .. seealso:: :func:`lisa.fuzz.retry_until`
    """
    pass


class _Retrier:
    def __init__(self, cond):
        self.cond = cond

    def __await__(self):
        if self.cond:<commit_msg>lisa.fuzz: Rewrite docstring example<commit_after># SPDX-License-Identifier: Apache-2.0
#
# Copyright (C) 2021, ARM Limited and contributors.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

"""
Fuzzing API to build random constrained values.

.. note:: The following example shows a direct use of the :class:`Gen` monad,
    but be aware that :mod:`lisa.wlgen.rta` API allows mixing both :class:`Gen`
    and RTA DSL into the same coroutine function using
    :func:`lisa.wlgen.rta.task_factory`.

**Example**::

    from lisa.platforms.platinfo import PlatformInfo
    from lisa.fuzz import GenMonad, Choice, Int, Float, retry_until

    # The function must be decorated with GenMonad.do() so that "await" gains
    # its special meaning.
    @GenMonad.do
    async def make_data(duration=None):
        # Draw a value from an iterable.
        period = await Choice([16e-3, 8e-3])
        nr = await Choice(range(1, 4))
        duration = duration or (await Float(1, 2))

        # Arbitrary properties can be enforced. If they are not satisfied, the
        # function will run again until the condition is true.
        await retry_until(0 < nr <= 2)

        return (nr, duration, period)

    # seed (or rng) can be fixed for reproducible results
    data = make_data(duration=42)(seed=1)
    print(data)

"""

import random
import functools
import itertools
import inspect
import logging
from operator import attrgetter, itemgetter
from collections.abc import Iterable, Mapping

from lisa.monad import StateDiscard
from lisa.utils import Loggable, deprecate


class RetryException(Exception):
    """
    Exception raised to signify to :class:`lisa.fuzz.Gen` to retry the random
    draw.

    .. seealso:: :func:`lisa.fuzz.retry_until`
    """
    pass


class _Retrier:
    def __init__(self, cond):
        self.cond = cond

    def __await__(self):
        if self.cond:
{'fraction_non_alphanumeric': 0.08542798913043478, 'fraction_numerical': 0.008831521739130434, 'mean_word_length': 2.794458762886598, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, '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': '1717915', 'n_tokens_mistral': 1730, 'n_tokens_neox': 1668, 'n_words': 618}