#
#
-# Copyright (C) 2011 Google Inc.
+# Copyright (C) 2011, 2012 Google Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
"""
-import operator
from cStringIO import StringIO
import docutils.statemachine
import sphinx.errors
import sphinx.util.compat
+s_compat = sphinx.util.compat
+
from ganeti import constants
from ganeti import compat
from ganeti import errors
from ganeti import utils
from ganeti import opcodes
from ganeti import ht
+from ganeti import rapi
+
+import ganeti.rapi.rlib2 # pylint: disable=W0611
+
+
+def _GetCommonParamNames():
+ """Builds a list of parameters common to all opcodes.
+
+ """
+ names = set(map(compat.fst, opcodes.OpCode.OP_PARAMS))
+ # The "depends" attribute should be listed
+ names.remove(opcodes.DEPEND_ATTR)
-COMMON_PARAM_NAMES = map(operator.itemgetter(0), opcodes.OpCode.OP_PARAMS)
+ return names
+
+
+COMMON_PARAM_NAMES = _GetCommonParamNames()
#: Namespace for evaluating expressions
-EVAL_NS = dict(compat=compat, constants=constants, utils=utils, errors=errors)
+EVAL_NS = dict(compat=compat, constants=constants, utils=utils, errors=errors,
+ rlib2=rapi.rlib2)
+
+# Constants documentation for man pages
+CV_ECODES_DOC = "ecodes"
+# We don't care about the leak of variables _, name and doc here.
+# pylint: disable=W0621
+CV_ECODES_DOC_LIST = [(name, doc) for (_, name, doc) in constants.CV_ALL_ECODES]
+DOCUMENTED_CONSTANTS = {
+ CV_ECODES_DOC: CV_ECODES_DOC_LIST,
+ }
class OpcodeError(sphinx.errors.SphinxError):
params_with_alias = \
utils.NiceSort([(alias.get(name, name), name, default, test, doc)
for (name, default, test, doc) in op_cls.GetAllParams()],
- key=operator.itemgetter(0))
+ key=compat.fst)
for (rapi_name, name, default, test, doc) in params_with_alias:
# Hide common parameters if not explicitely included
yield " %s" % line
-class OpcodeParams(sphinx.util.compat.Directive):
+def _BuildOpcodeResult(op_id):
+ """Build opcode result documentation.
+
+ @type op_id: string
+ @param op_id: Opcode ID
+
+ """
+ op_cls = opcodes.OP_MAPPING[op_id]
+
+ result_fn = getattr(op_cls, "OP_RESULT", None)
+
+ if not result_fn:
+ raise OpcodeError("Opcode '%s' has no result description" % op_id)
+
+ return "``%s``" % result_fn
+
+
+class OpcodeParams(s_compat.Directive):
"""Custom directive for opcode parameters.
See also <http://docutils.sourceforge.net/docs/howto/rst-directives.html>.
return []
+class OpcodeResult(s_compat.Directive):
+ """Custom directive for opcode result.
+
+ See also <http://docutils.sourceforge.net/docs/howto/rst-directives.html>.
+
+ """
+ has_content = False
+ required_arguments = 1
+ optional_arguments = 0
+ final_argument_whitespace = False
+
+ def run(self):
+ op_id = self.arguments[0]
+
+ tab_width = 2
+ path = op_id
+ include_text = _BuildOpcodeResult(op_id)
+
+ # Inject into state machine
+ include_lines = docutils.statemachine.string2lines(include_text, tab_width,
+ convert_whitespace=1)
+ self.state_machine.insert_input(include_lines, path)
+
+ return []
+
+
def PythonEvalRole(role, rawtext, text, lineno, inliner,
options={}, content=[]):
"""Custom role to evaluate Python expressions.
The expression's result is included as a literal.
"""
- # pylint: disable-msg=W0102,W0613,W0142
+ # pylint: disable=W0102,W0613,W0142
# W0102: Dangerous default value as argument
# W0142: Used * or ** magic
# W0613: Unused argument
try:
result = eval(code, EVAL_NS)
- except Exception, err: # pylint: disable-msg=W0703
+ except Exception, err: # pylint: disable=W0703
msg = inliner.reporter.error("Failed to evaluate %r: %s" % (code, err),
line=lineno)
return ([inliner.problematic(rawtext, rawtext, msg)], [msg])
return ([node], [])
-class PythonAssert(sphinx.util.compat.Directive):
+class PythonAssert(s_compat.Directive):
"""Custom directive for writing assertions.
The content must be a valid Python expression. If its result does not
@type fields: dict (field name as key, field details as value)
"""
- for (_, (fdef, _, _)) in utils.NiceSort(fields.items(),
- key=operator.itemgetter(0)):
- assert len(fdef.doc.splitlines()) == 1
- yield "``%s``" % fdef.name
- yield " %s" % fdef.doc
+ defs = [(fdef.name, fdef.doc)
+ for (_, (fdef, _, _, _)) in utils.NiceSort(fields.items(),
+ key=compat.fst)]
+ return BuildValuesDoc(defs)
+
+
+def BuildValuesDoc(values):
+ """Builds documentation for a list of values
+
+ @type values: list of tuples in the form (value, documentation)
+
+ """
+ for name, doc in values:
+ assert len(doc.splitlines()) == 1
+ yield "``%s``" % name
+ yield " %s" % doc
# TODO: Implement Sphinx directive for query fields
"""
app.add_directive("opcode_params", OpcodeParams)
+ app.add_directive("opcode_result", OpcodeResult)
app.add_directive("pyassert", PythonAssert)
app.add_role("pyeval", PythonEvalRole)