frontend: Change doc, summary, topic and NO_CLI to class properties

Avoid need to instantiate all commands just to get information for
displaying help.

https://fedorahosted.org/freeipa/ticket/6048

Reviewed-By: Jan Cholasta <jcholast@redhat.com>
This commit is contained in:
David Kupka
2016-08-03 16:32:39 +02:00
committed by Jan Cholasta
parent 47a693d174
commit 29f7f822ab
7 changed files with 120 additions and 47 deletions
+22 -10
View File
@@ -2,9 +2,11 @@
# Copyright (C) 2016 FreeIPA Contributors see COPYING for license
#
from ipalib import api
from ipalib.frontend import Command, Method
from ipalib.parameters import Str
from ipalib.text import _
from ipalib.util import classproperty
class ClientCommand(Command):
@@ -111,20 +113,30 @@ class CommandOverride(Command):
def __init__(self, api):
super(CommandOverride, self).__init__(api)
next_class = api.get_plugin_next(type(self))
next_class = self.__get_next()
self.next = next_class(api)
@property
def doc(self):
return self.next.doc
@classmethod
def __get_next(cls):
return api.get_plugin_next(cls)
@property
def NO_CLI(self):
return self.next.NO_CLI
@classmethod
def __doc_getter(cls):
return cls.__get_next().doc
@property
def topic(self):
return self.next.topic
doc = classproperty(__doc_getter)
@classmethod
def __NO_CLI_getter(cls):
return cls.__get_next().NO_CLI
NO_CLI = classproperty(__NO_CLI_getter)
@classmethod
def __topic_getter(cls):
return cls.__get_next().topic
topic = classproperty(__topic_getter)
@property
def forwarded_name(self):
+6 -3
View File
@@ -27,6 +27,7 @@ from ipalib import api, errors
from ipalib import Flag, Str
from ipalib.frontend import Command, Method, Object
from ipalib.plugable import Registry
from ipalib.util import classproperty
from ipalib import _
from ipapython.dn import DN
@@ -52,11 +53,13 @@ class _fake_automountlocation_show(Method):
@register(override=True, no_fail=True)
class automountlocation_tofiles(MethodOverride):
@property
def NO_CLI(self):
return isinstance(self.api.Command.automountlocation_show,
@classmethod
def __NO_CLI_getter(cls):
return isinstance(api.Command.automountlocation_show,
_fake_automountlocation_show)
NO_CLI = classproperty(__NO_CLI_getter)
def output_for_cli(self, textui, result, *keys, **options):
maps = result['result']['maps']
keys = result['result']['keys']
+7 -4
View File
@@ -23,10 +23,11 @@ import six
import usb.core
import yubico
from ipalib import _, IntEnum
from ipalib import _, api, IntEnum
from ipalib.errors import NotFound
from ipalib.frontend import Command, Method, Object
from ipalib.plugable import Registry
from ipalib.util import classproperty
if six.PY3:
unicode = str
@@ -74,11 +75,13 @@ class otptoken_add_yubikey(Command):
)
has_output_params = takes_options
@property
def NO_CLI(self):
return isinstance(self.api.Command.otptoken_add,
@classmethod
def __NO_CLI_getter(cls):
return isinstance(api.Command.otptoken_add,
_fake_otptoken_add)
NO_CLI = classproperty(__NO_CLI_getter)
def get_args(self):
for arg in self.api.Command.otptoken_add.args():
yield arg
+22 -13
View File
@@ -38,7 +38,8 @@ import nss.nss as nss
from ipaclient.frontend import MethodOverride
from ipalib.frontend import Local, Method, Object
from ipalib import errors
from ipalib.util import classproperty
from ipalib import api, errors
from ipalib import Bytes, Flag, Str
from ipalib.plugable import Registry
from ipalib import _
@@ -202,11 +203,13 @@ class vault_add(Local):
),
)
@property
def NO_CLI(self):
return isinstance(self.api.Command.vault_add_internal,
@classmethod
def __NO_CLI_getter(cls):
return isinstance(api.Command.vault_add_internal,
_fake_vault_add_internal)
NO_CLI = classproperty(__NO_CLI_getter)
def get_args(self):
for arg in self.api.Command.vault_add_internal.args():
yield arg
@@ -400,11 +403,13 @@ class vault_mod(Local):
),
)
@property
def NO_CLI(self):
return isinstance(self.api.Command.vault_mod_internal,
@classmethod
def __NO_CLI_getter(cls):
return isinstance(api.Command.vault_mod_internal,
_fake_vault_mod_internal)
NO_CLI = classproperty(__NO_CLI_getter)
def get_args(self):
for arg in self.api.Command.vault_mod_internal.args():
yield arg
@@ -579,11 +584,13 @@ class vault_archive(Local):
),
)
@property
def NO_CLI(self):
return isinstance(self.api.Command.vault_archive_internal,
@classmethod
def __NO_CLI_getter(cls):
return isinstance(api.Command.vault_archive_internal,
_fake_vault_archive_internal)
NO_CLI = classproperty(__NO_CLI_getter)
def get_args(self):
for arg in self.api.Command.vault_archive_internal.args():
yield arg
@@ -828,11 +835,13 @@ class vault_retrieve(Local):
),
)
@property
def NO_CLI(self):
return isinstance(self.api.Command.vault_retrieve_internal,
@classmethod
def __NO_CLI_getter(cls):
return isinstance(api.Command.vault_retrieve_internal,
_fake_vault_retrieve_internal)
NO_CLI = classproperty(__NO_CLI_getter)
def get_args(self):
for arg in self.api.Command.vault_retrieve_internal.args():
yield arg
+47 -6
View File
@@ -89,10 +89,32 @@ class _SchemaPlugin(object):
bases = None
schema_key = None
def __init__(self, full_name):
def __init__(self, schema, full_name):
self.name, _slash, self.version = full_name.partition('/')
self.full_name = full_name
self.__class = None
self._schema = schema
self._class = None
@property
def doc(self):
if self._class is not None:
return self._class.doc
else:
schema = self._schema[self.schema_key][self.full_name]
try:
return schema['doc']
except KeyError:
return None
@property
def summary(self):
if self._class is not None:
return self._class.summary
else:
if self.doc is not None:
return self.doc.split('\n\n', 1)[0].strip()
else:
return u'<%s>' % self.full_name
def _create_default_from(self, api, name, keys):
cmd_name = self.full_name
@@ -200,18 +222,37 @@ class _SchemaPlugin(object):
return self.name, self.bases, class_dict
def __call__(self, api):
if self.__class is None:
if self._class is None:
schema = api._schema[self.schema_key][self.full_name]
name, bases, class_dict = self._create_class(api, schema)
self.__class = type(name, bases, class_dict)
self._class = type(name, bases, class_dict)
return self.__class(api)
return self._class(api)
class _SchemaCommandPlugin(_SchemaPlugin):
bases = (_SchemaCommand,)
schema_key = 'commands'
@property
def topic(self):
if self._class is not None:
return self._class.topic
else:
schema = self._schema[self.schema_key][self.full_name]
try:
return str(schema['topic_topic']).partition('/')[0]
except KeyError:
return None
@property
def NO_CLI(self):
if self._class is not None:
return self._class.NO_CLI
else:
schema = self._schema[self.schema_key][self.full_name]
return 'cli' in schema.get('exclude', [])
def _create_output(self, api, schema):
if schema.get('multivalue', False):
type_type = (tuple, list)
@@ -565,7 +606,7 @@ def get_package(api, client):
module.register = plugable.Registry()
for plugin_cls in (_SchemaCommandPlugin, _SchemaObjectPlugin):
for full_name in schema[plugin_cls.schema_key]:
plugin = plugin_cls(str(full_name))
plugin = plugin_cls(schema, str(full_name))
plugin = module.register()(plugin)
sys.modules[module_name] = module
+6 -4
View File
@@ -38,7 +38,7 @@ from ipalib.errors import (ZeroArgumentError, MaxArgumentError, OverlapError,
ValidationError, ConversionError)
from ipalib import errors, messages
from ipalib.request import context, context_frame
from ipalib.util import json_serialize
from ipalib.util import classproperty, json_serialize
if six.PY3:
unicode = str
@@ -426,9 +426,11 @@ class Command(HasParam):
api_version = API_VERSION
@property
def topic(self):
return type(self).__module__.rpartition('.')[2]
@classmethod
def __topic_getter(cls):
return cls.__module__.rpartition('.')[2]
topic = classproperty(__topic_getter)
@property
def forwarded_name(self):
+10 -7
View File
@@ -155,19 +155,22 @@ class Plugin(ReadOnly):
bases = classproperty(__bases_getter)
@property
def doc(self):
return type(self).__doc__
@classmethod
def __doc_getter(cls):
return cls.__doc__
@property
def summary(self):
doc = self.doc
doc = classproperty(__doc_getter)
@classmethod
def __summary_getter(cls):
doc = cls.doc
if not _(doc).msg:
cls = type(self)
return u'<%s.%s>' % (cls.__module__, cls.__name__)
else:
return unicode(doc).split('\n\n', 1)[0].strip()
summary = classproperty(__summary_getter)
@property
def api(self):
"""