mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-02-25 18:55:28 -06:00
81: Switch from tab to 4-space indentation
This commit is contained in:
parent
f656e31a7e
commit
8e46824815
194
ipa
194
ipa
@ -31,54 +31,54 @@ from ipalib.startup import api
|
|||||||
TAB_WIDTH = 2
|
TAB_WIDTH = 2
|
||||||
|
|
||||||
def _(msg):
|
def _(msg):
|
||||||
"""
|
"""
|
||||||
Dummy gettext function for testing.
|
Dummy gettext function for testing.
|
||||||
"""
|
"""
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
class row(object):
|
class row(object):
|
||||||
def __init__(self, tab, c1, c2=None):
|
def __init__(self, tab, c1, c2=None):
|
||||||
assert type(tab) is int
|
assert type(tab) is int
|
||||||
assert type(c1) in (str, int)
|
assert type(c1) in (str, int)
|
||||||
assert type(c2) is str or c2 is None
|
assert type(c2) is str or c2 is None
|
||||||
self.tab = tab
|
self.tab = tab
|
||||||
self.c1 = c1
|
self.c1 = c1
|
||||||
self.c2 = c2
|
self.c2 = c2
|
||||||
|
|
||||||
def __len__(self):
|
def __len__(self):
|
||||||
return len(str(self.c1))
|
return len(str(self.c1))
|
||||||
|
|
||||||
def pretty_print(self, just):
|
def pretty_print(self, just):
|
||||||
tab = ' ' * (self.tab * TAB_WIDTH)
|
tab = ' ' * (self.tab * TAB_WIDTH)
|
||||||
if self.c2 is None:
|
if self.c2 is None:
|
||||||
print '%s%s' % (tab, self.c1)
|
print '%s%s' % (tab, self.c1)
|
||||||
else:
|
else:
|
||||||
if type(self.c1) is int:
|
if type(self.c1) is int:
|
||||||
c1 = str(self.c1).rjust(just)
|
c1 = str(self.c1).rjust(just)
|
||||||
else:
|
else:
|
||||||
c1 = self.c1.ljust(just)
|
c1 = self.c1.ljust(just)
|
||||||
print '%s%s %s' % (tab, c1, self.c2)
|
print '%s%s %s' % (tab, c1, self.c2)
|
||||||
|
|
||||||
def pretty_print(rows):
|
def pretty_print(rows):
|
||||||
rows = tuple(rows)
|
rows = tuple(rows)
|
||||||
def get_lengths():
|
def get_lengths():
|
||||||
yield 0
|
yield 0
|
||||||
for r in rows:
|
for r in rows:
|
||||||
if r.c2 is not None:
|
if r.c2 is not None:
|
||||||
yield len(r)
|
yield len(r)
|
||||||
max_len = max(get_lengths())
|
max_len = max(get_lengths())
|
||||||
for r in rows:
|
for r in rows:
|
||||||
r.pretty_print(max_len)
|
r.pretty_print(max_len)
|
||||||
|
|
||||||
|
|
||||||
def print_commands():
|
def print_commands():
|
||||||
print 'Commands:'
|
print 'Commands:'
|
||||||
m = api.max_cmd_len
|
m = api.max_cmd_len
|
||||||
for cmd in api.cmd:
|
for cmd in api.cmd:
|
||||||
print ' %s %s' % (str(cmd).ljust(m), cmd.get_doc(_))
|
print ' %s %s' % (str(cmd).ljust(m), cmd.get_doc(_))
|
||||||
|
|
||||||
def print_help(cmd):
|
def print_help(cmd):
|
||||||
print 'Help on %s' % cmd
|
print 'Help on %s' % cmd
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -94,79 +94,79 @@ def print_help(cmd):
|
|||||||
|
|
||||||
|
|
||||||
def print_api():
|
def print_api():
|
||||||
def iter_api(tab):
|
def iter_api(tab):
|
||||||
for name in api:
|
for name in api:
|
||||||
ns = getattr(api, name)
|
ns = getattr(api, name)
|
||||||
yield row(
|
yield row(
|
||||||
tab,
|
tab,
|
||||||
name,
|
name,
|
||||||
repr(ns),
|
repr(ns),
|
||||||
)
|
)
|
||||||
for i in ns:
|
for i in ns:
|
||||||
yield row(
|
yield row(
|
||||||
tab + 1,
|
tab + 1,
|
||||||
i.name,
|
i.name,
|
||||||
repr(i)
|
repr(i)
|
||||||
)
|
)
|
||||||
|
|
||||||
def iter_obj(tab):
|
def iter_obj(tab):
|
||||||
for obj in api.obj:
|
for obj in api.obj:
|
||||||
yield row(
|
yield row(
|
||||||
tab,
|
tab,
|
||||||
obj.name,
|
obj.name,
|
||||||
repr(obj),
|
repr(obj),
|
||||||
)
|
)
|
||||||
for (n, f) in [('mthd', '.%s()'), ('prop', '.%s')]:
|
for (n, f) in [('mthd', '.%s()'), ('prop', '.%s')]:
|
||||||
ns = getattr(obj, n)
|
ns = getattr(obj, n)
|
||||||
yield row(
|
yield row(
|
||||||
tab + 1,
|
tab + 1,
|
||||||
n,
|
n,
|
||||||
repr(ns),
|
repr(ns),
|
||||||
)
|
)
|
||||||
for attr in ns:
|
for attr in ns:
|
||||||
yield row(
|
yield row(
|
||||||
tab + 2,
|
tab + 2,
|
||||||
f % attr.name,
|
f % attr.name,
|
||||||
repr(attr),
|
repr(attr),
|
||||||
)
|
)
|
||||||
|
|
||||||
def iter_summary(tab):
|
def iter_summary(tab):
|
||||||
for name in api:
|
for name in api:
|
||||||
ns = getattr(api, name)
|
ns = getattr(api, name)
|
||||||
yield row(
|
yield row(
|
||||||
tab,
|
tab,
|
||||||
len(ns),
|
len(ns),
|
||||||
name
|
name
|
||||||
)
|
)
|
||||||
|
|
||||||
def print_heading(h):
|
def print_heading(h):
|
||||||
print '\n%s:' % h
|
print '\n%s:' % h
|
||||||
print '-' * (len(h) + 1)
|
print '-' * (len(h) + 1)
|
||||||
|
|
||||||
tab = 1
|
tab = 1
|
||||||
print_heading('API Overview')
|
print_heading('API Overview')
|
||||||
pretty_print(iter_api(tab))
|
pretty_print(iter_api(tab))
|
||||||
|
|
||||||
print_heading('Object Details')
|
print_heading('Object Details')
|
||||||
pretty_print(iter_obj(tab))
|
pretty_print(iter_obj(tab))
|
||||||
|
|
||||||
print_heading('Summary')
|
print_heading('Summary')
|
||||||
pretty_print(iter_summary(tab))
|
pretty_print(iter_summary(tab))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if len(sys.argv) < 2:
|
if len(sys.argv) < 2:
|
||||||
print_commands()
|
print_commands()
|
||||||
print 'Usage: ipa COMMAND [OPTIONS]'
|
print 'Usage: ipa COMMAND [OPTIONS]'
|
||||||
sys.exit(2)
|
sys.exit(2)
|
||||||
name= sys.argv[1]
|
name= sys.argv[1]
|
||||||
if name == '_api_':
|
if name == '_api_':
|
||||||
print_api()
|
print_api()
|
||||||
sys.exit()
|
sys.exit()
|
||||||
elif name not in api.cmd:
|
elif name not in api.cmd:
|
||||||
print_commands()
|
print_commands()
|
||||||
print 'ipa: ERROR: unknown command %r' % name
|
print 'ipa: ERROR: unknown command %r' % name
|
||||||
sys.exit(2)
|
sys.exit(2)
|
||||||
api.cmd[name]()
|
api.cmd[name]()
|
||||||
|
156
ipalib/errors.py
156
ipalib/errors.py
@ -22,128 +22,128 @@ All custom errors raised by `ipalib` package.
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
class IPAError(Exception):
|
class IPAError(Exception):
|
||||||
"""
|
"""
|
||||||
Use this base class for your custom IPA errors unless there is a
|
Use this base class for your custom IPA errors unless there is a
|
||||||
specific reason to subclass from AttributeError, KeyError, etc.
|
specific reason to subclass from AttributeError, KeyError, etc.
|
||||||
"""
|
"""
|
||||||
msg = None
|
msg = None
|
||||||
|
|
||||||
def __init__(self, *args, **kw):
|
def __init__(self, *args, **kw):
|
||||||
self.args = args
|
self.args = args
|
||||||
self.kw = kw
|
self.kw = kw
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
"""
|
"""
|
||||||
Returns the string representation of this exception.
|
Returns the string representation of this exception.
|
||||||
"""
|
"""
|
||||||
if self.msg is None:
|
if self.msg is None:
|
||||||
if len(self.args) == 1:
|
if len(self.args) == 1:
|
||||||
return unicode(self.args[0])
|
return unicode(self.args[0])
|
||||||
return unicode(self.args)
|
return unicode(self.args)
|
||||||
if len(self.args) > 0:
|
if len(self.args) > 0:
|
||||||
return self.msg % self.args
|
return self.msg % self.args
|
||||||
return self.msg % self.kw
|
return self.msg % self.kw
|
||||||
|
|
||||||
|
|
||||||
class ValidationError(IPAError):
|
class ValidationError(IPAError):
|
||||||
msg = 'invalid %r value %r: %s'
|
msg = 'invalid %r value %r: %s'
|
||||||
|
|
||||||
def __init__(self, name, value, error):
|
def __init__(self, name, value, error):
|
||||||
self.name = name
|
self.name = name
|
||||||
self.value = value
|
self.value = value
|
||||||
self.error = error
|
self.error = error
|
||||||
super(ValidationError, self).__init__(name, value, error)
|
super(ValidationError, self).__init__(name, value, error)
|
||||||
|
|
||||||
|
|
||||||
class NormalizationError(ValidationError):
|
class NormalizationError(ValidationError):
|
||||||
def __init__(self, name, value, type):
|
def __init__(self, name, value, type):
|
||||||
self.type = type
|
self.type = type
|
||||||
super(NormalizationError, self).__init__(name, value,
|
super(NormalizationError, self).__init__(name, value,
|
||||||
'not %r' % type
|
'not %r' % type
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class RuleError(ValidationError):
|
class RuleError(ValidationError):
|
||||||
def __init__(self, name, value, rule, error):
|
def __init__(self, name, value, rule, error):
|
||||||
self.rule = rule
|
self.rule = rule
|
||||||
super(RuleError, self).__init__(name, value, error)
|
super(RuleError, self).__init__(name, value, error)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class SetError(IPAError):
|
class SetError(IPAError):
|
||||||
msg = 'setting %r, but NameSpace does not allow attribute setting'
|
msg = 'setting %r, but NameSpace does not allow attribute setting'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class RegistrationError(IPAError):
|
class RegistrationError(IPAError):
|
||||||
"""
|
"""
|
||||||
Base class for errors that occur during plugin registration.
|
Base class for errors that occur during plugin registration.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
class NameSpaceError(RegistrationError):
|
class NameSpaceError(RegistrationError):
|
||||||
msg = 'name %r does not re.match %r'
|
msg = 'name %r does not re.match %r'
|
||||||
|
|
||||||
|
|
||||||
class SubclassError(RegistrationError):
|
class SubclassError(RegistrationError):
|
||||||
"""
|
"""
|
||||||
Raised when registering a plugin that is not a subclass of one of the
|
Raised when registering a plugin that is not a subclass of one of the
|
||||||
allowed bases.
|
allowed bases.
|
||||||
"""
|
"""
|
||||||
msg = 'plugin %r not subclass of any base in %r'
|
msg = 'plugin %r not subclass of any base in %r'
|
||||||
|
|
||||||
def __init__(self, cls, allowed):
|
def __init__(self, cls, allowed):
|
||||||
self.cls = cls
|
self.cls = cls
|
||||||
self.allowed = allowed
|
self.allowed = allowed
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.msg % (self.cls, self.allowed)
|
return self.msg % (self.cls, self.allowed)
|
||||||
|
|
||||||
|
|
||||||
class DuplicateError(RegistrationError):
|
class DuplicateError(RegistrationError):
|
||||||
"""
|
"""
|
||||||
Raised when registering a plugin whose exact class has already been
|
Raised when registering a plugin whose exact class has already been
|
||||||
registered.
|
registered.
|
||||||
"""
|
"""
|
||||||
msg = '%r at %d was already registered'
|
msg = '%r at %d was already registered'
|
||||||
|
|
||||||
def __init__(self, cls):
|
def __init__(self, cls):
|
||||||
self.cls = cls
|
self.cls = cls
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.msg % (self.cls, id(self.cls))
|
return self.msg % (self.cls, id(self.cls))
|
||||||
|
|
||||||
|
|
||||||
class OverrideError(RegistrationError):
|
class OverrideError(RegistrationError):
|
||||||
"""
|
"""
|
||||||
Raised when override=False yet registering a plugin that overrides an
|
Raised when override=False yet registering a plugin that overrides an
|
||||||
existing plugin in the same namespace.
|
existing plugin in the same namespace.
|
||||||
"""
|
"""
|
||||||
msg = 'unexpected override of %s.%s with %r (use override=True if intended)'
|
msg = 'unexpected override of %s.%s with %r (use override=True if intended)'
|
||||||
|
|
||||||
def __init__(self, base, cls):
|
def __init__(self, base, cls):
|
||||||
self.base = base
|
self.base = base
|
||||||
self.cls = cls
|
self.cls = cls
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.msg % (self.base.__name__, self.cls.__name__, self.cls)
|
return self.msg % (self.base.__name__, self.cls.__name__, self.cls)
|
||||||
|
|
||||||
|
|
||||||
class MissingOverrideError(RegistrationError):
|
class MissingOverrideError(RegistrationError):
|
||||||
"""
|
"""
|
||||||
Raised when override=True yet no preexisting plugin with the same name
|
Raised when override=True yet no preexisting plugin with the same name
|
||||||
and base has been registered.
|
and base has been registered.
|
||||||
"""
|
"""
|
||||||
msg = '%s.%s has not been registered, cannot override with %r'
|
msg = '%s.%s has not been registered, cannot override with %r'
|
||||||
|
|
||||||
def __init__(self, base, cls):
|
def __init__(self, base, cls):
|
||||||
self.base = base
|
self.base = base
|
||||||
self.cls = cls
|
self.cls = cls
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.msg % (self.base.__name__, self.cls.__name__, self.cls)
|
return self.msg % (self.base.__name__, self.cls.__name__, self.cls)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class TwiceSetError(IPAError):
|
class TwiceSetError(IPAError):
|
||||||
msg = '%s.%s cannot be set twice'
|
msg = '%s.%s cannot be set twice'
|
||||||
|
@ -5,50 +5,50 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
def get_label(self, _):
|
def get_label(self, _):
|
||||||
return _('Title') # Enum?
|
return _('Title') # Enum?
|
||||||
|
|
||||||
def get_label(self, _):
|
def get_label(self, _):
|
||||||
return _('First Name')
|
return _('First Name')
|
||||||
|
|
||||||
def get_label(self, _):
|
def get_label(self, _):
|
||||||
return _('Last Name')
|
return _('Last Name')
|
||||||
|
|
||||||
def get_label(self, _):
|
def get_label(self, _):
|
||||||
return _('Full Name') # Autofill
|
return _('Full Name') # Autofill
|
||||||
|
|
||||||
def get_label(self, _):
|
def get_label(self, _):
|
||||||
return _('Display Name') # Autofill
|
return _('Display Name') # Autofill
|
||||||
|
|
||||||
def get_label(self, _):
|
def get_label(self, _):
|
||||||
return _('Initials') # generated/ro?
|
return _('Initials') # generated/ro?
|
||||||
|
|
||||||
def get_label(self, _):
|
def get_label(self, _):
|
||||||
return _('Account Status') # Enum (active, inactive)
|
return _('Account Status') # Enum (active, inactive)
|
||||||
|
|
||||||
def get_label(self, _):
|
def get_label(self, _):
|
||||||
return _('Login')
|
return _('Login')
|
||||||
|
|
||||||
def get_label(self, _):
|
def get_label(self, _):
|
||||||
return _('Password')
|
return _('Password')
|
||||||
|
|
||||||
def get_label(self, _): # Same field as above, special interface
|
def get_label(self, _): # Same field as above, special interface
|
||||||
return _('Confirm Password')
|
return _('Confirm Password')
|
||||||
|
|
||||||
def get_label(self, _):
|
def get_label(self, _):
|
||||||
return _('UID') #ro
|
return _('UID') #ro
|
||||||
|
|
||||||
def get_label(self, _):
|
def get_label(self, _):
|
||||||
return _('GID') #ro
|
return _('GID') #ro
|
||||||
|
|
||||||
def get_label(self, _):
|
def get_label(self, _):
|
||||||
return _('Home Directory') #ro
|
return _('Home Directory') #ro
|
||||||
|
|
||||||
def get_label(self, _):
|
def get_label(self, _):
|
||||||
return _('Login Shell')
|
return _('Login Shell')
|
||||||
|
|
||||||
def get_label(self, _):
|
def get_label(self, _):
|
||||||
return _('GECOS')
|
return _('GECOS')
|
||||||
|
|
||||||
def get_label(self, _):
|
def get_label(self, _):
|
||||||
return _('')
|
return _('')
|
||||||
|
@ -27,323 +27,323 @@ import errors
|
|||||||
|
|
||||||
|
|
||||||
def to_cli(name):
|
def to_cli(name):
|
||||||
"""
|
"""
|
||||||
Takes a Python identifier and transforms it into form suitable for the
|
Takes a Python identifier and transforms it into form suitable for the
|
||||||
Command Line Interface.
|
Command Line Interface.
|
||||||
"""
|
"""
|
||||||
assert isinstance(name, str)
|
assert isinstance(name, str)
|
||||||
return name.replace('_', '-')
|
return name.replace('_', '-')
|
||||||
|
|
||||||
|
|
||||||
def from_cli(cli_name):
|
def from_cli(cli_name):
|
||||||
"""
|
"""
|
||||||
Takes a string from the Command Line Interface and transforms it into a
|
Takes a string from the Command Line Interface and transforms it into a
|
||||||
Python identifier.
|
Python identifier.
|
||||||
"""
|
"""
|
||||||
assert isinstance(cli_name, basestring)
|
assert isinstance(cli_name, basestring)
|
||||||
return cli_name.replace('-', '_')
|
return cli_name.replace('-', '_')
|
||||||
|
|
||||||
|
|
||||||
def check_identifier(name):
|
def check_identifier(name):
|
||||||
"""
|
"""
|
||||||
Raises errors.NameSpaceError if `name` is not a valid Python identifier
|
Raises errors.NameSpaceError if `name` is not a valid Python identifier
|
||||||
suitable for use in a NameSpace.
|
suitable for use in a NameSpace.
|
||||||
"""
|
"""
|
||||||
regex = r'^[a-z][_a-z0-9]*[a-z0-9]$'
|
regex = r'^[a-z][_a-z0-9]*[a-z0-9]$'
|
||||||
if re.match(regex, name) is None:
|
if re.match(regex, name) is None:
|
||||||
raise errors.NameSpaceError(name, regex)
|
raise errors.NameSpaceError(name, regex)
|
||||||
|
|
||||||
|
|
||||||
class Plugin(object):
|
class Plugin(object):
|
||||||
"""
|
"""
|
||||||
Base class for all plugins.
|
Base class for all plugins.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__api = None
|
__api = None
|
||||||
|
|
||||||
def __get_api(self):
|
def __get_api(self):
|
||||||
"""
|
"""
|
||||||
Returns the plugable.API instance passed to Plugin.finalize(), or
|
Returns the plugable.API instance passed to Plugin.finalize(), or
|
||||||
or returns None if finalize() has not yet been called.
|
or returns None if finalize() has not yet been called.
|
||||||
"""
|
"""
|
||||||
return self.__api
|
return self.__api
|
||||||
api = property(__get_api)
|
api = property(__get_api)
|
||||||
|
|
||||||
def finalize(self, api):
|
def finalize(self, api):
|
||||||
"""
|
"""
|
||||||
After all the plugins are instantiated, the plugable.API calls this
|
After all the plugins are instantiated, the plugable.API calls this
|
||||||
method, passing itself as the only argument. This is where plugins
|
method, passing itself as the only argument. This is where plugins
|
||||||
should check that other plugins they depend upon have actually be
|
should check that other plugins they depend upon have actually be
|
||||||
loaded.
|
loaded.
|
||||||
"""
|
"""
|
||||||
assert self.__api is None, 'finalize() can only be called once'
|
assert self.__api is None, 'finalize() can only be called once'
|
||||||
assert api is not None, 'finalize() argument cannot be None'
|
assert api is not None, 'finalize() argument cannot be None'
|
||||||
self.__api = api
|
self.__api = api
|
||||||
|
|
||||||
def __get_name(self):
|
def __get_name(self):
|
||||||
"""
|
"""
|
||||||
Returns the class name of this instance.
|
Returns the class name of this instance.
|
||||||
"""
|
"""
|
||||||
return self.__class__.__name__
|
return self.__class__.__name__
|
||||||
name = property(__get_name)
|
name = property(__get_name)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
"""
|
"""
|
||||||
Returns a fully qualified <module><name> representation of the class.
|
Returns a fully qualified <module><name> representation of the class.
|
||||||
"""
|
"""
|
||||||
return '%s.%s()' % (
|
return '%s.%s()' % (
|
||||||
self.__class__.__module__,
|
self.__class__.__module__,
|
||||||
self.__class__.__name__
|
self.__class__.__name__
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class ReadOnly(object):
|
class ReadOnly(object):
|
||||||
"""
|
"""
|
||||||
Base class for classes with read-only attributes.
|
Base class for classes with read-only attributes.
|
||||||
"""
|
"""
|
||||||
__slots__ = tuple()
|
__slots__ = tuple()
|
||||||
|
|
||||||
def __setattr__(self, name, value):
|
def __setattr__(self, name, value):
|
||||||
"""
|
"""
|
||||||
This raises an AttributeError anytime an attempt is made to set an
|
This raises an AttributeError anytime an attempt is made to set an
|
||||||
attribute.
|
attribute.
|
||||||
"""
|
"""
|
||||||
raise AttributeError('read-only: cannot set %s.%s' %
|
raise AttributeError('read-only: cannot set %s.%s' %
|
||||||
(self.__class__.__name__, name)
|
(self.__class__.__name__, name)
|
||||||
)
|
)
|
||||||
|
|
||||||
def __delattr__(self, name):
|
def __delattr__(self, name):
|
||||||
"""
|
"""
|
||||||
This raises an AttributeError anytime an attempt is made to delete an
|
This raises an AttributeError anytime an attempt is made to delete an
|
||||||
attribute.
|
attribute.
|
||||||
"""
|
"""
|
||||||
raise AttributeError('read-only: cannot del %s.%s' %
|
raise AttributeError('read-only: cannot del %s.%s' %
|
||||||
(self.__class__.__name__, name)
|
(self.__class__.__name__, name)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class Proxy(ReadOnly):
|
class Proxy(ReadOnly):
|
||||||
__slots__ = (
|
__slots__ = (
|
||||||
'__base',
|
'__base',
|
||||||
'__target',
|
'__target',
|
||||||
'__name_attr',
|
'__name_attr',
|
||||||
'__public',
|
'__public',
|
||||||
'name',
|
'name',
|
||||||
)
|
)
|
||||||
|
|
||||||
def __init__(self, base, target, name_attr='name'):
|
def __init__(self, base, target, name_attr='name'):
|
||||||
if not inspect.isclass(base):
|
if not inspect.isclass(base):
|
||||||
raise TypeError('arg1 must be a class, got %r' % base)
|
raise TypeError('arg1 must be a class, got %r' % base)
|
||||||
if not isinstance(target, base):
|
if not isinstance(target, base):
|
||||||
raise ValueError('arg2 must be instance of arg1, got %r' % target)
|
raise ValueError('arg2 must be instance of arg1, got %r' % target)
|
||||||
object.__setattr__(self, '_Proxy__base', base)
|
object.__setattr__(self, '_Proxy__base', base)
|
||||||
object.__setattr__(self, '_Proxy__target', target)
|
object.__setattr__(self, '_Proxy__target', target)
|
||||||
object.__setattr__(self, '_Proxy__name_attr', name_attr)
|
object.__setattr__(self, '_Proxy__name_attr', name_attr)
|
||||||
object.__setattr__(self, '_Proxy__public', base.__public__)
|
object.__setattr__(self, '_Proxy__public', base.__public__)
|
||||||
object.__setattr__(self, 'name', getattr(target, name_attr))
|
object.__setattr__(self, 'name', getattr(target, name_attr))
|
||||||
|
|
||||||
# Check __public
|
# Check __public
|
||||||
assert type(self.__public) is frozenset
|
assert type(self.__public) is frozenset
|
||||||
|
|
||||||
# Check name
|
# Check name
|
||||||
check_identifier(self.name)
|
check_identifier(self.name)
|
||||||
|
|
||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
for name in sorted(self.__public):
|
for name in sorted(self.__public):
|
||||||
yield name
|
yield name
|
||||||
|
|
||||||
def __getitem__(self, key):
|
def __getitem__(self, key):
|
||||||
if key in self.__public:
|
if key in self.__public:
|
||||||
return getattr(self.__target, key)
|
return getattr(self.__target, key)
|
||||||
raise KeyError('no proxy attribute %r' % key)
|
raise KeyError('no proxy attribute %r' % key)
|
||||||
|
|
||||||
def __getattr__(self, name):
|
def __getattr__(self, name):
|
||||||
if name in self.__public:
|
if name in self.__public:
|
||||||
return getattr(self.__target, name)
|
return getattr(self.__target, name)
|
||||||
raise AttributeError('no proxy attribute %r' % name)
|
raise AttributeError('no proxy attribute %r' % name)
|
||||||
|
|
||||||
def __call__(self, *args, **kw):
|
def __call__(self, *args, **kw):
|
||||||
return self['__call__'](*args, **kw)
|
return self['__call__'](*args, **kw)
|
||||||
|
|
||||||
def _clone(self, name_attr):
|
def _clone(self, name_attr):
|
||||||
return self.__class__(self.__base, self.__target, name_attr)
|
return self.__class__(self.__base, self.__target, name_attr)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return '%s(%s, %r, %r)' % (
|
return '%s(%s, %r, %r)' % (
|
||||||
self.__class__.__name__,
|
self.__class__.__name__,
|
||||||
self.__base.__name__,
|
self.__base.__name__,
|
||||||
self.__target,
|
self.__target,
|
||||||
self.__name_attr,
|
self.__name_attr,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class NameSpace(ReadOnly):
|
class NameSpace(ReadOnly):
|
||||||
"""
|
"""
|
||||||
A read-only namespace of (key, value) pairs that can be accessed
|
A read-only namespace of (key, value) pairs that can be accessed
|
||||||
both as instance attributes and as dictionary items.
|
both as instance attributes and as dictionary items.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, proxies):
|
def __init__(self, proxies):
|
||||||
"""
|
"""
|
||||||
NameSpace
|
NameSpace
|
||||||
"""
|
"""
|
||||||
object.__setattr__(self, '_NameSpace__proxies', tuple(proxies))
|
object.__setattr__(self, '_NameSpace__proxies', tuple(proxies))
|
||||||
object.__setattr__(self, '_NameSpace__d', dict())
|
object.__setattr__(self, '_NameSpace__d', dict())
|
||||||
for proxy in self.__proxies:
|
for proxy in self.__proxies:
|
||||||
assert isinstance(proxy, Proxy)
|
assert isinstance(proxy, Proxy)
|
||||||
assert proxy.name not in self.__d
|
assert proxy.name not in self.__d
|
||||||
self.__d[proxy.name] = proxy
|
self.__d[proxy.name] = proxy
|
||||||
assert not hasattr(self, proxy.name)
|
assert not hasattr(self, proxy.name)
|
||||||
object.__setattr__(self, proxy.name, proxy)
|
object.__setattr__(self, proxy.name, proxy)
|
||||||
|
|
||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
"""
|
"""
|
||||||
Iterates through the proxies in this NameSpace in the same order they
|
Iterates through the proxies in this NameSpace in the same order they
|
||||||
were passed in the contructor.
|
were passed in the contructor.
|
||||||
"""
|
"""
|
||||||
for proxy in self.__proxies:
|
for proxy in self.__proxies:
|
||||||
yield proxy
|
yield proxy
|
||||||
|
|
||||||
def __len__(self):
|
def __len__(self):
|
||||||
"""
|
"""
|
||||||
Returns number of proxies in this NameSpace.
|
Returns number of proxies in this NameSpace.
|
||||||
"""
|
"""
|
||||||
return len(self.__proxies)
|
return len(self.__proxies)
|
||||||
|
|
||||||
def __contains__(self, key):
|
def __contains__(self, key):
|
||||||
"""
|
"""
|
||||||
Returns True if a proxy named `key` is in this NameSpace.
|
Returns True if a proxy named `key` is in this NameSpace.
|
||||||
"""
|
"""
|
||||||
return key in self.__d
|
return key in self.__d
|
||||||
|
|
||||||
def __getitem__(self, key):
|
def __getitem__(self, key):
|
||||||
"""
|
"""
|
||||||
Returns proxy named `key`; otherwise raises KeyError.
|
Returns proxy named `key`; otherwise raises KeyError.
|
||||||
"""
|
"""
|
||||||
if key in self.__d:
|
if key in self.__d:
|
||||||
return self.__d[key]
|
return self.__d[key]
|
||||||
raise KeyError('NameSpace has no item for key %r' % key)
|
raise KeyError('NameSpace has no item for key %r' % key)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return '%s(<%d proxies>)' % (self.__class__.__name__, len(self))
|
return '%s(<%d proxies>)' % (self.__class__.__name__, len(self))
|
||||||
|
|
||||||
|
|
||||||
class Registrar(object):
|
class Registrar(object):
|
||||||
def __init__(self, *allowed):
|
def __init__(self, *allowed):
|
||||||
"""
|
"""
|
||||||
`*allowed` is a list of the base classes plugins can be subclassed
|
`*allowed` is a list of the base classes plugins can be subclassed
|
||||||
from.
|
from.
|
||||||
"""
|
"""
|
||||||
self.__allowed = frozenset(allowed)
|
self.__allowed = frozenset(allowed)
|
||||||
self.__d = {}
|
self.__d = {}
|
||||||
self.__registered = set()
|
self.__registered = set()
|
||||||
assert len(self.__allowed) == len(allowed)
|
assert len(self.__allowed) == len(allowed)
|
||||||
for base in self.__allowed:
|
for base in self.__allowed:
|
||||||
assert inspect.isclass(base)
|
assert inspect.isclass(base)
|
||||||
assert base.__name__ not in self.__d
|
assert base.__name__ not in self.__d
|
||||||
self.__d[base.__name__] = {}
|
self.__d[base.__name__] = {}
|
||||||
|
|
||||||
def __findbase(self, cls):
|
def __findbase(self, cls):
|
||||||
"""
|
"""
|
||||||
If `cls` is a subclass of a base in self.__allowed, returns that
|
If `cls` is a subclass of a base in self.__allowed, returns that
|
||||||
base; otherwise raises SubclassError.
|
base; otherwise raises SubclassError.
|
||||||
"""
|
"""
|
||||||
assert inspect.isclass(cls)
|
assert inspect.isclass(cls)
|
||||||
found = False
|
found = False
|
||||||
for base in self.__allowed:
|
for base in self.__allowed:
|
||||||
if issubclass(cls, base):
|
if issubclass(cls, base):
|
||||||
found = True
|
found = True
|
||||||
yield base
|
yield base
|
||||||
if not found:
|
if not found:
|
||||||
raise errors.SubclassError(cls, self.__allowed)
|
raise errors.SubclassError(cls, self.__allowed)
|
||||||
|
|
||||||
def __call__(self, cls, override=False):
|
def __call__(self, cls, override=False):
|
||||||
"""
|
"""
|
||||||
Register the plugin `cls`.
|
Register the plugin `cls`.
|
||||||
"""
|
"""
|
||||||
if not inspect.isclass(cls):
|
if not inspect.isclass(cls):
|
||||||
raise TypeError('plugin must be a class: %r' % cls)
|
raise TypeError('plugin must be a class: %r' % cls)
|
||||||
|
|
||||||
# Raise DuplicateError if this exact class was already registered:
|
# Raise DuplicateError if this exact class was already registered:
|
||||||
if cls in self.__registered:
|
if cls in self.__registered:
|
||||||
raise errors.DuplicateError(cls)
|
raise errors.DuplicateError(cls)
|
||||||
|
|
||||||
# Find the base class or raise SubclassError:
|
# Find the base class or raise SubclassError:
|
||||||
for base in self.__findbase(cls):
|
for base in self.__findbase(cls):
|
||||||
sub_d = self.__d[base.__name__]
|
sub_d = self.__d[base.__name__]
|
||||||
|
|
||||||
# Check override:
|
# Check override:
|
||||||
if cls.__name__ in sub_d:
|
if cls.__name__ in sub_d:
|
||||||
# Must use override=True to override:
|
# Must use override=True to override:
|
||||||
if not override:
|
if not override:
|
||||||
raise errors.OverrideError(base, cls)
|
raise errors.OverrideError(base, cls)
|
||||||
else:
|
else:
|
||||||
# There was nothing already registered to override:
|
# There was nothing already registered to override:
|
||||||
if override:
|
if override:
|
||||||
raise errors.MissingOverrideError(base, cls)
|
raise errors.MissingOverrideError(base, cls)
|
||||||
|
|
||||||
# The plugin is okay, add to sub_d:
|
# The plugin is okay, add to sub_d:
|
||||||
sub_d[cls.__name__] = cls
|
sub_d[cls.__name__] = cls
|
||||||
|
|
||||||
# The plugin is okay, add to __registered:
|
# The plugin is okay, add to __registered:
|
||||||
self.__registered.add(cls)
|
self.__registered.add(cls)
|
||||||
|
|
||||||
def __getitem__(self, item):
|
def __getitem__(self, item):
|
||||||
"""
|
"""
|
||||||
Returns a copy of the namespace dict of the base class named `name`.
|
Returns a copy of the namespace dict of the base class named `name`.
|
||||||
"""
|
"""
|
||||||
if inspect.isclass(item):
|
if inspect.isclass(item):
|
||||||
if item not in self.__allowed:
|
if item not in self.__allowed:
|
||||||
raise KeyError(repr(item))
|
raise KeyError(repr(item))
|
||||||
key = item.__name__
|
key = item.__name__
|
||||||
else:
|
else:
|
||||||
key = item
|
key = item
|
||||||
return dict(self.__d[key])
|
return dict(self.__d[key])
|
||||||
|
|
||||||
def __contains__(self, item):
|
def __contains__(self, item):
|
||||||
"""
|
"""
|
||||||
Returns True if a base class named `name` is in this Registrar.
|
Returns True if a base class named `name` is in this Registrar.
|
||||||
"""
|
"""
|
||||||
if inspect.isclass(item):
|
if inspect.isclass(item):
|
||||||
return item in self.__allowed
|
return item in self.__allowed
|
||||||
return item in self.__d
|
return item in self.__d
|
||||||
|
|
||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
"""
|
"""
|
||||||
Iterates through a (base, registered_plugins) tuple for each allowed
|
Iterates through a (base, registered_plugins) tuple for each allowed
|
||||||
base.
|
base.
|
||||||
"""
|
"""
|
||||||
for base in self.__allowed:
|
for base in self.__allowed:
|
||||||
sub_d = self.__d[base.__name__]
|
sub_d = self.__d[base.__name__]
|
||||||
yield (base, tuple(sub_d[k] for k in sorted(sub_d)))
|
yield (base, tuple(sub_d[k] for k in sorted(sub_d)))
|
||||||
|
|
||||||
|
|
||||||
class API(ReadOnly):
|
class API(ReadOnly):
|
||||||
def __init__(self, *allowed):
|
def __init__(self, *allowed):
|
||||||
keys = tuple(b.__name__ for b in allowed)
|
keys = tuple(b.__name__ for b in allowed)
|
||||||
object.__setattr__(self, '_API__keys', keys)
|
object.__setattr__(self, '_API__keys', keys)
|
||||||
object.__setattr__(self, 'register', Registrar(*allowed))
|
object.__setattr__(self, 'register', Registrar(*allowed))
|
||||||
|
|
||||||
def __call__(self):
|
def __call__(self):
|
||||||
"""
|
"""
|
||||||
Finalize the registration, instantiate the plugins.
|
Finalize the registration, instantiate the plugins.
|
||||||
"""
|
"""
|
||||||
d = {}
|
d = {}
|
||||||
def plugin_iter(base, classes):
|
def plugin_iter(base, classes):
|
||||||
for cls in classes:
|
for cls in classes:
|
||||||
if cls not in d:
|
if cls not in d:
|
||||||
d[cls] = cls()
|
d[cls] = cls()
|
||||||
plugin = d[cls]
|
plugin = d[cls]
|
||||||
yield Proxy(base, plugin)
|
yield Proxy(base, plugin)
|
||||||
|
|
||||||
for (base, classes) in self.register:
|
for (base, classes) in self.register:
|
||||||
ns = NameSpace(plugin_iter(base, classes))
|
ns = NameSpace(plugin_iter(base, classes))
|
||||||
assert not hasattr(self, base.__name__)
|
assert not hasattr(self, base.__name__)
|
||||||
object.__setattr__(self, base.__name__, ns)
|
object.__setattr__(self, base.__name__, ns)
|
||||||
for plugin in d.values():
|
for plugin in d.values():
|
||||||
plugin.finalize(self)
|
plugin.finalize(self)
|
||||||
assert plugin.api is self
|
assert plugin.api is self
|
||||||
|
|
||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
for key in self.__keys:
|
for key in self.__keys:
|
||||||
yield key
|
yield key
|
||||||
|
@ -27,109 +27,109 @@ from run import api
|
|||||||
|
|
||||||
# Hypothetical functional commands (not associated with any object):
|
# Hypothetical functional commands (not associated with any object):
|
||||||
class krbtest(public.cmd):
|
class krbtest(public.cmd):
|
||||||
def get_doc(self, _):
|
def get_doc(self, _):
|
||||||
return _('test your Kerberos ticket')
|
return _('test your Kerberos ticket')
|
||||||
api.register(krbtest)
|
api.register(krbtest)
|
||||||
|
|
||||||
class discover(public.cmd):
|
class discover(public.cmd):
|
||||||
def get_doc(self, _):
|
def get_doc(self, _):
|
||||||
return _('discover IPA servers on network')
|
return _('discover IPA servers on network')
|
||||||
api.register(discover)
|
api.register(discover)
|
||||||
|
|
||||||
|
|
||||||
# Register some methods for the 'user' object:
|
# Register some methods for the 'user' object:
|
||||||
class user_add(public.mthd):
|
class user_add(public.mthd):
|
||||||
def get_doc(self, _):
|
def get_doc(self, _):
|
||||||
return _('add new user')
|
return _('add new user')
|
||||||
api.register(user_add)
|
api.register(user_add)
|
||||||
|
|
||||||
class user_del(public.mthd):
|
class user_del(public.mthd):
|
||||||
def get_doc(self, _):
|
def get_doc(self, _):
|
||||||
return _('delete existing user')
|
return _('delete existing user')
|
||||||
api.register(user_del)
|
api.register(user_del)
|
||||||
|
|
||||||
class user_mod(public.mthd):
|
class user_mod(public.mthd):
|
||||||
def get_doc(self, _):
|
def get_doc(self, _):
|
||||||
return _('edit existing user')
|
return _('edit existing user')
|
||||||
api.register(user_mod)
|
api.register(user_mod)
|
||||||
|
|
||||||
class user_find(public.mthd):
|
class user_find(public.mthd):
|
||||||
def get_doc(self, _):
|
def get_doc(self, _):
|
||||||
return _('search for users')
|
return _('search for users')
|
||||||
api.register(user_find)
|
api.register(user_find)
|
||||||
|
|
||||||
|
|
||||||
# Register some properties for the 'user' object:
|
# Register some properties for the 'user' object:
|
||||||
class user_firstname(public.prop):
|
class user_firstname(public.prop):
|
||||||
pass
|
pass
|
||||||
api.register(user_firstname)
|
api.register(user_firstname)
|
||||||
|
|
||||||
class user_lastname(public.prop):
|
class user_lastname(public.prop):
|
||||||
pass
|
pass
|
||||||
api.register(user_lastname)
|
api.register(user_lastname)
|
||||||
|
|
||||||
class user_login(public.prop):
|
class user_login(public.prop):
|
||||||
pass
|
pass
|
||||||
api.register(user_login)
|
api.register(user_login)
|
||||||
|
|
||||||
|
|
||||||
# Register some methods for the 'group' object:
|
# Register some methods for the 'group' object:
|
||||||
class group_add(public.mthd):
|
class group_add(public.mthd):
|
||||||
def get_doc(self, _):
|
def get_doc(self, _):
|
||||||
return _('add new group')
|
return _('add new group')
|
||||||
api.register(group_add)
|
api.register(group_add)
|
||||||
|
|
||||||
class group_del(public.mthd):
|
class group_del(public.mthd):
|
||||||
def get_doc(self, _):
|
def get_doc(self, _):
|
||||||
return _('delete existing group')
|
return _('delete existing group')
|
||||||
api.register(group_del)
|
api.register(group_del)
|
||||||
|
|
||||||
class group_mod(public.mthd):
|
class group_mod(public.mthd):
|
||||||
def get_doc(self, _):
|
def get_doc(self, _):
|
||||||
return _('edit existing group')
|
return _('edit existing group')
|
||||||
api.register(group_mod)
|
api.register(group_mod)
|
||||||
|
|
||||||
class group_find(public.mthd):
|
class group_find(public.mthd):
|
||||||
def get_doc(self, _):
|
def get_doc(self, _):
|
||||||
return _('search for groups')
|
return _('search for groups')
|
||||||
api.register(group_find)
|
api.register(group_find)
|
||||||
|
|
||||||
|
|
||||||
# Register some methods for the 'service' object
|
# Register some methods for the 'service' object
|
||||||
class service_add(public.mthd):
|
class service_add(public.mthd):
|
||||||
def get_doc(self, _):
|
def get_doc(self, _):
|
||||||
return _('add new service')
|
return _('add new service')
|
||||||
api.register(service_add)
|
api.register(service_add)
|
||||||
|
|
||||||
class service_del(public.mthd):
|
class service_del(public.mthd):
|
||||||
def get_doc(self, _):
|
def get_doc(self, _):
|
||||||
return _('delete existing service')
|
return _('delete existing service')
|
||||||
api.register(service_del)
|
api.register(service_del)
|
||||||
|
|
||||||
class service_mod(public.mthd):
|
class service_mod(public.mthd):
|
||||||
def get_doc(self, _):
|
def get_doc(self, _):
|
||||||
return _('edit existing service')
|
return _('edit existing service')
|
||||||
api.register(service_mod)
|
api.register(service_mod)
|
||||||
|
|
||||||
class service_find(public.mthd):
|
class service_find(public.mthd):
|
||||||
def get_doc(self, _):
|
def get_doc(self, _):
|
||||||
return _('search for services')
|
return _('search for services')
|
||||||
api.register(service_find)
|
api.register(service_find)
|
||||||
|
|
||||||
|
|
||||||
# And to emphasis that the registration order doesn't matter,
|
# And to emphasis that the registration order doesn't matter,
|
||||||
# we'll register the objects last:
|
# we'll register the objects last:
|
||||||
class group(public.obj):
|
class group(public.obj):
|
||||||
def get_doc(self, _):
|
def get_doc(self, _):
|
||||||
return _('')
|
return _('')
|
||||||
api.register(group)
|
api.register(group)
|
||||||
|
|
||||||
class service(public.obj):
|
class service(public.obj):
|
||||||
def get_doc(self, _):
|
def get_doc(self, _):
|
||||||
return _('')
|
return _('')
|
||||||
api.register(service)
|
api.register(service)
|
||||||
|
|
||||||
class user(public.obj):
|
class user(public.obj):
|
||||||
def get_doc(self, _):
|
def get_doc(self, _):
|
||||||
return _('')
|
return _('')
|
||||||
api.register(user)
|
api.register(user)
|
||||||
|
392
ipalib/public.py
392
ipalib/public.py
@ -30,255 +30,255 @@ import errors
|
|||||||
RULE_FLAG = 'validation_rule'
|
RULE_FLAG = 'validation_rule'
|
||||||
|
|
||||||
def rule(obj):
|
def rule(obj):
|
||||||
assert not hasattr(obj, RULE_FLAG)
|
assert not hasattr(obj, RULE_FLAG)
|
||||||
setattr(obj, RULE_FLAG, True)
|
setattr(obj, RULE_FLAG, True)
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
def is_rule(obj):
|
def is_rule(obj):
|
||||||
return callable(obj) and getattr(obj, RULE_FLAG, False) is True
|
return callable(obj) and getattr(obj, RULE_FLAG, False) is True
|
||||||
|
|
||||||
|
|
||||||
class option(object):
|
class option(object):
|
||||||
"""
|
"""
|
||||||
The option class represents a kw argument from a command.
|
The option class represents a kw argument from a command.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__public__ = frozenset((
|
__public__ = frozenset((
|
||||||
'normalize',
|
'normalize',
|
||||||
'validate',
|
'validate',
|
||||||
'default',
|
'default',
|
||||||
'required',
|
'required',
|
||||||
'type',
|
'type',
|
||||||
))
|
))
|
||||||
__rules = None
|
__rules = None
|
||||||
|
|
||||||
# type = unicode, int, float # Set in subclass
|
# type = unicode, int, float # Set in subclass
|
||||||
|
|
||||||
def normalize(self, value):
|
def normalize(self, value):
|
||||||
"""
|
"""
|
||||||
Returns the normalized form of `value`. If `value` cannot be
|
Returns the normalized form of `value`. If `value` cannot be
|
||||||
normalized, NormalizationError is raised, which is a subclass of
|
normalized, NormalizationError is raised, which is a subclass of
|
||||||
ValidationError.
|
ValidationError.
|
||||||
|
|
||||||
The base class implementation only does type coercion, but subclasses
|
The base class implementation only does type coercion, but subclasses
|
||||||
might do other normalization (e.g., a unicode option might strip
|
might do other normalization (e.g., a unicode option might strip
|
||||||
leading and trailing white-space).
|
leading and trailing white-space).
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
return self.type(value)
|
return self.type(value)
|
||||||
except (TypeError, ValueError):
|
except (TypeError, ValueError):
|
||||||
raise errors.NormalizationError(
|
raise errors.NormalizationError(
|
||||||
self.__class__.__name__, value, self.type
|
self.__class__.__name__, value, self.type
|
||||||
)
|
)
|
||||||
|
|
||||||
def validate(self, value):
|
def validate(self, value):
|
||||||
"""
|
"""
|
||||||
Calls each validation rule and if any rule fails, raises RuleError,
|
Calls each validation rule and if any rule fails, raises RuleError,
|
||||||
which is a subclass of ValidationError.
|
which is a subclass of ValidationError.
|
||||||
"""
|
"""
|
||||||
for rule in self.rules:
|
for rule in self.rules:
|
||||||
msg = rule(value)
|
msg = rule(value)
|
||||||
if msg is not None:
|
if msg is not None:
|
||||||
raise errors.RuleError(
|
raise errors.RuleError(
|
||||||
self.__class__.__name__,
|
self.__class__.__name__,
|
||||||
value,
|
value,
|
||||||
rule,
|
rule,
|
||||||
msg,
|
msg,
|
||||||
)
|
)
|
||||||
|
|
||||||
def __get_rules(self):
|
def __get_rules(self):
|
||||||
"""
|
"""
|
||||||
Returns the tuple of rule methods used for input validation. This
|
Returns the tuple of rule methods used for input validation. This
|
||||||
tuple is lazily initialized the first time the property is accessed.
|
tuple is lazily initialized the first time the property is accessed.
|
||||||
"""
|
"""
|
||||||
if self.__rules is None:
|
if self.__rules is None:
|
||||||
self.__rules = tuple(sorted(
|
self.__rules = tuple(sorted(
|
||||||
self.__rules_iter(),
|
self.__rules_iter(),
|
||||||
key=lambda f: getattr(f, '__name__'),
|
key=lambda f: getattr(f, '__name__'),
|
||||||
))
|
))
|
||||||
return self.__rules
|
return self.__rules
|
||||||
rules = property(__get_rules)
|
rules = property(__get_rules)
|
||||||
|
|
||||||
def __rules_iter(self):
|
def __rules_iter(self):
|
||||||
"""
|
"""
|
||||||
Iterates through the attributes in this instance to retrieve the
|
Iterates through the attributes in this instance to retrieve the
|
||||||
methods implemented validation rules.
|
methods implemented validation rules.
|
||||||
"""
|
"""
|
||||||
for name in dir(self.__class__):
|
for name in dir(self.__class__):
|
||||||
if name.startswith('_'):
|
if name.startswith('_'):
|
||||||
continue
|
continue
|
||||||
base_attr = getattr(self.__class__, name)
|
base_attr = getattr(self.__class__, name)
|
||||||
if is_rule(base_attr):
|
if is_rule(base_attr):
|
||||||
attr = getattr(self, name)
|
attr = getattr(self, name)
|
||||||
if is_rule(attr):
|
if is_rule(attr):
|
||||||
yield attr
|
yield attr
|
||||||
|
|
||||||
def default(self, **kw):
|
def default(self, **kw):
|
||||||
"""
|
"""
|
||||||
Returns a default or auto-completed value for this option. If no
|
Returns a default or auto-completed value for this option. If no
|
||||||
default is available, this method should return None.
|
default is available, this method should return None.
|
||||||
"""
|
"""
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
class cmd(plugable.Plugin):
|
class cmd(plugable.Plugin):
|
||||||
__public__ = frozenset((
|
__public__ = frozenset((
|
||||||
'normalize',
|
'normalize',
|
||||||
'autofill',
|
'autofill',
|
||||||
'__call__',
|
'__call__',
|
||||||
'get_doc',
|
'get_doc',
|
||||||
'opt',
|
'opt',
|
||||||
|
|
||||||
))
|
))
|
||||||
__opt = None
|
__opt = None
|
||||||
|
|
||||||
def get_doc(self, _):
|
def get_doc(self, _):
|
||||||
"""
|
"""
|
||||||
Returns the gettext translated doc-string for this command.
|
Returns the gettext translated doc-string for this command.
|
||||||
|
|
||||||
For example:
|
For example:
|
||||||
|
|
||||||
>>> def get_doc(self, _):
|
>>> def get_doc(self, _):
|
||||||
>>> return _('add new user')
|
>>> return _('add new user')
|
||||||
"""
|
"""
|
||||||
raise NotImplementedError('%s.get_doc()' % self.name)
|
raise NotImplementedError('%s.get_doc()' % self.name)
|
||||||
|
|
||||||
def get_options(self):
|
def get_options(self):
|
||||||
"""
|
"""
|
||||||
Returns iterable with opt_proxy objects used to create the opt
|
Returns iterable with opt_proxy objects used to create the opt
|
||||||
NameSpace when __get_opt() is called.
|
NameSpace when __get_opt() is called.
|
||||||
"""
|
"""
|
||||||
raise NotImplementedError('%s.get_options()' % self.name)
|
raise NotImplementedError('%s.get_options()' % self.name)
|
||||||
|
|
||||||
def __get_opt(self):
|
def __get_opt(self):
|
||||||
"""
|
"""
|
||||||
Returns the NameSpace containing opt_proxy objects.
|
Returns the NameSpace containing opt_proxy objects.
|
||||||
"""
|
"""
|
||||||
if self.__opt is None:
|
if self.__opt is None:
|
||||||
self.__opt = plugable.NameSpace(self.get_options())
|
self.__opt = plugable.NameSpace(self.get_options())
|
||||||
return self.__opt
|
return self.__opt
|
||||||
opt = property(__get_opt)
|
opt = property(__get_opt)
|
||||||
|
|
||||||
def normalize_iter(self, kw):
|
def normalize_iter(self, kw):
|
||||||
for (key, value) in kw.items():
|
for (key, value) in kw.items():
|
||||||
if key in self.options:
|
if key in self.options:
|
||||||
yield (
|
yield (
|
||||||
key, self.options[key].normalize(value)
|
key, self.options[key].normalize(value)
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
yield (key, value)
|
yield (key, value)
|
||||||
|
|
||||||
def normalize(self, **kw):
|
def normalize(self, **kw):
|
||||||
return dict(self.normalize_iter(kw))
|
return dict(self.normalize_iter(kw))
|
||||||
|
|
||||||
def validate(self, **kw):
|
def validate(self, **kw):
|
||||||
for (key, value) in kw.items():
|
for (key, value) in kw.items():
|
||||||
if key in self.options:
|
if key in self.options:
|
||||||
self.options.validate(value)
|
self.options.validate(value)
|
||||||
|
|
||||||
def default(self, **kw):
|
def default(self, **kw):
|
||||||
for opt in self.options:
|
for opt in self.options:
|
||||||
if opt.name not in kw:
|
if opt.name not in kw:
|
||||||
value = opt.default(**kw)
|
value = opt.default(**kw)
|
||||||
if value is not None:
|
if value is not None:
|
||||||
kw[opt.name] = value
|
kw[opt.name] = value
|
||||||
|
|
||||||
def __call__(self, **kw):
|
def __call__(self, **kw):
|
||||||
(args, kw) = self.normalize(*args, **kw)
|
(args, kw) = self.normalize(*args, **kw)
|
||||||
(args, kw) = self.autofill(*args, **kw)
|
(args, kw) = self.autofill(*args, **kw)
|
||||||
self.validate(*args, **kw)
|
self.validate(*args, **kw)
|
||||||
self.execute(*args, **kw)
|
self.execute(*args, **kw)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class obj(plugable.Plugin):
|
class obj(plugable.Plugin):
|
||||||
__public__ = frozenset((
|
__public__ = frozenset((
|
||||||
'mthd',
|
'mthd',
|
||||||
'prop',
|
'prop',
|
||||||
))
|
))
|
||||||
__mthd = None
|
__mthd = None
|
||||||
__prop = None
|
__prop = None
|
||||||
|
|
||||||
def __get_mthd(self):
|
def __get_mthd(self):
|
||||||
return self.__mthd
|
return self.__mthd
|
||||||
mthd = property(__get_mthd)
|
mthd = property(__get_mthd)
|
||||||
|
|
||||||
def __get_prop(self):
|
def __get_prop(self):
|
||||||
return self.__prop
|
return self.__prop
|
||||||
prop = property(__get_prop)
|
prop = property(__get_prop)
|
||||||
|
|
||||||
def finalize(self, api):
|
def finalize(self, api):
|
||||||
super(obj, self).finalize(api)
|
super(obj, self).finalize(api)
|
||||||
self.__mthd = self.__create_ns('mthd')
|
self.__mthd = self.__create_ns('mthd')
|
||||||
self.__prop = self.__create_ns('prop')
|
self.__prop = self.__create_ns('prop')
|
||||||
|
|
||||||
def __create_ns(self, name):
|
def __create_ns(self, name):
|
||||||
return plugable.NameSpace(self.__filter(name))
|
return plugable.NameSpace(self.__filter(name))
|
||||||
|
|
||||||
def __filter(self, name):
|
def __filter(self, name):
|
||||||
for i in getattr(self.api, name):
|
for i in getattr(self.api, name):
|
||||||
if i.obj_name == self.name:
|
if i.obj_name == self.name:
|
||||||
yield i._clone('attr_name')
|
yield i._clone('attr_name')
|
||||||
|
|
||||||
|
|
||||||
class attr(plugable.Plugin):
|
class attr(plugable.Plugin):
|
||||||
__obj = None
|
__obj = None
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
m = re.match('^([a-z]+)_([a-z]+)$', self.__class__.__name__)
|
m = re.match('^([a-z]+)_([a-z]+)$', self.__class__.__name__)
|
||||||
assert m
|
assert m
|
||||||
self.__obj_name = m.group(1)
|
self.__obj_name = m.group(1)
|
||||||
self.__attr_name = m.group(2)
|
self.__attr_name = m.group(2)
|
||||||
|
|
||||||
def __get_obj_name(self):
|
def __get_obj_name(self):
|
||||||
return self.__obj_name
|
return self.__obj_name
|
||||||
obj_name = property(__get_obj_name)
|
obj_name = property(__get_obj_name)
|
||||||
|
|
||||||
def __get_attr_name(self):
|
def __get_attr_name(self):
|
||||||
return self.__attr_name
|
return self.__attr_name
|
||||||
attr_name = property(__get_attr_name)
|
attr_name = property(__get_attr_name)
|
||||||
|
|
||||||
def __get_obj(self):
|
def __get_obj(self):
|
||||||
"""
|
"""
|
||||||
Returns the obj instance this attribute is associated with, or None
|
Returns the obj instance this attribute is associated with, or None
|
||||||
if no association has been set.
|
if no association has been set.
|
||||||
"""
|
"""
|
||||||
return self.__obj
|
return self.__obj
|
||||||
obj = property(__get_obj)
|
obj = property(__get_obj)
|
||||||
|
|
||||||
def finalize(self, api):
|
def finalize(self, api):
|
||||||
super(attr, self).finalize(api)
|
super(attr, self).finalize(api)
|
||||||
self.__obj = api.obj[self.obj_name]
|
self.__obj = api.obj[self.obj_name]
|
||||||
|
|
||||||
|
|
||||||
class mthd(attr, cmd):
|
class mthd(attr, cmd):
|
||||||
__public__ = frozenset((
|
__public__ = frozenset((
|
||||||
'obj',
|
'obj',
|
||||||
'obj_name',
|
'obj_name',
|
||||||
))
|
))
|
||||||
|
|
||||||
|
|
||||||
class prop(attr):
|
class prop(attr):
|
||||||
__public__ = frozenset((
|
__public__ = frozenset((
|
||||||
'obj',
|
'obj',
|
||||||
'obj_name',
|
'obj_name',
|
||||||
))
|
))
|
||||||
|
|
||||||
def get_doc(self, _):
|
def get_doc(self, _):
|
||||||
return _('prop doc')
|
return _('prop doc')
|
||||||
|
|
||||||
|
|
||||||
class PublicAPI(plugable.API):
|
class PublicAPI(plugable.API):
|
||||||
__max_cmd_len = None
|
__max_cmd_len = None
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(PublicAPI, self).__init__(cmd, obj, mthd, prop)
|
super(PublicAPI, self).__init__(cmd, obj, mthd, prop)
|
||||||
|
|
||||||
def __get_max_cmd_len(self):
|
def __get_max_cmd_len(self):
|
||||||
if self.__max_cmd_len is None:
|
if self.__max_cmd_len is None:
|
||||||
if not hasattr(self, 'cmd'):
|
if not hasattr(self, 'cmd'):
|
||||||
return None
|
return None
|
||||||
max_cmd_len = max(len(str(cmd)) for cmd in self.cmd)
|
max_cmd_len = max(len(str(cmd)) for cmd in self.cmd)
|
||||||
object.__setattr__(self, '_PublicAPI__max_cmd_len', max_cmd_len)
|
object.__setattr__(self, '_PublicAPI__max_cmd_len', max_cmd_len)
|
||||||
return self.__max_cmd_len
|
return self.__max_cmd_len
|
||||||
max_cmd_len = property(__get_max_cmd_len)
|
max_cmd_len = property(__get_max_cmd_len)
|
||||||
|
@ -26,396 +26,396 @@ from ipalib import plugable, errors
|
|||||||
|
|
||||||
|
|
||||||
def test_to_cli():
|
def test_to_cli():
|
||||||
f = plugable.to_cli
|
f = plugable.to_cli
|
||||||
assert f('initialize') == 'initialize'
|
assert f('initialize') == 'initialize'
|
||||||
assert f('user_add') == 'user-add'
|
assert f('user_add') == 'user-add'
|
||||||
|
|
||||||
|
|
||||||
def test_from_cli():
|
def test_from_cli():
|
||||||
f = plugable.from_cli
|
f = plugable.from_cli
|
||||||
assert f('initialize') == 'initialize'
|
assert f('initialize') == 'initialize'
|
||||||
assert f('user-add') == 'user_add'
|
assert f('user-add') == 'user_add'
|
||||||
|
|
||||||
|
|
||||||
def test_valid_identifier():
|
def test_valid_identifier():
|
||||||
f = plugable.check_identifier
|
f = plugable.check_identifier
|
||||||
okay = [
|
okay = [
|
||||||
'user_add',
|
'user_add',
|
||||||
'stuff2junk',
|
'stuff2junk',
|
||||||
'sixty9',
|
'sixty9',
|
||||||
]
|
]
|
||||||
nope = [
|
nope = [
|
||||||
'_user_add',
|
'_user_add',
|
||||||
'__user_add',
|
'__user_add',
|
||||||
'user_add_',
|
'user_add_',
|
||||||
'user_add__',
|
'user_add__',
|
||||||
'_user_add_',
|
'_user_add_',
|
||||||
'__user_add__',
|
'__user_add__',
|
||||||
'60nine',
|
'60nine',
|
||||||
]
|
]
|
||||||
for name in okay:
|
for name in okay:
|
||||||
f(name)
|
f(name)
|
||||||
for name in nope:
|
for name in nope:
|
||||||
raises(errors.NameSpaceError, f, name)
|
raises(errors.NameSpaceError, f, name)
|
||||||
for name in okay:
|
for name in okay:
|
||||||
raises(errors.NameSpaceError, f, name.upper())
|
raises(errors.NameSpaceError, f, name.upper())
|
||||||
|
|
||||||
|
|
||||||
def test_Plugin():
|
def test_Plugin():
|
||||||
cls = plugable.Plugin
|
cls = plugable.Plugin
|
||||||
assert type(cls.name) is property
|
assert type(cls.name) is property
|
||||||
|
|
||||||
api = 'the api instance'
|
api = 'the api instance'
|
||||||
p = plugable.Plugin()
|
p = plugable.Plugin()
|
||||||
assert read_only(p, 'name') == 'Plugin'
|
assert read_only(p, 'name') == 'Plugin'
|
||||||
assert repr(p) == '%s.Plugin()' % plugable.__name__
|
assert repr(p) == '%s.Plugin()' % plugable.__name__
|
||||||
assert read_only(p, 'api') is None
|
assert read_only(p, 'api') is None
|
||||||
raises(AssertionError, p.finalize, None)
|
raises(AssertionError, p.finalize, None)
|
||||||
p.finalize(api)
|
p.finalize(api)
|
||||||
assert read_only(p, 'api') is api
|
assert read_only(p, 'api') is api
|
||||||
raises(AssertionError, p.finalize, api)
|
raises(AssertionError, p.finalize, api)
|
||||||
|
|
||||||
class some_plugin(plugable.Plugin):
|
class some_plugin(plugable.Plugin):
|
||||||
pass
|
pass
|
||||||
p = some_plugin()
|
p = some_plugin()
|
||||||
assert read_only(p, 'name') == 'some_plugin'
|
assert read_only(p, 'name') == 'some_plugin'
|
||||||
assert repr(p) == '%s.some_plugin()' % __name__
|
assert repr(p) == '%s.some_plugin()' % __name__
|
||||||
assert read_only(p, 'api') is None
|
assert read_only(p, 'api') is None
|
||||||
raises(AssertionError, p.finalize, None)
|
raises(AssertionError, p.finalize, None)
|
||||||
p.finalize(api)
|
p.finalize(api)
|
||||||
assert read_only(p, 'api') is api
|
assert read_only(p, 'api') is api
|
||||||
raises(AssertionError, p.finalize, api)
|
raises(AssertionError, p.finalize, api)
|
||||||
|
|
||||||
|
|
||||||
def test_ReadOnly():
|
def test_ReadOnly():
|
||||||
obj = plugable.ReadOnly()
|
obj = plugable.ReadOnly()
|
||||||
names = ['not_an_attribute', 'an_attribute']
|
names = ['not_an_attribute', 'an_attribute']
|
||||||
for name in names:
|
for name in names:
|
||||||
no_set(obj, name)
|
no_set(obj, name)
|
||||||
no_del(obj, name)
|
no_del(obj, name)
|
||||||
|
|
||||||
class some_ro_class(plugable.ReadOnly):
|
class some_ro_class(plugable.ReadOnly):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
object.__setattr__(self, 'an_attribute', 'Hello world!')
|
object.__setattr__(self, 'an_attribute', 'Hello world!')
|
||||||
obj = some_ro_class()
|
obj = some_ro_class()
|
||||||
for name in names:
|
for name in names:
|
||||||
no_set(obj, name)
|
no_set(obj, name)
|
||||||
no_del(obj, name)
|
no_del(obj, name)
|
||||||
assert read_only(obj, 'an_attribute') == 'Hello world!'
|
assert read_only(obj, 'an_attribute') == 'Hello world!'
|
||||||
|
|
||||||
|
|
||||||
def test_Proxy():
|
def test_Proxy():
|
||||||
cls = plugable.Proxy
|
cls = plugable.Proxy
|
||||||
assert issubclass(cls, plugable.ReadOnly)
|
assert issubclass(cls, plugable.ReadOnly)
|
||||||
|
|
||||||
# Setup:
|
# Setup:
|
||||||
class base(object):
|
class base(object):
|
||||||
__public__ = frozenset((
|
__public__ = frozenset((
|
||||||
'public_0',
|
'public_0',
|
||||||
'public_1',
|
'public_1',
|
||||||
'__call__',
|
'__call__',
|
||||||
))
|
))
|
||||||
|
|
||||||
def public_0(self):
|
def public_0(self):
|
||||||
return 'public_0'
|
return 'public_0'
|
||||||
|
|
||||||
def public_1(self):
|
def public_1(self):
|
||||||
return 'public_1'
|
return 'public_1'
|
||||||
|
|
||||||
def __call__(self, caller):
|
def __call__(self, caller):
|
||||||
return 'ya called it, %s.' % caller
|
return 'ya called it, %s.' % caller
|
||||||
|
|
||||||
def private_0(self):
|
def private_0(self):
|
||||||
return 'private_0'
|
return 'private_0'
|
||||||
|
|
||||||
def private_1(self):
|
def private_1(self):
|
||||||
return 'private_1'
|
return 'private_1'
|
||||||
|
|
||||||
class plugin(base):
|
class plugin(base):
|
||||||
name = 'user_add'
|
name = 'user_add'
|
||||||
attr_name = 'add'
|
attr_name = 'add'
|
||||||
|
|
||||||
# Test that TypeError is raised when base is not a class:
|
# Test that TypeError is raised when base is not a class:
|
||||||
raises(TypeError, cls, base(), None)
|
raises(TypeError, cls, base(), None)
|
||||||
|
|
||||||
# Test that ValueError is raised when target is not instance of base:
|
# Test that ValueError is raised when target is not instance of base:
|
||||||
raises(ValueError, cls, base, object())
|
raises(ValueError, cls, base, object())
|
||||||
|
|
||||||
# Test with correct arguments:
|
# Test with correct arguments:
|
||||||
i = plugin()
|
i = plugin()
|
||||||
p = cls(base, i)
|
p = cls(base, i)
|
||||||
assert read_only(p, 'name') == 'user_add'
|
assert read_only(p, 'name') == 'user_add'
|
||||||
assert list(p) == sorted(base.__public__)
|
assert list(p) == sorted(base.__public__)
|
||||||
|
|
||||||
# Test normal methods:
|
# Test normal methods:
|
||||||
for n in xrange(2):
|
for n in xrange(2):
|
||||||
pub = 'public_%d' % n
|
pub = 'public_%d' % n
|
||||||
priv = 'private_%d' % n
|
priv = 'private_%d' % n
|
||||||
assert getattr(i, pub)() == pub
|
assert getattr(i, pub)() == pub
|
||||||
assert getattr(p, pub)() == pub
|
assert getattr(p, pub)() == pub
|
||||||
assert hasattr(p, pub)
|
assert hasattr(p, pub)
|
||||||
assert getattr(i, priv)() == priv
|
assert getattr(i, priv)() == priv
|
||||||
assert not hasattr(p, priv)
|
assert not hasattr(p, priv)
|
||||||
|
|
||||||
# Test __call__:
|
# Test __call__:
|
||||||
value = 'ya called it, dude.'
|
value = 'ya called it, dude.'
|
||||||
assert i('dude') == value
|
assert i('dude') == value
|
||||||
assert p('dude') == value
|
assert p('dude') == value
|
||||||
assert callable(p)
|
assert callable(p)
|
||||||
|
|
||||||
# Test name_attr='name' kw arg
|
# Test name_attr='name' kw arg
|
||||||
i = plugin()
|
i = plugin()
|
||||||
p = cls(base, i, 'attr_name')
|
p = cls(base, i, 'attr_name')
|
||||||
assert read_only(p, 'name') == 'add'
|
assert read_only(p, 'name') == 'add'
|
||||||
|
|
||||||
# Test _clone():
|
# Test _clone():
|
||||||
i = plugin()
|
i = plugin()
|
||||||
p = cls(base, i)
|
p = cls(base, i)
|
||||||
assert read_only(p, 'name') == 'user_add'
|
assert read_only(p, 'name') == 'user_add'
|
||||||
c = p._clone('attr_name')
|
c = p._clone('attr_name')
|
||||||
assert isinstance(c, cls)
|
assert isinstance(c, cls)
|
||||||
assert read_only(c, 'name') == 'add'
|
assert read_only(c, 'name') == 'add'
|
||||||
assert c is not p
|
assert c is not p
|
||||||
assert c('whoever') == p('whoever')
|
assert c('whoever') == p('whoever')
|
||||||
|
|
||||||
|
|
||||||
def test_NameSpace():
|
def test_NameSpace():
|
||||||
cls = plugable.NameSpace
|
cls = plugable.NameSpace
|
||||||
assert issubclass(cls, plugable.ReadOnly)
|
assert issubclass(cls, plugable.ReadOnly)
|
||||||
|
|
||||||
class base(object):
|
class base(object):
|
||||||
__public__ = frozenset((
|
__public__ = frozenset((
|
||||||
'plusplus',
|
'plusplus',
|
||||||
))
|
))
|
||||||
|
|
||||||
def plusplus(self, n):
|
def plusplus(self, n):
|
||||||
return n + 1
|
return n + 1
|
||||||
|
|
||||||
class plugin(base):
|
class plugin(base):
|
||||||
def __init__(self, name):
|
def __init__(self, name):
|
||||||
self.name = name
|
self.name = name
|
||||||
|
|
||||||
def get_name(i):
|
def get_name(i):
|
||||||
return 'noun_verb%d' % i
|
return 'noun_verb%d' % i
|
||||||
|
|
||||||
def get_proxies(n):
|
def get_proxies(n):
|
||||||
for i in xrange(n):
|
for i in xrange(n):
|
||||||
yield plugable.Proxy(base, plugin(get_name(i)))
|
yield plugable.Proxy(base, plugin(get_name(i)))
|
||||||
|
|
||||||
cnt = 20
|
cnt = 20
|
||||||
ns = cls(get_proxies(cnt))
|
ns = cls(get_proxies(cnt))
|
||||||
|
|
||||||
# Test __len__
|
# Test __len__
|
||||||
assert len(ns) == cnt
|
assert len(ns) == cnt
|
||||||
|
|
||||||
# Test __iter__
|
# Test __iter__
|
||||||
i = None
|
i = None
|
||||||
for (i, proxy) in enumerate(ns):
|
for (i, proxy) in enumerate(ns):
|
||||||
assert type(proxy) is plugable.Proxy
|
assert type(proxy) is plugable.Proxy
|
||||||
assert proxy.name == get_name(i)
|
assert proxy.name == get_name(i)
|
||||||
assert i == cnt - 1
|
assert i == cnt - 1
|
||||||
|
|
||||||
# Test __contains__, __getitem__, getattr():
|
# Test __contains__, __getitem__, getattr():
|
||||||
proxies = frozenset(ns)
|
proxies = frozenset(ns)
|
||||||
for i in xrange(cnt):
|
for i in xrange(cnt):
|
||||||
name = get_name(i)
|
name = get_name(i)
|
||||||
assert name in ns
|
assert name in ns
|
||||||
proxy = ns[name]
|
proxy = ns[name]
|
||||||
assert proxy.name == name
|
assert proxy.name == name
|
||||||
assert type(proxy) is plugable.Proxy
|
assert type(proxy) is plugable.Proxy
|
||||||
assert proxy in proxies
|
assert proxy in proxies
|
||||||
assert read_only(ns, name) is proxy
|
assert read_only(ns, name) is proxy
|
||||||
|
|
||||||
# Test dir():
|
# Test dir():
|
||||||
assert set(get_name(i) for i in xrange(cnt)).issubset(set(dir(ns)))
|
assert set(get_name(i) for i in xrange(cnt)).issubset(set(dir(ns)))
|
||||||
|
|
||||||
# Test that KeyError, AttributeError is raised:
|
# Test that KeyError, AttributeError is raised:
|
||||||
name = get_name(cnt)
|
name = get_name(cnt)
|
||||||
assert name not in ns
|
assert name not in ns
|
||||||
raises(KeyError, getitem, ns, name)
|
raises(KeyError, getitem, ns, name)
|
||||||
raises(AttributeError, getattr, ns, name)
|
raises(AttributeError, getattr, ns, name)
|
||||||
no_set(ns, name)
|
no_set(ns, name)
|
||||||
|
|
||||||
|
|
||||||
def test_Registrar():
|
def test_Registrar():
|
||||||
class Base1(object):
|
class Base1(object):
|
||||||
pass
|
pass
|
||||||
class Base2(object):
|
class Base2(object):
|
||||||
pass
|
pass
|
||||||
class Base3(object):
|
class Base3(object):
|
||||||
pass
|
pass
|
||||||
class plugin1(Base1):
|
class plugin1(Base1):
|
||||||
pass
|
pass
|
||||||
class plugin2(Base2):
|
class plugin2(Base2):
|
||||||
pass
|
pass
|
||||||
class plugin3(Base3):
|
class plugin3(Base3):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# Test creation of Registrar:
|
# Test creation of Registrar:
|
||||||
r = plugable.Registrar(Base1, Base2)
|
r = plugable.Registrar(Base1, Base2)
|
||||||
|
|
||||||
# Test __hasitem__, __getitem__:
|
# Test __hasitem__, __getitem__:
|
||||||
for base in [Base1, Base2]:
|
for base in [Base1, Base2]:
|
||||||
assert base in r
|
assert base in r
|
||||||
assert base.__name__ in r
|
assert base.__name__ in r
|
||||||
assert r[base] == {}
|
assert r[base] == {}
|
||||||
assert r[base.__name__] == {}
|
assert r[base.__name__] == {}
|
||||||
|
|
||||||
|
|
||||||
# Check that TypeError is raised trying to register something that isn't
|
# Check that TypeError is raised trying to register something that isn't
|
||||||
# a class:
|
# a class:
|
||||||
raises(TypeError, r, plugin1())
|
raises(TypeError, r, plugin1())
|
||||||
|
|
||||||
# Check that SubclassError is raised trying to register a class that is
|
# Check that SubclassError is raised trying to register a class that is
|
||||||
# not a subclass of an allowed base:
|
# not a subclass of an allowed base:
|
||||||
raises(errors.SubclassError, r, plugin3)
|
raises(errors.SubclassError, r, plugin3)
|
||||||
|
|
||||||
# Check that registration works
|
# Check that registration works
|
||||||
r(plugin1)
|
r(plugin1)
|
||||||
sub_d = r['Base1']
|
sub_d = r['Base1']
|
||||||
assert len(sub_d) == 1
|
assert len(sub_d) == 1
|
||||||
assert sub_d['plugin1'] is plugin1
|
assert sub_d['plugin1'] is plugin1
|
||||||
# Check that a copy is returned
|
# Check that a copy is returned
|
||||||
assert sub_d is not r['Base1']
|
assert sub_d is not r['Base1']
|
||||||
assert sub_d == r['Base1']
|
assert sub_d == r['Base1']
|
||||||
|
|
||||||
# Check that DuplicateError is raised trying to register exact class
|
# Check that DuplicateError is raised trying to register exact class
|
||||||
# again:
|
# again:
|
||||||
raises(errors.DuplicateError, r, plugin1)
|
raises(errors.DuplicateError, r, plugin1)
|
||||||
|
|
||||||
# Check that OverrideError is raised trying to register class with same
|
# Check that OverrideError is raised trying to register class with same
|
||||||
# name and same base:
|
# name and same base:
|
||||||
orig1 = plugin1
|
orig1 = plugin1
|
||||||
class base1_extended(Base1):
|
class base1_extended(Base1):
|
||||||
pass
|
pass
|
||||||
class plugin1(base1_extended):
|
class plugin1(base1_extended):
|
||||||
pass
|
pass
|
||||||
raises(errors.OverrideError, r, plugin1)
|
raises(errors.OverrideError, r, plugin1)
|
||||||
|
|
||||||
# Check that overriding works
|
# Check that overriding works
|
||||||
r(plugin1, override=True)
|
r(plugin1, override=True)
|
||||||
sub_d = r['Base1']
|
sub_d = r['Base1']
|
||||||
assert len(sub_d) == 1
|
assert len(sub_d) == 1
|
||||||
assert sub_d['plugin1'] is plugin1
|
assert sub_d['plugin1'] is plugin1
|
||||||
assert sub_d['plugin1'] is not orig1
|
assert sub_d['plugin1'] is not orig1
|
||||||
|
|
||||||
# Check that MissingOverrideError is raised trying to override a name
|
# Check that MissingOverrideError is raised trying to override a name
|
||||||
# not yet registerd:
|
# not yet registerd:
|
||||||
raises(errors.MissingOverrideError, r, plugin2, override=True)
|
raises(errors.MissingOverrideError, r, plugin2, override=True)
|
||||||
|
|
||||||
# Check that additional plugin can be registered:
|
# Check that additional plugin can be registered:
|
||||||
r(plugin2)
|
r(plugin2)
|
||||||
sub_d = r['Base2']
|
sub_d = r['Base2']
|
||||||
assert len(sub_d) == 1
|
assert len(sub_d) == 1
|
||||||
assert sub_d['plugin2'] is plugin2
|
assert sub_d['plugin2'] is plugin2
|
||||||
|
|
||||||
|
|
||||||
# Setup to test __iter__:
|
# Setup to test __iter__:
|
||||||
class plugin1a(Base1):
|
class plugin1a(Base1):
|
||||||
pass
|
pass
|
||||||
r(plugin1a)
|
r(plugin1a)
|
||||||
|
|
||||||
class plugin1b(Base1):
|
class plugin1b(Base1):
|
||||||
pass
|
pass
|
||||||
r(plugin1b)
|
r(plugin1b)
|
||||||
|
|
||||||
class plugin2a(Base2):
|
class plugin2a(Base2):
|
||||||
pass
|
pass
|
||||||
r(plugin2a)
|
r(plugin2a)
|
||||||
|
|
||||||
class plugin2b(Base2):
|
class plugin2b(Base2):
|
||||||
pass
|
pass
|
||||||
r(plugin2b)
|
r(plugin2b)
|
||||||
|
|
||||||
m = {
|
m = {
|
||||||
'Base1': set([plugin1, plugin1a, plugin1b]),
|
'Base1': set([plugin1, plugin1a, plugin1b]),
|
||||||
'Base2': set([plugin2, plugin2a, plugin2b]),
|
'Base2': set([plugin2, plugin2a, plugin2b]),
|
||||||
}
|
}
|
||||||
|
|
||||||
# Now test __iter__:
|
# Now test __iter__:
|
||||||
for (base, plugins) in r:
|
for (base, plugins) in r:
|
||||||
assert base in [Base1, Base2]
|
assert base in [Base1, Base2]
|
||||||
assert set(plugins) == m[base.__name__]
|
assert set(plugins) == m[base.__name__]
|
||||||
assert len(list(r)) == 2
|
assert len(list(r)) == 2
|
||||||
|
|
||||||
# Again test __hasitem__, __getitem__:
|
# Again test __hasitem__, __getitem__:
|
||||||
for base in [Base1, Base2]:
|
for base in [Base1, Base2]:
|
||||||
assert base in r
|
assert base in r
|
||||||
assert base.__name__ in r
|
assert base.__name__ in r
|
||||||
d = dict((p.__name__, p) for p in m[base.__name__])
|
d = dict((p.__name__, p) for p in m[base.__name__])
|
||||||
assert len(d) == 3
|
assert len(d) == 3
|
||||||
assert r[base] == d
|
assert r[base] == d
|
||||||
assert r[base.__name__] == d
|
assert r[base.__name__] == d
|
||||||
|
|
||||||
|
|
||||||
def test_API():
|
def test_API():
|
||||||
assert issubclass(plugable.API, plugable.ReadOnly)
|
assert issubclass(plugable.API, plugable.ReadOnly)
|
||||||
|
|
||||||
# Setup the test bases, create the API:
|
# Setup the test bases, create the API:
|
||||||
class base0(plugable.Plugin):
|
class base0(plugable.Plugin):
|
||||||
__public__ = frozenset((
|
__public__ = frozenset((
|
||||||
'method',
|
'method',
|
||||||
))
|
))
|
||||||
|
|
||||||
def method(self, n):
|
def method(self, n):
|
||||||
return n
|
return n
|
||||||
|
|
||||||
class base1(plugable.Plugin):
|
class base1(plugable.Plugin):
|
||||||
__public__ = frozenset((
|
__public__ = frozenset((
|
||||||
'method',
|
'method',
|
||||||
))
|
))
|
||||||
|
|
||||||
def method(self, n):
|
def method(self, n):
|
||||||
return n + 1
|
return n + 1
|
||||||
|
|
||||||
api = plugable.API(base0, base1)
|
api = plugable.API(base0, base1)
|
||||||
r = api.register
|
r = api.register
|
||||||
assert isinstance(r, plugable.Registrar)
|
assert isinstance(r, plugable.Registrar)
|
||||||
assert read_only(api, 'register') is r
|
assert read_only(api, 'register') is r
|
||||||
|
|
||||||
class base0_plugin0(base0):
|
class base0_plugin0(base0):
|
||||||
pass
|
pass
|
||||||
r(base0_plugin0)
|
r(base0_plugin0)
|
||||||
|
|
||||||
class base0_plugin1(base0):
|
class base0_plugin1(base0):
|
||||||
pass
|
pass
|
||||||
r(base0_plugin1)
|
r(base0_plugin1)
|
||||||
|
|
||||||
class base0_plugin2(base0):
|
class base0_plugin2(base0):
|
||||||
pass
|
pass
|
||||||
r(base0_plugin2)
|
r(base0_plugin2)
|
||||||
|
|
||||||
class base1_plugin0(base1):
|
class base1_plugin0(base1):
|
||||||
pass
|
pass
|
||||||
r(base1_plugin0)
|
r(base1_plugin0)
|
||||||
|
|
||||||
class base1_plugin1(base1):
|
class base1_plugin1(base1):
|
||||||
pass
|
pass
|
||||||
r(base1_plugin1)
|
r(base1_plugin1)
|
||||||
|
|
||||||
class base1_plugin2(base1):
|
class base1_plugin2(base1):
|
||||||
pass
|
pass
|
||||||
r(base1_plugin2)
|
r(base1_plugin2)
|
||||||
|
|
||||||
# Test API instance:
|
# Test API instance:
|
||||||
api() # Calling instance performs finalization
|
api() # Calling instance performs finalization
|
||||||
|
|
||||||
def get_base(b):
|
def get_base(b):
|
||||||
return 'base%d' % b
|
return 'base%d' % b
|
||||||
|
|
||||||
def get_plugin(b, p):
|
def get_plugin(b, p):
|
||||||
return 'base%d_plugin%d' % (b, p)
|
return 'base%d_plugin%d' % (b, p)
|
||||||
|
|
||||||
for b in xrange(2):
|
for b in xrange(2):
|
||||||
base_name = get_base(b)
|
base_name = get_base(b)
|
||||||
ns = getattr(api, base_name)
|
ns = getattr(api, base_name)
|
||||||
assert isinstance(ns, plugable.NameSpace)
|
assert isinstance(ns, plugable.NameSpace)
|
||||||
assert read_only(api, base_name) is ns
|
assert read_only(api, base_name) is ns
|
||||||
assert len(ns) == 3
|
assert len(ns) == 3
|
||||||
for p in xrange(3):
|
for p in xrange(3):
|
||||||
plugin_name = get_plugin(b, p)
|
plugin_name = get_plugin(b, p)
|
||||||
proxy = ns[plugin_name]
|
proxy = ns[plugin_name]
|
||||||
assert isinstance(proxy, plugable.Proxy)
|
assert isinstance(proxy, plugable.Proxy)
|
||||||
assert proxy.name == plugin_name
|
assert proxy.name == plugin_name
|
||||||
assert read_only(ns, plugin_name) is proxy
|
assert read_only(ns, plugin_name) is proxy
|
||||||
assert read_only(proxy, 'method')(7) == 7 + b
|
assert read_only(proxy, 'method')(7) == 7 + b
|
||||||
|
@ -26,179 +26,179 @@ from ipalib import public, plugable, errors
|
|||||||
|
|
||||||
|
|
||||||
def test_RULE_FLAG():
|
def test_RULE_FLAG():
|
||||||
assert public.RULE_FLAG == 'validation_rule'
|
assert public.RULE_FLAG == 'validation_rule'
|
||||||
|
|
||||||
|
|
||||||
def test_rule():
|
def test_rule():
|
||||||
flag = public.RULE_FLAG
|
flag = public.RULE_FLAG
|
||||||
rule = public.rule
|
rule = public.rule
|
||||||
def my_func():
|
def my_func():
|
||||||
pass
|
pass
|
||||||
assert not hasattr(my_func, flag)
|
assert not hasattr(my_func, flag)
|
||||||
rule(my_func)
|
rule(my_func)
|
||||||
assert getattr(my_func, flag) is True
|
assert getattr(my_func, flag) is True
|
||||||
@rule
|
@rule
|
||||||
def my_func2():
|
def my_func2():
|
||||||
pass
|
pass
|
||||||
assert getattr(my_func2, flag) is True
|
assert getattr(my_func2, flag) is True
|
||||||
|
|
||||||
|
|
||||||
def test_is_rule():
|
def test_is_rule():
|
||||||
is_rule = public.is_rule
|
is_rule = public.is_rule
|
||||||
flag = public.RULE_FLAG
|
flag = public.RULE_FLAG
|
||||||
|
|
||||||
class no_call(object):
|
class no_call(object):
|
||||||
def __init__(self, value):
|
def __init__(self, value):
|
||||||
if value is not None:
|
if value is not None:
|
||||||
assert value in (True, False)
|
assert value in (True, False)
|
||||||
setattr(self, flag, value)
|
setattr(self, flag, value)
|
||||||
|
|
||||||
class call(no_call):
|
class call(no_call):
|
||||||
def __call__(self):
|
def __call__(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
assert is_rule(call(True))
|
assert is_rule(call(True))
|
||||||
assert not is_rule(no_call(True))
|
assert not is_rule(no_call(True))
|
||||||
assert not is_rule(call(False))
|
assert not is_rule(call(False))
|
||||||
assert not is_rule(call(None))
|
assert not is_rule(call(None))
|
||||||
|
|
||||||
|
|
||||||
class test_option():
|
class test_option():
|
||||||
def cls(self):
|
def cls(self):
|
||||||
return public.option
|
return public.option
|
||||||
|
|
||||||
def sub(self):
|
def sub(self):
|
||||||
rule = public.rule
|
rule = public.rule
|
||||||
class int_opt(self.cls()):
|
class int_opt(self.cls()):
|
||||||
type = int
|
type = int
|
||||||
@rule
|
@rule
|
||||||
def rule_0(self, value):
|
def rule_0(self, value):
|
||||||
if value == 0:
|
if value == 0:
|
||||||
return 'cannot be 0'
|
return 'cannot be 0'
|
||||||
@rule
|
@rule
|
||||||
def rule_1(self, value):
|
def rule_1(self, value):
|
||||||
if value == 1:
|
if value == 1:
|
||||||
return 'cannot be 1'
|
return 'cannot be 1'
|
||||||
@rule
|
@rule
|
||||||
def rule_2(self, value):
|
def rule_2(self, value):
|
||||||
if value == 2:
|
if value == 2:
|
||||||
return 'cannot be 2'
|
return 'cannot be 2'
|
||||||
return int_opt
|
return int_opt
|
||||||
|
|
||||||
def test_class(self):
|
def test_class(self):
|
||||||
"""
|
"""
|
||||||
Perform some tests on the class (not an instance).
|
Perform some tests on the class (not an instance).
|
||||||
"""
|
"""
|
||||||
cls = self.cls()
|
cls = self.cls()
|
||||||
#assert issubclass(cls, plugable.ReadOnly)
|
#assert issubclass(cls, plugable.ReadOnly)
|
||||||
assert type(cls.rules) is property
|
assert type(cls.rules) is property
|
||||||
|
|
||||||
def test_normalize(self):
|
def test_normalize(self):
|
||||||
sub = self.sub()
|
sub = self.sub()
|
||||||
i = sub()
|
i = sub()
|
||||||
# Test with values that can't be converted:
|
# Test with values that can't be converted:
|
||||||
nope = (
|
nope = (
|
||||||
'7.0'
|
'7.0'
|
||||||
'whatever',
|
'whatever',
|
||||||
object,
|
object,
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
for val in nope:
|
for val in nope:
|
||||||
e = raises(errors.NormalizationError, i.normalize, val)
|
e = raises(errors.NormalizationError, i.normalize, val)
|
||||||
assert isinstance(e, errors.ValidationError)
|
assert isinstance(e, errors.ValidationError)
|
||||||
assert e.name == 'int_opt'
|
assert e.name == 'int_opt'
|
||||||
assert e.value == val
|
assert e.value == val
|
||||||
assert e.error == "not <type 'int'>"
|
assert e.error == "not <type 'int'>"
|
||||||
assert e.type is int
|
assert e.type is int
|
||||||
# Test with values that can be converted:
|
# Test with values that can be converted:
|
||||||
okay = (
|
okay = (
|
||||||
7,
|
7,
|
||||||
7.0,
|
7.0,
|
||||||
7.2,
|
7.2,
|
||||||
7L,
|
7L,
|
||||||
'7',
|
'7',
|
||||||
' 7 ',
|
' 7 ',
|
||||||
)
|
)
|
||||||
for val in okay:
|
for val in okay:
|
||||||
assert i.normalize(val) == 7
|
assert i.normalize(val) == 7
|
||||||
|
|
||||||
def test_rules(self):
|
def test_rules(self):
|
||||||
"""
|
"""
|
||||||
Test the rules property.
|
Test the rules property.
|
||||||
"""
|
"""
|
||||||
o = self.sub()()
|
o = self.sub()()
|
||||||
assert len(o.rules) == 3
|
assert len(o.rules) == 3
|
||||||
def get_rule(i):
|
def get_rule(i):
|
||||||
return getattr(o, 'rule_%d' % i)
|
return getattr(o, 'rule_%d' % i)
|
||||||
rules = tuple(get_rule(i) for i in xrange(3))
|
rules = tuple(get_rule(i) for i in xrange(3))
|
||||||
assert o.rules == rules
|
assert o.rules == rules
|
||||||
|
|
||||||
def test_validation(self):
|
def test_validation(self):
|
||||||
"""
|
"""
|
||||||
Test the validation method.
|
Test the validation method.
|
||||||
"""
|
"""
|
||||||
o = self.sub()()
|
o = self.sub()()
|
||||||
o.validate(9)
|
o.validate(9)
|
||||||
for i in xrange(3):
|
for i in xrange(3):
|
||||||
e = raises(errors.RuleError, o.validate, i)
|
e = raises(errors.RuleError, o.validate, i)
|
||||||
assert e.error == 'cannot be %d' % i
|
assert e.error == 'cannot be %d' % i
|
||||||
assert e.value == i
|
assert e.value == i
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def test_cmd():
|
def test_cmd():
|
||||||
cls = public.cmd
|
cls = public.cmd
|
||||||
assert issubclass(cls, plugable.Plugin)
|
assert issubclass(cls, plugable.Plugin)
|
||||||
|
|
||||||
|
|
||||||
def test_obj():
|
def test_obj():
|
||||||
cls = public.obj
|
cls = public.obj
|
||||||
assert issubclass(cls, plugable.Plugin)
|
assert issubclass(cls, plugable.Plugin)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def test_attr():
|
def test_attr():
|
||||||
cls = public.attr
|
cls = public.attr
|
||||||
assert issubclass(cls, plugable.Plugin)
|
assert issubclass(cls, plugable.Plugin)
|
||||||
|
|
||||||
class api(object):
|
class api(object):
|
||||||
obj = dict(user='the user obj')
|
obj = dict(user='the user obj')
|
||||||
|
|
||||||
class user_add(cls):
|
class user_add(cls):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
i = user_add()
|
i = user_add()
|
||||||
assert read_only(i, 'obj_name') == 'user'
|
assert read_only(i, 'obj_name') == 'user'
|
||||||
assert read_only(i, 'attr_name') == 'add'
|
assert read_only(i, 'attr_name') == 'add'
|
||||||
assert read_only(i, 'obj') is None
|
assert read_only(i, 'obj') is None
|
||||||
i.finalize(api)
|
i.finalize(api)
|
||||||
assert read_only(i, 'api') is api
|
assert read_only(i, 'api') is api
|
||||||
assert read_only(i, 'obj') == 'the user obj'
|
assert read_only(i, 'obj') == 'the user obj'
|
||||||
|
|
||||||
|
|
||||||
def test_mthd():
|
def test_mthd():
|
||||||
cls = public.mthd
|
cls = public.mthd
|
||||||
assert issubclass(cls, public.attr)
|
assert issubclass(cls, public.attr)
|
||||||
assert issubclass(cls, public.cmd)
|
assert issubclass(cls, public.cmd)
|
||||||
|
|
||||||
|
|
||||||
def test_prop():
|
def test_prop():
|
||||||
cls = public.prop
|
cls = public.prop
|
||||||
assert issubclass(cls, public.attr)
|
assert issubclass(cls, public.attr)
|
||||||
|
|
||||||
|
|
||||||
def test_PublicAPI():
|
def test_PublicAPI():
|
||||||
cls = public.PublicAPI
|
cls = public.PublicAPI
|
||||||
assert issubclass(cls, plugable.API)
|
assert issubclass(cls, plugable.API)
|
||||||
|
|
||||||
api = cls()
|
api = cls()
|
||||||
|
|
||||||
class cmd1(public.cmd):
|
class cmd1(public.cmd):
|
||||||
pass
|
pass
|
||||||
api.register(cmd1)
|
api.register(cmd1)
|
||||||
|
|
||||||
class cmd2(public.cmd):
|
class cmd2(public.cmd):
|
||||||
pass
|
pass
|
||||||
api.register(cmd2)
|
api.register(cmd2)
|
||||||
|
|
||||||
api()
|
api()
|
||||||
|
@ -25,124 +25,124 @@ import tstutil
|
|||||||
|
|
||||||
|
|
||||||
class Prop(object):
|
class Prop(object):
|
||||||
def __init__(self, *ops):
|
def __init__(self, *ops):
|
||||||
self.__ops = frozenset(ops)
|
self.__ops = frozenset(ops)
|
||||||
self.__prop = 'prop value'
|
self.__prop = 'prop value'
|
||||||
|
|
||||||
def __get_prop(self):
|
def __get_prop(self):
|
||||||
if 'get' not in self.__ops:
|
if 'get' not in self.__ops:
|
||||||
raise AttributeError('get prop')
|
raise AttributeError('get prop')
|
||||||
return self.__prop
|
return self.__prop
|
||||||
|
|
||||||
def __set_prop(self, value):
|
def __set_prop(self, value):
|
||||||
if 'set' not in self.__ops:
|
if 'set' not in self.__ops:
|
||||||
raise AttributeError('set prop')
|
raise AttributeError('set prop')
|
||||||
self.__prop = value
|
self.__prop = value
|
||||||
|
|
||||||
def __del_prop(self):
|
def __del_prop(self):
|
||||||
if 'del' not in self.__ops:
|
if 'del' not in self.__ops:
|
||||||
raise AttributeError('del prop')
|
raise AttributeError('del prop')
|
||||||
self.__prop = None
|
self.__prop = None
|
||||||
|
|
||||||
prop = property(__get_prop, __set_prop, __del_prop)
|
prop = property(__get_prop, __set_prop, __del_prop)
|
||||||
|
|
||||||
|
|
||||||
def test_yes_raised():
|
def test_yes_raised():
|
||||||
f = tstutil.raises
|
f = tstutil.raises
|
||||||
|
|
||||||
class SomeError(Exception):
|
class SomeError(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
class AnotherError(Exception):
|
class AnotherError(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def callback1():
|
def callback1():
|
||||||
'raises correct exception'
|
'raises correct exception'
|
||||||
raise SomeError()
|
raise SomeError()
|
||||||
|
|
||||||
def callback2():
|
def callback2():
|
||||||
'raises wrong exception'
|
'raises wrong exception'
|
||||||
raise AnotherError()
|
raise AnotherError()
|
||||||
|
|
||||||
def callback3():
|
def callback3():
|
||||||
'raises no exception'
|
'raises no exception'
|
||||||
|
|
||||||
f(SomeError, callback1)
|
f(SomeError, callback1)
|
||||||
|
|
||||||
raised = False
|
raised = False
|
||||||
try:
|
try:
|
||||||
f(SomeError, callback2)
|
f(SomeError, callback2)
|
||||||
except AnotherError:
|
except AnotherError:
|
||||||
raised = True
|
raised = True
|
||||||
assert raised
|
assert raised
|
||||||
|
|
||||||
raised = False
|
raised = False
|
||||||
try:
|
try:
|
||||||
f(SomeError, callback3)
|
f(SomeError, callback3)
|
||||||
except tstutil.ExceptionNotRaised:
|
except tstutil.ExceptionNotRaised:
|
||||||
raised = True
|
raised = True
|
||||||
assert raised
|
assert raised
|
||||||
|
|
||||||
|
|
||||||
def test_no_set():
|
def test_no_set():
|
||||||
# Tests that it works when prop cannot be set:
|
# Tests that it works when prop cannot be set:
|
||||||
tstutil.no_set(Prop('get', 'del'), 'prop')
|
tstutil.no_set(Prop('get', 'del'), 'prop')
|
||||||
|
|
||||||
# Tests that ExceptionNotRaised is raised when prop *can* be set:
|
# Tests that ExceptionNotRaised is raised when prop *can* be set:
|
||||||
raised = False
|
raised = False
|
||||||
try:
|
try:
|
||||||
tstutil.no_set(Prop('set'), 'prop')
|
tstutil.no_set(Prop('set'), 'prop')
|
||||||
except tstutil.ExceptionNotRaised:
|
except tstutil.ExceptionNotRaised:
|
||||||
raised = True
|
raised = True
|
||||||
assert raised
|
assert raised
|
||||||
|
|
||||||
|
|
||||||
def test_no_del():
|
def test_no_del():
|
||||||
# Tests that it works when prop cannot be deleted:
|
# Tests that it works when prop cannot be deleted:
|
||||||
tstutil.no_del(Prop('get', 'set'), 'prop')
|
tstutil.no_del(Prop('get', 'set'), 'prop')
|
||||||
|
|
||||||
# Tests that ExceptionNotRaised is raised when prop *can* be set:
|
# Tests that ExceptionNotRaised is raised when prop *can* be set:
|
||||||
raised = False
|
raised = False
|
||||||
try:
|
try:
|
||||||
tstutil.no_del(Prop('del'), 'prop')
|
tstutil.no_del(Prop('del'), 'prop')
|
||||||
except tstutil.ExceptionNotRaised:
|
except tstutil.ExceptionNotRaised:
|
||||||
raised = True
|
raised = True
|
||||||
assert raised
|
assert raised
|
||||||
|
|
||||||
|
|
||||||
def test_read_only():
|
def test_read_only():
|
||||||
# Test that it works when prop is read only:
|
# Test that it works when prop is read only:
|
||||||
assert tstutil.read_only(Prop('get'), 'prop') == 'prop value'
|
assert tstutil.read_only(Prop('get'), 'prop') == 'prop value'
|
||||||
|
|
||||||
# Test that ExceptionNotRaised is raised when prop can be set:
|
# Test that ExceptionNotRaised is raised when prop can be set:
|
||||||
raised = False
|
raised = False
|
||||||
try:
|
try:
|
||||||
tstutil.read_only(Prop('get', 'set'), 'prop')
|
tstutil.read_only(Prop('get', 'set'), 'prop')
|
||||||
except tstutil.ExceptionNotRaised:
|
except tstutil.ExceptionNotRaised:
|
||||||
raised = True
|
raised = True
|
||||||
assert raised
|
assert raised
|
||||||
|
|
||||||
# Test that ExceptionNotRaised is raised when prop can be deleted:
|
# Test that ExceptionNotRaised is raised when prop can be deleted:
|
||||||
raised = False
|
raised = False
|
||||||
try:
|
try:
|
||||||
tstutil.read_only(Prop('get', 'del'), 'prop')
|
tstutil.read_only(Prop('get', 'del'), 'prop')
|
||||||
except tstutil.ExceptionNotRaised:
|
except tstutil.ExceptionNotRaised:
|
||||||
raised = True
|
raised = True
|
||||||
assert raised
|
assert raised
|
||||||
|
|
||||||
# Test that ExceptionNotRaised is raised when prop can be both set and
|
# Test that ExceptionNotRaised is raised when prop can be both set and
|
||||||
# deleted:
|
# deleted:
|
||||||
raised = False
|
raised = False
|
||||||
try:
|
try:
|
||||||
tstutil.read_only(Prop('get', 'del'), 'prop')
|
tstutil.read_only(Prop('get', 'del'), 'prop')
|
||||||
except tstutil.ExceptionNotRaised:
|
except tstutil.ExceptionNotRaised:
|
||||||
raised = True
|
raised = True
|
||||||
assert raised
|
assert raised
|
||||||
|
|
||||||
# Test that AttributeError is raised when prop can't be read:
|
# Test that AttributeError is raised when prop can't be read:
|
||||||
raised = False
|
raised = False
|
||||||
try:
|
try:
|
||||||
tstutil.read_only(Prop(), 'prop')
|
tstutil.read_only(Prop(), 'prop')
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
raised = True
|
raised = True
|
||||||
assert raised
|
assert raised
|
||||||
|
@ -22,78 +22,78 @@ Utility functions for the unit tests.
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
class ExceptionNotRaised(Exception):
|
class ExceptionNotRaised(Exception):
|
||||||
"""
|
"""
|
||||||
Exception raised when an *expected* exception is *not* raised during a
|
Exception raised when an *expected* exception is *not* raised during a
|
||||||
unit test.
|
unit test.
|
||||||
"""
|
"""
|
||||||
msg = 'expected %s'
|
msg = 'expected %s'
|
||||||
|
|
||||||
def __init__(self, expected):
|
def __init__(self, expected):
|
||||||
self.expected = expected
|
self.expected = expected
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.msg % self.expected.__name__
|
return self.msg % self.expected.__name__
|
||||||
|
|
||||||
|
|
||||||
def raises(exception, callback, *args, **kw):
|
def raises(exception, callback, *args, **kw):
|
||||||
"""
|
"""
|
||||||
Tests that the expected exception is raised; raises ExceptionNotRaised
|
Tests that the expected exception is raised; raises ExceptionNotRaised
|
||||||
if test fails.
|
if test fails.
|
||||||
"""
|
"""
|
||||||
raised = False
|
raised = False
|
||||||
try:
|
try:
|
||||||
callback(*args, **kw)
|
callback(*args, **kw)
|
||||||
except exception, e:
|
except exception, e:
|
||||||
raised = True
|
raised = True
|
||||||
if not raised:
|
if not raised:
|
||||||
raise ExceptionNotRaised(exception)
|
raise ExceptionNotRaised(exception)
|
||||||
return e
|
return e
|
||||||
|
|
||||||
|
|
||||||
def getitem(obj, key):
|
def getitem(obj, key):
|
||||||
"""
|
"""
|
||||||
Works like getattr but for dictionary interface. Uses this in combination
|
Works like getattr but for dictionary interface. Uses this in combination
|
||||||
with raises() to test that, for example, KeyError is raised.
|
with raises() to test that, for example, KeyError is raised.
|
||||||
"""
|
"""
|
||||||
return obj[key]
|
return obj[key]
|
||||||
|
|
||||||
|
|
||||||
def no_set(obj, name, value='some_new_obj'):
|
def no_set(obj, name, value='some_new_obj'):
|
||||||
"""
|
"""
|
||||||
Tests that attribute cannot be set.
|
Tests that attribute cannot be set.
|
||||||
"""
|
"""
|
||||||
raises(AttributeError, setattr, obj, name, value)
|
raises(AttributeError, setattr, obj, name, value)
|
||||||
|
|
||||||
|
|
||||||
def no_del(obj, name):
|
def no_del(obj, name):
|
||||||
"""
|
"""
|
||||||
Tests that attribute cannot be deleted.
|
Tests that attribute cannot be deleted.
|
||||||
"""
|
"""
|
||||||
raises(AttributeError, delattr, obj, name)
|
raises(AttributeError, delattr, obj, name)
|
||||||
|
|
||||||
|
|
||||||
def read_only(obj, name, value='some_new_obj'):
|
def read_only(obj, name, value='some_new_obj'):
|
||||||
"""
|
"""
|
||||||
Tests that attribute is read-only. Returns attribute.
|
Tests that attribute is read-only. Returns attribute.
|
||||||
"""
|
"""
|
||||||
# Test that it cannot be set:
|
# Test that it cannot be set:
|
||||||
no_set(obj, name, value)
|
no_set(obj, name, value)
|
||||||
|
|
||||||
# Test that it cannot be deleted:
|
# Test that it cannot be deleted:
|
||||||
no_del(obj, name)
|
no_del(obj, name)
|
||||||
|
|
||||||
# Return the attribute
|
# Return the attribute
|
||||||
return getattr(obj, name)
|
return getattr(obj, name)
|
||||||
|
|
||||||
|
|
||||||
def is_prop(prop):
|
def is_prop(prop):
|
||||||
return type(prop) is property
|
return type(prop) is property
|
||||||
|
|
||||||
|
|
||||||
class ClassChecker(object):
|
class ClassChecker(object):
|
||||||
|
|
||||||
def new(self, *args, **kw):
|
def new(self, *args, **kw):
|
||||||
return self.cls(*args, **kw)
|
return self.cls(*args, **kw)
|
||||||
|
|
||||||
def get_sub(self):
|
def get_sub(self):
|
||||||
raise NotImplementedError('get_sub()')
|
raise NotImplementedError('get_sub()')
|
||||||
|
Loading…
Reference in New Issue
Block a user