<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-3175310051823862908</id><updated>2011-07-07T21:31:34.143-07:00</updated><category term='python'/><category term='repoze programming gae testing'/><category term='programming'/><title type='text'>Darryl Cousins</title><subtitle type='html'>A more than unusually boring collection. May it be blessed with improvement.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://darrylcousins.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3175310051823862908/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://darrylcousins.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Darryl Cousins</name><uri>http://www.blogger.com/profile/00503179527741824865</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_T3dozklXrk8/S0ZNz_YLhYI/AAAAAAAABlI/zfqao6zElAU/S220/avatar-sm.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>11</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-3175310051823862908.post-2500500230641976728</id><published>2010-04-07T20:41:00.000-07:00</published><updated>2010-04-07T20:43:41.069-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><title type='text'>Running a HTTP Server in a Thread</title><content type='html'>I'm building a shop using &lt;a href="http://djangoproject.com/"&gt;Django&lt;/a&gt; and &lt;a href="http://satchmoproject.com/"&gt;Satchmo&lt;/a&gt; and I ran into an interesting problem while building tests for the Paypal payment module.&lt;br /&gt;&lt;br /&gt;The user is sent off to Paypal to process the payment and are returned to the success page. Paypal notifies the site of payment through an 'ipn' url on the shop. Faking the call to the ipn url is easy enough in the test:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&amp;gt;&amp;gt;&amp;gt; postdata = dict(payment_status='Completed',&lt;br /&gt;... &amp;nbsp; &amp;nbsp; invoice=order.id, memo=memo, txn_id='1234',&lt;br /&gt;... &amp;nbsp; &amp;nbsp; mc_gross=order.total)&lt;br /&gt;&amp;gt;&amp;gt;&amp;gt; response = client.post('/checkout/paypal/ipn/', postdata)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;But the problem then arose because the ipn django view then requests verification from paypal:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;def confirm_ipn_data(data, PP_URL):&lt;br /&gt;    # data is the form data that was submitted to the IPN URL.&lt;br /&gt;&lt;br /&gt;    newparams = {}&lt;br /&gt;    for key in data.keys():&lt;br /&gt;        newparams[key] = data[key]&lt;br /&gt;&lt;br /&gt;    newparams['cmd'] = "_notify-validate"&lt;br /&gt;    params = urlencode(newparams)&lt;br /&gt;&lt;br /&gt;    req = urllib2.Request(PP_URL)&lt;br /&gt;    req.add_header("Content-type", "application/x-www-form-urlencoded")&lt;br /&gt;    fo = urllib2.urlopen(req, params)&lt;br /&gt;&lt;br /&gt;    ret = fo.read()&lt;br /&gt;    if ret == "VERIFIED":&lt;br /&gt;        log.info("PayPal IPN data verification was successful.")&lt;br /&gt;    else:&lt;br /&gt;        log.info("PayPal IPN data verification failed.")&lt;br /&gt;        log.debug("HTTP code %s, response text: '%s'" % (fo.code, ret))&lt;br /&gt;        return False&lt;br /&gt;&lt;br /&gt;    return True&lt;br /&gt;&lt;/pre&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The problem here is opening the url using urllib2. I couldn't use the http://testserver/ that is 'running' in the Django test code. So I tried to start up a simple HTTPServer instance but this would lock up the testrunner. Finally then I came up with the following code which does the job nicely:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;pre&gt;# simple server to use as fake verification server&lt;br /&gt;from BaseHTTPServer import BaseHTTPRequestHandler,HTTPServer&lt;br /&gt;from threading import Thread&lt;br /&gt;&lt;br /&gt;class PaypalHandler(BaseHTTPRequestHandler):&lt;br /&gt;    """&lt;br /&gt;    Simple server to return verified value for our paypal tests&lt;br /&gt;    """&lt;br /&gt;    def do_POST(self):&lt;br /&gt;        self.send_response(200, 'OK')&lt;br /&gt;        self.send_header('Content-type', 'text/html')&lt;br /&gt;        self.end_headers()&lt;br /&gt;        self.wfile.write( "VERIFIED" )&lt;br /&gt;&lt;br /&gt;class RunThread(Thread):&lt;br /&gt;    def __init__(self, port):&lt;br /&gt;        Thread.__init__(self)&lt;br /&gt;        self.server = HTTPServer(('127.0.0.1', port), PaypalHandler)&lt;br /&gt;    def run(self):&lt;br /&gt;        self.server.serve_forever()&lt;br /&gt;&lt;br /&gt;server_thread = None&lt;br /&gt;&lt;br /&gt;def start_server(port):&lt;br /&gt;    global server_thread&lt;br /&gt;    server_thread = RunThread(port)&lt;br /&gt;    server_thread.start()&lt;br /&gt;&lt;br /&gt;def stop_server():&lt;br /&gt;    global server_thread&lt;br /&gt;    server_thread.server.socket.close()&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Now in my test setup I can call&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;pre&gt;def setUp(suite):&lt;br /&gt;    testing.start_server(10080)&lt;br /&gt;&lt;br /&gt;def tearDown(suite):&lt;br /&gt;    testing.stop_server()&lt;br /&gt;&lt;/pre&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;And it works as expected.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3175310051823862908-2500500230641976728?l=darrylcousins.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darrylcousins.blogspot.com/feeds/2500500230641976728/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3175310051823862908&amp;postID=2500500230641976728' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3175310051823862908/posts/default/2500500230641976728'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3175310051823862908/posts/default/2500500230641976728'/><link rel='alternate' type='text/html' href='http://darrylcousins.blogspot.com/2010/04/running-http-server-in-thread.html' title='Running a HTTP Server in a Thread'/><author><name>Darryl Cousins</name><uri>http://www.blogger.com/profile/00503179527741824865</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_T3dozklXrk8/S0ZNz_YLhYI/AAAAAAAABlI/zfqao6zElAU/S220/avatar-sm.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3175310051823862908.post-8175819278541817651</id><published>2010-02-28T15:53:00.000-08:00</published><updated>2010-02-28T15:55:04.686-08:00</updated><title type='text'>Snow Leopard and Zope3</title><content type='html'>I've been required to revisit an old zope application built using buildout. The application versions are quite old (3.4.* mostly) and includes old dependencies such as lxml-1.3.1, ZODB3-3.8 amongst others.&lt;br /&gt;&lt;br /&gt;As the buildout was running I noticed compile errors and finally it would grind to a halt when import say `_zope_proxy_proxy` which is a compiled .so file.&lt;br /&gt;&lt;br /&gt;To cut a long story short the solution for me was to edit `lib/python2.6/config/Makefile` (naturally this is within a `virtualenv`) and change the lines:&lt;br /&gt;&lt;br /&gt;CC= /usr/bin/gcc-4.2&lt;br /&gt;CXX= /usr/bin/g++-4.2&lt;br /&gt;&lt;br /&gt;to read:&lt;br /&gt;&lt;br /&gt;CC= /usr/bin/gcc-4.0&lt;br /&gt;CXX= /usr/bin/g++-4.0&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3175310051823862908-8175819278541817651?l=darrylcousins.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darrylcousins.blogspot.com/feeds/8175819278541817651/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3175310051823862908&amp;postID=8175819278541817651' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3175310051823862908/posts/default/8175819278541817651'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3175310051823862908/posts/default/8175819278541817651'/><link rel='alternate' type='text/html' href='http://darrylcousins.blogspot.com/2010/02/snow-leopard-and-zope.html' title='Snow Leopard and Zope3'/><author><name>Darryl Cousins</name><uri>http://www.blogger.com/profile/00503179527741824865</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_T3dozklXrk8/S0ZNz_YLhYI/AAAAAAAABlI/zfqao6zElAU/S220/avatar-sm.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3175310051823862908.post-3383438512044599708</id><published>2010-01-09T12:36:00.000-08:00</published><updated>2010-01-29T16:04:51.454-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='repoze programming gae testing'/><title type='text'>Repoze BFG on Google App Engine</title><content type='html'>&lt;h2&gt;Introduction &lt;/h2&gt;&lt;div class="notice"&gt;&lt;strong&gt;29/02/2010:&lt;/strong&gt; I've gone a different direction than what is detailed here, instead I am using the approach taken by &lt;a href="http://code.google.com/p/bridal/"&gt;the bridal-demo&lt;/a&gt;. It wasn't too much trouble to plug a repoze.bfg application into the demo code. Hopefully I will write up a post about how I did that in the near future.&lt;br /&gt;&lt;/div&gt;I've come back to a google appengine application that I'd put aside for a while. I've been using repoze.bfg in other work so was determined to do the same here. There is a &lt;a href="http://docs.repoze.org/bfg/1.2%20/tutorials/gae/index.html"&gt;good tutorial&lt;/a&gt; for getting a repoze.bfg application running on gae using appengine-monkey which sets up a virtualenv within which the application can be developed. Great, I'm a fan of &lt;a href="http://pypi.python.org/pypi/virtualenv"&gt;virtualenv&lt;/a&gt;. A point to remember is that dev_appserver cannot be run with the `virtualev`/bin/python. I would forget that; so now I use a `start.sh` script to run the application.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;start.sh:&lt;/b&gt; &lt;br /&gt;&lt;pre&gt;#!/bin/bash&lt;br /&gt;PYTHON=/opt/local/bin/python2.5&lt;br /&gt;GAE_PATH=/usr/local/google_appengine&lt;br /&gt;$PYTHON $GAE_PATH/dev_appserver.py ./&lt;br /&gt;&lt;/pre&gt;&lt;h2&gt;Testing&lt;/h2&gt;I found it surprisingly difficult to set up a test environment for gae. My requirements were firstly to be able to use &lt;a href="http://en.wikipedia.org/wiki/Doctest"&gt;doctests&lt;/a&gt;, secondly to have &lt;a href="http://nedbatchelder.com/code/coverage/"&gt;coverage&lt;/a&gt;. Coverage comes with &lt;a href="http://somethingaboutorange.com/mrl/projects/nose/0.11.1/"&gt;nose&lt;/a&gt; to I generally use nose for testing. Initially it seemed that `virtualenv`/bin/easy_install nose coverage would do the job until I came to testing models. No google.appengine, no datastore. &lt;a href="http://code.google.com/p/nose-gae/%20"&gt;NoseGAE&lt;/a&gt; seemed to be a good answer but wouldn't work well within the virtualenv (again import problems). I also looked at &lt;a href="http://code.google.com/p/gaeunit/"&gt;gaeunit&lt;/a&gt; but I can't see any benefits to running tests through the browser during development (I rarely even look at a web application that I'm developing - that's what tests are for, to save me the trouble).&lt;br /&gt;&lt;br /&gt;However code from gaeunit helped me a lot from which, along with &lt;a href="http://domderrien.blogspot.com/2009/01/automatic-testing-of-gae-applications.html"&gt;this post&lt;/a&gt;, I developed my own solution.&lt;br /&gt;&lt;br /&gt;First part of the problem was to get sys.path set up correctly. I took what I needed from runner.py and dev_appserver.py to get the sys.path in working order.&lt;br /&gt;&lt;br /&gt;Secondly, I needed to have a test datastore available for testing models, I took a stanza from &lt;a href="http://domderrien.blogspot.com/2009/01/automatic-testing-of-gae-applications.html"&gt;Dom's post&lt;/a&gt; (also used by gaeunit).&lt;br /&gt;&lt;br /&gt;Thirdly, when I&amp;nbsp; put() a model an error would be raised about a lack of&amp;nbsp; `app_id` so I solved that with a stanza from $GAE_PATH/tools/dev_appserver.py to read app.yaml and set os.environ['APPLICATION_ID']. &lt;br /&gt;&lt;br /&gt;The resulting files then are&lt;br /&gt;&lt;br /&gt;&lt;b&gt;test.sh&lt;/b&gt;&lt;br /&gt;&lt;pre&gt;#!/bin/bash&lt;br /&gt;PYTHON=/opt/local/bin/python2.5&lt;br /&gt;$PYTHON testrunner.py $@&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;testrunner.py&lt;/b&gt;&lt;br /&gt;&lt;pre&gt;#!/usr/bin/env python&lt;br /&gt;&lt;br /&gt;# a special test runner&lt;br /&gt;import sys&lt;br /&gt;import os&lt;br /&gt;&lt;br /&gt;# {{ the first stanza copied from $GAE_PATH/dev_appserver.py&lt;br /&gt;GAE_PATH = "/usr/local/google_appengine"&lt;br /&gt;DIR_PATH = GAE_PATH&lt;br /&gt;SCRIPT_DIR = os.path.join(DIR_PATH, 'google', 'appengine', 'tools')&lt;br /&gt;EXTRA_PATHS = [&lt;br /&gt;    DIR_PATH,&lt;br /&gt;    os.path.join(DIR_PATH, 'lib', 'antlr3'),&lt;br /&gt;    os.path.join(DIR_PATH, 'lib', 'django'),&lt;br /&gt;    os.path.join(DIR_PATH, 'lib', 'webob'),&lt;br /&gt;    os.path.join(DIR_PATH, 'lib', 'yaml', 'lib'),&lt;br /&gt;  ]&lt;br /&gt;sys.path = EXTRA_PATHS + sys.path&lt;br /&gt;# }}&lt;br /&gt;&lt;br /&gt;# {{ and the second from runner.py&lt;br /&gt;here = os.path.dirname(__file__)&lt;br /&gt;fixpaths = os.path.join(here, 'fixpaths.py')&lt;br /&gt;execfile(fixpaths)&lt;br /&gt;# }}&lt;br /&gt;&lt;br /&gt;from google.appengine.api import apiproxy_stub_map&lt;br /&gt;from google.appengine.api import datastore_file_stub&lt;br /&gt;from google.appengine.tools.dev_appserver import ReadAppConfig&lt;br /&gt;&lt;br /&gt;# read application config file &lt;br /&gt;appinfo_path = os.path.join(here, 'app.yaml')&lt;br /&gt;config = ReadAppConfig(appinfo_path)&lt;br /&gt;&lt;br /&gt;# set application id so that objects can be stored in test database&lt;br /&gt;os.environ['APPLICATION_ID'] = config.application&lt;br /&gt;&lt;br /&gt;def main(module=None):&lt;br /&gt;    original_apiproxy = apiproxy_stub_map.apiproxy&lt;br /&gt;    try:&lt;br /&gt;        apiproxy_stub_map.apiproxy = apiproxy_stub_map.APIProxyStubMap()&lt;br /&gt;        temp_stub = datastore_file_stub.DatastoreFileStub('TestDataStore', None, None, trusted=True)&lt;br /&gt;        apiproxy_stub_map.apiproxy.RegisterStub('datastore', temp_stub)&lt;br /&gt;        # Allow the other services to be used as-is for tests.&lt;br /&gt;        for name in ['user', 'urlfetch', 'mail', 'memcache', 'images']:&lt;br /&gt;             apiproxy_stub_map.apiproxy.RegisterStub(name, original_apiproxy.GetStub(name))&lt;br /&gt;        from nose.core import TestProgram&lt;br /&gt;        testprogram = TestProgram(module=module)&lt;br /&gt;    except:&lt;br /&gt;        apiproxy_stub_map.apiproxy = original_apiproxy&lt;br /&gt;&lt;br /&gt;# accept module name to pass to test runner&lt;br /&gt;try:&lt;br /&gt;    module = sys.argv[1]&lt;br /&gt;except:&lt;br /&gt;    module = None&lt;br /&gt;&lt;br /&gt;if __name__ == "__main__":&lt;br /&gt;    main(module=module)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;And for completeness here is setup.cfg&lt;br /&gt;&lt;pre&gt;[nosetests]&lt;br /&gt;verbose=1&lt;br /&gt;nocapture=1&lt;br /&gt;with-coverage=1&lt;br /&gt;cover-erase=1&lt;br /&gt;cover-inclusive=1&lt;br /&gt;cover-package=mybfgapp&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;So far, so good. I do rather suspect that this remains incomplete.&lt;br /&gt;&lt;h2&gt;References:&lt;/h2&gt;http://docs.repoze.org/bfg/1.2/tutorials/gae/index.html&lt;br /&gt;http://blog.appenginefan.com/2008/06/unit-tests-for-google-app-engine-apps.html&lt;br /&gt;http://www.cuberick.com/2008/11/unit-test-your-google-app-engine-models.html&lt;br /&gt;http://code.google.com/p/nose-gae/ &lt;br /&gt;http://code.google.com/p/gaeunit/&lt;br /&gt;http://domderrien.blogspot.com/2009/01/automatic-testing-of-gae-applications.html&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3175310051823862908-3383438512044599708?l=darrylcousins.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darrylcousins.blogspot.com/feeds/3383438512044599708/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3175310051823862908&amp;postID=3383438512044599708' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3175310051823862908/posts/default/3383438512044599708'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3175310051823862908/posts/default/3383438512044599708'/><link rel='alternate' type='text/html' href='http://darrylcousins.blogspot.com/2010/01/repoze-bfg-on-google-app-engine.html' title='Repoze BFG on Google App Engine'/><author><name>Darryl Cousins</name><uri>http://www.blogger.com/profile/00503179527741824865</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_T3dozklXrk8/S0ZNz_YLhYI/AAAAAAAABlI/zfqao6zElAU/S220/avatar-sm.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3175310051823862908.post-4100155131472767240</id><published>2009-12-09T17:51:00.000-08:00</published><updated>2009-12-09T18:02:27.948-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>mod_wsgi on OSX</title><content type='html'>The problem: mod_wsgi built fine but:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new;"&gt;$ apachectl configtest&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;httpd: Syntax error on line 118 of /private/etc/apache2/httpd.conf: Cannot load /usr/libexec/apache2/mod_wsgi.so into server: dlopen(/usr/libexec/apache2/mod_wsgi.so, 10&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;): Symbol not found: _PyExc_RuntimeError\n  Referenced from: /usr/libexec/apache2/mod_wsgi.so\n  Expected in: dynamic lookup\n&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;After following along with &lt;a href="http://code.google.com/p/modwsgi/wiki/InstallationOnMacOSX"&gt;InstallationOnMacOSX&lt;/a&gt; I latterly found &lt;a href="http://gidden.net/tom/2008/06/30/mysql-and-pdo-on-os-x-leopard-intel/comment-page-1/#comment-16477"&gt;this comment&lt;/a&gt; on his own post by Tom Giddens to get mod_wsgi to work with apache. I actually went with &lt;a href="http://codesnippets.joyent.com/posts/show/1328"&gt;this method&lt;/a&gt; to achieve the same goal. Thanks all.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3175310051823862908-4100155131472767240?l=darrylcousins.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darrylcousins.blogspot.com/feeds/4100155131472767240/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3175310051823862908&amp;postID=4100155131472767240' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3175310051823862908/posts/default/4100155131472767240'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3175310051823862908/posts/default/4100155131472767240'/><link rel='alternate' type='text/html' href='http://darrylcousins.blogspot.com/2009/12/modwsgi-on-osx.html' title='mod_wsgi on OSX'/><author><name>Darryl Cousins</name><uri>http://www.blogger.com/profile/00503179527741824865</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_T3dozklXrk8/S0ZNz_YLhYI/AAAAAAAABlI/zfqao6zElAU/S220/avatar-sm.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3175310051823862908.post-3926240199675416638</id><published>2009-08-10T03:55:00.000-07:00</published><updated>2009-12-09T17:51:43.448-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Some python notes on Leopard 10.5</title><content type='html'>Thanks again to Ian Bicking:&lt;br /&gt;&lt;p&gt;&lt;a href="http://blog.ianbicking.org/2008/12/10/lxml-an-underappreciated-web-scraping-library/"&gt;lxml: an underappreciated web scraping library&lt;/a&gt;&lt;/p&gt;&lt;pre class="literal-block"&gt;$ STATIC_DEPS=true easy_install 'lxml&gt;=2.2alpha1'&lt;/pre&gt;&lt;p&gt;Truly most appreciated.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3175310051823862908-3926240199675416638?l=darrylcousins.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darrylcousins.blogspot.com/feeds/3926240199675416638/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3175310051823862908&amp;postID=3926240199675416638' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3175310051823862908/posts/default/3926240199675416638'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3175310051823862908/posts/default/3926240199675416638'/><link rel='alternate' type='text/html' href='http://darrylcousins.blogspot.com/2009/08/lxml-on-leopard-105.html' title='Some python notes on Leopard 10.5'/><author><name>Darryl Cousins</name><uri>http://www.blogger.com/profile/00503179527741824865</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_T3dozklXrk8/S0ZNz_YLhYI/AAAAAAAABlI/zfqao6zElAU/S220/avatar-sm.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3175310051823862908.post-4413652259980736232</id><published>2009-04-19T22:54:00.000-07:00</published><updated>2009-08-06T00:14:22.258-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>A Life Stream</title><content type='html'>Version II of my life stream effort is acting now as my home page. The first version was using &lt;a href="http://friendfeed.com/darrylcousins"&gt;FriendFeed&lt;/a&gt; but in this version my server side code is directly requesting the feeds from &lt;a href="http://code.google.com/p/gdata-python-client/"&gt;google&lt;/a&gt;, &lt;a href="http://apiwiki.twitter.com/"&gt;twitter&lt;/a&gt; and &lt;a href="http://delicious.com/help/api"&gt;delicious&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The earlier version used a jsonrpc library but I'm now using &lt;a href="http://webpy.org/"&gt;web.py&lt;/a&gt; to provide the services.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3175310051823862908-4413652259980736232?l=darrylcousins.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darrylcousins.blogspot.com/feeds/4413652259980736232/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3175310051823862908&amp;postID=4413652259980736232' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3175310051823862908/posts/default/4413652259980736232'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3175310051823862908/posts/default/4413652259980736232'/><link rel='alternate' type='text/html' href='http://darrylcousins.blogspot.com/2009/04/life-stream.html' title='A Life Stream'/><author><name>Darryl Cousins</name><uri>http://www.blogger.com/profile/00503179527741824865</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_T3dozklXrk8/S0ZNz_YLhYI/AAAAAAAABlI/zfqao6zElAU/S220/avatar-sm.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3175310051823862908.post-8727447394563551577</id><published>2009-04-02T12:28:00.000-07:00</published><updated>2009-04-02T12:35:56.231-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Compiling mod_python on OSX</title><content type='html'>Source distribution of mod_python (3.3.1) didn't compile on my iMac, but that from the repository did:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;svn co https://svn.apache.org/repos/asf/quetzalcoatl/mod_python/trunk mod_python_src&lt;br /&gt;cd mod_python_src&lt;br /&gt;./configure --with-apxs=/usr/local/apache2/bin/apxs --with-python=/usr/local/Python/Python-2.5.2/bin/python2.5&lt;br /&gt;make&lt;br /&gt;sudo make install&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Note that I have built both apache2 and python2.5 from source on my system.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3175310051823862908-8727447394563551577?l=darrylcousins.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darrylcousins.blogspot.com/feeds/8727447394563551577/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3175310051823862908&amp;postID=8727447394563551577' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3175310051823862908/posts/default/8727447394563551577'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3175310051823862908/posts/default/8727447394563551577'/><link rel='alternate' type='text/html' href='http://darrylcousins.blogspot.com/2009/04/compiling-modpython-on-osx.html' title='Compiling mod_python on OSX'/><author><name>Darryl Cousins</name><uri>http://www.blogger.com/profile/00503179527741824865</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_T3dozklXrk8/S0ZNz_YLhYI/AAAAAAAABlI/zfqao6zElAU/S220/avatar-sm.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3175310051823862908.post-5496006397943470450</id><published>2008-10-06T11:15:00.000-07:00</published><updated>2008-10-21T23:48:39.727-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>apache, php, postgresql on osx</title><content type='html'>I've added some &lt;a href="http://darrylcousins.net.nz/projects/listing.php?repname=install-scripts&amp;amp;path=%2F&amp;amp;"&gt;scripts&lt;/a&gt; to build (cmmi) software on my mac. Although the software is readily available in binary form or using &lt;a href="http://www.macports.org/"&gt;macports&lt;/a&gt; I prefer complete control.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3175310051823862908-5496006397943470450?l=darrylcousins.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darrylcousins.blogspot.com/feeds/5496006397943470450/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3175310051823862908&amp;postID=5496006397943470450' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3175310051823862908/posts/default/5496006397943470450'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3175310051823862908/posts/default/5496006397943470450'/><link rel='alternate' type='text/html' href='http://darrylcousins.blogspot.com/2008/10/apache-php-postgresql-on-osx.html' title='apache, php, postgresql on osx'/><author><name>Darryl Cousins</name><uri>http://www.blogger.com/profile/00503179527741824865</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_T3dozklXrk8/S0ZNz_YLhYI/AAAAAAAABlI/zfqao6zElAU/S220/avatar-sm.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3175310051823862908.post-6255009142479492090</id><published>2008-09-15T03:02:00.000-07:00</published><updated>2008-10-21T23:49:08.176-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Events app</title><content type='html'>A little app using google data calendar api: &lt;a href="http://transitiontownthames.org.nz/events.html"&gt;http://transitiontownthames.org.nz/events.html&lt;/a&gt;. At the moment anyone with a google account can add events and therefore I had to disable the 'edit entry' and 'delete entry' functionality. Need to get my head around the authentication particulary access control. I spent around 30 hours coding the thing (including learning from scratch the necessary apis).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3175310051823862908-6255009142479492090?l=darrylcousins.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darrylcousins.blogspot.com/feeds/6255009142479492090/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3175310051823862908&amp;postID=6255009142479492090' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3175310051823862908/posts/default/6255009142479492090'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3175310051823862908/posts/default/6255009142479492090'/><link rel='alternate' type='text/html' href='http://darrylcousins.blogspot.com/2008/09/events-app.html' title='Events app'/><author><name>Darryl Cousins</name><uri>http://www.blogger.com/profile/00503179527741824865</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_T3dozklXrk8/S0ZNz_YLhYI/AAAAAAAABlI/zfqao6zElAU/S220/avatar-sm.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3175310051823862908.post-3263471266885019760</id><published>2008-09-05T18:32:00.000-07:00</published><updated>2009-04-04T15:32:32.964-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Compiling Python2.5 on Leopard</title><content type='html'>I had some bother with compiling &lt;a href="http://python.org/"&gt;python2.5&lt;/a&gt; on Leopard. But with the help of &lt;a href="http://www.zopyx.com/blog/compiling-readline-support-for-python-on-macosx"&gt;Andreas Jung&lt;/a&gt; I finally got it to work as I'd like. For what it's worth I've created a &lt;a href="http://darrylcousins.net.nz/projects/filedetails.php?repname=install-scripts&amp;amp;path=%2Fpython-install.sh"&gt;shell script&lt;/a&gt; for the process. It also includes installing easy_install, lxml and mx packages. (There was a &lt;a href="https://www.egenix.com/mailman-archives/egenix-users/2008-September/114439.html"&gt;problem&lt;/a&gt; with mxExperimental which is fixed with the development snapshot - thanks Marc-Andre.)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3175310051823862908-3263471266885019760?l=darrylcousins.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darrylcousins.blogspot.com/feeds/3263471266885019760/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3175310051823862908&amp;postID=3263471266885019760' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3175310051823862908/posts/default/3263471266885019760'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3175310051823862908/posts/default/3263471266885019760'/><link rel='alternate' type='text/html' href='http://darrylcousins.blogspot.com/2008/09/compiling-python25-on-leopard.html' title='Compiling Python2.5 on Leopard'/><author><name>Darryl Cousins</name><uri>http://www.blogger.com/profile/00503179527741824865</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_T3dozklXrk8/S0ZNz_YLhYI/AAAAAAAABlI/zfqao6zElAU/S220/avatar-sm.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3175310051823862908.post-4566526443397333654</id><published>2008-08-05T04:13:00.000-07:00</published><updated>2008-10-21T23:50:10.595-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>First Post</title><content type='html'>I suppose one has to start somewhere.&lt;div&gt;&lt;br /&gt;I've created a &lt;a href="http://pypi.python.org/pypi/zc.buildout/"&gt;buildout&lt;/a&gt; to get started with &lt;a href="http://code.google.com/p/gdata-python-client/"&gt;gdata.py&lt;/a&gt;. I needed to hack the &lt;a href="http://code.google.com/p/gdata-python-client/"&gt;gdata.py&lt;/a&gt; package &lt;span class="Apple-style-span" style="font-weight: bold;"&gt;setup.py&lt;/span&gt; to use &lt;a href="http://peak.telecommunity.com/DevCenter/setuptools"&gt;setuptools&lt;/a&gt; instead of &lt;span class="Apple-style-span" style="font-weight: bold;"&gt;disutils&lt;/span&gt;. Maybe later I'll find a different way to install &lt;a href="http://code.google.com/p/gdata-python-client/"&gt;gdata.py&lt;/a&gt; into the buildout but for now I've gone with unpacking the tar into my buildout directory and building the package as a develop egg.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I then created a new &lt;span class="Apple-style-span" style="font-weight: bold;"&gt;tfws.gdata&lt;/span&gt; package (for want of a better name) to start playing around with the &lt;a href="http://code.google.com/p/gdata-python-client/"&gt;gdata.py&lt;/a&gt; api. The &lt;a href="http://tfws.org.nz/"&gt;tfws&lt;/a&gt; namespace is one under which I've been building python packages in the past (almost exclusively unfinished and unreleased &lt;a href="http://www.zope.org/"&gt;zope&lt;/a&gt; work). The new &lt;span class="Apple-style-span" style="font-weight: bold;"&gt;t&lt;/span&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;fws.gdata&lt;/span&gt; package today contains only a &lt;a href="http://wiki.zope.org/zope3/doctests.html"&gt;doctest&lt;/a&gt; to ensure that the packages have installed correctly by simple imports.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Then, thanks to &lt;a href="http://blog.e-shell.org/72/"&gt;wu,&lt;/a&gt; I found out why my &lt;a href="http://www.macports.org/"&gt;macports&lt;/a&gt; installed &lt;a href="http://www.python.org/"&gt;python2.5&lt;/a&gt; didn't have &lt;span class="Apple-style-span" style="font-weight: bold;"&gt;ssl&lt;/span&gt; or indeed &lt;span class="Apple-style-span" style="font-weight: bold;"&gt;readline&lt;/span&gt; support.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3175310051823862908-4566526443397333654?l=darrylcousins.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://darrylcousins.blogspot.com/feeds/4566526443397333654/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3175310051823862908&amp;postID=4566526443397333654' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3175310051823862908/posts/default/4566526443397333654'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3175310051823862908/posts/default/4566526443397333654'/><link rel='alternate' type='text/html' href='http://darrylcousins.blogspot.com/2008/08/first-post.html' title='First Post'/><author><name>Darryl Cousins</name><uri>http://www.blogger.com/profile/00503179527741824865</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_T3dozklXrk8/S0ZNz_YLhYI/AAAAAAAABlI/zfqao6zElAU/S220/avatar-sm.jpg'/></author><thr:total>0</thr:total></entry></feed>
