def test_method_name_same_on_class_and_instance(self):
        # Check this works with Python object class.
        class MyClass:
            def value_changed(self):
                pass

        a = MyClass()

        self.assertEqual(get_method_name(a.value_changed),
                         get_method_name(MyClass.value_changed))

        # Check this works with Aggregate class and @event decorator.
        class MyAggregate(Aggregate):
            @event
            def value_changed(self):
                pass

        a = MyAggregate()

        self.assertEqual(get_method_name(a.value_changed),
                         get_method_name(MyAggregate.value_changed))

        self.assertTrue(
            get_method_name(a.value_changed).endswith("value_changed"), )

        self.assertTrue(
            get_method_name(
                MyAggregate.value_changed).endswith("value_changed"), )

        # Check this works with Aggregate class and @event decorator.
        class MyAggregate2(Aggregate):
            @event()
            def value_changed(self):
                pass

        a = MyAggregate2()

        self.assertEqual(
            get_method_name(a.value_changed),
            get_method_name(MyAggregate2.value_changed),
        )

        self.assertTrue(
            get_method_name(a.value_changed).endswith("value_changed"), )

        self.assertTrue(
            get_method_name(
                MyAggregate2.value_changed).endswith("value_changed"), )
    def test_aggregate_has_incompatible_created_event_class_in_event_decorator(
            self):
        class MyAggregate1(Aggregate):
            class Started(AggregateCreated):
                a: int

            @event(Started)
            def __init__(self):
                pass

        with self.assertRaises(TypeError) as cm:
            MyAggregate1()
        self.assertTrue(cm.exception.args[0].startswith(
            "Unable to construct 'Started' event"))

        with self.assertRaises(TypeError) as cm:
            MyAggregate1(a=1)

        method_name = get_method_name(MyAggregate1.__init__)
        self.assertEqual(
            f"{method_name}() got an unexpected keyword argument 'a'",
            cm.exception.args[0],
        )

        class MyAggregate2(Aggregate):
            class Started(AggregateCreated):
                pass

            @event(Started)
            def __init__(self, a: int):
                self.a = a

        with self.assertRaises(TypeError) as cm:
            MyAggregate2()

        method_name = get_method_name(MyAggregate2.__init__)
        self.assertEqual(
            f"{method_name}() missing 1 required positional argument: 'a'",
            cm.exception.args[0],
        )

        with self.assertRaises(TypeError) as cm:
            MyAggregate2(a=1)
        self.assertTrue(
            cm.exception.args[0].startswith(
                "Unable to construct 'Started' event:"),
            cm.exception.args[0],
        )
Exemplo n.º 3
0
    def test_init_defined_as_dataclass_with_default(self):
        class MyAgg(Aggregate):
            value: int = 0

        a = MyAgg(1)
        self.assertIsInstance(a, MyAgg)
        self.assertEqual(a.value, 1)
        self.assertIsInstance(a, Aggregate)
        self.assertEqual(len(a.pending_events), 1)

        a = MyAgg(value=1)
        self.assertIsInstance(a, MyAgg)
        self.assertEqual(a.value, 1)
        self.assertIsInstance(a, Aggregate)
        self.assertEqual(len(a.pending_events), 1)

        a = MyAgg()
        self.assertIsInstance(a, MyAgg)
        self.assertEqual(a.value, 0)
        self.assertIsInstance(a, Aggregate)
        self.assertEqual(len(a.pending_events), 1)

        with self.assertRaises(TypeError) as cm:
            MyAgg(wrong=1)

        method_name = get_method_name(MyAgg.__init__)

        self.assertEqual(
            f"{method_name}() got an unexpected keyword argument 'wrong'",
            cm.exception.args[0],
        )
Exemplo n.º 4
0
    def test_raises_when_init_gets_unexpected_keyword_argument(self):
        class MyAgg(Aggregate):
            def __init__(self, a=1):
                pass

        with self.assertRaises(TypeError) as cm:
            MyAgg(b=1)

        method_name = get_method_name(MyAgg.__init__)

        self.assertEqual(
            cm.exception.args[0],
            f"{method_name}() got an unexpected keyword argument 'b'",
        )

        with self.assertRaises(TypeError) as cm:
            MyAgg(c=1)

        self.assertEqual(
            cm.exception.args[0],
            f"{method_name}() got an unexpected keyword argument 'c'",
        )

        with self.assertRaises(TypeError) as cm:
            MyAgg(b=1, c=1)

        self.assertEqual(
            cm.exception.args[0],
            f"{method_name}() got an unexpected keyword argument 'b'",
        )
Exemplo n.º 5
0
    def test_raises_when_init_missing_required_positional_and_keyword_only_arg(
            self):
        class MyAgg(Aggregate):
            def __init__(self, a, *, b):
                pass

        with self.assertRaises(TypeError) as cm:
            MyAgg()

        method_name = get_method_name(MyAgg.__init__)

        self.assertEqual(
            cm.exception.args[0],
            f"{method_name}() missing 1 required positional argument: 'a'",
        )

        class MyAgg(Aggregate):
            def __init__(self, a, b=0, *, c):
                self.a = a
                self.b = b
                self.c = c

        with self.assertRaises(TypeError) as cm:
            MyAgg(c=2)

        self.assertEqual(
            cm.exception.args[0],
            f"{method_name}() missing 1 required positional argument: 'a'",
        )
 def assert_raises(cls):
     obj = cls()
     with self.assertRaises(TypeError) as cm:
         obj.value_changed()
     name = get_method_name(obj.value_changed)
     self.assertEqual(
         f"{name}() missing 2 required positional arguments: 'a' and 'b'",
         cm.exception.args[0],
     )
 def assert_raises(cls):
     obj = cls()
     with self.assertRaises(TypeError) as cm:
         # noinspection PyArgumentList
         obj.value_changed(1, 2)
     name = get_method_name(cls.value_changed)
     self.assertEqual(
         f"{name}() takes 2 positional arguments but 3 were given",
         cm.exception.args[0],
     )
        def assert_raises(cls):
            obj = cls()

            with self.assertRaises(TypeError) as cm:
                obj.value_changed(b=1)

            name = get_method_name(cls.value_changed)
            self.assertEqual(
                f"{name}() got an unexpected keyword argument 'b'",
                cm.exception.args[0],
            )
        def assert_raises(cls):
            obj = cls()

            with self.assertRaises(TypeError) as cm:
                obj.value_changed(1)

            name = get_method_name(cls.value_changed)
            self.assertEqual(
                f"{name}() missing 2 required keyword-only arguments: 'b' and 'c'",
                cm.exception.args[0],
            )
Exemplo n.º 10
0
    def test_raises_when_init_missing_2_required_positional_args(self):
        class MyAgg(Aggregate):
            def __init__(self, a, b, *, c):
                pass

        with self.assertRaises(TypeError) as cm:
            MyAgg()

        method_name = get_method_name(MyAgg.__init__)

        self.assertEqual(
            cm.exception.args[0],
            f"{method_name}() missing 2 required positional arguments: 'a' and 'b'",
        )
Exemplo n.º 11
0
    def test_raises_when_create_args_mismatch_created_event(self):
        class BrokenAggregate(Aggregate):
            @classmethod
            def create(cls, name):
                return cls._create(event_class=cls.Created,
                                   id=uuid4(),
                                   name=name)

        with self.assertRaises(TypeError) as cm:
            BrokenAggregate.create("name")

        method_name = get_method_name(BrokenAggregate.Created.__init__)

        self.assertEqual(
            (f"Unable to construct 'Created' event: "
             f"{method_name}() got an unexpected keyword argument 'name'"),
            cm.exception.args[0],
        )
Exemplo n.º 12
0
        def assert_raises(cls):

            method_name = get_method_name(cls.__init__)

            with self.assertRaises(TypeError) as cm:
                cls(0)

            self.assertEqual(
                cm.exception.args[0],
                f"{method_name}() takes 1 positional argument but 2 were given",
            )

            with self.assertRaises(TypeError) as cm:
                cls(value=0)

            self.assertEqual(
                cm.exception.args[0],
                f"{method_name}() got an unexpected keyword argument 'value'",
            )
Exemplo n.º 13
0
        def test_init(cls):
            obj = cls(b=1, a=2)
            self.assertEqual(obj.a, 2)
            self.assertEqual(obj.b, 1)
            self.assertEqual(obj.c, 1)
            self.assertEqual(obj.d, 2)

            obj = cls(1, 2, 3, 4)
            self.assertEqual(obj.a, 1)
            self.assertEqual(obj.b, 2)
            self.assertEqual(obj.c, 3)
            self.assertEqual(obj.d, 4)

            with self.assertRaises(TypeError) as cm:
                obj = cls(1, 2, 3, c=4)
                self.assertEqual(obj.a, 1)
                self.assertEqual(obj.b, 2)
                self.assertEqual(obj.c, 4)
                self.assertEqual(obj.d, 3)

            method_name = get_method_name(cls.__init__)

            self.assertEqual(
                f"{method_name}() got multiple values for argument 'c'",
                cm.exception.args[0],
            )

            with self.assertRaises(TypeError) as cm:
                obj = cls(1, a=2, d=3, c=4)
                self.assertEqual(obj.a, 2)
                self.assertEqual(obj.b, 1)
                self.assertEqual(obj.c, 4)
                self.assertEqual(obj.d, 3)

            self.assertEqual(
                f"{method_name}() got multiple values for argument 'a'",
                cm.exception.args[0],
            )
Exemplo n.º 14
0
def _spec_coerce_args_to_kwargs(
    method: Union[FunctionType, WrapperDescriptorType],
    len_args: int,
    kwargs_keys: Tuple[str],
    expects_id: bool,
) -> Tuple[Tuple[Tuple[int, str], ...], Tuple[Tuple[str, Any], ...]]:
    method_signature = inspect.signature(method)
    positional_names = []
    keyword_defaults = {}
    required_positional = []
    required_keyword_only = []
    if expects_id:
        positional_names.append("id")
        required_positional.append("id")
    for name, param in method_signature.parameters.items():
        if name == "self":
            continue
        # elif param.kind in (param.POSITIONAL_ONLY, param.POSITIONAL_OR_KEYWORD):
        if param.kind is param.KEYWORD_ONLY:
            required_keyword_only.append(name)
        if param.kind is param.POSITIONAL_OR_KEYWORD:
            positional_names.append(name)
            if param.default == param.empty:
                required_positional.append(name)
        if param.default != param.empty:
            keyword_defaults[name] = param.default
    # if not required_keyword_only and not positional_names:
    #     if args or kwargs:
    #         raise TypeError(f"{method.__name__}() takes no args")
    method_name = get_method_name(method)
    for name in kwargs_keys:
        if name not in required_keyword_only and name not in positional_names:
            raise TypeError(
                f"{method_name}() got an unexpected " f"keyword argument '{name}'"
            )
    if len_args > len(positional_names):
        msg = (
            f"{method_name}() takes {len(positional_names) + 1} "
            f"positional argument{'' if len(positional_names) + 1 == 1 else 's'} "
            f"but {len_args + 1} were given"
        )
        raise TypeError(msg)
    required_positional_not_in_kwargs = [
        n for n in required_positional if n not in kwargs_keys
    ]
    num_missing = len(required_positional_not_in_kwargs) - len_args
    if num_missing > 0:
        missing_names = [
            f"'{name}'" for name in required_positional_not_in_kwargs[len_args:]
        ]
        msg = (
            f"{method_name}() missing {num_missing} required positional "
            f"argument{'' if num_missing == 1 else 's'}: "
        )
        raise_missing_names_type_error(missing_names, msg)
    counter = 0
    args_names = []
    for name in positional_names:
        if counter + 1 > len_args:
            break
        if name in kwargs_keys:
            raise TypeError(
                f"{method_name}() got multiple values for argument '{name}'"
            )
        else:
            args_names.append(name)
            counter += 1
    missing_keyword_only_arguments = []
    for name in required_keyword_only:
        if name not in kwargs_keys:
            missing_keyword_only_arguments.append(name)
    if missing_keyword_only_arguments:
        missing_names = [f"'{name}'" for name in missing_keyword_only_arguments]
        msg = (
            f"{method_name}() missing {len(missing_names)} "
            f"required keyword-only argument"
            f"{'' if len(missing_names) == 1 else 's'}: "
        )
        raise_missing_names_type_error(missing_names, msg)
    for key in tuple(keyword_defaults.keys()):
        if key in args_names or key in kwargs_keys:
            keyword_defaults.pop(key)
    enumerated_args_names = tuple(enumerate(args_names))
    keyword_defaults_items = tuple(keyword_defaults.items())
    return enumerated_args_names, keyword_defaults_items