2011-08-29 11 views
5

मैं अपने एपीआई दस्तावेज करने के लिए स्फिंक्स की ऑटोडोक सुविधा का उपयोग कर रहा हूं।sphinx.ext.autodoc: हस्ताक्षर में स्थिरांक के नाम रखने

उदाहरण:

DEFAULT_OPTION = 'default' 
def do_something(msg, option=DEFAULT_OPTION): 
    print msg 

उत्पन्न प्रलेखन अब पता चलता निम्नलिखित हस्ताक्षर:

do_something(msg, option='default') 

मैं स्फिंक्स कैसे बता यानी निरंतर मूल्य के नाम पर रखने के लिए कर सकते हैं

do_something(msg, option=DEFAULT_OPTION) 

?

क्या कोई विकल्प है जिसे मैंने अनदेखा किया है? यदि संभव हो, तो मैं हाथ से सभी हस्ताक्षर लिखना नहीं चाहता हूं।

उत्तर

1

आपको शायद रीस्ट फ़ाइल में हाथ से override the signature होना चाहिए।

एक बेहतर उत्तर के साथ आना मुश्किल है। Autodoc मॉड्यूल को आयात करता है, इसलिए सभी मॉड्यूल-स्तरीय कोड (डिफ़ॉल्ट फ़ंक्शन तर्क सहित) निष्पादित किया जाता है।

इन समान प्रश्नों को भी देखें: here और here


अद्यतन:

मैं सिर्फ एहसास हुआ एक और विकल्प है। आप इसे डॉकस्ट्रिंग की पहली पंक्ति के रूप में शामिल करके हस्ताक्षर को ओवरराइड कर सकते हैं। autodoc_docstring_signature कॉन्फ़िगरेशन चर के दस्तावेज़, और this answer के दस्तावेज़ देखें।

+0

टिप के लिए धन्यवाद। मैं हालांकि यह पूरी तरह से बचने की उम्मीद कर रहा था। – basti

+1

रुचि रखने वाले किसी भी व्यक्ति के लिए, संबंधित बग रिपोर्ट यहां है https://bitbucket.org/birkenfeld/sphinx/issue/759/keeping-original-ignature-for-functions – basti

+0

बग रिपोर्ट अब गिटहब पर है: https: // github .com/स्फिंक्स-डॉक/स्फिंक्स/मुद्दों/759। – mzjn

1

आप एएसटी से निरंतर नामों के साथ हस्ताक्षर प्राप्त कर सकते हैं और इसे "अदृश्य" वापस पाइथन कोड पर प्राप्त कर सकते हैं।

अपने conf.py फ़ाइल में इस रखो:

import ast 
import inspect 

from unparser import Unparser 


unparse = Unparser() 

def get_signature_from_ast(app, what, name, obj, options, signature, 
          return_annotation): 
    if what in ('class', 'exception', 'function', 'method'): 
     remove_args = 0 
     if what == 'method': 
      remove_args += 1 # Remove self from instance methods. 
     while True: 
      if inspect.isclass(obj): 
       obj = obj.__init__ 
      elif inspect.ismethod(obj): 
       remove_args += 1 # Remove self from instance methods. 
       obj = obj.__func__ 
      elif hasattr(obj, '__wrapped__'): 
       obj = obj.__wrapped__ 
      else: 
       break 
     filename = sys.modules[obj.__module__].__file__ 
     with open(filename) as file: 
      node = ast.parse(file.read(), filename) 
     lineno = obj.__code__.co_firstlineno 
     for n in ast.walk(node): 
      if isinstance(n, ast.FunctionDef) and n.lineno == lineno: 
       signature = '(' + unparse.argspec(n.args, remove_args) + ')' 
       if n.returns: 
        return_annotation = unparse.expr(n.returns) 
       break 
    return signature, return_annotation 

def setup(app): 
    app.connect('autodoc-process-signature', get_signature_from_ast) 

और कुछ unparser.py फ़ाइल में इस, आयात योग्य conf.py से:

नोट: यह "unparser" शायद कई कीड़े है।

import ast 
from itertools import zip_longest 


class _Ast(object): 
    """Type that returns a dummy type on failed attribute access. 
    Used for backwards compatibility when accessing new types in the :mod:`ast` 
    module. 
    """ 
    def __getattribute__(self, attr): 
     """Return a type from :mod:`ast` or a dummy type when the attribute 
     does not exist in the module. 
     """ 
     return getattr(ast, attr, type(self)) 

_ast = _Ast() 


class Unparser(object): 
    """Unparse an AST back to Python code. 
    Supports only expressions, up to Python 3.3. 
    """ 
    #: Mapping of AST types to Python code strings. 
    ast_symbols = { 
     # Boolean binary operators. 
     _ast.And: 'and', 
     _ast.Or: 'or', 
     # Binary operators. 
     _ast.Add: '+', 
     _ast.Sub: '-', 
     _ast.Mult: '*', 
     _ast.Div: '/', 
     _ast.FloorDiv: '//', 
     _ast.Mod: '%', 
     _ast.LShift: '<<', 
     _ast.RShift: '>>', 
     _ast.BitOr: '|', 
     _ast.BitAnd: '&', 
     _ast.BitXor: '^', 
     # Comparison operators. 
     _ast.Eq: '==', 
     _ast.Gt: '>', 
     _ast.GtE: '>=', 
     _ast.In: 'in', 
     _ast.Is: 'is', 
     _ast.IsNot: 'is not', 
     _ast.Lt: '<', 
     _ast.LtE: '<=', 
     _ast.NotEq: '!=', 
     _ast.NotIn: 'not in', 
     # Unary operators. 
     _ast.Invert: '~', 
     _ast.Not: 'not', 
     _ast.UAdd: '+', 
     _ast.USub: '-' 
    } 

    def args(unparse, args, defaults, remove_args=0, override_args={}): 
     """Unparse arguments from an argspec. This can strip out positional 
     arguments and replace keyword arguments. 
     """ 
     l = [] 
     defaults = list(map(unparse.expr, defaults)) 
     args = list(zip_longest(reversed(args), reversed(defaults))) 
     args.reverse() 
     for arg, default in args[remove_args:]: 
      a = arg.arg 
      if a in override_args: 
       default = repr(override_args[a]) 
      if arg.annotation: 
       a += ': ' + unparse.expr(arg.annotation) 
      if default is not None: 
       a += '=' + default 
      l.append(a) 
     return l 

    def argspec(unparse, node, remove_args=0, override_args={}): 
     """Unparse an argspec from a function definition. This can strip out 
     positional arguments and replace keyword arguments.""" 
     s = [] 
     s.extend(unparse.args(node.args, node.defaults, 
           remove_args, override_args)) 
     if node.vararg or node.kwonlyargs: 
      vararg = '*' 
      if node.vararg: 
       vararg += node.vararg 
       if node.varargannotation: 
        vararg += ': ' + unparse.expr(node.varargannotation) 
      s.append(vararg) 
     s.extend(unparse.args(node.kwonlyargs, node.kw_defaults, 
           override_args=override_args)) 
     kwarg = node.kwarg 
     if kwarg: 
      if node.kwargannotation: 
       kwarg += ': ' + unparse.expr(node.kwargannotation) 
      s.append('**' + kwarg) 
     return ', '.join(s) 

    def comprehension(unparse, node): 
     """Unparse a comprehension.""" 
     s = ['for', unparse.expr(node.target), 'in', unparse.expr(node.iter)] 
     for cond in node.ifs: 
      s.extend(('if', cond)) 
     return ' '.join(s) 

    def slice(unparse, node): 
     """Unparse a slice.""" 
     s = '' 
     if isinstance(node, _ast.Slice): 
      s = [] 
      if node.lower: 
       s.append(unparse.expr(node.lower)) 
      else: 
       s.append('') 
      if node.upper: 
       s.append(unparse.expr(node.upper)) 
      else: 
       s.append('') 
      if node.step: 
       s.append(unparse.expr(node.step)) 
      s = ':'.join(s) 
     elif isinstance(node, _ast.ExtSlice): 
      s = ', '.join(map(unparse.slice, node.dims)) 
     elif isinstance(node, _ast.Index): 
      s = unparse.expr(node.value) 
     return s 

    def expr(unparse, node, parenthesise=False): 
     """Unparse an expression.""" 
     s = 'None' 
     if isinstance(node, _ast.BoolOp): 
      s = [] 
      for expr in node.values: 
       s.append(unparse.expr(expr, parenthesise=True)) 
      s = (' ' + unparse.ast_symbols[type(node.op)] + ' ').join(s) 
     elif isinstance(node, _ast.BinOp): 
      s = ' '.join((unparse.expr(node.left, parenthesise=True), 
          unparse.ast_symbols[type(node.op)], 
          unparse.expr(node.right, parenthesise=True))) 
     elif isinstance(node, _ast.UnaryOp): 
      s = (unparse.ast_symbols[type(node.op)] + 
       unparse.expr(node.operand, parenthesise=True)) 
     elif isinstance(node, _ast.Lambda): 
      s = ('lambda ' + unparse.argspec(node.args) + ': ' + 
       unparse.expr(node.body)) 
     elif isinstance(node, _ast.IfExp): 
      s = ' '.join((unparse.expr(node.body), 
          'if', unparse.expr(node.test), 
          'else', unparse.expr(node.orelse))) 
     elif isinstance(node, _ast.Dict): 
      s = [] 
      for key, value in zip(node.keys, node.values): 
       s.append(unparse.expr(key) + ': ' + unparse.expr(value)) 
      s = '{' + ', '.join(s) + '}' 
      parenthesise = False 
     elif isinstance(node, _ast.Set): 
      s = '{' + ', '.join(map(unparse.expr, node.elts)) + '}' 
      parenthesise = False 
     elif isinstance(node, _ast.ListComp): 
      s = [unparse.expr(node.elt)] 
      s.extend(map(unparse.comprehension, node.generators)) 
      s = '[' + ' '.join(map(unparse.expr, node.elts)) + ']' 
      parenthesise = False 
     elif isinstance(node, _ast.SetComp): 
      s = [unparse.expr(node.elt)] 
      s.extend(map(unparse.comprehension, node.generators)) 
      s = '{' + ' '.join(map(unparse.expr, node.elts)) + '}' 
      parenthesise = False 
     elif isinstance(node, _ast.DictComp): 
      s = [unparse.expr(node.key) + ': ' + unparse.expr(node.value)] 
      s.extend(map(unparse.comprehension, node.generators)) 
      s = '{' + ' '.join(map(unparse.expr, node.elts)) + '}' 
      parenthesise = False 
     elif isinstance(node, _ast.GeneratorExp): 
      s = [unparse.expr(node.elt)] 
      s.extend(map(unparse.comprehension, node.generators)) 
      s = '(' + ' '.join(map(unparse.expr, node.elts)) + ')' 
      parenthesise = False 
     elif isinstance(node, _ast.Yield): 
      s = ['yield'] 
      if node.value: 
       s.append(unparse.expr(node.value)) 
      s = ' '.join(s) 
      parenthesise = False 
     elif isinstance(node, _ast.YieldFrom): 
      s = ['yield from'] 
      if node.value: 
       s.append(unparse.expr(node.value)) 
      s = ' '.join(s) 
      parenthesise = False 
     elif isinstance(node, _ast.Compare): 
      s = [unparse.expr(node.left, parenthesise=True)] 
      for op, operand in zip(node.ops, node.comparators): 
       s.append(unparse.ast_symbols[type(op)]) 
       s.append(unparse.expr(operand, parenthesise=True)) 
      s = ' '.join(s) 
     elif isinstance(node, _ast.Call): 
      s = list(map(unparse.expr, node.args)) 
      if node.starargs: 
       s.append('*' + unparse.expr(node.starargs, parenthesise=True)) 
      for kw in node.keywords: 
       s.append(kw.arg + '=' + 
         unparse.expr(kw.value, parenthesise=True)) 
      if node.kwargs: 
       s.append('**' + unparse.expr(node.kwargs, parenthesise=True)) 
      s = (unparse.expr(node.func, parenthesise=True) + 
       '(' + ', '.join(s) + ')') 
      parenthesise = False 
     elif isinstance(node, _ast.Num): 
      s = repr(node.n) 
      parenthesise = False 
     elif isinstance(node, (_ast.Str, _ast.Bytes)): 
      s = repr(node.s) 
      parenthesise = False 
     elif isinstance(node, _ast.Ellipsis): 
      s = '...' 
      parenthesise = False 
     elif isinstance(node, _ast.Attribute): 
      s = unparse.expr(node.value) + '.' + node.attr 
      parenthesise = False 
     elif isinstance(node, _ast.Subscript): 
      s = (unparse.expr(node.value, parenthesise=True) + 
       '[' + unparse.slice(node.slice) + ']') 
      parenthesise = False 
     elif isinstance(node, _ast.Starred): 
      s = '*' + unparse.expr(node.value) 
      parenthesise = False 
     elif isinstance(node, _ast.Name): 
      s = node.id 
      parenthesise = False 
     elif isinstance(node, _ast.List): 
      s = '[' + ', '.join(map(unparse.expr, node.elts)) + ']' 
      parenthesise = False 
     elif isinstance(node, _ast.Tuple): 
      s = ', '.join(map(unparse.expr, node.elts)) 
      if len(node.elts) == 1: 
       s += ',' 
      s = '(' + s + ')' 
      parenthesise = False 
     if parenthesise: 
      s = '(' + s + ')' 
     return s 
+0

यह पायथन 3 के लिए है, है ना? – mzjn

+0

@mzjn हां, लेकिन इसे पायथन 2 पर बंद करना मुश्किल नहीं होना चाहिए। –

संबंधित मुद्दे