From 00de67ff88847d1de6f3b3d39485ce5e54b72a0f Mon Sep 17 00:00:00 2001 From: Tiago de Paula Peixoto Date: Thu, 8 Mar 2018 11:36:15 +0000 Subject: [PATCH] Sphinx cleanup and docs update --- Makefile.am | 9 - doc/conf.py | 2 +- doc/demos/inference/inference.rst | 135 +++--- doc/sphinxext/LICENSE.txt | 94 ---- doc/sphinxext/MANIFEST.in | 2 - doc/sphinxext/README.txt | 45 -- doc/sphinxext/__init__.py | 1 - doc/sphinxext/docscrape.py | 506 --------------------- doc/sphinxext/docscrape_sphinx.py | 228 ---------- doc/sphinxext/numpydoc.py | 170 ------- doc/sphinxext/setup.py | 23 - doc/sphinxext/tests/test_docscrape.py | 615 -------------------------- 12 files changed, 77 insertions(+), 1753 deletions(-) delete mode 100644 doc/sphinxext/LICENSE.txt delete mode 100644 doc/sphinxext/MANIFEST.in delete mode 100644 doc/sphinxext/README.txt delete mode 100644 doc/sphinxext/__init__.py delete mode 100644 doc/sphinxext/docscrape.py delete mode 100644 doc/sphinxext/docscrape_sphinx.py delete mode 100644 doc/sphinxext/numpydoc.py delete mode 100644 doc/sphinxext/setup.py delete mode 100644 doc/sphinxext/tests/test_docscrape.py diff --git a/Makefile.am b/Makefile.am index 1b1ab9c4..e51c5a55 100644 --- a/Makefile.am +++ b/Makefile.am @@ -34,19 +34,10 @@ nobase_dist_graphtooldoc_DATA = \ doc/demos/index.rst \ doc/demos/animation/animation.rst \ doc/demos/inference/inference.rst \ - doc/sphinxext/README.txt \ - doc/sphinxext/LICENSE.txt \ - doc/sphinxext/__init__.py \ - doc/sphinxext/setup.py \ doc/sphinxext/comment_eater.py \ - doc/sphinxext/docscrape.py \ - doc/sphinxext/MANIFEST.in \ doc/sphinxext/phantom_import.py \ doc/sphinxext/compiler_unparse.py \ - doc/sphinxext/docscrape_sphinx.py \ - doc/sphinxext/numpydoc.py \ doc/sphinxext/traitsdoc.py \ - doc/sphinxext/tests/test_docscrape.py \ doc/gt_theme/static/flasky.css \ doc/gt_theme/static/gt_style.css \ doc/gt_theme/theme.conf \ diff --git a/doc/conf.py b/doc/conf.py index 5c9b9f69..c62e1e84 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -184,7 +184,7 @@ intersphinx_mapping = {'python': ('https://docs.python.org/3', None), extlinks_fancy = {'ticket': (['https://graph-tool.skewed.de/tickets/ticket/{0}'], ['ticket {0}']), 'doi': (['https://dx.doi.org/{0}', - 'https://sci-hub.cc/{0}', + 'https://sci-hub.tw/{0}', 'https://scihub22266oqcxt.onion.link/{0}'], ['DOI: {0}', "sci-hub", "@tor"]), 'arxiv': (['https://arxiv.org/abs/{0}'], ['arXiv: {0}'])} diff --git a/doc/demos/inference/inference.rst b/doc/demos/inference/inference.rst index 033ec1e7..37b99cd2 100644 --- a/doc/demos/inference/inference.rst +++ b/doc/demos/inference/inference.rst @@ -359,7 +359,7 @@ illustrate its use with the neural network of the `C. elegans .. testsetup:: celegans - gt.seed_rng(43) + gt.seed_rng(47) .. testcode:: celegans @@ -411,10 +411,10 @@ which shows the number of nodes and groups in all levels: .. testoutput:: celegans - l: 0, N: 297, B: 15 - l: 1, N: 15, B: 6 - l: 2, N: 6, B: 4 - l: 3, N: 4, B: 1 + l: 0, N: 297, B: 17 + l: 1, N: 17, B: 9 + l: 2, N: 9, B: 3 + l: 3, N: 3, B: 1 The hierarchical levels themselves are represented by individual :meth:`~graph_tool.inference.BlockState` instances obtained via the @@ -428,10 +428,10 @@ The hierarchical levels themselves are represented by individual .. testoutput:: celegans - , at 0x...> - , at 0x...> - , at 0x...> - , at 0x...> + , at 0x...> + , at 0x...> + , at 0x...> + , at 0x...> This means that we can inspect the hierarchical partition just as before: @@ -446,7 +446,7 @@ This means that we can inspect the hierarchical partition just as before: .. testoutput:: celegans - 5 + 7 0 0 @@ -476,8 +476,8 @@ case of the `C. elegans` network we have .. testoutput:: model-selection :options: +NORMALIZE_WHITESPACE - Non-degree-corrected DL: 8478.791367... - Degree-corrected DL: 8207.895440... + Non-degree-corrected DL: 8456.994339... + Degree-corrected DL: 8233.850036... Since it yields the smallest description length, the degree-corrected fit should be preferred. The statistical significance of the choice can @@ -503,12 +503,12 @@ fits. In our particular case, we have .. testoutput:: model-selection :options: +NORMALIZE_WHITESPACE - ln Λ: -270.895926... + ln Λ: -223.144303... The precise threshold that should be used to decide when to `reject a hypothesis `_ is subjective and context-dependent, but the value above implies that the -particular degree-corrected fit is around :math:`\mathrm{e}^{270} \approx 10^{117}` +particular degree-corrected fit is around :math:`\mathrm{e}^{233} \approx 10^{96}` times more likely than the non-degree corrected one, and hence it can be safely concluded that it provides a substantially better fit. @@ -530,12 +530,12 @@ example, for the American football network above, we have: .. testoutput:: model-selection :options: +NORMALIZE_WHITESPACE - Non-degree-corrected DL: 1747.500987... - Degree-corrected DL: 1780.576716... - ln Λ: -33.075729... + Non-degree-corrected DL: 1734.814739... + Degree-corrected DL: 1780.576716... + ln Λ: -45.761977... -Hence, with a posterior odds ratio of :math:`\Lambda \approx \mathrm{e}^{-33} \approx -10^{-14}` in favor of the non-degree-corrected model, it seems like the +Hence, with a posterior odds ratio of :math:`\Lambda \approx \mathrm{e}^{-45} \approx +10^{-19}` in favor of the non-degree-corrected model, it seems like the degree-corrected variant is an unnecessarily complex description for this network. @@ -595,8 +595,8 @@ random partition into 20 groups .. testoutput:: model-averaging - Change in description length: -358.602505... - Number of accepted vertex moves: 36528 + Change in description length: -365.317522... + Number of accepted vertex moves: 38213 .. note:: @@ -619,8 +619,8 @@ random partition into 20 groups .. testoutput:: model-averaging - Change in description length: 16.127057... - Number of accepted vertex moves: 39217 + Change in description length: 1.660677... + Number of accepted vertex moves: 40461 Although the above is sufficient to implement model averaging, there is a convenience function called @@ -641,34 +641,51 @@ will output: .. testoutput:: model-averaging :options: +NORMALIZE_WHITESPACE - niter: 1 count: 0 breaks: 0 min_S: 706.94151 max_S: 715.47667 S: 706.94151 ΔS: -8.53516 moves: 394 - niter: 2 count: 0 breaks: 0 min_S: 706.94151 max_S: 729.78585 S: 729.78585 ΔS: 22.8443 moves: 420 - niter: 3 count: 1 breaks: 0 min_S: 706.94151 max_S: 729.78585 S: 720.88036 ΔS: -8.90549 moves: 406 - niter: 4 count: 2 breaks: 0 min_S: 706.94151 max_S: 729.78585 S: 726.95968 ΔS: 6.07932 moves: 370 - niter: 5 count: 3 breaks: 0 min_S: 706.94151 max_S: 729.78585 S: 721.59919 ΔS: -5.36049 moves: 384 - niter: 6 count: 4 breaks: 0 min_S: 706.94151 max_S: 729.78585 S: 724.02327 ΔS: 2.42408 moves: 379 - niter: 7 count: 5 breaks: 0 min_S: 706.94151 max_S: 729.78585 S: 715.51448 ΔS: -8.50879 moves: 352 - niter: 8 count: 6 breaks: 0 min_S: 706.94151 max_S: 729.78585 S: 711.38261 ΔS: -4.13187 moves: 365 - niter: 9 count: 7 breaks: 0 min_S: 706.94151 max_S: 729.78585 S: 717.02574 ΔS: 5.64312 moves: 364 - niter: 10 count: 8 breaks: 0 min_S: 706.94151 max_S: 729.78585 S: 714.98290 ΔS: -2.04284 moves: 358 - niter: 11 count: 9 breaks: 0 min_S: 706.94151 max_S: 729.78585 S: 721.79965 ΔS: 6.81675 moves: 382 - niter: 12 count: 0 breaks: 1 min_S: 709.20806 max_S: 709.20806 S: 709.20806 ΔS: -12.5916 moves: 345 - niter: 13 count: 0 breaks: 1 min_S: 704.69711 max_S: 709.20806 S: 704.69711 ΔS: -4.51094 moves: 361 - niter: 14 count: 0 breaks: 1 min_S: 704.09567 max_S: 709.20806 S: 704.09567 ΔS: -0.601444 moves: 373 - niter: 15 count: 1 breaks: 1 min_S: 704.09567 max_S: 709.20806 S: 704.71189 ΔS: 0.616215 moves: 393 - niter: 16 count: 0 breaks: 1 min_S: 704.09567 max_S: 717.16180 S: 717.16180 ΔS: 12.4499 moves: 379 - niter: 17 count: 1 breaks: 1 min_S: 704.09567 max_S: 717.16180 S: 708.38966 ΔS: -8.77214 moves: 428 - niter: 18 count: 0 breaks: 1 min_S: 704.09567 max_S: 721.85296 S: 721.85296 ΔS: 13.4633 moves: 410 - niter: 19 count: 1 breaks: 1 min_S: 704.09567 max_S: 721.85296 S: 720.27396 ΔS: -1.57901 moves: 385 - niter: 20 count: 2 breaks: 1 min_S: 704.09567 max_S: 721.85296 S: 706.59958 ΔS: -13.6744 moves: 410 - niter: 21 count: 3 breaks: 1 min_S: 704.09567 max_S: 721.85296 S: 711.00676 ΔS: 4.40718 moves: 404 - niter: 22 count: 4 breaks: 1 min_S: 704.09567 max_S: 721.85296 S: 717.22981 ΔS: 6.22305 moves: 403 - niter: 23 count: 5 breaks: 1 min_S: 704.09567 max_S: 721.85296 S: 714.83148 ΔS: -2.39833 moves: 414 - niter: 24 count: 6 breaks: 1 min_S: 704.09567 max_S: 721.85296 S: 710.06471 ΔS: -4.76676 moves: 400 - niter: 25 count: 7 breaks: 1 min_S: 704.09567 max_S: 721.85296 S: 706.67930 ΔS: -3.38541 moves: 377 - niter: 26 count: 8 breaks: 1 min_S: 704.09567 max_S: 721.85296 S: 704.53434 ΔS: -2.14496 moves: 399 - niter: 27 count: 9 breaks: 1 min_S: 704.09567 max_S: 721.85296 S: 720.67029 ΔS: 16.1360 moves: 397 - niter: 28 count: 10 breaks: 2 min_S: 704.09567 max_S: 721.85296 S: 705.87845 ΔS: -14.7918 moves: 388 + niter: 1 count: 0 breaks: 0 min_S: 706.26857 max_S: 708.14483 S: 708.14483 ΔS: 1.87626 moves: 418 + niter: 2 count: 0 breaks: 0 min_S: 699.23453 max_S: 708.14483 S: 699.23453 ΔS: -8.91030 moves: 409 + niter: 3 count: 0 breaks: 0 min_S: 699.23453 max_S: 715.33531 S: 715.33531 ΔS: 16.1008 moves: 414 + niter: 4 count: 0 breaks: 0 min_S: 699.23453 max_S: 723.13301 S: 723.13301 ΔS: 7.79770 moves: 391 + niter: 5 count: 1 breaks: 0 min_S: 699.23453 max_S: 723.13301 S: 702.93354 ΔS: -20.1995 moves: 411 + niter: 6 count: 2 breaks: 0 min_S: 699.23453 max_S: 723.13301 S: 706.39029 ΔS: 3.45675 moves: 389 + niter: 7 count: 3 breaks: 0 min_S: 699.23453 max_S: 723.13301 S: 706.80859 ΔS: 0.418293 moves: 404 + niter: 8 count: 4 breaks: 0 min_S: 699.23453 max_S: 723.13301 S: 707.61960 ΔS: 0.811010 moves: 417 + niter: 9 count: 5 breaks: 0 min_S: 699.23453 max_S: 723.13301 S: 706.46577 ΔS: -1.15383 moves: 392 + niter: 10 count: 6 breaks: 0 min_S: 699.23453 max_S: 723.13301 S: 714.34671 ΔS: 7.88094 moves: 410 + niter: 11 count: 7 breaks: 0 min_S: 699.23453 max_S: 723.13301 S: 706.43194 ΔS: -7.91477 moves: 383 + niter: 12 count: 8 breaks: 0 min_S: 699.23453 max_S: 723.13301 S: 705.19434 ΔS: -1.23760 moves: 405 + niter: 13 count: 9 breaks: 0 min_S: 699.23453 max_S: 723.13301 S: 702.21395 ΔS: -2.98039 moves: 423 + niter: 14 count: 0 breaks: 1 min_S: 715.54878 max_S: 715.54878 S: 715.54878 ΔS: 13.3348 moves: 400 + niter: 15 count: 0 breaks: 1 min_S: 715.54878 max_S: 716.65842 S: 716.65842 ΔS: 1.10964 moves: 413 + niter: 16 count: 0 breaks: 1 min_S: 701.19994 max_S: 716.65842 S: 701.19994 ΔS: -15.4585 moves: 382 + niter: 17 count: 1 breaks: 1 min_S: 701.19994 max_S: 716.65842 S: 715.56997 ΔS: 14.3700 moves: 394 + niter: 18 count: 0 breaks: 1 min_S: 701.19994 max_S: 719.25577 S: 719.25577 ΔS: 3.68580 moves: 404 + niter: 19 count: 0 breaks: 1 min_S: 701.19994 max_S: 723.78811 S: 723.78811 ΔS: 4.53233 moves: 413 + niter: 20 count: 1 breaks: 1 min_S: 701.19994 max_S: 723.78811 S: 709.77340 ΔS: -14.0147 moves: 387 + niter: 21 count: 2 breaks: 1 min_S: 701.19994 max_S: 723.78811 S: 714.14891 ΔS: 4.37551 moves: 419 + niter: 22 count: 3 breaks: 1 min_S: 701.19994 max_S: 723.78811 S: 722.05875 ΔS: 7.90984 moves: 399 + niter: 23 count: 4 breaks: 1 min_S: 701.19994 max_S: 723.78811 S: 714.32503 ΔS: -7.73371 moves: 422 + niter: 24 count: 5 breaks: 1 min_S: 701.19994 max_S: 723.78811 S: 708.53927 ΔS: -5.78576 moves: 392 + niter: 25 count: 6 breaks: 1 min_S: 701.19994 max_S: 723.78811 S: 714.05889 ΔS: 5.51962 moves: 404 + niter: 26 count: 7 breaks: 1 min_S: 701.19994 max_S: 723.78811 S: 713.93196 ΔS: -0.126937 moves: 414 + niter: 27 count: 8 breaks: 1 min_S: 701.19994 max_S: 723.78811 S: 709.49863 ΔS: -4.43333 moves: 410 + niter: 28 count: 9 breaks: 1 min_S: 701.19994 max_S: 723.78811 S: 707.42167 ΔS: -2.07696 moves: 397 + niter: 29 count: 0 breaks: 1 min_S: 699.89982 max_S: 723.78811 S: 699.89982 ΔS: -7.52185 moves: 388 + niter: 30 count: 0 breaks: 1 min_S: 698.57305 max_S: 723.78811 S: 698.57305 ΔS: -1.32677 moves: 391 + niter: 31 count: 1 breaks: 1 min_S: 698.57305 max_S: 723.78811 S: 706.02629 ΔS: 7.45324 moves: 412 + niter: 32 count: 2 breaks: 1 min_S: 698.57305 max_S: 723.78811 S: 701.97778 ΔS: -4.04852 moves: 421 + niter: 33 count: 3 breaks: 1 min_S: 698.57305 max_S: 723.78811 S: 707.50134 ΔS: 5.52356 moves: 410 + niter: 34 count: 4 breaks: 1 min_S: 698.57305 max_S: 723.78811 S: 708.56686 ΔS: 1.06552 moves: 424 + niter: 35 count: 0 breaks: 1 min_S: 698.57305 max_S: 724.07361 S: 724.07361 ΔS: 15.5067 moves: 399 + niter: 36 count: 1 breaks: 1 min_S: 698.57305 max_S: 724.07361 S: 723.51969 ΔS: -0.553915 moves: 384 + niter: 37 count: 2 breaks: 1 min_S: 698.57305 max_S: 724.07361 S: 702.36708 ΔS: -21.1526 moves: 406 + niter: 38 count: 3 breaks: 1 min_S: 698.57305 max_S: 724.07361 S: 707.60129 ΔS: 5.23420 moves: 405 + niter: 39 count: 4 breaks: 1 min_S: 698.57305 max_S: 724.07361 S: 709.67542 ΔS: 2.07413 moves: 400 + niter: 40 count: 5 breaks: 1 min_S: 698.57305 max_S: 724.07361 S: 714.52753 ΔS: 4.85212 moves: 398 + niter: 41 count: 6 breaks: 1 min_S: 698.57305 max_S: 724.07361 S: 707.86563 ΔS: -6.66190 moves: 409 + niter: 42 count: 7 breaks: 1 min_S: 698.57305 max_S: 724.07361 S: 718.80926 ΔS: 10.9436 moves: 400 + niter: 43 count: 8 breaks: 1 min_S: 698.57305 max_S: 724.07361 S: 716.37312 ΔS: -2.43615 moves: 378 + niter: 44 count: 9 breaks: 1 min_S: 698.57305 max_S: 724.07361 S: 713.76944 ΔS: -2.60368 moves: 399 + niter: 45 count: 10 breaks: 2 min_S: 698.57305 max_S: 724.07361 S: 715.29009 ΔS: 1.52066 moves: 421 Note that the value of ``wait`` above was made purposefully low so that the output would not be overly long. The most appropriate value requires @@ -799,8 +816,8 @@ network as above. .. testoutput:: nested-model-averaging - Change in description length: 10.744544... - Number of accepted vertex moves: 50702 + Change in description length: 2.371018... + Number of accepted vertex moves: 56087 Similarly to the the non-nested case, we can use :func:`~graph_tool.inference.mcmc_equilibrate` to do most of the boring @@ -1065,8 +1082,8 @@ evidence efficiently, as we show below, using .. testoutput:: model-evidence - Model evidence for deg_corr = True: -559.5804... (mean field), -841.8073... (Bethe) - Model evidence for deg_corr = False: -581.9044... (mean field), -712.7732... (Bethe) + Model evidence for deg_corr = True: -569.590426... (mean field), -817.788531... (Bethe) + Model evidence for deg_corr = False: -587.028530... (mean field), -736.990655... (Bethe) If we consider the more accurate approximation, the outcome shows a preference for the non-degree-corrected model. @@ -1130,8 +1147,8 @@ approach for the same network, using the nested model. .. testoutput:: model-evidence - Model evidence for deg_corr = True: -553.6993... (mean field), -724.2353... (Bethe) - Model evidence for deg_corr = False: -530.0536... (mean field), -637.6968... (Bethe) + Model evidence for deg_corr = True: -551.228195... (mean field), -740.460493... (Bethe) + Model evidence for deg_corr = False: -544.660366... (mean field), -649.135026... (Bethe) The results are similar: If we consider the most accurate approximation, the non-degree-corrected model possesses the largest evidence. Note also @@ -1386,9 +1403,9 @@ Therefore, we can compute the posterior odds ratio between both models as: .. testoutput:: food-web :options: +NORMALIZE_WHITESPACE - ln Λ: -6.560861... + ln Λ: -70.145685... -A value of :math:`\Lambda \approx \mathrm{e}^{-43} \approx 10^{-19}` in +A value of :math:`\Lambda \approx \mathrm{e}^{-70} \approx 10^{-30}` in favor the exponential model indicates that the log-normal model does not provide a better fit for this particular data. Based on this, we conclude that the exponential model should be preferred in this case. diff --git a/doc/sphinxext/LICENSE.txt b/doc/sphinxext/LICENSE.txt deleted file mode 100644 index b15c699d..00000000 --- a/doc/sphinxext/LICENSE.txt +++ /dev/null @@ -1,94 +0,0 @@ -------------------------------------------------------------------------------- - The files - - numpydoc.py - - docscrape.py - - docscrape_sphinx.py - - phantom_import.py - have the following license: - -Copyright (C) 2008 Stefan van der Walt , Pauli Virtanen - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - -THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING -IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -------------------------------------------------------------------------------- - The files - - compiler_unparse.py - - comment_eater.py - - traitsdoc.py - have the following license: - -This software is OSI Certified Open Source Software. -OSI Certified is a certification mark of the Open Source Initiative. - -Copyright (c) 2006, Enthought, Inc. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * Neither the name of Enthought, Inc. nor the names of its contributors may - be used to endorse or promote products derived from this software without - specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -------------------------------------------------------------------------------- - The file - - plot_directive.py - originates from Matplotlib (http://matplotlib.sf.net/) which has - the following license: - -Copyright (c) 2002-2008 John D. Hunter; All Rights Reserved. - -1. This LICENSE AGREEMENT is between John D. Hunter (“JDH”), and the Individual or Organization (“Licensee”) accessing and otherwise using matplotlib software in source or binary form and its associated documentation. - -2. Subject to the terms and conditions of this License Agreement, JDH hereby grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce, analyze, test, perform and/or display publicly, prepare derivative works, distribute, and otherwise use matplotlib 0.98.3 alone or in any derivative version, provided, however, that JDH’s License Agreement and JDH’s notice of copyright, i.e., “Copyright (c) 2002-2008 John D. Hunter; All Rights Reserved” are retained in matplotlib 0.98.3 alone or in any derivative version prepared by Licensee. - -3. In the event Licensee prepares a derivative work that is based on or incorporates matplotlib 0.98.3 or any part thereof, and wants to make the derivative work available to others as provided herein, then Licensee hereby agrees to include in any such work a brief summary of the changes made to matplotlib 0.98.3. - -4. JDH is making matplotlib 0.98.3 available to Licensee on an “AS IS” basis. JDH MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, JDH MAKES NO AND DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF MATPLOTLIB 0.98.3 WILL NOT INFRINGE ANY THIRD PARTY RIGHTS. - -5. JDH SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF MATPLOTLIB 0.98.3 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING MATPLOTLIB 0.98.3, OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. - -6. This License Agreement will automatically terminate upon a material breach of its terms and conditions. - -7. Nothing in this License Agreement shall be deemed to create any relationship of agency, partnership, or joint venture between JDH and Licensee. This License Agreement does not grant permission to use JDH trademarks or trade name in a trademark sense to endorse or promote products or services of Licensee, or any third party. - -8. By copying, installing or otherwise using matplotlib 0.98.3, Licensee agrees to be bound by the terms and conditions of this License Agreement. - diff --git a/doc/sphinxext/MANIFEST.in b/doc/sphinxext/MANIFEST.in deleted file mode 100644 index f88ed785..00000000 --- a/doc/sphinxext/MANIFEST.in +++ /dev/null @@ -1,2 +0,0 @@ -recursive-include tests *.py -include *.txt diff --git a/doc/sphinxext/README.txt b/doc/sphinxext/README.txt deleted file mode 100644 index 6ba63e6d..00000000 --- a/doc/sphinxext/README.txt +++ /dev/null @@ -1,45 +0,0 @@ -===================================== -numpydoc -- Numpy's Sphinx extensions -===================================== - -Numpy's documentation uses several custom extensions to Sphinx. These -are shipped in this ``numpydoc`` package, in case you want to make use -of them in third-party projects. - -The following extensions are available: - - - ``numpydoc``: support for the Numpy docstring format in Sphinx, and add - the code description directives ``np:function``, ``np-c:function``, etc. - that support the Numpy docstring syntax. - - - ``numpydoc.traitsdoc``: For gathering documentation about Traits attributes. - - - ``numpydoc.plot_directive``: Adaptation of Matplotlib's ``plot::`` - directive. Note that this implementation may still undergo severe - changes or eventually be deprecated. - - -numpydoc -======== - -Numpydoc inserts a hook into Sphinx's autodoc that converts docstrings -following the Numpy/Scipy format to a form palatable to Sphinx. - -Options -------- - -The following options can be set in conf.py: - -- numpydoc_use_plots: bool - - Whether to produce ``plot::`` directives for Examples sections that - contain ``import matplotlib``. - -- numpydoc_show_class_members: bool - - Whether to show all members of a class in the Methods and Attributes - sections automatically. - -- numpydoc_edit_link: bool (DEPRECATED -- edit your HTML template instead) - - Whether to insert an edit link after docstrings. diff --git a/doc/sphinxext/__init__.py b/doc/sphinxext/__init__.py deleted file mode 100644 index 68dbbb00..00000000 --- a/doc/sphinxext/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from .numpydoc import setup diff --git a/doc/sphinxext/docscrape.py b/doc/sphinxext/docscrape.py deleted file mode 100644 index 2b14e0d8..00000000 --- a/doc/sphinxext/docscrape.py +++ /dev/null @@ -1,506 +0,0 @@ -"""Extract reference documentation from the NumPy source tree. - -""" - -import inspect -import textwrap -import re -import pydoc -from io import StringIO -from warnings import warn -import collections - -class Reader(object): - """A line-based string reader. - - """ - def __init__(self, data): - """ - Parameters - ---------- - data : str - String with lines separated by '\n'. - - """ - if isinstance(data,list): - self._str = data - else: - self._str = data.split('\n') # store string as list of lines - - self.reset() - - def __getitem__(self, n): - return self._str[n] - - def reset(self): - self._l = 0 # current line nr - - def read(self): - if not self.eof(): - out = self[self._l] - self._l += 1 - return out - else: - return '' - - def seek_next_non_empty_line(self): - for l in self[self._l:]: - if l.strip(): - break - else: - self._l += 1 - - def eof(self): - return self._l >= len(self._str) - - def read_to_condition(self, condition_func): - start = self._l - for line in self[start:]: - if condition_func(line): - return self[start:self._l] - self._l += 1 - if self.eof(): - 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) - - def read_to_next_unindented_line(self): - 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): - if self._l + n < len(self._str): - return self[self._l + n] - else: - return '' - - def is_empty(self): - return not ''.join(self._str).strip() - - -class NumpyDocString(object): - def __init__(self, docstring, config={}): - docstring = textwrap.dedent(docstring).split('\n') - - self._doc = Reader(docstring) - self._parsed_data = { - 'Signature': '', - 'Summary': [''], - 'Extended Summary': [], - 'Parameters': [], - 'Returns': [], - 'Raises': [], - 'Warns': [], - 'Other Parameters': [], - 'Attributes': [], - 'Methods': [], - 'See Also': [], - 'Notes': [], - 'Warnings': [], - 'References': '', - 'Examples': '', - 'index': {} - } - - self._parse() - - def __getitem__(self,key): - return self._parsed_data[key] - - def __setitem__(self,key,val): - if key not in self._parsed_data: - warn("Unknown section %s" % key) - else: - self._parsed_data[key] = val - - def _is_at_section(self): - self._doc.seek_next_non_empty_line() - - if self._doc.eof(): - return False - - l1 = self._doc.peek().strip() # e.g. Parameters - - if l1.startswith('.. index::'): - return True - - l2 = self._doc.peek(1).strip() # ---------- or ========== - return l2.startswith('-'*len(l1)) or l2.startswith('='*len(l1)) - - def _strip(self,doc): - i = 0 - j = 0 - for i,line in enumerate(doc): - if line.strip(): break - - for j,line in enumerate(doc[::-1]): - if line.strip(): break - - 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 - section += [''] - - section += self._doc.read_to_next_empty_line() - - return section - - def _read_sections(self): - while not self._doc.eof(): - data = self._read_to_next_section() - name = data[0].strip() - - 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): - r = Reader(content) - params = [] - while not r.eof(): - header = r.read().strip() - if ' : ' in header: - arg_name, arg_type = header.split(' : ')[:2] - else: - arg_name, arg_type = header, '' - - desc = r.read_to_next_unindented_line() - desc = dedent_lines(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 - continued text - another_func_name : Descriptive text - func_name1, func_name2, :meth:`func_name`, func_name3 - - """ - items = [] - - def parse_item_name(text): - """Match ':role:`name`' or 'name'""" - m = self._name_rgx.match(text) - if m: - g = m.groups() - if g[1] is None: - return g[3], None - else: - return g[2], g[1] - raise ValueError("%s is not a item name" % text) - - def push_item(name, rest): - if not name: - return - name, role = parse_item_name(name) - items.append((name, list(rest), role)) - del rest[:] - - current_func = None - rest = [] - - for line in content: - if not line.strip(): continue - - m = self._name_rgx.match(line) - if m and line[m.end():].strip().startswith(':'): - push_item(current_func, rest) - current_func, line = line[:m.end()], line[m.end():] - rest = [line.split(':', 1)[1].strip()] - if not rest[0]: - rest = [] - elif not line.startswith(' '): - push_item(current_func, rest) - current_func = None - if ',' in line: - for func in line.split(','): - if func.strip(): - push_item(func, []) - elif line.strip(): - current_func = line - elif current_func is not None: - rest.append(line.strip()) - push_item(current_func, rest) - return items - - def _parse_index(self, section, content): - """ - .. index: default - :refguide: something, else, and more - - """ - def strip_each_in(lst): - return [s.strip() for s in lst] - - out = {} - section = section.split('::') - if len(section) > 1: - out['default'] = strip_each_in(section[1].split(','))[0] - for line in content: - line = line.split(':') - if len(line) > 2: - out[line[1]] = strip_each_in(line[2].split(',')) - return out - - def _parse_summary(self): - """Grab signature (if given) and summary""" - if self._is_at_section(): - return - - summary = self._doc.read_to_next_empty_line() - summary_str = " ".join([s.strip() for s in summary]).strip() - if re.compile('^([\w., ]+=)?\s*[\w\.]+\(.*\)$').match(summary_str): - self['Signature'] = summary_str - if not self._is_at_section(): - self['Summary'] = self._doc.read_to_next_empty_line() - else: - self['Summary'] = summary - - if not self._is_at_section(): - self['Extended Summary'] = self._read_to_next_section() - - def _parse(self): - self._doc.reset() - self._parse_summary() - - for (section,content) in self._read_sections(): - if not section.startswith('..'): - section = ' '.join([s.capitalize() for s in section.split(' ')]) - if section in ('Parameters', 'Returns', 'Raises', 'Warns', - 'Other Parameters', 'Attributes', 'Methods'): - self[section] = self._parse_param_list(content) - elif section.startswith('.. index::'): - self['index'] = self._parse_index(section, content) - elif section == 'See Also': - self['See Also'] = self._parse_see_also(content) - else: - self[section] = content - - # string conversion routines - - def _str_header(self, name, symbol='-'): - return [name, len(name)*symbol] - - def _str_indent(self, doc, indent=4): - out = [] - for line in doc: - out += [' '*indent + line] - return out - - def _str_signature(self): - if self['Signature']: - return [self['Signature'].replace('*','\*')] + [''] - else: - return [''] - - def _str_summary(self): - if self['Summary']: - return self['Summary'] + [''] - else: - return [] - - def _str_extended_summary(self): - if self['Extended Summary']: - return self['Extended Summary'] + [''] - else: - return [] - - def _str_param_list(self, name): - out = [] - if self[name]: - out += self._str_header(name) - for param,param_type,desc in self[name]: - out += ['%s : %s' % (param, param_type)] - out += self._str_indent(desc) - out += [''] - return out - - def _str_section(self, name): - out = [] - if self[name]: - out += self._str_header(name) - out += self[name] - out += [''] - return out - - def _str_see_also(self, func_role): - if not self['See Also']: return [] - out = [] - out += self._str_header("See Also") - last_had_desc = True - for func, desc, role in self['See Also']: - if role: - link = ':%s:`%s`' % (role, func) - elif func_role: - link = ':%s:`%s`' % (func_role, func) - else: - link = "`%s`_" % func - if desc or last_had_desc: - out += [''] - out += [link] - else: - out[-1] += ", %s" % link - if desc: - out += self._str_indent([' '.join(desc)]) - last_had_desc = True - else: - last_had_desc = False - out += [''] - return out - - def _str_index(self): - idx = self['index'] - out = [] - out += ['.. index:: %s' % idx.get('default','')] - for section, references in idx.items(): - if section == 'default': - continue - out += [' :%s: %s' % (section, ', '.join(references))] - return out - - def __str__(self, func_role=''): - out = [] - out += self._str_signature() - out += self._str_summary() - out += self._str_extended_summary() - for param_list in ('Parameters', 'Returns', 'Other Parameters', - 'Raises', 'Warns'): - 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'): - out += self._str_section(s) - for param_list in ('Attributes', 'Methods'): - out += self._str_param_list(param_list) - out += self._str_index() - return '\n'.join(out) - - -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' - - -class FunctionDoc(NumpyDocString): - def __init__(self, func, role='func', doc=None, config={}): - self._f = func - self._role = role # e.g. "func" or "meth" - - if doc is None: - if func is None: - raise ValueError("No function or docstring given") - doc = inspect.getdoc(func) or '' - NumpyDocString.__init__(self, doc) - - if not self['Signature'] and func is not None: - func, func_name = self.get_func() - try: - # try to read signature - argspec = inspect.getargspec(func) - argspec = inspect.formatargspec(*argspec) - argspec = argspec.replace('*','\*') - signature = '%s%s' % (func_name, argspec) - except TypeError as e: - signature = '%s()' % func_name - self['Signature'] = signature - - def get_func(self): - func_name = getattr(self._f, '__name__', self.__class__.__name__) - if inspect.isclass(self._f): - func = getattr(self._f, '__call__', self._f.__init__) - else: - func = self._f - return func, func_name - - def __str__(self): - out = '' - - func, func_name = self.get_func() - signature = self['Signature'].replace('*', '\*') - - roles = {'func': 'function', - '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,''), - func_name) - - out += super(FunctionDoc, self).__str__(func_role=self._role) - return out - - -class ClassDoc(NumpyDocString): - - extra_public_methods = ['__call__'] - - def __init__(self, cls, doc=None, modulename='', func_doc=FunctionDoc, - config={}): - if not inspect.isclass(cls) and cls is not None: - raise ValueError("Expected a class or None, but got %r" % cls) - self._cls = cls - - if modulename and not modulename.endswith('.'): - modulename += '.' - self._mod = modulename - - if doc is None: - if cls is None: - raise ValueError("No class or documentation string given") - doc = pydoc.getdoc(cls) - - NumpyDocString.__init__(self, doc) - - if config.get('show_class_members', True): - if not self['Methods']: - self['Methods'] = [(name, '', '') - for name in sorted(self.methods)] - if not self['Attributes']: - self['Attributes'] = [(name, '', '') - for name in sorted(self.properties)] - - @property - def methods(self): - if self._cls is None: - return [] - return [name for name,func in inspect.getmembers(self._cls) - if ((not name.startswith('_') - or name in self.extra_public_methods) - and isinstance(func, collections.Callable))] - - @property - def properties(self): - if self._cls is None: - return [] - 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 deleted file mode 100644 index ffae9df6..00000000 --- a/doc/sphinxext/docscrape_sphinx.py +++ /dev/null @@ -1,228 +0,0 @@ -import re, inspect, textwrap, pydoc -import sphinx -from .docscrape import NumpyDocString, FunctionDoc, ClassDoc -import collections - -class SphinxDocString(NumpyDocString): - def __init__(self, docstring, config={}): - self.use_plots = config.get('use_plots', False) - NumpyDocString.__init__(self, docstring, config=config) - - # string conversion routines - def _str_header(self, name, symbol='`'): - return ['.. rubric:: ' + name, ''] - - def _str_field_list(self, name): - return [':' + name + ':'] - - def _str_indent(self, doc, indent=4): - out = [] - for line in doc: - out += [' '*indent + line] - return out - - def _str_signature(self): - return [''] - if self['Signature']: - return ['``%s``' % self['Signature']] + [''] - else: - return [''] - - def _str_summary(self): - return self['Summary'] + [''] - - def _str_extended_summary(self): - return self['Extended Summary'] + [''] - - def _str_param_list(self, name): - out = [] - if self[name]: - out += self._str_field_list(name) - out += [''] - 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 += [''] - return out - - @property - def _obj(self): - if hasattr(self, '_cls'): - return self._cls - elif hasattr(self, '_f'): - return self._f - return None - - def _str_member_list(self, name): - """ - Generate a member listing, autosummary:: table where possible, - and a table where not. - - """ - out = [] - if self[name]: - out += ['.. rubric:: %s' % name, ''] - prefix = getattr(self, '_name', '') - - if prefix: - prefix = '~%s.' % prefix - - autosum = [] - others = [] - for param, param_type, desc in self[name]: - param = param.strip() - if not self._obj or hasattr(self._obj, param): - autosum += [" %s%s" % (prefix, param)] - else: - others.append((param, param_type, desc)) - - if autosum: - out += ['.. autosummary::', ' :toctree:', ''] - out += autosum - - 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 - fmt = '%%%ds %%%ds ' % (maxlen_0, maxlen_1) - n_indent = maxlen_0 + maxlen_1 + 4 - out += [hdr] - for param, param_type, desc in others: - out += [fmt % (param.strip(), param_type)] - out += self._str_indent(desc, n_indent) - out += [hdr] - out += [''] - return out - - def _str_section(self, name): - out = [] - if self[name]: - out += self._str_header(name) - out += [''] - content = textwrap.dedent("\n".join(self[name])).split("\n") - out += content - out += [''] - return out - - def _str_see_also(self, func_role): - out = [] - if self['See Also']: - see_also = super(SphinxDocString, self)._str_see_also(func_role) - out = ['.. seealso::', ''] - out += self._str_indent(see_also[2:]) - return out - - def _str_warnings(self): - out = [] - if self['Warnings']: - out = ['.. warning::', ''] - out += self._str_indent(self['Warnings']) - return out - - def _str_index(self): - idx = self['index'] - out = [] - if len(idx) == 0: - return out - - out += ['.. index:: %s' % idx.get('default','')] - for section, references in idx.items(): - if section == 'default': - continue - elif section == 'refguide': - out += [' single: %s' % (', '.join(references))] - else: - out += [' %s: %s' % (section, ','.join(references))] - return out - - def _str_references(self): - out = [] - if self['References']: - out += self._str_header('References') - if isinstance(self['References'], str): - self['References'] = [self['References']] - out.extend(self['References']) - out += [''] - # Latex collects all references to a separate bibliography, - # so we need to insert links to it - if sphinx.__version__ >= "0.6": - out += ['.. only:: latex',''] - else: - out += ['.. latexonly::',''] - items = [] - for line in self['References']: - m = re.match(r'.. \[([a-z0-9._-]+)\]', line, re.I) - if m: - items.append(m.group(1)) - out += [' ' + ", ".join(["[%s]_" % item for item in items]), ''] - return out - - def _str_examples(self): - examples_str = "\n".join(self['Examples']) - - if (self.use_plots and 'import matplotlib' in examples_str - and 'plot::' not in examples_str): - out = [] - out += self._str_header('Examples') - out += ['.. plot::', ''] - out += self._str_indent(self['Examples']) - out += [''] - return out - else: - return self._str_section('Examples') - - def __str__(self, indent=0, func_role="obj"): - out = [] - out += self._str_signature() - out += self._str_index() + [''] - out += self._str_summary() - out += self._str_extended_summary() - for param_list in ('Parameters', 'Returns', 'Other Parameters', - 'Raises', 'Warns'): - out += self._str_param_list(param_list) - out += self._str_warnings() - out += self._str_see_also(func_role) - out += self._str_section('Notes') - out += self._str_references() - out += self._str_examples() - for param_list in ('Attributes', 'Methods'): - out += self._str_member_list(param_list) - 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): - what = 'class' - elif inspect.ismodule(obj): - what = 'module' - elif isinstance(obj, collections.Callable): - what = 'function' - else: - what = 'object' - if what == 'class': - return SphinxClassDoc(obj, func_doc=SphinxFunctionDoc, doc=doc, - config=config) - elif what in ('function', 'method'): - return SphinxFunctionDoc(obj, doc=doc, config=config) - else: - if doc is None: - doc = pydoc.getdoc(obj) - return SphinxObjDoc(obj, doc, config=config) diff --git a/doc/sphinxext/numpydoc.py b/doc/sphinxext/numpydoc.py deleted file mode 100644 index 8c4abe0c..00000000 --- a/doc/sphinxext/numpydoc.py +++ /dev/null @@ -1,170 +0,0 @@ -""" -======== -numpydoc -======== - -Sphinx extension that handles docstrings in the Numpy standard format. [1] - -It will: - -- Convert Parameters etc. sections to field lists. -- Convert See Also section to a See also entry. -- Renumber references. -- Extract the signature from the docstring, if it can't be determined otherwise. - -.. [1] https://github.com/numpy/numpy/blob/master/doc/HOWTO_DOCUMENT.rst.txt - -""" - -import sphinx -import collections - -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 sphinx.util.compat import Directive -import inspect - -def mangle_docstrings(app, what, name, obj, options, lines, - reference_offset=[0]): - - cfg = dict(use_plots=app.config.numpydoc_use_plots, - show_class_members=app.config.numpydoc_show_class_members) - - if what == 'module': - # Strip top title - title_re = re.compile(r'^\s*[#*=]{4,}\n[a-z0-9 -]+\n[#*=]{4,}\s*', - re.I|re.S) - lines[:] = title_re.sub('', "\n".join(lines)).split("\n") - else: - doc = get_doc_object(obj, what, "\n".join(lines), config=cfg) - lines[:] = str(doc).split("\n") - - if app.config.numpydoc_edit_link and hasattr(obj, '__name__') and \ - obj.__name__: - if hasattr(obj, '__module__'): - v = dict(full_name="%s.%s" % (obj.__module__, obj.__name__)) - else: - v = dict(full_name=obj.__name__) - lines += ['', '.. htmlonly::', ''] - lines += [' %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(r'^.. \[([a-z0-9_.-])\]', line, re.I) - if m: - references.append(m.group(1)) - - # start renaming from the longest string, to avoid overwriting parts - references.sort(key=lambda x: -len(x)) - if references: - for i, line in enumerate(lines): - for r in references: - if re.match(r'^\d+$', r): - new_r = "R%d" % (reference_offset[0] + int(r)) - else: - new_r = "%s%d" % (r, reference_offset[0]) - lines[i] = lines[i].replace('[%s]_' % r, - '[%s]_' % new_r) - lines[i] = lines[i].replace('.. [%s]' % r, - '.. [%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__))): - return '', '' - - if not (isinstance(obj, collections.Callable) or hasattr(obj, '__argspec_is_invalid_')): return - if not hasattr(obj, '__doc__'): return - - doc = SphinxDocString(pydoc.getdoc(obj)) - if doc['Signature']: - sig = re.sub("^[^(]*", "", doc['Signature']) - return sig, '' - -def setup(app, get_doc_object_=get_doc_object): - global get_doc_object - get_doc_object = get_doc_object_ - - app.connect('autodoc-process-docstring', mangle_docstrings) - app.connect('autodoc-process-signature', mangle_signature) - app.add_config_value('numpydoc_edit_link', None, False) - app.add_config_value('numpydoc_use_plots', None, False) - app.add_config_value('numpydoc_show_class_members', True, True) - - # Extra mangling domains - app.add_domain(NumpyPythonDomain) - app.add_domain(NumpyCDomain) - -#------------------------------------------------------------------------------ -# Docstring-mangling domains -#------------------------------------------------------------------------------ - -from docutils.statemachine import ViewList -from sphinx.domains.c import CDomain -from sphinx.domains.python import PythonDomain - -class ManglingDomainBase(object): - directive_mangling_map = {} - - def __init__(self, *a, **kw): - super(ManglingDomainBase, self).__init__(*a, **kw) - self.wrap_mangling_directives() - - def wrap_mangling_directives(self): - for name, objtype in list(self.directive_mangling_map.items()): - self.directives[name] = wrap_mangling_directive( - self.directives[name], objtype) - -class NumpyPythonDomain(ManglingDomainBase, PythonDomain): - name = 'np' - directive_mangling_map = { - 'function': 'function', - 'class': 'class', - 'exception': 'class', - 'method': 'function', - 'classmethod': 'function', - 'staticmethod': 'function', - 'attribute': 'attribute', - } - -class NumpyCDomain(ManglingDomainBase, CDomain): - name = 'np-c' - directive_mangling_map = { - 'function': 'function', - 'member': 'attribute', - 'macro': 'function', - 'type': 'class', - 'var': 'object', - } - -def wrap_mangling_directive(base_directive, objtype): - class directive(base_directive): - def run(self): - env = self.state.document.settings.env - - name = None - if self.arguments: - m = re.match(r'^(.*\s+)?(.*?)(\(.*)?', self.arguments[0]) - name = m.group(2).strip() - - if not name: - name = self.arguments[0] - - lines = list(self.content) - mangle_docstrings(env.app, objtype, name, None, None, lines) - self.content = ViewList(lines, self.content.parent) - - return base_directive.run(self) - - return directive - diff --git a/doc/sphinxext/setup.py b/doc/sphinxext/setup.py deleted file mode 100644 index ec6aa384..00000000 --- a/doc/sphinxext/setup.py +++ /dev/null @@ -1,23 +0,0 @@ -from distutils.core import setup - -version = "0.4" - -setup( - name="numpydoc", - packages=["numpydoc"], - package_dir={"numpydoc": "."}, - version=version, - description="Sphinx extension to support docstrings in Numpy format", - # classifiers from http://pypi.python.org/pypi?%3Aaction=list_classifiers - classifiers=["Development Status :: 3 - Alpha", - "Environment :: Plugins", - "License :: OSI Approved :: BSD License", - "Topic :: Documentation"], - keywords="sphinx numpy", - author="Pauli Virtanen and others", - author_email="pav@iki.fi", - url="http://github.com/numpy/numpy/tree/master/doc/sphinxext", - license="BSD", - requires=["sphinx (>= 1.0.1)"], - package_data={'numpydoc': ['tests/test_*.py']}, -) diff --git a/doc/sphinxext/tests/test_docscrape.py b/doc/sphinxext/tests/test_docscrape.py deleted file mode 100644 index 6fab7983..00000000 --- a/doc/sphinxext/tests/test_docscrape.py +++ /dev/null @@ -1,615 +0,0 @@ -# -*- encoding:utf-8 -*- - -import sys, 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 * - -doc_txt = '''\ - numpy.multivariate_normal(mean, cov, shape=None, spam=None) - - Draw values from a multivariate normal distribution with specified - mean and covariance. - - The multivariate normal or Gaussian distribution is a generalisation - of the one-dimensional normal distribution to higher dimensions. - - Parameters - ---------- - mean : (N,) ndarray - Mean of the N-dimensional distribution. - - .. math:: - - (1+2+3)/3 - - cov : (N,N) ndarray - Covariance matrix of the distribution. - shape : tuple of ints - Given a shape of, for example, (m,n,k), m*n*k samples are - generated, and packed in an m-by-n-by-k arrangement. Because - each sample is N-dimensional, the output shape is (m,n,k,N). - - Returns - ------- - out : ndarray - The drawn samples, arranged according to `shape`. If the - shape given is (m,n,...), then the shape of `out` is is - (m,n,...,N). - - In other words, each entry ``out[i,j,...,:]`` is an N-dimensional - value drawn from the distribution. - - Other Parameters - ---------------- - spam : parrot - A parrot off its mortal coil. - - Raises - ------ - RuntimeError - Some error - - Warns - ----- - RuntimeWarning - Some warning - - Warnings - -------- - Certain warnings apply. - - Notes - ----- - - Instead of specifying the full covariance matrix, popular - approximations include: - - - Spherical covariance (`cov` is a multiple of the identity matrix) - - Diagonal covariance (`cov` has non-negative elements only on the diagonal) - - This geometrical property can be seen in two dimensions by plotting - generated data-points: - - >>> mean = [0,0] - >>> cov = [[1,0],[0,100]] # diagonal covariance, points lie on x or y-axis - - >>> x,y = multivariate_normal(mean,cov,5000).T - >>> plt.plot(x,y,'x'); plt.axis('equal'); plt.show() - - Note that the covariance matrix must be symmetric and non-negative - definite. - - References - ---------- - .. [1] A. Papoulis, "Probability, Random Variables, and Stochastic - Processes," 3rd ed., McGraw-Hill Companies, 1991 - .. [2] R.O. Duda, P.E. Hart, and D.G. Stork, "Pattern Classification," - 2nd ed., Wiley, 2001. - - See Also - -------- - some, other, funcs - otherfunc : relationship - - Examples - -------- - >>> mean = (1,2) - >>> cov = [[1,0],[1,0]] - >>> x = multivariate_normal(mean,cov,(3,3)) - >>> print x.shape - (3, 3, 2) - - The following is probably true, given that 0.6 is roughly twice the - standard deviation: - - >>> print list( (x[0,0,:] - mean) < 0.6 ) - [True, True] - - .. index:: random - :refguide: random;distributions, random;gauss - - ''' -doc = NumpyDocString(doc_txt) - - -def test_signature(): - assert doc['Signature'].startswith('numpy.multivariate_normal(') - assert doc['Signature'].endswith('spam=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']) - - 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_other_parameters(): - assert_equal(len(doc['Other Parameters']), 1) - assert_equal([n for n,_,_ in doc['Other Parameters']], ['spam']) - arg, arg_type, desc = doc['Other Parameters'][0] - assert_equal(arg_type, 'parrot') - assert desc[0].startswith('A parrot off its mortal coil') - -def test_returns(): - assert_equal(len(doc['Returns']), 1) - arg, arg_type, desc = doc['Returns'][0] - assert_equal(arg, 'out') - assert_equal(arg_type, 'ndarray') - 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'] - assert_equal(len(doc['index']), 2) - assert_equal(len(doc['index']['refguide']), 2) - -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): - if not line == b[n]: - raise AssertionError("Lines %s of a and b differ: " - "\n>>> %s\n<<< %s\n" % - (n,line,b[n])) -def test_str(): - non_blank_line_by_line_compare(str(doc), -"""numpy.multivariate_normal(mean, cov, shape=None, spam=None) - -Draw values from a multivariate normal distribution with specified -mean and covariance. - -The multivariate normal or Gaussian distribution is a generalisation -of the one-dimensional normal distribution to higher dimensions. - -Parameters ----------- -mean : (N,) ndarray - Mean of the N-dimensional distribution. - - .. math:: - - (1+2+3)/3 - -cov : (N,N) ndarray - Covariance matrix of the distribution. -shape : tuple of ints - Given a shape of, for example, (m,n,k), m*n*k samples are - generated, and packed in an m-by-n-by-k arrangement. Because - each sample is N-dimensional, the output shape is (m,n,k,N). - -Returns -------- -out : ndarray - The drawn samples, arranged according to `shape`. If the - shape given is (m,n,...), then the shape of `out` is is - (m,n,...,N). - - In other words, each entry ``out[i,j,...,:]`` is an N-dimensional - value drawn from the distribution. - -Other Parameters ----------------- -spam : parrot - A parrot off its mortal coil. - -Raises ------- -RuntimeError : - Some error - -Warns ------ -RuntimeWarning : - Some warning - -Warnings --------- -Certain warnings apply. - -See Also --------- -`some`_, `other`_, `funcs`_ - -`otherfunc`_ - relationship - -Notes ------ -Instead of specifying the full covariance matrix, popular -approximations include: - - - Spherical covariance (`cov` is a multiple of the identity matrix) - - Diagonal covariance (`cov` has non-negative elements only on the diagonal) - -This geometrical property can be seen in two dimensions by plotting -generated data-points: - ->>> mean = [0,0] ->>> cov = [[1,0],[0,100]] # diagonal covariance, points lie on x or y-axis - ->>> x,y = multivariate_normal(mean,cov,5000).T ->>> plt.plot(x,y,'x'); plt.axis('equal'); plt.show() - -Note that the covariance matrix must be symmetric and non-negative -definite. - -References ----------- -.. [1] A. Papoulis, "Probability, Random Variables, and Stochastic - Processes," 3rd ed., McGraw-Hill Companies, 1991 -.. [2] R.O. Duda, P.E. Hart, and D.G. Stork, "Pattern Classification," - 2nd ed., Wiley, 2001. - -Examples --------- ->>> mean = (1,2) ->>> cov = [[1,0],[1,0]] ->>> x = multivariate_normal(mean,cov,(3,3)) ->>> print x.shape -(3, 3, 2) - -The following is probably true, given that 0.6 is roughly twice the -standard deviation: - ->>> print list( (x[0,0,:] - mean) < 0.6 ) -[True, True] - -.. index:: random - :refguide: random;distributions, random;gauss""") - - -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 - -Draw values from a multivariate normal distribution with specified -mean and covariance. - -The multivariate normal or Gaussian distribution is a generalisation -of the one-dimensional normal distribution to higher dimensions. - -:Parameters: - - **mean** : (N,) ndarray - - Mean of the N-dimensional distribution. - - .. math:: - - (1+2+3)/3 - - **cov** : (N,N) ndarray - - Covariance matrix of the distribution. - - **shape** : tuple of ints - - Given a shape of, for example, (m,n,k), m*n*k samples are - generated, and packed in an m-by-n-by-k arrangement. Because - each sample is N-dimensional, the output shape is (m,n,k,N). - -:Returns: - - **out** : ndarray - - The drawn samples, arranged according to `shape`. If the - shape given is (m,n,...), then the shape of `out` is is - (m,n,...,N). - - In other words, each entry ``out[i,j,...,:]`` is an N-dimensional - value drawn from the distribution. - -:Other Parameters: - - **spam** : parrot - - A parrot off its mortal coil. - -:Raises: - - **RuntimeError** : - - Some error - -:Warns: - - **RuntimeWarning** : - - Some warning - -.. warning:: - - Certain warnings apply. - -.. seealso:: - - :obj:`some`, :obj:`other`, :obj:`funcs` - - :obj:`otherfunc` - relationship - -.. rubric:: Notes - -Instead of specifying the full covariance matrix, popular -approximations include: - - - Spherical covariance (`cov` is a multiple of the identity matrix) - - Diagonal covariance (`cov` has non-negative elements only on the diagonal) - -This geometrical property can be seen in two dimensions by plotting -generated data-points: - ->>> mean = [0,0] ->>> cov = [[1,0],[0,100]] # diagonal covariance, points lie on x or y-axis - ->>> x,y = multivariate_normal(mean,cov,5000).T ->>> plt.plot(x,y,'x'); plt.axis('equal'); plt.show() - -Note that the covariance matrix must be symmetric and non-negative -definite. - -.. rubric:: References - -.. [1] A. Papoulis, "Probability, Random Variables, and Stochastic - Processes," 3rd ed., McGraw-Hill Companies, 1991 -.. [2] R.O. Duda, P.E. Hart, and D.G. Stork, "Pattern Classification," - 2nd ed., Wiley, 2001. - -.. only:: latex - - [1]_, [2]_ - -.. rubric:: Examples - ->>> mean = (1,2) ->>> cov = [[1,0],[1,0]] ->>> x = multivariate_normal(mean,cov,(3,3)) ->>> print x.shape -(3, 3, 2) - -The following is probably true, given that 0.6 is roughly twice the -standard deviation: - ->>> print list( (x[0,0,:] - mean) < 0.6 ) -[True, True] -""") - - -doc2 = NumpyDocString(""" - Returns array of indices of the maximum values of along the given axis. - - Parameters - ---------- - a : {array_like} - Array to look in. - axis : {None, integer} - 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) - -doc3 = NumpyDocString(""" - my_signature(*params, **kwds) - - Return this and that. - """) - -def test_escape_stars(): - signature = str(doc3).split('\n')[0] - assert_equal(signature, 'my_signature(\*params, \*\*kwds)') - -doc4 = NumpyDocString( - """a.conj() - - Return an array with all complex-valued elements conjugated.""") - -def test_empty_extended_summary(): - assert_equal(doc4['Extended Summary'], []) - -doc5 = NumpyDocString( - """ - a.something() - - Raises - ------ - LinAlgException - If array is singular. - - Warns - ----- - SomeWarning - If needed - """) - -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.']) - -def test_warns(): - assert_equal(len(doc5['Warns']), 1) - name,_,desc = doc5['Warns'][0] - assert_equal(name,'SomeWarning') - assert_equal(desc,['If needed']) - -def test_see_also(): - doc6 = NumpyDocString( - """ - z(x,theta) - - See Also - -------- - func_a, func_b, func_c - func_d : some equivalent func - foo.func_e : some other func over - multiple lines - func_f, func_g, :meth:`func_h`, func_j, - func_k - :obj:`baz.obj_q` - :class:`class_j`: fubar - foobar - """) - - assert len(doc6['See Also']) == 12 - for func, desc, role in doc6['See Also']: - if func in ('func_a', 'func_b', 'func_c', 'func_f', - 'func_g', 'func_h', 'func_j', 'func_k', 'baz.obj_q'): - assert(not desc) - else: - assert(desc) - - if func == 'func_h': - assert role == 'meth' - elif func == 'baz.obj_q': - assert role == 'obj' - elif func == 'class_j': - assert role == 'class' - else: - assert role is None - - if func == 'func_d': - assert desc == ['some equivalent func'] - elif func == 'foo.func_e': - assert desc == ['some other func over', 'multiple lines'] - elif func == 'class_j': - assert desc == ['fubar', 'foobar'] - -def test_see_also_print(): - class Dummy(object): - """ - See Also - -------- - func_a, func_b - func_c : some relationship - goes here - func_d - """ - pass - - obj = Dummy() - s = str(FunctionDoc(obj, role='func')) - assert(':func:`func_a`, :func:`func_b`' in s) - assert(' some relationship' in s) - assert(':func:`func_d`' in s) - -doc7 = NumpyDocString(""" - - Doc starts on second line. - - """) - -def test_empty_first_line(): - assert doc7['Summary'][0].startswith('Doc starts') - - -def test_no_summary(): - str(SphinxDocString(""" - Parameters - ----------""")) - - -def test_unicode(): - doc = SphinxDocString(""" - öäöäöäöäöåååå - - öäöäöäööäååå - - Parameters - ---------- - ååå : äää - ööö - - Returns - ------- - ååå : ööö - äää - - """) - assert doc['Summary'][0] == u'öäöäöäöäöåååå'.encode('utf-8') - -def test_plot_examples(): - cfg = dict(use_plots=True) - - doc = SphinxDocString(""" - Examples - -------- - >>> import matplotlib.pyplot as plt - >>> plt.plot([1,2,3],[4,5,6]) - >>> plt.show() - """, config=cfg) - assert 'plot::' in str(doc), str(doc) - - doc = SphinxDocString(""" - Examples - -------- - .. plot:: - - import matplotlib.pyplot as plt - plt.plot([1,2,3],[4,5,6]) - plt.show() - """, 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 - - for cls in (ClassDoc, SphinxClassDoc): - doc = cls(Dummy, config=dict(show_class_members=False)) - assert 'Methods' not in str(doc), (cls, str(doc)) - assert 'spam' not in str(doc), (cls, str(doc)) - assert 'ham' not in str(doc), (cls, str(doc)) - - doc = cls(Dummy, config=dict(show_class_members=True)) - assert 'Methods' in str(doc), (cls, str(doc)) - assert 'spam' in str(doc), (cls, str(doc)) - assert 'ham' in str(doc), (cls, str(doc)) - - if cls is SphinxClassDoc: - assert '.. autosummary::' in str(doc), str(doc) - -if __name__ == "__main__": - import nose - nose.run() - -- GitLab