diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 7c07058b63ae6bde2d6562aa6933ad5ef7871f10..2025842631711bc383e175e4cb62ba3cab8674b3 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -39,3 +39,14 @@ Flake8: - python3.5 except: - tags + +Documentation: + script: + - EXTRA_INSTALL="numpy" + - curl -L -O -k https://gitlab.tiker.net/inducer/ci-support/raw/master/build-docs.sh + - ". ./build-docs.sh" + tags: + - python3.5 + only: + - master + diff --git a/README b/README deleted file mode 100644 index f4ef45f7edb2b80a7cd3f1edfb14b718c8c53115..0000000000000000000000000000000000000000 --- a/README +++ /dev/null @@ -1,6 +0,0 @@ -Miscellaneous Python lifesavers. - -Andreas Kloeckner <inform@tiker.net> - -Includes Michele Simionato's decorator module, from -http://www.phyast.pitt.edu/~micheles/python/ diff --git a/README.rst b/README.rst new file mode 100644 index 0000000000000000000000000000000000000000..b8c9ed9cef0063d797a0a181bb91520affdda3c3 --- /dev/null +++ b/README.rst @@ -0,0 +1,18 @@ +Pytools is a big bag of things that are "missing" from the Python standard +library. This is mainly a dependency of my other software packages, and is +probably of little interest to you unless you use those. If you're curious +nonetheless, here's what's on offer: + +* A ton of small tool functions such as `len_iterable`, `argmin`, + tuple generation, permutation generation, ASCII table pretty printing, + GvR's mokeypatch_xxx() hack, the elusive `flatten`, and much more. +* Michele Simionato's decorator module +* A time-series logging module, `pytools.log`. +* Batch job submission, `pytools.batchjob`. +* A lexer, `pytools.lex`. + +Links: + +* `Documentation <https://documen.tician.de/pytools>`_ + +* `Github <https://github.com/inducer/pytools>`_ diff --git a/doc/.gitignore b/doc/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..e35d8850c9688b1ce82711694692cc574a799396 --- /dev/null +++ b/doc/.gitignore @@ -0,0 +1 @@ +_build diff --git a/doc/Makefile b/doc/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..195e17ce0a2958904630a731b51ecfe4204d129c --- /dev/null +++ b/doc/Makefile @@ -0,0 +1,20 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +SPHINXPROJ = pytools +SOURCEDIR = . +BUILDDIR = _build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) \ No newline at end of file diff --git a/doc/conf.py b/doc/conf.py new file mode 100644 index 0000000000000000000000000000000000000000..c87091c3ef34558f6bc5d70e82fd3f09a25bac0a --- /dev/null +++ b/doc/conf.py @@ -0,0 +1,177 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# +# pytools documentation build configuration file, created by +# sphinx-quickstart on Wed Jun 14 16:28:43 2017. +# +# 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. + +# 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. +# +# import os +# import sys +# sys.path.insert(0, os.path.abspath('.')) + + +# -- General configuration ------------------------------------------------ + +# If your documentation needs a minimal Sphinx version, state it here. +# +# needs_sphinx = '1.0' + +# 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.autodoc', + 'sphinx.ext.doctest', + 'sphinx.ext.mathjax', + 'sphinx.ext.viewcode'] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix(es) of source filenames. +# You can specify multiple suffix as a list of string: +# +# source_suffix = ['.rst', '.md'] +source_suffix = '.rst' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = 'pytools' +copyright = '2017, Andreas Kloeckner' +author = 'Andreas Kloeckner' + +# 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. +ver_dic = {} +exec(compile(open("../pytools/version.py").read(), "../pytools/version.py", 'exec'), ver_dic) +version = ".".join(str(x) for x in ver_dic["VERSION"]) +release = ver_dic["VERSION_TEXT"] + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# +# This is also used if you do content translation via gettext catalogs. +# Usually you set "language" from the command line for these cases. +language = None + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This patterns also effect to html_static_path and html_extra_path +exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# If true, `todo` and `todoList` produce output, else they produce nothing. +todo_include_todos = False + + +# -- Options for HTML output ---------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +# +html_theme = 'alabaster' + +html_theme_options = { + "extra_nav_links": { + "🚀 Github": "https://github.com/inducer/pytools", + "💾 Download Releases": "https://pypi.python.org/pypi/pytools", + } + } + +html_sidebars = { + '**': [ + 'about.html', + 'navigation.html', + 'relations.html', + 'searchbox.html', + ] +} + +# 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 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'] + + +# -- Options for HTMLHelp output ------------------------------------------ + +# Output file base name for HTML help builder. +htmlhelp_basename = 'pytoolsdoc' + + +# -- Options for LaTeX output --------------------------------------------- + +latex_elements = { + # The paper size ('letterpaper' or 'a4paper'). + # + # 'papersize': 'letterpaper', + + # The font size ('10pt', '11pt' or '12pt'). + # + # 'pointsize': '10pt', + + # Additional stuff for the LaTeX preamble. + # + # 'preamble': '', + + # Latex figure (float) alignment + # + # 'figure_align': 'htbp', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). +latex_documents = [ + (master_doc, 'pytools.tex', 'pytools Documentation', + 'Andreas Kloeckner', 'manual'), +] + + +# -- Options for manual page output --------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + (master_doc, 'pytools', 'pytools Documentation', + [author], 1) +] + + +# -- Options for Texinfo output ------------------------------------------- + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + (master_doc, 'pytools', 'pytools Documentation', + author, 'pytools', 'One line description of project.', + 'Miscellaneous'), +] + + + diff --git a/doc/index.rst b/doc/index.rst new file mode 100644 index 0000000000000000000000000000000000000000..fb3dedd0fa7e8e984ef8c06d935d9893819fc6c8 --- /dev/null +++ b/doc/index.rst @@ -0,0 +1,18 @@ +Welcome to pytools's documentation! +=================================== + +.. toctree:: + :maxdepth: 2 + :caption: Contents: + + reference + obj_array + persistent_dict + misc + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` diff --git a/doc/misc.rst b/doc/misc.rst new file mode 100644 index 0000000000000000000000000000000000000000..4255ef6661a4d2b8139a4ac0659bb277a9d8a3fb --- /dev/null +++ b/doc/misc.rst @@ -0,0 +1,59 @@ +Installation +============ + +This command should install :mod:`pytools`:: + + pip install pytools + +You may need to run this with :command:`sudo`. +If you don't already have `pip <https://pypi.python.org/pypi/pip>`_, +run this beforehand:: + + curl -O https://raw.github.com/pypa/pip/master/contrib/get-pip.py + python get-pip.py + +For a more manual installation, download the source, unpack it, +and say:: + + python setup.py install + +User-visible changes +==================== + +Version 2017.4 +-------------- + +.. note:: + + This version is currently under development. You can get snapshots from + Pytools's `git repository <https://github.com/inducer/pytools>`_ + +.. _license: + +License +======= + +:mod:`pytools` is licensed to you under the MIT/X Consortium license: + +Copyright (c) 2008-17 Andreas Klöckner + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. diff --git a/doc/obj_array.rst b/doc/obj_array.rst new file mode 100644 index 0000000000000000000000000000000000000000..d7a8c46ce994e7027502c6dc5ddf101f5381a046 --- /dev/null +++ b/doc/obj_array.rst @@ -0,0 +1 @@ +.. automodule:: pytools.obj_array diff --git a/doc/persistent_dict.rst b/doc/persistent_dict.rst new file mode 100644 index 0000000000000000000000000000000000000000..7d10dc1ef3cbd969622479688690f3a600f4b3b7 --- /dev/null +++ b/doc/persistent_dict.rst @@ -0,0 +1 @@ +.. automodule:: pytools.persistent_dict diff --git a/doc/reference.rst b/doc/reference.rst new file mode 100644 index 0000000000000000000000000000000000000000..fce823adf86e6e9cee927f495da807d75e6e9c1b --- /dev/null +++ b/doc/reference.rst @@ -0,0 +1 @@ +.. automodule:: pytools diff --git a/doc/upload-docs.sh b/doc/upload-docs.sh new file mode 100755 index 0000000000000000000000000000000000000000..ef523e618ee92bf38fef33d8beae7015d132e58b --- /dev/null +++ b/doc/upload-docs.sh @@ -0,0 +1,3 @@ +#! /bin/sh + +rsync --verbose --archive --delete _build/html/* doc-upload:doc/pytools diff --git a/pytools/__init__.py b/pytools/__init__.py index 0920e46f2d40dc8e7c25f9110eb13d773abeea20..e5cfa3628fae819ab50ffda5ee861ff0f30f279a 100644 --- a/pytools/__init__.py +++ b/pytools/__init__.py @@ -41,6 +41,91 @@ except ImportError: else: my_decorator = decorator_module.decorator +__doc__ = """ +A Collection of Utilities +========================= + +Math +---- + +.. autofunction:: levi_civita +.. autofunction:: perm +.. autofunction:: comb + +Assertive accessors +------------------- + +.. autofunction:: one +.. autofunction:: is_single_valued +.. autofunction:: all_roughly_equal +.. autofunction:: single_valued + +Memoization +----------- + +.. autofunction:: memoize +.. autofunction:: memoize_on_first_arg +.. autofunction:: memoize_method +.. autofunction:: memoize_method_with_uncached +.. autofunction:: memoize_in + +Argmin/max +---------- + +.. autofunction:: argmin2 +.. autofunction:: argmax2 +.. autofunction:: argmin +.. autofunction:: argmax + +Cartesian products +------------------ +.. autofunction:: cartesian_product +.. autofunction:: distinct_pairs + +Permutations, Tuples, Integer sequences +--------------------------------------- + +.. autofunction:: wandering_element +.. autofunction:: indices_in_shape +.. autofunction:: generate_nonnegative_integer_tuples_below +.. autofunction:: generate_nonnegative_integer_tuples_summing_to_at_most +.. autofunction:: generate_all_nonnegative_integer_tuples +.. autofunction:: generate_all_integer_tuples_below +.. autofunction:: generate_all_integer_tuples +.. autofunction:: generate_permutations +.. autofunction:: generate_unique_permutations + +Graph Algorithms +---------------- + +.. autofunction:: a_star + +Formatting +---------- + +.. autoclass:: Table +.. autofunction:: string_histogram +.. autofunction:: word_wrap + +Debugging +--------- + +.. autofunction:: typedump +.. autofunction:: invoke_editor + +Progress bars +------------- + +.. autoclass:: ProgressBar + +Name generation +--------------- + +.. autofunction:: generate_unique_names +.. autofunction:: generate_numbered_unique_names +.. autofunction:: UniqueNameGenerator +""" + # {{{ math -------------------------------------------------------------------- @@ -1163,7 +1248,7 @@ def generate_all_integer_tuples(length, least_abs=0): def generate_permutations(original): - """Generate all permutations of the list `original'. + """Generate all permutations of the list *original*. Nicked from http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/252178 """ @@ -1177,7 +1262,7 @@ def generate_permutations(original): def generate_unique_permutations(original): - """Generate all unique permutations of the list `original'. + """Generate all unique permutations of the list *original*. """ had_those = set() @@ -1314,7 +1399,13 @@ def a_star(initial_state, goal_state, neighbor_map, # {{{ table formatting class Table: - """An ASCII table generator.""" + """An ASCII table generator. + + .. automethod:: add_row + .. automethod:: __str__ + .. automethod:: latex + """ + def __init__(self): self.rows = [] @@ -1402,10 +1493,10 @@ def string_histogram(iterable, min_value=None, max_value=None, def word_wrap(text, width, wrap_using="\n"): # http://code.activestate.com/recipes/148061-one-liner-word-wrap-function/ - """ + r""" A word-wrap function that preserves existing line breaks and most spaces in the text. Expects that existing line - breaks are posix newlines (\n). + breaks are posix newlines (``\n``). """ space_or_break = [" ", wrap_using] return reduce(lambda line, word, width=width: '%s%s%s' % @@ -1601,6 +1692,14 @@ def invoke_editor(s, filename="edit.txt", descr="the file"): # {{{ progress bars class ProgressBar: + """ + .. automethod:: draw + .. automethod:: progress + .. automethod:: set_progress + .. automethod:: finished + .. automethod:: __enter__ + .. automethod:: __exit__ + """ def __init__(self, descr, total, initial=0, length=40): import time self.description = descr @@ -1767,6 +1866,12 @@ generate_unique_possibilities = MovedFunctionDeprecationWrapper( class UniqueNameGenerator(object): + """ + .. automethod:: is_name_conflicting + .. automethod:: add_name + .. automethod:: add_names + .. automethod:: __call__ + """ def __init__(self, existing_names=set(), forced_prefix=""): self.existing_names = existing_names.copy() self.forced_prefix = forced_prefix diff --git a/pytools/obj_array.py b/pytools/obj_array.py index e425e70a5c6e1f697865239f5187625f65ccd360..f3310e45c57d0540470eed551aeeacc3b61f400d 100644 --- a/pytools/obj_array.py +++ b/pytools/obj_array.py @@ -2,6 +2,28 @@ from __future__ import absolute_import, division import numpy as np from pytools import my_decorator as decorator, MovedFunctionDeprecationWrapper +__doc__ = """ +Handling :mod:`numpy` Object Arrays +=================================== + +.. automethod:: oarray_real +.. automethod:: oarray_imag +.. automethod:: oarray_real_copy +.. automethod:: oarray_imag_copy + +Creation +-------- + +.. automethod:: join_fields +.. automethod:: make_obj_array + +Mapping +------- + +.. automethod:: with_object_array_or_scalar +.. automethod:: with_object_array_or_scalar_n_args +""" + def gen_len(expr): from pytools.obj_array import is_obj_array diff --git a/pytools/persistent_dict.py b/pytools/persistent_dict.py index 0a9fe6cdf2e942299d9dfa61fc2aab9b84807074..3fe69482955889499083d459dac68c995470e6a7 100644 --- a/pytools/persistent_dict.py +++ b/pytools/persistent_dict.py @@ -1,8 +1,6 @@ """Generic persistent, concurrent dictionary-like facility.""" -from __future__ import division, with_statement -from __future__ import absolute_import -import six +from __future__ import division, with_statement, absolute_import __copyright__ = "Copyright (C) 2011,2014 Andreas Kloeckner" @@ -30,10 +28,23 @@ import logging logger = logging.getLogger(__name__) +import six import sys import os import errno +__doc__ = """ +Persistent Hashing +================== + +This module contains functionality that allows hashing with keys that remain +valid across interpreter invocations, unlike Python's built-in hashes. + +.. autoexception:: NoSuchEntryError +.. autoclass:: KeyBuilder +.. autoclass:: PersistentDict +""" + try: import hashlib new_hash = hashlib.sha256 @@ -269,6 +280,11 @@ class PersistentDict(object): :arg identifier: a file-name-compatible string identifying this dictionary :arg key_builder: a subclass of :class:`KeyBuilder` + + .. automethod:: __getitem__ + .. automethod:: __setitem__ + .. automethod:: __delitem__ + .. automethod:: clear """ self.identifier = identifier diff --git a/setup.py b/setup.py index ce1838c6a50a7af833f9d2c6baf6235d03f1deb1..42b70c7613564c58f1d99acb3d3cdac6d4587d1a 100644 --- a/setup.py +++ b/setup.py @@ -15,20 +15,7 @@ exec(compile(version_file_contents, "pytools/version.py", 'exec'), ver_dic) setup(name="pytools", version=ver_dic["VERSION_TEXT"], description="A collection of tools for Python", - long_description=""" - Pytools is a big bag of things that are "missing" from the Python standard - library. This is mainly a dependency of my other software packages, and is - probably of little interest to you unless you use those. If you're curious - nonetheless, here's what's on offer: - - * A ton of small tool functions such as `len_iterable`, `argmin`, - tuple generation, permutation generation, ASCII table pretty printing, - GvR's mokeypatch_xxx() hack, the elusive `flatten`, and much more. - * Michele Simionato's decorator module - * A time-series logging module, `pytools.log`. - * Batch job submission, `pytools.batchjob`. - * A lexer, `pytools.lex`. - """, + long_description=open("README.rst", "r").read(), classifiers=[ 'Development Status :: 4 - Beta', 'Intended Audience :: Developers',