Bento is a packaging tool for Python software that aims to improve upon the existing distutils and setuptools tools. It uses a declarative configuration file called bento.info to describe package metadata and installation scheme. The bento tool provides commands like configure, build, and install via a command line interface. Bento's design principles emphasize flexibility, extensibility, and usability as both a library and standalone tool.
2. WHAT’S PACKAGING ?
• Whatever that has to happen between svn/git/etc... and the
end-user
• Different end-users, different workflows: not just tarballs
(maybe those guys don’t need
packaging)
3. DISTUTILS
• De-facto solution since ±2000
• Works well for simple packages:
• Setuptools/distribute
• add package dependencies
4. DISTUTILS ISSUES
• Make one’s head
hurt:
• Hard to extend
• Fragile codebase
• Reliability issues
5. BENTO
• Declarative description of package: metadata inspection
is simple
• Flexible installation scheme: install any file anywhere
• Layered internal architecture: easy to extend
• Scaledown and up: simpler for small packages, more
flexible for big ones
10. HOOK FILES
• Can “hook” python files into the build process
from bento.commands import hooks
@hooks.command
def hello(context):
print "hello"
$ bentomaker hello
hello
• Hook are pure python: no auto-import, etc...
11. FITTING IN THE PYTHON
ECOSYSTEM
Convert distutils package to bento
# Convert a setup.py to bento.info
$ bentomaker convert
Distutils compatibility layer (pip-installable !)
# setup.py
import setuptools
import bento.distutils
bento.distutils.monkey_patch()
# grab metadata from bento.info
setuptools.setup()
13. DESIGN PRINCIPLES
• Usable as a library (still a few singleton to remove...)
• Low-couplingof commands: new package format should not
care about building phase
• Driven by real packages (numpy, scipy, twisted, ipython, etc...)
15. COMMANDS AND
CONTEXTS
Context Command
self.pkg self.run(context)
self.cmd_argv
self.run_node
• Contexts encapsulate a command ‘environment’
• Context-command relationship is overridable (hook)
• e.g. mechanism to interact with 3rd party build tools
16. MORE ABOUT COMMANDS
• Command options defined externally: any command can
query any other’s options
• Commands dependencies resolved at runtime
@hooks.command
def hello(context):
print "hello"
@hooks.command
def goodbye(context):
print "goodbye"
@hooks.startup
def startup(context):
context.set_before("goodbye", "hello")
17. BUILD MANIFEST
• Goal: decouple build and install
• format: a json file containing info about built parts
• Inspired by cabal (‘distutils’ for haskell)
• build command produces a build manifest
• install only knows about build manifest
• Install only install built files
18. NODE
• Every file is represented internally as a node (waf concept)
• nodes are a in-memory representation of the fs
• gives reliable relative paths between files
sdir = os.getcwd()
bdir = os.path.join(os.getcwd(), "build")
root = create_root_with_source_tree(sdir, bdir)
top_node = root.find_node(sdir)
build_node = root.find_node(bdir)
print top_node.path_from(build_node)
19. SOME NEAT FEATURES (1)
• Using metadata in the packaged software
Name: foo # foo.py.in
Version: 1.0 name = $NAME
MetaTemplateFile: foo.py.in version = $VERSION
# foo.py.in
name = "foo"
version = "1.0"
20. SOME NEAT FEATURES (2)
• Sane way to load data files
Name: foo
Version: 1.0
ConfigPy: __config.py
# __config.py
BINDIR = r”/usr/bin”
...
21. SOME NEAT FEATURES (3)
• Out of tree build (bye bye source tree pollution)
# Convert a setup.py to bento.info
$ bentomaker --bento-info=../source_dir/bento.info
22. A FEW NUMBERS
• bento: ± 8000 LOC (not including ± 2500 LOC for tests)
• numpy.distutils: ±10000 LOC
• distutils: ± 10000 LOC
• numpy: ±2000 LOC for distutils vs ±1000 LOC for bento
• scipy: ±1600 LOC vs ±1100 LOC
24. WHERE TO GET IT ?
• Getting bento on github: http://github.com/cournape/Bento.git
• Bento doc: http://cournape.github.com/Bento
• Bento mailing-list: bento@librelist.com