Skip to content

Commit

Permalink
Merge ffb5936 into f467df5
Browse files Browse the repository at this point in the history
  • Loading branch information
jonathanj committed May 12, 2014
2 parents f467df5 + ffb5936 commit c39ee44
Show file tree
Hide file tree
Showing 15 changed files with 364 additions and 146 deletions.
10 changes: 6 additions & 4 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ Spinneret: Twisted Web's Silk Spinner

|build|_ |coverage|_

Spinneret is a collection of higher-level utility classes and functions to make
writing complex Twisted Web applications far simpler, it is designed to easily
integrate with existing Twisted Web projects for things like the improved
``IResource`` implementations.
(Spinneret is still young, its API should be considered unstable.)

Spinneret is a collection of higher-level utilities (such as URL routing,
content type negotiation and processing query arguments) to make writing
complex Twisted Web applications far simpler and (hopefully) more fun! It is
designed to easily integrate with existing Twisted Web projects.

For more info `read the docs <http://txspinneret.readthedocs.org>`_.

Expand Down
2 changes: 1 addition & 1 deletion docs/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,6 @@ Utility resources
Interfaces
----------

.. automodule:: txspinneret.interfaces
.. automodule:: txspinneret._interfaces
:members:
:show-inheritance:
1 change: 1 addition & 0 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
extensions = [
'sphinx.ext.autodoc',
'sphinx.ext.intersphinx',
'sphinx.ext.doctest',
'sphinx.ext.coverage',
'sphinx.ext.viewcode',
'sphinxcontrib.zopeext.autointerface',
Expand Down
8 changes: 4 additions & 4 deletions docs/examples/negotiator.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import json
from twisted.web.resource import Resource
from twisted.web.template import Element, TagLoader, tags
from txspinneret.interfaces import INegotiableResource
from txspinneret.resource import ContentTypeNegotiator, SpinneretResource
from txspinneret.resource import (
ContentTypeNegotiator, INegotiableResource, ISpinneretResource)
from zope.interface import implementer

@implementer(INegotiableResource)
Expand All @@ -20,8 +20,8 @@ def render_GET(self, request):
class FooElement(Element):
loader = TagLoader(tags.h1('Try accepting JSON!'))

@implementer(INegotiableResource)
class FooHTML(SpinneretResource):
@implementer(INegotiableResource, ISpinneretResource)
class FooHTML(object):
contentType = 'text/html'
acceptTypes = ['text/html']

Expand Down
4 changes: 2 additions & 2 deletions docs/examples/user_router.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@ def name(self, request, params):

@router.subroute('friend', Any('name'))
def friend(self, request, params):
return UserRouter(self.getFriend(params['name'])).router
return UserRouter(self.getFriend(params['name'])).router.resource()

def start():
User = namedtuple(b'User', ['name', 'friends'])
bob = User('bob', {})
chuck = User('chuck', {'bob': bob})
default = User('default', {'bob': bob, 'chuck': chuck})
return UserRouter(default).router
return UserRouter(default).router.resource()
4 changes: 2 additions & 2 deletions docs/query.rst
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
.. py:currentmodule:: txspinneret.query
URL Query Arguments
===================
Query Arguments
===============

The tedious process of processing query arguments usually follows this pattern:

Expand Down
18 changes: 10 additions & 8 deletions docs/resource.rst
Original file line number Diff line number Diff line change
@@ -1,25 +1,27 @@
.. py:currentmodule:: txspinneret.resource
Twisted Web Utility Resources
=============================
Resource Utilities
==================

A collection of higher-level Twisted Web resources, suitable for use with any
existing `IResource` implementations.
A collection of higher-level Twisted Web resource utilities, suitable for use
with any existing `IResource` implementations.


More featureful resources
-------------------------

`SpinneretResource` is an `IResource` implementation that allows child location
(via `SpinneretResource.locateChild`) and rendering (via the normal
`ISpinneretResource` is cut-down version of `IResource` that allows child
location (via `ISpinneretResource.locateChild`) and rendering (via the normal
``render_GET``, ``render_POST``, etc. methods) to return any of the following:

* `bytes`, in the same way that `IResource` does;
* An object that can be adapted to either `IResource` or `IRenderable`;
* A `URLPath` instance, to indicate an HTTP redirect;
* Or a `Deferred` that results in any of the above values.

Render methods may still return plain bytes, making it possible to reuse
existing `IResource` implementations.
`ISpinneretResource` implementations may be adapted to `IResource`, either via
``IResource(impl)`` or by ``SpinneretResource(impl)``, to produce a resource
suitable for use with Twisted Web.


Negotiating resources based on ``Accept``
Expand Down
18 changes: 12 additions & 6 deletions docs/route.rst
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
.. py:currentmodule:: txspinneret.route
URL Routing Resources
=====================
URL Routing
===========

Often it is desirable to describe a resource hierarchy without having to
create a separate resource for every segment in the URL path, this is commonly
referred to as "URL routing".
Often it is desirable to describe a resource hierarchy by matching URL
segments in the request, this is commonly referred to as "URL routing".

A Python-based Domain Specific Language is used to specify and match routing
paths, string literal components are matched for structure while plain callable
Expand All @@ -31,9 +30,16 @@ will be a match, regardless of whether there are URL path segments left over.
This is useful for the case where you wish to match enough of the URL to know
that you should delegate to another resource.

A route handler may return any of the values that
`ISpinneretResource.locateChild <txspinneret.resource.ISpinneretResource>`
supports.

Routes are intended to be used as method decorators and may be stacked to have
multiple routes serviced by the same handler.

Call `Router.resource` to produce an `IResource` suitable for composing with
other parts of Spinneret or Twisted Web.


Special routes
--------------
Expand All @@ -50,7 +56,7 @@ Assuming we had the following hierarchy:
@router.subroute('bar')
def bar(self, request, params):
return SubRoot().router
return SubRoot().router.resource()
class SubRoot(object):
Expand Down
52 changes: 52 additions & 0 deletions txspinneret/_interfaces.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
from zope.interface import Attribute, Interface



class ISpinneretResource(Interface):
"""
Spinneret resource.
Spinneret resources may additionally have methods like ``render_GET`` (to
handle a ``GET`` request) ``render_POST`` etc., like `IResource`, that may
return the same types of objects as `ISpinneretResource.locateChild`.
Adaptable to `IResource`.
"""
def locateChild(request, segments):
"""
Locate another object which can be adapted to `IResource`.
:type request: `IRequest <twisted:twisted.web.iweb.IRequest>`
:param request: Request.
:type segments: ``sequence`` of `bytes`
:param segments: Sequence of strings giving the remaining query
segments to resolve.
:rtype: 2-`tuple` of `IResource`, `IRenderable` or `URLPath` and
a ``sequence`` of `bytes`
:return: Pair of an `IResource`, `IRenderable` or `URLPath` and
a sequence of the remaining path segments to be process, or
a `Deferred` containing the aforementioned result.
"""



class INegotiableResource(Interface):
"""
Resource used for content negotiation.
The implementation should be adaptable to `IResource
<twisted:twisted.web.resource.IResource>`.
"""
contentType = Attribute(
"""
`bytes` indicating the content type of this resource when rendered.
""")


acceptTypes = Attribute(
"""
`list` of `bytes` indicating the content types this resource is capable
of accepting.
""")
20 changes: 0 additions & 20 deletions txspinneret/interfaces.py

This file was deleted.

0 comments on commit c39ee44

Please sign in to comment.