summaryrefslogtreecommitdiffstats
path: root/ipalib/frontend.py
diff options
context:
space:
mode:
authorJason Gerard DeRose <jderose@redhat.com>2009-01-14 11:39:29 -0700
committerJason Gerard DeRose <jderose@redhat.com>2009-01-14 11:39:29 -0700
commit2b2e73e7df90d38175e035d6ada4d752120dc0ec (patch)
tree1aa7e31836b7476049e01420e5de2413b1f85828 /ipalib/frontend.py
parentf3e0900ebc01d8fae8ce4068b0fae8d14c8069bb (diff)
downloadfreeipa-2b2e73e7df90d38175e035d6ada4d752120dc0ec.tar.gz
freeipa-2b2e73e7df90d38175e035d6ada4d752120dc0ec.tar.xz
freeipa-2b2e73e7df90d38175e035d6ada4d752120dc0ec.zip
Removed depreciated code from frontend.py; frontend.py no longer imports ipa_types
Diffstat (limited to 'ipalib/frontend.py')
-rw-r--r--ipalib/frontend.py453
1 files changed, 3 insertions, 450 deletions
diff --git a/ipalib/frontend.py b/ipalib/frontend.py
index c614e547..baa37b17 100644
--- a/ipalib/frontend.py
+++ b/ipalib/frontend.py
@@ -27,7 +27,7 @@ import plugable
from plugable import lock, check_name
import errors
from errors import check_type, check_isinstance, raise_TypeError
-import ipa_types
+import parameters
from util import make_repr
@@ -42,453 +42,6 @@ def is_rule(obj):
return callable(obj) and getattr(obj, RULE_FLAG, False) is True
-class DefaultFrom(plugable.ReadOnly):
- """
- Derive a default value from other supplied values.
-
- For example, say you wanted to create a default for the user's login from
- the user's first and last names. It could be implemented like this:
-
- >>> login = DefaultFrom(lambda first, last: first[0] + last)
- >>> login(first='John', last='Doe')
- 'JDoe'
-
- If you do not explicitly provide keys when you create a DefaultFrom
- instance, the keys are implicitly derived from your callback by
- inspecting ``callback.func_code.co_varnames``. The keys are available
- through the ``DefaultFrom.keys`` instance attribute, like this:
-
- >>> login.keys
- ('first', 'last')
-
- The callback is available through the ``DefaultFrom.callback`` instance
- attribute, like this:
-
- >>> login.callback # doctest:+ELLIPSIS
- <function <lambda> at 0x...>
- >>> login.callback.func_code.co_varnames # The keys
- ('first', 'last')
-
- The keys can be explicitly provided as optional positional arguments after
- the callback. For example, this is equivalent to the ``login`` instance
- above:
-
- >>> login2 = DefaultFrom(lambda a, b: a[0] + b, 'first', 'last')
- >>> login2.keys
- ('first', 'last')
- >>> login2.callback.func_code.co_varnames # Not the keys
- ('a', 'b')
- >>> login2(first='John', last='Doe')
- 'JDoe'
-
- If any keys are missing when calling your DefaultFrom instance, your
- callback is not called and None is returned. For example:
-
- >>> login(first='John', lastname='Doe') is None
- True
- >>> login() is None
- True
-
- Any additional keys are simply ignored, like this:
-
- >>> login(last='Doe', first='John', middle='Whatever')
- 'JDoe'
-
- As above, because `DefaultFrom.__call__` takes only pure keyword
- arguments, they can be supplied in any order.
-
- Of course, the callback need not be a lambda expression. This third
- example is equivalent to both the ``login`` and ``login2`` instances
- above:
-
- >>> def get_login(first, last):
- ... return first[0] + last
- ...
- >>> login3 = DefaultFrom(get_login)
- >>> login3.keys
- ('first', 'last')
- >>> login3.callback.func_code.co_varnames
- ('first', 'last')
- >>> login3(first='John', last='Doe')
- 'JDoe'
- """
-
- def __init__(self, callback, *keys):
- """
- :param callback: The callable to call when all keys are present.
- :param keys: Optional keys used for source values.
- """
- if not callable(callback):
- raise TypeError('callback must be callable; got %r' % callback)
- self.callback = callback
- if len(keys) == 0:
- fc = callback.func_code
- self.keys = fc.co_varnames[:fc.co_argcount]
- else:
- self.keys = keys
- for key in self.keys:
- if type(key) is not str:
- raise_TypeError(key, str, 'keys')
- lock(self)
-
- def __call__(self, **kw):
- """
- If all keys are present, calls the callback; otherwise returns None.
-
- :param kw: The keyword arguments.
- """
- vals = tuple(kw.get(k, None) for k in self.keys)
- if None in vals:
- return
- try:
- return self.callback(*vals)
- except StandardError:
- pass
-
-
-def parse_param_spec(spec):
- """
- Parse a param spec into to (name, kw).
-
- The ``spec`` string determines the param name, whether the param is
- required, and whether the param is multivalue according the following
- syntax:
-
- ====== ===== ======== ==========
- Spec Name Required Multivalue
- ====== ===== ======== ==========
- 'var' 'var' True False
- 'var?' 'var' False False
- 'var*' 'var' False True
- 'var+' 'var' True True
- ====== ===== ======== ==========
-
- For example,
-
- >>> parse_param_spec('login')
- ('login', {'required': True, 'multivalue': False})
- >>> parse_param_spec('gecos?')
- ('gecos', {'required': False, 'multivalue': False})
- >>> parse_param_spec('telephone_numbers*')
- ('telephone_numbers', {'required': False, 'multivalue': True})
- >>> parse_param_spec('group+')
- ('group', {'required': True, 'multivalue': True})
-
- :param spec: A spec string.
- """
- if type(spec) is not str:
- raise_TypeError(spec, str, 'spec')
- if len(spec) < 2:
- raise ValueError(
- 'param spec must be at least 2 characters; got %r' % spec
- )
- _map = {
- '?': dict(required=False, multivalue=False),
- '*': dict(required=False, multivalue=True),
- '+': dict(required=True, multivalue=True),
- }
- end = spec[-1]
- if end in _map:
- return (spec[:-1], _map[end])
- return (spec, dict(required=True, multivalue=False))
-
-
-class Param(plugable.ReadOnly):
- """
- A parameter accepted by a `Command`.
-
- ============ ================= ==================
- Keyword Type Default
- ============ ================= ==================
- cli_name str defaults to name
- type ipa_type.Type ipa_type.Unicode()
- doc str ""
- required bool True
- multivalue bool False
- primary_key bool False
- normalize callable None
- default same as type.type None
- default_from callable None
- flags frozenset frozenset()
- ============ ================= ==================
- """
- __nones = (None, '', tuple(), [])
- __defaults = dict(
- cli_name=None,
- type=ipa_types.Unicode(),
- doc='',
- required=True,
- multivalue=False,
- primary_key=False,
- normalize=None,
- default=None,
- default_from=None,
- flags=frozenset(),
- rules=tuple(),
- )
-
- def __init__(self, name, **override):
- self.__param_spec = name
- self.__override = override
- self.__kw = dict(self.__defaults)
- if not ('required' in override or 'multivalue' in override):
- (name, kw_from_spec) = parse_param_spec(name)
- self.__kw.update(kw_from_spec)
- self.__kw['cli_name'] = name
- if not set(self.__kw).issuperset(override):
- extra = sorted(set(override) - set(self.__kw))
- raise TypeError(
- 'Param.__init__() takes no such kwargs: %s' % ', '.join(extra)
- )
- self.__kw.update(override)
- self.name = check_name(name)
- self.cli_name = check_name(self.__kw.get('cli_name', name))
- self.type = self.__check_isinstance(ipa_types.Type, 'type')
- self.doc = self.__check_type(str, 'doc')
- self.required = self.__check_type(bool, 'required')
- self.multivalue = self.__check_type(bool, 'multivalue')
- self.default = self.__kw['default']
- df = self.__kw['default_from']
- if callable(df) and not isinstance(df, DefaultFrom):
- df = DefaultFrom(df)
- self.default_from = check_type(df, DefaultFrom, 'default_from',
- allow_none=True
- )
- self.flags = frozenset(self.__kw['flags'])
- self.__normalize = self.__kw['normalize']
- self.rules = self.__check_type(tuple, 'rules')
- self.all_rules = (self.type.validate,) + self.rules
- self.primary_key = self.__check_type(bool, 'primary_key')
- lock(self)
-
- def ispassword(self):
- """
- Return ``True`` is this Param is a password.
- """
- return 'password' in self.flags
-
- def __clone__(self, **override):
- """
- Return a new `Param` instance similar to this one.
- """
- kw = dict(self.__kw)
- kw.update(override)
- return self.__class__(self.name, **kw)
-
- def __check_type(self, type_, name, allow_none=False):
- value = self.__kw[name]
- return check_type(value, type_, name, allow_none)
-
- def __check_isinstance(self, type_, name, allow_none=False):
- value = self.__kw[name]
- return check_isinstance(value, type_, name, allow_none)
-
- def __dispatch(self, value, scalar):
- """
- Helper method used by `normalize` and `convert`.
- """
- if value in self.__nones:
- return
- if self.multivalue:
- if type(value) in (tuple, list):
- return tuple(
- scalar(v, i) for (i, v) in enumerate(value)
- )
- return (scalar(value, 0),) # tuple
- return scalar(value)
-
- def __normalize_scalar(self, value, index=None):
- """
- Normalize a scalar value.
-
- This method is called once with each value in multivalue.
- """
- if not isinstance(value, basestring):
- return value
- try:
- return self.__normalize(value)
- except StandardError:
- return value
-
- def normalize(self, value):
- """
- Normalize ``value`` using normalize callback.
-
- For example:
-
- >>> param = Param('telephone',
- ... normalize=lambda value: value.replace('.', '-')
- ... )
- >>> param.normalize('800.123.4567')
- '800-123-4567'
-
- If this `Param` instance does not have a normalize callback,
- ``value`` is returned unchanged.
-
- If this `Param` instance has a normalize callback and ``value`` is
- a basestring, the normalize callback is called and its return value
- is returned.
-
- If ``value`` is not a basestring, or if an exception is caught
- when calling the normalize callback, ``value`` is returned unchanged.
-
- :param value: A proposed value for this parameter.
- """
- if self.__normalize is None:
- return value
- return self.__dispatch(value, self.__normalize_scalar)
-
- def __convert_scalar(self, value, index=None):
- """
- Convert a scalar value.
-
- This method is called once with each value in multivalue.
- """
- if value in self.__nones:
- return
- converted = self.type(value)
- if converted is None:
- raise errors.ConversionError(
- self.name, value, self.type, index=index
- )
- return converted
-
- def convert(self, value):
- """
- Convert/coerce ``value`` to Python type for this `Param`.
-
- For example:
-
- >>> param = Param('an_int', type=ipa_types.Int())
- >>> param.convert(7.2)
- 7
- >>> param.convert(" 7 ")
- 7
-
- If ``value`` can not be converted, ConversionError is raised, which
- is as subclass of ValidationError.
-
- If ``value`` is None, conversion is not attempted and None is
- returned.
-
- :param value: A proposed value for this parameter.
- """
- return self.__dispatch(value, self.__convert_scalar)
-
- def __validate_scalar(self, value, index=None):
- """
- Validate a scalar value.
-
- This method is called once with each value in multivalue.
- """
- if type(value) is not self.type.type:
- raise_TypeError(value, self.type.type, 'value')
- for rule in self.rules:
- error = rule(value)
- if error is not None:
- raise errors.RuleError(
- self.name, value, error, rule, index=index
- )
-
- def validate(self, value):
- """
- Check validity of a value.
-
- Each validation rule is called in turn and if any returns and error,
- RuleError is raised, which is a subclass of ValidationError.
-
- :param value: A proposed value for this parameter.
- """
- if value is None:
- if self.required:
- raise errors.RequirementError(self.name)
- return
- if self.multivalue:
- if type(value) is not tuple:
- raise_TypeError(value, tuple, 'value')
- for (i, v) in enumerate(value):
- self.__validate_scalar(v, i)
- else:
- self.__validate_scalar(value)
-
- def get_default(self, **kw):
- """
- Return a default value for this parameter.
-
- If this `Param` instance does not have a default_from() callback, this
- method always returns the static Param.default instance attribute.
-
- On the other hand, if this `Param` instance has a default_from()
- callback, the callback is called and its return value is returned
- (assuming that value is not None).
-
- If the default_from() callback returns None, or if an exception is
- caught when calling the default_from() callback, the static
- Param.default instance attribute is returned.
-
- :param kw: Optional keyword arguments to pass to default_from().
- """
- if self.default_from is not None:
- default = self.default_from(**kw)
- if default is not None:
- try:
- return self.convert(self.normalize(default))
- except errors.ValidationError:
- return None
- return self.default
-
- def get_values(self):
- """
- Return a tuple of possible values.
-
- For enumerable types, a tuple containing the possible values is
- returned. For all other types, an empty tuple is returned.
- """
- if self.type.name in ('Enum', 'CallbackEnum'):
- return self.type.values
- return tuple()
-
- def __call__(self, value, **kw):
- if value in self.__nones:
- value = self.get_default(**kw)
- else:
- value = self.convert(self.normalize(value))
- self.validate(value)
- return value
-
- def __repr__(self):
- """
- Return an expresion that could construct this `Param` instance.
- """
- return make_repr(
- self.__class__.__name__,
- self.__param_spec,
- **self.__override
- )
-
-
-def create_param(spec):
- """
- Create a `Param` instance from a param spec.
-
- If ``spec`` is a `Param` instance, ``spec`` is returned unchanged.
-
- If ``spec`` is an str instance, then ``spec`` is parsed and an
- appropriate `Param` instance is created and returned.
-
- See `parse_param_spec` for the definition of the spec syntax.
-
- :param spec: A spec string or a `Param` instance.
- """
- if type(spec) is Param:
- return spec
- if type(spec) is not str:
- raise TypeError(
- 'create_param() takes %r or %r; got %r' % (str, Param, spec)
- )
- return Param(spec)
-
-
class Command(plugable.Plugin):
"""
A public IPA atomic operation.
@@ -810,7 +363,7 @@ class LocalOrRemote(Command):
"""
takes_options = (
- Param('server?', type=ipa_types.Bool(), default=False,
+ parameters.Flag('server?',
doc='Forward to server instead of running locally',
),
)
@@ -1064,7 +617,7 @@ class Property(Attribute):
'type',
)).union(Attribute.__public__)
- type = ipa_types.Unicode()
+ type = parameters.Str
required = False
multivalue = False
default = None