<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Tom E Stephens</title>
	<atom:link href="http://tomestephens.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://tomestephens.com</link>
	<description>Whatever interests me</description>
	<lastBuildDate>Wed, 19 Jun 2013 18:33:56 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.5.1</generator>
		<item>
		<title>ETW Manifest Registration</title>
		<link>http://tomestephens.com/2013/06/etw-manifest-registration/</link>
		<comments>http://tomestephens.com/2013/06/etw-manifest-registration/#comments</comments>
		<pubDate>Wed, 19 Jun 2013 18:33:14 +0000</pubDate>
		<dc:creator>Tom</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Tools]]></category>
		<category><![CDATA[Windows APIs]]></category>
		<category><![CDATA[ETW]]></category>
		<category><![CDATA[github]]></category>
		<category><![CDATA[Open source]]></category>
		<category><![CDATA[utilities]]></category>

		<guid isPermaLink="false">http://tomestephens.com/?p=141</guid>
		<description><![CDATA[In a previous post about working with ETW I mentioned that I had written a simple app that could modify the paths in the manifest then do the installation which allowed for me to keep a copy of the manifest in a repository and still allow each user to keep the actual repositories anywhere needed. Someone [...]]]></description>
				<content:encoded><![CDATA[<p><a title="Writing an ETW Event Provider" href="http://tomestephens.com/2013/03/writing-an-etw-event-provider-in-c/">In a previous post about working with ETW</a> I mentioned that I had written a simple app that could modify the paths in the manifest then do the installation which allowed for me to keep a copy of the manifest in a repository and still allow each user to keep the actual repositories anywhere needed. Someone requested that I release the code, so I put it up on <a title="ETW Manifest Register App" href="https://github.com/tomestephens/EtwManifestRegister">github</a>. This is a really simple app, just to simplify the manifest registration, I hope it helps.</p>
]]></content:encoded>
			<wfw:commentRss>http://tomestephens.com/2013/06/etw-manifest-registration/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The Unexpected Influence of IronPython</title>
		<link>http://tomestephens.com/2013/03/the-unexpected-influence-of-ironpython/</link>
		<comments>http://tomestephens.com/2013/03/the-unexpected-influence-of-ironpython/#comments</comments>
		<pubDate>Sat, 23 Mar 2013 02:12:49 +0000</pubDate>
		<dc:creator>Tom</dc:creator>
				<category><![CDATA[IronPython]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://tomestephens.com/?p=124</guid>
		<description><![CDATA[I haven&#8217;t posted much in the last 12-18 months for a number of reasons. In part, I&#8217;ve simply been busy &#8211; moving across the country and starting a new job tends to keep you occupied, but the type of work I&#8217;ve been doing also hasn&#8217;t inclined itself as much towards a blog post. Anyway, for [...]]]></description>
				<content:encoded><![CDATA[<p>I haven&#8217;t posted much in the last 12-18 months for a number of reasons. In part, I&#8217;ve simply been busy &#8211; moving across the country and starting a new job tends to keep you occupied, but the type of work I&#8217;ve been doing also hasn&#8217;t inclined itself as much towards a blog post. Anyway, for the first time in probably 18 months I went and investigated my site analytics to see if anyone had actually been visiting in my absence.</p>
<p>As it would happen, a post I never thought would really matter has actually gotten a fair amount of traffic. A couple of years back I was heavily into IronPython and <a title="Overriding the ConfigurationManager" href="http://tomestephens.com/2011/02/making-ironpython-work-overriding-the-configurationmanager/">I found a way to use config files in the IronPython shell</a>. It turns out that for one, I made some copy paste errors and my posted code didn&#8217;t compile &#8211; that&#8217;s a bit embarrassing &#8211; but, despite my mistakes, a couple of people have found some use for it. <a title="TechnoMosh overrides the ConfigManager too!" href="http://technomosh.blogspot.com/2012/01/using-appconfig-in-ironpython.html">Moshe Basanchig</a> fixed my compilation errors, cleaned things up a bit, and took the next step that in retrospect I really should have done: <a href="https://bitbucket.org/moshe.basanchig/blogsamples/src/e20f186fb8ed/ConfigurationProxy">He posted the code, a compiled version and some examples</a>.</p>
<p>I was pretty excited to see this, not least because I was happy to see more people using IronPython which I really love. But the story doesn&#8217;t end here, it turns out that <a title="Simon Opelt overrides the ConfigurationManager - IN PYTHON!" href="http://www.software-architects.com/devblog/2012/10/29/appconfig-in-IronPython-without-additional-assemblies">someone took the step to implement it in Python</a>. Now its a little easier. One less assembly to load in python.</p>
<p>I&#8217;m always happy to see that some slightly obscure work I do helps someone else. Curious that it seems to be the posts I didn&#8217;t imagine anyone besides me would find interesting are the ones seem to attract the most traffic.</p>
]]></content:encoded>
			<wfw:commentRss>http://tomestephens.com/2013/03/the-unexpected-influence-of-ironpython/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>My Open Source Revolution</title>
		<link>http://tomestephens.com/2013/03/my-open-source-revolution/</link>
		<comments>http://tomestephens.com/2013/03/my-open-source-revolution/#comments</comments>
		<pubDate>Wed, 20 Mar 2013 16:00:03 +0000</pubDate>
		<dc:creator>Tom</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Software Development]]></category>
		<category><![CDATA[Open source]]></category>
		<category><![CDATA[utilities]]></category>

		<guid isPermaLink="false">http://tomestephens.com/?p=115</guid>
		<description><![CDATA[I recently released my first open source project; a big step in the life of a software engineer. At least a big step for me. I resisted both contributing to existing projects and publishing my own for a few reasons. The one that I would like to address though came from a number of posts [...]]]></description>
				<content:encoded><![CDATA[<p>I recently released my first open source project; a big step in the life of a software engineer. At least a big step for me. I resisted both contributing to existing projects and publishing my own for a few reasons. The one that I would like to address though came from a number of posts and articles that all insisted that my open source contributions were not only a useful addition to my resume, but a replacement.</p>
<p><a title="My Github Resume" href="http://resume.github.com">Resume.Github.com</a> is an app that takes a github account name and creates a resume from the activity. Some news outlets even <a title="Github Resume Generation Is the Future" href="http://thenextweb.com/apps/2012/09/02/my-github-resume-generates-resume-github-account/">reported on the concept as the future</a>. <a title="Brandon Weiss" href="http://brandonweiss.me/">Brandon Weiss of Anti-Pattern.com</a>, posted an article in which he declared that <a title="Github is your Resume Now" href="http://anti-pattern.com/github-is-your-resume-now">my github account should be seen as my resume</a>. I&#8217;m not writing to argue against his article. I think he has some valid points and importantly, I think the concept has a place in the world. But I don&#8217;t think it applies as universally as these articles imply.</p>
<p><span id="more-115"></span></p>
<p>The real problem I want to address is that I was nervous about releasing and open source project or making contributions because I didn&#8217;t want to be judged by it. Perhaps unlike some, the open source world is never likely to get my best work. Not because of some resistance to the concept, but rather because I simply invest a large majority of my effort at my job. I work 10-12 hours days typically and when I get home I&#8217;m just not likely to invest heavily in a project that isn&#8217;t crucial to my job.  When I&#8217;m coding at home, I&#8217;m experimenting with ideas and trying things out. At best I&#8217;m hacking together a tool to make my life easier. I&#8217;m not developing elegant solutions.</p>
<p>I realized that this hesitation meant that despite the fact that I had some utilities that could actually improve the life and efficiency of other developers around the world, they simply sat rotting on my PC not being fully exploited. I was essentially forcing someone to redo work I had already done, because I was afraid that someone would use my hack of a tool as ammunition in a job interview at some point. Not only that, but I was losing the potential insight and improvements of other engineers that could increase my own efficiency because I wasn&#8217;t publishing this code.</p>
<p>I honestly feel that the idea that my open source work which (I freely admit) is often a little hacked together should be the judgement of the quality of my work on the whole goes against the very heart of the open source movement. I&#8217;m publishing my code, not because it&#8217;s so amazing, but rather because it solves a problem and I want others to be able to take advantage of the work I have done so far. I want to encourage people to improve upon the idea, perhaps make it a more elegant solution. Or maybe due to circumstances it is useful exactly as is, even without being made more elegant. I don&#8217;t see why that should be a problem.</p>
<p>So now I resist the idea that my open source code is my resume. My open source code is nothing more than me making available work I&#8217;ve done to solve a problem. If you don&#8217;t like my solution, don&#8217;t use it. With my new found liberating mindset on open source, I&#8217;ve released not one but two projects in recent months. Feel free to use them or contribute, maybe they will solve a problem you experienced as well. The code isn&#8217;t great and certainly not even close to my best (or most interesting work) but they solve a problem, which is all that concerned me.</p>
<ul>
<li><span style="line-height: 13px;"><a title="Programtically Updater Visual Studio References" href="https://refswap.codeplex.com/">Visual Studio Reference Swapper</a> &#8211; a utility for programmatically updating Visual Studio References</span></li>
<li><a title="A GUI For executing NAnt Builds" href="https://nantassist.codeplex.com/">NAnt Assistant</a> - a simple GUI geared around simplicity and keyboard shortcuts for running nant builds</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://tomestephens.com/2013/03/my-open-source-revolution/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Writing an ETW Event Provider in C</title>
		<link>http://tomestephens.com/2013/03/writing-an-etw-event-provider-in-c/</link>
		<comments>http://tomestephens.com/2013/03/writing-an-etw-event-provider-in-c/#comments</comments>
		<pubDate>Wed, 20 Mar 2013 14:29:59 +0000</pubDate>
		<dc:creator>Tom</dc:creator>
				<category><![CDATA[C]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Windows APIs]]></category>
		<category><![CDATA[ETW]]></category>
		<category><![CDATA[EventLog]]></category>
		<category><![CDATA[Events]]></category>
		<category><![CDATA[Instrumentation Manifest]]></category>
		<category><![CDATA[windows]]></category>

		<guid isPermaLink="false">http://tomestephens.com/?p=120</guid>
		<description><![CDATA[Recently, I came across a need for light event recording in a windows application written in C. We thought, &#8220;Hey, windows has an API for that. Should be a piece of cake.&#8221; Should be. I&#8217;ll go ahead and spoil the fun now. It took me approximately 3-4 hours to read about and implement the ETW [...]]]></description>
				<content:encoded><![CDATA[<p>Recently, I came across a need for light event recording in a windows application written in C. We thought, &#8220;Hey, windows has an <a title="Windows Eventing APIs" href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa964766(v=vs.85).aspx">API</a> for that. Should be a piece of cake.&#8221; <strong>Should</strong> be.</p>
<p>I&#8217;ll go ahead and spoil the fun now. It took me approximately 3-4 hours to read about and implement the ETW APIs in my application. However, I lost another ~16 hours trying to get windows configured to support my new event provider. Once I had gotten through that there was another round of trying to turn that data into useful information that I could act on, but that wasn&#8217;t so bad. Most of the time was lost in sorting out the configuration then finding a way to make the process easily repeatable for the rest of my team.</p>
<p>The basic process you need is not so bad:</p>
<ol>
<li><a title="Create an Instrumentation Manifest" href="http://msdn.microsoft.com/en-us/library/windows/desktop/dd996930(v=vs.85).aspx"><span style="line-height: 13px;">Create your Instrumentation Manifest</span></a></li>
<li><a title="Manifest Compiler" href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa385638(v=vs.85).aspx">Compile the Manifest</a></li>
<li>Add compiled data to your application and implement your events &#8211; rebuild the application</li>
<li><a title="WEvetUtil.exe" href="http://technet.microsoft.com/en-us/library/cc732848(v=ws.10).aspx">Register the Manifest</a></li>
</ol>
<p>I&#8217;ll go over each step and to gotcha&#8217;s that I encountered. Perhaps I can save someone else some time.</p>
<p><span id="more-120"></span></p>
<h3>Create an Instrumentation Manifest</h3>
<p>First things first, Microsoft it seems has adjusted the internal Windows event apis/methodology for pretty much each major release of windows since XP. It has been evolving, and that&#8217;s generally a good thing. They (at least for now) seem to have settled on something called the <a title="Writing an Instrumentation Manifest" href="http://msdn.microsoft.com/en-us/library/windows/desktop/dd996930(v=vs.85).aspx">Instrumentation Manifest</a>. This is an xml file that defines the details of the provider you are developing. It includes all of the event information you&#8217;re accustomed to seeing in the EventLog, and the Windows SDK even comes with a handy little tool (ECManGen.exe) that builds and edits your manifest file for you.</p>
<p>I could go into the schema but the Microsoft documentation surrounding this aspect is pretty solid. I&#8217;ll just cover one very important thing that I didn&#8217;t fully understand when I was getting started. When setting up your provider in ECManGen, there is a set of properties that were not clear to me, the <strong>Decoding File Locations. </strong>The decoding file locations are an absolute path to your assembly that has been compiled with the Manifest details. Once you&#8217;ve written a manifest, you have to compile it (we&#8217;ll cover this more later). The output of the compilation needs to be added to your application. When you go to register the your manifest Windows will need to know where to find the Event Provider. That&#8217;s the purpose of these properties. In my case, they are both ( exactly the same. There must be a situation where they would be different, but I don&#8217;t know what the situation would be.</p>
<h3>Compile the Instrumenation Manifest</h3>
<p>There isn&#8217;t much I&#8217;m going to cover here. It is generally pretty simple. Microsoft has provided a tool called <a title="MC.exe" href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa385638(v=vs.85).aspx">mc.exe</a> that is also included as part of the Windows SDK. The output is a series of files generated based on your manifest, a header file, a message .bin, a TEMP.bin and a .rc (Resource) file. You need to add the Resource and header files to your application so it is compiled into the application. The Header file just makes your life very easy when writing the code.</p>
<p>I didn&#8217;t run into any difficulty getting this to work correctly. Microsoft has good docs on the Message Compiler and it worked reliably.</p>
<h3>Writing the code</h3>
<p>I already mentioned that you&#8217;ll need to add the Resource and Header files from your Message Compiler output to your application. Once this is done, it is just a matter of following the <a title="Providing ETW Events" href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa364098(v=vs.85).aspx">MSDN docs on providing events</a>. In fact, this <a title="Manifest Based Events Code Example" href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa364098(v=vs.85).aspx">code example</a> was very easy to start from.</p>
<p>A couple of simple notes, make sure you initialize correctly with <a title="MSDN EventRegister Documentation" href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa363744(v=vs.85).aspx">EventRegister</a> and that you correctly close out your provider&#8217;s process with <a title="MDSN EventUnregister Documentation" href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa363749(v=vs.85).aspx">EventUnregister</a>. I had a bug that meant the Unregister wasn&#8217;t being correctly called and it led to some pretty odd behavior.</p>
<p>Here&#8217;s a quick example of some of my code &#8211; because of my implementation, I actually support enabling and disabling the eventing as you&#8217;ll noticed is referenced. Also, my application can run through a pretty substantial amount of functionality without ever entering code that does any EventLogging so you&#8217;ll notice that my code doesn&#8217;t assume the provider has been registered at the time of writing an event.</p>
<pre class="code">unsigned char eventLogging_RegisterHandle()
{
	ULONG status;
	// this one check will stop all events from being written
	if(eventLogging_IsEnabled != TRUE)
		return FALSE;

	status = EventRegister(&amp;EXAMPLE_INSTRUMENTATION_PROVIDER, NULL, NULL, &amp;runHandle);

	if(status != ERROR_SUCCESS)
	{
		runHandle = NULL;
	}
	else 
	{
		// start a session?
		EventActivityIdControl(EVENT_ACTIVITY_CTRL_CREATE_SET_ID, &amp;currentSession);
	}

	return status == ERROR_SUCCESS;
}
// simplify/remove duplication
void eventLogging_WriteEvent(PCEVENT_DESCRIPTOR evt, unsigned char eventDataCount, PEVENT_DATA_DESCRIPTOR evtData) 
{
	ULONG status;

	if(runHandle == NULL &amp;&amp; eventLogging_RegisterHandle() == FALSE)
		return;

	status = EventWriteEx(runHandle, evt, 0, 0, NULL, &amp;currentSession, eventDataCount, evtData);
}

void eventLogging_Exception(char* message)
{
	EventDataDescCreate(&amp;desc, message, strlen(message));
	eventLogging_writeEvent(&amp;ExampleProviderException, 1, &amp;desc);
}</pre>
<h3>Register the manifest</h3>
<p>This is where I ran into a few gotchas. The core of the problems, I already covered previously, but I&#8217;ll discuss how I addressed a couple of these problems for my situation.</p>
<ol>
<li>Absolute Path to the compiled application</li>
<li>Rebuild your application &#8211; I listed it explicitly in the steps above, but just to reiterate. Windows will barf on you when you try to register if the event resources haven&#8217;t been compiled into the application</li>
<li>Security &#8211; you&#8217;ll need to grant Read &amp; Execute permissions on the directory containing your application</li>
</ol>
<p>The Absolute Path for the application proved to be a little tricky for us. While most of my team uses keep their code repositories in a standard location, some people had other preferences. So, I actually wrote a small app that I keep in the repository to handle the manifest registration. It knows the relative path to the application and manifest, so it opens the manifest file and fills in the absolute path based on the known relative path and then registers it that way. This allows me to keep the manifest in the repository generically and not force the few people who keep their code non-standard locations from having to edit the absolute path just to register the manifest. It also means that if someone accidentally commits the absolute path for their pc it doesn&#8217;t cause any difficulties for everyone else.</p>
<p>When it&#8217;s all written out like this, it doesn&#8217;t seem so hard. The truth is, it isn&#8217;t. But if, like me, you run into a problem at one of these steps finding the right information on how to fix it can be difficult. I&#8217;m all around pretty surprised and happy with the Windows ETW Apis. Everything was surprisingly easy to use. While I&#8217;m not a fan of xml as a solution to all problems, in this case it seems to fit fairly well and offer the flexibility you would want from such a situation. I wish Microsoft had some slightly better docs on the full process, but I also wish I had better documentation at work of my code too. Alas, I think we all know it is much harder than it sounds.</p>
]]></content:encoded>
			<wfw:commentRss>http://tomestephens.com/2013/03/writing-an-etw-event-provider-in-c/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Automation &#8211; saving 15 mins/day at a time</title>
		<link>http://tomestephens.com/2011/10/automation-saving-15-minsday-at-a-time/</link>
		<comments>http://tomestephens.com/2011/10/automation-saving-15-minsday-at-a-time/#comments</comments>
		<pubDate>Tue, 25 Oct 2011 17:54:53 +0000</pubDate>
		<dc:creator>Tom</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[automation]]></category>
		<category><![CDATA[continuous integration]]></category>
		<category><![CDATA[hg]]></category>
		<category><![CDATA[mercurial]]></category>
		<category><![CDATA[source control]]></category>

		<guid isPermaLink="false">http://tomestephens.com/?p=105</guid>
		<description><![CDATA[So my wife laughs at me quite a bit, but I&#8217;m a little obsessed with efficiency and automation. I hate wasting my time on non-engaging tasks. Which is, as it happens, most of life. So I try to find ways to automate things. The less I have to invest my time in tasks with a [...]]]></description>
				<content:encoded><![CDATA[<p>So my wife laughs at me quite a bit, but I&#8217;m a little obsessed with efficiency and automation. I hate wasting my time on non-engaging tasks. Which is, as it happens, most of life. So I try to find ways to automate things. The less I have to invest my time in tasks with a clearly defined process the more time I can spend working on things I actually care about. At work I put this to the test constantly. Working as a software engineer there is just a pile of repetitive tasks that are ripe for automation. Fortunately a number of tools have entered the battlefield against wasting our time on processes that can be automated.</p>
<p>I love the growth and ever increasing adoption of <a href="http://en.wikipedia.org/wiki/Continuous_integration">continuous integration</a>. At my new job I was thrilled to see how much they had already begun to move in that direction. It&#8217;s not perfect, that&#8217;s for sure, but we&#8217;ve got a solid start and we always keep our eyes out for ways to improve that process. That said, there&#8217;s still a lot of room for grabbing the low hanging fruit and Python/IronPython (two tools I&#8217;ve mentioned a number of times) come in to save the day for me.</p>
<p>One place I decided to tackle recently was our revision control. We use <a href="http://mercurial.selenic.com/">Hg</a> which is a Python based tool itself, but they expressly discourage people from importing their libraries and using them, simply because they don&#8217;t guarantee they won&#8217;t change and therefore break everything. I had a short internal debate about if I thought it was worth it and eventually I opted against it, simply because it was just too easy to work around that issue (for my needs at least).</p>
<p>The problem came up that we have a pile of repositories that we all work in frequently. Keeping these repositories up to date was kind of a pain. That said the more familiar I get with the command line for Hg the easier, however I opted to write something with python to handle the task at hand. I came across <a href="http://bluebill.wordpress.com/2010/04/05/updated-mercurial-batch-pullupdate-python-script/">this script</a> which really accomplished what I needed, but I just wasn&#8217;t in love with the implementation. I wanted something a bit more flexible, I had in mind that I could use some of this for some tasks with our automated build too.</p>
<p>I started off by writing a simple &#8220;repo&#8221; class.<br />
<span id="more-105"></span></p>
<pre class="code">
import os
PENDING_STATUS = ['A','M']
ERRORS = ['access denied', 'abort']

PULL = 'hg pull'
UPDATE = 'hg update'
STATUS = 'hg status'
TIP = 'hg tip'
NUDGE = 'hg push --rev .'

class repo:
    def __init__(self, path=''):
        self.path = path
        self.validdir = False

        if path:
            self.__validate_dir__()

    def __validate_dir__(self):
        if not os.path.exists(os.path.join(self.path,'.hg')):
            print self.path, 'is not an hg directory.'
            self.validdir = False
            return
        
	self.validdir = True

    def __haspending__(self, show=False):
        if not self.__prep__(): return False
        out = os.popen(STATUS)
        changes = [ln for ln in out if ln[0] in PENDING_STATUS]
        if show:
            for chg in changes: print chg

        return len(changes) > 0

    def __indir__(self):
        return os.getcwd() == self.path

    def __gotorepo__(self):
        if not self.validdir: return False
        if not self.__indir__():
            os.chdir(self.path)

        return True

    def __prep__(self):
        if not self.validdir: return False
        return self.__gotorepo__()

    def __checkerror__(self, output):
        for l in output:
            err = [e for e in ERRORS if e in l]
            if err:
                print err
                return True

        return False

    def setpath(self, path):
        self.path = path
        self.__validate_dir__()
    
    def issafe(self):
        if not self.__prep__(): return False
        if self.__haspending__(True):
            print 'Will not update. Pending changes found.'
            return False
        
        print 'No pending changes found... safe to update.'
        return True

    def getchg(self):
        if not self.validdir: return False
        changeset = [ln for ln in os.popen(TIP) if 'changeset:' in ln]
        return ln.split(':')[2]

    def anypending(self):
        return __safe_to_update__()

    def pull(self):
        if not self.__prep__(): return
	out = [ln for ln in os.popen(PULL)]
	if self.__checkerror__(out): return
	
	for ln in out:            
            if 'no changes found' in ln:
                print ln
                return False

        print 'pulled latest'
        return True
			
    def update(self, show=True):
	if not self.__prep__(): return
	out = [ln for ln in os.popen(UPDATE)]
	if self.__checkerror__(out): return
        for ln in out:
            if show: print ln
            
    def sync(self, update_if_safe = True):
        if not self.__prep__(): return
        
        print 'Getting latest for ' + os.getcwd()
        #only try to update if there were changes...
        if self.pull():
            if update_if_safe and self.issafe():
                print 'Updating...'
                self.update(False)
                
        print 'done'

    def nudge(self, show=True):
        if not self.__prep__(): return
        out = [ln for ln in os.popen(NUDGE)]
	if self.__checkerror__(out): return
        for ln in out:
            if show: print ln
</pre>
<p>It&#8217;s not the prettiest, in fact I&#8217;ll change it soon to have a &#8216;verbose&#8217; property or something so I can ditch the &#8220;show=True&#8221; params from a number of those functions. The idea for the &#8220;nudge&#8221; function came from an <a href="http://hgtip.com/tips/advanced/2009-09-28-nudge-a-gentler-push/">hgtip.com post</a> where they address what is honestly an annoying part of mercurial to me.</p>
<p>Once I had this repo class then I just needed a simple script to wrap around it. This is a bit closer to the script I mentioned earlier, but it&#8217;s got some options for command line params.</p>
<pre class="code">
import os, hgutil, config, sys

def main(argv=None):
    if argv == None:
        argv = sys.argv

    arg_path = None
    # start at 1, 0 is the command
    for i in range(1, len(argv)):
        if argv[i] == '-p':
            arg_path = argv[i+1]
        if argv[i] == '-h':
            show_help()
            return True
        
    path = get_path(arg_path)

    if has_connection():
        for f in os.listdir(path):
            p = os.path.join(path,f)
            if os.path.isdir(p):
                repo = hgutil.repo(p)
                repo.sync()
    else:
        print 'No connection to hg found. Please ensure pageant is running.'
        return False

    return True

def has_connection():
    return len([ln for ln in os.popen('tasklist') if 'pageant' in ln]) > 0

def get_path(path=None):
    if path != None and os.path.exists(path):
        print 'starting from path:', path
        return path

    ##default
    print 'No valid path found... using default.'
    return config.get_home()

def show_help():
    print '--- sync.py ---'
    print 'Attempts to sync all hg repositories under a path.'
    print 'Returns errors if pageant is not running.'
    print 'Args:'
    print '-p : path to work from'
    print 'Example: sync.py -p c:\dev'
    print 'Done.'

if __name__ == "__main__":
    sys.exit(main())
</pre>
<p>Since we use pageant for our connections to mercurial it&#8217;s nice to have this be able to check and let me know in case I&#8217;ve forgotten to enable it.</p>
<p>Now that I had this full script, I create a windows scheduled task to run it behind the scenes for me every 10 mins. Now if I&#8217;m not actually working with a specific repository it just gets updated for me, and if I am, I pull the changes, but don&#8217;t update until I&#8217;m ready. This needs more work before it&#8217;s terribly useful on my automated build server, but the ground work is there and I&#8217;ve been really happy with it so far. It might not seem like it but this script saves me a solid 10-15 mins a day manually doing pulls and updates on my repos and a lot of help where I run into issues from running an older version of some code.</p>
<p>Now, it is possible that I&#8217;ll be working on something I don&#8217;t want automatically updated. Then I&#8217;ll just change it over to default to not update. The automated pull is still useful.</p>
]]></content:encoded>
			<wfw:commentRss>http://tomestephens.com/2011/10/automation-saving-15-minsday-at-a-time/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title></title>
		<link>http://tomestephens.com/2011/08/103/</link>
		<comments>http://tomestephens.com/2011/08/103/#comments</comments>
		<pubDate>Thu, 25 Aug 2011 16:50:02 +0000</pubDate>
		<dc:creator>Tom</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Tools]]></category>
		<category><![CDATA[editors]]></category>
		<category><![CDATA[ide]]></category>
		<category><![CDATA[vim]]></category>

		<guid isPermaLink="false">http://tomestephens.com/?p=103</guid>
		<description><![CDATA[I have yet to post since taking on my new position, but I&#8217;ve been doing quite a bit. I&#8217;ve had to really expand my knowledge of Linux and a few different distros. Along with that I&#8217;ve had to learn a bit about apache and mysql configuration. But that&#8217;s all been largely straightforward; just a different [...]]]></description>
				<content:encoded><![CDATA[<p>I have yet to post since taking on my new position, but I&#8217;ve been doing quite a bit. I&#8217;ve had to really expand my knowledge of Linux and a few different distros. Along with that I&#8217;ve had to learn a bit about <a href="http://apache.org" title="Apache Web Server">apache</a> and <a href="http://mysql.org" title="MySQL Open Source Database">mysql</a> configuration. But that&#8217;s all been largely straightforward; just a different environment but the same basic knowledge I&#8217;ve been applying for a while.</p>
<p>But what I&#8217;ve really enjoyed that&#8217;s been a fairly big change from the IDEs I&#8217;ve been using is <a href="http://www.vim.org" title="Vim Text Editor">vim</a>. Not long ago I wrote not to long ago about<a href="http://tomestephens.com/2011/03/resharper-and-friends-no-thanks/" title="Resharper and Friends - No Thanks">how I like minimalism from my editor</a> and while I&#8217;d used vim here and there in small chunks (mainly for commits with git) I never really spent a lot of time in it. Moving into a world of embedded code <a href="http://coreytabaka.com" title="Corey Tabaka">a friend of mine</a> who also works in embedded software highly recommended it. He pointed me to the <a href="ftp://ftp.vim.org/pub/vim/doc/book/vimbook-OPL.pdf" title="Vim Book">Vim Book</a> which gives a really solid overview of not just the tool, but the concepts and workflow behind it.</p>
<p>While some people might not see it as minimal, to me is. It&#8217;s *just* an editor. It can be a little convoluted and the commands don&#8217;t always seem like the most obvious choices, but the more I use it the more the system makes sense. Yesterday I even spent sometime customizing my config file. For one, I like line numbers. They don&#8217;t seem to be a general favorite of vim users, but I like it. The focus on keyboard is great. I don&#8217;t need my hands to move from the keyboard for anything. I did turn on the mouse just because I don&#8217;t like the Ctrl-Ww for switching between windows. I know it&#8217;s possible to make a custom command for that, but I&#8217;m still new and haven&#8217;t made sense of it yet.</p>
<p>A few of my choice settings:</p>
<pre class="code">
" Save a lot more of a history
history=1000
" Turn on line numbers
set number
" Show the file name in the title bar
set title
" Make tabs 4 spaces and convert tabs to spaces
set tabstop=4
set expandtab
" Enable mouse usage in all settings
set mouse=a
</pre>
<p>As I get better with vim and find more things that aren&#8217;t interacting the way I like, I&#8217;m sure I&#8217;ll add to this, but this seems like a good beginners config. Vim has a bit of a learning curve, but I think it&#8217;s worth it. I think it&#8217;s a bit like git that way. Weird at first, but the more you get used to it the more awesome it is. I still only know 1% of what&#8217;s possible, but so far, I love it.</p>
]]></content:encoded>
			<wfw:commentRss>http://tomestephens.com/2011/08/103/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Time for Change</title>
		<link>http://tomestephens.com/2011/06/time-for-change/</link>
		<comments>http://tomestephens.com/2011/06/time-for-change/#comments</comments>
		<pubDate>Mon, 20 Jun 2011 16:23:10 +0000</pubDate>
		<dc:creator>Tom</dc:creator>
				<category><![CDATA[Events]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[change]]></category>
		<category><![CDATA[engineering]]></category>
		<category><![CDATA[HID]]></category>
		<category><![CDATA[job]]></category>

		<guid isPermaLink="false">http://tomestephens.com/?p=101</guid>
		<description><![CDATA[I&#8217;ve been working at ASSA ABLOY for almost four years. After years of good opportunity to learn and grow I&#8217;ve been given the opportunity to continue to grow within the company. HID Global, a sister company, has offered me the chance to come work with their R&#038;D Engineering team on smart card readers. For me, [...]]]></description>
				<content:encoded><![CDATA[<p>I&#8217;ve been working at <a href="http://www.assaabloy.com/en/com/">ASSA ABLOY</a> for almost four years. After years of good opportunity to learn and grow I&#8217;ve been given the opportunity to continue to grow within the company. <a href="http://www.hidglobal.com/">HID Global</a>, a sister company, has offered me the chance to come work with their R&#038;D Engineering team on <a href="http://en.wikipedia.org/wiki/Smart_card">smart card</a> readers.</p>
<p>For me, this is very exciting work. I&#8217;ll get the chance to make use of my existing skill-set to help out the team with implementing a number of tools to assist with testing. The team right now is primarily Electrical Engineers and they are missing the skills for <a href="http://en.wikipedia.org/wiki/Object-oriented_programming">OO programming</a>. That happens to be my expertise right now. But what makes this great is that it puts me in a prime spot to start learning and expanding my skills to work in embedded software. Which is my goal for the not too distant future.</p>
<p>I just don&#8217;t really get excited about web development anymore. It&#8217;s given me a great chance to learn, but when it comes down to it, how many forms over data can I really build and have it be interesting? That&#8217;s not to say there isn&#8217;t innovation to be made or that there isn&#8217;t some really cool stuff happening on the web. Just that it turns out not to be exciting to me.</p>
<p>I&#8217;m grateful for the opportunity and glad to have a change of pace. I&#8217;ll be moving to the Denver, Colorado area which is beautiful and, if I have to move from Charlotte, it&#8217;s a pretty good option.</p>
]]></content:encoded>
			<wfw:commentRss>http://tomestephens.com/2011/06/time-for-change/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>IronPython&#8217;s missing csv</title>
		<link>http://tomestephens.com/2011/05/ironpythons-missing-csv/</link>
		<comments>http://tomestephens.com/2011/05/ironpythons-missing-csv/#comments</comments>
		<pubDate>Mon, 16 May 2011 18:49:51 +0000</pubDate>
		<dc:creator>Tom</dc:creator>
				<category><![CDATA[IronPython]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[read csv file]]></category>

		<guid isPermaLink="false">http://tomestephens.com/?p=95</guid>
		<description><![CDATA[Python already has a great csv module, but since it is implemented in C, it&#8217;s not available to IronPython. IronPython.info has a suggested workaround using an external library. But for some reason I just chose to write something really simple myself. Since for my purposes today I didn&#8217;t actually need to do any writing to [...]]]></description>
				<content:encoded><![CDATA[<p><a href="http://docs.python.org/library/csv.html">Python already has a great csv module</a>, but since it is implemented in C, it&#8217;s not available to IronPython. <a href="http://ironpython.info">IronPython.info</a> has a <a href="http://www.ironpython.info/index.php/Reading_CSV_Files">suggested workaround</a> using an external library. But for some reason I just chose to write something really simple myself. Since for my purposes today I didn&#8217;t actually need to do any writing to file, I just have a csv reader.</p>
<p>This is my really simple csv reader. I&#8217;m calling it, icsv.py. There&#8217;s a million things it doesn&#8217;t handle yet, but it covered what I happened to need today. Maybe I&#8217;ll expand it as the situation warrants.</p>
<pre class="code">
class reader:
    def __init__(self,path,delimiter=','):
        self.File = open(path, "r")
        self.Delimiter = delimiter
        self.Header = self.File.readline().replace('\n','').split(delimiter)
        self.__curr_line = None
	
    def canread(self):
        return not self.File.closed
	
    def stop(self):
        self.File.close()
	
    def nextline(self):
        if self.File.closed: return None
			
        curr = self.File.readline()
		
        if not curr: 
            self.File.close()
            return None
		
        self.__curr_line = curr
		
        ## no quoted text return the easy way...
        if curr.find('"') == -1:
            return dict(zip(self.Header,self.__curr_line.replace('\n','').split(self.Delimiter)))
			
        line = dict()
        for h in self.Header:
            if not curr.startswith('"'):
                line[h], s, curr = curr.partition(',')
            else:
                clsq = curr.find('"',1)+1
                line[h] = curr[0:clsq]
                curr = curr[clsq+1:]
					
        return line
</pre>
]]></content:encoded>
			<wfw:commentRss>http://tomestephens.com/2011/05/ironpythons-missing-csv/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Abstract Classes vs Interfaces: Performance</title>
		<link>http://tomestephens.com/2011/04/abstract-classes-vs-interfaces-performance/</link>
		<comments>http://tomestephens.com/2011/04/abstract-classes-vs-interfaces-performance/#comments</comments>
		<pubDate>Fri, 29 Apr 2011 12:40:18 +0000</pubDate>
		<dc:creator>Tom</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Software Development]]></category>
		<category><![CDATA[abstract class]]></category>
		<category><![CDATA[interface]]></category>
		<category><![CDATA[object oriented programming]]></category>
		<category><![CDATA[performance]]></category>

		<guid isPermaLink="false">http://tomestephens.com/?p=86</guid>
		<description><![CDATA[Recently I was talking to someone about the benefits of Abstract classes vs. Interfaces and performance came up. The theory being that interfaces are slower because it takes more time to loop through the whole object to find the appropriate method. This was an interesting concept to me. I did some searching around and it [...]]]></description>
				<content:encoded><![CDATA[<p>Recently I was talking to someone about the benefits of Abstract classes vs. Interfaces and performance came up. The theory being that interfaces are slower because it takes more time to loop through the whole object to find the appropriate method. This was an interesting concept to me. I did some searching around and it turns out that this is a common belief. <a href="http://www.codeproject.com/KB/cs/abstractsvsinterfaces.aspx">This CodeProject article</a> makes the same argument. I didn&#8217;t set out to win an argument or prove a point as I honestly had no idea which would be faster. In fact I can say that I know so little about the lower level implementation of this that I didn&#8217;t even know which I would expect to be faster.</p>
<p>I&#8217;m no good with simply taking everyone&#8217;s word for it, so I wrote up some basic tests. They aren&#8217;t perfect for sure but it gets the job done (<a href="http://tomestephens.com/wp-content/uploads/2011/04/AbsrVIface1.zip">download the project</a>), and I see some kind of large divergence in the times depending, I&#8217;m guessing, on what else my computer is doing at the time. However the overall trend of the results are consistent. Interfaces are faster until you get to an enormous number of iterations. I didn&#8217;t see Interfaces show as consistently slower until I was testing in the realm of 100mil or 1bil iterations, they started to become close enough as makes no difference around 10mil iterations.</p>
<p><a href="http://tomestephens.com/wp-content/uploads/2011/04/AbstVIface.png"><img src="http://tomestephens.com/wp-content/uploads/2011/04/AbstVIface.png" alt="" title="AbstVIface" width="600" class="alignnone size-full wp-image-87" /></a></p>
<p>Even with the divergence I saw, in the typical application I&#8217;m not sure this would play a real role. My approach to this will definitely be to not worry about it unless I am <b>A)</b> working on something where optimization is crucial or <b>B)</b> I start to notice some performance issues specifically related to my abstraction. Chances are that if you have performance issues, whether you are using an abstract class or an interface is not the problem. Of course that&#8217;s not to say you should ignore known performance issues, but there are enough non-performance related benefits around abstract classes and interfaces that you shouldn&#8217;t sacrifice good design or maintainability for an optimization you&#8217;re not likely to ever notice in the real world.</p>
<p>The thing I really wonder about now is if it&#8217;s a product of the CLR. If I get to it, I may write a similar test in java and post the results.</p>
]]></content:encoded>
			<wfw:commentRss>http://tomestephens.com/2011/04/abstract-classes-vs-interfaces-performance/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Lightning Strikes, no seriously&#8230;</title>
		<link>http://tomestephens.com/2011/04/lightning-strikes-no-seriously/</link>
		<comments>http://tomestephens.com/2011/04/lightning-strikes-no-seriously/#comments</comments>
		<pubDate>Wed, 27 Apr 2011 21:09:12 +0000</pubDate>
		<dc:creator>Tom</dc:creator>
				<category><![CDATA[Events]]></category>
		<category><![CDATA[lightning]]></category>
		<category><![CDATA[network cable]]></category>

		<guid isPermaLink="false">http://tomestephens.com/?p=84</guid>
		<description><![CDATA[My house was hit by a nasty bolt of lightning last night. It fried my cable modem, my router and at least the motherboard of my computer. No fun at all. But I thought it would be fun to show what the cat5 cable running from the modem to the router looks like&#8230; Cool eh?]]></description>
				<content:encoded><![CDATA[<p>My house was hit by a nasty bolt of lightning last night. It fried my cable modem, my router and at least the motherboard of my computer. No fun at all. But I thought it would be fun to show what the cat5 cable running from the modem to the router looks like&#8230;</p>
<p><a href="http://tomestephens.com/wp-content/uploads/2011/04/Photo_28026F13-DEA4-311E-B65C-6DC175A51FB4.jpg"><img class="alignnone size-medium wp-image-83" title="Network cable after Lightning" src="http://tomestephens.com/wp-content/uploads/2011/04/Photo_28026F13-DEA4-311E-B65C-6DC175A51FB4-225x300.jpg" alt="Network cable after Lightning" width="225" height="300" /></a></p>
<p>Cool eh?</p>
]]></content:encoded>
			<wfw:commentRss>http://tomestephens.com/2011/04/lightning-strikes-no-seriously/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
