bpo-34962: make doctest in Doc/ now passes, and is enforced in CI (GH-9806)
This commit is contained in:
parent
53ebf4b070
commit
859c068e52
14
.travis.yml
14
.travis.yml
|
@ -53,8 +53,8 @@ matrix:
|
|||
- cd Doc
|
||||
# Sphinx is pinned so that new versions that introduce new warnings won't suddenly cause build failures.
|
||||
# (Updating the version is fine as long as no warnings are raised by doing so.)
|
||||
# The theme used by the docs is stored seperately, so we need to install that as well.
|
||||
- python -m pip install sphinx~=1.6.1 blurb python-docs-theme
|
||||
# The theme used by the docs is stored separately, so we need to install that as well.
|
||||
- python -m pip install sphinx blurb python-docs-theme
|
||||
script:
|
||||
- make check suspicious html SPHINXOPTS="-q -W -j4"
|
||||
- os: osx
|
||||
|
@ -155,8 +155,14 @@ script:
|
|||
# Check that all symbols exported by libpython start with "Py" or "_Py"
|
||||
- make smelly
|
||||
# `-r -w` implicitly provided through `make buildbottest`.
|
||||
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then XVFB_RUN=xvfb-run; fi; $XVFB_RUN make buildbottest TESTOPTS="-j4 -uall,-cpu"
|
||||
|
||||
- |
|
||||
if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then
|
||||
XVFB_RUN=xvfb-run;
|
||||
fi
|
||||
$XVFB_RUN make buildbottest TESTOPTS="-j4 -uall,-cpu"
|
||||
if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then
|
||||
$XVFB_RUN make PYTHON=../python SPHINXOPTS="-q -W -j4" -C Doc/ venv doctest
|
||||
fi
|
||||
notifications:
|
||||
email: false
|
||||
webhooks:
|
||||
|
|
|
@ -16,6 +16,13 @@ sys.path.append(os.path.abspath('includes'))
|
|||
extensions = ['sphinx.ext.coverage', 'sphinx.ext.doctest',
|
||||
'pyspecific', 'c_annotations', 'escape4chm']
|
||||
|
||||
|
||||
doctest_global_setup = '''
|
||||
try:
|
||||
import _tkinter
|
||||
except ImportError:
|
||||
_tkinter = None
|
||||
'''
|
||||
# General substitutions.
|
||||
project = 'Python'
|
||||
copyright = '2001-%s, Python Software Foundation' % time.strftime('%Y')
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
.. _examples:
|
||||
.. _distutils_examples:
|
||||
|
||||
********
|
||||
Examples
|
||||
|
|
|
@ -621,18 +621,19 @@ The :mod:`multiprocessing` package mostly replicates the API of the
|
|||
Example usage of some of the methods of :class:`Process`:
|
||||
|
||||
.. doctest::
|
||||
:options: +ELLIPSIS
|
||||
|
||||
>>> import multiprocessing, time, signal
|
||||
>>> p = multiprocessing.Process(target=time.sleep, args=(1000,))
|
||||
>>> print(p, p.is_alive())
|
||||
<Process(Process-1, initial)> False
|
||||
<Process(..., initial)> False
|
||||
>>> p.start()
|
||||
>>> print(p, p.is_alive())
|
||||
<Process(Process-1, started)> True
|
||||
<Process(..., started)> True
|
||||
>>> p.terminate()
|
||||
>>> time.sleep(0.1)
|
||||
>>> print(p, p.is_alive())
|
||||
<Process(Process-1, stopped[SIGTERM])> False
|
||||
<Process(..., stopped[SIGTERM])> False
|
||||
>>> p.exitcode == -signal.SIGTERM
|
||||
True
|
||||
|
||||
|
|
|
@ -1234,9 +1234,7 @@ Checking for a Pair
|
|||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
In this example, we'll use the following helper function to display match
|
||||
objects a little more gracefully:
|
||||
|
||||
.. testcode::
|
||||
objects a little more gracefully::
|
||||
|
||||
def displaymatch(match):
|
||||
if match is None:
|
||||
|
@ -1269,10 +1267,9 @@ To match this with a regular expression, one could use backreferences as such::
|
|||
"<Match: '354aa', groups=('a',)>"
|
||||
|
||||
To find out what card the pair consists of, one could use the
|
||||
:meth:`~Match.group` method of the match object in the following manner:
|
||||
|
||||
.. doctest::
|
||||
:meth:`~Match.group` method of the match object in the following manner::
|
||||
|
||||
>>> pair = re.compile(r".*(.).*\1")
|
||||
>>> pair.match("717ak").group(1)
|
||||
'7'
|
||||
|
||||
|
@ -1377,7 +1374,9 @@ easily read and modified by Python as demonstrated in the following example that
|
|||
creates a phonebook.
|
||||
|
||||
First, here is the input. Normally it may come from a file, here we are using
|
||||
triple-quoted string syntax::
|
||||
triple-quoted string syntax
|
||||
|
||||
.. doctest::
|
||||
|
||||
>>> text = """Ross McFluff: 834.345.1254 155 Elm Street
|
||||
...
|
||||
|
|
|
@ -250,6 +250,7 @@ Turtle motion
|
|||
turtle is headed.
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
|
||||
>>> turtle.position()
|
||||
(0.00,0.00)
|
||||
|
@ -276,6 +277,7 @@ Turtle motion
|
|||
>>> turtle.goto(0, 0)
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
|
||||
>>> turtle.position()
|
||||
(0.00,0.00)
|
||||
|
@ -294,11 +296,13 @@ Turtle motion
|
|||
orientation depends on the turtle mode, see :func:`mode`.
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
:hide:
|
||||
|
||||
>>> turtle.setheading(22)
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
|
||||
>>> turtle.heading()
|
||||
22.0
|
||||
|
@ -317,11 +321,13 @@ Turtle motion
|
|||
orientation depends on the turtle mode, see :func:`mode`.
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
:hide:
|
||||
|
||||
>>> turtle.setheading(22)
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
|
||||
>>> turtle.heading()
|
||||
22.0
|
||||
|
@ -344,11 +350,13 @@ Turtle motion
|
|||
not change the turtle's orientation.
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
:hide:
|
||||
|
||||
>>> turtle.goto(0, 0)
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
|
||||
>>> tp = turtle.pos()
|
||||
>>> tp
|
||||
|
@ -372,11 +380,13 @@ Turtle motion
|
|||
unchanged.
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
:hide:
|
||||
|
||||
>>> turtle.goto(0, 240)
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
|
||||
>>> turtle.position()
|
||||
(0.00,240.00)
|
||||
|
@ -392,11 +402,13 @@ Turtle motion
|
|||
Set the turtle's second coordinate to *y*, leave first coordinate unchanged.
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
:hide:
|
||||
|
||||
>>> turtle.goto(0, 40)
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
|
||||
>>> turtle.position()
|
||||
(0.00,40.00)
|
||||
|
@ -423,6 +435,7 @@ Turtle motion
|
|||
=================== ====================
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
|
||||
>>> turtle.setheading(90)
|
||||
>>> turtle.heading()
|
||||
|
@ -435,12 +448,14 @@ Turtle motion
|
|||
its start-orientation (which depends on the mode, see :func:`mode`).
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
:hide:
|
||||
|
||||
>>> turtle.setheading(90)
|
||||
>>> turtle.goto(0, -10)
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
|
||||
>>> turtle.heading()
|
||||
90.0
|
||||
|
@ -472,6 +487,7 @@ Turtle motion
|
|||
calculated automatically. May be used to draw regular polygons.
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
|
||||
>>> turtle.home()
|
||||
>>> turtle.position()
|
||||
|
@ -500,6 +516,7 @@ Turtle motion
|
|||
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
|
||||
>>> turtle.home()
|
||||
>>> turtle.dot()
|
||||
|
@ -517,6 +534,7 @@ Turtle motion
|
|||
it by calling ``clearstamp(stamp_id)``.
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
|
||||
>>> turtle.color("blue")
|
||||
>>> turtle.stamp()
|
||||
|
@ -532,6 +550,7 @@ Turtle motion
|
|||
Delete stamp with given *stampid*.
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
|
||||
>>> turtle.position()
|
||||
(150.00,-0.00)
|
||||
|
@ -576,6 +595,7 @@ Turtle motion
|
|||
undo actions is determined by the size of the undobuffer.
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
|
||||
>>> for i in range(4):
|
||||
... turtle.fd(50); turtle.lt(80)
|
||||
|
@ -608,6 +628,7 @@ Turtle motion
|
|||
turtle turn instantly.
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
|
||||
>>> turtle.speed()
|
||||
3
|
||||
|
@ -628,6 +649,7 @@ Tell Turtle's state
|
|||
Return the turtle's current location (x,y) (as a :class:`Vec2D` vector).
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
|
||||
>>> turtle.pos()
|
||||
(440.00,-0.00)
|
||||
|
@ -643,6 +665,7 @@ Tell Turtle's state
|
|||
orientation which depends on the mode - "standard"/"world" or "logo").
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
|
||||
>>> turtle.goto(10, 10)
|
||||
>>> turtle.towards(0,0)
|
||||
|
@ -654,6 +677,7 @@ Tell Turtle's state
|
|||
Return the turtle's x coordinate.
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
|
||||
>>> turtle.home()
|
||||
>>> turtle.left(50)
|
||||
|
@ -669,6 +693,7 @@ Tell Turtle's state
|
|||
Return the turtle's y coordinate.
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
|
||||
>>> turtle.home()
|
||||
>>> turtle.left(60)
|
||||
|
@ -685,6 +710,7 @@ Tell Turtle's state
|
|||
:func:`mode`).
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
|
||||
>>> turtle.home()
|
||||
>>> turtle.left(67)
|
||||
|
@ -701,6 +727,7 @@ Tell Turtle's state
|
|||
other turtle, in turtle step units.
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
|
||||
>>> turtle.home()
|
||||
>>> turtle.distance(30,40)
|
||||
|
@ -724,6 +751,7 @@ Settings for measurement
|
|||
Default value is 360 degrees.
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
|
||||
>>> turtle.home()
|
||||
>>> turtle.left(90)
|
||||
|
@ -746,6 +774,7 @@ Settings for measurement
|
|||
``degrees(2*math.pi)``.
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
|
||||
>>> turtle.home()
|
||||
>>> turtle.left(90)
|
||||
|
@ -756,6 +785,7 @@ Settings for measurement
|
|||
1.5707963267948966
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
:hide:
|
||||
|
||||
>>> turtle.degrees(360)
|
||||
|
@ -791,6 +821,7 @@ Drawing state
|
|||
thickness. If no argument is given, the current pensize is returned.
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
|
||||
>>> turtle.pensize()
|
||||
1
|
||||
|
@ -822,6 +853,7 @@ Drawing state
|
|||
attributes in one statement.
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
:options: +NORMALIZE_WHITESPACE
|
||||
|
||||
>>> turtle.pen(fillcolor="black", pencolor="red", pensize=10)
|
||||
|
@ -844,6 +876,7 @@ Drawing state
|
|||
Return ``True`` if pen is down, ``False`` if it's up.
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
|
||||
>>> turtle.penup()
|
||||
>>> turtle.isdown()
|
||||
|
@ -884,6 +917,7 @@ Color control
|
|||
newly set pencolor.
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
|
||||
>>> colormode()
|
||||
1.0
|
||||
|
@ -932,6 +966,7 @@ Color control
|
|||
with the newly set fillcolor.
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
|
||||
>>> turtle.fillcolor("violet")
|
||||
>>> turtle.fillcolor()
|
||||
|
@ -970,6 +1005,7 @@ Color control
|
|||
with the newly set colors.
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
|
||||
>>> turtle.color("red", "green")
|
||||
>>> turtle.color()
|
||||
|
@ -986,6 +1022,7 @@ Filling
|
|||
~~~~~~~
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
:hide:
|
||||
|
||||
>>> turtle.home()
|
||||
|
@ -995,6 +1032,7 @@ Filling
|
|||
Return fillstate (``True`` if filling, ``False`` else).
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
|
||||
>>> turtle.begin_fill()
|
||||
>>> if turtle.filling():
|
||||
|
@ -1014,6 +1052,7 @@ Filling
|
|||
Fill the shape drawn after the last call to :func:`begin_fill`.
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
|
||||
>>> turtle.color("black", "red")
|
||||
>>> turtle.begin_fill()
|
||||
|
@ -1030,6 +1069,7 @@ More drawing control
|
|||
variables to the default values.
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
|
||||
>>> turtle.goto(0,-22)
|
||||
>>> turtle.left(100)
|
||||
|
@ -1080,6 +1120,7 @@ Visibility
|
|||
drawing observably.
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
|
||||
>>> turtle.hideturtle()
|
||||
|
||||
|
@ -1090,6 +1131,7 @@ Visibility
|
|||
Make the turtle visible.
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
|
||||
>>> turtle.showturtle()
|
||||
|
||||
|
@ -1120,6 +1162,7 @@ Appearance
|
|||
deal with shapes see Screen method :func:`register_shape`.
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
|
||||
>>> turtle.shape()
|
||||
'classic'
|
||||
|
@ -1145,6 +1188,7 @@ Appearance
|
|||
resizemode("user") is called by :func:`shapesize` when used with arguments.
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
|
||||
>>> turtle.resizemode()
|
||||
'noresize'
|
||||
|
@ -1168,6 +1212,7 @@ Appearance
|
|||
of the shapes's outline.
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
|
||||
>>> turtle.shapesize()
|
||||
(1.0, 1.0, 1)
|
||||
|
@ -1192,6 +1237,7 @@ Appearance
|
|||
heading of the turtle are sheared.
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
|
||||
>>> turtle.shape("circle")
|
||||
>>> turtle.shapesize(5,2)
|
||||
|
@ -1208,6 +1254,7 @@ Appearance
|
|||
change the turtle's heading (direction of movement).
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
|
||||
>>> turtle.reset()
|
||||
>>> turtle.shape("circle")
|
||||
|
@ -1227,6 +1274,7 @@ Appearance
|
|||
(direction of movement).
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
|
||||
>>> turtle.reset()
|
||||
>>> turtle.shape("circle")
|
||||
|
@ -1252,6 +1300,7 @@ Appearance
|
|||
turtle (its direction of movement).
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
|
||||
>>> turtle.reset()
|
||||
>>> turtle.shape("circle")
|
||||
|
@ -1280,6 +1329,7 @@ Appearance
|
|||
given matrix.
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
|
||||
>>> turtle = Turtle()
|
||||
>>> turtle.shape("square")
|
||||
|
@ -1295,6 +1345,7 @@ Appearance
|
|||
can be used to define a new shape or components of a compound shape.
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
|
||||
>>> turtle.shape("square")
|
||||
>>> turtle.shapetransform(4, -1, 0, 2)
|
||||
|
@ -1318,6 +1369,7 @@ Using events
|
|||
procedural way:
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
|
||||
>>> def turn(x, y):
|
||||
... left(180)
|
||||
|
@ -1338,6 +1390,7 @@ Using events
|
|||
``None``, existing bindings are removed.
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
|
||||
>>> class MyTurtle(Turtle):
|
||||
... def glow(self,x,y):
|
||||
|
@ -1365,6 +1418,7 @@ Using events
|
|||
mouse-click event on that turtle.
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
|
||||
>>> turtle.ondrag(turtle.goto)
|
||||
|
||||
|
@ -1392,6 +1446,7 @@ Special Turtle methods
|
|||
Return the last recorded polygon.
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
|
||||
>>> turtle.home()
|
||||
>>> turtle.begin_poly()
|
||||
|
@ -1411,6 +1466,7 @@ Special Turtle methods
|
|||
turtle properties.
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
|
||||
>>> mick = Turtle()
|
||||
>>> joe = mick.clone()
|
||||
|
@ -1423,6 +1479,7 @@ Special Turtle methods
|
|||
return the "anonymous turtle":
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
|
||||
>>> pet = getturtle()
|
||||
>>> pet.fd(50)
|
||||
|
@ -1436,6 +1493,7 @@ Special Turtle methods
|
|||
TurtleScreen methods can then be called for that object.
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
|
||||
>>> ts = turtle.getscreen()
|
||||
>>> ts
|
||||
|
@ -1453,6 +1511,7 @@ Special Turtle methods
|
|||
``None``, the undobuffer is disabled.
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
|
||||
>>> turtle.setundobuffer(42)
|
||||
|
||||
|
@ -1462,6 +1521,7 @@ Special Turtle methods
|
|||
Return number of entries in the undobuffer.
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
|
||||
>>> while undobufferentries():
|
||||
... undo()
|
||||
|
@ -1484,6 +1544,7 @@ below:
|
|||
For example:
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
|
||||
>>> s = Shape("compound")
|
||||
>>> poly1 = ((0,0),(10,-5),(0,10),(-10,-5))
|
||||
|
@ -1494,6 +1555,7 @@ below:
|
|||
3. Now add the Shape to the Screen's shapelist and use it:
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
|
||||
>>> register_shape("myshape", s)
|
||||
>>> shape("myshape")
|
||||
|
@ -1513,6 +1575,7 @@ Most of the examples in this section refer to a TurtleScreen instance called
|
|||
``screen``.
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
:hide:
|
||||
|
||||
>>> screen = Screen()
|
||||
|
@ -1529,6 +1592,7 @@ Window control
|
|||
Set or return background color of the TurtleScreen.
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
|
||||
>>> screen.bgcolor("orange")
|
||||
>>> screen.bgcolor()
|
||||
|
@ -1614,6 +1678,7 @@ Window control
|
|||
distorted.
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
|
||||
>>> screen.reset()
|
||||
>>> screen.setworldcoordinates(-50,-7.5,50,7.5)
|
||||
|
@ -1624,6 +1689,7 @@ Window control
|
|||
... left(45); fd(2) # a regular octagon
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
:hide:
|
||||
|
||||
>>> screen.reset()
|
||||
|
@ -1645,6 +1711,7 @@ Animation control
|
|||
Optional argument:
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
|
||||
>>> screen.delay()
|
||||
10
|
||||
|
@ -1666,6 +1733,7 @@ Animation control
|
|||
:func:`delay`).
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
|
||||
>>> screen.tracer(8, 25)
|
||||
>>> dist = 2
|
||||
|
@ -1702,6 +1770,7 @@ Using screen events
|
|||
must have the focus. (See method :func:`listen`.)
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
|
||||
>>> def f():
|
||||
... fd(50)
|
||||
|
@ -1722,6 +1791,7 @@ Using screen events
|
|||
must have focus. (See method :func:`listen`.)
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
|
||||
>>> def f():
|
||||
... fd(50)
|
||||
|
@ -1746,6 +1816,7 @@ Using screen events
|
|||
named turtle:
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
|
||||
>>> screen.onclick(turtle.goto) # Subsequently clicking into the TurtleScreen will
|
||||
>>> # make the turtle move to the clicked point.
|
||||
|
@ -1765,6 +1836,7 @@ Using screen events
|
|||
Install a timer that calls *fun* after *t* milliseconds.
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
|
||||
>>> running = True
|
||||
>>> def f():
|
||||
|
@ -1846,6 +1918,7 @@ Settings and special methods
|
|||
============ ========================= ===================
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
|
||||
>>> mode("logo") # resets turtle heading to north
|
||||
>>> mode()
|
||||
|
@ -1860,6 +1933,7 @@ Settings and special methods
|
|||
values of color triples have to be in the range 0..\ *cmode*.
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
|
||||
>>> screen.colormode(1)
|
||||
>>> turtle.pencolor(240, 160, 80)
|
||||
|
@ -1880,6 +1954,7 @@ Settings and special methods
|
|||
do with a Tkinter Canvas.
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
|
||||
>>> cv = screen.getcanvas()
|
||||
>>> cv
|
||||
|
@ -1891,6 +1966,7 @@ Settings and special methods
|
|||
Return a list of names of all currently available turtle shapes.
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
|
||||
>>> screen.getshapes()
|
||||
['arrow', 'blank', 'circle', ..., 'turtle']
|
||||
|
@ -1914,6 +1990,7 @@ Settings and special methods
|
|||
coordinates: Install the corresponding polygon shape.
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
|
||||
>>> screen.register_shape("triangle", ((5,-3), (0,5), (-5,-3)))
|
||||
|
||||
|
@ -1929,6 +2006,7 @@ Settings and special methods
|
|||
Return the list of turtles on the screen.
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
|
||||
>>> for turtle in screen.turtles():
|
||||
... turtle.color("red")
|
||||
|
@ -1990,6 +2068,7 @@ Methods specific to Screen, not inherited from TurtleScreen
|
|||
center window vertically
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
|
||||
>>> screen.setup (width=200, height=200, startx=0, starty=0)
|
||||
>>> # sets window to 200x200 pixels, in upper left of screen
|
||||
|
@ -2005,6 +2084,7 @@ Methods specific to Screen, not inherited from TurtleScreen
|
|||
Set title of turtle window to *titlestring*.
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
|
||||
>>> screen.title("Welcome to the turtle zoo!")
|
||||
|
||||
|
@ -2075,6 +2155,7 @@ Public classes
|
|||
Example:
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
|
||||
>>> poly = ((0,0),(10,-5),(0,10),(-10,-5))
|
||||
>>> s = Shape("compound")
|
||||
|
@ -2421,6 +2502,7 @@ Changes since Python 3.0
|
|||
|
||||
|
||||
.. doctest::
|
||||
:skipif: _tkinter is None
|
||||
:hide:
|
||||
|
||||
>>> for turtle in turtles():
|
||||
|
|
|
@ -9,6 +9,19 @@
|
|||
|
||||
.. _getting-started:
|
||||
|
||||
|
||||
.. testsetup::
|
||||
|
||||
import unittest
|
||||
from unittest.mock import Mock, MagicMock, patch, call, sentinel
|
||||
|
||||
class SomeClass:
|
||||
attribute = 'this is a doctest'
|
||||
|
||||
@staticmethod
|
||||
def static_method():
|
||||
pass
|
||||
|
||||
Using Mock
|
||||
----------
|
||||
|
||||
|
@ -99,7 +112,7 @@ by looking at the return value of the mocked class.
|
|||
In the example below we have a function ``some_function`` that instantiates ``Foo``
|
||||
and calls a method on it. The call to :func:`patch` replaces the class ``Foo`` with a
|
||||
mock. The ``Foo`` instance is the result of calling the mock, so it is configured
|
||||
by modifying the mock :attr:`~Mock.return_value`.
|
||||
by modifying the mock :attr:`~Mock.return_value`. ::
|
||||
|
||||
>>> def some_function():
|
||||
... instance = module.Foo()
|
||||
|
@ -321,7 +334,7 @@ whatever) to be replaced with. 'patch.object' takes an object and the name of
|
|||
the attribute you would like patched, plus optionally the value to patch it
|
||||
with.
|
||||
|
||||
``patch.object``:
|
||||
``patch.object``::
|
||||
|
||||
>>> original = SomeClass.attribute
|
||||
>>> @patch.object(SomeClass, 'attribute', sentinel.attribute)
|
||||
|
@ -348,7 +361,7 @@ instead of :func:`patch.object`:
|
|||
>>> mock.assert_called_with('filename', 'r')
|
||||
>>> assert handle == sentinel.file_handle, "incorrect file handle returned"
|
||||
|
||||
The module name can be 'dotted', in the form ``package.module`` if needed:
|
||||
The module name can be 'dotted', in the form ``package.module`` if needed::
|
||||
|
||||
>>> @patch('package.module.ClassName.attribute', sentinel.attribute)
|
||||
... def test():
|
||||
|
@ -380,7 +393,7 @@ passed into the test function / method:
|
|||
...
|
||||
>>> MyTest('test_something').test_something()
|
||||
|
||||
You can stack up multiple patch decorators using this pattern:
|
||||
You can stack up multiple patch decorators using this pattern::
|
||||
|
||||
>>> class MyTest(unittest.TestCase):
|
||||
... @patch('package.module.ClassName1')
|
||||
|
@ -485,7 +498,7 @@ response object for it. To set the response as the return value for that final
|
|||
mock_backend.get_endpoint.return_value.create_call.return_value.start_call.return_value = mock_response
|
||||
|
||||
We can do that in a slightly nicer way using the :meth:`~Mock.configure_mock`
|
||||
method to directly set the return value for us:
|
||||
method to directly set the return value for us::
|
||||
|
||||
>>> something = Something()
|
||||
>>> mock_response = Mock(spec=open)
|
||||
|
@ -494,7 +507,7 @@ method to directly set the return value for us:
|
|||
>>> mock_backend.configure_mock(**config)
|
||||
|
||||
With these we monkey patch the "mock backend" in place and can make the real
|
||||
call:
|
||||
call::
|
||||
|
||||
>>> something.backend = mock_backend
|
||||
>>> something.method()
|
||||
|
@ -502,7 +515,7 @@ call:
|
|||
Using :attr:`~Mock.mock_calls` we can check the chained call with a single
|
||||
assert. A chained call is several calls in one line of code, so there will be
|
||||
several entries in ``mock_calls``. We can use :meth:`call.call_list` to create
|
||||
this list of calls for us:
|
||||
this list of calls for us::
|
||||
|
||||
>>> chained = call.get_endpoint('foobar').create_call('spam', 'eggs').start_call()
|
||||
>>> call_list = chained.call_list()
|
||||
|
@ -525,7 +538,7 @@ The :func:`patch decorator <patch>` is used here to
|
|||
mock out the ``date`` class in the module under test. The :attr:`side_effect`
|
||||
attribute on the mock date class is then set to a lambda function that returns
|
||||
a real date. When the mock date class is called a real date will be
|
||||
constructed and returned by ``side_effect``.
|
||||
constructed and returned by ``side_effect``. ::
|
||||
|
||||
>>> from datetime import date
|
||||
>>> with patch('mymodule.date') as mock_date:
|
||||
|
@ -534,7 +547,6 @@ constructed and returned by ``side_effect``.
|
|||
...
|
||||
... assert mymodule.date.today() == date(2010, 10, 8)
|
||||
... assert mymodule.date(2009, 6, 8) == date(2009, 6, 8)
|
||||
...
|
||||
|
||||
Note that we don't patch :class:`datetime.date` globally, we patch ``date`` in the
|
||||
module that *uses* it. See :ref:`where to patch <where-to-patch>`.
|
||||
|
@ -600,10 +612,10 @@ is to apply the patch decorators to every method. This can feel like unnecessary
|
|||
repetition. For Python 2.6 or more recent you can use :func:`patch` (in all its
|
||||
various forms) as a class decorator. This applies the patches to all test
|
||||
methods on the class. A test method is identified by methods whose names start
|
||||
with ``test``:
|
||||
with ``test``::
|
||||
|
||||
>>> @patch('mymodule.SomeClass')
|
||||
... class MyTest(TestCase):
|
||||
... class MyTest(unittest.TestCase):
|
||||
...
|
||||
... def test_one(self, MockSomeClass):
|
||||
... self.assertIs(mymodule.SomeClass, MockSomeClass)
|
||||
|
@ -621,8 +633,9 @@ with ``test``:
|
|||
|
||||
An alternative way of managing patches is to use the :ref:`start-and-stop`.
|
||||
These allow you to move the patching into your ``setUp`` and ``tearDown`` methods.
|
||||
::
|
||||
|
||||
>>> class MyTest(TestCase):
|
||||
>>> class MyTest(unittest.TestCase):
|
||||
... def setUp(self):
|
||||
... self.patcher = patch('mymodule.foo')
|
||||
... self.mock_foo = self.patcher.start()
|
||||
|
@ -638,9 +651,9 @@ These allow you to move the patching into your ``setUp`` and ``tearDown`` method
|
|||
If you use this technique you must ensure that the patching is "undone" by
|
||||
calling ``stop``. This can be fiddlier than you might think, because if an
|
||||
exception is raised in the setUp then tearDown is not called.
|
||||
:meth:`unittest.TestCase.addCleanup` makes this easier:
|
||||
:meth:`unittest.TestCase.addCleanup` makes this easier::
|
||||
|
||||
>>> class MyTest(TestCase):
|
||||
>>> class MyTest(unittest.TestCase):
|
||||
... def setUp(self):
|
||||
... patcher = patch('mymodule.foo')
|
||||
... self.addCleanup(patcher.stop)
|
||||
|
@ -753,7 +766,7 @@ defined in 'mymodule'::
|
|||
val.clear()
|
||||
|
||||
When we try to test that ``grob`` calls ``frob`` with the correct argument look
|
||||
what happens:
|
||||
what happens::
|
||||
|
||||
>>> with patch('mymodule.frob') as mock_frob:
|
||||
... val = {6}
|
||||
|
@ -777,7 +790,7 @@ functionality. If you provide a ``side_effect`` function for a mock then
|
|||
opportunity to copy the arguments and store them for later assertions. In this
|
||||
example I'm using *another* mock to store the arguments so that I can use the
|
||||
mock methods for doing the assertion. Again a helper function sets this up for
|
||||
me.
|
||||
me. ::
|
||||
|
||||
>>> from copy import deepcopy
|
||||
>>> from unittest.mock import Mock, patch, DEFAULT
|
||||
|
@ -854,9 +867,9 @@ Nesting Patches
|
|||
|
||||
Using patch as a context manager is nice, but if you do multiple patches you
|
||||
can end up with nested with statements indenting further and further to the
|
||||
right:
|
||||
right::
|
||||
|
||||
>>> class MyTest(TestCase):
|
||||
>>> class MyTest(unittest.TestCase):
|
||||
...
|
||||
... def test_foo(self):
|
||||
... with patch('mymodule.Foo') as mock_foo:
|
||||
|
@ -873,9 +886,9 @@ right:
|
|||
With unittest ``cleanup`` functions and the :ref:`start-and-stop` we can
|
||||
achieve the same effect without the nested indentation. A simple helper
|
||||
method, ``create_patch``, puts the patch in place and returns the created mock
|
||||
for us:
|
||||
for us::
|
||||
|
||||
>>> class MyTest(TestCase):
|
||||
>>> class MyTest(unittest.TestCase):
|
||||
...
|
||||
... def create_patch(self, name):
|
||||
... patcher = patch(name)
|
||||
|
@ -969,7 +982,7 @@ mock methods and attributes:
|
|||
>>> mock.__setitem__.call_args_list
|
||||
[call('b', 'fish'), call('d', 'eggs')]
|
||||
>>> my_dict
|
||||
{'a': 1, 'c': 3, 'b': 'fish', 'd': 'eggs'}
|
||||
{'a': 1, 'b': 'fish', 'c': 3, 'd': 'eggs'}
|
||||
|
||||
|
||||
Mock subclasses and their attributes
|
||||
|
@ -1064,6 +1077,7 @@ previously will be restored safely.
|
|||
|
||||
Here's an example that mocks out the 'fooble' module.
|
||||
|
||||
>>> import sys
|
||||
>>> mock = Mock()
|
||||
>>> with patch.dict('sys.modules', {'fooble': mock}):
|
||||
... import fooble
|
||||
|
@ -1132,7 +1146,7 @@ the ``mock_calls`` attribute on the manager mock:
|
|||
|
||||
If ``patch`` is creating, and putting in place, your mocks then you can attach
|
||||
them to a manager mock using the :meth:`~Mock.attach_mock` method. After
|
||||
attaching calls will be recorded in ``mock_calls`` of the manager.
|
||||
attaching calls will be recorded in ``mock_calls`` of the manager. ::
|
||||
|
||||
>>> manager = MagicMock()
|
||||
>>> with patch('mymodule.Class1') as MockClass1:
|
||||
|
@ -1141,7 +1155,6 @@ attaching calls will be recorded in ``mock_calls`` of the manager.
|
|||
... manager.attach_mock(MockClass2, 'MockClass2')
|
||||
... MockClass1().foo()
|
||||
... MockClass2().bar()
|
||||
...
|
||||
<MagicMock name='mock.MockClass1().foo()' id='...'>
|
||||
<MagicMock name='mock.MockClass2().bar()' id='...'>
|
||||
>>> manager.mock_calls
|
||||
|
|
|
@ -41,6 +41,22 @@ available as `mock on PyPI <https://pypi.org/project/mock>`_.
|
|||
Quick Guide
|
||||
-----------
|
||||
|
||||
.. testsetup::
|
||||
|
||||
class ProductionClass:
|
||||
def method(self, a, b, c):
|
||||
pass
|
||||
|
||||
class SomeClass:
|
||||
@staticmethod
|
||||
def static_method(args):
|
||||
return args
|
||||
|
||||
@classmethod
|
||||
def class_method(cls, args):
|
||||
return args
|
||||
|
||||
|
||||
:class:`Mock` and :class:`MagicMock` objects create all attributes and
|
||||
methods as you access them and store details of how they have been used. You
|
||||
can configure them, to specify return values or limit what attributes are
|
||||
|
@ -80,7 +96,7 @@ that don't exist on the spec will fail with an :exc:`AttributeError`.
|
|||
|
||||
The :func:`patch` decorator / context manager makes it easy to mock classes or
|
||||
objects in a module under test. The object you specify will be replaced with a
|
||||
mock (or other object) during the test and restored when the test ends:
|
||||
mock (or other object) during the test and restored when the test ends::
|
||||
|
||||
>>> from unittest.mock import patch
|
||||
>>> @patch('module.ClassName2')
|
||||
|
@ -183,6 +199,12 @@ the ``__call__`` method.
|
|||
The Mock Class
|
||||
--------------
|
||||
|
||||
.. testsetup::
|
||||
|
||||
import unittest
|
||||
from unittest.mock import sentinel, DEFAULT, ANY
|
||||
from unittest.mock import patch, call, Mock, MagicMock, PropertyMock
|
||||
from unittest.mock import mock_open
|
||||
|
||||
:class:`Mock` is a flexible mock object intended to replace the use of stubs and
|
||||
test doubles throughout your code. Mocks are callable and create attributes as
|
||||
|
@ -774,7 +796,7 @@ apply to method calls on the mock object.
|
|||
so you can specify a return value when it is fetched.
|
||||
|
||||
Fetching a :class:`PropertyMock` instance from an object calls the mock, with
|
||||
no args. Setting it calls the mock with the value being set.
|
||||
no args. Setting it calls the mock with the value being set. ::
|
||||
|
||||
>>> class Foo:
|
||||
... @property
|
||||
|
@ -1001,7 +1023,7 @@ the "parenting" if for some reason you don't want it to happen.
|
|||
|
||||
Mocks created for you by :func:`patch` are automatically given names. To
|
||||
attach mocks that have names to a parent you use the :meth:`~Mock.attach_mock`
|
||||
method:
|
||||
method::
|
||||
|
||||
>>> thing1 = object()
|
||||
>>> thing2 = object()
|
||||
|
@ -1117,7 +1139,7 @@ patch
|
|||
available for alternate use-cases.
|
||||
|
||||
:func:`patch` as function decorator, creating the mock for you and passing it into
|
||||
the decorated function:
|
||||
the decorated function::
|
||||
|
||||
>>> @patch('__main__.SomeClass')
|
||||
... def function(normal_argument, mock_class):
|
||||
|
@ -1135,7 +1157,7 @@ If the class is instantiated multiple times you could use
|
|||
can set the *return_value* to be anything you want.
|
||||
|
||||
To configure return values on methods of *instances* on the patched class
|
||||
you must do this on the :attr:`return_value`. For example:
|
||||
you must do this on the :attr:`return_value`. For example::
|
||||
|
||||
>>> class Class:
|
||||
... def method(self):
|
||||
|
@ -1149,7 +1171,7 @@ you must do this on the :attr:`return_value`. For example:
|
|||
...
|
||||
|
||||
If you use *spec* or *spec_set* and :func:`patch` is replacing a *class*, then the
|
||||
return value of the created mock will have the same spec.
|
||||
return value of the created mock will have the same spec. ::
|
||||
|
||||
>>> Original = Class
|
||||
>>> patcher = patch('__main__.Class', spec=True)
|
||||
|
@ -1160,7 +1182,7 @@ return value of the created mock will have the same spec.
|
|||
|
||||
The *new_callable* argument is useful where you want to use an alternative
|
||||
class to the default :class:`MagicMock` for the created mock. For example, if
|
||||
you wanted a :class:`NonCallableMock` to be used:
|
||||
you wanted a :class:`NonCallableMock` to be used::
|
||||
|
||||
>>> thing = object()
|
||||
>>> with patch('__main__.thing', new_callable=NonCallableMock) as mock_thing:
|
||||
|
@ -1171,7 +1193,7 @@ you wanted a :class:`NonCallableMock` to be used:
|
|||
...
|
||||
TypeError: 'NonCallableMock' object is not callable
|
||||
|
||||
Another use case might be to replace an object with an :class:`io.StringIO` instance:
|
||||
Another use case might be to replace an object with an :class:`io.StringIO` instance::
|
||||
|
||||
>>> from io import StringIO
|
||||
>>> def foo():
|
||||
|
@ -1187,7 +1209,7 @@ Another use case might be to replace an object with an :class:`io.StringIO` inst
|
|||
When :func:`patch` is creating a mock for you, it is common that the first thing
|
||||
you need to do is to configure the mock. Some of that configuration can be done
|
||||
in the call to patch. Any arbitrary keywords you pass into the call will be
|
||||
used to set attributes on the created mock:
|
||||
used to set attributes on the created mock::
|
||||
|
||||
>>> patcher = patch('__main__.thing', first='one', second='two')
|
||||
>>> mock_thing = patcher.start()
|
||||
|
@ -1200,7 +1222,7 @@ As well as attributes on the created mock attributes, like the
|
|||
:attr:`~Mock.return_value` and :attr:`~Mock.side_effect`, of child mocks can
|
||||
also be configured. These aren't syntactically valid to pass in directly as
|
||||
keyword arguments, but a dictionary with these as keys can still be expanded
|
||||
into a :func:`patch` call using ``**``:
|
||||
into a :func:`patch` call using ``**``::
|
||||
|
||||
>>> config = {'method.return_value': 3, 'other.side_effect': KeyError}
|
||||
>>> patcher = patch('__main__.thing', **config)
|
||||
|
@ -1359,7 +1381,7 @@ patch.multiple
|
|||
|
||||
If you want :func:`patch.multiple` to create mocks for you, then you can use
|
||||
:data:`DEFAULT` as the value. If you use :func:`patch.multiple` as a decorator
|
||||
then the created mocks are passed into the decorated function by keyword.
|
||||
then the created mocks are passed into the decorated function by keyword. ::
|
||||
|
||||
>>> thing = object()
|
||||
>>> other = object()
|
||||
|
@ -1372,7 +1394,7 @@ then the created mocks are passed into the decorated function by keyword.
|
|||
>>> test_function()
|
||||
|
||||
:func:`patch.multiple` can be nested with other ``patch`` decorators, but put arguments
|
||||
passed by keyword *after* any of the standard arguments created by :func:`patch`:
|
||||
passed by keyword *after* any of the standard arguments created by :func:`patch`::
|
||||
|
||||
>>> @patch('sys.exit')
|
||||
... @patch.multiple('__main__', thing=DEFAULT, other=DEFAULT)
|
||||
|
@ -1384,7 +1406,7 @@ passed by keyword *after* any of the standard arguments created by :func:`patch`
|
|||
>>> test_function()
|
||||
|
||||
If :func:`patch.multiple` is used as a context manager, the value returned by the
|
||||
context manger is a dictionary where created mocks are keyed by name:
|
||||
context manger is a dictionary where created mocks are keyed by name::
|
||||
|
||||
>>> with patch.multiple('__main__', thing=DEFAULT, other=DEFAULT) as values:
|
||||
... assert 'other' in repr(values['other'])
|
||||
|
@ -1408,7 +1430,7 @@ normal and keep a reference to the returned ``patcher`` object. You can then
|
|||
call :meth:`start` to put the patch in place and :meth:`stop` to undo it.
|
||||
|
||||
If you are using :func:`patch` to create a mock for you then it will be returned by
|
||||
the call to ``patcher.start``.
|
||||
the call to ``patcher.start``. ::
|
||||
|
||||
>>> patcher = patch('package.module.ClassName')
|
||||
>>> from package import module
|
||||
|
@ -1422,9 +1444,9 @@ the call to ``patcher.start``.
|
|||
|
||||
|
||||
A typical use case for this might be for doing multiple patches in the ``setUp``
|
||||
method of a :class:`TestCase`:
|
||||
method of a :class:`TestCase`::
|
||||
|
||||
>>> class MyTest(TestCase):
|
||||
>>> class MyTest(unittest.TestCase):
|
||||
... def setUp(self):
|
||||
... self.patcher1 = patch('package.module.Class1')
|
||||
... self.patcher2 = patch('package.module.Class2')
|
||||
|
@ -1446,9 +1468,9 @@ method of a :class:`TestCase`:
|
|||
If you use this technique you must ensure that the patching is "undone" by
|
||||
calling ``stop``. This can be fiddlier than you might think, because if an
|
||||
exception is raised in the ``setUp`` then ``tearDown`` is not called.
|
||||
:meth:`unittest.TestCase.addCleanup` makes this easier:
|
||||
:meth:`unittest.TestCase.addCleanup` makes this easier::
|
||||
|
||||
>>> class MyTest(TestCase):
|
||||
>>> class MyTest(unittest.TestCase):
|
||||
... def setUp(self):
|
||||
... patcher = patch('package.module.Class')
|
||||
... self.MockClass = patcher.start()
|
||||
|
@ -1474,7 +1496,7 @@ It is also possible to stop all patches which have been started by using
|
|||
patch builtins
|
||||
~~~~~~~~~~~~~~
|
||||
You can patch any builtins within a module. The following example patches
|
||||
builtin :func:`ord`:
|
||||
builtin :func:`ord`::
|
||||
|
||||
>>> @patch('__main__.ord')
|
||||
... def test(mock_ord):
|
||||
|
@ -1494,7 +1516,7 @@ start with ``'test'`` as being test methods. This is the same way that the
|
|||
:class:`unittest.TestLoader` finds test methods by default.
|
||||
|
||||
It is possible that you want to use a different prefix for your tests. You can
|
||||
inform the patchers of the different prefix by setting ``patch.TEST_PREFIX``:
|
||||
inform the patchers of the different prefix by setting ``patch.TEST_PREFIX``::
|
||||
|
||||
>>> patch.TEST_PREFIX = 'foo'
|
||||
>>> value = 3
|
||||
|
@ -1931,7 +1953,7 @@ arguments are a dictionary:
|
|||
>>> args
|
||||
(1, 2, 3)
|
||||
>>> kwargs
|
||||
{'arg2': 'two', 'arg': 'one'}
|
||||
{'arg': 'one', 'arg2': 'two'}
|
||||
>>> args is kall[0]
|
||||
True
|
||||
>>> kwargs is kall[1]
|
||||
|
@ -1947,7 +1969,7 @@ arguments are a dictionary:
|
|||
>>> args
|
||||
(4, 5, 6)
|
||||
>>> kwargs
|
||||
{'arg2': 'three', 'arg': 'two'}
|
||||
{'arg': 'two', 'arg2': 'three'}
|
||||
>>> name is m.mock_calls[0][0]
|
||||
True
|
||||
|
||||
|
@ -2027,11 +2049,17 @@ If the mock was created with a *spec* (or *autospec* of course) then all the
|
|||
attributes from the original are shown, even if they haven't been accessed
|
||||
yet:
|
||||
|
||||
.. doctest::
|
||||
:options: +ELLIPSIS,+NORMALIZE_WHITESPACE
|
||||
|
||||
>>> dir(Mock())
|
||||
['assert_any_call',
|
||||
'assert_called',
|
||||
'assert_called_once',
|
||||
'assert_called_once_with',
|
||||
'assert_called_with',
|
||||
'assert_has_calls',
|
||||
'assert_not_called',
|
||||
'attach_mock',
|
||||
...
|
||||
>>> from urllib import request
|
||||
|
@ -2048,6 +2076,9 @@ filtered from the result of calling :func:`dir` on a :class:`Mock`. If you disli
|
|||
behaviour you can switch it off by setting the module level switch
|
||||
:data:`FILTER_DIR`:
|
||||
|
||||
.. doctest::
|
||||
:options: +ELLIPSIS,+NORMALIZE_WHITESPACE
|
||||
|
||||
>>> from unittest import mock
|
||||
>>> mock.FILTER_DIR = False
|
||||
>>> dir(mock.Mock())
|
||||
|
@ -2110,7 +2141,7 @@ The issue is that even if you mock out the call to :func:`open` it is the
|
|||
:meth:`__exit__` called).
|
||||
|
||||
Mocking context managers with a :class:`MagicMock` is common enough and fiddly
|
||||
enough that a helper function is useful.
|
||||
enough that a helper function is useful. ::
|
||||
|
||||
>>> m = mock_open()
|
||||
>>> with patch('__main__.open', m):
|
||||
|
@ -2126,7 +2157,7 @@ enough that a helper function is useful.
|
|||
>>> handle = m()
|
||||
>>> handle.write.assert_called_once_with('some stuff')
|
||||
|
||||
And for reading files:
|
||||
And for reading files::
|
||||
|
||||
>>> with patch('__main__.open', mock_open(read_data='bibble')) as m:
|
||||
... with open('foo') as h:
|
||||
|
@ -2219,7 +2250,7 @@ accessed) you can use it with very complex or deeply nested objects (like
|
|||
modules that import modules that import modules) without a big performance
|
||||
hit.
|
||||
|
||||
Here's an example of it in use:
|
||||
Here's an example of it in use::
|
||||
|
||||
>>> from urllib import request
|
||||
>>> patcher = patch('__main__.request', autospec=True)
|
||||
|
@ -2231,7 +2262,7 @@ Here's an example of it in use:
|
|||
|
||||
You can see that :class:`request.Request` has a spec. :class:`request.Request` takes two
|
||||
arguments in the constructor (one of which is *self*). Here's what happens if
|
||||
we try to call it incorrectly:
|
||||
we try to call it incorrectly::
|
||||
|
||||
>>> req = request.Request()
|
||||
Traceback (most recent call last):
|
||||
|
@ -2239,7 +2270,7 @@ we try to call it incorrectly:
|
|||
TypeError: <lambda>() takes at least 2 arguments (1 given)
|
||||
|
||||
The spec also applies to instantiated classes (i.e. the return value of
|
||||
specced mocks):
|
||||
specced mocks)::
|
||||
|
||||
>>> req = request.Request('foo')
|
||||
>>> req
|
||||
|
@ -2247,7 +2278,7 @@ specced mocks):
|
|||
|
||||
:class:`Request` objects are not callable, so the return value of instantiating our
|
||||
mocked out :class:`request.Request` is a non-callable mock. With the spec in place
|
||||
any typos in our asserts will raise the correct error:
|
||||
any typos in our asserts will raise the correct error::
|
||||
|
||||
>>> req.add_header('spam', 'eggs')
|
||||
<MagicMock name='request.Request().add_header()' id='...'>
|
||||
|
@ -2281,7 +2312,7 @@ objects so that introspection is safe [#]_.
|
|||
A more serious problem is that it is common for instance attributes to be
|
||||
created in the :meth:`__init__` method and not to exist on the class at all.
|
||||
*autospec* can't know about any dynamically created attributes and restricts
|
||||
the api to visible attributes.
|
||||
the api to visible attributes. ::
|
||||
|
||||
>>> class Something:
|
||||
... def __init__(self):
|
||||
|
@ -2299,7 +2330,7 @@ There are a few different ways of resolving this problem. The easiest, but
|
|||
not necessarily the least annoying, way is to simply set the required
|
||||
attributes on the mock after creation. Just because *autospec* doesn't allow
|
||||
you to fetch attributes that don't exist on the spec it doesn't prevent you
|
||||
setting them:
|
||||
setting them::
|
||||
|
||||
>>> with patch('__main__.Something', autospec=True):
|
||||
... thing = Something()
|
||||
|
@ -2350,7 +2381,7 @@ spec rather than the class. The other is to create a subclass of the
|
|||
production class and add the defaults to the subclass without affecting the
|
||||
production class. Both of these require you to use an alternative object as
|
||||
the spec. Thankfully :func:`patch` supports this - you can simply pass the
|
||||
alternative object as the *autospec* argument:
|
||||
alternative object as the *autospec* argument::
|
||||
|
||||
>>> class Something:
|
||||
... def __init__(self):
|
||||
|
@ -2372,6 +2403,11 @@ alternative object as the *autospec* argument:
|
|||
Sealing mocks
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
|
||||
.. testsetup::
|
||||
|
||||
from unittest.mock import seal
|
||||
|
||||
.. function:: seal(mock)
|
||||
|
||||
Seal will disable the creation of mock children by preventing getting or setting
|
||||
|
@ -2379,7 +2415,7 @@ Sealing mocks
|
|||
|
||||
If a mock instance is assigned to an attribute instead of being dynamically created
|
||||
it won't be considered in the sealing chain. This allows one to prevent seal from
|
||||
fixing part of the mock object.
|
||||
fixing part of the mock object. ::
|
||||
|
||||
>>> mock = Mock()
|
||||
>>> mock.submock.attribute1 = 2
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
make docstest in Doc now passes., and is enforced in CI
|
Loading…
Reference in New Issue