<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>SimpleExampleEgg</title>
<meta name="Generator" content="Vim reStructured Text b20 - Vim7.0" />
<meta name="Author" content="Todd Greenwood" />
<meta name="Title" content="SimpleExampleEgg" />
<meta name="Keywords" content="python, egg, setuptools, distutils, tutorial, doctests, unit tests, deploy, install, example" />
<meta name="Date" content="Dec 2005" />

<link rel="stylesheet" href="default.css" type="text/css" />
<link rel="stylesheet" href="oldstyle.css" type="text/css" />

</head>
<body>


<h1 id="lsimpleexampleegg">SimpleExampleEgg</h1>
<table class="field" summary="Field list"><tr><td class="fkey">Author:</td><td class="fval"> Todd Greenwood</td></tr>

<tr><td class="fkey">Title:</td><td class="fval"> SimpleExampleEgg</td></tr>

<tr><td class="fkey">Keywords:</td><td class="fval"> python, egg, setuptools, distutils, tutorial, doctests, unit tests, deploy, install, example</td></tr>

<tr><td class="fkey">Version:</td><td class="fval"> 0.1</td></tr>

<tr><td class="fkey">License:</td><td class="fval"> GPL v. 2</td></tr>

<tr><td class="fkey">Date:</td><td class="fval"> Dec 2005</td></tr>
</table>

<p>
This aims to be a super simple example of python, setuptools, docutils, unit-tests, and eggs.
</p>

<span id="tocheader" class="toc">Contents</span>
<ul class="toc">
 <li class="h1"><a href="#lsimpleexampleegg">SimpleExampleEgg</a></li>
  <li class="h2"><a href="#lintroduction">Introduction</a></li>
  <li class="h2"><a href="#lbasic-source-files">Basic Source Files</a></li>
  <li class="h2"><a href="#ltests-and-building">Tests and Building</a></li>
   <li class="h3"><a href="#lbuilding-the-rest-docs">Building the REST docs</a></li>
  <li class="h2"><a href="#lbacktracking">Backtracking</a></li>
   <li class="h3"><a href="#lthe-ez-setup46py-file">The ez_setup.py file</a></li>
   <li class="h3"><a href="#lcreate-a-pipy-account58">Create a PiPy account:</a></li>
  <li class="h2"><a href="#lapp-deployment">App Deployment</a></li>
   <li class="h3"><a href="#lscript-generation">Script Generation</a></li>
   <li class="h3"><a href="#lbuilding">Building</a></li>
   <li class="h3"><a href="#ldeploy-locally-40dev-mode41">Deploy Locally (Dev Mode)</a></li>
   <li class="h3"><a href="#ldeploy-to-pipy">Deploy To pipy</a></li>
  <li class="h2"><a href="#lend-user-app-install">End User App Install</a></li>
   <li class="h3"><a href="#luser-install">User Install</a></li>
   <li class="h3"><a href="#luser-run-unit-tests">User Run Unit Tests</a></li>
  <li class="h2"><a href="#lconclusion">Conclusion</a></li>
</ul>
<!--.. comment:: end of toc -->
<h2 id="lintroduction">Introduction</h2>

<p>
Hopefully, this will clarify, in my own mind, at least, how to make super simple apps that have all sorts of cool extras such as working unit tests, launch scripts, deploy and install flawlessly...etc. Ideally, I'll be able to write apps that 'just work'. So my end users can just point some tool (easy_install) at a file (an egg) and voila, a working app.
</p>

<p>
Here's what I'd like to have happen for this exercise:
</p>

 <ul class="circle">
 <li><p class="onlyli"> user clicks a link</p></li>
 <li><p class="firstli"> app downloads and installs</p></li>
 <li><p class="onlyli"> user runs the app's internal test suite</p>
</li>
</ul>

<p>
Along the way, I'll play around with:
</p>

 <ul class="circle">
 <li><p class="firstli"> deploying the app locally, and to pipy</p></li>
 <li><p class="firstli"> user may recieve the app via email, a web link, file copy, etc.</p></li>
 <li><p class="onlyli"> doctests and unit tests</p>
</li>
</ul>

<p>
Note, this documentation was written using Mikolaj Machowski's 
Vim reStructured Text plugin (<a href="http://skawina.eu.org/mikolaj/vst.html" title="vst">vst</a>). It is the coolest thing since the
'intraweb'. Look at the source 'readme.rest' and the generated 'readme.html'.
The code listings and sample code output were generated as part of the build,
very little 'copy and paste' here.
</p>

<h2 id="lbasic-source-files">Basic Source Files</h2>
<ol class="decimal">
<li><p class="firstli">dir listing:</p>
    <blockquote>

    <p>

<pre>
apple.py
docs
__init__.py
orange.py
simpletests.py
</pre>
    </p>

    </blockquote>
</li>
<li><p class="firstli">apple.py:</p>
    <blockquote>

    <p>

<pre>
import sys

def doConsole(): print make_pie('CONSOLE')

def make_pie(who):
        """
>>> import apple as a
>>> a.make_pie('Todd')
'Todd likes pie!!!'
        """
        return '%s likes pie!!!'%who
#
def _test():
        import doctest
        return doctest.testmod()
#
if __name__ == "__main__":
    _test()
    if len(sys.argv)>1: print make_pie(sys.argv[1])
    </p>
</pre>

    </blockquote>
</li>
<li><p class="firstli">Let's run this tiny app to see what we get:</p>
    <blockquote>

    <p>
    <code>$ python apple.py Mr.Guido</code>
    </p>

    <p>

<pre>
Mr.Guido likes pie!!!
</pre>
    </p>

    </blockquote>
</li>
<li><p class="firstli">setup.py:</p>
    <blockquote>

    <p>

<pre>
from ez_setup import use_setuptools
use_setuptools()
from setuptools import setup, find_packages
#
setup(name = "SimpleExampleEgg",
    version = "0.1",
    description = "test",
    author = "Todd Greenwood",
    author_email = "t.greenwoodgeer@gmail.com",
        entry_points = {'console_scripts': [
                'make_apple_pie = fruit.apple:doConsole'
                ]},
    packages = find_packages(exclude=['ez_setup'] ),
        package_data = {'':['docs/*.html', 'docs/*.rest','docs/*.vim']},
    test_suite = 'fruit.simpletests.getTestSuite',
    license = "GNU Lesser General Public License",
    classifiers = [
        "Development Status :: 3 - Alpha",
        "Intended Audience :: Developers",
        "License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)",
        "Programming Language :: Python",
        "Topic :: Utilities",
    ],
    zip_safe=True,
    )
    </p>
</pre>

    </blockquote>
</li>
<li><p class="firstli">simpletests.py:</p>
    <blockquote>

    <p>

<pre>
import apple
import unittest
import doctest
#
def getTestSuite():
        suite = unittest.TestSuite()
        for mod in apple,:
            suite.addTest(doctest.DocTestSuite(mod))
        return suite
#
runner = unittest.TextTestRunner()
runner.run(getTestSuite())
    </p>
</pre>

    </blockquote>
</li></ol>
<h2 id="ltests-and-building">Tests and Building</h2>
<ol class="decimal">
<li><p class="firstli">Let's run the test suite:</p>
    <blockquote>

    <p>
    <code>$ python simpletests.py</code>
    </p>

    <p>

<pre>
.
----------------------------------------------------------------------
Ran 1 test in 0.007s

OK
</pre>
    </p>

    </blockquote>
</li>
<li><p class="firstli">Now, let's run the test suite from setuptools:</p>
    <blockquote>

    <p>
    <code>$ python setup.py test</code>
    </p>

    <p>

<pre>
running test
running egg_info
writing ./SimpleExampleEgg.egg-info/PKG-INFO
writing top-level names to ./SimpleExampleEgg.egg-info/top_level.txt
writing entry points to ./SimpleExampleEgg.egg-info/entry_points.txt
running build_ext
.
----------------------------------------------------------------------
Ran 1 test in 0.008s

OK
Doctest: fruit.apple.make_pie ... ok

----------------------------------------------------------------------
Ran 1 test in 0.001s

OK
</pre>
    </p>

    </blockquote>
</li>
<li><p class="firstli">Next, let's make sure the build system works. But first, I should mention
    that this documentation is generated via a vim pluggin.</p>
</li></ol>
<h3 id="lbuilding-the-rest-docs">Building the REST docs</h3>
<ol class="decimal">
<li><p class="firstli">So, while from a command line you would execute:</p>
    <blockquote>

    <p>
    <code>$ python setup bdist_egg</code>
    </p>

    <p>
    Because this doc lives in ./fruit/docs/readme.rest, I will use the pbu
    utility to walk the directory tree and launch setup.py. If you would like
    to build the docs, here is the process:
    </p>

    <ol class="loweralpha">
    <li><p class="firstli">install pbu:</p>
<pre>
 $ easy_install buildutils
</pre>

    </li>    
    <li><p class="firstli">build the egg using the 'pbu' utility:</p>
<pre>
 $ cd ./fruit/docs
 $ pbu dbist_egg
</pre>

</li></ol>
    </blockquote>
</li>
<li><p class="firstli">So that's exactly what the docs do. So, to see all this in action, build
 the docs :</p>
<pre>
 $ vim readme.rest -s runvim.vim

 BTW - runvim.vim is just a quickie script to execute :Vsti within vim,
 write, save, and exit vim.
</pre>

</li>
<li><p class="firstli">Back to the build system, let's do a build :</p>
    <blockquote>

    <p>

<pre>
running bdist_egg
running egg_info
writing ./SimpleExampleEgg.egg-info/PKG-INFO
writing top-level names to ./SimpleExampleEgg.egg-info/top_level.txt
writing entry points to ./SimpleExampleEgg.egg-info/entry_points.txt
installing library code to build/bdist.linux-i686/egg
running install_lib
warning: install_lib: 'build/lib' does not exist -- no Python modules to install
creating build/bdist.linux-i686/egg
creating build/bdist.linux-i686/egg/EGG-INFO
copying ./SimpleExampleEgg.egg-info/PKG-INFO -> build/bdist.linux-i686/egg/EGG-INFO
copying ./SimpleExampleEgg.egg-info/top_level.txt -> build/bdist.linux-i686/egg/EGG-INFO
copying ./SimpleExampleEgg.egg-info/entry_points.txt -> build/bdist.linux-i686/egg/EGG-INFO
creating 'dist/SimpleExampleEgg-0.1-py2.4.egg' and adding 'build/bdist.linux-i686/egg' to it
removing 'build/bdist.linux-i686/egg' (and everything under it)
</pre>
    </p>

    </blockquote>
</li>
<li><p class="firstli">And lastly, let's check to make sure that we have what we expect in the
    output:</p>
    <blockquote>

    <p>
    ``unzip -l /home/tgreenwo/active/SimpleExampleEgg/dist/SimpleExampleEgg-0.1-py2.4.egg'``
    </p>

    <p>

<pre>
Archive:  /home/tgreenwo/active/SimpleExampleEgg/dist/SimpleExampleEgg-0.1-py2.4.egg
  Length     Date   Time    Name
 --------    ----   ----    ----
      290  12-14-05 12:11   fruit/orange.py
      330  12-14-05 15:33   fruit/apple.py
      240  12-14-05 12:26   fruit/simpletests.py
        0  12-14-05 12:13   fruit/__init__.py
      556  12-14-05 16:24   fruit/orange.pyc
      754  12-14-05 16:24   fruit/apple.pyc
      537  12-14-05 16:24   fruit/simpletests.pyc
      124  12-14-05 16:24   fruit/__init__.pyc
    18896  12-14-05 14:54   fruit/docs/readme.html
     8768  12-14-05 16:02   fruit/docs/readme.rest
      141  12-14-05 12:36   fruit/docs/vstrc.vim
       14  12-14-05 14:32   fruit/docs/runvim.vim
      489  12-14-05 16:24   EGG-INFO/PKG-INFO
        6  12-14-05 16:24   EGG-INFO/top_level.txt
       58  12-14-05 16:24   EGG-INFO/entry_points.txt
        0  12-14-05 16:24   EGG-INFO/zip-safe
 --------                   -------
    31203                   16 files
</pre>
    </p>

    </blockquote>
</li></ol>
<h2 id="lbacktracking">Backtracking</h2>

<p>
Some things I should mention....
</p>

 <ul class="circle">
 <li><p class="firstli"> apply the svn 'trick' to get the ez_setup file</p></li>
 <li><p class="firstli"> get a freebie ftp account to test uploading to</p></li>
 <li><p class="onlyli"> create a pipy account so that you can upload there, too</p>
</li>
</ul>
<h3 id="lthe-ez-setup46py-file">The ez_setup.py file</h3>
<ol class="decimal">
<li><p class="firstli">Per the <a href="http://peak.telecommunity.com/DevCenter/setuptools" title="Peak">Peak</a> website, install ez_setup.py as an svn external thingy. Here are the steps:</p>
<pre>
 $ cd SimpleExampleEgg/
 $ svn propedit svn:externals .
 # enter this in the editor: 
 ez_setup svn://svn.eby-sarna.com/svnroot/ez_setup
 # slurp down the latest ez_setup file  
 $ svn update
 # you should see the ez_setup dir now..., if you don't, try
 $ svn propget svn:externals
 ez_setup svn://svn.eby-sarna.com/svnroot/ez_setup
</pre>

</li>
<li><p class="firstli">It would be nice to be able to create a project that just housed the
    ez_setup project, and then just reference that project in all my other
    projects. However, apparently svn does not support chained external
    dependencies. So each project will either have to have a copy of
    ez_setup.py, or this external reference.</p>
</li></ol>
<h3 id="lcreate-a-pipy-account58">Create a PiPy account:</h3>
<ol class="decimal">
<li><p class="firstli">this part is easy:</p>
<pre>
 $ python setup.py register
</pre>

</li>
<li><p class="firstli">now just follow the instructions..:</p>
<pre>
 running register
 We need to know who you are, so please choose either:
 1. use your existing login,
 2. register as a new user,
 3. have the server generate a new password for you (and email it to you),
   or
 4. quit
 Your selection [default 1]:
</pre>

</li>
<li><p class="firstli">you'll need your username and password the first time you deploy.
    subsequent deploys will store your log in info somewhere in your home dir</p>
</li></ol>
<h2 id="lapp-deployment">App Deployment</h2>

<p>
Now, we want to do your basic 'app' stuff:
</p>

    <ul class="circle">
    <li><p class="firstli"> script generation</p></li>
    <li><p class="firstli"> build</p></li>
    <li><p class="onlyli"> deploy</p></li>
    <li><p class="firstli"> test</p>
</li>
</ul>
<h3 id="lscript-generation">Script Generation</h3>

<p>
The idea here is that if I have some cool command line app, then how do I
access it when it's all tucked inside an egg? The generated wrapper scripts do
just that.
</p>

<ol class="decimal">
<li><p class="onlyli">add entry points to setup.py:</p>
<pre>
 setup(
 ...
 entry_points = {'console_scripts': [
     'make_apple_pie = fruit.apple:make_pie'
     ]},
</pre>

</li>
<li><p class="firstli">note that you  cannot pass command line vars to the method:</p>
<pre>
 tgreenwo&#64;luxor~/active/SimpleExampleEgg$ make_apple_pie
 Traceback (most recent call last):
  File "/usr/bin/make_apple_pie", line 7, in ?
      sys.exit(
      TypeError: make_pie() takes exactly 1 argument (0 given)
      tgreenwo&#64;luxor~/active/SimpleExampleEgg$ python make_apple_pie
      python: can't open file 'make_apple_pie': [Errno 2] No such file or
      directory
 tgreenwo&#64;luxor~/active/SimpleExampleEgg$ which make_apple_pie
      /usr/bin/make_apple_pie
 tgreenwo&#64;luxor~/active/SimpleExampleEgg$ cat /usr/bin/make_apple_pie
      #!/home/tgreenwo/bin/python
      # EASY-INSTALL-ENTRY-SCRIPT:
      # 'SimpleExampleEgg==0.1','console_scripts','make_apple_pie'
      __requires__ = 'SimpleExampleEgg==0.1'
      import sys
      from pkg_resources import load_entry_point

      sys.exit(
         load_entry_point('SimpleExampleEgg==0.1', 'console_scripts',
         'make_apple_pie')()
         )
</pre>

</li>
<li><p class="firstli">add a method to apple.py w/o params:</p>
<pre>
 #apple.py
 def doConsole(): print make_pie('CONSOLE')

 #setup.py
 entry_points = {'console_scripts': [
     'make_apple_pie = fruit.apple:doConsole'
     ]},
</pre>

</li>
<li><p class="firstli">install (as root) again</p>
    <blockquote>

    <p>
    <code>easy_install dist/SimpleExampleEgg-0.1-py2.4.egg</code>
    </p>

    </blockquote>
</li>
<li><p class="firstli">and run again:</p>
<pre>
 tgreenwo&#64;luxor~/active/SimpleExampleEgg$ /usr/bin/make_apple_pie
 CONSOLE likes pie!!!
</pre>

</li></ol>
<h3 id="lbuilding">Building</h3>

<p>
We did this already, but, we'll do it again here.
</p>

<ol class="decimal">
<li><p class="firstli">Build the app into an egg:</p>
    <blockquote>

    <p>
    <code>$ python setup bdist_egg</code>
    </p>

    <p>

<pre>
running bdist_egg
running egg_info
writing ./SimpleExampleEgg.egg-info/PKG-INFO
writing top-level names to ./SimpleExampleEgg.egg-info/top_level.txt
writing entry points to ./SimpleExampleEgg.egg-info/entry_points.txt
installing library code to build/bdist.linux-i686/egg
running install_lib
warning: install_lib: 'build/lib' does not exist -- no Python modules to install
creating build/bdist.linux-i686/egg
creating build/bdist.linux-i686/egg/EGG-INFO
copying ./SimpleExampleEgg.egg-info/PKG-INFO -> build/bdist.linux-i686/egg/EGG-INFO
copying ./SimpleExampleEgg.egg-info/top_level.txt -> build/bdist.linux-i686/egg/EGG-INFO
copying ./SimpleExampleEgg.egg-info/entry_points.txt -> build/bdist.linux-i686/egg/EGG-INFO
creating 'dist/SimpleExampleEgg-0.1-py2.4.egg' and adding 'build/bdist.linux-i686/egg' to it
removing 'build/bdist.linux-i686/egg' (and everything under it)
</pre>
    </p>

    </blockquote>
</li>
<li><p class="firstli">And lastly, let's check to make sure that we have what we expect:</p>
    <blockquote>

    <p>
    <code>$ unzip -l /home/tgreenwo/active/SimpleExampleEgg/dist/SimpleExampleEgg-0.1-py2.4.egg</code>
    </p>

    <p>

<pre>
Archive:  /home/tgreenwo/active/SimpleExampleEgg/dist/SimpleExampleEgg-0.1-py2.4.egg
  Length     Date   Time    Name
 --------    ----   ----    ----
      290  12-14-05 12:11   fruit/orange.py
      330  12-14-05 15:33   fruit/apple.py
      240  12-14-05 12:26   fruit/simpletests.py
        0  12-14-05 12:13   fruit/__init__.py
      556  12-14-05 16:24   fruit/orange.pyc
      754  12-14-05 16:24   fruit/apple.pyc
      537  12-14-05 16:24   fruit/simpletests.pyc
      124  12-14-05 16:24   fruit/__init__.pyc
    18896  12-14-05 14:54   fruit/docs/readme.html
     8768  12-14-05 16:02   fruit/docs/readme.rest
      141  12-14-05 12:36   fruit/docs/vstrc.vim
       14  12-14-05 14:32   fruit/docs/runvim.vim
      489  12-14-05 16:24   EGG-INFO/PKG-INFO
        6  12-14-05 16:24   EGG-INFO/top_level.txt
       58  12-14-05 16:24   EGG-INFO/entry_points.txt
        0  12-14-05 16:24   EGG-INFO/zip-safe
 --------                   -------
    31203                   16 files
</pre>
    </p>

    </blockquote>
</li></ol>
<h3 id="ldeploy-locally-40dev-mode41">Deploy Locally (Dev Mode)</h3>
<ol class="decimal">
<li><p class="firstli">create a deployment directory to house the egg links:</p>
<pre>
 $ cd working
 $ mkdir deploy
</pre>

</li>
<li><p class="firstli">add the 'deploy' directory to your pythonpath:</p>
    <blockquote>

    <p>

<pre>
                export PYTHONPATH=/home/tgreenwo/working/twisted:/home/tgreenwo/working/django:/home/tgreenwo/working/deploy
</pre>
    </p>

    </blockquote>
</li>
<li><p class="firstli">install the egg locally in dev mode:</p>
    <blockquote>

    <p>
    <code>$ python setup.py develop</code>
    </p>

    <p>

<pre>
running develop
running egg_info
writing ./SimpleExampleEgg.egg-info/PKG-INFO
writing top-level names to ./SimpleExampleEgg.egg-info/top_level.txt
writing entry points to ./SimpleExampleEgg.egg-info/entry_points.txt
running build_ext
Creating /usr/lib/python2.4/site-packages/SimpleExampleEgg.egg-link (link to .)
error: /usr/lib/python2.4/site-packages/SimpleExampleEgg.egg-link: Permission denied
</pre>
    </p>

    </blockquote>
</li>
<li><p class="firstli">this time, we specify the deploy directory:</p>
    <blockquote>

    <p>
    <code>$ python setup.py develop -d /home/tgreenwo/working/deploy</code>
    </p>

    <p>

<pre>
running develop
running egg_info
writing ./SimpleExampleEgg.egg-info/PKG-INFO
writing top-level names to ./SimpleExampleEgg.egg-info/top_level.txt
writing entry points to ./SimpleExampleEgg.egg-info/entry_points.txt
running build_ext
Creating /home/tgreenwo/data/working/deploy/SimpleExampleEgg.egg-link (link to .)
Installing make_apple_pie script to /home/tgreenwo/working/deploy

Installed /home/tgreenwo/active/SimpleExampleEgg/fruit/docs

Because this distribution was installed --multi-version or --install-dir,
before you can import modules from this package in an application, you
will need to 'import pkg_resources' and then use a 'require()' call
similar to one of these examples, in order to select the desired version:

    pkg_resources.require("SimpleExampleEgg")  # latest installed version
    pkg_resources.require("SimpleExampleEgg==0.1")  # this exact version
    pkg_resources.require("SimpleExampleEgg>=0.1")  # this version or higher

Processing dependencies for SimpleExampleEgg==0.1
</pre>
    </p>

    </blockquote>
</li></ol>
<h3 id="ldeploy-to-pipy">Deploy To pipy</h3>
<ol class="decimal">
<li><p class="firstli">build and deploy in one step:</p>
<pre>
 $ setup.py register sdist bdist_egg upload
</pre>

</li>
<li><p class="firstli">I had problems, so I enabled the following:</p>
<pre>
 $ python setup.py register sdist bdist_egg upload --show-response
</pre>

</li>
<li><p class="firstli">Once you noodle thru all the errors for your log in, password, and whether
    all the meta information like url and topic are set, then the egg will
    upload.</p>
</li></ol>
<h2 id="lend-user-app-install">End User App Install</h2>

<p>
General steps are:
</p>

 <ul class="circle">
 <li><p class="firstli"> su or sudo</p></li>
 <li><p class="firstli"> easy_install [egg name] or</p></li>
 <li><p class="onlyli"> easy_install [pipy project name]</p></li>
 <li><p class="firstli"> run unit tests</p>
</li>
</ul>
<h3 id="luser-install">User Install</h3>
<ol class="decimal">
<li><p class="onlyli">Simple. One step:</p>
<pre>
 root$ easy_install SimpleExampleEgg

 Searching for SimpleExampleEgg
 Reading http://www.python.org/pypi/SimpleExampleEgg/
 Best match: SimpleExampleEgg 0.1
 Downloading
 http://cheeseshop.python.org/packages/2.4/S/SimpleExampleEgg/SimpleExampleEgg-0.1-py2.4.egg#md5=d53e38ea496e03d30b632dc08265128b
 Processing SimpleExampleEgg-0.1-py2.4.egg
 Moving SimpleExampleEgg-0.1-py2.4.egg to /usr/lib/python2.4/site-packages
 Adding SimpleExampleEgg 0.1 to easy-install.pth file
 Installing make_apple_pie script to /usr/bin

 Installed /usr/lib/python2.4/site-packages/SimpleExampleEgg-0.1-py2.4.egg
 Processing dependencies for SimpleExampleEgg
</pre>

</li>
<li><p class="firstli">done</p>
</li></ol>
<h3 id="luser-run-unit-tests">User Run Unit Tests</h3>
<ol class="decimal">
<li><p class="firstli">this should run the unit tests for the installed app:</p>
<pre>
 $ python -c "from unittest import main; main(None)"
 fruit.simpletests.getTestSuite
</pre>

</li>
<li><p class="firstli">let's try that:</p>
    <blockquote>

    <p>
    <code>python -c 'from unittest import main; main(None)'
    fruit.simpletests.getTestSuite</code>
    </p>

    <p>

<pre>
.
----------------------------------------------------------------------
Ran 1 test in 0.007s

OK
.
----------------------------------------------------------------------
Ran 1 test in 0.001s

OK
</pre>
    </p>

    </blockquote>
</li></ol>
<h2 id="lconclusion">Conclusion</h2>
<ol class="decimal">
<li><p class="firstli">vim + vst rocks</p></li>
<li><p class="firstli">eggs are cool</p>
</li></ol>
<!-- .. links:
 -->

</body>
</html>