Skip to content

Fix typing interface to align with std Enum classes#145

Merged
bckohan merged 8 commits intomainfrom
hints
Feb 9, 2026
Merged

Fix typing interface to align with std Enum classes#145
bckohan merged 8 commits intomainfrom
hints

Conversation

@bckohan
Copy link
Owner

@bckohan bckohan commented Feb 9, 2026

fixes #144

We had to add a stub file to do this.

Copilot AI review requested due to automatic review settings February 9, 2026 07:43
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR addresses #144 by improving the library’s static typing story so enums derived from enum-properties expose the same type-hint interface as standard library Enum classes. It does this primarily by introducing a shipped .pyi stub for enum_properties and adding dedicated type-hint probe tests, while also bumping the package to v2.5.0 and dropping Python 3.9 support.

Changes:

  • Add src/enum_properties/__init__.pyi to provide a typed public API aligned with stdlib Enum/Flag behaviors.
  • Add a new tests/type_hints/ suite to probe typing behavior (mypy/pyright) and expand typing tool configs to include these tests.
  • Raise minimum supported Python to 3.10 (update pyproject.toml, CI matrices, and lockfile), plus doc/changelog/version updates.

Reviewed changes

Copilot reviewed 14 out of 16 changed files in this pull request and generated 17 comments.

Show a summary per file
File Description
src/enum_properties/__init__.pyi New public type stub defining metaclass + enum bases to match stdlib typing expectations.
tests/type_hints/test.py New typing probe test module validating Enum/Flag behaviors and member typing.
pyproject.toml Bumps version/min Python and updates mypy/pyright scope to include typing tests.
.github/workflows/test.yml Drops Python 3.9 from test matrix to match new min version.
.github/workflows/lint.yml Drops Python 3.9 from lint matrix; still runs typing checks.
uv.lock Lockfile updated for new Python constraint and dependency set.
tests/annotations/test.py Typing-related tweaks (overloads/ignores) to satisfy checkers.
tests/annotations/test_flags.py Renames nested test enums to avoid collisions/shadowing.
doc/source/changelog.rst Adds v2.5.0 entry referencing #144 and stub shipping.
justfile Updates docs-live paths.
LICENSE Updates copyright year.
CONTRIBUTING.md Updates docs/test instructions.
.pre-commit-config.yaml Removes typing pre-commit hook.
tests/type_hints/pyright.json Adds a local pyright config for typing tests.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +68 to +80
@overload
def __call__(
cls,
value: str,
names: str | Iterable[str] | Iterable[Iterable[str | Any]] | Mapping[str, Any],
*,
module: str | None = None,
qualname: str | None = None,
type: type | None = None,
start: int = 1,
boundary: enum.FlagBoundary | None = None,
) -> type[enum.Enum]: ...
@overload
Copy link

Copilot AI Feb 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The stub references enum.FlagBoundary, which is not available on Python 3.10. Because the package supports 3.10, this can cause type-checking failures when running mypy/pyright under 3.10. Consider guarding this type with a sys.version_info check in the stub or using a looser type (e.g., Any) for the boundary parameter on <3.11.

Suggested change
@overload
def __call__(
cls,
value: str,
names: str | Iterable[str] | Iterable[Iterable[str | Any]] | Mapping[str, Any],
*,
module: str | None = None,
qualname: str | None = None,
type: type | None = None,
start: int = 1,
boundary: enum.FlagBoundary | None = None,
) -> type[enum.Enum]: ...
@overload
if sys.version_info >= (3, 11):
@overload
def __call__(
cls,
value: str,
names: str | Iterable[str] | Iterable[Iterable[str | Any]] | Mapping[str, Any],
*,
module: str | None = None,
qualname: str | None = None,
type: type | None = None,
start: int = 1,
boundary: enum.FlagBoundary | None = None,
) -> type[enum.Enum]: ...
else:
@overload
def __call__(
cls,
value: str,
names: str | Iterable[str] | Iterable[Iterable[str | Any]] | Mapping[str, Any],
*,
module: str | None = None,
qualname: str | None = None,
type: type | None = None,
start: int = 1,
boundary: Any = None,
) -> type[enum.Enum]: ...
@overload

Copilot uses AI. Check for mistakes.
self.assertTrue((0, 1, 0) != Color.RED)
self.assertTrue(Color.RED == "0xFF0000")
self.assertTrue("0xFF0000" == Color.RED)
self.assertTrue(Color2.RED == (1, 0, 0))
Copy link

Copilot AI Feb 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

assertTrue(a == b) cannot provide an informative message. Using assertEqual(a, b) instead will give more informative messages.

Suggested change
self.assertTrue(Color2.RED == (1, 0, 0))
self.assertEqual(Color2.RED, (1, 0, 0))

Copilot uses AI. Check for mistakes.
from __future__ import annotations

from enum import Enum, Flag, IntEnum, IntFlag, StrEnum
from typing import TYPE_CHECKING, Any, Literal
Copy link

Copilot AI Feb 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Import of 'TYPE_CHECKING' is not used.

Suggested change
from typing import TYPE_CHECKING, Any, Literal
from typing import Any, Literal

Copilot uses AI. Check for mistakes.
Comment on lines +888 to 890
class FlagProperties( # pyright: ignore[reportIncompatibleMethodOverride,reportIncompatibleVariableOverride]
DecomposeMixin, SymmetricMixin, enum.Flag, metaclass=EnumPropertiesMeta
):
Copy link

Copilot AI Feb 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Base classes have conflicting values for attribute 'missing': classmethod() and classmethod().

Copilot uses AI. Check for mistakes.
Comment on lines +913 to 915
class IntFlagProperties( # pyright: ignore[reportIncompatibleMethodOverride,reportIncompatibleVariableOverride]
DecomposeMixin, SymmetricMixin, enum.IntFlag, metaclass=EnumPropertiesMeta
):
Copy link

Copilot AI Feb 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Base classes have conflicting values for attribute 'missing': classmethod() and classmethod().

Copilot uses AI. Check for mistakes.
Comment on lines +888 to 890
class FlagProperties( # pyright: ignore[reportIncompatibleMethodOverride,reportIncompatibleVariableOverride]
DecomposeMixin, SymmetricMixin, enum.Flag, metaclass=EnumPropertiesMeta
):
Copy link

Copilot AI Feb 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This class implements hash, but does not implement eq.

Copilot uses AI. Check for mistakes.
Comment on lines +913 to 915
class IntFlagProperties( # pyright: ignore[reportIncompatibleMethodOverride,reportIncompatibleVariableOverride]
DecomposeMixin, SymmetricMixin, enum.IntFlag, metaclass=EnumPropertiesMeta
):
Copy link

Copilot AI Feb 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This class implements hash, but does not implement eq.

Copilot uses AI. Check for mistakes.
@bckohan bckohan merged commit f488472 into main Feb 9, 2026
26 checks passed
@bckohan bckohan deleted the hints branch February 9, 2026 18:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Enum properties derived enums do not inherit type hint interface of Enum.

2 participants