def make_google_docstring(self, width, indent_level, tabsize): """Return the docstring of the content in google style. Parameters ---------- width : int Maximum number of characters allowed in a line. indent_level : int Number of indents (tabs) that are needed for the docstring. tabsize : int Number of spaces that corresponds to a tab. Returns ------- content_docstring : str Docstring of the given content in google style. Notes ----- The signature of a function is not included in the google docstring. """ output = '' first_block = [] # var_name: if not self.types: first_block = wrap('{0}:'.format(self.name), width=width, indent_level=indent_level, tabsize=tabsize) # var_name (type1, type2): else: # FIXME: optional parameters need to be specified within google doc types_str = [i if isinstance(i, str) else ':obj:`{0}`'.format(j) for i, j in zip(self.types, self.types_str)] text = '{0} ({1}):'.format(self.name, ', '.join(types_str)) # if there are too many types to fit into one line, the remaining lines should be # indented to line up after "var_name (" # FIXME: following can probably be replaced with a better wrapping function first_block = [' ' * indent_level * tabsize + line for line in wrap_indent_subsequent(text, width=width - indent_level*tabsize, indent_level=1, tabsize=len('{0} ('.format(self.name)))] # add descriptions if self.descs: output += '\n'.join(first_block[:-1]) if len(first_block) != 1: output += '\n' # FIXME: following can probably be replaced with a better wrapping function first_desc = wrap_indent_subsequent(first_block[-1] + ' ' + self.descs[0], width=width, indent_level=indent_level+1, tabsize=tabsize) output += '\n'.join(first_desc) output += '\n' for desc in self.descs[1:]: output += '\n'.join(wrap(desc, width=width, indent_level=indent_level+1, tabsize=tabsize)) output += '\n' else: output += '\n'.join(first_block) output += '\n' return output
def make_docstring(self, width, indent_level, tabsize, summary_only=False, special=False): """Return the docstring for the summary. Parameters ---------- width : int Maximum number of characters allowed in a line. indent_level : int Number of indents (tabs) that are needed for the docstring. tabsize : int Number of spaces that corresponds to a tab. summary_only : {bool, False} Flag for indicating that there is only summary in the docstring. If True, then newlines are not added to the output if the summary can fit both triple quotations on either side. Otherwise, newlines are added. By default, False. special : {bool, False} Flag for indicating that the docstring is raw or is unicode. By default, False. Returns ------- summary : str First line of the docstring. Raises ------ ValueError If the title is too long for the given width and indentation. """ output = '' summary = self.contents[0] # if summary cannot fit into first line with one triple quotation # if len(summary) + ' ' * indent_level * tabsize > width - 3: if len(wrap(summary, width - 3 - int(special), indent_level, tabsize)) > 1: output += '\n' # if summary cannot fit into the second line (without tripple quotation) # if len(summary) + ' ' * indent_level * tabsize > width: if len(wrap(summary, width, indent_level, tabsize)) > 1: raise ValueError( 'First section of the docstring (summary) must fit completely into' ' the first line of the docstring (including the triple quotation)' ' or the second line.') output += summary # if summary only and summary can fit into the first line with two triple quotations if not (summary_only and len( wrap(summary, width - 6 - int(special), indent_level, tabsize)) == 1): output += '\n\n' return output
def make_rst_docstring(self, width, indent_level, tabsize): """Return the docstring in sphinx's rst format. Parameters ---------- width : int Maximum number of characters allowed in a line. indent_level : int Number of indents (tabs) that are needed for the docstring. tabsize : int Number of spaces that corresponds to a tab. Returns ------- content_docstring : str Docstring of the given content in sphinx's rst style. Raises ------ ValueError If the parameter name is too long to fit within the given width and indent. """ output = '' if self.descs: text = ':param {0}: {1}'.format(self.name, self.descs[0]) # FIXME: following can probably be replaced with a better wrapping function block = [' ' * indent_level * tabsize + line for line in wrap_indent_subsequent(text, width=width - indent_level*tabsize, indent_level=1, tabsize=tabsize)] output += '\n'.join(block) output += '\n' if len(self.descs) > 1: for desc in self.descs[1:]: output += '\n'.join(wrap(desc, width=width, indent_level=indent_level+1, tabsize=tabsize)) output += '\n' else: block = wrap(':param {0}:'.format(self.name), width=width, indent_level=indent_level, tabsize=tabsize) if len(block) > 1: raise ValueError('Parameter name is too long to fit within the given line width and' ' indent level.') output += block[0] output += '\n' types_str = [i if isinstance(i, str) else ':obj:`{0}`'.format(j) for i, j in zip(self.types, self.types_str)] if self.types: text = ':type {0}: {1}'.format(self.name, ', '.join(types_str)) block = [' ' * indent_level * tabsize + line for line in wrap_indent_subsequent(text, width=width - indent_level*tabsize, indent_level=1, tabsize=tabsize)] output += '\n'.join(block) output += '\n' return output
def make_numpy_docstring(self, width, indent_level, tabsize): """Return the docstring in numpy style. Parameters ---------- width : int Maximum number of characters allowed in a line. indent_level : int Number of indents (tabs) that are needed for the docstring. tabsize : int Number of spaces that corresponds to a tab. Returns ------- equation_docstring : str Docstring of the given equations in numpy style. Raises ------ ValueError If the width is too small to fit the equation for the given indent and tabsize. """ output = '' if len(self.equations) == 1: first_line = wrap('.. math:: ' + self.equations[0], width=width, indent_level=indent_level, tabsize=tabsize) if len(first_line) == 1: output += first_line[0] output += '\n\n' return output first_line = wrap('.. math:: ', width=width, indent_level=indent_level, tabsize=tabsize) if len(first_line) != 1: raise ValueError('Given line width is too small to fit the equation for the given ' 'indent and tab size') output += first_line[0] output += '\n\n' output += '\n'.join('\n'.join(wrap(equation, width=width, indent_level=indent_level + 1, tabsize=tabsize)) for equation in self.equations) output += '\n\n' return output
def make_numpy_docstring(self, width, indent_level, tabsize, include_signature=False): """Return the docstring in numpy style. Parameters ---------- width : int Maximum number of characters allowed in a line. indent_level : int Number of indents (tabs) that are needed for the docstring. tabsize : int Number of spaces that corresponds to a tab. include_signature : {bool, False} Flag for modifying the numpy docstring format to include the signature of a function. Default is False. Returns ------- section_docstring : str Docstring of the given section in numpy style. Raises ------ ValueError If the title is too long for the given width and indentation. """ output = '' # title if self.header != '': title = wrap(self.header.title(), width=width, indent_level=indent_level, tabsize=tabsize) divider = wrap('-' * len(self.header), width=width, indent_level=indent_level, tabsize=tabsize) # NOTE: error will be raised if the line width is not wide enough to fit the title and # the divider in one line because the divider is one word and wrap will complain if the # line width is not big enough to fit the first word output += '{0}\n{1}\n'.format(title[0], divider[0]) # contents for paragraph in self.contents: # NOTE: since the contents are checked in the initialization, we will assume that the # paragraph can only be string or DocDescription if isinstance(paragraph, str): output += '\n'.join( wrap(paragraph, width=width, indent_level=indent_level, tabsize=tabsize)) output += '\n\n' # if isinstance(paragraph, DocContent) elif include_signature and hasattr( paragraph, 'make_numpy_docstring_signature'): output += paragraph.make_numpy_docstring_signature( width, indent_level, tabsize) else: output += paragraph.make_numpy_docstring( width, indent_level, tabsize) # pylint: disable=W0120 # following block clause should always be executed else: # end a section with two newlines (note that the section already ends with a newline if # it ends with a paragraph) output += '\n' * isinstance(paragraph, DocDescription) return output
def make_rst_docstring(self, width, indent_level, tabsize): """Return the docstring in sphinx's rst format. Parameters ---------- width : int Maximum number of characters allowed in a line. indent_level : int Number of indents (tabs) that are needed for the docstring. tabsize : int Number of spaces that corresponds to a tab. Returns ------- content_docstring : str Docstring of the given content in sphinx's rst style. """ output = '' header = '' special_headers = { 'see also': 'seealso', 'warnings': 'warning', 'warning': 'warning', 'notes': 'note', 'note': 'note', 'to do': 'todo', 'todo': 'todo' } if self.header.lower() in special_headers: header = '.. {0}::'.format(special_headers[self.header.lower()]) elif self.header != '': output += ':{0}:\n\n'.format(self.header.title()) for i, paragraph in enumerate(self.contents): # first content must be treated with care for special headers if i == 0 and self.header.lower() in special_headers: # str if isinstance(paragraph, str): text = '{0} {1}'.format(header, paragraph) # FIXME: following can probably be replaced with a better wrapping function first_content = [ ' ' * indent_level * tabsize + line for line in wrap_indent_subsequent( text, width=width - indent_level * tabsize, indent_level=indent_level + 1, tabsize=tabsize) ] output += '\n'.join(first_content) output += '\n' # DocContent else: output += header output += '\n' output += paragraph.make_rst_docstring( width=width, indent_level=indent_level + 1, tabsize=tabsize) # indent all susequent content indent_level += 1 elif isinstance(paragraph, str): output += '\n'.join( wrap(paragraph, width=width, indent_level=indent_level, tabsize=tabsize)) # NOTE: the second newline may cause problems (because the field might not # recognize text that is more than one newline away) output += '\n\n' else: output += paragraph.make_rst_docstring(width, indent_level, tabsize) # pylint: disable=W0120 # following block clause should always be executed else: # end a section with two newlines (note that the section already ends with a newline # if it ends with a paragraph) output += '\n' * isinstance(paragraph, DocDescription) return output
def make_google_docstring(self, width, indent_level, tabsize): """Return the docstring of the section in google style. Parameters ---------- width : int Maximum number of characters allowed in a line. indent_level : int Number of indents (tabs) that are needed for the docstring. tabsize : int Number of spaces that corresponds to a tab. Returns ------- content_docstring : str Docstring of the given content in google style. Raises ------ ValueError If the title is too long for the given width and indentation. """ output = '' # title if self.header != '': title = wrap('{0}:'.format(self.header.title()), width=width, indent_level=indent_level, tabsize=tabsize) if len(title) > 1: raise ValueError( 'The header must fit into the given width with the indentation' ) output += title[0] output += '\n' else: # don't indent the contents if there is no header indent_level -= 1 # contents for paragraph in self.contents: # NOTE: since the contents are checked in the initialization, we will assume that the # paragraph can only be string or DocDescription if isinstance(paragraph, str): output += '\n'.join( wrap(paragraph, width=width, indent_level=indent_level + 1, tabsize=tabsize)) output += '\n\n' # if isinstance(paragraph, DocContent) else: output += paragraph.make_google_docstring( width, indent_level + 1, tabsize) # pylint: disable=W0120 # following block clause should always be executed else: # end a section with two newlines (note that the section already ends with a newline if # it ends with a paragraph) output += '\n' * isinstance(paragraph, DocDescription) return output
def make_numpy_docstring(self, width, indent_level, tabsize): """Return the docstring in numpy style. Parameters ---------- width : int Maximum number of characters allowed in a line. indent_level : int Number of indents (tabs) that are needed for the docstring. tabsize : int Number of spaces that corresponds to a tab. Returns ------- descripton_docstring : str Docstring of the given descriptions of the object/error in numpy style. Raises ------ ValueError If the name and the type of variable cannot fit into the given width and indentation. If the name and the first type of the variable cannot fit into the given width and indentation. Notes ----- The signature of a function is not included in the numpy docstring. """ if self.signature != '': print('Warning: In NumPy docstring format, the signature of a function is not ' 'included.') output = '' # var_name # OR # error_name if not self.types: # NOTE: error is raised by wrap if the name is too long to fit in the given width and # indentation output += wrap(self.name, width=width, indent_level=indent_level, tabsize=tabsize)[0] # var_name : var_type elif len(self.types) == 1: name_type = wrap('{0} : {1}'.format(self.name, self.types_str[0]), width=width, indent_level=indent_level, tabsize=tabsize) # check that the both the name and the type can fit in the given width and indentation if len(name_type) > 1: # FIXME: need a better message raise ValueError('The name and the type of the variable are too long to fit into ' 'given width and indentation.') output += name_type[0] # var_name : {var_type1, var_type2, default_type} else: name_types = wrap('{0} : {{{1}}}'.format(self.name, ', '.join(self.types_str)), width=width, indent_level=indent_level, tabsize=tabsize) # if there are too many types to fit into one line, the remaining lines should be # indented to line up after "var_name : {" wrap_point = len('{0} : {{'.format(self.name)) # check that the name and first type can fit into the first line if not name_types[0].startswith('{0}{1} : {{{2}'.format(' ' * indent_level * tabsize, self.name, self.types_str[0])): # FIXME: need a better message raise ValueError('The name and the first type of the variable are too long to fit ' 'into the given width and indentation.') # wrap the remaining lines name_types_lines = [name_types[0]] for line in name_types[1:]: name_types_lines += wrap(line, width=width, indent_level=1, tabsize=wrap_point) output += '\n'.join(name_types_lines) output += '\n' # descriptions for paragraph in self.descs: output += '\n'.join(wrap(paragraph, width=width, indent_level=indent_level+1, tabsize=tabsize)) output += '\n' return output