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() )