The Occasional Occurence

Rebasing to a New Branch with Mercurial

July 09, 2010 at 08:53 AM | categories: Python, Software, work, computing, General

I had a situation at work the other day where I had made a number of local commits to the default branch of my repo. I wanted to push them upstream to our central server but the feature was incomplete and I didn't want to break anything in case someone needed to make a tweak to the current code in the default branch.

I had the idea to use the `hg rebase <http://mercurial.selenic.com/wiki/RebaseProject>`_ command to move all my local commits to a new branch before pushing. It worked, and here's how I did it.

  1. hg clone localrepo temp-localrepo. I always try crazy ideas in another local clone in case I trash the repo.
  2. hg up to the revision before my local commits that I want to put in a branch.
  3. hg branch newbranchname && hg ci -m "Branching for reason foo." This creates a new branch and head that can be used as a rebase destination.
  4. Now for the rebase. I needed to rebase the first changeset in my series of local changes onto the newbranchname changeset. Something like hg rebase --source 94 --dest 105.

That's about it. After verifying that it did what I wanted all that was left was to repeat the steps in my main local repo and push to the central server.*

cw

* Of course what I actually did was push these changes to my main local repo and then to the central repo. Woops. That left me with the changes both in ``default`` and in ``newbranchname``.

Don't do that. Repeat the steps after you've tried them in another local clone. I leave recovering from such a situation with ```hg strip <http://mercurial.selenic.com/wiki/Strip>`_`` as an exercise for the reader.

Getting Version Information from Mercurial

May 13, 2010 at 04:52 PM | categories: Python, work, computing, Software

In an application I'm working on at work I want to be able to display various bits of version information in the UI. This goes for both production deployments from Python EGG files and in development running straight out of the repository.

We use Mercurial for revision control so it is a logical choice for a version information source. The result of some hacking is my first Mercurial extension and commit hook.

Mercurial Version Info Plugin.

See the README file rendered at that link for the details. Click here to download version 1.0.

cw

Tagged Revision Log Messages in Mercurial

March 12, 2010 at 01:49 PM | categories: work, Software, computing, General

I work at YouGov and we use the Mercurial for revision control.

We tag every release in a MAJOR.MINOR.BUGFIX format. 2.32.2 for example.

Recently I wanted to get a summary of the commit log messages for each of the tagged revisions. Here is the magic command that got me the output that I wanted:

# get all log entries for releases tagged with a 2.31 MAJOR.MINOR
hg tags | grep 2\.31 | cut -c33-36 | xargs -L1 hg log -r

cw

Odd Old-Style vs. New-Style Class Behavior

May 21, 2009 at 10:55 AM | categories: Python, Software, work, computing, General

So we have some older Python code at work that uses old-style classes. We usually try and bring those up to date when we encounter them.

The other day one of the developers did that and one of our tests started failing. A simple change from:

class Foo:
    # stuff here

to:

class Foo(object):
    # stuff here

was all that happened.

Here is some code that encapsulates the problem and runs with some interesting results:

"""Two nearly identical classes with quite different behavior."""

class LameContainerOld:
    def __init__(self):
        self._items = {'bar':'test'}

    def __getitem__(self, name):
        return self._items[name]

    def __getattr__(self, attr):
        return getattr(self._items, attr)

class LameContainerNew(object):
    def __init__(self):
        self._items = {'bar':'test'}

    def __getitem__(self, name):
        return self._items[name]

    def __getattr__(self, attr):
        return getattr(self._items, attr)

if __name__ == '__main__':
    for cls in [LameContainerOld, LameContainerNew]:
        container = cls()
        print "Testing", cls
        try:
            'foo' in container
        except Exception, e:
            print "\tMembership in %s raised %r!" % (container.__class__, e)
        else:
            print "\tMembership in %s worked!" % container.__class__
        print "\t%s" % container.__getitem__

Here is some output from running that:

Testing __main__.LameContainerOld
        Membership in __main__.LameContainerOld worked!
            bound method LameContainerOld.__getitem__ of {'bar': 'test'}
Testing     class '__main__.LameContainerNew'
        Membership in     class '__main__.LameContainerNew'     raised KeyError(0,)!
            bound method LameContainerNew.__getitem__ of     __main__.LameContainerNew object at 0xb7d1c1ac

From what I can tell, when a membership test happens on the old-style instance, a membership test is done on self._items and it returns False. When the membership test happens on the new-style instance, it tries to treat it like a sequence and calls the __getitem__ method with index 0.

Does that seem like a correct analysis? Does anyone know why the behavior is different there?

Also look at the output for printing container.__getitem__. Isn't __getattr__ only supposed to be called when the attribute isn't present on the instance? Why does it return the __getitem__ method of self._items for the old-style instance then?

Very puzzling.

cw

Coffee Shop Bum

September 18, 2008 at 10:37 AM | categories: work, General

I've been working from Starbucks for the past few days while we've been without power from the remnants of Ike. Sounds like I'm not alone:

http://www.cnn.com/2008/US/09/17/ike.recovery.starbucks/index.html

UPDATE: My sister saved me from another afternoon at Starbucks and put me up in a temporary office at KSU*. Hooray!

* My sister designed their website, btw.

Next Page ยป