improved sentinel after learning from @taleinat on python-dev
This commit is contained in:
parent
08a4001b43
commit
0ce109a9fe
@ -1,23 +1,41 @@
|
||||
"""
|
||||
This module provides a ``Sentinel`` class that can be used directly as a
|
||||
sentinel singleton, or subclassed if a distinct sentinel singleton is needed.
|
||||
|
||||
The ``repr`` of a ``Sentinel`` class is its name::
|
||||
|
||||
>>> class Missing(Sentinel): pass
|
||||
>>> Missing
|
||||
Missing
|
||||
|
||||
If a different ``repr`` is required,
|
||||
you can define it as a class attribute::
|
||||
|
||||
>>> class CustomRepr(Sentinel):
|
||||
... repr = '<CustomRepr>'
|
||||
...
|
||||
>>> CustomRepr
|
||||
<CustomRepr>
|
||||
|
||||
``Sentinel`` classes cannot be instantiated::
|
||||
|
||||
>>> Missing()
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
TypeError: 'Missing' is a sentinel and cannot be instantiated
|
||||
|
||||
"""
|
||||
|
||||
class SentinelMeta(type):
|
||||
|
||||
class _SentinelMeta(type):
|
||||
def __repr__(cls):
|
||||
try:
|
||||
return cls.repr
|
||||
except AttributeError:
|
||||
return cls.__name__
|
||||
return f'{cls.__name__}'
|
||||
|
||||
class Sentinel(metaclass=SentinelMeta):
|
||||
|
||||
class Sentinel(metaclass=_SentinelMeta):
|
||||
def __new__(cls):
|
||||
return cls
|
||||
msg = 'is a sentinel and cannot be instantiated'
|
||||
raise TypeError(f"'{cls!r}' {msg}")
|
||||
|
@ -1,8 +1,12 @@
|
||||
import pickle
|
||||
|
||||
import pytest
|
||||
|
||||
from sentinel import Sentinel
|
||||
|
||||
class PlainSentinel(Sentinel): pass
|
||||
|
||||
class PlainSentinel(Sentinel):
|
||||
pass
|
||||
|
||||
|
||||
class SentinelCustomRepr(Sentinel):
|
||||
@ -13,16 +17,23 @@ def test_repr():
|
||||
assert repr(PlainSentinel) == 'PlainSentinel'
|
||||
|
||||
|
||||
def test_pickle():
|
||||
s = pickle.dumps(PlainSentinel)
|
||||
ps = pickle.loads(s)
|
||||
assert ps is PlainSentinel
|
||||
def test_cannot_instantiate():
|
||||
with pytest.raises(TypeError) as e:
|
||||
PlainSentinel()
|
||||
msg = "'PlainSentinel' is a sentinel and cannot be instantiated"
|
||||
assert msg in str(e.value)
|
||||
|
||||
|
||||
def test_custom_repr():
|
||||
assert repr(SentinelCustomRepr) == '***SentinelRepr***'
|
||||
|
||||
|
||||
def test_pickle():
|
||||
s = pickle.dumps(SentinelCustomRepr)
|
||||
ps = pickle.loads(s)
|
||||
assert ps is SentinelCustomRepr
|
||||
|
||||
|
||||
def test_sentinel_comes_ready_to_use():
|
||||
assert repr(Sentinel) == 'Sentinel'
|
||||
s = pickle.dumps(Sentinel)
|
||||
|
Loading…
Reference in New Issue
Block a user