Peter's Blog

Redefining the Impossible

Items filed under turbogears


I am about to embark on some more web development so it's framework decision time again. It's a year since I dabbled with Turbogears and Django and they both seem to have had extensive development done since then. However, since a year has passed I am basically at the start of the learning curve again.

I still have bad memories about Turbogears, specifically the mess that seems to be the link between mod_python and the application itself, i.e. cherrypy and hacky glue scripts. I was left in the situation where I could only run one app on my server because the glue didn't permit any more.

I looked at Django again and I spent some time fiddling about trying to set it up on my site5 hosting. This involved scanning through umpteen forum postings, emailing site5 tech support (I am now trusted to run compilers and bash so my account is pretty powerful) but the fcgi link was refusing to work and I was frustrated about Django not appearing to generate log files or if it did, not telling me where it put them.

On a whim I bought a book about Ruby on Rails which is a similar kind of framework but is based on the Ruby language instead of python. I wanted a good book as I am tired of using tutorials and google searches to learn these things. Since someone is being paid to write the book they can take the time to explain things in more detail and express themselves better. I think there are books under development for the python frameworks but not a nice printed second edition that I can order from Amazon and be reading the next day.

I've never got into ruby before, I read a description of it by it's author/designer years ago and he came across to me as arrogant in the way that he was criticising python. It may just be a cultural thing, the guy is japanese. By contrast Guido von Rossam, the designer of python is one of those guys like John Carmack or Linus Torvolds who don't need to be arrogant, from the way they write you know they are smart.

Without ever having written a line of it, Ruby seems to me more perl derivative than anything else, like php but better designed. This may just be the use of sigils: $blah. However in Ruby the sigils seems to be useful in telling you the scope of the variable whereas in php they appear to serve no purpose except to tell the interpreter that an identifier is not a literal string and forgetting it normally leads to obscure bugs.

Ruby on Rails was the In Thing in 2006, so important that web hosting companies advertised support for it, it wasn't something that just happened to work if you messed about long enough. Rails is more mainstream. Ruby offers similar productivity improvements to Python, being essentially a typeless language you are freer to express yourself than in languages like Java or C# where the language keeps slapping your wrists with type checking. The frameworks for these languages are also pretty overbearing, Java frameworks apparently want you to define everything in XML, that odd designed-by-commitee compromise between awkward for humans to read and inefficient for computers to parse. Life is too short.

The book is 'Agile Web Development with Rails' 2nd edition and so is reasonably up to date. It is one of those bible books that become de facto for a particular platform, being co-authored by the guy that designed Rails. The book is very descriptive, walking you through development, it is not structured like a reference but the index looks very comprehensive which is useful when you don't have google. What I have read so far has been very interesting, the book is readable and Rails looks very well designed.

I cannot give a point by point comparison with the other frameworks yet but one example of nice design is the use of what they call 'migrations'. Suppose you want to add a new column to a table: you write a migration which is the code that adds the new column and another function to undo it. Each migration gets a number. You can then use the framework to update the database schema through however many migrations to get it to the version that you want. If you need to you can roll back the migrations to undo your changes. Get the migrations working in your development database and then apply them to the production database. Compare this to Django and Turbogears a year ago where if you wanted to add a column to your database you had to update the databases (development and production) and the code individually by hand (these two only had support for creating tables from table definitions, they didn't automate support changing table definitions).

I haven't got into the template language yet but it appears to be simply ruby embedded in html, no crippled little embedded languages. I haven't tried the Rails templates, I have no idea how it copes with the ability to have a 'master' template to layout all your pages with 'sub-templates' to modify the template according to each page.

Something nice that I haven't tried yet is 'InstantRails': a 50m download that you unzip, run and get a full development environment including Ruby, Rails, Apache and Mysql. It manages this without setting all these apps up so your pc.

If LAMP means Linux, Apache, Mysql and Php, is this 'LAMR' ?


Filed under: django rails ruby turbogears

2 Comments

Just found out that my new site5 server has python 2.4.3. This is Good News. Last time I had a site5 server it was running python 2.2 which was getting a bit ancient. 2.3 introduced generators which have been widely adopted. The latest version is 2.5 which is (flame bait) not exactly a must have, >= 2.3 will do.

Another job for my todo list is to see if I can get django or turbogears running through cgi, but I am not optimistic.

Should I get desperate, site5 offer ruby-on-rails hosting but that would involve selling my soul in a manner akin to adopting asp.net


Filed under: django python site5 turbogears


I updated a server from ubuntu hoary hedgehog to breezy badger. I followed this and it went smoothly enough, although it took a number of

sudo apt-get upgrade
sudo apt-get dist=update
sudo apt-get update

cycles to stop it installing new packages.

Afterwards my turbogears projects were dead: the apache2 error log files said:

[Mon Feb 20 13:01:21 2006] mod_python: (Re)importing module 'mpcp'
[Mon Feb 20 13:01:24 2006] mod_python: (Re)importing module 'mpcp'
[Mon Feb 20 13:01:24 2006] child pid 26833 exit signal Segmentation fault (11)
[Mon Feb 20 13:01:25 2006] child pid 26832 exit signal Segmentation fault (11)
[Mon Feb 20 13:01:25 2006] mod_python: (Re)importing module 'mpcp'
[Mon Feb 20 13:01:26 2006] mod_python: (Re)importing module 'mpcp'
[Mon Feb 20 13:01:27 2006] child pid 26834 exit signal Segmentation fault (11)
[Mon Feb 20 13:01:27 2006] mod_python: (Re)importing module 'mpcp'
[Mon Feb 20 13:01:28 2006] child pid 26835 exit signal Segmentation fault (11)
[Mon Feb 20 13:01:29 2006] child pid 26836 exit signal Segmentation fault (11)
[Mon Feb 20 13:01:42 2006] mod_python: (Re)importing module 'mpcp'
[Mon Feb 20 13:01:43 2006] mod_python: (Re)importing module 'mpcp'
[Mon Feb 20 13:01:44 2006] child pid 29065 exit signal Segmentation fault (11)
[Mon Feb 20 13:01:44 2006] mod_python: (Re)importing module 'mpcp'

Googling, the problem seems to be due to mod_php and mod_python using different versions of the mysql library. By simplifying my project I established that it was indeed due to mysql and not expat which is another possible cause. The solutions provided were to recompile. I decided the simplest thing to recompile would be MySQLdb, the python mysql module, it being the smallest component and I didn't fancy trying to rebuild mod_php. I downloaded the source for MySQLdb and looked through the setup.py file and found this line:

mysqlstatic = eval(os.getenv('mysqlstatic', 'False'))

which implies that MySQLdb can use a static library: excellent. By default it is using a dynamic library which presumably is a different version to the one mod_php is using. I defined the environment variable with

export mysqlstatic=True

and I ran

python setup.py build

This died because it couldn't find something called mysql_config. I installed the libmysqlclient12-dev package with

sudo apt-get install libmysqlclient12-dev

to get this and it built ok. Note that there are three libmysqlclient packages, 10, 12 and 14. 12 appears to be a match for the version of mysql on the server (4.0.24: latest ubuntu is lagging debian somewhat).

I uninstalled the ubuntu MySQLdb package to avoid any future problems and then installed the MySQLdb module with

sudo python setup.py install

I tested the library from the python interactive shell and no problems. I rebooted the apache server and problem solved.

I'll have to keep an eye in this, I can no longer rely on the Ubuntu package system.


Filed under: python turbogears ubuntu

1 Comment

Had a problem in my Turbogears app in that I was trying to set a cookie. It worked nicely under development, running on the cherrypy server but it didn't work in production when running under mod_python/apache. Eventually I established that it was because my http response was trying to send two cookies (my cookie and the session cookie) and only the last one was actually being sent to the browser.

I pinned it down to the mpcp script that I am using to interface mod_python with cherrypy. It has this code:

elif tv is str:
    req.headers_out[header] = value

which is only allowing one 'Set-Cookie' header to be defined, later ones will overwrite the original.

Changing the code to the following fixes the problem:

elif tv is str:
    if header.lower() != 'set-cookie':
        req.headers_out[header] = value
    else:
        req.headers_out.add( 'Set-Cookie', value)

2 Comments

Turbogears supports two configurations, development and server, each with it's own configuration file. This is handy because I can use different databases for development and production and avoid breaking the production system while developing.

I've just moved the development database to the same server as the production database as using mysql instead of sqlite makes it easier for me to upgrade tables by dumping the sql, running "tg-admin sql drop; tg-admin sql create" and reimporting the old sql.

Just tried this on the production system and fried the development database. Why? It seems that turbogears decides whether it is running in development or production mode based on the existance of a setup.py file in the project directory. In my setup I copy all the files from the development directories on windows to the production directories on the server, I don't mess with python setup tools. Hence my production server has a copy of setup.py and so was deciding to use the development database.

I don't want to start hacking the turbogears source so I've hidden the setup.py file on the production server and modified the rsync script that I use to upload the database so that it doesn't upload setup.py.


Filed under: python turbogears


Sessions in TurboGears are easy enough: the documents are very clear.

This ran pretty much first time. During development, using cherrypy's internal server the sessions were all lost whenever I rebooted the server, which was frustrating as it meant I had to log into my web app every time.

When I moved the app to the production server (mod_python) my sessions appeared to die after about 30 seconds. I think this is because apache reboots or something to kill any zombie/trojan activities.

I studied the cherrypy docs which are typically vague and incomplete. In combination with looking in the cherrypy source code, it seems that cherrypy defaults to storing the sessions in ram so they are deleted whenever the process dies. The fix boils down to putting the following in the config file:

sessionFilter.on = True
sessionFilter.storageType='File'
sessionFilter.storagePath='/var/www/wherever/sessions'

This stores the sessions in files on the server. This may well work on windows too, I haven't tried it yet.

From the source it seems cherrypy only supports sessions in a postgresql database, not mysql sad Still, it is possible that files are ultimately more efficient for something simple like this.

I must say I like the way TurboGears has two setup files, one for development and one for production. This makes it very easy for me to develop under windows and deploy on linux. I can use sqlite on windows and mysql on linux. I have needed to create separate startup files as well (on windows to use cherrypy with a debugger, on linux to get it working with mod_python) but once this is done the code is pretty much identical (apart from using samba.winbind under linux to validate users).


Filed under: cherrypy python turbogears

1 Comment

statcounter tells me this site is linked from the cheetah template website on the Who uses it page. Yes, I do use it, I like it a lot. Since I started using TurboGears I have been using kid but only because TurboGears didn't originally support Cheetah (Cheetah support is being added via template plugins).

What I like most about cheetah is that most of the time things just work the way you think they will and you can get on with your coding, instead of working out why things don't work. kid also gives me that feeling but cheetah is more powerful: kid is mainly aimed at xml/html, it can do plain text but cheetah is truly agnostic.

Kid and Cheetah share the ${variable} method of replacing text in the template with python expressions. This is very easy and powerful, although it goes against the doctrine of separating code from display. In django templates you can only substitute variables, you cannot call functions. I feel there is a fine line between python code that says 'object.name' and 'object.name()'. If you can explain one to a web designer, is it so hard to explain the other? Anyway, for my projects I am the web designer.

If there is one thing I would change about kid it would be to somehow add an else term to the if statement: I end up duplicating the test code and adding a not. The more duplication there is, the less maintainable it is.

Kid templates can be previewed as html very nicely which is useful in creating the layout of a site. If you preview kid templates as html you get substitute text where your dynamic content will go (e.g. 'Users name goes here') whereas cheetah would show the python expression that generates the content (e.g. '$(UserName}'). However, once you start working on the dynamic content you can only preview by passing through the template engine anyway. One of my projects generates a complex table, the columns and rows being generated dynamically. The kid preview is pretty useless.

Kid's other advantage is that it will gripe if your xhtml is not well formed, e.g. you miss out a closing tag. This has saved me a couple of times but there are other tools to validate your output.

Apparently there is a tantalising new version of cheetah out. Must have a look,


Filed under: cheetah kid python turbogears

2 Comments

Still umming and arring about django vs turbogears. I knocked up an online questionnaire for our intranet in TurboGears in a couple of days and it is now running. I'm starting another intranet program so I thought I'd give django a try. Once again I had to go through the tutorial to remember all the steps to set the project up. I fiddled with batch files to set up environment variables and everything, hacked the source to get it to run under WingIDE, started on the database model, all the while seeming to struggle with django itself. I got the admin screens up and running and was figuring out how to stop a password being displayed in a password field. As far as I could see, this involved editing the templates for the admin screen. It's about here that I got tired and went back to turbogears as I couldn't be bothered to tackle the django template system.

In about the same amount of time with turbogears, the project was underway and I was focused on getting the main template running. There is something about turbogears that is to me more 'pythonic' in terms of things working the way you expect and not having to waste time figuring out how to do things. kid Just Works, it is fundamentally simple and keeps out of the way, leaving you to get on with your work.

SQLObject does not appear to handle relations as nicely as the Django ORM: in django it appears I can delete an object and have the associated many-to-many mapping in the database deleted automatically whereas SQLObject does not delete it automatically and neither the documentation or the tests show me how to delete it explicitly. There is a 'remove' method in there but the object model is too complex for me how to work out how to reach it. The SQLObject documentation is comprehensive but is essentially a list of examples (not a bad thing), it does not seem to include a detailed api listing. I will have to fiddle around at the interactive prompt and see if I can figure out the incantation. Then again, the django ORM api is currently being made more intuitive. If I was going to do a lot of database work I'd be tempted to use my own db wrapper: I'd have to write SQL but I don't care, I know how to write SQL, I don't know how to use these librarys.

I have looked through the tests for both projects as example code and in both the tests are a bit cursory. The django tests are far more readable than the SQLObject tests (doctestish vs unittestish). The django tests also benefit from being commented.

Right now I'm back with turbogears as the project I am working on will not have many relationships and they will rarely need deleting.

Members of both projects have left comments on this blog, making me feel guilty about picking one over the other. I like them both equally, choosing one over the other is hard. Right now I'm further along the TurboGears learning curve which for me is not as steep as the Django learning curve.


Filed under: django python turbogears


So I develop an online questionnaire (and learnt to spell that word) for the online intranet in turbogears, it takes maybe a day total to have a nice sqlite database driven app that walks you through the questions, allows you to go back and forth, handles errors, themed exactly like the main intranet (drupal) really nice.

After developing under windows I casually copy the files to the ubuntu intranet server and try installing it in a virtual path under the root domain (e.g. intranet.com/subdirectory). Then I mess around for hours because the mod_python support for cherrypy appears to be hacked on, the support for mapping applications to virtual paths in turbogears using servo.webpath is broken and cherrypy support for virtual paths boils down to this hack which it states is buggy but doesn't say what the bugs are! The main bug I see is that IT DOESN'T MAKE ANY DIFFERENCE.

Argh.

I can get the app to work but only the index, none of the other methods in the controller are recognised.

While googling for this I came across an interesting django vs turbogears review here. He makes an interesting point: django sites survive slashdotting. I look at the cherrypy site and see where cherrypy is being used: um, sorry but these sites don't look all that impressive compared to the django equivalents.

So I'm disillusioned with cherrypy: while the raw api is clean, it looks a bit hacky and the documentation is poor ('in progress') by comparison to the other elements of the turbogears stack. I have no idea whether django supports virtual paths but it Just Worked under mod_python. Should I switch back to that, given that they are working on cleaning up their database api? I'd be tempted to stick with kid even if I went back to django, like this guy.

Dunno what to do, almost tempted to learn ruby, I'm that fed up with it all.

UPDATE: It took me a few days to figure the problem out: I had an extra .htaccess file I didn't know was there, causing mischief and interfering with whatever I did in the main config file. I've got rid of it and turbogears/ cherrypy is working fine.

The turbogears server.webpath="/subdir" does not seem to be working (as mentioned in the turbogears issue tracker) but if I hack my controllers.py file I can work around it:

class subdir:
    @@turbogears.expose(html="tgpcw.templates.welcome")
    def index(self):
        import time
        return dict(now=time.ctime())

class Root(controllers.Root):
    subdir = subdir()

I enabled this in the apache2 config file thusly:

<Location "/hands">
    SetHandler mod_python
    PythonHandler mpcp
    PythonDebug On
    PythonPath "['/var/www/tgpcw'] + sys.path"
    PythonOption cherrysetup tgpcw_start::mp_setup

    AllowOverride All
    Order deny,allow
    Deny from all
    Allow from all
</Location>

where tgpcw is the name of my turbogears stuff.


Filed under: django python turbogears

5 Comments

Coding away with TurboGears and found that glorious nirvava where whatever I tried Just Worked. Kid, SQLObjects and cherrypy are nice and clean and turbogears has generated a nice boilerplate framework. Going through the code of the various librarys while debugging, there is magic in the way they are working but it is not causing me big troubles as the api's they present are nice and clean. Python is such a lovely language I always felt it would be great for web development and now it feels like I have the tools.

I commented previously on SQLObjects support for introspection and I was wrong here as the help command (possibly docstrings in general?) is broken and generates an exception but the online documents are fairly comprehensive.

I have a heavy cold and hence had one of those tortured nights sleep with recurring dreams. I kept seeing Kid's XML element tree sitting in memory, branches being swapped in and out and the resulting document changing in wonderful ways. It was not a bad dream. I woke up thinking it was a great way to manipulate a document compared to primitive string substitution. I have never really tried DOM models before, being reluctant to use all that memory, but now that memory is cheap I shouldn't be so cautious. Playing with SAX parsers is a pain, if I have to write another state machine I'll scream.

Another discovery, the TurboGears command `tg-admin shell` somehow picked up IPython and I was able to play with the database api whil admiring the pretty colours.

It was nice until I tried porting a theme from php and ran into an annoying works-in-ie-but-not-firefox problem. There are some things that even the nicest development environments cannot help with. I tried using html-kit to clean up the template code and it is indeed easy to preview kid templates in a browser, they Just Work.

Tip for the Day: although kid templates are xml it is better to tell WingIDE they are html as it avoids a limitation of the xml syntax highlighting where it treats Processing Instructions as errors and marks most of the file as a syntax error, making the editor run pretty sluggishly.


2 Comments

Had turbogears hanging while debugging under WingIDE but working fine from the command line. One nice thing about using a decent debugger like WingIDE is I can press the pause button and see what it is doing when it appears to be hung.

It turns out it was in a kid function called 'relativize' that looks like this:

   1  def relativize(self, file, path):
   2      from os.path import normpath, join, dirname, abspath, split, sep
   3      head, tail = (dirname(abspath(file)), '')
   4      parts = path.split(sep)
   5      paths = self.paths
   6      while 1:
   7          if head in paths or head == '/':
   8              return join(*parts)
   9          head, tail = split(head)
  10          parts.insert(0, tail)
Toggle Line Numbers

It is trying to turn an absolute path into a relative path. The code was stuck in the while loop because 'head' was never 'in paths' or == '/'. The '/' would never match as this was windows and uses '\' as a file seperator, 'in paths' was broken because the path was in there a 'c:\Project\Path' but head was equal to 'C:\Project\Path': different capitalisation on the C. Tracing back, the upper case version was being returned by os.getcwd, the lower case version by the python package module. To cut a long story short, I had set the initial debug directory in WingIDE to 'c:\Project\Path' with a lower case c and changing it to an upper case c in Wing fixed the problem.

Conclusion: Must bear in mind that kid may be flaky on Windows.

UPDATE: it broke again sad Resorted to fixing kid thusly:

   1  def relativize(self, file, path):
   2      from os.path import normpath, join, dirname, abspath, split, sep
   3      from os.path import normcase  # pcw
   4      file = normcase( file)  # pcw
   5      head, tail = (dirname(abspath(file)), '')
   6      parts = path.split(sep)
   7      paths = [normcase( strPath) for strPath in self.paths]  # pcw
   8      while 1:
   9          if head in paths or head == '\\':
  10              return join(*parts)
  11          head, tail = split(head)
  12          parts.insert(0, tail)
Toggle Line Numbers

Filed under: kid python turbogears


I've been giving TurboGears a try as a means of reimplementing this blog in python. I have been trying django but I felt the need to try something else, mainly prompted by frustrations with the database api.

TurboGears is similar in the tools that it provides for web application development. It is essentially an amalgum of a number of existing python projects:

kid
a templating system based on XML.
cherrypy
web application framework, essentially maps urls to python method calls
SQLObject
an SQL database wrapper
Mochikit
a javascript library which I have tried before

Turbogears itself provides 'glue' to put these together. It has tools for creating project files, setting up and using the database etc. The TurboGears administration script creates a boilerplate application that can be running in no time. It all feels very similar to django, the main thing missing I can see is the administration screens but they are working on something called 'catwalk' which I think will do this. At the end of the day there are many database front ends that can provide administration (phpmyadmin, webmin mysql module etc) which are not so end-user friendly but good enough for me.

The librarys that turbogears has chosen appear to be very good in their own rigght. Their designs are clean and they are well documented. Each has greater depth than the django equivalents.

Kid looks powerful: it is an intersting mix of xml and python: your kid scripts can be used like python modules: they compile to .pyc files and so are presumably only parsed once. You can define xml snippets of boilerplate code, such as an html list, and call it like a function from elsewhere in your template. As it is XML based, if your template is not XML compliant the XML parser (expat at the lowest level) slaps your wrist. An interesting side effect of the pythonic nature of it is that if a problem appears in the python embedded in your template, Wing IDE's debugger will stop on that line. Useful! Kid does not support inheritance like django's template system, it effectively gives you macro templates that could be very powerful. The syntax is clearer than django, you can use python code inline )like cheetah) and the template substitution allows you to use the same substitution twice (if, for example, you want to use the same title string in two places, header and page title): a pedantic limitation in django. Looking through the documentation, Kid shows great attention to xhtml compliance and generation of conformant XHTML. This is not the greatest concern to me, I don't lose sleep over whether my XHTML is standards compliant, I am more worried about whether browsers will display it properly, but it is nice to know that someone somewhere has thought about all this for me.

SQLObject looks very clean and the objects can be introspected nicely. You work with the classes you define directly and not with meta classes that appear from nowhere. SQLObject has also introduced me to SQLite a really nice, simple SQL database library. This looks very solid, certainly good enough for development without the hastle of getting mysql running. It would probably be good enough for production use for me, if I can get it to run SQL dumps for backup (which I prefer to backing up binarys). Certainly I will be using it in the places where I can't be bothered to set up mysql (user's, permissions, passwords, yawn).

CherryPy: TurboGears creates enough boilerplate code that I haven't needed to look at the documents for this yet. It maps urls to method calls simply enough but one thing I like about django is the regular expression based url mapping which is totally flexible but there is nothing to stop me adding such a mapping layer.

I've ported the basics of my blog (the theme I use in drupal, lists of posts etc) to TurboGears. I had to study the Kid documentation to get the TurboGears generated code to use the head from the master.kid file so I could put my css import in one fixed place. By default the head here is ignored. The solution to this conundrum is to modify master.kid like this:

<head py:match="item.tag=='{http://www.w3.org/1999/xhtml}head'">
    <meta content="text/html; charset=UTF-8" http-equiv="content-type" py:replace="''"/>
    <title>Peter's Better Blog | ${strPageTitle}</title>
    <link rel="stylesheet" href="/static/css/style.css" />
</head>

i.e. turn it into a match template. I had the django inheritance thing in my head (not a million miles away from the drupal phptemplate engine) and I had to read the kid documentation to realise it simply works by sequentially replacing blocks of XML, in this case any later head block is replaced by the block above.



My unhappiness with django is growing. I have a model containing the following classes:

class Post:

class Tag:

I have a many-to-many relationship between these two classes. Trying to code something, if I do something like the following:

class Post:
   def DoSmethingWithTags( self):
       oTags = tags.get_tags()

it fails because it needs:

from django.models.blog import posts,tags

but I cannot put this in the model file or module import starts recursing (or so I believe). This kind of thing is just a pain and I don't want to spend my time working around architectural oddities. I tried creating a library module in the model directory but then it couldn't be found when I tried to import it (?). Python path weirdness, and django is fussy about the python path setup, more so than any other package I can think of, usually everthing is relative to a current directory and is happy.

So I gave Turbogears a look. I watched the wiki in 20 minutes film, seems ok but a lot to learn (like django), including it's own architectural oddities.

I installed it directly onto Windows which was very easy.

Next stumbling block is to get it to run under WingIDE. This was more fiddly. Like django it has autoreload but unlike django there is a config entry to disable it. Next problem is that it is multi-threaded which gives WingIDE a hard time. Here is my solution:

Add the following to the turbogears dev.cfg file:

   1  #
   2  # Run in a single thread
   3  #
   4  server.class="_cphttpserver.embedded_server"
   5  server.threadPool=1
   6  
   7  #
   8  # Disable auto reload.
   9  #
  10  autoreload.on=0
Toggle Line Numbers

but this is not enough as it still runs two threads, one to watch the keyboard. Don't care about this if running under a debugger with a stop button: I can't stop it cleanly but this is not a big deal for development. Making it strictly single threaded involves overriding the _cpserver.Server class. I changed my turbogears xxx-start.py file as follows:

   1  cherrypy.root = Root()
   2  #cherrypy.server.start()
   3  
   4  import cherrypy._cpserver
   5  
   6  class NonThreadedServer( cherrypy._cpserver.Server):
   7      def start_http_server(self, blocking=True):
   8          """Start the requested HTTP server."""
   9          if self.httpserver is not None:
  10              msg = ("You seem to have an HTTP server still running."
  11                     "Please call server.stop_http_server() "
  12                     "before continuing.")
  13              warnings.warn(msg)
  14  
  15          if self.httpserverclass is None:
  16              return
  17  
  18          if cherrypy.config.get('server.socketPort'):
  19              host = cherrypy.config.get('server.socketHost')
  20              port = cherrypy.config.get('server.socketPort')
  21  
  22              cherrypy._cpserver.wait_for_free_port(host, port)
  23  
  24              if not host:
  25                  host = 'localhost'
  26              onWhat = "http://%s:%s/" % (host, port)
  27          else:
  28              onWhat = "socket file: %s" % cherrypy.config.get('server.socketFile')
  29  
  30          # Instantiate the server.
  31          self.httpserver = self.httpserverclass()
  32  
  33          # HTTP servers MUST be started in a new thread, so that the
  34          # main thread persists to receive KeyboardInterrupt's. This
  35          # wrapper traps an interrupt in the http server's main thread
  36          # and shutdowns CherryPy.
  37          def _start_http():
  38              try:
  39                  self.httpserver.start()
  40              except (KeyboardInterrupt, SystemExit), exc:
  41                  self.interrupt = exc
  42  #        threading.Thread(target=_start_http).start()
  43  
  44          #
  45          # Run in a single thread to make debugging a joy
  46          #
  47          self.state = cherrypy._cpserver.STARTED
  48          # Changing the socket timeout makes WingIDE more responsive
  49          self.httpserver.socket.settimeout( 0.1)
  50          self.httpserver.start()  # Should not return from here!!
  51  
  52          if blocking:
  53              self.wait_for_http_ready()
  54  
  55          cherrypy.log("Serving HTTP on %s" % onWhat, 'HTTP')
  56  
  57  # _cphttpserver uses this global variable so have to poke it
  58  cherrypy.server = NonThreadedServer()
  59  cherrypy.server.start()
Toggle Line Numbers

I wasn't able to make django debuggable in WingIDE without hacking it's source: it didn't seem to have as many useful hooks as cherrypy/turbogears.


Filed under: django python turbogears

1 Comment