summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ipalib/base.py7
-rw-r--r--ipalib/config.py50
-rw-r--r--tests/test_ipalib/test_base.py7
3 files changed, 44 insertions, 20 deletions
diff --git a/ipalib/base.py b/ipalib/base.py
index 2d80a0778..1651b01d1 100644
--- a/ipalib/base.py
+++ b/ipalib/base.py
@@ -36,9 +36,10 @@ class ReadOnly(object):
The point of this class is not to make it impossible to set or to delete
attributes after an instance is locked, but to make it impossible to do so
- *accidentally*. Rather than simply telling our programmers something like,
- "Don't set any attributes on this ``FooBar`` instance because doing so wont
- be thread-safe", this class gives us a way to enforce it.
+ *accidentally*. Rather than constantly reminding our programmers of things
+ like, for example, "Don't set any attributes on this ``FooBar`` instance
+ because doing so wont be thread-safe", this class offers a real way to
+ enforce read-only attribute usage.
For example, before a `ReadOnly` instance is locked, you can set and delete
its attributes as normal:
diff --git a/ipalib/config.py b/ipalib/config.py
index c3c3a95ce..84c0aab4c 100644
--- a/ipalib/config.py
+++ b/ipalib/config.py
@@ -18,11 +18,14 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
"""
-Basic configuration management.
+Process-wide static configuration and environment.
-This module handles the reading and representation of basic local settings.
-It will also take care of settings that can be discovered by different
-methods, such as DNS.
+The standard run-time instance of the `Env` class is initialized early in the
+`ipalib` process and is then locked into a read-only state, after which no
+further changes can be made to the environment throughout the remaining life
+of the process.
+
+For the per-request thread-local information, see `ipalib.request`.
"""
from ConfigParser import RawConfigParser, ParsingError
@@ -288,6 +291,8 @@ class Env(object):
(0, 3)
Also see `Env._merge_from_file()`.
+
+ :param kw: Variables provides as keyword arguments.
"""
i = 0
for (key, value) in kw.iteritems():
@@ -311,8 +316,23 @@ class Env(object):
containing first the number of variables that were actually set, and
second the total number of variables found in ``config_file``.
+ This method will raise a ``ValueError`` if ``config_file`` is not an
+ absolute path. For example:
+
+ >>> env = Env()
+ >>> env._merge_from_file('my/config.conf')
+ Traceback (most recent call last):
+ ...
+ ValueError: config_file must be an absolute path; got 'my/config.conf'
+
Also see `Env._merge()`.
+
+ :param config_file: Absolute path of the configuration file to load.
"""
+ if path.abspath(config_file) != config_file:
+ raise ValueError(
+ 'config_file must be an absolute path; got %r' % config_file
+ )
if not path.isfile(config_file):
return
parser = RawConfigParser()
@@ -361,8 +381,8 @@ class Env(object):
`Env._merge()`. The intended use of ``overrides`` is to merge-in
variables specified on the command-line.
- 3. Intelligently fill-in the ``in_tree``, ``context``, ``conf``,
- and ``conf_default`` variables if they haven`t been set already.
+ 3. Intelligently fill-in the *in_tree*, *context*, *conf*, and
+ *conf_default* variables if they haven`t been set already.
Also see `Env._finalize_core()`, the next method in the bootstrap
sequence.
@@ -413,22 +433,24 @@ class Env(object):
``self.conf_default`` (if it exists) by calling
`Env._merge_from_file()`.
- 4. Intelligently fill-in the ``in_server`` and ``log`` variables
+ 4. Intelligently fill-in the *in_server* and *log* variables
if they haven't already been set.
- 5. Merge in the internal defaults by calling `Env._merge()`. In
- normal circumstances, these internal defaults will simply be
- those specified in `constants.DEFAULT_CONFIG`.
+ 5. Merge-in the variables in ``defaults`` by calling `Env._merge()`.
+ In normal circumstances ``defaults`` will simply be those
+ specified in `constants.DEFAULT_CONFIG`.
- After this method is called, the all environment variables
- used by all the built-in plugins will be available. As such, this
- method should be called *before* any plugins are loaded.
+ After this method is called, all the environment variables used by all
+ the built-in plugins will be available. As such, this method should be
+ called *before* any plugins are loaded.
After this method has finished, the `Env` instance is still writable
so that 3rd-party plugins can set variables they may require as the
plugins are registered.
Also see `Env._finalize()`, the final method in the bootstrap sequence.
+
+ :param defaults: Internal defaults for all built-in variables.
"""
self.__doing('_finalize_core')
self.__do_if_not_done('_bootstrap')
@@ -464,6 +486,8 @@ class Env(object):
This method should be called after all plugins have been loaded and
after `plugable.API.finalize()` has been called.
+
+ :param lastchance: Any final variables to merge-in before locking.
"""
self.__doing('_finalize')
self.__do_if_not_done('_finalize_core')
diff --git a/tests/test_ipalib/test_base.py b/tests/test_ipalib/test_base.py
index 9feac6acf..49d5f39df 100644
--- a/tests/test_ipalib/test_base.py
+++ b/tests/test_ipalib/test_base.py
@@ -22,7 +22,7 @@ Test the `ipalib.base` module.
"""
from tests.util import ClassChecker, raises
-from ipalib.constants import NAME_REGEX
+from ipalib.constants import NAME_REGEX, NAME_ERROR
from ipalib.constants import TYPE_ERROR, SET_ERROR, DEL_ERROR
from ipalib import base
@@ -107,10 +107,9 @@ def test_check_name():
assert name is f(name)
e = raises(TypeError, f, unicode(name))
assert str(e) == TYPE_ERROR % ('name', str, unicode(name), unicode)
- error = 'name must match %r; got %r'
for name in nope:
e = raises(ValueError, f, name)
- assert str(e) == error % (NAME_REGEX, name)
+ assert str(e) == NAME_ERROR % (NAME_REGEX, name)
for name in okay:
e = raises(ValueError, f, name.upper())
- assert str(e) == error % (NAME_REGEX, name.upper())
+ assert str(e) == NAME_ERROR % (NAME_REGEX, name.upper())