Example #1
0
    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
Example #2
0
    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
Example #3
0
    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
Example #4
0
    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
Example #5
0
    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
Example #6
0
    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
Example #7
0
    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
Example #8
0
    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