From ff52cbb334f8b9c58b215efdc44752246ecc33ad Mon Sep 17 00:00:00 2001 From: Phillip Cloud Date: Wed, 31 Jul 2013 11:35:11 -0400 Subject: [PATCH] FIX: revert docs and fix for py3 compat --- ci/script.sh | 2 +- doc/plots/stats/moment_plots.py | 1 - doc/source/10min.rst | 5 +- doc/source/basics.rst | 9 +- doc/source/conf.py | 9 +- doc/source/cookbook.rst | 14 +- doc/source/enhancingperf.rst | 8 +- doc/source/faq.rst | 7 +- doc/source/gotchas.rst | 7 +- doc/source/groupby.rst | 6 +- doc/source/indexing.rst | 13 +- doc/source/install.rst | 10 +- doc/source/io.rst | 16 +- doc/source/merging.rst | 2 +- doc/source/missing_data.rst | 9 +- doc/source/remote_data.rst | 4 +- doc/source/reshaping.rst | 3 +- doc/source/rplot.rst | 2 +- doc/source/v0.11.0.txt | 7 +- doc/source/v0.12.0.txt | 7 +- doc/source/v0.8.0.txt | 2 +- doc/source/visualization.rst | 3 +- doc/sphinxext/__init__.py | 2 +- doc/sphinxext/comment_eater.py | 21 +- doc/sphinxext/compiler_unparse.py | 204 ++++++++-------- doc/sphinxext/docscrape.py | 107 +++++---- doc/sphinxext/docscrape_sphinx.py | 35 ++- doc/sphinxext/ipython_console_highlighting.py | 2 + doc/sphinxext/ipython_directive.py | 227 +++++++++--------- doc/sphinxext/numpydoc.py | 62 +++-- doc/sphinxext/only_directives.py | 7 + doc/sphinxext/phantom_import.py | 55 +++-- doc/sphinxext/plot_directive.py | 58 +++-- doc/sphinxext/setup.py | 3 +- doc/sphinxext/tests/test_docscrape.py | 54 +++-- doc/sphinxext/traitsdoc.py | 28 ++- 36 files changed, 581 insertions(+), 430 deletions(-) diff --git a/ci/script.sh b/ci/script.sh index e8c3cf66bd9ba..2e466e58bf377 100755 --- a/ci/script.sh +++ b/ci/script.sh @@ -2,7 +2,7 @@ echo "inside $0" -if [ x"$LOCALE_OVERRIDE" != x"" ]; then +if [ -n "$LOCALE_OVERRIDE" ]; then export LC_ALL="$LOCALE_OVERRIDE"; echo "Setting LC_ALL to $LOCALE_OVERRIDE" (cd /; python -c 'import pandas; print("pandas detected console encoding: %s" % pandas.get_option("display.encoding"))') diff --git a/doc/plots/stats/moment_plots.py b/doc/plots/stats/moment_plots.py index 86ec1d10de520..9e3a902592c6b 100644 --- a/doc/plots/stats/moment_plots.py +++ b/doc/plots/stats/moment_plots.py @@ -1,4 +1,3 @@ -from pandas.compat import range import numpy as np import matplotlib.pyplot as plt diff --git a/doc/source/10min.rst b/doc/source/10min.rst index e3cfcc765d7c3..d1c19d3345ffc 100644 --- a/doc/source/10min.rst +++ b/doc/source/10min.rst @@ -15,6 +15,7 @@ randint = np.random.randint np.set_printoptions(precision=4, suppress=True) options.display.mpl_style='default' + from pandas.compat import lrange, lzip #### portions of this were borrowed from the #### Pandas cheatsheet @@ -64,7 +65,7 @@ Creating a ``DataFrame`` by passing a dict of objects that can be converted to s df2 = pd.DataFrame({ 'A' : 1., 'B' : pd.Timestamp('20130102'), - 'C' : pd.Series(1,index=range(4),dtype='float32'), + 'C' : pd.Series(1,index=lrange(4),dtype='float32'), 'D' : np.array([3] * 4,dtype='int32'), 'E' : 'foo' }) df2 @@ -510,7 +511,7 @@ Stack .. ipython:: python - tuples = zip(*[['bar', 'bar', 'baz', 'baz', + tuples = lzip(*[['bar', 'bar', 'baz', 'baz', 'foo', 'foo', 'qux', 'qux'], ['one', 'two', 'one', 'two', 'one', 'two', 'one', 'two']]) diff --git a/doc/source/basics.rst b/doc/source/basics.rst index 677284572ca6f..479dd23b819da 100644 --- a/doc/source/basics.rst +++ b/doc/source/basics.rst @@ -8,6 +8,7 @@ from pandas import * randn = np.random.randn np.set_printoptions(precision=4, suppress=True) + from pandas.compat import lrange ============================== Essential Basic Functionality @@ -1090,16 +1091,16 @@ By default integer types are ``int64`` and float types are ``float64``, .. ipython:: python - DataFrame([1,2],columns=['a']).dtypes - DataFrame({'a' : [1,2] }).dtypes - DataFrame({'a' : 1 }, index=range(2)).dtypes + DataFrame([1, 2], columns=['a']).dtypes + DataFrame({'a': [1, 2]}).dtypes + DataFrame({'a': 1 }, index=lrange(2)).dtypes Numpy, however will choose *platform-dependent* types when creating arrays. The following **WILL** result in ``int32`` on 32-bit platform. .. ipython:: python - frame = DataFrame(np.array([1,2])) + frame = DataFrame(np.array([1, 2])) upcasting diff --git a/doc/source/conf.py b/doc/source/conf.py index 99da77dd5d570..99d1703b9ca34 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -12,7 +12,6 @@ import sys import os -from pandas.compat import u # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the @@ -64,8 +63,8 @@ master_doc = 'index' # General information about the project. -project = u('pandas') -copyright = u('2008-2012, the pandas development team') +project = u'pandas' +copyright = u'2008-2012, the pandas development team' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the @@ -212,8 +211,8 @@ # (source start file, target name, title, author, documentclass [howto/manual]). latex_documents = [ ('index', 'pandas.tex', - u('pandas: powerful Python data analysis toolkit'), - u('Wes McKinney\n\& PyData Development Team'), 'manual'), + u'pandas: powerful Python data analysis toolkit', + u'Wes McKinney\n\& PyData Development Team', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of diff --git a/doc/source/cookbook.rst b/doc/source/cookbook.rst index 17aed9ae5a422..1279ce1720a4f 100644 --- a/doc/source/cookbook.rst +++ b/doc/source/cookbook.rst @@ -56,8 +56,7 @@ Indexing using both row labels and conditionals, see `__ Use loc for label-oriented slicing and iloc positional slicing, see -`here -`__ +`here `__ Extend a panel frame by transposing, adding a new dimension, and transposing back to the original dimensions, see `here @@ -280,7 +279,7 @@ The :ref:`Plotting ` docs. `__ `Annotate a time-series plot #2 -`__ Data In/Out ----------- @@ -295,8 +294,7 @@ CSV The :ref:`CSV ` docs -`read_csv in action -`__ +`read_csv in action `__ `appending to a csv `__ @@ -317,7 +315,7 @@ using that handle to read. `__ `Dealing with bad lines -`__ +`__ `Dealing with bad lines II `__ @@ -359,7 +357,7 @@ The :ref:`HDFStores ` docs `__ `Managing heteregenous data using a linked multiple table hierarchy -`__ +`__ `Merging on-disk tables with millions of rows `__ @@ -420,7 +418,7 @@ Miscellaneous The :ref:`Timedeltas ` docs. `Operating with timedeltas -`__ +`__ `Create timedeltas with date differences `__ diff --git a/doc/source/enhancingperf.rst b/doc/source/enhancingperf.rst index db28dfde926bf..2fd606daa43b9 100644 --- a/doc/source/enhancingperf.rst +++ b/doc/source/enhancingperf.rst @@ -28,14 +28,14 @@ Cython (Writing C extensions for pandas) For many use cases writing pandas in pure python and numpy is sufficient. In some computationally heavy applications however, it can be possible to achieve sizeable -speed-ups by offloading work to `cython `_. +speed-ups by offloading work to `cython `__. This tutorial assumes you have refactored as much as possible in python, for example trying to remove for loops and making use of numpy vectorization, it's always worth optimising in python first. This tutorial walks through a "typical" process of cythonizing a slow computation. -We use an `example from the cython documentation `_ +We use an `example from the cython documentation `__ but in the context of pandas. Our final cythonized solution is around 100 times faster than the pure python. @@ -73,7 +73,7 @@ We achieve our result by by using ``apply`` (row-wise): But clearly this isn't fast enough for us. Let's take a look and see where the time is spent during this operation (limited to the most time consuming -four calls) using the `prun ipython magic function `_: +four calls) using the `prun ipython magic function `__: .. ipython:: python @@ -270,4 +270,4 @@ Further topics - Loading C modules into cython. -Read more in the `cython docs `_. \ No newline at end of file +Read more in the `cython docs `__. diff --git a/doc/source/faq.rst b/doc/source/faq.rst index 68387ba9f873c..77826eff03cbe 100644 --- a/doc/source/faq.rst +++ b/doc/source/faq.rst @@ -21,6 +21,7 @@ Frequently Asked Questions (FAQ) import matplotlib.pyplot as plt plt.close('all') options.display.mpl_style='default' + from pandas.compat import lrange .. _ref-repr-control: @@ -65,7 +66,7 @@ operations implemented, most of them are very fast as well. It's very possible however that certain functionality that would make your life easier is missing. In that case you have several options: -1) Open an issue on `Github `_ , explain your need and the sort of functionality you would like to see implemented. +1) Open an issue on `Github `__ , explain your need and the sort of functionality you would like to see implemented. 2) Fork the repo, Implement the functionality yourself and open a PR on Github. 3) Write a method that performs the operation you are interested in and @@ -85,7 +86,7 @@ life easier is missing. In that case you have several options: return [x for x in self.columns if 'foo' in x] pd.DataFrame.just_foo_cols = just_foo_cols # monkey-patch the DataFrame class - df = pd.DataFrame([range(4)],columns= ["A","foo","foozball","bar"]) + df = pd.DataFrame([lrange(4)],columns= ["A","foo","foozball","bar"]) df.just_foo_cols() del pd.DataFrame.just_foo_cols # you can also remove the new method @@ -258,7 +259,7 @@ using something similar to the following: .. ipython:: python - x = np.array(range(10), '>i4') # big endian + x = np.array(lrange(10), '>i4') # big endian newx = x.byteswap().newbyteorder() # force native byteorder s = Series(newx) diff --git a/doc/source/gotchas.rst b/doc/source/gotchas.rst index 0b736d8ddbe11..a4db5eb497ce3 100644 --- a/doc/source/gotchas.rst +++ b/doc/source/gotchas.rst @@ -9,6 +9,7 @@ from pandas import * randn = np.random.randn np.set_printoptions(precision=4, suppress=True) + from pandas.compat import lrange ******************* Caveats and Gotchas @@ -437,8 +438,8 @@ parse HTML tables in the top-level pandas io function ``read_html``. # install the latest version of beautifulsoup4 pip install 'bzr+lp:beautifulsoup' - Note that you need `bzr `_ and `git - `_ installed to perform the last two operations. + Note that you need `bzr `__ and `git + `__ installed to perform the last two operations. .. |svm| replace:: **strictly valid markup** .. _svm: http://validator.w3.org/docs/help.html#validation_basics @@ -466,7 +467,7 @@ using something similar to the following: .. ipython:: python - x = np.array(range(10), '>i4') # big endian + x = np.array(lrange(10), '>i4') # big endian newx = x.byteswap().newbyteorder() # force native byteorder s = Series(newx) diff --git a/doc/source/groupby.rst b/doc/source/groupby.rst index 90722bcf4b68b..c87f21511473f 100644 --- a/doc/source/groupby.rst +++ b/doc/source/groupby.rst @@ -12,6 +12,7 @@ import matplotlib.pyplot as plt plt.close('all') options.display.mpl_style='default' + from pandas.compat import lzip ***************************** Group By: split-apply-combine @@ -198,9 +199,10 @@ natural to group by one of the levels of the hierarchy. .. ipython:: python :suppress: + arrays = [['bar', 'bar', 'baz', 'baz', 'foo', 'foo', 'qux', 'qux'], ['one', 'two', 'one', 'two', 'one', 'two', 'one', 'two']] - tuples = zip(*arrays) + tuples = lzip(*arrays) tuples index = MultiIndex.from_tuples(tuples, names=['first', 'second']) s = Series(randn(8), index=index) @@ -234,7 +236,7 @@ Also as of v0.6, grouping with multiple levels is supported. arrays = [['bar', 'bar', 'baz', 'baz', 'foo', 'foo', 'qux', 'qux'], ['doo', 'doo', 'bee', 'bee', 'bop', 'bop', 'bop', 'bop'], ['one', 'two', 'one', 'two', 'one', 'two', 'one', 'two']] - tuples = zip(*arrays) + tuples = lzip(*arrays) index = MultiIndex.from_tuples(tuples, names=['first', 'second', 'third']) s = Series(randn(8), index=index) diff --git a/doc/source/indexing.rst b/doc/source/indexing.rst index d2f16c798fdb3..b953a29e035f4 100644 --- a/doc/source/indexing.rst +++ b/doc/source/indexing.rst @@ -13,6 +13,7 @@ randn = np.random.randn randint = np.random.randint np.set_printoptions(precision=4, suppress=True) + from pandas.compat import lrange, lzip *************************** Indexing and Selecting Data @@ -293,7 +294,7 @@ The ``.iloc`` attribute is the primary access method. The following are valid in .. ipython:: python - s1 = Series(np.random.randn(5),index=range(0,10,2)) + s1 = Series(np.random.randn(5),index=lrange(0,10,2)) s1 s1.iloc[:3] s1.iloc[3] @@ -310,8 +311,8 @@ With a DataFrame .. ipython:: python df1 = DataFrame(np.random.randn(6,4), - index=range(0,12,2), - columns=range(0,8,2)) + index=lrange(0,12,2), + columns=lrange(0,8,2)) df1 Select via integer slicing @@ -786,7 +787,7 @@ numpy array. For instance, .. ipython:: python dflookup = DataFrame(np.random.rand(20,4), columns = ['A','B','C','D']) - dflookup.lookup(xrange(0,10,2), ['B','C','A','B','D']) + dflookup.lookup(lrange(0,10,2), ['B','C','A','B','D']) Setting values in mixed-type DataFrame ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -896,7 +897,7 @@ display: .. ipython:: python - index = Index(range(5), name='rows') + index = Index(lrange(5), name='rows') columns = Index(['A', 'B', 'C'], name='cols') df = DataFrame(np.random.randn(5, 3), index=index, columns=columns) df @@ -971,7 +972,7 @@ can think of ``MultiIndex`` an array of tuples where each tuple is unique. A arrays = [['bar', 'bar', 'baz', 'baz', 'foo', 'foo', 'qux', 'qux'], ['one', 'two', 'one', 'two', 'one', 'two', 'one', 'two']] - tuples = zip(*arrays) + tuples = lzip(*arrays) tuples index = MultiIndex.from_tuples(tuples, names=['first', 'second']) s = Series(randn(8), index=index) diff --git a/doc/source/install.rst b/doc/source/install.rst index a7feea4bbf6ac..4d9864b272c2a 100644 --- a/doc/source/install.rst +++ b/doc/source/install.rst @@ -47,11 +47,11 @@ ___________ Windows, all, stable, :ref:`all-platforms`, ``pip install pandas`` Mac, all, stable, :ref:`all-platforms`, ``pip install pandas`` - Linux, Debian, stable, `official Debian repository `_ , ``sudo apt-get install python-pandas`` - Linux, Debian & Ubuntu, unstable (latest packages), `NeuroDebian `_ , ``sudo apt-get install python-pandas`` - Linux, Ubuntu, stable, `official Ubuntu repository `_ , ``sudo apt-get install python-pandas`` - Linux, Ubuntu, unstable (daily builds), `PythonXY PPA `_; activate by: ``sudo add-apt-repository ppa:pythonxy/pythonxy-devel && sudo apt-get update``, ``sudo apt-get install python-pandas`` - Linux, OpenSuse & Fedora, stable, `OpenSuse Repository `_ , ``zypper in python-pandas`` + Linux, Debian, stable, `official Debian repository `__ , ``sudo apt-get install python-pandas`` + Linux, Debian & Ubuntu, unstable (latest packages), `NeuroDebian `__ , ``sudo apt-get install python-pandas`` + Linux, Ubuntu, stable, `official Ubuntu repository `__ , ``sudo apt-get install python-pandas`` + Linux, Ubuntu, unstable (daily builds), `PythonXY PPA `__; activate by: ``sudo add-apt-repository ppa:pythonxy/pythonxy-devel && sudo apt-get update``, ``sudo apt-get install python-pandas`` + Linux, OpenSuse & Fedora, stable, `OpenSuse Repository `__ , ``zypper in python-pandas`` diff --git a/doc/source/io.rst b/doc/source/io.rst index 2537d52df6dac..21c3866e73576 100644 --- a/doc/source/io.rst +++ b/doc/source/io.rst @@ -1061,7 +1061,7 @@ Writing to a file, with a date index and a date column dfj2 = dfj.copy() dfj2['date'] = Timestamp('20130101') - dfj2['ints'] = range(5) + dfj2['ints'] = lrange(5) dfj2['bools'] = True dfj2.index = date_range('20130101',periods=5) dfj2.to_json('test.json') @@ -1156,7 +1156,7 @@ I like my string indicies .. ipython:: python si = DataFrame(np.zeros((4, 4)), - columns=range(4), + columns=lrange(4), index=[str(i) for i in range(4)]) si si.index @@ -1649,7 +1649,7 @@ HDF5 (PyTables) ``HDFStore`` is a dict-like object which reads and writes pandas using the high performance HDF5 format using the excellent `PyTables -`__ library. See the :ref:`cookbook` +`__ library. See the :ref:`cookbook ` for some advanced strategies .. note:: @@ -1740,7 +1740,7 @@ similar to how ``read_csv`` and ``to_csv`` work. (new in 0.11.0) .. ipython:: python - df_tl = DataFrame(dict(A=range(5), B=range(5))) + df_tl = DataFrame(dict(A=lrange(5), B=lrange(5))) df_tl.to_hdf('store_tl.h5','table',append=True) read_hdf('store_tl.h5', 'table', where = ['index>2']) @@ -1862,7 +1862,7 @@ defaults to `nan`. 'int' : 1, 'bool' : True, 'datetime64' : Timestamp('20010102')}, - index=range(8)) + index=lrange(8)) df_mixed.ix[3:5,['A', 'B', 'string', 'datetime64']] = np.nan store.append('df_mixed', df_mixed, min_itemsize = {'values': 50}) @@ -2287,7 +2287,7 @@ Starting in 0.11, passing a ``min_itemsize`` dict will cause all passed columns .. ipython:: python - dfs = DataFrame(dict(A = 'foo', B = 'bar'),index=range(5)) + dfs = DataFrame(dict(A = 'foo', B = 'bar'),index=lrange(5)) dfs # A and B have a size of 30 @@ -2424,7 +2424,7 @@ SQL Queries The :mod:`pandas.io.sql` module provides a collection of query wrappers to both facilitate data retrieval and to reduce dependency on DB-specific API. These wrappers only support the Python database adapters which respect the `Python -DB-API `_. See some +DB-API `__. See some :ref:`cookbook examples ` for some advanced strategies For example, suppose you want to query some data with different types from a @@ -2443,7 +2443,7 @@ table such as: Functions from :mod:`pandas.io.sql` can extract some data into a DataFrame. In -the following example, we use the `SQlite `_ SQL database +the following example, we use the `SQlite `__ SQL database engine. You can use a temporary SQLite database where data are stored in "memory". Just do: diff --git a/doc/source/merging.rst b/doc/source/merging.rst index b719f0c24e3f9..bc3bec4de654d 100644 --- a/doc/source/merging.rst +++ b/doc/source/merging.rst @@ -119,7 +119,7 @@ behavior: from pandas.util.testing import rands df = DataFrame(np.random.randn(10, 4), columns=['a', 'b', 'c', 'd'], - index=[rands(5) for _ in xrange(10)]) + index=[rands(5) for _ in range(10)]) df concat([df.ix[:7, ['a', 'b']], df.ix[2:-2, ['c']], diff --git a/doc/source/missing_data.rst b/doc/source/missing_data.rst index 2d8ac5d953a21..65d43a87a709b 100644 --- a/doc/source/missing_data.rst +++ b/doc/source/missing_data.rst @@ -14,6 +14,7 @@ pandas. import numpy as np; randn = np.random.randn; randint =np.random.randint from pandas import * import matplotlib.pyplot as plt + from pandas.compat import lrange .. note:: @@ -348,7 +349,7 @@ String/Regular Expression Replacement backslashes than strings without this prefix. Backslashes in raw strings will be interpreted as an escaped backslash, e.g., ``r'\' == '\\'``. You should `read about them - `_ + `__ if this is unclear. Replace the '.' with ``nan`` (str -> str) @@ -362,7 +363,7 @@ Replace the '.' with ``nan`` (str -> str) .. ipython:: python - d = {'a': range(4), 'b': list('ab..'), 'c': ['a', 'b', nan, 'd']} + d = {'a': lrange(4), 'b': list('ab..'), 'c': ['a', 'b', nan, 'd']} df = DataFrame(d) df.replace('.', nan) @@ -499,7 +500,7 @@ For example: s = Series(randn(5), index=[0, 2, 4, 6, 7]) s > 0 (s > 0).dtype - crit = (s > 0).reindex(range(8)) + crit = (s > 0).reindex(lrange(8)) crit crit.dtype @@ -511,7 +512,7 @@ contains NAs, an exception will be generated: .. ipython:: python :okexcept: - reindexed = s.reindex(range(8)).fillna(0) + reindexed = s.reindex(lrange(8)).fillna(0) reindexed[crit] However, these can be filled in using **fillna** and it will work fine: diff --git a/doc/source/remote_data.rst b/doc/source/remote_data.rst index be954e1bf653c..bda532317ffe8 100644 --- a/doc/source/remote_data.rst +++ b/doc/source/remote_data.rst @@ -87,7 +87,7 @@ Fama/French ----------- Tthe dataset names are listed at `Fama/French Data Library -`_) +`__) .. ipython:: python @@ -101,7 +101,7 @@ World Bank ---------- ``Pandas`` users can easily access thousands of panel data series from the -`World Bank's World Development Indicators `_ +`World Bank's World Development Indicators `__ by using the ``wb`` I/O functions. For example, if you wanted to compare the Gross Domestic Products per capita in diff --git a/doc/source/reshaping.rst b/doc/source/reshaping.rst index 5f7526235a4c3..dcc8889c24133 100644 --- a/doc/source/reshaping.rst +++ b/doc/source/reshaping.rst @@ -12,6 +12,7 @@ randn = np.random.randn np.set_printoptions(precision=4, suppress=True) from pandas.tools.tile import * + from pandas.compat import lzip ************************** Reshaping and Pivot Tables @@ -116,7 +117,7 @@ from the hierarchical indexing section: .. ipython:: python - tuples = zip(*[['bar', 'bar', 'baz', 'baz', + tuples = lzip(*[['bar', 'bar', 'baz', 'baz', 'foo', 'foo', 'qux', 'qux'], ['one', 'two', 'one', 'two', 'one', 'two', 'one', 'two']]) diff --git a/doc/source/rplot.rst b/doc/source/rplot.rst index f268bafc2aa07..8ede1a41f8dd8 100644 --- a/doc/source/rplot.rst +++ b/doc/source/rplot.rst @@ -25,7 +25,7 @@ Trellis plotting interface .. note:: The tips data set can be downloaded `here - `_. Once you download it execute + `__. Once you download it execute .. code-block:: python diff --git a/doc/source/v0.11.0.txt b/doc/source/v0.11.0.txt index 6b7fac0fc12dc..84d0806e457bf 100644 --- a/doc/source/v0.11.0.txt +++ b/doc/source/v0.11.0.txt @@ -233,9 +233,14 @@ Enhancements - support ``read_hdf/to_hdf`` API similar to ``read_csv/to_csv`` + .. ipython:: python + :suppress: + + from pandas.compat import lrange + .. ipython:: python - df = DataFrame(dict(A=range(5), B=range(5))) + df = DataFrame(dict(A=lrange(5), B=lrange(5))) df.to_hdf('store.h5','table',append=True) read_hdf('store.h5', 'table', where = ['index>2']) diff --git a/doc/source/v0.12.0.txt b/doc/source/v0.12.0.txt index 9054ef4a5444e..beb62df505a37 100644 --- a/doc/source/v0.12.0.txt +++ b/doc/source/v0.12.0.txt @@ -77,8 +77,13 @@ API changes ``iloc`` API to be *purely* positional based. .. ipython:: python + :suppress: - df = DataFrame(range(5), list('ABCDE'), columns=['a']) + from pandas.compat import lrange + + .. ipython:: python + + df = DataFrame(lrange(5), list('ABCDE'), columns=['a']) mask = (df.a%2 == 0) mask diff --git a/doc/source/v0.8.0.txt b/doc/source/v0.8.0.txt index 3b11582ac2a04..a76c4e487d5d8 100644 --- a/doc/source/v0.8.0.txt +++ b/doc/source/v0.8.0.txt @@ -157,7 +157,7 @@ New plotting methods :suppress: import pandas as pd - fx = pd.load('data/fx_prices') + fx = pd.read_pickle('data/fx_prices') import matplotlib.pyplot as plt ``Series.plot`` now supports a ``secondary_y`` option: diff --git a/doc/source/visualization.rst b/doc/source/visualization.rst index a3a02e1a978af..972a828ca3e95 100644 --- a/doc/source/visualization.rst +++ b/doc/source/visualization.rst @@ -13,6 +13,7 @@ import matplotlib.pyplot as plt plt.close('all') options.display.mpl_style = 'default' + from pandas.compat import lrange ************************ Plotting with matplotlib @@ -101,7 +102,7 @@ You can plot one column versus another using the `x` and `y` keywords in plt.figure() df3 = DataFrame(randn(1000, 2), columns=['B', 'C']).cumsum() - df3['A'] = Series(range(len(df))) + df3['A'] = Series(lrange(len(df))) @savefig df_plot_xy.png df3.plot(x='A', y='B') diff --git a/doc/sphinxext/__init__.py b/doc/sphinxext/__init__.py index 68dbbb00a7cfb..ae9073bc4115f 100755 --- a/doc/sphinxext/__init__.py +++ b/doc/sphinxext/__init__.py @@ -1 +1 @@ -from .numpydoc import setup +from numpydoc import setup diff --git a/doc/sphinxext/comment_eater.py b/doc/sphinxext/comment_eater.py index 1c6d46c5aed6c..af1e21d7bb4ee 100755 --- a/doc/sphinxext/comment_eater.py +++ b/doc/sphinxext/comment_eater.py @@ -1,22 +1,25 @@ -from pandas.compat import cStringIO +from cStringIO import StringIO import compiler import inspect import textwrap import tokenize -from .compiler_unparse import unparse +from compiler_unparse import unparse class Comment(object): + """ A comment block. """ is_comment = True + def __init__(self, start_lineno, end_lineno, text): # int : The first line number in the block. 1-indexed. self.start_lineno = start_lineno # int : The last line number. Inclusive! self.end_lineno = end_lineno - # str : The text block including '#' character but not any leading spaces. + # str : The text block including '#' character but not any leading + # spaces. self.text = text def add(self, string, start, end, line): @@ -28,13 +31,15 @@ def add(self, string, start, end, line): def __repr__(self): return '%s(%r, %r, %r)' % (self.__class__.__name__, self.start_lineno, - self.end_lineno, self.text) + self.end_lineno, self.text) class NonComment(object): + """ A non-comment block of code. """ is_comment = False + def __init__(self, start_lineno, end_lineno): self.start_lineno = start_lineno self.end_lineno = end_lineno @@ -49,12 +54,14 @@ def add(self, string, start, end, line): def __repr__(self): return '%s(%r, %r)' % (self.__class__.__name__, self.start_lineno, - self.end_lineno) + self.end_lineno) class CommentBlocker(object): + """ Pull out contiguous comment blocks. """ + def __init__(self): # Start with a dummy. self.current_block = NonComment(0, 0) @@ -153,6 +160,6 @@ def get_class_traits(klass): if isinstance(node, compiler.ast.Assign): name = node.nodes[0].name rhs = unparse(node.expr).strip() - doc = strip_comment_marker(cb.search_for_comment(node.lineno, default='')) + doc = strip_comment_marker( + cb.search_for_comment(node.lineno, default='')) yield name, rhs, doc - diff --git a/doc/sphinxext/compiler_unparse.py b/doc/sphinxext/compiler_unparse.py index 46b7257c455f7..8233e968071ec 100755 --- a/doc/sphinxext/compiler_unparse.py +++ b/doc/sphinxext/compiler_unparse.py @@ -12,28 +12,32 @@ """ import sys -from pandas.compat import cStringIO as StringIO +import cStringIO from compiler.ast import Const, Name, Tuple, Div, Mul, Sub, Add + def unparse(ast, single_line_functions=False): - s = StringIO() + s = cStringIO.StringIO() UnparseCompilerAst(ast, s, single_line_functions) return s.getvalue().lstrip() -op_precedence = { 'compiler.ast.Power':3, 'compiler.ast.Mul':2, 'compiler.ast.Div':2, - 'compiler.ast.Add':1, 'compiler.ast.Sub':1 } +op_precedence = { + 'compiler.ast.Power': 3, 'compiler.ast.Mul': 2, 'compiler.ast.Div': 2, + 'compiler.ast.Add': 1, 'compiler.ast.Sub': 1} + class UnparseCompilerAst: + """ Methods in this class recursively traverse an AST and output source code for the abstract syntax; original formatting is disregarged. """ - ######################################################################### + # # object interface. - ######################################################################### + # - def __init__(self, tree, file = sys.stdout, single_line_functions=False): + def __init__(self, tree, file=sys.stdout, single_line_functions=False): """ Unparser(tree, file=sys.stdout) -> None. Print the source for tree to file. @@ -46,16 +50,16 @@ def __init__(self, tree, file = sys.stdout, single_line_functions=False): self._write("\n") self.f.flush() - ######################################################################### + # # Unparser private interface. - ######################################################################### + # - ### format, output, and dispatch methods ################################ + # format, output, and dispatch methods ################################ - def _fill(self, text = ""): + def _fill(self, text=""): "Indent a piece of text, according to the current indentation level" if self._do_indent: - self._write("\n"+" "*self._indent + text) + self._write("\n" + " " * self._indent + text) else: self._write(text) @@ -78,19 +82,17 @@ def _dispatch(self, tree): for t in tree: self._dispatch(t) return - meth = getattr(self, "_"+tree.__class__.__name__) + meth = getattr(self, "_" + tree.__class__.__name__) if tree.__class__.__name__ == 'NoneType' and not self._do_indent: return meth(tree) - - ######################################################################### + # # compiler.ast unparsing methods. # # There should be one method per concrete grammar type. They are # organized in alphabetical order. - ######################################################################### - + # def _Add(self, t): self.__binary_op(t, '+') @@ -98,7 +100,7 @@ def _And(self, t): self._write(" (") for i, node in enumerate(t.nodes): self._dispatch(node) - if i != len(t.nodes)-1: + if i != len(t.nodes) - 1: self._write(") and (") self._write(")") @@ -106,7 +108,7 @@ def _AssAttr(self, t): """ Handle assigning an attribute of an object """ self._dispatch(t.expr) - self._write('.'+t.attrname) + self._write('.' + t.attrname) def _Assign(self, t): """ Expression Assignment such as "a = 1". @@ -148,7 +150,7 @@ def _AugAssign(self, t): self._fill() self._dispatch(t.node) - self._write(' '+t.op+' ') + self._write(' ' + t.op + ' ') self._dispatch(t.expr) if not self._do_indent: self._write(';') @@ -161,7 +163,7 @@ def _Bitand(self, t): self._write("(") self._dispatch(node) self._write(")") - if i != len(t.nodes)-1: + if i != len(t.nodes) - 1: self._write(" & ") def _Bitor(self, t): @@ -172,7 +174,7 @@ def _Bitor(self, t): self._write("(") self._dispatch(node) self._write(")") - if i != len(t.nodes)-1: + if i != len(t.nodes) - 1: self._write(" | ") def _CallFunc(self, t): @@ -182,17 +184,23 @@ def _CallFunc(self, t): self._write("(") comma = False for e in t.args: - if comma: self._write(", ") - else: comma = True + if comma: + self._write(", ") + else: + comma = True self._dispatch(e) if t.star_args: - if comma: self._write(", ") - else: comma = True + if comma: + self._write(", ") + else: + comma = True self._write("*") self._dispatch(t.star_args) if t.dstar_args: - if comma: self._write(", ") - else: comma = True + if comma: + self._write(", ") + else: + comma = True self._write("**") self._dispatch(t.dstar_args) self._write(")") @@ -216,11 +224,11 @@ def _Decorators(self, t): def _Dict(self, t): self._write("{") - for i, (k, v) in enumerate(t.items): + for i, (k, v) in enumerate(t.items): self._dispatch(k) self._write(": ") self._dispatch(v) - if i < len(t.items)-1: + if i < len(t.items) - 1: self._write(", ") self._write("}") @@ -243,12 +251,12 @@ def _From(self, t): self._fill("from ") self._write(t.modname) self._write(" import ") - for i, (name,asname) in enumerate(t.names): + for i, (name, asname) in enumerate(t.names): if i != 0: self._write(", ") self._write(name) if asname is not None: - self._write(" as "+asname) + self._write(" as " + asname) def _Function(self, t): """ Handle function definitions @@ -256,14 +264,15 @@ def _Function(self, t): if t.decorators is not None: self._fill("@") self._dispatch(t.decorators) - self._fill("def "+t.name + "(") - defaults = [None] * (len(t.argnames) - len(t.defaults)) + list(t.defaults) + self._fill("def " + t.name + "(") + defaults = [None] * ( + len(t.argnames) - len(t.defaults)) + list(t.defaults) for i, arg in enumerate(zip(t.argnames, defaults)): self._write(arg[0]) if arg[1] is not None: self._write('=') self._dispatch(arg[1]) - if i < len(t.argnames)-1: + if i < len(t.argnames) - 1: self._write(', ') self._write(")") if self._single_func: @@ -283,12 +292,12 @@ def _Getattr(self, t): else: self._dispatch(t.expr) - self._write('.'+t.attrname) + self._write('.' + t.attrname) def _If(self, t): self._fill() - for i, (compare,code) in enumerate(t.tests): + for i, (compare, code) in enumerate(t.tests): if i == 0: self._write("if ") else: @@ -323,12 +332,12 @@ def _Import(self, t): """ self._fill("import ") - for i, (name,asname) in enumerate(t.names): + for i, (name, asname) in enumerate(t.names): if i != 0: self._write(", ") self._write(name) if asname is not None: - self._write(" as "+asname) + self._write(" as " + asname) def _Keyword(self, t): """ Keyword value assignment within function calls and definitions. @@ -339,9 +348,9 @@ def _Keyword(self, t): def _List(self, t): self._write("[") - for i,node in enumerate(t.nodes): + for i, node in enumerate(t.nodes): self._dispatch(node) - if i < len(t.nodes)-1: + if i < len(t.nodes) - 1: self._write(", ") self._write("]") @@ -368,7 +377,7 @@ def _Or(self, t): self._write(" (") for i, node in enumerate(t.nodes): self._dispatch(node) - if i != len(t.nodes)-1: + if i != len(t.nodes) - 1: self._write(") or (") self._write(")") @@ -383,8 +392,10 @@ def _Printnl(self, t): self._write(", ") comma = False for node in t.nodes: - if comma: self._write(', ') - else: comma = True + if comma: + self._write(', ') + else: + comma = True self._dispatch(node) def _Power(self, t): @@ -394,7 +405,7 @@ def _Return(self, t): self._fill("return ") if t.value: if isinstance(t.value, Tuple): - text = ', '.join([ name.name for name in t.value.asList() ]) + text = ', '.join([name.name for name in t.value.asList()]) self._write(text) else: self._dispatch(t.value) @@ -409,7 +420,7 @@ def _Slice(self, t): self._write(":") if t.upper: self._dispatch(t.upper) - #if t.step: + # if t.step: # self._write(":") # self._dispatch(t.step) self._write("]") @@ -505,7 +516,7 @@ def __binary_op(self, t, symbol): has_paren = False left_class = str(t.left.__class__) if (left_class in op_precedence.keys() and - op_precedence[left_class] < op_precedence[str(t.__class__)]): + op_precedence[left_class] < op_precedence[str(t.__class__)]): has_paren = True if has_paren: self._write('(') @@ -518,7 +529,7 @@ def __binary_op(self, t, symbol): has_paren = False right_class = str(t.right.__class__) if (right_class in op_precedence.keys() and - op_precedence[right_class] < op_precedence[str(t.__class__)]): + op_precedence[right_class] < op_precedence[str(t.__class__)]): has_paren = True if has_paren: self._write('(') @@ -537,14 +548,14 @@ def _str(self, t): def _tuple(self, t): self._write(str(t)) - ######################################################################### + # # These are the methods from the _ast modules unparse. # # As our needs to handle more advanced code increase, we may want to # modify some of the methods below so that they work for compiler.ast. - ######################################################################### + # -# # stmt +# stmt # def _Expr(self, tree): # self._fill() # self._dispatch(tree.value) @@ -561,18 +572,18 @@ def _tuple(self, t): # if a.asname: # self._write(" as "+a.asname) # -## def _ImportFrom(self, t): -## self._fill("from ") -## self._write(t.module) -## self._write(" import ") -## for i, a in enumerate(t.names): -## if i == 0: -## self._write(", ") -## self._write(a.name) -## if a.asname: -## self._write(" as "+a.asname) -## # XXX(jpe) what is level for? -## +# def _ImportFrom(self, t): +# self._fill("from ") +# self._write(t.module) +# self._write(" import ") +# for i, a in enumerate(t.names): +# if i == 0: +# self._write(", ") +# self._write(a.name) +# if a.asname: +# self._write(" as "+a.asname) +# XXX(jpe) what is level for? +# # # def _Break(self, t): # self._fill("break") @@ -714,10 +725,10 @@ def _tuple(self, t): # self._dispatch(t.orelse) # self._leave # -# # expr +# expr # def _Str(self, tree): # self._write(repr(tree.s)) -## +# # def _Repr(self, t): # self._write("`") # self._dispatch(t.value) @@ -788,31 +799,31 @@ def _tuple(self, t): # self._write(".") # self._write(t.attr) # -## def _Call(self, t): -## self._dispatch(t.func) -## self._write("(") -## comma = False -## for e in t.args: -## if comma: self._write(", ") -## else: comma = True -## self._dispatch(e) -## for e in t.keywords: -## if comma: self._write(", ") -## else: comma = True -## self._dispatch(e) -## if t.starargs: -## if comma: self._write(", ") -## else: comma = True -## self._write("*") -## self._dispatch(t.starargs) -## if t.kwargs: -## if comma: self._write(", ") -## else: comma = True -## self._write("**") -## self._dispatch(t.kwargs) -## self._write(")") -# -# # slice +# def _Call(self, t): +# self._dispatch(t.func) +# self._write("(") +# comma = False +# for e in t.args: +# if comma: self._write(", ") +# else: comma = True +# self._dispatch(e) +# for e in t.keywords: +# if comma: self._write(", ") +# else: comma = True +# self._dispatch(e) +# if t.starargs: +# if comma: self._write(", ") +# else: comma = True +# self._write("*") +# self._dispatch(t.starargs) +# if t.kwargs: +# if comma: self._write(", ") +# else: comma = True +# self._write("**") +# self._dispatch(t.kwargs) +# self._write(")") +# +# slice # def _Index(self, t): # self._dispatch(t.value) # @@ -822,7 +833,7 @@ def _tuple(self, t): # self._write(': ') # self._dispatch(d) # -# # others +# others # def _arguments(self, t): # first = True # nonDef = len(t.args)-len(t.defaults) @@ -845,16 +856,13 @@ def _tuple(self, t): # else: self._write(", ") # self._write("**"+t.kwarg) # -## def _keyword(self, t): -## self._write(t.arg) -## self._write("=") -## self._dispatch(t.value) +# def _keyword(self, t): +# self._write(t.arg) +# self._write("=") +# self._dispatch(t.value) # # def _Lambda(self, t): # self._write("lambda ") # self._dispatch(t.args) # self._write(": ") # self._dispatch(t.body) - - - diff --git a/doc/sphinxext/docscrape.py b/doc/sphinxext/docscrape.py index 3c2c303e85ccd..a6a42ac40042e 100755 --- a/doc/sphinxext/docscrape.py +++ b/doc/sphinxext/docscrape.py @@ -1,19 +1,21 @@ """Extract reference documentation from the NumPy source tree. """ -from __future__ import print_function import inspect import textwrap import re import pydoc +from StringIO import StringIO from warnings import warn -from pandas.compat import StringIO, callable + class Reader(object): + """A line-based string reader. """ + def __init__(self, data): """ Parameters @@ -22,10 +24,10 @@ def __init__(self, data): String with lines separated by '\n'. """ - if isinstance(data,list): + if isinstance(data, list): self._str = data else: - self._str = data.split('\n') # store string as list of lines + self._str = data.split('\n') # store string as list of lines self.reset() @@ -33,7 +35,7 @@ def __getitem__(self, n): return self._str[n] def reset(self): - self._l = 0 # current line nr + self._l = 0 # current line nr def read(self): if not self.eof(): @@ -60,11 +62,12 @@ def read_to_condition(self, condition_func): return self[start:self._l] self._l += 1 if self.eof(): - return self[start:self._l+1] + return self[start:self._l + 1] return [] def read_to_next_empty_line(self): self.seek_next_non_empty_line() + def is_empty(line): return not line.strip() return self.read_to_condition(is_empty) @@ -74,7 +77,7 @@ def is_unindented(line): return (line.strip() and (len(line.lstrip()) == len(line))) return self.read_to_condition(is_unindented) - def peek(self,n=0): + def peek(self, n=0): if self._l + n < len(self._str): return self[self._l + n] else: @@ -85,6 +88,7 @@ def is_empty(self): class NumpyDocString(object): + def __init__(self, docstring, config={}): docstring = textwrap.dedent(docstring).split('\n') @@ -106,15 +110,15 @@ def __init__(self, docstring, config={}): 'References': '', 'Examples': '', 'index': {} - } + } self._parse() - def __getitem__(self,key): + def __getitem__(self, key): return self._parsed_data[key] - def __setitem__(self,key,val): - if key not in self._parsed_data: + def __setitem__(self, key, val): + if not self._parsed_data.has_key(key): warn("Unknown section %s" % key) else: self._parsed_data[key] = val @@ -130,25 +134,27 @@ def _is_at_section(self): if l1.startswith('.. index::'): return True - l2 = self._doc.peek(1).strip() # ---------- or ========== - return l2.startswith('-'*len(l1)) or l2.startswith('='*len(l1)) + l2 = self._doc.peek(1).strip() # ---------- or ========== + return l2.startswith('-' * len(l1)) or l2.startswith('=' * len(l1)) - def _strip(self,doc): + def _strip(self, doc): i = 0 j = 0 - for i,line in enumerate(doc): - if line.strip(): break + for i, line in enumerate(doc): + if line.strip(): + break - for j,line in enumerate(doc[::-1]): - if line.strip(): break + for j, line in enumerate(doc[::-1]): + if line.strip(): + break - return doc[i:len(doc)-j] + return doc[i:len(doc) - j] def _read_to_next_section(self): section = self._doc.read_to_next_empty_line() while not self._is_at_section() and not self._doc.eof(): - if not self._doc.peek(-1).strip(): # previous line was empty + if not self._doc.peek(-1).strip(): # previous line was empty section += [''] section += self._doc.read_to_next_empty_line() @@ -160,14 +166,14 @@ def _read_sections(self): data = self._read_to_next_section() name = data[0].strip() - if name.startswith('..'): # index section + if name.startswith('..'): # index section yield name, data[1:] elif len(data) < 2: yield StopIteration else: yield name, self._strip(data[2:]) - def _parse_param_list(self,content): + def _parse_param_list(self, content): r = Reader(content) params = [] while not r.eof(): @@ -180,13 +186,13 @@ def _parse_param_list(self,content): desc = r.read_to_next_unindented_line() desc = dedent_lines(desc) - params.append((arg_name,arg_type,desc)) + params.append((arg_name, arg_type, desc)) return params - _name_rgx = re.compile(r"^\s*(:(?P\w+):`(?P[a-zA-Z0-9_.-]+)`|" r" (?P[a-zA-Z0-9_.-]+))\s*", re.X) + def _parse_see_also(self, content): """ func_name : Descriptive text @@ -219,7 +225,8 @@ def push_item(name, rest): rest = [] for line in content: - if not line.strip(): continue + if not line.strip(): + continue m = self._name_rgx.match(line) if m and line[m.end():].strip().startswith(':'): @@ -282,9 +289,10 @@ def _parse(self): self._doc.reset() self._parse_summary() - for (section,content) in self._read_sections(): + for (section, content) in self._read_sections(): if not section.startswith('..'): - section = ' '.join([s.capitalize() for s in section.split(' ')]) + section = ' '.join([s.capitalize() + for s in section.split(' ')]) if section in ('Parameters', 'Attributes', 'Methods', 'Returns', 'Raises', 'Warns'): self[section] = self._parse_param_list(content) @@ -298,17 +306,17 @@ def _parse(self): # string conversion routines def _str_header(self, name, symbol='-'): - return [name, len(name)*symbol] + return [name, len(name) * symbol] def _str_indent(self, doc, indent=4): out = [] for line in doc: - out += [' '*indent + line] + out += [' ' * indent + line] return out def _str_signature(self): if self['Signature']: - return [self['Signature'].replace('*','\*')] + [''] + return [self['Signature'].replace('*', '\*')] + [''] else: return [''] @@ -328,7 +336,7 @@ def _str_param_list(self, name): out = [] if self[name]: out += self._str_header(name) - for param,param_type,desc in self[name]: + for param, param_type, desc in self[name]: out += ['%s : %s' % (param, param_type)] out += self._str_indent(desc) out += [''] @@ -343,7 +351,8 @@ def _str_section(self, name): return out def _str_see_also(self, func_role): - if not self['See Also']: return [] + if not self['See Also']: + return [] out = [] out += self._str_header("See Also") last_had_desc = True @@ -370,8 +379,8 @@ def _str_see_also(self, func_role): def _str_index(self): idx = self['index'] out = [] - out += ['.. index:: %s' % idx.get('default','')] - for section, references in compat.iteritems(idx): + out += ['.. index:: %s' % idx.get('default', '')] + for section, references in idx.iteritems(): if section == 'default': continue out += [' :%s: %s' % (section, ', '.join(references))] @@ -382,11 +391,11 @@ def __str__(self, func_role=''): out += self._str_signature() out += self._str_summary() out += self._str_extended_summary() - for param_list in ('Parameters','Returns','Raises'): + for param_list in ('Parameters', 'Returns', 'Raises'): out += self._str_param_list(param_list) out += self._str_section('Warnings') out += self._str_see_also(func_role) - for s in ('Notes','References','Examples'): + for s in ('Notes', 'References', 'Examples'): out += self._str_section(s) for param_list in ('Attributes', 'Methods'): out += self._str_param_list(param_list) @@ -394,25 +403,28 @@ def __str__(self, func_role=''): return '\n'.join(out) -def indent(str,indent=4): - indent_str = ' '*indent +def indent(str, indent=4): + indent_str = ' ' * indent if str is None: return indent_str lines = str.split('\n') return '\n'.join(indent_str + l for l in lines) + def dedent_lines(lines): """Deindent a list of lines maximally""" return textwrap.dedent("\n".join(lines)).split("\n") + def header(text, style='-'): - return text + '\n' + style*len(text) + '\n' + return text + '\n' + style * len(text) + '\n' class FunctionDoc(NumpyDocString): + def __init__(self, func, role='func', doc=None, config={}): self._f = func - self._role = role # e.g. "func" or "meth" + self._role = role # e.g. "func" or "meth" if doc is None: if func is None: @@ -426,9 +438,9 @@ def __init__(self, func, role='func', doc=None, config={}): # try to read signature argspec = inspect.getargspec(func) argspec = inspect.formatargspec(*argspec) - argspec = argspec.replace('*','\*') + argspec = argspec.replace('*', '\*') signature = '%s%s' % (func_name, argspec) - except TypeError as e: + except TypeError, e: signature = '%s()' % func_name self['Signature'] = signature @@ -450,9 +462,9 @@ def __str__(self): 'meth': 'method'} if self._role: - if self._role not in roles: - print("Warning: invalid role %s" % self._role) - out += '.. %s:: %s\n \n\n' % (roles.get(self._role,''), + if not roles.has_key(self._role): + print "Warning: invalid role %s" % self._role + out += '.. %s:: %s\n \n\n' % (roles.get(self._role, ''), func_name) out += super(FunctionDoc, self).__str__(func_role=self._role) @@ -460,6 +472,7 @@ def __str__(self): class ClassDoc(NumpyDocString): + def __init__(self, cls, doc=None, modulename='', func_doc=FunctionDoc, config={}): if not inspect.isclass(cls) and cls is not None: @@ -489,12 +502,12 @@ def __init__(self, cls, doc=None, modulename='', func_doc=FunctionDoc, def methods(self): if self._cls is None: return [] - return [name for name,func in inspect.getmembers(self._cls) + return [name for name, func in inspect.getmembers(self._cls) if not name.startswith('_') and callable(func)] @property def properties(self): if self._cls is None: return [] - return [name for name,func in inspect.getmembers(self._cls) + return [name for name, func in inspect.getmembers(self._cls) if not name.startswith('_') and func is None] diff --git a/doc/sphinxext/docscrape_sphinx.py b/doc/sphinxext/docscrape_sphinx.py index 650a2d8f33dd0..cf3873c3a5f0c 100755 --- a/doc/sphinxext/docscrape_sphinx.py +++ b/doc/sphinxext/docscrape_sphinx.py @@ -1,9 +1,13 @@ -import re, inspect, textwrap, pydoc +import re +import inspect +import textwrap +import pydoc import sphinx -from .docscrape import NumpyDocString, FunctionDoc, ClassDoc -from pandas.compat import callable +from docscrape import NumpyDocString, FunctionDoc, ClassDoc + class SphinxDocString(NumpyDocString): + def __init__(self, docstring, config={}): self.use_plots = config.get('use_plots', False) NumpyDocString.__init__(self, docstring, config=config) @@ -18,7 +22,7 @@ def _str_field_list(self, name): def _str_indent(self, doc, indent=4): out = [] for line in doc: - out += [' '*indent + line] + out += [' ' * indent + line] return out def _str_signature(self): @@ -39,11 +43,11 @@ def _str_param_list(self, name): if self[name]: out += self._str_field_list(name) out += [''] - for param,param_type,desc in self[name]: + for param, param_type, desc in self[name]: out += self._str_indent(['**%s** : %s' % (param.strip(), param_type)]) out += [''] - out += self._str_indent(desc,8) + out += self._str_indent(desc, 8) out += [''] return out @@ -85,7 +89,7 @@ def _str_member_list(self, name): if others: maxlen_0 = max([len(x[0]) for x in others]) maxlen_1 = max([len(x[1]) for x in others]) - hdr = "="*maxlen_0 + " " + "="*maxlen_1 + " " + "="*10 + hdr = "=" * maxlen_0 + " " + "=" * maxlen_1 + " " + "=" * 10 fmt = '%%%ds %%%ds ' % (maxlen_0, maxlen_1) n_indent = maxlen_0 + maxlen_1 + 4 out += [hdr] @@ -127,8 +131,8 @@ def _str_index(self): if len(idx) == 0: return out - out += ['.. index:: %s' % idx.get('default','')] - for section, references in compat.iteritems(idx): + out += ['.. index:: %s' % idx.get('default', '')] + for section, references in idx.iteritems(): if section == 'default': continue elif section == 'refguide': @@ -148,9 +152,9 @@ def _str_references(self): # Latex collects all references to a separate bibliography, # so we need to insert links to it if sphinx.__version__ >= "0.6": - out += ['.. only:: latex',''] + out += ['.. only:: latex', ''] else: - out += ['.. latexonly::',''] + out += ['.. latexonly::', ''] items = [] for line in self['References']: m = re.match(r'.. \[([a-z0-9._-]+)\]', line, re.I) @@ -188,24 +192,31 @@ def __str__(self, indent=0, func_role="obj"): out += self._str_examples() for param_list in ('Attributes', 'Methods'): out += self._str_member_list(param_list) - out = self._str_indent(out,indent) + out = self._str_indent(out, indent) return '\n'.join(out) + class SphinxFunctionDoc(SphinxDocString, FunctionDoc): + def __init__(self, obj, doc=None, config={}): self.use_plots = config.get('use_plots', False) FunctionDoc.__init__(self, obj, doc=doc, config=config) + class SphinxClassDoc(SphinxDocString, ClassDoc): + def __init__(self, obj, doc=None, func_doc=None, config={}): self.use_plots = config.get('use_plots', False) ClassDoc.__init__(self, obj, doc=doc, func_doc=None, config=config) + class SphinxObjDoc(SphinxDocString): + def __init__(self, obj, doc=None, config={}): self._f = obj SphinxDocString.__init__(self, doc, config=config) + def get_doc_object(obj, what=None, doc=None, config={}): if what is None: if inspect.isclass(obj): diff --git a/doc/sphinxext/ipython_console_highlighting.py b/doc/sphinxext/ipython_console_highlighting.py index f0a41bebc82ce..569335311aeab 100644 --- a/doc/sphinxext/ipython_console_highlighting.py +++ b/doc/sphinxext/ipython_console_highlighting.py @@ -26,7 +26,9 @@ #----------------------------------------------------------------------------- # Code begins - classes and functions + class IPythonConsoleLexer(Lexer): + """ For IPython console output or doctests, such as: diff --git a/doc/sphinxext/ipython_directive.py b/doc/sphinxext/ipython_directive.py index 948d60c3760e9..f05330c371885 100644 --- a/doc/sphinxext/ipython_directive.py +++ b/doc/sphinxext/ipython_directive.py @@ -51,15 +51,14 @@ - VĂĄclavĹ milauer : Prompt generalizations. - Skipper Seabold, refactoring, cleanups, pure python addition """ -from __future__ import print_function #----------------------------------------------------------------------------- # Imports #----------------------------------------------------------------------------- # Stdlib -from pandas.compat import zip, range, map, lmap, u, cStringIO as StringIO import ast +import cStringIO import os import re import sys @@ -88,6 +87,8 @@ #----------------------------------------------------------------------------- # Functions and class declarations #----------------------------------------------------------------------------- + + def block_parser(part, rgxin, rgxout, fmtin, fmtout): """ part is a string of ipython text, comprised of at most one @@ -115,9 +116,9 @@ def block_parser(part, rgxin, rgxout, fmtin, fmtout): N = len(lines) i = 0 decorator = None - while True: + while 1: - if i==N: + if i == N: # nothing left to parse -- the last line break @@ -140,7 +141,7 @@ def block_parser(part, rgxin, rgxout, fmtin, fmtout): lineno, inputline = int(matchin.group(1)), matchin.group(2) # the ....: continuation string - continuation = ' %s:'% ''.join(['.']*(len(str(lineno))+2)) + continuation = ' %s:' % ''.join(['.'] * (len(str(lineno)) + 2)) Nc = len(continuation) # input lines can continue on for more than one line, if # we have a '\' line continuation char or a function call @@ -150,21 +151,22 @@ def block_parser(part, rgxin, rgxout, fmtin, fmtout): # multiline as well as any echo text rest = [] - while i2: + # print lines + if len(lines) > 2: if debug: - print('\n'.join(lines)) - else: #NOTE: this raises some errors, what's it for? - #print 'INSERTING %d lines'%len(lines) + print '\n'.join(lines) + else: # NOTE: this raises some errors, what's it for? + # print 'INSERTING %d lines'%len(lines) self.state_machine.insert_input( lines, self.state_machine.input_lines.source(0)) text = '\n'.join(lines) txtnode = nodes.literal_block(text, text) txtnode['language'] = 'ipython' - #imgnode = nodes.image(figs) + # imgnode = nodes.image(figs) # cleanup self.teardown() - return []#, imgnode] + return [] # , imgnode] # Enable as a proper Sphinx directive + + def setup(app): setup.app = app @@ -799,7 +808,7 @@ def test(): In [3]: x.st x.startswith x.strip """, - r""" + r""" In [130]: url = 'http://ichart.finance.yahoo.com/table.csv?s=CROX\ .....: &d=9&e=22&f=2009&g=d&a=1&br=8&c=2006&ignore=.csv' @@ -810,7 +819,7 @@ def test(): In [60]: import urllib """, - r"""\ + r"""\ In [133]: import numpy.random @@ -833,7 +842,7 @@ def test(): """, - r""" + r""" In [106]: print x jdh @@ -880,7 +889,7 @@ def test(): In [151]: hist(np.random.randn(10000), 100); """, - r""" + r""" # update the current fig In [151]: ylabel('number') @@ -891,12 +900,12 @@ def test(): In [153]: grid(True) """, - ] + ] # skip local-file depending first example: examples = examples[1:] - #ipython_directive.DEBUG = True # dbg - #options = dict(suppress=True) # dbg + # ipython_directive.DEBUG = True # dbg + # options = dict(suppress=True) # dbg options = dict() for example in examples: content = example.split('\n') @@ -907,8 +916,8 @@ def test(): ) # Run test suite as a script -if __name__=='__main__': +if __name__ == '__main__': if not os.path.isdir('_static'): os.mkdir('_static') test() - print('All OK? Check figures in _static/') + print 'All OK? Check figures in _static/' diff --git a/doc/sphinxext/numpydoc.py b/doc/sphinxext/numpydoc.py index 6f79703380a3d..1cba77cd7412e 100755 --- a/doc/sphinxext/numpydoc.py +++ b/doc/sphinxext/numpydoc.py @@ -21,12 +21,14 @@ if sphinx.__version__ < '1.0.1': raise RuntimeError("Sphinx 1.0.1 or newer is required") -import os, re, pydoc -from .docscrape_sphinx import get_doc_object, SphinxDocString -from pandas.compat import u, callable +import os +import re +import pydoc +from docscrape_sphinx import get_doc_object, SphinxDocString from sphinx.util.compat import Directive import inspect + def mangle_docstrings(app, what, name, obj, options, lines, reference_offset=[0]): @@ -35,28 +37,28 @@ def mangle_docstrings(app, what, name, obj, options, lines, if what == 'module': # Strip top title - title_re = re.compile(u(r'^\s*[#*=]{4,}\n[a-z0-9 -]+\n[#*=]{4,}\s*'), - re.I|re.S) - lines[:] = title_re.sub(u(''), u("\n").join(lines)).split(u("\n")) + title_re = re.compile(ur'^\s*[#*=]{4,}\n[a-z0-9 -]+\n[#*=]{4,}\s*', + re.I | re.S) + lines[:] = title_re.sub(u'', u"\n".join(lines)).split(u"\n") else: - doc = get_doc_object(obj, what, u("\n").join(lines), config=cfg) - lines[:] = compat.text_type(doc).split(u("\n")) + doc = get_doc_object(obj, what, u"\n".join(lines), config=cfg) + lines[:] = unicode(doc).split(u"\n") if app.config.numpydoc_edit_link and hasattr(obj, '__name__') and \ - obj.__name__: + obj.__name__: if hasattr(obj, '__module__'): - v = dict(full_name=u("%s.%s") % (obj.__module__, obj.__name__)) + v = dict(full_name=u"%s.%s" % (obj.__module__, obj.__name__)) else: v = dict(full_name=obj.__name__) - lines += [u(''), u('.. htmlonly::'), ''] - lines += [u(' %s') % x for x in + lines += [u'', u'.. htmlonly::', ''] + lines += [u' %s' % x for x in (app.config.numpydoc_edit_link % v).split("\n")] # replace reference numbers so that there are no duplicates references = [] for line in lines: line = line.strip() - m = re.match(u(r'^.. \[([a-z0-9_.-])\]'), line, re.I) + m = re.match(ur'^.. \[([a-z0-9_.-])\]', line, re.I) if m: references.append(m.group(1)) @@ -65,31 +67,35 @@ def mangle_docstrings(app, what, name, obj, options, lines, if references: for i, line in enumerate(lines): for r in references: - if re.match(u(r'^\d+$'), r): - new_r = u("R%d") % (reference_offset[0] + int(r)) + if re.match(ur'^\d+$', r): + new_r = u"R%d" % (reference_offset[0] + int(r)) else: - new_r = u("%s%d") % (r, reference_offset[0]) - lines[i] = lines[i].replace(u('[%s]_') % r, - u('[%s]_') % new_r) - lines[i] = lines[i].replace(u('.. [%s]') % r, - u('.. [%s]') % new_r) + new_r = u"%s%d" % (r, reference_offset[0]) + lines[i] = lines[i].replace(u'[%s]_' % r, + u'[%s]_' % new_r) + lines[i] = lines[i].replace(u'.. [%s]' % r, + u'.. [%s]' % new_r) reference_offset[0] += len(references) + def mangle_signature(app, what, name, obj, options, sig, retann): # Do not try to inspect classes that don't define `__init__` if (inspect.isclass(obj) and (not hasattr(obj, '__init__') or - 'initializes x; see ' in pydoc.getdoc(obj.__init__))): + 'initializes x; see ' in pydoc.getdoc(obj.__init__))): return '', '' - if not (callable(obj) or hasattr(obj, '__argspec_is_invalid_')): return - if not hasattr(obj, '__doc__'): return + if not (callable(obj) or hasattr(obj, '__argspec_is_invalid_')): + return + if not hasattr(obj, '__doc__'): + return doc = SphinxDocString(pydoc.getdoc(obj)) if doc['Signature']: - sig = re.sub(u("^[^(]*"), u(""), doc['Signature']) - return sig, u('') + sig = re.sub(u"^[^(]*", u"", doc['Signature']) + return sig, u'' + def setup(app, get_doc_object_=get_doc_object): global get_doc_object @@ -113,6 +119,7 @@ def setup(app, get_doc_object_=get_doc_object): from sphinx.domains.c import CDomain from sphinx.domains.python import PythonDomain + class ManglingDomainBase(object): directive_mangling_map = {} @@ -125,6 +132,7 @@ def wrap_mangling_directives(self): self.directives[name] = wrap_mangling_directive( self.directives[name], objtype) + class NumpyPythonDomain(ManglingDomainBase, PythonDomain): name = 'np' directive_mangling_map = { @@ -137,6 +145,7 @@ class NumpyPythonDomain(ManglingDomainBase, PythonDomain): 'attribute': 'attribute', } + class NumpyCDomain(ManglingDomainBase, CDomain): name = 'np-c' directive_mangling_map = { @@ -147,8 +156,10 @@ class NumpyCDomain(ManglingDomainBase, CDomain): 'var': 'object', } + def wrap_mangling_directive(base_directive, objtype): class directive(base_directive): + def run(self): env = self.state.document.settings.env @@ -167,4 +178,3 @@ def run(self): return base_directive.run(self) return directive - diff --git a/doc/sphinxext/only_directives.py b/doc/sphinxext/only_directives.py index c0dff7e65a17c..25cef30d21dc8 100755 --- a/doc/sphinxext/only_directives.py +++ b/doc/sphinxext/only_directives.py @@ -17,12 +17,15 @@ from docutils.parsers.rst import directives + class html_only(Body, Element): pass + class latex_only(Body, Element): pass + def run(content, node_class, state, content_offset): text = '\n'.join(content) node = node_class(text) @@ -71,6 +74,7 @@ class LatexOnlyDirective(OnlyDirective): directives.register_directive('htmlonly', HtmlOnlyDirective) directives.register_directive('latexonly', LatexOnlyDirective) + def setup(app): app.add_node(html_only) app.add_node(latex_only) @@ -78,10 +82,13 @@ def setup(app): # Add visit/depart methods to HTML-Translator: def visit_perform(self, node): pass + def depart_perform(self, node): pass + def visit_ignore(self, node): node.children = [] + def depart_ignore(self, node): node.children = [] diff --git a/doc/sphinxext/phantom_import.py b/doc/sphinxext/phantom_import.py index a92eb96e589c8..926641827e937 100755 --- a/doc/sphinxext/phantom_import.py +++ b/doc/sphinxext/phantom_import.py @@ -14,22 +14,31 @@ .. [1] http://code.google.com/p/pydocweb """ -from __future__ import print_function -import imp, sys, compiler, types, os, inspect, re +import imp +import sys +import compiler +import types +import os +import inspect +import re + def setup(app): app.connect('builder-inited', initialize) app.add_config_value('phantom_import_file', None, True) + def initialize(app): fn = app.config.phantom_import_file if (fn and os.path.isfile(fn)): - print("[numpydoc] Phantom importing modules from", fn, "...") + print "[numpydoc] Phantom importing modules from", fn, "..." import_phantom_module(fn) #------------------------------------------------------------------------------ # Creating 'phantom' modules from an XML description #------------------------------------------------------------------------------ + + def import_phantom_module(xml_file): """ Insert a fake Python module to sys.modules, based on a XML file. @@ -47,7 +56,7 @@ def import_phantom_module(xml_file): ---------- xml_file : str Name of an XML file to read - + """ import lxml.etree as etree @@ -60,7 +69,7 @@ def import_phantom_module(xml_file): # - Base classes come before classes inherited from them # - Modules come before their contents all_nodes = dict([(n.attrib['id'], n) for n in root]) - + def _get_bases(node, recurse=False): bases = [x.attrib['ref'] for x in node.findall('base')] if recurse: @@ -68,26 +77,31 @@ def _get_bases(node, recurse=False): while True: try: b = bases[j] - except IndexError: break + except IndexError: + break if b in all_nodes: bases.extend(_get_bases(all_nodes[b])) j += 1 return bases type_index = ['module', 'class', 'callable', 'object'] - + def base_cmp(a, b): x = cmp(type_index.index(a.tag), type_index.index(b.tag)) - if x != 0: return x + if x != 0: + return x if a.tag == 'class' and b.tag == 'class': a_bases = _get_bases(a, recurse=True) b_bases = _get_bases(b, recurse=True) x = cmp(len(a_bases), len(b_bases)) - if x != 0: return x - if a.attrib['id'] in b_bases: return -1 - if b.attrib['id'] in a_bases: return 1 - + if x != 0: + return x + if a.attrib['id'] in b_bases: + return -1 + if b.attrib['id'] in a_bases: + return 1 + return cmp(a.attrib['id'].count('.'), b.attrib['id'].count('.')) nodes = root.getchildren() @@ -97,14 +111,17 @@ def base_cmp(a, b): for node in nodes: name = node.attrib['id'] doc = (node.text or '').decode('string-escape') + "\n" - if doc == "\n": doc = "" + if doc == "\n": + doc = "" # create parent, if missing parent = name while True: parent = '.'.join(parent.split('.')[:-1]) - if not parent: break - if parent in object_cache: break + if not parent: + break + if parent in object_cache: + break obj = imp.new_module(parent) object_cache[parent] = obj sys.modules[parent] = obj @@ -130,13 +147,14 @@ def base_cmp(a, b): doc = "%s%s\n\n%s" % (funcname, argspec, doc) obj = lambda: 0 obj.__argspec_is_invalid_ = True - obj.__name__ = funcname + obj.func_name = funcname obj.__name__ = name obj.__doc__ = doc if inspect.isclass(object_cache[parent]): obj.__objclass__ = object_cache[parent] else: - class Dummy(object): pass + class Dummy(object): + pass obj = Dummy() obj.__name__ = name obj.__doc__ = doc @@ -152,7 +170,8 @@ class Dummy(object): pass # Populate items for node in root: obj = object_cache.get(node.attrib['id']) - if obj is None: continue + if obj is None: + continue for ref in node.findall('ref'): if node.tag == 'class': if ref.attrib['ref'].startswith(node.attrib['id'] + '.'): diff --git a/doc/sphinxext/plot_directive.py b/doc/sphinxext/plot_directive.py index b86c43249dbe8..0a85c6c7f108a 100755 --- a/doc/sphinxext/plot_directive.py +++ b/doc/sphinxext/plot_directive.py @@ -75,8 +75,16 @@ """ -from pandas.compat import range, cStringIO as StringIO, map -import sys, os, glob, shutil, imp, warnings, re, textwrap, traceback +import sys +import os +import glob +import shutil +import imp +import warnings +import cStringIO +import re +import textwrap +import traceback import sphinx import warnings @@ -111,11 +119,13 @@ def setup(app): from docutils.parsers.rst import directives from docutils import nodes + def plot_directive(name, arguments, options, content, lineno, content_offset, block_text, state, state_machine): return run(arguments, content, options, state_machine, state, lineno) plot_directive.__doc__ = __doc__ + def _option_boolean(arg): if not arg or not arg.strip(): # no argument given, assume used as a flag @@ -127,9 +137,11 @@ def _option_boolean(arg): else: raise ValueError('"%s" unknown boolean' % arg) + def _option_format(arg): return directives.choice(arg, ('python', 'lisp')) + def _option_align(arg): return directives.choice(arg, ("top", "middle", "bottom", "left", "center", "right")) @@ -153,10 +165,12 @@ def _option_align(arg): try: # Sphinx depends on either Jinja or Jinja2 import jinja2 + def format_template(template, **kw): return jinja2.Template(template).render(**kw) except ImportError: import jinja + def format_template(template, **kw): return jinja.from_string(template, **kw) @@ -205,7 +219,9 @@ def format_template(template, **kw): """ + class ImageFile(object): + def __init__(self, basename, dirname): self.basename = basename self.dirname = dirname @@ -217,6 +233,7 @@ def filename(self, format): def filenames(self): return [self.filename(fmt) for fmt in self.formats] + def run(arguments, content, options, state_machine, state, lineno): if arguments and content: raise RuntimeError("plot:: directive can't have both args and content") @@ -258,7 +275,7 @@ def run(arguments, content, options, state_machine, state, lineno): # is it in doctest format? is_doctest = contains_doctest(code) - if 'format' in options: + if options.has_key('format'): if options['format'] == 'python': is_doctest = False else: @@ -292,7 +309,7 @@ def run(arguments, content, options, state_machine, state, lineno): results = makefig(code, source_file_name, build_dir, output_base, config) errors = [] - except PlotError as err: + except PlotError, err: reporter = state.memo.reporter sm = reporter.system_message( 2, "Exception occurred in plotting %s: %s" % (output_base, err), @@ -381,6 +398,7 @@ def run(arguments, content, options, state_machine, state, lineno): import exceptions + def contains_doctest(text): try: # check if it's valid Python as-is @@ -392,6 +410,7 @@ def contains_doctest(text): m = r.search(text) return bool(m) + def unescape_doctest(text): """ Extract code from a piece of text, which contains either Python code @@ -412,6 +431,7 @@ def unescape_doctest(text): code += "\n" return code + def split_code_at_show(text): """ Split code at plt.show() @@ -424,7 +444,7 @@ def split_code_at_show(text): part = [] for line in text.split("\n"): if (not is_doctest and line.strip() == 'plt.show()') or \ - (is_doctest and line.strip() == '>>> plt.show()'): + (is_doctest and line.strip() == '>>> plt.show()'): part.append(line) parts.append("\n".join(part)) part = [] @@ -434,9 +454,11 @@ def split_code_at_show(text): parts.append("\n".join(part)) return parts + class PlotError(RuntimeError): pass + def run_code(code, code_path, ns=None): # Change the working directory to the directory of the example, so # it can get at its data files, if any. @@ -449,7 +471,7 @@ def run_code(code, code_path, ns=None): # Redirect stdout stdout = sys.stdout - sys.stdout = StringIO() + sys.stdout = cStringIO.StringIO() # Reset sys.argv old_sys_argv = sys.argv @@ -461,9 +483,9 @@ def run_code(code, code_path, ns=None): if ns is None: ns = {} if not ns: - exec(setup.config.plot_pre_code, ns) - exec(code, ns) - except (Exception, SystemExit) as err: + exec setup.config.plot_pre_code in ns + exec code in ns + except (Exception, SystemExit), err: raise PlotError(traceback.format_exc()) finally: os.chdir(pwd) @@ -499,7 +521,7 @@ def makefig(code, code_path, output_dir, output_base, config): for fmt in config.plot_formats: if isinstance(fmt, str): formats.append((fmt, default_dpi.get(fmt, 80))) - elif type(fmt) in (tuple, list) and len(fmt)==2: + elif type(fmt) in (tuple, list) and len(fmt) == 2: formats.append((str(fmt[0]), int(fmt[1]))) else: raise PlotError('invalid image format "%r" in plot_formats' % fmt) @@ -525,7 +547,7 @@ def makefig(code, code_path, output_dir, output_base, config): all_exists = True for i, code_piece in enumerate(code_pieces): images = [] - for j in range(1000): + for j in xrange(1000): img = ImageFile('%s_%02d_%02d' % (output_base, i, j), output_dir) for format, dpi in formats: if out_of_date(code_path, img.filename(format)): @@ -571,7 +593,7 @@ def makefig(code, code_path, output_dir, output_base, config): try: figman.canvas.figure.savefig(img.filename(format), dpi=dpi, bbox_inches='tight') - except exceptions.BaseException as err: + except exceptions.BaseException, err: raise PlotError(traceback.format_exc()) img.formats.append(format) @@ -593,7 +615,7 @@ def makefig(code, code_path, output_dir, output_base, config): def relpath(path, start=os.path.curdir): """Return a relative version of a path""" from os.path import sep, curdir, join, abspath, commonprefix, \ - pardir + pardir if not path: raise ValueError("no path specified") @@ -604,7 +626,7 @@ def relpath(path, start=os.path.curdir): # Work out how much of the filepath is shared by start and path. i = len(commonprefix([start_list, path_list])) - rel_list = [pardir] * (len(start_list)-i) + path_list[i:] + rel_list = [pardir] * (len(start_list) - i) + path_list[i:] if not rel_list: return curdir return join(*rel_list) @@ -612,7 +634,7 @@ def relpath(path, start=os.path.curdir): def relpath(path, start=os.path.curdir): """Return a relative version of a path""" from os.path import sep, curdir, join, abspath, commonprefix, \ - pardir, splitunc + pardir, splitunc if not path: raise ValueError("no path specified") @@ -623,10 +645,10 @@ def relpath(path, start=os.path.curdir): unc_start, rest = splitunc(start) if bool(unc_path) ^ bool(unc_start): raise ValueError("Cannot mix UNC and non-UNC paths (%s and %s)" - % (path, start)) + % (path, start)) else: raise ValueError("path is on drive %s, start on drive %s" - % (path_list[0], start_list[0])) + % (path_list[0], start_list[0])) # Work out how much of the filepath is shared by start and path. for i in range(min(len(start_list), len(path_list))): if start_list[i].lower() != path_list[i].lower(): @@ -634,7 +656,7 @@ def relpath(path, start=os.path.curdir): else: i += 1 - rel_list = [pardir] * (len(start_list)-i) + path_list[i:] + rel_list = [pardir] * (len(start_list) - i) + path_list[i:] if not rel_list: return curdir return join(*rel_list) diff --git a/doc/sphinxext/setup.py b/doc/sphinxext/setup.py index 016d8f8ae5a5c..f73287eee2351 100755 --- a/doc/sphinxext/setup.py +++ b/doc/sphinxext/setup.py @@ -1,6 +1,7 @@ from distutils.core import setup import setuptools -import sys, os +import sys +import os version = "0.3.dev" diff --git a/doc/sphinxext/tests/test_docscrape.py b/doc/sphinxext/tests/test_docscrape.py index ef2dfacc5b560..96c9d5639b5c2 100755 --- a/doc/sphinxext/tests/test_docscrape.py +++ b/doc/sphinxext/tests/test_docscrape.py @@ -1,13 +1,12 @@ -from __future__ import print_function # -*- encoding:utf-8 -*- -import sys, os +import sys +import os sys.path.append(os.path.join(os.path.dirname(__file__), '..')) from docscrape import NumpyDocString, FunctionDoc, ClassDoc from docscrape_sphinx import SphinxDocString, SphinxClassDoc from nose.tools import * -from pandas.compat import u doc_txt = '''\ numpy.multivariate_normal(mean, cov, shape=None) @@ -106,22 +105,27 @@ def test_signature(): assert doc['Signature'].startswith('numpy.multivariate_normal(') assert doc['Signature'].endswith('shape=None)') + def test_summary(): assert doc['Summary'][0].startswith('Draw values') assert doc['Summary'][-1].endswith('covariance.') + def test_extended_summary(): assert doc['Extended Summary'][0].startswith('The multivariate normal') + def test_parameters(): assert_equal(len(doc['Parameters']), 3) - assert_equal([n for n,_,_ in doc['Parameters']], ['mean','cov','shape']) + assert_equal( + [n for n, _, _ in doc['Parameters']], ['mean', 'cov', 'shape']) arg, arg_type, desc = doc['Parameters'][1] assert_equal(arg_type, '(N,N) ndarray') assert desc[0].startswith('Covariance matrix') assert doc['Parameters'][0][-1][-2] == ' (1+2+3)/3' + def test_returns(): assert_equal(len(doc['Returns']), 1) arg, arg_type, desc = doc['Returns'][0] @@ -130,36 +134,43 @@ def test_returns(): assert desc[0].startswith('The drawn samples') assert desc[-1].endswith('distribution.') + def test_notes(): assert doc['Notes'][0].startswith('Instead') assert doc['Notes'][-1].endswith('definite.') assert_equal(len(doc['Notes']), 17) + def test_references(): assert doc['References'][0].startswith('..') assert doc['References'][-1].endswith('2001.') + def test_examples(): assert doc['Examples'][0].startswith('>>>') assert doc['Examples'][-1].endswith('True]') + def test_index(): assert_equal(doc['index']['default'], 'random') - print(doc['index']) + print doc['index'] assert_equal(len(doc['index']), 2) assert_equal(len(doc['index']['refguide']), 2) -def non_blank_line_by_line_compare(a,b): + +def non_blank_line_by_line_compare(a, b): a = [l for l in a.split('\n') if l.strip()] b = [l for l in b.split('\n') if l.strip()] - for n,line in enumerate(a): + for n, line in enumerate(a): if not line == b[n]: raise AssertionError("Lines %s of a and b differ: " "\n>>> %s\n<<< %s\n" % - (n,line,b[n])) + (n, line, b[n])) + + def test_str(): non_blank_line_by_line_compare(str(doc), -"""numpy.multivariate_normal(mean, cov, shape=None) + """numpy.multivariate_normal(mean, cov, shape=None) Draw values from a multivariate normal distribution with specified mean and covariance. @@ -252,7 +263,7 @@ def test_str(): def test_sphinx_str(): sphinx_doc = SphinxDocString(doc_txt) non_blank_line_by_line_compare(str(sphinx_doc), -""" + """ .. index:: random single: random;distributions, random;gauss @@ -362,6 +373,7 @@ def test_sphinx_str(): If None, the index is into the flattened array, otherwise along the specified axis""") + def test_parameters_without_extended_description(): assert_equal(len(doc2['Parameters']), 2) @@ -371,6 +383,7 @@ def test_parameters_without_extended_description(): Return this and that. """) + def test_escape_stars(): signature = str(doc3).split('\n')[0] assert_equal(signature, 'my_signature(\*params, \*\*kwds)') @@ -380,6 +393,7 @@ def test_escape_stars(): Return an array with all complex-valued elements conjugated.""") + def test_empty_extended_summary(): assert_equal(doc4['Extended Summary'], []) @@ -394,15 +408,17 @@ def test_empty_extended_summary(): """) + def test_raises(): assert_equal(len(doc5['Raises']), 1) - name,_,desc = doc5['Raises'][0] - assert_equal(name,'LinAlgException') - assert_equal(desc,['If array is singular.']) + name, _, desc = doc5['Raises'][0] + assert_equal(name, 'LinAlgException') + assert_equal(desc, ['If array is singular.']) + def test_see_also(): doc6 = NumpyDocString( - """ + """ z(x,theta) See Also @@ -442,8 +458,10 @@ def test_see_also(): elif func == 'class_j': assert desc == ['fubar', 'foobar'] + def test_see_also_print(): class Dummy(object): + """ See Also -------- @@ -466,6 +484,7 @@ class Dummy(object): """) + def test_empty_first_line(): assert doc7['Summary'][0].startswith('Doc starts') @@ -493,7 +512,8 @@ def test_unicode(): äää """) - assert doc['Summary'][0] == u('öäöäöäöäöåååå').encode('utf-8') + assert doc['Summary'][0] == u'öäöäöäöäöåååå'.encode('utf-8') + def test_plot_examples(): cfg = dict(use_plots=True) @@ -518,16 +538,20 @@ def test_plot_examples(): """, config=cfg) assert str(doc).count('plot::') == 1, str(doc) + def test_class_members(): class Dummy(object): + """ Dummy class. """ + def spam(self, a, b): """Spam\n\nSpam spam.""" pass + def ham(self, c, d): """Cheese\n\nNo cheese.""" pass diff --git a/doc/sphinxext/traitsdoc.py b/doc/sphinxext/traitsdoc.py index 8ec57a607ffb9..f39fe0c2e23da 100755 --- a/doc/sphinxext/traitsdoc.py +++ b/doc/sphinxext/traitsdoc.py @@ -15,19 +15,18 @@ """ import inspect -import os import pydoc -from pandas.compat import callable -from . import docscrape -from . import docscrape_sphinx -from .docscrape_sphinx import SphinxClassDoc, SphinxFunctionDoc, SphinxDocString +import docscrape +from docscrape_sphinx import SphinxClassDoc, SphinxFunctionDoc, SphinxDocString -from . import numpydoc +import numpydoc + +import comment_eater -from . import comment_eater class SphinxTraitsDoc(SphinxClassDoc): + def __init__(self, cls, modulename='', func_doc=SphinxFunctionDoc): if not inspect.isclass(cls): raise ValueError("Initialise using a class. Got %r" % cls) @@ -49,7 +48,7 @@ def __init__(self, cls, modulename='', func_doc=SphinxFunctionDoc): except ValueError: indent = 0 - for n,line in enumerate(docstring): + for n, line in enumerate(docstring): docstring[n] = docstring[n][indent:] self._doc = docscrape.Reader(docstring) @@ -71,7 +70,7 @@ def __init__(self, cls, modulename='', func_doc=SphinxFunctionDoc): 'Example': '', 'Examples': '', 'index': {} - } + } self._parse() @@ -88,16 +87,17 @@ def __str__(self, indent=0, func_role="func"): out += self._str_summary() out += self._str_extended_summary() for param_list in ('Parameters', 'Traits', 'Methods', - 'Returns','Raises'): + 'Returns', 'Raises'): out += self._str_param_list(param_list) out += self._str_see_also("obj") out += self._str_section('Notes') out += self._str_references() out += self._str_section('Example') out += self._str_section('Examples') - out = self._str_indent(out,indent) + out = self._str_indent(out, indent) return '\n'.join(out) + def looks_like_issubclass(obj, classname): """ Return True if the object has a class or superclass with the given class name. @@ -112,6 +112,7 @@ def looks_like_issubclass(obj, classname): return True return False + def get_doc_object(obj, what=None, config=None): if what is None: if inspect.isclass(obj): @@ -123,7 +124,8 @@ def get_doc_object(obj, what=None, config=None): else: what = 'object' if what == 'class': - doc = SphinxTraitsDoc(obj, '', func_doc=SphinxFunctionDoc, config=config) + doc = SphinxTraitsDoc( + obj, '', func_doc=SphinxFunctionDoc, config=config) if looks_like_issubclass(obj, 'HasTraits'): for name, trait, comment in comment_eater.get_class_traits(obj): # Exclude private traits. @@ -135,7 +137,7 @@ def get_doc_object(obj, what=None, config=None): else: return SphinxDocString(pydoc.getdoc(obj), config=config) + def setup(app): # init numpydoc numpydoc.setup(app, get_doc_object) -