schema: Generate bits for help load them on request

Store name, summary, topic_topic and exclude in single entry in cache
for all commands. These data are needed for help and storing and
loading them together allows fast help response.

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

Reviewed-By: Jan Cholasta <jcholast@redhat.com>
This commit is contained in:
David Kupka 2016-08-02 08:16:30 +02:00 committed by Jan Cholasta
parent 86977070e1
commit 23609d5955

View File

@ -23,7 +23,7 @@ from ipapython.dn import DN
from ipapython.dnsutil import DNSName from ipapython.dnsutil import DNSName
from ipapython.ipa_log_manager import log_mgr from ipapython.ipa_log_manager import log_mgr
FORMAT = '0' FORMAT = '1'
if six.PY3: if six.PY3:
unicode = str unicode = str
@ -113,9 +113,11 @@ class _SchemaPlugin(object):
if self._class is not None: if self._class is not None:
return self._class.summary return self._class.summary
else: else:
if self.doc is not None: self._schema.load_help()
return self.doc.split('\n\n', 1)[0].strip() schema = self._schema[self.schema_key][self.full_name]
else: try:
return schema['summary']
except KeyError:
return u'<%s>' % self.full_name return u'<%s>' % self.full_name
def _create_default_from(self, api, name, keys): def _create_default_from(self, api, name, keys):
@ -241,6 +243,7 @@ class _SchemaCommandPlugin(_SchemaPlugin):
if self._class is not None: if self._class is not None:
return self._class.topic return self._class.topic
else: else:
self._schema.load_help()
schema = self._schema[self.schema_key][self.full_name] schema = self._schema[self.schema_key][self.full_name]
try: try:
return str(schema['topic_topic']).partition('/')[0] return str(schema['topic_topic']).partition('/')[0]
@ -252,6 +255,7 @@ class _SchemaCommandPlugin(_SchemaPlugin):
if self._class is not None: if self._class is not None:
return self._class.NO_CLI return self._class.NO_CLI
else: else:
self._schema.load_help()
schema = self._schema[self.schema_key][self.full_name] schema = self._schema[self.schema_key][self.full_name]
return 'cli' in schema.get('exclude', []) return 'cli' in schema.get('exclude', [])
@ -432,7 +436,6 @@ class Schema(object):
""" """
namespaces = {'classes', 'commands', 'topics'} namespaces = {'classes', 'commands', 'topics'}
schema_info_path = 'schema'
_DIR = os.path.join(USER_CACHE_PATH, 'ipa', 'schema') _DIR = os.path.join(USER_CACHE_PATH, 'ipa', 'schema')
def __init__(self, api, server_info, client): def __init__(self, api, server_info, client):
@ -488,8 +491,7 @@ class Schema(object):
if fmt != FORMAT: if fmt != FORMAT:
raise RuntimeError('invalid format') raise RuntimeError('invalid format')
schema_info = json.loads(schema.read(self.schema_info_path)) return json.loads(schema.read('fingerprint'))
return schema_info['fingerprint']
def _fetch(self, client): def _fetch(self, client):
if not client.isconnected(): if not client.isconnected():
@ -522,6 +524,7 @@ class Schema(object):
else: else:
fp = schema['fingerprint'] fp = schema['fingerprint']
ttl = schema.pop('ttl', 0) ttl = schema.pop('ttl', 0)
schema.pop('version', None)
for key, value in schema.items(): for key, value in schema.items():
if key in self.namespaces: if key in self.namespaces:
@ -534,8 +537,6 @@ class Schema(object):
def _read_schema(self): def _read_schema(self):
with self._open_schema(self._fingerprint, 'r') as schema: with self._open_schema(self._fingerprint, 'r') as schema:
self._dict['fingerprint'] = self._get_schema_fingerprint(schema) self._dict['fingerprint'] = self._get_schema_fingerprint(schema)
schema_info = json.loads(schema.read(self.schema_info_path))
self._dict['version'] = schema_info['version']
for name in schema.namelist(): for name in schema.namelist():
ns, _slash, key = name.partition('/') ns, _slash, key = name.partition('/')
@ -548,6 +549,27 @@ class Schema(object):
except KeyError: except KeyError:
return self._dict[key] return self._dict[key]
def _generate_help(self, schema):
halp = {}
for namespace in ('commands', 'topics'):
halp[namespace] = {}
for member_schema in schema[namespace].values():
member_full_name = member_schema['full_name']
topic = halp[namespace].setdefault(member_full_name, {})
topic['name'] = member_schema['name']
if 'doc' in member_schema:
topic['summary'] = (
member_schema['doc'].split('\n\n', 1)[0].strip())
if 'topic_topic' in member_schema:
topic['topic_topic'] = member_schema['topic_topic']
if 'exclude' in member_schema:
topic['exclude'] = member_schema['exclude']
return halp
def _write_schema(self): def _write_schema(self):
try: try:
os.makedirs(self._DIR) os.makedirs(self._DIR)
@ -557,7 +579,6 @@ class Schema(object):
return return
with self._open_schema(self._fingerprint, 'w') as schema: with self._open_schema(self._fingerprint, 'w') as schema:
schema_info = {}
for key, value in self._dict.items(): for key, value in self._dict.items():
if key in self.namespaces: if key in self.namespaces:
ns = value ns = value
@ -565,9 +586,10 @@ class Schema(object):
path = '{}/{}'.format(key, member) path = '{}/{}'.format(key, member)
schema.writestr(path, json.dumps(ns[member])) schema.writestr(path, json.dumps(ns[member]))
else: else:
schema_info[key] = value schema.writestr(key, json.dumps(value))
schema.writestr(self.schema_info_path, json.dumps(schema_info)) schema.writestr('_help',
json.dumps(self._generate_help(self._dict)))
def _read(self, path): def _read(self, path):
with self._open_schema(self._fingerprint, 'r') as zf: with self._open_schema(self._fingerprint, 'r') as zf:
@ -587,6 +609,14 @@ class Schema(object):
def iter_namespace(self, namespace): def iter_namespace(self, namespace):
return iter(self._dict[namespace]) return iter(self._dict[namespace])
def load_help(self):
if not self._help:
self._help = self._read('_help')
for ns in self._help:
for member in self._help[ns]:
self._dict[ns][member].update(self._help[ns][member])
def get_package(api, client): def get_package(api, client):
try: try: