Archive for the 'CherryPy' Category

Using **kwargs with CherryPy and WTForms

Sunday, June 23rd, 2013

I just ran into a problem with using **kwargs as a catchall parameter in cherrypy while sending the data into a form built with WTForms. Like this:


def index(self, **kwargs):
sf = forms.SearchForm(kwargs)

This leads to an error:

TypeError: formdata should be a multidict-type wrapper that supports the 'getlist' method

The reason is that WTForms expects something that supports the ‘getlist’ method while kwargs is a plain dictionary and does not have any ‘getlist’ method. The solution i found was to subclass dict and just add the getlist method. As far as I know, getlist refers to a method in the official cgi module and the cgi module documentation says that

This method always returns a list of values associated with form field name. The method returns an empty list if no such form field or value exists for name. It returns a list consisting of one item if only one such value exists.

So, a simple implementation of a subclass of dict that just adds the getlist method looks like this:


class InputDict(dict):
def getlist(self, arg):
for key in self.keys():
if self.has_key(arg):
if isinstance(self[arg], list):
return self[arg]
else:
return [self[arg]]
else:
return []

And we can use it to fill our form:


def index(self, **kwargs):
sf = forms.SearchForm(InputDict(kwargs))

Search engine friendly urls with CherryPy’s default method

Thursday, December 29th, 2005

My fishing directory haven’t been a success at the search engines and I discovered that most of the pages were listed as Supplemental Results in Google. One reason for that can be urls with question marks and multiple parameters. So i tried to figure out how to implement that. Apache’s mod_rewrite is a common method for this but
it’s just very cryptic. I implemented a search engine friendly url system for an earlier version of CherryPy (0.x) with a filter but filters just have to be more complicated than the solution I found.

CherryPy has a default method that will be called in case of a partial match. It is explained in the CherryPy tutorial (scroll down to “Partial matches and the default method”). So, just define a method named default with a suitable amount of parameters and expose it. With a few lines of Python code I could transform urls like DOMAIN/?node1=10&node2=20 into DOMAIN/10/20 and DOMAIN/website?wid=123 into DOMAIN/website/123,


  def default(self, node1=0, node2=0, pagenr=1, perpage=10):
    if node1 == "website":
      return self.website(node2)
    else: #index method
      if node1 == 0 or node1== "0":
        node1 = ""
      if node2 == 0 or node2 == "0":
        node2 = ""
      return self.index(node1, node2, pagenr, perpage)
  default.exposed = True

The zero-checking is there so I can use DOMAIN/0/10 etc. for urls where node1 isn’t specified and still keep compatibility with the current index method.

I choose to keep perpage and pagenr as normal query string parameters to keep it simple and not overwhelm search engines with a massive amount of pages with friendly urls. The parameter list is adapted at my index method so it is a little hackish to use it for the website method, but it’s simple and it works. Now I just have to change all the output methods and ideally something for 301 redirecting the old-style urls to the new-style urls to get the old urls out of the search engine as fast as possible.

CherryPy 2 beta is out

Friday, December 31st, 2004

Details including changelog and download at the CherryPy website. My simple quickstart guide for the CherryPy 2 alpha release should still be valid.

First CherryPy 2 alpha release out

Tuesday, October 19th, 2004

The first public alpha release of CherryPy2 was made available yesterday. It represents a step away from extensions to the Python language and includes no “toy code”. Because of this, the compilation step is no longer necessary and no modifications have to be done to make current Python editors correctly colorize the code and build browsable code trees.

After you have downloaded the CherryPy2 alpha available from the
CherryPy website, unpack it to a temporary directory. Then, assuming you already have a recent version of Python installed on your computer:

  1. Open a shell (Konsole, Bash, Dos, whatever you have)
  2. Navigate to the temporary directory
  3. Type python setup.py install

Now, the cherrypy module should be installed into your $PYTHON/Lib/site-packages directory. (Edit: It might be $PYTHON/site-packages, depends on OS) Go there and open the tutorials directory. To run a tutorial, do the following

  1. Execute a tutorial script (type python tutorial1.py in a shell f.ex.)
  2. Open a web browser and point it to http://localhost:8080
  3. Play with it
  4. Open the tutorial1.py file in an your favorite Python editor and inspect the code.
    The tutorial files are well commented so it’s easy to understand what is happening.

There’s a small error in the 2 bonus tutorials, they try to import CherryPy.
Just change that to import cherrypy and run.

The templating system that has been built into CherryPy is also released as a pure Python module to go along with CherryPy2 or any other web framework. It’s now called CherryTemplate.

PyPe and CherryClasses

Friday, August 20th, 2004

The CherryPy web framework (for Python) have some great features, like automatic url-to-method mapping. But it uses some “toy code” that makes it hard to handle for some Python editors. PyPe is a Python editor written in Python, so it’s easy to modify for a Python programmer. Let’s modify the builtin class browser so it handles CherryPy files perfectly. To follow this guide you should have PyPe installed (I have some problems with version 1.9.3, but 1.9.2 works perfectly) and a CherryClass (any .cpy file from the CherryPy distribution up to the current 0.10) or this file. Future versions of CherryPy will use only Regular Python code so unfortunately this guide will not be so useful within a few months. Let’s first take a look at the PyPe class browser’s presentation of a CherryClass :

CherryClass before

As you see, it only shows the functions. We want it to create a browsable tree with the CherryClass at the top level, sections as children of the CherryClass, and functions as children of the sections.

First, CherryPy uses an extension of Python classes called CherryClasses, identified by the keyword CherryClass. CherryClasses are divided into multiple sections called variable, aspect, mask, view and function. We need to make PyPe code parser aware of these keywords. The function we must modify is called fun and is a method of the function fast_parser in the parsers.py file. The fun function starts at line 35 (for PyPy 1.9.3). The relevant code is from line 100.

if ls[:4] == 'def ':
fun('def ', line, ls, line_no, stk)
elif ls[:6] == 'class ':
fun('class ', line, ls, line_no, stk)
elif ls[:1] == '#':
a = ls.lower().find('todo:')
if a+1:
todo.append((line_no, ls.count('!'), ls[a+5:].strip()))

You can see that it identifies class and function declarations and “todo” comments (a PyPe special feature). We just need to make it aware of the special CherryPy keywords. We also need 2 small hacks to make CherryClass sections reside within the CherryClass in the tree (because these are not indented) and to identify them as sections. The code to add, preferably after

elif ls[:6] == 'class ':
fun('class ', line, ls, line_no, stk)

is this:

elif ls[:12] == 'CherryClass ':
fun('CherryClass ', line, ls, line_no, stk)
elif ls[:9] == 'variable:':
ls = "section variable:"
line = " " + ls
fun('section ', line, ls, line_no, stk)
elif ls[:5] == 'mask:':
ls = "section mask:"
line = " " + ls
fun('section ', line, ls, line_no, stk)
elif ls[:5] == 'view:':
ls = "section view:"
line = " " + ls
fun('section ', line, ls, line_no, stk)
elif ls[:9] == 'function:':
ls = "section function:"
line = " " + ls
fun('section ', line, ls, line_no, stk)
elif ls[:7] == 'aspect:':
ls = "section aspect:"
line = " " + ls
fun('section ', line, ls, line_no, stk)

The 2 hacks are ls = "section keyword:" to add the section keyword before the type of section, and line = " " + ls to artificially indent the section identifier lines with one space. If you are normal, you have indented functions with at least two spaces and sections are then placed at a level above functions. Now, let’s take a look at how the PyPe class browser presents our CherryClass :

CherryClass after

Wohoo!!!! Just what we wanted!!!

One more thing to do is to modify the file browser so it associates .cpy files with Python/CherryPy. I’ll leave this as an exercise to the reader. Look at the code at line 101 and below in configuration.py and it should be quite easy.