Minor documentation edits

Change-Id: I0f8049241ffd870a4dac405fa0ca53fb122f2181
This commit is contained in:
Dustin J. Mitchell 2014-06-20 15:24:22 -04:00
parent 2c29787386
commit 4441ca74a9
6 changed files with 88 additions and 86 deletions

View File

@ -4,19 +4,19 @@ Web Services Made Easy
Introduction Introduction
------------ ------------
Web Service Made Easy (WSME) simplify the writing of REST web services Web Services Made Easy (WSME) simplifies the writing of REST web services
by providing simple yet powerful typing which removes the need to directly by providing simple yet powerful typing, removing the need to directly
manipulate the request and the response objects. manipulate the request and the response objects.
WSME can work standalone or on top of your favorite python web WSME can work standalone or on top of your favorite Python web
(micro)framework, so you can use both your preferred way of routing your REST (micro)framework, so you can use both your preferred way of routing your REST
requests and most of the features of WSME that rely on the typing system like: requests and most of the features of WSME that rely on the typing system like:
- Alternate protocols, including ones supporting batch-calls - Alternate protocols, including those supporting batch-calls
- Easy documentation through a Sphinx_ extension - Easy documentation through a Sphinx_ extension
WSME is originally a rewrite of TGWebServices WSME is originally a rewrite of TGWebServices
with focus on extensibility, framework-independance and better type handling. with a focus on extensibility, framework-independance and better type handling.
How Easy ? How Easy ?
~~~~~~~~~~ ~~~~~~~~~~

View File

@ -10,7 +10,7 @@ Install the extension
Here we consider that you already quick-started a sphinx project. Here we consider that you already quick-started a sphinx project.
#. In your ``conf.py`` file, add ``'ext'`` to you extensions, #. In your ``conf.py`` file, add ``'ext'`` to your extensions,
and optionally set the enabled protocols. and optionally set the enabled protocols.
.. code-block:: python .. code-block:: python
@ -34,7 +34,7 @@ Config values
.. confval:: wsme_protocols .. confval:: wsme_protocols
A list of strings that are WSME protocol names. If provided by an A list of strings that are WSME protocol names. If provided by an
additionnal package (for example WSME-Soap or WSME-ExtDirect), it must additional package (for example WSME-Soap or WSME-ExtDirect), that package must
be installed. be installed.
The types and services generated documentation will include code samples The types and services generated documentation will include code samples
@ -57,10 +57,10 @@ Directives
.. rst:directive:: .. root:: <WSRoot full path> .. rst:directive:: .. root:: <WSRoot full path>
Allow to define the service root controller in one documentation source file. Define the service root controller for this documentation source file.
To set it globally, see :confval:`wsme_root`. To set it globally, see :confval:`wsme_root`.
A ``webpath`` option allow to override :confval:`wsme_webpath`. A ``webpath`` option allows override of :confval:`wsme_webpath`.
Example: Example:
@ -80,7 +80,7 @@ Directives
.. rst:directive:: .. attribute:: aname .. rst:directive:: .. attribute:: aname
Equivalent to the :rst:dir:`py:attribute` directive to document a complex type Equivalent to the :rst:dir:`py:attribute` directive to document a complex type
attribute. It takes an additionnal ``:type:`` field. attribute. It takes an additional ``:type:`` field.
Example Example
~~~~~~~ ~~~~~~~
@ -151,7 +151,7 @@ Python source
~~~~~~~~~~~~~ ~~~~~~~~~~~~~
.. literalinclude:: ../wsmeext/sphinxext.py .. literalinclude:: ../wsmeext/sphinxext.py
:lines: 42-67 :lines: 69-96
:language: python :language: python
Documentation source Documentation source
@ -161,6 +161,10 @@ Documentation source
.. default-domain:: wsmeext .. default-domain:: wsmeext
.. type:: int
An integer
.. autotype:: wsmeext.sphinxext.SampleType .. autotype:: wsmeext.sphinxext.SampleType
:members: :members:

View File

@ -2,18 +2,17 @@ Functions
========= =========
WSME is based on the idea that most of the time the input and output of web WSME is based on the idea that most of the time the input and output of web
services are actually stricly typed. It uses this fact to ease the services are actually strictly typed. It uses this idea to ease the
implementation of the actual functions by handling those input/output. implementation of the actual functions by handling those input/output.
It also uses these informations to propose alternate protocols on top of a It also proposes alternate protocols on top of a proper REST api.
proper REST api.
This chapter explains in details how to 'sign' a function with WSME. This chapter explains in detail how to 'sign' a function with WSME.
The decorators The decorators
-------------- --------------
Depending on the framework you are using, you will have to use either a Depending on the framework you are using, you will have to use either a
@signature decorator, either a @wsexpose decorator. @\ :class:`wsme.signature` decorator or a @\ :class:`wsme.wsexpose` decorator.
@signature @signature
~~~~~~~~~~ ~~~~~~~~~~
@ -24,23 +23,23 @@ of the function, and if needed a few more options.
The Flask and Cornice adapters both propose a specific version of it, which The Flask and Cornice adapters both propose a specific version of it, which
also wrap the function so that it becomes suitable for the host framework. also wrap the function so that it becomes suitable for the host framework.
In any case, the use of @signature has the same meaning: tell WSME what is the In any case, the use of @\ :class:`wsme.signature` has the same meaning: tell WSME what is the
signature of the function. signature of the function.
@wsexpose @wsexpose
~~~~~~~~~ ~~~~~~~~~
The native Rest implementation, and the TG and Pecan adapters add a @wsexpose The native Rest implementation, and the TG and Pecan adapters add a @\ :class:`wsme.wsexpose`
decorator. decorator.
It does what @signature does, *and* expose the function in the routing system It does what @\ :class:`wsme.signature` does, *and* exposes the function in the routing system
of the host framework. of the host framework.
This decorator is generally used in object-dispatch routing context. This decorator is generally used in an object-dispatch routing context.
.. note:: .. note::
Since both decorators plays the same role function-wise, the rest of this Since both decorators play the same role, the rest of this
document will alway use @signature. document will alway use @signature.
Signing a function Signing a function
@ -57,7 +56,7 @@ Signing a function is just a matter of decorating it with @signature:
In this trivial example, we tell WSME that the 'multiply' function returns an In this trivial example, we tell WSME that the 'multiply' function returns an
integer, and takes two integer parameters. integer, and takes two integer parameters.
WSME will match the argument types by order, and know the exact type of each WSME will match the argument types by order to determine the exact type of each
named argument. This is important since most of the web service protocols don't named argument. This is important since most of the web service protocols don't
provide strict argument ordering but only named parameters. provide strict argument ordering but only named parameters.
@ -75,13 +74,13 @@ Defining an argument as optional is done by providing a default value:
In this example, the caller may omit the 'delta' argument, and no In this example, the caller may omit the 'delta' argument, and no
'MissingArgument' error will be raised. 'MissingArgument' error will be raised.
Additionally this argument will be documented as optional by the sphinx Additionally, this argument will be documented as optional by the sphinx
extension. extension.
Body argument Body argument
~~~~~~~~~~~~~ ~~~~~~~~~~~~~
When defining a Rest CRUD api, we generally have a URL on which we POST datas. When defining a Rest CRUD API, we generally have a URL to which we POST data.
For example: For example:
@ -92,9 +91,9 @@ For example:
# ... # ...
return data return data
Such a function will take at least one parameter 'data' that is a structured Such a function will take at least one parameter, 'data', that is a structured
type. With the default way of handling parameters, the body of the request type. With the default way of handling parameters, the body of the request
would be like this: would look like this:
.. code-block:: javascript .. code-block:: javascript
@ -106,7 +105,7 @@ would be like this:
} }
} }
If you think (and you should) that it has one extra nest level, the 'body' If you think (and you should) that it has one extra level of nesting, the 'body'
argument is here for you:: argument is here for you::
@signature(Author, body=Author) @signature(Author, body=Author)
@ -123,7 +122,7 @@ With this syntax, we can now post a simpler body:
"name": "Pierre-Joseph" "name": "Pierre-Joseph"
} }
Note that it does not prevent from having multiple parameters, it just requires Note that this does not prevent the function from having multiple parameters; it just requires
the body argument to be the last: the body argument to be the last:
.. code-block:: python .. code-block:: python
@ -139,7 +138,7 @@ body parameter. For example, a POST on ``/author/SOMEID?force_update=true``.
Status code Status code
~~~~~~~~~~~ ~~~~~~~~~~~
The default status code returned by WSME are 200, 400 (if the client send wrong The default status codes returned by WSME are 200, 400 (if the client sends invalid
inputs) and 500 (for server-side errors). inputs) and 500 (for server-side errors).
Since a proper Rest API should use different return codes (201, etc), one can Since a proper Rest API should use different return codes (201, etc), one can
@ -152,10 +151,10 @@ use the 'status=' option of @signature to do so.
# ... # ...
return data return data
Of course this code will only be used if no error occur. Of course this code will only be used if no error occurs.
In case the function needs to change the status code on a per-request base, it In case the function needs to change the status code on a per-request basis, it
can return a :class:`wsme.Response` object, that allow to override the status can return a :class:`wsme.Response` object, allowing it to override the status
code: code:
.. code-block:: python .. code-block:: python
@ -171,15 +170,15 @@ code:
Extra arguments Extra arguments
~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~
The default behavior of WSME is to reject requests that gives extra/unknown The default behavior of WSME is to reject requests that give extra/unknown
arguments. In some (rare) cases, it can be unwanted. arguments. In some (rare) cases, this is undesirable.
Adding 'ignore_extra_args=True' to @signature changes this behavior. Adding 'ignore_extra_args=True' to @signature changes this behavior.
.. note:: .. note::
If using this option seems to solution to your problem, please think twice If using this option seems to solve your problem, please think twice
before using it ! before using it!
Accessing the request Accessing the request
~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~

View File

@ -6,7 +6,7 @@ General considerations
Using WSME within another framework providing its own REST capabilities is Using WSME within another framework providing its own REST capabilities is
generally done by using a specific decorator to declare the function signature, generally done by using a specific decorator to declare the function signature,
in addition to the framework own way of declaring exposed functions. in addition to the framework's own way of declaring exposed functions.
This decorator can have two different names depending on the adapter. This decorator can have two different names depending on the adapter.
@ -19,18 +19,18 @@ This decorator can have two different names depending on the adapter.
:ref:`adapter-tg1`. :ref:`adapter-tg1`.
``@signature`` ``@signature``
This decorator only set the function signature and returns a function This decorator only sets the function signature and returns a function
that can be used by the host framework as a REST request target. that can be used by the host framework as a REST request target.
Generally this decorator is provided for frameworks that expects functions Generally this decorator is provided for frameworks that expect functions
taking a request object as a single parameter and returning a response taking a request object as a single parameter and returning a response
object. This is the case of :ref:`adapter-cornice` and object. This is the case for :ref:`adapter-cornice` and
:ref:`adapter-flask`. :ref:`adapter-flask`.
Additionnaly, if you want to enable additionnal protocols, you will need to If you want to enable additional protocols, you will need to
mount a :class:`WSRoot` instance somewhere in the application, generally mount a :class:`WSRoot` instance somewhere in the application, generally
``/ws``. This subpath will then handle the additional protocols. In a future ``/ws``. This subpath will then handle the additional protocols. In a future
version, a wsgi middleware will probably play this role. version, a WSGI middleware will probably play this role.
.. note:: .. note::
@ -39,13 +39,13 @@ version, a wsgi middleware will probably play this role.
WSGI Application WSGI Application
---------------- ----------------
The :func:`wsme.WSRoot.wsgiapp` function of WSRoot returns a wsgi The :func:`wsme.WSRoot.wsgiapp` function of WSRoot returns a WSGI
application. application.
Example Example
~~~~~~~ ~~~~~~~
The following example assume the REST protocol will be entirely handled by The following example assumes the REST protocol will be entirely handled by
WSME, which is the case if you write a WSME standalone application. WSME, which is the case if you write a WSME standalone application.
.. code-block:: python .. code-block:: python
@ -164,9 +164,9 @@ Pecan
.. warning:: .. warning::
A pecan application is not able to mount another wsgi application on a A pecan application is not able to mount another WSGI application on a
subpath. For that reason, additional protocols are not supported for now, subpath. For that reason, additional protocols are not supported for now,
ie until wsme provides a middleware that can do the same as a mounted until WSME provides a middleware that can do the same as a mounted
WSRoot. WSRoot.
:mod:`wsmeext.pecan` -- Pecan adapter :mod:`wsmeext.pecan` -- Pecan adapter

View File

@ -10,8 +10,8 @@ REST
.. note:: .. note::
This chapter applies also for the different adapters, not only the native This chapter applies for all adapters, not just the native REST
REST implementation. implementation.
The two REST protocols share common characterics. The two REST protocols share common characterics.
@ -19,8 +19,7 @@ Each function corresponds to distinct webpath that starts with the
root webpath, followed by the controllers names if any, and finally root webpath, followed by the controllers names if any, and finally
the function name. the function name.
For example, the functions exposed functions will be mapped to the The example's exposed functions will be mapped to the following paths:
following paths :
- ``/ws/persons/create`` - ``/ws/persons/create``
- ``/ws/persons/get`` - ``/ws/persons/get``
@ -31,10 +30,10 @@ following paths :
In addition to this trivial function mapping, a `method` option can In addition to this trivial function mapping, a `method` option can
be given to the `expose` decorator. In such a case, the function be given to the `expose` decorator. In such a case, the function
name can be omitted by the caller, and the dispatch will look at the name can be omitted by the caller, and the dispatch will look at the
http method used in the request to select the correct function. HTTP method used in the request to select the correct function.
The function parameters can be transmitted in two ways (is using The function parameters can be transmitted in two ways (if using
the http method to select the function, one way or the other the HTTP method to select the function, one way or the other
may be usable) : may be usable) :
#. As a GET query string or POST form parameters. #. As a GET query string or POST form parameters.
@ -49,7 +48,7 @@ may be usable) :
#. In a Json or XML encoded POST body (see below) #. In a Json or XML encoded POST body (see below)
The result will be return Json or XML encoded (see below). The result will be returned Json or XML encoded (see below).
In case of error, a 400 or 500 status code is returned, and the In case of error, a 400 or 500 status code is returned, and the
response body contains details about the error (see below). response body contains details about the error (see below).
@ -63,8 +62,8 @@ Implements a REST+Json protocol.
This protocol is selected if: This protocol is selected if:
- The request content-type is either text/javascript or application/json - The request content-type is either 'text/javascript' or 'application/json'
- The request 'Accept' header contains 'text/javascript' or 'application.json' - The request 'Accept' header contains 'text/javascript' or 'application/json'
- A trailing '.json' is added to the path - A trailing '.json' is added to the path
- A 'wsmeproto=restjson' is added in the query string - A 'wsmeproto=restjson' is added in the query string
@ -108,11 +107,11 @@ Types
Return Return
~~~~~~ ~~~~~~
The json encoded result when the response code is 200, OR a json object The Json encoded result when the response code is 200, or a Json object
with error properties ('faulcode', 'faultstring' and 'debuginfo' if with error properties ('faulcode', 'faultstring' and 'debuginfo' if
available). available) on error.
For example, the /ws/person/get result looks like: For example, the '/ws/person/get' result looks like:
.. code-block:: javascript .. code-block:: javascript
@ -143,7 +142,7 @@ REST+XML
This protocol is selected if This protocol is selected if
- The request content-type is text/xml - The request content-type is 'text/xml'
- The request 'Accept' header contains 'text/xml' - The request 'Accept' header contains 'text/xml'
- A trailing '.xml' is added to the path - A trailing '.xml' is added to the path
- A 'wsmeproto=restxml' is added in the query string - A 'wsmeproto=restxml' is added in the query string
@ -245,7 +244,7 @@ Implements the SOAP protocol.
A wsdl definition of the webservice is available at the 'api.wsdl' subpath. A wsdl definition of the webservice is available at the 'api.wsdl' subpath.
(``/ws/api.wsdl`` in our example). (``/ws/api.wsdl`` in our example).
The protocol is selected if the request match one of the following condition: The protocol is selected if the request matches one of the following condition:
- The Content-Type is 'application/soap+xml' - The Content-Type is 'application/soap+xml'
- A header 'Soapaction' is present - A header 'Soapaction' is present

View File

@ -1,13 +1,13 @@
Types Types
===== =====
3 kinds of data types can be used as input or output by WSME. Three kinds of data types can be used as input or output by WSME.
Native types Native types
------------ ------------
The native types are a fixed set of standard python types that The native types are a fixed set of standard Python types that
the different protocols will map to theirs own basic types. different protocols map to their own basic types.
The native types are : The native types are :
@ -59,7 +59,7 @@ The native types are :
def getlist(self): def getlist(self):
return ['a', 'b', 'c'] return ['a', 'b', 'c']
- Dictionaries -- Statically typed mapping are allowed. When exposing - Dictionaries -- Statically typed mappings are allowed. When exposing
a dictionary datatype, you can specify the key and value types, a dictionary datatype, you can specify the key and value types,
with a restriction on the key value that must be a 'pod' type. with a restriction on the key value that must be a 'pod' type.
Example:: Example::
@ -67,16 +67,16 @@ The native types are :
class SomeType(object): class SomeType(object):
amap = {str: SomeOthertype} amap = {str: SomeOthertype}
There are other types that are supported out of the box, see There are other types that are supported out of the box. See the
the :ref:`pre-defined-user-types`. :ref:`pre-defined-user-types`.
User types User types
---------- ----------
User types allow to define new almost-native types. User types allow you to define new, almost-native types.
The idea is that you may have python data that should be transported as native The idea is that you may have Python data that should be transported as base
types by the different protocols, but needs conversion to/from this basetypes, types by the different protocols, but needs conversion to/from these base types,
or needs to validate data integrity. or needs to validate data integrity.
To define a user type, you just have to inherit from To define a user type, you just have to inherit from
@ -101,7 +101,7 @@ WSME provides some pre-defined user types:
pre-defined list of values. pre-defined list of values.
These types are good examples of how to define user types. Have These types are good examples of how to define user types. Have
a look at their source code ! a look at their source code!
Here is a little example that combines :class:`binary <wsme.types.binary>` Here is a little example that combines :class:`binary <wsme.types.binary>`
and :class:`Enum <wsme.types.Enum>`:: and :class:`Enum <wsme.types.Enum>`::
@ -116,7 +116,7 @@ and :class:`Enum <wsme.types.Enum>`::
.. data:: wsme.types.binary .. data:: wsme.types.binary
The :class:`wsme.types.BinaryType` instance to use when you need to The :class:`wsme.types.BinaryType` instance to use when you need to
transfert base64 encoded data. transfer base64 encoded data.
.. autoclass:: wsme.types.BinaryType .. autoclass:: wsme.types.BinaryType
@ -126,24 +126,24 @@ and :class:`Enum <wsme.types.Enum>`::
Complex types Complex types
------------- -------------
Complex types are structured types. They are defined as simple python classes Complex types are structured types. They are defined as simple Python classes
and will be mapped to adequate structured types in the various protocols. and will be mapped to adequate structured types in the various protocols.
A base class for structured types is proposed, :class:`wsme.types.Base`, A base class for structured types is provided, :class:`wsme.types.Base`,
but is not mandatory. The only thing it add is a default constructor. but is not mandatory. The only thing it adds is a default constructor.
The attributes that are set at the class level will be used by WSME to discover The attributes that are set at the class level will be used by WSME to discover
the structure. These attributes can be: the structure. These attributes can be:
- A datatype -- Any native, user or complex type. - A datatype -- Any native, user or complex type.
- A :class:`wsattr <wsme.wsattr>` -- Allow to add more information about - A :class:`wsattr <wsme.wsattr>` -- This allows you to add more information about
the attribute, for example if it is mandatory. the attribute, for example if it is mandatory.
- A :class:`wsproperty <wsme.wsproperty>` -- Special typed property. Works - A :class:`wsproperty <wsme.wsproperty>` -- A special typed property. Works
like standard properties with additional properties like like standard ``property`` with additional properties like
:class:`wsattr <wsme.wsattr>`. :class:`wsattr <wsme.wsattr>`.
Attributes having a leading '_' in there name will be ignored, as well as the Attributes having a leading '_' in their name will be ignored, as well as the
ones that are none of the above list. It means the type can have functions, attributes that are not in the above list. This means the type can have methods,
they will not get in the way. they will not get in the way.
Example Example
@ -177,10 +177,10 @@ A few things you should know about complex types:
(and thus inspected) as soon a they are used in expose or validate, (and thus inspected) as soon a they are used in expose or validate,
even if they are nested in another complex type. even if they are nested in another complex type.
If for some reasons you need to control when type is inspected, you If for some reason you need to control when type is inspected, you
can use :func:`wsme.types.register_type`. can use :func:`wsme.types.register_type`.
- The datatype attributes will be replaced - The datatype attributes will be replaced.
When using the 'short' way of defining attributes, ie setting a When using the 'short' way of defining attributes, ie setting a
simple data type, they will be replaced by a wsattr instance. simple data type, they will be replaced by a wsattr instance.
@ -207,7 +207,7 @@ A few things you should know about complex types:
assert Person.name.key == "name" assert Person.name.key == "name"
assert Person.name.mandatory is False assert Person.name.mandatory is False
- The default value of instances attributes is - The default value of instance attributes is
:data:`Unset <wsme.Unset>`. :data:`Unset <wsme.Unset>`.
:: ::
@ -218,13 +218,13 @@ A few things you should know about complex types:
p = Person() p = Person()
assert p.name is Unset assert p.name is Unset
This allow the protocol to make a clear distinction between null values This allows the protocol to make a clear distinction between null values
that will be transmitted, and unset values that will not be transmitted. that will be transmitted, and unset values that will not be transmitted.
For input values, it allows the code to know if the values were, or not, For input values, it allows the code to know if the values were, or were not,
sent by the caller. sent by the caller.
- When 2 complex types refers to each other, their names can be - When 2 complex types refer to each other, their names can be
used as datatypes to avoid adding attributes afterwards: used as datatypes to avoid adding attributes afterwards:
:: ::