Skip to content

Commit 08315f6

Browse files
committed
DOC: Don't show traceback for :okexcept:
- use local modified ipython_directive to add optional no_traceback argument to :ok_except: which prevents the (sometimes long) traceback from being printed (default is no argument, i.e. the traceback is printed) and enable the @okexcept pseudodecorator so that it can be applied to individual instructions instead of the whole block - use local modified ipython_console_highlighting to enable syntax highlighting of exceptions without a traceback - fix pylint warnings for ipython_directive.py and simplify "".join(["."] * x) to "." * x The "# noqa: E999" after "@okexcept no_traceback" is necessary to prevent flake8-rst from complaining about syntax errors as it interprets the pseudodecorator as a real python decorator. Items 1 and 2 can be reverted if github.com/ipython/ipython/pull/13751 gets merged upstream.
1 parent 3c72d6f commit 08315f6

File tree

8 files changed

+1455
-40
lines changed

8 files changed

+1455
-40
lines changed

doc/source/conf.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,8 @@
5151

5252
extensions = [
5353
"contributors", # custom pandas extension
54-
"IPython.sphinxext.ipython_directive",
55-
"IPython.sphinxext.ipython_console_highlighting",
54+
"ipython_sphinxext.ipython_directive",
55+
"ipython_sphinxext.ipython_console_highlighting",
5656
"matplotlib.sphinxext.plot_directive",
5757
"numpydoc",
5858
"sphinx_copybutton",

doc/source/user_guide/categorical.rst

+19-37
Original file line numberDiff line numberDiff line change
@@ -356,20 +356,16 @@ Renaming categories is done by using the
356356
Categories must be unique or a ``ValueError`` is raised:
357357

358358
.. ipython:: python
359+
:okexcept: no_traceback
359360
360-
try:
361-
s = s.cat.rename_categories([1, 1, 1])
362-
except ValueError as e:
363-
print("ValueError:", str(e))
361+
s = s.cat.rename_categories([1, 1, 1])
364362
365363
Categories must also not be ``NaN`` or a ``ValueError`` is raised:
366364

367365
.. ipython:: python
366+
:okexcept: no_traceback
368367
369-
try:
370-
s = s.cat.rename_categories([1, 2, np.nan])
371-
except ValueError as e:
372-
print("ValueError:", str(e))
368+
s = s.cat.rename_categories([1, 2, np.nan])
373369
374370
Appending new categories
375371
~~~~~~~~~~~~~~~~~~~~~~~~
@@ -572,11 +568,9 @@ Equality comparisons work with any list-like object of same length and scalars:
572568
This doesn't work because the categories are not the same:
573569

574570
.. ipython:: python
571+
:okexcept: no_traceback
575572
576-
try:
577-
cat > cat_base2
578-
except TypeError as e:
579-
print("TypeError:", str(e))
573+
cat > cat_base2
580574
581575
If you want to do a "non-equality" comparison of a categorical series with a list-like object
582576
which is not categorical data, you need to be explicit and convert the categorical data back to
@@ -586,10 +580,8 @@ the original values:
586580
587581
base = np.array([1, 2, 3])
588582
589-
try:
590-
cat > base
591-
except TypeError as e:
592-
print("TypeError:", str(e))
583+
@okexcept no_traceback # noqa: E999
584+
cat > base
593585
594586
np.asarray(cat) > base
595587
@@ -768,21 +760,17 @@ value is included in the ``categories``:
768760
769761
df.iloc[2:4, :] = [["b", 2], ["b", 2]]
770762
df
771-
try:
772-
df.iloc[2:4, :] = [["c", 3], ["c", 3]]
773-
except TypeError as e:
774-
print("TypeError:", str(e))
763+
@okexcept no_traceback # noqa: E999
764+
df.iloc[2:4, :] = [["c", 3], ["c", 3]]
775765
776766
Setting values by assigning categorical data will also check that the ``categories`` match:
777767

778768
.. ipython:: python
779769
780770
df.loc["j":"k", "cats"] = pd.Categorical(["a", "a"], categories=["a", "b"])
781771
df
782-
try:
783-
df.loc["j":"k", "cats"] = pd.Categorical(["b", "b"], categories=["a", "b", "c"])
784-
except TypeError as e:
785-
print("TypeError:", str(e))
772+
@okexcept no_traceback # noqa: E999
773+
df.loc["j":"k", "cats"] = pd.Categorical(["b", "b"], categories=["a", "b", "c"])
786774
787775
Assigning a ``Categorical`` to parts of a column of other types will use the values:
788776

@@ -1067,16 +1055,12 @@ NumPy itself doesn't know about the new ``dtype``:
10671055

10681056
.. ipython:: python
10691057
1070-
try:
1071-
np.dtype("category")
1072-
except TypeError as e:
1073-
print("TypeError:", str(e))
1058+
@okexcept no_traceback # noqa: E999
1059+
np.dtype("category")
10741060
10751061
dtype = pd.Categorical(["a"]).dtype
1076-
try:
1077-
np.dtype(dtype)
1078-
except TypeError as e:
1079-
print("TypeError:", str(e))
1062+
@okexcept no_traceback # noqa: E999
1063+
np.dtype(dtype)
10801064
10811065
Dtype comparisons work:
10821066

@@ -1098,11 +1082,9 @@ are not numeric data (even in the case that ``.categories`` is numeric).
10981082
.. ipython:: python
10991083
11001084
s = pd.Series(pd.Categorical([1, 2, 3, 4]))
1101-
try:
1102-
np.sum(s)
1103-
# same with np.log(s),...
1104-
except TypeError as e:
1105-
print("TypeError:", str(e))
1085+
@okexcept no_traceback # noqa: E999
1086+
np.sum(s)
1087+
# same with np.log(s),...
11061088
11071089
.. note::
11081090
If such a function works, please file a bug at https://github.com/pandas-dev/pandas!

doc/sphinxext/ipython_sphinxext/__init__.py

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
"""
2+
reST directive for syntax-highlighting ipython interactive sessions.
3+
4+
"""
5+
6+
from IPython.lib.lexers import IPyLexer
7+
from sphinx import highlighting
8+
9+
10+
def patch_IPythonConsoleLexer():
11+
"""Patch lexers.IPythonConsoleLexer.ipytb_start.
12+
13+
This extension uses IPyLexer to highlight the exception. An exception is
14+
recognized by the traceback. The start of a traceback is found using the
15+
ipytb_start regex. This regex has to be patched to also find exceptions
16+
without a preceding traceback.
17+
"""
18+
import builtins
19+
import re
20+
21+
import IPython.lib.lexers as lexers
22+
23+
exceptions = [
24+
name
25+
for name, value in builtins.__dict__.items()
26+
if isinstance(value, type)
27+
and issubclass(value, Exception)
28+
and not issubclass(value, Warning)
29+
]
30+
lexers.IPythonConsoleLexer.ipytb_start = re.compile(
31+
r"^(\^C)?(-+\n)|^( File)(.*)(, line )(\d+\n)|^("
32+
+ "|".join(exceptions)
33+
+ r"): \S.*\n"
34+
)
35+
36+
37+
patch_IPythonConsoleLexer()
38+
39+
40+
def setup(app):
41+
"""Setup as a sphinx extension."""
42+
43+
# This is only a lexer, so adding it below to pygments appears sufficient.
44+
# But if somebody knows what the right API usage should be to do that via
45+
# sphinx, by all means fix it here. At least having this setup.py
46+
# suppresses the sphinx warning we'd get without it.
47+
metadata = {"parallel_read_safe": True, "parallel_write_safe": True}
48+
return metadata
49+
50+
51+
# Register the extension as a valid pygments lexer.
52+
# Alternatively, we could register the lexer with pygments instead. This would
53+
# require using setuptools entrypoints: http://pygments.org/docs/plugins
54+
55+
ipy2 = IPyLexer(python3=False)
56+
ipy3 = IPyLexer(python3=True)
57+
58+
highlighting.lexers["ipython"] = ipy2
59+
highlighting.lexers["ipython2"] = ipy2
60+
highlighting.lexers["ipython3"] = ipy3

0 commit comments

Comments
 (0)