File tree Expand file tree Collapse file tree 3 files changed +38
-9
lines changed
25-class-metaprog/sentinel Expand file tree Collapse file tree 3 files changed +38
-9
lines changed Original file line number Diff line number Diff line change 11"""
2+ This module provides a ``Sentinel`` class that can be used directly as a
3+ sentinel singleton, or subclassed if a distinct sentinel singleton is needed.
4+
5+ The ``repr`` of a ``Sentinel`` class is its name::
26
37 >>> class Missing(Sentinel): pass
48 >>> Missing
59 Missing
10+
11+ If a different ``repr`` is required,
12+ you can define it as a class attribute::
13+
614 >>> class CustomRepr(Sentinel):
715 ... repr = '<CustomRepr>'
816 ...
917 >>> CustomRepr
1018 <CustomRepr>
1119
20+ ``Sentinel`` classes cannot be instantiated::
21+
22+ >>> Missing()
23+ Traceback (most recent call last):
24+ ...
25+ TypeError: 'Missing' is a sentinel and cannot be instantiated
26+
1227"""
1328
14- class SentinelMeta (type ):
29+
30+ class _SentinelMeta (type ):
1531 def __repr__ (cls ):
1632 try :
1733 return cls .repr
1834 except AttributeError :
1935 return cls .__name__
2036
21- class Sentinel (metaclass = SentinelMeta ):
37+
38+ class Sentinel (metaclass = _SentinelMeta ):
2239 def __new__ (cls ):
23- return cls
40+ msg = 'is a sentinel and cannot be instantiated'
41+ raise TypeError (f"'{ cls !r} ' { msg } " )
Original file line number Diff line number Diff line change 11import pickle
22
3+ import pytest
4+
35from sentinel import Sentinel
46
5- class PlainSentinel (Sentinel ): pass
7+
8+ class PlainSentinel (Sentinel ):
9+ pass
610
711
812class SentinelCustomRepr (Sentinel ):
@@ -13,16 +17,23 @@ def test_repr():
1317 assert repr (PlainSentinel ) == 'PlainSentinel'
1418
1519
16- def test_pickle ():
17- s = pickle .dumps (PlainSentinel )
18- ps = pickle .loads (s )
19- assert ps is PlainSentinel
20+ def test_cannot_instantiate ():
21+ with pytest .raises (TypeError ) as e :
22+ PlainSentinel ()
23+ msg = "'PlainSentinel' is a sentinel and cannot be instantiated"
24+ assert msg in str (e .value )
2025
2126
2227def test_custom_repr ():
2328 assert repr (SentinelCustomRepr ) == '***SentinelRepr***'
2429
2530
31+ def test_pickle ():
32+ s = pickle .dumps (SentinelCustomRepr )
33+ ps = pickle .loads (s )
34+ assert ps is SentinelCustomRepr
35+
36+
2637def test_sentinel_comes_ready_to_use ():
2738 assert repr (Sentinel ) == 'Sentinel'
2839 s = pickle .dumps (Sentinel )
Original file line number Diff line number Diff line change 11# Fluent Python 2e example code
22
3- Example code for the book ** Fluent Python, 2<sup >nd</sup > edition** by Luciano Ramalho (O'Reilly, 2020 ).
3+ Example code for the book ** Fluent Python, 2<sup >nd</sup > edition** by Luciano Ramalho (O'Reilly, 2021 ).
44
55> ** BEWARE** : This is a work in progress!
66>
You can’t perform that action at this time.
0 commit comments