Skip to content
Merged
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
4 changes: 2 additions & 2 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: [ "3.13", "3.9" ]
python-version: [ "3.13", "3.10" ]
tox-command: [ "lint", "pyroma", "mypy" ]
steps:
- uses: actions/checkout@v4
Expand Down Expand Up @@ -76,7 +76,7 @@ jobs:
strategy:
matrix:
os: [ ubuntu-latest ]
python-version: [ "3.13", "3.9" ]
python-version: [ "3.13", "3.10" ]
steps:
- uses: actions/checkout@v4
- name: "Install uv"
Expand Down
2 changes: 1 addition & 1 deletion CITATION.cff
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ message: "If you use this software, please cite it as below."
title: "Class Resolver"
authors:
- name: "Charles Tapley Hoyt"
version: 0.6.2-dev
version: 0.7.0-dev
doi:
url: "https://github.com/cthoyt/class-resolver"
2 changes: 1 addition & 1 deletion docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
author = "Charles Tapley Hoyt"

# The full version, including alpha/beta/rc tags.
release = "0.6.2-dev"
release = "0.7.0-dev"

# The short X.Y version.
parsed_version = re.match(
Expand Down
12 changes: 5 additions & 7 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
[build-system]
requires = ["uv_build>=0.6.6,<0.7"]
requires = ["uv_build>=0.6.6,<1.0"]
build-backend = "uv_build"

[project]
name = "class_resolver"
version = "0.6.2-dev"
version = "0.7.0-dev"
description = "Lookup and instantiate classes with style."
readme = "README.md"
authors = [
Expand All @@ -27,7 +27,6 @@ classifiers = [
"Framework :: Sphinx",
"Natural Language :: English",
"Programming Language :: Python",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
Expand All @@ -48,9 +47,8 @@ license-files = [
"LICENSE",
]

requires-python = ">=3.9"
requires-python = ">=3.10"
dependencies = [
"importlib-metadata > 3.6; python_version<'3.10'",
"typing-extensions",
]

Expand Down Expand Up @@ -108,7 +106,7 @@ release = [
# see https://packaging.python.org/en/latest/guides/writing-pyproject-toml/#dependencies-optional-dependencies
[project.optional-dependencies]
click = [
"click<8.2"
"click>=8.2"
]
torch = [
"torch"
Expand Down Expand Up @@ -256,7 +254,7 @@ known-first-party = [
docstring-code-format = true

[tool.bumpversion]
current_version = "0.6.2-dev"
current_version = "0.7.0-dev"
parse = "(?P<major>\\d+)\\.(?P<minor>\\d+)\\.(?P<patch>\\d+)(?:-(?P<release>[0-9A-Za-z-]+(?:\\.[0-9A-Za-z-]+)*))?(?:\\+(?P<build>[0-9A-Za-z-]+(?:\\.[0-9A-Za-z-]+)*))?"
serialize = [
"{major}.{minor}.{patch}-{release}+{build}",
Expand Down
6 changes: 3 additions & 3 deletions src/class_resolver/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ def make(
**kwargs: Any,
) -> X:
"""Instantiate a class with optional kwargs."""
if query is None or isinstance(query, (str, type)):
if query is None or isinstance(query, str | type):
cls: type[X] = self.lookup(query)
try:
return cls(**(pos_kwargs or {}), **kwargs)
Expand Down Expand Up @@ -288,7 +288,7 @@ def make_many(
raise ValueError("Mismatch in number number of queries and kwargs")
return [
self.make(query=_result_tracker, pos_kwargs=_result_tracker_kwargs, **common_kwargs)
for _result_tracker, _result_tracker_kwargs in zip(_query_list, _kwargs_list)
for _result_tracker, _result_tracker_kwargs in zip(_query_list, _kwargs_list, strict=False)
]

def make_table(
Expand Down Expand Up @@ -339,7 +339,7 @@ def get_cls(
if default is None:
raise ValueError(f"No default {base.__name__} set")
return default
elif not isinstance(query, (str, type, base)):
elif not isinstance(query, str | type | base):
raise TypeError(f"Invalid {base.__name__} type: {type(query)} - {query}")
elif isinstance(query, str):
key = normalize_string(query, suffix=suffix)
Expand Down
17 changes: 6 additions & 11 deletions src/class_resolver/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,13 @@
from __future__ import annotations

import logging
import sys
from abc import ABC, abstractmethod
from collections.abc import Collection, Iterable, Iterator, Mapping
from typing import TYPE_CHECKING, Any, Callable, Generic, overload
from collections.abc import Callable, Collection, Iterable, Iterator, Mapping
from importlib.metadata import entry_points
from typing import TYPE_CHECKING, Any, Generic, overload

from typing_extensions import Self

if sys.version_info[:2] >= (3, 10):
from importlib.metadata import entry_points
else:
from importlib_metadata import entry_points

from .utils import Hint, OptionalKwargs, X, Y, make_callback, normalize_string

if TYPE_CHECKING:
Expand Down Expand Up @@ -258,7 +253,7 @@ def _get_reverse_synonyms(self) -> dict[str, list[str]]:

def _get_click_choice(
self, prefix: str | None = None, delimiter: str | None = None, suffix: str | None = None
) -> click.Choice:
) -> click.Choice[str]:
"""Get a dynamically generated :class:`click.Choice` that shows values and synonyms.

:param prefix: The string shown after the opening square bracket, before the
Expand All @@ -274,14 +269,14 @@ def _get_click_choice(
rev = self._get_reverse_synonyms()
norm_func = self.normalize

class _Choice(click.Choice):
class _Choice(click.Choice[str]):
"""An extended choice that is aware of synonyms."""

def convert(self, value: Any, param: click.Parameter | None, ctx: click.Context | None) -> Any:
"""Normalize."""
return super().convert(norm_func(value), param=param, ctx=ctx)

def get_metavar(self, param: click.Parameter) -> str:
def get_metavar(self, param: click.Parameter, ctx: click.Context) -> str:
"""Get the text that shows the choices, including synonyms."""
choices_lst = []
for key, synonyms in rev.items():
Expand Down
4 changes: 2 additions & 2 deletions src/class_resolver/contrib/numpy.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
"""NumPy is a numerical package for Python."""

from typing import Callable
from collections.abc import Callable
from typing import TypeAlias

import numpy as np
from numpy.typing import ArrayLike
from typing_extensions import TypeAlias

from ..func import FunctionResolver

Expand Down
4 changes: 2 additions & 2 deletions src/class_resolver/contrib/torch.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@
to make it possible to more easily parametrize models and training loops.
""" # noqa: D205

from typing import Callable
from collections.abc import Callable
from typing import TypeAlias

import torch
from torch import nn
from torch.nn import init
from torch.nn.modules import activation
from torch.optim import Adam, Optimizer
from torch.optim.lr_scheduler import ExponentialLR, ReduceLROnPlateau
from typing_extensions import TypeAlias

try:
# when torch >= 2.0
Expand Down
3 changes: 2 additions & 1 deletion src/class_resolver/docs.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
import inspect
import textwrap
from collections import defaultdict
from typing import Any, Callable, TypeVar
from collections.abc import Callable
from typing import Any, TypeVar

from typing_extensions import ParamSpec

Expand Down
3 changes: 2 additions & 1 deletion src/class_resolver/func.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@

from __future__ import annotations

from collections.abc import Callable
from functools import partial
from typing import Any, Callable, Generic, TypeVar
from typing import Any, Generic, TypeVar

from typing_extensions import ParamSpec

Expand Down
28 changes: 14 additions & 14 deletions src/class_resolver/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@

import collections.abc
import logging
from collections.abc import Iterable, Mapping, Sequence
from typing import TYPE_CHECKING, Any, Callable, Optional, TypeVar, Union, overload
from collections.abc import Callable, Iterable, Mapping, Sequence
from typing import TYPE_CHECKING, Any, TypeAlias, TypeVar, overload

if TYPE_CHECKING:
import click # pragma: no cover
Expand Down Expand Up @@ -37,19 +37,19 @@
Y = TypeVar("Y")

#: A type annotation for either an instance of X or a class of X
InstOrType = Union[X, type[X]]
InstOrType: TypeAlias = X | type[X]
#: A type annotation for either an instance of X or name a class X
Lookup = Union[str, X]

LookupType = Lookup[type[X]]
LookupOrType = Lookup[InstOrType[X]]
Hint = Optional[Lookup[X]]
HintType = Hint[type[X]]
HintOrType = Hint[InstOrType[X]]
OptionalKwargs = Optional[Mapping[str, Any]]
OneOrSequence = Union[X, Sequence[X]]
OneOrManyHintOrType = Optional[OneOrSequence[HintOrType[X]]]
OneOrManyOptionalKwargs = Optional[OneOrSequence[OptionalKwargs]]
Lookup: TypeAlias = str | X

LookupType: TypeAlias = Lookup[type[X]]
LookupOrType: TypeAlias = Lookup[InstOrType[X]]
Hint: TypeAlias = Lookup[X] | None
HintType: TypeAlias = Hint[type[X]]
HintOrType: TypeAlias = Hint[InstOrType[X]]
OptionalKwargs: TypeAlias = Mapping[str, Any] | None
OneOrSequence: TypeAlias = X | Sequence[X]
OneOrManyHintOrType: TypeAlias = OneOrSequence[HintOrType[X]] | None
OneOrManyOptionalKwargs: TypeAlias = OneOrSequence[OptionalKwargs] | None


def is_private(class_name: str, module_name: str, main_is_private: bool = True) -> bool:
Expand Down
2 changes: 1 addition & 1 deletion src/class_resolver/version.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@
"VERSION",
]

VERSION = "0.6.2-dev"
VERSION = "0.7.0-dev"
4 changes: 2 additions & 2 deletions tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import importlib.util
import unittest
from collections.abc import Collection, Sequence
from typing import Any, ClassVar, Optional, cast
from typing import Any, ClassVar, cast

import click
from click.testing import CliRunner, Result
Expand Down Expand Up @@ -60,7 +60,7 @@ class D(Base):
class E(Base):
"""E base class."""

def __init__(self, name: Optional[str] = None) -> None:
def __init__(self, name: str | None = None) -> None:
"""Initialize the class."""
super().__init__(name or "default_name")

Expand Down
2 changes: 1 addition & 1 deletion tests/test_function_resolver.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import operator
import unittest
from typing import Callable
from collections.abc import Callable

from class_resolver import FunctionResolver

Expand Down
Loading