|
|
403b09 |
From 8293d36c504b59a6dac46187baf51719ab355fd2 Mon Sep 17 00:00:00 2001
|
|
|
403b09 |
From: David Kupka <dkupka@redhat.com>
|
|
|
403b09 |
Date: Wed, 20 Jul 2016 13:23:33 +0200
|
|
|
403b09 |
Subject: [PATCH] frontend: Change doc, summary, topic and NO_CLI to class
|
|
|
403b09 |
properties
|
|
|
403b09 |
|
|
|
403b09 |
Avoid need to instantiate all commands just to get information for
|
|
|
403b09 |
displaying help.
|
|
|
403b09 |
|
|
|
403b09 |
https://fedorahosted.org/freeipa/ticket/6048
|
|
|
403b09 |
|
|
|
403b09 |
Reviewed-By: Jan Cholasta <jcholast@redhat.com>
|
|
|
403b09 |
---
|
|
|
403b09 |
ipaclient/frontend.py | 32 ++++++++++++++-------
|
|
|
403b09 |
ipaclient/plugins/automount.py | 9 ++++--
|
|
|
403b09 |
ipaclient/plugins/otptoken_yubikey.py | 11 +++++---
|
|
|
403b09 |
ipaclient/plugins/vault.py | 35 ++++++++++++++---------
|
|
|
403b09 |
ipaclient/remote_plugins/schema.py | 53 +++++++++++++++++++++++++++++++----
|
|
|
403b09 |
ipalib/frontend.py | 10 ++++---
|
|
|
403b09 |
ipalib/plugable.py | 17 ++++++-----
|
|
|
403b09 |
7 files changed, 120 insertions(+), 47 deletions(-)
|
|
|
403b09 |
|
|
|
403b09 |
diff --git a/ipaclient/frontend.py b/ipaclient/frontend.py
|
|
|
403b09 |
index 1525c88b3dfeadccd8115cb4b6ba149caef22103..aeaed550771d3c6af04a9b34fcae414faacb47d7 100644
|
|
|
403b09 |
--- a/ipaclient/frontend.py
|
|
|
403b09 |
+++ b/ipaclient/frontend.py
|
|
|
403b09 |
@@ -2,9 +2,11 @@
|
|
|
403b09 |
# Copyright (C) 2016 FreeIPA Contributors see COPYING for license
|
|
|
403b09 |
#
|
|
|
403b09 |
|
|
|
403b09 |
+from ipalib import api
|
|
|
403b09 |
from ipalib.frontend import Command, Method
|
|
|
403b09 |
from ipalib.parameters import Str
|
|
|
403b09 |
from ipalib.text import _
|
|
|
403b09 |
+from ipalib.util import classproperty
|
|
|
403b09 |
|
|
|
403b09 |
|
|
|
403b09 |
class ClientCommand(Command):
|
|
|
403b09 |
@@ -111,20 +113,30 @@ class CommandOverride(Command):
|
|
|
403b09 |
def __init__(self, api):
|
|
|
403b09 |
super(CommandOverride, self).__init__(api)
|
|
|
403b09 |
|
|
|
403b09 |
- next_class = api.get_plugin_next(type(self))
|
|
|
403b09 |
+ next_class = self.__get_next()
|
|
|
403b09 |
self.next = next_class(api)
|
|
|
403b09 |
|
|
|
403b09 |
- @property
|
|
|
403b09 |
- def doc(self):
|
|
|
403b09 |
- return self.next.doc
|
|
|
403b09 |
+ @classmethod
|
|
|
403b09 |
+ def __get_next(cls):
|
|
|
403b09 |
+ return api.get_plugin_next(cls)
|
|
|
403b09 |
|
|
|
403b09 |
- @property
|
|
|
403b09 |
- def NO_CLI(self):
|
|
|
403b09 |
- return self.next.NO_CLI
|
|
|
403b09 |
+ @classmethod
|
|
|
403b09 |
+ def __doc_getter(cls):
|
|
|
403b09 |
+ return cls.__get_next().doc
|
|
|
403b09 |
|
|
|
403b09 |
- @property
|
|
|
403b09 |
- def topic(self):
|
|
|
403b09 |
- return self.next.topic
|
|
|
403b09 |
+ doc = classproperty(__doc_getter)
|
|
|
403b09 |
+
|
|
|
403b09 |
+ @classmethod
|
|
|
403b09 |
+ def __NO_CLI_getter(cls):
|
|
|
403b09 |
+ return cls.__get_next().NO_CLI
|
|
|
403b09 |
+
|
|
|
403b09 |
+ NO_CLI = classproperty(__NO_CLI_getter)
|
|
|
403b09 |
+
|
|
|
403b09 |
+ @classmethod
|
|
|
403b09 |
+ def __topic_getter(cls):
|
|
|
403b09 |
+ return cls.__get_next().topic
|
|
|
403b09 |
+
|
|
|
403b09 |
+ topic = classproperty(__topic_getter)
|
|
|
403b09 |
|
|
|
403b09 |
@property
|
|
|
403b09 |
def forwarded_name(self):
|
|
|
403b09 |
diff --git a/ipaclient/plugins/automount.py b/ipaclient/plugins/automount.py
|
|
|
403b09 |
index c6537bc6c24b905a8e1f7fb6a7e2c931b95374c7..925b635ff27411fc7e2f8c3dae17c747216d7fb6 100644
|
|
|
403b09 |
--- a/ipaclient/plugins/automount.py
|
|
|
403b09 |
+++ b/ipaclient/plugins/automount.py
|
|
|
403b09 |
@@ -27,6 +27,7 @@ from ipalib import api, errors
|
|
|
403b09 |
from ipalib import Flag, Str
|
|
|
403b09 |
from ipalib.frontend import Command, Method, Object
|
|
|
403b09 |
from ipalib.plugable import Registry
|
|
|
403b09 |
+from ipalib.util import classproperty
|
|
|
403b09 |
from ipalib import _
|
|
|
403b09 |
from ipapython.dn import DN
|
|
|
403b09 |
|
|
|
403b09 |
@@ -52,11 +53,13 @@ class _fake_automountlocation_show(Method):
|
|
|
403b09 |
|
|
|
403b09 |
@register(override=True, no_fail=True)
|
|
|
403b09 |
class automountlocation_tofiles(MethodOverride):
|
|
|
403b09 |
- @property
|
|
|
403b09 |
- def NO_CLI(self):
|
|
|
403b09 |
- return isinstance(self.api.Command.automountlocation_show,
|
|
|
403b09 |
+ @classmethod
|
|
|
403b09 |
+ def __NO_CLI_getter(cls):
|
|
|
403b09 |
+ return isinstance(api.Command.automountlocation_show,
|
|
|
403b09 |
_fake_automountlocation_show)
|
|
|
403b09 |
|
|
|
403b09 |
+ NO_CLI = classproperty(__NO_CLI_getter)
|
|
|
403b09 |
+
|
|
|
403b09 |
def output_for_cli(self, textui, result, *keys, **options):
|
|
|
403b09 |
maps = result['result']['maps']
|
|
|
403b09 |
keys = result['result']['keys']
|
|
|
403b09 |
diff --git a/ipaclient/plugins/otptoken_yubikey.py b/ipaclient/plugins/otptoken_yubikey.py
|
|
|
403b09 |
index 3c310eacbaeef654e43049db78437c8c29f52279..549376a0ff65d44c5698666a84608849152368b2 100644
|
|
|
403b09 |
--- a/ipaclient/plugins/otptoken_yubikey.py
|
|
|
403b09 |
+++ b/ipaclient/plugins/otptoken_yubikey.py
|
|
|
403b09 |
@@ -23,10 +23,11 @@ import six
|
|
|
403b09 |
import usb.core
|
|
|
403b09 |
import yubico
|
|
|
403b09 |
|
|
|
403b09 |
-from ipalib import _, IntEnum
|
|
|
403b09 |
+from ipalib import _, api, IntEnum
|
|
|
403b09 |
from ipalib.errors import NotFound
|
|
|
403b09 |
from ipalib.frontend import Command, Method, Object
|
|
|
403b09 |
from ipalib.plugable import Registry
|
|
|
403b09 |
+from ipalib.util import classproperty
|
|
|
403b09 |
|
|
|
403b09 |
if six.PY3:
|
|
|
403b09 |
unicode = str
|
|
|
403b09 |
@@ -74,11 +75,13 @@ class otptoken_add_yubikey(Command):
|
|
|
403b09 |
)
|
|
|
403b09 |
has_output_params = takes_options
|
|
|
403b09 |
|
|
|
403b09 |
- @property
|
|
|
403b09 |
- def NO_CLI(self):
|
|
|
403b09 |
- return isinstance(self.api.Command.otptoken_add,
|
|
|
403b09 |
+ @classmethod
|
|
|
403b09 |
+ def __NO_CLI_getter(cls):
|
|
|
403b09 |
+ return isinstance(api.Command.otptoken_add,
|
|
|
403b09 |
_fake_otptoken_add)
|
|
|
403b09 |
|
|
|
403b09 |
+ NO_CLI = classproperty(__NO_CLI_getter)
|
|
|
403b09 |
+
|
|
|
403b09 |
def get_args(self):
|
|
|
403b09 |
for arg in self.api.Command.otptoken_add.args():
|
|
|
403b09 |
yield arg
|
|
|
403b09 |
diff --git a/ipaclient/plugins/vault.py b/ipaclient/plugins/vault.py
|
|
|
403b09 |
index 3e116bbad54fea419b571d1f09c1b00280e94991..c0ded21d515fe41bde5fb0e547087cb7789aa6a3 100644
|
|
|
403b09 |
--- a/ipaclient/plugins/vault.py
|
|
|
403b09 |
+++ b/ipaclient/plugins/vault.py
|
|
|
403b09 |
@@ -38,7 +38,8 @@ import nss.nss as nss
|
|
|
403b09 |
|
|
|
403b09 |
from ipaclient.frontend import MethodOverride
|
|
|
403b09 |
from ipalib.frontend import Local, Method, Object
|
|
|
403b09 |
-from ipalib import errors
|
|
|
403b09 |
+from ipalib.util import classproperty
|
|
|
403b09 |
+from ipalib import api, errors
|
|
|
403b09 |
from ipalib import Bytes, Flag, Str
|
|
|
403b09 |
from ipalib.plugable import Registry
|
|
|
403b09 |
from ipalib import _
|
|
|
403b09 |
@@ -202,11 +203,13 @@ class vault_add(Local):
|
|
|
403b09 |
),
|
|
|
403b09 |
)
|
|
|
403b09 |
|
|
|
403b09 |
- @property
|
|
|
403b09 |
- def NO_CLI(self):
|
|
|
403b09 |
- return isinstance(self.api.Command.vault_add_internal,
|
|
|
403b09 |
+ @classmethod
|
|
|
403b09 |
+ def __NO_CLI_getter(cls):
|
|
|
403b09 |
+ return isinstance(api.Command.vault_add_internal,
|
|
|
403b09 |
_fake_vault_add_internal)
|
|
|
403b09 |
|
|
|
403b09 |
+ NO_CLI = classproperty(__NO_CLI_getter)
|
|
|
403b09 |
+
|
|
|
403b09 |
def get_args(self):
|
|
|
403b09 |
for arg in self.api.Command.vault_add_internal.args():
|
|
|
403b09 |
yield arg
|
|
|
403b09 |
@@ -406,11 +409,13 @@ class vault_mod(Local):
|
|
|
403b09 |
),
|
|
|
403b09 |
)
|
|
|
403b09 |
|
|
|
403b09 |
- @property
|
|
|
403b09 |
- def NO_CLI(self):
|
|
|
403b09 |
- return isinstance(self.api.Command.vault_mod_internal,
|
|
|
403b09 |
+ @classmethod
|
|
|
403b09 |
+ def __NO_CLI_getter(cls):
|
|
|
403b09 |
+ return isinstance(api.Command.vault_mod_internal,
|
|
|
403b09 |
_fake_vault_mod_internal)
|
|
|
403b09 |
|
|
|
403b09 |
+ NO_CLI = classproperty(__NO_CLI_getter)
|
|
|
403b09 |
+
|
|
|
403b09 |
def get_args(self):
|
|
|
403b09 |
for arg in self.api.Command.vault_mod_internal.args():
|
|
|
403b09 |
yield arg
|
|
|
403b09 |
@@ -591,11 +596,13 @@ class vault_archive(Local):
|
|
|
403b09 |
),
|
|
|
403b09 |
)
|
|
|
403b09 |
|
|
|
403b09 |
- @property
|
|
|
403b09 |
- def NO_CLI(self):
|
|
|
403b09 |
- return isinstance(self.api.Command.vault_archive_internal,
|
|
|
403b09 |
+ @classmethod
|
|
|
403b09 |
+ def __NO_CLI_getter(cls):
|
|
|
403b09 |
+ return isinstance(api.Command.vault_archive_internal,
|
|
|
403b09 |
_fake_vault_archive_internal)
|
|
|
403b09 |
|
|
|
403b09 |
+ NO_CLI = classproperty(__NO_CLI_getter)
|
|
|
403b09 |
+
|
|
|
403b09 |
def get_args(self):
|
|
|
403b09 |
for arg in self.api.Command.vault_archive_internal.args():
|
|
|
403b09 |
yield arg
|
|
|
403b09 |
@@ -846,11 +853,13 @@ class vault_retrieve(Local):
|
|
|
403b09 |
),
|
|
|
403b09 |
)
|
|
|
403b09 |
|
|
|
403b09 |
- @property
|
|
|
403b09 |
- def NO_CLI(self):
|
|
|
403b09 |
- return isinstance(self.api.Command.vault_retrieve_internal,
|
|
|
403b09 |
+ @classmethod
|
|
|
403b09 |
+ def __NO_CLI_getter(cls):
|
|
|
403b09 |
+ return isinstance(api.Command.vault_retrieve_internal,
|
|
|
403b09 |
_fake_vault_retrieve_internal)
|
|
|
403b09 |
|
|
|
403b09 |
+ NO_CLI = classproperty(__NO_CLI_getter)
|
|
|
403b09 |
+
|
|
|
403b09 |
def get_args(self):
|
|
|
403b09 |
for arg in self.api.Command.vault_retrieve_internal.args():
|
|
|
403b09 |
yield arg
|
|
|
403b09 |
diff --git a/ipaclient/remote_plugins/schema.py b/ipaclient/remote_plugins/schema.py
|
|
|
403b09 |
index d039fb41991c26a9c7b7f76f6959668efb677586..f165736cde6f08d6d22c17070d570da261799e4b 100644
|
|
|
403b09 |
--- a/ipaclient/remote_plugins/schema.py
|
|
|
403b09 |
+++ b/ipaclient/remote_plugins/schema.py
|
|
|
403b09 |
@@ -89,10 +89,32 @@ class _SchemaPlugin(object):
|
|
|
403b09 |
bases = None
|
|
|
403b09 |
schema_key = None
|
|
|
403b09 |
|
|
|
403b09 |
- def __init__(self, full_name):
|
|
|
403b09 |
+ def __init__(self, schema, full_name):
|
|
|
403b09 |
self.name, _slash, self.version = full_name.partition('/')
|
|
|
403b09 |
self.full_name = full_name
|
|
|
403b09 |
- self.__class = None
|
|
|
403b09 |
+ self._schema = schema
|
|
|
403b09 |
+ self._class = None
|
|
|
403b09 |
+
|
|
|
403b09 |
+ @property
|
|
|
403b09 |
+ def doc(self):
|
|
|
403b09 |
+ if self._class is not None:
|
|
|
403b09 |
+ return self._class.doc
|
|
|
403b09 |
+ else:
|
|
|
403b09 |
+ schema = self._schema[self.schema_key][self.full_name]
|
|
|
403b09 |
+ try:
|
|
|
403b09 |
+ return schema['doc']
|
|
|
403b09 |
+ except KeyError:
|
|
|
403b09 |
+ return None
|
|
|
403b09 |
+
|
|
|
403b09 |
+ @property
|
|
|
403b09 |
+ def summary(self):
|
|
|
403b09 |
+ if self._class is not None:
|
|
|
403b09 |
+ return self._class.summary
|
|
|
403b09 |
+ else:
|
|
|
403b09 |
+ if self.doc is not None:
|
|
|
403b09 |
+ return self.doc.split('\n\n', 1)[0].strip()
|
|
|
403b09 |
+ else:
|
|
|
403b09 |
+ return u'<%s>' % self.full_name
|
|
|
403b09 |
|
|
|
403b09 |
def _create_default_from(self, api, name, keys):
|
|
|
403b09 |
cmd_name = self.full_name
|
|
|
403b09 |
@@ -200,18 +222,37 @@ class _SchemaPlugin(object):
|
|
|
403b09 |
return self.name, self.bases, class_dict
|
|
|
403b09 |
|
|
|
403b09 |
def __call__(self, api):
|
|
|
403b09 |
- if self.__class is None:
|
|
|
403b09 |
+ if self._class is None:
|
|
|
403b09 |
schema = api._schema[self.schema_key][self.full_name]
|
|
|
403b09 |
name, bases, class_dict = self._create_class(api, schema)
|
|
|
403b09 |
- self.__class = type(name, bases, class_dict)
|
|
|
403b09 |
+ self._class = type(name, bases, class_dict)
|
|
|
403b09 |
|
|
|
403b09 |
- return self.__class(api)
|
|
|
403b09 |
+ return self._class(api)
|
|
|
403b09 |
|
|
|
403b09 |
|
|
|
403b09 |
class _SchemaCommandPlugin(_SchemaPlugin):
|
|
|
403b09 |
bases = (_SchemaCommand,)
|
|
|
403b09 |
schema_key = 'commands'
|
|
|
403b09 |
|
|
|
403b09 |
+ @property
|
|
|
403b09 |
+ def topic(self):
|
|
|
403b09 |
+ if self._class is not None:
|
|
|
403b09 |
+ return self._class.topic
|
|
|
403b09 |
+ else:
|
|
|
403b09 |
+ schema = self._schema[self.schema_key][self.full_name]
|
|
|
403b09 |
+ try:
|
|
|
403b09 |
+ return str(schema['topic_topic']).partition('/')[0]
|
|
|
403b09 |
+ except KeyError:
|
|
|
403b09 |
+ return None
|
|
|
403b09 |
+
|
|
|
403b09 |
+ @property
|
|
|
403b09 |
+ def NO_CLI(self):
|
|
|
403b09 |
+ if self._class is not None:
|
|
|
403b09 |
+ return self._class.NO_CLI
|
|
|
403b09 |
+ else:
|
|
|
403b09 |
+ schema = self._schema[self.schema_key][self.full_name]
|
|
|
403b09 |
+ return 'cli' in schema.get('exclude', [])
|
|
|
403b09 |
+
|
|
|
403b09 |
def _create_output(self, api, schema):
|
|
|
403b09 |
if schema.get('multivalue', False):
|
|
|
403b09 |
type_type = (tuple, list)
|
|
|
403b09 |
@@ -565,7 +606,7 @@ def get_package(api, client):
|
|
|
403b09 |
module.register = plugable.Registry()
|
|
|
403b09 |
for plugin_cls in (_SchemaCommandPlugin, _SchemaObjectPlugin):
|
|
|
403b09 |
for full_name in schema[plugin_cls.schema_key]:
|
|
|
403b09 |
- plugin = plugin_cls(str(full_name))
|
|
|
403b09 |
+ plugin = plugin_cls(schema, str(full_name))
|
|
|
403b09 |
plugin = module.register()(plugin)
|
|
|
403b09 |
sys.modules[module_name] = module
|
|
|
403b09 |
|
|
|
403b09 |
diff --git a/ipalib/frontend.py b/ipalib/frontend.py
|
|
|
403b09 |
index cb00841f21bd5a3e3b4095dcd17a8816ca24400f..455b222d4d7fcbb65b43c4d8e1ffbbaf3e131d22 100644
|
|
|
403b09 |
--- a/ipalib/frontend.py
|
|
|
403b09 |
+++ b/ipalib/frontend.py
|
|
|
403b09 |
@@ -38,7 +38,7 @@ from ipalib.errors import (ZeroArgumentError, MaxArgumentError, OverlapError,
|
|
|
403b09 |
ValidationError, ConversionError)
|
|
|
403b09 |
from ipalib import errors, messages
|
|
|
403b09 |
from ipalib.request import context, context_frame
|
|
|
403b09 |
-from ipalib.util import json_serialize
|
|
|
403b09 |
+from ipalib.util import classproperty, json_serialize
|
|
|
403b09 |
|
|
|
403b09 |
if six.PY3:
|
|
|
403b09 |
unicode = str
|
|
|
403b09 |
@@ -426,9 +426,11 @@ class Command(HasParam):
|
|
|
403b09 |
|
|
|
403b09 |
api_version = API_VERSION
|
|
|
403b09 |
|
|
|
403b09 |
- @property
|
|
|
403b09 |
- def topic(self):
|
|
|
403b09 |
- return type(self).__module__.rpartition('.')[2]
|
|
|
403b09 |
+ @classmethod
|
|
|
403b09 |
+ def __topic_getter(cls):
|
|
|
403b09 |
+ return cls.__module__.rpartition('.')[2]
|
|
|
403b09 |
+
|
|
|
403b09 |
+ topic = classproperty(__topic_getter)
|
|
|
403b09 |
|
|
|
403b09 |
@property
|
|
|
403b09 |
def forwarded_name(self):
|
|
|
403b09 |
diff --git a/ipalib/plugable.py b/ipalib/plugable.py
|
|
|
403b09 |
index 26fbeaa26d7986f2e184f0974ef396bd323d6bf5..073ad05d7aee5e83cae5c6e20bac8f9439505198 100644
|
|
|
403b09 |
--- a/ipalib/plugable.py
|
|
|
403b09 |
+++ b/ipalib/plugable.py
|
|
|
403b09 |
@@ -155,19 +155,22 @@ class Plugin(ReadOnly):
|
|
|
403b09 |
|
|
|
403b09 |
bases = classproperty(__bases_getter)
|
|
|
403b09 |
|
|
|
403b09 |
- @property
|
|
|
403b09 |
- def doc(self):
|
|
|
403b09 |
- return type(self).__doc__
|
|
|
403b09 |
+ @classmethod
|
|
|
403b09 |
+ def __doc_getter(cls):
|
|
|
403b09 |
+ return cls.__doc__
|
|
|
403b09 |
|
|
|
403b09 |
- @property
|
|
|
403b09 |
- def summary(self):
|
|
|
403b09 |
- doc = self.doc
|
|
|
403b09 |
+ doc = classproperty(__doc_getter)
|
|
|
403b09 |
+
|
|
|
403b09 |
+ @classmethod
|
|
|
403b09 |
+ def __summary_getter(cls):
|
|
|
403b09 |
+ doc = cls.doc
|
|
|
403b09 |
if not _(doc).msg:
|
|
|
403b09 |
- cls = type(self)
|
|
|
403b09 |
return u'<%s.%s>' % (cls.__module__, cls.__name__)
|
|
|
403b09 |
else:
|
|
|
403b09 |
return unicode(doc).split('\n\n', 1)[0].strip()
|
|
|
403b09 |
|
|
|
403b09 |
+ summary = classproperty(__summary_getter)
|
|
|
403b09 |
+
|
|
|
403b09 |
@property
|
|
|
403b09 |
def api(self):
|
|
|
403b09 |
"""
|
|
|
403b09 |
--
|
|
|
403b09 |
2.7.4
|
|
|
403b09 |
|