2. Python is not
compiled
(actually, it is, but that’s not important right now)
3. Python projects
certainly do not need
• Redistributable files to move
around
• Deployment to other machines
• Interaction with source control
systems
• Documentation that’s built from
the source code
• Documentation that’s built from a
format other than its final display
format
4.
5. If only there was
some scripting
language that we
already knew.
7. Project-related
scripts need...
• Command line argument handling
• Configuration
• Often work with files
• Sometimes need to use distutils/
setuptools, but wish they could do
a little more
• Need to work with other common
tools (Sphinx, svn, virtualenv)
10. Lots of working with files
import os
if not os.path.exists(“foo”):
os.mkdir(“foo”)
if not os.path.exists(os.path.join(“foo, “bar”)):
open(os.path.join(“foo”, “bar”), “w”).write(“Hi”)
12. Other common tools
sphinx-build ...
subprocess.Popen(“svn info”... # and do something with the
output
virtualenv.create_bootstrap_script(“# more code”)
18. Why Python build
files?
• You already know Python
• The language rules are well-defined
• The language rules are well-
documented
• Python is powerful, so you’ll never
be left hanging or need an escape
hatch
30. Namespace searching (continued)
>>> options(
... setup=Bunch(version=quot;1.0quot;),
... sphinx=Bunch(builddir=quot;docbuildquot;)
... )
>>> options.order('sphinx')
>>> options.version
Traceback (most recent call last):
File quot;<stdin>quot;, line 1, in <module>
File quot;/Users/admin/projects/paver/paver/runtime.pyquot;, line
31, in __getattr__
raise AttributeError(name)
AttributeError: version
31. Namespace searching (continued)
>>> options(
... setup=Bunch(version=quot;1.0quot;),
... sphinx=Bunch(builddir=quot;docbuildquot;)
... )
>>> options.order('sphinx')
>>> options.version
Traceback (most recent call last):
File quot;<stdin>quot;, line 1, in <module>
File quot;/Users/admin/projects/paver/paver/runtime.pyquot;, line
31, in __getattr__
raise AttributeError(name)
AttributeError: version
32. Namespace searching (continued)
>>> options(
... setup=Bunch(version=quot;1.0quot;),
... sphinx=Bunch(builddir=quot;docbuildquot;)
... )
>>> options.order('sphinx')
>>> options.version
Traceback (most recent call last):
File quot;<stdin>quot;, line 1, in <module>
File quot;/Users/admin/projects/paver/paver/runtime.pyquot;, line
31, in __getattr__
raise AttributeError(name)
AttributeError: version
33. Configuration is
still standard
Python
• You can treat options like a normal,
nested dictionary
• The only unusual thing would be
that callables are called.
34.
35. Tasks
@task
def clean():
quot;quot;quot;Cleans up this paver directory. Removes the virtualenv
traces and
the build directory.quot;quot;quot;
pass
36. Tasks
@task
def clean():
quot;quot;quot;Cleans up this paver directory. Removes the virtualenv
traces and
the build directory.quot;quot;quot;
pass
37. Tasks
@task
def clean():
quot;quot;quot;Cleans up this paver directory. Removes the virtualenv
traces and
the build directory.quot;quot;quot;
pass
38. Tasks
@task
def clean():
quot;quot;quot;Cleans up this paver directory. Removes the virtualenv
traces and
the build directory.quot;quot;quot;
pass
39. Tasks
@task
def clean():
quot;quot;quot;Cleans up this paver directory. Removes the virtualenv
traces and
the build directory.quot;quot;quot;
pass
40. paver help
$ paver help
---> help
Paver 0.8.1
Usage: paver [global options] [option.name=value] task [task
options] [task...]
Run 'paver help [section]' to see the following sections of
info:
options global command line options
setup available distutils/setuptools tasks
tasks all tasks that have been imported by your pavement
'paver help taskname' will display details for a task.
Tasks defined in your pavement:
bootstrap - Build a virtualenv bootstrap for developing
41. paver help
$ paver help
---> help
Paver 0.8.1
Usage: paver [global options] [option.name=value] task [task
options] [task...]
Run 'paver help [section]' to see the following sections of
info:
options global command line options
setup available distutils/setuptools tasks
tasks all tasks that have been imported by your pavement
'paver help taskname' will display details for a task.
Tasks defined in your pavement:
bootstrap - Build a virtualenv bootstrap for developing
42. paver help
$ paver help
---> help
Paver 0.8.1
Usage: paver [global options] [option.name=value] task [task
options] [task...]
Run 'paver help [section]' to see the following sections of
info:
options global command line options
setup available distutils/setuptools tasks
tasks all tasks that have been imported by your pavement
'paver help taskname' will display details for a task.
Tasks defined in your pavement:
bootstrap - Build a virtualenv bootstrap for developing
43. paver help
$ paver help
---> help
Paver 0.8.1
Usage: paver [global options] [option.name=value] task [task
options] [task...]
Run 'paver help [section]' to see the following sections of
info:
options global command line options
setup available distutils/setuptools tasks
tasks all tasks that have been imported by your pavement
'paver help taskname' will display details for a task.
Tasks defined in your pavement:
bootstrap - Build a virtualenv bootstrap for developing
44. paver help
$ paver help
---> help
Paver 0.8.1
Usage: paver [global options] [option.name=value] task [task
options] [task...]
Run 'paver help [section]' to see the following sections of
info:
options global command line options
setup available distutils/setuptools tasks
tasks all tasks that have been imported by your pavement
'paver help taskname' will display details for a task.
Tasks defined in your pavement:
bootstrap - Build a virtualenv bootstrap for developing
45. paver help tasks
Tasks defined in and imported by your pavement:
bootstrap - Build a virtualenv bootstrap for
developing paver
clean - Cleans up this paver directory
cog - Runs the cog code generator
against the files matching your
specification
commit - Removes the generated code from
the docs and then commits to bzr
deploy - Copy the Paver website up
doc_clean - Clean (delete) the built docs
generate_setup - Generates a setup
help - Displays the list of commands and
the details
html - Build Paver's documentation and
install it into paver/docs
minilib - Create a Paver mini library that
contains enough for a simple
46. paver help <taskname>
Details for minilib:
Create a Paver mini library that contains enough for a simple
pavement.py to be installed using a generated setup.py.
This
is a good temporary measure until more people have
deployed paver.
The output file is 'paver-minilib.zip' in the current
directory.
Options:
extra_files
list of other paver modules to include (don't include
the .py
extension)
47. @needs
@task
@needs(quot;uncogquot;)
def commit():
quot;quot;quot;Removes the generated code from the docs and then
commits to bzr.quot;quot;quot;
pass
48. @needs
@task
@needs(quot;uncogquot;)
def commit():
quot;quot;quot;Removes the generated code from the docs and then
commits to bzr.quot;quot;quot;
pass
49. @needs
@task
@needs(quot;uncogquot;)
def commit():
quot;quot;quot;Removes the generated code from the docs and then
commits to bzr.quot;quot;quot;
pass
54. “Using the Distutils is quite
simple, both for module
developers and for users/
administrators installing
third-party modules.”
– Distributing Python Modules, section 1.1
68. paver.runtime
# display text if verbose is set
debug(“Hi there. Feeling chatty today?”)
# display text if quiet is not set
info(“Glad we don’t have to keep quiet”)
# display text regardless of setting
error(“HA! I’M SHOUTING AND YOU CAN’T STOP ME!”)
69. paver.runtime
# display text if verbose is set
debug(“Hi there. Feeling chatty today?”)
# display text if quiet is not set
info(“Glad we don’t have to keep quiet”)
# display text regardless of setting
error(“HA! I’M SHOUTING AND YOU CAN’T STOP ME!”)
70. paver.runtime
# display text if verbose is set
debug(“Hi there. Feeling chatty today?”)
# display text if quiet is not set
info(“Glad we don’t have to keep quiet”)
# display text regardless of setting
error(“HA! I’M SHOUTING AND YOU CAN’T STOP ME!”)
71. paver.runtime
# display text if verbose is set
debug(“Hi there. Feeling chatty today?”)
# display text if quiet is not set
info(“Glad we don’t have to keep quiet”)
# display text regardless of setting
error(“HA! I’M SHOUTING AND YOU CAN’T STOP ME!”)
72. paver.runtime
# display text if verbose is set
debug(“Hi there. Feeling chatty today?”)
# display text if quiet is not set
info(“Glad we don’t have to keep quiet”)
# display text regardless of setting
error(“HA! I’M SHOUTING AND YOU CAN’T STOP ME!”)
73. paver.runtime
# display text if verbose is set
debug(“Hi there. Feeling chatty today?”)
# display text if quiet is not set
info(“Glad we don’t have to keep quiet”)
# display text regardless of setting
error(“HA! I’M SHOUTING AND YOU CAN’T STOP ME!”)
74. paver.runtime
# display text if verbose is set
debug(“Hi there. Feeling chatty today?”)
# display text if quiet is not set
info(“Glad we don’t have to keep quiet”)
# display text regardless of setting
error(“HA! I’M SHOUTING AND YOU CAN’T STOP ME!”)
75. paver.runtime (continued)
# run a command, as long as dry-run is off
# capture the output into myval
myval = sh(“cat /tmp/foo”, capture=True)
# run a function (delete_all(‘/’) to be exact).
# if dry-run is set, then
# just print the message instead
dry(“Delete everything”, delete_all, ‘/’)
76. paver.runtime (continued)
# run a command, as long as dry-run is off
# capture the output into myval
myval = sh(“cat /tmp/foo”, capture=True)
# run a function (delete_all(‘/’) to be exact).
# if dry-run is set, then
# just print the message instead
dry(“Delete everything”, delete_all, ‘/’)
77. paver.runtime (continued)
# run a command, as long as dry-run is off
# capture the output into myval
myval = sh(“cat /tmp/foo”, capture=True)
# run a function (delete_all(‘/’) to be exact).
# if dry-run is set, then
# just print the message instead
dry(“Delete everything”, delete_all, ‘/’)
78. paver.runtime (continued)
# run a command, as long as dry-run is off
# capture the output into myval
myval = sh(“cat /tmp/foo”, capture=True)
# run a function (delete_all(‘/’) to be exact).
# if dry-run is set, then
# just print the message instead
dry(“Delete everything”, delete_all, ‘/’)
79. paver.runtime (continued)
# run a command, as long as dry-run is off
# capture the output into myval
myval = sh(“cat /tmp/foo”, capture=True)
# run a function (delete_all(‘/’) to be exact).
# if dry-run is set, then
# just print the message instead
dry(“Delete everything”, delete_all, ‘/’)
81. paver.path
• Jason Orendorff’s path.py module
(also available separately)
• It’s a subclass of string!
• Fun use of operator overloading
• Lots of great methods
• Makes working with files/directories
fun and easy
82. paver.path examples
p = path(quot;docsquot;)
tmpdir = p / quot;tmpquot;
tmpdir.mkdir()
fn = tmpdir / quot;myfile.txtquot;
fn.write_text(quot;Hi there!quot;)
83. paver.path examples
p = path(quot;docsquot;)
tmpdir = p / quot;tmpquot;
tmpdir.mkdir()
fn = tmpdir / quot;myfile.txtquot;
fn.write_text(quot;Hi there!quot;)
84. paver.path examples
p = path(quot;docsquot;)
tmpdir = p / quot;tmpquot;
tmpdir.mkdir()
fn = tmpdir / quot;myfile.txtquot;
fn.write_text(quot;Hi there!quot;)
85. paver.path examples
p = path(quot;docsquot;)
tmpdir = p / quot;tmpquot;
tmpdir.mkdir()
fn = tmpdir / quot;myfile.txtquot;
fn.write_text(quot;Hi there!quot;)
86. paver.path examples
p = path(quot;docsquot;)
tmpdir = p / quot;tmpquot;
tmpdir.mkdir()
fn = tmpdir / quot;myfile.txtquot;
fn.write_text(quot;Hi there!quot;)
87. paver.path examples
p = path(quot;docsquot;)
tmpdir = p / quot;tmpquot;
tmpdir.mkdir()
fn = tmpdir / quot;myfile.txtquot;
fn.write_text(quot;Hi there!quot;)
88. paver.path examples
p = path(quot;docsquot;)
tmpdir = p / quot;tmpquot;
tmpdir.mkdir()
fn = tmpdir / quot;myfile.txtquot;
fn.write_text(quot;Hi there!quot;)
90. paver.doctools – Sphinx
paver.doctools.html()¶
Build HTML documentation using Sphinx. This uses the following options in a
“sphinx” section of the options.
docroot
the root under which Sphinx will be working. Default: docs
builddir
directory under the docroot where the resulting files are put. default: build
sourcedir
directory under the docroot for the source files default: (empty string)
paver.doctools.doc_clean()¶
Clean (delete) the built docs. Specifically, this deletes the build directory under the
docroot. See the html task for the options list.
91. paver.doctools –
Cog & SectionedFile
• Solutions to common problems of
creating high-quality docs
• Ideally, your code samples will be in
convenient runnable code files and
have unit tests.
• But you also want nice, minimal
code samples in your text as you’re
writing.
92. paver.doctools sample code
# mysample.py
# [[[section mysample]]]
def sample_func():
print quot;To sample, or not to sample?quot;
# [[[endsection]]]
93. paver.doctools in docs
And then when you want to print the sample string, you just
call::
# [[[cog include(“code/mysample.py”, “mysample”)]]]
# [[[end]]]
94. paver.doctools in docs (2)
And then when you want to print the sample string, you just
call::
# [[[cog include(“code/mysample.py”, “mysample”)]]]
def sample_func():
print quot;To sample, or not to sample?quot;
# [[[end]]]
95. paver.doctools uncog before
commit
@task
@needs(quot;uncogquot;)
def commit():
quot;quot;quot;Removes the generated code from the docs and then
commits to bzr.quot;quot;quot;
sh(quot;bzr commitquot;)
96. paver.svn
paver.svn.checkout(url, dest, revision='')
Checks out the specified URL to the given destination.
paver.svn.checkup(url, dest, revision='')
Does a checkout or update, depending on whether the destination exists and is up
to date (if a revision is passed in). Returns true if a checkout or update was
performed. False otherwise.
paver.svn.info(path='')
Retrieves the svn info for the path and returns a dictionary of the values. Names
are normalized to lower case with spaces converted to underscores.
paver.svn.update(path='', revision='')
Run an svn update on the given path.
Example at: https://projects.sitepen.com/toolbox/svn/trunk/pavement.py
98. paver.virtual
paver.virtual.bootstrap()
Creates a virtualenv bootstrap script. The script will create a bootstrap script that
populates a virtualenv in the current directory. The environment will have paver,
the packages of your choosing and will run the paver command of your choice.
This task looks in the virtualenv options for:
script_name
name of the generated script
packages_to_install
packages to install with easy_install. The version of paver that you are using is
included automatically. This should be a list of strings.
paver_command_line
run this paver command line after installation (just the command line arguments,
not the paver command itself).
99. paver.misctasks
paver.misctasks.generate_setup()
paver.misctasks.help()
paver.misctasks.minilib()
Options:
extra_files
list of other paver modules to include (donʼt include the .py extension)
paver.misctasks.paverdocs()
100. Pulling it all
together
• write functions with the @task
decorator.
• Just plain old Python with lots of
conveniences
• Paver’s pavement.py is a good
example
• Even better, take a look at
“Getting Started with Paver”
http://bit.ly/starting_paver
102. Paver needs to do that too
@task
@needs(['html', quot;minilibquot;, quot;generate_setupquot;,
“setuptools.command.sdist”])
def sdist():
quot;quot;quot;Builds the documentation and the tarball.quot;quot;quot;
pass
103. But wait, it does more!
@task
@needs(['cog', 'paver.doctools.html'])
def html():
quot;quot;quot;Build Paver's documentation and install it into paver/
docsquot;quot;quot;
builtdocs = path(quot;docsquot;) / options.sphinx.builddir /
quot;htmlquot;
destdir = path(quot;paverquot;) / quot;docsquot;
destdir.rmtree()
builtdocs.move(destdir)
104. Changes coming to
Paver
• The little bit of magic goes away
• Support for CloudControl
• Ability to run sub-builds easily
• Virtualenv/pyinstall management
• zc.buildout recipe running