# Path: matchpy/utils.py
# T = TypeVar('T')
# def fixed_integer_vector_iter(max_vector: Tuple[int, ...], vector_sum: int) -> Iterator[Tuple[int, ...]]:
# def weak_composition_iter(n: int, num_parts: int) -> Iterator[Tuple[int, ...]]:
# def optional_iter(remaining, count):
# def _make_variable_generator_factory(value, total, variables: List[VariableWithCount]):
#     def _factory(subst):
# def _commutative_single_variable_partiton_iter(values: 'Multiset[T]',
#                                                variable: VariableWithCount) -> Iterator[Dict[str, 'Multiset[T]']]:
# def commutative_sequence_variable_partition_iter(values: Multiset, variables: List[VariableWithCount]
#                                                 ) -> Iterator[Dict[str, Multiset]]:
#     def __init__(self, lines):
#     def visit(self, node):
#     def visit_Lambda(self, node):
#     def generic_visit(self, node):
# def get_short_lambda_source(lambda_func: LambdaType) -> Optional[str]:
# def extended_euclid(a: int, b: int) -> Tuple[int, int, int]:
# def base_solution_linear(a: int, b: int, c: int) -> Iterator[Tuple[int, int]]:
# def solve_linear_diop(total: int, *coeffs: int) -> Iterator[Tuple[int, ...]]:
# def generator_chain(initial_data: T, *factories: Callable[[T], Iterator[T]]) -> Iterator[T]:
#     def __init__(self, getter, slot=None):
#     def __get__(self, obj, cls):
# def slot_cached_property(slot):
#     def _wrapper(getter):
# class LambdaNodeVisitor(ast.NodeVisitor):
# class cached_property(property):


import itertools
import os
import hypothesis.strategies as st
import pytest
from hypothesis import assume, example, given, settings
from multiset import Multiset
from matchpy.utils import (
    VariableWithCount, base_solution_linear, cached_property, commutative_sequence_variable_partition_iter,
    extended_euclid, fixed_integer_vector_iter, get_short_lambda_source, weak_composition_iter, slot_cached_property,
    solve_linear_diop
)
# yapf: disable
# =========================================================================
# DON'T CHANGE THE FORMATTING OF THESE LINES, IT IS IMPORTANT FOR THE TESTS
lambda_example = lambda a: a > 0, 0
def not_a_lambda(): pass
lambda_multiline_example = [
    lambda x, y: x == y
]
# =========================================================================
# yapf: enable

@pytest.mark.parametrize(
    '   lambda_func,                                expected_source',
    [
        ((lambda x: x == 1),                        'x == 1'),
        (lambda x: x == 1,                          'x == 1'),
        (lambda_example[0],                         'a > 0'),
        (lambda_multiline_example[0],               'x == y'),
        (lambda x: x[0],                            'x[0]'),
        (lambda x: x == (0, 1),                     'x == (0, 1)'),
        # FORMATTING IS IMPORTANT HERE TOO
        (lambda x: x > 1 and \
                   x < 5,                           'x > 1 and x < 5'),
        ([lambda x: x == 42, 5][0],                 'x == 42'),
        (not_a_lambda,                              None),
        (5,                                         None),
        ([lambda x: x == 3, lambda x: x == 4][0],   'x == 3'),
        ([lambda x: x == 3, lambda x: x == 4][1],   'x == 4'),
    ]
)  # yapf: disable

# Path: matchpy/utils.py
# T = TypeVar('T')
# def fixed_integer_vector_iter(max_vector: Tuple[int, ...], vector_sum: int) -> Iterator[Tuple[int, ...]]:
# def weak_composition_iter(n: int, num_parts: int) -> Iterator[Tuple[int, ...]]:
# def optional_iter(remaining, count):
# def _make_variable_generator_factory(value, total, variables: List[VariableWithCount]):
#     def _factory(subst):
# def _commutative_single_variable_partiton_iter(values: 'Multiset[T]',
#                                                variable: VariableWithCount) -> Iterator[Dict[str, 'Multiset[T]']]:
# def commutative_sequence_variable_partition_iter(values: Multiset, variables: List[VariableWithCount]
#                                                 ) -> Iterator[Dict[str, Multiset]]:
#     def __init__(self, lines):
#     def visit(self, node):
#     def visit_Lambda(self, node):
#     def generic_visit(self, node):
# def get_short_lambda_source(lambda_func: LambdaType) -> Optional[str]:
# def extended_euclid(a: int, b: int) -> Tuple[int, int, int]:
# def base_solution_linear(a: int, b: int, c: int) -> Iterator[Tuple[int, int]]:
# def solve_linear_diop(total: int, *coeffs: int) -> Iterator[Tuple[int, ...]]:
# def generator_chain(initial_data: T, *factories: Callable[[T], Iterator[T]]) -> Iterator[T]:
#     def __init__(self, getter, slot=None):
#     def __get__(self, obj, cls):
# def slot_cached_property(slot):
#     def _wrapper(getter):
# class LambdaNodeVisitor(ast.NodeVisitor):
# class cached_property(property):


# Path: tests/test_utils.py
import itertools
import os
import hypothesis.strategies as st
import pytest
from hypothesis import assume, example, given, settings
from multiset import Multiset
from matchpy.utils import (
    VariableWithCount, base_solution_linear, cached_property, commutative_sequence_variable_partition_iter,
    extended_euclid, fixed_integer_vector_iter, get_short_lambda_source, weak_composition_iter, slot_cached_property,
    solve_linear_diop
)

# yapf: disable
# =========================================================================
# DON'T CHANGE THE FORMATTING OF THESE LINES, IT IS IMPORTANT FOR THE TESTS
lambda_example = lambda a: a > 0, 0
def not_a_lambda(): pass
lambda_multiline_example = [
    lambda x, y: x == y
]
# =========================================================================
# yapf: enable

@pytest.mark.parametrize(
    '   lambda_func,                                expected_source',
    [
        ((lambda x: x == 1),                        'x == 1'),
        (lambda x: x == 1,                          'x == 1'),
        (lambda_example[0],                         'a > 0'),
        (lambda_multiline_example[0],               'x == y'),
        (lambda x: x[0],                            'x[0]'),
        (lambda x: x == (0, 1),                     'x == (0, 1)'),
        # FORMATTING IS IMPORTANT HERE TOO
        (lambda x: x > 1 and \
                   x < 5,                           'x > 1 and x < 5'),
        ([lambda x: x == 42, 5][0],                 'x == 42'),
        (not_a_lambda,                              None),
        (5,                                         None),
        ([lambda x: x == 3, lambda x: x == 4][0],   'x == 3'),
        ([lambda x: x == 3, lambda x: x == 4][1],   'x == 4'),
    ]
)  # yapf: disable

def test_get_short_lambda_source(lambda_func, expected_source):