Merged cdevienne/wsme into default
This commit is contained in:
commit
3d69ac33d8
@ -62,7 +62,7 @@ Main features
|
|||||||
- Extensible : easy to add more protocols or more base types.
|
- Extensible : easy to add more protocols or more base types.
|
||||||
- Framework independance : adapters are provided to easily integrate
|
- Framework independance : adapters are provided to easily integrate
|
||||||
your API in any web framework, for example a wsgi container,
|
your API in any web framework, for example a wsgi container,
|
||||||
Pecan_, TurboGears_, cornice_...
|
Pecan_, TurboGears_, Flask_, cornice_...
|
||||||
- Very few runtime dependencies: webob, simplegeneric. Optionnaly lxml and
|
- Very few runtime dependencies: webob, simplegeneric. Optionnaly lxml and
|
||||||
simplejson if you need better performances.
|
simplejson if you need better performances.
|
||||||
- Integration in `Sphinx`_ for making clean documentation with
|
- Integration in `Sphinx`_ for making clean documentation with
|
||||||
@ -70,6 +70,7 @@ Main features
|
|||||||
|
|
||||||
.. _Pecan: http://pecanpy.org/
|
.. _Pecan: http://pecanpy.org/
|
||||||
.. _TurboGears: http://www.turbogears.org/
|
.. _TurboGears: http://www.turbogears.org/
|
||||||
|
.. _Flask: http://flask.pocoo.org/
|
||||||
.. _cornice: http://pypi.python.org/pypi/cornice
|
.. _cornice: http://pypi.python.org/pypi/cornice
|
||||||
|
|
||||||
Install
|
Install
|
||||||
|
@ -4,6 +4,8 @@ Changes
|
|||||||
next
|
next
|
||||||
----
|
----
|
||||||
|
|
||||||
|
* New Flask adapter: wsmeext.flask
|
||||||
|
|
||||||
* Fix: Submodules of wsmeext were missing in the packages.
|
* Fix: Submodules of wsmeext were missing in the packages.
|
||||||
|
|
||||||
* Fix: The demo app was still depending on the WSME-Soap package (which has
|
* Fix: The demo app was still depending on the WSME-Soap package (which has
|
||||||
|
@ -110,6 +110,44 @@ Example
|
|||||||
print("Got a message: %s" % info.message)
|
print("Got a message: %s" % info.message)
|
||||||
|
|
||||||
|
|
||||||
|
.. _adapter-flask:
|
||||||
|
|
||||||
|
Flask
|
||||||
|
-----
|
||||||
|
|
||||||
|
*"Flask is a microframework for Python based on Werkzeug, Jinja 2 and good intentions. And before you ask: It's BSD licensed! "*
|
||||||
|
|
||||||
|
|
||||||
|
.. warning::
|
||||||
|
|
||||||
|
Flask support is limited to function signature handling. It does not
|
||||||
|
support additional protocols. This is a temporary limitation, if you have
|
||||||
|
needs on that matter please tell us at python-wsme@googlegroups.com.
|
||||||
|
|
||||||
|
|
||||||
|
:mod:`wsmeext.flask` -- Flask adapter
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
.. module:: wsmeext.flask
|
||||||
|
|
||||||
|
.. function:: signature(return_type, \*arg_types, \*\*options)
|
||||||
|
|
||||||
|
See @\ :func:`signature` for parameters documentation.
|
||||||
|
|
||||||
|
Can be used on a function before routing it with flask.
|
||||||
|
|
||||||
|
Example
|
||||||
|
~~~~~~~
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from wsmeext.flask import signature
|
||||||
|
|
||||||
|
@app.route('/multiply')
|
||||||
|
@signature(int, int, int)
|
||||||
|
def multiply(a, b):
|
||||||
|
return a * b
|
||||||
|
|
||||||
.. _adapter-pecan:
|
.. _adapter-pecan:
|
||||||
|
|
||||||
Pecan
|
Pecan
|
||||||
|
@ -9,6 +9,11 @@ class Model(Base):
|
|||||||
name = text
|
name = text
|
||||||
|
|
||||||
|
|
||||||
|
class Criterion(Base):
|
||||||
|
op = text
|
||||||
|
attr = text
|
||||||
|
value = text
|
||||||
|
|
||||||
test_app = Flask(__name__)
|
test_app = Flask(__name__)
|
||||||
|
|
||||||
|
|
||||||
@ -25,9 +30,13 @@ def divide_by_zero():
|
|||||||
|
|
||||||
|
|
||||||
@test_app.route('/models')
|
@test_app.route('/models')
|
||||||
@signature([Model])
|
@signature([Model], [Criterion])
|
||||||
def list_models():
|
def list_models(q=None):
|
||||||
return [Model(name='first')]
|
if q:
|
||||||
|
name = q[0].value
|
||||||
|
else:
|
||||||
|
name = 'first'
|
||||||
|
return [Model(name=name)]
|
||||||
|
|
||||||
|
|
||||||
@test_app.route('/models/<name>')
|
@test_app.route('/models/<name>')
|
||||||
@ -63,6 +72,14 @@ class FlaskrTestCase(unittest.TestCase):
|
|||||||
resp = self.app.get('/models')
|
resp = self.app.get('/models')
|
||||||
assert resp.status_code == 200
|
assert resp.status_code == 200
|
||||||
|
|
||||||
|
def test_array_parameter(self):
|
||||||
|
resp = self.app.get('/models?q.op=%3D&q.attr=name&q.value=second')
|
||||||
|
assert resp.status_code == 200
|
||||||
|
print resp.data
|
||||||
|
self.assertEquals(
|
||||||
|
resp.data, '[{"name": "second"}]'
|
||||||
|
)
|
||||||
|
|
||||||
def test_post_model(self):
|
def test_post_model(self):
|
||||||
resp = self.app.post('/models', data={"body.name": "test"})
|
resp = self.app.post('/models', data={"body.name": "test"})
|
||||||
assert resp.status_code == 200
|
assert resp.status_code == 200
|
||||||
|
@ -81,11 +81,19 @@ def from_params(datatype, params, path, hit_paths):
|
|||||||
|
|
||||||
@from_params.when_type(ArrayType)
|
@from_params.when_type(ArrayType)
|
||||||
def array_from_params(datatype, params, path, hit_paths):
|
def array_from_params(datatype, params, path, hit_paths):
|
||||||
|
if hasattr(params, 'getall'):
|
||||||
|
# webob multidict
|
||||||
|
def getall(params, path):
|
||||||
|
return params.getall(path)
|
||||||
|
elif hasattr(params, 'getlist'):
|
||||||
|
# werkzeug multidict
|
||||||
|
def getall(params, path): # noqa
|
||||||
|
return params.getlist(path)
|
||||||
if path in params:
|
if path in params:
|
||||||
hit_paths.add(path)
|
hit_paths.add(path)
|
||||||
return [
|
return [
|
||||||
from_param(datatype.item_type, value)
|
from_param(datatype.item_type, value)
|
||||||
for value in params.getall(path)]
|
for value in getall(params, path)]
|
||||||
|
|
||||||
if iscomplex(datatype.item_type):
|
if iscomplex(datatype.item_type):
|
||||||
attributes = set()
|
attributes = set()
|
||||||
@ -99,7 +107,7 @@ def array_from_params(datatype, params, path, hit_paths):
|
|||||||
for attrdef in list_attributes(datatype.item_type):
|
for attrdef in list_attributes(datatype.item_type):
|
||||||
attrpath = '%s.%s' % (path, attrdef.key)
|
attrpath = '%s.%s' % (path, attrdef.key)
|
||||||
hit_paths.add(attrpath)
|
hit_paths.add(attrpath)
|
||||||
attrvalues = params.getall(attrpath)
|
attrvalues = getall(params, attrpath)
|
||||||
if len(value) < len(attrvalues):
|
if len(value) < len(attrvalues):
|
||||||
value[-1:] = [
|
value[-1:] = [
|
||||||
datatype.item_type()
|
datatype.item_type()
|
||||||
@ -158,7 +166,9 @@ def args_from_args(funcdef, args, kwargs):
|
|||||||
newargs.append(from_param(argdef.datatype, arg))
|
newargs.append(from_param(argdef.datatype, arg))
|
||||||
newkwargs = {}
|
newkwargs = {}
|
||||||
for argname, value in kwargs.items():
|
for argname, value in kwargs.items():
|
||||||
newkwargs[argname] = from_param(funcdef.get_arg(argname).datatype, value)
|
newkwargs[argname] = from_param(
|
||||||
|
funcdef.get_arg(argname).datatype, value
|
||||||
|
)
|
||||||
return newargs, newkwargs
|
return newargs, newkwargs
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user