Skip to content

Commit be79822

Browse files
Add classproperty for spec_property like behavior for classmethods.
1 parent f4b1a21 commit be79822

File tree

5 files changed

+491
-58
lines changed

5 files changed

+491
-58
lines changed

docsite/docs/usage/special_types.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,7 @@ class MyClass:
304304
overridable=True, # Whether to allow overriding by default.
305305
cache=False, # Whether to cache the result after first evaluation.
306306
invalidated_by=None, # An iterable of attributes which when mutated invalidate the cache (only supported when used with spec-classes)
307+
allow_attribute_error=True, # Whether to allow properties to raise `AttributeErrors` which are often masked during attribute lookup.
307308
)
308309
def method(self):
309310
...
@@ -316,6 +317,33 @@ class MyClass:
316317

317318
As always you can refer to the inline `help(spec_property)` for more details.
318319

320+
321+
### `classproperty`
322+
323+
`classproperty` is implemented in `spec_classes.types.classproperty`, and
324+
behaves exactly like `spec_property` except that it acts on classmethods, and
325+
does not offer inbuilt access to spec-class state. You can use `classproperty`
326+
as follows:
327+
328+
```python
329+
class MyClass:
330+
@classproperty(
331+
overridable=True, # Whether to allow overriding by default.
332+
cache=False, # Whether to cache the result after first evaluation.
333+
cache_per_subclass=False, # Whether cache should be stored per subclass
334+
# rather than once for all classes.
335+
allow_attribute_error=True, # Whether to allow properties to raise `AttributeErrors` which are often masked during attribute lookup.
336+
)
337+
def method(cls):
338+
...
339+
340+
# And of course you can override the setters as you would with regular properties
341+
@method.setter
342+
def method(cls, value):
343+
...
344+
```
345+
346+
319347
### `AttrProxy`
320348

321349
`AttrProxy` is implemented in `spec_classes.types.attr_proxy`, and allows one

spec_classes/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from .spec_class import spec_class
44
from .types import (
55
spec_property,
6+
classproperty,
67
Alias,
78
DeprecatedAlias,
89
Attr,
@@ -22,6 +23,7 @@
2223
"__author_email__",
2324
"spec_class",
2425
"spec_property",
26+
"classproperty",
2527
"FrozenInstanceError",
2628
"Alias",
2729
"DeprecatedAlias",

spec_classes/types/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from .attr_proxy import AttrProxy
44
from .keyed import KeyedList, KeyedSet
55
from .missing import MISSING, EMPTY, SENTINEL
6-
from .spec_property import spec_property
6+
from .spec_property import spec_property, classproperty
77
from .validated import ValidatedType, bounded, validated
88

99
__all__ = (
@@ -19,5 +19,6 @@
1919
"ValidatedType",
2020
"bounded",
2121
"spec_property",
22+
"classproperty",
2223
"validated",
2324
)

0 commit comments

Comments
 (0)