Moved setting of run-time variables from Env.__init__() to Env._bootstrap()

This commit is contained in:
Jason Gerard DeRose
2008-12-22 23:09:35 -07:00
parent 01cae56e0a
commit fd43b39145
5 changed files with 57 additions and 55 deletions

View File

@@ -685,41 +685,40 @@ is configured.
Environment variables
---------------------
Plugins access various environment variables and run-time information through
``self.api.env`` (for convenience, ``self.env`` is equivalent).
Plugins access configuration variables and run-time information through
``self.api.env`` (or for convenience, ``self.env`` is equivalent). This
attribute is a refences to the `ipalib.config.Env` instance created in
`plugable.API.__init__()`.
When you create a fresh `plugable.API` instance, its ``env`` attribute is
likewise a freshly created `config.Env` instance, which will already be
populated with certain run-time information. For example:
After `API.bootstrap()` has been called, the `Env` instance will be populated
with all the environment information used by the built-in plugins.
This will be called before any plugins are registered, so plugin authors can
assume these variables will all exist by the time the module containing their
plugin (or plugins) is imported. For example:
>>> api = create_api()
>>> list(api.env)
['bin', 'dot_ipa', 'home', 'ipalib', 'mode', 'script', 'site_packages']
Here is a quick overview of the run-time information:
============= ================================ =======================
Key Source or example value Description
============= ================================ =======================
bin /usr/bin Dir. containing script
dot_ipa ~/.ipa User config directory
home os.environ['HOME'] User home dir.
ipalib .../site-packages/ipalib Dir. of ipalib package
mode 'production' or 'unit_test' The mode ipalib is in
script sys.argv[0] Path of script
site_packages /usr/lib/python2.5/site-packages Dir. containing ipalib/
============= ================================ =======================
After `plugable.API.bootstrap()` has been called, the env instance will be
populated with all the environment information used by the built-in plugins.
This will typically be called before any plugins are registered. For example:
>>> len(api.env)
7
1
>>> api.bootstrap(in_server=True) # We want to execute, not forward
>>> len(api.env)
35
`Env._bootstrap()`, which is called by `API.bootstrap()`, will create several
run-time variables that connot be overriden in configuration files or through
command-line options. Here is an overview of this run-time information:
============= ============================= =======================
Key Example value Description
============= ============================= =======================
bin '/usr/bin' Dir. containing script
dot_ipa '/home/jderose/.ipa' User config directory
home os.environ['HOME'] User home dir.
ipalib '.../site-packages/ipalib' Dir. of ipalib package
mode 'unit_test' The mode ipalib is in
script sys.argv[0] Path of script
site_packages '.../python2.5/site-packages' Dir. containing ipalib/
============= ============================= =======================
If your plugin requires new environment variables *and* will be included in
the freeIPA built-in plugins, you should add the defaults for your variables
in `ipalib.constants.DEFAULT_CONFIG`. Also, you should consider whether your

View File

@@ -62,15 +62,18 @@ class Env(object):
The variable values can be ``str`` or ``int`` instances, or the ``True``,
``False``, or ``None`` constants. When the value provided is an ``str``
instance, some limited automatic type conversion is performed, which allows
values of specific types to be set easily from configuration files and from
values of specific types to be set easily from configuration files or
command-line options.
The ``True``, ``False``, and ``None`` constants can be specified with a
string that matches what ``repr()`` would return. For example:
>>> env.true = 'True'
>>> env.true = True
>>> env.also_true = 'True'
>>> env.true
True
>>> env.also_true
True
Note that the automatic type conversion is case sensitive. For example:
@@ -98,14 +101,14 @@ class Env(object):
>>> env.actually_false
False
`Env` is set-once, first-one-wins. Once a variable has been set, trying to
override it will raise an ``AttributeError``. For example:
`Env` variables are all set-once (first-one-wins). Once a variable has been
set, trying to override it will raise an ``AttributeError``. For example:
>>> env.my_var = 'first'
>>> env.my_var = 'second'
>>> env.date = 'First'
>>> env.date = 'Second'
Traceback (most recent call last):
...
AttributeError: cannot override Env.my_var value 'first' with 'second'
AttributeError: cannot override Env.date value 'First' with 'Second'
An `Env` instance can also be *locked*, after which no further variables can
be set. Trying to set variables on a locked `Env` instance will also raise
@@ -127,12 +130,6 @@ class Env(object):
def __init__(self):
object.__setattr__(self, '_Env__d', {})
object.__setattr__(self, '_Env__done', set())
self.ipalib = path.dirname(path.abspath(__file__))
self.site_packages = path.dirname(self.ipalib)
self.script = path.abspath(sys.argv[0])
self.bin = path.dirname(self.script)
self.home = path.abspath(os.environ['HOME'])
self.dot_ipa = path.join(self.home, '.ipa')
def __setattr__(self, name, value):
"""
@@ -211,6 +208,15 @@ class Env(object):
and the location of the configuration file.
"""
self.__doing('_bootstrap')
# Set run-time variables:
self.ipalib = path.dirname(path.abspath(__file__))
self.site_packages = path.dirname(self.ipalib)
self.script = path.abspath(sys.argv[0])
self.bin = path.dirname(self.script)
self.home = path.abspath(os.environ['HOME'])
self.dot_ipa = path.join(self.home, '.ipa')
for (key, value) in overrides.iteritems():
self[key] = value
if 'in_tree' not in self:

View File

@@ -10,7 +10,7 @@ do
if [[ -f $executable ]]; then
echo "[ $name: Starting tests... ]"
((runs += 1))
if $executable /usr/bin/nosetests -v --with-doctest --stop
if $executable /usr/bin/nosetests -v --with-doctest
then
echo "[ $name: Tests OK ]"
else

View File

@@ -147,13 +147,9 @@ class test_Env(ClassChecker):
Test the `ipalib.config.Env.__init__` method.
"""
(o, home) = self.new()
ipalib = path.dirname(path.abspath(config.__file__))
assert o.ipalib == ipalib
assert o.site_packages == path.dirname(ipalib)
assert o.script == path.abspath(sys.argv[0])
assert o.bin == path.dirname(path.abspath(sys.argv[0]))
assert o.home == home.path
assert o.dot_ipa == home.join('.ipa')
assert list(o) == []
assert len(o) == 0
assert o.__islocked__() is False
def test_setattr(self):
"""
@@ -246,10 +242,14 @@ class test_Env(ClassChecker):
"""
# Test defaults created by _bootstrap():
(o, home) = self.new()
assert 'in_tree' not in o
assert 'context' not in o
assert 'conf' not in o
o._bootstrap()
ipalib = path.dirname(path.abspath(config.__file__))
assert o.ipalib == ipalib
assert o.site_packages == path.dirname(ipalib)
assert o.script == path.abspath(sys.argv[0])
assert o.bin == path.dirname(path.abspath(sys.argv[0]))
assert o.home == home.path
assert o.dot_ipa == home.join('.ipa')
assert o.in_tree is False
assert o.context == 'default'
assert o.conf == '/etc/ipa/default.conf'
@@ -422,6 +422,7 @@ class test_Env(ClassChecker):
no_exist = tmp.join('no_exist.conf')
assert not path.exists(no_exist)
o = self.cls()
o._bootstrap()
keys = tuple(o)
orig = dict((k, o[k]) for k in o)
assert o._merge_config(no_exist) is None

View File

@@ -84,10 +84,6 @@ class TempHome(TempDir):
self.__home = os.environ['HOME']
os.environ['HOME'] = self.path
def rmtree(self):
os.environ['HOME'] = self.__home
super(TempHome, self).rmtree()
class ExceptionNotRaised(Exception):
"""