From bab86c8ab932e874266680c093cebcb3aa7dfffe Mon Sep 17 00:00:00 2001 From: Hamid Molareza Date: Fri, 31 Mar 2023 17:06:26 +0330 Subject: [PATCH] feat: Add Result and ResultDetail classes --- def_result/Result.py | 26 ++++++++++++++++ def_result/ResultDetail.py | 42 ++++++++++++++++++++++++++ def_result/main.py | 3 -- tests/test_ResultDetail.py | 62 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 130 insertions(+), 3 deletions(-) create mode 100644 def_result/Result.py create mode 100644 def_result/ResultDetail.py delete mode 100644 def_result/main.py create mode 100644 tests/test_ResultDetail.py diff --git a/def_result/Result.py b/def_result/Result.py new file mode 100644 index 0000000..acca187 --- /dev/null +++ b/def_result/Result.py @@ -0,0 +1,26 @@ +from typing import Optional, Any +from def_result.ResultDetail import ResultDetail + + +class Result: + success: bool + detail: Optional[ResultDetail] = None + value: Optional[Any] = None + + def __init__(self, success: bool, detail: Optional[ResultDetail] = None, value: Optional[Any] = None): + self.success = success + self.detail = detail + self.value = value + + @staticmethod + def ok(value: Optional[Any] = None, detail: Optional[ResultDetail] = None): + return Result(True, detail=detail, value=value) + + @staticmethod + def fail(detail: Optional[ResultDetail] = None): + return Result(False, detail) + + def code(self, default_success_code: int = 200, default_error_code: int = 500) -> int: + if self.detail and self.detail.code: + return self.detail.code + return default_success_code if self.success else default_error_code diff --git a/def_result/ResultDetail.py b/def_result/ResultDetail.py new file mode 100644 index 0000000..909b75e --- /dev/null +++ b/def_result/ResultDetail.py @@ -0,0 +1,42 @@ +from typing import Optional, Any, List + + +class ResultDetail: + title: str + message: Optional[str] + code: Optional[int] + more_data: List[Any] = [] + + def __init__(self, title: str, + message: Optional[str] = None, + code: Optional[int] = None, + more_data: Optional[List[Any]] = None): + if not title: + raise ValueError("title is required") + self.title = title + self.message = message + self.code = code + if more_data is not None: + self.more_data = more_data + + def is_instance_of(self, cls): + return isinstance(self, cls) + + def add_more_data(self, data: Any) -> None: + if not data: + return + if not self.more_data: + self.more_data = [] + self.more_data.append(data) + + def __str__(self): + result: str = "" + + if self.title: + result += f"Title: {self.title}\n" + if self.message: + result += f"Message: {self.message}\n" + if self.code: + result += f"Code: {self.code}\n" + + return result diff --git a/def_result/main.py b/def_result/main.py deleted file mode 100644 index 14e4198..0000000 --- a/def_result/main.py +++ /dev/null @@ -1,3 +0,0 @@ -def say_hello(name: str) -> str: - """ Say hello """ - return f"Hello {name}!" diff --git a/tests/test_ResultDetail.py b/tests/test_ResultDetail.py new file mode 100644 index 0000000..1ed793a --- /dev/null +++ b/tests/test_ResultDetail.py @@ -0,0 +1,62 @@ +import unittest + +from def_result.ResultDetail import ResultDetail + + +class TestResultDetail(unittest.TestCase): + def test_init_without_optional_args(self): + title = 'title' + result_detail = ResultDetail(title=title) + + self.assertEqual(result_detail.title, title) + self.assertIsNone(result_detail.message) + self.assertIsNone(result_detail.code) + self.assertIsNotNone(result_detail.more_data) + self.assertEqual(len(result_detail.more_data), 0) + + def test_init_with_optional_args(self): + result_detail = ResultDetail(title='title', message='message', code=100, more_data=["more data"]) + + self.assertEqual(result_detail.title, 'title') + self.assertEqual(result_detail.message, 'message') + self.assertEqual(result_detail.code, 100) + + self.assertIsNotNone(result_detail.more_data) + self.assertEqual(len(result_detail.more_data), 1) + self.assertEqual(result_detail.more_data[0], "more data") + + def test_is_instance_of(self): + test_detail = FakeDetail("title") + + self.assertTrue(test_detail.is_instance_of(FakeDetail)) + self.assertTrue(test_detail.is_instance_of(ResultDetail)) + + def test_add_more_data(self): + result_detail = ResultDetail(title='title') + result_detail.more_data = None # We use none to make sure that our function does not run into problems. + + result_detail.add_more_data("more data") + + self.assertIsNotNone(result_detail.more_data) + self.assertEqual(len(result_detail.more_data), 1) + self.assertEqual(result_detail.more_data[0], "more data") + + def test_str_without_args(self): + result_detail = ResultDetail(title='title') + expected = "Title: title\n" + + self.assertEqual(str(result_detail), expected) + + def test_str_with_args(self): + result_detail = ResultDetail(title='title', message='message', code=100) + expected = "Title: title\nMessage: message\nCode: 100\n" + + self.assertEqual(str(result_detail), expected) + + +class FakeDetail(ResultDetail): + pass + + +if __name__ == "__main__": + unittest.main()