diff --git a/.github/workflows/python.yml b/.github/workflows/python.yml index 43f8df7..c370247 100644 --- a/.github/workflows/python.yml +++ b/.github/workflows/python.yml @@ -78,14 +78,16 @@ jobs: - name: pytest working-directory: ./python run: bash run_unittests.sh - # mypy: - # timeout-minutes: 10 - # runs-on: ubuntu-latest - # needs: change-detection - # if: needs.change-detection.outputs.python-changes == 'true' - # steps: - # - uses: actions/checkout@v6 - # - uses: ./.github/actions/setup-python - # - name: mypy - # working-directory: ./python - # run: mypy . + mypy: + timeout-minutes: 10 + runs-on: ubuntu-latest + needs: change-detection + if: needs.change-detection.outputs.python-changes == 'true' + steps: + - uses: actions/checkout@v6 + - uses: ./.github/actions/setup-python + - name: mypy + working-directory: ./python + env: + MYPYPATH: src + run: mypy --namespace-packages --explicit-package-bases . diff --git a/.gitignore b/.gitignore index 2553707..06537b0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ # Python python/**/__pycache__/ +python/**/.mypy_cache # JavaScript javascript/node_modules/ diff --git a/python/calculator_cli_app/src/application.py b/python/calculator_cli_app/src/application.py index 0bbb2e0..5d4180d 100644 --- a/python/calculator_cli_app/src/application.py +++ b/python/calculator_cli_app/src/application.py @@ -1,6 +1,5 @@ -from args_validation import __validate__ -from calculation_query import CalculationQuery -from data_type_conversion import __to_int_with_rescue__ +from __future__ import annotations + import sys sys.path.append('./calculator_cli_app/src') sys.path.append('./calculator_cli_app/src/lib') @@ -9,7 +8,7 @@ class Application: - def __init__(self, args): + def __init__(self, args: list[str]) -> None: self.args_size = len(args) if self.args_size > 0: self.seed = args[0] @@ -19,7 +18,7 @@ def __init__(self, args): self.n = '' self.calculation_query = CalculationQuery(self.seed) - def run(self): + def run(self) -> None: __validate__(self.args_size, self.seed, __to_int_with_rescue__(self.n)) result = self.calculation_query.f(__to_int_with_rescue__(self.n)) diff --git a/python/calculator_cli_app/src/lib/data_type_conversion.py b/python/calculator_cli_app/src/lib/data_type_conversion.py index beed52f..bee8fe1 100644 --- a/python/calculator_cli_app/src/lib/data_type_conversion.py +++ b/python/calculator_cli_app/src/lib/data_type_conversion.py @@ -1,4 +1,7 @@ -def __to_int_with_rescue__(n): +from __future__ import annotations + + +def __to_int_with_rescue__(n: str) -> int | str: try: return int(n) except ValueError: diff --git a/python/calculator_cli_app/src/queries/calculation_query.py b/python/calculator_cli_app/src/queries/calculation_query.py index cd88de1..d72a2ff 100644 --- a/python/calculator_cli_app/src/queries/calculation_query.py +++ b/python/calculator_cli_app/src/queries/calculation_query.py @@ -4,11 +4,11 @@ class CalculationQuery: - def __init__(self, seed): + def __init__(self, seed: str) -> None: self.seed = seed self.uri = os.environ['CALCULATION_API'] - def f(self, n): + def f(self, n: int) -> int: if n == 0: return 1 elif n == 2: @@ -21,7 +21,7 @@ def f(self, n): # private - def __ask_server__(self, n): + def __ask_server__(self, n: int) -> int: params = {'seed': self.seed, 'n': n} req = urllib.request.Request('{}?{}'.format( self.uri, urllib.parse.urlencode(params))) diff --git a/python/calculator_cli_app/src/validations/args_validation.py b/python/calculator_cli_app/src/validations/args_validation.py index f9331eb..9f4d901 100644 --- a/python/calculator_cli_app/src/validations/args_validation.py +++ b/python/calculator_cli_app/src/validations/args_validation.py @@ -1,4 +1,7 @@ -def __validate__(args_size, seed, n): +from __future__ import annotations + + +def __validate__(args_size: int, seed: str, n: int | str) -> None: if args_size > 2: print('Too many arguments') exit(1) diff --git a/python/calculator_cli_app/test/queries/test_calculation_query.py b/python/calculator_cli_app/test/queries/test_calculation_query.py index 5ba1748..500a6d9 100644 --- a/python/calculator_cli_app/test/queries/test_calculation_query.py +++ b/python/calculator_cli_app/test/queries/test_calculation_query.py @@ -9,7 +9,7 @@ class TestCalculationQuery(unittest.TestCase): - def setUp(self): + def setUp(self) -> None: self.calculation_query = CalculationQuery('foo') self.org_stdout = sys.stdout sys.stdout = StringIO() @@ -20,7 +20,7 @@ def setUp(self): '__pycache__'), recursive=True) - def tearDown(self): + def tearDown(self) -> None: sys.stdout = self.org_stdout for pycache in self.pycaches: if os.path.exists(pycache): @@ -28,17 +28,17 @@ def tearDown(self): class TestArgumentZero(TestCalculationQuery): - def test_f_with_zero(self): + def test_f_with_zero(self) -> None: self.assertEqual(self.calculation_query.f(0), 1) class TestArgumentTwo(TestCalculationQuery): - def test_f_with_two(self): + def test_f_with_two(self) -> None: self.assertEqual(self.calculation_query.f(2), 2) class TestArgumentFour(TestCalculationQuery): - def test_f_with_four(self): + def test_f_with_four(self) -> None: self.assertEqual(self.calculation_query.f(4), 348) diff --git a/python/calculator_cli_app/test/test_application.py b/python/calculator_cli_app/test/test_application.py index 1ed1b09..258de1c 100644 --- a/python/calculator_cli_app/test/test_application.py +++ b/python/calculator_cli_app/test/test_application.py @@ -12,7 +12,7 @@ class TestApplication(unittest.TestCase): - def setUp(self): + def setUp(self) -> None: self.org_stdout = sys.stdout sys.stdout = StringIO() argv = ['foo', 4] @@ -24,11 +24,11 @@ def setUp(self): '__pycache__'), recursive=True) - def test_run_success(self): + def test_run_success(self) -> None: self.app.run() self.assertEqual(sys.stdout.getvalue(), '348\n') - def tearDown(self): + def tearDown(self) -> None: sys.stdout = self.org_stdout for pycache in self.pycaches: if os.path.exists(pycache): diff --git a/python/fibonacci_sequence/src/fibonacci.py b/python/fibonacci_sequence/src/fibonacci.py index b8dd637..6165a9a 100644 --- a/python/fibonacci_sequence/src/fibonacci.py +++ b/python/fibonacci_sequence/src/fibonacci.py @@ -1,4 +1,7 @@ -def fibonacci(init_num, iter): +from __future__ import annotations + + +def fibonacci(init_num: int, iter: int) -> list[int]: current_num = init_num next_num = current_num + 1 result = list() diff --git a/python/fibonacci_sequence/test/test_fibonacci.py b/python/fibonacci_sequence/test/test_fibonacci.py index 9284476..6f02e4e 100644 --- a/python/fibonacci_sequence/test/test_fibonacci.py +++ b/python/fibonacci_sequence/test/test_fibonacci.py @@ -8,7 +8,7 @@ class TestFibonacci(unittest.TestCase): - def setUp(self): + def setUp(self) -> None: self.pycaches = glob.glob( os.path.join( '.', @@ -16,14 +16,14 @@ def setUp(self): '__pycache__'), recursive=True) - def tearDown(self): + def tearDown(self) -> None: for pycache in self.pycaches: if os.path.exists(pycache): shutil.rmtree(pycache) class TestCase1(TestFibonacci): - def test_fibonacci(self): + def test_fibonacci(self) -> None: self.assertEqual( fibonacci(0, 10), [0, 1, 1, 2, 3, 5, 8, 13, 21, 34] @@ -31,7 +31,7 @@ def test_fibonacci(self): class TestCase2(TestFibonacci): - def test_fibonacci(self): + def test_fibonacci(self) -> None: self.assertEqual( fibonacci(10, 10), [10, 11, 21, 32, 53, 85, 138, 223, 361, 584] diff --git a/python/fizzbuzz/src/fizzbuzz.py b/python/fizzbuzz/src/fizzbuzz.py index 047c962..cbbb33e 100644 --- a/python/fizzbuzz/src/fizzbuzz.py +++ b/python/fizzbuzz/src/fizzbuzz.py @@ -1,4 +1,4 @@ -def fizzbuzz_in_if(num): +def fizzbuzz_in_if(num: int) -> str: if num % 3 == 0 and num % 5 == 0: result = 'FizzBuzz' elif num % 3 == 0: @@ -10,7 +10,7 @@ def fizzbuzz_in_if(num): return result -def fizzbuzz_in_ternary(num): +def fizzbuzz_in_ternary(num: int) -> str: result = 'FizzBuzz' if num % 3 == 0 and num % 5 == 0 else 'Fizz' if num % 3 == 0 else 'Buzz' if num % 5 == 0 else str( num) return result diff --git a/python/fizzbuzz/test/test_fizzbuzz.py b/python/fizzbuzz/test/test_fizzbuzz.py index 03b0c32..cbc5206 100644 --- a/python/fizzbuzz/test/test_fizzbuzz.py +++ b/python/fizzbuzz/test/test_fizzbuzz.py @@ -8,7 +8,7 @@ class TestFizzBuzz(unittest.TestCase): - def setUp(self): + def setUp(self) -> None: self.pycaches = glob.glob( os.path.join( '.', @@ -16,14 +16,14 @@ def setUp(self): '__pycache__'), recursive=True) - def tearDown(self): + def tearDown(self) -> None: for pycache in self.pycaches: if os.path.exists(pycache): shutil.rmtree(pycache) class TestIfStatement(TestFizzBuzz): - def test_fizzbuzz(self): + def test_fizzbuzz(self) -> None: for num in range(1, 101): if num % 3 == 0 and num % 5 == 0: self.assertEqual(fizzbuzz_in_if(num), 'FizzBuzz') @@ -36,7 +36,7 @@ def test_fizzbuzz(self): class TestTernaryStatement(TestFizzBuzz): - def test_fizzbuzz(self): + def test_fizzbuzz(self) -> None: for num in range(1, 101): if num % 3 == 0 and num % 5 == 0: self.assertEqual(fizzbuzz_in_ternary(num), 'FizzBuzz') diff --git a/python/letter_inspection/src/application.py b/python/letter_inspection/src/application.py index 30e7e1e..dd77ff1 100644 --- a/python/letter_inspection/src/application.py +++ b/python/letter_inspection/src/application.py @@ -1,14 +1,14 @@ class Application: - def __init__(self, str_1, str_2): + def __init__(self, str_1: str, str_2: str) -> None: self.str_1 = str_1 self.str_2 = str_2 - def exactly_equal_size_and_included(self): + def exactly_equal_size_and_included(self) -> bool: return self.__sort_string__( self.str_1) == self.__sort_string__( self.str_2) # private - def __sort_string__(self, str): + def __sort_string__(self, str: str) -> str: return ''.join(sorted(str)) diff --git a/python/letter_inspection/test/test_application.py b/python/letter_inspection/test/test_application.py index f361c8a..8c13da8 100644 --- a/python/letter_inspection/test/test_application.py +++ b/python/letter_inspection/test/test_application.py @@ -8,7 +8,7 @@ class TestApplication(unittest.TestCase): - def setUp(self): + def setUp(self) -> None: str_1 = 'hogefoobar' str_2 = 'abefghooor' str_3 = 'hoge' @@ -23,14 +23,14 @@ def setUp(self): '__pycache__'), recursive=True) - def tearDown(self): + def tearDown(self) -> None: for pycache in self.pycaches: if os.path.exists(pycache): shutil.rmtree(pycache) class TestRegularCase(TestApplication): - def test_exactly_equal_size_and_included_1(self): + def test_exactly_equal_size_and_included_1(self) -> None: self.assertTrue(self.pattern_1.exactly_equal_size_and_included()) @@ -39,12 +39,12 @@ class TestIrregularCase(TestApplication): class TestCase1(TestIrregularCase): - def test_exactly_equal_size_and_included_2(self): + def test_exactly_equal_size_and_included_2(self) -> None: self.assertFalse(self.pattern_2.exactly_equal_size_and_included()) class TestCase1(TestIrregularCase): - def test_exactly_equal_size_and_included_3(self): + def test_exactly_equal_size_and_included_3(self) -> None: self.assertFalse(self.pattern_3.exactly_equal_size_and_included()) diff --git a/python/nabeatsu/src/nabeatsu.py b/python/nabeatsu/src/nabeatsu.py index 2dee77a..be724aa 100644 --- a/python/nabeatsu/src/nabeatsu.py +++ b/python/nabeatsu/src/nabeatsu.py @@ -1,4 +1,4 @@ -def go_crazy_in_if(num): +def go_crazy_in_if(num: int) -> str: if num % 3 == 0 or '3' in str(num): # Express the status of 'crazy' with '!' result = str(num) + '!' @@ -7,7 +7,7 @@ def go_crazy_in_if(num): return result -def go_crazy_in_ternary(num): +def go_crazy_in_ternary(num: int) -> str: # Express the status of 'crazy' with '!' result = str(num) + '!' if num % 3 == 0 or '3' in str(num) else str(num) return result diff --git a/python/nabeatsu/test/test_nabeatsu.py b/python/nabeatsu/test/test_nabeatsu.py index 00de333..eeb13c7 100644 --- a/python/nabeatsu/test/test_nabeatsu.py +++ b/python/nabeatsu/test/test_nabeatsu.py @@ -8,7 +8,7 @@ class TestNabeatsu(unittest.TestCase): - def setUp(self): + def setUp(self) -> None: self.pycaches = glob.glob( os.path.join( '.', @@ -16,14 +16,14 @@ def setUp(self): '__pycache__'), recursive=True) - def tearDown(self): + def tearDown(self) -> None: for pycache in self.pycaches: if os.path.exists(pycache): shutil.rmtree(pycache) class TestIfStatement(TestNabeatsu): - def test_go_crazy(self): + def test_go_crazy(self) -> None: for num in range(1, 41): if num % 3 == 0 or '3' in str(num): self.assertEqual(go_crazy_in_if(num), str(num) + '!') @@ -32,7 +32,7 @@ def test_go_crazy(self): class TestTernaryStatement(TestNabeatsu): - def test_go_crazy(self): + def test_go_crazy(self) -> None: for num in range(1, 41): if num % 3 == 0 or '3' in str(num): self.assertEqual(go_crazy_in_ternary(num), str(num) + '!') diff --git a/python/pyproject.toml b/python/pyproject.toml new file mode 100644 index 0000000..caba914 --- /dev/null +++ b/python/pyproject.toml @@ -0,0 +1,5 @@ +[tool.mypy] +python_version = "3.14" +warn_return_any = true +warn_unused_configs = true +disallow_untyped_defs = true