<?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'><id>tag:blogger.com,1999:blog-18697241</id><updated>2010-01-24T13:21:04.897-08:00</updated><title type='text'>Darrell Hawley: Home Page</title><subtitle type='html'></subtitle><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18697241/posts/default'/><link rel='alternate' type='text/html' href='http://www.darrellhawley.com/default.html'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/18697241/posts/default?start-index=26&amp;max-results=25'/><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://www.darrellhawley.com/atom.xml'/><author><name>Darrell Hawley</name><uri>http://www.blogger.com/profile/13626445665115916691</uri><email>noreply@blogger.com</email></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>101</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-18697241.post-8003076775359655118</id><published>2010-01-24T13:21:00.001-08:00</published><updated>2010-01-24T13:21:04.961-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Django'/><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>Django at the Ann Arbor Software Development Study Group</title><content type='html'>&lt;p&gt;I was supposed to lead a jam last December at the Ann Arbor &lt;a href="http://sites.google.com/site/softwaredevelopmentstudygroup/home"&gt;Software Development Study Group&lt;/a&gt;, but a client project postponed it. On Tuesday, February 2, we’ll try one more time. The topic is “&lt;em&gt;Zero to Django: Writing Web Apps with Python Using the Django Framework&lt;/em&gt;”. By the end of the session, you will be collecting form data and redisplaying it on a webpage.&lt;/p&gt;  &lt;p&gt;NOTE: This exercise is meant to get you collecting data quickly and I’ll be skipping a lot of explanations. Feel free to ask questions or research any areas that you may find particularly tricky.&lt;/p&gt;  &lt;p&gt;On with the jam!&lt;/p&gt;  &lt;p&gt;Pre-Requisites: &lt;/p&gt;  &lt;p&gt;Though there is only one requirement for this session - installing Django - you'll want to get this done ahead of time. It's not difficult, but there are a few steps and it will take enough time that it could keep you from completing all the exercises. To install Django, go to&lt;a href="http://docs.djangoproject.com/en/dev/topics/install/#topics-install"&gt; http://docs.djangoproject.com/en/dev/topics/install&lt;/a&gt; for a detailed description of what you need to do. Before following that link, here's a couple of suggestions:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Be sure to install &lt;b&gt;Python 2.5&lt;/b&gt; (Python 2.6 will probably be fine). Django will not run with the 3.x series of Python. &lt;/li&gt;    &lt;li&gt;You can skip installing Apache and mod-wsgi. This session is only about how to use the framework which can be done completely within the development environment provided by Django. &lt;/li&gt;    &lt;li&gt;You can also skip the section on getting a database running. We'll be using SQLite which is baked into Python 2.5 and later versions. &lt;/li&gt;    &lt;li&gt;Be sure to install an official release of Django. Under &amp;quot;Installing an&amp;#160; official release&amp;quot;, click on &amp;quot;download page&amp;quot; in line item 1. Use the version under &amp;quot;Option 1: Get the latest official version&amp;quot;. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;The Exercise:&lt;/p&gt;  &lt;p&gt;Create a folder where all of your Django apps can you live. I'm using Windows and I'm putting all of my Django projects in the C:\django directory.&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;From the command line, navigate to the directory you just created &lt;/li&gt;    &lt;li&gt;from the command line, run &amp;quot;python django-admin.py startproject people&amp;quot;. You may have to explicity give the path of the django-admin.py file which can be found in python25/Lib/site-packages/[django dir]. If you copied the file as suggested by the installation directions, just use that version of the file instead. Also, you may get a &amp;quot;permission denied&amp;quot; message. If that's the case, check your permissions on the folder. &lt;/li&gt;    &lt;li&gt;If you successfully completed step 3, you should now have a &amp;quot;people&amp;quot; directory. On my machine, the path is c:\django\people. &lt;/li&gt;    &lt;li&gt;Navigate to the directory mentioned in Step 4 and run &amp;quot;python manage.py runserver&amp;quot; &lt;/li&gt;    &lt;li&gt;Open up a browser and navigate to &amp;quot;http://localhost:8000/people&amp;quot;. You should see a message congratulating you on &amp;quot;your first Django-powered Page&amp;quot; &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;Now that you’ve created a page, let’s configure our site so that we can do something useful.&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Django Projects contain one or more Apps (OK, they don’t &lt;em&gt;have to&lt;/em&gt; contain Apps, but if you want to connect to a database they do). To create an app, run &lt;em&gt;“python&lt;/em&gt;&lt;em&gt; manage.py startapp dataentry”&lt;/em&gt;. The “&lt;em&gt;manage.py&lt;/em&gt;” file can be found in the root of the people directory you created earlier. On my machine, the path is C:\django\people\manage.py. &lt;/li&gt;    &lt;li&gt;In the “&lt;em&gt;settings.py&lt;/em&gt;” file contained within the project root, configure the database. For this exercise we’ll use SQLite since it comes bundled with &lt;a href="http://python.org/"&gt;Python&lt;/a&gt; 2.5 and all later versions:       &lt;blockquote&gt;       &lt;p&gt;DATABASE_ENGINE = 'sqlite3'          &lt;br /&gt;DATABASE_NAME = 'peopledb'           &lt;br /&gt;DATABASE_USER = ''           &lt;br /&gt;DATABASE_PASSWORD = ''           &lt;br /&gt;DATABASE_HOST = ''           &lt;br /&gt;DATABASE_PORT = ''&lt;/p&gt;     &lt;/blockquote&gt;   &lt;/li&gt; &lt;/ul&gt;  &lt;ul&gt;   &lt;li&gt;In the settings file, you need to add your app to the INSTALLED_APPS section. Your INSTALLED_APPS section should look like the following (note the “people.dataentry” on the last line):      &lt;p&gt;INSTALLED_APPS = (        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; 'django.contrib.auth',         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; 'django.contrib.contenttypes',         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; 'django.contrib.sessions',         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; 'django.contrib.admin',&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; people.dataentry',         &lt;br /&gt;)&lt;/p&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;p&gt;Again in the settings file, add “&lt;em&gt;&amp;quot;/templates&amp;quot;,&lt;/em&gt;” to the TEMPLATE_DIRS setting.         &lt;br /&gt;        &lt;br /&gt;Don’t worry about the extra lines. Those go beyond the scope of this session. If they really bother you, you can remove them. Just be aware that you’ll need add the extra comma (,) at the end so Python understands that this is a single item tuple.&lt;/p&gt;   &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Now that the configuration is done, it’s time to setup your database. To do that, we’ll need to open up model.py file inside your application directory. On my machine, that’s “&lt;em&gt;c:\django\people\dataentry\model.py&lt;/em&gt;”. Your model should like the following:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;from django.db import models &lt;/p&gt;    &lt;p&gt;class Person(models.Model):      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; T_SHIRT_SIZE_CHOICES = (       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; (&amp;quot;WS&amp;quot;,&amp;quot;Women's Small&amp;quot;),       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; (&amp;quot;WM&amp;quot;,&amp;quot;Women's Medium&amp;quot;),       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; (&amp;quot;WL&amp;quot;,&amp;quot;Women's Large&amp;quot;),       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; (&amp;quot;S&amp;quot;,&amp;quot;Small&amp;quot;),       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; (&amp;quot;M&amp;quot;,&amp;quot;Medium&amp;quot;),       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; (&amp;quot;L&amp;quot;,&amp;quot;Large&amp;quot;),       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; (&amp;quot;XL&amp;quot;,&amp;quot;X-Large&amp;quot;),       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; (&amp;quot;2XL&amp;quot;,&amp;quot;2X-Large&amp;quot;),       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; (&amp;quot;3XL&amp;quot;,&amp;quot;3X-Large&amp;quot;),       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; )       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; name = models.CharField(max_length=30)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; t_shirt_size = models.CharField(max_length=10,       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; choices=T_SHIRT_SIZE_CHOICES)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; special_dietary_concerns = models.BooleanField(       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; default=False)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; special_dietary_concerns_comments = models.TextField(null=True,       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; blank=True) &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; def __unicode__(self):      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return &amp;quot;&amp;lt;Person %s %s %s&amp;gt;&amp;quot; % (       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; self.name,       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; self.t_shirt_size,       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; self.special_dietary_concerns)&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Now that your model is in place, let’s make sure that it’s reflected in the database.&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;From the command line in the directory where the model.py file lives (“&lt;em&gt;c:\django\people\dataentry\model.py&lt;/em&gt;” on my machine), run “&lt;em&gt;python manage.py syncdb&lt;/em&gt;”. A series of tables will be created. &lt;/li&gt;    &lt;li&gt;You will be prompted to create a superuser. Type “&lt;em&gt;yes&lt;/em&gt;” and continue through the prompts. &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;That’s it! The Person class is now in the database. But how do you use it.? To test it out, run “&lt;em&gt;python manage.py shell&lt;/em&gt;” from the command line. You’ll be placed into Python’s Interactive Console. Now run the following commands&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;from dataentry.models import Person &lt;/li&gt;    &lt;li&gt;p = Person() &lt;/li&gt;    &lt;li&gt;p.name = “Me” &lt;/li&gt;    &lt;li&gt;p.t_shirt_size = “L” &lt;/li&gt;    &lt;li&gt;p.save() &lt;/li&gt;    &lt;li&gt;Person.objects.get(id=1) &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;That last command should have printed “&amp;lt;Person Me L False&amp;gt;” in the console. Assuming it did, how do we get this form on a webpage? Before we do that, let’s make a webpage first.&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Create a new folder called “templates” in the “&lt;em&gt;c:\django\people\dataentry&lt;/em&gt;” directory. &lt;/li&gt;    &lt;li&gt;In the “&lt;em&gt;c:\django\people\dataentry&lt;/em&gt;\templates” directory, create a new file called “template.html” &lt;/li&gt;    &lt;li&gt;In the template.html file, paste the following snippet “&amp;lt;h1&amp;gt;{{ hello }}&amp;lt;/h1&amp;gt;” . Save the file. &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;You’ve just created a very basic template. To use it, make sure that your views.py file looks like the following:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;from django.shortcuts import render_to_response &lt;/p&gt;    &lt;p&gt;def hello(request):      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; hello = &amp;quot;Hello, World&amp;quot;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; return render_to_response(&amp;quot;template.html&amp;quot;, locals())&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Open “c:\django\people\urls.py” and make sure the following code is in it:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;from django.conf.urls.defaults import *      &lt;br /&gt;from people.dataentry import views &lt;/p&gt;    &lt;p&gt;urlpatterns = patterns('',      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; (r'^hello/$', views.hello)       &lt;br /&gt;)&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;All the pieces should be in place for you to actually view your webpage. From the command line, run “python manage.py runserver”. Open your favorite web browser and navigate to http://localhost:8000/hello. You should be rewarded with “Hello, World” in a very large font. That’s all well and good, but what about that model we created? Let’s put it to good use right now. Let’s create a list.html in our template directory that looks something like the following:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&amp;lt;html&amp;gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;head&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;title&amp;gt;{{ title }}&amp;lt;/title&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;/head&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;body&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;table&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;tr&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;th&amp;gt;Name&amp;lt;/th&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;th&amp;gt;T Shirt Size&amp;lt;/th&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;th&amp;gt;Special Diet&amp;lt;/th&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;th&amp;gt;Special Diet Comments&amp;lt;/th&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;/tr&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {%&amp;#160; for person in people %}       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;tr&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;td&amp;gt;{{ person.name }}&amp;lt;/td&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;td&amp;gt;{{ person.t_shirt_size }}&amp;lt;/td&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;td&amp;gt;{{ person.special_dietary_concerns }}&amp;lt;/td&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;td&amp;gt;{{ person.special_dietary_concerns_comments }}&amp;lt;/td&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;/tr&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {% endfor %}       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;/body&amp;gt;       &lt;br /&gt;&amp;lt;/html&amp;gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Now let’s create a new method in our view so that our views.py file looks like the following:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;from django.shortcuts import render_to_response      &lt;br /&gt;from people.dataentry.models import Person &lt;/p&gt;    &lt;p&gt;def hello(request):      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; hello = &amp;quot;Hello, World&amp;quot;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; return render_to_response(&amp;quot;template.html&amp;quot;, locals()) &lt;/p&gt;    &lt;p&gt;def list_people(request):      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; title = &amp;quot;List of People&amp;quot;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; people = Person.objects.all()       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; return render_to_response(&amp;quot;list.html&amp;quot;, locals())&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Switch to the urls.py file and wire a url to our new method. Our updated urls.py file should look like the following:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;from django.conf.urls.defaults import *      &lt;br /&gt;from people.dataentry import views &lt;/p&gt;    &lt;p&gt;urlpatterns = patterns('',      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; (r'^hello/$', views.hello),       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; (r'^list/$', views.list_people),       &lt;br /&gt;)&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;From your web browser, navigate to http://localhost:8000/list. You should see the person you entered in the Interactive Console. Cool! By now you should see a pattern on how to create a new page in Django: create a template, create a new method in the view and then edit the urls.py file. Let’s add a bit more complexity by creating a form. Create a new forms.py file in the “C:\django\people\dataentry” directory. Put the following code block in that new file:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;from django import forms      &lt;br /&gt;from models import Person &lt;/p&gt;    &lt;p&gt;class PersonForm(forms.ModelForm):      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; class Meta(object):       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; model = Person&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Create a new template in the template folder called “form.html” and put the following html inside it:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&amp;lt;html&amp;gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;head&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;title&amp;gt;Adding a Person&amp;lt;/title&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;/head&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;body&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;form method=&amp;quot;post&amp;quot;&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;table&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {{ form.as_table }}       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;/table&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;input type='submit'&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;/form&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;/body&amp;gt;       &lt;br /&gt;&amp;lt;/html&amp;gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Switch over to your view.py file and modify it so that it looks like the following:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;from django.shortcuts import render_to_response, HttpResponseRedirect      &lt;br /&gt;from people.dataentry.models import Person       &lt;br /&gt;from people.dataentry.forms import PersonForm &lt;/p&gt;    &lt;p&gt;def hello(request):      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; hello = &amp;quot;Hello, World&amp;quot;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; return render_to_response(&amp;quot;template.html&amp;quot;, locals()) &lt;/p&gt;    &lt;p&gt;def list_people(request):      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; title = &amp;quot;List of People&amp;quot;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; people = Person.objects.all()       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; return render_to_response(&amp;quot;list.html&amp;quot;, locals()) &lt;/p&gt;    &lt;p&gt;def add_person(request):      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; title = &amp;quot;Add Person&amp;quot;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; if 'name' in request.POST:       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; form = PersonForm(request.POST)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if form.errors:       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; errors = form.errors       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; else:       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; form.save()       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return HttpResponseRedirect(&amp;quot;../list&amp;quot;)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; else:       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; form = PersonForm()       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; return render_to_response(&amp;quot;form.html&amp;quot;, locals())&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Now all you have to do is wire up the url in the urls.py file. Now when you successfully add a new person using the form you will be redirected back to the list of people where you will see your entry at the bottom of the list.&amp;#160; &lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18697241-8003076775359655118?l=www.darrellhawley.com%2Fdefault.html' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/18697241/8003076775359655118/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=18697241&amp;postID=8003076775359655118' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18697241/posts/default/8003076775359655118'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18697241/posts/default/8003076775359655118'/><link rel='alternate' type='text/html' href='http://www.darrellhawley.com/2010/01/django-at-ann-arbor-software.html' title='Django at the Ann Arbor Software Development Study Group'/><author><name>Darrell Hawley</name><uri>http://www.blogger.com/profile/13626445665115916691</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='03881874778058834600'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18697241.post-4198779655815676883</id><published>2009-12-29T09:53:00.001-08:00</published><updated>2009-12-29T11:41:10.109-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='IronPython'/><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><category scheme='http://www.blogger.com/atom/ns#' term='IterHelper'/><title type='text'>IterHelper Released</title><content type='html'>&lt;p&gt;I’ve mentioned &lt;a href="https://launchpad.net/iterhelper"&gt;IterHelper&lt;/a&gt; in my last few posts and I’m glad to say that I finally released a version of it that I feel is solid. I’ve run my unit tests on &lt;a href="http://python.org/"&gt;Python&lt;/a&gt; versions 2.5 and 2.6 and also on &lt;a href="http://www.codeplex.com/IronPython"&gt;IronPython&lt;/a&gt; 2.0 and 2.6.&lt;/p&gt;  &lt;p&gt;It doesn’t do anything earth-shattering at this point, but it does have some functions I find particularly useful such as a couple of filter methods and a number of “skip” and “take” methods. For a complete rundown of what it does, just run “help(IterHelper)”&lt;/p&gt;  &lt;p&gt;I’ve used &lt;a href="https://launchpad.net/"&gt;LaunchPad&lt;/a&gt; to manage my project and the experience has been good thus far. If you want to download it, you’ll need to do so from the trunk. I’m eventually moving to Python eggs, but until I work out the particulars, you’ll have to do include it in your project manually.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18697241-4198779655815676883?l=www.darrellhawley.com%2Fdefault.html' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/18697241/4198779655815676883/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=18697241&amp;postID=4198779655815676883' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18697241/posts/default/4198779655815676883'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18697241/posts/default/4198779655815676883'/><link rel='alternate' type='text/html' href='http://www.darrellhawley.com/2009/12/iterhelper-released.html' title='IterHelper Released'/><author><name>Darrell Hawley</name><uri>http://www.blogger.com/profile/13626445665115916691</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='03881874778058834600'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18697241.post-1072706127748191068</id><published>2009-11-29T17:22:00.001-08:00</published><updated>2009-11-29T17:22:02.793-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Euler'/><category scheme='http://www.blogger.com/atom/ns#' term='IronPython'/><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><category scheme='http://www.blogger.com/atom/ns#' term='IterHelper'/><title type='text'>Euler Problem 1 Revisited</title><content type='html'>&lt;p&gt;&lt;/p&gt;  &lt;p&gt;The other day at the &lt;a href="http://sites.google.com/site/softwaredevelopmentstudygroup/home"&gt;Software Development Study Group&lt;/a&gt; in Ann Arbor, &lt;a href="http://srtsolutions.com/blogs/chrismarinos/"&gt;Chris Marinos&lt;/a&gt; was demonstrating &lt;a href="http://research.microsoft.com/en-us/um/cambridge/projects/fsharp/"&gt;F#&lt;/a&gt;, a functional programming language targeting the .NET framework. Of course, this got me thinking about programming styles in Python. So what better way to compare and contrast programming styles than with &lt;a href="http://projecteuler.net/"&gt;Euler problems&lt;/a&gt;? As you probably &lt;em&gt;don’t&lt;/em&gt; recall, the first Euler problem is:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23.&lt;/p&gt;    &lt;p&gt;Find the sum of all the multiples of 3 or 5 below 1000.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;The traditional approach to this might look something like the following:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;def traditional_approach():      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; total = 0       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; for i in range(1,1000):       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if i % 5 == 0 or i % 3 == 0:       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; total += i       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; return total&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;It’s not a bad approach, but there are more concise approaches. Here is my original solution using a list comprehension:&lt;/p&gt;  &lt;blockquote&gt;isValid = lambda x: x % 5 == 0 or x % 3 == 0    &lt;br /&gt;    &lt;p&gt;def with_list_comprehension():      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; filteredValues = [x for x in range(1,1000) if isValid(x)]       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; return sum(filteredValues)&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;I like list comprehensions, but this feature &lt;em&gt;does&lt;/em&gt; introduce a lot of noise characters. If you use list comprehensions, you probably like this solution, otherwise you’re looking for something else. The next approach uses the itertools module (and the &lt;em&gt;isValid&lt;/em&gt; lambda from the previous example).&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;def with_itertools():      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; filteredValues = itertools.ifilter(isValid, range(1,1000))       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; return sum(filteredValues)&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;This approach removes a couple of noise characters and is structured in a way familiar to most developers. My last solution uses a module called &lt;a href="https://launchpad.net/iterhelper"&gt;IterHelper&lt;/a&gt; that I proposed in a &lt;a href="http://www.darrellhawley.com/2009/09/does-ironpython-need-linq.html"&gt;previous post&lt;/a&gt;. As I mentioned in that post, &lt;a href="https://launchpad.net/iterhelper"&gt;IterHelper&lt;/a&gt; sits on top of the itertools module and implements some of the recipes from the &lt;a href="http://docs.python.org/library/itertools.html"&gt;official itertools documentation&lt;/a&gt;. It’s largely inspired by my desire to use &lt;a href="http://msdn.microsoft.com/en-us/netframework/aa904594.aspx"&gt;LINQ&lt;/a&gt; from both &lt;a href="http://python.org/"&gt;Python&lt;/a&gt; and &lt;a href="http://www.codeplex.com/IronPython"&gt;IronPython&lt;/a&gt;. Here’s my solution to Euler Problem 1 using &lt;a href="https://launchpad.net/iterhelper"&gt;IterHelper&lt;/a&gt;:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;def with_iterhelper():      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; return IterHelper(range(1,1000))\       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; .where(isValid)\       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; .sum()&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Thanks to the Python continuation character, a backslash, I can put discreet units of functionality on their own line, making it easier for me to consume.&lt;/p&gt;  &lt;p&gt;If you decide to download and try out &lt;a href="https://launchpad.net/iterhelper"&gt;IterHelper&lt;/a&gt;, be aware that I’m not even considering it alpha yet. It’s still very much in the R &amp;amp; D phase and I’m planning on changing some of the method names.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18697241-1072706127748191068?l=www.darrellhawley.com%2Fdefault.html' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/18697241/1072706127748191068/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=18697241&amp;postID=1072706127748191068' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18697241/posts/default/1072706127748191068'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18697241/posts/default/1072706127748191068'/><link rel='alternate' type='text/html' href='http://www.darrellhawley.com/2009/11/euler-problem-1-revisited.html' title='Euler Problem 1 Revisited'/><author><name>Darrell Hawley</name><uri>http://www.blogger.com/profile/13626445665115916691</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='03881874778058834600'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18697241.post-6303180132145261212</id><published>2009-10-28T14:14:00.001-07:00</published><updated>2009-10-28T14:23:51.130-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='process'/><category scheme='http://www.blogger.com/atom/ns#' term='project management'/><title type='text'>Note to Self 12 – Lessons Learned from Our Latest Project</title><content type='html'>&lt;p&gt;I know I’m supposed to be releasing my IterHelper tool right now, but I’ve been on a bit of death march lately and have had no time. Though the project hasn’t ended yet, there are some items that I need to store away for future use before they’re forgotten.&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;On small teams, non-development related responsibilities should be divided among the team. Then the single non-dev responsibility (hopefully it’s the only one) should always take precedence over development responsibilities. It sounds backwards, but no matter what my priorities, I’m always going to find a way to write code. The same isn’t true of project management. &lt;/li&gt;    &lt;li&gt;I can’t say enough about having a non-developer - who I’ll refer to as the Customer Advocate – on the project team. Things we had problems making time for – client meetings and acceptance testing for instance – fell to the Customer Advocate which takes a lot of pressure off everyone else. &lt;/li&gt;    &lt;li&gt;Story points are great, but in order to get value out of them you actually have to use them – obvious, I know. Estimating tasks and then tracking how many points were completed daily, turned an out of control project into a manageable one. &lt;/li&gt;    &lt;li&gt;Speaking of scoring, I wish we would have re-scored each task after we completed it. It would have taken minimal effort while at the same time providing us with enough information to improve our estimates. &lt;/li&gt;    &lt;li&gt;We started using &lt;a href="http://agilezen.com/"&gt;Agile Zen&lt;/a&gt; at the beginning of our project, but eventually abandoned it in favor of physical notecards. This introduced a lot of challenges, but it did allow us to grow our process exactly the way we wanted it. The added benefit is we’re in a much better position to evaluate the various kanban applications for our next project. To be clear, &lt;a href="http://agilezen.com/"&gt;Agile Zen&lt;/a&gt; is a great product it just wasn’t what we needed at the time. &lt;/li&gt;    &lt;li&gt;We didn’t use &lt;a href="http://seleniumhq.org/"&gt;Selenium&lt;/a&gt; or &lt;a href="http://watir.com/"&gt;Watir&lt;/a&gt; to run acceptance tests. Even if we couldn’t run all the tests we wanted, it would have been a huge time saver. A costly mistake that won’t be repeated. &lt;/li&gt; &lt;/ul&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18697241-6303180132145261212?l=www.darrellhawley.com%2Fdefault.html' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/18697241/6303180132145261212/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=18697241&amp;postID=6303180132145261212' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18697241/posts/default/6303180132145261212'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18697241/posts/default/6303180132145261212'/><link rel='alternate' type='text/html' href='http://www.darrellhawley.com/2009/10/note-to-self-12-lessons-learned-from.html' title='Note to Self 12 – Lessons Learned from Our Latest Project'/><author><name>Darrell Hawley</name><uri>http://www.blogger.com/profile/13626445665115916691</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='03881874778058834600'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18697241.post-7507295957577662230</id><published>2009-09-10T15:17:00.001-07:00</published><updated>2009-09-10T15:17:44.273-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='IronPython'/><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>Does IronPython need LINQ?</title><content type='html'>&lt;p&gt;Before I get started, I think I need to clear up some misconceptions that the Python community might have about LINQ. From the posts I’ve read, Python developers have dismissed LINQ as only a series of language enhancements that allow for SQL-like querying of lists. Though it is true that both C# and VB.NET have made changes to their respective languages for working with lists, you can still use LINQ without the aforementioned language enhancements. Python developers would be better served to think of LINQ as wrappers around the map, filter and reduce functions. In fact, LINQ is not much different than the “recipes” found in the &lt;a href="http://docs.python.org/library/itertools.html#recipes"&gt;official itertools documentation&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;So the question still stands: does IronPython need LINQ? In my &lt;a href="http://srtsolutions.com/blogs/darrellhawley/archive/2009/08/15/ironpython-and-linq-a-devlink-correction.aspx"&gt;last post&lt;/a&gt;, I described how to use LINQ from an &lt;a href="http://www.codeplex.com/IronPython"&gt;IronPython&lt;/a&gt; application and implied that I didn’t think it was the best idea. Don’t get me wrong, I really enjoy writing LINQ statements, I just don’t think LINQ fits well with IronPython. Why not? The first problem I have with the IronPython/LINQ combination is put on prominent display in this code sample.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;print Enumerable.Average[object](      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; list, Func[object, int](lambda x:x))&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;If you are a static language aficionado, you probably are wondering what the problem is. If you’re a Python developer, however, the fact that I’m explicitly naming the “object” and “int” types is sending up giant, red flags. Python folks don’t really care what type of object it is they’re using, they only want to know what the object can do and what it contains (i.e., duck-typing). It’s much easier – and more readable - to simply write a completely Python version of the Average function. Consider the following chunk of LINQ code from C#:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;List&amp;lt;string&amp;gt; values = new List&amp;lt;string&amp;gt;(&amp;quot;the quick brown fox jumped over the lazy dogs&amp;quot;.Split());&lt;/p&gt;    &lt;p&gt;double avgLengthOfLongWords = values      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; .Select(x =&amp;gt; x.Length)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; .Where(x =&amp;gt; x &amp;gt; 3)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; .Average();&lt;/p&gt;    &lt;p&gt;Console.WriteLine(avgLengthOfLongWords)&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;To convert that to IronPython, we’d be forced to write something like the following:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;import clr      &lt;br /&gt;clr.AddReferenceToFileAndPath(&amp;quot;c:\users\darrell\desktop\System.Core.dll&amp;quot;) &lt;/p&gt;    &lt;p&gt;import System.Linq      &lt;br /&gt;from System import Func       &lt;br /&gt;from System.Linq import Enumerable &lt;/p&gt;    &lt;p&gt;stuff = &amp;quot;the quick brown fox jumped over the lazy dogs&amp;quot;.split() &lt;/p&gt;    &lt;p&gt;def Select(col, func):      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; return Enumerable.Select[object, object](col, Func[object, object](func))       &lt;br /&gt;def Where(col, func):       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; return Enumerable.Where[object](col, Func[object, bool](func))       &lt;br /&gt;def Average(col):       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; return Enumerable.Average[object](       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; col, Func[object, float](lambda x:x)) &lt;/p&gt;    &lt;p&gt;avgLengthOfLongWords = Average(Where(Select(stuff, lambda x:len(x)), lambda x:x &amp;gt; 3))      &lt;br /&gt;print avgLengthOfLongWords&lt;/p&gt;    &lt;p&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Before I’m even able to write useable code, I need to add a reference to a dll, import a namespace and a couple of classes and then write some helper functions; all so that I can write LINQ statements without the benefits of chaining. That’s right – I have to nest my LINQ statements. No chaining. That’s because when we use IronPython, the &lt;em&gt;Select&lt;/em&gt; and &lt;em&gt;Where&lt;/em&gt; don’t return an IEnumerable or an IQueryable. Instead they returna WhereSelectEnumerableIterator.&lt;/p&gt;  &lt;p&gt;But do you know what &lt;em&gt;&lt;strong&gt;really&lt;/strong&gt;&lt;/em&gt; rankles me about using LINQ in IronPython? It contributes absolutely nothing to the Python community. The only way you can use LINQ is if you are using IronPython, not CPython, not Jython. I want to engage the entire Python community, not just my corner of the world. If ever there was a case where implementing the principle trumps migrating the implementation, this is it.&lt;/p&gt;  &lt;p&gt;Enter the itertools module. Itertools is a Python standard library module containing tools for working with iterators. It also will serve as the cornerstone for my implementation of LINQ. When you visit the official itertools documentation at python.org, you’re even presented with code “recipes” that could be described as LINQ-ish. The only problem is that the recipes only accomodate nesting of statements. Why is this a problem? Consider the differences in readability between &lt;em&gt;nested&lt;/em&gt; and &lt;em&gt;chained&lt;/em&gt; in the following example:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;stuff = &amp;quot;the quick brown fox jumped over the lazy dogs&amp;quot;.split() &lt;/p&gt;    &lt;p&gt;getLength = lambda x:len(x)      &lt;br /&gt;isNotTooLong = lambda x:x&amp;lt;6       &lt;br /&gt;isNotTooShort = lambda x:x&amp;gt;3 &lt;/p&gt;    &lt;p&gt;nested = ifilter(isNotTooShort, ifilter(isNotTooLong, imap(getLength, stuff))) &lt;/p&gt;    &lt;p&gt;chained = IterHelper(stuff).select(getLength).where(isNotTooLong).where(isNotTooShort)&lt;/p&gt;    &lt;p&gt;&lt;/p&gt;    &lt;p&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;As always is the case with nesting methods, you have to read the statement populating &lt;em&gt;nested&lt;/em&gt; backwards. That is, the outermost function call is the last to be run and you work your way inwards from there to find the origin. This is not a big deal to most of us since this is something we had to get used to very early in our careers. But when you compare that to the statement populating &lt;em&gt;chained&lt;/em&gt;, I know I can read it from left to right. My eyes aren’t jumping back and forth to understand what is happening in what should be a relatively simple statement.&lt;/p&gt;  &lt;p&gt;So what does IterHelper look like?&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;class IterHelper(object):      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; def __init__(self, someIterable):       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; self.someIterable = someIterable       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; def __iter__(self):       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return self.someIterable       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; def next(self):       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return self.someIterable.next()       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; def select(self, func):       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return IterHelper(itertools.imap(func, self.someIterable))       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; def where(self, predicate):       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return IterHelper(itertools.ifilter(predicate, self.someIterable))&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;This extremely simplistic version of IterHelper is really only a wrapper around functions found in the itertools module. This is great news since any application written using Python 2.3 or later can make use of this pattern with little effort. There’s no special libraries AND everyone is invited regardless of your flavor of Python.&lt;/p&gt;  &lt;p&gt;My plan is to release IterHelper as an open source project by sometime by mid-October. I have a well-tested, basic implementation now, but I still have questions regarding licensing, hosting and deployment. I will be doing a bit of research on these topics and be posting what I’ve learned in my Notes to Self series.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18697241-7507295957577662230?l=www.darrellhawley.com%2Fdefault.html' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/18697241/7507295957577662230/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=18697241&amp;postID=7507295957577662230' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18697241/posts/default/7507295957577662230'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18697241/posts/default/7507295957577662230'/><link rel='alternate' type='text/html' href='http://www.darrellhawley.com/2009/09/does-ironpython-need-linq.html' title='Does IronPython need LINQ?'/><author><name>Darrell Hawley</name><uri>http://www.blogger.com/profile/13626445665115916691</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='03881874778058834600'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18697241.post-5181194511299938609</id><published>2009-08-15T20:19:00.001-07:00</published><updated>2009-08-15T20:19:31.478-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='IronPython'/><category scheme='http://www.blogger.com/atom/ns#' term='LINQ'/><title type='text'>IronPython and LINQ: A Devlink Correction</title><content type='html'>&lt;p&gt;During my “Anatomy of an &lt;a href="http://www.codeplex.com/IronPython"&gt;IronPython&lt;/a&gt; Application” presentation at Devlink, I mistakenly said that LINQ can be consumed from IronPython easily. I said this because I was thinking that IronPython 2.6 was built using .NET 3.5 when in fact it’s built with .NET 2.0. Fortunately, if you want to use LINQ, you still can because .NET 3.5 is really .NET 2.0 plus extensions; you just have a bit of extra work to do. First on the todo list is to copy the System.Core.dll for 3.5 to some other location (I was able to get to it from it’s home in the c:\windows\assembly directory) and then use the “clr.AddReferenceToFileAndPath” in your IP code to gain access. Then, with a simple import of the Enumerable or Queryable type, you magically have access to LINQ.&lt;/p&gt;  &lt;p&gt;Still, the story doesn’t end there. You have to remember that IronPython does NOT support extension methods and since LINQ is pretty much a collection of extensions methods, there’s a problem. Why this design decision? Because in order to support extension methods, the IronPython team would have had to make changes to the core language which would have, of course, been rather un-Pythonic. This means that the code for consuming LINQ is going to be somewhat messy. The following snippet gives an example of consuming the Average function of the Enumerable object.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;clr.AddReferenceToFileAndPath(r&amp;quot;C:\folder\System.Core.dll&amp;quot;)      &lt;br /&gt;from System.Linq import Enumerable       &lt;br /&gt;from System import Func &lt;/p&gt;    &lt;p&gt;list = [1,2,3,4,5] &lt;/p&gt;    &lt;p&gt;print Enumerable.Average[object](     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; list, Func[object, int](lambda x:x))&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;I have a lot of concerns as soon as I see “object” and “int” in brackets. At this point I’m going to hold save those concerns until my next post. Instead I’m going to leave this as an example of consuming LINQ from IronPython.&lt;/p&gt;  &lt;p&gt;I should point out that &lt;a href="http://devhawk.net/"&gt;Harry Pierson&lt;/a&gt;’s post on &lt;a href="http://ironpython-urls.blogspot.com/2009/01/devhawk-ironpython-and-linq-to-xml.html"&gt;IronPython and Linq-to-XML&lt;/a&gt; really got me started on this topic. I also have to give a shout-out to &lt;a href="http://blogs.msdn.com/chrsmith/"&gt;Chris Smith&lt;/a&gt; who was kind enough to help me out and relay a couple of &lt;a href="http://www.codemash.org/"&gt;CodeMash&lt;/a&gt; stories at the same time.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18697241-5181194511299938609?l=www.darrellhawley.com%2Fdefault.html' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/18697241/5181194511299938609/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=18697241&amp;postID=5181194511299938609' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18697241/posts/default/5181194511299938609'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18697241/posts/default/5181194511299938609'/><link rel='alternate' type='text/html' href='http://www.darrellhawley.com/2009/08/ironpython-and-linq-devlink-correction.html' title='IronPython and LINQ: A Devlink Correction'/><author><name>Darrell Hawley</name><uri>http://www.blogger.com/profile/13626445665115916691</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='03881874778058834600'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18697241.post-2493173478879190796</id><published>2009-07-31T07:31:00.001-07:00</published><updated>2009-07-31T07:31:03.711-07:00</updated><title type='text'>Speaking at the Lansing Day of .NET on Saturday</title><content type='html'>&lt;p&gt;If you’re going to be at the &lt;a href="http://dodn.org"&gt;Lansing Day of .NET&lt;/a&gt; this Saturday, stop by and catch my Anatomy of an &lt;a href="http://www.codeplex.com/IronPython"&gt;IronPython&lt;/a&gt; Application presentation. I’ve completely rewritten the talk so if you’ve seen it before, this new version will be covering completely different topics including testing and mocking. I’ll also be giving away a copy of &lt;a href="http://www.ironpythoninaction.com/"&gt;IronPython in Action&lt;/a&gt;, courtesy of &lt;a href="http://www.manning.com/"&gt;Manning Publications&lt;/a&gt;, at the end of my talk.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18697241-2493173478879190796?l=www.darrellhawley.com%2Fdefault.html' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/18697241/2493173478879190796/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=18697241&amp;postID=2493173478879190796' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18697241/posts/default/2493173478879190796'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18697241/posts/default/2493173478879190796'/><link rel='alternate' type='text/html' href='http://www.darrellhawley.com/2009/07/speaking-at-lansing-day-of-net-on.html' title='Speaking at the Lansing Day of .NET on Saturday'/><author><name>Darrell Hawley</name><uri>http://www.blogger.com/profile/13626445665115916691</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='03881874778058834600'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18697241.post-4195417206354888929</id><published>2009-07-25T05:01:00.001-07:00</published><updated>2009-07-25T05:01:13.215-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='process'/><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Testing'/><category scheme='http://www.blogger.com/atom/ns#' term='IronPython'/><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>Note to Self 11 – Patterns in Python, Process is Everything, Selenium</title><content type='html'>&lt;ul&gt;   &lt;li&gt;While studying a particular portion of &lt;a href="http://www.ironpythoninaction.com/"&gt;IronPython in Action&lt;/a&gt;, I came across a footnote to a blog post entitled &lt;a href="http://www.suttoncourtenay.org.uk/duncan/accu/pythonpatterns.html"&gt;Patterns in Python&lt;/a&gt;. By the end of the post, I found myself mentally tweaking a lot of my code. Though quite old (the page was posted February of 2003), the content remains quite relevant. &lt;/li&gt;    &lt;li&gt;I’m fortunate to be working on a project where everyone involved is committed to being agile (note the lack of a capital “A”). We’ve done enough things right that the items I would do differently are very minor. With that said, the imbalance in hours spent by each team member seems to be causing a problem… &lt;/li&gt;    &lt;li&gt;Another interesting observation – the project that I feel very fortunate to be working on is not using the technology of my choice. It’s a Java project. In fact, almost every facet of the project requires some specific technology in which I almost know nothing, yet the development process makes the experience a joy. &lt;/li&gt;    &lt;li&gt;Configuring my Selenium tests to work with Selenium RC and IE8 has not been an easy task. Some things I learned along the way…      &lt;ul&gt;       &lt;li&gt;Easiest way to create a new Selenium test is to use the Selenium IDE plugin for FireFox. It records everything you click and do and allows you to convert the recording to C#, Java, Python, PHP or Ruby. From there, further customizations are a snap. &lt;/li&gt;        &lt;li&gt;Selenium RC allows you to run your Selenium tests in browsers other than FireFox, such as IE, Chrome and Safari. &lt;/li&gt;        &lt;li&gt;Before running your tests in one of these “other” browsers, you’ll need to start the Selenium Server. Selenium Server comes parceled with the Selenium RC download and can be started from the command line with “java -jar selenium-server.jar”. &lt;/li&gt;        &lt;li&gt;To run my Selenium tests with IE8, I had to use the *iexploreproxy option even though I’m not using a proxy. Otherwise I kept getting redirected to a phantom file supposedly hidden away in my user directory. &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt; &lt;/ul&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18697241-4195417206354888929?l=www.darrellhawley.com%2Fdefault.html' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/18697241/4195417206354888929/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=18697241&amp;postID=4195417206354888929' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18697241/posts/default/4195417206354888929'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18697241/posts/default/4195417206354888929'/><link rel='alternate' type='text/html' href='http://www.darrellhawley.com/2009/07/note-to-self-11-patterns-in-python.html' title='Note to Self 11 – Patterns in Python, Process is Everything, Selenium'/><author><name>Darrell Hawley</name><uri>http://www.blogger.com/profile/13626445665115916691</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='03881874778058834600'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18697241.post-1293937164517723018</id><published>2009-07-14T08:24:00.001-07:00</published><updated>2009-07-14T08:30:12.641-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='BookReview'/><category scheme='http://www.blogger.com/atom/ns#' term='IronPython'/><title type='text'>Book Review: IronPython in Action</title><content type='html'>&lt;p&gt;&lt;a href="http://www.ironpythoninaction.com/"&gt;IronPython in Action&lt;/a&gt; (&lt;a href="http://www.ironpythoninaction.com/"&gt;IPIA&lt;/a&gt;) gets the distinction of being the first book published on &lt;a href="http://www.codeplex.com/IronPython"&gt;IronPython&lt;/a&gt;. As the first book, it has the responsibility of giving developers their first impression of &lt;a href="http://www.codeplex.com/IronPython"&gt;IronPython&lt;/a&gt;. &lt;a href="http://www.ironpythoninaction.com/"&gt;IPIA&lt;/a&gt; does exactly that by taking numerous shallow dives into various technologies and techniques. To be clear, this book is aimed at professional developers preferably with either .NET or Python experience. Pythonistas will find the book offers quick introductions to a number of Microsoft technologies such as Windows Forms, WPF and ASP.NET. .NET developers will get the chance to see technologies they’re already familiar with expressed in a completely new fashion.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.ironpythoninaction.com/"&gt;IPIA&lt;/a&gt; avoids the trap of simply being a brochure of Microsoft technologies using “&lt;a href="http://www.codeplex.com/IronPython"&gt;IronPython&lt;/a&gt;” in place of “C#” and “VB.NET”. Instead, the authors mix in chapters on development techniques ranging from the familiar - such as unit testing and mocking – to the more exotic such as metaprogramming. As .NET developers wind their way through the book, they’ll begin to appreciate the differences between the static and dynamic worlds – a crucial step toward wide ranging acceptance. &lt;/p&gt;  &lt;p&gt;If you’re curious about what &lt;a href="http://www.codeplex.com/IronPython"&gt;IronPython&lt;/a&gt; can do for you, &lt;a href="http://www.ironpythoninaction.com/"&gt;IronPython in Action&lt;/a&gt; is well worth your time.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18697241-1293937164517723018?l=www.darrellhawley.com%2Fdefault.html' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/18697241/1293937164517723018/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=18697241&amp;postID=1293937164517723018' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18697241/posts/default/1293937164517723018'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18697241/posts/default/1293937164517723018'/><link rel='alternate' type='text/html' href='http://www.darrellhawley.com/2009/07/book-review-ironpython-in-action.html' title='Book Review: IronPython in Action'/><author><name>Darrell Hawley</name><uri>http://www.blogger.com/profile/13626445665115916691</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='03881874778058834600'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18697241.post-7690627568813053910</id><published>2009-06-28T09:01:00.001-07:00</published><updated>2009-06-30T18:32:36.613-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='jQuery'/><title type='text'>Note to Self 10 – JQuery Selectors and Custom Functions and a thought on JQuery</title><content type='html'>&lt;p&gt;After using &lt;a href="http://www.python.org"&gt;Python&lt;/a&gt;, diving into &lt;a href="http://jquery.com/"&gt;jQuery&lt;/a&gt; has proven exceptionally difficult. Even though it solves the not-so-small problem of commonizing the DOM across multiple browsers, I find it very difficult to read. I know with time I’ll get used to it and maybe even find some beauty in my jQuery code, but it will never stop me from wishing for a cleaner syntax like that of Python or &lt;a href="http://www.ruby-lang.org/en/"&gt;Ruby&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;With that said, here’s a bit of what I learned about jQuery recently.&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Selectors in jQuery are a syntax for selecting an html element. Selectors can return a single element or several (or none if nothing matching is found). &lt;/li&gt;    &lt;li&gt;$(“#[elementID]”) – finds an element with an &lt;em&gt;id&lt;/em&gt; attribute equal to “elementID”. &lt;/li&gt;    &lt;li&gt;$(“[name=’elementName’]”) – gets all elements with a &lt;em&gt;name&lt;/em&gt; attribute equal to “&lt;em&gt;elementName”&lt;/em&gt; &lt;/li&gt;    &lt;li&gt;$(“[name^=’element’]”) – gets all elements with a &lt;em&gt;name&lt;/em&gt; attribute that begins with “&lt;em&gt;element”&lt;/em&gt; &lt;/li&gt;    &lt;li&gt;$(“[name$=’Name’]”) – gets all elements with a &lt;em&gt;name&lt;/em&gt; attribute that ends with “&lt;em&gt;Name”&lt;/em&gt; &lt;/li&gt;    &lt;li&gt;$(“input:checkbox”) – gets all checkboxes &lt;/li&gt;    &lt;li&gt;$(“#blah &amp;gt; input:checkbox”) – gets all checkboxes within a parent element of id &lt;em&gt;“blah”&lt;/em&gt; &lt;/li&gt;    &lt;li&gt;Creating a custom function in jQuery: &lt;/li&gt; &lt;/ul&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;strike&gt;$.fn.CustomFunctionName({function()({        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; //code here         &lt;br /&gt;})&lt;/strike&gt;&lt;/p&gt;    &lt;p&gt;&lt;font color="#ff0000"&gt;$.fn.exclaim = function(message){       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; alert(message)        &lt;br /&gt;}        &lt;br /&gt;$.fn.exclaim(&amp;quot;hello, world&amp;quot;)&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18697241-7690627568813053910?l=www.darrellhawley.com%2Fdefault.html' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/18697241/7690627568813053910/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=18697241&amp;postID=7690627568813053910' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18697241/posts/default/7690627568813053910'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18697241/posts/default/7690627568813053910'/><link rel='alternate' type='text/html' href='http://www.darrellhawley.com/2009/06/note-to-self-10-jquery-selectors-and_28.html' title='Note to Self 10 – JQuery Selectors and Custom Functions and a thought on JQuery'/><author><name>Darrell Hawley</name><uri>http://www.blogger.com/profile/13626445665115916691</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='03881874778058834600'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18697241.post-4175159309556728108</id><published>2009-05-29T07:05:00.001-07:00</published><updated>2009-05-29T07:05:29.665-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='SharpDevelop'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><category scheme='http://www.blogger.com/atom/ns#' term='IronPython'/><title type='text'>Note to Self 9 – Exploring SharpDevelop and Going off Topic</title><content type='html'>&lt;p&gt;It’s been too long since I last blogged which typically means I have too many competing ideas to settle on just one. So welcome to Note to Self 9!&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://icsharpcode.net/OpenSource/SD/Default.aspx"&gt;SharpDevelop&lt;/a&gt; is an open source IDE for the .NET platform. Is it new? Hardly. Based on the &lt;a href="http://icsharpcode.net/OpenSource/SD/NewsHistory.aspx"&gt;history of news releases&lt;/a&gt; from their website, It’s been around since December of 2000. Considering that the .NET platform was publicly announced only 6 months earlier, SharpDevelop seems only that much more mature.&lt;/li&gt;    &lt;li&gt;If you’re comfortable with the basics of Visual Studio, SharpDevelop should feel like home to you. In fact, the best way to describe SharpDevelop is “Visual Studio without a lot of stuff I don’t want and a few thid-party items I do”.&lt;/li&gt;    &lt;li&gt;SharpDevelop uses NUnit instead of MSTest. That’s right. No third party plugins to make your IDE work with NUnit. It simply works.&lt;/li&gt;    &lt;li&gt;It’s time for me to confess. It’s all about IronPython. The reason I started investigating SharpDevelop is because of my frustration with Visual Studio’s lack of support for the language. Specifically, I want Intellisense when I write IronPython. To be sure, you only get Intellisense for “non-DLR code”, but surprisingly that doesn’t seem to be as much of a handicap as you might think.&lt;/li&gt;    &lt;li&gt;Speaking of first class citizens, SharpDevelop comes stock with C#, Visual Basic, Boo (I can hear Jay Wren cheering now), IronPython and F# (now a number of SRT folks are cheering).&lt;/li&gt;    &lt;li&gt;If you’re frightened of the consequences that may come from changing your development environment, don’t be. You can open one of your existing Visual Studio solutions with SharpDevelop and start coding. Switching back is as simple as opening up your now modified project/solution in Visual Studio.&lt;/li&gt;    &lt;li&gt;For clarity, SharpDevelop is new to me. I haven’t used SharpDevelop for any projects yet so I can’t tell you about any of its nuances. I plan on putting it to the test, however, over the next several weeks. I’ll be posting about my experiences.&lt;/li&gt;    &lt;li&gt;Now for the off-topic part. I’ve been listening to &lt;a href="http://thehistoryofrome.typepad.com/"&gt;The History of Rome&lt;/a&gt;, a FANTASTIC podcast series on, well, the history of Rome. Mike Duncan, creator and narrator, is not only an engaging story teller, but also has the technical savvy to put together a professional podcast. Though it’s not the sort of podcast typically on a geek’s menu, I think there are enough parallels to some of the challenges we are facing in the software industry to make it worthwhile.&lt;/li&gt; &lt;/ul&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18697241-4175159309556728108?l=www.darrellhawley.com%2Fdefault.html' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/18697241/4175159309556728108/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=18697241&amp;postID=4175159309556728108' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18697241/posts/default/4175159309556728108'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18697241/posts/default/4175159309556728108'/><link rel='alternate' type='text/html' href='http://www.darrellhawley.com/2009/05/note-to-self-9-exploring-sharpdevelop.html' title='Note to Self 9 – Exploring SharpDevelop and Going off Topic'/><author><name>Darrell Hawley</name><uri>http://www.blogger.com/profile/13626445665115916691</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='03881874778058834600'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18697241.post-5933719459525401431</id><published>2009-04-07T20:00:00.001-07:00</published><updated>2009-04-07T20:00:35.184-07:00</updated><title type='text'>Anatomy of an IronPython Application at AADND</title><content type='html'>&lt;p&gt;I'm going to be talking IronPython at the &lt;a href="http://www.aadnd.org" target="_blank"&gt;Ann Arbor .NET Developers Group&lt;/a&gt; at &lt;a href="http://srtsolutions.com/" target="_blank"&gt;SRT Solutions&lt;/a&gt; tomorrow night (April 8) at 6:00. I'll be showing you how you might introduce IronPython into your existing .NET environment through a lot of sample code and very few PowerPoint slides. I hope to see you there.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Anatomy of an IronPython Application&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;em&gt;You've heard about IronPython and maybe have even taken the time to write the obligatory &amp;quot;Hello, World&amp;quot; application. Now what? The buzz around IronPython continues but there's still little guidance on tools and development processes.&amp;#160; This presentation focuses on the basics of interacting with C# and VB.NET libraries using IronPython while introducing useful tools and techniques to get you started. Though experience with .NET is necessary, the samples and discussions are understandable to even beginning Python developers.&lt;/em&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18697241-5933719459525401431?l=www.darrellhawley.com%2Fdefault.html' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/18697241/5933719459525401431/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=18697241&amp;postID=5933719459525401431' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18697241/posts/default/5933719459525401431'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18697241/posts/default/5933719459525401431'/><link rel='alternate' type='text/html' href='http://www.darrellhawley.com/2009/04/anatomy-of-ironpython-application-at.html' title='Anatomy of an IronPython Application at AADND'/><author><name>Darrell Hawley</name><uri>http://www.blogger.com/profile/13626445665115916691</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='03881874778058834600'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18697241.post-8027568377207805970</id><published>2009-03-15T06:19:00.001-07:00</published><updated>2009-03-15T06:19:18.921-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='IronPython'/><category scheme='http://www.blogger.com/atom/ns#' term='WCF'/><title type='text'>Writing an IronPython WCF Host</title><content type='html'>&lt;p&gt;This is a simple WCF host written in IronPython that consumes a library I wrote in C#.&lt;/p&gt;  &lt;p&gt;import clr   &lt;br /&gt;clr.AddReferenceByPartialName(&amp;quot;System.ServiceModel&amp;quot;)    &lt;br /&gt;clr.AddReferenceByPartialName(&amp;quot;CSharpClass&amp;quot;) &lt;/p&gt;  &lt;p&gt;from System.ServiceModel import ServiceHost, BasicHttpBinding   &lt;br /&gt;from System.ServiceModel.Description import ServiceMetadataBehavior    &lt;br /&gt;from CSharpClass import PersonService, IPersonService    &lt;br /&gt;from System import Array, Uri &lt;/p&gt;  &lt;p&gt;uri = Uri(&amp;quot;&lt;a href="http://localhost:1234/people")"&gt;http://localhost:1234/people&amp;quot;)&lt;/a&gt;    &lt;br /&gt;uriArray = Array[Uri]([uri]) # creates a generic array of type Uri    &lt;br /&gt;serviceHost = ServiceHost(PersonService, uriArray) &lt;/p&gt;  &lt;p&gt;binding = BasicHttpBinding() &lt;/p&gt;  &lt;p&gt;serviceHost.AddServiceEndpoint(IPersonService, binding, &amp;quot;&lt;a href="http://localhost:1234/people")"&gt;http://localhost:1234/people&amp;quot;)&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;behavior = ServiceMetadataBehavior()   &lt;br /&gt;behavior.HttpGetEnabled = True    &lt;br /&gt;serviceHost.Description.Behaviors.Add(behavior) &lt;/p&gt;  &lt;p&gt;serviceHost.Open() &lt;/p&gt;  &lt;p&gt;raw_input(&amp;quot;Service has been started. Press Enter to exit...&amp;quot;)&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18697241-8027568377207805970?l=www.darrellhawley.com%2Fdefault.html' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/18697241/8027568377207805970/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=18697241&amp;postID=8027568377207805970' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18697241/posts/default/8027568377207805970'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18697241/posts/default/8027568377207805970'/><link rel='alternate' type='text/html' href='http://www.darrellhawley.com/2009/03/writing-ironpython-wcf-host.html' title='Writing an IronPython WCF Host'/><author><name>Darrell Hawley</name><uri>http://www.blogger.com/profile/13626445665115916691</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='03881874778058834600'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18697241.post-8265670058660956714</id><published>2009-03-06T11:28:00.001-08:00</published><updated>2009-03-06T11:29:25.131-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='Testing'/><category scheme='http://www.blogger.com/atom/ns#' term='IronPython'/><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>Running nose with IronPython</title><content type='html'>&lt;p&gt;I just spent the past week at the 2009 Microsoft MVP Summit where I got a chance to talk to the some of the crew behind the dynamic languages at Microsoft. When I mentioned that I had gotten nose, a Python unit testing framework, working with IronPython, I was strongly encouraged to blog about it. Without further adieu, here's my code.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;import sys      &lt;br /&gt;sys.path.append(r&amp;quot;C:\Python25\Lib\site-packages\nose-0.10.4-py2.5.egg&amp;quot;)       &lt;br /&gt;sys.path.append(r&amp;quot;C:\python25\lib&amp;quot;)       &lt;br /&gt;sys.path.append(r&amp;quot;C:\Python25\Lib\email&amp;quot;)       &lt;br /&gt;sys.path.append(r&amp;quot;C:\Python25\Scripts&amp;quot;)       &lt;br /&gt;import nose       &lt;br /&gt;nose.main()&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;I dropped this script into a directory with a couple of bogus unit tests and ran it with Python 2.5.4. Results were consistent with my expectations - successful tests passed and failing tests threw exceptions. When I ran the same suite against IronPython 2.0.0, I still received the correct results but the script took 1 minute and 20 seconds to complete. Compare that to less than a second (estimated) for CPython. For the sake of completeness, I ran the same test with IronPython 2.0.1 and received the same result.&lt;/p&gt;  &lt;p&gt;The root of the problem appears to be the large number of GeneratorExitExceptions being thrown. I'm not sure why they're being thrown, but I'll continue to investigate and report my findings. If you're interested in the gory details, here's the stack trace of the first exception:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;at IronPython.Runtime.PythonGenerator.ThrowThrowable()      &lt;br /&gt;at IronPython.Runtime.PythonGenerator.CheckThrowable()       &lt;br /&gt;at IronPython.Runtime.PythonGenerator.       &lt;br /&gt;CheckThrowableAndReturnSendValue()       &lt;br /&gt;at IronPython.Runtime.Operations.PythonOps.       &lt;br /&gt;GeneratorCheckThrowableAndReturnSendValue(Object self)       &lt;br /&gt;at S$11.lambda_method$312(Closure , Int32&amp;amp; state, Object&amp;amp; current) in C:\python25\lib\types.py:line 52       &lt;br /&gt;at Microsoft.Scripting.Runtime.GeneratorEnumerator`1.       &lt;br /&gt;System.Collections.IEnumerator.MoveNext()       &lt;br /&gt;at IronPython.Runtime.PythonGenerator.MoveNextWorker()       &lt;br /&gt;at IronPython.Runtime.PythonGenerator.System.       &lt;br /&gt;Collections.IEnumerator.MoveNext()       &lt;br /&gt;at IronPython.Runtime.PythonGenerator.throw(Object type, Object value, Object traceback)       &lt;br /&gt;at IronPython.Runtime.PythonGenerator.throw(Object type)       &lt;br /&gt;at IronPython.Runtime.PythonGenerator.close()&lt;/p&gt;&lt;/blockquote&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18697241-8265670058660956714?l=www.darrellhawley.com%2Fdefault.html' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/18697241/8265670058660956714/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=18697241&amp;postID=8265670058660956714' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18697241/posts/default/8265670058660956714'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18697241/posts/default/8265670058660956714'/><link rel='alternate' type='text/html' href='http://www.darrellhawley.com/2009/03/running-nose-with-ironpython.html' title='Running nose with IronPython'/><author><name>Darrell Hawley</name><uri>http://www.blogger.com/profile/13626445665115916691</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='03881874778058834600'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18697241.post-9136387387445195503</id><published>2009-02-20T12:54:00.001-08:00</published><updated>2009-02-20T12:54:52.298-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='Hosting'/><category scheme='http://www.blogger.com/atom/ns#' term='IronPython'/><title type='text'>IronPython Exception: [A]Person cannot be cast to [B]Person</title><content type='html'>&lt;p&gt;Had an interesting problem while using the Hosting API the other day. Here's the exception message.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;[A]CSharpClass.Person cannot be cast to [B]CSharpClass.Person. Type A originates from 'CSharpClass, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' in the context 'LoadNeither' at location '[project directory]\bin\Debug\CSharpClass.dll'. Type B originates from 'CSharpClass, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' in the context 'Default' at location '[temp directory]\CSharpClass.DLL'.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;I was struggling with this for a while until I found this &lt;a href="http://www.nabble.com/Question-on-instantiating-a-.NET-class-in-Python-and-pass-the-instantiated-object-back-to-C--td21608470.html" target="_blank"&gt;link&lt;/a&gt;. In order to get my IronPython scripts to communicate with my CLR-based code, I was using the clr module's AddReference methods. These methods require you to point at the appropriate &lt;em&gt;copy&lt;/em&gt; of the library you want to consume. I do stress &amp;quot;&lt;em&gt;copy&lt;/em&gt;&amp;quot;. Let's say you point your IronPython script at the bin\debug folder of a C# library project you're consuming in a console application. When you run the application, you'll get the exception message above. To make this example work, you'd have to point your IronPython script at the bin\Debug folder of your console application instead. Clearly, this is a maintenance nightmare. Instead, insert the following chunk of code into your hosting application (in the example described above, your console application) to avoid the problem all together.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Assembly assembly = typeof (CSharpClass.Person).Assembly;     &lt;br /&gt;runtime.LoadAssembly(assembly);&lt;/p&gt;&lt;/blockquote&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18697241-9136387387445195503?l=www.darrellhawley.com%2Fdefault.html' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/18697241/9136387387445195503/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=18697241&amp;postID=9136387387445195503' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18697241/posts/default/9136387387445195503'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18697241/posts/default/9136387387445195503'/><link rel='alternate' type='text/html' href='http://www.darrellhawley.com/2009/02/ironpython-exception-aperson-cannot-be.html' title='IronPython Exception: [A]Person cannot be cast to [B]Person'/><author><name>Darrell Hawley</name><uri>http://www.blogger.com/profile/13626445665115916691</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='03881874778058834600'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18697241.post-4045338151122134543</id><published>2009-02-04T19:03:00.001-08:00</published><updated>2009-02-04T19:03:27.096-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='Hosting'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><category scheme='http://www.blogger.com/atom/ns#' term='IronPython'/><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>Note to Self 8 - IronPython2, Hosting, DLR</title><content type='html'>&lt;ul&gt;   &lt;li&gt;The latest DLR code and documentation can be found at &lt;a href="http://www.codeplex.com/dlr"&gt;www.codeplex.com/dlr&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;For the examples below, here is the Python script I'm using     &lt;br /&gt;&lt;/li&gt;    &lt;blockquote&gt;     &lt;p&gt;class Person(object):       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; def __init__(self, name, phone):        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; self.name = name        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; self.phone = phone        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; def TalkToCSharp(self):        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; val = {&amp;quot;name&amp;quot;:self.name, &amp;quot;phone&amp;quot;:self.phone}        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return val &lt;/p&gt;      &lt;p&gt;&amp;#160;&lt;/p&gt;      &lt;p&gt;def GetPerson():       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; person = Person(&amp;quot;darrell&amp;quot;, &amp;quot;555-4321&amp;quot;)        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; return person.TalkToCSharp()        &lt;br /&gt;&lt;/p&gt;      &lt;p&gt;def GetPersonWithParams(name, phone):       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; person = Person(name, phone)        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; return person.TalkToCSharp() &lt;/p&gt;      &lt;p&gt;theNumberFive = 5       &lt;br /&gt;myPerson = GetPerson()&lt;/p&gt;   &lt;/blockquote&gt;    &lt;li&gt;Simplest thing you can do is execute a Python script.     &lt;br /&gt;      &lt;br /&gt;&lt;/li&gt;    &lt;blockquote&gt;     &lt;p&gt;static void ExecutePythonScript(string path)       &lt;br /&gt;{        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; ScriptRuntime runtime = Python.CreateRuntime();        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; runtime.ExecuteFile(path);        &lt;br /&gt;}&lt;/p&gt;   &lt;/blockquote&gt;    &lt;li&gt;Sometimes you need to get a variable after a script has run.     &lt;br /&gt;&lt;/li&gt;    &lt;blockquote&gt;     &lt;p&gt;static void GetDoubleVariable(string path)       &lt;br /&gt;{        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; ScriptRuntime runtime = Python.CreateRuntime();        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; ScriptScope scope = runtime.ExecuteFile(path);        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; object x = scope.GetVariable(&amp;quot;theNumberFive&amp;quot;);        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Console.WriteLine(x);        &lt;br /&gt;}&lt;/p&gt;   &lt;/blockquote&gt;    &lt;li&gt;What happens if you're trying to return a custom class defined in the script? The easiest - and IMHO the best - way to go about this is to convert the object to a dictionary before passing it to your C# code.     &lt;br /&gt;&lt;/li&gt;    &lt;blockquote&gt;     &lt;p&gt;static void GetInstanceCustomClass(string path)       &lt;br /&gt;{        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; ScriptRuntime runtime = Python.CreateRuntime();        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; ScriptScope scope = runtime.ExecuteFile(path);        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; PythonDictionary dictionary =         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; scope.GetVariable(&amp;quot;myPerson&amp;quot;)         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; as PythonDictionary;        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; foreach (var property in dictionary)        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Console.WriteLine(property.Key +         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;quot; == &amp;quot; + property.Value);        &lt;br /&gt;}&lt;/p&gt;   &lt;/blockquote&gt;    &lt;li&gt;Getting properties is definitely useful, but you'll probably want to call a function.     &lt;br /&gt;&lt;/li&gt;    &lt;blockquote&gt;     &lt;p&gt;static void CallingAFunction(string path)       &lt;br /&gt;{        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; ScriptRuntime runtime = Python.CreateRuntime();        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; ScriptScope scope = runtime.ExecuteFile(path);        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; ObjectOperations op =         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; scope.Engine.CreateOperations();        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; ObjectHandle handle =         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; scope.GetVariableHandle(&amp;quot;GetPerson&amp;quot;);        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; var x = op.Call(handle, new object[0]);        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; PythonDictionary dictionary =         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; x.Unwrap() as PythonDictionary;        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; foreach (var property in dictionary)        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Console.WriteLine(property.Key +        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;quot; == &amp;quot; + property.Value);        &lt;br /&gt;}&lt;/p&gt;   &lt;/blockquote&gt;    &lt;li&gt;Here's an example of passing parameters to a Python function.     &lt;br /&gt;&lt;/li&gt;    &lt;blockquote&gt;     &lt;p&gt;static void CallingAFunctionWithParameters(string path)       &lt;br /&gt;{        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; ScriptRuntime runtime = Python.CreateRuntime();        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; ScriptScope scope = runtime.ExecuteFile(path);        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; ObjectOperations op =         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; scope.Engine.CreateOperations();        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; ObjectHandle handle =         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; scope.GetVariableHandle(&amp;quot;GetPersonWithParams&amp;quot;);        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; var x = op.Call(handle, &amp;quot;Larry&amp;quot;, &amp;quot;555-1234&amp;quot;);        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; PythonDictionary dictionary =        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; x.Unwrap() as PythonDictionary;        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; foreach (var property in dictionary)        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Console.WriteLine(property.Key +        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;quot; == &amp;quot; + property.Value);        &lt;br /&gt;}        &lt;br /&gt;&lt;/p&gt;   &lt;/blockquote&gt; &lt;/ul&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18697241-4045338151122134543?l=www.darrellhawley.com%2Fdefault.html' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/18697241/4045338151122134543/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=18697241&amp;postID=4045338151122134543' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18697241/posts/default/4045338151122134543'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18697241/posts/default/4045338151122134543'/><link rel='alternate' type='text/html' href='http://www.darrellhawley.com/2009/02/note-to-self-8-ironpython2-hosting-dlr.html' title='Note to Self 8 - IronPython2, Hosting, DLR'/><author><name>Darrell Hawley</name><uri>http://www.blogger.com/profile/13626445665115916691</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='03881874778058834600'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18697241.post-716965728420404397</id><published>2009-01-29T08:14:00.001-08:00</published><updated>2009-02-01T06:37:01.747-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='SciTE'/><category scheme='http://www.blogger.com/atom/ns#' term='IronPython'/><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>Note to Self 7 - Naming Python Modules, SciTE, IronPython and __name__</title><content type='html'>&lt;ul&gt;   &lt;li&gt;Be careful naming your Python modules. If you name a Python file the same as an existing file in your Python install directory, you may get the following exception message: &lt;em&gt;&amp;quot;'module' object has no attribute '[some-attribute-name]'&amp;quot;&lt;/em&gt;. &lt;/li&gt;    &lt;li&gt;I'm really loving SciTE. It's a dead simple code editor that offers syntax highlighting for an impressive number of languages and displays the results of the run in it's own output window. &lt;/li&gt;    &lt;li&gt;More SciTE: If you decide to use SciTE, you'll probably want to customize how it works. Here's a nice &lt;a href="http://novicenotes.com/software/scite-quick-reference/" target="_blank"&gt;quick reference&lt;/a&gt; to supplement the &lt;a href="http://www.scintilla.org/SciTEDoc.html" target="_blank"&gt;SciTE documentation&lt;/a&gt; to help guide you through the config files. &lt;/li&gt;    &lt;li&gt;If you want to use SciTE as your IronPython editor, you'll need to modify the existing python.properties file. Select &amp;quot;Open python.properties&amp;quot; from the &amp;quot;Options&amp;quot; menu. Search for &amp;quot;command.go&amp;quot; and modify the value so that it points at your IronPython directory. &lt;/li&gt;    &lt;li&gt;All Python modules have a special variable called &amp;quot;__name__&amp;quot;. When the code in your module is executed with CPython, __name__ is set to the file name of your module minus the &amp;quot;py&amp;quot; extension (&amp;quot;mymodule&amp;quot; if the file name of your module is &amp;quot;mymodule.py&amp;quot;, for example), except when the module is executed directly. If that's the case, __name__ is equal to &amp;quot;__main__&amp;quot;. Unfortunately, this is not the case if you execute it with IronPython. The special variable __name__ will always be based on the file name. &lt;em&gt;UPDATE: The above is true only when you compile your IronPython code. If you launch a *.py file with ipy.exe, the __name__ variable will be &amp;quot;__main__&amp;quot;.&lt;/em&gt;&lt;/li&gt; &lt;/ul&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18697241-716965728420404397?l=www.darrellhawley.com%2Fdefault.html' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/18697241/716965728420404397/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=18697241&amp;postID=716965728420404397' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18697241/posts/default/716965728420404397'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18697241/posts/default/716965728420404397'/><link rel='alternate' type='text/html' href='http://www.darrellhawley.com/2009/01/note-to-self-7-naming-python-modules.html' title='Note to Self 7 - Naming Python Modules, SciTE, IronPython and __name__'/><author><name>Darrell Hawley</name><uri>http://www.blogger.com/profile/13626445665115916691</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='03881874778058834600'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18697241.post-7083510773503905421</id><published>2009-01-19T20:09:00.001-08:00</published><updated>2009-01-19T20:09:24.851-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='IronPython'/><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>Note to Self 6 - IronPython, pyc.py and SciTE</title><content type='html'>&lt;ul&gt;   &lt;li&gt;The pyc.py file can compile you IronPython code into .NET executables. &lt;/li&gt;    &lt;li&gt;The pyc.py file is part of the sample code released with IronPython. It can be found &lt;a href="http://www.codeplex.com/IronPython/Release/ProjectReleases.aspx?ReleaseId=8365" target="_blank"&gt;here&lt;/a&gt;. Look for the &amp;quot;IronPython-2.0-Samples.zip&amp;quot; link. &lt;/li&gt;    &lt;li&gt;Typing out &amp;quot;[IP directory]\ipy [code directory]pyc.py&amp;quot; explicitly everytime you want to use the tool is somewhat annoying. Consider creating a script to do this for you. Here's a simple batch file.      &lt;br /&gt;      &lt;br /&gt;      &lt;blockquote&gt;cd C:\data\FeClass        &lt;br /&gt;c:\fepython\ipy.exe pyc.py class.py /main:main.py &lt;/blockquote&gt;      &lt;br /&gt;Note that you'll have to copy the pyc.py file to the same directory as your code for this to work. &lt;/li&gt;    &lt;li&gt;IronPython Studio just isn't up to snuff. You're better off to use a text editor and a build script &lt;/li&gt;    &lt;li&gt;I like SciTE as my IronPython editor even more so than Notepad++. I really like that I can run my Python or IronPython script from SciTE and the output the normally would be displayed in the command window is captured in SciTE. &lt;/li&gt; &lt;/ul&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18697241-7083510773503905421?l=www.darrellhawley.com%2Fdefault.html' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/18697241/7083510773503905421/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=18697241&amp;postID=7083510773503905421' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18697241/posts/default/7083510773503905421'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18697241/posts/default/7083510773503905421'/><link rel='alternate' type='text/html' href='http://www.darrellhawley.com/2009/01/note-to-self-6-ironpython-pycpy-and.html' title='Note to Self 6 - IronPython, pyc.py and SciTE'/><author><name>Darrell Hawley</name><uri>http://www.blogger.com/profile/13626445665115916691</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='03881874778058834600'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18697241.post-5803143768554273096</id><published>2009-01-11T20:25:00.001-08:00</published><updated>2009-01-11T20:25:54.344-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL Alchemy'/><title type='text'>SQL Alchemy ORM Basics</title><content type='html'>&lt;p&gt;In my previous post, &lt;a href="http://www.darrellhawley.com/2009/01/learning-sql-alchemy.html" target="_blank"&gt;Learning SQL Alchemy&lt;/a&gt;, I focused on the SQL-like aspect of SQL Alchemy. You'll need to review the sample code in that post before understanding the code below. On with the code.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;class User(object): pass      &lt;br /&gt;mapper(User, user_table)&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Believe it or not, we just created a class with an ID, Name and Password. Simply create an empty class and pass it to the the mapper along with the user_table we had created. How do we use it? First off we have to create a Session object. Note that when we call the sessionmaker, it returns a Session class which you use to create the session.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Session = sqlalchemy.orm.sessionmaker()      &lt;br /&gt;session = Session()&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;All have we to do now is create a new User object, set the appropriate fields and pass it to the &amp;quot;save&amp;quot; method.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;user = User()      &lt;br /&gt;user.name = &amp;quot;Fred Flintstone&amp;quot;       &lt;br /&gt;user.password = &amp;quot;yaba daba doo&amp;quot;       &lt;br /&gt;session.save(user)&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;But how do we get our user back from the database?&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;query = session.query(User)&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;We can now iterate through the query like any list.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;for user in query:      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; print user.id, user.name, user.password&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;You can see the new record we inserted along with the other records in the table.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;2 angie password2      &lt;br /&gt;3 nate awesomeness       &lt;br /&gt;4 Fred Flintstone yaba daba doo&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;The important thing to note is that the query object is actually a list of the very same User type I defined at the beginning of this post. Of course we probably don't want everything in the table, so here's an example of getting back a single object.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;for user in query.filter_by(name = &amp;quot;angie&amp;quot;):      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; print user.id, user.name, user.password&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;The result is just what we would expect.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;2 angie password2&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;But let's say I want to change Angie's password.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;user.password = &amp;quot;a much more secure passphrase&amp;quot; &lt;/p&gt;    &lt;p&gt;for user in query.filter_by(name = &amp;quot;angie&amp;quot;):     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; print user.id, user.name, user.password&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;The result?&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;2 angie a much more secure passphrase&lt;/p&gt;&lt;/blockquote&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18697241-5803143768554273096?l=www.darrellhawley.com%2Fdefault.html' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/18697241/5803143768554273096/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=18697241&amp;postID=5803143768554273096' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18697241/posts/default/5803143768554273096'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18697241/posts/default/5803143768554273096'/><link rel='alternate' type='text/html' href='http://www.darrellhawley.com/2009/01/sql-alchemy-orm-basics.html' title='SQL Alchemy ORM Basics'/><author><name>Darrell Hawley</name><uri>http://www.blogger.com/profile/13626445665115916691</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='03881874778058834600'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18697241.post-3340216019905635562</id><published>2009-01-07T17:58:00.001-08:00</published><updated>2009-01-07T18:00:30.797-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL Alchemy'/><title type='text'>Learning SQL Alchemy</title><content type='html'>&lt;p&gt;I spent a portion of my holidays studying the basics of SQL Alchemy. My first lesson is that SQL Alchemy is NOT an ORM for Python but instead a SQL abstraction tool with an ORM built-into it. At first I was having trouble understanding what this really meant, but after seeing an example it sunk in. Let's start by building a table.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;from sqlalchemy import&amp;#160; Table, Column, Integer, String&lt;/p&gt;    &lt;p&gt;meta = sqlalchemy.MetaData(&amp;quot;sqlite:///&amp;quot;) &lt;/p&gt;    &lt;p&gt;user_table = Table('userTable', meta,      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Column('id', Integer, primary_key=True),       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Column('name', String, unique=True, nullable=False),       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Column('password', String, nullable=False)) &lt;/p&gt;    &lt;p&gt;meta.create_all()&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;First thing we need is a MetaData object which holds all of our database schema information as well as our engine for executing queries. By passing &amp;quot;sqlite:///&amp;quot; in the MetData constructor we create an engine pointing at an in-memory SQLite database. To create a table, we just declare an instance of the Table object and pass in the necessary parameters: table name, our MetData instance and whatever columns we need in the table. The constructor for the Column class not only takes the column name and type, but constraints as well. Then all we have to do is execute the statement by using the create_all() method of the MetaData class.&lt;/p&gt;  &lt;p&gt;Did you note the user_table variable we created? That comes in really handy when we want to start manipulating our new table.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;insert = user_table.insert()      &lt;br /&gt;insert.execute(name='darrell', password='password1')       &lt;br /&gt;insert.execute(name='angie', password='password2')       &lt;br /&gt;insert.execute(name='nate', password='password3')       &lt;br /&gt;insert.execute(name='drew', password='password4')&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;See how easy inserting data is? There are methods just like the insert method above for select, insert and delete. Let's take a look at the select method.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;select = user_table.select()      &lt;br /&gt;results = select.execute() &lt;/p&gt;    &lt;p&gt;for row in results:      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; print row.name, row.password&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;The result are just as you would expect.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;darrell password1      &lt;br /&gt;angie password2       &lt;br /&gt;nate password3       &lt;br /&gt;drew password4&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;That's great, but how do we change Nate's password and then return only his record?&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;update = user_table.update(user_table.c.name=='nate')      &lt;br /&gt;update.execute(password='awesomeness') &lt;/p&gt;    &lt;p&gt;select = user_table.select(user_table.c.name=='nate')      &lt;br /&gt;results = select.execute() &lt;/p&gt;    &lt;p&gt;for row in results:      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; print row.name, row.password&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;It's very simple and readable code with one caveat: what is &amp;quot;user_table.c.name&amp;quot;? It's a convenience attribute containing a collection of all the columns in userTable. So what our update statement is saying in terms of SQL is &amp;quot;UPDATE userTable SET ????? WHERE name = 'nate'&amp;quot;. The only thing we don't know at this point is what to change. That happens when we execute the statement on the next line. If you understand the update statement above, the select statement works exactly the same way. Our result is below.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;nate awesomeness&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;We've seen select, update and insert, but what about delete?&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;delete = user_table.delete(user_table.c.name.like(&amp;quot;d%&amp;quot;))     &lt;br /&gt;delete.execute()      &lt;br /&gt;select = user_table.select()      &lt;br /&gt;results = select.execute()&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;I couldn't help myself - I &lt;em&gt;had&lt;/em&gt; to confuse the issue by using &amp;quot;LIKE&amp;quot;. In my defense, now you know how to introduce a &amp;quot;LIKE&amp;quot; comparison into your code AND that the &amp;quot;c&amp;quot; attribute is more than just a collection of strings. Beyond that, the delete works exactly the way you would expect it to work: call the delete method by passing the constraining expression as a parameter and then execute the result.&lt;/p&gt;  &lt;p&gt;Now I understand why SQL Alchemy is an SQL abstration tool. All I did in the examples above were execute very basic SQL statements; the ORM was never used. Why is this so powerful? Imagine being able to write the same code for a SQL Server database as you did for a MySQL server and having the confidence that it's going to work. That's the power of SQL Alchemy.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18697241-3340216019905635562?l=www.darrellhawley.com%2Fdefault.html' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/18697241/3340216019905635562/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=18697241&amp;postID=3340216019905635562' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18697241/posts/default/3340216019905635562'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18697241/posts/default/3340216019905635562'/><link rel='alternate' type='text/html' href='http://www.darrellhawley.com/2009/01/learning-sql-alchemy.html' title='Learning SQL Alchemy'/><author><name>Darrell Hawley</name><uri>http://www.blogger.com/profile/13626445665115916691</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='03881874778058834600'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18697241.post-261405553121119225</id><published>2009-01-02T06:26:00.001-08:00</published><updated>2009-01-02T06:28:44.663-08:00</updated><title type='text'>Congratulations 2009 Microsoft MVP!</title><content type='html'>&lt;p&gt;That's the subject line of an email I received yesterday. No one is more surprised than me. Considering who the other MVPs are, I'm honored to be among them. I'm not entirely sure what I did to deserve this, but I'm grateful all the same. Thank you, Microsoft, for noticing me and here's to a productive 2009. Cheers!&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18697241-261405553121119225?l=www.darrellhawley.com%2Fdefault.html' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/18697241/261405553121119225/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=18697241&amp;postID=261405553121119225' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18697241/posts/default/261405553121119225'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18697241/posts/default/261405553121119225'/><link rel='alternate' type='text/html' href='http://www.darrellhawley.com/2009/01/congratulations-2009-microsoft-mvp.html' title='Congratulations 2009 Microsoft MVP!'/><author><name>Darrell Hawley</name><uri>http://www.blogger.com/profile/13626445665115916691</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='03881874778058834600'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18697241.post-2336433541660932514</id><published>2008-12-27T08:37:00.001-08:00</published><updated>2008-12-27T08:37:07.711-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Testing'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><category scheme='http://www.blogger.com/atom/ns#' term='refactoring'/><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>Note to Self 5 - Inherit and Override</title><content type='html'>&lt;p&gt;I've been reading &lt;em&gt;Working Effectively with Legacy Code&lt;/em&gt; by Michael C. Feathers. It's a trove of useful information for turning your unreadable and unreliable code into the complete opposite.&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Here's a useful technique for dealing with dependencies that have problematic methods for testing. Mark the offending method as virtual and inherit from the class. Now you can use this new derivative class in your test methods in place of the original. Here's an example in C#.      &lt;br /&gt;      &lt;br /&gt;      &lt;blockquote&gt;       &lt;p&gt;public class MyClass          &lt;br /&gt;{           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; public MyClass()           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Console.WriteLine(&amp;quot;MyClass has been initialized&amp;quot;);           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; } &lt;/p&gt;        &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; public virtual void DifficultMethod()          &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Console.WriteLine(           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;quot;Difficult method makes testing difficult.&amp;quot;);           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }           &lt;br /&gt;} &lt;/p&gt;        &lt;p&gt;public class MyClassDerived : MyClass          &lt;br /&gt;{           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; public MyClassDerived() : base()           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; } &lt;/p&gt;        &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; public override void DifficultMethod()          &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Console.WriteLine(&amp;quot;It's testable!&amp;quot;);           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; } &lt;/p&gt;        &lt;p&gt;} &lt;/p&gt;        &lt;p&gt;public class ClassToTest          &lt;br /&gt;{           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; public ClassToTest(MyClass myclass)           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Console.WriteLine(&amp;quot;Initializing ClassToTest&amp;quot;);           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; myclass.DifficultMethod();           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }           &lt;br /&gt;}&lt;/p&gt;        &lt;br /&gt;&lt;/blockquote&gt;      &lt;p&gt;The ClassToTest has a constructor that takes a MyClass parameter. Unfortunately, MyClass has the DifficultMethod which is a very...well, difficult method. By marking DifficultMethod as virtual we can override it in a derived class which can then be used to pass into the ClassToTest constructor. Handy.&lt;/p&gt;   &lt;/li&gt;    &lt;li&gt;Here's the same idea in Python      &lt;br /&gt;      &lt;blockquote&gt;       &lt;p&gt;class MyClass(object):          &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; def __init__(self):           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; print &amp;quot;MyClass Initialized&amp;quot;           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; def difficult_method(self):           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; print &amp;quot;this makes things hard&amp;quot;           &lt;br /&gt;&lt;/p&gt;        &lt;p&gt;class MyClassDerivative(MyClass):          &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; def __init__(self):           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; MyClass.__init__(self)           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; def difficult_method(self):           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; print &amp;quot;MUCH better&amp;quot;           &lt;br /&gt;&lt;/p&gt;        &lt;p&gt;class ClassToTest(object):          &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; def __init__(self, myClass):           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; print &amp;quot;ClassToTest has been initialized&amp;quot;           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; myClass.difficult_method()          &lt;br /&gt;          &lt;br /&gt;&lt;/p&gt;     &lt;/blockquote&gt;   &lt;/li&gt; &lt;/ul&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18697241-2336433541660932514?l=www.darrellhawley.com%2Fdefault.html' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/18697241/2336433541660932514/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=18697241&amp;postID=2336433541660932514' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18697241/posts/default/2336433541660932514'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18697241/posts/default/2336433541660932514'/><link rel='alternate' type='text/html' href='http://www.darrellhawley.com/2008/12/note-to-self-5-inherit-and-override.html' title='Note to Self 5 - Inherit and Override'/><author><name>Darrell Hawley</name><uri>http://www.blogger.com/profile/13626445665115916691</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='03881874778058834600'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18697241.post-8333166480642852034</id><published>2008-12-16T20:20:00.001-08:00</published><updated>2008-12-16T20:20:23.561-08:00</updated><title type='text'>Using Lambdas to Avoid Gnarly IF Statements</title><content type='html'>&lt;p&gt;Do you have a function in your C# code somewhere that takes a parameter - the type doesn't matter - and then executes another function based on that parameter's value?&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;public void what_to_do(string param)     &lt;br /&gt;{      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; if (param == &amp;quot;this&amp;quot;)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; DoThis();      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; else if (param == &amp;quot;that&amp;quot;)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; DoThat();      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; else      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; DoSomethingElse();      &lt;br /&gt;}&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Whenever I see &amp;quot;else if&amp;quot;, my spider-sense starts tingling. Adding another &amp;quot;else if&amp;quot; is just too easy and the result can be cumbersome. I do use &amp;quot;else if&amp;quot; (and &amp;quot;switch&amp;quot; - it's just as vulnerable to this idea), but I don't always like it. The good news is that there is a fix - if you're willing to think &amp;quot;functionally&amp;quot;. The bad news is it took me so long to piece it all together.&lt;/p&gt;  &lt;p&gt;When did this epiphany come? At the latest &lt;a href="http://groups.google.com/group/michipug/web/index-2?pli=1" target="_blank"&gt;MichiPUG&lt;/a&gt; meeting, while &lt;a href="http://compoundthinking.com/blog/" target="_blank"&gt;Mark Ramm&lt;/a&gt; was demonstrating a Python library for implementing generics, he displayed an interesting technique for avoiding the Python version of the above code. Here's my rendition of what he showed us:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;whatToDoDictionary = {'this':do_this, 'that':do_that} &lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;def what_to_do(param):     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; if param in whatToDoDictionary:      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; whatToDoDictionary[param]();      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; else:      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; do_something_else();&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;The key to this bit of Python is the values in the&amp;#160; whatToDoDictionary. Instead of your standard string or integers, the values are functions. When we call the what_to_do method, we look to see if the parameter is present as a key in the dictionary. If it is, we simple execute the value portion of the key/value pair. Voil&amp;#224;! No more &amp;quot;else if&amp;quot;!&lt;/p&gt;  &lt;p&gt;Can we do this in C#? Sure. Let's do it using lambdas.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Dictionary&amp;lt;string, Action&amp;gt; dict = &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; new Dictionary&amp;lt;string, Action&amp;gt;(); &lt;/p&gt;    &lt;p&gt;public Lambda()     &lt;br /&gt;{      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; dict.Add(&amp;quot;this&amp;quot;, () =&amp;gt; do_this());      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; dict.Add(&amp;quot;that&amp;quot;, () =&amp;gt; do_that());      &lt;br /&gt;} &lt;/p&gt;    &lt;p&gt;public void WhatToDo(string param)     &lt;br /&gt;{      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; if (dict.ContainsKey(param))      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; dict[param]();      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; else      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; do_something_else();      &lt;br /&gt;}&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;The concept is exactly the same. Build a dictionary of lambdas (functions in Python), see if the parameter passed to the WhatToDo(string) is in the dictionary and then execute the lambda if it is. &lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18697241-8333166480642852034?l=www.darrellhawley.com%2Fdefault.html' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/18697241/8333166480642852034/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=18697241&amp;postID=8333166480642852034' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18697241/posts/default/8333166480642852034'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18697241/posts/default/8333166480642852034'/><link rel='alternate' type='text/html' href='http://www.darrellhawley.com/2008/12/using-lambdas-to-avoid-gnarly-if.html' title='Using Lambdas to Avoid Gnarly IF Statements'/><author><name>Darrell Hawley</name><uri>http://www.blogger.com/profile/13626445665115916691</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='03881874778058834600'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18697241.post-1106972138331870081</id><published>2008-12-13T13:11:00.001-08:00</published><updated>2008-12-13T13:11:20.224-08:00</updated><title type='text'>Note to Self 4 - Python Editors, Debuggers, stdout and stderr</title><content type='html'>&lt;ul&gt;   &lt;li&gt;PyScripter has been IDE of choice for Python, but I've run into some problems with it. I would have continued to use it, but I noticed that the latest anyone did any work on it was October of 2006 - or at least that's what I thought. It turns out that early this year PyScripter is now maintained in Google Code and supports Python 2.6. You can download it &lt;a href="http://code.google.com/p/pyscripter/" target="_blank"&gt;here&lt;/a&gt;. &lt;/li&gt;    &lt;li&gt;I've started using &lt;a href="http://notepad-plus.sourceforge.net/uk/site.htm" target="_blank"&gt;Notepad++&lt;/a&gt; for editing my Python. Though it's only an editor, it uses syntax highlighting, supports macros and allows me to define hot keys to run external programs. This last point makes it possible for me to launch my code in Python with a simple keypress. &lt;/li&gt;    &lt;li&gt;Want to know how to use Notepad++ to launch the file you're currently editing in Python? Type &amp;quot;[%Python directory%]\python.exe &amp;quot;$(FULL_CURRENT_PATH)&amp;quot; into the Notepad++ Run dialog and then save it to the keystroke combination of you choice. &lt;/li&gt;    &lt;li&gt;If you took my previous bullet point to heart, you'll find that Python launches in a command window and then promptly closes after your tests run losing any output you may have had. The only way that I've been able to solve this is by pointing the stdout and stderr to a file. I would prefer to override the these when I launch Python, but instead I have to put some addtional code into my application. Bummer. &lt;/li&gt;    &lt;li&gt;&lt;a href="http://winpdb.org/" target="_blank"&gt;WinPDB&lt;/a&gt; is a debugging tool for Python. The only tool I'd used for debugging in the past is the one embedded into &lt;a href="http://code.google.com/p/pyscripter/" target="_blank"&gt;PyScripter&lt;/a&gt;. When I started using Notepad++ as my editor, I started trying to debug from the command line using the PDB module. No fun. That's when I came across WinPDB. It's worked well for the past few days that I've been using it, but it still isn't as nice as having your debugger integrated into your environment. &lt;/li&gt; &lt;/ul&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18697241-1106972138331870081?l=www.darrellhawley.com%2Fdefault.html' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/18697241/1106972138331870081/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=18697241&amp;postID=1106972138331870081' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18697241/posts/default/1106972138331870081'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18697241/posts/default/1106972138331870081'/><link rel='alternate' type='text/html' href='http://www.darrellhawley.com/2008/12/note-to-self-4-python-editors-debuggers.html' title='Note to Self 4 - Python Editors, Debuggers, stdout and stderr'/><author><name>Darrell Hawley</name><uri>http://www.blogger.com/profile/13626445665115916691</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='03881874778058834600'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18697241.post-6979377162939117941</id><published>2008-11-17T10:41:00.001-08:00</published><updated>2008-11-17T10:41:54.353-08:00</updated><title type='text'>Note to Self 3 - CodeMash Screen Casting Options</title><content type='html'>&lt;p&gt;I've been learning a lot about Screencasting this week...&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;I've updated my podcasting links at &lt;a title="http://delicious.com/dwhawley/podcasting" href="http://delicious.com/dwhawley/podcasting"&gt;http://delicious.com/dwhawley/podcasting&lt;/a&gt; with a couple of new items.&lt;/li&gt;    &lt;li&gt;I reviewed a couple of USB devices to capture video and audio (&lt;a href="http://www.amazon.com/review/product/B000234SMQ/ref=cm_cr_pr_hist_5?_encoding=UTF8&amp;amp;showViewpoints=0&amp;amp;filterBy=addFiveStar" target="_blank"&gt;USB 28000D DVD Maker&lt;/a&gt; and the &lt;a href="http://www.amazon.com/Diamond-VC500-Touch-Capture-Device/dp/B000VM60I8/ref=pd_cp_e_0?pf_rd_p=413863501&amp;amp;pf_rd_s=center-41&amp;amp;pf_rd_t=201&amp;amp;pf_rd_i=B000234SMQ&amp;amp;pf_rd_m=ATVPDKIKX0DER&amp;amp;pf_rd_r=0VJFAC945FBNH58A11D8" target="_blank"&gt;Diamond VC500 One Touch Video Capture Device&lt;/a&gt;) and I wasn't happy with any of the reviews. This really seemed to be the simplest avenue but seems to be a dead-end.&lt;/li&gt;    &lt;li&gt;The solution I'm searching for assumes that I'll only have laptops available. There are a lot of video capture cards out there for a desktop machine but I'm avoiding this one for now.&lt;/li&gt;    &lt;li&gt;I like the VNC option the best, but a major problem with this is that we'll need to rely on speakers installing something on their machine. &lt;a href="http://jasonfollas.com/blog/" target="_blank"&gt;Jason Follas&lt;/a&gt; pointed this out to me and he's right. I think the only way to resolve this is ask the community. If they don't like the solution I'll know to keep looking. Besides, someone might have a really good idea.&lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.jingproject.com/" target="_blank"&gt;Jing&lt;/a&gt; is cool. &lt;a href="http://srtsolutions.com/blogs/jaywren/default.aspx" target="_blank"&gt;Jay Wren&lt;/a&gt; gave me quick demo earlier today and I was impressed with it's simplicity. One of the things that I really like about &lt;a href="http://www.jingproject.com/" target="_blank"&gt;Jing&lt;/a&gt; is it's social spirit. I was looking at &lt;a href="http://www.techsmith.com/camtasia.asp" target="_blank"&gt;Camtasia&lt;/a&gt;, another offering by &lt;a href="http://www.techsmith.com/" target="_blank"&gt;TechSmith&lt;/a&gt; , but I think &lt;a href="http://www.jingproject.com/" target="_blank"&gt;Jing&lt;/a&gt; may be a better fit.&lt;/li&gt; &lt;/ul&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18697241-6979377162939117941?l=www.darrellhawley.com%2Fdefault.html' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/18697241/6979377162939117941/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=18697241&amp;postID=6979377162939117941' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18697241/posts/default/6979377162939117941'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18697241/posts/default/6979377162939117941'/><link rel='alternate' type='text/html' href='http://www.darrellhawley.com/2008/11/note-to-self-3-codemash-screen-casting.html' title='Note to Self 3 - CodeMash Screen Casting Options'/><author><name>Darrell Hawley</name><uri>http://www.blogger.com/profile/13626445665115916691</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='03881874778058834600'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>1</thr:total></entry></feed>