Git Product home page Git Product logo

calm's Introduction

Calm

Calm Logo

PyPI Build Status Coverage Status Code Health Gitter License

Introduction

Calm is an extension to Tornado Framework that provides decorators and other tools to easily implement RESTful APIs. The purpose of Calm is to ease the process of defining your API, parsing argument values in the request handlers, etc.

Installation

Calm installation process is dead simple with pip:

$ pip install calm

Note: Calm works only with Python 3.5

Let's code!

Here is a basic usage example of Calm:

import tornado.ioloop
from calm import Application


app = Application()


@app.get('/hello/:your_name')
async def hello_world(request, your_name):
    return {'hello': your_name}


tornado_app = app.make_app()
tornado_app.listen(8888)
tornado.ioloop.IOLoop.current().start()

Now go ahead and try your new application! Navigate to http://localhost:8888/hello/YOUR_NAME_HERE and see what you get.

Now that you built your first Calm RESTful API, let us dive deeper and see more features of Calm. Go ahead and add the following code to your first application.

# Calm has the notion of a Service. A Service is nothing more than a URL prefix for
# a group of endpoints.
my_service = app.service('/my_service')


# So when usually you would define your handler with `@app.get`
# (or `post`, `put`, `delete`), with Service you use the same named methods of
# the Service instance
@my_service.post('/body_demo')
async def body_demo(request):
    """
    The request body is automatically parsed to a dict.

    If the request body is not a valid JSON, `400` HTTP error is returned.

    When the handler returns not a `dict` object, the return value is nested
    into a JSON, e.g.:

        {"result": YOUR_RETURN_VALUE}

    """
    return request.body['key']


@my_service.get('/args_demo/:number')
async def args_demo(request, number: int, arg1: int, arg2='arg2_default'):
    """
    You can specify types for your request arguments.

    When specified, Calm will parse the arguments to the appropriate type. When
    there is an error parsing the value, `400` HTTP error is returned.

    Any function parameters that do not appear as path arguments, are
    considered query arguments. If a default value is assigned for a query
    argument it is considered optional. And finally if not all required query
    arguments are passed, `400` HTTP error is returned.
    """
    return {
        'type(number)': str(type(number)),
        'type(arg1)': str(type(arg1)),
        'arg2': arg2
    }

If you followed the comments in the example, then we are ready to play with it!

First let us see how Calm treats request and response bodies:

$ curl -X POST --data '{"key": "value"}' 'localhost:8888/my_service/body_demo'
{"result": "value"}

$ curl -X POST --data '{"another_key": "value"}' 'localhost:8888/my_service/body_demo'
{"error": "Oops our bad. We are working to fix this!"}

$ curl -X POST --data 'This is not JSON' 'localhost:8888/my_service/body_demo'
{"error": "Malformed request body. JSON is expected."}

Now it's time to observe some request argument magic!

$ curl 'localhost:8888/my_service/args_demo/0'
{"error": "Missing required query param 'arg1'"}

$ curl 'localhost:8888/my_service/args_demo/0?arg1=12'
{"type(arg1)": "<class 'int'>", "type(number)": "<class 'int'>", "arg2": "arg2_default"}

$ curl 'localhost:8888/my_service/args_demo/0?arg1=not_a_number'
{"error": "Bad value for integer: not_a_number"}

$ curl 'localhost:8888/my_service/args_demo/0?arg1=12&arg2=hello'
{"type(arg1)": "<class 'int'>", "type(number)": "<class 'int'>", "arg2": "hello"}

Adding custom RequestHandler implementations

If you have a custom Tornado RequestHandler implementation, you can easily add them to your Calm application in one of the two ways:

  • using the Application.add_handler method
  • using the Application.custom_handler decorator

For the first option, you can just define the custom handler and manually add it to the Calm application, just like you would define a Tornado application:

class MyHandler(RequestHandler):
    def get(self):
        self.write('Hello Custom Handler!')

app.add_handler('/custom_handler', MyHandler)

The second option might look more consistent with other Calm-style definitions:

@app.custom_handler('/custom_handler')
class MyHandler(RequestHandler):
    def get(self):
        self.write('Hello Custom Handler!')

You can also use the custom_handler decorator of services, e.g.:

custom_service = app.service('/custom')

@custom_service.custom_handler('/custom_handler')
class MyHandler(RequestHandler):
    def get(self):
        self.write('Hello Custom Handler!')

Contributions

Calm loves Pull Requests and welcomes any contribution be it an issue, documentation or code. A good start for a contribution can be reviewing existing open issues and trying to fix one of them.

If you find nothing to work on but cannot kill the urge, jump into the gitter channel and ask "what can I do?".

calm's People

Contributors

haykd avatar mivade avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

Forkers

gitter-badger

calm's Issues

Add mechanism for setting default headers

Hi
Firstly, thank you for releasing Calm - I am having fun working with it.

I found that I needed to set a default header on all requests to enable CORS. I ended up using the following hack:

import calm.core
def set_default_headers(self, args, **kwargs):
self.set_header("Access-Control-Allow-Origin", "
")

calm.core.MainHandler.set_default_headers = set_default_headers

May be this is not the correct way to achieve this, but it would be great if there was a documented way to add a default header with out having to use custom request handler classes.

Many thanks

Richard

Add security layer

Add a means to be able to define Calm Application security layer:

  • Add decorators and classes to define the security logic
  • Add security definitions to swagger.json

Update PyPI long description

PyPI does not support Markdown as the long_description format, thus we cannot use README.md for it.

Write up a brief description of Calm including all references for more information.

JSON-ify 404 page

When a URL is not found the Tornado 404 response is returned to the client, which happens to be HTML.

Make a custom JSON 404 response by configuring Tornado's default_handler application setting.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.