<?xml version="1.0" encoding="UTF-8" standalone="no"?><!--Generated by Site-Server v@build.version@ (http://www.squarespace.com) on Sat, 22 Mar 2025 21:43:24 GMT
--><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:media="http://www.rssboard.org/media-rss" xmlns:wfw="http://wellformedweb.org/CommentAPI/" version="2.0"><channel><title>Blog​ - Katz Consulting Group - A Blog about Software Development, DevOps, Source Control, SCM, ALM &amp; other related topics.</title><link>https://www.omerkatz.com/blog/</link><lastBuildDate>Sun, 26 Mar 2017 09:07:11 +0000</lastBuildDate><language>en-US</language><generator>Site-Server v@build.version@ (http://www.squarespace.com)</generator><description/><xhtml:meta content="noindex" name="robots" xmlns:xhtml="http://www.w3.org/1999/xhtml"/><item><title>Using Protobuf With PyPy</title><category>Software Development</category><dc:creator>Omer Katz</dc:creator><pubDate>Thu, 10 Sep 2015 23:00:30 +0000</pubDate><link>https://www.omerkatz.com/blog/2015/09/11/using-protobuf-with-pypy</link><guid isPermaLink="false">5138dccfe4b073120964d739:5138e128e4b0653ec0f305ae:54c49a2ae4b08c884a02afae</guid><description><![CDATA[In case you're not familiar with PyPy yet, it's a Python interpreter with 
JIT compiler.

PyPy has many advantages. It can run Python code faster then any existing 
interpreter, has a lower memory footprint then CPython, it allows you to 
choose the right level of language abstraction for your code depending on 
how fast you need it to be since it supports running Python, RPython and 
allows you to provide C and C++ extensions and It's 99% compatible with 
CPython.

One of the major differences and what makes PyPy adoption a non-trivial 
process is the why PyPy interfaces with CPython extensions. If you're 
interfacing with C code you need to ensure that you use the right bindings.

CPython extensions use Python's C API which PyPy does not have. PyPy can 
run some CPython extensions using cpyext but those extensions will run 
slower on PyPy due to the need to emulate reference counting. That also 
means that Cython generated extensions will be slower.

PyPy on the other hand has support for the not very commonly used ctypes 
and CFFI which can be run on both interpreters. CFFI runs much faster on 
PyPy than ctypes so if you're targeting PyPy it's better to use it. I was 
told that CFFI has been known to be a bit slower than C extensions on 
CPython because it does not access the C API directly but it wraps it. I 
could not find evidence for that claim although it makes sense.

If you're interfacing with C++ code, there has been a discussion to port 
boost::python to PyPy but I don't think it has been done yet.

PyPy provides cppyy which is written in CPython and thus able to JIT out 
most of the binding related code. cppyy has multiple backends it can use. 
In this post I'm going to cover Reflex since it's the default and it is 
currently the most stable backend.

In this post I'm going to demonstrate how to run Protobuf 2.5.1 on PyPy. 
Protobuf's compiler generates Python code which relies on a CPython 
extension in order to interface with the Protobuf implementation and is I 
mentioned before this is not going to be as fast as it should be for PyPy. 
Google provides a pure python implementation of Protobuf in version 3.0 
which is not yet release and breaks compatibility in some aspects from 
Protobuf 2.x.]]></description><content:encoded><![CDATA[<p>In case you're not familiar with <a href="http://pypy.org/">PyPy</a> yet, it's a Python interpreter with <a href="http://en.wikipedia.org/wiki/Just-in-time_compilation">JIT</a> compiler.</p><p>PyPy has many advantages. It can run Python code faster then any existing interpreter, has a lower memory footprint then CPython, it allows you to choose the right level of language abstraction for your code depending on how fast you need it to be since it supports running Python, <a href="http://pypy.readthedocs.org/en/latest/extending.html#rpython-mixed-modules">RPython</a> and allows you to provide <a href="http://pypy.readthedocs.org/en/latest/extending.html#cffi">C</a> and <a href="http://pypy.readthedocs.org/en/latest/extending.html#reflex">C++</a> extensions and It's <a href="http://pypy.readthedocs.org/en/latest/cpython_differences.html">99%</a> compatible with CPython.</p><p>One of the major differences and what makes PyPy adoption a non-trivial process is the why PyPy interfaces with CPython extensions. If you're interfacing with C code you need to ensure that you use the right bindings.</p><p>CPython extensions use Python's C API which PyPy does not have. PyPy can run some CPython extensions using cpyext but those extensions <a href="http://pypy.readthedocs.org/en/latest/faq.html#do-cpython-extension-modules-work-with-pypy">will run slower</a> on PyPy due to the need to emulate reference counting. That also means that <a href="http://docs.cython.org/src/userguide/pypy.html#efficiency">Cython generated extensions</a> will be slower.</p><p>PyPy on the other hand has support for the not very commonly used <a href="http://pypy.readthedocs.org/en/latest/extending.html#ctypes">ctypes</a> and <a href="http://pypy.readthedocs.org/en/latest/extending.html#cffi">CFFI</a> which can be run on both interpreters. CFFI runs much faster on PyPy than ctypes so if you're targeting PyPy it's better to use it. I was told that CFFI has been known to be a bit slower than C extensions on CPython because it does not access the C API directly but it wraps it. I could not find evidence for that claim although it makes sense.</p><p>If you're interfacing with C++ code, there has been a discussion to <a href="https://mail.python.org/pipermail/pypy-dev/2014-January/012038.html">port boost::python</a> to PyPy but I don't think it has been done yet.</p><p>PyPy provides <a href="http://pypy.readthedocs.org/en/latest/cppyy.html">cppyy</a> which is written in CPython and thus able to JIT out most of the binding related code. cppyy has multiple backends it can use. In this post I'm going to cover <a href="https://root.cern.ch/how/how-use-reflex">Reflex</a> since it's the default and it is currently the most stable backend.</p><p>In this post I'm going to demonstrate how to run <a href="https://developers.google.com/protocol-buffers/">Protobuf </a>2.5.1 on PyPy. Protobuf's compiler generates Python code which relies on a CPython extension in order to interface with the Protobuf implementation and is I mentioned before this is not going to be as fast as it should be for PyPy. Google provides a pure python implementation of Protobuf in version 3.0 which is not released yet and breaks compatibility in some aspects from Protobuf 2.x.</p><p>In order to use Protobuf with PyPy we have two options. Using CFFI or cppyy. Using CFFI requires us to be familiar with Protobuf's C API and writing the bindings manually which is not something we wanted since we needed to start working on our product as soon as possible. Fortunately Protobuf also generates C++ code so we can use cppyy in order to create a C++ binding to our Protobuf messages.</p><h1>Installing the dependencies</h1><h2>Installing Protobuf</h2><p>In order to install Protobuf type:</p>


























  <h2>Installing Reflex</h2><p>Reflex has some dependencies that are required in order to compile and use it.</p>


























  <p>In order to compile Reflex type:</p>


























  <p>In case anyone runs into trouble the full output of a successful installation can be found <a href="https://gist.github.com/thedrow/1071646c832d28e7f211">here</a>.</p><p>If you want to always be able to use reflex add the export statements to your .bashrc file and restart your shell.</p><p>In order to test that the process succeeded type:</p>


























  <p id="yui_3_17_2_1_1449414819830_43380">You'll get the usage information of the genreflex command line program.<br></p><p>In order to check if PyPy recognizes the Reflex backend type:</p>


























  <p>If something went wrong you'll see the following traceback:</p>


























  <h1>Compiling the Protobuf messages</h1><p>For this post we're going to use the following Protobuf messages:</p>


























  <p>In order to compile the mesages to C++ type:</p>


























  <p>If the compilation succeeded you'll see OK printed to your screen.</p><h1>Generating the bindings</h1><p>This is where things get interesting. The first time we run genreflex we got some errors:</p>


























  <p>This error is caused by what is probably a bug in GCCXML since the code can be compiled by g++. Googling reveals that <a href="http://en.cppreference.com/w/cpp/types/ptrdiff_t">ptrdif_t</a> is defined in the standard C++ library.</p><p>The solution is to include the std namespace prefix before each usage of the ptrdiff_t type.</p><p>For your convinience here's a patch that does exactly that. Make sure to back up the original header.</p>


























  <p>Apply it by typing:</p>


























  <p>After that, generate the bindings again and you should not be getting any errors.</p>


























  <p>Don't rush into compiling this just yet. Since we're using strings and we haven't provided any reflection information on std::string, cppyy will segfault.</p><p>In order to resolve that we need to specify the <strong>--deep</strong> argument when invoking genreflex. Generaly speaking this is always a good idea to specify this argument if you want to avoid these kind of problems later on as I have found out.</p>


























  <p>After running genreflex with the <strong>--deep</strong> command line argument compile the generated bindings:</p>


























  <p>After that you may load the resulting shared object into PyPy and start working with it.</p>


























  <p>It's not all roses and peaches. There are still issues with the Reflex backend. Exceptions from C++ will just be printed instead of being raised on the Python side for example so test this carefully to see if it works for you too.</p><p>As you can see there are API differences between the Python Protobuf implementation and the C++ Protobuf implementation. I leave it as an exercise for the readers to implement the appropriate adapters. If you do so, please leave a comment.</p><p>There's also a good chance that we could create a Makefile that automates all these tasks. If you have written one, please also leave a comment.</p><p> </p>]]></content:encoded></item><item><title>Git Hooks (Part II) – Implementing Git hooks using Python</title><category>Git</category><category>SCM</category><dc:creator>Omer Katz</dc:creator><pubDate>Sun, 21 Sep 2014 22:31:00 +0000</pubDate><link>https://www.omerkatz.com/blog/2013/5/23/git-hooks-part-2-implementing-git-hooks-using-python</link><guid isPermaLink="false">5138dccfe4b073120964d739:5138e128e4b0653ec0f305ae:519df5a1e4b0b0b645c71ade</guid><description><![CDATA[This post describes how to implement Git hooks using Python. If you have 
some commit hooks in Python or any other languages please do share them in 
the comments as Gists or repositories.]]></description><content:encoded><![CDATA[<p>This post describes how to implement Git hooks using Python. If you have some commit hooks in Python or any other languages please do share them in the comments as <a href="https://gist.github.com">Gists</a> or repositories.</p><h1>General Information</h1><h2>The Templates Directories</h2><p>We have two directories that interest us:</p><ul><li>The '<em>/usr/share/git-core/templates/</em>' directory on <strong>Linux</strong> and '<em>C:/Program Files (x86)/Git/share/git-core/templates/</em>' directory on <strong>Windows</strong> (Note that on 32bit machines msysGit is installed by default on <em>'C:/Program Files/…'</em>) in which the default hooks are being copied from. If you installed Git using another configuration the installation might reside in a different folder. Adjust the path accordingly.</li><li>The '<em>.git/hooks/</em>' directory is the directory in which the hooks templates are being copied to.</li></ul><p>The hooked are being copied from the '<em>[...]/share/git-core/templates/</em>'&nbsp; directory.&nbsp; There are other types of templates but they are out of scope for this post.</p><p><strong>Note:&nbsp;</strong> If you change the templates directory the hooks directory <strong>&nbsp;</strong>must be a subdirectory of the templates directory. <strong>Do not</strong> set the templates directory to the desired hooks directory instead.</p><h3>Changing the global templates directory</h3><p>If you'd like to change the global templates directory open the terminal and type:</p>


























  <p>You can also <a href="http://www.cyberciti.biz/faq/set-environment-variable-linux/">set</a> the $GIT_TEMPLATE_DIR environment variable:</p>


























  <p>The global templates
directory is <strong>exclusively</strong> for hook templates. Just as we
usually don’t like to use site-packages for Python and therefore we
set up a virtualenv for containment of each project/deployment/test suite we
don’t want global business logic for our hooks, just framework code.</p><p>The .git/hooks/
directory should contain the business logic of the hooks.</p><h3>Changing the repository's templates directory</h3><p>You can change the
template directory when you <em>git init </em>or <em>git clone </em>using
the <em>--template</em> option to the desired templates directory specifically for the newly created repository.</p><p>For new repositories open the terminal and type:</p>


























  <p>For cloned repositories open the terminal and type:&nbsp;</p>


























  <h3>Order of precedence</h3><p>The hooks templates folder will be chosen by the following precedence:</p><ul><li>The argument given with the <em>--template</em> option.</li><li>The value of the $GIT_TEMPLATE_DIR.</li><li>The init.templatedir configuration variable.</li><li>The default templates directory.</li></ul><h1>Starting Fresh</h1><p>The default templates directory contains some examples. Each example script ends with the <em>*.example</em> extension. If you remove the extension they become executable git hooks.</p><p>Since we are developing using Python lets create a new templates folder. Copy the templates into the python-templates folder.</p><p>Erase the contents of the hooks folder, <a href="https://gist.github.com/thedrow/5711130/download">download this gist</a> and extract it into the empty hooks folder.</p>


























  <h1>Architecture</h1><p>Hooks are simple <a href="http://en.wikipedia.org/wiki/Command-line_interface">CLI</a> programs. That's how git works. Every git command or sub system is a CLI program.&nbsp;</p><h2>Parsing Arguments</h2><p>The Python standard library provides us with two libraries for parsing command line arguments:&nbsp;</p><ul><li>Optparse - Simple but deprecated.</li><li>Argparse - Has support for everything we need including accepting STDIN as an argument which is used by <a href="http://git-scm.com/book/ch7-3.html#Server-Side-Hooks">git's server side hooks</a>.&nbsp;</li></ul><p>You can also use the wonderful&nbsp;<a href="http://docopt.org">docopt</a>&nbsp;, a library that automagically parses your docstrings and generates a CLI for you. It has ports to different languages so if you are not using python, you can still use it.</p><h2>Communicating with Git</h2><p>Sometimes you need to access your git repository to fetch information or even modify it. Python has a library that do just that. It's called&nbsp;<a href="https://github.com/jelmer/dulwich">Dulwitch</a>,&nbsp;<span>A pure&nbsp;</span><span>Python&nbsp;</span><span>i</span><span>mplementation of Git.</span></p><h1>Testing Your Hooks</h1><p>Testing your hooks is not hard but here are a few guidelines that might help you in doing so:</p><h2>Unit Testing</h2><p>Since we know git works we should mock out the dependencies that git hooks use. For example commit hooks provide the name of the file that contains the commit message as an argument.</p><p>You can do so by mocking open() as explained <a href="http://stackoverflow.com/questions/1289894/how-do-i-mock-an-open-used-in-a-with-statement-using-the-mock-framework-in-pyth">here</a>.</p><p>If you're using a tool like pep8 in a commit hook mock it as well and ensure it is called.</p><h2>Functional Testing</h2><p>Fake the process object and invoke the commit hook with the correct arguments.</p><p><a href="https://github.com/nose-devs/nose2/blob/master/nose2/tests/_common.py#L161">See how we did it with nose2</a>. It's not complicated.&nbsp;</p><h2>Integration Testing</h2><p>In order to verify that your hooks work exactly as expected you need to invoke git directly.</p><p>You're integration tests should git init when you initialize the suite and remove the .git folder when the suite is done running.</p><p>I prefer using <a href="https://github.com/cenkalti/what">what</a>&nbsp;instead of the standard library to run sub processes because it has some assertions built into it.</p><p>That's it you're good to go. Your commits will be safer now that you write hooks that protect you from making silly mistakes.</p>]]></content:encoded></item><item><title>Measuring Coverage Accurately with Coveralls.io</title><category>Continuous Integretion</category><category>SCM</category><dc:creator>Omer Katz</dc:creator><pubDate>Sun, 13 Oct 2013 20:00:00 +0000</pubDate><link>https://www.omerkatz.com/blog/2013/10/13/measuring-coverage-accurately-with-coverallsio</link><guid isPermaLink="false">5138dccfe4b073120964d739:5138e128e4b0653ec0f305ae:5256b62be4b04e2e8158749b</guid><description><![CDATA[If you've ever developed an open source project on Github you probably have 
heard about coveralls.io already but you, like me until recently are 
probably not measuring code coverage accurately enough if you have multiple 
testsuites (e.g.. unit, functional, integration).

How did I reach this conclusion? Keep reading.]]></description><content:encoded><![CDATA[<p>If you've ever developed an open source project on Github you probably have heard about <a href="https://coveralls.io">coveralls.io</a>&nbsp;already but you, like me until recently are probably not measuring code coverage accurately enough if you have multiple testsuites (e.g.. unit, functional, integration).</p><p>How did I reach this conclusion? Keep reading.</p><h1>What Is Coveralls</h1><blockquote>Coveralls is a web service to help you track your code coverage over time, and ensure that all your new code is fully covered.</blockquote><blockquote>There is but one prerequisite: Your code must be hosted on Github.</blockquote><blockquote>The Coveralls service is language-agnostic and CI-agnostic.</blockquote><p></p><h1>The Incident</h1><p>At my day job we started &nbsp;<a href="http://about.travis-ci.org/blog/2012-11-28-speeding-up-your-tests-by-parallelizing-them/">parallelizing our builds</a>&nbsp;on Travis-Ci so that we will know faster if the unit and functional tests have passed in the meanwhile until the integration testsuite finishes up.</p><p>When the first parallelized build completed and succeeded we got the a notification from coveralls that our coverage decreased by <strong>50%</strong>. That's a very drastic change. It's seems like a bug no? But it's an unintended feature and a great one.</p><h1>The Cause</h1><p>When you split the build by testsuites each testsuite's code coverage is being measured&nbsp;<strong>separately</strong>&nbsp;. Apparently, our integration tests covered much more code than our unit tests. It seems intuitive but it took me a minute or two to figure it out.</p><h1>Conclusion</h1><p>Parallelize your build. It's important not only because the build process is more responsive but because it helps you measure code coverage correctly.<span></span></p><p>&nbsp;</p>]]></content:encoded></item><item><title>I am Now a nose2 Core Commiter!</title><category>General Announcements</category><dc:creator>Omer Katz</dc:creator><pubDate>Sun, 11 Aug 2013 13:31:11 +0000</pubDate><link>https://www.omerkatz.com/blog/2013/8/11/nose2-core-commiter</link><guid isPermaLink="false">5138dccfe4b073120964d739:5138e128e4b0653ec0f305ae:52079252e4b0b43f79704b1f</guid><description><![CDATA[<p>I am now part of the <a href="https://github.com/nose-devs/nose2/">nose2 </a>core development team. nose2 is the next generation of nicer testing for Python, based
on the plugins branch of unittest2.</p>]]></description></item><item><title>More Information About Steps To Install The New Setuptools</title><category>Packaging</category><category>SCM</category><dc:creator>Omer Katz</dc:creator><pubDate>Tue, 25 Jun 2013 06:00:00 +0000</pubDate><link>https://www.omerkatz.com/blog/2013/6/24/more-information-about-steps-to-install-the-new-setuptools</link><guid isPermaLink="false">5138dccfe4b073120964d739:5138e128e4b0653ec0f305ae:51c8abd1e4b00d4cc589561e</guid><description><![CDATA[<p>I had some problems with packages that still depend on Distribute directly. I solved them by installing Distribute 0.7.x compatibility layer. <br></p><p>I updated the original post with the information on how to do so.<br></p><p>You can find it <a href="https://omer-katz.squarespace.com/blog/2013/6/20/distribute-is-now-merged-back-to-setuptools">here</a>.&nbsp;</p>]]></description></item><item><title>Enforce Plugin Dependency Requirements Using Vagrant Plugin Bundler</title><category>Packaging</category><category>Virtualization</category><category>SCM</category><dc:creator>Omer Katz</dc:creator><pubDate>Wed, 19 Jun 2013 17:00:00 +0000</pubDate><link>https://www.omerkatz.com/blog/2013/6/19/manage-your-vagrant-plugins-requirements-with-vagrant-plugin-bundler</link><guid isPermaLink="false">5138dccfe4b073120964d739:5138e128e4b0653ec0f305ae:51c0dd89e4b0e7a2ae96d25c</guid><description><![CDATA[ 

We like package managers. They help us maintain our dependencies easily.

Vagrant has a package manager for it's plugins which make them very easy to 
install, upgrade or remove but before Vagrant Plugin Bundler we had no way 
to ensure our Vagrantfile is using the right version of each plugin.

With Vagrant Plugin Bundler you can do so very easily. ]]></description><content:encoded><![CDATA[<p>We like package managers. They help us maintain our dependencies easily.<br></p><p>Vagrant has a package manager for it's plugins which make them very easy to install, upgrade or remove but before Vagrant Plugin Bundler we had no way to ensure our <em>Vagrantfile</em> is using the right version of each plugin.</p><p>With Vagrant Plugin Bundler you can do so very easily.&nbsp;</p><h1>Installation</h1><p>This is simply a must if you use Vagrant. To install type:&nbsp;</p>























<iframe scrolling="0" src="http://ghbtns.com/github-btn.html?user=tknerr&amp;repo=vagrant-plugin-bundler&amp;type=watch&amp;count=true&amp;size=large" allowtransparency="true" width="150" frameborder="0" height="30"></iframe>
<iframe scrolling="0" src="http://ghbtns.com/github-btn.html?user=tknerr&amp;repo=vagrant-plugin-bundler&amp;type=fork&amp;count=true&amp;size=large" allowtransparency="true" width="100" frameborder="0" height="30"></iframe>
<iframe scrolling="no" seamless="seamless" src="http://colmdoyle.github.io/gh-activity/gh-activity.html?user=tknerr&amp;repo=vagrant-plugin-bundler&amp;type=repo" allowtransparency="true" width="300" frameborder="0" height="320"></iframe>


  <p>Done? Great!&nbsp;</p><p>This should be installed with every machine that runs Vagrant. Period.&nbsp;</p><h1>Usage</h1><p>It's very easy to get started with Vagrant Plugin Bundler. Open up your <em>Vagrantfile</em> and define your dependencies in the following way:<br></p>


























  <p>If you have only one dependency you can simply add the following line to your <em>Vagrantfile</em>:&nbsp;</p>


























  <p>Assuming that vagrant-omnibus is not installed you will get an error that says that you should install the version you specified in your <em>Vagrantfile</em> of vagrant-omnibus in order to proceed.&nbsp;</p><h1>Why Vagrant Plugin Bundler Is Useful</h1><p>If you distribute your Vagrant boxes to be used as baselines you can specify the dependency requirements with the <em>Vagrantfile</em> that was included inside the box. This ensures that further development on that box will be made possible quickly. In fact you should include the plugin dependencies anyway as they will be required to run the box at times (if not at all times).<br></p><p>Assuming that <a href="https://omerkatz.com/blog/2013/6/15/travis-ci-does-not-work-when-you-package-vagrant-boxes-as-a-build-step-yet">Travis will be able to run Vagrant in the near future</a>, with Vagrant Plugin Bundler you can ensure your build fails very early if you haven't installed all your plugin dependencies correctly.<br></p><h1>What's Missing</h1><ul><li>Specifying the plugin's version is currently a requirement. <a href="https://github.com/tknerr/vagrant-plugin-bundler/issues/4">It should be optional.</a><br></li><li><a href="https://github.com/tknerr/vagrant-plugin-bundler/issues/10">A plugins sandbox</a> that will allow to install plugins per <em>Vagrantfile</em>&nbsp; in order to run Vagrant projects with the same plugins but different versions.</li><li><a href="https://github.com/tknerr/vagrant-plugin-bundler/issues/6">A command to install all required dependencies</a> and <a href="https://github.com/tknerr/vagrant-plugin-bundler/issues/8">a command to check that the current state of the dependencies matches the required state</a>.&nbsp;</li><li><a href="https://github.com/tknerr/vagrant-plugin-bundler/issues/5">Flexible Version Constraints</a>.&nbsp;</li></ul><p>Got more ideas? <a href="https://github.com/tknerr/vagrant-plugin-bundler/issues/new">Create an issue</a>.<br></p><p>Would you like to contribute? <a href="https://github.com/tknerr/vagrant-plugin-bundler/fork">Fork it</a>.&nbsp;</p><h1>And Finally</h1><p>You should all thank the developer that made it happen. Thank you <a href="https://github.com/tknerr">@tknerr!</a></p><p>&nbsp;</p>]]></content:encoded></item><item><title>Distribute Is Now Merged Back To Setuptools</title><category>Packaging</category><dc:creator>Omer Katz</dc:creator><pubDate>Wed, 19 Jun 2013 06:00:00 +0000</pubDate><link>https://www.omerkatz.com/blog/2013/6/20/distribute-is-now-merged-back-to-setuptools</link><guid isPermaLink="false">5138dccfe4b073120964d739:5138e128e4b0653ec0f305ae:51c0d6b6e4b0cf320a6177f9</guid><description><![CDATA[As of Setuptools 0.7 Distribute is now merged back into Setuptools.

This means that you should remove Distribute if you have it installed 
already and you probably do. 

You can find the instructions to do so here but I have encountered some 
problems during the process so I'll share my solution here.]]></description><content:encoded><![CDATA[<p>As of <a href="https://pypi.python.org/pypi/setuptools/">Setuptools</a> 0.7 <a href="https://pypi.python.org/pypi/distribute/">Distribute</a> is now merged back into Setuptools. The new king is dead - Long live the old king. I know it's the other way around usually but hey haven't you watched <a href="http://www.youtube.com/watch?v=78juOpTM3tE">episode 9 of Game of Thrones (Spoiler Alert)</a>?<br></p><p>This means that you should remove Distribute if you have it installed already and you probably do.&nbsp;</p><p>You can find the instructions to do so <a href="https://bitbucket.org/pypa/setuptools/overview#rst-header-uninstalling">here</a> but I have encountered some problems during the process so I'll share my solution here.<br></p><h1>Step 1 - Remove Distribute<br></h1><p>You have to remove all Distribute versions that were already installed on all Python versions across the system.</p><p>To do so simply type:&nbsp;&nbsp;</p>


























  <h1>Step 2 - Upgrade Setuptools</h1><p>You want to install Setuptools 0.7 and above for all Python versions.<br></p><p>To do so type:&nbsp;</p>


























  <h1>Step 3 - Reinstall pip</h1><p>It might be necessary to reinstall pip. After upgrading on my machine pip stopped working.&nbsp; It seems that there is an <a href="https://github.com/pypa/pip/pull/992">active pull request </a>that obsoletes this step. The awesome developers that work on pip are attempting to resolve this.<br></p><p>In the meanwhile type:&nbsp;</p>


























  <h1>Step 4 - Install Distribute 0.7.x<br></h1><p>I know I just said distribute is deprecated but some python packages still depend on it. Setuptools provides a compatibility layer that redirects all distribute calls to Setuptools.<br></p><p>Make sure you install Distribute 0.7.x <strong>after</strong>&nbsp; you install Setuptools or <a href="https://github.com/pypa/pip/issues/986">you'll have trouble</a>.<br></p><p>To install Distribute 0.7.x type:&nbsp;</p><p></p>


























  <h1>Step 5 (Optional) - Upgrade Tox</h1><p><a href="http://testrun.org/tox/latest//">Tox</a> 1.5.0 will now use Setuptools 0.7.x by default instead of Distribute. I filed the <a href="https://bitbucket.org/hpk42/tox/issue/104/distribute-is-now-deprecated-use">issue</a>. You're welcome.</p><p>If you are using Tox it is strongly advised to upgrade. If you are not using Tox you can skip this step.<br></p><p>To do so type:&nbsp;</p>


























  <p><strong>All done.</strong>&nbsp;</p><p>Goodbye Distribute. You won't be missed anymore.&nbsp;</p>]]></content:encoded></item><item><title>Travis-CI Does Not Work When You Package Vagrant Boxes As A Build Step (Yet)</title><category>Virtualization</category><category>Continuous Integretion</category><dc:creator>Omer Katz</dc:creator><pubDate>Sat, 15 Jun 2013 15:08:57 +0000</pubDate><link>https://www.omerkatz.com/blog/2013/6/15/travis-ci-does-not-work-when-you-package-vagrant-boxes-as-a-build-step-yet</link><guid isPermaLink="false">5138dccfe4b073120964d739:5138e128e4b0653ec0f305ae:51bc72c4e4b0510af19fc6d7</guid><description><![CDATA[I'm learning how to use Salt Stack so I started a new project that 
provisions a baseline Vagrant Box for Python development.

I wanted to check that my vagrant box can be provisioned & packaged every 
single time for every single change I committed into the repository so I 
created a .travis.yml configuration file in order to do so.

That attempt has failed unfortunately.  Read this post to understand why.]]></description><content:encoded><![CDATA[<p>I'm learning how to use <a href="http://saltstack.com/community.html">Salt Stack</a>&nbsp;so I started a new project that provisions a baseline Vagrant Box for Python development.</p><h1>The Goal</h1><p>I wanted to check that my vagrant box can be provisioned &amp; packaged every single time for every single change I committed into the repository so I created a <em>.travis.yml&nbsp;</em>configuration file in order to do so.</p><h1>What is Travis-Ci</h1><p>If you are not familiar with Travis CI then you should be. <a href="http://travis-ci.org">Travis CI</a> is the most popular Continuous Integration service for Github repositories and for a good reason: It's Free and Awesome™.&nbsp;</p><p>&nbsp;</p>























<iframe scrolling="0" src="http://ghbtns.com/github-btn.html?user=thedrow&amp;repo=python-baseline&amp;type=watch&amp;count=true&amp;size=large" allowtransparency="true" width="150" frameborder="0" height="30"></iframe>
<iframe scrolling="0" src="http://ghbtns.com/github-btn.html?user=thedrow&amp;type=fork&amp;repo=python-baseline&amp;count=true&amp;size=large" allowtransparency="true" width="100" frameborder="0" height="30"></iframe>
<iframe scrolling="no" seamless="seamless" src="http://colmdoyle.github.io/gh-activity/gh-activity.html?user=thedrow&amp;repo=python-baseline&amp;type=repo" allowtransparency="true" width="300" frameborder="0" height="320"></iframe>


  <p>Please consider using it for your current and future open source projects. It's&nbsp;<a href="http://about.travis-ci.org/docs/user/getting-started/">really easy</a>.</p><p>Before you continue go read a little bit about the&nbsp;<a href="http://about.travis-ci.org/docs/user/build-configuration/#.travis.yml-file%3A-what-it-is-and-how-it-is-used">.travis.yml</a>&nbsp;configuration file format if you haven't done so already. I'll wait.</p><p>Done? Great, let's proceed.&nbsp;</p><h1>The Build Process</h1><p>I configured Travis to execute the following build process and thought it should work as is.</p><p>&nbsp;</p>


























  <p>I was wrong. So very wrong.&nbsp; As you will see it's not trivial to implement at all.</p><h1>The Problem</h1><p>Travis CI uses <a href="http://openvz.org">OpenVZ</a> virtualized containers to execute your build process.&nbsp;<span>Vagrant uses a virtualization provider like VirtualBox in order to provision &amp; package a box.</span></p><p>The result is that you have a virtualized container inside a virtualized container which is akin to placing a hamster wheel on top of another hamster wheel with both hamsters running in the opposite directions.</p>

































































 

  
  
    

      

      
        <figure class="
              sqs-block-image-figure
              intrinsic
            "
        >
          
        
        

        
          
            
          
            
                
                
                
                
                
                
                
                <img data-stretch="false" data-image="https://images.squarespace-cdn.com/content/v1/5138dccfe4b073120964d739/1371314230447-6YPB8XQWC79I996NH01T/surprised-hamster.jpg" data-image-dimensions="603x400" data-image-focal-point="0.5,0.5" alt="" data-load="false" elementtiming="system-image-block" src="https://images.squarespace-cdn.com/content/v1/5138dccfe4b073120964d739/1371314230447-6YPB8XQWC79I996NH01T/surprised-hamster.jpg?format=1000w" width="603" height="400" sizes="(max-width: 640px) 100vw, (max-width: 767px) 100vw, 100vw" onload="this.classList.add(&quot;loaded&quot;)" srcset="https://images.squarespace-cdn.com/content/v1/5138dccfe4b073120964d739/1371314230447-6YPB8XQWC79I996NH01T/surprised-hamster.jpg?format=100w 100w, https://images.squarespace-cdn.com/content/v1/5138dccfe4b073120964d739/1371314230447-6YPB8XQWC79I996NH01T/surprised-hamster.jpg?format=300w 300w, https://images.squarespace-cdn.com/content/v1/5138dccfe4b073120964d739/1371314230447-6YPB8XQWC79I996NH01T/surprised-hamster.jpg?format=500w 500w, https://images.squarespace-cdn.com/content/v1/5138dccfe4b073120964d739/1371314230447-6YPB8XQWC79I996NH01T/surprised-hamster.jpg?format=750w 750w, https://images.squarespace-cdn.com/content/v1/5138dccfe4b073120964d739/1371314230447-6YPB8XQWC79I996NH01T/surprised-hamster.jpg?format=1000w 1000w, https://images.squarespace-cdn.com/content/v1/5138dccfe4b073120964d739/1371314230447-6YPB8XQWC79I996NH01T/surprised-hamster.jpg?format=1500w 1500w, https://images.squarespace-cdn.com/content/v1/5138dccfe4b073120964d739/1371314230447-6YPB8XQWC79I996NH01T/surprised-hamster.jpg?format=2500w 2500w" loading="lazy" decoding="async" data-loader="sqs">

            
          
        
          
        

        
          
          <figcaption class="image-caption-wrapper">
            <p>A very surprised hamster</p>
          </figcaption>
        
      
        </figure>
      

    
  






  <p>Even the OpenVZ twitter account maintainer says it's generally considered as a bad idea:</p>























<blockquote class="twitter-tweet"><p><a href="https://twitter.com/the_drow">@the_drow</a> <a href="https://twitter.com/travisci">@travisci</a> running virtualization inside virtualization is hardly a good idea. Rent a dedicated server and run VirtualBox on that.</p>— OpenVZ Containers (@_openvz_) <a href="https://twitter.com/_openvz_/statuses/345755705766182913">June 15, 2013</a></blockquote>



  <p>But not being able to assure that you can release your Vagrant box at any given time defies the whole purpose of Continuous integration. So we run into a deadlock here.</p>

































































 

  
  
    

      

      
        <figure class="
              sqs-block-image-figure
              intrinsic
            "
        >
          
        
        

        
          
            
          
            
                
                
                
                
                
                
                
                <img data-stretch="false" data-image="https://images.squarespace-cdn.com/content/v1/5138dccfe4b073120964d739/1371314152170-0OSCWF44H5DOCW1ZE0CH/hamster2.jpg" data-image-dimensions="601x400" data-image-focal-point="0.5,0.5" alt="" data-load="false" elementtiming="system-image-block" src="https://images.squarespace-cdn.com/content/v1/5138dccfe4b073120964d739/1371314152170-0OSCWF44H5DOCW1ZE0CH/hamster2.jpg?format=1000w" width="601" height="400" sizes="(max-width: 640px) 100vw, (max-width: 767px) 100vw, 100vw" onload="this.classList.add(&quot;loaded&quot;)" srcset="https://images.squarespace-cdn.com/content/v1/5138dccfe4b073120964d739/1371314152170-0OSCWF44H5DOCW1ZE0CH/hamster2.jpg?format=100w 100w, https://images.squarespace-cdn.com/content/v1/5138dccfe4b073120964d739/1371314152170-0OSCWF44H5DOCW1ZE0CH/hamster2.jpg?format=300w 300w, https://images.squarespace-cdn.com/content/v1/5138dccfe4b073120964d739/1371314152170-0OSCWF44H5DOCW1ZE0CH/hamster2.jpg?format=500w 500w, https://images.squarespace-cdn.com/content/v1/5138dccfe4b073120964d739/1371314152170-0OSCWF44H5DOCW1ZE0CH/hamster2.jpg?format=750w 750w, https://images.squarespace-cdn.com/content/v1/5138dccfe4b073120964d739/1371314152170-0OSCWF44H5DOCW1ZE0CH/hamster2.jpg?format=1000w 1000w, https://images.squarespace-cdn.com/content/v1/5138dccfe4b073120964d739/1371314152170-0OSCWF44H5DOCW1ZE0CH/hamster2.jpg?format=1500w 1500w, https://images.squarespace-cdn.com/content/v1/5138dccfe4b073120964d739/1371314152170-0OSCWF44H5DOCW1ZE0CH/hamster2.jpg?format=2500w 2500w" loading="lazy" decoding="async" data-loader="sqs">

            
          
        
          
        

        
      
        </figure>
      

    
  






  <h2>Bad Ideas can Still Lead to Working Solutions Right?</h2><p>Not in this case. You see, OpenVZ containers have a custom made kernel based on version 2.6.32. VirtualBox requires the running kernel to be a standard kernel in order to be able to host the Vagrant boxes. If a standard kernel does not exist VirtualBox won't be able to use the current machine as a host for anything.</p><p>Here's the <a href="https://travis-ci.org/thedrow/python-baseline/builds/8117503">build log</a>. Go through it. If you can find a solution please leave a comment.&nbsp;</p><p></p>

































































 

  
  
    

      

      
        <figure class="
              sqs-block-image-figure
              intrinsic
            "
        >
          
        
        

        
          
            
          
            
                
                
                
                
                
                
                
                <img data-stretch="true" data-image="https://images.squarespace-cdn.com/content/v1/5138dccfe4b073120964d739/1371314310790-YKTZFL2MESGKYZ02CQZB/master-hamster.jpg" data-image-dimensions="266x300" data-image-focal-point="0.5,0.5" alt="" data-load="false" elementtiming="system-image-block" src="https://images.squarespace-cdn.com/content/v1/5138dccfe4b073120964d739/1371314310790-YKTZFL2MESGKYZ02CQZB/master-hamster.jpg?format=1000w" width="266" height="300" sizes="(max-width: 640px) 100vw, (max-width: 767px) 100vw, 100vw" onload="this.classList.add(&quot;loaded&quot;)" srcset="https://images.squarespace-cdn.com/content/v1/5138dccfe4b073120964d739/1371314310790-YKTZFL2MESGKYZ02CQZB/master-hamster.jpg?format=100w 100w, https://images.squarespace-cdn.com/content/v1/5138dccfe4b073120964d739/1371314310790-YKTZFL2MESGKYZ02CQZB/master-hamster.jpg?format=300w 300w, https://images.squarespace-cdn.com/content/v1/5138dccfe4b073120964d739/1371314310790-YKTZFL2MESGKYZ02CQZB/master-hamster.jpg?format=500w 500w, https://images.squarespace-cdn.com/content/v1/5138dccfe4b073120964d739/1371314310790-YKTZFL2MESGKYZ02CQZB/master-hamster.jpg?format=750w 750w, https://images.squarespace-cdn.com/content/v1/5138dccfe4b073120964d739/1371314310790-YKTZFL2MESGKYZ02CQZB/master-hamster.jpg?format=1000w 1000w, https://images.squarespace-cdn.com/content/v1/5138dccfe4b073120964d739/1371314310790-YKTZFL2MESGKYZ02CQZB/master-hamster.jpg?format=1500w 1500w, https://images.squarespace-cdn.com/content/v1/5138dccfe4b073120964d739/1371314310790-YKTZFL2MESGKYZ02CQZB/master-hamster.jpg?format=2500w 2500w" loading="lazy" decoding="async" data-loader="sqs">

            
          
        
          
        

        
          
          <figcaption class="image-caption-wrapper">
            <p>Master Hamster to the rescue</p>
          </figcaption>
        
      
        </figure>
      

    
  






  <h1>Possible Workarounds</h1><ol><li>As @_OpenVZ_ sugguested above, rent a dedicated server. After you installed VirtualBox &amp; Vagrant develop a <a href="http://fabfile.org/">Fabric</a>&nbsp;tasks that connects to that server through SSH, executes <em>vagrant up</em>&nbsp; and&nbsp;<em></em><i>vagrant package mybox. If the any of these tasks return a non-zero status code the build will fail. This solution <strong>certainly</strong> works but it is also very expensive to implement when you are developing a small open source project with no financial support. When you log in through SSH make sure your credentials are being passed over using <a href="http://about.travis-ci.org/docs/user/build-configuration/#Secure-environment-variables">secured environment variables</a>.</i></li><li>Attempt to build VirtualBox for the OpenVZ customized kernel. I haven't tried yet but I have little hopes that it will work.</li><li>Wait until the awesome infrastructure team at Travis will find a solution. I will make sure to report when they will find one. Follow the Storify below for updates.</li></ol>]]></content:encoded></item><item><title>Vagrant Providers - VMWare Support Out Of The Box</title><category>Virtualization</category><dc:creator>Omer Katz</dc:creator><pubDate>Wed, 29 May 2013 14:43:21 +0000</pubDate><link>https://www.omerkatz.com/blog/2013/5/29/vagrant-providers-vmware-support-out-of-the-box</link><guid isPermaLink="false">5138dccfe4b073120964d739:5138e128e4b0653ec0f305ae:51a60141e4b01fcfc74c7fa2</guid><description><![CDATA[Since version 1.1.0 Vagrant supports multiple virtualization solutions 
through a new concept called providers. They are easy to install and use.

The first paid providers that were developed are for VMWare Fusion & VMWare 
Workstation.  There are other providers for the cloud. ]]></description><content:encoded><![CDATA[<p>Since version 1.1.0 Vagrant supports multiple virtualization solutions through a new concept called providers.<br></p><p>They are very easy to use and install. The learning curve is really low.&nbsp;</p><h1>Usage</h1><p>Installing a provider is as easy as <a href="http://docs.vagrantup.com/v2/plugins/usage.html">installing any other Vagrant plugin</a>:</p>


























  <p>The workflow is exactly the same. When running a machine with a specific provider you only need to add the <em>--provider</em> option when you type <em>vagrant up</em>:</p>


























  <p>The rest is <strong>exactly</strong> the same.<br></p><p>Read more about providers at <a href="http://docs.vagrantup.com/v2/providers/">Vagrant's documentation site</a>.&nbsp;</p><h1>VMWare Workstation &amp; VMWare Fusion Support<br></h1><p>Vagrant now provides a paid providers for <a href="http://www.vmware.com/products/fusion/overview.html">VMWare Fusion</a> (for Mac OS X) &amp; <a href="http://www.vmware.com/products/workstation/">VMWare Workstation</a> (For Windows &amp; Linux).<br></p><p>A license for one of these providers costs 79$ per person for a seat (two computers).<br></p><h2>Why is this exciting?<br></h2><p>Because VMWare outperforms VirtualBox in almost every aspect if you are managing a serious virtualization layer.&nbsp;</p><p>I have never encountered a serious VirtualBox virtualization layer, it is just never done but not only for performance reasons.&nbsp;<br></p><p>Both <a href="http://www.vmware.com">VMWare</a> &amp; <a href="http://www.hashicorp.com/">Hashicorp</a>&nbsp; provide paid support for their software which is very important for major cooperations because they can get instant support when something goes wrong and someone can be held accountable. <br></p><p>If you are interested in an <a href="http://www.infoworld.com/d/virtualization/review-vmware-workstation-9-vs-virtualbox-42-203277">extensive comparison</a> between VMWare &amp; VirtualBox <a href="http://www.infoworld.com">InfoWorld</a> has already written an excellent and accurate one.<br></p><h1>Providers For The Cloud<br></h1><p>There are two official providers for:&nbsp;</p><ul><li><a href="https://github.com/mitchellh/vagrant-aws">Amazon Web Services</a>&nbsp;</li><li><a href="https://github.com/mitchellh/vagrant-rackspace">Rackspace</a>&nbsp;</li></ul><p>Both cloud services are <a href="http://en.wikipedia.org/wiki/Cloud_computing#Infrastructure_as_a_service_.28IaaS.29">Infrastructure as a Service (IaaS)</a> which means that they fit well to what Vagrant does, managing the virtualization layer configuration items and provisioning them.<br></p><h1>What's Missing?</h1><p>The only thing that in my opinion is missing is a provider for <a href="http://www.vmware.com/products/player/">VMWare Player</a> for those who prefer it over VirtualBox. It's not really a must but a very nice to have feature.<br></p><p>Another thing that is clearly missing is the ability to package multiple images into one box file in order to use the same box for multiple providers. This is evident if you read about the <a href="http://docs.vagrantup.com/v2/boxes/format.html">Vagrant's box format</a>.<br></p><p>I have filed issues <a href="https://github.com/mitchellh/vagrant/issues/1773">#1773</a>&nbsp; &amp; <a href="https://github.com/mitchellh/vagrant/issues/1774">#1774</a> on these subjects. Follow them and this post for updates.</p><h2>Updates</h2><p>As it turns out it is <a href="https://github.com/mitchellh/vagrant/issues/1774#issuecomment-18716624">impossible</a> to add VMWare Player as a provider due to missing features and licensing restrictions.&nbsp;</p>]]></content:encoded></item><item><title>A customized shell for Git</title><dc:creator>Omer Katz</dc:creator><pubDate>Sat, 04 May 2013 17:27:47 +0000</pubDate><link>https://www.omerkatz.com/blog/2013/5/4/a-customized-shell-for-git</link><guid isPermaLink="false">5138dccfe4b073120964d739:5138e128e4b0653ec0f305ae:51853de6e4b0580e000a299f</guid><description><![CDATA[If you are working with Git heavily like me you probably want a customized 
shell.

It lets you know exactly where you stand without typing anything.

It saves you time typing git branch to know what is the correct branch. It 
let's you know how many files are uncommitted/added, what revision are you 
looking at and much more.

If it saves you time you should probably use it. Because if it does it 
allows you to focus on what's important - your product.]]></description><content:encoded><![CDATA[<p>If you are working with Git heavily like me you probably want a customized shell.<br></p><h2>Why Do I Think You Need One</h2><p>​It lets you know exactly where you stand without typing anything.<br></p><p>It saves you time typing <em>git branch</em> to know what is the correct branch. It let's you know how many files are uncommitted/added, what revision are you looking at and much more.​</p><p><em></em>If it saves you time you should probably use it. Because if it does it allows you to focus on what's important - your product.<br></p><h2>For Bash</h2><p><a href="https://github.com/rtomayko/git-sh">git-sh</a>​ is the best customized shell I have found for bash.<br></p><p>​First of all it turns all git commands and aliases to top level commands which saves you from typing git all the time.<br></p><p>It has bash completion built-in.​</p><p>It has a nice customizable prompt ​that allows you to display any relevant information you need about your repository.</p><p>Installing it is very easy. Open the terminal and type:​</p>


























  <p>To activate it type <em>git sh</em> and cd into your repository (if it's not your working directory yet).<br></p><h2>For Powershell</h2><p><a href="https://github.com/dahlbyk/posh-git">Posh-Git</a> takes a different approach. It only customizes the prompt. However, it provides almost anything that git-sh provides besides turning the git commands and aliases to top level commands and there seems to be <a href="https://github.com/dahlbyk/posh-git/issues/97">a discussion</a> to do just that.​</p><p>​To install it use <a href="http://chocolatey.org">chocolatey</a>:<br></p>


























  <p>​And restart the shell.<br></p><p>Note that if you want to install Posh-Hg as well you'd have to install the <a href="http://chocolatey.org/packages/Posh-GIT-HG">Posh-Git-Hg </a>package instead.</p><p>Happy hacking everyone :)​</p>]]></content:encoded></item><item><title>Git Hooks (Part I) - The Basics</title><category>Git</category><category>Source Control</category><dc:creator>Omer Katz</dc:creator><pubDate>Fri, 15 Feb 2013 10:50:03 +0000</pubDate><link>https://www.omerkatz.com/blog/2013/2/15/git-hooks-part-1-the-basics</link><guid isPermaLink="false">5138dccfe4b073120964d739:5138e128e4b0653ec0f305ae:5138e129e4b0653ec0f305b0</guid><description><![CDATA[Hooks are scripts that help you enforce policies on your repository by 
triggering scripts at certain events that enforce policies such as 'The 
commit message must be longer than 20 characters' or 'The test suite must 
be run before a commit and if it fails, reject the commit'.

Hooks are available in every VCS I have used before. They are also 
available in Visual Sourcesafe which is not a VCS.]]></description><content:encoded><![CDATA[<h2>What are hooks?</h2><p>Hooks are scripts that help you enforce policies on your repository by triggering scripts at certain events that enforce policies such as 'The commit message must be longer than 20 characters' or 'The test suite must be run before a commit and if it fails, reject the commit'.</p><p>Hooks are available in every VCS I have used before. They are also available in <a href="http://msdn.microsoft.com/en-us/library/bb509341(v=vs.80).aspx" title="May the force be with you if you actually need this">Visual Sourcesafe</a> which is <strong>not </strong>a VCS.</p><h2>Git Hooks</h2><p>In Git the hook scripts can be implemented using any language but Shell, Ruby, Perl and Python scripts are the most common as far as I know.</p><p>The language of the script is determined by the <a href="http://en.wikipedia.org/wiki/Shebang_(Unix)" title="Wikipedia - Shebang">shebang</a> notation as it is usually in Linux based software. Note that this also applies to Windows because Git for Windows runs under MSYS.</p><p>If you supply the --no-verify argument to the git command then the command will still be executed even if one (or more) of the hooks failed (i.e. returned a non-zero status code). Please do this&nbsp;only&nbsp;if you know what you are doing.</p><p>These hooks reside under the .git/hooks/ directory of your repository.</p><p>The <a href="http://git-scm.com/book/en/Customizing-Git-Git-Hooks" title="Git - Git Hooks">Git-SCM</a> book already covered the various hooks available. It also provided <a href="http://git-scm.com/book/en/Customizing-Git-An-Example-Git-Enforced-Policy" title="Git - An Example Git Enforced Policy">an example</a> of how those hooks can be written in Ruby.</p><p>For a quick reference you can open your favorite shell and type:</p><blockquote class="posterous_short_quote">
<p>git hooks --help</p>
</blockquote><h2>Why should you be using hooks?</h2><p><a href="http://whatthecommit.com/" title="What The Commit - Bad commit messages generator">Because this is the last time we let Tim commit ASCII porn in the comments!</a></p><h3>Controlling commit contents</h3><p>Seriously now, no one wants to be the guy/girl who has to bring coffee &amp; doughnuts at his/her expense for tomorrow’s <a href="http://en.wikipedia.org/wiki/Stand-up_meeting" title="Wikipedia - Stand-up Meeting">standup</a> <a href="http://martinfowler.com/articles/itsNotJustStandingUp.html" title="Martin Fowler - It's Not Just Standing Up: Patterns for Daily Standup Meetings">meeting</a> because he broke the build so we want to make sure our codebase does exactly what it should. If it happens to you too many times you might end up being broke :)</p><p>We want the test suite to run automatically every time we change something. It's one of the reasons we have a test suite, so we know we're on the right path and things aren't broken.</p><p>We also want to make sure that our test coverage is high enough, because untested code won't break the build but it will surely break your production environment.</p><p>These are good example of common hooks that you should implement in order to decrease build breakage and long, frustrating and lonely nights spent screaming “WORK GODDAMIT WORK!” at your development machine.</p><p>Allow me to paraphrase <a href="http://www.quotefully.com/movie/Training+Day/Crackhead+%232" title="Training Day - You wanna' go to jail or you wanna' go home">a line from the movie</a> “Training Day” (It’s a great movie by the way)</p>

































































 

  
  
    

      

      
        <figure class="
              sqs-block-image-figure
              intrinsic
            "
        >
          
        
        

        
          
            
              
              
          
            
                
                
                
                
                
                
                
                <img data-stretch="true" data-image="https://images.squarespace-cdn.com/content/v1/5138dccfe4b073120964d739/1362750542902-OGMIIR12HJBACL3EA8MV/training-day-meme-generator-you-wanna-break-the-build-or-you-wanna-go-home-8b9d17.jpg" data-image-dimensions="510x383" data-image-focal-point="0.5,0.5" alt="" data-load="false" elementtiming="system-image-block" src="https://images.squarespace-cdn.com/content/v1/5138dccfe4b073120964d739/1362750542902-OGMIIR12HJBACL3EA8MV/training-day-meme-generator-you-wanna-break-the-build-or-you-wanna-go-home-8b9d17.jpg?format=1000w" width="510" height="383" sizes="(max-width: 640px) 100vw, (max-width: 767px) 100vw, 100vw" onload="this.classList.add(&quot;loaded&quot;)" srcset="https://images.squarespace-cdn.com/content/v1/5138dccfe4b073120964d739/1362750542902-OGMIIR12HJBACL3EA8MV/training-day-meme-generator-you-wanna-break-the-build-or-you-wanna-go-home-8b9d17.jpg?format=100w 100w, https://images.squarespace-cdn.com/content/v1/5138dccfe4b073120964d739/1362750542902-OGMIIR12HJBACL3EA8MV/training-day-meme-generator-you-wanna-break-the-build-or-you-wanna-go-home-8b9d17.jpg?format=300w 300w, https://images.squarespace-cdn.com/content/v1/5138dccfe4b073120964d739/1362750542902-OGMIIR12HJBACL3EA8MV/training-day-meme-generator-you-wanna-break-the-build-or-you-wanna-go-home-8b9d17.jpg?format=500w 500w, https://images.squarespace-cdn.com/content/v1/5138dccfe4b073120964d739/1362750542902-OGMIIR12HJBACL3EA8MV/training-day-meme-generator-you-wanna-break-the-build-or-you-wanna-go-home-8b9d17.jpg?format=750w 750w, https://images.squarespace-cdn.com/content/v1/5138dccfe4b073120964d739/1362750542902-OGMIIR12HJBACL3EA8MV/training-day-meme-generator-you-wanna-break-the-build-or-you-wanna-go-home-8b9d17.jpg?format=1000w 1000w, https://images.squarespace-cdn.com/content/v1/5138dccfe4b073120964d739/1362750542902-OGMIIR12HJBACL3EA8MV/training-day-meme-generator-you-wanna-break-the-build-or-you-wanna-go-home-8b9d17.jpg?format=1500w 1500w, https://images.squarespace-cdn.com/content/v1/5138dccfe4b073120964d739/1362750542902-OGMIIR12HJBACL3EA8MV/training-day-meme-generator-you-wanna-break-the-build-or-you-wanna-go-home-8b9d17.jpg?format=2500w 2500w" loading="lazy" decoding="async" data-loader="sqs">

            
          
        
            
          
        

        
          
          <figcaption class="image-caption-wrapper">
            <p>​I wanna go home :)</p>
          </figcaption>
        
      
        </figure>
      

    
  






  <p>I don’t know about you guys but I wanna’ go home. I implement these hooks for every project I work on.</p><p>Apart from testing, we want to make sure that our codebase fits our style guidelines so we need to run a lint tool.</p><p>We also want to make sure that the docs can be generated and that every public module, class &amp; method is documented.</p><h3>Controlling commit messages contents</h3><p>Remember that time where you spent a day figuring out what changed in a specific commit that caused major downtime because the commit message was “Fixed this bug” for a commit that added new 20 files and modified 90 other files? If you don’t want to repeat that experience than we have to make sure that we know exactly what changed in each commit.</p><p>First of all, thank Linus, empty commit messages are not allowed in Git. If you do not provide a commit message your favorite editor will be opened for you. If you still haven’t typed anything in your favorite editor, the commit will be aborted.</p><p>But it’s not enough. We have to make sure the commit messages are meaningful.</p><p>It is recommended to reject very short commit messages. Commit messages that contain below 10 characters are usually useless.</p><p>All commit messages must be in English only because your team may speak another language but you never know when you’ll have to subcontract or hire a team member from abroad.</p><p>Since each commit that contains a new feature/bugfix will have its own tests you might want to append a diff of the test results &amp; code coverage from the last commit. This will allow you to understand exactly what was added, removed or changed in each commit.</p><p>If you are willing to write a somewhat complex hook, a hook that verifies that every class &amp; method that was added, modified or removed in the commit is mentioned in the commit message might be useful.</p><p>This list can grow very long and I just wrote the hooks I usually implement and some ideas I have. You are most welcome to share your own ideas in the comments.</p><h2>Next Time</h2><p>Next time I’m going to show you how hooks should be implemented in a much more structured way than what was suggested in the Git-SCM book.</p><p>The examples will be in Python but the theory is relevant for every scripting language.</p>]]></content:encoded></item><item><title>A Vagrant Base Box For Django Development</title><category>Virtualization</category><dc:creator>Omer Katz</dc:creator><pubDate>Fri, 08 Feb 2013 12:59:00 +0000</pubDate><link>https://www.omerkatz.com/blog/2013/2/8/a-vagrant-base-box-for-django-development</link><guid isPermaLink="false">5138dccfe4b073120964d739:5138e128e4b0653ec0f305ae:5138e129e4b0653ec0f305b3</guid><description><![CDATA[I stumbled into this project which is a project template that provides some 
integration with Vagrant. It also provides a base box that can be 
customized for your needs.]]></description><content:encoded><![CDATA[<p>I stumbled into this <a href="https://github.com/torchbox/vagrant-django-template" title="Vagrant Django Template">project</a>&nbsp;which is a project template that provides some integration with Vagrant. It also provides a <a href="https://github.com/torchbox/vagrant-django-base" title="Vagrant Django Base Box">base box</a>&nbsp;that can be customized for your needs.</p><p>It's a good start but in my opinion it's not enough.</p><p>I'm currently thinking about writing a new app that will integrate Django with vagrant in order to enable a better development workflow.</p><p>I'll update when I'll have something concrete.</p><p>P.S.</p><p>More posts coming up soon. I know I've been slacking off and I'm picking up the pace.</p>]]></content:encoded></item><item><title>Finally, a package manager for windows</title><category>SCM</category><dc:creator>Omer Katz</dc:creator><pubDate>Thu, 12 Jul 2012 17:04:49 +0000</pubDate><link>https://www.omerkatz.com/blog/2012/7/12/finally-a-package-manager-for-windows</link><guid isPermaLink="false">5138dccfe4b073120964d739:5138e128e4b0653ec0f305ae:5138e129e4b0653ec0f305b4</guid><description><![CDATA[I have finally found a good package manager for windows and installed 
node.js pretty easily with it. Add it to your tool chain.

It's called Chocolatey.]]></description><content:encoded><![CDATA[<p>I have finally found a good package manager for windows and installed node.js pretty easily with it. Add it to your tool chain.</p><p>If you are interested in an introduction Scott Hanselman has already written a great <a href="http://www.hanselman.com/blog/IsTheWindowsUserReadyForAptget.aspx">blog post</a> about it.​</p><p>It's called <a href="http://chocolatey.org" title="Chocolatey - A package management tool for windows">Chocolatey</a>.</p><p>If you are not familiar with package managers here is the definition from <a href="http://en.wikipedia.org/wiki/Package_management_system" title="Package Management System">Wikipedia</a>:</p><blockquote>
<p>In software, a package management system, also called package manager, is a collection of software tools to automate the process of installing, upgrading, configuring, and removing software packages for a computer's  operating system in a consistent manner. It typically maintains a  database of software dependencies and version information to prevent  software mismatches and missing prerequisites.</p>
<p>Packages are distributions of software, applications and data. Packages also contain metadata, such as the software's name, description of its purpose, version number, vendor, checksum, and a list of dependencies necessary for the software to run properly. Upon installation, metadata is stored in a local package database.</p>
<p>Package management systems are designed to save organizations time  and money through remote administration and software distribution  technology that eliminate the need for manual installs and updates. This  can be particularly useful for large enterprises whose operating  systems are based on Linux and other Unix-like  systems, typically consisting of hundreds or even thousands of distinct  software packages; in the former case, a package management system is a  convenience, in the latter case it becomes essential.</p>
</blockquote><p>Now all that's left is that puppetlabs will add a provider for it and than provisioning windows machines will be much easier.</p>]]></content:encoded></item><item><title>Vagrant &amp; Puppet Best Practices</title><category>Virtualization</category><dc:creator>Omer Katz</dc:creator><pubDate>Thu, 12 Jul 2012 16:57:57 +0000</pubDate><link>https://www.omerkatz.com/blog/2012/7/12/vagrant-and-puppet-best-practices</link><guid isPermaLink="false">5138dccfe4b073120964d739:5138e128e4b0653ec0f305ae:5138e129e4b0653ec0f305b7</guid><description><![CDATA[During my usage of Vagrant I've discovered some best practices that will 
help you develop puppet projects more efficiently.

Here are 4 best practices to act upon when using Vagrant.]]></description><content:encoded><![CDATA[<p>During my usage of Vagrant I've discovered some best practices that will help you develop puppet projects more efficiently.</p><h2>1) Use librarian-puppet to manage your puppet modules</h2><p>librarian-puppet is an excellent tool for managing your puppet module dependencies.</p><p>It is only supported on Linux at the current moment as far as I can tell so if you are running on windows there are two solutions:</p><ol><li>Attempt to use it with MSYS which is something I haven't tried yet. YMMV.</li><li>Install it on the target machine you are currently testing and ssh to it in order to use librarian-puppet. It's not optimal but it works.</li></ol><p>I have tested and used the second option mainly to save time and to allow me to develop my puppet projects more easily on windows.</p><p>You have to share the modules library in order to manage the puppet modules using librarian-puppet on the target machine and develop your project on windows which brings me to my next point.</p><h2>2) Share the modules directory</h2><p>In order to use the puppet modules globally share the /modules/ directory using:</p><p>config.vm.share_folder('modules', '/etc/puppet/modules', 'modules')</p><p>This way you can ensure that the dependencies are both on the development machine and on the target machine.</p><p>Make sure your module path in the provisioning configuration is set to <em>'modules'</em> like this:</p><p>puppet.module_path = "modules"</p><h2>3) Share the templates directory</h2><p>In order to use templates with vagrant you have to share the project's template directory using:</p><p>config.vm.share_folder('templates', '/tmp/vagrant-puppet/templates', 'templates')</p><p>Make sure your templates path in the provisioning configuration is set to <em>'/tmp/vagrant-puppet/templates'</em> like this:</p><p>puppet.options = ["--templatedir","/tmp/vagrant-puppet/templates"]</p><h2>4) When provisioning a puppet master share the required manifests</h2><p>In order for the puppet master to provision the rest of the nodes share the project's manifests that are not related to the puppet master itself using:</p><p> </p><p>master_config.vm.share_folder("puppet-master", "/etc/puppet/manifests", "puppet-master")</p><p> </p><p>I selected puppet-master as the folder name where all the manifests reside but you can select any folder name you'd like.</p><p>Happy provisioning everyone.</p>]]></content:encoded></item><item><title>Setting Up A Development Workstation (Part II) - Scripting The Installation</title><dc:creator>Omer Katz</dc:creator><pubDate>Thu, 07 Jun 2012 11:21:00 +0000</pubDate><link>https://www.omerkatz.com/blog/2012/6/7/setting-up-a-development-workstation-part-2</link><guid isPermaLink="false">5138dccfe4b073120964d739:5138e128e4b0653ec0f305ae:5138e129e4b0653ec0f305b8</guid><description><![CDATA[Last time we talked about selecting and installing the OS. I have referred 
you to resources about preseeding and Kickstart in order for you to have a 
better grasp about unattended installations. You've probably attempted (and 
even succeeded) to perform one already. In this post I am going to further 
elaborate on how to improve the installation and configuration process of a 
new development machine.]]></description><content:encoded><![CDATA[<p><span>First of all I'd like to apologize about the delay between the posts. I've been quite busy with a new project at work and the amount of needed research done about this subject is pretty high.</span></p><p><span>Last time we talked about&nbsp;<a href="https://www.omerkatz.com/static/5138dccfe4b073120964d739/5138e128e4b0653ec0f305ae/5138e129e4b0653ec0f305b9/1333961280000/" title="Setting Up A Development Workstation (Part I) - Selecting and Installing the OS">selecting and installing the OS</a>. I have referred you to resources about preseeding and Kickstart in order for you to have a better grasp about unattended installations. You've probably attempted (and even succeeded) to perform one already. In this post I am going to further elaborate on how to improve the installation and configuration process of a new development machine.</span></p><p><span><br></span></p><h1><span>What is provisioning?</span></h1><p><span><br></span></p><p><span>As described on&nbsp;<a href="http://en.wikipedia.org/wiki/Provisioning#Server_provisioning" title="Server Provisioning">Wikipedia</a>:</span></p><blockquote>
<p><span>Server provisioning is a set of actions to prepare a server with appropriate systems, data and software, and make it ready for network operation. Typical tasks when provisioning a server are: select a server from a pool of available servers, load the appropriate software (operating system, device drivers, middleware, and applications), appropriately customize and configure the system and the software to create or change a boot image for this server, and then change its parameters, such as IP address, IP Gateway to find associated network and storage resources (sometimes separated as resource provisioning) to audit the system.</span></p>
</blockquote><p><span>In our context provisioning is a set of actions to prepare a workstation with the appropriate software (such as IDEs, web browsers, Version Control Systems, language interpreters etc.), configuration and data and make it ready for development of software.</span></p><p><span>The required software, configuration and data vary between language ecosystems and target environment.</span></p><p><span><br></span></p><h2><span>Push based automation systems vs. pull based automation systems</span></h2><p><span><br></span></p><p><span>A push based automation system is a system that commands an endpoint (usually a workstation or a server in our context, but an endpoint can be any system that supports remote invocation of commands) to perform a specific set of tasks. Push based systems usually work using&nbsp;<a href="http://he.wikipedia.org/wiki/Secure_Shell" title="Secure Shell">ssh</a>&nbsp;or another protocol such as&nbsp;<a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ee706585(v=vs.85).aspx" title="WS-Remoting in PowerShell">WS-Remoting</a>. A pull based automation system is a system that relies on the fact that a client running on the endpoint will request a server for instructions on what needs to be done in order to keep the endpoint up to date. </span></p><p><span>You can read more about the topic&nbsp;<a href="http://agiletesting.blogspot.co.il/2010/03/automated-deployment-systems-push-vs.html" title="Push vs. Pull">here</a>. </span></p><p>&nbsp;</p><h2>What is configuration management?</h2><p>&nbsp;</p><p><span>As described on&nbsp;<a href="http://en.wikipedia.org/wiki/Configuration_management" title="Configuration Management">Wikipedia</a>:</span></p><blockquote>
<p><span>CM is the practice of handling changes systematically so that a&nbsp;system&nbsp;maintains its integrity over time. CM implements the policies, procedures, techniques, and tools that are required to manage, evaluate proposed changes, track the status of changes, and to maintain an inventory of system and support documents as the system changes. CM programs and plans provide technical and administrative direction to the development and implementation the procedures, functions, services, tools, processes, and resources required for to successfully develop and support a complex system.</span></p>
<p><span><br></span></p>
</blockquote><h2><span>Provisioning tools</span></h2><p><span><br></span></p><h3><span>Puppet - A configuration management tool</span></h3><p><span><a href="http://puppetlabs.com/puppet/what-is-puppet/" title="What is Puppet?">Puppet</a>&nbsp;is a pull based configuration management automation tool that uses a declarative language in order to define what software, data &amp; configuration is needed in order to keep the system in a well defined and healthy state. I strongly recommend to read&nbsp;<a href="http://www.amazon.com/Pro-Puppet-James-Turnbull/dp/1430230576" title="Amazon: Pro Puppet">Pro Puppet</a>&nbsp;in order to learn more about how configuration management is done using Puppet. For an example of a Puppet module which sets up a certain development box see&nbsp;<a href="https://github.com/khoomeister/puppet-devbox" title="Puppet-DevBox">here</a>.</span></p><h3><span>Blueprint - A configuration management reverse engineering tool</span></h3><p><span>In most cases you already have set up at least one development workstation. Writing a puppet module that replicates the same configuration is a tiresome and erroneous work. This is where&nbsp;<a href="https://github.com/devstructure/blueprint" title="Blueprint">Blueprint</a>&nbsp;comes in. It scans a machine and outputs the equivalent puppet module that is required to produce the same results on another machine.</span></p><h3><span>Fabric - a tool for executing shell commands locally or remotely through SSH</span></h3><p><span><a href="http://docs.fabfile.org/en/1.4.2/index.html" title="Fabric">Fabric</a>&nbsp;is a push based automation tool that can be used to execute shell commands both locally and on a remote endpoint.</span></p><p><span>It is used for maintenance tasks that need to occur right away such as restarting a web server, initializing or cloning a repository from source control and more.</span></p><h3><span>Vagrant - A VirtualBox configuration management and provisioning tool</span></h3><p><span><a href="http://vagrantup.com/" title="Vagrant">Vagrant</a>&nbsp;is a tool for developing &amp; packaging&nbsp;<a href="https://www.virtualbox.org/" title="VirtualBox">VirtualBox</a>&nbsp;virtual machines. It uses puppet as a provisioning tool.</span></p><p><span>Vagrant can be used to develop and test the development workstation configuration before provisioning the actual development workstation.</span></p><h3><span>VeeWee&nbsp;-&nbsp;A tool for building Vagrant base boxes</span></h3><p><span><a href="https://github.com/jedi4ever/veewee" title="VeeWee">VeeWee</a>&nbsp;is a tool for building<span>&nbsp;</span><a href="http://vagrantup.com/v1/docs/base_boxes.html" title="Vagrant - Base Boxes">Vagrant Base Boxes</a>.</span></p><p><span>VeeWee also allows developing, testing &amp; packaging VMWare Fusion and KVM&nbsp;virtual machines.</span></p><p><span>VeeWee does not support windows at this time although<span>&nbsp;</span><a href="https://github.com/jedi4ever/veewee/issues/6" title="VeeWee Issue 6#: Make it work on Windows">some</a>&nbsp;<a href="https://github.com/jedi4ever/veewee/pull/273" title="VeeWee Issue #237: Feature/Windows">work</a><span>&nbsp;</span>has been done to add support to it.</span><span>&nbsp;</span></p><h3>Foreman - A tool for machine lifecycle management</h3><p><a href="http://theforeman.org/" title="Foreman">Foreman</a>&nbsp;is a tool that is capable of performing many operations including unattended installations using Kickstart and Preseeding, acting as a web front of Puppet, DNS &amp; DHCP management, virtual machines management and much more.</p><p>If you have a physical machine as the deployment target Foreman is optimal for deploying it and provisioning it.</p><p><em><span>Side note: Puppetlabs are developing&nbsp;<a href="https://github.com/puppetlabs/Razor" title="Razor">Razor</a>&nbsp;which aims to supreceed Foreman but it is currently not as stable and extensive feature-wise as Foreman.</span></em></p><p><em><span><br></span></em></p><h2>Scripting the installation</h2><p>&nbsp;</p><p>If you already have an existing workstation use Blueprint to reverse engineer the current configuration. Adjust as necessary.</p><p>If you need a base box check<span>&nbsp;</span><a href="http://www.vagrantbox.es/" title="A list of Vagrant boxes">here</a>&nbsp;if someone hasn't already built one for you, if it does not exist create it with VeeWee.</p><p>If you are following my lead there are base boxes for Ubuntu 12.04 in<span>&nbsp;</span><a href="http://files.vagrantup.com/precise32.box" title="Ubuntu 12.04 32bit">32bit version</a>&nbsp;and<span>&nbsp;</span><a href="http://files.vagrantup.com/precise64.box" title="Ubuntu 12.04 64bit">64bit version</a>.</p><p>Write the configuration for the development workstation using puppet and test it with Vagrant. Refine and adjust as necessary.&nbsp;Make sure that the ubuntu-desktop package is required by your puppet module as vagrant base boxes come without one in order to allow faster downloading of base boxes. In order to edit puppet files more easily try to use<span>&nbsp;</span><a href="http://cloudsmith.github.com/geppetto/" title="Geppetto - A Puppet IDE">Geppetto</a>, an Eclipse based IDE for Puppet projects.</p><p>Optionally, use fabric to clone any active project the developer will be working on.</p><p>After all that provision to a physical machine using Foreman.</p><p>And that's it.</p><p>I haven't shown any code since all environments have different requirements and this post would never end if I had to cover them all. Make sure you check puppet-devbox to get a better grasp of how it's done.</p>]]></content:encoded></item><item><title>Setting Up A Development Workstation (Part I) - Selecting and Installing the OS</title><dc:creator>Omer Katz</dc:creator><pubDate>Mon, 09 Apr 2012 08:48:00 +0000</pubDate><link>https://www.omerkatz.com/blog/2012/4/9/setting-up-a-development-machine-part-1</link><guid isPermaLink="false">5138dccfe4b073120964d739:5138e128e4b0653ec0f305ae:5138e129e4b0653ec0f305b9</guid><description><![CDATA[Whenever a new developer arrives to the team he and/or the IT department 
usually spends some time on setting up their development workstation. This 
time is wasted as the man-hours spent on setting up a new workstation could 
have been spent on creating a better product (aka adding value).]]></description><content:encoded><![CDATA[<h2>The Situation</h2><p>Whenever a new developer arrives to the team he and/or the IT department usually spends some time on setting up their development workstation. This time is wasted as the man-hours spent on setting up a new workstation could have been spent on creating a better product (aka adding value).</p><h2>The Task</h2><p>Automating the installation and configuration of a new development workstation while still maintaining flexibility and room for personal customization and preferences using scripting.</p><h2>Selecting an Operating System</h2><p>For Python development I strongly suggest a Linux based OS. My personal choice is <a href="http://www.ubuntu.com/" title="Ubuntu">Ubuntu</a>.</p><h3><span>Why Linux?</span></h3><ul>
<li>
Most Linux distributions are shipped with Python already installed.
</li>
<li>
Most if not all Linux distributions are shipped with a C compiler which allows us to compile Python C extensions with no effort.
</li>
<li>
Some Linux distributions are shipped with&nbsp;package management utilities (such as apt-get and yum) which allows us to script the installation of the development environment required components.
</li>
<li>Native SSH.</li>
<li>Some Python essentials are written exclusively for linux (e.g.&nbsp;<a href="http://supervisord.org/introduction.html#platform-requirements" title="supervisord will not work under any version of windows">supervisord</a>,&nbsp;<a href="https://github.com/utahta/pythonbrew/issues/6" title="pythonbrew is not planning to support windows">pythonbrew</a>&nbsp;and<a href="http://www.doughellmann.com/docs/virtualenvwrapper/install.html#msys" title="virtualenvwrapper requires MSYS">virtualenvwrapper</a>) and some may need&nbsp;to be configured differently in order&nbsp;to work (e.g.<a href="http://www.virtualenv.org/en/latest/index.html#windows-notes">virtualenv</a>).</li>
<li>
Deploying disk images is by far more trivial.
</li>
<li>
Linux is completely free.
</li>
</ul><h4><span>Why Ubuntu?</span></h4><p>First of all, this choice is based on personal preference. If you find an OS that suits for your organization go ahead and use it. With that being said, there are some rational choices for why one should Ubuntu as their development workstation OS.</p><p>The latest version of Ubuntu is shipped with&nbsp;a fully configured&nbsp;Python 2.7.2 which is the latest and the last 2.x Python version on which most of the modern Python code is currently targeted on.</p><p>You may think it is not much but what I learned from&nbsp;my experiment with&nbsp;CentOS is that it is depended on Python 2.4.</p><p>Python 2.4 is a very old version of python and most modern Python&nbsp;programs and libraries won't be targeting it at all.</p><p>The consequences are that switching the active Python version using pythonbrew system-wide may&nbsp;temporarily or permanently&nbsp;hurt the system's functionality. I haven't tried it though. I will check it out and let you guys know.</p><p>Ubuntu is also very easy to learn Linux with for those who aren't&nbsp;haven't used a&nbsp;Linux based OS yet.</p><p>Ubuntu has <a href="http://www.ubuntu.com/business/services/overview" title="Ubuntu services from cannonical">enterprise support</a>&nbsp;which is important for companies who need to resolve issues quickly and can't afford to waste time that otherwise would be spent on adding value.</p><h3><span>Why Not Windows?</span></h3><ul>
<li>
Multiple Python installations are harder to manage using a Windows operating system since pythonbrew is not available. I have yet to see an alternative solution.
</li>
<li>
Compiling C extensions is far from trivial since Windows does not provide a C compiler by default and the C extensions must be compiled with the same compiler that Python was compiled on. Currently the Python installer distribution is compiled with MSVC 2008. Alternatively you can use MinGW but that is <a href="http://eli.thegreenplace.net/2008/06/28/compiling-python-extensions-with-distutils-and-mingw/">far from trivial</a>.&nbsp;The implications are that if you are <strong>only </strong>working with a newer version of MSVC you may need to compile the Python sources yourself which is again far from trivial.
</li>
<li>
I've had issues with x64 Python&nbsp;installations where C extensions compilation is not even possible since the compiler only ships with x86 version (See above for the same compiler note).
</li>
<li>
<a href="http://docs.fabfile.org/en/1.4.1/index.html" title="Fabric">Fabric</a>'s dependencies uses C extensions. As a result to the above, installing fabric is not trivial and sometimes not possible. Fabric is very important when automating the development process since (and I'm quoting)&nbsp;<em>"it provides basic suite of operations for executing local or remote shell</em><br><em>commands (normally or via 'sudo') and uploading/downloading files, as well as</em><br><em>auxiliary functionality such as prompting the running user for input, or</em><br><em>aborting execution."</em>.
</li>
<li>
<a href="http://www.doughellmann.com/projects/virtualenvwrapper/" title="virtualenvwrapper">virtualenvwrapper</a>&nbsp;is based on shell scripts and although there is a <a href="https://bitbucket.org/guillermooo/virtualenvwrapper-powershell/src" title="virtualenvwrapper-powershell">port</a>&nbsp;to PowerShell it is not compatible and I've had little experience with it so I can't say I recommend it. Another option is to use virtualenvwrapper with MSYS but I haven't tested how well it works with MSYS.
</li>
<li>
As mentioned before, other Python essentials are written exclusively for Linux.
</li>
<li>
Costs money.
</li>
</ul><h2>Installing The Operating System</h2><p>If your IT department has chosen to work with virtualization and you are working with VirtualBox you can get <a href="http://virtualboxes.org/images/" title="VirtualBox OSes images">images</a> for most Linux based OSes.</p><p>If your IT department are using VMWere, there are <a href="http://www.thoughtpolice.co.uk/vmware/" title="VMWare Linux Images">images</a> you can use for some Linux based OSes as well.</p><p>Your mileage may vary.</p><p>If you listened to my advice and you chose Ubuntu, there is an <a href="https://help.ubuntu.com/11.04/installation-guide/i386/automatic-install.html" title="Ubuntu automatic install">automatic installer</a>&nbsp;that can install itself on multiple computers. Ubuntu has only preliminary support and the automatic installer has some limitations and features that are not supported yet.</p><p>Again, your mileage may vary.</p><p>From now and on I assume you are have chosen to work with Ubuntu 11.10.</p><h4><span>Images vs. Automatic Installers</span></h4><p>Images are a <a href="http://en.wikipedia.org/wiki/Standard_operating_environment" title="Standard Operating System">"one size fits all"</a> solution. If all 99% of your development workstations will be exactly the same, use an image because you can just deploy it and boot the system.</p><p>Further customization can be applied using boot scripts that will remove themselves after the first run but again, they script will be the same..</p><p>As mentioned, with Linux deploying images is by far more trivial. While incompatible hardware will often result in a crash on Windows won't crash Linux at all. All you need is that the operating system in the disc image will be the same as the deployment target's architecture and the disk image must contain all possible .</p><p>Automatic Installers are by far much more configurable and customizable but setting them up the first time can be quite consuming. If some of your development workstations will be different use an automatic installer.</p><p>Even if you are not planning to use an automatic installer currently due to the lack of time or resources, do take the time to learn what the <a href="https://help.ubuntu.com/11.04/installation-guide/i386/automatic-install.html" title="Automatic installation methods">different methods are</a> and how to <a href="https://help.ubuntu.com/11.04/installation-guide/i386/appendix-preseed.html" title="Preseeding documentation">perform</a> <a href="http://docs.redhat.com/docs/en-US/Red_Hat_Enterprise_Linux/6/html/Installation_Guide/ch-kickstart2.html" title="Kickstart documentation">them</a>.</p><p></p><p>Next time we will cover the scripting of the operating system installation.</p>]]></content:encoded></item></channel></rss>