From d473a171cd63fd58ce8888359dd4dcf42db4f5fa Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Tue, 22 Apr 2025 12:42:24 +0000 Subject: [PATCH 1/2] Format with ruff --- extras/__init__.py | 17 +++++---- extras/tests/__init__.py | 5 ++- extras/tests/test_extras.py | 74 +++++++++++++++++++------------------ setup.py | 48 ++++++++++++------------ 4 files changed, 75 insertions(+), 69 deletions(-) diff --git a/extras/__init__.py b/extras/__init__.py index 1ac6a01..3b33ef1 100644 --- a/extras/__init__.py +++ b/extras/__init__.py @@ -5,9 +5,9 @@ import sys __all__ = [ - 'try_import', - 'try_imports', - ] + "try_import", + "try_imports", +] # same format as sys.version_info: "A tuple containing the five components of # the version number: major, minor, micro, releaselevel, and serial. All @@ -21,7 +21,7 @@ # If the releaselevel is 'final', then the tarball will be major.minor.micro. # Otherwise it is major.minor.micro~$(revno). -__version__ = (1, 0, 0, 'final', 0) +__version__ = (1, 0, 0, "final", 0) def try_import(name, alternative=None, error_callback=None): @@ -37,14 +37,14 @@ def try_import(name, alternative=None, error_callback=None): :param error_callback: If non-None, a callable that is passed the ImportError when the module cannot be loaded. """ - module_segments = name.split('.') + module_segments = name.split(".") last_error = None remainder = [] # module_name will be what successfully imports. We cannot walk from the # __import__ result because in import loops (A imports A.B, which imports # C, which calls try_import("A.B")) A.B will not yet be set. while module_segments: - module_name = '.'.join(module_segments) + module_name = ".".join(module_segments) try: __import__(module_name) except ImportError: @@ -69,6 +69,8 @@ def try_import(name, alternative=None, error_callback=None): _RAISE_EXCEPTION = object() + + def try_imports(module_names, alternative=_RAISE_EXCEPTION, error_callback=None): """Attempt to import modules. @@ -92,6 +94,5 @@ def try_imports(module_names, alternative=_RAISE_EXCEPTION, error_callback=None) if module: return module if alternative is _RAISE_EXCEPTION: - raise ImportError( - "Could not import any of: %s" % ', '.join(module_names)) + raise ImportError("Could not import any of: %s" % ", ".join(module_names)) return alternative diff --git a/extras/tests/__init__.py b/extras/tests/__init__.py index e0d7d4a..0946e38 100644 --- a/extras/tests/__init__.py +++ b/extras/tests/__init__.py @@ -8,10 +8,11 @@ def test_suite(): from extras.tests import ( test_extras, - ) + ) + modules = [ test_extras, - ] + ] loader = TestLoader() suites = map(loader.loadTestsFromModule, modules) return TestSuite(suites) diff --git a/extras/tests/test_extras.py b/extras/tests/test_extras.py index b01dfb6..543dc40 100644 --- a/extras/tests/test_extras.py +++ b/extras/tests/test_extras.py @@ -8,15 +8,15 @@ Equals, Is, Not, - ) +) from extras import ( try_import, try_imports, - ) +) -def check_error_callback(test, function, arg, expected_error_count, - expect_result): + +def check_error_callback(test, function, arg, expected_error_count, expect_result): """General test template for error_callback argument. :param test: Test case instance. @@ -27,9 +27,11 @@ def check_error_callback(test, function, arg, expected_error_count, ultimately be returned or not. """ cb_calls = [] + def cb(e): test.assertIsInstance(e, ImportError) cb_calls.append(e) + try: result = function(arg, error_callback=cb) except ImportError: @@ -43,58 +45,60 @@ def cb(e): class TestTryImport(TestCase): - def test_doesnt_exist(self): # try_import('thing', foo) returns foo if 'thing' doesn't exist. marker = object() - result = try_import('doesntexist', marker) + result = try_import("doesntexist", marker) self.assertThat(result, Is(marker)) def test_None_is_default_alternative(self): # try_import('thing') returns None if 'thing' doesn't exist. - result = try_import('doesntexist') + result = try_import("doesntexist") self.assertThat(result, Is(None)) def test_existing_module(self): # try_import('thing', foo) imports 'thing' and returns it if it's a # module that exists. - result = try_import('os', object()) + result = try_import("os", object()) import os + self.assertThat(result, Is(os)) def test_existing_submodule(self): # try_import('thing.another', foo) imports 'thing' and returns it if # it's a module that exists. - result = try_import('os.path', object()) + result = try_import("os.path", object()) import os + self.assertThat(result, Is(os.path)) def test_nonexistent_submodule(self): # try_import('thing.another', foo) imports 'thing' and returns foo if # 'another' doesn't exist. marker = object() - result = try_import('os.doesntexist', marker) + result = try_import("os.doesntexist", marker) self.assertThat(result, Is(marker)) def test_object_from_module(self): # try_import('thing.object') imports 'thing' and returns # 'thing.object' if 'thing' is a module and 'object' is not. - result = try_import('os.path.join') + result = try_import("os.path.join") import os + self.assertThat(result, Is(os.path.join)) def test_error_callback(self): # the error callback is called on failures. - check_error_callback(self, try_import, 'doesntexist', 1, False) + check_error_callback(self, try_import, "doesntexist", 1, False) def test_error_callback_missing_module_member(self): # the error callback is called on failures to find an object # inside an existing module. - check_error_callback(self, try_import, 'os.nonexistent', 1, False) + check_error_callback(self, try_import, "os.nonexistent", 1, False) def test_error_callback_not_on_success(self): # the error callback is not called on success. - check_error_callback(self, try_import, 'os.path', 0, True) + check_error_callback(self, try_import, "os.path", 0, True) def test_handle_partly_imported_name(self): # try_import('thing.other') when thing.other is mid-import @@ -114,62 +118,60 @@ def test_handle_partly_imported_name(self): class TestTryImports(TestCase): - def test_doesnt_exist(self): # try_imports('thing', foo) returns foo if 'thing' doesn't exist. marker = object() - result = try_imports(['doesntexist'], marker) + result = try_imports(["doesntexist"], marker) self.assertThat(result, Is(marker)) def test_fallback(self): - result = try_imports(['doesntexist', 'os']) + result = try_imports(["doesntexist", "os"]) import os + self.assertThat(result, Is(os)) def test_None_is_default_alternative(self): # try_imports('thing') returns None if 'thing' doesn't exist. - e = self.assertRaises( - ImportError, try_imports, ['doesntexist', 'noreally']) + e = self.assertRaises(ImportError, try_imports, ["doesntexist", "noreally"]) self.assertThat( - str(e), - Equals("Could not import any of: doesntexist, noreally")) + str(e), Equals("Could not import any of: doesntexist, noreally") + ) def test_existing_module(self): # try_imports('thing', foo) imports 'thing' and returns it if it's a # module that exists. - result = try_imports(['os'], object()) + result = try_imports(["os"], object()) import os + self.assertThat(result, Is(os)) def test_existing_submodule(self): # try_imports('thing.another', foo) imports 'thing' and returns it if # it's a module that exists. - result = try_imports(['os.path'], object()) + result = try_imports(["os.path"], object()) import os + self.assertThat(result, Is(os.path)) def test_nonexistent_submodule(self): # try_imports('thing.another', foo) imports 'thing' and returns foo if # 'another' doesn't exist. marker = object() - result = try_imports(['os.doesntexist'], marker) + result = try_imports(["os.doesntexist"], marker) self.assertThat(result, Is(marker)) def test_fallback_submodule(self): - result = try_imports(['os.doesntexist', 'os.path']) + result = try_imports(["os.doesntexist", "os.path"]) import os + self.assertThat(result, Is(os.path)) def test_error_callback(self): # One error for every class that doesn't exist. - check_error_callback(self, try_imports, - ['os.doesntexist', 'os.notthiseither'], - 2, False) - check_error_callback(self, try_imports, - ['os.doesntexist', 'os.notthiseither', 'os'], - 2, True) - check_error_callback(self, try_imports, - ['os.path'], - 0, True) - - + check_error_callback( + self, try_imports, ["os.doesntexist", "os.notthiseither"], 2, False + ) + check_error_callback( + self, try_imports, ["os.doesntexist", "os.notthiseither", "os"], 2, True + ) + check_error_callback(self, try_imports, ["os.path"], 0, True) diff --git a/setup.py b/setup.py index a30f72f..879f7f5 100755 --- a/setup.py +++ b/setup.py @@ -5,37 +5,38 @@ import os.path import extras -testtools_cmd = extras.try_import('testtools.TestCommand') + +testtools_cmd = extras.try_import("testtools.TestCommand") def get_version(): """Return the version of extras that we are building.""" - version = '.'.join( - str(component) for component in extras.__version__[0:3]) + version = ".".join(str(component) for component in extras.__version__[0:3]) return version def get_long_description(): - readme_path = os.path.join( - os.path.dirname(__file__), 'README.rst') + readme_path = os.path.join(os.path.dirname(__file__), "README.rst") return open(readme_path).read() cmdclass = {} if testtools_cmd is not None: - cmdclass['test'] = testtools_cmd - - -setup(name='extras', - author='Testing cabal', - author_email='testtools-dev@lists.launchpad.net', - url='https://github.com/testing-cabal/extras', - description=('Useful extra bits for Python - things that should be ' - 'in the standard library'), - long_description=get_long_description(), - version=get_version(), - classifiers=[ + cmdclass["test"] = testtools_cmd + + +setup( + name="extras", + author="Testing cabal", + author_email="testtools-dev@lists.launchpad.net", + url="https://github.com/testing-cabal/extras", + description=( + "Useful extra bits for Python - things that should be in the standard library" + ), + long_description=get_long_description(), + version=get_version(), + classifiers=[ "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Programming Language :: Python", @@ -48,9 +49,10 @@ def get_long_description(): "Programming Language :: Python :: 3.11", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", - ], - packages=[ - 'extras', - 'extras.tests', - ], - cmdclass=cmdclass) + ], + packages=[ + "extras", + "extras.tests", + ], + cmdclass=cmdclass, +) From 116ff4d6078c34e62f98d4320a54d9ab20ea2719 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Tue, 22 Apr 2025 12:42:49 +0000 Subject: [PATCH 2/2] github: check formatting with ruff --- .github/workflows/python-package.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/python-package.yml b/.github/workflows/python-package.yml index f604dd2..100ced8 100644 --- a/.github/workflows/python-package.yml +++ b/.github/workflows/python-package.yml @@ -23,6 +23,10 @@ jobs: run: | python -m pip install --upgrade pip python -m pip install testtools + python -m pip install ruff - name: Test with testtools run: | python -m testtools.run extras.tests.test_suite + - name: Lint with ruff + run: | + python -m ruff check .