<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-8400732</id><updated>2012-01-28T22:09:28.711-08:00</updated><category term='C#'/><category term='SharpDev'/><category term='.net'/><category term='linq'/><category term='python'/><category term='SQL Server'/><title type='text'>hwiechers</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://hwiechers.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8400732/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://hwiechers.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>hwiechers</name><uri>http://www.blogger.com/profile/11242164300585745124</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>22</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-8400732.post-743028879455308855</id><published>2012-01-28T22:05:00.000-08:00</published><updated>2012-01-28T22:09:28.717-08:00</updated><title type='text'>Stashing Changes in Mercurial</title><content type='html'>&lt;p&gt;Stashing means setting aside changes to a working directory without commiting them.&lt;/p&gt;&lt;p&gt;It's useful if, for example, you're adding a feature to one of your projects when you find a bug that you want to fix immediately. You don't want to not mix the fix up with your feature code and you aren't ready to commit and start a new changeset. The solution is to stash your changes, code the bug fix and commit it and then unstash them to resume working on the feature.&lt;/p&gt;&lt;h4&gt;Recipe&lt;/h4&gt;&lt;pre&gt;hg diff | Out-File -Encoding ascii stash.patch
hg update -C
# other stuff...
hg import --no-commit stash.patch
&lt;/pre&gt;&lt;h4&gt;Explanation&lt;/h4&gt;&lt;p&gt;Output of &lt;code&gt;hg diff&lt;/code&gt; is a unified diff which we save to file. &lt;code&gt;hg update -C&lt;/code&gt;, of course, removes the changes from the working directly. &lt;b&gt;Be careful that you don't accidentally lose work when you're doing this!&lt;/b&gt; After other stuff, we use the &lt;code&gt;import&lt;/code&gt; command to unstash the changes.&lt;/p&gt;&lt;h4&gt;Comparison to Other Methods&lt;/h4&gt;&lt;p&gt;There are extensions for stashing but, in my experience, they don't work very well.&lt;/p&gt;&lt;p&gt;mq is used for this as well but that procedure is unnecessarily complicated if you don't normally use mq.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8400732-743028879455308855?l=hwiechers.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hwiechers.blogspot.com/feeds/743028879455308855/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8400732&amp;postID=743028879455308855' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8400732/posts/default/743028879455308855'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8400732/posts/default/743028879455308855'/><link rel='alternate' type='text/html' href='http://hwiechers.blogspot.com/2012/01/stashing-changes-in-mercurial.html' title='Stashing Changes in Mercurial'/><author><name>hwiechers</name><uri>http://www.blogger.com/profile/11242164300585745124</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8400732.post-3584418066189586824</id><published>2011-09-23T23:21:00.000-07:00</published><updated>2011-09-23T23:21:24.549-07:00</updated><title type='text'>Vim: Reading from stdin</title><content type='html'>Here is a neat tip for Vim.&lt;br /&gt;
&lt;br /&gt;
To read from stdin use&lt;br /&gt;
&lt;pre&gt;&amp;lt;other commands&amp;gt; | gvim -R -&lt;/pre&gt;
&lt;br /&gt;
&lt;code&gt;-R&lt;/code&gt; instructs Vim to read the file in read-only mode.&lt;br /&gt;
&lt;code&gt;-&lt;/code&gt; is a utility convention that means open from stdin. (See &lt;a href="http://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap12.html#tag_12_02"&gt;Guideline 13&lt;/a&gt; of Utility Syntax Guidelines from the Posix standard.)&lt;br /&gt;
&lt;br /&gt;
Source: &lt;a href="http://stackoverflow.com/questions/230718/redirection-and-vim"&gt;http://stackoverflow.com/questions/230718/redirection-and-vim&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8400732-3584418066189586824?l=hwiechers.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hwiechers.blogspot.com/feeds/3584418066189586824/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8400732&amp;postID=3584418066189586824' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8400732/posts/default/3584418066189586824'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8400732/posts/default/3584418066189586824'/><link rel='alternate' type='text/html' href='http://hwiechers.blogspot.com/2011/09/vim-reading-from-stdin.html' title='Vim: Reading from stdin'/><author><name>hwiechers</name><uri>http://www.blogger.com/profile/11242164300585745124</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8400732.post-5454079049237517493</id><published>2011-09-18T07:07:00.000-07:00</published><updated>2011-09-18T07:07:48.928-07:00</updated><title type='text'>Mercurial: Automatically pushing changes on commit</title><content type='html'>Here is a neat tip for Mercurial.&lt;br /&gt;
&lt;br /&gt;
To automatically push on every commit add this hook to your repo hgrc:&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;[hooks]
commit.autopush = hg push
&lt;/pre&gt;
&lt;br /&gt;
Source: &lt;a href="http://stackoverflow.com/questions/1235597/mercurial-automatic-push-on-every-commit"&gt;http://stackoverflow.com/questions/1235597/mercurial-automatic-push-on-every-commit&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8400732-5454079049237517493?l=hwiechers.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hwiechers.blogspot.com/feeds/5454079049237517493/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8400732&amp;postID=5454079049237517493' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8400732/posts/default/5454079049237517493'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8400732/posts/default/5454079049237517493'/><link rel='alternate' type='text/html' href='http://hwiechers.blogspot.com/2011/09/mercurial-automatically-pushing-changes.html' title='Mercurial: Automatically pushing changes on commit'/><author><name>hwiechers</name><uri>http://www.blogger.com/profile/11242164300585745124</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8400732.post-7984331986224385212</id><published>2011-03-22T22:30:00.000-07:00</published><updated>2011-03-22T22:45:38.506-07:00</updated><title type='text'>Moving the Windows User folder</title><content type='html'>&lt;p&gt;With a bit effort, it's now possible to move your user folder and link to it with &lt;a href="http://en.wikipedia.org/wiki/NTFS_junction_point"&gt;junction point&lt;/a&gt;. &lt;a href="http://superuser.com/questions/53029/mount-second-drive-as-c-users-in-windows-7/53449#53449"&gt;Here&lt;/a&gt; are some instructions I found on &lt;a href="http://superuser.com"&gt;superuser.com&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;This makes it possible to truly separate your data and system files by moving your user folder to a completely separate drive.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8400732-7984331986224385212?l=hwiechers.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hwiechers.blogspot.com/feeds/7984331986224385212/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8400732&amp;postID=7984331986224385212' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8400732/posts/default/7984331986224385212'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8400732/posts/default/7984331986224385212'/><link rel='alternate' type='text/html' href='http://hwiechers.blogspot.com/2011/03/moving-windows-user-folder.html' title='Moving the Windows User folder'/><author><name>hwiechers</name><uri>http://www.blogger.com/profile/11242164300585745124</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8400732.post-4684463751042382696</id><published>2010-08-28T00:52:00.000-07:00</published><updated>2010-08-28T00:52:09.683-07:00</updated><title type='text'>Case classes in Python</title><content type='html'>&lt;p&gt;I'm trying to build a parser. The main function I've writing is 
called &lt;code&gt;parse&lt;/code&gt;. It takes a &lt;code&gt;str&lt;/code&gt; and returns a parse tree of 
token classes. I have a heap of tests that parse some text and 
then compare the parse tree against the an expected parse tree.&lt;/p&gt;
&lt;p&gt;The way I started testing this looked a little like:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# token classes
class Add(Token):
    def __init__(self, left, right):
        self.left = left
        self.right = right

    def __repr__(self):
        return 'Add(' + repr(left) + ', ' + repr(right) + ')'

class Number(Token):
    def __init__(self, numberStr):
        self.numberStr = numberStr

    def __repr__(self):
        return 'Number(' + repr(numberStr) + ')'

# tests
class Tests(unittest.TestCase):
    def test_add(self):
        self.assertEqual(
            "Add(Number('1'), Number('1'))", 
            repr(parse('1+1'))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Making the token classes was a real chore. After a while, I had around
10 of them and writing them was increasingly tedious. It 
occurred to me that if I had somethinng like &lt;a href="http://www.scala-lang.org/node/107"&gt;Scala Case Classes&lt;/a&gt;, 
I could change the code to something like:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# token classes
class Add(Token):
    def __init__(self, left, right):
        pass

class Number(Token):
    def __init__(self, numberStr):
        pass

# tests
class Tests(unittest.TestCase):
    def test_add(self):
        self.assertEqual(
            Add(Number('1'), Number('1'), 
            parse('1+1'))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This way the token classes basically write themselves and, because 
they have a handy &lt;strong&gt;eq&lt;/strong&gt; method, the test don't need those messy 
string comparisons.&lt;/p&gt;
&lt;p&gt;I did some research and found out that I could basically get the
case class functionality (apart from the pattern matching aspect)
using a custom Metaclass.&lt;/p&gt;
&lt;p&gt;Here the result:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; from caseclasses import CaseMetaClass
&amp;gt;&amp;gt;&amp;gt;
&amp;gt;&amp;gt;&amp;gt; class MyCaseClass():
...     __metaclass__ = CaseMetaClass
...     def __init__(self, a, b):
...         pass
...
&amp;gt;&amp;gt;&amp;gt; instance = MyCaseClass(1, 'x')
&amp;gt;&amp;gt;&amp;gt; instance.a
1
&amp;gt;&amp;gt;&amp;gt; instance.b
'x'
&amp;gt;&amp;gt;&amp;gt; instance == MyCaseClass(1, 'y')
False
&amp;gt;&amp;gt;&amp;gt; instance == MyCaseClass(1, 'x')
True
&amp;gt;&amp;gt;&amp;gt; str(instance)
"MyCaseClass(1, 'x')"
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is how it works. Case classes are marked with the CaseMetaClass.
For each argument in the &lt;code&gt;__init__&lt;/code&gt; method, a read-only property 
is generated with the same value as the argument when an instance
is constructed. It should be obvious from the example how the 
generated &lt;code&gt;__eq__&lt;/code&gt; and &lt;code&gt;__str__&lt;/code&gt; methods work. I also added simple
implementations of &lt;code&gt;__ne__&lt;/code&gt; and &lt;code&gt;__hash__&lt;/code&gt; to be consistnt with 
the &lt;code&gt;__eq__&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Getting this working was much easier than I expected it to be.
Here is the code: &lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import inspect

from decorator import decorator

class CaseMetaClass(type):
    def __new__(mcs, name, bases, dict):
        def noop(self):
            pass

        for meth in ('__eq__', '__ne__', '__hash__', '__str__'):
            if meth in dict:
                raise Exception('{} must not be defined on class.' % (meth))

        if '__init__' in dict:
            args, varargs, varkw, _ = inspect.getargspec(dict['__init__'])
            if varkw is not None:
                raise Exception("__init__ can't take **kwargs")
            args = args[1:]
        else:
            args = []
            varargs = None

        if args and varargs:
            raise Exception("Case class __init__ can't have both args (other than self) and *args")

        for arg in args + ([varargs] if varargs else []):
            if arg.startswith('_'):
                raise Exception("Case class attributes can't start with '_'.")
            dict[arg] = property(lambda self, arg=arg: getattr(self, '_' + arg))

        def _init(func, self, *init_args) :
            setattr(self, '_CaseMetaClass__args', init_args)
            if varargs:
                setattr(self, '_' + varargs, init_args)
            else:
                for (name, value) in zip(args, init_args):
                    setattr(self, '_' + name, value)
        dict['__init__'] = decorator(_init, dict.get('__init__', noop))

        def str(self):
            values = [repr(x) for x in getattr(self,'_CaseMetaClass__args')]
            return name + '(' + ', '.join(values) + ')'
        dict['__str__'] = str
        dict['__repr__'] = str

        def eq(self, other):
            if other is None:
                return False
            if type(self) is not type(other):
                return False
            return self._CaseMetaClass__args == other._CaseMetaClass__args
        dict['__eq__'] = eq

        dict['__ne__'] = lambda self, other: not (self == other)
        dict['__hash__'] = lambda self: hash(type(self)) ^ hash(self._CaseMetaClass__args)

        return type.__new__(mcs, name, bases, dict)
&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8400732-4684463751042382696?l=hwiechers.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hwiechers.blogspot.com/feeds/4684463751042382696/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8400732&amp;postID=4684463751042382696' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8400732/posts/default/4684463751042382696'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8400732/posts/default/4684463751042382696'/><link rel='alternate' type='text/html' href='http://hwiechers.blogspot.com/2010/08/case-classes-in-python.html' title='Case classes in Python'/><author><name>hwiechers</name><uri>http://www.blogger.com/profile/11242164300585745124</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8400732.post-3179976791053426254</id><published>2010-04-18T22:03:00.000-07:00</published><updated>2010-04-18T22:03:57.490-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server'/><title type='text'>UDFs and Underlying Schema Changes</title><content type='html'>&lt;p&gt;I had a problem at work recently where we changed a column's collation but a User Defined Function that referenced this column didn't reflect the updates and started complaining about collation conflicts. In this situation, most people (at least most people I know) recommend dropping the UDF and recreating it to force the UDF to update, but there is a better way.&lt;/p&gt;

&lt;p&gt;&lt;a href='http://msdn.microsoft.com/en-us/library/bb326754.aspx'&gt;sp_refreshsqlmodule&lt;/a&gt; will refresh the UDF in a single step and without the risk in dropping an object. The MSDN documentation for &lt;a href='http://msdn.microsoft.com/en-us/library/ms186755.aspx'&gt;CREATE FUNCTION&lt;/a&gt; (under Best Practices) recommends creating functions WITH SCHEMABINDING as an alternative.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8400732-3179976791053426254?l=hwiechers.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hwiechers.blogspot.com/feeds/3179976791053426254/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8400732&amp;postID=3179976791053426254' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8400732/posts/default/3179976791053426254'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8400732/posts/default/3179976791053426254'/><link rel='alternate' type='text/html' href='http://hwiechers.blogspot.com/2010/04/udfs-and-underlying-schema-changes.html' title='UDFs and Underlying Schema Changes'/><author><name>hwiechers</name><uri>http://www.blogger.com/profile/11242164300585745124</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8400732.post-5485576180462742067</id><published>2010-04-03T05:21:00.000-07:00</published><updated>2010-04-03T05:21:25.543-07:00</updated><title type='text'>Truth and Python 3: The 'and' and 'or' Operators</title><content type='html'>&lt;p&gt;The Python &lt;code&gt;and&lt;/code&gt; and &lt;code&gt;or&lt;/code&gt; operators are a little involved but work in a useful and helpful way. These operators combine two objects, called operands, into a single object. The operators can be of any type and aren't restricted to &lt;code&gt;bool&lt;/code&gt;. Python uses the keywords for these operators instead of the &amp;&amp; and || symbols common in other languages.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;and&lt;/code&gt; operator returns the first false operand or the last one if both operands and true. Some examples will make this clearer:&lt;/p&gt;

&lt;pre&gt;
&gt;&gt;&gt; '' and 0
''
&gt;&gt;&gt; 'x' and 0
0
&gt;&gt;&gt; 'x' and 1
1
&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;or&lt;/code&gt; operator returns the first true operand or the last one if both operands are false. Here are some examples:&lt;/p&gt;

&lt;pre&gt;
&gt;&gt;&gt; 'x' or 1
'x'
&gt;&gt;&gt; '' or 1
1
&gt;&gt;&gt; '' or 0
0
&lt;/pre&gt;

&lt;p&gt;Of course, &lt;code&gt;bool(x and y)&lt;/code&gt; will always be equal to &lt;code&gt;bool(x) and bool(y)&lt;/code&gt;. For this reason, &lt;code&gt;and&lt;/code&gt; operator will work as expected when used in conditional clauses. Similarly, &lt;code&gt;bool(x or y)&lt;/code&gt; will always be equal to &lt;code&gt;bool(x) or bool(y)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;
These operators are 'lazy' or 'short-circuiting'. The second operand is only evaluated if it would make a difference to the result. Here's an example:
&lt;/p&gt;

&lt;pre&gt;
&gt;&gt;&gt; def x():
...     print('x')
...     return True
...
&gt;&gt;&gt; def y():
...     print ('y')
...     return True
...
&gt;&gt;&gt; x() or y()
x
True
&lt;/pre&gt;

&lt;p&gt;In the example above &lt;code&gt;y&lt;/code&gt; isn't called since &lt;code&gt;x&lt;/code&gt; returns &lt;code&gt;True&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Logically &lt;code&gt;or&lt;/code&gt; will return the first operand if it's true, otherwise it will return the last. This means that or works like the null coalescing operator (&lt;code&gt;??&lt;/code&gt;) in C# and it's often used in that way. Here's a vague example:&lt;/p&gt;

&lt;pre&gt;
def some_method(some_parameter=None):
    some_parameter = some_parameter or get_default_value()
    # details...
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8400732-5485576180462742067?l=hwiechers.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hwiechers.blogspot.com/feeds/5485576180462742067/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8400732&amp;postID=5485576180462742067' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8400732/posts/default/5485576180462742067'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8400732/posts/default/5485576180462742067'/><link rel='alternate' type='text/html' href='http://hwiechers.blogspot.com/2010/04/truth-and-python-3-and-and-or-operators.html' title='Truth and Python 3: The &apos;and&apos; and &apos;or&apos; Operators'/><author><name>hwiechers</name><uri>http://www.blogger.com/profile/11242164300585745124</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8400732.post-7473012664942588125</id><published>2010-03-01T19:44:00.000-08:00</published><updated>2010-03-01T19:44:34.662-08:00</updated><title type='text'>Truth and Python 3: The if statement</title><content type='html'>&lt;p&gt;In it's basic form the Python if statement looks like this:&lt;/p&gt;

&lt;pre&gt;
if &lt;em&gt;expression&lt;/em&gt;:
    &lt;em&gt;statements&lt;/em&gt;
&lt;/pre&gt;

&lt;p&gt;If &lt;em&gt;expression&lt;/em&gt; is true, &lt;em&gt;statements&lt;/em&gt; are executed; otherwise &lt;em&gt;statements&lt;/em&gt; are skipped. &lt;em&gt;expression&lt;/em&gt; can be of any type; it doesn't have to evaluate to &lt;code&gt;True&lt;/code&gt; or &lt;code&gt;False&lt;/code&gt;. The if statement automatically converts &lt;em&gt;expression&lt;/em&gt; to &lt;code&gt;bool(expression)&lt;/code&gt; if needed.&lt;/p&gt;

&lt;p&gt;Unlike other languages, parenthesis are not required around &lt;em&gt;expression&lt;/em&gt;. In fact, it's considered bad style to include them.&lt;/p&gt;

&lt;p&gt;If &lt;em&gt;statements&lt;/em&gt; consists of a single statement, the whole &lt;code&gt;if&lt;/code&gt; statement may be written as one line:&lt;/p&gt;

&lt;pre&gt;if &lt;em&gt;expression&lt;/em&gt;: &lt;em&gt;statement&lt;/em&gt;&lt;/pre&gt;

&lt;h2&gt;The &lt;code&gt;else&lt;/code&gt; Clause&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;if&lt;/code&gt; statement can include an &lt;code&gt;else&lt;/code&gt; clause. The &lt;code&gt;else&lt;/code&gt; clause is optional; an &lt;code&gt;if&lt;/code&gt; statement doesn't have to have one.&lt;/p&gt;

&lt;pre&gt;
if &lt;em&gt;expression&lt;/em&gt;:
    &lt;em&gt;statements&lt;/em&gt;
else:
    &lt;em&gt;else-statements&lt;/em&gt;
&lt;/pre&gt;

&lt;p&gt;The &lt;em&gt;else-statements&lt;/em&gt; are executed if none of the other branches of the if statement are executed. In the case above, if &lt;em&gt;expression&lt;/em&gt; is false, &lt;em&gt;else-statements&lt;/em&gt; are executed.&lt;/p&gt;

&lt;h2&gt;The &lt;code&gt;elif&lt;/code&gt; Clauses&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;if&lt;/code&gt; statement can include one or more &lt;code&gt;elif&lt;/code&gt; or 'else-if' clauses. These clauses are also optional.&lt;/p&gt;

&lt;pre&gt;
if &lt;em&gt;expression&lt;/em&gt;:
    &lt;em&gt;statements&lt;/em&gt;
elif &lt;em&gt;elif-1-expression&lt;/em&gt;:
    &lt;em&gt;elif-1-statements&lt;/em&gt;
elif &lt;em&gt;elif-2-expression&lt;/em&gt;:
    &lt;em&gt;elif-2-statements&lt;/em&gt;
&lt;em&gt;more elif clauses...&lt;/em&gt;
&lt;/pre&gt;

&lt;p&gt;An &lt;code&gt;elif&lt;/code&gt; clause contains an expression and statements. The &lt;code&gt;elif&lt;/code&gt; statements are only examined if &lt;em&gt;expression&lt;/em&gt; is false. The interpretter starts going through the &lt;em&gt;elif&lt;/em&gt; conditions from top to bottom until it finds one that is true. It then executes the corresponding statements and exits the &lt;em&gt;if&lt;/em&gt; statement.&lt;/p&gt;

&lt;h2&gt;The &lt;code&gt;if&lt;/code&gt; Statement in Full&lt;/h2&gt;

&lt;p&gt;An &lt;code&gt;if&lt;/code&gt; statement may include both &lt;code&gt;elif&lt;/code&gt; clauses and an &lt;code&gt;else&lt;/code&gt; clause. The complete form of the &lt;code&gt;if&lt;/code&gt; statement looks like this:&lt;/p&gt;

&lt;pre&gt;
if &lt;em&gt;expression&lt;/em&gt;:
    &lt;em&gt;statements&lt;/em&gt;
elif &lt;em&gt;elif-1-expression&lt;/em&gt;:
    &lt;em&gt;elif-1-statements&lt;/em&gt;
elif &lt;em&gt;elif-2-expression&lt;/em&gt;:
    &lt;em&gt;elif-2-statements&lt;/em&gt;
&lt;em&gt;more elif clauses...&lt;/em&gt;
else:
    &lt;em&gt;else-statement&lt;/em&gt;
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8400732-7473012664942588125?l=hwiechers.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hwiechers.blogspot.com/feeds/7473012664942588125/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8400732&amp;postID=7473012664942588125' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8400732/posts/default/7473012664942588125'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8400732/posts/default/7473012664942588125'/><link rel='alternate' type='text/html' href='http://hwiechers.blogspot.com/2010/03/truth-and-python-3-if-statement.html' title='Truth and Python 3: The if statement'/><author><name>hwiechers</name><uri>http://www.blogger.com/profile/11242164300585745124</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8400732.post-2330074262321332329</id><published>2010-01-31T07:28:00.000-08:00</published><updated>2010-01-31T07:29:39.870-08:00</updated><title type='text'>Truth and Python 3: The bool Type</title><content type='html'>&lt;p&gt;Python 3 has a &lt;code&gt;bool&lt;/code&gt; type representing Boolean values. There are two builtin &lt;code&gt;bool&lt;/code&gt; constants, &lt;code&gt;True&lt;/code&gt; and &lt;code&gt;False&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For legacy reasons, &lt;code&gt;bool&lt;/code&gt; is actually a subtype of &lt;code&gt;int&lt;/code&gt; and  &lt;code&gt;True&lt;/code&gt; behaves like &lt;code&gt;1&lt;/code&gt; while &lt;code&gt;False&lt;/code&gt; behaves like &lt;code&gt;0&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For example,&lt;/p&gt;
&lt;pre&gt;
&gt;&gt;&gt; True + 0
1
&gt;&gt;&gt; False * 3
0
&lt;/pre&gt;
&lt;p&gt;and even...&lt;/p&gt;
&lt;pre&gt;
&gt;&gt;&gt; True == 1
True
&lt;/pre&gt;
The main difference between &lt;code&gt;True&lt;/code&gt; and &lt;code&gt;1&lt;/code&gt; is that &lt;code&gt;str(True)&lt;/code&gt; returns &lt;code&gt;'True'&lt;/code&gt; and not &lt;code&gt;'1'&lt;/code&gt;. Similarly, &lt;code&gt;str(False)&lt;/code&gt; returns &lt;code&gt;'False'&lt;/code&gt; and not &lt;code&gt;'0'&lt;code&gt;.
&lt;/p&gt;

&lt;p&gt;Any object can be converted to &lt;code&gt;bool&lt;/code&gt; by running it through the &lt;code&gt;bool&lt;/code&gt; constructor. Here are some examples:&lt;/p&gt;
&lt;pre&gt;
&gt;&gt;&gt; bool(True)
True
&gt;&gt;&gt; bool(None)
False
&gt;&gt;&gt; bool([])
False
&lt;/pre&gt;

&lt;p&gt;For any object, &lt;code&gt;x&lt;/code&gt;, if &lt;code&gt;bool(x)&lt;/code&gt; is &lt;code&gt;True&lt;/code&gt;, we say it's truth value is true and we consider &lt;code&gt;x&lt;/code&gt; as true in a Boolean context. If &lt;code&gt;bool(x)&lt;/code&gt; is &lt;code&gt;False&lt;/code&gt;, we say it's truth value is false and we consider it as false in a Boolean context.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;x&lt;/code&gt;'s  truth value is determined as follows:&lt;/p&gt;
&lt;ol&gt;
    &lt;li&gt;If x is &lt;code&gt;None&lt;/code&gt;, it's false&lt;/li&gt;
    &lt;li&gt;If &lt;code&gt;x&lt;/code&gt; defines a &lt;code&gt;__bool__&lt;/code&gt; method that returns &lt;code&gt;False&lt;/code&gt; or &lt;code&gt;0&lt;/code&gt;, it's false.
    &lt;li&gt;If &lt;code&gt;x&lt;/code&gt; doesn't define a &lt;code&gt;__bool__&lt;/code&gt; method but defines a &lt;code&gt;__len__&lt;/code&gt; method that returns 0, it's false.&lt;/li&gt;
    &lt;li&gt;Otherwise, it's true&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Given the rules above, it's no surprise that the vast majority of objects are considered true. The main ones that are considered false are:&lt;/p&gt;
&lt;ul&gt;
   &lt;li&gt;None&lt;/li&gt;
   &lt;li&gt;False&lt;/li&gt;
   &lt;li&gt;The zero value of each numeric type i.e. &lt;code&gt;0&lt;/code&gt;, &lt;code&gt;0.0&lt;/code&gt;, &lt;code&gt;0+0j&lt;/code&gt;&lt;/li&gt;
   &lt;li&gt;Empty containers e.g. &lt;code&gt;()&lt;/code&gt;, &lt;code&gt;{}&lt;/code&gt; and &lt;code&gt;[]&lt;/code&gt;.&lt;/li&gt;
   &lt;li&gt;"" (the empty string)&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/8400732-2330074262321332329?l=hwiechers.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hwiechers.blogspot.com/feeds/2330074262321332329/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8400732&amp;postID=2330074262321332329' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8400732/posts/default/2330074262321332329'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8400732/posts/default/2330074262321332329'/><link rel='alternate' type='text/html' href='http://hwiechers.blogspot.com/2010/01/truth-and-python-3-bool-type.html' title='Truth and Python 3: The bool Type'/><author><name>hwiechers</name><uri>http://www.blogger.com/profile/11242164300585745124</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8400732.post-164955209909457473</id><published>2010-01-17T05:12:00.000-08:00</published><updated>2010-01-17T05:12:27.430-08:00</updated><title type='text'>FireFox without a Mouse</title><content type='html'>&lt;p&gt;I finished reading The Productive Programmer a few weeks ago and since then I've been thinking about how to be more productive on the 'micro' level.&lt;/p&gt; 

&lt;p&gt;"Keep you hands on the keyboard as much as possible" is one of the recommendations that people always make. Constantly moving your hand from keyboard to mouse and back slows you down and feels pretty awkward too.&lt;/p&gt;

&lt;p&gt;With that in mind, I've been learning how to browse with FireFox using the keyboard only. Some sites make this difficult but I can now go for much quite a while without reaching for the mouse.&lt;/p&gt;

&lt;p&gt;Here are some basic tasks and how to do them with the keyboard. Note that I've chosen the methods and shortcuts that I like best and that there are other ways of doing these things.&lt;/p&gt;

&lt;h2&gt;Entering an Address&lt;/h2&gt;
&lt;ol&gt;
    &lt;li&gt;Use &lt;code&gt;alt+d&lt;/code&gt; to focus the Location bar&lt;/li&gt;
    &lt;li&gt;Type the URL&lt;/li&gt;
    &lt;li&gt;Press &lt;code&gt;enter&lt;/code&gt; to open the URL.&lt;br/&gt;
        You can hold these keys down to modify the behavior:
        &lt;ul&gt;
            &lt;li&gt;&lt;code&gt;ctrl&lt;/code&gt; - prepend &lt;em&gt;www.&lt;/em&gt; and append &lt;em&gt;.com&lt;/em&gt; to the address&lt;/li&gt;
            &lt;li&gt;&lt;code&gt;shift&lt;/code&gt; - prepend &lt;em&gt;www.&lt;/em&gt; and append &lt;em&gt;.net&lt;/em&gt; to the address&lt;/li&gt;
            &lt;li&gt;&lt;code&gt;ctrl+shift&lt;code&gt; - prepend &lt;em&gt;www.&lt;/em&gt; and append &lt;em&gt;.org&lt;/em&gt; to the address&lt;/li&gt;
            &lt;li&gt;&lt;code&gt;alt&lt;/code&gt; - open in a new tab&lt;/li&gt;
        &lt;/ul&gt;
        For example, pressing &lt;code&gt;ctrl+shift+alt+enter&lt;/code&gt; with an address of &lt;em&gt;python&lt;/em&gt; will open &lt;em&gt;www.python.org&lt;/em&gt; in a new tab.
    &lt;/li&gt;     
&lt;/ol&gt;

&lt;h2&gt;Searching&lt;/h2&gt;
&lt;ol&gt;
    &lt;li&gt;Use &lt;code&gt;ctrl+k&lt;/code&gt; to focus the Search bar&lt;/li&gt;
    &lt;li&gt;Type the search terms&lt;/li&gt;
    &lt;li&gt;Press &lt;code&gt;enter&lt;/code&gt; to open the search in the current tab&lt;br/&gt;
        You can hold down &lt;code&gt;alt&lt;/code&gt; to open the search in a new tab instead&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;Navigating between tabs&lt;/h2&gt;
&lt;p&gt;On Ubuntu these shortcuts use alt instead of ctrl.&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;code&gt;ctrl+tab&lt;/code&gt; displays the next tab&lt;/li&gt;
    &lt;li&gt;&lt;code&gt;shift+ctrl+tab&lt;/code&gt; displays the previous tab&lt;/li&gt;
    &lt;li&gt;&lt;code&gt;ctrl+n&lt;/code&gt; where n is the digit 1 to 8 displays the nth tab&lt;/li&gt;
    &lt;li&gt;&lt;code&gt;ctrl+9&lt;/code&gt; displays the last tab&lt;/li&gt;
    &lt;li&gt;&lt;code&gt;ctrl+w&lt;/code&gt; closes the current tab&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Searching within a page&lt;/h2&gt; 
&lt;ol&gt;
    &lt;li&gt;Use &lt;code&gt;/&lt;/code&gt; to open the Quick Find bar&lt;/li&gt;
    &lt;li&gt;Type the search text&lt;/li&gt;
    &lt;li&gt;Use &lt;code&gt;F3&lt;/code&gt; to cycle forward and &lt;code&gt;shift+F3&lt;/code&gt; to cycle backward through the matches&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;'Clicking' on links&lt;/h2&gt;
&lt;ol&gt;
    &lt;li&gt;Use &lt;code&gt;'&lt;/code&gt; to open the Quick Find bar for links only&lt;/li&gt;
    &lt;li&gt;Type the search text&lt;/li&gt;
    &lt;li&gt;Use &lt;code&gt;F3&lt;/code&gt; and &lt;code&gt;shift+F3&lt;/code&gt; to cycle to focus the link you desire&lt;/li&gt;
    &lt;li&gt;Hit &lt;code&gt;enter&lt;/code&gt; to 'click' the link. The following modifiers are available:
        &lt;ul&gt;
            &lt;li&gt;&lt;code&gt;shift&lt;/code&gt; - open the page in a new window&lt;/li&gt;
            &lt;li&gt;&lt;code&gt;ctrl&lt;/code&gt; - open the page in a new tab&lt;/li&gt;
            &lt;li&gt;&lt;code&gt;alt&lt;/code&gt; - save the page instead of opening it&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/li&gt;
&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8400732-164955209909457473?l=hwiechers.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hwiechers.blogspot.com/feeds/164955209909457473/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8400732&amp;postID=164955209909457473' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8400732/posts/default/164955209909457473'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8400732/posts/default/164955209909457473'/><link rel='alternate' type='text/html' href='http://hwiechers.blogspot.com/2010/01/firefox-without-mouse.html' title='FireFox without a Mouse'/><author><name>hwiechers</name><uri>http://www.blogger.com/profile/11242164300585745124</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8400732.post-4244648180272932988</id><published>2009-12-26T08:52:00.000-08:00</published><updated>2009-12-26T08:53:16.494-08:00</updated><title type='text'>Changing Your Domain Password When Your PC is not on the Domain</title><content type='html'>&lt;p&gt;Recently, I had to change my domain password from a desktop wasn't on the domain. The solution I found was to terminal service into a server with my domain account and use Ctrl+Alt+End to bring up the Windows Security menu and select Change Password.&lt;/p&gt;

&lt;p&gt;This took me way longer to figure out than I'd like to admit.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8400732-4244648180272932988?l=hwiechers.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hwiechers.blogspot.com/feeds/4244648180272932988/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8400732&amp;postID=4244648180272932988' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8400732/posts/default/4244648180272932988'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8400732/posts/default/4244648180272932988'/><link rel='alternate' type='text/html' href='http://hwiechers.blogspot.com/2009/12/changing-your-domain-password-when-your.html' title='Changing Your Domain Password When Your PC is not on the Domain'/><author><name>hwiechers</name><uri>http://www.blogger.com/profile/11242164300585745124</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8400732.post-4813476821872179375</id><published>2009-12-19T06:07:00.000-08:00</published><updated>2009-12-19T06:10:13.144-08:00</updated><title type='text'>?? Operator Precedence in C#</title><content type='html'>&lt;p&gt;I've been stung by this a few times in the last month.&lt;/p&gt;

&lt;p&gt;The ?? (Null coalescing operator) has a really low precedence in C#. It's well below the arithmetic operators. In fact, it's second from the bottom according to &lt;a href="http://msdn.microsoft.com/en-us/library/ms173145.aspx"&gt;MSDN.&lt;/a&gt; For some reason, I expected it to be quite high.&lt;/p&gt;

&lt;p&gt;Take this code as an example.&lt;/p&gt;

&lt;pre class="brush: csharp;"&gt;
    int? x = 10;
    int? y = 10;

    Console.WriteLine(x ?? y + 1);
&lt;/pre&gt;

Previously, I'd expect this to print 11. It actually prints 10 (since &lt;code&gt;x ?? y + 1&lt;/code&gt; is equivalent to &lt;code&gt;x ?? (y + 1)&lt;/code&gt;).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8400732-4813476821872179375?l=hwiechers.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hwiechers.blogspot.com/feeds/4813476821872179375/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8400732&amp;postID=4813476821872179375' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8400732/posts/default/4813476821872179375'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8400732/posts/default/4813476821872179375'/><link rel='alternate' type='text/html' href='http://hwiechers.blogspot.com/2009/12/operator-precedence-in-c.html' title='?? Operator Precedence in C#'/><author><name>hwiechers</name><uri>http://www.blogger.com/profile/11242164300585745124</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8400732.post-4420277771708422902</id><published>2009-12-15T19:03:00.000-08:00</published><updated>2009-12-15T19:03:51.719-08:00</updated><title type='text'>Easy Backups with rsync: Part 3 of 3</title><content type='html'>&lt;p&gt;In this part we'll write a back up script and finish up.&lt;/p&gt;

&lt;p&gt;
Boot up off your USB flash drive. Now you need to figure out which drives you want to back up and what they are called in /dev. In puppy this is a piece of cake. An icon for each device is displayed at the bottom of the desktop. Clicking on the icon mounts the device as /mnt/&amp;lt;device name&amp;gt; and opens a file explorer on that drive. All you need to do is click through the devices until you find the ones you want.
&lt;/p&gt;

&lt;p&gt;
Now you need to write the rsync script. Here is mine:
&lt;/p&gt;

&lt;pre&gt;
backup.sh
---------
rsync -rltDvP /mnt/sda1/Users/Henri/ /mnt/sde1/backups/windows/
rsync -rltDvP /mnt/sdc3/henri/ /mnt/sde1/backups/ubuntu/
&lt;/pre&gt;

&lt;p&gt;
I use this to backup the home directories on my Windows and Ubuntu partitions. Before I run this, I ensure that both sda1 and sdc3 are mounted and my backup drive is mounted at sde1. 
&lt;/p&gt;

&lt;p&gt;Note that the trailing slashes on the paths are important. Otherwise the source folder will copied into the destination.&lt;/p&gt;

&lt;p&gt;
The switches were chosen to make a copy of the source directory recursively(-r), with symlinks copied as symlinks (-l) and modification times preserved(-t). The verbose messages (-v) and progress indicators (-P) are turned on. This is equivalent to the archive (-a) option but without preserving permissions, ownership and file groups. Because I'm backing up onto a NTFS drive, those options don't work correctly. (Ultimately I'll add the --delete flag to delete files in the destination not present in the source.)
&lt;/p&gt;

&lt;p&gt;
Now save the script and you're ready. Once a week follow the steps given the &lt;a href="http://hwiechers.blogspot.com/2009/11/easy-backups-with-rsync-part-1-of-3.html"&gt;Part 1&lt;/a&gt; and your backups are sorted.
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8400732-4420277771708422902?l=hwiechers.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hwiechers.blogspot.com/feeds/4420277771708422902/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8400732&amp;postID=4420277771708422902' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8400732/posts/default/4420277771708422902'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8400732/posts/default/4420277771708422902'/><link rel='alternate' type='text/html' href='http://hwiechers.blogspot.com/2009/12/easy-backups-with-rsync-part-3-of-3.html' title='Easy Backups with rsync: Part 3 of 3'/><author><name>hwiechers</name><uri>http://www.blogger.com/profile/11242164300585745124</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8400732.post-2896911906344512404</id><published>2009-12-07T11:26:00.000-08:00</published><updated>2009-12-07T11:26:50.760-08:00</updated><title type='text'>Easy Backups with rsync: Part 2 of 3</title><content type='html'>&lt;p&gt;In this part I'll give pointer on how to install some version of Linux onto a USB flash drive.&lt;/p&gt;

&lt;p&gt;The idea is to be able to boot off the drive and run the backups from there. The set up must have "persistence" i.e. you need to be able to save files to the drive. Not every set up of Linux supports this - some of the Live USB versions are read-only. I use &lt;a href="http://www.puppylinux.org/"&gt;PuppyLinux&lt;/a&gt; because it's easy to set up and has quite a pleasant UI. There are many alternatives but most require quite a bit of effort to get working.&lt;/p&gt;

&lt;p&gt;Get a smallish USB stick and follow the installation instructions over &lt;a href="http://www.puppylinux.com/flash-puppy.htm"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In the next part, I'll detail how to write the backup script.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8400732-2896911906344512404?l=hwiechers.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hwiechers.blogspot.com/feeds/2896911906344512404/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8400732&amp;postID=2896911906344512404' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8400732/posts/default/2896911906344512404'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8400732/posts/default/2896911906344512404'/><link rel='alternate' type='text/html' href='http://hwiechers.blogspot.com/2009/12/easy-backups-with-rsync-part-2-of-3.html' title='Easy Backups with rsync: Part 2 of 3'/><author><name>hwiechers</name><uri>http://www.blogger.com/profile/11242164300585745124</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8400732.post-4275921649032882630</id><published>2009-11-29T00:23:00.000-08:00</published><updated>2009-11-29T00:23:58.479-08:00</updated><title type='text'>Easy Backups with rsync: Part 1 of 3</title><content type='html'>&lt;p&gt;The most important thing about a home backup strategy is to make sure that the back ups &lt;em&gt;actually get done&lt;/em&gt;. You're more likely to get this right if your process is simple and easy and if you make it part of your routine.&lt;/p&gt;

&lt;p&gt;My strategy is to maintain mirrors of my home directories on an external hard drive. The process uses only free software but takes some effort to get set up.&lt;/p&gt;

&lt;p&gt;The process has 4 steps.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Shutdown&lt;/li&gt;
&lt;li&gt;Boot up Linux off a flash drive&lt;/li&gt;
&lt;li&gt;Plug in an external drive&lt;/li&gt;
&lt;li&gt;Run a backup script&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The backup script mounts the target drives and uses rsync to mirror the home directories on  them onto the external drive.&lt;/p&gt;

&lt;p&gt;To set this up you need to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Have an external drive with sufficient capacity&lt;/li&gt;
&lt;li&gt;Have bootable flash drive with some flavor of Linux on it&lt;/li&gt;
&lt;li&gt;Write a backup script&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In the next post I'll detail how to get Linux on a bootable flash drive.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8400732-4275921649032882630?l=hwiechers.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hwiechers.blogspot.com/feeds/4275921649032882630/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8400732&amp;postID=4275921649032882630' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8400732/posts/default/4275921649032882630'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8400732/posts/default/4275921649032882630'/><link rel='alternate' type='text/html' href='http://hwiechers.blogspot.com/2009/11/easy-backups-with-rsync-part-1-of-3.html' title='Easy Backups with rsync: Part 1 of 3'/><author><name>hwiechers</name><uri>http://www.blogger.com/profile/11242164300585745124</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8400732.post-3339047690142351472</id><published>2009-11-03T21:12:00.000-08:00</published><updated>2009-11-03T21:12:19.415-08:00</updated><title type='text'>Book Review: The Mythical Man-Month</title><content type='html'>&lt;p&gt;I finished reading the &lt;a href="http://en.wikipedia.org/wiki/Mythical_man_month"&gt;Mythical Man Month&lt;/a&gt; last week. I bought the &lt;a href="http://www.amazon.com/gp/product/0201835959?ie=UTF8&amp;tag=hwiechers-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0201835959"&gt;20th Anniversary Edition&lt;/a&gt;&lt;img src="http://www.assoc-amazon.com/e/ir?t=hwiechers-20&amp;l=as2&amp;o=1&amp;a=0201835959" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /&gt;
which includes the famous 'No Silver Bullet' essay and some updated content. This must be the oldest coding-related book I have ever bought - even that anniversary edition was published more than 10 years ago!&lt;/p&gt; 

&lt;p&gt;The Mythical Man-Month has stood the test of time. In spite of it's age, it's still read and quoted today. If you've been a programmer for a decent length of time you will have come across discussions and references to it. This is the book that introduced &lt;a href="http://en.wikipedia.org/wiki/Brooks%27s_law"&gt;Brooks' Law&lt;/a&gt;, &lt;a href="http://en.wikipedia.org/wiki/Second-system_effect"&gt;Second-System Syndrome&lt;/a&gt;  and made the much debated recommendation to 'plan to throw one away'. It's also the second book on the Coding Horror &lt;a href="http://www.codinghorror.com/blog/archives/000020.html"&gt;recommended reading list&lt;/a&gt;. Baring in mind how fast technology changes, it is arguably a classic book in the true sense of the word.&lt;/p&gt;

&lt;p&gt;That said, I have mixed feelings about MM-M. The book contains some timeless insights but, unfortunately, whole chapters are completely irrelevant to today's coders. The information is just too dated and obsolete. For example, there is a whole chapter about managing paper based documentation systems including tips about microfiche and page numbering.&lt;/p&gt;

&lt;p&gt;Buy MM-M if you're looking for a historical perspective on the craft. If you're purely looking for a practical book on programming practices, try &lt;a href="http://www.amazon.com/gp/product/0735619670?ie=UTF8&amp;tag=hwiechers-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0735619670"&gt;Code Complete&lt;/a&gt;&lt;img src="http://www.assoc-amazon.com/e/ir?t=hwiechers-20&amp;l=as2&amp;o=1&amp;a=0735619670" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /&gt;
 instead.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8400732-3339047690142351472?l=hwiechers.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hwiechers.blogspot.com/feeds/3339047690142351472/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8400732&amp;postID=3339047690142351472' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8400732/posts/default/3339047690142351472'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8400732/posts/default/3339047690142351472'/><link rel='alternate' type='text/html' href='http://hwiechers.blogspot.com/2009/11/book-review-mythical-man-month.html' title='Book Review: The Mythical Man-Month'/><author><name>hwiechers</name><uri>http://www.blogger.com/profile/11242164300585745124</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8400732.post-2756019064594225033</id><published>2009-11-01T19:38:00.000-08:00</published><updated>2009-11-01T19:39:55.991-08:00</updated><title type='text'>Dude, Where's My Powershell 2.0?</title><content type='html'>&lt;p&gt;Yesterday, I installed PowerShell 2.0 but encountered some issues that had me scratching my head. After I installed it, I couldn't find it.&lt;/p&gt;

&lt;p&gt;I grabbed the latest installer listed on &lt;a href="http://blogs.msdn.com/powershell/pages/download-windows-powershell.aspx"&gt;download page&lt;/a&gt; and ran it. It completed and then... nothing. I checked under my start menu and I couldn't see any new items. I found the PowerShell 1.0 directory (C:\WINDOWS\system32\windowspowershell\v1.0) but I couldn't find a 2.0 directory. It looked as if the installer didn't install 2.0 at all!&lt;/p&gt;

&lt;p&gt;After reading the release notes and some fussing, I found out that 2.0 was, in fact, installed. The short cuts are placed unders 'All Programs' &gt; 'Accessories' and the new files are installed in the 1.0 directory over the previous version.&lt;/p&gt;

&lt;p&gt;I wonder if anyone else was confused by this.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8400732-2756019064594225033?l=hwiechers.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hwiechers.blogspot.com/feeds/2756019064594225033/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8400732&amp;postID=2756019064594225033' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8400732/posts/default/2756019064594225033'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8400732/posts/default/2756019064594225033'/><link rel='alternate' type='text/html' href='http://hwiechers.blogspot.com/2009/11/dude-wheres-my-powershell-20.html' title='Dude, Where&apos;s My Powershell 2.0?'/><author><name>hwiechers</name><uri>http://www.blogger.com/profile/11242164300585745124</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8400732.post-6851684832263333135</id><published>2009-10-18T09:08:00.000-07:00</published><updated>2009-10-18T09:11:50.320-07:00</updated><title type='text'>Live Expressions With Obtics</title><content type='html'>&lt;p&gt;I'm busy working on a WPF app that's replacing a Excel spreadsheet solution. It involves lots of summary stats (sums, averages etc.) against a set of items. As the items are editted the changes need to be detected and the stats have to be updated so that the user can see the affects of his changes.&lt;/p&gt;&lt;p&gt;The normal way of doing this is to make the items implement INotifyPropertyChanged and then listen to changed in the properties that the stats are dependent on. As the stats get more complicated this gets more and more complicated and error prone.&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.codeplex.com/Obtics"&gt;Obtics&lt;/a&gt; is a library that makes this much easier.&lt;/p&gt;&lt;p&gt;Take the following example:&lt;/p&gt;&lt;pre class="brush: csharp;"&gt;public class Portfolio
{
  public Portfolio()
  {
    Holdings = new ObservableCollection&amp;lt;Holding&amp;gt;();
  }

  public ObservableCollection&amp;lt;Holding&amp;gt; Holdings { get; private set; }
}

public sealed class Holding : INotifyPropertyChanged
{
  private int quantity;
  private Stock stock;

  public int Quantity
  {
    get 
    {
      return quantity;
    }
    set
    {
      if (quantity == value) 
      {
        return;
      }
      quantity = value;
      OnPropertyChanged("Quantity");
    }
  }

  public Stock Stock
  {
    get
    {
      return stock;
    }
    set
    {
      if (stock == value) 
      {
        return;
      }
      stock = value;
      OnPropertyChanged("Stock");
    }
  }  

  private void OnPropertyChanged(string propertyName)
  {
    var handler = PropertyChanged;
    if (handler != null) 
    {
      handler(this, new PropertyChangedEventArgs(propertyName));
    }
  }

  public event PropertyChangedEventHandler PropertyChanged;
}

public sealed class Stock : INotifyPropertyChanged
{
  private decimal price;

  public decimal Price
  {
    get
    {
      return price;
    }
    set
    {
      if (price == value) 
      {
        return;
      }
      price = value;
      OnPropertyChanged("Price");
    }
  }  

  private void OnPropertyChanged(string propertyName)
  {
    var handler = PropertyChanged;
    if (handler != null) 
    {
      handler(this, new PropertyChangedEventArgs(propertyName));
    }
  }

  public event PropertyChangedEventHandler PropertyChanged;
}&lt;/pre&gt;&lt;p&gt;If I want the value of the portfolio I can write this:&lt;br /&gt;
&lt;/p&gt;&lt;pre class="brush: csharp;"&gt;var portfolioValue = Obtics.Values.ExpressionObserver.Execute(() =&gt; porfolio.Holdings.Sum( x =&gt; x.Quantity * x.Stock.Price));
&lt;/pre&gt;&lt;p&gt;portfolioValue is of the type IValueProvider and portfolioValue.Value will give the current value of expression. The real magic is that Obtics analyzes the expression and automatically refreshes the value when the inputs change. In this example, adding and removing holdings, changing the holding quantities and even the stock prices will cause the value to update. If you did that by listening to the PropertyChanged events, it would take 10 times the amounts of code.&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;portfolioValue can also be cast to INotifyPropertyChanged, so porfolioValue.Value can be bound in WPF.&lt;br /&gt;
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8400732-6851684832263333135?l=hwiechers.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hwiechers.blogspot.com/feeds/6851684832263333135/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8400732&amp;postID=6851684832263333135' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8400732/posts/default/6851684832263333135'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8400732/posts/default/6851684832263333135'/><link rel='alternate' type='text/html' href='http://hwiechers.blogspot.com/2009/10/live-expressions-with-obtics.html' title='Live Expressions With Obtics'/><author><name>hwiechers</name><uri>http://www.blogger.com/profile/11242164300585745124</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8400732.post-8941759002025413754</id><published>2009-10-11T03:09:00.000-07:00</published><updated>2009-10-17T12:37:09.856-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server'/><title type='text'>Deleting a Column's Default Constraints</title><content type='html'>At work I recently had the problem where I needed to drop some columns that had default constraints which had generated names. Here is the set up:&lt;br /&gt;
&lt;pre class="brush: sql;"&gt;CREATE TABLE ExampleTable ( 
    ExampleColumn int NOT NULL DEFAULT 0,
    OtherColumn int NULL)
GO

ALTER TABLE ExampleTable
    DROP COLUMN ExampleColumn
GO

Msg 5074, Level 16, State 1, Server HENRI-XP\SQLEXPRESS, Line 1
The object 'DF__ExampleTa__Examp__7E6CC920' is dependent on column 'ExampleColumn'.
Msg 4922, Level 16, State 9, Server HENRI-XP\SQLEXPRESS, Line 1
ALTER TABLE DROP COLUMN ExampleColumn failed because one or more objects access this column.
&lt;/pre&gt;At this point I could have just dropped the constraint using the name in the error message, however I had to apply the same change to multiple databases with the same schema. Of course, the generated name was different for each database.&lt;br /&gt;
&lt;br /&gt;
I ended up writing a procedure that would look up the default constraint given a table name and column name in the sys views and drop it. It's pretty simple here is the code: &lt;br /&gt;
&lt;pre class="brush: sql;"&gt;CREATE PROC dbo.DropDefaultConstraint
    @TableName sysname,
    @ColumnName sysname
AS
    DECLARE @defaultConstraintName sysname;

    SELECT @defaultConstraintName = OBJECT_NAME(default_object_id)
    FROM sys.columns
    WHERE object_id = OBJECT_ID(@TableName) and name = @ColumnName

    IF(@defaultConstraintName IS NOT NULL)
    BEGIN
        EXEC ('ALTER TABLE ' + @TableName + ' DROP CONSTRAINT ' + @defaultConstraintName);
    END;
GO
&lt;/pre&gt;Of course, this isn't the kind of procedure you'd actually deploy to a production server, but it's handy anyway.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8400732-8941759002025413754?l=hwiechers.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hwiechers.blogspot.com/feeds/8941759002025413754/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8400732&amp;postID=8941759002025413754' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8400732/posts/default/8941759002025413754'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8400732/posts/default/8941759002025413754'/><link rel='alternate' type='text/html' href='http://hwiechers.blogspot.com/2009/10/deleting-columns-default-constraints.html' title='Deleting a Column&apos;s Default Constraints'/><author><name>hwiechers</name><uri>http://www.blogger.com/profile/11242164300585745124</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8400732.post-8797968003903255692</id><published>2009-09-30T21:17:00.000-07:00</published><updated>2009-10-11T03:16:06.237-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.net'/><category scheme='http://www.blogger.com/atom/ns#' term='SharpDev'/><title type='text'>SharpDevelop Rocks</title><content type='html'>I'm starting a little OSS project and was thinking about writing it with a free IDE. C# Express was my first thought but I decided to try out &lt;a href="http://www.sharpdevelop.com/OpenSource/SD/"&gt;SharpDev&lt;/a&gt;. &lt;br /&gt;
&lt;br /&gt;
I last looked at SharpDev out a couple of years ago and wasn't too impressed. It seemed a quite unpolished and a little incomplete. Things have changed - alot! The latest version, 3.1, was released just last month and it's brilliant. It can do WPF apps. It has an integrated debugger. It supports IronPython. It even has a profiler!&lt;br /&gt;
&lt;br /&gt;
I'm definitely using this thing.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8400732-8797968003903255692?l=hwiechers.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hwiechers.blogspot.com/feeds/8797968003903255692/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8400732&amp;postID=8797968003903255692' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8400732/posts/default/8797968003903255692'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8400732/posts/default/8797968003903255692'/><link rel='alternate' type='text/html' href='http://hwiechers.blogspot.com/2009/09/sharpdevelop-rocks.html' title='SharpDevelop Rocks'/><author><name>hwiechers</name><uri>http://www.blogger.com/profile/11242164300585745124</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8400732.post-1577673532266758770</id><published>2009-09-06T05:47:00.001-07:00</published><updated>2009-09-06T05:58:38.913-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><title type='text'>Installing Easy_Install and setuptools on Windows 7 64-bit/Python 2.6</title><content type='html'>&lt;p&gt;This procedure worked for me.&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Download ez_setup.py from the &lt;a href="http://peak.telecommunity.com/"&gt;PEAK&lt;/a&gt; site. (I found it here: &lt;a href="http://peak.telecommunity.com/dist/ez_setup.py"&gt;http://peak.telecommunity.com/dist/ez_setup.py&lt;/a&gt;.)&lt;/li&gt;&lt;li&gt;Run it!&lt;/li&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8400732-1577673532266758770?l=hwiechers.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hwiechers.blogspot.com/feeds/1577673532266758770/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8400732&amp;postID=1577673532266758770' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8400732/posts/default/1577673532266758770'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8400732/posts/default/1577673532266758770'/><link rel='alternate' type='text/html' href='http://hwiechers.blogspot.com/2009/09/installing-easyinstall-and-setuptools.html' title='Installing Easy_Install and setuptools on Windows 7 64-bit/Python 2.6'/><author><name>hwiechers</name><uri>http://www.blogger.com/profile/11242164300585745124</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8400732.post-3693098658454989169</id><published>2009-04-05T12:31:00.001-07:00</published><updated>2009-10-18T00:16:47.578-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='linq'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Left Joins for 1 to 0..1 relationships in Linq</title><content type='html'>&lt;p&gt;Here is an example of doing a ‘left join’ between two classes with a 1 to 0..1 relationship between them.&lt;/p&gt;&lt;p&gt;We have an Employee class.&lt;/p&gt;&lt;pre class="brush: csharp;"&gt;public class Employee
{
    public Employee(int id, int? bossId)
    {
         Id = id;
         BossId = bossId;
    }

    public int Id { get; set; }
    public int? BossId { get; set; }
}&lt;/pre&gt;&lt;p&gt;And a collection of employees.&lt;/p&gt;&lt;pre class="brush: csharp;"&gt;var employees = new[] {
    new Employee(1, null),
    new Employee(2, 1),
    new Employee(3, 2),
    new Employee(4, 2)
};&lt;/pre&gt;&lt;p&gt;Each employee has 0 or 1 bosses.&lt;/p&gt;&lt;p&gt;Now to get a list of each employee and his boss, we can use the following linq query. (We want employee 1 to be in the list with a null boss.)&lt;/p&gt;&lt;pre class="brush: csharp;"&gt;var result =
from employee in employees
join boss in employees
on employee.BossId equals boss.Id
into employeeBosses
select new {
    Employee = employee,
    Boss = employeeBosses.SingleOrDefault()
};&lt;/pre&gt;&lt;p&gt;The trick is to perform a group join on the employee and his bosses and then use SingleOrDefault to collapse employeeBosses to a single item or null. &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8400732-3693098658454989169?l=hwiechers.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hwiechers.blogspot.com/feeds/3693098658454989169/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8400732&amp;postID=3693098658454989169' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8400732/posts/default/3693098658454989169'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8400732/posts/default/3693098658454989169'/><link rel='alternate' type='text/html' href='http://hwiechers.blogspot.com/2009/04/left-joins-for-1-to-01-relationships-in.html' title='Left Joins for 1 to 0..1 relationships in Linq'/><author><name>hwiechers</name><uri>http://www.blogger.com/profile/11242164300585745124</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
