From 2c3231db49f05e40c87424c16d6494947788f798 Mon Sep 17 00:00:00 2001 From: Vasudev Kamath Date: Tue, 3 Jun 2014 20:13:50 +0530 Subject: New post on wsme with Flask apps --- content/development/wsme_with_flask.rst | 156 ++++++++++++++++++++++++++++++++ 1 file changed, 156 insertions(+) create mode 100644 content/development/wsme_with_flask.rst diff --git a/content/development/wsme_with_flask.rst b/content/development/wsme_with_flask.rst new file mode 100644 index 0000000..b69e40f --- /dev/null +++ b/content/development/wsme_with_flask.rst @@ -0,0 +1,156 @@ +Using WSME with Flask microframework +#################################### + +:date: 2014-06-03 20:15 +:slug: wsme-with-flask +:tags: python, programming, wsme, rest +:authors: copyninja +:summary: This is short guide on how to use wsme with Flask + applications, writing this because I felt documentation is + lacking. + +After reading `Julien Danjou's `_ I found +out WSME (Web Service Made Easy) a Python framework which allows us to +easily create Web Services in Python. For `SILPA +`_ we needed a REST like interface and I thought +of giving it try as WSME readily advertised the Flask integration, and +this post was born when I read the documentation for Flask +integration. + +First of all Flask is a nice framework which will right way allow +development of REST api for simple purposes, but my requirement was +bit complicated where I had to expose function in a separate python +modules through SILPA. I think detailed requirement can be part of +another post, so let me explain how to use WSME with Flask app. + +WSME integration with Flask is done via decorator function +`wsmeext.flask.signature` which expects you to provide it with +signature of function to expose. And `here +`_ +is its documentation, basically signature of `signature` function is + +.. code-block:: python + + wsmeext.flask.signature(return_type, *arg_types, **options) + +Yeah thats all docs have sadly. + +So basically exposing is the only thing WSME handles for us here, +routing and other stuffs need to be done by Flask itself. So lets +consider a example, simple function to add as shown below. + +.. code-block:: python + + def add(a, b): + return a + b + +For providing REST like service, all you need below code. + +.. code-block:: python + + from flask import Flask + from wsmeext.flask import signature + + app = Flask(__name__) + + @app.route('/add') + @signature(int, int, int) + def add(a, b): + return a + b + + if __name__ == '__main__': + app.run() + +So first argument to `signature` is return type of function and rest +arguments are the argument to function to be exposed. Now you can +access the newly exposed service by visiting +*http://localhost:5000/add* but don't forget to pass the arguments +either via query string or through post. You can restrict methods of +access via Flask's `route`. + +So what's the big deal of not having docs right?.. Well fun part began +when we use bit more complex return type like *dictionaries* or +*lists* . Below is modified code I'm using to demonstrate problem I +faced during using `dict` as return type. + +.. code-block:: python + + from flask import Flask + from wsmeext.flask import signature + + app = Flask(__name__) + + @app.route('/add') + @signature(dict, int, int) + def add(a, b): + return {"result": a + b} + + if __name__ == '__main__': + app.run() + + +Basically I'm returning a dictionary containing result now, for +demonstration purpose. When I run the application **boom** python +barked at me with following message. + +.. code-block:: py3tb + + Traceback (most recent call last): + File "wsme_dummy.py", line 7, in + @signature(dict, int, int) + File "c:\Users\invakam2\.virtualenvs\wsmetest\lib\site-packages\wsmeext\flask.py", line 48, in decorator + funcdef.resolve_types(wsme.types.registry) + File "c:\Users\invakam2\.virtualenvs\wsmetest\lib\site-packages\wsme\api.py", line 109, in resolve_types + self.return_type = registry.resolve_type(self.return_type) + File "c:\Users\invakam2\.virtualenvs\wsmetest\lib\site-packages\wsme\types.py", line 739, in resolve_type + type_ = self.register(type_) + File "c:\Users\invakam2\.virtualenvs\wsmetest\lib\site-packages\wsme\types.py", line 668, in register + class_._wsme_attributes = None + TypeError: can't set attributes of built-in/extension type 'dict' + + +After going through code from files involved in above traces this is +what I found + +1. `wsmeext.flask.signature` inturn uses `wsme.signature` which is + just alias of `wsme.api.signature`. +2. Link in documentation in sentence *See @signature for parameter + documentation* is broken and should actually link to + `wsme.signature` in docs. +3. `wsme.signature` actually calls `resolve_type` to check on types of + return and arguments. This function checks if types are instance of + `dict` or `list` in such cases it creates instances of + `wsme.type.DictType` and `wsme.type.ArrayType` respectively with + values from the argument. +4. When I just passed built-in type `dict` the control went to else + part which just passed the type to `wsme.type.Register.registry` + function which tries to set the attribute `_wsme_attribute` which + actually raises `TypeError` as we can't set attribute for built-in + types. + +So by inspecting code of `wsme.type.Registry.resolve_type` and +`wsme.type.Registry.register` its clear that what signature expects +when arguments or return type is dictionary/list is instance of +dictionary/list with `type` of value in it. May be sentence is bit +vague but I'm not sure how to put it more clearly, as an example in +our case add function returns dictioanry with key as string and value +as int, so return type argument for signature will be `{str: +int}`. Similarly if you return array with int values it will be +`[int]`. + +With above understanding our add function now looks like below. + +.. code:: python + + @signature({str: int}, int, int) + def add(a, b): + return {'result': a + b} + + +and now code worked just fine!. What I couldn't figure out here is +there is no way to have `tuple` as return value or argument, but I +guess that is not big deal. + +So immidiate task for me after finding this is fix the link in +documentation to point to `wsme.signature` and probably put some note +some where in documentation about above finding. -- cgit v1.2.3