# Path: tests/util/asserts.py
# def assert_that(obj, matcher):
#     assert_implements(obj, object)
#     assert_implements(matcher, Matcher)
#     if not matcher.matches(obj):
#         raise AssertionError(matcher.description())
# 
# def equals(expected):
#     class EqualsMatcher:
# 
#         def __init__(self, expected):
#             self.expected = expected
# 
#         def matches(self, actual):
#             self.actual = actual
#             return actual == expected
# 
#         def description(self):
#             ret = (
#                 repr(self.actual)
#                 + " does not equal "
#                 + repr(self.expected)
#                 + " as expected."
#             )
#             if len(ret) > 80:
#                 ret = """Values are not equal (actual then expected):
# %s
# %s
# """ % ( repr(self.actual), repr(self.expected))
#             return ret
#     return EqualsMatcher(expected)
# 
# def is_not(expected):
#     class NotEqualsMatcher:
# 
#         def __init__(self, expected):
#             self.expected = expected
# 
#         def matches(self, actual):
#             self.actual = actual
#             return actual != expected
# 
#         def description(self):
#             return (
#                 str(self.actual)
#                 + " equals "
#                 + str(self.expected)
#                 + " but we expected it not to."
#             )
#     return NotEqualsMatcher(expected)
# 
# def fail(msg):
#     raise AssertionError(msg)
# 
# Path: tests/util/test.py
# def test(t):
#     return TestFunctionType(t)
# 
# Path: pycell/valueclass.py
# def valueclass(*members):
#     """
#     A classdecorator that makes a class into a standard value type.
# 
#     This decorator provides an __init__ method that takes in the supplied
#     members and stores them in instance variables.
# 
#     This decorator also provides standard __eq__, __repr__ and __str__
#     functions that use the supplied members
#     """
# 
#     def _wrong_init_args_message(member_name):
#         return (
#             "__init__() missing 1 required positional argument: "
#             + "'{arg}'").format(
#                 arg=member_name
#         )
# 
#     def _too_many_args_message(args):
#         if len(members) == 0:
#             return "object() takes no parameters"
#         else:
#             return (
#                 "__init__() takes "
#                 + "{lenmem} positional arguments but "
#                 + "{lenargs} were given"
#             ).format(
#                 lenmem=len(members) + 1,
#                 lenargs=len(args) + 1
#             )
# 
#     def _multiple_values_message(member_name):
#         return (
#             "__init__() got multiple values for argument '{arg}'").format(
#                 arg=member_name
#         )
# 
#     def value_init(self, *args, **kwargs):
#         for (i, m) in enumerate(members):
#             if i < len(args):
#                 self.__dict__[m] = args[i]
#                 if m in kwargs:
#                     raise TypeError(_multiple_values_message(m))
#             elif m in kwargs:
#                 self.__dict__[m] = kwargs[m]
#             else:
#                 raise TypeError(_wrong_init_args_message(m))
#         if len(args) > len(members):
#             raise TypeError(_too_many_args_message(args))
#         for k in kwargs:
#             if k not in members:
#                 raise TypeError(
#                     (
#                         "__init__() got an unexpected keyword "
#                         + "argument '{k}'"
#                     ).format(k=k)
#                 )
# 
#     def value_eq(self, other):
#         if not isinstance(other, type(self)):
#             return False
#         for m in members:
#             if self.__dict__[m] != other.__dict__[m]:
#                 return False
#         return True
# 
#     def value_repr(self):
#         return "{type}({args})".format(
#             type=type(self).__name__,
#             args=", ".join(repr(self.__dict__[m]) for m in members)
#         )
# 
#     def ret(cl):
#         cl.__init__ = value_init
#         cl.__eq__ = value_eq
#         cl.__repr__ = value_repr
#         return cl
# 
#     return ret


from tests.util.asserts import assert_that, equals, is_not, fail
from tests.util.test import test
from pycell.valueclass import valueclass

@test
def Empty_value_classes_compare_equal_if_same_class():
    @valueclass()
    class MyClass:
        pass

    assert_that(MyClass(), equals(MyClass()))


@test
def Empty_value_classes_compare_not_equal_if_different_class():
    @valueclass()
    class MyClass1:
        pass

    @valueclass()
    class MyClass2:
        pass

    assert_that(MyClass1(), is_not(MyClass2()))


@test
def Can_construct_a_nonempty_value_class_using_positional_args():
    @valueclass("mem1", "mem2")
    class MyClass:
        pass

    b = MyClass(3, 4)

# Path: tests/util/asserts.py
# def assert_that(obj, matcher):
#     assert_implements(obj, object)
#     assert_implements(matcher, Matcher)
#     if not matcher.matches(obj):
#         raise AssertionError(matcher.description())
# 
# def equals(expected):
#     class EqualsMatcher:
# 
#         def __init__(self, expected):
#             self.expected = expected
# 
#         def matches(self, actual):
#             self.actual = actual
#             return actual == expected
# 
#         def description(self):
#             ret = (
#                 repr(self.actual)
#                 + " does not equal "
#                 + repr(self.expected)
#                 + " as expected."
#             )
#             if len(ret) > 80:
#                 ret = """Values are not equal (actual then expected):
# %s
# %s
# """ % ( repr(self.actual), repr(self.expected))
#             return ret
#     return EqualsMatcher(expected)
# 
# def is_not(expected):
#     class NotEqualsMatcher:
# 
#         def __init__(self, expected):
#             self.expected = expected
# 
#         def matches(self, actual):
#             self.actual = actual
#             return actual != expected
# 
#         def description(self):
#             return (
#                 str(self.actual)
#                 + " equals "
#                 + str(self.expected)
#                 + " but we expected it not to."
#             )
#     return NotEqualsMatcher(expected)
# 
# def fail(msg):
#     raise AssertionError(msg)
# 
# Path: tests/util/test.py
# def test(t):
#     return TestFunctionType(t)
# 
# Path: pycell/valueclass.py
# def valueclass(*members):
#     """
#     A classdecorator that makes a class into a standard value type.
# 
#     This decorator provides an __init__ method that takes in the supplied
#     members and stores them in instance variables.
# 
#     This decorator also provides standard __eq__, __repr__ and __str__
#     functions that use the supplied members
#     """
# 
#     def _wrong_init_args_message(member_name):
#         return (
#             "__init__() missing 1 required positional argument: "
#             + "'{arg}'").format(
#                 arg=member_name
#         )
# 
#     def _too_many_args_message(args):
#         if len(members) == 0:
#             return "object() takes no parameters"
#         else:
#             return (
#                 "__init__() takes "
#                 + "{lenmem} positional arguments but "
#                 + "{lenargs} were given"
#             ).format(
#                 lenmem=len(members) + 1,
#                 lenargs=len(args) + 1
#             )
# 
#     def _multiple_values_message(member_name):
#         return (
#             "__init__() got multiple values for argument '{arg}'").format(
#                 arg=member_name
#         )
# 
#     def value_init(self, *args, **kwargs):
#         for (i, m) in enumerate(members):
#             if i < len(args):
#                 self.__dict__[m] = args[i]
#                 if m in kwargs:
#                     raise TypeError(_multiple_values_message(m))
#             elif m in kwargs:
#                 self.__dict__[m] = kwargs[m]
#             else:
#                 raise TypeError(_wrong_init_args_message(m))
#         if len(args) > len(members):
#             raise TypeError(_too_many_args_message(args))
#         for k in kwargs:
#             if k not in members:
#                 raise TypeError(
#                     (
#                         "__init__() got an unexpected keyword "
#                         + "argument '{k}'"
#                     ).format(k=k)
#                 )
# 
#     def value_eq(self, other):
#         if not isinstance(other, type(self)):
#             return False
#         for m in members:
#             if self.__dict__[m] != other.__dict__[m]:
#                 return False
#         return True
# 
#     def value_repr(self):
#         return "{type}({args})".format(
#             type=type(self).__name__,
#             args=", ".join(repr(self.__dict__[m]) for m in members)
#         )
# 
#     def ret(cl):
#         cl.__init__ = value_init
#         cl.__eq__ = value_eq
#         cl.__repr__ = value_repr
#         return cl
# 
#     return ret


# Path: tests/valueclass_tests.py
from tests.util.asserts import assert_that, equals, is_not, fail
from tests.util.test import test
from pycell.valueclass import valueclass


@test
def Empty_value_classes_compare_equal_if_same_class():
    @valueclass()
    class MyClass:
        pass

    assert_that(MyClass(), equals(MyClass()))


@test
def Empty_value_classes_compare_not_equal_if_different_class():
    @valueclass()
    class MyClass1:
        pass

    @valueclass()
    class MyClass2:
        pass

    assert_that(MyClass1(), is_not(MyClass2()))


@test
def Can_construct_a_nonempty_value_class_using_positional_args():
    @valueclass("mem1", "mem2")
    class MyClass:
        pass

    b = MyClass(3, 4)

    assert_that(b.mem1, equals(3))