From 95a4692e5fc8b553b9df1052b95a4cba5db155ef Mon Sep 17 00:00:00 2001 From: Michael Kennedy Date: Thu, 11 Sep 2025 13:16:16 -0700 Subject: [PATCH 1/3] =?UTF-8?q?Refactor=20codebase=20for=20consistent=20do?= =?UTF-8?q?uble=E2=80=91quoted=20strings=20and=20add=20type=20hints?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This update replaces single‑quoted literals with double quotes throughout the repository, standardizes string formatting in `setup.py`, `__init__.py`, and test files, and introduces comprehensive type annotations to improve readability and static analysis support. The changes also clean up import statements, adjust exception messages for clarity, and ensure the package metadata uses consistent quoting conventions. 🚀 --- setup.py | 39 +++++++++------------ switchlang/__init__.py | 6 ++-- switchlang/__switchlang_impl.py | 46 +++++++++++++++--------- tests/test_core.py | 62 ++++++++++++++++----------------- 4 files changed, 80 insertions(+), 73 deletions(-) diff --git a/setup.py b/setup.py index bf5b7de..e37e6fc 100644 --- a/setup.py +++ b/setup.py @@ -8,17 +8,17 @@ def read(filename): filename = os.path.join(os.path.dirname(__file__), filename) - text_type = type(u"") - with io.open(filename, mode="r", encoding='utf-8') as fd: - return re.sub(text_type(r':[a-z]+:`~?(.*?)`'), text_type(r'``\1``'), fd.read()) + text_type = type("") + with io.open(filename, mode="r", encoding="utf-8") as fd: + return re.sub(text_type(r":[a-z]+:`~?(.*?)`"), text_type(r"``\1``"), fd.read()) def read_version(): - filename = os.path.join(os.path.dirname(__file__), 'switchlang', '__init__.py') - with open(filename, mode="r", encoding='utf-8') as fin: + filename = os.path.join(os.path.dirname(__file__), "switchlang", "__init__.py") + with open(filename, mode="r", encoding="utf-8") as fin: for line in fin: - if line and line.strip() and line.startswith('__version__'): - return line.split('=')[1].strip().strip("'") + if line and line.strip() and line.startswith("__version__"): + return line.split("=")[1].strip().strip("'") return "0.0.0.0" @@ -29,26 +29,21 @@ def read_version(): name="switchlang", version=read_version(), url="https://github.com/mikeckennedy/python-switch", - license='MIT', - + license="MIT", author="Michael Kennedy", author_email="michael@talkpython.fm", - description="Adds switch blocks to the Python language.", long_description=read("README.md"), - long_description_content_type='text/markdown', - - packages=find_packages(exclude=('tests',)), - + long_description_content_type="text/markdown", + packages=find_packages(exclude=("tests",)), install_requires=requires, - classifiers=[ - 'Development Status :: 4 - Beta', - 'License :: OSI Approved :: MIT License', - 'Programming Language :: Python', - 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.6', - 'Programming Language :: Python :: 3.7', - 'Programming Language :: Python :: 3.8', + "Development Status :: 4 - Beta", + "License :: OSI Approved :: MIT License", + "Programming Language :: Python", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", ], ) diff --git a/switchlang/__init__.py b/switchlang/__init__.py index b14ca62..543738b 100644 --- a/switchlang/__init__.py +++ b/switchlang/__init__.py @@ -6,9 +6,9 @@ License: MIT """ -__version__ = '0.1.0' -__author__ = 'Michael Kennedy ' -__all__ = ['switch', 'closed_range'] +__version__ = "0.1.1" +__author__ = "Michael Kennedy " +__all__ = ["switch", "closed_range"] from .__switchlang_impl import switch from .__switchlang_impl import closed_range diff --git a/switchlang/__switchlang_impl.py b/switchlang/__switchlang_impl.py index 81bfcef..eb4384a 100644 --- a/switchlang/__switchlang_impl.py +++ b/switchlang/__switchlang_impl.py @@ -1,26 +1,27 @@ +import typing import uuid -from typing import Callable, Any, Optional class switch: """ - switch is a module-level implementation of the switch statement for Python. - See https://github.com/mikeckennedy/python-switch for full details. - Copyright Michael Kennedy (https://twitter.com/mkennedy) - License: MIT + switch is a module-level implementation of the switch statement for Python. + See https://github.com/mikeckennedy/python-switch for full details. + Copyright Michael Kennedy (https://mkennedy.codes) + License: MIT """ - __no_result = uuid.uuid4() - __default = uuid.uuid4() - def __init__(self, value): + __no_result: typing.Any = uuid.uuid4() + __default: typing.Any = uuid.uuid4() + + def __init__(self, value: typing.Any): self.value = value - self.cases = set() + self.cases: typing.Set[typing.Any] = set() self._found = False self.__result = switch.__no_result self._falling_through = False - self._func_stack = [] + self._func_stack: typing.List[typing.Callable[[], typing.Any]] = [] - def default(self, func: Callable[[], Any]): + def default(self, func: typing.Callable[[], typing.Any]): """ Use as option final statement in switch block. @@ -36,7 +37,12 @@ def default(self, func: Callable[[], Any]): """ self.case(switch.__default, func) - def case(self, key, func: Callable[[], Any], fallthrough: Optional[bool] = False): + def case( + self, + key: typing.Any, + func: typing.Callable[[], typing.Any], + fallthrough: typing.Optional[bool] = False, + ): """ Specify a case for the switch block: @@ -63,7 +69,9 @@ def case(self, key, func: Callable[[], Any], fallthrough: Optional[bool] = False if isinstance(key, list): if not key: - raise ValueError("You cannot pass an empty collection as the case. It will never match.") + raise ValueError( + "You cannot pass an empty collection as the case. It will never match." + ) found = False for i in key: @@ -97,8 +105,10 @@ def __exit__(self, exc_type, exc_val, exc_tb): raise exc_val if not self._func_stack: - raise Exception("Value does not match any case and there " - "is no default case: value {}".format(self.value)) + raise Exception( + "Value does not match any case and there " + "is no default case: value {}".format(self.value) + ) for func in self._func_stack: # noinspection PyCallingNonCallable @@ -121,8 +131,10 @@ def result(self): :return: The value captured from the method called for a given case. """ if self.__result == switch.__no_result: - raise Exception("No result has been computed (did you access " - "switch.result inside the with block?)") + raise Exception( + "No result has been computed (did you access " + "switch.result inside the with block?)" + ) return self.__result diff --git a/tests/test_core.py b/tests/test_core.py index f343adc..448858c 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -14,7 +14,7 @@ def test_has_matched_case_int(self): s.case(1, lambda: "one") s.case(5, lambda: "five") s.case(7, lambda: "seven") - s.default(lambda: 'default') + s.default(lambda: "default") self.assertEqual(s.result, "seven") @@ -34,29 +34,29 @@ def test_has_matched_case_object(self): def test_default_passthrough(self): value = 11 with switch(value) as s: - s.case(1, lambda: '1') - s.case(2, lambda: '2') - s.default(lambda: 'default') + s.case(1, lambda: "1") + s.case(2, lambda: "2") + s.default(lambda: "default") self.assertEqual(s.result, "default") def test_none_as_valid_case(self): with switch(None) as s: - s.case(1, lambda: 'one') - s.case(None, lambda: 'none') + s.case(1, lambda: "one") + s.case(None, lambda: "none") s.default(lambda: "default") - self.assertEqual(s.result, 'none') + self.assertEqual(s.result, "none") def test_error_no_match_no_default(self): with self.assertRaises(Exception): - with switch('val') as s: + with switch("val") as s: s.case(1, lambda: None) s.case(2, lambda: None) def test_error_duplicate_case(self): with self.assertRaises(ValueError): - with switch('val') as s: + with switch("val") as s: s.case(1, lambda: None) s.case(1, lambda: None) @@ -65,7 +65,7 @@ def test_multiple_values_one_case_range(self): with switch(value) as s: s.case(range(1, 6), lambda: "1-to-5") s.case(range(6, 7), lambda: "6") - s.default(lambda: 'default') + s.default(lambda: "default") self.assertEqual(s.result, "1-to-5") @@ -73,14 +73,14 @@ def test_multiple_values_one_case_range(self): with switch(value) as s: s.case(range(1, 6), lambda: "1-to-5") s.case(range(6, 7), lambda: "6") - s.default(lambda: 'default') + s.default(lambda: "default") self.assertEqual(s.result, "6") with switch(7) as s: s.case(range(1, 6), lambda: "1-to-5") s.case(range(6, 7), lambda: "6") - s.default(lambda: 'default') + s.default(lambda: "default") self.assertEqual(s.result, "default") @@ -88,7 +88,7 @@ def test_multiple_values_one_case_list(self): with switch(6) as s: s.case([1, 3, 5, 7], lambda: "odd") s.case([0, 2, 4, 6, 8], lambda: "even") - s.default(lambda: 'default') + s.default(lambda: "default") self.assertEqual(s.result, "even") @@ -112,21 +112,21 @@ def test_closed_range(self): with switch(value) as s: s.case(closed_range(1, 5), lambda: "1-to-5") s.case(closed_range(6, 7), lambda: "6") - s.default(lambda: 'default') + s.default(lambda: "default") self.assertEqual(s.result, "1-to-5") with switch(0) as s: s.case(closed_range(1, 5), lambda: "1-to-5") s.case(closed_range(6, 7), lambda: "6") - s.default(lambda: 'default') + s.default(lambda: "default") self.assertEqual(s.result, "default") with switch(6) as s: s.case(closed_range(1, 5), lambda: "1-to-5") s.case(closed_range(6, 7), lambda: "6") - s.default(lambda: 'default') + s.default(lambda: "default") self.assertEqual(s.result, "6") @@ -136,10 +136,10 @@ def test_fallthrough_simple(self): with switch(value) as s: s.case(1, lambda: visited.append(1) or 1) s.case(2, lambda: visited.append(2) or 2, fallthrough=True) - s.default(lambda: visited.append('default') or 'default') + s.default(lambda: visited.append("default") or "default") self.assertEqual(s.result, "default") - self.assertEqual(visited, [2, 'default']) + self.assertEqual(visited, [2, "default"]) def test_fallthrough_list(self): visited = [] @@ -148,10 +148,10 @@ def test_fallthrough_list(self): s.case([1, 2, 3], lambda: visited.append(1) or 1) s.case([4, 5, 6], lambda: visited.append(4) or 4, fallthrough=True) s.case([7, 8, 9], lambda: visited.append(7) or 7, fallthrough=True) - s.default(lambda: visited.append('default') or 'default') + s.default(lambda: visited.append("default") or "default") self.assertEqual(s.result, "default") - self.assertEqual(visited, [4, 7, 'default']) + self.assertEqual(visited, [4, 7, "default"]) def test_fallthrough_some_list(self): visited = [] @@ -160,7 +160,7 @@ def test_fallthrough_some_list(self): s.case([1, 2, 3], lambda: visited.append(1) or 1) s.case([4, 5, 6], lambda: visited.append(4) or 4, fallthrough=True) s.case([7, 8, 9], lambda: visited.append(7) or 7) - s.default(lambda: visited.append('default') or 'default') + s.default(lambda: visited.append("default") or "default") self.assertEqual(s.result, 7) self.assertEqual(visited, [4, 7]) @@ -174,7 +174,7 @@ def test_fallthrough_then_stop(self): s.case(3, lambda: visited.append(3) or 3, fallthrough=True) s.case(4, lambda: visited.append(4) or 4) s.case(5, lambda: visited.append(5) or 5) - s.default(lambda: visited.append('default') or 'default') + s.default(lambda: visited.append("default") or "default") self.assertEqual(s.result, 4) self.assertEqual(visited, [2, 3, 4]) @@ -188,7 +188,7 @@ def test_fallthrough_middle_then_stop(self): s.case(3, lambda: visited.append(3) or 3, fallthrough=True) s.case(4, lambda: visited.append(4) or 4) s.case(5, lambda: visited.append(5) or 5) - s.default(lambda: visited.append('default') or 'default') + s.default(lambda: visited.append("default") or "default") self.assertEqual(s.result, 4) self.assertEqual(visited, [3, 4]) @@ -202,31 +202,31 @@ def test_fallthrough_available_but_not_hit(self): s.case(3, lambda: visited.append(3) or 3, fallthrough=True) s.case(4, lambda: visited.append(4) or 4) s.case(5, lambda: visited.append(5) or 5) - s.default(lambda: visited.append('default') or 'default') + s.default(lambda: visited.append("default") or "default") self.assertEqual(s.result, 5) self.assertEqual(visited, [5]) def test_fallthrough__no_match_but_not_hit(self): visited = [] - value = 'gone' + value = "gone" with switch(value) as s: s.case(1, lambda: visited.append(1) or 1) s.case(2, lambda: visited.append(2) or 2, fallthrough=True) s.case(3, lambda: visited.append(3) or 3, fallthrough=True) s.case(4, lambda: visited.append(4) or 4) s.case(5, lambda: visited.append(5) or 5) - s.default(lambda: visited.append('default') or 'default') + s.default(lambda: visited.append("default") or "default") - self.assertEqual(s.result, 'default') - self.assertEqual(visited, ['default']) + self.assertEqual(s.result, "default") + self.assertEqual(visited, ["default"]) def test_empty_collection_clause_is_error(self): with self.assertRaises(ValueError): - with switch('val') as s: + with switch("val") as s: s.case([], lambda: None) - s.default(lambda: 'default') + s.default(lambda: "default") -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() From c24f7739a892ad9f2f04bdeb2f2e05e3eb1bd1f9 Mon Sep 17 00:00:00 2001 From: Michael Kennedy Date: Thu, 11 Sep 2025 13:18:37 -0700 Subject: [PATCH 2/3] Add ruff toml and fix build that didn't account for " vs. ' --- ruff.toml | 43 ++++++++++++ setup.py | 48 ++++++------- switchlang/__init__.py | 6 +- switchlang/__switchlang_impl.py | 22 ++---- tests/test_core.py | 120 ++++++++++++++++---------------- 5 files changed, 137 insertions(+), 102 deletions(-) create mode 100644 ruff.toml diff --git a/ruff.toml b/ruff.toml new file mode 100644 index 0000000..eee74ff --- /dev/null +++ b/ruff.toml @@ -0,0 +1,43 @@ +# [ruff] +line-length = 120 +format.quote-style = "single" + +# Enable Pyflakes `E` and `F` codes by default. +lint.select = ["E", "F"] +lint.ignore = [] + +# Exclude a variety of commonly ignored directories. +exclude = [ + ".bzr", + ".direnv", + ".eggs", + ".git", + ".hg", + ".mypy_cache", + ".nox", + ".pants.d", + ".ruff_cache", + ".svn", + ".tox", + "__pypackages__", + "_build", + "buck-out", + "build", + "dist", + "node_modules", + ".env", + ".venv", + "venv", + "typings/**/*.pyi", +] +lint.per-file-ignores = { } + +# Allow unused variables when underscore-prefixed. +# dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$" + +# Assume Python 3.13. +target-version = "py313" + +#[tool.ruff.mccabe] +## Unlike Flake8, default to a complexity level of 10. +lint.mccabe.max-complexity = 10 diff --git a/setup.py b/setup.py index e37e6fc..f4d8418 100644 --- a/setup.py +++ b/setup.py @@ -8,42 +8,42 @@ def read(filename): filename = os.path.join(os.path.dirname(__file__), filename) - text_type = type("") - with io.open(filename, mode="r", encoding="utf-8") as fd: - return re.sub(text_type(r":[a-z]+:`~?(.*?)`"), text_type(r"``\1``"), fd.read()) + text_type = type('') + with io.open(filename, mode='r', encoding='utf-8') as fd: + return re.sub(text_type(r':[a-z]+:`~?(.*?)`'), text_type(r'``\1``'), fd.read()) def read_version(): - filename = os.path.join(os.path.dirname(__file__), "switchlang", "__init__.py") - with open(filename, mode="r", encoding="utf-8") as fin: + filename = os.path.join(os.path.dirname(__file__), 'switchlang', '__init__.py') + with open(filename, mode='r', encoding='utf-8') as fin: for line in fin: - if line and line.strip() and line.startswith("__version__"): - return line.split("=")[1].strip().strip("'") + if line and line.strip() and line.startswith('__version__'): + return line.split('=')[1].strip().strip("'") - return "0.0.0.0" + return '0.0.0.0' requires = [] setup( - name="switchlang", + name='switchlang', version=read_version(), - url="https://github.com/mikeckennedy/python-switch", - license="MIT", - author="Michael Kennedy", - author_email="michael@talkpython.fm", - description="Adds switch blocks to the Python language.", - long_description=read("README.md"), - long_description_content_type="text/markdown", - packages=find_packages(exclude=("tests",)), + url='https://github.com/mikeckennedy/python-switch', + license='MIT', + author='Michael Kennedy', + author_email='michael@talkpython.fm', + description='Adds switch blocks to the Python language.', + long_description=read('README.md'), + long_description_content_type='text/markdown', + packages=find_packages(exclude=('tests',)), install_requires=requires, classifiers=[ - "Development Status :: 4 - Beta", - "License :: OSI Approved :: MIT License", - "Programming Language :: Python", - "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.6", - "Programming Language :: Python :: 3.7", - "Programming Language :: Python :: 3.8", + 'Development Status :: 4 - Beta', + 'License :: OSI Approved :: MIT License', + 'Programming Language :: Python', + 'Programming Language :: Python :: 3', + 'Programming Language :: Python :: 3.6', + 'Programming Language :: Python :: 3.7', + 'Programming Language :: Python :: 3.8', ], ) diff --git a/switchlang/__init__.py b/switchlang/__init__.py index 543738b..29a3506 100644 --- a/switchlang/__init__.py +++ b/switchlang/__init__.py @@ -6,9 +6,9 @@ License: MIT """ -__version__ = "0.1.1" -__author__ = "Michael Kennedy " -__all__ = ["switch", "closed_range"] +__version__ = '0.1.1' +__author__ = 'Michael Kennedy ' +__all__ = ['switch', 'closed_range'] from .__switchlang_impl import switch from .__switchlang_impl import closed_range diff --git a/switchlang/__switchlang_impl.py b/switchlang/__switchlang_impl.py index eb4384a..5def359 100644 --- a/switchlang/__switchlang_impl.py +++ b/switchlang/__switchlang_impl.py @@ -69,9 +69,7 @@ def case( if isinstance(key, list): if not key: - raise ValueError( - "You cannot pass an empty collection as the case. It will never match." - ) + raise ValueError('You cannot pass an empty collection as the case. It will never match.') found = False for i in key: @@ -83,11 +81,11 @@ def case( return found if key in self.cases: - raise ValueError(f"Duplicate case: {key}") + raise ValueError(f'Duplicate case: {key}') if not func: - raise ValueError("Action for case cannot be None.") + raise ValueError('Action for case cannot be None.') if not callable(func): - raise ValueError("Func must be callable.") + raise ValueError('Func must be callable.') self.cases.add(key) if key == self.value or not self._found and key == self.__default: @@ -105,10 +103,7 @@ def __exit__(self, exc_type, exc_val, exc_tb): raise exc_val if not self._func_stack: - raise Exception( - "Value does not match any case and there " - "is no default case: value {}".format(self.value) - ) + raise Exception('Value does not match any case and there is no default case: value {}'.format(self.value)) for func in self._func_stack: # noinspection PyCallingNonCallable @@ -131,10 +126,7 @@ def result(self): :return: The value captured from the method called for a given case. """ if self.__result == switch.__no_result: - raise Exception( - "No result has been computed (did you access " - "switch.result inside the with block?)" - ) + raise Exception('No result has been computed (did you access switch.result inside the with block?)') return self.__result @@ -157,6 +149,6 @@ def closed_range(start: int, stop: int, step=1) -> range: :return: A range() generator that has a closed upper bound. """ if start >= stop: - raise ValueError("Start must be less than stop.") + raise ValueError('Start must be less than stop.') return range(start, stop + step, step) diff --git a/tests/test_core.py b/tests/test_core.py index 448858c..bfe73f5 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -11,12 +11,12 @@ class CoreTests(unittest.TestCase): def test_has_matched_case_int(self): value = 7 with switch(value) as s: - s.case(1, lambda: "one") - s.case(5, lambda: "five") - s.case(7, lambda: "seven") - s.default(lambda: "default") + s.case(1, lambda: 'one') + s.case(5, lambda: 'five') + s.case(7, lambda: 'seven') + s.default(lambda: 'default') - self.assertEqual(s.result, "seven") + self.assertEqual(s.result, 'seven') def test_has_matched_case_object(self): t1 = TestKeyObject() @@ -34,63 +34,63 @@ def test_has_matched_case_object(self): def test_default_passthrough(self): value = 11 with switch(value) as s: - s.case(1, lambda: "1") - s.case(2, lambda: "2") - s.default(lambda: "default") + s.case(1, lambda: '1') + s.case(2, lambda: '2') + s.default(lambda: 'default') - self.assertEqual(s.result, "default") + self.assertEqual(s.result, 'default') def test_none_as_valid_case(self): with switch(None) as s: - s.case(1, lambda: "one") - s.case(None, lambda: "none") - s.default(lambda: "default") + s.case(1, lambda: 'one') + s.case(None, lambda: 'none') + s.default(lambda: 'default') - self.assertEqual(s.result, "none") + self.assertEqual(s.result, 'none') def test_error_no_match_no_default(self): with self.assertRaises(Exception): - with switch("val") as s: + with switch('val') as s: s.case(1, lambda: None) s.case(2, lambda: None) def test_error_duplicate_case(self): with self.assertRaises(ValueError): - with switch("val") as s: + with switch('val') as s: s.case(1, lambda: None) s.case(1, lambda: None) def test_multiple_values_one_case_range(self): for value in range(1, 5): with switch(value) as s: - s.case(range(1, 6), lambda: "1-to-5") - s.case(range(6, 7), lambda: "6") - s.default(lambda: "default") + s.case(range(1, 6), lambda: '1-to-5') + s.case(range(6, 7), lambda: '6') + s.default(lambda: 'default') - self.assertEqual(s.result, "1-to-5") + self.assertEqual(s.result, '1-to-5') for value in range(6, 7): with switch(value) as s: - s.case(range(1, 6), lambda: "1-to-5") - s.case(range(6, 7), lambda: "6") - s.default(lambda: "default") + s.case(range(1, 6), lambda: '1-to-5') + s.case(range(6, 7), lambda: '6') + s.default(lambda: 'default') - self.assertEqual(s.result, "6") + self.assertEqual(s.result, '6') with switch(7) as s: - s.case(range(1, 6), lambda: "1-to-5") - s.case(range(6, 7), lambda: "6") - s.default(lambda: "default") + s.case(range(1, 6), lambda: '1-to-5') + s.case(range(6, 7), lambda: '6') + s.default(lambda: 'default') - self.assertEqual(s.result, "default") + self.assertEqual(s.result, 'default') def test_multiple_values_one_case_list(self): with switch(6) as s: - s.case([1, 3, 5, 7], lambda: "odd") - s.case([0, 2, 4, 6, 8], lambda: "even") - s.default(lambda: "default") + s.case([1, 3, 5, 7], lambda: 'odd') + s.case([0, 2, 4, 6, 8], lambda: 'even') + s.default(lambda: 'default') - self.assertEqual(s.result, "even") + self.assertEqual(s.result, 'even') def test_return_value_from_case(self): value = 4 @@ -110,25 +110,25 @@ def test_result_inaccessible_if_hasnt_run(self): def test_closed_range(self): for value in [1, 2, 3, 4, 5]: with switch(value) as s: - s.case(closed_range(1, 5), lambda: "1-to-5") - s.case(closed_range(6, 7), lambda: "6") - s.default(lambda: "default") + s.case(closed_range(1, 5), lambda: '1-to-5') + s.case(closed_range(6, 7), lambda: '6') + s.default(lambda: 'default') - self.assertEqual(s.result, "1-to-5") + self.assertEqual(s.result, '1-to-5') with switch(0) as s: - s.case(closed_range(1, 5), lambda: "1-to-5") - s.case(closed_range(6, 7), lambda: "6") - s.default(lambda: "default") + s.case(closed_range(1, 5), lambda: '1-to-5') + s.case(closed_range(6, 7), lambda: '6') + s.default(lambda: 'default') - self.assertEqual(s.result, "default") + self.assertEqual(s.result, 'default') with switch(6) as s: - s.case(closed_range(1, 5), lambda: "1-to-5") - s.case(closed_range(6, 7), lambda: "6") - s.default(lambda: "default") + s.case(closed_range(1, 5), lambda: '1-to-5') + s.case(closed_range(6, 7), lambda: '6') + s.default(lambda: 'default') - self.assertEqual(s.result, "6") + self.assertEqual(s.result, '6') def test_fallthrough_simple(self): visited = [] @@ -136,10 +136,10 @@ def test_fallthrough_simple(self): with switch(value) as s: s.case(1, lambda: visited.append(1) or 1) s.case(2, lambda: visited.append(2) or 2, fallthrough=True) - s.default(lambda: visited.append("default") or "default") + s.default(lambda: visited.append('default') or 'default') - self.assertEqual(s.result, "default") - self.assertEqual(visited, [2, "default"]) + self.assertEqual(s.result, 'default') + self.assertEqual(visited, [2, 'default']) def test_fallthrough_list(self): visited = [] @@ -148,10 +148,10 @@ def test_fallthrough_list(self): s.case([1, 2, 3], lambda: visited.append(1) or 1) s.case([4, 5, 6], lambda: visited.append(4) or 4, fallthrough=True) s.case([7, 8, 9], lambda: visited.append(7) or 7, fallthrough=True) - s.default(lambda: visited.append("default") or "default") + s.default(lambda: visited.append('default') or 'default') - self.assertEqual(s.result, "default") - self.assertEqual(visited, [4, 7, "default"]) + self.assertEqual(s.result, 'default') + self.assertEqual(visited, [4, 7, 'default']) def test_fallthrough_some_list(self): visited = [] @@ -160,7 +160,7 @@ def test_fallthrough_some_list(self): s.case([1, 2, 3], lambda: visited.append(1) or 1) s.case([4, 5, 6], lambda: visited.append(4) or 4, fallthrough=True) s.case([7, 8, 9], lambda: visited.append(7) or 7) - s.default(lambda: visited.append("default") or "default") + s.default(lambda: visited.append('default') or 'default') self.assertEqual(s.result, 7) self.assertEqual(visited, [4, 7]) @@ -174,7 +174,7 @@ def test_fallthrough_then_stop(self): s.case(3, lambda: visited.append(3) or 3, fallthrough=True) s.case(4, lambda: visited.append(4) or 4) s.case(5, lambda: visited.append(5) or 5) - s.default(lambda: visited.append("default") or "default") + s.default(lambda: visited.append('default') or 'default') self.assertEqual(s.result, 4) self.assertEqual(visited, [2, 3, 4]) @@ -188,7 +188,7 @@ def test_fallthrough_middle_then_stop(self): s.case(3, lambda: visited.append(3) or 3, fallthrough=True) s.case(4, lambda: visited.append(4) or 4) s.case(5, lambda: visited.append(5) or 5) - s.default(lambda: visited.append("default") or "default") + s.default(lambda: visited.append('default') or 'default') self.assertEqual(s.result, 4) self.assertEqual(visited, [3, 4]) @@ -202,31 +202,31 @@ def test_fallthrough_available_but_not_hit(self): s.case(3, lambda: visited.append(3) or 3, fallthrough=True) s.case(4, lambda: visited.append(4) or 4) s.case(5, lambda: visited.append(5) or 5) - s.default(lambda: visited.append("default") or "default") + s.default(lambda: visited.append('default') or 'default') self.assertEqual(s.result, 5) self.assertEqual(visited, [5]) def test_fallthrough__no_match_but_not_hit(self): visited = [] - value = "gone" + value = 'gone' with switch(value) as s: s.case(1, lambda: visited.append(1) or 1) s.case(2, lambda: visited.append(2) or 2, fallthrough=True) s.case(3, lambda: visited.append(3) or 3, fallthrough=True) s.case(4, lambda: visited.append(4) or 4) s.case(5, lambda: visited.append(5) or 5) - s.default(lambda: visited.append("default") or "default") + s.default(lambda: visited.append('default') or 'default') - self.assertEqual(s.result, "default") - self.assertEqual(visited, ["default"]) + self.assertEqual(s.result, 'default') + self.assertEqual(visited, ['default']) def test_empty_collection_clause_is_error(self): with self.assertRaises(ValueError): - with switch("val") as s: + with switch('val') as s: s.case([], lambda: None) - s.default(lambda: "default") + s.default(lambda: 'default') -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() From f390438df6a3434882ff01fc4105ca1a977ba0ba Mon Sep 17 00:00:00 2001 From: Michael Kennedy Date: Wed, 15 Oct 2025 17:18:50 -0700 Subject: [PATCH 3/3] ruff settings --- ruff.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ruff.toml b/ruff.toml index eee74ff..8c1e8a7 100644 --- a/ruff.toml +++ b/ruff.toml @@ -3,7 +3,7 @@ line-length = 120 format.quote-style = "single" # Enable Pyflakes `E` and `F` codes by default. -lint.select = ["E", "F"] +lint.select = ["E", "F", "I"] lint.ignore = [] # Exclude a variety of commonly ignored directories.