From 5eeed47705a577f196c69efb03756bf4b38b9981 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 4 Aug 2026 08:12:10 +0000 Subject: [PATCH] Update ruff pre-commit hook to v0.16.1 and fix lint issues Ruff 0.16 greatly expanded its default rule set. Fix the newly surfaced issues (TRY201, TRY203, TRY004, FLY002, LOG001, LOG009, stale noqa directives) and ignore BLE001 (blind except), matching this codebase's existing style of deliberate broad exception handling for defensive fallbacks. --- .pre-commit-config.yaml | 2 +- docs/source/conf.py | 2 +- pyproject.toml | 1 + tests/config/test_application.py | 12 ++++++------ tests/config/test_loader.py | 2 +- tests/test_traitlets.py | 6 +++--- tests/test_typing.py | 2 +- traitlets/config/__init__.py | 2 +- traitlets/config/application.py | 10 +++++----- traitlets/traitlets.py | 18 +++++++++--------- traitlets/utils/text.py | 2 +- 11 files changed, 30 insertions(+), 29 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 104180872..a6e915162 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -68,7 +68,7 @@ repos: - id: rst-inline-touching-normal - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.15.22 + rev: v0.16.1 hooks: - id: ruff-check types_or: [python, jupyter] diff --git a/docs/source/conf.py b/docs/source/conf.py index 47c8b4876..1cbbcd361 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -23,7 +23,7 @@ HERE = osp.abspath(osp.dirname(__file__)) ROOT = osp.dirname(osp.dirname(HERE)) -from traitlets import __version__, version_info # noqa: E402 +from traitlets import __version__, version_info # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the diff --git a/pyproject.toml b/pyproject.toml index 831ab0d8d..0d0679c93 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -232,6 +232,7 @@ ignore = [ "E501", # Line too long "S105", "S106", # Possible hardcoded password "S110", # S110 `try`-`except`-`pass` detected + "BLE001", # Do not catch blind exception: `Exception` (used deliberately for defensive fallbacks) "RUF012", # Mutable class attributes should be annotated with `typing.ClassVar` "ARG001", "ARG002", # Unused function argument "RET503", # Missing explicit `return` at the end of function diff --git a/tests/config/test_application.py b/tests/config/test_application.py index 59b7d1be6..fc0ec2911 100644 --- a/tests/config/test_application.py +++ b/tests/config/test_application.py @@ -488,11 +488,11 @@ def test_warn_autocorrect(self): def test_flatten_flags(self): cfg = Config() - cfg.MyApp.log_level = logging.WARN + cfg.MyApp.log_level = logging.WARNING app = MyApp() app.update_config(cfg) - self.assertEqual(app.log_level, logging.WARN) - self.assertEqual(app.config.MyApp.log_level, logging.WARN) + self.assertEqual(app.log_level, logging.WARNING) + self.assertEqual(app.config.MyApp.log_level, logging.WARNING) app.initialize(["--crit"]) self.assertEqual(app.log_level, logging.CRITICAL) # this would be app.config.Application.log_level if it failed: @@ -500,11 +500,11 @@ def test_flatten_flags(self): def test_flatten_aliases(self): cfg = Config() - cfg.MyApp.log_level = logging.WARN + cfg.MyApp.log_level = logging.WARNING app = MyApp() app.update_config(cfg) - self.assertEqual(app.log_level, logging.WARN) - self.assertEqual(app.config.MyApp.log_level, logging.WARN) + self.assertEqual(app.log_level, logging.WARNING) + self.assertEqual(app.config.MyApp.log_level, logging.WARNING) app.initialize(["--log-level", "CRITICAL"]) self.assertEqual(app.log_level, logging.CRITICAL) # this would be app.config.Application.log_level if it failed: diff --git a/tests/config/test_loader.py b/tests/config/test_loader.py index a39eadfc8..dcccb5a19 100644 --- a/tests/config/test_loader.py +++ b/tests/config/test_loader.py @@ -536,7 +536,7 @@ def test_deepcopy(self): c1.Foo.bam = 30 c1.a = "asdf" c1.b = range(10) - c1.Test.logger = logging.Logger("test") + c1.Test.logger = logging.Logger("test") # noqa: LOG001 c1.Test.get_logger = logging.getLogger("test") c2 = copy.deepcopy(c1) self.assertEqual(c1, c2) diff --git a/tests/test_traitlets.py b/tests/test_traitlets.py index 3e9377fa8..2e7b8459a 100644 --- a/tests/test_traitlets.py +++ b/tests/test_traitlets.py @@ -2190,7 +2190,7 @@ def another_update(self, change): self.i = change.new * 2 mc = MyClass() - l = link((mc, "i"), (mc, "j")) # noqa: E741 + l = link((mc, "i"), (mc, "j")) self.assertRaises(TraitError, setattr, mc, "i", 2) def test_link_broken_at_target(self): @@ -2203,7 +2203,7 @@ def another_update(self, change): self.j = change.new * 2 mc = MyClass() - l = link((mc, "i"), (mc, "j")) # noqa: E741 + l = link((mc, "i"), (mc, "j")) self.assertRaises(TraitError, setattr, mc, "j", 2) @@ -2433,7 +2433,7 @@ class OrderTraits(HasTraits): i = Unicode() j = Unicode() k = Unicode() - l = Unicode() # noqa: E741 + l = Unicode() def _notify(self, name, old, new): """check the value of all traits when each trait change is triggered diff --git a/tests/test_typing.py b/tests/test_typing.py index 44b3a32e6..592955d78 100644 --- a/tests/test_typing.py +++ b/tests/test_typing.py @@ -215,7 +215,7 @@ def mypy_enum_typing() -> None: class T(HasTraits): log_level = Enum( (0, 10, 20, 30, 40, 50), - default_value=logging.WARN, + default_value=logging.WARNING, help="Set the log level by value or name.", ).tag(config=True) diff --git a/traitlets/config/__init__.py b/traitlets/config/__init__.py index 2f7b7b0e7..8d20fb2d0 100644 --- a/traitlets/config/__init__.py +++ b/traitlets/config/__init__.py @@ -6,7 +6,7 @@ from .configurable import * from .loader import Config -__all__ = [ # noqa: F405 +__all__ = [ "Application", "ApplicationError", "Config", diff --git a/traitlets/config/application.py b/traitlets/config/application.py index dc80ab123..2027bcb13 100644 --- a/traitlets/config/application.py +++ b/traitlets/config/application.py @@ -134,7 +134,7 @@ class LevelFormatter(logging.Formatter): without adding 'INFO' to info, etc. """ - highlevel_limit = logging.WARN + highlevel_limit = logging.WARNING highlevel_format = " %(levelname)s |" def format(self, record: logging.LogRecord) -> str: @@ -204,7 +204,7 @@ def _classes_inc_parents( # The log level for the application log_level = Enum( (0, 10, 20, 30, 40, 50, "DEBUG", "INFO", "WARN", "ERROR", "CRITICAL"), - default_value=logging.WARN, + default_value=logging.WARNING, help="Set the log level by value or name.", ).tag(config=True) @@ -717,7 +717,7 @@ def initialize_subcommand(self, subc: str, argv: ArgvType = None) -> None: # or ask factory to create it... self.subapp = subapp(self) else: - raise AssertionError(f"Invalid mappings for subcommand '{subc}'!") + raise TypeError(f"Invalid mappings for subcommand '{subc}'!") # ... and finally initialize subapp. self.subapp.initialize(argv) @@ -757,7 +757,7 @@ def flatten_flags(self) -> tuple[dict[str, t.Any], dict[str, t.Any]]: if not isinstance(alias, tuple): # type:ignore[unreachable] alias = (alias,) # type:ignore[assignment] for al in alias: - aliases[al] = ".".join([cls, trait]) + aliases[al] = f"{cls}.{trait}" # flatten flags, which are of the form: # { 'key' : ({'Cls' : {'trait' : value}}, 'help')} @@ -881,7 +881,7 @@ def parse_command_line(self, argv: ArgvType = None) -> None: loader = self._create_loader(argv, aliases, flags, classes=classes) try: self.cli_config = deepcopy(loader.load_config()) - except SystemExit: + except SystemExit: # noqa: TRY203 # traitlets 5: no longer print help output on error # help output is huge, and comes after the error raise diff --git a/traitlets/traitlets.py b/traitlets/traitlets.py index 5e066aee4..0989ea981 100644 --- a/traitlets/traitlets.py +++ b/traitlets/traitlets.py @@ -1494,7 +1494,7 @@ def hold(change: Bunch) -> None: trait = getattr(self.__class__, name) value = trait._cross_validate(self, getattr(self, name)) self.set_trait(name, value) - except TraitError as e: + except TraitError: # Roll back in case of TraitError during final cross validation. self.notify_change = lambda x: None # type:ignore[method-assign, assignment] # noqa: ARG005 for name, changes in cache.items(): @@ -1506,7 +1506,7 @@ def hold(change: Bunch) -> None: else: self._trait_values.pop(name) cache = {} - raise e + raise finally: self._cross_validation_lock = False # Restore method retrieval from class @@ -2024,8 +2024,8 @@ class Type(ClassBasedTraitType[G, S]): @t.overload def __init__( self: Type[type, type], - default_value: Sentinel | None | str = ..., - klass: None | str = ..., + default_value: Sentinel | str | None = ..., + klass: str | None = ..., allow_none: Literal[False] = ..., read_only: bool | None = ..., help: str | None = ..., @@ -2036,8 +2036,8 @@ def __init__( @t.overload def __init__( self: Type[type | None, type | None], - default_value: Sentinel | None | str = ..., - klass: None | str = ..., + default_value: Sentinel | str | None = ..., + klass: str | None = ..., allow_none: Literal[True] = ..., read_only: bool | None = ..., help: str | None = ..., @@ -2345,7 +2345,7 @@ def _resolve_string(self, string: str) -> t.Any: our this_class attribute was defined. """ modname = self.this_class.__module__ # type:ignore[attr-defined] - return import_item(".".join([modname, string])) + return import_item(f"{modname}.{string}") class ForwardDeclaredType(ForwardDeclaredMixin, Type[G, S]): @@ -4138,7 +4138,7 @@ def __init__( @t.overload def __init__( self: TCPAddress[tuple[str, int] | None, tuple[str, int] | None], - default_value: bool | None | Sentinel = ..., + default_value: bool | Sentinel | None = ..., allow_none: Literal[True] = ..., read_only: bool | None = ..., help: str | None = ..., @@ -4149,7 +4149,7 @@ def __init__( def __init__( self: TCPAddress[tuple[str, int] | None, tuple[str, int] | None] | TCPAddress[tuple[str, int], tuple[str, int]], - default_value: bool | None | Sentinel = Undefined, + default_value: bool | Sentinel | None = Undefined, allow_none: Literal[True, False] = False, read_only: bool | None = None, help: str | None = None, diff --git a/traitlets/utils/text.py b/traitlets/utils/text.py index b0136964f..8611f236f 100644 --- a/traitlets/utils/text.py +++ b/traitlets/utils/text.py @@ -29,7 +29,7 @@ def _dedent(text: str) -> str: first, rest = splits # dedent everything but the first line rest = textwrap.dedent(rest) - return "\n".join([first, rest]) + return f"{first}\n{rest}" def wrap_paragraphs(text: str, ncols: int = 80) -> list[str]: