diff options
70 files changed, 1436 insertions, 1594 deletions
diff --git a/DEV_README.txt b/DEV_README.txt index ae9b59fb6..65f84994c 100644 --- a/DEV_README.txt +++ b/DEV_README.txt @@ -3,7 +3,7 @@ available. We have a few simple rules: - * try hard to keep the SVN repository in a buildable state and to not + * try hard to keep the Git repository in a buildable state and to not indiscriminately muck with what others have contributed. * Simple changes (including bug fixes) and obvious improvements are @@ -14,6 +14,6 @@ We have a few simple rules: * Please add meaningful comments when you check changes in. These comments form the basis of the change-log. - * Add unit tests to excercise new code, and regression tests + * Add unit tests to exercise new code, and regression tests whenever you fix a bug. diff --git a/doc/HOWTO_BUILD_DOCS.txt b/doc/HOWTO_BUILD_DOCS.txt index 8c1722712..3b677263b 100644 --- a/doc/HOWTO_BUILD_DOCS.txt +++ b/doc/HOWTO_BUILD_DOCS.txt @@ -3,9 +3,7 @@ Building the NumPy API and reference docs ========================================= We currently use Sphinx_ for generating the API and reference -documentation for Numpy. You will need Sphinx 0.5 or newer. Sphinx's -current development version also works as of now (2009-06-24), and -using it is recommended though not required. +documentation for Numpy. You will need Sphinx 1.0.1 or newer. If you only want to get the documentation, note that pre-built versions can be found at diff --git a/doc/HOWTO_DOCUMENT.txt b/doc/HOWTO_DOCUMENT.txt index 8d00ab7d2..bbd9531e8 100644 --- a/doc/HOWTO_DOCUMENT.txt +++ b/doc/HOWTO_DOCUMENT.txt @@ -333,6 +333,13 @@ The sections of the docstring are: >>> np.add([1, 2], [3, 4]) array([4, 6]) + For tests with a result that is random or platform-dependent, mark the + output as such:: + + >>> import numpy.random + >>> np.random.rand(2) + array([ 0.35773152, 0.38568979]) #random + You can run examples using:: >>> np.test(doctests=True) diff --git a/doc/Makefile b/doc/Makefile index 5058fbc42..03b327079 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -11,15 +11,13 @@ PAPER = FILES= -NEED_AUTOSUMMARY = $(shell $(PYTHON) -c 'import sphinx; print sphinx.__version__ < "0.7" and "1" or ""') - # Internal variables. PAPEROPT_a4 = -D latex_paper_size=a4 PAPEROPT_letter = -D latex_paper_size=letter ALLSPHINXOPTS = -d build/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source .PHONY: help clean html web pickle htmlhelp latex changes linkcheck \ - dist dist-build + dist dist-build gitwash-update #------------------------------------------------------------------------------ @@ -33,10 +31,18 @@ help: @echo " linkcheck to check all external links for integrity" @echo " dist PYVER=... to make a distribution-ready tree" @echo " upload USER=... to upload results to docs.scipy.org" + @echo " gitwash-update GITWASH=path/to/gitwash update gitwash developer docs" clean: -rm -rf build/* source/reference/generated +gitwash-update: + rm -rf source/dev/gitwash + install -d source/dev/gitwash + python $(GITWASH)/gitwash_dumper.py source/dev NumPy \ + --repo-name=numpy \ + --github-user=numpy + cat source/dev/gitwash_links.txt >> source/dev/gitwash/git_links.inc #------------------------------------------------------------------------------ # Automated generation of all documents @@ -99,11 +105,6 @@ dist-build: generate: build/generate-stamp build/generate-stamp: $(wildcard source/reference/*.rst) mkdir -p build -ifeq ($(NEED_AUTOSUMMARY),1) - $(PYTHON) \ - ./sphinxext/autosummary_generate.py source/reference/*.rst \ - -p dump.xml -o source/reference/generated -endif touch build/generate-stamp html: generate diff --git a/doc/TESTS.txt b/doc/TESTS.txt index e1d39079a..c0b866054 100644 --- a/doc/TESTS.txt +++ b/doc/TESTS.txt @@ -41,7 +41,6 @@ follows:: >>> import numpy >>> numpy.test() - The test method may take two or more arguments; the first is a string label specifying what should be tested and the second is an integer giving the level of output verbosity. See the docstring for numpy.test @@ -86,25 +85,27 @@ module called ``test_yyy.py``. If you only need to test one aspect of ``zzz``, you can simply add a test function:: def test_zzz(): - assert zzz() == 'Hello from zzz' + assert_(zzz() == 'Hello from zzz') More often, we need to group a number of tests together, so we create a test class:: - from numpy.testing import * + from numpy.testing import assert_, assert_raises # import xxx symbols from scipy.xxx.yyy import zzz class TestZzz: def test_simple(self): - assert zzz() == 'Hello from zzz' + assert_(zzz() == 'Hello from zzz') def test_invalid_parameter(self): assert_raises(...) -Within these test methods, ``assert()`` is used to test whether a -certain assumption is valid. If the assert fails, the test fails. +Within these test methods, ``assert_()`` and related functions are used to test +whether a certain assumption is valid. If the assertion fails, the test fails. +Note that the Python builtin ``assert`` should not be used, because it is +stripped during compilation with ``-O``. Sometimes it is convenient to run ``test_yyy.py`` by itself, so we add @@ -124,7 +125,7 @@ therefore reserved for a full ``scipy.test(label='full')`` run, you can label it with a nose decorator:: # numpy.testing module includes 'import decorators as dec' - from numpy.testing import * + from numpy.testing import dec, assert_ @dec.slow def test_big(self): @@ -135,7 +136,7 @@ Similarly for methods:: class test_zzz: @dec.slow def test_simple(self): - assert zzz() == 'Hello from zzz' + assert_(zzz() == 'Hello from zzz') Easier setup and teardown functions / methods --------------------------------------------- @@ -156,7 +157,9 @@ You can add setup and teardown functions to functions and methods with nose decorators:: import nose - from numpy.testing import * + # import all functions from numpy.testing that are needed + from numpy.testing import assert_, assert_array_almost_equal + def setup_func(): """A trivial setup function.""" global helpful_variable @@ -185,7 +188,7 @@ with test generators:: def check_even(n, nn): """A check function to be used in a test generator.""" - assert n % 2 == 0 or nn % 2 == 0 + assert_(n % 2 == 0 or nn % 2 == 0) def test_evens(): for i in range(0,4,2): @@ -306,13 +309,13 @@ from one in `numpy/linalg/tests/test_linalg.py def do(self, a, b): x = linalg.solve(a, b) assert_almost_equal(b, dot(a, x)) - assert imply(isinstance(b, matrix), isinstance(x, matrix)) + assert_(imply(isinstance(b, matrix), isinstance(x, matrix))) class TestInv(LinalgTestCase): def do(self, a, b): a_inv = linalg.inv(a) assert_almost_equal(dot(a, a_inv), identity(asarray(a).shape[0])) - assert imply(isinstance(a, matrix), isinstance(a_inv, matrix)) + assert_(imply(isinstance(a, matrix), isinstance(a_inv, matrix))) In this case, we wanted to test solving a linear algebra problem using matrices of several data types, using ``linalg.solve`` and @@ -329,7 +332,7 @@ The decorators from numpy.testing.dec can be used to do this. To skip a test, simply use ``skipif``:: - from numpy.testing import * + from numpy.testing import dec @dec.skipif(SkipMyTest, "Skipping this test because...") def test_something(foo): @@ -340,7 +343,7 @@ and the message in verbose test output is the second argument given to ``skipif``. Similarly, a test can be marked as a known failure by using ``knownfailureif``:: - from numpy.testing import * + from numpy.testing import dec @dec.knownfailureif(MyTestFails, "This test is known to fail because...") def test_something_else(foo): diff --git a/doc/numpy.scipy.org/Makefile b/doc/numpy.scipy.org/Makefile deleted file mode 100644 index 1d42a61c4..000000000 --- a/doc/numpy.scipy.org/Makefile +++ /dev/null @@ -1,112 +0,0 @@ -# Makefile for Sphinx documentation -# - -# You can set these variables from the command line. -SPHINXOPTS = -SPHINXBUILD = sphinx-build -PAPER = - -# Internal variables. -PAPEROPT_a4 = -D latex_paper_size=a4 -PAPEROPT_letter = -D latex_paper_size=letter -ALLSPHINXOPTS = -d _build/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . - -.PHONY: help clean html dirhtml pickle json htmlhelp qthelp latex changes linkcheck doctest - -help: - @echo "Please use \`make <target>' where <target> is one of" - @echo " upload USER=... to upload to numpy.scipy.org" - @echo " html to make standalone HTML files" - @echo " dirhtml to make HTML files named index.html in directories" - @echo " pickle to make pickle files" - @echo " json to make JSON files" - @echo " htmlhelp to make HTML files and a HTML help project" - @echo " qthelp to make HTML files and a qthelp project" - @echo " devhelp to make HTML files and a Devhelp project" - @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" - @echo " latexpdf to make LaTeX files and run them through pdflatex" - @echo " changes to make an overview of all changed/added/deprecated items" - @echo " linkcheck to check all external links for integrity" - @echo " doctest to run all doctests embedded in the documentation (if enabled)" - -clean: - -rm -rf _build/* - -upload: html - chmod ug=rwX,o=rX -R _build/html - rsync -r -z --delete-after -p \ - _build/html/ \ - $(USER)@new.scipy.org:/srv/www/numpy/ - -html: - $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) _build/html - @echo - @echo "Build finished. The HTML pages are in _build/html." - -dirhtml: - $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) _build/dirhtml - @echo - @echo "Build finished. The HTML pages are in _build/dirhtml." - -pickle: - $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) _build/pickle - @echo - @echo "Build finished; now you can process the pickle files." - -json: - $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) _build/json - @echo - @echo "Build finished; now you can process the JSON files." - -htmlhelp: - $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) _build/htmlhelp - @echo - @echo "Build finished; now you can run HTML Help Workshop with the" \ - ".hhp project file in _build/htmlhelp." - -qthelp: - $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) _build/qthelp - @echo - @echo "Build finished; now you can run "qcollectiongenerator" with the" \ - ".qhcp project file in _build/qthelp, like this:" - @echo "# qcollectiongenerator _build/qthelp/Numpy.qhcp" - @echo "To view the help file:" - @echo "# assistant -collectionFile _build/qthelp/Numpy.qhc" - -devhelp: - $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) _build/devhelp - @echo - @echo "Build finished." - @echo "To view the help file:" - @echo "# mkdir -p $$HOME/.local/share/devhelp/Numpy" - @echo "# ln -s _build/devhelp $$HOME/.local/share/devhelp/Numpy" - @echo "# devhelp" - -latex: - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) _build/latex - @echo - @echo "Build finished; the LaTeX files are in _build/latex." - @echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \ - "run these through (pdf)latex." - -latexpdf: latex - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) _build/latex - @echo "Running LaTeX files through pdflatex..." - make -C _build/latex all-pdf - @echo "pdflatex finished; the PDF files are in _build/latex." - -changes: - $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) _build/changes - @echo - @echo "The overview file is in _build/changes." - -linkcheck: - $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) _build/linkcheck - @echo - @echo "Link check complete; look for any errors in the above output " \ - "or in _build/linkcheck/output.txt." - -doctest: - $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) _build/doctest - @echo "Testing of doctests in the sources finished, look at the " \ - "results in _build/doctest/output.txt." diff --git a/doc/numpy.scipy.org/_theme/scipy/index.html b/doc/numpy.scipy.org/_theme/scipy/index.html deleted file mode 100644 index 1a71ea1ab..000000000 --- a/doc/numpy.scipy.org/_theme/scipy/index.html +++ /dev/null @@ -1,79 +0,0 @@ -{% extends "!layout.html" %} -{% set title = 'Scientific Computing Tools For Python' %} - -{% block body %} - -<table> - - <tr> - <td style="border-style: none;"> - <a href="http://new.scipy.org/download.html"> - <img alt="Download" src="_static/images/download.png" title="Download" height="80" style="display: block; margin-left: auto; margin-right: auto;"/></a> </td> - <td style="border: medium none ;"> - <a href="http://new.scipy.org/getting-started.html"> - <img alt="Getting Started" src="_static/images/tutorial.png" title="Getting Started" height="80" style="display: block; margin-left: auto; margin-right: auto;"/></a> </td> - <td style="border: medium none ;"> - <a href="http://docs.scipy.org"> - <img alt="Documentation" src="_static/images/documentation.png" title="Documentation" height="80" style="display: block; margin-left: auto; margin-right: auto;"/></a> </td> - <td style="border: medium none ;"> - <a href="http://new.scipy.org/bug-report.html"> - <img alt="Bug Report" src="_static/images/bugs.png" title="Bug Report" height="80" style="display: block; margin-left: auto; margin-right: auto;"/></a> </td> - <td style="border: medium none ;"> - <a href="http://planet.scipy.org"> - <img alt="Blog" src="_static/images/feed-icon.png" title="Blog" height="80" style="display: block; margin-left: auto; margin-right: auto;"/></a> </td> - </tr> - - <tr> - <td style="border: medium none; text-align: center;"><strong><small><a href="http://new.scipy.org/download.html">Download</a></small></strong></td> - <td style="border: medium none; text-align: center;"><strong><small><a href="http://new.scipy.org/getting-started.html">Getting Started</a></small></strong></td> - <td style="border: medium none; text-align: center;"><strong><small><a href="http://docs.scipy.org">Documentation</a></small></strong></td> - <td style="border: medium none; text-align: center;"><strong><small><a href="http://new.scipy.org/bug-report.html">Report Bugs</a></small></strong></td> - <td style="border: medium none; text-align: center;"><strong><small><a href="http://planet.scipy.org">Read the Blog</a></small></strong></td> - </tr> - -</table> - - - <p>NumPy is the fundamental package needed for scientific computing with Python. - It contains among other things:</p> - <ul class="simple"> - <li>a powerful N-dimensional array object</li> - <li>sophisticated (broadcasting) functions</li> - <li>tools for integrating C/C++ and Fortran code</li> - <li>useful linear algebra, Fourier transform, and random number capabilities.</li> - </ul> - <p>Besides its obvious scientific uses, NumPy can also be used as an efficient - multi-dimensional container of generic data. Arbitrary data-types can be - defined. This allows NumPy to seamlessly and speedily integrate with a wide - variety of databases.</p> - <p>Numpy is licensed under the <a class="reference external" href="license.html">BSD license</a>, - enabling reuse with few restrictions.</p> - - <div class="section" id="getting-started"> - <h1>Getting Started<a class="headerlink" href="#getting-started" title="Permalink to this headline">¶</a></h1> - <ul class="simple"> - <li><a class="reference external" href="http://www.scipy.org/Download">Getting Numpy</a></li> - <li><a class="reference external" href="http://www.scipy.org/Installing_SciPy">Installing NumPy and SciPy</a></li> - <li><a class="reference external" href="http://docs.scipy.org/doc/">NumPy and SciPy documentation page</a></li> - <li><a class="reference external" href="http://www.scipy.org/Tentative_NumPy_Tutorial">NumPy Tutorial</a></li> - <li><a class="reference external" href="http://www.scipy.org/NumPy_for_Matlab_Users">NumPy for MATLAB© Users</a></li> - <li><a class="reference external" href="http://www.scipy.org/Numpy_Functions_by_Category">NumPy functions by category</a></li> - <li><a class="reference external" href="http://www.scipy.org/Mailing_Lists">NumPy Mailing List</a></li> - </ul> - </div> - - <div class="section" id="more-information"> - <h1>More Information<a class="headerlink" href="#more-information" title="Permalink to this headline">¶</a></h1> - <ul class="simple"> - <li><a class="reference external" href="http://sourceforge.net/projects/numpy/">NumPy Sourceforge Home Page</a></li> - <li><a class="reference external" href="http://www.scipy.org/">SciPy Home Page</a></li> - <li><a class="reference external" href="http://www.scipy.org/Topical_Software#head-7153b42ac4ea517c7d99ec4f4453555b2302a1f8">Interfacing with compiled code</a></li> - <li><a class="reference external" href="old_array_packages.html"><em>Older python array packages</em></a></li> - </ul> - </div> - -<div style="padding-top: 40px;" align=center> - <script type="text/javascript" src="http://www.ohloh.net/p/4894/widgets/project_partner_badge.js"></script> -</div> - -{% endblock %} diff --git a/doc/numpy.scipy.org/_theme/scipy/layout.html b/doc/numpy.scipy.org/_theme/scipy/layout.html deleted file mode 100644 index 75da3963d..000000000 --- a/doc/numpy.scipy.org/_theme/scipy/layout.html +++ /dev/null @@ -1,16 +0,0 @@ -{% extends "sphinxdoc/layout.html" %} - -{% block rootrellink %} -{% endblock %} - -{% block relbar1 %} -<div class="top-logo-header"> -<a href="{{ pathto('index') }}"><img src="{{ pathto("_static/numpy_logo.png", 1) }}" border="0" alt="NumPy Homepage"/></a> -</div> -{% endblock %} - -{% block relbar2 %} {% endblock %} - -{# put the sidebar before the body #} -{% block sidebar1 %}{% endblock %} -{% block sidebar2 %}{% endblock %} diff --git a/doc/numpy.scipy.org/_theme/scipy/static/favicon.ico b/doc/numpy.scipy.org/_theme/scipy/static/favicon.ico Binary files differdeleted file mode 100644 index d7ae6012a..000000000 --- a/doc/numpy.scipy.org/_theme/scipy/static/favicon.ico +++ /dev/null diff --git a/doc/numpy.scipy.org/_theme/scipy/static/images/bugs.png b/doc/numpy.scipy.org/_theme/scipy/static/images/bugs.png Binary files differdeleted file mode 100644 index 68810148a..000000000 --- a/doc/numpy.scipy.org/_theme/scipy/static/images/bugs.png +++ /dev/null diff --git a/doc/numpy.scipy.org/_theme/scipy/static/images/documentation.png b/doc/numpy.scipy.org/_theme/scipy/static/images/documentation.png Binary files differdeleted file mode 100644 index 7f9a03856..000000000 --- a/doc/numpy.scipy.org/_theme/scipy/static/images/documentation.png +++ /dev/null diff --git a/doc/numpy.scipy.org/_theme/scipy/static/images/download.png b/doc/numpy.scipy.org/_theme/scipy/static/images/download.png Binary files differdeleted file mode 100644 index a50baf8a2..000000000 --- a/doc/numpy.scipy.org/_theme/scipy/static/images/download.png +++ /dev/null diff --git a/doc/numpy.scipy.org/_theme/scipy/static/images/feed-icon.png b/doc/numpy.scipy.org/_theme/scipy/static/images/feed-icon.png Binary files differdeleted file mode 100644 index a1a5d7ef5..000000000 --- a/doc/numpy.scipy.org/_theme/scipy/static/images/feed-icon.png +++ /dev/null diff --git a/doc/numpy.scipy.org/_theme/scipy/static/images/tutorial.png b/doc/numpy.scipy.org/_theme/scipy/static/images/tutorial.png Binary files differdeleted file mode 100644 index 23995e73a..000000000 --- a/doc/numpy.scipy.org/_theme/scipy/static/images/tutorial.png +++ /dev/null diff --git a/doc/numpy.scipy.org/_theme/scipy/static/logo.gif b/doc/numpy.scipy.org/_theme/scipy/static/logo.gif Binary files differdeleted file mode 100644 index ab2e3ac33..000000000 --- a/doc/numpy.scipy.org/_theme/scipy/static/logo.gif +++ /dev/null diff --git a/doc/numpy.scipy.org/_theme/scipy/static/numpy_logo.png b/doc/numpy.scipy.org/_theme/scipy/static/numpy_logo.png Binary files differdeleted file mode 100644 index 5ed48c094..000000000 --- a/doc/numpy.scipy.org/_theme/scipy/static/numpy_logo.png +++ /dev/null diff --git a/doc/numpy.scipy.org/_theme/scipy/static/scipy.css b/doc/numpy.scipy.org/_theme/scipy/static/scipy.css deleted file mode 100644 index f818c6f14..000000000 --- a/doc/numpy.scipy.org/_theme/scipy/static/scipy.css +++ /dev/null @@ -1,207 +0,0 @@ -@import "sphinxdoc.css"; - -/** - * Spacing fixes - */ - - -div.body { - width: 90%; -} - -div.bodywrapper { - width: 100%; -} - -div.documentwrapper { - border-left: 1px solid #ccc; - border-right: 1px solid #ccc; - border-bottom: 1px solid #ccc; -} - -div.body p, div.body dd, div.body li { - line-height: 125%; -} - -ul.simple { - margin-top: 0; - margin-bottom: 0; - padding-top: 0; - padding-bottom: 0; -} - -/* spacing around blockquoted fields in parameters/attributes/returns */ -td.field-body > blockquote { - margin-top: 0.1em; - margin-bottom: 0.5em; -} - -/* spacing around example code */ -div.highlight > pre { - padding: 2px 5px 2px 5px; -} - -/* spacing in see also definition lists */ -dl.last > dd { - margin-top: 1px; - margin-bottom: 5px; - margin-left: 30px; -} - -/** - * Hide dummy toctrees - */ - -ul { - padding-top: 0; - padding-bottom: 0; - margin-top: 0; - margin-bottom: 0; -} -ul li { - padding-top: 0; - padding-bottom: 0; - margin-top: 0; - margin-bottom: 0; -} -ul li a.reference { - padding-top: 0; - padding-bottom: 0; - margin-top: 0; - margin-bottom: 0; -} - -/** - * Make high-level subsections easier to distinguish from top-level ones - */ -div.body h3 { - background-color: transparent; -} - -div.body h4 { - border: none; - background-color: transparent; -} - -/** - * Scipy colors - */ - -body { - background-color: rgb(100,135,220); - border: none; -} - -div.sphinxsidebar { - display: none; -} - -div.sphinxsidebar h3 { - color: rgb(0,102,204); -} - -div.sphinxsidebar h4 { - color: rgb(0,82,194); -} - -div.sphinxsidebar p { - color: black; -} - -div.sphinxsidebar ul.want-points { - list-style: disc; -} - -.field-list th { - color: rgb(0,102,204); -} - -/** - * Extra admonitions - */ - -div.tip { - background-color: #ffffe4; - border: 1px solid #ee6; -} - -div.plot-output { - clear-after: both; -} - -div.plot-output .figure { - float: left; - text-align: center; - margin-bottom: 0; - padding-bottom: 0; -} - -div.plot-output .caption { - margin-top: 2; - padding-top: 0; -} - -div.plot-output p.admonition-title { - display: none; -} - -div.plot-output:after { - content: ""; - display: block; - height: 0; - clear: both; -} - - -/* -div.admonition-example { - background-color: #e4ffe4; - border: 1px solid #ccc; -}*/ - - -/** - * Styling for field lists - */ - -table.field-list th { - border-left: 1px solid #aaa !important; - padding-left: 5px; -} - -table.field-list { - border-collapse: separate; - border-spacing: 10px; -} - -/** - * Styling for footnotes - */ - -table.footnote td, table.footnote th { - border: none; -} - -/** - * Top header logo and colors - */ -body div.top-logo-header { - text-align: left; - background-color: #a2bae8; - border-bottom: 8px solid #003399; - margin-top: 10px; - border-top: 1px solid #bbb; -} - -/** - * Footer colors - */ -body div.footer { - background-color: #6487dc; - border: none; - color: white; - text-align: center; -} -body div.footer a { - color: white; -} diff --git a/doc/numpy.scipy.org/_theme/scipy/theme.conf b/doc/numpy.scipy.org/_theme/scipy/theme.conf deleted file mode 100644 index e2f5ed848..000000000 --- a/doc/numpy.scipy.org/_theme/scipy/theme.conf +++ /dev/null @@ -1,4 +0,0 @@ -[theme] -inherit = sphinxdoc -stylesheet = scipy.css -pygments_css = friendly diff --git a/doc/numpy.scipy.org/conf.py b/doc/numpy.scipy.org/conf.py deleted file mode 100644 index 2efb286b5..000000000 --- a/doc/numpy.scipy.org/conf.py +++ /dev/null @@ -1,208 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Scipy.org documentation build configuration file -# -# This file is execfile()d with the current directory set to its containing dir. -# -# Note that not all possible configuration values are present in this -# autogenerated file. -# -# All configuration values have a default; values that are commented out -# serve to show the default. - -import sys, os - -# 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 -# documentation root, use os.path.abspath to make it absolute, like shown here. -#sys.path.append(os.path.abspath('.')) - -# -- General configuration ----------------------------------------------------- - -# Add any Sphinx extension module names here, as strings. They can be extensions -# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. -extensions = ['sphinx.ext.intersphinx', 'sphinx.ext.pngmath', - 'sphinx.ext.ifconfig'] - -# Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] - -# The suffix of source filenames. -source_suffix = '.rst' - -# The encoding of source files. -#source_encoding = 'utf-8-sig' - -# The master toctree document. -master_doc = 'content' - -# General information about the project. -project = u'Numpy' -copyright = u'2009 Numpy developers' - -# The version info for the project you're documenting, acts as replacement for -# |version| and |release|, also used in various other places throughout the -# built documents. -# -# The short X.Y version. -version = '' -# The full version, including alpha/beta/rc tags. -release = '' - -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. -#language = None - -# There are two options for replacing |today|: either, you set today to some -# non-false value, then it is used: -#today = '' -# Else, today_fmt is used as the format for a strftime call. -#today_fmt = '%B %d, %Y' - -# List of documents that shouldn't be included in the build. -#unused_docs = [] - -# List of directories, relative to source directory, that shouldn't be searched -# for source files. -exclude_trees = [] - -# The reST default role (used for this markup: `text`) to use for all documents. -#default_role = None - -# If true, '()' will be appended to :func: etc. cross-reference text. -#add_function_parentheses = True - -# If true, the current module name will be prepended to all description -# unit titles (such as .. function::). -#add_module_names = True - -# If true, sectionauthor and moduleauthor directives will be shown in the -# output. They are ignored by default. -#show_authors = False - -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' - -# A list of ignored prefixes for module index sorting. -#modindex_common_prefix = [] - - -# -- Options for HTML output --------------------------------------------------- - -# The theme to use for HTML and HTML Help pages. Major themes that come with -# Sphinx are currently 'default' and 'sphinxdoc'. -html_theme = 'scipy' - -# Theme options are theme-specific and customize the look and feel of a theme -# further. For a list of options available for each theme, see the -# documentation. -#html_theme_options = {} - -# Add any paths that contain custom themes here, relative to this directory. -html_theme_path = ["_theme"] - -# The name for this set of Sphinx documents. If None, it defaults to -# "<project> v<release> documentation". -html_title = "Numpy" - -# A shorter title for the navigation bar. Default is the same as html_title. -#html_short_title = None - -# The name of an image file (relative to this directory) to place at the top -# of the sidebar. -#html_logo = "" - -# The name of an image file (within the static path) to use as favicon of the -# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 -# pixels large. -#html_favicon = None -html_favicon = 'favicon.ico' - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -#html_static_path = ['static'] - -# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, -# using the given strftime format. -#html_last_updated_fmt = '%b %d, %Y' - -# If true, SmartyPants will be used to convert quotes and dashes to -# typographically correct entities. -#html_use_smartypants = True - -# Custom sidebar templates, maps document names to template names. -#html_sidebars = {} - -# Additional templates that should be rendered to pages, maps page names to -# template names. -#html_additional_pages = {} -html_additional_pages = {'index': 'index.html'} - -# If false, no module index is generated. -#html_use_modindex = True - -# If false, no index is generated. -#html_use_index = True - -# If true, the index is split into individual pages for each letter. -#html_split_index = False - -# If true, links to the reST sources are added to the pages. -html_show_sourcelink = False - -# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. -#html_show_sphinx = True - -# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. -#html_show_copyright = True - -# If true, an OpenSearch description file will be output, and all pages will -# contain a <link> tag referring to it. The value of this option must be the -# base URL from which the finished HTML is served. -#html_use_opensearch = '' - -# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml"). -#html_file_suffix = '' - -# Output file base name for HTML help builder. -htmlhelp_basename = 'Scipy.org' - - -# -- Options for LaTeX output -------------------------------------------------- - -# The paper size ('letter' or 'a4'). -#latex_paper_size = 'letter' - -# The font size ('10pt', '11pt' or '12pt'). -#latex_font_size = '10pt' - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, author, documentclass [howto/manual]). -latex_documents = [ - ('index', 'numpy-scipy-org.tex', u'numpy.scipy.org', - u'NumPy collaborators', 'manual'), -] - -# The name of an image file (relative to this directory) to place at the top of -# the title page. -#latex_logo = None - -# For "manual" documents, if this is true, then toplevel headings are parts, -# not chapters. -#latex_use_parts = False - -# Additional stuff for the LaTeX preamble. -#latex_preamble = '' - -# Documents to append as an appendix to all manuals. -#latex_appendices = [] - -# If false, no module index is generated. -#latex_use_modindex = True - -# Example configuration for intersphinx: refer to the Python standard library. -intersphinx_mapping = { - 'http://docs.python.org/': None, - 'http://docs.scipy.org/doc/numpy/': None, -} diff --git a/doc/numpy.scipy.org/content.rst b/doc/numpy.scipy.org/content.rst deleted file mode 100644 index 5c1ed49d4..000000000 --- a/doc/numpy.scipy.org/content.rst +++ /dev/null @@ -1,9 +0,0 @@ -Numerical Python -================= - -.. toctree:: - :maxdepth: 2 - - old_array_packages.rst - license.rst - diff --git a/doc/numpy.scipy.org/license.rst b/doc/numpy.scipy.org/license.rst deleted file mode 100644 index 862859658..000000000 --- a/doc/numpy.scipy.org/license.rst +++ /dev/null @@ -1,33 +0,0 @@ -Numpy license -============= - -| Copyright © 2005-2010, NumPy Developers. -| 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 the NumPy Developers nor the names of any - 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. diff --git a/doc/numpy.scipy.org/old_array_packages.rst b/doc/numpy.scipy.org/old_array_packages.rst deleted file mode 100644 index 814083ed6..000000000 --- a/doc/numpy.scipy.org/old_array_packages.rst +++ /dev/null @@ -1,40 +0,0 @@ -==================== -Older Array Packages -==================== - -It may take months for the large code base that uses Numeric and/or Numarray -to transition to the new NumPy system. Links to the older packages are -provided here. New users should start out with NumPy. - -Much of the documentation for Numeric and Numarray is applicable to the NumPy package. However, there are `significant feature improvements <http://numpy.scipy.org/new_features.html>`_. A complete guide to the new system has been written by the primary developer, Travis Oliphant. It is now in the public domain. Other Documentation is available at `the scipy website <http://www.scipy.org/>`_ and in the docstrings (which can be extracted using pydoc). Free Documentation for Numeric (most of which is still valid) is `here <http://numpy.scipy.org/numpydoc/numdoc.htm>`_ or as a `pdf <http://numpy.scipy.org/numpy.pdf>`_ file. Obviously you should replace references to Numeric in that document with numpy (i.e. instead of "import Numeric", use "import numpy"). - -Upgrading from historical implementations -========================================= - -NumPy derives from the old Numeric code base and can be used as a replacement for Numeric. It also adds the features introduced by Numarray and can also be used to replace Numarray. - -Numeric users should find the transition relatively easy (although not without some effort). There is a module (numpy.oldnumeric.alter_code1) that can makemost of the necessary changes to your Python code that used Numeric to work with NumPy's Numeric compatibility module. - -Users of numarray can also transition their code using a similar module (numpy.numarray.alter_code1) and the numpy.numarray compatibility layer. - -C-code written to either package can be easily ported to NumPy using "numpy/oldnumeric.h" and "numpy/libnumarray.h" for the Numeric C-API and the Numarray C-API respectively. `Sourceforge download site <http://sourceforge.net/project/showfiles.php?group_id=1369&package_id=175103>`_ - -For about 6 months at the end of 2005, the new package was called SciPy Core (not to be confused with the full SciPy package which remains a `separate <http://www.scipy.org/>`_ package), and so you will occasionally see references to SciPy Core floating around. It was decided in January 2006 to go with the historical name of NumPy for the new package. Realize that NumPy (module name numpy) is the new name. Because of the name-change, there were a lot of dicussions that took place on scipy-dev@scipy.org and scipy-user@scipy.org. If you have a question about the new system, you may wish to run a search on those mailing lists as well as the main NumPy list (numpy-discussion@lists.sourceforge.net) - -Numeric (version 24.2) -====================== - -Numeric was the first array object built for Python. It has been quite successful and is used in a wide variety of settings and applications. Maintenance has ceased for Numeric, and users should transisition to NumPy as quickly as possible. There is a module called numpy.oldnumeric.alter_code1 in NumPy that can make the transition to NumPy easier (it will automatically perform the search-and-replace style changes that need to be made to python code that uses Numeric to make it work with NumPy). - -Documentation for Numeric is at http://numpy.scipy.org/numpydoc/numdoc.htm> or as a `pdf <http://numpy.scipy.org/numpy.pdf>`_ file `Sourceforge Numeric Download Page <http://sourceforge.net/project/showfiles.php?group_id=1369&package_id=1351>`_ - -Numarray -======== - -Numarray is another implementation of an array object for Python written after -Numeric and before NumPy. Sponsors of numarray have indicated they will be -moving to NumPy as soon as is feasible for them so that eventually numarray -will be phased out (probably sometime in 2007). This project shares some of -the resources with the Numeric sourceforge site but maintains its own web page -at http://www.stsci.edu/resources/software_hardware/numarray -`Sourceforge Numarray Download Page <http://sourceforge.net/project/showfiles.php?group_id=1369&package_id=32367>`_
\ No newline at end of file diff --git a/doc/source/_templates/indexcontent.html b/doc/source/_templates/indexcontent.html index 49d955d8c..b497c93dd 100644 --- a/doc/source/_templates/indexcontent.html +++ b/doc/source/_templates/indexcontent.html @@ -7,6 +7,8 @@ <span class="linkdescr">start here</span></p> <p class="biglink"><a class="biglink" href="{{ pathto("reference/index") }}">Numpy Reference</a><br/> <span class="linkdescr">reference documentation</span></p> + <p class="biglink"><a class="biglink" href="{{ pathto("dev/index") }}">Numpy Developer Guide</a><br/> + <span class="linkdescr">contributing to NumPy</span></p> </td></tr> </table> diff --git a/doc/source/conf.py b/doc/source/conf.py index 59bf3e909..4dfec91db 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -4,8 +4,10 @@ import sys, os, re # Check Sphinx version import sphinx -if sphinx.__version__ < "0.5": - raise RuntimeError("Sphinx 0.5.dev or newer required") +if sphinx.__version__ < "1.0.1": + raise RuntimeError("Sphinx 1.0.1 or newer required") + +needs_sphinx = '1.0' # ----------------------------------------------------------------------------- # General configuration @@ -18,15 +20,9 @@ sys.path.insert(0, os.path.abspath('../sphinxext')) extensions = ['sphinx.ext.autodoc', 'sphinx.ext.pngmath', 'numpydoc', 'sphinx.ext.intersphinx', 'sphinx.ext.coverage', - 'sphinx.ext.doctest', + 'sphinx.ext.doctest', 'sphinx.ext.autosummary', 'plot_directive'] -if sphinx.__version__ >= "0.7": - extensions.append('sphinx.ext.autosummary') -else: - extensions.append('autosummary') - extensions.append('only_directives') - # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] @@ -222,9 +218,8 @@ numpydoc_use_plots = True # Autosummary # ----------------------------------------------------------------------------- -if sphinx.__version__ >= "0.7": - import glob - autosummary_generate = glob.glob("reference/*.rst") +import glob +autosummary_generate = glob.glob("reference/*.rst") # ----------------------------------------------------------------------------- # Coverage checker diff --git a/doc/source/contents.rst b/doc/source/contents.rst index 31ade2306..04ee229b2 100644 --- a/doc/source/contents.rst +++ b/doc/source/contents.rst @@ -6,6 +6,7 @@ Numpy manual contents user/index reference/index + dev/index release about bugs diff --git a/doc/source/dev/gitwash/branch_list.png b/doc/source/dev/gitwash/branch_list.png Binary files differnew file mode 100644 index 000000000..1196eb754 --- /dev/null +++ b/doc/source/dev/gitwash/branch_list.png diff --git a/doc/source/dev/gitwash/branch_list_compare.png b/doc/source/dev/gitwash/branch_list_compare.png Binary files differnew file mode 100644 index 000000000..336afa374 --- /dev/null +++ b/doc/source/dev/gitwash/branch_list_compare.png diff --git a/doc/source/dev/gitwash/configure_git.rst b/doc/source/dev/gitwash/configure_git.rst new file mode 100644 index 000000000..fd6d69d55 --- /dev/null +++ b/doc/source/dev/gitwash/configure_git.rst @@ -0,0 +1,123 @@ +.. _configure-git: + +=============== + Configure git +=============== + +.. _git-config-basic: + +Overview +======== + +Your personal git_ configurations are saved in the ``.gitconfig`` file in +your home directory. +Here is an example ``.gitconfig`` file:: + + [user] + name = Your Name + email = you@yourdomain.example.com + + [alias] + ci = commit -a + co = checkout + st = status -a + stat = status -a + br = branch + wdiff = diff --color-words + + [core] + editor = vim + + [merge] + summary = true + +You can edit this file directly or you can use the ``git config --global`` +command:: + + git config --global user.name "Your Name" + git config --global user.email you@yourdomain.example.com + git config --global alias.ci "commit -a" + git config --global alias.co checkout + git config --global alias.st "status -a" + git config --global alias.stat "status -a" + git config --global alias.br branch + git config --global alias.wdiff "diff --color-words" + git config --global core.editor vim + git config --global merge.summary true + +To set up on another computer, you can copy your ``~/.gitconfig`` file, +or run the commands above. + +In detail +========= + +user.name and user.email +------------------------ + +It is good practice to tell git_ who you are, for labeling any changes +you make to the code. The simplest way to do this is from the command +line:: + + git config --global user.name "Your Name" + git config --global user.email you@yourdomain.example.com + +This will write the settings into your git configuration file, which +should now contain a user section with your name and email:: + + [user] + name = Your Name + email = you@yourdomain.example.com + +Of course you'll need to replace ``Your Name`` and ``you@yourdomain.example.com`` +with your actual name and email address. + +Aliases +------- + +You might well benefit from some aliases to common commands. + +For example, you might well want to be able to shorten ``git checkout`` +to ``git co``. Or you may want to alias ``git diff --color-words`` +(which gives a nicely formatted output of the diff) to ``git wdiff`` + +The following ``git config --global`` commands:: + + git config --global alias.ci "commit -a" + git config --global alias.co checkout + git config --global alias.st "status -a" + git config --global alias.stat "status -a" + git config --global alias.br branch + git config --global alias.wdiff "diff --color-words" + +will create an ``alias`` section in your ``.gitconfig`` file with contents +like this:: + + [alias] + ci = commit -a + co = checkout + st = status -a + stat = status -a + br = branch + wdiff = diff --color-words + +Editor +------ + +You may also want to make sure that your editor of choice is used :: + + git config --global core.editor vim + +Merging +------- + +To enforce summaries when doing merges (``~/.gitconfig`` file again):: + + [merge] + log = true + +Or from the command line:: + + git config --global merge.log true + + +.. include:: git_links.inc diff --git a/doc/source/dev/gitwash/development_workflow.rst b/doc/source/dev/gitwash/development_workflow.rst new file mode 100644 index 000000000..2d9248054 --- /dev/null +++ b/doc/source/dev/gitwash/development_workflow.rst @@ -0,0 +1,239 @@ +.. _development-workflow: + +==================== +Development workflow +==================== + +You already have your own forked copy of the NumPy_ repository, by +following :ref:`forking`, :ref:`set-up-fork`, and you have configured +git_ by following :ref:`configure-git`. + +Workflow summary +================ + +* Keep your ``master`` branch clean of edits that have not been merged + to the main NumPy_ development repo. Your ``master`` then will follow + the main NumPy_ repository. +* Start a new *feature branch* for each set of edits that you do. +* If you can avoid it, try not to merge other branches into your feature + branch while you are working. +* Ask for review! + +This way of working really helps to keep work well organized, and in +keeping history as clear as possible. + +See - for example - `linux git workflow`_. + +Making a new feature branch +=========================== + +:: + + git branch my-new-feature + git checkout my-new-feature + +Generally, you will want to keep this also on your public github_ fork +of NumPy_. To do this, you `git push`_ this new branch up to your github_ +repo. Generally (if you followed the instructions in these pages, and +by default), git will have a link to your github_ repo, called +``origin``. You push up to your own repo on github_ with:: + + git push origin my-new-feature + +In git >1.7 you can ensure that the link is correctly set by using the +``--set-upstream`` option:: + + git push --set-upstream origin my-new-feature + +From now on git_ will know that ``my-new-feature`` is related to the +``my-new-feature`` branch in the github_ repo. + +The editing workflow +==================== + +Overview +-------- + +:: + + # hack hack + git add my_new_file + git commit -am 'NF - some message' + git push + +In more detail +-------------- + +#. Make some changes +#. See which files have changed with ``git status`` (see `git status`_). + You'll see a listing like this one:: + + # On branch ny-new-feature + # Changed but not updated: + # (use "git add <file>..." to update what will be committed) + # (use "git checkout -- <file>..." to discard changes in working directory) + # + # modified: README + # + # Untracked files: + # (use "git add <file>..." to include in what will be committed) + # + # INSTALL + no changes added to commit (use "git add" and/or "git commit -a") + +#. Check what the actual changes are with ``git diff`` (`git diff`_). +#. Add any new files to version control ``git add new_file_name`` (see + `git add`_). +#. To commit all modified files into the local copy of your repo,, do + ``git commit -am 'A commit message'``. Note the ``-am`` options to + ``commit``. The ``m`` flag just signals that you're going to type a + message on the command line. The ``a`` flag - you can just take on + faith - or see `why the -a flag?`_ - and the helpful use-case description in + the `tangled working copy problem`_. The `git commit`_ manual + page might also be useful. +#. To push the changes up to your forked repo on github_, do a ``git + push`` (see `git push`). + +Asking for code review +====================== + +#. Go to your repo URL - e.g. ``http://github.com/your-user-name/numpy``. +#. Click on the *Branch list* button: + + .. image:: branch_list.png + +#. Click on the *Compare* button for your feature branch - here ``my-new-feature``: + + .. image:: branch_list_compare.png + +#. If asked, select the *base* and *comparison* branch names you want to + compare. Usually these will be ``master`` and ``my-new-feature`` + (where that is your feature branch name). +#. At this point you should get a nice summary of the changes. Copy the + URL for this, and post it to the `NumPy mailing list`_, asking for + review. The URL will look something like: + ``http://github.com/your-user-name/numpy/compare/master...my-new-feature``. + There's an example at + http://github.com/matthew-brett/nipy/compare/master...find-install-data + See: http://github.com/blog/612-introducing-github-compare-view for + more detail. + +The generated comparison, is between your feature branch +``my-new-feature``, and the place in ``master`` from which you branched +``my-new-feature``. In other words, you can keep updating ``master`` +without interfering with the output from the comparison. More detail? +Note the three dots in the URL above (``master...my-new-feature``) and +see :ref:`dot2-dot3`. + +Asking for your changes to be merged with the main repo +======================================================= + +When you are ready to ask for the merge of your code: + +#. Go to the URL of your forked repo, say + ``http://github.com/your-user-name/numpy.git``. +#. Click on the 'Pull request' button: + + .. image:: pull_button.png + + Enter a message; we suggest you select only ``NumPy`` as the + recipient. The message will go to the `NumPy mailing list`_. Please + feel free to add others from the list as you like. + +Merging from trunk +================== + +This updates your code from the upstream `NumPy github`_ repo. + +Overview +-------- + +:: + + # go to your master branch + git checkout master + # pull changes from github + git fetch upstream + # merge from upstream + git merge upstream/master + +In detail +--------- + +We suggest that you do this only for your ``master`` branch, and leave +your 'feature' branches unmerged, to keep their history as clean as +possible. This makes code review easier:: + + git checkout master + +Make sure you have done :ref:`linking-to-upstream`. + +Merge the upstream code into your current development by first pulling +the upstream repo to a copy on your local machine:: + + git fetch upstream + +then merging into your current branch:: + + git merge upstream/master + +Deleting a branch on github_ +============================ + +:: + + git checkout master + # delete branch locally + git branch -D my-unwanted-branch + # delete branch on github + git push origin :my-unwanted-branch + +(Note the colon ``:`` before ``test-branch``. See also: +http://github.com/guides/remove-a-remote-branch + +Several people sharing a single repository +========================================== + +If you want to work on some stuff with other people, where you are all +committing into the same repository, or even the same branch, then just +share it via github_. + +First fork NumPy into your account, as from :ref:`forking`. + +Then, go to your forked repository github page, say +``http://github.com/your-user-name/numpy`` + +Click on the 'Admin' button, and add anyone else to the repo as a +collaborator: + + .. image:: pull_button.png + +Now all those people can do:: + + git clone git@githhub.com:your-user-name/numpy.git + +Remember that links starting with ``git@`` use the ssh protocol and are +read-write; links starting with ``git://`` are read-only. + +Your collaborators can then commit directly into that repo with the +usual:: + + git commit -am 'ENH - much better code' + git push origin master # pushes directly into your repo + +Exploring your repository +========================= + +To see a graphical representation of the repository branches and +commits:: + + gitk --all + +To see a linear list of commits for this branch:: + + git log + +You can also look at the `network graph visualizer`_ for your github_ +repo. + +.. include:: git_links.inc diff --git a/doc/source/dev/gitwash/dot2_dot3.rst b/doc/source/dev/gitwash/dot2_dot3.rst new file mode 100644 index 000000000..7759e2e60 --- /dev/null +++ b/doc/source/dev/gitwash/dot2_dot3.rst @@ -0,0 +1,28 @@ +.. _dot2-dot3: + +======================================== + Two and three dots in difference specs +======================================== + +Thanks to Yarik Halchenko for this explanation. + +Imagine a series of commits A, B, C, D... Imagine that there are two +branches, *topic* and *master*. You branched *topic* off *master* when +*master* was at commit 'E'. The graph of the commits looks like this:: + + + A---B---C topic + / + D---E---F---G master + +Then:: + + git diff master..topic + +will output the difference from G to C (i.e. with effects of F and G), +while:: + + git diff master...topic + +would output just differences in the topic branch (i.e. only A, B, and +C). diff --git a/doc/source/dev/gitwash/following_latest.rst b/doc/source/dev/gitwash/following_latest.rst new file mode 100644 index 000000000..c74cb88bf --- /dev/null +++ b/doc/source/dev/gitwash/following_latest.rst @@ -0,0 +1,36 @@ +.. _following-latest: + +============================= + Following the latest source +============================= + +These are the instructions if you just want to follow the latest +*NumPy* source, but you don't need to do any development for now. + +The steps are: + +* :ref:`install-git` +* get local copy of the git repository from github_ +* update local copy from time to time + +Get the local copy of the code +============================== + +From the command line:: + + git clone git://github.com/numpy/numpy.git + +You now have a copy of the code tree in the new ``numpy`` directory. + +Updating the code +================= + +From time to time you may want to pull down the latest code. Do this with:: + + cd numpy + git pull + +The tree in ``numpy`` will now have the latest changes from the initial +repository. + +.. include:: git_links.inc diff --git a/doc/source/dev/gitwash/forking_button.png b/doc/source/dev/gitwash/forking_button.png Binary files differnew file mode 100644 index 000000000..d0e04134d --- /dev/null +++ b/doc/source/dev/gitwash/forking_button.png diff --git a/doc/source/dev/gitwash/forking_hell.rst b/doc/source/dev/gitwash/forking_hell.rst new file mode 100644 index 000000000..3af444e0b --- /dev/null +++ b/doc/source/dev/gitwash/forking_hell.rst @@ -0,0 +1,33 @@ +.. _forking: + +========================================== +Making your own copy (fork) of NumPy +========================================== + +You need to do this only once. The instructions here are very similar +to the instructions at http://help.github.com/forking/ - please see that +page for more detail. We're repeating some of it here just to give the +specifics for the NumPy_ project, and to suggest some default names. + +Set up and configure a github_ account +====================================== + +If you don't have a github_ account, go to the github_ page, and make one. + +You then need to configure your account to allow write access - see the +``Generating SSH keys`` help on `github help`_. + +Create your own forked copy of NumPy_ +========================================= + +#. Log into your github_ account. +#. Go to the NumPy_ github home at `NumPy github`_. +#. Click on the *fork* button: + + .. image:: forking_button.png + + Now, after a short pause and some 'Hardcore forking action', you + should find yourself at the home page for your own forked copy of NumPy_. + +.. include:: git_links.inc + diff --git a/doc/source/dev/gitwash/git_development.rst b/doc/source/dev/gitwash/git_development.rst new file mode 100644 index 000000000..64522c658 --- /dev/null +++ b/doc/source/dev/gitwash/git_development.rst @@ -0,0 +1,16 @@ +.. _git-development: + +===================== + Git for development +===================== + +Contents: + +.. toctree:: + :maxdepth: 2 + + forking_hell + set_up_fork + configure_git + development_workflow + diff --git a/doc/source/dev/gitwash/git_install.rst b/doc/source/dev/gitwash/git_install.rst new file mode 100644 index 000000000..422bdf66a --- /dev/null +++ b/doc/source/dev/gitwash/git_install.rst @@ -0,0 +1,26 @@ +.. _install-git: + +============= + Install git +============= + +Overview +======== + +================ ============= +Debian / Ubuntu ``sudo apt-get install git-core`` +Fedora ``sudo yum install git-core`` +Windows Download and install msysGit_ +OS X Use the git-osx-installer_ +================ ============= + +In detail +========= + +See the git_ page for the most recent information. + +Have a look at the github_ install help pages available from `github help`_ + +There are good instructions here: http://book.git-scm.com/2_installing_git.html + +.. include:: git_links.inc diff --git a/doc/source/dev/gitwash/git_intro.rst b/doc/source/dev/gitwash/git_intro.rst new file mode 100644 index 000000000..655804383 --- /dev/null +++ b/doc/source/dev/gitwash/git_intro.rst @@ -0,0 +1,18 @@ +============== + Introduction +============== + +These pages describe a git_ and github_ workflow for the NumPy_ +project. + +There are several different workflows here, for different ways of +working with *NumPy*. + +This is not a comprehensive git_ reference, it's just a workflow for our +own project. It's tailored to the github_ hosting service. You may well +find better or quicker ways of getting stuff done with git_, but these +should get you started. + +For general resources for learning git_ see :ref:`git-resources`. + +.. include:: git_links.inc diff --git a/doc/source/dev/gitwash/git_links.inc b/doc/source/dev/gitwash/git_links.inc new file mode 100644 index 000000000..e33dacc2a --- /dev/null +++ b/doc/source/dev/gitwash/git_links.inc @@ -0,0 +1,85 @@ +.. This (-*- rst -*-) format file contains commonly used link targets + and name substitutions. It may be included in many files, + therefore it should only contain link targets and name + substitutions. Try grepping for "^\.\. _" to find plausible + candidates for this list. + +.. NOTE: reST targets are + __not_case_sensitive__, so only one target definition is needed for + nipy, NIPY, Nipy, etc... + +.. PROJECTNAME placeholders +.. _PROJECTNAME: http://neuroimaging.scipy.org +.. _`PROJECTNAME github`: http://github.com/nipy +.. _`PROJECTNAME mailing list`: http://projects.scipy.org/mailman/listinfo/nipy-devel + +.. nipy +.. _nipy: http://nipy.org/nipy +.. _`nipy github`: http://github.com/nipy/nipy +.. _`nipy mailing list`: http://mail.scipy.org/mailman/listinfo/nipy-devel + +.. ipython +.. _ipython: http://ipython.scipy.org +.. _`ipython github`: http://github.com/ipython/ipython +.. _`ipython mailing list`: http://mail.scipy.org/mailman/listinfo/IPython-dev + +.. dipy +.. _dipy: http://nipy.org/dipy +.. _`dipy github`: http://github.com/Garyfallidis/dipy +.. _`dipy mailing list`: http://mail.scipy.org/mailman/listinfo/nipy-devel + +.. nibabel +.. _nibabel: http://nipy.org/nibabel +.. _`nibabel github`: http://github.com/nipy/nibabel +.. _`nibabel mailing list`: http://mail.scipy.org/mailman/listinfo/nipy-devel + +.. marsbar +.. _marsbar: http://marsbar.sourceforge.net +.. _`marsbar github`: http://github.com/matthew-brett/marsbar +.. _`MarsBaR mailing list`: https://lists.sourceforge.net/lists/listinfo/marsbar-users + +.. git stuff +.. _git: http://git-scm.com/ +.. _github: http://github.com +.. _github help: http://help.github.com +.. _msysgit: http://code.google.com/p/msysgit/downloads/list +.. _git-osx-installer: http://code.google.com/p/git-osx-installer/downloads/list +.. _subversion: http://subversion.tigris.org/ +.. _git cheat sheet: http://github.com/guides/git-cheat-sheet +.. _pro git book: http://progit.org/ +.. _git svn crash course: http://git-scm.com/course/svn.html +.. _learn.github: http://learn.github.com/ +.. _network graph visualizer: http://github.com/blog/39-say-hello-to-the-network-graph-visualizer +.. _git user manual: http://www.kernel.org/pub/software/scm/git/docs/user-manual.html +.. _git tutorial: http://www.kernel.org/pub/software/scm/git/docs/gittutorial.html +.. _git community book: http://book.git-scm.com/ +.. _git ready: http://www.gitready.com/ +.. _git casts: http://www.gitcasts.com/ +.. _Fernando's git page: http://www.fperez.org/py4science/git.html +.. _git magic: http://www-cs-students.stanford.edu/~blynn/gitmagic/index.html +.. _git concepts: http://www.eecs.harvard.edu/~cduan/technical/git/ +.. _git clone: http://www.kernel.org/pub/software/scm/git/docs/git-clone.html +.. _git checkout: http://www.kernel.org/pub/software/scm/git/docs/git-checkout.html +.. _git commit: http://www.kernel.org/pub/software/scm/git/docs/git-commit.html +.. _git push: http://www.kernel.org/pub/software/scm/git/docs/git-push.html +.. _git pull: http://www.kernel.org/pub/software/scm/git/docs/git-pull.html +.. _git add: http://www.kernel.org/pub/software/scm/git/docs/git-add.html +.. _git status: http://www.kernel.org/pub/software/scm/git/docs/git-status.html +.. _git diff: http://www.kernel.org/pub/software/scm/git/docs/git-diff.html +.. _git log: http://www.kernel.org/pub/software/scm/git/docs/git-log.html +.. _git branch: http://www.kernel.org/pub/software/scm/git/docs/git-branch.html +.. _git remote: http://www.kernel.org/pub/software/scm/git/docs/git-remote.html +.. _git config: http://www.kernel.org/pub/software/scm/git/docs/git-config.html +.. _why the -a flag?: http://www.gitready.com/beginner/2009/01/18/the-staging-area.html +.. _git staging area: http://www.gitready.com/beginner/2009/01/18/the-staging-area.html +.. _tangled working copy problem: http://tomayko.com/writings/the-thing-about-git +.. _git management: http://kerneltrap.org/Linux/Git_Management +.. _linux git workflow: http://www.mail-archive.com/dri-devel@lists.sourceforge.net/msg39091.html +.. _git parable: http://tom.preston-werner.com/2009/05/19/the-git-parable.html +.. _git foundation: http://matthew-brett.github.com/pydagogue/foundation.html + +.. other stuff +.. _python: http://www.python.org +.. _NumPy: http://numpy.scipy.org +.. _`NumPy github`: http://github.com/numpy/numpy +.. _`NumPy mailing list`: http://scipy.org/Mailing_Lists diff --git a/doc/source/dev/gitwash/git_resources.rst b/doc/source/dev/gitwash/git_resources.rst new file mode 100644 index 000000000..ae350806e --- /dev/null +++ b/doc/source/dev/gitwash/git_resources.rst @@ -0,0 +1,58 @@ +.. _git-resources: + +================ + git_ resources +================ + +Tutorials and summaries +======================= + +* `github help`_ has an excellent series of how-to guides. +* `learn.github`_ has an excellent series of tutorials +* The `pro git book`_ is a good in-depth book on git. +* A `git cheat sheet`_ is a page giving summaries of common commands. +* The `git user manual`_ +* The `git tutorial`_ +* The `git community book`_ +* `git ready`_ - a nice series of tutorials +* `git casts`_ - video snippets giving git how-tos. +* `git magic`_ - extended introduction with intermediate detail +* The `git parable`_ is an easy read explaining the concepts behind git. +* Our own `git foundation`_ expands on the `git parable`_. +* Fernando Perez' git page - `Fernando's git page`_ - many links and tips +* A good but technical page on `git concepts`_ +* `git svn crash course`_: git_ for those of us used to subversion_ + +Advanced git workflow +===================== + +There are many ways of working with git_; here are some posts on the +rules of thumb that other projects have come up with: + +* Linus Torvalds on `git management`_ +* Linus Torvalds on `linux git workflow`_ . Summary; use the git tools + to make the history of your edits as clean as possible; merge from + upstream edits as little as possible in branches where you are doing + active development. + +Manual pages online +=================== + +You can get these on your own machine with (e.g) ``git help push`` or +(same thing) ``git push --help``, but, for convenience, here are the +online manual pages for some common commands: + +* `git add`_ +* `git branch`_ +* `git checkout`_ +* `git clone`_ +* `git commit`_ +* `git config`_ +* `git diff`_ +* `git log`_ +* `git pull`_ +* `git push`_ +* `git remote`_ +* `git status`_ + +.. include:: git_links.inc diff --git a/doc/source/dev/gitwash/index.rst b/doc/source/dev/gitwash/index.rst new file mode 100644 index 000000000..aecef1464 --- /dev/null +++ b/doc/source/dev/gitwash/index.rst @@ -0,0 +1,18 @@ +.. _using-git: + +Working with *NumPy* source code +====================================== + +Contents: + +.. toctree:: + :maxdepth: 2 + + git_intro + git_install + following_latest + patching + git_development + git_resources + + diff --git a/doc/source/dev/gitwash/patching.rst b/doc/source/dev/gitwash/patching.rst new file mode 100644 index 000000000..01ece8fc6 --- /dev/null +++ b/doc/source/dev/gitwash/patching.rst @@ -0,0 +1,123 @@ +================ + Making a patch +================ + +You've discovered a bug or something else you want to change in NumPy_ - excellent! + +You've worked out a way to fix it - even better! + +You want to tell us about it - best of all! + +The easiest way is to make a *patch* or set of patches. Here we explain +how. Making a patch is the simplest and quickest, but if you're going +to be doing anything more than simple quick things, please consider +following the :ref:`git-development` model instead. + +.. _making-patches: + +Making patches +============== + +Overview +-------- + +:: + + # tell git who you are + git config --global user.email you@yourdomain.example.com + git config --global user.name "Your Name Comes Here" + # get the repository if you don't have it + git clone git://github.com/numpy/numpy.git + # make a branch for your patching + cd numpy + git branch the-fix-im-thinking-of + git checkout the-fix-im-thinking-of + # hack, hack, hack + # Tell git about any new files you've made + git add somewhere/tests/test_my_bug.py + # commit work in progress as you go + git commit -am 'BF - added tests for Funny bug' + # hack hack, hack + git commit -am 'BF - added fix for Funny bug' + # make the patch files + git format-patch -M -C master + +Then, send the generated patch files to the `NumPy mailing list`_ - where we will thank you warmly. + +In detail +--------- + +#. Tell git_ who you are so it can label the commits you've made:: + + git config --global user.email you@yourdomain.example.com + git config --global user.name "Your Name Comes Here" + +#. If you don't already have one, clone a copy of the NumPy_ repository:: + + git clone git://github.com/numpy/numpy.git + cd numpy + +#. Make a 'feature branch'. This will be where you work on your bug + fix. It's nice and safe and leaves you with access to an unmodified + copy of the code in the main branch:: + + git branch the-fix-im-thinking-of + git checkout the-fix-im-thinking-of + +#. Do some edits, and commit them as you go:: + + # hack, hack, hack + # Tell git about any new files you've made + git add somewhere/tests/test_my_bug.py + # commit work in progress as you go + git commit -am 'BF - added tests for Funny bug' + # hack hack, hack + git commit -am 'BF - added fix for Funny bug' + + Note the ``-am`` options to ``commit``. The ``m`` flag just signals + that you're going to type a message on the command line. The ``a`` + flag - you can just take on faith - or see `why the -a flag?`_. + +#. When you have finished, check you have committed all your changes:: + + git status + +#. Finally, make your commits into patches. You want all the commits + since you branched from the ``master`` branch:: + + git format-patch -M -C master + + You will now have several files named for the commits:: + + 0001-BF-added-tests-for-Funny-bug.patch + 0002-BF-added-fix-for-Funny-bug.patch + + Send these files to the `NumPy mailing list`_. + +When you are done, to switch back to the main copy of the code, just +return to the ``master`` branch:: + + git checkout master + +Moving from patching to development +=================================== + +If you find you have done some patches, and you have one or more feature +branches, you will probably want to switch to development mode. You can +do this with the repository you have. + +Fork the NumPy_ repository on github_ - :ref:`forking`. Then:: + + # checkout and refresh master branch from main repo + git checkout master + git pull origin master + # rename pointer to main repository to 'upstream' + git remote rename origin upstream + # point your repo to default read / write to your fork on github + git remote add origin git@github.com:your-user-name/numpy.git + # push up any branches you've made and want to keep + git push origin the-fix-im-thinking-of + +Then you can, if you want, follow the :ref:`development-workflow`. + +.. include:: git_links.inc diff --git a/doc/source/dev/gitwash/pull_button.png b/doc/source/dev/gitwash/pull_button.png Binary files differnew file mode 100644 index 000000000..e5031681b --- /dev/null +++ b/doc/source/dev/gitwash/pull_button.png diff --git a/doc/source/dev/gitwash/set_up_fork.rst b/doc/source/dev/gitwash/set_up_fork.rst new file mode 100644 index 000000000..8b964e52a --- /dev/null +++ b/doc/source/dev/gitwash/set_up_fork.rst @@ -0,0 +1,68 @@ +.. _set-up-fork: + +================== + Set up your fork +================== + +First you follow the instructions for :ref:`forking`. + +Overview +======== + +:: + + git clone git@github.com:your-user-name/numpy.git + cd numpy + git remote add upstream git://github.com/numpy/numpy.git + +In detail +========= + +Clone your fork +--------------- + +#. Clone your fork to the local computer with ``git clone + git@github.com:your-user-name/numpy.git`` +#. Investigate. Change directory to your new repo: ``cd numpy``. Then + ``git branch -a`` to show you all branches. You'll get something + like:: + + * master + remotes/origin/master + + This tells you that you are currently on the ``master`` branch, and + that you also have a ``remote`` connection to ``origin/master``. + What remote repository is ``remote/origin``? Try ``git remote -v`` to + see the URLs for the remote. They will point to your github_ fork. + + Now you want to connect to the upstream `NumPy github`_ repository, so + you can merge in changes from trunk. + +.. _linking-to-upstream: + +Linking your repository to the upstream repo +-------------------------------------------- + +:: + + cd numpy + git remote add upstream git://github.com/numpy/numpy.git + +``upstream`` here is just the arbitrary name we're using to refer to the +main NumPy_ repository at `NumPy github`_. + +Note that we've used ``git://`` for the URL rather than ``git@``. The +``git://`` URL is read only. This means we that we can't accidentally +(or deliberately) write to the upstream repo, and we are only going to +use it to merge into our own code. + +Just for your own satisfaction, show yourself that you now have a new +'remote', with ``git remote -v show``, giving you something like:: + + upstream git://github.com/numpy/numpy.git (fetch) + upstream git://github.com/numpy/numpy.git (push) + origin git@github.com:your-user-name/numpy.git (fetch) + origin git@github.com:your-user-name/numpy.git (push) + +.. include:: git_links.inc + diff --git a/doc/source/dev/gitwash_links.txt b/doc/source/dev/gitwash_links.txt new file mode 100644 index 000000000..c598ba4aa --- /dev/null +++ b/doc/source/dev/gitwash_links.txt @@ -0,0 +1,3 @@ +.. _NumPy: http://numpy.scipy.org +.. _`NumPy github`: http://github.com/numpy/numpy +.. _`NumPy mailing list`: http://scipy.org/Mailing_Lists diff --git a/doc/source/dev/index.rst b/doc/source/dev/index.rst new file mode 100644 index 000000000..727c2f4f2 --- /dev/null +++ b/doc/source/dev/index.rst @@ -0,0 +1,8 @@ +##################### +Contributing to Numpy +##################### + +.. toctree:: + :maxdepth: 1 + + gitwash/index diff --git a/doc/sphinxext/README.txt b/doc/sphinxext/README.txt index f3d782c95..6ba63e6d8 100644 --- a/doc/sphinxext/README.txt +++ b/doc/sphinxext/README.txt @@ -14,17 +14,10 @@ The following extensions are available: - ``numpydoc.traitsdoc``: For gathering documentation about Traits attributes. - - ``numpydoc.plot_directives``: Adaptation of Matplotlib's ``plot::`` + - ``numpydoc.plot_directive``: Adaptation of Matplotlib's ``plot::`` directive. Note that this implementation may still undergo severe changes or eventually be deprecated. - - ``numpydoc.only_directives``: (DEPRECATED) - - - ``numpydoc.autosummary``: (DEPRECATED) An ``autosummary::`` directive. - Available in Sphinx 0.6.2 and (to-be) 1.0 as ``sphinx.ext.autosummary``, - and it the Sphinx 1.0 version is recommended over that included in - Numpydoc. - numpydoc ======== diff --git a/doc/sphinxext/autosummary.py b/doc/sphinxext/autosummary.py deleted file mode 100644 index 2f8a00a30..000000000 --- a/doc/sphinxext/autosummary.py +++ /dev/null @@ -1,349 +0,0 @@ -""" -=========== -autosummary -=========== - -Sphinx extension that adds an autosummary:: directive, which can be -used to generate function/method/attribute/etc. summary lists, similar -to those output eg. by Epydoc and other API doc generation tools. - -An :autolink: role is also provided. - -autosummary directive ---------------------- - -The autosummary directive has the form:: - - .. autosummary:: - :nosignatures: - :toctree: generated/ - - module.function_1 - module.function_2 - ... - -and it generates an output table (containing signatures, optionally) - - ======================== ============================================= - module.function_1(args) Summary line from the docstring of function_1 - module.function_2(args) Summary line from the docstring - ... - ======================== ============================================= - -If the :toctree: option is specified, files matching the function names -are inserted to the toctree with the given prefix: - - generated/module.function_1 - generated/module.function_2 - ... - -Note: The file names contain the module:: or currentmodule:: prefixes. - -.. seealso:: autosummary_generate.py - - -autolink role -------------- - -The autolink role functions as ``:obj:`` when the name referred can be -resolved to a Python object, and otherwise it becomes simple emphasis. -This can be used as the default role to make links 'smart'. - -""" -import sys, os, posixpath, re - -from docutils.parsers.rst import directives -from docutils.statemachine import ViewList -from docutils import nodes - -import sphinx.addnodes, sphinx.roles -from sphinx.util import patfilter - -from docscrape_sphinx import get_doc_object - -import warnings -warnings.warn( - "The numpydoc.autosummary extension can also be found as " - "sphinx.ext.autosummary in Sphinx >= 0.6, and the version in " - "Sphinx >= 0.7 is superior to the one in numpydoc. This numpydoc " - "version of autosummary is no longer maintained.", - DeprecationWarning, stacklevel=2) - -def setup(app): - app.add_directive('autosummary', autosummary_directive, True, (0, 0, False), - toctree=directives.unchanged, - nosignatures=directives.flag) - app.add_role('autolink', autolink_role) - - app.add_node(autosummary_toc, - html=(autosummary_toc_visit_html, autosummary_toc_depart_noop), - latex=(autosummary_toc_visit_latex, autosummary_toc_depart_noop)) - app.connect('doctree-read', process_autosummary_toc) - -#------------------------------------------------------------------------------ -# autosummary_toc node -#------------------------------------------------------------------------------ - -class autosummary_toc(nodes.comment): - pass - -def process_autosummary_toc(app, doctree): - """ - Insert items described in autosummary:: to the TOC tree, but do - not generate the toctree:: list. - - """ - env = app.builder.env - crawled = {} - def crawl_toc(node, depth=1): - crawled[node] = True - for j, subnode in enumerate(node): - try: - if (isinstance(subnode, autosummary_toc) - and isinstance(subnode[0], sphinx.addnodes.toctree)): - env.note_toctree(env.docname, subnode[0]) - continue - except IndexError: - continue - if not isinstance(subnode, nodes.section): - continue - if subnode not in crawled: - crawl_toc(subnode, depth+1) - crawl_toc(doctree) - -def autosummary_toc_visit_html(self, node): - """Hide autosummary toctree list in HTML output""" - raise nodes.SkipNode - -def autosummary_toc_visit_latex(self, node): - """Show autosummary toctree (= put the referenced pages here) in Latex""" - pass - -def autosummary_toc_depart_noop(self, node): - pass - -#------------------------------------------------------------------------------ -# .. autosummary:: -#------------------------------------------------------------------------------ - -def autosummary_directive(dirname, arguments, options, content, lineno, - content_offset, block_text, state, state_machine): - """ - Pretty table containing short signatures and summaries of functions etc. - - autosummary also generates a (hidden) toctree:: node. - - """ - - names = [] - names += [x.strip().split()[0] for x in content - if x.strip() and re.search(r'^[a-zA-Z_]', x.strip()[0])] - - table, warnings, real_names = get_autosummary(names, state, - 'nosignatures' in options) - node = table - - env = state.document.settings.env - suffix = env.config.source_suffix - all_docnames = env.found_docs.copy() - dirname = posixpath.dirname(env.docname) - - if 'toctree' in options: - tree_prefix = options['toctree'].strip() - docnames = [] - for name in names: - name = real_names.get(name, name) - - docname = tree_prefix + name - if docname.endswith(suffix): - docname = docname[:-len(suffix)] - docname = posixpath.normpath(posixpath.join(dirname, docname)) - if docname not in env.found_docs: - warnings.append(state.document.reporter.warning( - 'toctree references unknown document %r' % docname, - line=lineno)) - docnames.append(docname) - - tocnode = sphinx.addnodes.toctree() - tocnode['includefiles'] = docnames - tocnode['maxdepth'] = -1 - tocnode['glob'] = None - tocnode['entries'] = [(None, docname) for docname in docnames] - - tocnode = autosummary_toc('', '', tocnode) - return warnings + [node] + [tocnode] - else: - return warnings + [node] - -def get_autosummary(names, state, no_signatures=False): - """ - Generate a proper table node for autosummary:: directive. - - Parameters - ---------- - names : list of str - Names of Python objects to be imported and added to the table. - document : document - Docutils document object - - """ - document = state.document - - real_names = {} - warnings = [] - - prefixes = [''] - prefixes.insert(0, document.settings.env.currmodule) - - table = nodes.table('') - group = nodes.tgroup('', cols=2) - table.append(group) - group.append(nodes.colspec('', colwidth=10)) - group.append(nodes.colspec('', colwidth=90)) - body = nodes.tbody('') - group.append(body) - - def append_row(*column_texts): - row = nodes.row('') - for text in column_texts: - node = nodes.paragraph('') - vl = ViewList() - vl.append(text, '<autosummary>') - state.nested_parse(vl, 0, node) - try: - if isinstance(node[0], nodes.paragraph): - node = node[0] - except IndexError: - pass - row.append(nodes.entry('', node)) - body.append(row) - - for name in names: - try: - obj, real_name = import_by_name(name, prefixes=prefixes) - except ImportError: - warnings.append(document.reporter.warning( - 'failed to import %s' % name)) - append_row(":obj:`%s`" % name, "") - continue - - real_names[name] = real_name - - doc = get_doc_object(obj) - - if doc['Summary']: - title = " ".join(doc['Summary']) - else: - title = "" - - col1 = u":obj:`%s <%s>`" % (name, real_name) - if doc['Signature']: - sig = re.sub('^[^(\[]*', '', doc['Signature'].strip()) - if '=' in sig: - # abbreviate optional arguments - sig = re.sub(r', ([a-zA-Z0-9_]+)=', r'[, \1=', sig, count=1) - sig = re.sub(r'\(([a-zA-Z0-9_]+)=', r'([\1=', sig, count=1) - sig = re.sub(r'=[^,)]+,', ',', sig) - sig = re.sub(r'=[^,)]+\)$', '])', sig) - # shorten long strings - sig = re.sub(r'(\[.{16,16}[^,]*?),.*?\]\)', r'\1, ...])', sig) - else: - sig = re.sub(r'(\(.{16,16}[^,]*?),.*?\)', r'\1, ...)', sig) - # make signature contain non-breaking spaces - col1 += u"\\ \u00a0" + unicode(sig).replace(u" ", u"\u00a0") - col2 = title - append_row(col1, col2) - - return table, warnings, real_names - -def import_by_name(name, prefixes=[None]): - """ - Import a Python object that has the given name, under one of the prefixes. - - Parameters - ---------- - name : str - Name of a Python object, eg. 'numpy.ndarray.view' - prefixes : list of (str or None), optional - Prefixes to prepend to the name (None implies no prefix). - The first prefixed name that results to successful import is used. - - Returns - ------- - obj - The imported object - name - Name of the imported object (useful if `prefixes` was used) - - """ - for prefix in prefixes: - try: - if prefix: - prefixed_name = '.'.join([prefix, name]) - else: - prefixed_name = name - return _import_by_name(prefixed_name), prefixed_name - except ImportError: - pass - raise ImportError - -def _import_by_name(name): - """Import a Python object given its full name""" - try: - # try first interpret `name` as MODNAME.OBJ - name_parts = name.split('.') - try: - modname = '.'.join(name_parts[:-1]) - __import__(modname) - return getattr(sys.modules[modname], name_parts[-1]) - except (ImportError, IndexError, AttributeError): - pass - - # ... then as MODNAME, MODNAME.OBJ1, MODNAME.OBJ1.OBJ2, ... - last_j = 0 - modname = None - for j in reversed(range(1, len(name_parts)+1)): - last_j = j - modname = '.'.join(name_parts[:j]) - try: - __import__(modname) - except ImportError: - continue - if modname in sys.modules: - break - - if last_j < len(name_parts): - obj = sys.modules[modname] - for obj_name in name_parts[last_j:]: - obj = getattr(obj, obj_name) - return obj - else: - return sys.modules[modname] - except (ValueError, ImportError, AttributeError, KeyError), e: - raise ImportError(e) - -#------------------------------------------------------------------------------ -# :autolink: (smart default role) -#------------------------------------------------------------------------------ - -def autolink_role(typ, rawtext, etext, lineno, inliner, - options={}, content=[]): - """ - Smart linking role. - - Expands to ":obj:`text`" if `text` is an object that can be imported; - otherwise expands to "*text*". - """ - r = sphinx.roles.xfileref_role('obj', rawtext, etext, lineno, inliner, - options, content) - pnode = r[0][0] - - prefixes = [None] - #prefixes.insert(0, inliner.document.settings.env.currmodule) - try: - obj, name = import_by_name(pnode['reftarget'], prefixes) - except ImportError: - content = pnode[0] - r[0][0] = nodes.emphasis(rawtext, content[0].astext(), - classes=content['classes']) - return r diff --git a/doc/sphinxext/autosummary_generate.py b/doc/sphinxext/autosummary_generate.py deleted file mode 100755 index a32706748..000000000 --- a/doc/sphinxext/autosummary_generate.py +++ /dev/null @@ -1,219 +0,0 @@ -#!/usr/bin/env python -r""" -autosummary_generate.py OPTIONS FILES - -Generate automatic RST source files for items referred to in -autosummary:: directives. - -Each generated RST file contains a single auto*:: directive which -extracts the docstring of the referred item. - -Example Makefile rule:: - - generate: - ./ext/autosummary_generate.py -o source/generated source/*.rst - -""" -import glob, re, inspect, os, optparse, pydoc -from autosummary import import_by_name - -try: - from phantom_import import import_phantom_module -except ImportError: - import_phantom_module = lambda x: x - -def main(): - p = optparse.OptionParser(__doc__.strip()) - p.add_option("-p", "--phantom", action="store", type="string", - dest="phantom", default=None, - help="Phantom import modules from a file") - p.add_option("-o", "--output-dir", action="store", type="string", - dest="output_dir", default=None, - help=("Write all output files to the given directory (instead " - "of writing them as specified in the autosummary:: " - "directives)")) - options, args = p.parse_args() - - if len(args) == 0: - p.error("wrong number of arguments") - - if options.phantom and os.path.isfile(options.phantom): - import_phantom_module(options.phantom) - - # read - names = {} - for name, loc in get_documented(args).items(): - for (filename, sec_title, keyword, toctree) in loc: - if toctree is not None: - path = os.path.join(os.path.dirname(filename), toctree) - names[name] = os.path.abspath(path) - - # write - for name, path in sorted(names.items()): - if options.output_dir is not None: - path = options.output_dir - - if not os.path.isdir(path): - os.makedirs(path) - - try: - obj, name = import_by_name(name) - except ImportError, e: - print "Failed to import '%s': %s" % (name, e) - continue - - fn = os.path.join(path, '%s.rst' % name) - - if os.path.exists(fn): - # skip - continue - - f = open(fn, 'w') - - try: - f.write('%s\n%s\n\n' % (name, '='*len(name))) - - if inspect.isclass(obj): - if issubclass(obj, Exception): - f.write(format_modulemember(name, 'autoexception')) - else: - f.write(format_modulemember(name, 'autoclass')) - elif inspect.ismodule(obj): - f.write(format_modulemember(name, 'automodule')) - elif inspect.ismethod(obj) or inspect.ismethoddescriptor(obj): - f.write(format_classmember(name, 'automethod')) - elif callable(obj): - f.write(format_modulemember(name, 'autofunction')) - elif hasattr(obj, '__get__'): - f.write(format_classmember(name, 'autoattribute')) - else: - f.write(format_modulemember(name, 'autofunction')) - finally: - f.close() - -def format_modulemember(name, directive): - parts = name.split('.') - mod, name = '.'.join(parts[:-1]), parts[-1] - return ".. currentmodule:: %s\n\n.. %s:: %s\n" % (mod, directive, name) - -def format_classmember(name, directive): - parts = name.split('.') - mod, name = '.'.join(parts[:-2]), '.'.join(parts[-2:]) - return ".. currentmodule:: %s\n\n.. %s:: %s\n" % (mod, directive, name) - -def get_documented(filenames): - """ - Find out what items are documented in source/*.rst - See `get_documented_in_lines`. - - """ - documented = {} - for filename in filenames: - f = open(filename, 'r') - lines = f.read().splitlines() - documented.update(get_documented_in_lines(lines, filename=filename)) - f.close() - return documented - -def get_documented_in_docstring(name, module=None, filename=None): - """ - Find out what items are documented in the given object's docstring. - See `get_documented_in_lines`. - - """ - try: - obj, real_name = import_by_name(name) - lines = pydoc.getdoc(obj).splitlines() - return get_documented_in_lines(lines, module=name, filename=filename) - except AttributeError: - pass - except ImportError, e: - print "Failed to import '%s': %s" % (name, e) - return {} - -def get_documented_in_lines(lines, module=None, filename=None): - """ - Find out what items are documented in the given lines - - Returns - ------- - documented : dict of list of (filename, title, keyword, toctree) - Dictionary whose keys are documented names of objects. - The value is a list of locations where the object was documented. - Each location is a tuple of filename, the current section title, - the name of the directive, and the value of the :toctree: argument - (if present) of the directive. - - """ - title_underline_re = re.compile("^[-=*_^#]{3,}\s*$") - autodoc_re = re.compile(".. auto(function|method|attribute|class|exception|module)::\s*([A-Za-z0-9_.]+)\s*$") - autosummary_re = re.compile(r'^\.\.\s+autosummary::\s*') - module_re = re.compile(r'^\.\.\s+(current)?module::\s*([a-zA-Z0-9_.]+)\s*$') - autosummary_item_re = re.compile(r'^\s+([_a-zA-Z][a-zA-Z0-9_.]*)\s*.*?') - toctree_arg_re = re.compile(r'^\s+:toctree:\s*(.*?)\s*$') - - documented = {} - - current_title = [] - last_line = None - toctree = None - current_module = module - in_autosummary = False - - for line in lines: - try: - if in_autosummary: - m = toctree_arg_re.match(line) - if m: - toctree = m.group(1) - continue - - if line.strip().startswith(':'): - continue # skip options - - m = autosummary_item_re.match(line) - if m: - name = m.group(1).strip() - if current_module and not name.startswith(current_module + '.'): - name = "%s.%s" % (current_module, name) - documented.setdefault(name, []).append( - (filename, current_title, 'autosummary', toctree)) - continue - if line.strip() == '': - continue - in_autosummary = False - - m = autosummary_re.match(line) - if m: - in_autosummary = True - continue - - m = autodoc_re.search(line) - if m: - name = m.group(2).strip() - if m.group(1) == "module": - current_module = name - documented.update(get_documented_in_docstring( - name, filename=filename)) - elif current_module and not name.startswith(current_module+'.'): - name = "%s.%s" % (current_module, name) - documented.setdefault(name, []).append( - (filename, current_title, "auto" + m.group(1), None)) - continue - - m = title_underline_re.match(line) - if m and last_line: - current_title = last_line.strip() - continue - - m = module_re.match(line) - if m: - current_module = m.group(2) - continue - finally: - last_line = line - - return documented - -if __name__ == "__main__": - main() diff --git a/doc/sphinxext/docscrape.py b/doc/sphinxext/docscrape.py index 63fec42ad..615ea11f8 100644 --- a/doc/sphinxext/docscrape.py +++ b/doc/sphinxext/docscrape.py @@ -284,8 +284,8 @@ class NumpyDocString(object): for (section,content) in self._read_sections(): if not section.startswith('..'): section = ' '.join([s.capitalize() for s in section.split(' ')]) - if section in ('Parameters', 'Attributes', 'Methods', - 'Returns', 'Raises', 'Warns'): + 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) @@ -381,7 +381,8 @@ class NumpyDocString(object): 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', 'Other Parameters', + 'Raises', 'Warns'): out += self._str_param_list(param_list) out += self._str_section('Warnings') out += self._str_see_also(func_role) diff --git a/doc/sphinxext/docscrape_sphinx.py b/doc/sphinxext/docscrape_sphinx.py index 9f4350d46..e44e770ef 100644 --- a/doc/sphinxext/docscrape_sphinx.py +++ b/doc/sphinxext/docscrape_sphinx.py @@ -178,7 +178,8 @@ class SphinxDocString(NumpyDocString): out += self._str_index() + [''] out += self._str_summary() out += self._str_extended_summary() - for param_list in ('Parameters', 'Returns', 'Raises'): + 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) diff --git a/doc/sphinxext/only_directives.py b/doc/sphinxext/only_directives.py deleted file mode 100644 index c0dff7e65..000000000 --- a/doc/sphinxext/only_directives.py +++ /dev/null @@ -1,96 +0,0 @@ -# -# A pair of directives for inserting content that will only appear in -# either html or latex. -# - -from docutils.nodes import Body, Element -from docutils.writers.html4css1 import HTMLTranslator -try: - from sphinx.latexwriter import LaTeXTranslator -except ImportError: - from sphinx.writers.latex import LaTeXTranslator - - import warnings - warnings.warn("The numpydoc.only_directives module is deprecated;" - "please use the only:: directive available in Sphinx >= 0.6", - DeprecationWarning, stacklevel=2) - -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) - state.nested_parse(content, content_offset, node) - return [node] - -try: - from docutils.parsers.rst import Directive -except ImportError: - from docutils.parsers.rst.directives import _directives - - def html_only_directive(name, arguments, options, content, lineno, - content_offset, block_text, state, state_machine): - return run(content, html_only, state, content_offset) - - def latex_only_directive(name, arguments, options, content, lineno, - content_offset, block_text, state, state_machine): - return run(content, latex_only, state, content_offset) - - for func in (html_only_directive, latex_only_directive): - func.content = 1 - func.options = {} - func.arguments = None - - _directives['htmlonly'] = html_only_directive - _directives['latexonly'] = latex_only_directive -else: - class OnlyDirective(Directive): - has_content = True - required_arguments = 0 - optional_arguments = 0 - final_argument_whitespace = True - option_spec = {} - - def run(self): - self.assert_has_content() - return run(self.content, self.node_class, - self.state, self.content_offset) - - class HtmlOnlyDirective(OnlyDirective): - node_class = html_only - - class LatexOnlyDirective(OnlyDirective): - node_class = latex_only - - directives.register_directive('htmlonly', HtmlOnlyDirective) - directives.register_directive('latexonly', LatexOnlyDirective) - -def setup(app): - app.add_node(html_only) - app.add_node(latex_only) - - # 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 = [] - - HTMLTranslator.visit_html_only = visit_perform - HTMLTranslator.depart_html_only = depart_perform - HTMLTranslator.visit_latex_only = visit_ignore - HTMLTranslator.depart_latex_only = depart_ignore - - LaTeXTranslator.visit_html_only = visit_ignore - LaTeXTranslator.depart_html_only = depart_ignore - LaTeXTranslator.visit_latex_only = visit_perform - LaTeXTranslator.depart_latex_only = depart_perform diff --git a/doc/sphinxext/plot_directive.py b/doc/sphinxext/plot_directive.py index efbd0d303..80801e798 100644 --- a/doc/sphinxext/plot_directive.py +++ b/doc/sphinxext/plot_directive.py @@ -317,12 +317,8 @@ def run(arguments, content, options, state_machine, state, lineno): opts = [':%s: %s' % (key, val) for key, val in options.items() if key in ('alt', 'height', 'width', 'scale', 'align', 'class')] - if sphinx.__version__ >= "0.6": - only_html = ".. only:: html" - only_latex = ".. only:: latex" - else: - only_html = ".. htmlonly::" - only_latex = ".. latexonly::" + only_html = ".. only:: html" + only_latex = ".. only:: latex" if j == 0: src_link = source_link diff --git a/doc/sphinxext/setup.py b/doc/sphinxext/setup.py index 016d8f8ae..76e3fd81b 100644 --- a/doc/sphinxext/setup.py +++ b/doc/sphinxext/setup.py @@ -2,7 +2,7 @@ from distutils.core import setup import setuptools import sys, os -version = "0.3.dev" +version = "0.4" setup( name="numpydoc", @@ -18,10 +18,10 @@ setup( keywords="sphinx numpy", author="Pauli Virtanen and others", author_email="pav@iki.fi", - url="http://projects.scipy.org/numpy/browser/trunk/doc/sphinxext", + url="http://github.com/numpy/numpy/tree/master/doc/sphinxext", license="BSD", zip_safe=False, - install_requires=["Sphinx >= 0.5"], + install_requires=["Sphinx >= 1.0.1"], package_data={'numpydoc': 'tests', '': ''}, entry_points={ "console_scripts": [ diff --git a/doc/sphinxext/tests/test_docscrape.py b/doc/sphinxext/tests/test_docscrape.py index 1d775e99e..6fab79832 100644 --- a/doc/sphinxext/tests/test_docscrape.py +++ b/doc/sphinxext/tests/test_docscrape.py @@ -8,7 +8,7 @@ from docscrape_sphinx import SphinxDocString, SphinxClassDoc from nose.tools import * doc_txt = '''\ - numpy.multivariate_normal(mean, cov, shape=None) + numpy.multivariate_normal(mean, cov, shape=None, spam=None) Draw values from a multivariate normal distribution with specified mean and covariance. @@ -42,6 +42,21 @@ doc_txt = '''\ 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. @@ -102,7 +117,7 @@ doc = NumpyDocString(doc_txt) def test_signature(): assert doc['Signature'].startswith('numpy.multivariate_normal(') - assert doc['Signature'].endswith('shape=None)') + assert doc['Signature'].endswith('spam=None)') def test_summary(): assert doc['Summary'][0].startswith('Draw values') @@ -120,6 +135,13 @@ def test_parameters(): 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] @@ -157,7 +179,7 @@ def non_blank_line_by_line_compare(a,b): (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, spam=None) Draw values from a multivariate normal distribution with specified mean and covariance. @@ -191,6 +213,21 @@ out : ndarray 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. @@ -291,6 +328,24 @@ of the one-dimensional normal distribution to higher dimensions. 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. @@ -390,6 +445,10 @@ doc5 = NumpyDocString( LinAlgException If array is singular. + Warns + ----- + SomeWarning + If needed """) def test_raises(): @@ -398,6 +457,12 @@ def test_raises(): 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( """ @@ -543,3 +608,8 @@ def test_class_members(): if cls is SphinxClassDoc: assert '.. autosummary::' in str(doc), str(doc) + +if __name__ == "__main__": + import nose + nose.run() + diff --git a/numpy/core/setup.py b/numpy/core/setup.py index ad8d5cb3b..f71ec108a 100644 --- a/numpy/core/setup.py +++ b/numpy/core/setup.py @@ -215,10 +215,13 @@ def check_ieee_macros(config): _macros = ["isnan", "isinf", "signbit", "isfinite"] if sys.version_info[:2] >= (2, 6): for f in _macros: - already_declared = config.check_decl(fname2def("decl_%s" % f), + py_symbol = fname2def("decl_%s" % f) + already_declared = config.check_decl(py_symbol, headers=["Python.h", "math.h"]) if already_declared: - pub.append('NPY_%s' % fname2def("decl_%s" % f)) + if config.check_macro_true(py_symbol, + headers=["Python.h", "math.h"]): + pub.append('NPY_%s' % fname2def("decl_%s" % f)) else: macros.append(f) else: diff --git a/numpy/core/src/multiarray/arrayobject.c b/numpy/core/src/multiarray/arrayobject.c index ab1e824be..587e45d26 100644 --- a/numpy/core/src/multiarray/arrayobject.c +++ b/numpy/core/src/multiarray/arrayobject.c @@ -907,16 +907,15 @@ array_richcompare(PyArrayObject *self, PyObject *other, int cmp_op) array_other = PyArray_FromObject(other, typenum, 0, 0); /* - * If not successful, then return False. This fixes code - * that used to allow equality comparisons between arrays - * and other objects which would give a result of False. + * If not successful, indicate that the items cannot be compared + * this way. */ if ((array_other == NULL) || (array_other == Py_None)) { Py_XDECREF(array_other); PyErr_Clear(); - Py_INCREF(Py_False); - return Py_False; + Py_INCREF(Py_NotImplemented); + return Py_NotImplemented; } } else { @@ -952,14 +951,14 @@ array_richcompare(PyArrayObject *self, PyObject *other, int cmp_op) } /* * If the comparison results in NULL, then the - * two array objects can not be compared together so - * return zero + * two array objects can not be compared together; + * indicate that */ Py_DECREF(array_other); if (result == NULL) { PyErr_Clear(); - Py_INCREF(Py_False); - return Py_False; + Py_INCREF(Py_NotImplemented); + return Py_NotImplemented; } break; case Py_NE: @@ -976,14 +975,13 @@ array_richcompare(PyArrayObject *self, PyObject *other, int cmp_op) array_other = PyArray_FromObject(other, typenum, 0, 0); /* * If not successful, then objects cannot be - * compared and cannot be equal, therefore, - * return True; + * compared this way */ if ((array_other == NULL) || (array_other == Py_None)) { Py_XDECREF(array_other); PyErr_Clear(); - Py_INCREF(Py_True); - return Py_True; + Py_INCREF(Py_NotImplemented); + return Py_NotImplemented; } } else { @@ -1021,8 +1019,8 @@ array_richcompare(PyArrayObject *self, PyObject *other, int cmp_op) Py_DECREF(array_other); if (result == NULL) { PyErr_Clear(); - Py_INCREF(Py_True); - return Py_True; + Py_INCREF(Py_NotImplemented); + return Py_NotImplemented; } break; case Py_GT: diff --git a/numpy/core/src/multiarray/convert_datatype.c b/numpy/core/src/multiarray/convert_datatype.c index 37b0e5e18..5cb62b82f 100644 --- a/numpy/core/src/multiarray/convert_datatype.c +++ b/numpy/core/src/multiarray/convert_datatype.c @@ -112,21 +112,25 @@ PyArray_GetCastFunc(PyArray_Descr *descr, int type_num) PyTypeNum_ISNUMBER(type_num) && !PyTypeNum_ISBOOL(type_num)) { PyObject *cls = NULL, *obj = NULL; + int ret; obj = PyImport_ImportModule("numpy.core"); if (obj) { cls = PyObject_GetAttrString(obj, "ComplexWarning"); Py_DECREF(obj); } #if PY_VERSION_HEX >= 0x02050000 - PyErr_WarnEx(cls, - "Casting complex values to real discards the imaginary " - "part", 0); + ret = PyErr_WarnEx(cls, + "Casting complex values to real discards the imaginary " + "part", 0); #else - PyErr_Warn(cls, - "Casting complex values to real discards the imaginary " - "part"); + ret = PyErr_Warn(cls, + "Casting complex values to real discards the imaginary " + "part"); #endif Py_XDECREF(cls); + if (ret < 0) { + return NULL; + } } if (castfunc) { return castfunc; diff --git a/numpy/core/src/multiarray/descriptor.c b/numpy/core/src/multiarray/descriptor.c index 74cb7da7a..f635e1c48 100644 --- a/numpy/core/src/multiarray/descriptor.c +++ b/numpy/core/src/multiarray/descriptor.c @@ -1828,6 +1828,7 @@ arraydescr_names_set(PyArray_Descr *self, PyObject *val) int N = 0; int i; PyObject *new_names; + PyObject *new_fields; if (self->names == NULL) { PyErr_SetString(PyExc_ValueError, "there are no fields defined"); @@ -1857,26 +1858,38 @@ arraydescr_names_set(PyArray_Descr *self, PyObject *val) } /* Update dictionary keys in fields */ new_names = PySequence_Tuple(val); + new_fields = PyDict_New(); for (i = 0; i < N; i++) { PyObject *key; PyObject *item; PyObject *new_key; + int ret; key = PyTuple_GET_ITEM(self->names, i); - /* Borrowed reference to item */ + /* Borrowed references to item and new_key */ item = PyDict_GetItem(self->fields, key); - /* Hold on to it even through DelItem */ - Py_INCREF(item); new_key = PyTuple_GET_ITEM(new_names, i); - PyDict_DelItem(self->fields, key); - PyDict_SetItem(self->fields, new_key, item); - /* self->fields now holds reference */ - Py_DECREF(item); + /* Check for duplicates */ + ret = PyDict_Contains(new_fields, new_key); + if (ret != 0) { + if (ret < 0) { + PyErr_Clear(); + } + PyErr_SetString(PyExc_ValueError, "Duplicate field names given."); + Py_DECREF(new_names); + Py_DECREF(new_fields); + return -1; + } + PyDict_SetItem(new_fields, new_key, item); } /* Replace names */ Py_DECREF(self->names); self->names = new_names; + /* Replace fields */ + Py_DECREF(self->fields); + self->fields = new_fields; + return 0; } diff --git a/numpy/core/src/scalarmathmodule.c.src b/numpy/core/src/scalarmathmodule.c.src index f3ee6724e..6261c4c73 100644 --- a/numpy/core/src/scalarmathmodule.c.src +++ b/numpy/core/src/scalarmathmodule.c.src @@ -974,10 +974,11 @@ NONZERO_NAME(@name@_,)(PyObject *a) /**end repeat**/ -static void +static int emit_complexwarning() { static PyObject *cls = NULL; + int ret; if (cls == NULL) { PyObject *mod; mod = PyImport_ImportModule("numpy.core"); @@ -987,13 +988,13 @@ emit_complexwarning() Py_DECREF(mod); } #if PY_VERSION_HEX >= 0x02050000 - PyErr_WarnEx(cls, - "Casting complex values to real discards the imaginary " - "part", 0); + return PyErr_WarnEx(cls, + "Casting complex values to real discards the imaginary " + "part", 0); #else - PyErr_Warn(cls, - "Casting complex values to real discards the imaginary " - "part"); + return PyErr_Warn(cls, + "Casting complex values to real discards the imaginary " + "part"); #endif } @@ -1003,7 +1004,7 @@ emit_complexwarning() * #Name=Byte,UByte,Short,UShort,Int,UInt,Long,ULong,LongLong,ULongLong,Float,Double,LongDouble,CFloat,CDouble,CLongDouble# * #cmplx=0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1# * #sign=(signed,unsigned)*5,,,,,,# - * #unsigntyp=0,1,0,1,0,1,0,1,0,1,1*6# + * #unsigntyp=0,1,0,1,0,1,0,1,0,1,0*6# * #ctype=long*8,PY_LONG_LONG*2,double*6# * #realtyp=0*10,1*6# * #func=(PyLong_FromLong,PyLong_FromUnsignedLong)*4,PyLong_FromLongLong,PyLong_FromUnsignedLongLong,PyLong_FromDouble*6# @@ -1013,6 +1014,7 @@ static PyObject * { #if @cmplx@ @sign@ @ctype@ x= PyArrayScalar_VAL(obj, @Name@).real; + int ret; #else @sign@ @ctype@ x= PyArrayScalar_VAL(obj, @Name@); #endif @@ -1022,15 +1024,14 @@ static PyObject * x = ix; #endif #if @cmplx@ - emit_complexwarning(); + ret = emit_complexwarning(); + if (ret < 0) { + return NULL; + } #endif -/* - * For unsigned type, the (@ctype@) cast just does what is implicitely done by - * the compiler. - */ #if @unsigntyp@ - if(LONG_MIN < (@ctype@)x && (@ctype@)x < LONG_MAX) + if(x < LONG_MAX) return PyInt_FromLong(x); #else if(LONG_MIN < x && x < LONG_MAX) @@ -1052,7 +1053,11 @@ static PyObject * @name@_@which@(PyObject *obj) { #if @cmplx@ - emit_complexwarning(); + int ret; + ret = emit_complexwarning(); + if (ret < 0) { + return NULL; + } return @func@((PyArrayScalar_VAL(obj, @Name@)).real); #else return @func@((PyArrayScalar_VAL(obj, @Name@))); diff --git a/numpy/core/src/umath/loops.c.src b/numpy/core/src/umath/loops.c.src index e77da0691..850126482 100644 --- a/numpy/core/src/umath/loops.c.src +++ b/numpy/core/src/umath/loops.c.src @@ -1546,9 +1546,9 @@ C@TYPE@_sign(char **args, intp *dimensions, intp *steps, void *NPY_UNUSED(func)) UNARY_LOOP { const @type@ in1r = ((@type@ *)ip1)[0]; const @type@ in1i = ((@type@ *)ip1)[1]; - ((@type@ *)op1)[0] = CGT(in1r, in1i, 0, 0) ? 1 : - (CLT(in1r, in1i, 0, 0) ? -1 : - (CEQ(in1r, in1i, 0, 0) ? 0 : NPY_NAN@C@)); + ((@type@ *)op1)[0] = CGT(in1r, in1i, 0.0, 0.0) ? 1 : + (CLT(in1r, in1i, 0.0, 0.0) ? -1 : + (CEQ(in1r, in1i, 0.0, 0.0) ? 0 : NPY_NAN@C@)); ((@type@ *)op1)[1] = 0; } } diff --git a/numpy/core/tests/test_multiarray.py b/numpy/core/tests/test_multiarray.py index 45cc1c858..7c38fcf56 100644 --- a/numpy/core/tests/test_multiarray.py +++ b/numpy/core/tests/test_multiarray.py @@ -1512,6 +1512,7 @@ class TestWarnings(object): warnings.simplefilter("error", np.ComplexWarning) assert_raises(np.ComplexWarning, x.__setitem__, slice(None), y) + assert_equal(x, [1,2]) warnings.simplefilter("default", np.ComplexWarning) if sys.version_info >= (2, 6): diff --git a/numpy/core/tests/test_regression.py b/numpy/core/tests/test_regression.py index 49490c05a..12fe089e6 100644 --- a/numpy/core/tests/test_regression.py +++ b/numpy/core/tests/test_regression.py @@ -1416,5 +1416,23 @@ class TestRegression(TestCase): x = tp(1+2j) assert_equal(complex(x), 1+2j) + def test_uint_int_conversion(self): + x = 2**64 - 1 + assert_equal(int(np.uint64(x)), x) + + def test_duplicate_field_names_assign(self): + ra = np.fromiter(((i*3, i*2) for i in xrange(10)), dtype='i8,f8') + ra.dtype.names = ('f1', 'f2') + rep = repr(ra) # should not cause a segmentation fault + assert_raises(ValueError, setattr, ra.dtype, 'names', ('f1', 'f1')) + + def test_eq_string_and_object_array(self): + # From e-mail thread "__eq__ with str and object" (Keith Goodman) + a1 = np.array(['a', 'b'], dtype=object) + a2 = np.array(['a', 'c']) + assert_array_equal(a1 == a2, [True, False]) + assert_array_equal(a2 == a1, [True, False]) + + if __name__ == "__main__": run_module_suite() diff --git a/numpy/distutils/command/config.py b/numpy/distutils/command/config.py index dafc7002f..85a86990f 100644 --- a/numpy/distutils/command/config.py +++ b/numpy/distutils/command/config.py @@ -169,6 +169,22 @@ int main() return self.try_compile(body, headers, include_dirs) + def check_macro_true(self, symbol, + headers=None, include_dirs=None): + self._check_compiler() + body = """ +int main() +{ +#if %s +#else +#error false or undefined macro +#endif + ; + return 0; +}""" % (symbol,) + + return self.try_compile(body, headers, include_dirs) + def check_type(self, type_name, headers=None, include_dirs=None, library_dirs=None): """Check type availability. Return True if the type can be compiled, diff --git a/numpy/distutils/fcompiler/__init__.py b/numpy/distutils/fcompiler/__init__.py index 3fd3f22dc..5c9395869 100644 --- a/numpy/distutils/fcompiler/__init__.py +++ b/numpy/distutils/fcompiler/__init__.py @@ -695,14 +695,14 @@ _default_compilers = ( ('cygwin.*', ('gnu','intelv','absoft','compaqv','intelev','gnu95','g95')), ('linux.*', ('gnu','intel','lahey','pg','absoft','nag','vast','compaq', 'intele','intelem','gnu95','g95')), - ('darwin.*', ('nag', 'absoft', 'ibm', 'intel', 'gnu', 'gnu95', 'g95')), + ('darwin.*', ('nag', 'absoft', 'ibm', 'intel', 'gnu', 'gnu95', 'g95', 'pg')), ('sunos.*', ('sun','gnu','gnu95','g95')), ('irix.*', ('mips','gnu','gnu95',)), ('aix.*', ('ibm','gnu','gnu95',)), # os.name mappings ('posix', ('gnu','gnu95',)), ('nt', ('gnu','gnu95',)), - ('mac', ('gnu','gnu95',)), + ('mac', ('gnu','gnu95','pg')), ) fcompiler_class = None diff --git a/numpy/distutils/fcompiler/pg.py b/numpy/distutils/fcompiler/pg.py index 60c7f4e4b..a34669c36 100644 --- a/numpy/distutils/fcompiler/pg.py +++ b/numpy/distutils/fcompiler/pg.py @@ -2,6 +2,7 @@ # http://www.pgroup.com from numpy.distutils.fcompiler import FCompiler +from sys import platform compilers = ['PGroupFCompiler'] @@ -11,7 +12,19 @@ class PGroupFCompiler(FCompiler): description = 'Portland Group Fortran Compiler' version_pattern = r'\s*pg(f77|f90|hpf) (?P<version>[\d.-]+).*' - executables = { + if platform == 'darwin': + executables = { + 'version_cmd' : ["<F77>", "-V 2>/dev/null"], + 'compiler_f77' : ["pgf77", "-dynamiclib"], + 'compiler_fix' : ["pgf90", "-Mfixed", "-dynamiclib"], + 'compiler_f90' : ["pgf90", "-dynamiclib"], + 'linker_so' : ["libtool"], + 'archiver' : ["ar", "-cr"], + 'ranlib' : ["ranlib"] + } + pic_flags = [''] + else: + executables = { 'version_cmd' : ["<F77>", "-V 2>/dev/null"], 'compiler_f77' : ["pgf77"], 'compiler_fix' : ["pgf90", "-Mfixed"], @@ -20,7 +33,9 @@ class PGroupFCompiler(FCompiler): 'archiver' : ["ar", "-cr"], 'ranlib' : ["ranlib"] } - pic_flags = ['-fpic'] + pic_flags = ['-fpic'] + + module_dir_switch = '-module ' module_include_switch = '-I' @@ -31,6 +46,10 @@ class PGroupFCompiler(FCompiler): return ['-fast'] def get_flags_debug(self): return ['-g'] + + if platform == 'darwin': + def get_flags_linker_so(self): + return ["-dynamic", '-undefined', 'dynamic_lookup'] if __name__ == '__main__': from distutils import log diff --git a/numpy/f2py/capi_maps.py b/numpy/f2py/capi_maps.py index cba98af2b..c10e3ee84 100644 --- a/numpy/f2py/capi_maps.py +++ b/numpy/f2py/capi_maps.py @@ -643,8 +643,10 @@ def modsign2map(m): else: ret['interface_usercode'] = '' ret['pymethoddef'] = getpymethoddef(m) or '' - ret['coutput'] = m['coutput'] - ret['f2py_wrapper_output'] = m['f2py_wrapper_output'] + if 'coutput' in m: + ret['coutput'] = m['coutput'] + if 'f2py_wrapper_output' in m: + ret['f2py_wrapper_output'] = m['f2py_wrapper_output'] return ret def cb_sign2map(a,var,index=None): diff --git a/numpy/lib/index_tricks.py b/numpy/lib/index_tricks.py index eb1ab22e9..264ebaad0 100644 --- a/numpy/lib/index_tricks.py +++ b/numpy/lib/index_tricks.py @@ -700,24 +700,15 @@ class IndexExpression(object): array([2, 4]) """ - maxint = sys.maxint def __init__(self, maketuple): self.maketuple = maketuple def __getitem__(self, item): - if self.maketuple and type(item) != type(()): + if self.maketuple and type(item) != tuple: return (item,) else: return item - def __len__(self): - return self.maxint - - def __getslice__(self, start, stop): - if stop == self.maxint: - stop = None - return self[start:stop:None] - index_exp = IndexExpression(maketuple=True) s_ = IndexExpression(maketuple=False) diff --git a/numpy/lib/npyio.py b/numpy/lib/npyio.py index 8c4a1a823..2668357bc 100644 --- a/numpy/lib/npyio.py +++ b/numpy/lib/npyio.py @@ -1,6 +1,6 @@ __all__ = ['savetxt', 'loadtxt', 'genfromtxt', 'ndfromtxt', 'mafromtxt', - 'recfromtxt', 'recfromcsv', 'load', 'loads', 'save', 'savez', - 'packbits', 'unpackbits', 'fromregex', 'DataSource'] + 'recfromtxt', 'recfromcsv', 'load', 'loads', 'save', 'savez', + 'savez_compressed', 'packbits', 'unpackbits', 'fromregex', 'DataSource'] import numpy as np import format @@ -108,7 +108,11 @@ class BagObj(object): except KeyError: raise AttributeError, key - +def zipfile_factory(*args, **kwargs): + import zipfile + if sys.version_info >= (2, 5): + kwargs['allowZip64'] = True + return zipfile.ZipFile(*args, **kwargs) class NpzFile(object): """ @@ -142,6 +146,9 @@ class NpzFile(object): fid : file or str The zipped archive to open. This is either a file-like object or a string containing the path to the archive. + own_fid : bool, optional + Whether NpzFile should close the file handle. + Requires that `fid` is a file-like object. Examples -------- @@ -163,11 +170,10 @@ class NpzFile(object): array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) """ - def __init__(self, fid): + def __init__(self, fid, own_fid=False): # Import is postponed to here since zipfile depends on gzip, an optional # component of the so-called standard library. - import zipfile - _zip = zipfile.ZipFile(fid) + _zip = zipfile_factory(fid) self._files = _zip.namelist() self.files = [] for x in self._files: @@ -177,6 +183,25 @@ class NpzFile(object): self.files.append(x) self.zip = _zip self.f = BagObj(self) + if own_fid: + self.fid = fid + else: + self.fid = None + + def close(self): + """ + Close the file. + + """ + if self.zip is not None: + self.zip.close() + self.zip = None + if self.fid is not None: + self.fid.close() + self.fid = None + + def __del__(self): + self.close() def __getitem__(self, key): # FIXME: This seems like it will copy strings around @@ -293,31 +318,39 @@ def load(file, mmap_mode=None): """ import gzip + own_fid = False if isinstance(file, basestring): fid = open(file, "rb") + own_fid = True elif isinstance(file, gzip.GzipFile): fid = seek_gzip_factory(file) + own_fid = True else: fid = file - # Code to distinguish from NumPy binary files and pickles. - _ZIP_PREFIX = asbytes('PK\x03\x04') - N = len(format.MAGIC_PREFIX) - magic = fid.read(N) - fid.seek(-N, 1) # back-up - if magic.startswith(_ZIP_PREFIX): # zip-file (assume .npz) - return NpzFile(fid) - elif magic == format.MAGIC_PREFIX: # .npy file - if mmap_mode: - return format.open_memmap(file, mode=mmap_mode) - else: - return format.read_array(fid) - else: # Try a pickle - try: - return _cload(fid) - except: - raise IOError, \ - "Failed to interpret file %s as a pickle" % repr(file) + try: + # Code to distinguish from NumPy binary files and pickles. + _ZIP_PREFIX = asbytes('PK\x03\x04') + N = len(format.MAGIC_PREFIX) + magic = fid.read(N) + fid.seek(-N, 1) # back-up + if magic.startswith(_ZIP_PREFIX): # zip-file (assume .npz) + own_fid = False + return NpzFile(fid, own_fid=True) + elif magic == format.MAGIC_PREFIX: # .npy file + if mmap_mode: + return format.open_memmap(file, mode=mmap_mode) + else: + return format.read_array(fid) + else: # Try a pickle + try: + return _cload(fid) + except: + raise IOError, \ + "Failed to interpret file %s as a pickle" % repr(file) + finally: + if own_fid: + fid.close() def save(file, arr): """ @@ -335,7 +368,7 @@ def save(file, arr): See Also -------- - savez : Save several arrays into a ``.npz`` compressed archive + savez : Save several arrays into a ``.npz`` archive savetxt, load Notes @@ -355,19 +388,25 @@ def save(file, arr): array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) """ + own_fid = False if isinstance(file, basestring): if not file.endswith('.npy'): file = file + '.npy' fid = open(file, "wb") + own_fid = True else: fid = file - arr = np.asanyarray(arr) - format.write_array(fid, arr) + try: + arr = np.asanyarray(arr) + format.write_array(fid, arr) + finally: + if own_fid: + fid.close() def savez(file, *args, **kwds): """ - Save several arrays into a single, archive file in ``.npz`` format. + Save several arrays into a single file in uncompressed ``.npz`` format. If arguments are passed in with no keywords, the corresponding variable names, in the .npz file, are 'arr_0', 'arr_1', etc. If keyword arguments @@ -380,12 +419,12 @@ def savez(file, *args, **kwds): Either the file name (string) or an open file (file-like object) where the data will be saved. If file is a string, the ``.npz`` extension will be appended to the file name if it is not already there. - \\*args : Arguments, optional + *args : Arguments, optional Arrays to save to the file. Since it is not possible for Python to know the names of the arrays outside `savez`, the arrays will be saved with names "arr_0", "arr_1", and so on. These arguments can be any expression. - \\*\\*kwds : Keyword arguments, optional + **kwds : Keyword arguments, optional Arrays to save to the file. Arrays will be saved in the file with the keyword names. @@ -417,7 +456,7 @@ def savez(file, *args, **kwds): >>> x = np.arange(10) >>> y = np.sin(x) - Using `savez` with \\*args, the arrays are saved with default names. + Using `savez` with *args, the arrays are saved with default names. >>> np.savez(outfile, x, y) >>> outfile.seek(0) # Only needed here to simulate closing & reopening file @@ -427,7 +466,7 @@ def savez(file, *args, **kwds): >>> npzfile['arr_0'] array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) - Using `savez` with \\*\\*kwds, the arrays are saved with the keyword names. + Using `savez` with **kwds, the arrays are saved with the keyword names. >>> outfile = TemporaryFile() >>> np.savez(outfile, x=x, y=y) @@ -438,8 +477,38 @@ def savez(file, *args, **kwds): >>> npzfile['x'] array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) + See Also + -------- + numpy.savez_compressed : Save several arrays into a compressed .npz file format + + """ + _savez(file, args, kwds, False) + +def savez_compressed(file, *args, **kwds): """ + Save several arrays into a single file in compressed ``.npz`` format. + + If keyword arguments are given, then filenames are taken from the keywords. + If arguments are passed in with no keywords, then stored file names are + arr_0, arr_1, etc. + Parameters + ---------- + file : string + File name of .npz file. + args : Arguments + Function arguments. + kwds : Keyword arguments + Keywords. + + See Also + -------- + numpy.savez : Save several arrays into an uncompressed .npz file format + + """ + _savez(file, args, kwds, True) + +def _savez(file, args, kwds, compress): # Import is postponed to here since zipfile depends on gzip, an optional # component of the so-called standard library. import zipfile @@ -457,7 +526,12 @@ def savez(file, *args, **kwds): raise ValueError, "Cannot use un-named variables and keyword %s" % key namedict[key] = val - zip = zipfile.ZipFile(file, mode="w") + if compress: + compression = zipfile.ZIP_DEFLATED + else: + compression = zipfile.ZIP_STORED + + zip = zipfile_factory(file, mode="w", compression=compression) # Stage arrays in a temporary file on disk, before writing to zip. fd, tmpfile = tempfile.mkstemp(suffix='-numpy.npy') @@ -586,9 +660,9 @@ def loadtxt(fname, dtype=float, comments='#', delimiter=None, if usecols is not None: usecols = list(usecols) - isstring = False + own_fh = False if _is_string_like(fname): - isstring = True + own_fh = True if fname.endswith('.gz'): import gzip fh = seek_gzip_factory(fname) @@ -676,7 +750,7 @@ def loadtxt(fname, dtype=float, comments='#', delimiter=None, # Convert each value according to its column and store X.append(tuple([conv(val) for (conv, val) in zip(converters, vals)])) finally: - if isstring: + if own_fh: fh.close() if len(dtype_types) > 1: @@ -798,7 +872,9 @@ def savetxt(fname, X, fmt='%.18e', delimiter=' ', newline='\n'): fmt = asstr(fmt) delimiter = asstr(delimiter) + own_fh = False if _is_string_like(fname): + own_fh = True if fname.endswith('.gz'): import gzip fh = gzip.open(fname, 'wb') @@ -812,39 +888,43 @@ def savetxt(fname, X, fmt='%.18e', delimiter=' ', newline='\n'): else: raise ValueError('fname must be a string or file handle') - X = np.asarray(X) + try: + X = np.asarray(X) - # Handle 1-dimensional arrays - if X.ndim == 1: - # Common case -- 1d array of numbers - if X.dtype.names is None: - X = np.atleast_2d(X).T - ncol = 1 + # Handle 1-dimensional arrays + if X.ndim == 1: + # Common case -- 1d array of numbers + if X.dtype.names is None: + X = np.atleast_2d(X).T + ncol = 1 - # Complex dtype -- each field indicates a separate column - else: - ncol = len(X.dtype.descr) - else: - ncol = X.shape[1] - - # `fmt` can be a string with multiple insertion points or a list of formats. - # E.g. '%10.5f\t%10d' or ('%10.5f', '$10d') - if type(fmt) in (list, tuple): - if len(fmt) != ncol: - raise AttributeError('fmt has wrong shape. %s' % str(fmt)) - format = asstr(delimiter).join(map(asstr, fmt)) - elif type(fmt) is str: - if fmt.count('%') == 1: - fmt = [fmt, ]*ncol - format = delimiter.join(fmt) - elif fmt.count('%') != ncol: - raise AttributeError('fmt has wrong number of %% formats. %s' - % fmt) + # Complex dtype -- each field indicates a separate column + else: + ncol = len(X.dtype.descr) else: - format = fmt + ncol = X.shape[1] + + # `fmt` can be a string with multiple insertion points or a + # list of formats. E.g. '%10.5f\t%10d' or ('%10.5f', '$10d') + if type(fmt) in (list, tuple): + if len(fmt) != ncol: + raise AttributeError('fmt has wrong shape. %s' % str(fmt)) + format = asstr(delimiter).join(map(asstr, fmt)) + elif type(fmt) is str: + if fmt.count('%') == 1: + fmt = [fmt, ]*ncol + format = delimiter.join(fmt) + elif fmt.count('%') != ncol: + raise AttributeError('fmt has wrong number of %% formats. %s' + % fmt) + else: + format = fmt - for row in X: - fh.write(asbytes(format % tuple(row) + newline)) + for row in X: + fh.write(asbytes(format % tuple(row) + newline)) + finally: + if own_fh: + fh.close() import re def fromregex(file, regexp, dtype): @@ -902,25 +982,32 @@ def fromregex(file, regexp, dtype): array([1312, 1534, 444], dtype=int64) """ + own_fh = False if not hasattr(file, "read"): file = open(file, 'rb') - if not hasattr(regexp, 'match'): - regexp = re.compile(asbytes(regexp)) - if not isinstance(dtype, np.dtype): - dtype = np.dtype(dtype) + own_fh = True - seq = regexp.findall(file.read()) - if seq and not isinstance(seq[0], tuple): - # Only one group is in the regexp. - # Create the new array as a single data-type and then - # re-interpret as a single-field structured array. - newdtype = np.dtype(dtype[dtype.names[0]]) - output = np.array(seq, dtype=newdtype) - output.dtype = dtype - else: - output = np.array(seq, dtype=dtype) + try: + if not hasattr(regexp, 'match'): + regexp = re.compile(asbytes(regexp)) + if not isinstance(dtype, np.dtype): + dtype = np.dtype(dtype) + + seq = regexp.findall(file.read()) + if seq and not isinstance(seq[0], tuple): + # Only one group is in the regexp. + # Create the new array as a single data-type and then + # re-interpret as a single-field structured array. + newdtype = np.dtype(dtype[dtype.names[0]]) + output = np.array(seq, dtype=newdtype) + output.dtype = dtype + else: + output = np.array(seq, dtype=dtype) - return output + return output + finally: + if own_fh: + fh.close() @@ -1092,8 +1179,10 @@ def genfromtxt(fname, dtype=float, comments='#', delimiter=None, raise TypeError(errmsg % type(user_converters)) # Initialize the filehandle, the LineSplitter and the NameValidator + own_fhd = False if isinstance(fname, basestring): fhd = np.lib._datasource.open(fname, 'U') + own_fhd = True elif not hasattr(fname, 'read'): raise TypeError("The input should be a string or a filehandle. "\ "(got %s instead)" % type(fname)) @@ -1354,6 +1443,8 @@ def genfromtxt(fname, dtype=float, comments='#', delimiter=None, append_to_masks(tuple([v.strip() in m for (v, m) in zip(values, missing_values)])) + if own_fhd: + fhd.close() # Upgrade the converters (if needed) if dtype is None: diff --git a/numpy/lib/tests/test_index_tricks.py b/numpy/lib/tests/test_index_tricks.py index 3307cef3e..c17ee5d6a 100644 --- a/numpy/lib/tests/test_index_tricks.py +++ b/numpy/lib/tests/test_index_tricks.py @@ -2,7 +2,7 @@ from numpy.testing import * import numpy as np from numpy import ( array, ones, r_, mgrid, unravel_index, zeros, where, ndenumerate, fill_diagonal, diag_indices, - diag_indices_from ) + diag_indices_from, s_, index_exp ) class TestUnravelIndex(TestCase): def test_basic(self): @@ -77,6 +77,19 @@ class TestNdenumerate(TestCase): [((0,0), 1), ((0,1), 2), ((1,0), 3), ((1,1), 4)]) +class TestIndexExpression(TestCase): + def test_regression_1(self): + # ticket #1196 + a = np.arange(2) + assert_equal(a[:-1], a[s_[:-1]]) + assert_equal(a[:-1], a[index_exp[:-1]]) + + def test_simple_1(self): + a = np.random.rand(4,5,6) + + assert_equal(a[:,:3,[1,2]], a[index_exp[:,:3,[1,2]]]) + assert_equal(a[:,:3,[1,2]], a[s_[:,:3,[1,2]]]) + def test_fill_diagonal(): a = zeros((3, 3),int) fill_diagonal(a, 5) diff --git a/numpy/linalg/linalg.py b/numpy/linalg/linalg.py index eb8c8379a..c044176cf 100644 --- a/numpy/linalg/linalg.py +++ b/numpy/linalg/linalg.py @@ -1680,12 +1680,13 @@ def lstsq(a, b, rcond=-1): """ Return the least-squares solution to a linear matrix equation. - Solves the equation `a x = b` by computing a vector `x` that minimizes - the norm `|| b - a x ||`. The equation may be under-, well-, or over- - determined (i.e., the number of linearly independent rows of `a` can be - less than, equal to, or greater than its number of linearly independent - columns). If `a` is square and of full rank, then `x` (but for round-off - error) is the "exact" solution of the equation. + Solves the equation `a x = b` by computing a vector `x` that + minimizes the Euclidean 2-norm `|| b - a x ||^2`. The equation may + be under-, well-, or over- determined (i.e., the number of + linearly independent rows of `a` can be less than, equal to, or + greater than its number of linearly independent columns). If `a` + is square and of full rank, then `x` (but for round-off error) is + the "exact" solution of the equation. Parameters ---------- @@ -1706,7 +1707,7 @@ def lstsq(a, b, rcond=-1): Least-squares solution. The shape of `x` depends on the shape of `b`. residues : ndarray, shape (), (1,), or (K,) - Sums of residues; squared Euclidean norm for each column in + Sums of residues; squared Euclidean 2-norm for each column in ``b - a*x``. If the rank of `a` is < N or > M, this is an empty array. If `b` is 1-dimensional, this is a (1,) shape array. @@ -1772,6 +1773,7 @@ def lstsq(a, b, rcond=-1): if m != b.shape[0]: raise LinAlgError, 'Incompatible dimensions' t, result_t = _commonType(a, b) + result_real_t = _realType(result_t) real_t = _linalgRealType(t) bstar = zeros((ldb, n_rhs), t) bstar[:b.shape[0],:n_rhs] = b.copy() @@ -1811,16 +1813,27 @@ def lstsq(a, b, rcond=-1): 0, work, lwork, iwork, 0) if results['info'] > 0: raise LinAlgError, 'SVD did not converge in Linear Least Squares' - resids = array([], t) + resids = array([], result_real_t) if is_1d: x = array(ravel(bstar)[:n], dtype=result_t, copy=True) if results['rank'] == n and m > n: - resids = array([sum((ravel(bstar)[n:])**2)], dtype=result_t) + if isComplexType(t): + resids = array([sum(abs(ravel(bstar)[n:])**2)], + dtype=result_real_t) + else: + resids = array([sum((ravel(bstar)[n:])**2)], + dtype=result_real_t) else: x = array(transpose(bstar)[:n,:], dtype=result_t, copy=True) if results['rank'] == n and m > n: - resids = sum((transpose(bstar)[n:,:])**2, axis=0).astype(result_t) - st = s[:min(n, m)].copy().astype(_realType(result_t)) + if isComplexType(t): + resids = sum(abs(transpose(bstar)[n:,:])**2, axis=0).astype( + result_real_t) + else: + resids = sum((transpose(bstar)[n:,:])**2, axis=0).astype( + result_real_t) + + st = s[:min(n, m)].copy().astype(result_real_t) return wrap(x), wrap(resids), results['rank'], st def norm(x, ord=None): diff --git a/numpy/linalg/tests/test_linalg.py b/numpy/linalg/tests/test_linalg.py index 3a9584dd6..a672ed08a 100644 --- a/numpy/linalg/tests/test_linalg.py +++ b/numpy/linalg/tests/test_linalg.py @@ -33,6 +33,11 @@ class LinalgTestCase: b = array([2., 1.], dtype=double) self.do(a, b) + def test_double_2(self): + a = array([[1.,2.], [3.,4.]], dtype=double) + b = array([[2., 1., 4.], [3., 4., 6.]], dtype=double) + self.do(a, b) + def test_csingle(self): a = array([[1.+2j,2+3j], [3+4j,4+5j]], dtype=csingle) b = array([2.+1j, 1.+2j], dtype=csingle) @@ -43,6 +48,11 @@ class LinalgTestCase: b = array([2.+1j, 1.+2j], dtype=cdouble) self.do(a, b) + def test_cdouble_2(self): + a = array([[1.+2j,2+3j], [3+4j,4+5j]], dtype=cdouble) + b = array([[2.+1j, 1.+2j, 1+3j], [1-2j, 1-3j, 1-6j]], dtype=cdouble) + self.do(a, b) + def test_empty(self): a = atleast_2d(array([], dtype = double)) b = atleast_2d(array([], dtype = double)) @@ -70,6 +80,58 @@ class LinalgTestCase: self.do(a, b) +class LinalgNonsquareTestCase: + def test_single_nsq_1(self): + a = array([[1.,2.,3.], [3.,4.,6.]], dtype=single) + b = array([2., 1.], dtype=single) + self.do(a, b) + + def test_single_nsq_2(self): + a = array([[1.,2.], [3.,4.], [5.,6.]], dtype=single) + b = array([2., 1., 3.], dtype=single) + self.do(a, b) + + def test_double_nsq_1(self): + a = array([[1.,2.,3.], [3.,4.,6.]], dtype=double) + b = array([2., 1.], dtype=double) + self.do(a, b) + + def test_double_nsq_2(self): + a = array([[1.,2.], [3.,4.], [5.,6.]], dtype=double) + b = array([2., 1., 3.], dtype=double) + self.do(a, b) + + def test_csingle_nsq_1(self): + a = array([[1.+1j,2.+2j,3.-3j], [3.-5j,4.+9j,6.+2j]], dtype=csingle) + b = array([2.+1j, 1.+2j], dtype=csingle) + self.do(a, b) + + def test_csingle_nsq_2(self): + a = array([[1.+1j,2.+2j], [3.-3j,4.-9j], [5.-4j,6.+8j]], dtype=csingle) + b = array([2.+1j, 1.+2j, 3.-3j], dtype=csingle) + self.do(a, b) + + def test_cdouble_nsq_1(self): + a = array([[1.+1j,2.+2j,3.-3j], [3.-5j,4.+9j,6.+2j]], dtype=cdouble) + b = array([2.+1j, 1.+2j], dtype=cdouble) + self.do(a, b) + + def test_cdouble_nsq_2(self): + a = array([[1.+1j,2.+2j], [3.-3j,4.-9j], [5.-4j,6.+8j]], dtype=cdouble) + b = array([2.+1j, 1.+2j, 3.-3j], dtype=cdouble) + self.do(a, b) + + def test_cdouble_nsq_1_2(self): + a = array([[1.+1j,2.+2j,3.-3j], [3.-5j,4.+9j,6.+2j]], dtype=cdouble) + b = array([[2.+1j, 1.+2j], [1-1j, 2-2j]], dtype=cdouble) + self.do(a, b) + + def test_cdouble_nsq_2_2(self): + a = array([[1.+1j,2.+2j], [3.-3j,4.-9j], [5.-4j,6.+8j]], dtype=cdouble) + b = array([[2.+1j, 1.+2j], [1-1j, 2-2j], [1-1j, 2-2j]], dtype=cdouble) + self.do(a, b) + + class TestSolve(LinalgTestCase, TestCase): def do(self, a, b): x = linalg.solve(a, b) @@ -153,13 +215,28 @@ class TestDet(LinalgTestCase, TestCase): assert_equal(type(linalg.slogdet([[0.0j]])[0]), cdouble) assert_equal(type(linalg.slogdet([[0.0j]])[1]), double) -class TestLstsq(LinalgTestCase, TestCase): +class TestLstsq(LinalgTestCase, LinalgNonsquareTestCase, TestCase): def do(self, a, b): + arr = np.asarray(a) + m, n = arr.shape u, s, vt = linalg.svd(a, 0) x, residuals, rank, sv = linalg.lstsq(a, b) - assert_almost_equal(b, dot(a, x)) - assert_equal(rank, asarray(a).shape[0]) + if m <= n: + assert_almost_equal(b, dot(a, x)) + assert_equal(rank, m) + else: + assert_equal(rank, n) assert_almost_equal(sv, sv.__array_wrap__(s)) + if rank == n and m > n: + expect_resids = (np.asarray(abs(np.dot(a, x) - b))**2).sum(axis=0) + expect_resids = np.asarray(expect_resids) + if len(np.asarray(b).shape) == 1: + expect_resids.shape = (1,) + assert_equal(residuals.shape, expect_resids.shape) + else: + expect_resids = type(x)([]) + assert_almost_equal(residuals, expect_resids) + assert_(np.issubdtype(residuals.dtype, np.floating)) assert imply(isinstance(b, matrix), isinstance(x, matrix)) assert imply(isinstance(b, matrix), isinstance(residuals, matrix)) |