Skip to content

Commit 519423d

Browse files
committed
Use MyST-native doctest blocks in all MD
1 parent 403adab commit 519423d

6 files changed

Lines changed: 166 additions & 192 deletions

File tree

docs/examples.md

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -408,18 +408,16 @@ Therefore if you use `@validator`, it is *not* enough to annotate said attribute
408408

409409
*attrs* ships with a bunch of validators, make sure to [check them out](api-validators) before writing your own:
410410

411-
```{eval-rst}
412-
.. doctest::
413-
414-
>>> @define
415-
... class C:
416-
... x: int = field(validator=validators.instance_of(int))
417-
>>> C(42)
418-
C(x=42)
419-
>>> C("42")
420-
Traceback (most recent call last):
421-
...
422-
TypeError: ("'x' must be <type 'int'> (got '42' that is a <type 'str'>).", Attribute(name='x', default=NOTHING, factory=NOTHING, validator=<instance_of validator for type <type 'int'>>, type=None, kw_only=False), <type 'int'>, '42')
411+
```{doctest}
412+
>>> @define
413+
... class C:
414+
... x: int = field(validator=validators.instance_of(int))
415+
>>> C(42)
416+
C(x=42)
417+
>>> C("42")
418+
Traceback (most recent call last):
419+
...
420+
TypeError: ("'x' must be <type 'int'> (got '42' that is a <type 'str'>).", Attribute(name='x', default=NOTHING, factory=NOTHING, validator=<instance_of validator for type <type 'int'>>, type=None, kw_only=False), <type 'int'>, '42')
423421
```
424422

425423
Please note that if you use {func}`attr.s` (and **not** {func}`attrs.define`) to define your class, validators only run on initialization by default -- not when you set an attribute.

docs/extending.md

Lines changed: 38 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ Here are some tips for effective use of metadata:
160160

161161
- To avoid metadata key collisions, consider exposing your metadata keys from your modules.:
162162

163-
```
163+
```python
164164
from mylib import MY_METADATA_KEY
165165

166166
@define
@@ -173,31 +173,28 @@ Here are some tips for effective use of metadata:
173173
- Expose `field` wrappers for your specific metadata.
174174
This is a more graceful approach if your users don't require metadata from other libraries.
175175

176-
```{eval-rst}
177-
.. doctest::
178-
179-
>>> from attr import fields, NOTHING
180-
>>> MY_TYPE_METADATA = '__my_type_metadata'
181-
>>>
182-
>>> def typed(
183-
... cls, default=NOTHING, validator=None, repr=True,
184-
... eq=True, order=None, hash=None, init=True, metadata=None,
185-
... converter=None
186-
... ):
187-
... metadata = metadata or {}
188-
... metadata[MY_TYPE_METADATA] = cls
189-
... return field(
190-
... default=default, validator=validator, repr=repr,
191-
... eq=eq, order=order, hash=hash, init=init,
192-
... metadata=metadata, converter=converter
193-
... )
194-
>>>
195-
>>> @define
196-
... class C:
197-
... x: int = typed(int, default=1, init=False)
198-
>>> fields(C).x.metadata[MY_TYPE_METADATA]
199-
<class 'int'>
200-
176+
```{doctest}
177+
>>> from attrs import fields, NOTHING
178+
>>> MY_TYPE_METADATA = '__my_type_metadata'
179+
>>>
180+
>>> def typed(
181+
... cls, default=NOTHING, validator=None, repr=True,
182+
... eq=True, order=None, hash=None, init=True, metadata=None,
183+
... converter=None
184+
... ):
185+
... metadata = metadata or {}
186+
... metadata[MY_TYPE_METADATA] = cls
187+
... return field(
188+
... default=default, validator=validator, repr=repr,
189+
... eq=eq, order=order, hash=hash, init=init,
190+
... metadata=metadata, converter=converter
191+
... )
192+
>>>
193+
>>> @define
194+
... class C:
195+
... x: int = typed(int, default=1, init=False)
196+
>>> fields(C).x.metadata[MY_TYPE_METADATA]
197+
<class 'int'>
201198
```
202199

203200
(transform-fields)=
@@ -293,24 +290,22 @@ Data(public=42, _private='spam', explicit='yes')
293290
*attrs* allows you to serialize instances of *attrs* classes to dicts using the {func}`attrs.asdict` function.
294291
However, the result can not always be serialized since most data types will remain as they are:
295292

296-
```{eval-rst}
297-
.. doctest::
298-
299-
>>> import json
300-
>>> import datetime
301-
>>> from attrs import asdict
302-
>>>
303-
>>> @frozen
304-
... class Data:
305-
... dt: datetime.datetime
293+
```{doctest}
294+
>>> import json
295+
>>> import datetime
296+
>>> from attrs import asdict
297+
>>>
298+
>>> @frozen
299+
... class Data:
300+
... dt: datetime.datetime
301+
...
302+
>>> data = asdict(Data(datetime.datetime(2020, 5, 4, 13, 37)))
303+
>>> data
304+
{'dt': datetime.datetime(2020, 5, 4, 13, 37)}
305+
>>> json.dumps(data)
306+
Traceback (most recent call last):
306307
...
307-
>>> data = asdict(Data(datetime.datetime(2020, 5, 4, 13, 37)))
308-
>>> data
309-
{'dt': datetime.datetime(2020, 5, 4, 13, 37)}
310-
>>> json.dumps(data)
311-
Traceback (most recent call last):
312-
...
313-
TypeError: Object of type datetime is not JSON serializable
308+
TypeError: Object of type datetime is not JSON serializable
314309
```
315310

316311
To help you with this, {func}`~attrs.asdict` allows you to pass a *value_serializer* hook.

docs/glossary.md

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -26,20 +26,18 @@ slotted classes
2626

2727
- Slotted classes don't allow for any other attribute to be set except for those defined in one of the class' hierarchies `__slots__`:
2828

29-
```{eval-rst}
30-
.. doctest::
31-
32-
>>> from attr import define
33-
>>> @define
34-
... class Coordinates:
35-
... x: int
36-
... y: int
37-
...
38-
>>> c = Coordinates(x=1, y=2)
39-
>>> c.z = 3
40-
Traceback (most recent call last):
41-
...
42-
AttributeError: 'Coordinates' object has no attribute 'z'
29+
```{doctest}
30+
>>> from attr import define
31+
>>> @define
32+
... class Coordinates:
33+
... x: int
34+
... y: int
35+
...
36+
>>> c = Coordinates(x=1, y=2)
37+
>>> c.z = 3
38+
Traceback (most recent call last):
39+
...
40+
AttributeError: 'Coordinates' object has no attribute 'z'
4341
```
4442
4543
- Slotted classes can inherit from other classes just like non-slotted classes, but some of the benefits of slotted classes are lost if you do that.

docs/how-does-it-work.md

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,18 +20,16 @@ While creating new classes is more elegant, we've run into several edge cases su
2020

2121
To be very clear: if you define a class with a single attribute without a default value, the generated `__init__` will look *exactly* how you'd expect:
2222

23-
```{eval-rst}
24-
.. doctest::
25-
26-
>>> import inspect
27-
>>> from attr import define
28-
>>> @define
29-
... class C:
30-
... x: int
31-
>>> print(inspect.getsource(C.__init__))
32-
def __init__(self, x):
33-
self.x = x
34-
<BLANKLINE>
23+
```{doctest}
24+
>>> import inspect
25+
>>> from attrs import define
26+
>>> @define
27+
... class C:
28+
... x: int
29+
>>> print(inspect.getsource(C.__init__))
30+
def __init__(self, x):
31+
self.x = x
32+
<BLANKLINE>
3533
```
3634

3735
No magic, no meta programming, no expensive introspection at runtime.

docs/types.md

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,17 @@
44

55
However they will forever remain *optional*, therefore the example from the README could also be written as:
66

7-
```{eval-rst}
8-
.. doctest::
7+
```{doctest}
8+
>>> from attrs import define, field
99
10-
>>> from attrs import define, field
10+
>>> @define
11+
... class SomeClass:
12+
... a_number = field(default=42)
13+
... list_of_numbers = field(factory=list)
1114
12-
>>> @define
13-
... class SomeClass:
14-
... a_number = field(default=42)
15-
... list_of_numbers = field(factory=list)
16-
17-
>>> sc = SomeClass(1, [1, 2, 3])
18-
>>> sc
19-
SomeClass(a_number=1, list_of_numbers=[1, 2, 3])
15+
>>> sc = SomeClass(1, [1, 2, 3])
16+
>>> sc
17+
SomeClass(a_number=1, list_of_numbers=[1, 2, 3])
2018
```
2119

2220
You can choose freely between the approaches, but please remember that if you choose to use type annotations, you **must** annotate **all** attributes!

0 commit comments

Comments
 (0)