Restore basic functionality on 3.14[sic] (#1329)
* Restore basic functionality on 3.14[sic] Essentially switch to PEP 649 / 749 for annotations. Some tests need to be skipped for now, but the rest is working. Fixes #1326 * Add news fragment * We have not 3.14 CI yet * Use imprerative xfails instead of skips
This commit is contained in:
parent
f520d9a89f
commit
7373d88f9b
|
@ -0,0 +1 @@
|
|||
Restored support for PEP [649](https://peps.python.org/pep-0649/) / [749](https://peps.python.org/pep-0749/)-implementing Pythons -- currently 3.14-dev.
|
|
@ -15,6 +15,7 @@ PY_3_9_PLUS = sys.version_info[:2] >= (3, 9)
|
|||
PY_3_10_PLUS = sys.version_info[:2] >= (3, 10)
|
||||
PY_3_12_PLUS = sys.version_info[:2] >= (3, 12)
|
||||
PY_3_13_PLUS = sys.version_info[:2] >= (3, 13)
|
||||
PY_3_14_PLUS = sys.version_info[:2] >= (3, 14)
|
||||
|
||||
|
||||
if sys.version_info < (3, 8):
|
||||
|
@ -25,6 +26,19 @@ if sys.version_info < (3, 8):
|
|||
else:
|
||||
from typing import Protocol # noqa: F401
|
||||
|
||||
if PY_3_14_PLUS: # pragma: no cover
|
||||
import annotationlib
|
||||
|
||||
_get_annotations = annotationlib.get_annotations
|
||||
|
||||
else:
|
||||
|
||||
def _get_annotations(cls):
|
||||
"""
|
||||
Get annotations for *cls*.
|
||||
"""
|
||||
return cls.__dict__.get("__annotations__", {})
|
||||
|
||||
|
||||
class _AnnotationExtractor:
|
||||
"""
|
||||
|
|
|
@ -23,6 +23,7 @@ from ._compat import (
|
|||
PY_3_8_PLUS,
|
||||
PY_3_10_PLUS,
|
||||
_AnnotationExtractor,
|
||||
_get_annotations,
|
||||
get_generic_base,
|
||||
)
|
||||
from .exceptions import (
|
||||
|
@ -308,13 +309,6 @@ def _has_own_attribute(cls, attrib_name):
|
|||
return attrib_name in cls.__dict__
|
||||
|
||||
|
||||
def _get_annotations(cls):
|
||||
"""
|
||||
Get annotations for *cls*.
|
||||
"""
|
||||
return cls.__dict__.get("__annotations__", {})
|
||||
|
||||
|
||||
def _collect_base_attrs(cls, taken_attr_names):
|
||||
"""
|
||||
Collect attr.ibs from base classes of *cls*, except *taken_attr_names*.
|
||||
|
|
|
@ -8,12 +8,17 @@ import pytest
|
|||
|
||||
from hypothesis import given
|
||||
|
||||
from attr._compat import PY_3_14_PLUS
|
||||
|
||||
from .strategies import simple_classes
|
||||
|
||||
|
||||
cloudpickle = pytest.importorskip("cloudpickle")
|
||||
|
||||
|
||||
@pytest.mark.xfail(
|
||||
PY_3_14_PLUS, reason="cloudpickle is currently broken on 3.14."
|
||||
)
|
||||
class TestCloudpickleCompat:
|
||||
"""
|
||||
Tests for compatibility with ``cloudpickle``.
|
||||
|
|
|
@ -12,6 +12,7 @@ import pytest
|
|||
|
||||
import attr
|
||||
|
||||
from attr._compat import PY_3_14_PLUS
|
||||
from attr._make import _is_class_var
|
||||
from attr.exceptions import UnannotatedAttributeError
|
||||
|
||||
|
@ -588,6 +589,8 @@ class TestAnnotations:
|
|||
"""
|
||||
References to self class using quotes can be resolved.
|
||||
"""
|
||||
if PY_3_14_PLUS and not slots:
|
||||
pytest.xfail("References are changing a lot in 3.14.")
|
||||
|
||||
@attr.s(slots=slots, auto_attribs=True)
|
||||
class A:
|
||||
|
@ -603,6 +606,8 @@ class TestAnnotations:
|
|||
"""
|
||||
Forward references can be resolved.
|
||||
"""
|
||||
if PY_3_14_PLUS and not slots:
|
||||
pytest.xfail("Forward references are changing a lot in 3.14.")
|
||||
|
||||
@attr.s(slots=slots, auto_attribs=True)
|
||||
class A:
|
||||
|
|
|
@ -21,7 +21,7 @@ from hypothesis.strategies import booleans, integers, lists, sampled_from, text
|
|||
import attr
|
||||
|
||||
from attr import _config
|
||||
from attr._compat import PY_3_8_PLUS, PY_3_10_PLUS
|
||||
from attr._compat import PY_3_8_PLUS, PY_3_10_PLUS, PY_3_14_PLUS
|
||||
from attr._make import (
|
||||
Attribute,
|
||||
Factory,
|
||||
|
@ -1838,9 +1838,11 @@ class TestClassBuilder:
|
|||
assert [C2] == C.__subclasses__()
|
||||
|
||||
@pytest.mark.skipif(not PY_3_8_PLUS, reason="cached_property is 3.8+")
|
||||
@pytest.mark.xfail(PY_3_14_PLUS, reason="Currently broken on nightly.")
|
||||
def test_no_references_to_original_when_using_cached_property(self):
|
||||
"""
|
||||
When subclassing a slotted class and using cached property, there are no stray references to the original class.
|
||||
When subclassing a slotted class and using cached property, there are
|
||||
no stray references to the original class.
|
||||
"""
|
||||
|
||||
@attr.s(slots=True)
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
"""
|
||||
Unit tests for slots-related functionality.
|
||||
"""
|
||||
|
||||
import functools
|
||||
import pickle
|
||||
import weakref
|
||||
|
@ -14,7 +15,7 @@ import pytest
|
|||
import attr
|
||||
import attrs
|
||||
|
||||
from attr._compat import PY_3_8_PLUS, PYPY
|
||||
from attr._compat import PY_3_8_PLUS, PY_3_14_PLUS, PYPY
|
||||
|
||||
|
||||
# Pympler doesn't work on PyPy.
|
||||
|
@ -774,6 +775,9 @@ def test_slots_cached_property_works_on_frozen_isntances():
|
|||
|
||||
|
||||
@pytest.mark.skipif(not PY_3_8_PLUS, reason="cached_property is 3.8+")
|
||||
@pytest.mark.xfail(
|
||||
PY_3_14_PLUS, reason="3.14 returns weird annotation for cached_properies"
|
||||
)
|
||||
def test_slots_cached_property_infers_type():
|
||||
"""
|
||||
Infers type of cached property.
|
||||
|
|
Loading…
Reference in New Issue