Skip to content

Commit

Permalink
Updating documentation and README content
Browse files Browse the repository at this point in the history
  • Loading branch information
Tythos committed Jun 16, 2016
1 parent 62c0d0a commit 14fa564
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 7 deletions.
85 changes: 79 additions & 6 deletions README.rst
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
remisc
======

REST-ful microservice framework for scientific computing. Users define a class
derived from remisc.service.Service, for which microservice operations are
defined by methods decorated by *@remisc.service.isop*. Operations utilize
user-defined models for data exchange, supported by I/O parsing behaviors
defined in the *remisc.dxm* module.
Another framework!? What's the point? Aren't there a thousand-and-one web
frameworks out there already? Don't *some* of them already support REST-oriented
operations? (Spoiler: Sort of...) Who cares about scientific computing anyways?

Here's the problem... Who needs a full-up MVC framework if all you're doing is
passing system model data back and forth, or hosting a simulation service in a
cloud environment? You don't. You need something model-centric, which doesn't
assume clients are using a web browser. You need something that's going to
provide the supporting infrastructure, like WSGI mapping and automated operation
& model documentation, with the least possible overhead of work and processing
power. Focus on the unique part of your work--defining operations and the models
they use--and let *remisc* take care of everything else.

Services
--------
Expand All @@ -17,7 +24,7 @@ parsed from the URL's query string segment. They should return a textual
response. A request will be mapped to an operation method by matching the method
name to the top-level directory in the request URL (i.e., if a service is hosted
on http://mysvcs.com/, the request to http://mysvcs.com/test will look for the
method 'test' of the host Service-derived class.
method *test* of the host Service-derived class.

The base Service class includes an *app()* method that defines a WSGI-compliant
application interface used to parse request arguments, map them to the
Expand Down Expand Up @@ -68,3 +75,69 @@ core module *wsgiref*'s *simple_server* model to host a Service. All
Service-derived classes include a WSGI-compliant *app()* method invoked by the
server host process. For production runs, it is strongly advised to invoke that
methods from a production-level WSGI server instead.

Getting Started
---------------

In Action
~~~~~~~~~

When the *remisc.server.main* method is invoked directly, the reference WSGI
server in Python's core module *wsgiref* is used to host an instance of a given
*remisc.service.Service* class. (If no class is provided, the base class is used
instead.) This can be done procedurally::

>>> from remisc import server
>>> server.main()
Serving "remisc.service.Service" with wsgiref.simple_server @ 127.0.0.1:8000

If you use your web browser to load *http://127.0.0.1:8000*, you will see the
default operation implemented by the *remisc.service.Service._root()* method
("Here is the base."). You will also see, in the Python environment where you
launched the server, how that request was mapped to an operation by the WSGI
application interface implemented by *remisc.service.Service.app()*::

"http://127.0.0.1:8000/" => "_root"
127.0.0.1 - - [{date} {time}] "GET / HTTP/1.1" 200 {response time}
"http://127.0.0.1:8000/favicon.ico" => "_null"
127.0.0.1 - - [{date} {time}] "GET /favicon.ico HTTP/1.1" 200 {response time}

Note that most browsers implicitly request *favicon.ico* with each page request;
this is one useful application of the *_null* method, which is hard-coded to
reply to such requests with an empty response.

You can view the base responses directly by browsing to the following URLs while
your test server is still running. Once you have seen the responses, press
CTRL-C in the Python environment to stop the server.

- http://127.0.0.1:8000/_root
- http://127.0.0.1:8000/_null
- http://127.0.0.1:8000/_help

Your Own Service
~~~~~~~~~~~~~~~~

Subclassing *remisc.service.Service* will let you define your own operations and
override those already implemented. Make sure you decorate each method that
implements an operation with *@remisc.service.isop*. Such methods should take
two arguments: a *urlparse* object capturing the original request, and an args
dictionary constructed from the URL query string. The operation should return
the textual content of the response.

For example, let's implement a simple service *Joker* that implements a *joke*
operation::

>>> from remisc import service
>>> class Joker(service.Service):
>>> @service.isop
>>> def joke(self, urlobj, args):
>>> return 'Why did the spam cross the road?\n\nTo evade the dead parrot!'

We can host this service by passing the class to the *remisc.server.main*
function as the *Svc* parameter::

>>> server.main(Svc=Joker)

Now, try browsing to http://127.0.0.1:8000/joke. For a bonus, note that your new
operation has automatically been added to the response at
http://127.0.0.1:8000/_help!
5 changes: 4 additions & 1 deletion docs/remisc.dxm.html
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,10 @@
<td colspan=3 valign=bottom>&nbsp;<br>
<font color="#000000" face="helvetica, arial"><a name="Empty">class <strong>Empty</strong></a>(<a href="__builtin__.html#object">__builtin__.object</a>)</font></td></tr>

<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
<tr bgcolor="#ffc8d8"><td rowspan=2><tt>&nbsp;&nbsp;&nbsp;</tt></td>
<td colspan=2><tt>This&nbsp;is&nbsp;an&nbsp;empty&nbsp;class&nbsp;used&nbsp;to&nbsp;define&nbsp;a&nbsp;data&nbsp;exchange&nbsp;model&nbsp;for&nbsp;testing,<br>
demonstration,&nbsp;and&nbsp;(although&nbsp;completely&nbsp;unnecessary)&nbsp;extension&nbsp;purposes.<br>&nbsp;</tt></td></tr>
<tr><td>&nbsp;</td>
<td width="100%">Data descriptors defined here:<br>
<dl><dt><strong>__dict__</strong></dt>
<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
Expand Down
3 changes: 3 additions & 0 deletions dxm.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,7 @@ def isdxm(cls):

@isdxm
class Empty(object):
"""This is an empty class used to define a data exchange model for testing,
demonstration, and (although completely unnecessary) extension purposes.
"""
pass

0 comments on commit 14fa564

Please sign in to comment.