Archive for the ‘Software’ Category

Open Source Software and Production Engineering

Saturday, September 27th, 2008

In the past I have struggled with the fact that some of the OSS code that I write wraps other’s work, creating an evil dependency which is not easily rectified.  I am then bound by the wrapee’s software release schedule, as are those who choose to use my software.  Yes, I’m talking about ToscaWidgets.I wanted to break free from this paradigm, and I have taken initial steps in my ToscaWidget wrapper for Yahoo YUI.  Here comes a huge block of code, but don’t let it scare you, I will explain the problem it intends to solve:


class YUILinkMixin(Link):
    params = {'basename': '(string) basename for the given file.  if you want yuitest-min.js, the base is yuitest/yuitest',
              'suffix': '(string) "", min, beta-min, or beta.  Default is "min"',
              'version': '(string) select the yui version you would like to use. Default version is: '+__YUI_VERSION__,
              'external': '(boolean) default:False True if you would like to grab the file from YAHOO! instead of locally',
              'yui_url_base':'The base url for fetching the YUI library externally',
    }

    version = __YUI_VERSION__
    external = __DEFAULT_LINK_IS_EXTERNAL__
    yui_url_base = __YUI_URL_BASE__
    modname = "tw.yui"
    extension = 'js'
    default_suffix = __DEFAULT_SUFFIX__
    _suffix = ''

    def __init__(self, *args, **kw):
        super(Link, self).__init__(*args, **kw)
        if not self.is_external:
            modname = self.modname or self.__module__
            self.webdir, self.dirname, self.link = registry.register(
                modname, self.filename
                )
        if 'suffix' in kw:
            self.suffix = kw['suffix']
        else:
            self.suffix = self.default_suffix

    def _get_suffix(self):
        if self._suffix == '':
            return ''
        return '-'+self._suffix

    def _set_suffix(self, value):
        self._suffix = value

    suffix = property(_get_suffix, _set_suffix)

    @property
    def external_link(self):
        link = '/'.join((self.yui_url_base, self.version, 'build', self.basename+self.suffix+'.'+self.extension))
        #xxx:check for existance of this resource and choose -min -min-beta -debug or no suffix as alternatives.
        return link

    def _get_link(self):
        if self.is_external:
            return self.external_link
        return tw.framework.url(self._link or '')

    def _set_link(self, link):
        self._link = link

    link = property(_get_link, _set_link)

    def abspath(self, filename):
        return os.sep.join((os.path.dirname(__file__), filename))

    def try_filename(self, filename):
        abspath = self.abspath(filename)
        if os.path.exists(abspath):
            return filename
        return False

    @property
    def filename(self):
        #make basename windows/qnix compat
        basename = self.basename.replace('/', os.sep)
        basename = self.basename.replace('\\', os.sep)

        basename = os.sep.join(('static', self.version, 'build', basename))
        #try the default
        filename =  basename+self.suffix+'.'+self.extension
        if self.try_filename(filename):
            return filename

        #try '' if the default suffix is min
        if self.default_suffix == '':
            filename =  basename+self.suffix+'.'+self.extension
            if self.try_filename(filename):
                return filename

        #try min if the default suffix is ''
        if self.default_suffix == 'min':
            filename =  basename+'.'+self.extension
            if self.try_filename(filename):
                return filename

        #try debug
        filename =  basename+'-debug'+'.'+self.extension
        if self.try_filename(filename):
            return filename

        #try beta-min
        filename =  basename+'-beta-min'+'.'+self.extension
        if self.try_filename(filename):
            return filename

        #try beta
        filename =  basename+'-beta'+'.'+self.extension
        if self.try_filename(filename):
            return filename

        #try beta-debug
        filename =  basename+'-beta-debug'+'.'+self.extension
        if self.try_filename(filename):
            return filename
        return None

    @property
    def is_external(self):
        return self.external

class YUIJSLink(JSLink, YUILinkMixin):
    pass

class YUICSSLink(YUILinkMixin, CSSLink):
    extension = 'css'
 
So, the question is, how does using this code differ from using direct links to the YUI library, or using the ubiquitous JSLink Widget provided by ToscaWidgets, which is found in just about every other tw.js_wrapper available?
1) Testabliltiy - First and foremost, I wanted a way to test a new version of the library with my JS code to see if it would work, without having to change the wrapper at all.  A bit of a monkey-patch, but if you change the version of YUI that is fetched by altering one variable in the tw.yui library before doing subsequent imports.  If the current version is not available in the widget library, you can point it directly at yui's online library.  Run your tests, see what breaks, fix it, and you are now compatible with the new library.
2) Debugability - Synchronous with Testability, you can also set a flag for tw.yui to include all of the debug versions of the yui modules so you can dig down into the code using firebug if need be. (The default is minified)
3) Compatibility - Since you now can control what version of YUI you want to use, you can retro-fit an older project with Toscawidgets by downgrading the version of YUI that tw.yui is using.  You can also try out the newest version of YUI that may tw.yui is not yet using, and with the exception of new modules that have not been integrated into tw.yui, it should still work.
4) Maintainability - Since we now have the ability to swap versions, the maintainers of tw.yui can keep multiple versions of yui in the library, and deprecate them as they see fit.  This provides maintainability, as you would expect to see deprecation warnings about your WSGI Application's use of an out-of-date JS library.  This helps the whole process of knowing what libraries are current to what version, which can be a real bear, given all of the things we all must keep track of.
5) Producibility - The bottom line always comes down to whether or not you can pipe your development software up to production level efficiently.  (Is the code producible).  With the ability to test compatibility, and drop down to different versions of dependent libraries when compatibility is a concern, you will be able to keep all that works on your production server working, while bringing up new or updated functionality incrementally.  Keep in mind that the above code demonstrates the ability for system-level defaults of the javascript link widgets to be overridden for any particular widget instantiation.
These 5 items I call Production Engineering.  Basically, Production Engineering is developing a process which allows you to integrate working development code into your stead-fast production site, and allow you to back out software which may have mistakes.  A good software engineer realizes that people make mistakes, and there needs to be a way to buy some time so those mistakes can be fixed.  I believe that YUILinkMixin is a step in this direction, and I hope to extend it in the future to provide an even more robust toolset in line with Production Engineering.The complete source code for tw.yui is available at www.toscawidgets.org/hg .

Busy times with OSS

Friday, July 25th, 2008

I’ve not posted to this blog in over a month, mainly because I have been busy. Busy is a good thing I think. I have been helping clearwired get their newest web application off the ground, working on a number of screencasts, helping Mark with the latest batches of TG2 releases, learning about new and interesting OSS Python projects.

sphinx logo One of the more interesting things I have started to use with some frequency is Sphinx. Sphinx is a documentation system whichallows you to create webpages (among other things) with .rst files. It also grabs directly from your modules and inserts your docstrings (including your doctests.) It is great to have code which is not only documented, but also tested using nose. Look for a screencast from me in the near future on this one.

Two of the recent screencasts I have written show how to use virtualenv, PasteScript, and Nose. I go through a ground-up example showing how to create a virtualenv, a project package, and finally how to test that package and provide robustness with code coverage. The final screencast is about how to install TG2, which has become much easier in the advent of TG2’s first alpha release.

mountain gears TG2 is actually nearing it’s second alpha release. I think This is the best release yet. I spent some time moving DBSprockets to pep-8 compliance, and the two things TG2 depends on (tg.ext.silverplate and tgcrud) are now both using the newest release of DBSprockets. I also released basketweaver which allows you to create a simple local pypi made of static HTML files. Special thanks to Chris McDonough, who wrote the makeindex.py script. All I did was to fixed it up a little, and package using PasteScript, and provide a console_script for easy usage.

rum screenshot

Along with Sphinx, I have been trying to wrap my head around Rum, which is a new project to generate forms from database schema, much like DBSprockets. Although the internals of the system are somewhat mystifying, the API is squeaky clean, and in my mind what DBSprockets was eventually planned to be. The great news is that Alberto has done such a good job laying the groundwork for Rum I should be able to jump right in and apply lessons learned from DBSprockets. At this point it is safe to say that I will continue to maintain DBSprockets for bug fixes, but that the internals of it are going to be converted over to using Rum, before being deprecated altogether. DBSprockets had a great run, but it is time to move on and move forward with a superior design which promises to integrate so many WSGI technologies.

Speaking at Front Range Pythoneers

Tuesday, June 17th, 2008

Tomorrow Night I will be speaking about agile technologies with SQLAlchemy at the Front Range Pythoneers monthly meeting. I spent a few hours last night working out my presentation and creating a number of screencasts which show how to use tools like virtualenv, paster, and nosetests.  I also touch apon sqlalchemy, and how one would set up a test environment for their database schema.  Even if you don’t live in the Boulder/Denver area the information could be valuable to you, so I decided to set up a googlecode repository to store all of my tutorial-related materials.  It is called PythonTutorials.

My Blog’s Wordle

Tuesday, June 17th, 2008

wordle

http://wordle.net/

What Open Source means in a migratory world.

Friday, April 4th, 2008

Are you a software engineer? Programmer? QA specialist? How long have you been at your current position? How long do you expect to be? I bet it’s less than 5 years.

Why would that be an important issue for open source? Most of the time you spend most of your time working OSS projects at home, right? But I bet someday you’d like to get paid for that work, unless like some OSS developers you base your happiness on the proliferation of your software.

So one day you are going to pack up and leave your company, and all of it’s proprietary software behind. And if you are developing Python, that probably means you are leaving a gaping, expensive hole for your former employer. But what if you could keep working for that employer, after you left? What if what you were doing at the new job was so transferable that you could be productive from day 1?

This is the promise that is OSS. And while this promise is probably idealist, it haImage taken bu Alan D. Wilson, and modified by Diliff s at least one tentacle sticking out from reality. The fact is, workers are migratory these days. Personally I think this is because short-sighted investors value fiscal gains over a longer payoff, but we do live in the day of day-trading. The fact is, many people don’t see programmers for what they really are, a mixture of engineer, mathematician and artist. I can always seem to find someone who will pay me more money to do the same job I already have. When something I just can’t turn down for my family’s sake comes up, I have to take it. For this reason programmers, and even the greater workforce migrates.

Employers have already realized that employees are migratory. They have all but done-away with pension plans in exchange for portability: the 401k. Who cares what kind of health insurance we offer? 80/20 is now the norm, because employers don’t expect to have to pay in the long run, and employees accept it too, because they don’t expect to be working at the company for the long haul, when health insurance becomes more of a factor.

But lets get back to the original question. What does a migratory worker mean to open source. Portability of work. I can take my Django/Turbogears/Zope knowledge to any other company using these technologies and pick up right where I left off. If I am one of the few developing software in the OSS world (as apposed to just using it) I can actually contribute more to my OSS project on my companies dime. The question is, are the companies really losing out by providing their software to the world?

Definitely not. In fact, companies stand to gain much more by choosing (and contributing to) something “free” and open. They retain some value from their employee after said person has left the company.  Bug patches, new features, etc. all pulled from the same pot they were putting their goodies in before. Since the software is open and free, more people have access to it in the age where replication of information is almost cost-less. That means they have a larger work force to choose from, and more experts and shared expertise to gain from.

So then the question becomes, “As a company, why should I contribute to open source?”  The fact is you are going to get back more than you give.  Your employees will gain greater expertise by helping to build the tools that they use.  Additionally, the company is helping to keep the project’s momentum going, which ensures the OSS project’s longevity.  It is no secret that “feature complete” projects often fall by the wayside, regardless of quality.  By playing an active role in a project’s development, you are ensuring that that project will be available, and have a good support system even if your employees have moved on.

If you are a company who is battling with the decision to contribute to, or even use open source, I implore you to look seriously at your options, your [migratory] workforce, and your ability to develop a product for the long haul. I bet you find more value in free software than the sticker price. Software, more than ever, is about the people, not the product.