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
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Łukasz Nowak
slapos.buildout
Commits
defdcec1
Commit
defdcec1
authored
Jun 17, 2006
by
Jim Fulton
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added logging support.
parent
eb311a70
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
242 additions
and
54 deletions
+242
-54
src/zc/buildout/buildout.py
src/zc/buildout/buildout.py
+93
-27
src/zc/buildout/buildout.txt
src/zc/buildout/buildout.txt
+149
-25
todo.txt
todo.txt
+0
-2
No files found.
src/zc/buildout/buildout.py
View file @
defdcec1
...
...
@@ -16,6 +16,7 @@
$Id$
"""
import
logging
import
md5
import
os
import
pprint
...
...
@@ -64,15 +65,17 @@ class Buildout(dict):
super
(
Buildout
,
self
).
__init__
()
# default options
data
=
dict
(
buildout
=
{
'directory'
:
os
.
path
.
dirname
(
config_file
),
'eggs-directory'
:
'eggs'
,
'bin-directory'
:
'bin'
,
'parts-directory'
:
'parts'
,
'installed'
:
'.installed.cfg'
,
'python'
:
'buildout'
,
'executable'
:
sys
.
executable
,
},
)
data
=
dict
(
buildout
=
{
'directory'
:
os
.
path
.
dirname
(
config_file
),
'eggs-directory'
:
'eggs'
,
'bin-directory'
:
'bin'
,
'parts-directory'
:
'parts'
,
'installed'
:
'.installed.cfg'
,
'python'
:
'buildout'
,
'executable'
:
sys
.
executable
,
'log-level'
:
'WARNING'
,
'log-format'
:
'%(name)s: %(message)s'
,
})
# load user defaults, which override defaults
if
'HOME'
in
os
.
environ
:
...
...
@@ -116,8 +119,6 @@ class Buildout(dict):
for
name
in
(
'bin'
,
'parts'
,
'eggs'
):
d
=
self
.
_buildout_path
(
options
[
name
+
'-directory'
])
options
[
name
+
'-directory'
]
=
d
if
not
os
.
path
.
exists
(
d
):
os
.
mkdir
(
d
)
options
[
'installed'
]
=
os
.
path
.
join
(
options
[
'directory'
],
options
[
'installed'
])
...
...
@@ -163,6 +164,15 @@ class Buildout(dict):
return
os
.
path
.
join
(
self
.
_buildout_dir
,
*
names
)
def
install
(
self
,
install_parts
):
# Create buildout directories
for
name
in
(
'bin'
,
'parts'
,
'eggs'
):
d
=
self
[
'buildout'
][
name
+
'-directory'
]
if
not
os
.
path
.
exists
(
d
):
self
.
_logger
.
info
(
'Creating directory %s'
,
d
)
os
.
mkdir
(
d
)
# Build develop eggs
self
.
_develop
()
# load installed data
...
...
@@ -181,7 +191,7 @@ class Buildout(dict):
if
install_parts
:
extra
=
[
p
for
p
in
install_parts
if
p
not
in
conf_parts
]
if
extra
:
error
(
'Invalid install parts:'
,
*
extra
)
self
.
_
error
(
'Invalid install parts:'
,
*
extra
)
uninstall_missing
=
False
else
:
install_parts
=
conf_parts
...
...
@@ -206,12 +216,14 @@ class Buildout(dict):
continue
# ununstall part
self
.
_logger
.
info
(
'Uninstalling %s'
,
part
)
self
.
_uninstall
(
installed_part_options
[
part
][
'__buildout_installed__'
])
installed_parts
=
[
p
for
p
in
installed_parts
if
p
!=
part
]
# 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
()
...
...
@@ -241,7 +253,7 @@ class Buildout(dict):
setup
=
self
.
_buildout_path
(
setup
)
if
os
.
path
.
isdir
(
setup
):
setup
=
os
.
path
.
join
(
setup
,
'setup.py'
)
self
.
_logger
.
info
(
"Running %s -q develop ..."
,
setup
)
os
.
chdir
(
os
.
path
.
dirname
(
setup
))
os
.
spawnle
(
os
.
P_WAIT
,
sys
.
executable
,
sys
.
executable
,
...
...
@@ -348,6 +360,33 @@ class Buildout(dict):
print
>>
f
_save_options
(
part
,
installed_options
[
part
],
f
)
f
.
close
()
def
_error
(
self
,
message
,
*
args
,
**
kw
):
self
.
_logger
.
error
(
message
,
*
args
,
**
kw
)
sys
.
exit
(
1
)
def
_setup_logging
(
self
):
root_logger
=
logging
.
getLogger
()
handler
=
logging
.
StreamHandler
(
sys
.
stdout
)
handler
.
setFormatter
(
logging
.
Formatter
(
self
[
'buildout'
][
'log-format'
]))
root_logger
.
addHandler
(
handler
)
self
.
_logger
=
logging
.
getLogger
(
'buildout'
)
level
=
self
[
'buildout'
][
'log-level'
]
if
level
in
(
'DEBUG'
,
'INFO'
,
'WARNING'
,
'ERROR'
,
'CRITICAL'
):
level
=
getattr
(
logging
,
level
)
else
:
try
:
level
=
int
(
level
)
except
ValueError
:
self
.
_error
(
"Invalid logging level %s"
,
level
)
verbosity
=
self
[
'buildout'
].
get
(
'verbosity'
,
0
)
try
:
verbosity
=
int
(
verbosity
)
except
ValueError
:
self
.
_error
(
"Invalid verbosity %s"
,
verbosity
)
root_logger
.
setLevel
(
level
-
verbosity
)
def
_save_options
(
section
,
options
,
f
):
print
>>
f
,
'[%s]'
%
section
...
...
@@ -435,23 +474,47 @@ def _error(*message):
def
main
(
args
=
None
):
if
args
is
None
:
args
=
sys
.
argv
[
1
:]
if
args
and
args
[
0
]
==
'-c'
:
args
.
pop
(
0
)
if
not
args
:
_error
(
"No configuration file specified,"
)
config_file
=
args
.
pop
(
0
)
else
:
config_file
=
'buildout.cfg'
config_file
=
'buildout.cfg'
verbosity
=
0
options
=
[]
while
args
and
'='
in
args
[
0
]:
option
,
value
=
args
.
pop
(
0
).
split
(
'='
,
1
)
if
len
(
option
.
split
(
':'
))
!=
2
:
_error
(
'Invalid option:'
,
option
)
section
,
option
=
option
.
split
(
':'
)
options
.
append
((
section
.
strip
(),
option
.
strip
(),
value
.
strip
()))
while
args
:
if
args
[
0
][
0
]
==
'-'
:
op
=
orig_op
=
args
.
pop
(
0
)
op
=
op
[
1
:]
while
op
and
op
[
0
]
in
'vq'
:
if
op
[
0
]
==
'v'
:
verbosity
+=
10
else
:
verbosity
-=
10
op
=
op
[
1
:]
if
op
[:
1
]
==
'c'
:
op
=
op
[
1
:]
if
op
:
config_file
=
op
else
:
if
args
:
config_file
=
args
.
pop
(
0
)
else
:
_error
(
"No file name specified for option"
,
orig_op
)
elif
op
:
_error
(
"Invalid option"
,
'-'
+
op
[
0
])
elif
'='
in
args
[
0
]:
option
,
value
=
args
.
pop
(
0
).
split
(
'='
,
1
)
if
len
(
option
.
split
(
':'
))
!=
2
:
_error
(
'Invalid option:'
,
option
)
section
,
option
=
option
.
split
(
':'
)
options
.
append
((
section
.
strip
(),
option
.
strip
(),
value
.
strip
()))
else
:
# We've run out of command-line options and option assignnemnts
# The rest should be commands, so we'll stop here
break
if
verbosity
:
options
.
append
((
'buildout'
,
'verbosity'
,
str
(
verbosity
)))
buildout
=
Buildout
(
config_file
,
options
)
buildout
.
_setup_logging
()
if
args
:
command
=
args
.
pop
(
0
)
...
...
@@ -460,7 +523,10 @@ def main(args=None):
else
:
command
=
'install'
getattr
(
buildout
,
command
)(
args
)
try
:
getattr
(
buildout
,
command
)(
args
)
finally
:
logging
.
shutdown
()
if
sys
.
version_info
[:
2
]
<
(
2
,
4
):
def
reversed
(
iterable
):
...
...
src/zc/buildout/buildout.txt
View file @
defdcec1
...
...
@@ -102,7 +102,7 @@ and then we'll create a source file for our mkdir recipe:
>>> write(sample_buildout, 'recipes', 'mkdir.py',
... """
... import os
... import
logging,
os
...
... class Mkdir:
...
...
...
@@ -118,7 +118,8 @@ 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):
... print 'Creating directory', os.path.basename(path)
... logging.getLogger(self.name).info(
... 'Creating directory %s', os.path.basename(path))
... os.mkdir(path)
... return path
... """)
...
...
@@ -151,8 +152,7 @@ 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.
We made the method chatty so that we can observe what it's doing.
XXX use python logging module!
The install method logs what it's doing using the Python logging call.
We return the path that we installed. If the part is unistalled or
reinstalled, then the path returned will be removed by the buildout
...
...
@@ -203,6 +203,7 @@ Now let's update our buildout.cfg:
... [buildout]
... develop = recipes
... parts = data_dir
... log-level = INFO
...
... [data_dir]
... recipe = recipes:mkdir
...
...
@@ -230,6 +231,14 @@ Here we've named a part to be "built". We can use any name we want
except that different part names must be unique and recipes will often
use the part name to decide what to do.
::
log-level = INFO
The default level is WARNING, which is fairly quite. In this example,
we set the level to INFO so we can see more details about what the
buildout and recipes are doing.
::
[data_dir]
...
...
@@ -247,7 +256,9 @@ buildout:
>>> import os
>>> os.chdir(sample_buildout)
>>> print system(os.path.join(sample_buildout, 'bin', 'buildout')),
Creating directory mystuff
buildout: Running /tmp/sample-buildout/recipes/setup.py -q develop ...
buildout: Installing data_dir
data_dir: Creating directory mystuff
We see that the recipe created the directory, as expected:
...
...
@@ -285,6 +296,7 @@ we'll see that the directory gets removed and recreated:
... [buildout]
... develop = recipes
... parts = data_dir
... log-level = INFO
...
... [data_dir]
... recipe = recipes:mkdir
...
...
@@ -292,7 +304,10 @@ we'll see that the directory gets removed and recreated:
... """)
>>> print system(os.path.join(sample_buildout, 'bin', 'buildout')),
Creating directory mydata
buildout: Running /tmp/sample-buildout/recipes/setup.py -q develop ...
buildout: Uninstalling data_dir
buildout: Installing data_dir
data_dir: Creating directory mydata
>>> ls(sample_buildout)
- .installed.cfg
...
...
@@ -358,6 +373,7 @@ examples:
... [buildout]
... develop = recipes
... parts = data_dir debug
... log-level = INFO
...
... [debug]
... recipe = recipes:debug
...
...
@@ -387,7 +403,11 @@ Now, if we run the buildout, we'll see the options with the values
substituted.
>>> print system(os.path.join(sample_buildout, 'bin', 'buildout')),
Creating directory mydata
buildout: Running /tmp/sample-buildout/recipes/setup.py -q develop ...
buildout: Uninstalling data_dir
buildout: Installing data_dir
data_dir: Creating directory mydata
buildout: Installing debug
base var
file1 mydata/file
file2 mydata/file.out
...
...
@@ -401,6 +421,9 @@ recipe, so it assumed it could and reinstalled mydata. If we rerun
the buildout:
>>> print system(os.path.join(sample_buildout, 'bin', 'buildout')),
buildout: Running /tmp/sample-buildout/recipes/setup.py -q develop ...
buildout: Installing data_dir
buildout: Installing debug
base var
file1 mydata/file
file2 mydata/file.out
...
...
@@ -409,6 +432,9 @@ the buildout:
We can see that mydata was not recreated.
Note that, in this vase, we didn't specify a log level, so
we didn't get output about what the buildout was doing.
Multiple configuration files
----------------------------
...
...
@@ -615,14 +641,23 @@ Command-line usage
A number of arguments can be given on the buildout command line. The
command usage is::
buildout [-c file] [
option
s] [command [command arguments]]
buildout [-c file] [
-q] [-v] [assignment
s] [command [command arguments]]
The -c option can be used to specify a configuration file, rather than
buildout.cfg in the current durectory. Options are of the form::
buildout.cfg in the current durectory.
The -q and -v decrement and incremement the verbosity by 10. The
verbosity is used to adjust the logging level. The verbosity is
subtracted from the numeric value of the log-level option specified in
the configuration file.
Assignments are of the form::
section_name:option_name=value
for example:
Options and assignments can be given in any order.
Here's an example:
>>> write(sample_buildout, 'other.cfg',
... """
...
...
@@ -640,12 +675,33 @@ Note that we used the installed buildout option to specify an
alternate file to store information about installed parts.
>>> print system(os.path.join(sample_buildout, 'bin', 'buildout')
... + ' -c other.cfg debug:op1=foo'),
... + ' -c other.cfg debug:op1=foo -v'),
buildout: Running /tmp/sample-buildout/recipes/setup.py -q develop ...
buildout: Installing debug
name other
op1 foo
op7 7
recipe recipes:debug
Here we used the -c option to specify an alternate configuration file,
and the -v option to increase the level of logging from the default,
WARNING.
Options can also be combined in the usual Unix way, as in:
>>> print system(os.path.join(sample_buildout, 'bin', 'buildout')
... + ' -vcother.cfg debug:op1=foo'),
buildout: Running /tmp/sample-buildout/recipes/setup.py -q develop ...
buildout: Installing debug
name other
op1 foo
op7 7
recipe recipes:debug
Here we combined the -v and -c options with the configuration file
name. Note that the -c option has to be last, because it takes an
argument.
>>> os.remove(os.path.join(sample_buildout, 'other.cfg'))
>>> os.remove(os.path.join(sample_buildout, '.other.cfg'))
...
...
@@ -677,13 +733,19 @@ the buildout in the usual way:
... recipe = recipes:debug
... """)
>>> print system(os.path.join(sample_buildout, 'bin', 'buildout')),
>>> print system(os.path.join(sample_buildout, 'bin', 'buildout') + ' -v'),
buildout: Running /sample-buildout/recipes/setup.py -q develop ...
buildout: Uninstalling debug
buildout: Installing debug
op1 1
op7 7
recipe recipes:debug
Creating directory d1
Creating directory d2
Creating directory d3
buildout: Installing d1
d1: Creating directory d1
buildout: Installing d2
d2: Creating directory d2
buildout: Installing d3
d3: Creating directory d3
>>> ls(sample_buildout)
- .installed.cfg
...
...
@@ -756,10 +818,14 @@ Now we'll update our configuration file:
and run the buildout specifying just d2 and d3:
>>> print system(os.path.join(sample_buildout, 'bin', 'buildout')
>>> print system(os.path.join(sample_buildout, 'bin', 'buildout'
+ ' -v'
)
... + ' install d3 d4'),
Creating directory data3
Creating directory data4
buildout: Running /sample-buildout/recipes/setup.py -q develop ...
buildout: Uninstalling d3
buildout: Installing d3
d3: Creating directory data3
buildout: Installing d4
d4: Creating directory data4
>>> ls(sample_buildout)
- .installed.cfg
...
...
@@ -821,14 +887,22 @@ Note that the installed data for debug, d1, and d2 haven't changed,
because we didn't install those parts and that the d1 and d2
directories are still there.
Now, if we run the buildout without
arguments
:
Now, if we run the buildout without
the install command
:
>>> print system(os.path.join(sample_buildout, 'bin', 'buildout')),
>>> print system(os.path.join(sample_buildout, 'bin', 'buildout') + ' -v'),
buildout: Running /sample-buildout/recipes/setup.py -q develop ...
buildout: Uninstalling d1
buildout: Uninstalling d2
buildout: Uninstalling debug
buildout: Installing debug
op1 1
op7 7
recipe recipes:debug
x 1
Creating directory data2
buildout: Installing d2
d2: Creating directory data2
buildout: Installing d3
buildout: Installing d4
We see the output of the debug recipe and that data2 was created. We
also see that d1 and d2 have gone away:
...
...
@@ -855,7 +929,7 @@ The buildout normally puts the bin, eggs, and parts directories in the
directory in the directory containing the configuration file. You can
provide alternate locations, and even names for these directories.
>>> alt = tempfile.mkdtemp()
>>> alt = tempfile.mkdtemp(
'sample-alt'
)
>>> write(sample_buildout, 'buildout.cfg',
... """
...
...
@@ -871,7 +945,15 @@ provide alternate locations, and even names for these directories.
... work = os.path.join(alt, 'work'),
... ))
>>> print system(os.path.join(sample_buildout, 'bin', 'buildout')),
>>> print system(os.path.join(sample_buildout, 'bin', 'buildout') + ' -v'),
buildout: Creating directory /tmp/sample-alt/scripts
buildout: Creating directory /tmp/sample-alt/work
buildout: Creating directory /tmp/sample-alt/basket
buildout: Running /tmp/sample-buildout/recipes/setup.py -q develop ...
buildout: Uninstalling d4
buildout: Uninstalling d3
buildout: Uninstalling d2
buildout: Uninstalling debug
>>> ls(alt)
d basket
...
...
@@ -886,7 +968,7 @@ provide alternate locations, and even names for these directories.
You can also specify an alternate buildout directory:
>>> alt = tempfile.mkdtemp()
>>> alt = tempfile.mkdtemp(
'sample-alt'
)
>>> write(sample_buildout, 'buildout.cfg',
... """
...
...
@@ -899,7 +981,11 @@ You can also specify an alternate buildout directory:
... recipes=os.path.join(sample_buildout, 'recipes'),
... ))
>>> print system(os.path.join(sample_buildout, 'bin', 'buildout')),
>>> print system(os.path.join(sample_buildout, 'bin', 'buildout') + ' -v'),
buildout: Creating directory /tmp/sample-alt/bin
buildout: Creating directory /tmp/sample-alt/parts
buildout: Creating directory /tmp/sample-alt/eggs
buildout: Running /tmp/sample-buildout/recipes/setup.py -q develop ...
>>> ls(alt)
- .installed.cfg
...
...
@@ -912,3 +998,41 @@ You can also specify an alternate buildout directory:
>>> import shutil
>>> shutil.rmtree(alt)
Logging control
---------------
Three buildout options are used to control logging:
log-level
specifies the log level
verbosity
adjusts the log level
log-format
allows an alternate logging for mat to be specified
We've already seen the log level and verbosity. Let's look at an example
of changing the format:
>>> write(sample_buildout, 'buildout.cfg',
... """
... [buildout]
... develop = recipes
... parts =
... log-level = 25
... verbosity = 5
... log-format = %%(levelname)s %%(message)s
... """)
Here, we've changed the format to include the log-level name, rather
than the logger name.
We've also illustrated, with a contrived example, that the log level
can be a numeric value and that the verbosity can be specified in the
configuration file. Because the verbosoty is subtracted from the log
level, we get a final log level of 20, which is the INFO level.
>>> print system(os.path.join(sample_buildout, 'bin', 'buildout')),
INFO Running /tmp/sample-buildout/recipes/setup.py -q develop ...
todo.txt
View file @
defdcec1
...
...
@@ -24,8 +24,6 @@
- Local download cache
- Logging
- Some way to freeze versions so we can have reproducable buildouts.
- Part dependencies
...
...
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