def doc2html(obj, doc): """Generate an HTML representation of a docstring""" if doc is None or not doc.strip(): return '<div class="undocumented">Undocumented</div>' if not EPYTEXT: return boringDocstring(doc) errs = [] pdoc = epytext.parse_docstring(doc, errs) if errs: errs = [] def crappit(): pass crappit.__doc__ = doc doc = inspect.getdoc(crappit) pdoc = epytext.parse_docstring(doc, errs) if errs: if obj.system.options.verbosity > 0: print obj if obj.system.options.verbosity > 1: for i, l in enumerate(doc.splitlines()): print "%4s"%(i+1), l for err in errs: print err global errcount errcount += len(errs) return boringDocstring(doc) pdoc, fields = pdoc.split_fields() crap = pdoc.to_html(_EpydocLinker(obj)) s = '<div>%s</div>' % (crap,) for field in fields: s += (('<div class="metadata"><span class="tag">%s</span> ' '<span class="arg">%s</span>' '<span class="body">%s</span></div>') % (field.tag(), field.arg(), field.body().to_html(_EpydocLinker(obj)))) return s
def doc2html(obj, doc): """Generate an HTML representation of a docstring""" if doc is None or not doc.strip(): return '<div class="undocumented">Undocumented</div>' if not EPYTEXT: return boringDocstring(doc) errs = [] pdoc = epytext.parse_docstring(doc, errs) if errs: errs = [] def crappit(): pass crappit.__doc__ = doc doc = inspect.getdoc(crappit) pdoc = epytext.parse_docstring(doc, errs) if errs: if obj.system.options.verbosity > 0: print(obj) if obj.system.options.verbosity > 1: for i, l in enumerate(doc.splitlines()): print("%4s"%(i+1), l) for err in errs: print(err) global errcount errcount += len(errs) return boringDocstring(doc) pdoc, fields = pdoc.split_fields() crap = pdoc.to_html(_EpydocLinker(obj)) s = '<div>%s</div>' % (crap,) for field in fields: s += (('<div class="metadata"><span class="tag">%s</span> ' '<span class="arg">%s</span>' '<span class="body">%s</span></div>') % (field.tag(), field.arg(), field.body().to_html(_EpydocLinker(obj)))) return s
def doc(obj, docform=2, join_token='\n '): """Return documentation associated with an object. If the object does not have any documentation, return the empty string. Otherwise return the object documentation, in a form that depends on doc form. If docform==0, the first line (short-form) of the documentation is returned. If docform==1, the body of the documentation is returned, without the short-form. If docform==2, the whole documentation is returned (both short-form and body). """ docstr = obj.__doc__ if docstr is None: return '' lines = string.split(docstr, '\n') if docform == 0: lines = [lines[0]] elif docform == 1: ## Determine a logical starting point that skips blank lines after ## the first line of documentation #for i in range(1,len(lines)): i = 1 while i < len(lines): if lines[i].strip() != "": break i += 1 lines = lines[i:] elif docform == 2: pass else: raise ValueError, "Argument to 'docform' must be either 0, 1, or 2" parsed_lines = [] for line in lines: striped = string.lstrip(line) errors = [] parsed = striped try: from epydoc.markup import epytext parsed = epytext.parse_docstring(striped, errors).to_plaintext(None) except: pass parsed = string.rstrip(parsed) if errors: exc = "'%s' contains the following errors\n" % parsed for e in errors: exc = "%s\n%s" % (exc, str(e)) raise ValueError(exc) parsed_lines.append(parsed) as_string = string.join(parsed_lines, join_token) return as_string
def doc(obj, docform = 2, join_token = '\n '): """Return documentation associated with an object. If the object does not have any documentation, return the empty string. Otherwise return the object documentation, in a form that depends on doc form. If docform==0, the first line (short-form) of the documentation is returned. If docform==1, the body of the documentation is returned, without the short-form. If docform==2, the whole documentation is returned (both short-form and body). """ docstr = obj.__doc__ if docstr is None: return '' lines = string.split(docstr, '\n') if docform==0: lines = [ lines[0] ] elif docform==1: ## Determine a logical starting point that skips blank lines after ## the first line of documentation #for i in range(1,len(lines)): i= 1 while i < len(lines): if lines[i].strip() != "": break i+= 1 lines = lines[i:] elif docform==2: pass else: raise ValueError,"Argument to 'docform' must be either 0, 1, or 2" parsed_lines = [] for line in lines: striped = string.lstrip(line) errors = [] parsed = striped try: from epydoc.markup import epytext parsed = epytext.parse_docstring( striped, errors ).to_plaintext(None) except: pass parsed = string.rstrip( parsed ) if errors: exc = "'%s' contains the following errors\n" % parsed for e in errors: exc = "%s\n%s" % (exc, str(e)) raise ValueError(exc) parsed_lines.append( parsed ) as_string = string.join( parsed_lines, join_token ) return as_string
def format_epytext(docstring): if six.PY3: return u('Epydoc is not compatible with Python 3 interpreter') import epydoc.markup.epytext from epydoc.markup import DocstringLinker from epydoc.markup.epytext import parse_docstring, ParseError, _colorize def _add_para(doc, para_token, stack, indent_stack, errors): """Colorize the given paragraph, and add it to the DOM tree.""" para = _colorize(doc, para_token, errors) if para_token.inline: para.attribs['inline'] = True stack[-1].children.append(para) epydoc.markup.epytext._add_para = _add_para ParseError.is_fatal = lambda self: False errors = [] class EmptyLinker(DocstringLinker): def translate_indexterm(self, indexterm): return "" def translate_identifier_xref(self, identifier, label=None): return identifier docstring = parse_docstring(docstring, errors) docstring, fields = docstring.split_fields() html = docstring.to_html(EmptyLinker()) if errors and not html: # It's not possible to recover original stacktraces of the errors error_lines = '\n'.join(text_type(e) for e in errors) raise Exception('Error parsing docstring. Probable causes:\n' + error_lines) return html
return False ParseError.is_fatal = is_fatal try: src = sys.stdin.read() errors = [] class EmptyLinker(DocstringLinker): def translate_indexterm(self, indexterm): return "" def translate_identifier_xref(self, identifier, label=None): return identifier docstring = parse_docstring(src, errors) docstring, fields = docstring.split_fields() html = docstring.to_html(EmptyLinker()) if errors and not html: sys.stderr.write("Error parsing docstring:\n") for error in errors: sys.stderr.write(str(error) + "\n") sys.exit(1) sys.stdout.write(html) sys.stdout.flush() except: exc_type, exc_value, exc_traceback = sys.exc_info() sys.stderr.write("Error calculating docstring: " + str(exc_value)) sys.exit(1)
ParseError.is_fatal = is_fatal try: src = sys.stdin.read() errors = [] class EmptyLinker(DocstringLinker): def translate_indexterm(self, indexterm): return "" def translate_identifier_xref(self, identifier, label=None): return identifier docstring = parse_docstring(src, errors) docstring, fields = docstring.split_fields() html = docstring.to_html(EmptyLinker()) if errors and not html: sys.stderr.write("Error parsing docstring:\n") for error in errors: sys.stderr.write(str(error) + "\n") sys.exit(1) sys.stdout.write(html) sys.stdout.flush() except: exc_type, exc_value, exc_traceback = sys.exc_info() sys.stderr.write("Error calculating docstring: " + str(exc_value)) sys.exit(1)
def process_from_epydoc_to_sphinx(fle, imp): from epydoc.markup.epytext import parse_docstring astinput = ast.parse(imp.encode('utf8'), filename=fle.path) docstrings = [] f = imp.split("\n") class Vis(NodeVisitor): def visit_FunctionDef(self, node, indent=4): if len(node.body) > 0 and isinstance(node.body[0], ast.Expr): potential_docstring = node.body[0] if isinstance(potential_docstring.value, ast.Str): doc = "\n".join(f[node.lineno : potential_docstring.lineno]) doc = doc.split('"""')[1] length = len(doc.split("\n")) if doc[0] != "\n": doc = " " * (node.col_offset + 4) + doc length -= 1 if doc[-1] != "\n": length -= 1 docstrings.append( { "offset": node.col_offset + indent, "line_no": potential_docstring.lineno - length - 1, "content": dedent(doc).strip(), "length": length + 2, } ) def visit_ClassDef(self, node): self.visit_FunctionDef(node) for i in node.body: if isinstance(i, (ast.FunctionDef, ast.ClassDef)): self.visit_FunctionDef(i) def visit_Module(self, node): node.lineno = 0 node.col_offset = 0 self.visit_FunctionDef(node, indent=0) for i in node.body: if isinstance(i, (ast.FunctionDef, ast.ClassDef)): self.visit_FunctionDef(i) v = Vis() v.visit(astinput) for i in docstrings: err = [] parsed = parse_docstring(i["content"], err).split_fields() err = [x for x in err if x.is_fatal()] if err: print("") print("Errors, skipping " + fle.path + ":" + str(i["line_no"])) print(err) i["new_content"] = i["content"] continue def dump(t): resp = [] if not t._tree.children: return "" for child in t._tree.children: if child.tag == "para": for i in child.children: if isinstance(i, (str, unicode)): resp.append(i) continue if i.tag == "link": resp.append(":py:obj:`" + i.children[0].children[0] + "`") continue if i.tag == "code": resp.append("``%s``" % (i.children[0],)) continue if i.tag == "italic": resp.append("*%s*" % (i.children[0],)) continue if i.tag == "bold": resp.append("**%s**" % (i.children[0],)) continue raise Exception(i.tag) resp.append("\n\n") elif child.tag == "literalblock": resp.append(":\n\n ```\n" + child.children[0] + "\n ```") else: continue raise Exception(child.tag) return "".join(resp) content = [] if parsed[0]: content.append(dump(parsed[0])) content.append("") for x in parsed[1]: tag = x.tag() if tag in ["param", "type", "ivar", "cvar", "var", "see"]: content.append(":%s %s: " % (tag, x.arg()) + dump(x.body())) elif tag in ["rtype", "since"]: content.append(":%s: %s" % (tag, dump(x.body()))) elif tag in ["raise", "raises"]: content.append(":raises %s: %s" % (tag, dump(x.body()))) # TYPO IN TWISTED elif tag in ["params"]: content.append(":param %s: %s" % (tag, dump(x.body()))) # TYPO IN TWISTED elif tag in ["types"]: content.append(":type %s: " % (tag,) + dump(x.body())) # TYPO IN TWISTED elif tag in ["arg"]: content.append(":param %s: %s" % (tag, dump(x.body()))) # TYPO IN TWISTED elif tag in ["returntype"]: content.append(":rtype: %s" % (dump(x.body()),)) elif tag in ["return", "returns"]: content.append(":returns: %s" % (dump(x.body()),)) elif tag in ["note"]: content.append(".. note::") content.append(" " + dump(x.body())) else: print(x.body()) print(parsed[0]) raise Exception("Can't parse %s" % (tag,)) k = StringIO() from .docstring_wrap import wrapPythonDocstring wrapPythonDocstring( "\n".join(content).decode('utf8'), k, width=79 - i["offset"], indentation=u'', ) k.seek(0) i["new_content"] = k.read().strip() # Process docstrings here... last_point = 0 regions = [[1, 0]] finished_file = [] for i in docstrings: line_no = i["line_no"] length = i["length"] regions[-1][1] = line_no regions.append([line_no + length, -1]) for region, i in zip(regions, docstrings): offset = i["offset"] new_content = i["new_content"] indented = list( map(lambda x: " " * offset + x if x else "", new_content.split("\n")) ) indented_quotes = ' ' * offset + '"""' ripped = f[region[0] - 1 : region[1]] finished_file.extend(ripped) finished_file.extend([indented_quotes] + indented + [indented_quotes]) return finished_file