import unittest

from cpbox.tool import functocli


class TestFuncCliScenarios(unittest.TestCase):
    def test_inherit_keep_class_exposes_base(self):
        # 继承 + keep_class_for_inheritance：父类公开方法可见
        @functocli.keep_class_for_inheritance
        class BaseKeepClass(object):
            def present_base_action(self):
                print('base')

        class AppKeepClass(BaseKeepClass):
            def present_app_action(self):
                print('app')

        methods = set(functocli.AppSepc(AppKeepClass).public_methods)
        self.assertSetEqual(methods, {'present_app_action', 'present_base_action'})

    def test_inherit_keep_method_exposes_only_marked(self):
        # 继承 + keep_method_for_inheritance：仅标记方法可见，未标记隐藏
        class BaseKeepMethod(object):
            def hidden_base_action(self):
                print('hidden')

            @functocli.keep_method_for_inheritance
            def present_keep_base(self):
                print('keep')

        class AppKeepMethod(BaseKeepMethod):
            def present_app_action(self):
                print('app')

        methods = set(functocli.AppSepc(AppKeepMethod).public_methods)
        self.assertSetEqual(methods, {'present_app_action', 'present_keep_base'})
        self.assertNotIn('hidden_base_action', methods)

    def test_compose_append_merge_exposes_tool(self):
        # append_cli_for_composition + merge_class_for_composition：组合对象方法可见
        class MergeTool(object):
            def present_tool_action(self):
                print('tool')

        @functocli.merge_class_for_composition(MergeTool)
        class AppMerge(object):
            def __init__(self):
                functocli.append_cli_for_composition(self, MergeTool())

            def present_app_action(self):
                print('app')

        methods = set(functocli.AppSepc(AppMerge).public_methods)
        self.assertSetEqual(methods, {'present_app_action', 'present_tool_action'})

    def test_compose_append_keep_method_hides_tool(self):
        # append_cli_for_composition + keep_method_for_inheritance：组合对象方法不可见
        class ToolKeepMethod(object):
            @functocli.keep_method_for_inheritance
            def hidden_tool_action(self):
                print('tool')

        class AppAppendKeepMethod(object):
            def __init__(self):
                functocli.append_cli_for_composition(self, ToolKeepMethod())

            def present_app_action(self):
                print('app')

        methods = set(functocli.AppSepc(AppAppendKeepMethod).public_methods)
        self.assertSetEqual(methods, {'present_app_action'})
        self.assertNotIn('hidden_tool_action', methods)

    def test_compose_append_keep_class_hides_tool(self):
        # append_cli_for_composition + keep_class_for_inheritance：组合对象方法不可见
        @functocli.keep_class_for_inheritance
        class ToolKeepClass(object):
            def hidden_tool_action(self):
                print('tool')

        class AppAppendKeepClass(object):
            def __init__(self):
                functocli.append_cli_for_composition(self, ToolKeepClass())

            def present_app_action(self):
                print('app')

        methods = set(functocli.AppSepc(AppAppendKeepClass).public_methods)
        self.assertSetEqual(methods, {'present_app_action'})
        self.assertNotIn('hidden_tool_action', methods)


if __name__ == '__main__':
    unittest.main()
