diff --git a/aspen/__init__.py b/aspen/__init__.py
index 76780126..df98148a 100644
--- a/aspen/__init__.py
+++ b/aspen/__init__.py
@@ -1,3 +1,77 @@
+"""
+#########
+ Aspen
+#########
+
+Aspen is a filesystem dispatch library for Python web frameworks. Instead of
+using regular expressions, decorators, or object traversal, Aspen dispatches
+HTTP requests based on the natural symmetry of URL paths and filesystem paths.
+In the `immortal words`_ of Jeff Lindsay, "so like. a web server." Exactly! ;-)
+
+.. _immortal words: https://twitter.com/progrium/status/773694289033383937
+
+This is the documentation for the development version of the core Aspen
+library, describing its filesystem dispatch behavior regardless of the web
+framework you're using it with. For instructions on configuring Aspen with a
+specific web framework, see the docs for `django-aspen`_, `Flask-Aspen`_, or
+`Pando`_. See the `project homepage`_ for an overview.
+
+.. _django-aspen: http://django.aspen.io/
+.. _Flask-aspen: http://flask.aspen.io/
+.. _Pando: http://pando.aspen.io/
+.. _project homepage: http://aspen.io/
+
+This version of Aspen has been tested with Python 2.7, 3.4, and 3.5, on both
+Ubuntu and Windows.
+
+
+**************
+ Installation
+**************
+
+Aspen is available on `GitHub`_ and on `PyPI`_::
+
+ $ pip install aspen
+
+.. _GitHub: https://github.com/AspenWeb/aspen.py
+.. _PyPI: https://pypi.python.org/pypi/aspen
+
+
+*******
+ Legal
+*******
+
+Aspen is distributed under the `MIT license`_.
+
+.. _MIT license: https://github.com/AspenWeb/aspen.py/blob/master/COPYRIGHT
+
+
+**********
+ See Also
+**********
+
+The `Keystone`_ web framework was inspired by Aspen.
+
+.. _Keystone: http://keystone.readthedocs.org/
+
+
+***********
+ Reference
+***********
+
+This is the API reference for the Aspen library.
+
+.. automodule:: aspen.simplates
+.. automodule:: aspen.http
+.. automodule:: aspen.request_processor
+.. automodule:: aspen.resources
+.. automodule:: aspen.output
+.. automodule:: aspen.configuration
+.. automodule:: aspen.exceptions
+.. automodule:: aspen.testing
+.. automodule:: aspen.utils
+
+"""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
diff --git a/aspen/configuration/__init__.py b/aspen/configuration/__init__.py
index ab66f1d2..e2f55858 100644
--- a/aspen/configuration/__init__.py
+++ b/aspen/configuration/__init__.py
@@ -1,3 +1,13 @@
+"""
+
+:mod:`configuration`
+====================
+
+Configuration.
+
+.. automodule:: aspen.configuration.parse
+
+"""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
diff --git a/aspen/configuration/parse.py b/aspen/configuration/parse.py
index 340a4062..b28a8333 100644
--- a/aspen/configuration/parse.py
+++ b/aspen/configuration/parse.py
@@ -1,4 +1,8 @@
"""
+
+:mod:`parse`
+============
+
Define parser/validators for configuration system
Each of these is guaranteed to be passed a unicode object as read from the
diff --git a/aspen/exceptions.py b/aspen/exceptions.py
index 38dec132..dacbef8f 100644
--- a/aspen/exceptions.py
+++ b/aspen/exceptions.py
@@ -1,3 +1,9 @@
+"""
+:mod:`exceptions`
+=================
+
+Exceptions.
+"""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
diff --git a/aspen/http/__init__.py b/aspen/http/__init__.py
index e69de29b..0c84e1be 100644
--- a/aspen/http/__init__.py
+++ b/aspen/http/__init__.py
@@ -0,0 +1,12 @@
+"""
+:mod:`http`
+===========
+
+Aspen doesn't implement all of HTTP, only things related to filesystem
+dispatch.
+
+.. automodule:: aspen.http.mapping
+.. automodule:: aspen.http.request
+.. automodule:: aspen.http.resource
+
+"""
diff --git a/aspen/http/mapping.py b/aspen/http/mapping.py
index c05213ca..cf90bd3c 100644
--- a/aspen/http/mapping.py
+++ b/aspen/http/mapping.py
@@ -1,23 +1,29 @@
+"""
+:mod:`mapping`
+--------------
+
+This module implements a class to represent HTTP mappings.
+
+"""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
-
NO_DEFAULT = object()
class Mapping(dict):
- """Base class for HTTP mappings: Path, Querystring, Headers, Cookie, Body.
+ """Base class for HTTP mappings.
Mappings in HTTP differ from Python dictionaries in that they may have one
or more values. This dictionary subclass maintains a list of values for
- each key. However, access semantics are asymetric: subscript assignment
- clobbers to the list, while subscript access returns the last item. Think
+ each key. However, access semantics are asymmetric: subscript assignment
+ clobbers to list, while subscript access returns the last item. Think
about it.
- WARNING: this isn't thread-safe
+ .. warning:: This isn't thread-safe.
"""
diff --git a/aspen/http/request.py b/aspen/http/request.py
index 3ac79859..1b1bab06 100644
--- a/aspen/http/request.py
+++ b/aspen/http/request.py
@@ -1,4 +1,8 @@
"""
+:mod:`request`
+--------------
+
+Aspen models the path and querystring parts of an HTTP request message.
"""
from __future__ import absolute_import
from __future__ import division
diff --git a/aspen/http/resource.py b/aspen/http/resource.py
index 40ef00dc..47bcd6b2 100644
--- a/aspen/http/resource.py
+++ b/aspen/http/resource.py
@@ -1,4 +1,9 @@
+"""
+:mod:`resource`
+---------------
+This module implements classes for modeling static and dynamic HTTP resources.
+"""
import mimeparse
from ..exceptions import NegotiationFailure
diff --git a/aspen/output.py b/aspen/output.py
index 64a938fa..338f6fea 100644
--- a/aspen/output.py
+++ b/aspen/output.py
@@ -1,3 +1,11 @@
+"""
+:mod:`output`
+=============
+
+Implement a class for capturing request processing output.
+
+"""
+
class Output(object):
body = media_type = charset = None
diff --git a/aspen/renderers.py b/aspen/renderers.py
index 1ee2ccc3..a040cd98 100644
--- a/aspen/renderers.py
+++ b/aspen/renderers.py
@@ -1,4 +1,3 @@
-
# for backwards compatibility with aspen-renderer modules
from .simplates.renderers import Factory, Renderer
diff --git a/aspen/request_processor/__init__.py b/aspen/request_processor/__init__.py
index 0d200647..a42fe08a 100644
--- a/aspen/request_processor/__init__.py
+++ b/aspen/request_processor/__init__.py
@@ -1,3 +1,17 @@
+"""
+:mod:`request_processor`
+========================
+
+The request processor dispatches requests to the filesystem (typecasting URL
+path variables), loads the resource from the filesystem, and then renders and
+encodes the resource. This algorithm is defined in the :mod:`algorithm` module,
+with dispatching and typecasting in additional modules.
+
+.. automodule:: aspen.request_processor.algorithm
+.. automodule:: aspen.request_processor.dispatcher
+.. automodule:: aspen.request_processor.typecasting
+
+"""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
diff --git a/aspen/request_processor/algorithm.py b/aspen/request_processor/algorithm.py
index d8be81ee..bff5e9c5 100644
--- a/aspen/request_processor/algorithm.py
+++ b/aspen/request_processor/algorithm.py
@@ -1,4 +1,7 @@
"""
+:mod:`algorithm`
+----------------
+
These functions comprise the request processing functionality of Aspen.
The order of functions in this module defines Aspen algorithm for request
diff --git a/aspen/request_processor/dispatcher.py b/aspen/request_processor/dispatcher.py
index e0523278..44792ccc 100644
--- a/aspen/request_processor/dispatcher.py
+++ b/aspen/request_processor/dispatcher.py
@@ -1,4 +1,7 @@
"""
+:mod:`dispatcher`
+-----------------
+
Implement Aspen's filesystem dispatch algorithm.
"""
from __future__ import absolute_import
diff --git a/aspen/request_processor/typecasting.py b/aspen/request_processor/typecasting.py
index 00d531ef..97e14e1a 100644
--- a/aspen/request_processor/typecasting.py
+++ b/aspen/request_processor/typecasting.py
@@ -1,5 +1,9 @@
"""
-Pluggable typecasting of virtual path values
+:mod:`typecasting`
+------------------
+
+This module implements pluggable typecasting of URL path variables.
+
"""
from __future__ import absolute_import
from __future__ import division
diff --git a/aspen/resources.py b/aspen/resources.py
index d06e3d00..2589c4c3 100644
--- a/aspen/resources.py
+++ b/aspen/resources.py
@@ -1,4 +1,7 @@
"""
+:mod:`resources`
+================
+
This is a registry of filesystem paths to objects representing HTTP resources.
Use :py:func:`get` to use the cache, use :py:func:`load` to circumvent it.
diff --git a/aspen/simplates/__init__.py b/aspen/simplates/__init__.py
index e69de29b..1451b5c8 100644
--- a/aspen/simplates/__init__.py
+++ b/aspen/simplates/__init__.py
@@ -0,0 +1,36 @@
+"""
+:mod:`simplates`
+================
+
+The simplates module implements Aspen's file format, simplates (*.spt).
+Simplates combine request processing logic (think: Rails controller, or Django
+view) with template code in one file. Here's an example::
+
+ # Python syntax. Runs once on startup.
+ import random
+
+ [----]
+ # Python syntax. Runs once per request..
+ program = request.qs['program']
+ excitement = '!' * random.randint(1, 10)
+
+ # One of the following is used on each request, based on content type
+ # negotiation. The syntax depends on the renderer.
+
+ [----] text/html via jinja2
+
Greetings, {{ program }}{{ excitement }}
+
+ [----] text/plain via stdlib_format
+ Greetings, {program}{excitement}
+
+ [----] application/json via json_dump
+ { "program": program
+ , "excitement": excitement
+ }
+
+
+.. automodule:: aspen.simplates.renderers
+.. automodule:: aspen.simplates.pagination
+.. automodule:: aspen.simplates.json_
+
+"""
diff --git a/aspen/simplates/json_.py b/aspen/simplates/json_.py
index 351059e5..32dbaaae 100644
--- a/aspen/simplates/json_.py
+++ b/aspen/simplates/json_.py
@@ -1,3 +1,7 @@
+"""
+:mod:`json_`
+------------
+"""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
diff --git a/aspen/simplates/pagination.py b/aspen/simplates/pagination.py
index 7d7fccfc..890f81c8 100644
--- a/aspen/simplates/pagination.py
+++ b/aspen/simplates/pagination.py
@@ -1,3 +1,7 @@
+"""
+:mod:`pagination`
+-----------------
+"""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
diff --git a/aspen/simplates/renderers/__init__.py b/aspen/simplates/renderers/__init__.py
index 524bf8e6..dd11e988 100644
--- a/aspen/simplates/renderers/__init__.py
+++ b/aspen/simplates/renderers/__init__.py
@@ -1,4 +1,7 @@
"""
+:mod:`renderers`
+----------------
+
This module implements pluggable content rendering.
Negotiated and rendered resources have content pages the bytes for which are
@@ -68,6 +71,12 @@ class CheeseFactory(Factory):
machinery is inadequate for some reason let's evolve the machinery so all
renderers behave consistently for users. Thanks.
+.. automodule:: aspen.simplates.renderers.jsonp_dump
+.. automodule:: aspen.simplates.renderers.json_dump
+.. automodule:: aspen.simplates.renderers.stdlib_format
+.. automodule:: aspen.simplates.renderers.stdlib_percent
+.. automodule:: aspen.simplates.renderers.stdlib_template
+
"""
from __future__ import absolute_import
from __future__ import division
diff --git a/aspen/simplates/renderers/json_dump.py b/aspen/simplates/renderers/json_dump.py
index 3fec21a5..03657e6f 100644
--- a/aspen/simplates/renderers/json_dump.py
+++ b/aspen/simplates/renderers/json_dump.py
@@ -1,3 +1,7 @@
+"""
+:mod:`json_dump`
+^^^^^^^^^^^^^^^^
+"""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
diff --git a/aspen/simplates/renderers/jsonp_dump.py b/aspen/simplates/renderers/jsonp_dump.py
index 5ec64f3d..4c601a54 100644
--- a/aspen/simplates/renderers/jsonp_dump.py
+++ b/aspen/simplates/renderers/jsonp_dump.py
@@ -1,3 +1,7 @@
+"""
+:mod:`jsonp_dump`
+^^^^^^^^^^^^^^^^^^
+"""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
diff --git a/aspen/simplates/renderers/stdlib_format.py b/aspen/simplates/renderers/stdlib_format.py
index 3aff9c27..15f4138d 100644
--- a/aspen/simplates/renderers/stdlib_format.py
+++ b/aspen/simplates/renderers/stdlib_format.py
@@ -1,3 +1,7 @@
+"""
+:mod:`stdlib_format`
+^^^^^^^^^^^^^^^^^^^^
+"""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
diff --git a/aspen/simplates/renderers/stdlib_percent.py b/aspen/simplates/renderers/stdlib_percent.py
index 847be9cf..2a02a97d 100644
--- a/aspen/simplates/renderers/stdlib_percent.py
+++ b/aspen/simplates/renderers/stdlib_percent.py
@@ -1,3 +1,7 @@
+"""
+:mod:`stdlib_percent`
+^^^^^^^^^^^^^^^^^^^^^
+"""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
diff --git a/aspen/simplates/renderers/stdlib_template.py b/aspen/simplates/renderers/stdlib_template.py
index ce053264..aa830ed7 100644
--- a/aspen/simplates/renderers/stdlib_template.py
+++ b/aspen/simplates/renderers/stdlib_template.py
@@ -1,3 +1,7 @@
+"""
+:mod:`stdlib_template`
+^^^^^^^^^^^^^^^^^^^^^^
+"""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
diff --git a/aspen/simplates/simplate.py b/aspen/simplates/simplate.py
index d48c1864..4e3b9220 100644
--- a/aspen/simplates/simplate.py
+++ b/aspen/simplates/simplate.py
@@ -1,3 +1,7 @@
+"""
+:mod:`simplate`
+---------------
+"""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
diff --git a/aspen/testing.py b/aspen/testing.py
index e1c919f5..8f7b3761 100644
--- a/aspen/testing.py
+++ b/aspen/testing.py
@@ -1,3 +1,10 @@
+"""
+:mod:`testing`
+==============
+
+This module provides helpers for testing applications that use Aspen.
+
+"""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
diff --git a/aspen/utils.py b/aspen/utils.py
index e4e2c42b..0e909895 100644
--- a/aspen/utils.py
+++ b/aspen/utils.py
@@ -1,3 +1,11 @@
+"""
+:mod:`utils`
+============
+
+This module collects a few random bits that should be placed somewhere that
+makes more sense.
+
+"""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
diff --git a/build.py b/build.py
index 1bfa8eed..58bd60cf 100644
--- a/build.py
+++ b/build.py
@@ -9,24 +9,6 @@
# Core Executables
# ================
-ASPEN_DEPS = [
- 'python-mimeparse>=0.1.4',
- 'first>=2.0.1',
- 'algorithm>=1.0.0',
- 'filesystem_tree>=1.0.1',
- 'dependency_injection>=1.1.0',
- 'six',
- ]
-
-TEST_DEPS = [
- 'coverage>=3.7.1',
- 'cov-core>=1.7',
- 'py>=1.4.20',
- 'pyflakes',
- 'pytest>=2.5.2',
- 'pytest-cov>=1.6',
- ]
-
ENV_ARGS = [
'-m', 'virtualenv',
'--prompt=[aspen]',
@@ -52,11 +34,6 @@ def _env(envdir='env'):
# extend the PATH
path = os.path.join(d, 'Scripts' if os.name == "nt" else 'bin')
os.environ['PATH'] = path + os.pathsep + os.environ.get('PATH', '')
- # install tox if it isn't there
- try:
- shell('pip', 'show', 'tox')
- except ExecutionError:
- run('pip', 'install', 'tox')
return d
@@ -82,17 +59,26 @@ def env():
_env()
+def _install_tox():
+ # install tox if it isn't there
+ try:
+ shell('pip', 'show', 'tox')
+ except ExecutionError:
+ run('pip', 'install', 'tox')
+
+
def _deps():
- shell('pip', 'install', *ASPEN_DEPS, ignore_status=False)
+ shell('pip', 'install', '-r', 'requirements.txt', ignore_status=False)
def _test_deps():
_deps()
- shell('pip', 'install', *TEST_DEPS, ignore_status=False)
+ shell('pip', 'install', '-r', 'requirements_tests.txt', ignore_status=False)
def _dev(envdir='env'):
envdir = _env(envdir)
+ _install_tox()
run('tox', '--notest', '--skip-missing-interpreters')
return envdir
@@ -120,9 +106,10 @@ def clean():
# Docs
# ====
-def _sphinx_cmd(packages, cmd):
+def _sphinx_cmd(cmd, extra_pkgs=[]):
envdir = _env()
- run('pip', 'install', *packages)
+ _deps()
+ run('pip', 'install', *(['sphinx', 'sphinx-rtd-theme'] + extra_pkgs))
builddir = 'docs/_build'
run('mkdir', '-p', builddir)
args = ['-b', 'html', '-d', builddir + '/doctrees', 'docs', builddir + '/html']
@@ -130,16 +117,15 @@ def _sphinx_cmd(packages, cmd):
def sphinx():
"""build sphinx documents"""
- _sphinx_cmd(['sphinx'], "sphinx-build")
+ _sphinx_cmd("sphinx-build")
def autosphinx():
"""run sphinx-autobuild"""
- _sphinx_cmd(['sphinx', 'sphinx-autobuild'], "sphinx-autobuild")
+ _sphinx_cmd("sphinx-autobuild", extra_pkgs=['sphinx-autobuild'])
def clean_sphinx():
"""clean sphinx artifacts"""
shell('rm', '-rf', 'docs/_build')
- shell('rm', '-rf', 'denv')
# Testing
@@ -147,6 +133,7 @@ def clean_sphinx():
def _tox(*args, **kw):
_env()
+ _install_tox()
kw.setdefault('silent', False)
shell('tox', '--skip-missing-interpreters', '--', *args, **kw)
diff --git a/docs/conf.py b/docs/conf.py
index a08f9f42..78435940 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -32,7 +32,7 @@
# General information about the project.
project = u'Aspen'
-copyright = u'2016, Chad Whitacre, Paul Jimenez, and others'
+copyright = u'2016, Chad Whitacre et al.'
# The full version, including alpha/beta/rc tags.
release = open('../version.txt').read().strip()
@@ -55,9 +55,9 @@
# -- 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 = 'default'
+import sphinx_rtd_theme
+html_theme = "sphinx_rtd_theme"
+html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
# Output file base name for HTML help builder.
htmlhelp_basename = 'Aspendoc'
@@ -69,7 +69,7 @@
# (source start file, target name, title, author, documentclass [howto/manual]).
latex_documents = [
('index', 'Aspen.tex', u'Aspen Documentation',
- u'Chad Whitacre, Paul Jimenez, and others', 'manual'),
+ u'Chad Whitacre et al.', 'manual'),
]
@@ -79,7 +79,7 @@
# (source start file, name, description, authors, manual section).
man_pages = [
('index', 'aspen', u'Aspen Documentation',
- [u'Chad Whitacre, Paul Jimenez, and others'], 1)
+ [u'Chad Whitacre et al.'], 1)
]
@@ -90,7 +90,7 @@
# dir menu entry, description, category)
texinfo_documents = [
('index', 'Aspen', u'Aspen Documentation',
- u'Chad Whitacre, Paul Jimenez, and others', 'Aspen',
+ u'Chad Whitacre et al.', 'Aspen',
'A filesystem router for Python web frameworks.',
'Miscellaneous'),
]
diff --git a/docs/index.rst b/docs/index.rst
index fc7d4aba..8eea7642 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -1,95 +1,4 @@
-************
-aspen module
-************
-
.. automodule:: aspen
-
-configuration
-=============
-
-.. automodule:: aspen.configuration
-
-parse
------
-
-.. automodule:: aspen.configuration.parse
-
-exceptions
-==========
-
-.. automodule:: aspen.exceptions
-
-http
-====
-
-.. automodule:: aspen.http
-
-mapping
--------
-
-.. automodule:: aspen.http.mapping
-
-request
--------
-
-.. automodule:: aspen.http.request
-
-request_processor
-=================
-
-.. automodule:: aspen.request_processor
-
-algorithm
----------
-
-.. automodule:: aspen.request_processor.algorithm
-
-dispatcher
-----------
-
-.. automodule:: aspen.request_processor.dispatcher
-
-typecasting
------------
-
-.. automodule:: aspen.request_processor.typecasting
-
-resources
-=========
-
-.. automodule:: aspen.resources
-
-simplates
-=========
-
-.. automodule:: aspen.simplates
-
-json_
------
-
-.. automodule:: aspen.simplates.json_
-
-pagination
-----------
-
-.. automodule:: aspen.simplates.pagination
-
-simplate
---------
-
-.. automodule:: aspen.simplates.simplate
-
-renderers
----------
-
-.. automodule:: aspen.simplates.renderers
-
-testing
-=======
-
-.. automodule:: aspen.testing
-
-utils
-=====
-
-.. automodule:: aspen.utils
+ :members:
+ :member-order: bysource
+ :special-members:
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 00000000..cc93ec9c
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,5 @@
+python-mimeparse>=0.1.4
+algorithm>=1.0.0
+filesystem_tree>=1.0.1
+dependency_injection>=1.1.0
+six
diff --git a/requirements_tests.txt b/requirements_tests.txt
new file mode 100644
index 00000000..d1290c25
--- /dev/null
+++ b/requirements_tests.txt
@@ -0,0 +1,6 @@
+coverage>=3.7.1
+cov-core>=1.7
+py>=1.4.20
+pyflakes
+pytest>=2.5.2
+pytest-cov>=1.6
diff --git a/setup.py b/setup.py
index f7b9a560..21ff72e7 100644
--- a/setup.py
+++ b/setup.py
@@ -6,8 +6,6 @@
from setuptools import find_packages, setup
-from build import ASPEN_DEPS, TEST_DEPS
-
version = open('version.txt').read()
@@ -32,6 +30,6 @@
, version = version
, zip_safe = False
, package_data = {'aspen': ['request_processor/mime.types']}
- , install_requires = ASPEN_DEPS
- , tests_require = TEST_DEPS
+ , install_requires = open('requirements.txt').read()
+ , tests_require = open('requirements_tests.txt').read()
)