/
niceSOFT
/
python3-attrs
Обзор
Документация
Войти
/
niceSOFT
/
python3-attrs
Код
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
typing_tests/pyrefly.py
399 строк
8 KB
Hynek Schlawack
oops
07 авг 2026, 08:35
07 авг 2026, 08:35
c1dc5dc
Код
Авторство
О чём код?
# SPDX-License-Identifier: MIT """ Typing examples that rely on Pyrefly's advanced attrs integration. """ from __future__ import annotations import copy import re import sys from typing import Any import attrs @attrs.define class C: a: int = attrs.field() cc = C(1) C(a=1) if sys.version_info >= (3, 13): cc = copy.replace(cc, a=1) @attrs.define class D: x: list[int] = attrs.field() li: list[int] = D([1]).x @attrs.define class E: y: "list[int]" = attrs.field() li = E([1]).y @attrs.define class F: z: Any = attrs.field() # Inheritance -- @attrs.define class GG(D): y: str = attrs.field() GG(x=[1], y="foo") @attrs.define class HH(D, E): z: float = attrs.field() HH(x=[1], y=[], z=1.1) # Exceptions @attrs.define class Error(Exception): x: int = attrs.field() try: raise Error(1) except Error as e: e.x e.args str(e) @attrs.define(auto_exc=False) class Error2(Exception): x: int try: raise Error2(1) except Error as e: e.x e.args str(e) # Field aliases @attrs.define class AliasExample: without_alias: int _with_alias: int = attrs.field(alias="_with_alias") attrs.fields(AliasExample).without_alias.alias attrs.fields(AliasExample)._with_alias.alias # Converters @attrs.define class ConvCOptional: x: int | None = attrs.field(converter=attrs.converters.optional(int)) ConvCOptional(1) ConvCOptional(None) @attrs.define class ConvCPipe: x: str = attrs.field(converter=attrs.converters.pipe(int, str)) ConvCPipe(3.4) ConvCPipe("09") @attrs.define class ConvCDefaultIfNone: x: int = attrs.field(converter=attrs.converters.default_if_none(42)) ConvCDefaultIfNone(1) ConvCDefaultIfNone(None) @attrs.define class ConvCToBool: x: int = attrs.field(converter=attrs.converters.to_bool) ConvCToBool(1) ConvCToBool(True) ConvCToBool("on") ConvCToBool("yes") ConvCToBool(0) ConvCToBool(False) ConvCToBool("n") @attrs.define class DecoratorConverter: x: int = attrs.field() @x.converter def _to_int(self, field: attrs.Attribute, val: str | float) -> int: return int(val) DecoratorConverter("foo") # Validators @attrs.define class Validated: a: list[C] = attrs.field( validator=attrs.validators.deep_iterable( attrs.validators.instance_of(C), attrs.validators.instance_of(list) ), ) a2: tuple[C] = attrs.field( validator=attrs.validators.deep_iterable( attrs.validators.instance_of(C), attrs.validators.instance_of(tuple), ), ) a3: tuple[C] = attrs.field( validator=attrs.validators.deep_iterable( [attrs.validators.instance_of(C)], [attrs.validators.instance_of(tuple)], ), ) b: list[C] = attrs.field( validator=attrs.validators.deep_iterable( attrs.validators.instance_of(C) ), ) c: dict[C, D] = attrs.field( validator=attrs.validators.deep_mapping( attrs.validators.instance_of(C), attrs.validators.instance_of(D), attrs.validators.instance_of(dict), ), ) d: dict[C, D] = attrs.field( validator=attrs.validators.deep_mapping( attrs.validators.instance_of(C), attrs.validators.instance_of(D) ), ) d2: dict[C, D] = attrs.field( validator=attrs.validators.deep_mapping( attrs.validators.instance_of(C) ), ) d3: dict[C, D] = attrs.field( validator=attrs.validators.deep_mapping( value_validator=attrs.validators.instance_of(C) ), ) d4: dict[C, D] = attrs.field( validator=attrs.validators.deep_mapping( key_validator=[attrs.validators.instance_of(C)], value_validator=[attrs.validators.instance_of(C)], mapping_validator=[attrs.validators.instance_of(dict)], ), ) e: str = attrs.field( validator=attrs.validators.matches_re(re.compile(r"foo")) ) f: str = attrs.field( validator=attrs.validators.matches_re(r"foo", flags=42, func=re.search) ) # Test different forms of instance_of g: int = attrs.field(validator=attrs.validators.instance_of(int)) h: int = attrs.field(validator=attrs.validators.instance_of((int,))) j: int | str = attrs.field( validator=attrs.validators.instance_of((int, str)) ) k: int | str | C = attrs.field( validator=attrs.validators.instance_of((int, C, str)) ) kk: int | str | C = attrs.field( validator=attrs.validators.instance_of(int | C | str) ) l: Any = attrs.field( validator=attrs.validators.not_(attrs.validators.in_("abc")) ) m: Any = attrs.field( validator=attrs.validators.not_( attrs.validators.in_("abc"), exc_types=ValueError ) ) n: Any = attrs.field( validator=attrs.validators.not_( attrs.validators.in_("abc"), exc_types=(ValueError,) ) ) o: Any = attrs.field( validator=attrs.validators.not_( attrs.validators.in_("abc"), msg="spam" ) ) p: Any = attrs.field( validator=attrs.validators.not_(attrs.validators.in_("abc"), msg=None) ) q: Any = attrs.field( validator=attrs.validators.optional(attrs.validators.instance_of(C)) ) r: Any = attrs.field( validator=attrs.validators.optional([attrs.validators.instance_of(C)]) ) s: Any = attrs.field( validator=attrs.validators.optional((attrs.validators.instance_of(C),)) ) @attrs.define class Validated2: num: int = attrs.field(validator=attrs.validators.ge(0)) with attrs.validators.disabled(): Validated2(num=-1) try: attrs.validators.set_disabled(True) Validated2(num=-1) finally: attrs.validators.set_disabled(False) # Custom repr() @attrs.define class WithCustomRepr: a: int = attrs.field(repr=True) b: str = attrs.field(repr=False) c: str = attrs.field(repr=lambda value: "c is for cookie") d: bool = attrs.field(repr=str) # Check some of our own types @attrs.define(eq=True, order=False) class OrderFlags: a: int = attrs.field(eq=False, order=False) b: int = attrs.field(eq=True, order=True) # on_setattr hooks @attrs.define(on_setattr=attrs.setters.validate) class ValidatedSetter: a: int b: str = attrs.field(on_setattr=attrs.setters.NO_OP) c: bool = attrs.field(on_setattr=attrs.setters.frozen) d: int = attrs.field( converter=int, on_setattr=[attrs.setters.convert, attrs.setters.validate], ) e: bool = attrs.field( converter=attrs.converters.to_bool, on_setattr=attrs.setters.pipe( attrs.setters.convert, attrs.setters.validate ), ) vs = ValidatedSetter(1, "2", True, 4, False) vs.d = "2" vs.e = "yes" vs.e = "foo" # XXX: should only allow the literals we know # field_transformer def ft_hook( cls: type, attribs: list[attrs.Attribute] ) -> list[attrs.Attribute]: return attribs @attrs.define(field_transformer=ft_hook) class TransformedAttrs: x: int # Auto-detect @attrs.define(auto_detect=True) class AutoDetect: x: int def __init__(self, x: int): self.x = x @attrs.define(order=True) class NGClass: x: int = attrs.field(default=42) ngc = NGClass(1) @attrs.frozen(str=True) class NGFrozen: x: int attrs.fields(NGFrozen).x.evolve(eq=False) a = attrs.fields(NGFrozen).x a.evolve(repr=False) @attrs.define class FactoryTest: a: list[int] = attrs.field(default=attrs.Factory(list)) b: list[Any] = attrs.field(default=attrs.Factory(list, False)) c: list[int] = attrs.field(default=attrs.Factory((lambda s: s.a), True)) attrs.asdict(FactoryTest(), tuple_keys=True) # Check match_args stub @attrs.define(match_args=False) class MatchArgs: a: int = attrs.field() b: int = attrs.field() attrs.asdict(FactoryTest()) attrs.asdict(FactoryTest(), retain_collection_types=False) foo = object if attrs.has(foo) or attrs.has(foo): foo.__attrs_attrs__ @attrs.define(unsafe_hash=True) class Hashable: pass def test(cls: type) -> None: if attrs.has(cls): attrs.resolve_types(cls)