Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
S
slapos.buildout
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Kirill Smelkov
slapos.buildout
Commits
7e5bdea9
Commit
7e5bdea9
authored
Oct 07, 2006
by
Jim Fulton
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added a recipe update method.
parent
65da05ac
Changes
11
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
197 additions
and
80 deletions
+197
-80
CHANGES.txt
CHANGES.txt
+6
-1
src/zc/buildout/buildout.py
src/zc/buildout/buildout.py
+59
-10
src/zc/buildout/buildout.txt
src/zc/buildout/buildout.txt
+102
-57
src/zc/buildout/tests.py
src/zc/buildout/tests.py
+13
-11
src/zc/buildout/update.txt
src/zc/buildout/update.txt
+1
-0
zc.recipe.egg_/CHANGES.txt
zc.recipe.egg_/CHANGES.txt
+2
-0
zc.recipe.egg_/src/zc/recipe/egg/api.txt
zc.recipe.egg_/src/zc/recipe/egg/api.txt
+3
-0
zc.recipe.egg_/src/zc/recipe/egg/custom.py
zc.recipe.egg_/src/zc/recipe/egg/custom.py
+4
-1
zc.recipe.egg_/src/zc/recipe/egg/egg.py
zc.recipe.egg_/src/zc/recipe/egg/egg.py
+3
-0
zc.recipe.testrunner/CHANGES.txt
zc.recipe.testrunner/CHANGES.txt
+2
-0
zc.recipe.testrunner/src/zc/recipe/testrunner/__init__.py
zc.recipe.testrunner/src/zc/recipe/testrunner/__init__.py
+2
-0
No files found.
CHANGES.txt
View file @
7e5bdea9
...
...
@@ -28,7 +28,12 @@ Next Release
Feature Changes
---------------
Renamed the runsetup command to setup. (The old name still works.)
- Renamed the runsetup command to setup. (The old name still works.)
- Added a recipe update method. Now install is only called when a part
is installed for the first time, or after an uninstall. Otherwise,
update is called. For backward compatibility, recipes that don't
define update methiods are still supported.
1.0.0b9 (2006-10-02)
====================
...
...
src/zc/buildout/buildout.py
View file @
7e5bdea9
...
...
@@ -288,10 +288,21 @@ class Buildout(dict):
for
part
in
reversed
(
installed_parts
):
if
part
in
install_parts
:
old_options
=
installed_part_options
[
part
].
copy
()
old_options
.
pop
(
'__buildout_installed__'
)
installed_files
=
old_options
.
pop
(
'__buildout_installed__'
)
new_options
=
self
.
get
(
part
)
if
old_options
==
new_options
:
continue
# The options are the same, but are all of the
# installed files still there? If not, we should
# reinstall.
if
not
installed_files
:
continue
for
f
in
installed_files
.
split
(
'
\
n
'
):
if
not
os
.
path
.
exists
(
self
.
_buildout_path
(
f
)):
break
else
:
continue
# output debugging info
for
k
in
old_options
:
if
k
not
in
new_options
:
self
.
_logger
.
debug
(
"Part: %s, dropped option %s"
,
...
...
@@ -305,6 +316,7 @@ class Buildout(dict):
if
k
not
in
old_options
:
self
.
_logger
.
debug
(
"Part: %s, new option %s"
,
part
,
k
)
elif
not
uninstall_missing
:
continue
...
...
@@ -316,17 +328,52 @@ class Buildout(dict):
# install new parts
for
part
in
install_parts
:
self
.
_logger
.
info
(
'Installing %s'
,
part
)
installed_part_options
[
part
]
=
self
[
part
].
copy
()
del
self
[
part
][
'__buildout_signature__'
]
installed_files
=
recipes
[
part
].
install
()
or
()
signature
=
self
[
part
].
pop
(
'__buildout_signature__'
)
saved_options
=
self
[
part
].
copy
()
if
part
in
installed_parts
:
self
.
_logger
.
info
(
'Updating %s'
,
part
)
old_options
=
installed_part_options
[
part
]
old_installed_files
=
old_options
[
'__buildout_installed__'
]
try
:
update
=
recipes
[
part
].
update
except
AttributeError
:
update
=
recipes
[
part
].
install
self
.
_logger
.
warning
(
"The recipe for %s doesn't define an update "
"method. Using it's install method"
,
part
)
try
:
installed_files
=
update
()
except
:
installed_parts
.
remove
(
part
)
self
.
_uninstall
(
old_installed_files
)
raise
if
installed_files
is
None
:
installed_files
=
old_installed_files
.
split
(
'
\
n
'
)
else
:
self
.
_logger
.
info
(
'Installing %s'
,
part
)
installed_files
=
recipes
[
part
].
install
()
if
installed_files
is
None
:
self
.
_logger
.
warning
(
"The %s install returned None. A path or "
"iterable os paths should be returned."
,
part
)
installed_files
=
()
if
isinstance
(
installed_files
,
str
):
installed_files
=
[
installed_files
]
installed_part_options
[
part
][
'__buildout_installed__'
]
=
(
'
\
n
'
.
join
(
installed_files
)
)
installed_part_options
[
part
]
=
saved_options
saved_options
[
'__buildout_installed__'
]
=
'
\
n
'
.
join
(
installed_files
)
saved_options
[
'__buildout_signature__'
]
=
signature
if
part
not
in
installed_parts
:
installed_parts
.
append
(
part
)
finally
:
installed_part_options
[
'buildout'
][
'parts'
]
=
' '
.
join
(
[
p
for
p
in
conf_parts
if
p
in
installed_parts
]
...
...
@@ -475,7 +522,9 @@ class Buildout(dict):
return
self
.
_buildout_path
(
self
[
'buildout'
][
'installed'
])
def
_uninstall
(
self
,
installed
):
for
f
in
installed
.
split
():
for
f
in
installed
.
split
(
'
\
n
'
):
if
not
f
:
continue
f
=
self
.
_buildout_path
(
f
)
if
os
.
path
.
isdir
(
f
):
shutil
.
rmtree
(
f
)
...
...
src/zc/buildout/buildout.txt
View file @
7e5bdea9
...
...
@@ -14,9 +14,8 @@ This document describes how to define buildouts using buildout
configuration files and recipes. There are three ways to set up the
buildout software and create a buildout instance:
1. Install the zc.buildout egg with easy_install `easy_install
<http://peak.telecommunity.com/DevCenter/EasyInstall>`_ and use the
buildout script installed in a Python scripts area.
1. Install the zc.buildout egg with easy_install and use the buildout
script installed in a Python scripts area.
2. Use the buildout bootstrap script to create a buildout that
includes both the setuptools and zc.buildout eggs. This allows you
...
...
@@ -31,7 +30,7 @@ buildout software and create a buildout instance:
Often, a software project will be managed in a software repository,
such as a subversion repository, that includes some software source
directories, buildout configuration files, and a copy of the buildout
bootstrap script
,
To work on the project, one would check out the
bootstrap script
.
To work on the project, one would check out the
project from the repository and run the bootstrap script which
installs setuptools and zc.buildout into the checkout as well as any
parts defined.
...
...
@@ -92,14 +91,23 @@ A part is simply something to be created by a buildout. It can be
almost anything, such as a Python package, a program, a directory, or
even a configuration file.
Recipes
-------
A part is created by a recipe. Recipes are always installed as Python
eggs. They can be downloaded from a package server, such as the
Python Package Index, or they can be developed as part of a project.
Let's create a recipe as part of the sample project. We'll create a
recipe for creating directories.
Python Package Index, or they can be developed as part of a project
using a "develop" egg.
A develop egg is a special kind of egg that gets installed as an "egg
link" that contains the name of a source directory. Develop eggs
don't have to be packaged for distribution to be used and can be
modified in place, which is especially useful while they are being
developed.
First, we'll create a recipes directory for
our local recipes:
Let's create a recipe as part of the sample project. We'll create a
recipe for creating directories. First, we'll create a recipes source
directory for our local recipes:
>>> mkdir(sample_buildout, 'recipes')
...
...
@@ -128,56 +136,81 @@ and then we'll create a source file for our mkdir recipe:
...
... def install(self):
... path = self.options['path']
... if not os.path.isdir(path):
... logging.getLogger(self.name).info(
... 'Creating directory %s', os.path.basename(path))
... os.mkdir(path)
... logging.getLogger(self.name).info(
... 'Creating directory %s', os.path.basename(path))
... os.mkdir(path)
... return path
...
... def update(self):
... pass
... """)
The recipe defines a constructor that takes a buildout object, a part
name, and an options dictionary. It saves them in instance attributes.
Currently, recipes must define 3 methods [#future_recipe_methods]_:
If the path is relative, we'll interpret it as relative to the
buildout directory. The buildout object passed in is a mapping from
section name to a mapping of options for that section. The buildout
directory is available as the directory option of the buildout
section. We normalize the path and save it back into the options
directory.
- a constructor,
- an install method, and
Any time we use data from another section, it is important to reflect
that data in the recipe's options when the recipe is constructed.
- an update method.
The constructor is responsible for updating a parts options to reflect
data read from other sections. The buildout system keeps track of
whether a part specification has changed. A part specification has
changed if it's options, after ajusting for data read from other
sections, has changed, or if the recipe has changed. Only the options
for the part are considered. If data are read from other sections,
then that information has to be reflected in the parts options. In
the Mkdir example, the given path is interpreted relative to the
buildout directory, and data from the buildout directory is read. The
path option is updated to reflect this. If the directory option was
changed in the buildout sections, we would know to update parts
created using the mkdir recipe using relative path names.
When buildout is run, it saves configuration data for installed parts
in a file named
installed.cfg
. In subsequent runs, it compares
part-configuration data stored in the installed.cfg file and the
in a file named
".installed.cfg"
. In subsequent runs, it compares
part-configuration data stored in the
.
installed.cfg file and the
part-configuration data loaded from the configuration files as
modified by recipe constructors to decide if the configuration of a
part has changed. If the configuration has changed, or if the recipe
has changed, then the part is uninstalled
before reinstalling it
. The
has changed, then the part is uninstalled
and reinstalled
. The
buildout only looks at the part's options, so any data used to
configure the part needs to be reflected in the part's options. It is
the job of a recipe constructor to make sure that the options include
all rel
event data.
all relevent data.
Of course, parts are also uninstalled if they are no-longer used.
The install method is responsible for creating the part. In this
case, we need the path of the directory to create. We'll use a
path option from our options dictionary.
The install method logs what it's doing using the Python logging call.
The recipe defines a constructor that takes a buildout object, a part
name, and an options dictionary. It saves them in instance attributes.
If the path is relative, we'll interpret it as relative to the
buildout directory. The buildout object passed in is a mapping from
section name to a mapping of options for that section. The buildout
directory is available as the directory option of the buildout
section. We normalize the path and save it back into the options
directory.
We return the path that we installed. If the part is uninstalled or
reinstalled, then the path returned will be removed by the buildout
machinery. A recipe install method is expected to return None, a
string, or an iterable of strings containing paths to be removed if a
part is uninstalled. For most recipes, this is all of the uninstall
support needed. A recipe can provide custom uninstall support as will
be described later.
The install method is responsible for creating the part. In this
case, we need the path of the directory to create. We'll use a path
option from our options dictionary. The install method logs what it's
doing using the Python logging call. We return the path that we
installed. If the part is uninstalled or reinstalled, then the path
returned will be removed by the buildout machinery. A recipe install
method is expected to return a string, or an iterable of strings
containing paths to be removed if a part is uninstalled. For most
recipes, this is all of the uninstall support needed.
The update method is responsible for updating an already installed
part. An empty method is often provided, as in this example, if parts
can't be updated. An update method can return None, a string, or an
iterable of strings. If a string or iterable of strings is returned,
then the saved list of paths to be uninstalled is updated with the new
information.
We need to provide packaging information so that our recipe can be
installed as an egg. We need to define a setup script for this:
installed as a develop egg. The minimum information we need to specify
[#packaging_info]_ is a name. For recipes, we also need to define the
names of the recipe classes as entry points. Packaging information is
provided via a setup.py script:
>>> write(sample_buildout, 'recipes', 'setup.py',
... """
...
...
@@ -189,21 +222,11 @@ installed as an egg. We need to define a setup script for this:
... )
... """)
This setup script is incomplete. It doesn't describe what is to be
included in a distribution. This is fine if we never actually create
a distribution. If recipes are going to be used only internally in a
buildout, then we needn't include distribution information. If we
wanted to use the same recipes in multiple buildouts, then we'd need
to include proper distribution data. To find out more about creating
distributions, see the setuptools documentation.
Our setup script defines an entry point. Entry points provide
a way for an egg to define the services it provides. Here we've said
that we define a zc.buildout entry point named
default
. Recipe
that we define a zc.buildout entry point named
mkdir
. Recipe
classes must be exposed as entry points in the zc.buildout group. we
give entry points names within the group. The name "default" is
somewhat special because it allows a recipe to be referenced using a
package name without naming an entry point.
give entry points names within the group.
We also need a README.txt for our recipes to avoid an annoying warning
from distutils, on which setuptools and zc.buildout are based:
...
...
@@ -326,6 +349,15 @@ we'll see that the directory gets removed and recreated:
d parts
d recipes
If any of the files or directories created by a recipe are removed,
the part will be reinstalled:
>>> rmdir(sample_buildout, 'mydata')
>>> print system(buildout),
buildout: Develop: /sample-buildout/recipes/setup.py
buildout: Uninstalling data-dir
buildout: Installing data-dir
data-dir: Creating directory mydata
Error reporting
---------------
...
...
@@ -404,6 +436,9 @@ allow us to see interactions with the buildout:
... items.sort()
... for option, value in items:
... print option, value
... return ()
...
... update = install
... """)
In this example, we've used a simple base class that provides a
...
...
@@ -488,8 +523,8 @@ the buildout:
>>> print system(buildout),
buildout: Develop: /sample-buildout/recipes/setup.py
buildout:
Install
ing data-dir
buildout:
Install
ing debug
buildout:
Updat
ing data-dir
buildout:
Updat
ing debug
File 1 mydata/file
File 2 mydata/file.out
File 3 var/file3
...
...
@@ -799,7 +834,7 @@ Options can also be combined in the usual Unix way, as in:
>>> print system(buildout+' -vcother.cfg debug:op1=foo'),
buildout: Develop: /sample-buildout/recipes/setup.py
buildout:
Install
ing debug
buildout:
Updat
ing debug
name other
op1 foo
recipe recipes:debug
...
...
@@ -1000,8 +1035,8 @@ Now, if we run the buildout without the install command:
x 1
buildout: Installing d2
d2: Creating directory data2
buildout:
Install
ing d3
buildout:
Install
ing d4
buildout:
Updat
ing d3
buildout:
Updat
ing d4
We see the output of the debug recipe and that data2 was created. We
also see that d1 and d2 have gone away:
...
...
@@ -1346,3 +1381,13 @@ We see that out extension is loaded and executed:
ext ['buildout']
buildout: Develop: /sample-bootstrapped/demo/setup.py
.. [#future_recipe_methods] In the future, additional mathods may be
added. Older recipes with fewer methods will still be
supported.
.. [#packaging_info] If we wanted to create a distribution from this
package, we would need specify much more information. See the
`setuptools documentation
<http://peak.telecommunity.com/DevCenter/setuptools>`_.
src/zc/buildout/tests.py
View file @
7e5bdea9
...
...
@@ -178,6 +178,8 @@ def test_comparing_saved_options_with_funny_characters():
... def install(self):
... open('t', 'w').write('t')
... return 't'
...
... update = install
... ''')
...
...
@@ -214,7 +216,7 @@ uninstalling anything because the configuration hasn't changed.
>>> print system(buildout), # doctest: +ELLIPSIS
buildout: Develop: ...setup.py
buildout:
Install
ing debug
buildout:
Updat
ing debug
"""
...
...
@@ -277,22 +279,22 @@ Options:
<BLANKLINE>
-q
<BLANKLINE>
Dec
creaa
e the level of verbosity. This option can be used multiple times.
Dec
reas
e the level of verbosity. This option can be used multiple times.
<BLANKLINE>
-c config_file
<BLANKLINE>
Specify the path to the buildout configuration file to be used.
This defaults to the file named"buildout.cfg" in the current
working directory.
This defaults to the file named
"buildout.cfg" in the current
working directory.
<BLANKLINE>
Assignments are of the form: section:option=value and are used to
provide configuration options that override those give
m
in the
provide configuration options that override those give
n
in the
configuration file. For example, to run the buildout in offline mode,
use buildout:offline=true.
<BLANKLINE>
Options and assignments can be interspersed.
<BLANKLINE>
Comm
mo
nds:
Comm
a
nds:
<BLANKLINE>
install [parts]
<BLANKLINE>
...
...
@@ -324,22 +326,22 @@ Options:
<BLANKLINE>
-q
<BLANKLINE>
Dec
creaa
e the level of verbosity. This option can be used multiple times.
Dec
reas
e the level of verbosity. This option can be used multiple times.
<BLANKLINE>
-c config_file
<BLANKLINE>
Specify the path to the buildout configuration file to be used.
This defaults to the file named"buildout.cfg" in the current
working directory.
This defaults to the file named
"buildout.cfg" in the current
working directory.
<BLANKLINE>
Assignments are of the form: section:option=value and are used to
provide configuration options that override those give
m
in the
provide configuration options that override those give
n
in the
configuration file. For example, to run the buildout in offline mode,
use buildout:offline=true.
<BLANKLINE>
Options and assignments can be interspersed.
<BLANKLINE>
Comm
mo
nds:
Comm
a
nds:
<BLANKLINE>
install [parts]
<BLANKLINE>
...
...
src/zc/buildout/update.txt
View file @
7e5bdea9
...
...
@@ -44,6 +44,7 @@ zc.buildout used:
... for project in 'zc.buildout', 'setuptools':
... req = pkg_resources.Requirement.parse(project)
... print project, pkg_resources.working_set.find(req).version
... return ()
... """)
...
...
zc.recipe.egg_/CHANGES.txt
View file @
7e5bdea9
...
...
@@ -8,6 +8,8 @@ To do
Change History
**************
Updated to work with zc.buildout 1.0.0b10.
1.0.0b1
=======
...
...
zc.recipe.egg_/src/zc/recipe/egg/api.txt
View file @
7e5bdea9
...
...
@@ -38,6 +38,9 @@ around the egg recipe:
... for d in ws:
... print d
... print 'extra paths:', self.egg.extra_paths
... return ()
...
... update = install
... """)
Here we instantiated the egg recipe in the constructor, saving it in
...
...
zc.recipe.egg_/src/zc/recipe/egg/custom.py
View file @
7e5bdea9
...
...
@@ -67,7 +67,7 @@ class Custom:
def
install
(
self
):
if
self
.
buildout
[
'buildout'
].
get
(
'offline'
)
==
'true'
:
return
return
()
options
=
self
.
options
distribution
=
options
.
get
(
'eggs'
,
self
.
name
).
strip
()
build_ext
=
dict
([
...
...
@@ -80,3 +80,6 @@ class Custom:
self
.
links
,
self
.
index
,
options
[
'executable'
],
[
options
[
'_e'
]],
)
return
()
update
=
install
zc.recipe.egg_/src/zc/recipe/egg/egg.py
View file @
7e5bdea9
...
...
@@ -119,3 +119,6 @@ class Egg:
interpreter
=
options
.
get
(
'interpreter'
),
)
return
()
update
=
install
zc.recipe.testrunner/CHANGES.txt
View file @
7e5bdea9
...
...
@@ -2,6 +2,8 @@
Change History
**************
Updated to work with zc.buildout 1.0.0b10.
1.0.0b2
=======
...
...
zc.recipe.testrunner/src/zc/recipe/testrunner/__init__.py
View file @
7e5bdea9
...
...
@@ -54,6 +54,8 @@ class TestRunner:
)),
)
update
=
install
arg_template
=
"""[
'--test-path', %(TESTPATH)s,
]"""
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment