<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:copyright="http://blogs.law.harvard.edu/tech/rss" xmlns:image="http://purl.org/rss/1.0/modules/image/">
    <channel>
        <title>Python</title>
        <link>http://nimblecoder.com/blog/category/7.aspx</link>
        <description>Python</description>
        <language>en-US</language>
        <copyright>Ryan Van Slooten</copyright>
        <generator>Subtext Version 2.1.1.1</generator>
        <item>
            <title>Programming Crutch, Litmus Test, or Silver Bullet?</title>
            <link>http://nimblecoder.com/blog/archive/2007/10/23/programming-crutch-litmus-test-or-silver-bullet.aspx</link>
            <description>&lt;p&gt;Lately I've been reading more about &lt;a href="http://www.rubyonrails.com/" target="_blank"&gt;Ruby on Rails&lt;/a&gt; -- actually it has been rather &lt;a href="http://blog.wekeroad.com/2007/10/10/imploding-rails-jesus-dhh-and-the-uncle-ben-principle/" target="_blank"&gt;entertaining&lt;/a&gt;, &lt;a title="Mark Pilgrims translation of DHH’s response to the Twitter scaling problems" href="http://diveintomark.org/archives/2007/04/16/dhh-translation" target="_blank"&gt;colorful&lt;/a&gt;, &lt;a href="http://www.loudthinking.com/posts/15-potty-mouths" target="_blank"&gt;testy&lt;/a&gt;, and somewhat enlightening. One important aspect of programming is the ability to analyze, understand, and adapt. I have been using more Python lately in work as well as JavaScript and it has been enjoyable although I still like and prefer C#.&lt;/p&gt; &lt;p&gt;Sometimes I wonder how many programmers get fixated on specific language features that in turn becomes a "must have" or requirement for any language he or she uses. That isn't to say the feature is not important but rather usually the task can be accomplished in multiple ways albeit with more creativity (or even hacks) than otherwise necessary.&lt;/p&gt; &lt;p&gt;The examples can be found in any language or product comparison from C++/C#/Python/Ruby/Java to Oracle/SQL Server/MySQL and so on. I recently had to write a stored procedure on Oracle that manipulated data in a table and exported the data. I struggled for several hours as I am not intimately familiar with Oracle before deciding I could accomplish the same task in SQL Server in ten minutes. Sure enough, I used a linked server connection and a temporary table in SQL Server and had the issue solved in practically no time. The issue for me wasn't that Oracle could not accomplish the task, but that I was more familiar with SQL Server and the programming options I could use with it. Oracle does indeed have advantages over SQL Server and vice versa, but it seems IMHO that temporary tables are indeed easier to use in SQL Server and can be contained much easier (I initially tried local temporary tables in Oracle and then global temporary tables and then objects and tables of objects before going back to SQL Server). Ultimately, it was personal preference and familiarity though and not inability of the database. But we as programmers usually fall back on the same techniques that we are familiar with at times, rather than objectively using the best language or technique. It is somewhat like a sore spot that every time you rub against it becomes sorer (even when you shouldn't or don't need to touch that spot). On the other hand, we should be careful were preference out weighs objectivity.&lt;/p&gt; &lt;p&gt;When I read comments about one language being better than another, I always take the comments with a grain of salt. I like to think of programming language differences very similar to spoken and written language differences: the main point can almost always be expressed in another language although it may be longer or more verbose or less "natural" and may not convey the subtleties.&lt;/p&gt; &lt;p&gt;Finally, about Twitter having to write a small portion of code in C -- all of my projects have tight schedules and I would not be happy if I was the developer of the application. Even if it only took 300 lines of C and 2 hours to write, how much more time was spent analyzing, debugging, and getting to that point? And of course, it was solved by the authors of the platform who know it better than anyone else -- so it takes someone who wrote the system or at least very intimately familiar with the system to solve -- it seems to be a very small resource pool, which IMHO is a big problem. It is usually &lt;strong&gt;is easier &lt;/strong&gt;to solve when &lt;strong&gt;you &lt;/strong&gt;wrote the software and know where to look.&lt;/p&gt;&lt;img src="http://nimblecoder.com/blog/aggbug/42.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Ryan Van Slooten</dc:creator>
            <guid>http://nimblecoder.com/blog/archive/2007/10/23/programming-crutch-litmus-test-or-silver-bullet.aspx</guid>
            <pubDate>Tue, 23 Oct 2007 20:58:37 GMT</pubDate>
            <wfw:comment>http://nimblecoder.com/blog/comments/42.aspx</wfw:comment>
            <comments>http://nimblecoder.com/blog/archive/2007/10/23/programming-crutch-litmus-test-or-silver-bullet.aspx#feedback</comments>
            <wfw:commentRss>http://nimblecoder.com/blog/comments/commentRss/42.aspx</wfw:commentRss>
            <trackback:ping>http://nimblecoder.com/blog/services/trackbacks/42.aspx</trackback:ping>
        </item>
        <item>
            <title>Subtext Configuration</title>
            <link>http://nimblecoder.com/blog/archive/2007/05/03/SubText-Configuration.aspx</link>
            <description>&lt;p&gt;I really like Subtext, but unfortunately I haven't had too much time to try to configure my blog. I've looked through the wiki, but haven't seen enough information to emulate the configuration of Subtext founder &lt;a href="http://haacked.com/"&gt;Phil Haack&lt;/a&gt;. For example, the FeedBurner plugin which lists the number of subscribers and links to get the RSS and even email feeds -- how exactly is that configured? I suppose I should RTFM but I'm having trouble finding it at the moment (not to mention I have &lt;strong&gt;way too much &lt;/strong&gt;to do right now with work!). It seems the &lt;a href="http://www.subtextproject.com/Home/Wiki/tabid/150/Default.aspx"&gt;Subtext Wiki&lt;/a&gt; is describing &lt;a href="http://www.subtextproject.com/DesktopDefault.aspx?tabid=150&amp;amp;pageID=4&amp;amp;pageName="&gt;plug-in features&lt;/a&gt; in Subtext 2.0 (I'm running 1.9.x currently -- 2.0 is not released yet) so that doesn't help.&lt;/p&gt; &lt;p&gt;Sooner or later I will install &lt;a href="http://www.php-compiler.net/doku.php"&gt;Phalanger&lt;/a&gt; and test out &lt;a href="http://wiki.splitbrain.org/wiki:dokuwiki"&gt;DokuWiki&lt;/a&gt;. I also want to install &lt;a href="http://umbraco.org/"&gt;umbraco&lt;/a&gt; and possibly &lt;a href="http://community.rainbowportal.net/"&gt;Rainbow portal&lt;/a&gt; while I'm at it. I'd love to have &lt;a href="http://www.gnu.org/software/mailman/"&gt;GNU Mailman&lt;/a&gt; installed to manage mailing lists, but there are too many issues related its dependence on UNIX-style usernames and groups and I would probably need to user &lt;a href="http://www.codeplex.com/Wiki/View.aspx?ProjectName=IronPython"&gt;IronPython&lt;/a&gt; for the &lt;a href="http://python.org/"&gt;Python&lt;/a&gt; functionality. I guess it is just too much work right now, especially as I am utterly swamped at work. Unfortunately at work I am stuck working on a design portion of a project and I don't even get to do "real" programming that much -- sometimes you long to launch Visual Studio or work on source code. Oh well, hopefully this phase will end soon.&lt;/p&gt;&lt;img src="http://nimblecoder.com/blog/aggbug/21.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Ryan Van Slooten</dc:creator>
            <guid>http://nimblecoder.com/blog/archive/2007/05/03/SubText-Configuration.aspx</guid>
            <pubDate>Thu, 03 May 2007 14:32:25 GMT</pubDate>
            <wfw:comment>http://nimblecoder.com/blog/comments/21.aspx</wfw:comment>
            <comments>http://nimblecoder.com/blog/archive/2007/05/03/SubText-Configuration.aspx#feedback</comments>
            <slash:comments>2</slash:comments>
            <wfw:commentRss>http://nimblecoder.com/blog/comments/commentRss/21.aspx</wfw:commentRss>
            <trackback:ping>http://nimblecoder.com/blog/services/trackbacks/21.aspx</trackback:ping>
        </item>
        <item>
            <title>Altering SQL Server</title>
            <link>http://nimblecoder.com/blog/archive/2007/04/04/Altering-SQL-Server.aspx</link>
            <description>&lt;p&gt;I was working on a project last week where I needed to update the columns and data types in tables in SQL Server. It is pretty quick to do this manually such as:&lt;/p&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;ALTER&lt;/span&gt; &lt;span class="kwrd"&gt;TABLE&lt;/span&gt; orders
&lt;span class="kwrd"&gt;    ALTER&lt;/span&gt; &lt;span class="kwrd"&gt;COLUMN&lt;/span&gt; orderid &lt;span class="kwrd"&gt;varchar(36)&lt;/span&gt; &lt;span class="kwrd"&gt;NOT&lt;/span&gt; NULL&lt;/pre&gt;
&lt;p&gt;I prefer this compared to the code SQL Server generates in the change script which typically renames the existing table, creates a new table, copies the data from the previous table to the new table, and then restores indices and keys. While that is appropriate for dramatic changes, it is overkill for something of this nature.&lt;/p&gt;
&lt;p&gt;Since I love using tools and scripting, I decided to make a small Python program which would let me just specify which tables and columns to modify. This simplifies maintenance as I only have to manage the tables and columns rather than reading the entire SQL script looking for missing columns or keys.&lt;/p&gt;
&lt;p&gt;While I was developing the Python script, I wanted to add enough SQL to avoid obvious errors such as trying to add duplicate primary keys or trying to alter columns that are already NOT NULL. I used MSDN and looked at some of the generated SQL to get the following templates:&lt;/p&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;IF&lt;/span&gt; &lt;span class="kwrd"&gt;EXISTS&lt;/span&gt; (&lt;span class="kwrd"&gt;SELECT&lt;/span&gt; * &lt;span class="kwrd"&gt;FROM&lt;/span&gt; dbo.sysobjects &lt;span class="kwrd"&gt;WHERE&lt;/span&gt; id = OBJECT_ID(&lt;span class="str"&gt;'orders'&lt;/span&gt;) &lt;span class="kwrd"&gt;AND&lt;/span&gt; COLUMNPROPERTY(id, &lt;span class="str"&gt;'orderid'&lt;/span&gt;, &lt;span class="str"&gt;'AllowsNull'&lt;/span&gt;) = 1)
&lt;span class="kwrd"&gt;BEGIN&lt;/span&gt;
    &lt;span class="kwrd"&gt;PRINT&lt;/span&gt; &lt;span class="str"&gt;'Altering column: orders.orderid'&lt;/span&gt;
    &lt;span class="kwrd"&gt;ALTER&lt;/span&gt; &lt;span class="kwrd"&gt;TABLE&lt;/span&gt; orders
        &lt;span class="kwrd"&gt;ALTER&lt;/span&gt; &lt;span class="kwrd"&gt;COLUMN&lt;/span&gt; orderid &lt;span class="kwrd"&gt;varchar&lt;/span&gt;(36) &lt;span class="kwrd"&gt;NOT&lt;/span&gt; &lt;span class="kwrd"&gt;NULL&lt;/span&gt;
&lt;span class="kwrd"&gt;END&lt;/span&gt;
&lt;span class="kwrd"&gt;GO&lt;/span&gt;

&lt;span class="kwrd"&gt;IF&lt;/span&gt; &lt;span class="kwrd"&gt;EXISTS&lt;/span&gt; (&lt;span class="kwrd"&gt;SELECT&lt;/span&gt; * &lt;span class="kwrd"&gt;FROM&lt;/span&gt; dbo.sysobjects &lt;span class="kwrd"&gt;WHERE&lt;/span&gt; id = OBJECT_ID(&lt;span class="str"&gt;'orders'&lt;/span&gt;) &lt;span class="kwrd"&gt;AND&lt;/span&gt; OBJECTPROPERTY(id, &lt;span class="str"&gt;'TableHasPrimaryKey'&lt;/span&gt;) = 0)
&lt;span class="kwrd"&gt;BEGIN&lt;/span&gt;
    &lt;span class="kwrd"&gt;PRINT&lt;/span&gt; &lt;span class="str"&gt;'Adding primary key: orders.orderid'&lt;/span&gt;
    &lt;span class="kwrd"&gt;ALTER&lt;/span&gt; &lt;span class="kwrd"&gt;TABLE&lt;/span&gt; orders
        &lt;span class="kwrd"&gt;ADD&lt;/span&gt; &lt;span class="kwrd"&gt;CONSTRAINT&lt;/span&gt; PK_orders
            &lt;span class="kwrd"&gt;PRIMARY&lt;/span&gt; &lt;span class="kwrd"&gt;KEY&lt;/span&gt; (orderid)
&lt;span class="kwrd"&gt;END&lt;/span&gt;
&lt;span class="kwrd"&gt;GO&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;So the Python script used the string templates to write the output SQL and it looked like:&lt;/p&gt;&lt;pre class="csharpcode"&gt;&lt;span class="rem"&gt;#!/usr/bin/env python&lt;/span&gt;

&lt;span class="str"&gt;"""Generate a T-SQL script to set the appropriate NOT NULL
columns and PRIMARY KEY indices for the database.

TODO: Create indices for specific columns as well
"""&lt;/span&gt;

&lt;span class="kwrd"&gt;import&lt;/span&gt; string

&lt;span class="rem"&gt;# database properties&lt;/span&gt;

tables = {
    &lt;span class="str"&gt;"orders"&lt;/span&gt;:           { &lt;span class="str"&gt;'notnull'&lt;/span&gt;: [(&lt;span class="str"&gt;'orderid'&lt;/span&gt;, &lt;span class="str"&gt;'varchar(36)'&lt;/span&gt;)],
                          &lt;span class="str"&gt;'pk'&lt;/span&gt;     : [&lt;span class="str"&gt;'orderid'&lt;/span&gt;] },

    &lt;span class="str"&gt;"accounts"&lt;/span&gt;:         { &lt;span class="str"&gt;'notnull'&lt;/span&gt;: [(&lt;span class="str"&gt;'accountid'&lt;/span&gt;, &lt;span class="str"&gt;'varchar(50)'&lt;/span&gt;),
                                      (&lt;span class="str"&gt;'name'&lt;/span&gt;, &lt;span class="str"&gt;'varchar(100)'&lt;/span&gt;)],
                          &lt;span class="str"&gt;'pk'&lt;/span&gt;     : [&lt;span class="str"&gt;'accountid'&lt;/span&gt;] },

    &lt;span class="rem"&gt;# More tables and columns...&lt;/span&gt;
    }

&lt;span class="rem"&gt;# Functions&lt;/span&gt;

def generatenotnull(table, column, datatype):
    print alternotnull % { &lt;span class="str"&gt;'table'&lt;/span&gt;:table, &lt;span class="str"&gt;'column'&lt;/span&gt;:column, &lt;span class="str"&gt;'datatype'&lt;/span&gt;:datatype }

def generatepk(table, columns):
    print alterpk % { &lt;span class="str"&gt;'table'&lt;/span&gt;:table, &lt;span class="str"&gt;'columns'&lt;/span&gt;:&lt;span class="kwrd"&gt;string&lt;/span&gt;.join(columns, &lt;span class="str"&gt;'"'&lt;/span&gt;) }

# SQL statements and formats

alternotnull = &lt;span class="str"&gt;"""IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID('%(table)s') AND COLUMNPROPERTY(id, '%(column)s', 'AllowsNull') = 1)
BEGIN
    PRINT 'Altering nullable column: %(table)s.%(column)s'
    ALTER TABLE %(table)s
        ALTER COLUMN %(column)s %(datatype)s NOT NULL
END
GO"""&lt;/span&gt;

alterpk = &lt;span class="str"&gt;"""IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID('%(table)s') AND OBJECTPROPERTY(id, 'TableHasPrimaryKey') = 0)
BEGIN
    PRINT 'Adding primary key: %(table)s.%(columns)s'
    ALTER TABLE %(table)s
        ADD CONSTRAINT PK_%(table)s
            PRIMARY KEY (%(columns)s)
END
GO"""&lt;/span&gt;


&lt;span class="rem"&gt;# Main entry&lt;/span&gt;
&lt;span class="kwrd"&gt;if&lt;/span&gt; __name__ == &lt;span class="str"&gt;"__main__"&lt;/span&gt;:
    &lt;span class="kwrd"&gt;for&lt;/span&gt; table &lt;span class="kwrd"&gt;in&lt;/span&gt; tables:
        print &lt;span class="str"&gt;"/* ==== Processing %s ==== */"&lt;/span&gt; % table
        tabledict = tables[table]
        &lt;span class="kwrd"&gt;for&lt;/span&gt; column &lt;span class="kwrd"&gt;in&lt;/span&gt; tabledict[&lt;span class="str"&gt;'notnull'&lt;/span&gt;]:
            generatenotnull(table, column[0], column[1])
        &lt;span class="rem"&gt;# TODO: Allow for compound primary keys&lt;/span&gt;
        generatepk(table, tabledict[&lt;span class="str"&gt;'pk'&lt;/span&gt;])
        print &lt;span class="str"&gt;""&lt;/span&gt;
&lt;/pre&gt;&lt;img src="http://nimblecoder.com/blog/aggbug/17.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Ryan Van Slooten</dc:creator>
            <guid>http://nimblecoder.com/blog/archive/2007/04/04/Altering-SQL-Server.aspx</guid>
            <pubDate>Wed, 04 Apr 2007 21:17:53 GMT</pubDate>
            <wfw:comment>http://nimblecoder.com/blog/comments/17.aspx</wfw:comment>
            <comments>http://nimblecoder.com/blog/archive/2007/04/04/Altering-SQL-Server.aspx#feedback</comments>
            <wfw:commentRss>http://nimblecoder.com/blog/comments/commentRss/17.aspx</wfw:commentRss>
            <trackback:ping>http://nimblecoder.com/blog/services/trackbacks/17.aspx</trackback:ping>
        </item>
        <item>
            <title>Decisions (so many tools)</title>
            <link>http://nimblecoder.com/blog/archive/2007/03/26/Decisions-so-many-tools.aspx</link>
            <description>&lt;p&gt;During a database schema upgrade yesterday, I had to create a new primary key field for a table and then generate the new primary key values. At the moment this key value is a custom generated value by a Python class, but it will eventually use an &lt;a href="http://www.ietf.org/rfc/rfc4122.txt"&gt;RFC 4122&lt;/a&gt; or &lt;a href="http://www.itu.int/ITU-T/studygroups/com17/oid.html"&gt;ISO/IEC 9834-8&lt;/a&gt; compliant algorithm (see &lt;a href="http://en.wikipedia.org/wiki/UUID"&gt;Wikipedia&lt;/a&gt; for more information).&lt;/p&gt; &lt;p&gt;I had to decide how to generate this value and I ended up using a combination of Python, &lt;a href="http://www.gnu.org/software/gawk/gawk.html"&gt;gawk&lt;/a&gt;, and T-SQL. I suppose I could have left out the gawk, but it would have taken almost the same amount of time to do it in Python and it took a just moment to write. I will present three different methods that I could have accomplished the same task, although there were reasons that I used the method that I did.&lt;/p&gt; &lt;h4&gt;Method 1 - Python, gawk, and SQL&lt;/h4&gt;&lt;pre class="csharpcode"&gt;&lt;span class="rem"&gt;# Requires Python 2.5 or higher&lt;/span&gt;
&lt;span class="kwrd"&gt;import&lt;/span&gt; uuid
&lt;span class="kwrd"&gt;for&lt;/span&gt; i &lt;span class="kwrd"&gt;in&lt;/span&gt; range(200):
    print uuid.uuid4()

C:\&amp;gt;python genuuid.py &amp;gt; uuid.txt

C:\&amp;gt;gawk "/^'/ { i += 1; print \"INSERT @issueid VALUES (\" $1 \", \" i \")\"; }" uuid.txt &amp;amp;gt; uuid.sql

&lt;span class="rem"&gt;/* Add the table variable to the SQL file */&lt;/span&gt;
&lt;span class="kwrd"&gt;DECLARE&lt;/span&gt; @issueid &lt;span class="kwrd"&gt;TABLE&lt;/span&gt; (
    issueid &lt;span class="kwrd"&gt;varchar&lt;/span&gt;(36),
    issuenum &lt;span class="kwrd"&gt;int&lt;/span&gt;
)&lt;/pre&gt;
&lt;h4&gt;Method 2 - Python and SQL&lt;/h4&gt;&lt;pre class="csharpcode"&gt;&lt;span class="rem"&gt;# Requires Python 2.5 or higher&lt;/span&gt;
&lt;span class="kwrd"&gt;import&lt;/span&gt; uuid

&lt;span class="kwrd"&gt;print&lt;/span&gt; &lt;span class="str"&gt;"""DECLARE @issueid TABLE (
    issueid varchar(36),
    issuenum int
)"""&lt;/span&gt;

&lt;span class="kwrd"&gt;for&lt;/span&gt; i &lt;span class="kwrd"&gt;in&lt;/span&gt; range(200):
    &lt;span class="kwrd"&gt;print&lt;/span&gt; &lt;span class="str"&gt;"INSERT @issueid VALUES ('%s', %d)"&lt;/span&gt; % (uuid.uuid4(), i+1)

C:\&amp;gt;python genuuid.py &amp;gt; uuid.sql&lt;/pre&gt;
&lt;h4&gt;Method 3 - SQL&lt;/h4&gt;&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;pre class="csharpcode"&gt;&lt;span class="rem"&gt;/* Add the table variable to the SQL script */&lt;/span&gt;
&lt;span class="kwrd"&gt;DECLARE&lt;/span&gt; @issueid &lt;span class="kwrd"&gt;TABLE&lt;/span&gt; (
    issueid &lt;span class="kwrd"&gt;varchar&lt;/span&gt;(36),
    issuenum &lt;span class="kwrd"&gt;int&lt;/span&gt;
)
&lt;span class="kwrd"&gt;DECLARE&lt;/span&gt; @i &lt;span class="kwrd"&gt;int&lt;/span&gt;

&lt;span class="kwrd"&gt;SET&lt;/span&gt; @i = 0
&lt;span class="kwrd"&gt;WHILE&lt;/span&gt; @i &amp;lt; 200
&lt;span class="kwrd"&gt;BEGIN&lt;/span&gt;
    &lt;span class="kwrd"&gt;INSERT&lt;/span&gt; @issueid &lt;span class="kwrd"&gt;VALUES&lt;/span&gt;(NEWID(), @i+1)
    &lt;span class="kwrd"&gt;SET&lt;/span&gt; @i = @i + 1
&lt;span class="kwrd"&gt;END&lt;/span&gt;

&lt;span class="rem"&gt;/* Process table here */&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;After looking back, Method 2 seems to be the most straight-forward and self-contained method. The reason I chose Option 1 was that it was the first method that I thought of. Now that I am using Python more, I will probably start favoring quick solutions like Method 2.&lt;/p&gt;&lt;img src="http://nimblecoder.com/blog/aggbug/16.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Ryan Van Slooten</dc:creator>
            <guid>http://nimblecoder.com/blog/archive/2007/03/26/Decisions-so-many-tools.aspx</guid>
            <pubDate>Mon, 26 Mar 2007 14:21:52 GMT</pubDate>
            <wfw:comment>http://nimblecoder.com/blog/comments/16.aspx</wfw:comment>
            <comments>http://nimblecoder.com/blog/archive/2007/03/26/Decisions-so-many-tools.aspx#feedback</comments>
            <wfw:commentRss>http://nimblecoder.com/blog/comments/commentRss/16.aspx</wfw:commentRss>
            <trackback:ping>http://nimblecoder.com/blog/services/trackbacks/16.aspx</trackback:ping>
        </item>
    </channel>
</rss>