Skip to content

Commit

Permalink
Allow subclassing of AttrsInstance and Protocol at once (#1172)
Browse files Browse the repository at this point in the history
  • Loading branch information
hynek authored Aug 6, 2023
1 parent 8f4e7e9 commit c824bbe
Show file tree
Hide file tree
Showing 7 changed files with 30 additions and 2 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ jobs:
python -Im coverage html --skip-covered --skip-empty
# Report and write to summary.
python -Im coverage report | sed 's/^/ /' >> $GITHUB_STEP_SUMMARY
python -Im coverage report --format=markdown >> $GITHUB_STEP_SUMMARY
# Report again and fail if under 100%.
python -Im coverage report --fail-under=100
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,4 @@ tmp*
attrs.docset
attrs.tgz
Justfile
t.py
2 changes: 2 additions & 0 deletions changelog.d/1172.change.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
`attrs.AttrsInstance` is now a `typing.Protocol` in both type hints and code.
This allows you to subclass it along with another `Protocol`.
3 changes: 3 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,9 @@ exclude_lines = [
"pragma: no cover",
# PyPy is unacceptably slow under coverage.
"if PYPY:",
# not meant to be executed
': \.\.\.$',
'^ +\.\.\.$',
]


Expand Down
3 changes: 2 additions & 1 deletion src/attr/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

from . import converters, exceptions, filters, setters, validators
from ._cmp import cmp_using
from ._compat import Protocol
from ._config import get_run_validators, set_run_validators
from ._funcs import asdict, assoc, astuple, evolve, has, resolve_types
from ._make import (
Expand All @@ -31,7 +32,7 @@
dataclass = partial(attrs, auto_attribs=True) # happy Easter ;)


class AttrsInstance:
class AttrsInstance(Protocol):
pass


Expand Down
9 changes: 9 additions & 0 deletions src/attr/_compat.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,15 @@
PY_3_12_PLUS = sys.version_info[:2] >= (3, 12)


if sys.version_info < (3, 8):
try:
from typing_extensions import Protocol
except ImportError: # pragma: no cover
Protocol = object
else:
from typing import Protocol # noqa: F401


def just_warn(*args, **kw):
warnings.warn(
"Running interpreter doesn't sufficiently support code object "
Expand Down
12 changes: 12 additions & 0 deletions tests/test_compat.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

import pytest

import attr


@pytest.fixture(name="mp")
def _mp():
Expand Down Expand Up @@ -50,3 +52,13 @@ def test_immutable(self, mp):

with pytest.raises(AttributeError, match="no attribute 'setdefault'"):
mp.setdefault("x")


def test_attrsinstance_subclass_protocol():
"""
It's possible to subclass AttrsInstance and Protocol at once.
"""

class Foo(attr.AttrsInstance, attr._compat.Protocol):
def attribute(self) -> int:
...

0 comments on commit c824bbe

Please sign in to comment.