Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ classifiers = [
"Programming Language :: Python",
"Typing :: Typed",
]
requires-python = ">=3.9"
requires-python = ">=3.10"
dynamic = ["version"]

[project.urls]
Expand All @@ -31,7 +31,8 @@ Tracker = "https://github.com/ipython/traitlets/issues"

[project.optional-dependencies]
test = [
"argcomplete>=3.0.3",
"argcomplete>=3.0.3; python_version < '3.12'",
"argcomplete>=3.5.2; python_version >= '3.12'",
# See https://github.com/python/mypy/issues/20329 for PyPy support issue.
# Also, test assertions will need to be updated for 1.20+ because
# `reveal_type()` representations were simplified in
Expand All @@ -40,7 +41,7 @@ test = [
"pre-commit",
"pytest-mock",
"pytest-mypy-testing",
"pytest>=7.0,<8.2",
"pytest>=7.0,<10.0",
]
docs = [
"myst-parser",
Expand Down Expand Up @@ -189,8 +190,7 @@ ignore = [
"S105", "S106", # Possible hardcoded password
"S110", # S110 `try`-`except`-`pass` detected
"RUF012", # Mutable class attributes should be annotated with `typing.ClassVar`
"UP006", # non-pep585-annotation
"UP007", # non-pep604-annotation
"UP038", # non-pep604-isinstance (removed in ruff 0.13.0)
"ARG001", "ARG002", # Unused function argument
"RET503", # Missing explicit `return` at the end of function
"RET505", # Unnecessary `else` after `return` statement
Expand Down
4 changes: 2 additions & 2 deletions tests/config/test_application.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ class MyApp(Application):
help="Should print a warning if `MyApp.warn-typo=...` command is passed",
)

aliases: t.Dict[t.Any, t.Any] = {}
aliases: dict[t.Any, t.Any] = {}
aliases.update(Application.aliases)
aliases.update(
{
Expand All @@ -83,7 +83,7 @@ class MyApp(Application):
}
)

flags: t.Dict[t.Any, t.Any] = {}
flags: dict[t.Any, t.Any] = {}
flags.update(Application.flags)
flags.update(
{
Expand Down
6 changes: 3 additions & 3 deletions tests/config/test_argcomplete.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
class ArgcompleteApp(Application):
"""Override loader to pass through kwargs for argcomplete testing"""

argcomplete_kwargs: t.Dict[str, t.Any]
argcomplete_kwargs: dict[str, t.Any]

def __init__(self, *args, **kwargs):
# For subcommands, inherit argcomplete_kwargs from parent app
Expand Down Expand Up @@ -99,9 +99,9 @@ def run_completer(
self,
app: ArgcompleteApp,
command: str,
point: t.Union[str, int, None] = None,
point: str | int | None = None,
**kwargs: t.Any,
) -> t.List[str]:
) -> list[str]:
"""Mostly borrowed from argcomplete's unit tests

Modified to take an application instead of an ArgumentParser
Expand Down
18 changes: 9 additions & 9 deletions tests/test_traitlets.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@

def change_dict(*ordered_values):
change_names = ("name", "old", "new", "owner", "type")
return dict(zip(change_names, ordered_values))
return dict(zip(change_names, ordered_values, strict=True))


# -----------------------------------------------------------------------------
Expand Down Expand Up @@ -1650,7 +1650,7 @@ class ListTrait(HasTraits):
class TestList(TraitTestBase):
obj = ListTrait()

_default_value: t.List[t.Any] = []
_default_value: list[t.Any] = []
_good_values = [[], [1], list(range(10)), (1, 2)]
_bad_values = [10, [1, "a"], "a"]

Expand All @@ -1667,7 +1667,7 @@ class SetTrait(HasTraits):
class TestSet(TraitTestBase):
obj = SetTrait()

_default_value: t.Set[str] = set()
_default_value: set[str] = set()
_good_values = [{"a", "b"}, "ab"]
_bad_values = [1]

Expand All @@ -1689,7 +1689,7 @@ class NoneInstanceListTrait(HasTraits):
class TestNoneInstanceList(TraitTestBase):
obj = NoneInstanceListTrait()

_default_value: t.List[t.Any] = []
_default_value: list[t.Any] = []
_good_values = [[Foo(), Foo()], []]
_bad_values = [[None], [Foo(), None]]

Expand All @@ -1705,7 +1705,7 @@ def test_klass(self):
"""Test that the instance klass is properly assigned."""
self.assertIs(self.obj.traits()["value"]._trait.klass, Foo)

_default_value: t.List[t.Any] = []
_default_value: list[t.Any] = []
_good_values = [[Foo(), Foo()], []]
_bad_values = [
[
Expand All @@ -1725,7 +1725,7 @@ class UnionListTrait(HasTraits):
class TestUnionListTrait(TraitTestBase):
obj = UnionListTrait()

_default_value: t.List[t.Any] = []
_default_value: list[t.Any] = []
_good_values = [[True, 1], [False, True]]
_bad_values = [[1, "True"], False]

Expand Down Expand Up @@ -1881,7 +1881,7 @@ class DictTrait(HasTraits):


def test_dict_assignment():
d: t.Dict[str, int] = {}
d: dict[str, int] = {}
c = DictTrait()
c.value = d
d["a"] = 5
Expand Down Expand Up @@ -2504,7 +2504,7 @@ def test_klass(self):
"""Test that the instance klass is properly assigned."""
self.assertIs(self.obj.traits()["value"]._trait.klass, ForwardDeclaredBar)

_default_value: t.List[t.Any] = []
_default_value: list[t.Any] = []
_good_values = [
[ForwardDeclaredBar(), ForwardDeclaredBarSub()],
[],
Expand All @@ -2527,7 +2527,7 @@ def test_klass(self):
"""Test that the instance klass is properly assigned."""
self.assertIs(self.obj.traits()["value"]._trait.klass, ForwardDeclaredBar)

_default_value: t.List[t.Any] = []
_default_value: list[t.Any] = []
_good_values = [
[ForwardDeclaredBar, ForwardDeclaredBarSub],
[],
Expand Down
2 changes: 1 addition & 1 deletion tests/test_typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,7 @@ class T(HasTraits):
reveal_type(
T.ob # R: traitlets.traitlets.Bool[builtins.bool | None, builtins.bool | builtins.int | None]
)
# we would expect this to be Optional[bool | int], but...
# we would expect this to be bool | int | None, but...
t.b = "foo" # E: Incompatible types in assignment (expression has type "str", variable has type "bool | int") [assignment]
t.b = None # E: Incompatible types in assignment (expression has type "None", variable has type "bool | int") [assignment]

Expand Down
10 changes: 5 additions & 5 deletions traitlets/config/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,9 +98,9 @@

T = t.TypeVar("T", bound=t.Callable[..., t.Any])
AnyLogger = t.Union[logging.Logger, "logging.LoggerAdapter[t.Any]"]
StrDict = t.Dict[str, t.Any]
ArgvType = t.Optional[t.List[str]]
ClassesType = t.List[t.Type[Configurable]]
StrDict = dict[str, t.Any]
ArgvType = list[str] | None
ClassesType = list[type[Configurable]]


def catch_config_error(method: T) -> T:
Expand Down Expand Up @@ -520,7 +520,7 @@ def emit_alias_help(self) -> t.Generator[str, None, None]:
for cls in self.classes:
# include all parents (up to, but excluding Configurable) in available names
for c in cls.mro()[:-3]:
classdict[c.__name__] = t.cast(t.Type[Configurable], c)
classdict[c.__name__] = t.cast(type[Configurable], c)

fhelp: str | None
for alias, longname in self.aliases.items():
Expand Down Expand Up @@ -931,7 +931,7 @@ def _load_config_files(
if log:
log.debug("Loaded config file: %s", loader.full_filename)
if config:
for filename, earlier_config in zip(filenames, loaded):
for filename, earlier_config in zip(filenames, loaded, strict=True):
collisions = earlier_config.collisions(config)
if collisions and log:
log.warning(
Expand Down
20 changes: 9 additions & 11 deletions traitlets/config/argcomplete_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ def __getattr__(self, attr: str) -> t.Any:
CompletionFinder = object # type:ignore[assignment, misc]


def get_argcomplete_cwords() -> t.Optional[t.List[str]]:
def get_argcomplete_cwords() -> list[str] | None:
"""Get current words prior to completion point

This is normally done in the `argcomplete.CompletionFinder` constructor,
Expand All @@ -37,7 +37,7 @@ def get_argcomplete_cwords() -> t.Optional[t.List[str]]:
comp_line = os.environ["COMP_LINE"]
comp_point = int(os.environ["COMP_POINT"])
# argcomplete.debug("splitting COMP_LINE for:", comp_line, comp_point)
comp_words: t.List[str]
comp_words: list[str]
try:
(
cword_prequote,
Expand Down Expand Up @@ -98,10 +98,10 @@ class in `Application.classes` that could complete the current option.
"""

_parser: argparse.ArgumentParser
config_classes: t.List[t.Any] = [] # Configurables
subcommands: t.List[str] = []
config_classes: list[t.Any] = [] # Configurables
subcommands: list[str] = []

def match_class_completions(self, cword_prefix: str) -> t.List[t.Tuple[t.Any, str]]:
def match_class_completions(self, cword_prefix: str) -> list[tuple[t.Any, str]]:
"""Match the word to be completed against our Configurable classes

Check if cword_prefix could potentially match against --{class}. for any class
Expand Down Expand Up @@ -146,9 +146,7 @@ def inject_class_to_parser(self, cls: t.Any) -> None:
except AttributeError:
pass

def _get_completions(
self, comp_words: t.List[str], cword_prefix: str, *args: t.Any
) -> t.List[str]:
def _get_completions(self, comp_words: list[str], cword_prefix: str, *args: t.Any) -> list[str]:
"""Overridden to dynamically append --Class.trait arguments if appropriate

Warning:
Expand Down Expand Up @@ -187,7 +185,7 @@ def _get_completions(
self.inject_class_to_parser(matched_cls)
break

completions: t.List[str]
completions: list[str]
completions = super()._get_completions(comp_words, cword_prefix, *args) # type:ignore[no-untyped-call]

# For subcommand-handling: it is difficult to get this to work
Expand All @@ -203,9 +201,9 @@ def _get_completions(

def _get_option_completions(
self, parser: argparse.ArgumentParser, cword_prefix: str
) -> t.List[str]:
) -> list[str]:
"""Overridden to add --Class. completions when appropriate"""
completions: t.List[str]
completions: list[str]
completions = super()._get_option_completions(parser, cword_prefix) # type:ignore[no-untyped-call]
if cword_prefix.endswith("."):
return completions
Expand Down
2 changes: 1 addition & 1 deletion traitlets/config/configurable.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
# -----------------------------------------------------------------------------

if t.TYPE_CHECKING:
LoggerType = t.Union[logging.Logger, logging.LoggerAdapter[t.Any]]
LoggerType = logging.Logger | logging.LoggerAdapter[t.Any]
else:
LoggerType = t.Any

Expand Down
4 changes: 2 additions & 2 deletions traitlets/config/loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -420,7 +420,7 @@ def __repr__(self) -> str:
return f"{self.__class__.__name__}({self._super_repr()})"


class DeferredConfigList(t.List[t.Any], DeferredConfig):
class DeferredConfigList(list[t.Any], DeferredConfig):
"""Config value for loading config from a list of strings

Interpretation is deferred until it is loaded into the trait.
Expand Down Expand Up @@ -791,7 +791,7 @@ def parse_known_args( # type:ignore[override]


# type aliases
SubcommandsDict = t.Dict[str, t.Any]
SubcommandsDict = dict[str, t.Any]


class ArgParseConfigLoader(CommandLineConfigLoader):
Expand Down
Loading
Loading