Skip to content

Commit d381022

Browse files
jorisvandenbosschevictor
authored and
victor
committed
DOC/CI: run doctests on travis (pandas-dev#19952)
1 parent 835be11 commit d381022

File tree

9 files changed

+105
-40
lines changed

9 files changed

+105
-40
lines changed

.travis.yml

+2-1
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ matrix:
5656
- python-gtk2
5757
- dist: trusty
5858
env:
59-
- JOB="3.6, coverage" ENV_FILE="ci/travis-36.yaml" TEST_ARGS="--skip-slow --skip-network" PANDAS_TESTING_MODE="deprecate" COVERAGE=true
59+
- JOB="3.6, coverage" ENV_FILE="ci/travis-36.yaml" TEST_ARGS="--skip-slow --skip-network" PANDAS_TESTING_MODE="deprecate" COVERAGE=true DOCTEST=true
6060
# In allow_failures
6161
- dist: trusty
6262
env:
@@ -119,6 +119,7 @@ script:
119119
- ci/script_single.sh
120120
- ci/script_multi.sh
121121
- ci/lint.sh
122+
- ci/doctests.sh
122123
- echo "checking imports"
123124
- source activate pandas && python ci/check_imports.py
124125
- echo "script done"

ci/build_docs.sh

-18
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,6 @@ fi
88
cd "$TRAVIS_BUILD_DIR"
99
echo "inside $0"
1010

11-
git show --pretty="format:" --name-only HEAD~5.. --first-parent | grep -P "rst|txt|doc"
12-
13-
# if [ "$?" != "0" ]; then
14-
# echo "Skipping doc build, none were modified"
15-
# # nope, skip docs build
16-
# exit 0
17-
# fi
18-
19-
2011
if [ "$DOC" ]; then
2112

2213
echo "Will build docs"
@@ -60,15 +51,6 @@ if [ "$DOC" ]; then
6051
git remote -v
6152

6253
git push origin gh-pages -f
63-
64-
echo "Running doctests"
65-
cd "$TRAVIS_BUILD_DIR"
66-
pytest --doctest-modules \
67-
pandas/core/reshape/concat.py \
68-
pandas/core/reshape/pivot.py \
69-
pandas/core/reshape/reshape.py \
70-
pandas/core/reshape/tile.py
71-
7254
fi
7355

7456
exit 0

ci/doctests.sh

+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
#!/bin/bash
2+
3+
echo "inside $0"
4+
5+
6+
source activate pandas
7+
cd "$TRAVIS_BUILD_DIR"
8+
9+
RET=0
10+
11+
if [ "$DOCTEST" ]; then
12+
13+
echo "Running doctests"
14+
15+
# running all doctests is not yet working
16+
# pytest --doctest-modules --ignore=pandas/tests -v pandas
17+
18+
# if [ $? -ne "0" ]; then
19+
# RET=1
20+
# fi
21+
22+
# DataFrame / Series docstrings
23+
pytest --doctest-modules -v pandas/core/frame.py \
24+
-k"-assign -axes -combine -isin -itertuples -join -nlargest -nsmallest -nunique -pivot_table -quantile -query -reindex -reindex_axis -replace -round -set_index -stack -to_dict -to_records -to_stata -transform"
25+
26+
if [ $? -ne "0" ]; then
27+
RET=1
28+
fi
29+
30+
pytest --doctest-modules -v pandas/core/series.py \
31+
-k"-agg -map -nlargest -nonzero -nsmallest -reindex -searchsorted -to_dict"
32+
33+
if [ $? -ne "0" ]; then
34+
RET=1
35+
fi
36+
37+
pytest --doctest-modules -v pandas/core/generic.py \
38+
-k"-_set_axis_name -_xs -describe -droplevel -groupby -interpolate -pct_change -pipe -reindex -reindex_axis -resample -sample -to_json -to_xarray -transform -transpose -values -xs"
39+
40+
if [ $? -ne "0" ]; then
41+
RET=1
42+
fi
43+
44+
# top-level reshaping functions
45+
pytest --doctest-modules -v \
46+
pandas/core/reshape/concat.py \
47+
pandas/core/reshape/pivot.py \
48+
pandas/core/reshape/reshape.py \
49+
pandas/core/reshape/tile.py \
50+
-k"-crosstab -pivot_table -cut"
51+
52+
if [ $? -ne "0" ]; then
53+
RET=1
54+
fi
55+
56+
else
57+
echo "NOT running doctests"
58+
fi
59+
60+
exit $RET

doc/source/contributing.rst

+25
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,31 @@ This will identify methods documented in ``doc/source/api.rst`` that are not act
365365
class methods, and existing methods that are not documented in ``doc/source/api.rst``.
366366

367367

368+
Updating a *pandas* docstring
369+
-----------------------------
370+
371+
When improving a single function or method's docstring, it is not necessarily
372+
needed to build the full documentation (see next section).
373+
However, there is a script that checks a docstring (for example for the ``DataFrame.mean`` method)::
374+
375+
python scripts/validate_docstrings.py pandas.DataFrame.mean
376+
377+
This script will indicate some formatting errors if present, and will also
378+
run and test the examples included in the docstring.
379+
Check the :ref:`pandas docstring guide <docstring>` for a detailed guide
380+
on how to format the docstring.
381+
382+
The examples in the docstring ('doctests') must be valid Python code,
383+
that in a deterministic way returns the presented output, and that can be
384+
copied and run by users. This can be checked with the script above, and is
385+
also tested on Travis. A failing doctest will be a blocker for merging a PR.
386+
Check the :ref:`examples <docstring.examples>` section in the docstring guide
387+
for some tips and tricks to get the doctests passing.
388+
389+
When doing a PR with a docstring update, it is good to post the
390+
output of the validation script in a comment on github.
391+
392+
368393
How to build the *pandas* documentation
369394
---------------------------------------
370395

pandas/core/config.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,7 @@ class option_context(object):
384384
--------
385385
386386
>>> with option_context('display.max_rows', 10, 'display.max_columns', 5):
387-
...
387+
... ...
388388
389389
"""
390390

pandas/core/frame.py

+6-8
Original file line numberDiff line numberDiff line change
@@ -314,15 +314,13 @@ class DataFrame(NDFrame):
314314
315315
Constructing DataFrame from numpy ndarray:
316316
317-
>>> df2 = pd.DataFrame(np.random.randint(low=0, high=10, size=(5, 5)),
318-
... columns=['a', 'b', 'c', 'd', 'e'])
317+
>>> df2 = pd.DataFrame(np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]),
318+
... columns=['a', 'b', 'c'])
319319
>>> df2
320-
a b c d e
321-
0 2 8 8 3 4
322-
1 4 2 9 0 9
323-
2 1 0 7 8 0
324-
3 5 1 7 1 3
325-
4 6 0 2 4 2
320+
a b c
321+
0 1 2 3
322+
1 4 5 6
323+
2 7 8 9
326324
327325
See also
328326
--------

pandas/core/generic.py

+6-6
Original file line numberDiff line numberDiff line change
@@ -738,14 +738,14 @@ def droplevel(self, level, axis=0):
738738
Examples
739739
--------
740740
>>> df = pd.DataFrame([
741-
...: [1, 2, 3, 4],
742-
...: [5, 6, 7, 8],
743-
...: [9, 10, 11, 12]
744-
...: ]).set_index([0, 1]).rename_axis(['a', 'b'])
741+
... [1, 2, 3, 4],
742+
... [5, 6, 7, 8],
743+
... [9, 10, 11, 12]
744+
... ]).set_index([0, 1]).rename_axis(['a', 'b'])
745745
746746
>>> df.columns = pd.MultiIndex.from_tuples([
747-
...: ('c', 'e'), ('d', 'f')
748-
...:], names=['level_1', 'level_2'])
747+
... ('c', 'e'), ('d', 'f')
748+
... ], names=['level_1', 'level_2'])
749749
750750
>>> df
751751
level_1 c d

pandas/util/testing.py

+4-5
Original file line numberDiff line numberDiff line change
@@ -591,7 +591,7 @@ def set_defaultencoding(encoding):
591591

592592

593593
def capture_stdout(f):
594-
"""
594+
r"""
595595
Decorator to capture stdout in a buffer so that it can be checked
596596
(or suppressed) during testing.
597597
@@ -609,7 +609,6 @@ def capture_stdout(f):
609609
--------
610610
611611
>>> from pandas.util.testing import capture_stdout
612-
>>>
613612
>>> import sys
614613
>>>
615614
>>> @capture_stdout
@@ -639,7 +638,7 @@ def wrapper(*args, **kwargs):
639638

640639

641640
def capture_stderr(f):
642-
"""
641+
r"""
643642
Decorator to capture stderr in a buffer so that it can be checked
644643
(or suppressed) during testing.
645644
@@ -657,7 +656,6 @@ def capture_stderr(f):
657656
--------
658657
659658
>>> from pandas.util.testing import capture_stderr
660-
>>>
661659
>>> import sys
662660
>>>
663661
>>> @capture_stderr
@@ -2370,7 +2368,7 @@ def wrapper(*args, **kwargs):
23702368

23712369
def assert_raises_regex(_exception, _regexp, _callable=None,
23722370
*args, **kwargs):
2373-
r"""
2371+
"""
23742372
Check that the specified Exception is raised and that the error message
23752373
matches a given regular expression pattern. This may be a regular
23762374
expression object or a string containing a regular expression suitable
@@ -2396,6 +2394,7 @@ def assert_raises_regex(_exception, _regexp, _callable=None,
23962394
AssertionError: "pear" does not match "'apple'"
23972395
23982396
You can also use this in a with statement.
2397+
23992398
>>> with assert_raises_regex(TypeError, 'unsupported operand type\(s\)'):
24002399
... 1 + {}
24012400
>>> with assert_raises_regex(TypeError, 'banana'):

setup.cfg

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,5 +38,5 @@ markers =
3838
slow: mark a test as slow
3939
network: mark a test as network
4040
high_memory: mark a test as a high-memory only
41+
doctest_optionflags = NORMALIZE_WHITESPACE IGNORE_EXCEPTION_DETAIL
4142
addopts = --strict-data-files
42-
doctest_optionflags= NORMALIZE_WHITESPACE IGNORE_EXCEPTION_DETAIL

0 commit comments

Comments
 (0)