pylons
30/04/2009
minitage 1.0 is out
I did not find the time earlier to post about it.
Minitage 1.0 is out for a week now.
What you can find there ?
- Documentation has been drasticly improved
See by yourself:
- Trac got Git support
- There are cgit and gitweb instances configured against all minitage repositories
- A lot of bugfixes, as always
- Recipes have been rewritten a bit to stick to zc.recipe.* implementations
- minitage.recipe egg based recipes got a fresh touch:
- They do not totally rely any more on easy_install dependency system, just on their declared dependencies (extras are also supported). Thas was something i disliked with zc.recipe.egg, potentially, the easy_install call can install something, which we would'nt. And also, in some cases, the extras requirement could be wiped out. All are bugs reported upstream on the zc.buildout launchpad bugtracker.
- Their installer should now try not to look in the site-packages first, but rather the eggs cache to avoid conflict errors.
- I also implemented an adaptation of the zc.buildout redo_pyc function which seems to be somehow slow.
- Welcome to the buildout.minitagificator egg which help minitage to conquer the world with replacing some well known recipes with their equivalent minitage implementations with some violent monkey patches. It's a buildout extension.
- The "static fetcher" has been improved and bug fixed
- There some new cool API functions like a search function which take regexes to look for minibuilds in the available minilays
- minitage.paste got a great step forward with all pastes
- All templates now have now minitage layout as an optionnal dependency.
That means that you do not need minitage to generate templates, however, the normal use is to use them in minitage.
- Plone32 template:
- Predefined set of products to install
- A developper mode where you have aditionnal tools installed (ptprofiler, collective.autorestart on linux, and so on) and debug mode turned on by default
- wsgi configuration and launchers
- A working filesystemstorage integration
- You can use either RelStorage, ZEO or classical ZODB access
- You can give to paster whatever you want to custom the buildout generation by some predefined keys.
- Zope3 template:
- wsgi configuration and launchers (paster and Zdaemon based)
- You can use either RelStorage, ZEO or classical ZODB access
- You can give to paster whatever you want to custom the buildout generation by some predefined keys.
- wsgi configuration and launchers (paster and Zdaemon based)
- Django template:
- wsgi configuration and launchers
- GeoDjango support
- dj.paste (http://pypi.python.org/pypi/dj.paste) integration. This paster factory enables you to have multiple django instances in the same pipeline
- A basic application created when you generate your project to quickstart.
- You can give to paster whatever you want to custom the buildout generation by some predefined keys.
- Nearly all templates which have WSGI support got Spawning integration. Spawning is an über performant python based WSGI server.
- postgresql, varnish, varnish2, and env profils:
- Can run now without minitage or any project installed
- The new paste-initd profil:
- it generates an initscript wrapper to trigger a "paster serve" from some paste configuration of your choice
- Plone32 template:
What are the minitage projects and profiles, after all ?
All are paster (see PasteScripts on pypi) templates.
Projects target to quickstart an application or a project like a plone3 or a django website.
Profiles, on the other side, are a piece of integration, targeted to be in general integrated into a minitage based project. That can be a postgresql database instance, or a shell environement file with has all minitage dependencies, that you can source when playing with your project.
21/10/2008
Pylons, xmlrpc and doctest
How to make some doctests with pylons and an xmlrpc controller
I m actually developping some application around XMLRPC protocol at work.
We are using Pylons for the framework part, and i played this afternoon at setting up some testing environnement for doing doctests.
This test is a proof of concept, it 's code extracted from our internal application, it's just a starter for you. The whole is working with some tweaks.
controllers/mycontroller.py, a simple controller doing simple stuff
class MyController(XMLRPCController):
"""controller."""
def index(self):
return '\_o<'
lib/base.py, Please add the XMLRPCController import
lib/base.py:from pylons.controllers import WSGIController, XMLRPCController
Then, we are setted up to continue with tests
First of all, the doctest boilerplate:
tests/test_doctest_files.py
import doctest
from doctest import DocFileSuite
from myproject.tests import setUp, tearDown
flags = (doctest.ELLIPSIS | doctest.NORMALIZE_WHITESPACE | doctest.REPORT_ONLY_FIRST_FAILURE)
def test_suite():
return DocFileSuite(
"test.txt",
setUp = setUp,
tearDown = tearDown,
optionflags = flags
)
setUp and tearDown will have a central place as they are intialising the application.
As we can't use paste.fixture.TestApp objects with XMLRPC because it does not bind everywhere, the idea is
- launch the server somewhere in a thread
- use it later, as usual throught xmlrplib.
- We will even declare it as a global to ease the doctests writings.
- We also add a wrapper to url_for to return the host to bind to.
import os
import sys
import re
import threading
from ConfigParser import ConfigParser
from unittest import TestCase
import paste.fixture
import paste.script.appinstall
from paste.deploy import loadapp
from paste.httpserver import serve
from routes.util import url_for
here_dir = os.path.dirname(os.path.abspath(__file__))
conf_dir = os.path.dirname(os.path.dirname(here_dir))
test_file = os.path.join(here_dir, 'test.ini')
cmd = paste.script.appinstall.SetupCommand('setup-app')
cmd.run([test_file])
def setUp(test, *args, **kwargs):
print "\t-----------------------------------------------------------------"
print "\t--- Setting up database test environment, please stand by. ---"
print "\t-----------------------------------------------------------------"
config = ConfigParser()
config.read(
os.path.join(os.path.dirname(sys.argv[0]), '..', 'etc', 'config.ini')
)
infos = ConfigParser()
infos.read(test_file)
sinfos = infos._sections['server:main']
wsgiapp = loadapp('config:test.ini', relative_to = here_dir)
server = test.globs['server'] = serve(wsgiapp,
t = threading.Thread(target=server.serve_forever)
t.setDaemon(True)
t.start()
test.globs['app'] = paste.fixture.TestApp(wsgiapp)
def url_for_wrapper(*args, **kwargs):
lkwargs = {'protocol': 'http' ,'host': "%s:%s" % (server.server_name, server.server_port)}
lkwargs.update(kwargs)
return url_for(*args, **lkwargs)
test.globs['url_for'] = url_for_wrapper
test.globs['url_for_orig'] = url_for
def tearDown(test):
test.globs['server'].server_close()
class TestController(TestCase):
def __init__(self, *args, **kwargs):
wsgiapp = loadapp('config:test.ini', relative_to = here_dir)
self.app = paste.fixture.TestApp(wsgiapp)
TestCase.__init__(self, *args, **kwargs)
And finally, letz play with our doctest
tests/text.txt
>>> create_url = url_for(controller='mycontroller') >>> import xmlrpclib >>> s = xmlrpclib.Server(create_url) >>> s.index() '\\_o<'


