Introducción a 

Joel Rivera

@cyraxjoe

19 de Noviembre de 2015

www.pymty.org

Agenda

  • Introducción
  • ¿Cómo se usa?
  • ¿Cuándo usarlo?
  • ¿Quién lo usa?
  • Preguntas

Introducción

CherryPy

Es un web framework minimalista orientado a objetos con un estilo de desarrollo simple semejante a Python común y corriente.

Características principales

 

  • Robusto, rápido, suporta SSL y HTTP 1.1

  • No es necesario hacer reverse proxy o algún otro servidor de frontal (mod_wsgi).

  • Fácil para iniciar a usarlo

  • No tiene dependencias externas

  • Arquitectura de extensiones muy poderosa

Partes claves de su arquitectura

  • cherrypy.engine: Controla el manejo de procesos startup/teardown y manejo de eventos.

  • cherrypy.server: Configura y controla el servidor WSGI o HTTP.

  • cherrypy.tools: Caja de herramientas para el manejo de las peticiones HTTP. e.g. sesiones, json, autorización, etc

Hola Mundo

import cherrypy as cp


class Root:

    @cp.expose
    def index(self):
        return "Hola Mundo!"

    @cp.expose
    def user(self, uid):
        return "Información de usuario {}".format(uid)


if __name__ == "__main__":
    cp.quickstart(Root())

¿Cómo se usa?

Componentes principales

  • Handlers / Controladores

  • Tools

  • Plugins

  • Dispatchers

Handlers

Son objetos en python que se relacionan a las partes de una URL

class UserApp:

    @cherrypy.expose
    def sub_path(self):
        return "Sub Path"

Handlers

class App:

    def __init__(self):
         self.project = Project()

    @cp.expose
    def index(self):
        return "Indice"

    @cp.expose
    def default(self, *args, **kwargs):
        return "Catch all args: {}, " \
               "kwargs: {}".format(args, kwargs)

    @cp.expose
    def tasks(self, tid, name, **datos):
        return "Indice de tareas"

class Project:

    @cp.expose
    def index(self):
        return "Indice de proyectos"    

1

2

3

4

Composición de objetos/aplicaciones

Se asigna al path: "/"

Atrapa todo lo que no se define en el objeto

       Se asigna al path:

/tareas/<tid>/<name>?datos

Donde datos representan los parámetros en la URL

Usando el dispatcher default

Handlers

class Project:
    exposed = True

    def GET(self):
        return "Indice de proyectos"    

class Tasks:
    exposed = True

    def GET(self, tid=None):
        if tid is None:
            return "Indice de tareas"
        return "Tarea {}".format(tid) 

    def DELETE(self, tid):
        return "DELETED"

class App:
    exposed = True
    project = Project()
    tasks   = Tasks()

    def GET(self):
        return "Indice"
                  

1

Usando MethodDispatcher

Los métodos se nombran como los verbos de HTTP

Al igual, se compone de sub-handers/objetos.

Se expone a nivel de recurso, no a nivel de método.

2

3

Partes importantes para un handler

  • cherrypy.config: Determina el comportamiento de la aplicación en cada path

  • cherrypy.tree: Árbol de objetos que representa a la aplicación

  • cherrypy.request: Un objeto thread_local que representa a la petición HTTP

  • cherrypy.response: Un objeto thread_local que representa la respuesta a la petición HTTP

Tools

CherryPy uses Tools to change application behavior at various points in the http request lifecycle.

cherrypy.tools.TOOL_NAME.on = True

 enables a tool

cherrypy.tools.TOOL_NAME.<parameter> = <value> 

sets Tool parameters.


Tools do not (typically) deepen the call stacks like decorators or middleware.

 

Builtin Tools

  • Session

  • XMLRPC

  • Auth

  • Caching

  •  Allow

  •  Proxy

  •  ResponseHeaders

  • Logging

  • Error Handling

  • ETags

  • Encoding/Decoding

  • GZip

  • JSON

Tool hooks

POST / HTTP/1.0
on_start_resource
Content-Type: application/x-www-form-urlencoded
Content-Length: 135
before_request_body
param1=one&param2=two...
before_handler
<handler called>
before_finalize
Content-Type: text/html
...
<html>...</html>
on_end_resource
Connection closed.
on_end_request    
* before_error_response
* after_error_response

Plugins

class ScratchDB(plugins.SimplePlugin):
 
    def start(self):
        self.fname = 'myapp_%d.db' % os.getpid()
        self.db = sqlite.connect(database=self.fname)
    start.priority = 80
 
    def stop(self):
        self.db.close()
        os.remove(self.fname)

cherrypy.engine.scratchdb = ScratchDB(cherrypy.engine)
cherrypy.engine.scratchdb.subscribe()

¿Cuándo usarlo?

Donde es más efectivo

  • Aplicaciones web "stand alone" con ejecutables entregables

  • Extensión de una aplicación de escritorio

  • Sitios web y backend de RESTful APIs de volumen moderado

  • Donde la compatibilidad multi-plataforma sera muy relevante para la aplicación

Donde es menos efectivo

  • Aplicaciones web de alta concurrencia

  • Creación de aplicaciones web grandes de patrones muy bien definidos. e.g. tiendas/CMS/

  • Cuando no se conocer nada de web o Python y se espera que el framework te delimite como construir tu aplicación

  • La inter-operabilidad entre SO es irrelevante

¿Quién lo usa?

Zen of CherryPy

  1. Common tasks should be fast and easy.
  2. Doing nothing should be easier and faster.
  3. Extensions to CherryPy should look like CherryPy.
  4. Objects are better than referents.
  5. Domain-specific Python is better than new DSL's.
  6. But imperative Python is better yet.
  7. Unless that isn't enough.
  8. Subclassed builtins are better than custom types.
  9. But builtin types are even better.
  10. 1 < 2, but 0 > 1
     

¿Preguntas?

We are hiring!