Exemple #1
0
    def test_callable_after(self):
        def after1(proxy, ret_val):
            """
            after在被代理的方法调用之后调用,用来改变输出
            :param proxy: 代理实例
            :param ret_val: 被代理的方法返回值
            :return:
            """
            if ret_val < 10:
                return 10

            if ret_val < 100:
                Return(100)

            return ret_val

        def after2(proxy, ret_val):
            return ret_val // 2

        aa = A()
        a = Proxy(aa,
                  after=[
                      AOP.Hook(after1, ["__call__"]),
                      AOP.Hook(after2, ["__call__"])
                  ])

        # 传入1,得到结果1*3,走到after1之后被改成了10,走到after2的时候被改成了5
        assert a(1) == 5
        # 传入4,得到结果4*3,走到after1直接被返回了100,不再走after2
        assert a(4) == 100
        # 传入70,得到结果70*3,无修改通过after1,随后在after2被改成105
        assert a(70) == 105
Exemple #2
0
    def test_callable_before(self):
        def before1(proxy, a):
            """
            before在被代理的方法调用之前调用,用来改变输入
            :param proxy: 代理实例
            :param a: 被代理的方法传入的参数,需要与代理的方法形参列表保持一致
            :return:
            """
            if a == 1:
                a = 5
                return (a, ), dict()

            if a == 3:
                Return(1000)

        def before2(proxy, a):
            return (a // 2, ), dict()

        aa = A()
        a = Proxy(aa,
                  before=[
                      AOP.Hook(before1, ["__call__"]),
                      AOP.Hook(before2, ["__call__"])
                  ])

        # 传入1,走到before1之后被改成了5,走到before2的时候被改成了2, 最后得到结果2*3
        assert a(1) == 6
        # 传入3,走到before1直接被返回了1000,不再走before2和被代理的方法。
        assert a(3) == 1000
        # 传入7,无修改通过before1, 随后在before2被改成3,最后得到结果3*3
        assert a(7) == 9
Exemple #3
0
    def test_customize(self):
        class FunProxy(Proxy):
            proxy_methods = ["fun", "bar"]

        def common(proxy, name):
            return 2

        aa = A()
        a = FunProxy(
            aa,
            before=[AOP.Hook(lambda *args, **kwargs: None, ["fun"])],
            after=[AOP.Hook(common, ["__getitem__", "__call__", "fun"])])

        assert a.b == 3
        assert aa.b == 3
        assert a.__dict__ == {"b": 3}
        assert aa.__dict__ == {"b": 3}
        a.b = 5
        assert a.b == 5
        assert aa.b == 5
        assert a.__dict__ == {"b": 5}
        assert aa.__dict__ == {"b": 5}
        assert a["333"] == 2
        assert aa["333"] == 1
        assert a(3) == 2
        assert aa(3) == 9
        assert a.fun(3, 4) == 2
        assert aa.fun(3, 4) == 12
        assert a.bar(3, 4) == 7
Exemple #4
0
    def test_nomal(self):
        aa = A()

        def common(proxy, name, value=None):
            if name == "b":
                Return(2)

        a = Proxy(
            aa,
            before=[
                AOP.Hook(common,
                         ["__getattribute__", "__setattr__", "__delattr__"])
            ])

        assert aa.b == 3
        assert a.b == 2
        a.b = 10
        assert aa.b == 3
        a.c = 10
        assert aa.c == 10
        assert a.c == 10
        del a.b
        assert hasattr(a, "b")
        assert hasattr(aa, "b")
        del a.c
        assert not hasattr(a, "c")
        assert not hasattr(aa, "c")
def prop_alias(mock_obj_prefix=None, mock_factory_prefix="factories"):
    """
    prop mark装饰器别名,指定要mock对象及工厂对象名字的前缀,减少装饰器长度。
    :param mock_obj_prefix:
    :param mock_factory_prefix:
    :return:
    """
    return Proxy(MarkDecorator(Mark("prop", (), {})),
                 before=[
                     AOP.Hook(wrapper(mock_obj_prefix, mock_factory_prefix),
                              ["__call__"])
                 ])
Exemple #6
0
 def get_store(cls, self_or_cls, **callargs):
     conn, cur = cls.init_sqlite
     with super(SqliteDriverMixin,
                cls).get_store(self_or_cls, **callargs) as self_or_cls:
         cur = conn.cursor()
         if hasattr(self_or_cls, "_need_proxy") \
                 and self_or_cls._need_proxy("store"):
             store = SqliteProxy(
                 cur, before=[AOP.Hook(execute_before, ["execute"])])
             self_or_cls = proxy(self_or_cls, prop_name="store", prop=store)
         try:
             yield self_or_cls
         finally:
             conn.commit()
Exemple #7
0
def proxy(obj, prop, prop_name):
    """
    为 object 对象代理一个属性

    :param object obj: 被代理的对象
    :param object prop: 代理返回的属性
    :param str prop_name: 被代理的属性名
    :return: 被代理之后的对象
    :rtype: object
    """
    def common(_proxy, name, value=None):  # pylint: disable=W0613
        """
        用于 Hook 的钩子函数
        """
        if name == prop_name:
            Return(prop)

    return Proxy(obj, before=[
        AOP.Hook(common, ["__getattribute__", "__setattr__", "__delattr__"]),
    ])
Exemple #8
0
def proxy(obj, prop, prop_name):
    """
    为object对象代理一个属性
    :param obj:
    :param prop: 属性
    :param prop_name: 属性名
    :return:
    """
    assert isinstance(prop_name, str), "prop_name must be string!"

    def common(proxy, name, value=None):
        if name == prop_name:
            if value:
                raise RuntimeError(f"{prop_name} readonly!")
            else:
                Return(prop)

    return Proxy(
        obj,
        before=[
            AOP.Hook(common,
                     ["__getattribute__", "__setattr__", "__delattr__"]),
        ])
Exemple #9
0
 def test_object_del(self):
     aa = A()
     assert hasattr(aa, "b")
     AOP.object_del(aa, "b")
     assert not hasattr(aa, "b")