isolated development in python
DESCRIPTION
How to develop in python safely using isolated environments, create packages and unit testing with code coverage.TRANSCRIPT
Isolated Developmentin Python
1. pip installer
pip installer
$ pip install <package>
pip installer
$ pip install <package>
Download package from pypi.python.org
pip installer
$ pip install <package>
$ pip install <directory>
$ pip install <tar.gz>
Download package from pypi.python.org
pip installer
$ pip install <gitrepo>
pip installer
$ pip install <gitrepo>
GREAT!!
pip installer
$ pip install <gitrepo>
GREAT!!
$ pip install git+git://github.com/ajdiaz/mole
$ pip install git+ssh://github.com/ajdiaz/mole
$ pip install git+git://github.com/ajdiaz/mole@840d25
$ pip install git+git://github.com/ajdiaz/mole@devel-branch
$ pip install git+git://....@devel-branch#egg=Mole
pip installer
$ pip freeze
pip installer
$ pip freeze
Fabric==1.5.2
GitPython==0.3.2.RC1
Jinja2==2.6
Pygments==1.6
Sphinx==1.2b1
argparse==1.2.1
async==0.6.1
boto==2.7.0
cuisine==0.5.1
distribute==0.6.24
docutils==0.10
gitdb==0.5.4
mico==0
paramiko==1.9.0
pycrypto==2.6
smmap==0.8.2
wsgiref==0.1.2
Create requirements.txt
2. Virtualenv: a jail for python
Virtualenv: the python jail
$ virtualenv --python=/usr/bin/python2.7 mynewenvironment
Virtualenv: the python jail
OR EVEN BETTER
$ virtualenv --python=/usr/bin/python2.7 mynewenvironment
Virtualenv: the python jail
$ virtualenv --python=/usr/bin/python2.7 mynewenvironment
OR EVEN BETTER
$ mkvirtualenv --python=/usr/bin/python2.7 mynewenvironment
Virtualenv: the python jail
$ virtualenv --python=/usr/bin/python2.7 mynewenvironment
OR EVEN BETTER
$ mkvirtualenv --python=/usr/bin/python2.7 mynewenvironment
mkvirtualenvwrapper
Virtualenvwrapper
$ mkvirtualenv test
Virtualenvwrapper
$ mkvirtualenv test
New python executable in test/bin/python
Installing
distribute......................................................................................................................
.......................................................................done.
Installing pip...............done.
virtualenvwrapper.user_scripts creating /home/ajdiaz/env/test/bin/predeactivate
virtualenvwrapper.user_scripts creating /home/ajdiaz/env/test/bin/postdeactivate
virtualenvwrapper.user_scripts creating /home/ajdiaz/env/test/bin/preactivate
virtualenvwrapper.user_scripts creating /home/ajdiaz/env/test/bin/postactivate
virtualenvwrapper.user_scripts creating /home/ajdiaz/env/test/bin/get_env_details
(test) $
Virtualenvwrapper
$ mkvirtualenv test
New python executable in test/bin/python
Installing
distribute......................................................................................................................
.......................................................................done.
Installing pip...............done.
virtualenvwrapper.user_scripts creating /home/ajdiaz/env/test/bin/predeactivate
virtualenvwrapper.user_scripts creating /home/ajdiaz/env/test/bin/postdeactivate
virtualenvwrapper.user_scripts creating /home/ajdiaz/env/test/bin/preactivate
virtualenvwrapper.user_scripts creating /home/ajdiaz/env/test/bin/postactivate
virtualenvwrapper.user_scripts creating /home/ajdiaz/env/test/bin/get_env_details
(test) $ which python
/home/ajdiaz/env/test/bin/python
Virtualenvwrapper
$ mkvirtualenv test
New python executable in test/bin/python
Installing
distribute......................................................................................................................
.......................................................................done.
Installing pip...............done.
virtualenvwrapper.user_scripts creating /home/ajdiaz/env/test/bin/predeactivate
virtualenvwrapper.user_scripts creating /home/ajdiaz/env/test/bin/postdeactivate
virtualenvwrapper.user_scripts creating /home/ajdiaz/env/test/bin/preactivate
virtualenvwrapper.user_scripts creating /home/ajdiaz/env/test/bin/postactivate
virtualenvwrapper.user_scripts creating /home/ajdiaz/env/test/bin/get_env_details
(test) $ which python
/home/ajdiaz/env/test/bin/python
yep, these are hooks!
Unit testing
Unit testing: nose
class A(object):
def __init__(self):
self.value = "Some Value"
def return_true(self):
return True
def raise_exc(self, val):
raise KeyError(val)
save it in a.py
Unit testing: nose
from a import A
from nose.tools import assert_equal
from nose.tools import assert_not_equal
from nose.tools import assert_raises
from nose.tools import raises
class TestA(object):
@classmethod
def setup_class(klass):
"""This method is run once for each class before any tests are run"""
@classmethod
def teardown_class(klass):
"""This method is run once for each class _after_ all tests are run"""
def setUp(self):
"""This method is run once before _each_ test method is executed"""
def teardown(self):
"""This method is run once after _each_ test method is executed"""
.... continue ....
Unit testing: nose
def test_init(self):
a = A()
assert_equal(a.value, "Some Value")
assert_not_equal(a.value, "Incorrect Value")
def test_return_true(self):
a = A()
assert_equal(a.return_true(), True)
assert_not_equal(a.return_true(), False)
def test_raise_exc(self):
a = A()
assert_raises(KeyError, a.raise_exc, "A value")
@raises(KeyError)
def test_raise_exc_with_decorator(self):
a = A()
a.raise_exc("A message")
save it in tests/testa.py
Unit testing: nose
$ nosetests -v tests/
Unit testing: nose
$ nosetests -v tests/
testa.TestA.test_init ... ok
testa.TestA.test_raise_exc ... ok
testa.TestA.test_raise_exc_with_decorator ... ok
testa.TestA.test_return_true ... ok
---------------------------------------------------------
Ran 4 tests in 0.002s
OK
Unit testing: Bonus: code coverage
$ pip install coverage
$ nosetests --with-coverage
....
Name Stmts Miss Cover Missing
-------------------------------------
a 8 0 100%
-------------------------------------
Ran 4 tests in 0.006s OK
Packaging Python Eggs
Python eggs: basic setup.py
from setuptools import setup
setup(
name = "example",
version = "1.0",
description = "An example package",
author='Andres J. Diaz'
)
Python eggs: basic setup.py
from setuptools import setup, find_packages
setup(
name = "example",
version = "1.0",
description = "An example package",
author='Andres J. Diaz',
packages=find_packages()
)
Python eggs: complex setup.py
import re
from setuptools import setup, find_packages
from os import path
def parse_requirements(file_name):
requirements = []
for line in open(file_name, 'r').read().split('\n'):
if re.match(r'(\s*#)|(\s*$)', line):
continue
if re.match(r'\s*-e\s+', line):
requirements.append(re.sub(r'\s*-e\s+.*#egg=(.*)$', r'\1', line))
elif re.match(r'\s*-f\s+', line):
pass
else:
requirements.append(line)
return requirements
.... continue ....
Python eggs: complex setup.py
def parse_dependency_links(file_name):
dependency_links = []
for line in open(file_name, 'r').read().split('\n'):
if re.match(r'\s*-[ef]\s+', line):
dependency_links.append(re.sub(r'\s*-[ef]\s+', '', line))
return dependency_links
def get_file_contents(filename):
fd = file(path.join(path.dirname(__file__), filename), "r")
content = fd.read()
fd.close()
return content
.... continue ....
Python eggs: complex setup.py
setup(
name = "mico",
version = "0.1",
description = "A monkey driven cloud management",
long_description=get_file_contents("README.rst"),
author='Andres J. Diaz',
author_email='[email protected]',
url='http://ajdiaz.github.com/mico',
packages=find_packages(),
install_requires = parse_requirements('requirements.txt'),
dependency_links = parse_dependency_links('requirements.txt'),
entry_points={
'console_scripts': [
'mico = mico.scripts.cmdline:main',
]
},
classifiers=[
'Development Status :: 4 - Beta',
'Intended Audience :: Developers',
'License :: OSI Approved :: GNU General Public License (GPL)',
'Operating System :: OS Independent',
'Programming Language :: Python',
],
)
Python eggs: complex setup.py
setup(
name = "mico",
version = "0.1",
description = "A monkey driven cloud management",
long_description=get_file_contents("README.rst"),
author='Andres J. Diaz',
author_email='[email protected]',
url='http://ajdiaz.github.com/mico',
packages=find_packages(),
install_requires = parse_requirements('requirements.txt'),
dependency_links = parse_dependency_links('requirements.txt'),
entry_points={
'console_scripts': [
'mico = mico.scripts.cmdline:main',
]
},
classifiers=[
'Development Status :: 4 - Beta',
'Intended Audience :: Developers',
'License :: OSI Approved :: GNU General Public License (GPL)',
'Operating System :: OS Independent',
'Programming Language :: Python',
],
)
Applauses & questionsNot necessarily in that order.