From b5f15d581d5c226f96697ce2c9e1c3e6a35ef950 Mon Sep 17 00:00:00 2001 From: Ioannis Tziakos Date: Sat, 13 Sep 2014 00:50:11 +0100 Subject: [PATCH 01/63] re-arrange the package layout --- refactordoc/__init__.py | 4 +- refactordoc/base_doc.py | 5 +- refactordoc/class_doc.py | 9 +- refactordoc/definition_items.py | 546 ------------------ refactordoc/function_doc.py | 7 +- refactordoc/items/__init__.py | 1 + refactordoc/items/argument_item.py | 62 ++ refactordoc/items/attribute_item.py | 65 +++ refactordoc/items/definition_item.py | 180 ++++++ refactordoc/items/list_item.py | 67 +++ refactordoc/items/method_item.py | 94 +++ refactordoc/items/table_row_item.py | 46 ++ refactordoc/items/util.py | 39 ++ {tests => refactordoc/tests}/__init__.py | 0 {tests => refactordoc/tests}/_compat.py | 0 {tests => refactordoc/tests}/test_base_doc.py | 2 +- .../tests}/test_class_doc.py | 0 .../tests}/test_definition_items.py | 16 +- .../tests}/test_function_doc.py | 0 .../tests}/test_line_functions.py | 31 +- refactordoc/{line_functions.py => util.py} | 0 setup.py | 5 +- 22 files changed, 596 insertions(+), 583 deletions(-) delete mode 100644 refactordoc/definition_items.py create mode 100644 refactordoc/items/__init__.py create mode 100644 refactordoc/items/argument_item.py create mode 100644 refactordoc/items/attribute_item.py create mode 100644 refactordoc/items/definition_item.py create mode 100644 refactordoc/items/list_item.py create mode 100644 refactordoc/items/method_item.py create mode 100644 refactordoc/items/table_row_item.py create mode 100644 refactordoc/items/util.py rename {tests => refactordoc/tests}/__init__.py (100%) rename {tests => refactordoc/tests}/_compat.py (100%) rename {tests => refactordoc/tests}/test_base_doc.py (96%) rename {tests => refactordoc/tests}/test_class_doc.py (100%) rename {tests => refactordoc/tests}/test_definition_items.py (94%) rename {tests => refactordoc/tests}/test_function_doc.py (100%) rename {tests => refactordoc/tests}/test_line_functions.py (72%) rename refactordoc/{line_functions.py => util.py} (100%) diff --git a/refactordoc/__init__.py b/refactordoc/__init__.py index be231cf..93b5741 100644 --- a/refactordoc/__init__.py +++ b/refactordoc/__init__.py @@ -5,8 +5,8 @@ # Copyright (c) 2011, Enthought, Inc. # All rights reserved. #------------------------------------------------------------------------------ -from .function_doc import FunctionDoc -from .class_doc import ClassDoc +from refactordoc.function_doc import FunctionDoc +from refactordoc.class_doc import ClassDoc try: # pragma: no cover from ._version import full_version as __version__ diff --git a/refactordoc/base_doc.py b/refactordoc/base_doc.py index 5fa3e89..f0cdf86 100644 --- a/refactordoc/base_doc.py +++ b/refactordoc/base_doc.py @@ -8,8 +8,9 @@ #------------------------------------------------------------------------------ import re -from .definition_items import DefinitionItem -from .line_functions import is_empty, get_indent, fix_backspace, NEW_LINE +from refactordoc.items.definition_item import DefinitionItem +from refactordoc.util import ( + is_empty, get_indent, fix_backspace, NEW_LINE) underline_regex = re.compile(r'\s*\S+\s*\Z') diff --git a/refactordoc/class_doc.py b/refactordoc/class_doc.py index e214e65..58ffca8 100644 --- a/refactordoc/class_doc.py +++ b/refactordoc/class_doc.py @@ -6,10 +6,11 @@ # Copyright (c) 2011, Enthought, Inc. # All rights reserved. #------------------------------------------------------------------------------ -from .base_doc import BaseDoc -from .line_functions import add_indent -from .definition_items import (MethodItem, AttributeItem, max_attribute_length, - max_attribute_index) +from refactordoc.base_doc import BaseDoc +from refactordoc.util import add_indent +from refactordoc.items.attribute_item import AttributeItem +from refactordoc.items.method_item import MethodItem +from refactordoc.items.util import max_attribute_length, max_attribute_index class ClassDoc(BaseDoc): diff --git a/refactordoc/definition_items.py b/refactordoc/definition_items.py deleted file mode 100644 index 7d8a3d2..0000000 --- a/refactordoc/definition_items.py +++ /dev/null @@ -1,546 +0,0 @@ -# -*- coding: utf-8 -*- -#----------------------------------------------------------------------------- -# file: fields.py -# License: LICENSE.TXT -# Author: Ioannis Tziakos -# -# Copyright (c) 2011, Enthought, Inc. -# All rights reserved. -#----------------------------------------------------------------------------- -import collections -import re - -from .line_functions import (add_indent, fix_star, trim_indent, NEW_LINE, - fix_trailing_underscore) - -header_regex = re.compile(r'\s:\s?') -definition_regex = re.compile(r""" -\*{0,2} # no, one or two stars -\w+\s: # a word followed by a semicolumn and optionally a space -( - \s # just a space - | # OR - \s[\w.]+ # dot separated words - (\(.*\))? # with maybe a signature - | - \s[\w.]+ # dot separated words - (\(.*\))? - \sor # with an or in between - \s[\w.]+ - (\(.*\))? -)? -$ # match at the end of the line -""", re.VERBOSE) -function_regex = re.compile(r'\w+\(.*\)\s*') -signature_regex = re.compile('\((.*)\)') - - -class DefinitionItem(collections.namedtuple( - 'DefinitionItem', ('term', 'classifier', 'definition'))): - """ A docstring definition item - - Syntax diagram:: - - +-------------------------------------------------+ - | term [ " : " classifier [ " or " classifier] ] | - +--+----------------------------------------------+---+ - | definition | - | (body elements)+ | - +--------------------------------------------------+ - - The Definition class is based on the nametuple class and is responsible - to check, parse and refactor a docstring definition item into sphinx - friendly rst. - - Attributes - ---------- - term : str - The term usually reflects the name of a parameter or an attribute. - - classifier: str - The classifier of the definition. Commonly used to reflect the type - of an argument or the signature of a function. - - .. note:: Currently only one classifier is supported. - - definition : list - The list of strings that holds the description the definition item. - - .. note:: A Definition item is based on the item of a section definition - list as it defined in restructured text - (_http://docutils.sourceforge.net/docs/ref/rst/restructuredtext.html#sections). - - """ - - @classmethod - def is_definition(cls, line): - """ Check if the line is describing a definition item. - - The method is used to check that a line is following the expected - format for the term and classifier attributes. - - The expected format is:: - - +-------------------------------------------------+ - | term [ " : " classifier [ " or " classifier] ] | - +-------------------------------------------------+ - - Subclasses can subclass to restrict or expand this format. - - """ - return definition_regex.match(line) is not None - - @classmethod - def parse(cls, lines): - """Parse a definition item from a set of lines. - - The class method parses the definition list item from the list of - docstring lines and produces a DefinitionItem with the term, - classifier and the definition. - - .. note:: The global indention in the definition lines is striped - - The term definition is assumed to be in one of the following formats:: - - term - Definition. - - :: - - term - Definition, paragraph 1. - - Definition, paragraph 2. - - :: - - term : classifier - Definition. - - Arguments - --------- - lines - docstring lines of the definition without any empty lines before or - after. - - Returns - ------- - definition : DefinitionItem - - """ - header = lines[0].strip() - term, classifier = header_regex.split(header, maxsplit=1) if \ - (' :' in header) else (header, '') - trimed_lines = trim_indent(lines[1:]) if (len(lines) > 1) else [''] - definition = [line.rstrip() for line in trimed_lines] - return cls(term.strip(), classifier.strip(), definition) - - def to_rst(self, **kwards): - """ Outputs the Definition in sphinx friendly rst. - - The method renders the definition into a list of lines that follow - the rst markup. The default behaviour is to render the definition - as an sphinx definition item:: - - - - () -- - - - Subclasses will usually override the method to provide custom made - behaviour. However the signature of the method should hold only - keyword arguments which have default values. The keyword arguments - can be used to pass addition rendering information to subclasses. - - Returns - ------- - lines : list - A list of string lines rendered in rst. - - Example - ------- - - :: - - >>> item = DefinitionItem('lines', 'list', - ['A list of string lines rendered in rst.']) - >>> item.to_rst() - lines - - *(list)* -- - A list of string lines rendered in rst. - - .. note:: An empty line is added at the end of the list of strings so - that the results can be concatenated directly and rendered properly - by sphinx. - - - """ - postfix = ' --' if (len(self.definition) > 0) else '' - lines = [] - lines += [self.term] - lines += [NEW_LINE] - lines += [' *({0})*{1}'.format(self.classifier, postfix)] - lines += add_indent(self.definition) # definition is all ready a list - lines += [NEW_LINE] - return lines - - -class AttributeItem(DefinitionItem): - """ Definition that renders the rst output using the attribute directive. - - """ - _normal = (".. attribute:: {0}\n" - " :annotation: = {1}\n" - "\n" - "{2}\n\n") - _no_definition = (".. attribute:: {0}\n" - " :annotation: = {1}\n\n") - _no_classifier = (".. attribute:: {0}\n\n" - "{2}\n\n") - _only_term = ".. attribute:: {0}\n\n" - - def to_rst(self, ): - """ Return the attribute info using the attribute sphinx markup. - - Examples - -------- - - :: - - >>> item = AttributeItem('indent', 'int', - ... ['The indent to use for the description block.']) - >>> item.to_rst() - .. attribute:: indent - :annotation: = int - - The indent to use for the description block - >>> - - :: - - >>> item = AttributeItem('indent', '', - ... ['The indent to use for the description block.']) - >>> item.to_rst() - .. attribute:: indent - - The indent to use for the description block - >>> - - .. note:: An empty line is added at the end of the list of strings so - that the results can be concatenated directly and rendered properly - by sphinx. - - """ - definition = '\n'.join(add_indent(self.definition)) - template = self.template.format(self.term, self.classifier, definition) - return template.splitlines() - - @property - def template(self): - if self.classifier == '' and self.definition == ['']: - template = self._only_term - elif self.classifier == '': - template = self._no_classifier - elif self.definition == ['']: - template = self._no_definition - else: - template = self._normal - return template - - -class ArgumentItem(DefinitionItem): - """ A definition item for function argument sections. - - """ - _normal = (":param {0}:\n" - "{2}\n" - ":type {0}: {1}") - _no_definition = (":param {0}:\n" - ":type {0}: {1}") - _no_classifier = (":param {0}:\n" - "{2}") - _only_term = ":param {0}:" - - def to_rst(self): - """ Render ArgumentItem in sphinx friendly rst using the ``:param:`` - role. - - Example - ------- - - :: - - >>> item = ArgumentItem('indent', 'int', - ... ['The indent to use for the description block.', - '' - 'This is the second paragraph of the argument definition.']) - >>> item.to_rst() - :param indent: - The indent to use for the description block. - - This is the second paragraph of the argument definition. - :type indent: int - - .. note:: - - There is no new line added at the last line of the :meth:`to_rst` - method. - - """ - argument = fix_star(self.term) - argument = fix_trailing_underscore(argument) - argument_type = self.classifier - definition = '\n'.join(add_indent(self.definition)) - template = self.template.format(argument, argument_type, definition) - return template.splitlines() - - @property - def template(self): - if self.classifier == '' and self.definition == ['']: - template = self._only_term - elif self.classifier == '': - template = self._no_classifier - elif self.definition == ['']: - template = self._no_definition - else: - template = self._normal - return template - - -class ListItem(DefinitionItem): - """ A definition item that is rendered as an ordered/unordered list - - """ - - _normal = ("**{0}** (*{1}*) --\n" - "{2}\n\n") - _only_term = "**{0}**\n\n" - _no_definition = "**{0}** (*{1}*)\n\n" - _no_classifier = ("**{0}** --\n" - "{2}\n\n") - - def to_rst(self, prefix=None): - """ Outputs ListItem in rst using as items in an list. - - Arguments - --------- - prefix : str - The prefix to use. For example if the item is part of a numbered - list then ``prefix='-'``. - - Example - ------- - - >>> item = ListItem('indent', 'int', - ... ['The indent to use for the description block.']) - >>> item.to_rst(prefix='-') - - **indent** (`int`) -- - The indent to use for the description block. - - >>> item = ListItem('indent', 'int', - ... ['The indent to use for' - 'the description block.']) - >>> item.to_rst(prefix='-') - - **indent** (`int`) -- - The indent to use for - the description block. - - - .. note:: An empty line is added at the end of the list of strings so - that the results can be concatenated directly and rendered properly - by sphinx. - - """ - indent = 0 if (prefix is None) else len(prefix) + 1 - definition = '\n'.join(add_indent(self.definition, indent)) - template = self.template.format(self.term, self.classifier, definition) - if prefix is not None: - template = prefix + ' ' + template - return template.splitlines() - - @property - def template(self): - if self.classifier == '' and self.definition == ['']: - template = self._only_term - elif self.classifier == '': - template = self._no_classifier - elif self.definition == ['']: - template = self._no_definition - else: - template = self._normal - return template - - -class TableLineItem(DefinitionItem): - """ A Definition Item that represents a table line. - - """ - - def to_rst(self, columns=(0, 0, 0)): - """ Outputs definition in rst as a line in a table. - - Arguments - --------- - columns : tuple - The three item tuple of column widths for the term, classifier - and definition fields of the TableLineItem. When the column width - is 0 then the field - - .. note:: - - The strings attributes are clipped to the column width. - - Example - ------- - - >>> item = TableLineItem('function(arg1, arg2)', '', - ... ['This is the best function ever.']) - >>> item.to_rst(columns=(22, 0, 20)) - function(arg1, arg2) This is the best fun - - """ - definition = ' '.join([line.strip() for line in self.definition]) - term = self.term[:columns[0]] - classifier = self.classifier[:columns[1]] - definition = definition[:columns[2]] - - first_column = '' if columns[0] == 0 else '{0:<{first}} ' - second_column = '' if columns[1] == 0 else '{1:<{second}} ' - third_column = '' if columns[2] == 0 else '{2:<{third}}' - table_line = ''.join((first_column, second_column, third_column)) - - lines = [] - lines += [table_line.format(term, classifier, definition, - first=columns[0], second=columns[1], third=columns[2])] - lines += [''] - return lines - - -class MethodItem(DefinitionItem): - """ A TableLineItem subclass to parse and render class methods. - - """ - @classmethod - def is_definition(cls, line): - """ Check if the definition header is a function signature. - - """ - match = function_regex.match(line) - return match - - @classmethod - def parse(cls, lines): - """Parse a method definition item from a set of lines. - - The class method parses the method signature and definition from the - list of docstring lines and produces a MethodItem where the term - is the method name and the classifier is arguments - - .. note:: The global indention in the definition lines is striped - - The method definition item is assumed to be as follows:: - - +------------------------------+ - | term "(" [ classifier ] ")" | - +--+---------------------------+---+ - | definition | - | (body elements)+ | - +--------------------- ---------+ - - Arguments - --------- - lines : - docstring lines of the method definition item without any empty - lines before or after. - - Returns - ------- - definition : MethodItem - - """ - header = lines[0].strip() - term, classifier, _ = signature_regex.split(header) - definition = trim_indent(lines[1:]) if (len(lines) > 1) else [''] - return cls(term, classifier, definition) - - def to_rst(self, columns=(0, 0)): - """ Outputs definition in rst as a line in a table. - - Arguments - --------- - columns : tuple - The two item tuple of column widths for the :meth: role column - and the definition (i.e. summary) of the MethodItem - - .. note:: The strings attributes are clipped to the column width. - - Example - ------- - - :: - - >>> item = MethodItem('function', 'arg1, arg2', - ... ['This is the best function ever.']) - >>> item.to_rst(columns=(40, 20)) - :meth:`function ` This is the best fun - - """ - definition = ' '.join([line.strip() for line in self.definition]) - method_role = ':meth:`{0}({1}) <{0}>`'.format(self.term, - self.classifier) - table_line = '{0:<{first}} {1:<{second}}' - - lines = [] - lines += [table_line.format(method_role[:columns[0]], - definition[:columns[1]], first=columns[0], - second=columns[1])] - return lines - - @property - def signature(self): - return '{0}({1})'.format(self.term, self.classifier) - - -#------------------------------------------------------------------------------ -# Functions to work with Definition Items -#------------------------------------------------------------------------------ - -def max_attribute_length(items, attr): - """ Find the max length of the attribute in a list of DefinitionItems. - - Arguments - --------- - items : list - The list of the DefinitionItem instances (or subclasses). - - attr : str - Attribute to look at. - - """ - if attr == 'definition': - maximum = max([len(' '.join(item.definition)) for item in items]) - else: - maximum = max([len(getattr(item, attr)) for item in items]) - return maximum - - -def max_attribute_index(items, attr): - """ Find the index of the attribute with the maximum length in a list of - DefinitionItems. - - Arguments - --------- - items : list - The list of the DefinitionItems (or subclasses). - - attr : str - Attribute to look at. - - """ - if attr == 'definition': - attributes = [len(' '.join(item.definition)) for item in items] - else: - attributes = [len(getattr(item, attr)) for item in items] - - maximum = max(attributes) - return attributes.index(maximum) diff --git a/refactordoc/function_doc.py b/refactordoc/function_doc.py index f761e17..31ca137 100644 --- a/refactordoc/function_doc.py +++ b/refactordoc/function_doc.py @@ -7,9 +7,10 @@ # Copyright (c) 2011, Enthought, Inc. # All rights reserved. #------------------------------------------------------------------------------ -from .base_doc import BaseDoc -from .line_functions import add_indent -from .definition_items import ArgumentItem, ListItem +from refactordoc.base_doc import BaseDoc +from refactordoc.util import add_indent +from refactordoc.items.argument_item import ArgumentItem +from refactordoc.items.list_item import ListItem class FunctionDoc(BaseDoc): diff --git a/refactordoc/items/__init__.py b/refactordoc/items/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/refactordoc/items/__init__.py @@ -0,0 +1 @@ + diff --git a/refactordoc/items/argument_item.py b/refactordoc/items/argument_item.py new file mode 100644 index 0000000..124ba59 --- /dev/null +++ b/refactordoc/items/argument_item.py @@ -0,0 +1,62 @@ +from refactordoc.items.definition_item import DefinitionItem +from refactordoc.util import add_indent, fix_star, fix_trailing_underscore + + +class ArgumentItem(DefinitionItem): + """ A definition item for function argument sections. + + """ + _normal = (":param {0}:\n" + "{2}\n" + ":type {0}: {1}") + _no_definition = (":param {0}:\n" + ":type {0}: {1}") + _no_classifier = (":param {0}:\n" + "{2}") + _only_term = ":param {0}:" + + def to_rst(self): + """ Render ArgumentItem in sphinx friendly rst using the ``:param:`` + role. + + Example + ------- + + :: + + >>> item = ArgumentItem('indent', 'int', + ... ['The indent to use for the description block.', + '' + 'This is the second paragraph of the argument definition.']) + >>> item.to_rst() + :param indent: + The indent to use for the description block. + + This is the second paragraph of the argument definition. + :type indent: int + + .. note:: + + There is no new line added at the last line of the :meth:`to_rst` + method. + + """ + argument = fix_star(self.term) + argument = fix_trailing_underscore(argument) + argument_type = self.classifier + definition = '\n'.join(add_indent(self.definition)) + template = self.template.format(argument, argument_type, definition) + return template.splitlines() + + @property + def template(self): + if self.classifier == '' and self.definition == ['']: + template = self._only_term + elif self.classifier == '': + template = self._no_classifier + elif self.definition == ['']: + template = self._no_definition + else: + template = self._normal + return template + diff --git a/refactordoc/items/attribute_item.py b/refactordoc/items/attribute_item.py new file mode 100644 index 0000000..0faf1b8 --- /dev/null +++ b/refactordoc/items/attribute_item.py @@ -0,0 +1,65 @@ +from refactordoc.items.definition_item import DefinitionItem +from refactordoc.util import add_indent + + +class AttributeItem(DefinitionItem): + """ Definition that renders the rst output using the attribute directive. + + """ + _normal = (".. attribute:: {0}\n" + " :annotation: = {1}\n" + "\n" + "{2}\n\n") + _no_definition = (".. attribute:: {0}\n" + " :annotation: = {1}\n\n") + _no_classifier = (".. attribute:: {0}\n\n" + "{2}\n\n") + _only_term = ".. attribute:: {0}\n\n" + + def to_rst(self, ): + """ Return the attribute info using the attribute sphinx markup. + + Examples + -------- + + :: + + >>> item = AttributeItem('indent', 'int', + ... ['The indent to use for the description block.']) + >>> item.to_rst() + .. attribute:: indent + :annotation: = int + + The indent to use for the description block + >>> + + :: + + >>> item = AttributeItem('indent', '', + ... ['The indent to use for the description block.']) + >>> item.to_rst() + .. attribute:: indent + + The indent to use for the description block + >>> + + .. note:: An empty line is added at the end of the list of strings so + that the results can be concatenated directly and rendered properly + by sphinx. + + """ + definition = '\n'.join(add_indent(self.definition)) + template = self.template.format(self.term, self.classifier, definition) + return template.splitlines() + + @property + def template(self): + if self.classifier == '' and self.definition == ['']: + template = self._only_term + elif self.classifier == '': + template = self._no_classifier + elif self.definition == ['']: + template = self._no_definition + else: + template = self._normal + return template diff --git a/refactordoc/items/definition_item.py b/refactordoc/items/definition_item.py new file mode 100644 index 0000000..3f54e13 --- /dev/null +++ b/refactordoc/items/definition_item.py @@ -0,0 +1,180 @@ +import collections +import re + +from refactordoc.util import ( + add_indent, fix_star, trim_indent, NEW_LINE, fix_trailing_underscore) + + + +#: Regex to use for matching the header for the d +header_regex = re.compile(r'\s:\s?') + +#: +definition_regex = re.compile(r""" +\*{0,2} # no, one or two stars +\w+\s: # a word followed by a semicolumn and optionally a space +( + \s # just a space + | # OR + \s[\w.]+ # dot separated words + (\(.*\))? # with maybe a signature + | + \s[\w.]+ # dot separated words + (\(.*\))? + \sor # with an or in between + \s[\w.]+ + (\(.*\))? +)? +$ # match at the end of the line +""", re.VERBOSE) + + +class DefinitionItem(collections.namedtuple( + 'DefinitionItem', ('term', 'classifier', 'definition'))): + """ A docstring definition item + + Syntax diagram:: + + +-------------------------------------------------+ + | term [ " : " classifier [ " or " classifier] ] | + +--+----------------------------------------------+---+ + | definition | + | (body elements)+ | + +--------------------------------------------------+ + + The Definition class is based on the nametuple class and is responsible + to check, parse and refactor a docstring definition item into sphinx + friendly rst. + + Attributes + ---------- + term : str + The term usually reflects the name of a parameter or an attribute. + + classifier: str + The classifier of the definition. Commonly used to reflect the type + of an argument or the signature of a function. + + .. note:: Currently only one classifier is supported. + + definition : list + The list of strings that holds the description the definition item. + + .. note:: A Definition item is based on the item of a section definition + list as it defined in restructured text + (_http://docutils.sourceforge.net/docs/ref/rst/restructuredtext.html#sections). + + """ + + @classmethod + def is_definition(cls, line): + """ Check if the line is describing a definition item. + + The method is used to check that a line is following the expected + format for the term and classifier attributes. + + The expected format is:: + + +-------------------------------------------------+ + | term [ " : " classifier [ " or " classifier] ] | + +-------------------------------------------------+ + + Subclasses can subclass to restrict or expand this format. + + """ + return definition_regex.match(line) is not None + + @classmethod + def parse(cls, lines): + """Parse a definition item from a set of lines. + + The class method parses the definition list item from the list of + docstring lines and produces a DefinitionItem with the term, + classifier and the definition. + + .. note:: The global indention in the definition lines is striped + + The term definition is assumed to be in one of the following formats:: + + term + Definition. + + :: + + term + Definition, paragraph 1. + + Definition, paragraph 2. + + :: + + term : classifier + Definition. + + Arguments + --------- + lines + docstring lines of the definition without any empty lines before or + after. + + Returns + ------- + definition : DefinitionItem + + """ + header = lines[0].strip() + term, classifier = header_regex.split(header, maxsplit=1) if \ + (' :' in header) else (header, '') + trimed_lines = trim_indent(lines[1:]) if (len(lines) > 1) else [''] + definition = [line.rstrip() for line in trimed_lines] + return cls(term.strip(), classifier.strip(), definition) + + def to_rst(self, **kwards): + """ Outputs the Definition in sphinx friendly rst. + + The method renders the definition into a list of lines that follow + the rst markup. The default behaviour is to render the definition + as an sphinx definition item:: + + + + () -- + + + Subclasses will usually override the method to provide custom made + behaviour. However the signature of the method should hold only + keyword arguments which have default values. The keyword arguments + can be used to pass addition rendering information to subclasses. + + Returns + ------- + lines : list + A list of string lines rendered in rst. + + Example + ------- + + :: + + >>> item = DefinitionItem('lines', 'list', + ['A list of string lines rendered in rst.']) + >>> item.to_rst() + lines + + *(list)* -- + A list of string lines rendered in rst. + + .. note:: An empty line is added at the end of the list of strings so + that the results can be concatenated directly and rendered properly + by sphinx. + + + """ + postfix = ' --' if (len(self.definition) > 0) else '' + lines = [] + lines += [self.term] + lines += [NEW_LINE] + lines += [' *({0})*{1}'.format(self.classifier, postfix)] + lines += add_indent(self.definition) # definition is all ready a list + lines += [NEW_LINE] + return lines diff --git a/refactordoc/items/list_item.py b/refactordoc/items/list_item.py new file mode 100644 index 0000000..8520b22 --- /dev/null +++ b/refactordoc/items/list_item.py @@ -0,0 +1,67 @@ +from refactordoc.items.definition_item import DefinitionItem +from refactordoc.util import add_indent + + +class ListItem(DefinitionItem): + """ A definition item that is rendered as an ordered/unordered list + + """ + + _normal = ("**{0}** (*{1}*) --\n" + "{2}\n\n") + _only_term = "**{0}**\n\n" + _no_definition = "**{0}** (*{1}*)\n\n" + _no_classifier = ("**{0}** --\n" + "{2}\n\n") + + def to_rst(self, prefix=None): + """ Outputs ListItem in rst using as items in an list. + + Arguments + --------- + prefix : str + The prefix to use. For example if the item is part of a numbered + list then ``prefix='-'``. + + Example + ------- + + >>> item = ListItem('indent', 'int', + ... ['The indent to use for the description block.']) + >>> item.to_rst(prefix='-') + - **indent** (`int`) -- + The indent to use for the description block. + + >>> item = ListItem('indent', 'int', + ... ['The indent to use for' + 'the description block.']) + >>> item.to_rst(prefix='-') + - **indent** (`int`) -- + The indent to use for + the description block. + + + .. note:: An empty line is added at the end of the list of strings so + that the results can be concatenated directly and rendered properly + by sphinx. + + """ + indent = 0 if (prefix is None) else len(prefix) + 1 + definition = '\n'.join(add_indent(self.definition, indent)) + template = self.template.format(self.term, self.classifier, definition) + if prefix is not None: + template = prefix + ' ' + template + return template.splitlines() + + @property + def template(self): + if self.classifier == '' and self.definition == ['']: + template = self._only_term + elif self.classifier == '': + template = self._no_classifier + elif self.definition == ['']: + template = self._no_definition + else: + template = self._normal + return template + diff --git a/refactordoc/items/method_item.py b/refactordoc/items/method_item.py new file mode 100644 index 0000000..d9106e6 --- /dev/null +++ b/refactordoc/items/method_item.py @@ -0,0 +1,94 @@ +import re + +from refactordoc.items.definition_item import DefinitionItem +from refactordoc.util import trim_indent + + +function_regex = re.compile(r'\w+\(.*\)\s*') +signature_regex = re.compile('\((.*)\)') + + +class MethodItem(DefinitionItem): + """ A TableLineItem subclass to parse and render class methods. + + """ + @classmethod + def is_definition(cls, line): + """ Check if the definition header is a function signature. + + """ + match = function_regex.match(line) + return match + + @classmethod + def parse(cls, lines): + """Parse a method definition item from a set of lines. + + The class method parses the method signature and definition from the + list of docstring lines and produces a MethodItem where the term + is the method name and the classifier is arguments + + .. note:: The global indention in the definition lines is striped + + The method definition item is assumed to be as follows:: + + +------------------------------+ + | term "(" [ classifier ] ")" | + +--+---------------------------+---+ + | definition | + | (body elements)+ | + +--------------------- ---------+ + + Arguments + --------- + lines : + docstring lines of the method definition item without any empty + lines before or after. + + Returns + ------- + definition : MethodItem + + """ + header = lines[0].strip() + term, classifier, _ = signature_regex.split(header) + definition = trim_indent(lines[1:]) if (len(lines) > 1) else [''] + return cls(term, classifier, definition) + + def to_rst(self, columns=(0, 0)): + """ Outputs definition in rst as a line in a table. + + Arguments + --------- + columns : tuple + The two item tuple of column widths for the :meth: role column + and the definition (i.e. summary) of the MethodItem + + .. note:: The strings attributes are clipped to the column width. + + Example + ------- + + :: + + >>> item = MethodItem('function', 'arg1, arg2', + ... ['This is the best function ever.']) + >>> item.to_rst(columns=(40, 20)) + :meth:`function ` This is the best fun + + """ + definition = ' '.join([line.strip() for line in self.definition]) + method_role = ':meth:`{0}({1}) <{0}>`'.format(self.term, + self.classifier) + table_line = '{0:<{first}} {1:<{second}}' + + lines = [] + lines += [table_line.format(method_role[:columns[0]], + definition[:columns[1]], first=columns[0], + second=columns[1])] + return lines + + @property + def signature(self): + return '{0}({1})'.format(self.term, self.classifier) + diff --git a/refactordoc/items/table_row_item.py b/refactordoc/items/table_row_item.py new file mode 100644 index 0000000..b980244 --- /dev/null +++ b/refactordoc/items/table_row_item.py @@ -0,0 +1,46 @@ +from refactordoc.items.definition_item import DefinitionItem + + +class TableRowItem(DefinitionItem): + """ A Definition Item that represents a table line. + + """ + + def to_rst(self, columns=(0, 0, 0)): + """ Outputs definition in rst as a line in a table. + + Arguments + --------- + columns : tuple + The three item tuple of column widths for the term, classifier + and definition fields of the TableLineItem. When the column width + is 0 then the field + + .. note:: + - The strings attributes are clipped to the column width. + + Example + ------- + + >>> item = TableRowItem('function(arg1, arg2)', '', + ... ['This is the best function ever.']) + >>> item.to_rst(columns=(22, 0, 20)) + function(arg1, arg2) This is the best fun + + """ + definition = ' '.join([line.strip() for line in self.definition]) + term = self.term[:columns[0]] + classifier = self.classifier[:columns[1]] + definition = definition[:columns[2]] + + first_column = '' if columns[0] == 0 else '{0:<{first}} ' + second_column = '' if columns[1] == 0 else '{1:<{second}} ' + third_column = '' if columns[2] == 0 else '{2:<{third}}' + table_line = ''.join((first_column, second_column, third_column)) + + lines = [] + lines += [table_line.format(term, classifier, definition, + first=columns[0], second=columns[1], third=columns[2])] + lines += [''] + return lines + diff --git a/refactordoc/items/util.py b/refactordoc/items/util.py new file mode 100644 index 0000000..2958495 --- /dev/null +++ b/refactordoc/items/util.py @@ -0,0 +1,39 @@ +def max_attribute_length(items, attr): + """ Find the max length of the attribute in a list of DefinitionItems. + + Arguments + --------- + items : list + The list of the DefinitionItem instances (or subclasses). + + attr : str + Attribute to look at. + + """ + if attr == 'definition': + maximum = max([len(' '.join(item.definition)) for item in items]) + else: + maximum = max([len(getattr(item, attr)) for item in items]) + return maximum + + +def max_attribute_index(items, attr): + """ Find the index of the attribute with the maximum length in a list of + DefinitionItems. + + Arguments + --------- + items : list + The list of the DefinitionItems (or subclasses). + + attr : str + Attribute to look at. + + """ + if attr == 'definition': + attributes = [len(' '.join(item.definition)) for item in items] + else: + attributes = [len(getattr(item, attr)) for item in items] + + maximum = max(attributes) + return attributes.index(maximum) diff --git a/tests/__init__.py b/refactordoc/tests/__init__.py similarity index 100% rename from tests/__init__.py rename to refactordoc/tests/__init__.py diff --git a/tests/_compat.py b/refactordoc/tests/_compat.py similarity index 100% rename from tests/_compat.py rename to refactordoc/tests/_compat.py diff --git a/tests/test_base_doc.py b/refactordoc/tests/test_base_doc.py similarity index 96% rename from tests/test_base_doc.py rename to refactordoc/tests/test_base_doc.py index dd8ff50..ed81d6d 100644 --- a/tests/test_base_doc.py +++ b/refactordoc/tests/test_base_doc.py @@ -7,7 +7,7 @@ # All rights reserved. #------------------------------------------------------------------------------ from refactordoc.base_doc import BaseDoc -from ._compat import unittest +from refactordoc.tests._compat import unittest class TestBaseDoc(unittest.TestCase): diff --git a/tests/test_class_doc.py b/refactordoc/tests/test_class_doc.py similarity index 100% rename from tests/test_class_doc.py rename to refactordoc/tests/test_class_doc.py diff --git a/tests/test_definition_items.py b/refactordoc/tests/test_definition_items.py similarity index 94% rename from tests/test_definition_items.py rename to refactordoc/tests/test_definition_items.py index b7ad706..0fb70c5 100644 --- a/tests/test_definition_items.py +++ b/refactordoc/tests/test_definition_items.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# -*- coding: utf-8 -*- #------------------------------------------------------------------------------ # file: test_line_functions.py # License: LICENSE.TXT @@ -7,11 +7,13 @@ # Copyright (c) 2011, Enthought, Inc. # All rights reserved. #------------------------------------------------------------------------------ -from refactordoc.definition_items import (DefinitionItem, AttributeItem, - ArgumentItem, ListItem, - TableLineItem, - MethodItem) -from ._compat import unittest +from refactordoc.items.definition_item import DefinitionItem +from refactordoc.items.method_item import MethodItem +from refactordoc.items.argument_item import ArgumentItem +from refactordoc.items.attribute_item import AttributeItem +from refactordoc.items.list_item import ListItem +from refactordoc.items.table_row_item import TableRowItem +from refactordoc.tests._compat import unittest class TestDefinitionItem(unittest.TestCase): @@ -189,7 +191,7 @@ def test_to_rst(self): rst = """\ function(arg1, arg2) This is the best fun """ - item = TableLineItem('function(arg1, arg2)', 'and', + item = TableRowItem('function(arg1, arg2)', 'and', ['This is the best function ever.']) rendered = '\n'.join(item.to_rst(columns=(22, 0, 20))) self.assertMultiLineEqual(rst, rendered) diff --git a/tests/test_function_doc.py b/refactordoc/tests/test_function_doc.py similarity index 100% rename from tests/test_function_doc.py rename to refactordoc/tests/test_function_doc.py diff --git a/tests/test_line_functions.py b/refactordoc/tests/test_line_functions.py similarity index 72% rename from tests/test_line_functions.py rename to refactordoc/tests/test_line_functions.py index 5a5d6dd..4537af3 100644 --- a/tests/test_line_functions.py +++ b/refactordoc/tests/test_line_functions.py @@ -7,37 +7,36 @@ # Copyright (c) 2011, Enthought, Inc. # All rights reserved. #------------------------------------------------------------------------------ -from refactordoc.line_functions import (add_indent, remove_indent, get_indent, - fix_star, fix_backspace, is_empty, - replace_at) -from ._compat import unittest +from refactordoc.util import ( + add_indent, remove_indent, get_indent, fix_star, fix_backspace, is_empty, + replace_at) +from refactordoc.tests._compat import unittest class TestLineFunctions(unittest.TestCase): def test_add_indent(self): - input = ["This is the first line", "", - " This is the third line"] - expected = [" This is the first line", "", - " This is the third line"] + input = ["This is the first line", "", " This is the third line"] + expected = [ + " This is the first line", "", " This is the third line"] output = add_indent(input, indent=3) self.assertEqual(output, expected) - expected = ["This is the first line", "", - " This is the third line"] + expected = [ + "This is the first line", "", " This is the third line"] output = add_indent(input, indent=0) self.assertEqual(output, expected) - expected = [" This is the first line", "", - " This is the third line"] + expected = [ + " This is the first line", "", " This is the third line"] output = add_indent(input) self.assertEqual(output, expected) def test_remove_indent(self): - input = [" This is the first line", "", - " This is the third line"] - expected = ["This is the first line", "", - "This is the third line"] + input = [ + " This is the first line", "", " This is the third line"] + expected = [ + "This is the first line", "", "This is the third line"] output = remove_indent(input) self.assertEqual(output, expected) diff --git a/refactordoc/line_functions.py b/refactordoc/util.py similarity index 100% rename from refactordoc/line_functions.py rename to refactordoc/util.py diff --git a/setup.py b/setup.py index d74c840..b0b43dd 100644 --- a/setup.py +++ b/setup.py @@ -6,7 +6,7 @@ # Copyright (c) 2014, Enthought, Inc. # All rights reserved. #------------------------------------------------------------------------------ -from setuptools import setup +from setuptools import setup, find_packages import os import subprocess @@ -90,7 +90,8 @@ def write_version_py(filename='refactordoc/_version.py'): setup( name='refactordoc', version=__version__, - packages=['refactordoc'], + packages=find_packages(), author="Enthought Ltd", author_email="info@enthought.com", + test_suite='refactordoc.tests', ) From 65544497dadfca47b42ee10f82965640ca763465 Mon Sep 17 00:00:00 2001 From: Ioannis Tziakos Date: Sat, 13 Sep 2014 00:50:39 +0100 Subject: [PATCH 02/63] update the copyright dates --- LICENSE.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE.txt b/LICENSE.txt index 64ef4ee..19c8982 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,7 +1,7 @@ This software is OSI Certified Open Source Software. OSI Certified is a certification mark of the Open Source Initiative. -Copyright (c) 2006, Enthought, Inc. +Copyright (c) 2012-2014, Enthought, Inc. All rights reserved. Redistribution and use in source and binary forms, with or without From a79cf72ff5f2d0a5ced35cd75f41bf320d46a214 Mon Sep 17 00:00:00 2001 From: Ioannis Tziakos Date: Sat, 13 Sep 2014 01:06:34 +0100 Subject: [PATCH 03/63] flake8 fixes --- refactordoc/base_doc.py | 5 +- refactordoc/class_doc.py | 8 +- refactordoc/items/__init__.py | 1 - refactordoc/items/argument_item.py | 1 - refactordoc/items/definition_item.py | 7 +- refactordoc/items/list_item.py | 1 - refactordoc/items/method_item.py | 1 - refactordoc/items/table_row_item.py | 1 - refactordoc/tests/test_base_doc.py | 8 +- refactordoc/tests/test_class_doc.py | 14 ++-- refactordoc/tests/test_definition_items.py | 94 ++++++++++------------ refactordoc/tests/test_function_doc.py | 44 +++++----- 12 files changed, 88 insertions(+), 97 deletions(-) diff --git a/refactordoc/base_doc.py b/refactordoc/base_doc.py index f0cdf86..2ecfe02 100644 --- a/refactordoc/base_doc.py +++ b/refactordoc/base_doc.py @@ -246,8 +246,9 @@ def is_section(self): striped_header = header.rstrip() expected_underline1 = re.sub(r'[A-Za-z\\]|\b\s', '-', striped_header) expected_underline2 = re.sub(r'[A-Za-z\\]|\b\s', '=', striped_header) - if ((underline.group().rstrip() == expected_underline1) or - (underline.group().rstrip() == expected_underline2)): + if ( + (underline.group().rstrip() == expected_underline1) or + (underline.group().rstrip() == expected_underline2)): return header.strip() else: return False diff --git a/refactordoc/class_doc.py b/refactordoc/class_doc.py index 58ffca8..fb3436b 100644 --- a/refactordoc/class_doc.py +++ b/refactordoc/class_doc.py @@ -33,8 +33,10 @@ class ClassDoc(BaseDoc): def __init__(self, lines, headers=None): if headers is None: - headers = {'Attributes': 'attributes', 'Methods': 'methods', - 'Notes':'notes'} + headers = { + 'Attributes': 'attributes', + 'Methods': 'methods', + 'Notes': 'notes'} super(ClassDoc, self).__init__(lines, headers) return @@ -55,7 +57,7 @@ def _refactor_methods(self, header): """ items = self.extract_items(MethodItem) lines = [] - if len(items) > 0 : + if len(items) > 0: columns = self._get_column_lengths(items) border = '{0:=^{1}} {0:=^{2}}'.format('', columns[0], columns[1]) heading = '{0:<{2}} {1:<{3}}'.format('Method', 'Description', diff --git a/refactordoc/items/__init__.py b/refactordoc/items/__init__.py index 8b13789..e69de29 100644 --- a/refactordoc/items/__init__.py +++ b/refactordoc/items/__init__.py @@ -1 +0,0 @@ - diff --git a/refactordoc/items/argument_item.py b/refactordoc/items/argument_item.py index 124ba59..35509b2 100644 --- a/refactordoc/items/argument_item.py +++ b/refactordoc/items/argument_item.py @@ -59,4 +59,3 @@ def template(self): else: template = self._normal return template - diff --git a/refactordoc/items/definition_item.py b/refactordoc/items/definition_item.py index 3f54e13..4fae2bd 100644 --- a/refactordoc/items/definition_item.py +++ b/refactordoc/items/definition_item.py @@ -1,9 +1,8 @@ import collections import re -from refactordoc.util import ( - add_indent, fix_star, trim_indent, NEW_LINE, fix_trailing_underscore) +from refactordoc.util import add_indent, trim_indent, NEW_LINE #: Regex to use for matching the header for the d @@ -123,8 +122,8 @@ def parse(cls, lines): """ header = lines[0].strip() - term, classifier = header_regex.split(header, maxsplit=1) if \ - (' :' in header) else (header, '') + term, classifier = header_regex.split( + header, maxsplit=1) if (' :' in header) else (header, '') trimed_lines = trim_indent(lines[1:]) if (len(lines) > 1) else [''] definition = [line.rstrip() for line in trimed_lines] return cls(term.strip(), classifier.strip(), definition) diff --git a/refactordoc/items/list_item.py b/refactordoc/items/list_item.py index 8520b22..4ca49aa 100644 --- a/refactordoc/items/list_item.py +++ b/refactordoc/items/list_item.py @@ -64,4 +64,3 @@ def template(self): else: template = self._normal return template - diff --git a/refactordoc/items/method_item.py b/refactordoc/items/method_item.py index d9106e6..aedd5b6 100644 --- a/refactordoc/items/method_item.py +++ b/refactordoc/items/method_item.py @@ -91,4 +91,3 @@ def to_rst(self, columns=(0, 0)): @property def signature(self): return '{0}({1})'.format(self.term, self.classifier) - diff --git a/refactordoc/items/table_row_item.py b/refactordoc/items/table_row_item.py index b980244..8edae2c 100644 --- a/refactordoc/items/table_row_item.py +++ b/refactordoc/items/table_row_item.py @@ -43,4 +43,3 @@ def to_rst(self, columns=(0, 0, 0)): first=columns[0], second=columns[1], third=columns[2])] lines += [''] return lines - diff --git a/refactordoc/tests/test_base_doc.py b/refactordoc/tests/test_base_doc.py index ed81d6d..5485377 100644 --- a/refactordoc/tests/test_base_doc.py +++ b/refactordoc/tests/test_base_doc.py @@ -17,7 +17,7 @@ def setUp(self): def test_refactor_header(self): docstring =\ -""" This is a sample docstring. + """ This is a sample docstring. My Header --------- @@ -25,7 +25,7 @@ def test_refactor_header(self): """ rst =\ -""" This is a sample docstring. + """ This is a sample docstring. .. rubric:: My Header @@ -39,7 +39,7 @@ def test_refactor_header(self): def test_refactor_complex_header(self): docstring =\ -""" This is a sample docstring. + """ This is a sample docstring. Input\\Output header ------------------- @@ -48,7 +48,7 @@ def test_refactor_complex_header(self): """ rst =\ -""" This is a sample docstring. + """ This is a sample docstring. .. rubric:: Input\\\\Output header diff --git a/refactordoc/tests/test_class_doc.py b/refactordoc/tests/test_class_doc.py index e7936b0..8b1ef1f 100644 --- a/refactordoc/tests/test_class_doc.py +++ b/refactordoc/tests/test_class_doc.py @@ -17,7 +17,7 @@ def setUp(self): def test_refactor_attributes(self): docstring =\ -"""Base abstract docstring refactoring class. + """Base abstract docstring refactoring class. The class' main purpose is to parse the dosctring and find the sections that need to be refactored. It also provides a number of @@ -35,7 +35,7 @@ def test_refactor_attributes(self): """ rst = \ -"""Base abstract docstring refactoring class. + """Base abstract docstring refactoring class. The class' main purpose is to parse the dosctring and find the sections that need to be refactored. It also provides a number of @@ -62,7 +62,7 @@ def test_refactor_attributes(self): def test_refactor_methods(self): docstring =\ -""" This is a sample class docstring + """ This is a sample class docstring Methods ------- @@ -78,7 +78,7 @@ def test_refactor_methods(self): """ rst = \ -""" This is a sample class docstring + """ This is a sample class docstring ==================================================================== =================================================== Method Description @@ -98,7 +98,7 @@ def test_refactor_methods(self): def test_refactor_notes(self): docstring1 =\ -""" This is a sample class docstring + """ This is a sample class docstring Notes ----- @@ -109,7 +109,7 @@ def test_refactor_notes(self): """ docstring2 =\ -""" This is a sample class docstring + """ This is a sample class docstring Notes ----- @@ -121,7 +121,7 @@ def test_refactor_notes(self): """ rst = \ -""" This is a sample class docstring + """ This is a sample class docstring .. note:: This is the test. diff --git a/refactordoc/tests/test_definition_items.py b/refactordoc/tests/test_definition_items.py index 0fb70c5..b44f193 100644 --- a/refactordoc/tests/test_definition_items.py +++ b/refactordoc/tests/test_definition_items.py @@ -41,36 +41,30 @@ def test_is_definition(self): self.assertTrue(DefinitionItem.is_definition(header_with_or)) def test_parse(self): - item = DefinitionItem.parse(['term', - ' Definition.']) - self.assertEqual(item, DefinitionItem('term', '', - ['Definition.'])) - - item = DefinitionItem.parse(['term', - ' Definition, paragraph 1.', - '', - ' Definition, paragraph 2.']) - self.assertEqual(item, DefinitionItem('term', '', - ['Definition, paragraph 1.', - '', - 'Definition, paragraph 2.'])) - - item = DefinitionItem.parse(['term :', - ' Definition.']) - self.assertEqual(item, DefinitionItem('term', '', - ['Definition.'])) - - item = DefinitionItem.parse(['term : classifier', - ' Definition.']) - self.assertEqual(item, DefinitionItem('term', 'classifier', - ['Definition.'])) - - item = DefinitionItem.parse(['term : classifier', - ' Block.', - ' Definition.']) - self.assertEqual(item, DefinitionItem('term', 'classifier', - ['Block.', - ' Definition.'])) + item = DefinitionItem.parse(['term', ' Definition.']) + self.assertEqual(item, DefinitionItem('term', '', ['Definition.'])) + + item = DefinitionItem.parse([ + 'term', ' Definition, paragraph 1.', + '', ' Definition, paragraph 2.']) + self.assertEqual( + item, DefinitionItem( + 'term', '', + ['Definition, paragraph 1.', '', 'Definition, paragraph 2.'])) + + item = DefinitionItem.parse( + ['term :', ' Definition.']) + self.assertEqual(item, DefinitionItem('term', '', ['Definition.'])) + + item = DefinitionItem.parse(['term : classifier', ' Definition.']) + self.assertEqual( + item, DefinitionItem('term', 'classifier', ['Definition.'])) + + item = DefinitionItem.parse( + ['term : classifier', ' Block.', ' Definition.']) + self.assertEqual( + item, DefinitionItem( + 'term', 'classifier', ['Block.', ' Definition.'])) def test_to_rst(self): rst = """\ @@ -79,8 +73,8 @@ def test_to_rst(self): *(list)* -- A list of string lines rendered in rst. """ - item = DefinitionItem('lines', 'list', - ['A list of string lines rendered in rst.']) + item = DefinitionItem( + 'lines', 'list', ['A list of string lines rendered in rst.']) rendered = '\n'.join(item.to_rst()) self.assertMultiLineEqual(rst, rendered) @@ -127,10 +121,10 @@ def test_to_rst(self): This is the second paragraph of the argument definition. :type indent: int""" - item = ArgumentItem('indent', 'int', - ['The indent to use for the description block.', - '' - 'This is the second paragraph of the argument definition.']) + item = ArgumentItem( + 'indent', 'int', [ + 'The indent to use for the description block.', + 'This is the second paragraph of the argument definition.']) rendered = '\n'.join(item.to_rst()) self.assertMultiLineEqual(rst, rendered) @@ -147,10 +141,10 @@ def test_to_rst_normal(self): This is the second paragraph of the argument definition. """ - item = ListItem('indent', 'int', - ['The indent to use for the description block.', - '', - 'This is the second paragraph of the argument definition.']) + item = ListItem( + 'indent', 'int', [ + 'The indent to use for the description block.', '', + 'This is the second paragraph of the argument definition.']) rendered = '\n'.join(item.to_rst(prefix='-')) self.assertMultiLineEqual(rst, rendered) @@ -159,8 +153,8 @@ def test_to_rst_no_classifier(self): - **indent** -- The indent to use for the description block. """ - item = ListItem('indent', '', - ['The indent to use for the description block.']) + item = ListItem( + 'indent', '', ['The indent to use for the description block.']) rendered = '\n'.join(item.to_rst(prefix='-')) self.assertMultiLineEqual(rst, rendered) @@ -191,8 +185,8 @@ def test_to_rst(self): rst = """\ function(arg1, arg2) This is the best fun """ - item = TableRowItem('function(arg1, arg2)', 'and', - ['This is the best function ever.']) + item = TableRowItem( + 'function(arg1, arg2)', 'and', ['This is the best function ever.']) rendered = '\n'.join(item.to_rst(columns=(22, 0, 20))) self.assertMultiLineEqual(rst, rendered) @@ -204,16 +198,16 @@ def setUp(self): def test_is_definition(self): self.assertTrue(MethodItem.is_definition("term()")) - self.assertTrue(MethodItem.is_definition( - "term(*args, my_keyword=None)")) + self.assertTrue( + MethodItem.is_definition("term(*args, my_keyword=None)")) self.assertFalse(MethodItem.is_definition("term")) self.assertFalse(MethodItem.is_definition("term : *args")) def test_parse(self): - item = MethodItem.parse(['method(arguments)', - ' Definition in a single line']) - self.assertEqual(item, MethodItem('method', 'arguments', - ['Definition in a single line'])) + item = MethodItem.parse( + ['method(arguments)', ' Definition in a single line']) + self.assertEqual(item, MethodItem( + 'method', 'arguments', ['Definition in a single line'])) def test_to_rst(self): # with annotation diff --git a/refactordoc/tests/test_function_doc.py b/refactordoc/tests/test_function_doc.py index 1b9c6d7..7658fc4 100644 --- a/refactordoc/tests/test_function_doc.py +++ b/refactordoc/tests/test_function_doc.py @@ -16,8 +16,8 @@ def setUp(self): self.maxDiff = None def test_refactor_returns(self): - docstring =\ -""" This is a sample function docstring. + docstring = \ + """ This is a sample function docstring. Returns ------- @@ -27,7 +27,7 @@ def test_refactor_returns(self): """ rst = \ -""" This is a sample function docstring. + """ This is a sample function docstring. :returns: **myvalue** (*list*) -- @@ -42,8 +42,8 @@ def test_refactor_returns(self): self.assertMultiLineEqual(rst, output) def test_refactor_raises(self): - docstring =\ -""" This is a sample function docstring. + docstring = \ + """ This is a sample function docstring. Raises ------ @@ -56,7 +56,7 @@ def test_refactor_raises(self): """ rst = \ -""" This is a sample function docstring. + """ This is a sample function docstring. :raises: - **TypeError** -- @@ -75,7 +75,7 @@ def test_refactor_raises(self): def test_refactor_arguments(self): docstring =\ -""" This is a sample function docstring + """ This is a sample function docstring Arguments --------- @@ -92,7 +92,7 @@ def test_refactor_arguments(self): """ rst = \ -""" This is a sample function docstring + """ This is a sample function docstring :param inputa: The first argument holds the first input!. @@ -114,8 +114,8 @@ def test_refactor_arguments(self): self.assertMultiLineEqual(rst, output) def test_refactor_strange_arguments(self): - docstring =\ -""" This is a sample function docstring + docstring = \ + """ This is a sample function docstring Parameters ---------- @@ -132,7 +132,7 @@ def test_refactor_strange_arguments(self): """ rst = \ -""" This is a sample function docstring + """ This is a sample function docstring :param \*args: Positional arguments with which this constructor was called @@ -151,8 +151,8 @@ def test_refactor_strange_arguments(self): self.assertMultiLineEqual(rst, output) def test_refactor_notes(self): - docstring =\ -""" This is a sample function docstring. + docstring = \ + """ This is a sample function docstring. Notes ----- @@ -163,7 +163,7 @@ def test_refactor_notes(self): """ rst = \ -""" This is a sample function docstring. + """ This is a sample function docstring. .. note:: This is the test. @@ -179,8 +179,8 @@ def test_refactor_notes(self): self.assertMultiLineEqual(rst, output) def test_docstring_cases_1(self): - docstring1 =\ -""" Sets the selection to the bounds of start and end. + docstring1 = \ + """ Sets the selection to the bounds of start and end. If the indices are invalid, no selection will be made, and any current selection will be cleared. @@ -198,8 +198,8 @@ def test_docstring_cases_1(self): result : None """ - docstring2 =\ -""" Sets the selection to the bounds of start and end. + docstring2 = \ + """ Sets the selection to the bounds of start and end. If the indices are invalid, no selection will be made, and any current selection will be cleared. @@ -216,8 +216,8 @@ def test_docstring_cases_1(self): result : None """ - rst =\ -""" Sets the selection to the bounds of start and end. + rst = \ + """ Sets the selection to the bounds of start and end. If the indices are invalid, no selection will be made, and any current selection will be cleared. @@ -248,7 +248,7 @@ def test_docstring_cases_1(self): def test_docstring_cases_2(self): docstring = \ -""" Verify that the requested attribute is properly set + """ Verify that the requested attribute is properly set The method compares the attribute value in the Enaml object and check if it is synchronized with the toolkit widget. The component @@ -279,7 +279,7 @@ def test_docstring_cases_2(self): """ rst = \ -""" Verify that the requested attribute is properly set + """ Verify that the requested attribute is properly set The method compares the attribute value in the Enaml object and check if it is synchronized with the toolkit widget. The component From 637a6228aa5cda2d49ebbfa9b901e165466050c6 Mon Sep 17 00:00:00 2001 From: Ioannis Tziakos Date: Sat, 13 Sep 2014 01:12:27 +0100 Subject: [PATCH 04/63] add unittest2 to the requirements --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index b675993..4affe3b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,6 +9,7 @@ python: before_install: - pip install haas + - pip install unittest2 - pip install coverage - pip install coveralls From b5922cb5329de95d86795cb29aa093918c69a442 Mon Sep 17 00:00:00 2001 From: Ioannis Tziakos Date: Sat, 13 Sep 2014 01:14:21 +0100 Subject: [PATCH 05/63] place requirements into a separate file --- .travis.yml | 6 +----- test_requirements.txt | 5 +++++ 2 files changed, 6 insertions(+), 5 deletions(-) create mode 100644 test_requirements.txt diff --git a/.travis.yml b/.travis.yml index 4affe3b..7ea003b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,11 +8,7 @@ python: - 3.4 before_install: - - pip install haas - - pip install unittest2 - - pip install coverage - - pip install coveralls - + - pip install -r test_requirements.txt script: - coverage run -m haas -v - coverage report -m diff --git a/test_requirements.txt b/test_requirements.txt new file mode 100644 index 0000000..17364e1 --- /dev/null +++ b/test_requirements.txt @@ -0,0 +1,5 @@ +haas +unittest2 +coverage +coveralls + From c6ad5b375cce74d3a389001a61800eb9852339db Mon Sep 17 00:00:00 2001 From: itziakos Date: Mon, 15 Sep 2014 01:34:38 +0100 Subject: [PATCH 06/63] factor out Item --- refactordoc/items/item.py | 99 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 refactordoc/items/item.py diff --git a/refactordoc/items/item.py b/refactordoc/items/item.py new file mode 100644 index 0000000..ccf48ad --- /dev/null +++ b/refactordoc/items/item.py @@ -0,0 +1,99 @@ +import abc + + +class Item(object): + """ A docstring item. + + The Item class is responsible to check, parse and refactor a docstring + item into sphinx friendly rst. + + Syntax diagram: + + +-------------------------------------------------+ + | header | + +--+----------------------------------------------+---+ + | definition | + | (body elements)+ | + +--------------------------------------------------+ + + + Depending only the type of the list item the header is split into a + term and one or more classifiers. + + Attributes + ---------- + term : str + The term usually reflects the name of a parameter or an attribute. + + classifiers: list + The classifier(s) of the term. Commonly used to reflect the type + of an argument or the signature of a function. + + definition : list + The list of strings that holds the description the definition item. + + """ + + __metaclass__ = abc.ABCMeta + + def __init__(self, term, classifiers, definition): + self.term = term + self.classifiers = classifiers + self.definition = definition + + @classmethod + def is_item(cls, line): + """ Check if the line is describing an item. + + The method is used to check that a line is following the expected + format for the term and classifiers attributes. + + """ + raise NotImplementedError() + + @classmethod + def header_split(cls, line): + """ Splits the header line into term and one or more classifiers. + + """ + raise NotImplementedError() + + @classmethod + def parse(cls, lines): + """Parse a definition item from a set of lines. + + The class method parses the item from the list of docstring lines and + produces a DefinitionItem with the term, classifier and the definition. + + .. note:: The global indention in the definition lines is striped + + Arguments + --------- + lines : + docstring lines of the definition without any empty lines before or + after. + + Returns + ------- + item : Item + + """ + raise NotImplementedError() + + @abc.abstractmethod + def to_rst(self, **kwards): + """ Outputs the Definition in sphinx friendly rst. + + The method renders the definition into a list of lines that follow + the rst markup. + + Subclasses need to override the method to provide their custom made + behaviour. However the signature of the method should hold only + keyword arguments which always have default values. + + Returns + ------- + lines : list + A list of string lines rendered in rst. + + """ From a0d43745f4b674007ff1dbbae75de86a424af2b4 Mon Sep 17 00:00:00 2001 From: itziakos Date: Mon, 15 Sep 2014 03:00:34 +0100 Subject: [PATCH 07/63] use the Item as a base class --- refactordoc/items/argument_item.py | 12 ++-- refactordoc/items/attribute_item.py | 7 ++- refactordoc/items/definition_item.py | 32 ++++++++--- refactordoc/items/list_item.py | 7 ++- refactordoc/items/method_item.py | 12 ++-- refactordoc/items/table_row_item.py | 8 +-- refactordoc/tests/test_definition_items.py | 64 +++++++++++++++------- refactordoc/tests/test_function_doc.py | 3 +- 8 files changed, 93 insertions(+), 52 deletions(-) diff --git a/refactordoc/items/argument_item.py b/refactordoc/items/argument_item.py index 35509b2..f6f87a8 100644 --- a/refactordoc/items/argument_item.py +++ b/refactordoc/items/argument_item.py @@ -11,7 +11,7 @@ class ArgumentItem(DefinitionItem): ":type {0}: {1}") _no_definition = (":param {0}:\n" ":type {0}: {1}") - _no_classifier = (":param {0}:\n" + _no_classifiers = (":param {0}:\n" "{2}") _only_term = ":param {0}:" @@ -43,17 +43,17 @@ def to_rst(self): """ argument = fix_star(self.term) argument = fix_trailing_underscore(argument) - argument_type = self.classifier + argument_types = ' or '.join(self.classifiers) definition = '\n'.join(add_indent(self.definition)) - template = self.template.format(argument, argument_type, definition) + template = self.template.format(argument, argument_types, definition) return template.splitlines() @property def template(self): - if self.classifier == '' and self.definition == ['']: + if self.classifiers == [] and self.definition == ['']: template = self._only_term - elif self.classifier == '': - template = self._no_classifier + elif self.classifiers == []: + template = self._no_classifiers elif self.definition == ['']: template = self._no_definition else: diff --git a/refactordoc/items/attribute_item.py b/refactordoc/items/attribute_item.py index 0faf1b8..7bfa326 100644 --- a/refactordoc/items/attribute_item.py +++ b/refactordoc/items/attribute_item.py @@ -49,14 +49,15 @@ def to_rst(self, ): """ definition = '\n'.join(add_indent(self.definition)) - template = self.template.format(self.term, self.classifier, definition) + template = self.template.format( + self.term, ' or '.join(self.classifiers), definition) return template.splitlines() @property def template(self): - if self.classifier == '' and self.definition == ['']: + if self.classifiers == [] and self.definition == ['']: template = self._only_term - elif self.classifier == '': + elif self.classifiers == []: template = self._no_classifier elif self.definition == ['']: template = self._no_definition diff --git a/refactordoc/items/definition_item.py b/refactordoc/items/definition_item.py index 4fae2bd..53224aa 100644 --- a/refactordoc/items/definition_item.py +++ b/refactordoc/items/definition_item.py @@ -1,7 +1,7 @@ import collections import re - +from refactordoc.items.item import Item from refactordoc.util import add_indent, trim_indent, NEW_LINE @@ -28,8 +28,7 @@ """, re.VERBOSE) -class DefinitionItem(collections.namedtuple( - 'DefinitionItem', ('term', 'classifier', 'definition'))): +class DefinitionItem(Item): """ A docstring definition item Syntax diagram:: @@ -50,8 +49,8 @@ class DefinitionItem(collections.namedtuple( term : str The term usually reflects the name of a parameter or an attribute. - classifier: str - The classifier of the definition. Commonly used to reflect the type + classifiers: list + The classifiers of the definition. Commonly used to reflect the type of an argument or the signature of a function. .. note:: Currently only one classifier is supported. @@ -110,6 +109,11 @@ def parse(cls, lines): term : classifier Definition. + :: + + term : classifier or classifier + Definition. + Arguments --------- lines @@ -122,11 +126,15 @@ def parse(cls, lines): """ header = lines[0].strip() - term, classifier = header_regex.split( + term, classifiers = header_regex.split( header, maxsplit=1) if (' :' in header) else (header, '') + classifiers = [ + classifier.strip() for classifier in classifiers.split('or')] + if classifiers == ['']: + classifiers = [] trimed_lines = trim_indent(lines[1:]) if (len(lines) > 1) else [''] definition = [line.rstrip() for line in trimed_lines] - return cls(term.strip(), classifier.strip(), definition) + return cls(term.strip(), classifiers, definition) def to_rst(self, **kwards): """ Outputs the Definition in sphinx friendly rst. @@ -137,7 +145,7 @@ def to_rst(self, **kwards): - () -- + () -- Subclasses will usually override the method to provide custom made @@ -173,7 +181,13 @@ def to_rst(self, **kwards): lines = [] lines += [self.term] lines += [NEW_LINE] - lines += [' *({0})*{1}'.format(self.classifier, postfix)] + number_of_classifiers = len(self.classifiers) + if number_of_classifiers == 1: + lines += [' *({0[0]})*{1}'.format(self.classifiers, postfix)] + elif number_of_classifiers == 2: + lines += [ + ' *({0[0]} or {0[1]})*{2}'.format( + self.classifiers, postfix)] lines += add_indent(self.definition) # definition is all ready a list lines += [NEW_LINE] return lines diff --git a/refactordoc/items/list_item.py b/refactordoc/items/list_item.py index 4ca49aa..1a328a7 100644 --- a/refactordoc/items/list_item.py +++ b/refactordoc/items/list_item.py @@ -48,16 +48,17 @@ def to_rst(self, prefix=None): """ indent = 0 if (prefix is None) else len(prefix) + 1 definition = '\n'.join(add_indent(self.definition, indent)) - template = self.template.format(self.term, self.classifier, definition) + template = self.template.format( + self.term, ' or '.join(self.classifiers), definition) if prefix is not None: template = prefix + ' ' + template return template.splitlines() @property def template(self): - if self.classifier == '' and self.definition == ['']: + if self.classifiers == [] and self.definition == ['']: template = self._only_term - elif self.classifier == '': + elif self.classifiers == []: template = self._no_classifier elif self.definition == ['']: template = self._no_definition diff --git a/refactordoc/items/method_item.py b/refactordoc/items/method_item.py index aedd5b6..4501949 100644 --- a/refactordoc/items/method_item.py +++ b/refactordoc/items/method_item.py @@ -51,9 +51,11 @@ def parse(cls, lines): """ header = lines[0].strip() - term, classifier, _ = signature_regex.split(header) + term, classifiers, _ = signature_regex.split(header) + classifiers = [ + classifiers.strip() for classifier in classifiers.split()] definition = trim_indent(lines[1:]) if (len(lines) > 1) else [''] - return cls(term, classifier, definition) + return cls(term, classifiers, definition) def to_rst(self, columns=(0, 0)): """ Outputs definition in rst as a line in a table. @@ -78,8 +80,8 @@ def to_rst(self, columns=(0, 0)): """ definition = ' '.join([line.strip() for line in self.definition]) - method_role = ':meth:`{0}({1}) <{0}>`'.format(self.term, - self.classifier) + method_role = ':meth:`{0}({1}) <{0}>`'.format( + self.term, ', '.join(self.classifiers)) table_line = '{0:<{first}} {1:<{second}}' lines = [] @@ -90,4 +92,4 @@ def to_rst(self, columns=(0, 0)): @property def signature(self): - return '{0}({1})'.format(self.term, self.classifier) + return '{0}({1})'.format(self.term, ', '.join(self.classifiers)) diff --git a/refactordoc/items/table_row_item.py b/refactordoc/items/table_row_item.py index 8edae2c..33518e2 100644 --- a/refactordoc/items/table_row_item.py +++ b/refactordoc/items/table_row_item.py @@ -12,9 +12,9 @@ def to_rst(self, columns=(0, 0, 0)): Arguments --------- columns : tuple - The three item tuple of column widths for the term, classifier + The three item tuple of column widths for the term, classifiers and definition fields of the TableLineItem. When the column width - is 0 then the field + is 0 then the field is empty. .. note:: - The strings attributes are clipped to the column width. @@ -30,7 +30,7 @@ def to_rst(self, columns=(0, 0, 0)): """ definition = ' '.join([line.strip() for line in self.definition]) term = self.term[:columns[0]] - classifier = self.classifier[:columns[1]] + classifiers = ', '.join(self.classifiers)[:columns[1]] definition = definition[:columns[2]] first_column = '' if columns[0] == 0 else '{0:<{first}} ' @@ -39,7 +39,7 @@ def to_rst(self, columns=(0, 0, 0)): table_line = ''.join((first_column, second_column, third_column)) lines = [] - lines += [table_line.format(term, classifier, definition, + lines += [table_line.format(term, classifiers, definition, first=columns[0], second=columns[1], third=columns[2])] lines += [''] return lines diff --git a/refactordoc/tests/test_definition_items.py b/refactordoc/tests/test_definition_items.py index b44f193..9d39d69 100644 --- a/refactordoc/tests/test_definition_items.py +++ b/refactordoc/tests/test_definition_items.py @@ -42,29 +42,39 @@ def test_is_definition(self): def test_parse(self): item = DefinitionItem.parse(['term', ' Definition.']) - self.assertEqual(item, DefinitionItem('term', '', ['Definition.'])) + self.assertEqual(item, DefinitionItem('term', [''], ['Definition.'])) item = DefinitionItem.parse([ 'term', ' Definition, paragraph 1.', '', ' Definition, paragraph 2.']) self.assertEqual( - item, DefinitionItem( - 'term', '', - ['Definition, paragraph 1.', '', 'Definition, paragraph 2.'])) + item, + DefinitionItem( + 'term', [''], [ + 'Definition, paragraph 1.', + '', + 'Definition, paragraph 2.'])) - item = DefinitionItem.parse( - ['term :', ' Definition.']) - self.assertEqual(item, DefinitionItem('term', '', ['Definition.'])) + item = DefinitionItem.parse(['term :', ' Definition.']) + self.assertEqual(item, DefinitionItem('term', [''], ['Definition.'])) item = DefinitionItem.parse(['term : classifier', ' Definition.']) self.assertEqual( - item, DefinitionItem('term', 'classifier', ['Definition.'])) + item, DefinitionItem('term', ['classifier'], ['Definition.'])) + + + item = DefinitionItem.parse( + ['term : classifier or classifier', ' Definition.']) + self.assertEqual( + item, + DefinitionItem('term', + ['classifier','classifier'], ['Definition.'])) item = DefinitionItem.parse( ['term : classifier', ' Block.', ' Definition.']) self.assertEqual( item, DefinitionItem( - 'term', 'classifier', ['Block.', ' Definition.'])) + 'term', ['classifier'], ['Block.', ' Definition.'])) def test_to_rst(self): rst = """\ @@ -74,7 +84,7 @@ def test_to_rst(self): A list of string lines rendered in rst. """ item = DefinitionItem( - 'lines', 'list', ['A list of string lines rendered in rst.']) + 'lines', ['list'], ['A list of string lines rendered in rst.']) rendered = '\n'.join(item.to_rst()) self.assertMultiLineEqual(rst, rendered) @@ -92,7 +102,7 @@ def test_to_rst(self): The indent to use for the description block. """ - item = AttributeItem('indent', 'int', + item = AttributeItem('indent', ['int'], ['The indent to use for the description block.']) rendered = '\n'.join(item.to_rst()) self.assertMultiLineEqual(rst, rendered) @@ -103,7 +113,7 @@ def test_to_rst(self): The indent to use for the description block. """ - item = AttributeItem('indent', '', + item = AttributeItem('indent', [], ['The indent to use for the description block.']) rendered = '\n'.join(item.to_rst()) self.assertMultiLineEqual(rst, rendered) @@ -114,7 +124,7 @@ class TestArgumentItem(unittest.TestCase): def setUp(self): self.maxDiff = None - def test_to_rst(self): + def test_to_rst_with_one_classifier(self): rst = """\ :param indent: The indent to use for the description block. @@ -122,7 +132,21 @@ def test_to_rst(self): :type indent: int""" item = ArgumentItem( - 'indent', 'int', [ + 'indent', ['int'], [ + 'The indent to use for the description block.', + 'This is the second paragraph of the argument definition.']) + rendered = '\n'.join(item.to_rst()) + self.assertMultiLineEqual(rst, rendered) + + def test_to_with_two_classifiers(self): + rst = """\ +:param indent: + The indent to use for the description block. + This is the second paragraph of the argument definition. +:type indent: int or float""" + + item = ArgumentItem( + 'indent', ['int', 'float'], [ 'The indent to use for the description block.', 'This is the second paragraph of the argument definition.']) rendered = '\n'.join(item.to_rst()) @@ -142,7 +166,7 @@ def test_to_rst_normal(self): This is the second paragraph of the argument definition. """ item = ListItem( - 'indent', 'int', [ + 'indent', ['int'], [ 'The indent to use for the description block.', '', 'This is the second paragraph of the argument definition.']) rendered = '\n'.join(item.to_rst(prefix='-')) @@ -154,7 +178,7 @@ def test_to_rst_no_classifier(self): The indent to use for the description block. """ item = ListItem( - 'indent', '', ['The indent to use for the description block.']) + 'indent', [], ['The indent to use for the description block.']) rendered = '\n'.join(item.to_rst(prefix='-')) self.assertMultiLineEqual(rst, rendered) @@ -162,7 +186,7 @@ def test_to_rst_only_term(self): rst = """\ - **indent** """ - item = ListItem('indent', '', ['']) + item = ListItem('indent', [], ['']) rendered = '\n'.join(item.to_rst(prefix='-')) self.assertMultiLineEqual(rst, rendered) @@ -170,7 +194,7 @@ def test_to_rst_no_defintition(self): rst = """\ - **indent** (*int*) """ - item = ListItem('indent', 'int', ['']) + item = ListItem('indent', ['int'], ['']) rendered = '\n'.join(item.to_rst(prefix='-')) self.assertMultiLineEqual(rst, rendered) @@ -207,14 +231,14 @@ def test_parse(self): item = MethodItem.parse( ['method(arguments)', ' Definition in a single line']) self.assertEqual(item, MethodItem( - 'method', 'arguments', ['Definition in a single line'])) + 'method', ['arguments'], ['Definition in a single line'])) def test_to_rst(self): # with annotation rst = """\ :meth:`function(arg1, arg2) ` This is the best fun """ - item = MethodItem('function', 'arg1, arg2', + item = MethodItem('function', ['arg1', 'arg2'], ['This is the best function ever.']) rendered = '\n'.join(item.to_rst(columns=(39, 20))) + '\n' self.assertMultiLineEqual(rst, rendered) diff --git a/refactordoc/tests/test_function_doc.py b/refactordoc/tests/test_function_doc.py index 7658fc4..bd45108 100644 --- a/refactordoc/tests/test_function_doc.py +++ b/refactordoc/tests/test_function_doc.py @@ -7,7 +7,7 @@ # All rights reserved. #------------------------------------------------------------------------------ from refactordoc.function_doc import FunctionDoc -from ._compat import unittest +from refactordoc.tests._compat import unittest class TestFunctionDoc(unittest.TestCase): @@ -130,7 +130,6 @@ def test_refactor_strange_arguments(self): from_ : Arguments with trailing underscore. """ - rst = \ """ This is a sample function docstring From a83475927327e7d060841af64267377b60a4b51c Mon Sep 17 00:00:00 2001 From: itziakos Date: Mon, 15 Sep 2014 03:01:32 +0100 Subject: [PATCH 08/63] subclass namedtuple --- refactordoc/items/item.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/refactordoc/items/item.py b/refactordoc/items/item.py index ccf48ad..277bf98 100644 --- a/refactordoc/items/item.py +++ b/refactordoc/items/item.py @@ -1,7 +1,8 @@ import abc +from collections import namedtuple -class Item(object): +class Item(namedtuple('Item', ['term', 'classifiers', 'definition'])): """ A docstring item. The Item class is responsible to check, parse and refactor a docstring @@ -36,11 +37,6 @@ class Item(object): __metaclass__ = abc.ABCMeta - def __init__(self, term, classifiers, definition): - self.term = term - self.classifiers = classifiers - self.definition = definition - @classmethod def is_item(cls, line): """ Check if the line is describing an item. From ccb8426b873d2f070a594e6f3e825ace085b33bf Mon Sep 17 00:00:00 2001 From: itziakos Date: Tue, 23 Sep 2014 20:42:48 +0100 Subject: [PATCH 09/63] factor out section refactoring functions to the sections module --- refactordoc/sections/__init__.py | 14 +++++++++ refactordoc/sections/arguments.py | 28 ++++++++++++++++++ refactordoc/sections/attributes.py | 20 +++++++++++++ refactordoc/sections/item_list.py | 31 ++++++++++++++++++++ refactordoc/sections/methods.py | 32 ++++++++++++++++++++ refactordoc/sections/notes.py | 21 +++++++++++++ refactordoc/sections/rubric.py | 26 +++++++++++++++++ refactordoc/sections/util.py | 47 ++++++++++++++++++++++++++++++ 8 files changed, 219 insertions(+) create mode 100644 refactordoc/sections/__init__.py create mode 100644 refactordoc/sections/arguments.py create mode 100644 refactordoc/sections/attributes.py create mode 100644 refactordoc/sections/item_list.py create mode 100644 refactordoc/sections/methods.py create mode 100644 refactordoc/sections/notes.py create mode 100644 refactordoc/sections/rubric.py create mode 100644 refactordoc/sections/util.py diff --git a/refactordoc/sections/__init__.py b/refactordoc/sections/__init__.py new file mode 100644 index 0000000..ea771a6 --- /dev/null +++ b/refactordoc/sections/__init__.py @@ -0,0 +1,14 @@ +__all__ = [ + 'attributes', + 'notes_paragraph', + 'methods_table', + 'rubric', + 'arguments', + 'item_list'] + +from refactordoc.sections.attributes import attributes +from refactordoc.sections.notes import notes_paragraph +from refactordoc.sections.methods import methods_table +from refactordoc.sections.rubric import rubric +from refactordoc.sections.arguments import arguments +from refactordoc.sections.item_list import item_list diff --git a/refactordoc/sections/arguments.py b/refactordoc/sections/arguments.py new file mode 100644 index 0000000..78ab837 --- /dev/null +++ b/refactordoc/sections/arguments.py @@ -0,0 +1,28 @@ +# -*- coding: utf-8 -*- +# ----------------------------------------------------------------------------- +# file: function_doc.py +# License: LICENSE.TXT +# Author: Ioannis Tziakos +# +# Copyright (c) 2011, Enthought, Inc. +# All rights reserved. +# ----------------------------------------------------------------------------- +from refactordoc.items.argument_item import ArgumentItem + + +def arguments(doc, header): + """ Refactor the argument section to sphinx friendly format. + + Arguments + --------- + doc : BaseDoc + The docstring container. + header : string + This parameter is ignored in this method. + + """ + items = doc.extract_items(item_class=ArgumentItem) + lines = [] + for item in items: + lines += item.to_rst() + return lines diff --git a/refactordoc/sections/attributes.py b/refactordoc/sections/attributes.py new file mode 100644 index 0000000..e56aa01 --- /dev/null +++ b/refactordoc/sections/attributes.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# ----------------------------------------------------------------------------- +# file: sections/attributes.py +# License: LICENSE.TXT +# +# Copyright (c) 2011-14, Enthought, Inc. +# All rights reserved. +# ----------------------------------------------------------------------------- +from refactordoc.items import AttributeItem + + +def attributes(doc, header): + """Refactor the attributes section to sphinx friendly format. + + """ + items = doc.extract_items(AttributeItem) + lines = [] + for item in items: + lines += item.to_rst() + return lines diff --git a/refactordoc/sections/item_list.py b/refactordoc/sections/item_list.py new file mode 100644 index 0000000..f347e4e --- /dev/null +++ b/refactordoc/sections/item_list.py @@ -0,0 +1,31 @@ +# -*- coding: utf-8 -*- +# ----------------------------------------------------------------------------- +# file: sections/item_list.py +# License: LICENSE.TXT +# Author: Ioannis Tziakos +# +# Copyright (c) 2011-14, Enthought, Inc. +# All rights reserved. +# ----------------------------------------------------------------------------- +from refactordoc.util import add_indent +from refactordoc.items.list_item import ListItem + + +def item_list(doc, header): + """ Refactor the a section to sphinx friendly item list. + + Arguments + --------- + doc : BaseDoc + The docstring container. + + header : str + The header name that is used for the fields (i.e. ``:
:``). + + """ + items = doc.extract_items(item_class=ListItem) + lines = [':{0}:'.format(header.lower())] + prefix = None if len(items) == 1 else '-' + for item in items: + lines += add_indent(item.to_rst(prefix)) + return lines diff --git a/refactordoc/sections/methods.py b/refactordoc/sections/methods.py new file mode 100644 index 0000000..90601bc --- /dev/null +++ b/refactordoc/sections/methods.py @@ -0,0 +1,32 @@ +# -*- coding: utf-8 -*- +# ----------------------------------------------------------------------------- +# file: sections/methods.py +# License: LICENSE.TXT +# +# Copyright (c) 2011-14, Enthought, Inc. +# All rights reserved. +# ----------------------------------------------------------------------------- +from refactordoc.items import MethodItem +from refactordoc.sections.util import get_column_lengths + + +def methods_table(doc, header): + """Refactor the methods section to sphinx friendly table format. + + """ + items = doc.extract_items(MethodItem) + lines = [] + if len(items) > 0: + columns = get_column_lengths(items) + border = '{0:=^{1}} {0:=^{2}}'.format('', columns[0], columns[1]) + heading = '{0:<{2}} {1:<{3}}'.format('Method', 'Description', + columns[0], columns[1]) + lines += [border] + lines += [heading] + lines += [border] + for items in items: + lines += items.to_rst(columns) + lines += [border] + lines += [''] + lines = [line.rstrip() for line in lines] + return lines diff --git a/refactordoc/sections/notes.py b/refactordoc/sections/notes.py new file mode 100644 index 0000000..4989986 --- /dev/null +++ b/refactordoc/sections/notes.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +# ----------------------------------------------------------------------------- +# file: sections/notes.py +# License: LICENSE.TXT +# +# Copyright (c) 2011-14, Enthought, Inc. +# All rights reserved. +# ----------------------------------------------------------------------------- +from refactordoc.util import add_indent + + +def notes_paragraph(doc, header): + """Refactor the note section to use the rst ``.. note`` directive. + + The section is expected to be given as a paragraph. + + """ + paragraph = doc.get_next_paragraph() + lines = ['.. note::'] + lines += add_indent(paragraph) + return lines diff --git a/refactordoc/sections/rubric.py b/refactordoc/sections/rubric.py new file mode 100644 index 0000000..7547741 --- /dev/null +++ b/refactordoc/sections/rubric.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- +# ----------------------------------------------------------------------------- +# file: sections/rubric.py +# License: LICENSE.TXT +# +# Copyright (c) 2011-14, Enthought, Inc. +# All rights reserved. +# ----------------------------------------------------------------------------- +from refactordoc.util import fix_backspace, EMPTY_LINE + + +def rubric(doc, header): + """ Refactor a header section using the rubric directive. + + The method supports refactoring of single word headers, two word headers + and headers that include a backslash ''\''. + + Arguments + --------- + header : string + The header string to use with the rubric directive. + + """ + header = fix_backspace(header) + directive = '.. rubric:: {0}'.format(header) + return [directive, EMPTY_LINE] diff --git a/refactordoc/sections/util.py b/refactordoc/sections/util.py new file mode 100644 index 0000000..c01601a --- /dev/null +++ b/refactordoc/sections/util.py @@ -0,0 +1,47 @@ + +# -*- coding: utf-8 -*- +# ----------------------------------------------------------------------------- +# file: sections/util.py +# License: LICENSE.TXT +# +# Copyright (c) 2011-14, Enthought, Inc. +# All rights reserved. +# ----------------------------------------------------------------------------- +from refactordoc.items.util import max_attribute_length, max_attribute_index + + +def get_column_lengths(items): + """ Helper function to estimate the column widths for the refactoring of + the ``Methods`` section. + + The method finds the index of the item that has the largest function + name (i.e. self.term) and the largest signature. If the indexes are not + the same then checks to see which of the two items have the largest + string sum (i.e. self.term + self.signature). + + Parameters + ---------- + items : list + A list of MethodItems + + Returns + ------- + widths : tuple + A tuple of the first_column and second_column maximum widths. + + """ + name_index = max_attribute_index(items, 'term') + signature_index = max_attribute_index(items, 'signature') + if signature_index != name_index: + index = signature_index + item1_width = len(items[index].term + items[index].signature) + index = name_index + item2_width = len(items[index].term + items[index].signature) + first_column = max(item1_width, item2_width) + else: + index = name_index + first_column = len(items[index].term + items[index].signature) + + first_column += 11 # Add boilerplate characters + second_column = max_attribute_length(items, 'definition') + return (first_column, second_column) From a6ba097f1f6fb282f6cb9b2dfe66c9a035d99425 Mon Sep 17 00:00:00 2001 From: itziakos Date: Tue, 23 Sep 2014 20:43:27 +0100 Subject: [PATCH 10/63] provide eaiser access to the Items and fix code --- refactordoc/items/__init__.py | 16 ++++++++++++++++ refactordoc/items/argument_item.py | 14 ++++++++------ refactordoc/items/definition_item.py | 9 ++++----- refactordoc/items/method_item.py | 4 +--- 4 files changed, 29 insertions(+), 14 deletions(-) diff --git a/refactordoc/items/__init__.py b/refactordoc/items/__init__.py index e69de29..a257633 100644 --- a/refactordoc/items/__init__.py +++ b/refactordoc/items/__init__.py @@ -0,0 +1,16 @@ +__all__ = [ + 'ArgumentItem', + 'AttributeItem', + 'DefinitionItem', + 'ListItem', + 'MethodItem', + 'TableRowItem', + 'Item'] + +from refactordoc.items.item import Item +from refactordoc.items.definition_item import DefinitionItem +from refactordoc.items.argument_item import ArgumentItem +from refactordoc.items.attribute_item import AttributeItem +from refactordoc.items.list_item import ListItem +from refactordoc.items.method_item import MethodItem +from refactordoc.items.table_row_item import TableRowItem diff --git a/refactordoc/items/argument_item.py b/refactordoc/items/argument_item.py index f6f87a8..0dd9f03 100644 --- a/refactordoc/items/argument_item.py +++ b/refactordoc/items/argument_item.py @@ -1,18 +1,20 @@ -from refactordoc.items.definition_item import DefinitionItem from refactordoc.util import add_indent, fix_star, fix_trailing_underscore +from .definition_item import DefinitionItem class ArgumentItem(DefinitionItem): """ A definition item for function argument sections. """ - _normal = (":param {0}:\n" - "{2}\n" - ":type {0}: {1}") + _normal = ( + ":param {0}:\n" + "{2}\n" + ":type {0}: {1}") _no_definition = (":param {0}:\n" ":type {0}: {1}") - _no_classifiers = (":param {0}:\n" - "{2}") + _no_classifiers = ( + ":param {0}:\n" + "{2}") _only_term = ":param {0}:" def to_rst(self): diff --git a/refactordoc/items/definition_item.py b/refactordoc/items/definition_item.py index 53224aa..3a9ab7f 100644 --- a/refactordoc/items/definition_item.py +++ b/refactordoc/items/definition_item.py @@ -1,8 +1,7 @@ -import collections -import re +import re from refactordoc.items.item import Item -from refactordoc.util import add_indent, trim_indent, NEW_LINE +from refactordoc.util import add_indent, trim_indent, EMPTY_LINE #: Regex to use for matching the header for the d @@ -180,7 +179,7 @@ def to_rst(self, **kwards): postfix = ' --' if (len(self.definition) > 0) else '' lines = [] lines += [self.term] - lines += [NEW_LINE] + lines += [EMPTY_LINE] number_of_classifiers = len(self.classifiers) if number_of_classifiers == 1: lines += [' *({0[0]})*{1}'.format(self.classifiers, postfix)] @@ -189,5 +188,5 @@ def to_rst(self, **kwards): ' *({0[0]} or {0[1]})*{2}'.format( self.classifiers, postfix)] lines += add_indent(self.definition) # definition is all ready a list - lines += [NEW_LINE] + lines += [EMPTY_LINE] return lines diff --git a/refactordoc/items/method_item.py b/refactordoc/items/method_item.py index 4501949..e779548 100644 --- a/refactordoc/items/method_item.py +++ b/refactordoc/items/method_item.py @@ -52,8 +52,7 @@ def parse(cls, lines): """ header = lines[0].strip() term, classifiers, _ = signature_regex.split(header) - classifiers = [ - classifiers.strip() for classifier in classifiers.split()] + classifiers = [classifiers.strip()] definition = trim_indent(lines[1:]) if (len(lines) > 1) else [''] return cls(term, classifiers, definition) @@ -83,7 +82,6 @@ def to_rst(self, columns=(0, 0)): method_role = ':meth:`{0}({1}) <{0}>`'.format( self.term, ', '.join(self.classifiers)) table_line = '{0:<{first}} {1:<{second}}' - lines = [] lines += [table_line.format(method_role[:columns[0]], definition[:columns[1]], first=columns[0], From 898875e96467ddf2a3b938a72cc33f5fdcdbc07e Mon Sep 17 00:00:00 2001 From: itziakos Date: Tue, 23 Sep 2014 20:44:10 +0100 Subject: [PATCH 11/63] move code for old_styles to the styles module --- refactordoc/__init__.py | 34 +++++------------------- refactordoc/styles/__init__.py | 0 refactordoc/styles/old_style.py | 46 +++++++++++++++++++++++++++++++++ 3 files changed, 53 insertions(+), 27 deletions(-) create mode 100644 refactordoc/styles/__init__.py create mode 100644 refactordoc/styles/old_style.py diff --git a/refactordoc/__init__.py b/refactordoc/__init__.py index 93b5741..7c5232c 100644 --- a/refactordoc/__init__.py +++ b/refactordoc/__init__.py @@ -1,35 +1,15 @@ -#------------------------------------------------------------------------------ -# file: refactor_doc.py +# ----------------------------------------------------------------------------- +# file: __init__.py # License: LICENSE.TXT # -# Copyright (c) 2011, Enthought, Inc. +# Copyright (c) 2011-2014, Enthought, Inc. # All rights reserved. -#------------------------------------------------------------------------------ -from refactordoc.function_doc import FunctionDoc -from refactordoc.class_doc import ClassDoc +# ----------------------------------------------------------------------------- +__all__ = ['__version__', 'setup'] try: # pragma: no cover - from ._version import full_version as __version__ + from refactordoc._version import full_version as __version__ except ImportError: # pragma: no cover __version__ = "not-built" - -#------------------------------------------------------------------------------ -# Extension definition -#------------------------------------------------------------------------------ - -def refactor_docstring(app, what, name, obj, options, lines): - - refactor = None - if 'class' in what: - refactor = ClassDoc(lines) - elif 'function' in what or 'method' in what: - refactor = FunctionDoc(lines) - - if refactor is not None: - refactor.parse() - - -def setup(app): - app.setup_extension('sphinx.ext.autodoc') - app.connect('autodoc-process-docstring', refactor_docstring) +from refactordoc.styles.old_style import setup diff --git a/refactordoc/styles/__init__.py b/refactordoc/styles/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/refactordoc/styles/old_style.py b/refactordoc/styles/old_style.py new file mode 100644 index 0000000..f6be607 --- /dev/null +++ b/refactordoc/styles/old_style.py @@ -0,0 +1,46 @@ +from refactordoc.base_doc import BaseDoc +from refactordoc.sections import ( + attributes, methods_table, notes_paragraph, item_list, arguments) + +# ----------------------------------------------------------------------------- +# Extension definition +# ----------------------------------------------------------------------------- + + +def refactor_class(lines): + return BaseDoc( + lines, + sections={ + 'Attributes': attributes, + 'Methods': methods_table, + 'Notes': notes_paragraph}) + + +def refactor_function(lines): + return BaseDoc( + lines, + sections={ + 'Returns': item_list, + 'Arguments': arguments, + 'Parameters': arguments, + 'Raises': item_list, + 'Yields': item_list, + 'Notes': notes_paragraph}) + + +def refactor_docstring(app, what, name, obj, options, lines): + + if 'class' in what: + refactor = refactor_class(lines) + elif 'function' in what or 'method' in what: + refactor = refactor_function(lines) + else: + refactor = None + + if refactor is not None: + refactor.parse() + + +def setup(app): + app.setup_extension('sphinx.ext.autodoc') + app.connect('autodoc-process-docstring', refactor_docstring) From 2db9264c03dedbbd2c10a6b90a4cab15743647b4 Mon Sep 17 00:00:00 2001 From: itziakos Date: Tue, 23 Sep 2014 20:45:05 +0100 Subject: [PATCH 12/63] remove unused classes --- refactordoc/base_doc.py | 105 ++++++++++++----------------------- refactordoc/class_doc.py | 108 ------------------------------------ refactordoc/function_doc.py | 89 ----------------------------- 3 files changed, 36 insertions(+), 266 deletions(-) delete mode 100644 refactordoc/class_doc.py delete mode 100644 refactordoc/function_doc.py diff --git a/refactordoc/base_doc.py b/refactordoc/base_doc.py index 2ecfe02..361b20e 100644 --- a/refactordoc/base_doc.py +++ b/refactordoc/base_doc.py @@ -1,25 +1,21 @@ # -*- coding: utf-8 -*- -#------------------------------------------------------------------------------ +# ----------------------------------------------------------------------------- # file: base_doc.py # License: LICENSE.TXT # -# Copyright (c) 2011, Enthought, Inc. +# Copyright (c) 2011-14, Enthought, Inc. # All rights reserved. -#------------------------------------------------------------------------------ +# ----------------------------------------------------------------------------- import re from refactordoc.items.definition_item import DefinitionItem -from refactordoc.util import ( - is_empty, get_indent, fix_backspace, NEW_LINE) +from refactordoc.util import is_empty, get_indent +from refactordoc.sections import rubric underline_regex = re.compile(r'\s*\S+\s*\Z') -#------------------------------------------------------------------------------ -# Classes -#------------------------------------------------------------------------------ - class BaseDoc(object): """Base abstract docstring refactoring class. @@ -50,7 +46,7 @@ class BaseDoc(object): """ - def __init__(self, lines, headers=None): + def __init__(self, lines, sections=None): """ Initialize the class The method setups the class attributes and starts parsing the @@ -65,16 +61,15 @@ def __init__(self, lines, headers=None): The sections for which the class has custom refactor methods. Each entry in the dictionary should have as key the name of the section in the form that it appears in the docstrings. - The value should be the postfix of the method, in the - subclasses, that is responsible for refactoring (e.g. - {'Methods': 'method'}). + The value should be a callable, which be responsible for rendering + the header (e.g. {'Methods': method}). """ try: self._docstring = lines.splitlines() except AttributeError: self._docstring = lines - self.headers = {} if headers is None else headers + self.sections = {} if sections is None else sections self.bookmarks = [] def parse(self): @@ -87,68 +82,41 @@ def parse(self): self.index = 0 self.seek_to_next_non_empty_line() while not self.eod: - header = self.is_section() - if header: - self._refactor(header) + section = self.is_section() + if len(section) > 0: + self._refactor(section) else: self.index += 1 self.seek_to_next_non_empty_line() - def _refactor(self, header): + def _refactor(self, section): """Call the heading refactor method. The header is removed from the docstring and the docstring refactoring is dispatched to the appropriate refactoring method. - The name of the refactoring method is constructed using the form - _refactor_
. Where
is the value corresponding to - ``self.headers[header]``. If there is no custom method for the - section then the self._refactor_header() is called with the - found header name as input. - """ self.remove_lines(self.index, 2) # Remove header self.remove_if_empty(self.index) # Remove space after header - refactor_postfix = self.headers.get(header, 'header') - method_name = ''.join(('_refactor_', refactor_postfix)) - method = getattr(self, method_name) - lines = method(header) + method = self.sections.get(section, rubric) + lines = method(self, section) self.insert_and_move(lines, self.index) - def _refactor_header(self, header): - """ Refactor the header section using the rubric directive. - - The method has been tested and supports refactoring single word - headers, two word headers and headers that include a backslash - ''\''. - - Arguments - --------- - header : string - The header string to use with the rubric directive. - - """ - header = fix_backspace(header) - directive = '.. rubric:: {0}'.format(header) - lines = [] - lines += [directive, NEW_LINE] - return lines - - def extract_items(self, item_class=None): + def extract_items(self, item_class): """ Extract the definition items from a docstring. Parse the items in the description of a section into items of the - provided class time. Given a DefinitionItem or a subclass defined by - the ``item_class`` parameter. Staring from the current index position, - the method checks if in the next two lines a valid header exists. - If successful, then the lines that belong to the item description - block (i.e. header + definition) are popped out from the docstring - and passed to the ``item_class`` parser and create an instance of + provided class time. Given an Item or a subclass defined by + the ``item_class`` parameter. The method starts at the current index + position and checks if in the next two lines a valid header exists. + If successful, the lines that belong to the item description + block (i.e. item header + item body) are popped out from the docstring + and passed to the ``item_class`` parser to get an instance of ``item_class``. The process is repeated until there is no compatible ``item_class`` - found or we run out of docstring. Then the method returns a list of - item_class instances. + found or we run out of docstring lines, The collected item class + instances are return. The exit conditions allow for two valid section item layouts: @@ -174,17 +142,16 @@ def extract_items(self, item_class=None): Arguments --------- - item_class : DefinitionItem - A DefinitionItem or a subclass. This argument is used to check + item_class : Item + An Item or a subclass. This argument is used to check if a line in the docstring is a valid item and to parse the - individual list items in the section. When ``None`` (default) the - base DefinitionItem class is used. + individual list items in the section. Returns ------- parameters : list - List of the parsed item instances of ``item_class`` type. + List of the collected item instances of :class:`~.Item` type. """ item_type = DefinitionItem if (item_class is None) else item_class @@ -201,8 +168,8 @@ def get_next_block(self): """ Get the next item block from the docstring. The method reads the next item block in the docstring. The first line - is assumed to be the DefinitionItem header and the following lines to - belong to the definition:: + is assumed to be the Item header and the following lines to + belong to the definition body::
@@ -217,9 +184,9 @@ def get_next_block(self): while not self.eod: peek_0 = self.peek() peek_1 = self.peek(1) - if is_empty(peek_0) and not peek_1.startswith(sub_indent) \ - or not is_empty(peek_0) \ - and not peek_0.startswith(sub_indent): + if is_empty(peek_0) and not peek_1.startswith(sub_indent): + break + elif not is_empty(peek_0) and not peek_0.startswith(sub_indent): break else: line = self.pop() @@ -241,7 +208,7 @@ def is_section(self): # check for underline type format underline = underline_regex.match(line2) if underline is None: - return False + return '' # is the next line an rst section underline? striped_header = header.rstrip() expected_underline1 = re.sub(r'[A-Za-z\\]|\b\s', '-', striped_header) @@ -251,7 +218,7 @@ def is_section(self): (underline.group().rstrip() == expected_underline2)): return header.strip() else: - return False + return '' def insert_lines(self, lines, index): """ Insert refactored lines @@ -364,7 +331,7 @@ def pop(self, index=None): """ Pop a line from the dostrings. """ - index = self.index if (index is None) else index + index = self.index if index is None else index return self._docstring.pop(index) @property diff --git a/refactordoc/class_doc.py b/refactordoc/class_doc.py deleted file mode 100644 index fb3436b..0000000 --- a/refactordoc/class_doc.py +++ /dev/null @@ -1,108 +0,0 @@ -# -*- coding: utf-8 -*- -#------------------------------------------------------------------------------ -# file: class_doc.py -# License: LICENSE.TXT -# -# Copyright (c) 2011, Enthought, Inc. -# All rights reserved. -#------------------------------------------------------------------------------ -from refactordoc.base_doc import BaseDoc -from refactordoc.util import add_indent -from refactordoc.items.attribute_item import AttributeItem -from refactordoc.items.method_item import MethodItem -from refactordoc.items.util import max_attribute_length, max_attribute_index - - -class ClassDoc(BaseDoc): - """ Docstring refactoring for classes. - - The class provides the following refactoring methods. - - Methods - ------- - _refactor_attributes(self, header): - Refactor the attributes section to sphinx friendly format. - - _refactor_methods(self, header): - Refactor the methods section to sphinx friendly format. - - _refactor_notes(self, header): - Refactor the note section to use the rst ``.. note`` directive. - - """ - - def __init__(self, lines, headers=None): - if headers is None: - headers = { - 'Attributes': 'attributes', - 'Methods': 'methods', - 'Notes': 'notes'} - - super(ClassDoc, self).__init__(lines, headers) - return - - def _refactor_attributes(self, header): - """Refactor the attributes section to sphinx friendly format. - - """ - items = self.extract_items(AttributeItem) - lines = [] - for item in items: - lines += item.to_rst() - return lines - - def _refactor_methods(self, header): - """Refactor the methods section to sphinx friendly format. - - """ - items = self.extract_items(MethodItem) - lines = [] - if len(items) > 0: - columns = self._get_column_lengths(items) - border = '{0:=^{1}} {0:=^{2}}'.format('', columns[0], columns[1]) - heading = '{0:<{2}} {1:<{3}}'.format('Method', 'Description', - columns[0], columns[1]) - lines += [border] - lines += [heading] - lines += [border] - for items in items: - lines += items.to_rst(columns) - lines += [border] - lines += [''] - lines = [line.rstrip() for line in lines] - return lines - - def _refactor_notes(self, header): - """Refactor the note section to use the rst ``.. note`` directive. - - """ - paragraph = self.get_next_paragraph() - lines = ['.. note::'] - lines += add_indent(paragraph) - return lines - - def _get_column_lengths(self, items): - """ Helper function to estimate the column widths for the refactoring of - the ``Methods`` section. - - The method finds the index of the item that has the largest function - name (i.e. self.term) and the largest signature. If the indexes are not - the same then checks to see which of the two items have the largest - string sum (i.e. self.term + self.signature). - - """ - name_index = max_attribute_index(items, 'term') - signature_index = max_attribute_index(items, 'signature') - if signature_index != name_index: - index = signature_index - item1_width = len(items[index].term + items[index].signature) - index = name_index - item2_width = len(items[index].term + items[index].signature) - first_column = max(item1_width, item2_width) - else: - index = name_index - first_column = len(items[index].term + items[index].signature) - - first_column += 11 # Add boilerplate characters - second_column = max_attribute_length(items, 'definition') - return (first_column, second_column) diff --git a/refactordoc/function_doc.py b/refactordoc/function_doc.py deleted file mode 100644 index 31ca137..0000000 --- a/refactordoc/function_doc.py +++ /dev/null @@ -1,89 +0,0 @@ -# -*- coding: utf-8 -*- -#------------------------------------------------------------------------------ -# file: function_doc.py -# License: LICENSE.TXT -# Author: Ioannis Tziakos -# -# Copyright (c) 2011, Enthought, Inc. -# All rights reserved. -#------------------------------------------------------------------------------ -from refactordoc.base_doc import BaseDoc -from refactordoc.util import add_indent -from refactordoc.items.argument_item import ArgumentItem -from refactordoc.items.list_item import ListItem - - -class FunctionDoc(BaseDoc): - """Docstring refactoring for functions - - The class provides the following refactoring methods. - - Methods - ------- - _refactor_arguments(self, header): - Refactor the Arguments and Parameters section to sphinx friendly - format. - - _refactor_as_items_list(self, header): - Refactor the Returns, Raises and Yields sections to sphinx friendly - format. - - _refactor_notes(self, header): - Refactor the note section to use the rst ``.. note`` directive. - - """ - - def __init__(self, lines, headers=None): - - if headers is None: - headers = {'Returns': 'as_item_list', 'Arguments': 'arguments', - 'Parameters': 'arguments', 'Raises': 'as_item_list', - 'Yields': 'as_item_list', 'Notes': 'notes'} - - super(FunctionDoc, self).__init__(lines, headers) - return - - def _refactor_as_item_list(self, header): - """ Refactor the a section to sphinx friendly item list. - - Arguments - --------- - header : str - The header name that is used for the fields (i.e. ``:
:``). - - """ - items = self.extract_items(item_class=ListItem) - lines = [':{0}:'.format(header.lower())] - prefix = None if len(items) == 1 else '-' - for item in items: - lines += add_indent(item.to_rst(prefix)) - return lines - - def _refactor_arguments(self, header): - """ Refactor the argument section to sphinx friendly format. - - Arguments - --------- - header : unused - This parameter is ignored in thi method. - - """ - items = self.extract_items(item_class=ArgumentItem) - lines = [] - for item in items: - lines += item.to_rst() - return lines - - def _refactor_notes(self, header): - """ Refactor the notes section to sphinx friendly format. - - Arguments - --------- - header : unused - This parameter is ignored in this method. - - """ - paragraph = self.get_next_paragraph() - lines = ['.. note::'] - lines += add_indent(paragraph) - return lines From 48f9c80d6c8f49e3017e07aca68e588d79b13274 Mon Sep 17 00:00:00 2001 From: itziakos Date: Tue, 23 Sep 2014 20:45:35 +0100 Subject: [PATCH 13/63] rework class and function tests to old_style tests --- ...t_class_doc.py => test_old_style_class.py} | 23 +++++++----------- ...tion_doc.py => test_old_style_function.py} | 24 +++++++++---------- 2 files changed, 20 insertions(+), 27 deletions(-) rename refactordoc/tests/{test_class_doc.py => test_old_style_class.py} (85%) rename refactordoc/tests/{test_function_doc.py => test_old_style_function.py} (91%) diff --git a/refactordoc/tests/test_class_doc.py b/refactordoc/tests/test_old_style_class.py similarity index 85% rename from refactordoc/tests/test_class_doc.py rename to refactordoc/tests/test_old_style_class.py index 8b1ef1f..800a4ab 100644 --- a/refactordoc/tests/test_class_doc.py +++ b/refactordoc/tests/test_old_style_class.py @@ -1,16 +1,9 @@ # -*- coding: utf-8 -*- -#------------------------------------------------------------------------------ -# file: test_class_doc.py -# License: LICENSE.TXT -# -# Copyright (c) 2011, Enthought, Inc. -# All rights reserved. -#------------------------------------------------------------------------------ -from refactordoc.class_doc import ClassDoc -from ._compat import unittest +from refactordoc.styles.old_style import refactor_class +from refactordoc.tests._compat import unittest -class TestClassDoc(unittest.TestCase): +class TestOldStyleClass(unittest.TestCase): def setUp(self): self.maxDiff = None @@ -55,13 +48,13 @@ def test_refactor_attributes(self): """ docstring_lines = docstring.splitlines() - class_doc = ClassDoc(docstring_lines) + class_doc = refactor_class(docstring_lines) class_doc.parse() output = '\n'.join(docstring_lines) self.assertMultiLineEqual(rst, output) def test_refactor_methods(self): - docstring =\ + docstring = \ """ This is a sample class docstring Methods @@ -91,7 +84,7 @@ def test_refactor_methods(self): """ docstring_lines = docstring.splitlines() - class_doc = ClassDoc(docstring_lines) + class_doc = refactor_class(docstring_lines) class_doc.parse() output = '\n'.join(docstring_lines) self.assertMultiLineEqual(rst, output) @@ -131,13 +124,13 @@ def test_refactor_notes(self): """ docstring_lines = docstring1.splitlines() - class_doc = ClassDoc(docstring_lines) + class_doc = refactor_class(docstring_lines) class_doc.parse() output = '\n'.join(docstring_lines) + '\n' self.assertMultiLineEqual(rst, output) docstring_lines = docstring2.splitlines() - class_doc = ClassDoc(docstring_lines) + class_doc = refactor_class(docstring_lines) class_doc.parse() output = '\n'.join(docstring_lines) + '\n' self.assertMultiLineEqual(rst, output) diff --git a/refactordoc/tests/test_function_doc.py b/refactordoc/tests/test_old_style_function.py similarity index 91% rename from refactordoc/tests/test_function_doc.py rename to refactordoc/tests/test_old_style_function.py index bd45108..00ca3cd 100644 --- a/refactordoc/tests/test_function_doc.py +++ b/refactordoc/tests/test_old_style_function.py @@ -1,16 +1,16 @@ # -*- coding: utf-8 -*- -#------------------------------------------------------------------------------ +# ----------------------------------------------------------------------------- # file: test_function_doc.py # License: LICENSE.TXT # # Copyright (c) 2011, Enthought, Inc. # All rights reserved. -#------------------------------------------------------------------------------ -from refactordoc.function_doc import FunctionDoc +# ----------------------------------------------------------------------------- +from refactordoc.styles.old_style import refactor_function from refactordoc.tests._compat import unittest -class TestFunctionDoc(unittest.TestCase): +class TestOldStyleFunction(unittest.TestCase): def setUp(self): self.maxDiff = None @@ -36,7 +36,7 @@ def test_refactor_returns(self): """ docstring_lines = docstring.splitlines() - function_doc = FunctionDoc(docstring_lines) + function_doc = refactor_function(docstring_lines) function_doc.parse() output = '\n'.join(docstring_lines) self.assertMultiLineEqual(rst, output) @@ -68,7 +68,7 @@ def test_refactor_raises(self): """ docstring_lines = docstring.splitlines() - function_doc = FunctionDoc(docstring_lines) + function_doc = refactor_function(docstring_lines) function_doc.parse() output = '\n'.join(docstring_lines) self.assertMultiLineEqual(rst, output) @@ -108,7 +108,7 @@ def test_refactor_arguments(self): """ docstring_lines = docstring.splitlines() - function_doc = FunctionDoc(docstring_lines) + function_doc = refactor_function(docstring_lines) function_doc.parse() output = '\n'.join(docstring_lines) + '\n' self.assertMultiLineEqual(rst, output) @@ -144,7 +144,7 @@ def test_refactor_strange_arguments(self): """ docstring_lines = docstring.splitlines() - function_doc = FunctionDoc(docstring_lines) + function_doc = refactor_function(docstring_lines) function_doc.parse() output = '\n'.join(docstring_lines) + '\n' self.assertMultiLineEqual(rst, output) @@ -172,7 +172,7 @@ def test_refactor_notes(self): """ docstring_lines = docstring.splitlines() - function_doc = FunctionDoc(docstring_lines) + function_doc = refactor_function(docstring_lines) function_doc.parse() output = '\n'.join(docstring_lines) + '\n' self.assertMultiLineEqual(rst, output) @@ -233,13 +233,13 @@ def test_docstring_cases_1(self): """ docstring_lines = docstring1.splitlines() - function_doc = FunctionDoc(docstring_lines) + function_doc = refactor_function(docstring_lines) function_doc.parse() output = '\n'.join(docstring_lines) self.assertMultiLineEqual(rst, output) docstring_lines = docstring2.splitlines() - function_doc = FunctionDoc(docstring_lines) + function_doc = refactor_function(docstring_lines) function_doc.parse() output = '\n'.join(docstring_lines) self.assertMultiLineEqual(rst, output) @@ -307,7 +307,7 @@ def test_docstring_cases_2(self): """ docstring_lines = docstring.splitlines() - function_doc = FunctionDoc(docstring_lines) + function_doc = refactor_function(docstring_lines) function_doc.parse() output = '\n'.join(docstring_lines) + '\n' self.assertMultiLineEqual(rst, output) From fce78f23d552869c12679e5cd4db8d93b9bccb13 Mon Sep 17 00:00:00 2001 From: itziakos Date: Tue, 23 Sep 2014 20:45:46 +0100 Subject: [PATCH 14/63] minor cleanup --- refactordoc/util.py | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/refactordoc/util.py b/refactordoc/util.py index 7032654..a23e119 100644 --- a/refactordoc/util.py +++ b/refactordoc/util.py @@ -1,30 +1,30 @@ # -*- coding: utf-8 -*- -#----------------------------------------------------------------------------- +# ---------------------------------------------------------------------------- # file: line_functions.py # License: LICENSE.TXT # Author: Ioannis Tziakos # # Copyright (c) 2011, Enthought, Inc. # All rights reserved. -#----------------------------------------------------------------------------- +# ---------------------------------------------------------------------------- import re -#----------------------------------------------------------------------------- +# ---------------------------------------------------------------------------- # Pre-compiled regexes -#----------------------------------------------------------------------------- +# ---------------------------------------------------------------------------- indent_regex = re.compile(r'\s+') -#----------------------------------------------------------------------------- +# ---------------------------------------------------------------------------- # Constants -#----------------------------------------------------------------------------- -NEW_LINE = '' +# ---------------------------------------------------------------------------- +EMPTY_LINE = '' -#------------------------------------------------------------------------------ +# ----------------------------------------------------------------------------- # Functions to manage indention -#------------------------------------------------------------------------------ +# ----------------------------------------------------------------------------- def add_indent(lines, indent=4): """ Add spaces to indent a list of lines. @@ -91,17 +91,17 @@ def get_indent(line): return indent.group() -#------------------------------------------------------------------------------ +# ----------------------------------------------------------------------------- # Functions to detect line type -#------------------------------------------------------------------------------ +# ----------------------------------------------------------------------------- def is_empty(line): return not line.strip() -#------------------------------------------------------------------------------ +# ----------------------------------------------------------------------------- # Functions to adjust strings -#------------------------------------------------------------------------------ +# ----------------------------------------------------------------------------- def fix_star(word): """ Replace ``*`` with ``\*`` so that is will be parse properly by From a30b5036a7de192e9b9cac5817bd832ab804966a Mon Sep 17 00:00:00 2001 From: itziakos Date: Tue, 23 Sep 2014 20:47:21 +0100 Subject: [PATCH 15/63] minor cleanup --- refactordoc/tests/test_base_doc.py | 8 -------- refactordoc/tests/test_definition_items.py | 9 --------- refactordoc/tests/test_line_functions.py | 8 -------- 3 files changed, 25 deletions(-) diff --git a/refactordoc/tests/test_base_doc.py b/refactordoc/tests/test_base_doc.py index 5485377..f97470e 100644 --- a/refactordoc/tests/test_base_doc.py +++ b/refactordoc/tests/test_base_doc.py @@ -1,11 +1,3 @@ -# -*- coding: utf-8 -*- -#------------------------------------------------------------------------------ -# file: test_base_doc.py -# License: LICENSE.TXT -# -# Copyright (c) 2011, Enthought, Inc. -# All rights reserved. -#------------------------------------------------------------------------------ from refactordoc.base_doc import BaseDoc from refactordoc.tests._compat import unittest diff --git a/refactordoc/tests/test_definition_items.py b/refactordoc/tests/test_definition_items.py index 9d39d69..dc9f088 100644 --- a/refactordoc/tests/test_definition_items.py +++ b/refactordoc/tests/test_definition_items.py @@ -1,12 +1,3 @@ -# -*- coding: utf-8 -*- -#------------------------------------------------------------------------------ -# file: test_line_functions.py -# License: LICENSE.TXT -# Author: Ioannis Tziakos -# -# Copyright (c) 2011, Enthought, Inc. -# All rights reserved. -#------------------------------------------------------------------------------ from refactordoc.items.definition_item import DefinitionItem from refactordoc.items.method_item import MethodItem from refactordoc.items.argument_item import ArgumentItem diff --git a/refactordoc/tests/test_line_functions.py b/refactordoc/tests/test_line_functions.py index 4537af3..d962cdd 100644 --- a/refactordoc/tests/test_line_functions.py +++ b/refactordoc/tests/test_line_functions.py @@ -1,12 +1,4 @@ # -*- coding: utf-8 -*- -#------------------------------------------------------------------------------ -# file: test_line_functions.py -# License: LICENSE.TXT -# Author: Ioannis Tziakos -# -# Copyright (c) 2011, Enthought, Inc. -# All rights reserved. -#------------------------------------------------------------------------------ from refactordoc.util import ( add_indent, remove_indent, get_indent, fix_star, fix_backspace, is_empty, replace_at) From 3834d8fb283df30896cbf100fbcc563a9cb94bec Mon Sep 17 00:00:00 2001 From: itziakos Date: Tue, 23 Sep 2014 20:47:32 +0100 Subject: [PATCH 16/63] update tests --- refactordoc/tests/test_definition_items.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/refactordoc/tests/test_definition_items.py b/refactordoc/tests/test_definition_items.py index dc9f088..780a652 100644 --- a/refactordoc/tests/test_definition_items.py +++ b/refactordoc/tests/test_definition_items.py @@ -1,4 +1,4 @@ -from refactordoc.items.definition_item import DefinitionItem +from refactordoc.items.definition_item import DefinitionItem from refactordoc.items.method_item import MethodItem from refactordoc.items.argument_item import ArgumentItem from refactordoc.items.attribute_item import AttributeItem @@ -33,7 +33,7 @@ def test_is_definition(self): def test_parse(self): item = DefinitionItem.parse(['term', ' Definition.']) - self.assertEqual(item, DefinitionItem('term', [''], ['Definition.'])) + self.assertEqual(item, DefinitionItem('term', [], ['Definition.'])) item = DefinitionItem.parse([ 'term', ' Definition, paragraph 1.', @@ -41,25 +41,25 @@ def test_parse(self): self.assertEqual( item, DefinitionItem( - 'term', [''], [ + 'term', [], [ 'Definition, paragraph 1.', '', 'Definition, paragraph 2.'])) item = DefinitionItem.parse(['term :', ' Definition.']) - self.assertEqual(item, DefinitionItem('term', [''], ['Definition.'])) + self.assertEqual(item, DefinitionItem('term', [], ['Definition.'])) item = DefinitionItem.parse(['term : classifier', ' Definition.']) self.assertEqual( item, DefinitionItem('term', ['classifier'], ['Definition.'])) - item = DefinitionItem.parse( ['term : classifier or classifier', ' Definition.']) self.assertEqual( item, - DefinitionItem('term', - ['classifier','classifier'], ['Definition.'])) + DefinitionItem( + 'term', + ['classifier', 'classifier'], ['Definition.'])) item = DefinitionItem.parse( ['term : classifier', ' Block.', ' Definition.']) From 1db7518f2d680451f2234f6c1c23b057d7f7e012 Mon Sep 17 00:00:00 2001 From: itziakos Date: Wed, 15 Oct 2014 22:50:19 +0100 Subject: [PATCH 17/63] add a subpackage for renderers --- refactordoc/renderers/__init__.py | 0 refactordoc/renderers/argument.py | 63 ++++++++++++++++++++++++++ refactordoc/renderers/attribute.py | 66 +++++++++++++++++++++++++++ refactordoc/renderers/definition.py | 61 +++++++++++++++++++++++++ refactordoc/renderers/list_item.py | 69 +++++++++++++++++++++++++++++ refactordoc/renderers/method.py | 43 ++++++++++++++++++ refactordoc/renderers/renderer.py | 27 +++++++++++ 7 files changed, 329 insertions(+) create mode 100644 refactordoc/renderers/__init__.py create mode 100644 refactordoc/renderers/argument.py create mode 100644 refactordoc/renderers/attribute.py create mode 100644 refactordoc/renderers/definition.py create mode 100644 refactordoc/renderers/list_item.py create mode 100644 refactordoc/renderers/method.py create mode 100644 refactordoc/renderers/renderer.py diff --git a/refactordoc/renderers/__init__.py b/refactordoc/renderers/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/refactordoc/renderers/argument.py b/refactordoc/renderers/argument.py new file mode 100644 index 0000000..f1a87a0 --- /dev/null +++ b/refactordoc/renderers/argument.py @@ -0,0 +1,63 @@ +from refactordoc.renderer.renderer import Renderer +from refactordoc.util import add_indent, fix_star, fix_trailing_underscore + + +class Argument(Renderer): + """ A definition item for function argument sections. + + """ + _normal = ( + ":param {0}:\n" + "{2}\n" + ":type {0}: {1}") + _no_definition = (":param {0}:\n" + ":type {0}: {1}") + _no_classifiers = ( + ":param {0}:\n" + "{2}") + _only_term = ":param {0}:" + + def to_rst(self): + """ Render an item as an argument using the ``:param:`` + role. + + Example + ------- + + :: + + >>> item = DefinitionItem('indent', 'int', + ... ['The indent to use for the description block.', + '' + 'This is the second paragraph of the argument definition.']) + >>> renderer = ArgumentRenderer(item) + >>> renderer.to_rst() + :param indent: + The indent to use for the description block. + This is the second paragraph of the argument definition. + :type indent: int + + .. note:: + + There is no new line added at the last line of the :meth:`to_rst` + method. + + """ + argument = fix_star(self.term) + argument = fix_trailing_underscore(argument) + argument_types = ' or '.join(self.classifiers) + definition = '\n'.join(add_indent(self.definition)) + template = self.template.format(argument, argument_types, definition) + return template.splitlines() + + @property + def template(self): + if self.classifiers == [] and self.definition == ['']: + template = self._only_term + elif self.classifiers == []: + template = self._no_classifiers + elif self.definition == ['']: + template = self._no_definition + else: + template = self._normal + return template diff --git a/refactordoc/renderers/attribute.py b/refactordoc/renderers/attribute.py new file mode 100644 index 0000000..7044db8 --- /dev/null +++ b/refactordoc/renderers/attribute.py @@ -0,0 +1,66 @@ +from refactordoc.renderers.renderer import Renderer +from refactordoc.util import add_indent + + +class Attribute(Renderer): + """ Definition that renders the rst output using the attribute directive. + + """ + _normal = (".. attribute:: {0}\n" + " :annotation: = {1}\n" + "\n" + "{2}\n\n") + _no_definition = (".. attribute:: {0}\n" + " :annotation: = {1}\n\n") + _no_classifier = (".. attribute:: {0}\n\n" + "{2}\n\n") + _only_term = ".. attribute:: {0}\n\n" + + def to_rst(self, ): + """ Return the attribute info using the attribute sphinx markup. + + Examples + -------- + + :: + + >>> item = AttributeItem('indent', 'int', + ... ['The indent to use for the description block.']) + >>> item.to_rst() + .. attribute:: indent + :annotation: = int + + The indent to use for the description block + >>> + + :: + + >>> item = AttributeItem('indent', '', + ... ['The indent to use for the description block.']) + >>> item.to_rst() + .. attribute:: indent + + The indent to use for the description block + >>> + + .. note:: An empty line is added at the end of the list of strings so + that the results can be concatenated directly and rendered properly + by sphinx. + + """ + definition = '\n'.join(add_indent(self.definition)) + template = self.template.format( + self.term, ' or '.join(self.classifiers), definition) + return template.splitlines() + + @property + def template(self): + if self.classifiers == [] and self.definition == ['']: + template = self._only_term + elif self.classifiers == []: + template = self._no_classifier + elif self.definition == ['']: + template = self._no_definition + else: + template = self._normal + return template diff --git a/refactordoc/renderers/definition.py b/refactordoc/renderers/definition.py new file mode 100644 index 0000000..acb42c3 --- /dev/null +++ b/refactordoc/renderers/definition.py @@ -0,0 +1,61 @@ +from refactordoc.renderers.renderer import Renderer +from refactordoc.util import add_indent, EMPTY_LINE + + +class DefinitionRenderer(Renderer): + + def to_rst(self, **kwards): + """ Outputs the DefinitionItem in sphinx friendly rst. + + The method renders the definition into a list of lines that follow + the rst markup of a sphinx definition item:: + + + + () -- + + + Subclasses will usually override the method to provide custom made + behaviour. However the signature of the method should hold only + keyword arguments which have default values. The keyword arguments + can be used to pass addition rendering information to subclasses. + + Returns + ------- + lines : list + A list of string lines rendered in rst. + + Example + ------- + + :: + + >>> item = DefinitionItem('lines', 'list', + ['A list of string lines rendered in rst.']) + >>> renderer = DefinitionRenderer(item) + >>> renderer.to_rst + lines + + *(list)* -- + A list of string lines rendered in rst. + + .. note:: An empty line is added at the end of the list of strings so + that the results can be concatenated directly and rendered properly + by sphinx. + + + """ + postfix = ' --' if (len(self.definition) > 0) else '' + lines = [] + lines += [self.term] + lines += [EMPTY_LINE] + number_of_classifiers = len(self.classifiers) + if number_of_classifiers == 1: + lines += [' *({0[0]})*{1}'.format(self.classifiers, postfix)] + elif number_of_classifiers == 2: + lines += [ + ' *({0[0]} or {0[1]})*{2}'.format( + self.classifiers, postfix)] + lines += add_indent(self.definition) # definition is all ready a list + lines += [EMPTY_LINE] + return lines diff --git a/refactordoc/renderers/list_item.py b/refactordoc/renderers/list_item.py new file mode 100644 index 0000000..fd91c25 --- /dev/null +++ b/refactordoc/renderers/list_item.py @@ -0,0 +1,69 @@ +from refactordoc.renderers import Renderer +from refactordoc.util import add_indent + + +class ListItem(Renderer): + """ A definition item that is rendered as an ordered/unordered list + + """ + + _normal = ("**{0}** (*{1}*) --\n" + "{2}\n\n") + _only_term = "**{0}**\n\n" + _no_definition = "**{0}** (*{1}*)\n\n" + _no_classifier = ("**{0}** --\n" + "{2}\n\n") + + def to_rst(self, prefix=None): + """ Renders DefinitionItems as items in an list. + + Arguments + --------- + prefix : str + The prefix to use. For example if the item is part of an + unnumbered list then ``prefix='-'``. + + Example + ------- + + >>> item = DefinitionItem('indent', 'int', + ... ['The indent to use for the description block.']) + >>> renderer = ListItem(item) + >>> renderer.to_rst(prefix='-') + - **indent** (`int`) -- + The indent to use for the description block. + + >>> item = DefinitionItem('indent', 'int', + ... ['The indent to use for' + 'the description block.']) + >>> renderer = ListItem(item) + >>> renderer.to_rst(prefix='-') + - **indent** (`int`) -- + The indent to use for + the description block. + + + .. note:: An empty line is added at the end of the list of strings so + that the results can be concatenated directly and rendered properly + by sphinx. + + """ + indent = 0 if (prefix is None) else len(prefix) + 1 + definition = '\n'.join(add_indent(self.definition, indent)) + template = self.template.format( + self.term, ' or '.join(self.classifiers), definition) + if prefix is not None: + template = prefix + ' ' + template + return template.splitlines() + + @property + def template(self): + if self.classifiers == [] and self.definition == ['']: + template = self._only_term + elif self.classifiers == []: + template = self._no_classifier + elif self.definition == ['']: + template = self._no_definition + else: + template = self._normal + return template diff --git a/refactordoc/renderers/method.py b/refactordoc/renderers/method.py new file mode 100644 index 0000000..6249181 --- /dev/null +++ b/refactordoc/renderers/method.py @@ -0,0 +1,43 @@ +from refactordoc.renderers.renderer import Renderer + + +class Method(Renderer): + """ Render method items as a table row. + """ + + def to_rst(self, columns=(0, 0)): + """ Outputs definition in rst as a line in a table. + + Arguments + --------- + columns : tuple + The two item tuple of column widths for the :meth: role column + and the definition (i.e. summary) of the MethodItem + + .. note:: The strings attributes are clipped to the column width. + + Example + ------- + + :: + + >>> item = MethodItem('function', 'arg1, arg2', + ... ['This is the best function ever.']) + >>> renderer = Method(item) + >>> renderer.to_rst(columns=(40, 20)) + :meth:`function ` This is the best fun + + """ + definition = ' '.join([line.strip() for line in self.definition]) + method_role = ':meth:`{0}({1}) <{0}>`'.format( + self.term, ', '.join(self.classifiers)) + table_line = '{0:<{first}} {1:<{second}}' + lines = [] + lines += [table_line.format(method_role[:columns[0]], + definition[:columns[1]], first=columns[0], + second=columns[1])] + return lines + + @property + def signature(self): + return '{0}({1})'.format(self.term, ', '.join(self.classifiers)) diff --git a/refactordoc/renderers/renderer.py b/refactordoc/renderers/renderer.py new file mode 100644 index 0000000..7066c1e --- /dev/null +++ b/refactordoc/renderers/renderer.py @@ -0,0 +1,27 @@ +import abc + + +class Renderer(object): + """ An item renderer. + """ + + def __init__(self, item): + self.item = item + + @abc.abstractmethod + def to_rst(self, **kwards): + """ Outputs the definition item in sphinx friendly rst. + + The method renders the passed into a list of lines that follow + the rst markup. + + Subclasses need to override the method to provide their custom made + behaviour. However the signature of the method should hold only + keyword arguments which always have default values. + + Returns + ------- + lines : list + A list of string lines rendered in rst. + + """ From 312c7db99ca4123eec205e0a80c69c9c0b5cfc49 Mon Sep 17 00:00:00 2001 From: itziakos Date: Fri, 17 Oct 2014 08:33:15 +0100 Subject: [PATCH 18/63] better separate the items and thier parsing constructors from the renderers --- refactordoc/items/__init__.py | 8 -- refactordoc/items/argument_item.py | 63 ------------- refactordoc/items/attribute_item.py | 66 -------------- refactordoc/items/definition_item.py | 88 +------------------ refactordoc/items/item.py | 39 +++----- refactordoc/items/list_item.py | 67 -------------- refactordoc/items/method_item.py | 57 +++--------- refactordoc/items/regex.py | 22 +++++ refactordoc/renderers/argument.py | 47 ++++------ refactordoc/renderers/attribute.py | 44 ++++------ refactordoc/renderers/definition.py | 17 ++-- refactordoc/renderers/list_item.py | 36 +++----- refactordoc/renderers/method.py | 13 ++- .../table_row.py} | 19 ++-- 14 files changed, 116 insertions(+), 470 deletions(-) delete mode 100644 refactordoc/items/argument_item.py delete mode 100644 refactordoc/items/attribute_item.py delete mode 100644 refactordoc/items/list_item.py create mode 100644 refactordoc/items/regex.py rename refactordoc/{items/table_row_item.py => renderers/table_row.py} (69%) diff --git a/refactordoc/items/__init__.py b/refactordoc/items/__init__.py index a257633..8bc2b54 100644 --- a/refactordoc/items/__init__.py +++ b/refactordoc/items/__init__.py @@ -1,16 +1,8 @@ __all__ = [ - 'ArgumentItem', - 'AttributeItem', 'DefinitionItem', - 'ListItem', 'MethodItem', - 'TableRowItem', 'Item'] from refactordoc.items.item import Item from refactordoc.items.definition_item import DefinitionItem -from refactordoc.items.argument_item import ArgumentItem -from refactordoc.items.attribute_item import AttributeItem -from refactordoc.items.list_item import ListItem from refactordoc.items.method_item import MethodItem -from refactordoc.items.table_row_item import TableRowItem diff --git a/refactordoc/items/argument_item.py b/refactordoc/items/argument_item.py deleted file mode 100644 index 0dd9f03..0000000 --- a/refactordoc/items/argument_item.py +++ /dev/null @@ -1,63 +0,0 @@ -from refactordoc.util import add_indent, fix_star, fix_trailing_underscore -from .definition_item import DefinitionItem - - -class ArgumentItem(DefinitionItem): - """ A definition item for function argument sections. - - """ - _normal = ( - ":param {0}:\n" - "{2}\n" - ":type {0}: {1}") - _no_definition = (":param {0}:\n" - ":type {0}: {1}") - _no_classifiers = ( - ":param {0}:\n" - "{2}") - _only_term = ":param {0}:" - - def to_rst(self): - """ Render ArgumentItem in sphinx friendly rst using the ``:param:`` - role. - - Example - ------- - - :: - - >>> item = ArgumentItem('indent', 'int', - ... ['The indent to use for the description block.', - '' - 'This is the second paragraph of the argument definition.']) - >>> item.to_rst() - :param indent: - The indent to use for the description block. - - This is the second paragraph of the argument definition. - :type indent: int - - .. note:: - - There is no new line added at the last line of the :meth:`to_rst` - method. - - """ - argument = fix_star(self.term) - argument = fix_trailing_underscore(argument) - argument_types = ' or '.join(self.classifiers) - definition = '\n'.join(add_indent(self.definition)) - template = self.template.format(argument, argument_types, definition) - return template.splitlines() - - @property - def template(self): - if self.classifiers == [] and self.definition == ['']: - template = self._only_term - elif self.classifiers == []: - template = self._no_classifiers - elif self.definition == ['']: - template = self._no_definition - else: - template = self._normal - return template diff --git a/refactordoc/items/attribute_item.py b/refactordoc/items/attribute_item.py deleted file mode 100644 index 7bfa326..0000000 --- a/refactordoc/items/attribute_item.py +++ /dev/null @@ -1,66 +0,0 @@ -from refactordoc.items.definition_item import DefinitionItem -from refactordoc.util import add_indent - - -class AttributeItem(DefinitionItem): - """ Definition that renders the rst output using the attribute directive. - - """ - _normal = (".. attribute:: {0}\n" - " :annotation: = {1}\n" - "\n" - "{2}\n\n") - _no_definition = (".. attribute:: {0}\n" - " :annotation: = {1}\n\n") - _no_classifier = (".. attribute:: {0}\n\n" - "{2}\n\n") - _only_term = ".. attribute:: {0}\n\n" - - def to_rst(self, ): - """ Return the attribute info using the attribute sphinx markup. - - Examples - -------- - - :: - - >>> item = AttributeItem('indent', 'int', - ... ['The indent to use for the description block.']) - >>> item.to_rst() - .. attribute:: indent - :annotation: = int - - The indent to use for the description block - >>> - - :: - - >>> item = AttributeItem('indent', '', - ... ['The indent to use for the description block.']) - >>> item.to_rst() - .. attribute:: indent - - The indent to use for the description block - >>> - - .. note:: An empty line is added at the end of the list of strings so - that the results can be concatenated directly and rendered properly - by sphinx. - - """ - definition = '\n'.join(add_indent(self.definition)) - template = self.template.format( - self.term, ' or '.join(self.classifiers), definition) - return template.splitlines() - - @property - def template(self): - if self.classifiers == [] and self.definition == ['']: - template = self._only_term - elif self.classifiers == []: - template = self._no_classifier - elif self.definition == ['']: - template = self._no_definition - else: - template = self._normal - return template diff --git a/refactordoc/items/definition_item.py b/refactordoc/items/definition_item.py index 3a9ab7f..0fbca86 100644 --- a/refactordoc/items/definition_item.py +++ b/refactordoc/items/definition_item.py @@ -1,30 +1,6 @@ -import re - +from refactordoc.items.regex import definition_regex, header_regex from refactordoc.items.item import Item -from refactordoc.util import add_indent, trim_indent, EMPTY_LINE - - -#: Regex to use for matching the header for the d -header_regex = re.compile(r'\s:\s?') - -#: -definition_regex = re.compile(r""" -\*{0,2} # no, one or two stars -\w+\s: # a word followed by a semicolumn and optionally a space -( - \s # just a space - | # OR - \s[\w.]+ # dot separated words - (\(.*\))? # with maybe a signature - | - \s[\w.]+ # dot separated words - (\(.*\))? - \sor # with an or in between - \s[\w.]+ - (\(.*\))? -)? -$ # match at the end of the line -""", re.VERBOSE) +from refactordoc.util import trim_indent class DefinitionItem(Item): @@ -64,7 +40,7 @@ class DefinitionItem(Item): """ @classmethod - def is_definition(cls, line): + def is_item(cls, line): """ Check if the line is describing a definition item. The method is used to check that a line is following the expected @@ -133,60 +109,4 @@ def parse(cls, lines): classifiers = [] trimed_lines = trim_indent(lines[1:]) if (len(lines) > 1) else [''] definition = [line.rstrip() for line in trimed_lines] - return cls(term.strip(), classifiers, definition) - - def to_rst(self, **kwards): - """ Outputs the Definition in sphinx friendly rst. - - The method renders the definition into a list of lines that follow - the rst markup. The default behaviour is to render the definition - as an sphinx definition item:: - - - - () -- - - - Subclasses will usually override the method to provide custom made - behaviour. However the signature of the method should hold only - keyword arguments which have default values. The keyword arguments - can be used to pass addition rendering information to subclasses. - - Returns - ------- - lines : list - A list of string lines rendered in rst. - - Example - ------- - - :: - - >>> item = DefinitionItem('lines', 'list', - ['A list of string lines rendered in rst.']) - >>> item.to_rst() - lines - - *(list)* -- - A list of string lines rendered in rst. - - .. note:: An empty line is added at the end of the list of strings so - that the results can be concatenated directly and rendered properly - by sphinx. - - - """ - postfix = ' --' if (len(self.definition) > 0) else '' - lines = [] - lines += [self.term] - lines += [EMPTY_LINE] - number_of_classifiers = len(self.classifiers) - if number_of_classifiers == 1: - lines += [' *({0[0]})*{1}'.format(self.classifiers, postfix)] - elif number_of_classifiers == 2: - lines += [ - ' *({0[0]} or {0[1]})*{2}'.format( - self.classifiers, postfix)] - lines += add_indent(self.definition) # definition is all ready a list - lines += [EMPTY_LINE] - return lines + return Item(term.strip(), classifiers, definition) diff --git a/refactordoc/items/item.py b/refactordoc/items/item.py index 277bf98..0dfe49e 100644 --- a/refactordoc/items/item.py +++ b/refactordoc/items/item.py @@ -35,7 +35,19 @@ class Item(namedtuple('Item', ['term', 'classifiers', 'definition'])): """ - __metaclass__ = abc.ABCMeta + @property + def mode(self): + """ The operational mode of the item based on the available info. + """ + if self.classifiers == [] and self.definition == ['']: + mode = 'only_term' + elif self.classifiers == []: + mode = 'no_classifiers' + elif self.definition == ['']: + mode = 'no_definition' + else: + mode = 'full' + return mode @classmethod def is_item(cls, line): @@ -47,13 +59,6 @@ def is_item(cls, line): """ raise NotImplementedError() - @classmethod - def header_split(cls, line): - """ Splits the header line into term and one or more classifiers. - - """ - raise NotImplementedError() - @classmethod def parse(cls, lines): """Parse a definition item from a set of lines. @@ -75,21 +80,3 @@ def parse(cls, lines): """ raise NotImplementedError() - - @abc.abstractmethod - def to_rst(self, **kwards): - """ Outputs the Definition in sphinx friendly rst. - - The method renders the definition into a list of lines that follow - the rst markup. - - Subclasses need to override the method to provide their custom made - behaviour. However the signature of the method should hold only - keyword arguments which always have default values. - - Returns - ------- - lines : list - A list of string lines rendered in rst. - - """ diff --git a/refactordoc/items/list_item.py b/refactordoc/items/list_item.py deleted file mode 100644 index 1a328a7..0000000 --- a/refactordoc/items/list_item.py +++ /dev/null @@ -1,67 +0,0 @@ -from refactordoc.items.definition_item import DefinitionItem -from refactordoc.util import add_indent - - -class ListItem(DefinitionItem): - """ A definition item that is rendered as an ordered/unordered list - - """ - - _normal = ("**{0}** (*{1}*) --\n" - "{2}\n\n") - _only_term = "**{0}**\n\n" - _no_definition = "**{0}** (*{1}*)\n\n" - _no_classifier = ("**{0}** --\n" - "{2}\n\n") - - def to_rst(self, prefix=None): - """ Outputs ListItem in rst using as items in an list. - - Arguments - --------- - prefix : str - The prefix to use. For example if the item is part of a numbered - list then ``prefix='-'``. - - Example - ------- - - >>> item = ListItem('indent', 'int', - ... ['The indent to use for the description block.']) - >>> item.to_rst(prefix='-') - - **indent** (`int`) -- - The indent to use for the description block. - - >>> item = ListItem('indent', 'int', - ... ['The indent to use for' - 'the description block.']) - >>> item.to_rst(prefix='-') - - **indent** (`int`) -- - The indent to use for - the description block. - - - .. note:: An empty line is added at the end of the list of strings so - that the results can be concatenated directly and rendered properly - by sphinx. - - """ - indent = 0 if (prefix is None) else len(prefix) + 1 - definition = '\n'.join(add_indent(self.definition, indent)) - template = self.template.format( - self.term, ' or '.join(self.classifiers), definition) - if prefix is not None: - template = prefix + ' ' + template - return template.splitlines() - - @property - def template(self): - if self.classifiers == [] and self.definition == ['']: - template = self._only_term - elif self.classifiers == []: - template = self._no_classifier - elif self.definition == ['']: - template = self._no_definition - else: - template = self._normal - return template diff --git a/refactordoc/items/method_item.py b/refactordoc/items/method_item.py index e779548..bfbc4e7 100644 --- a/refactordoc/items/method_item.py +++ b/refactordoc/items/method_item.py @@ -1,24 +1,23 @@ -import re - -from refactordoc.items.definition_item import DefinitionItem +from refactordoc.items.item import Item +from refactordoc.items.regex import function_regex, signature_regex from refactordoc.util import trim_indent -function_regex = re.compile(r'\w+\(.*\)\s*') -signature_regex = re.compile('\((.*)\)') +class MethodItem(Item): + """ A MethodItem that knows how to parse methods + """ -class MethodItem(DefinitionItem): - """ A TableLineItem subclass to parse and render class methods. + @property + def signature(self): + return '{0}({1})'.format(self.term, ', '.join(self.classifiers)) - """ @classmethod - def is_definition(cls, line): + def is_item(cls, line): """ Check if the definition header is a function signature. """ - match = function_regex.match(line) - return match + return function_regex.match(line) @classmethod def parse(cls, lines): @@ -55,39 +54,3 @@ def parse(cls, lines): classifiers = [classifiers.strip()] definition = trim_indent(lines[1:]) if (len(lines) > 1) else [''] return cls(term, classifiers, definition) - - def to_rst(self, columns=(0, 0)): - """ Outputs definition in rst as a line in a table. - - Arguments - --------- - columns : tuple - The two item tuple of column widths for the :meth: role column - and the definition (i.e. summary) of the MethodItem - - .. note:: The strings attributes are clipped to the column width. - - Example - ------- - - :: - - >>> item = MethodItem('function', 'arg1, arg2', - ... ['This is the best function ever.']) - >>> item.to_rst(columns=(40, 20)) - :meth:`function ` This is the best fun - - """ - definition = ' '.join([line.strip() for line in self.definition]) - method_role = ':meth:`{0}({1}) <{0}>`'.format( - self.term, ', '.join(self.classifiers)) - table_line = '{0:<{first}} {1:<{second}}' - lines = [] - lines += [table_line.format(method_role[:columns[0]], - definition[:columns[1]], first=columns[0], - second=columns[1])] - return lines - - @property - def signature(self): - return '{0}({1})'.format(self.term, ', '.join(self.classifiers)) diff --git a/refactordoc/items/regex.py b/refactordoc/items/regex.py new file mode 100644 index 0000000..5f6a287 --- /dev/null +++ b/refactordoc/items/regex.py @@ -0,0 +1,22 @@ +import re + +function_regex = re.compile(r'\w+\(.*\)\s*') +signature_regex = re.compile('\((.*)\)') +header_regex = re.compile(r'\s:\s?') +definition_regex = re.compile(r""" +\*{0,2} # no, one or two stars +\w+\s: # a word followed by a semicolumn and optionally a space +( + \s # just a space + | # OR + \s[\w.]+ # dot separated words + (\(.*\))? # with maybe a signature + | + \s[\w.]+ # dot separated words + (\(.*\))? + \sor # with an or in between + \s[\w.]+ + (\(.*\))? +)? +$ # match at the end of the line +""", re.VERBOSE) diff --git a/refactordoc/renderers/argument.py b/refactordoc/renderers/argument.py index f1a87a0..e0409bf 100644 --- a/refactordoc/renderers/argument.py +++ b/refactordoc/renderers/argument.py @@ -3,21 +3,16 @@ class Argument(Renderer): - """ A definition item for function argument sections. + """ Render an item as a sphinx parameter role. """ - _normal = ( - ":param {0}:\n" - "{2}\n" - ":type {0}: {1}") - _no_definition = (":param {0}:\n" - ":type {0}: {1}") - _no_classifiers = ( - ":param {0}:\n" - "{2}") - _only_term = ":param {0}:" - - def to_rst(self): + templates = { + "normal": ":param {0}:\n{2}\n:type {0}: {1}", + "no_definition": ":param {0}:\n:type {0}: {1}", + "no_classifiers": ":param {0}:\n{2}", + "only_term": ":param {0}:"} + + def to_rst(self, item): """ Render an item as an argument using the ``:param:`` role. @@ -26,11 +21,11 @@ def to_rst(self): :: - >>> item = DefinitionItem('indent', 'int', + >>> item = Item('indent', 'int', ... ['The indent to use for the description block.', '' 'This is the second paragraph of the argument definition.']) - >>> renderer = ArgumentRenderer(item) + >>> renderer = Argument(item) >>> renderer.to_rst() :param indent: The indent to use for the description block. @@ -43,21 +38,11 @@ def to_rst(self): method. """ - argument = fix_star(self.term) + item = self.item + argument = fix_star(item.term) argument = fix_trailing_underscore(argument) - argument_types = ' or '.join(self.classifiers) - definition = '\n'.join(add_indent(self.definition)) - template = self.template.format(argument, argument_types, definition) + argument_types = ' or '.join(item.classifiers) + definition = '\n'.join(add_indent(item.definition)) + template = self.templates[item.mode].format( + argument, argument_types, definition) return template.splitlines() - - @property - def template(self): - if self.classifiers == [] and self.definition == ['']: - template = self._only_term - elif self.classifiers == []: - template = self._no_classifiers - elif self.definition == ['']: - template = self._no_definition - else: - template = self._normal - return template diff --git a/refactordoc/renderers/attribute.py b/refactordoc/renderers/attribute.py index 7044db8..5fca30e 100644 --- a/refactordoc/renderers/attribute.py +++ b/refactordoc/renderers/attribute.py @@ -6,17 +6,14 @@ class Attribute(Renderer): """ Definition that renders the rst output using the attribute directive. """ - _normal = (".. attribute:: {0}\n" - " :annotation: = {1}\n" - "\n" - "{2}\n\n") - _no_definition = (".. attribute:: {0}\n" - " :annotation: = {1}\n\n") - _no_classifier = (".. attribute:: {0}\n\n" - "{2}\n\n") - _only_term = ".. attribute:: {0}\n\n" - def to_rst(self, ): + templates = { + "normal": ".. attribute:: {0}\n :annotation: = {1}\n\n{2}\n\n", + "no_definition": ".. attribute:: {0}\n :annotation: = {1}\n\n", + "no_classifier": ".. attribute:: {0}\n\n{2}\n\n", + "only_term": ".. attribute:: {0}\n\n"} + + def to_rst(self): """ Return the attribute info using the attribute sphinx markup. Examples @@ -24,9 +21,9 @@ def to_rst(self, ): :: - >>> item = AttributeItem('indent', 'int', + >>> item = Item('indent', 'int', ... ['The indent to use for the description block.']) - >>> item.to_rst() + >>> Attribute(item).to_rst() .. attribute:: indent :annotation: = int @@ -35,9 +32,9 @@ def to_rst(self, ): :: - >>> item = AttributeItem('indent', '', + >>> item = Item('indent', '', ... ['The indent to use for the description block.']) - >>> item.to_rst() + >>> Attribute(item).to_rst() .. attribute:: indent The indent to use for the description block @@ -48,19 +45,8 @@ def to_rst(self, ): by sphinx. """ - definition = '\n'.join(add_indent(self.definition)) - template = self.template.format( - self.term, ' or '.join(self.classifiers), definition) + item = self.item + definition = '\n'.join(add_indent(item.definition)) + template = self.templates[item.mode].format( + item.term, ' or '.join(item.classifiers), definition) return template.splitlines() - - @property - def template(self): - if self.classifiers == [] and self.definition == ['']: - template = self._only_term - elif self.classifiers == []: - template = self._no_classifier - elif self.definition == ['']: - template = self._no_definition - else: - template = self._normal - return template diff --git a/refactordoc/renderers/definition.py b/refactordoc/renderers/definition.py index acb42c3..02ba348 100644 --- a/refactordoc/renderers/definition.py +++ b/refactordoc/renderers/definition.py @@ -2,7 +2,7 @@ from refactordoc.util import add_indent, EMPTY_LINE -class DefinitionRenderer(Renderer): +class Definition(Renderer): def to_rst(self, **kwards): """ Outputs the DefinitionItem in sphinx friendly rst. @@ -32,7 +32,7 @@ def to_rst(self, **kwards): >>> item = DefinitionItem('lines', 'list', ['A list of string lines rendered in rst.']) - >>> renderer = DefinitionRenderer(item) + >>> renderer = Definition(item) >>> renderer.to_rst lines @@ -45,17 +45,18 @@ def to_rst(self, **kwards): """ - postfix = ' --' if (len(self.definition) > 0) else '' + item = self.item + postfix = ' --' if (len(item.definition) > 0) else '' lines = [] - lines += [self.term] + lines += [item.term] lines += [EMPTY_LINE] - number_of_classifiers = len(self.classifiers) + number_of_classifiers = len(item.classifiers) if number_of_classifiers == 1: - lines += [' *({0[0]})*{1}'.format(self.classifiers, postfix)] + lines += [' *({0[0]})*{1}'.format(item.classifiers, postfix)] elif number_of_classifiers == 2: lines += [ ' *({0[0]} or {0[1]})*{2}'.format( - self.classifiers, postfix)] - lines += add_indent(self.definition) # definition is all ready a list + item.classifiers, postfix)] + lines += add_indent(item.definition) # definition is already a list lines += [EMPTY_LINE] return lines diff --git a/refactordoc/renderers/list_item.py b/refactordoc/renderers/list_item.py index fd91c25..c2ede80 100644 --- a/refactordoc/renderers/list_item.py +++ b/refactordoc/renderers/list_item.py @@ -7,15 +7,14 @@ class ListItem(Renderer): """ - _normal = ("**{0}** (*{1}*) --\n" - "{2}\n\n") - _only_term = "**{0}**\n\n" - _no_definition = "**{0}** (*{1}*)\n\n" - _no_classifier = ("**{0}** --\n" - "{2}\n\n") + templates = { + "full": "**{0}** (*{1}*) --\n{2}\n\n", + "only_term": "**{0}**\n\n", + "no_definition": "**{0}** (*{1}*)\n\n", + "no_classifier": "**{0}** --\n{2}\n\n"} def to_rst(self, prefix=None): - """ Renders DefinitionItems as items in an list. + """ Renders an item as items in an rst list. Arguments --------- @@ -26,14 +25,14 @@ def to_rst(self, prefix=None): Example ------- - >>> item = DefinitionItem('indent', 'int', + >>> item = Item('indent', 'int', ... ['The indent to use for the description block.']) >>> renderer = ListItem(item) >>> renderer.to_rst(prefix='-') - **indent** (`int`) -- The indent to use for the description block. - >>> item = DefinitionItem('indent', 'int', + >>> item = Item('indent', 'int', ... ['The indent to use for' 'the description block.']) >>> renderer = ListItem(item) @@ -48,22 +47,11 @@ def to_rst(self, prefix=None): by sphinx. """ + item = self.item indent = 0 if (prefix is None) else len(prefix) + 1 - definition = '\n'.join(add_indent(self.definition, indent)) - template = self.template.format( - self.term, ' or '.join(self.classifiers), definition) + definition = '\n'.join(add_indent(item.definition, indent)) + template = self.templates[item.mode].format( + item.term, ' or '.join(item.classifiers), definition) if prefix is not None: template = prefix + ' ' + template return template.splitlines() - - @property - def template(self): - if self.classifiers == [] and self.definition == ['']: - template = self._only_term - elif self.classifiers == []: - template = self._no_classifier - elif self.definition == ['']: - template = self._no_definition - else: - template = self._normal - return template diff --git a/refactordoc/renderers/method.py b/refactordoc/renderers/method.py index 6249181..b470b8a 100644 --- a/refactordoc/renderers/method.py +++ b/refactordoc/renderers/method.py @@ -11,10 +11,10 @@ def to_rst(self, columns=(0, 0)): Arguments --------- columns : tuple - The two item tuple of column widths for the :meth: role column + The two item tuple of column widths for the `:meth:` role column and the definition (i.e. summary) of the MethodItem - .. note:: The strings attributes are clipped to the column width. + .. note:: The string attributes are clipped to the column width. Example ------- @@ -28,16 +28,13 @@ def to_rst(self, columns=(0, 0)): :meth:`function ` This is the best fun """ - definition = ' '.join([line.strip() for line in self.definition]) + item = self.item + definition = ' '.join([line.strip() for line in item.definition]) method_role = ':meth:`{0}({1}) <{0}>`'.format( - self.term, ', '.join(self.classifiers)) + self.term, ', '.join(item.classifiers)) table_line = '{0:<{first}} {1:<{second}}' lines = [] lines += [table_line.format(method_role[:columns[0]], definition[:columns[1]], first=columns[0], second=columns[1])] return lines - - @property - def signature(self): - return '{0}({1})'.format(self.term, ', '.join(self.classifiers)) diff --git a/refactordoc/items/table_row_item.py b/refactordoc/renderers/table_row.py similarity index 69% rename from refactordoc/items/table_row_item.py rename to refactordoc/renderers/table_row.py index 33518e2..c555fda 100644 --- a/refactordoc/items/table_row_item.py +++ b/refactordoc/renderers/table_row.py @@ -1,8 +1,8 @@ -from refactordoc.items.definition_item import DefinitionItem +from refactordoc.rendirexderers.renderer import Renderer -class TableRowItem(DefinitionItem): - """ A Definition Item that represents a table line. +class TableRow(Renderer): + """ Render an Item that represents a table line. """ @@ -14,7 +14,7 @@ def to_rst(self, columns=(0, 0, 0)): columns : tuple The three item tuple of column widths for the term, classifiers and definition fields of the TableLineItem. When the column width - is 0 then the field is empty. + is 0 then the field is ignored. .. note:: - The strings attributes are clipped to the column width. @@ -22,15 +22,16 @@ def to_rst(self, columns=(0, 0, 0)): Example ------- - >>> item = TableRowItem('function(arg1, arg2)', '', + >>> item = Item('function(arg1, arg2)', '', ... ['This is the best function ever.']) - >>> item.to_rst(columns=(22, 0, 20)) + >>> TableRow(item).to_rst(columns=(22, 0, 20)) function(arg1, arg2) This is the best fun """ - definition = ' '.join([line.strip() for line in self.definition]) - term = self.term[:columns[0]] - classifiers = ', '.join(self.classifiers)[:columns[1]] + item = self.item + definition = ' '.join([line.strip() for line in item.definition]) + term = item.term[:columns[0]] + classifiers = ', '.join(item.classifiers)[:columns[1]] definition = definition[:columns[2]] first_column = '' if columns[0] == 0 else '{0:<{first}} ' From 9593657850f27af614cb635d3c79df4b88e8a374 Mon Sep 17 00:00:00 2001 From: itziakos Date: Fri, 17 Oct 2014 08:33:52 +0100 Subject: [PATCH 19/63] start updading the section rendering methods --- refactordoc/sections/arguments.py | 17 +++++++++++++---- refactordoc/sections/attributes.py | 10 ++++++---- refactordoc/sections/item_list.py | 19 ++++++++++++++----- refactordoc/sections/methods.py | 4 +++- 4 files changed, 36 insertions(+), 14 deletions(-) diff --git a/refactordoc/sections/arguments.py b/refactordoc/sections/arguments.py index 78ab837..9475884 100644 --- a/refactordoc/sections/arguments.py +++ b/refactordoc/sections/arguments.py @@ -7,10 +7,11 @@ # Copyright (c) 2011, Enthought, Inc. # All rights reserved. # ----------------------------------------------------------------------------- -from refactordoc.items.argument_item import ArgumentItem +from refactordoc.items import DefinitionItem +from refactordoc.renderers.argument import Argument -def arguments(doc, header): +def arguments(doc, header, renderer=None, item_class=DefinitionItem): """ Refactor the argument section to sphinx friendly format. Arguments @@ -20,9 +21,17 @@ def arguments(doc, header): header : string This parameter is ignored in this method. + renderer : Renderer + A renderer instance to render the items. + + item_class : type + The item parser class to use. Default is :class:`~.DefinitionItem`. + """ - items = doc.extract_items(item_class=ArgumentItem) + items = doc.extract_items(item_class=item_class) lines = [] + renderer = Argument if renderer is None else renderer for item in items: - lines += item.to_rst() + renderer.item = item + lines += renderer.to_rst() return lines diff --git a/refactordoc/sections/attributes.py b/refactordoc/sections/attributes.py index e56aa01..613a7b2 100644 --- a/refactordoc/sections/attributes.py +++ b/refactordoc/sections/attributes.py @@ -6,15 +6,17 @@ # Copyright (c) 2011-14, Enthought, Inc. # All rights reserved. # ----------------------------------------------------------------------------- -from refactordoc.items import AttributeItem +from refactordoc.items import DefinitionItem +from refctordoc.renderers import Attribute -def attributes(doc, header): +def attributes(doc, header, renderer=None, item_class=DefinitionItem): """Refactor the attributes section to sphinx friendly format. """ - items = doc.extract_items(AttributeItem) + + items = doc.extract_items(item_class=DefinitionItem) lines = [] for item in items: - lines += item.to_rst() + lines += renderer(item).to_rst() return lines diff --git a/refactordoc/sections/item_list.py b/refactordoc/sections/item_list.py index f347e4e..b7c294a 100644 --- a/refactordoc/sections/item_list.py +++ b/refactordoc/sections/item_list.py @@ -8,11 +8,12 @@ # All rights reserved. # ----------------------------------------------------------------------------- from refactordoc.util import add_indent -from refactordoc.items.list_item import ListItem +from refactordoc.items import DefinitionItem +from refactordoc.renderers import ListItem -def item_list(doc, header): - """ Refactor the a section to sphinx friendly item list. +def item_list(doc, header, renderer=None, item_class=DefinitionItem): + """ Refactor the section to sphinx friendly item list. Arguments --------- @@ -22,10 +23,18 @@ def item_list(doc, header): header : str The header name that is used for the fields (i.e. ``:
:``). + renderer : Renderer + A renderer instance to render the items. + + item_class : type + The item parser class to use. Default is :class:`~.DefinitionItem`. + """ - items = doc.extract_items(item_class=ListItem) + items = doc.extract_items(item_class=item_class) lines = [':{0}:'.format(header.lower())] prefix = None if len(items) == 1 else '-' + renderer = ListItem if renderer is None else renderer for item in items: - lines += add_indent(item.to_rst(prefix)) + renderer.item = item + lines += add_indent(renderer.to_rst(prefix)) return lines diff --git a/refactordoc/sections/methods.py b/refactordoc/sections/methods.py index 90601bc..3bc6ce1 100644 --- a/refactordoc/sections/methods.py +++ b/refactordoc/sections/methods.py @@ -8,6 +8,7 @@ # ----------------------------------------------------------------------------- from refactordoc.items import MethodItem from refactordoc.sections.util import get_column_lengths +from refactordoc.renderers import Method def methods_table(doc, header): @@ -24,8 +25,9 @@ def methods_table(doc, header): lines += [border] lines += [heading] lines += [border] + renderer = Method() for items in items: - lines += items.to_rst(columns) + lines += renderer.to_rst(columns) lines += [border] lines += [''] lines = [line.rstrip() for line in lines] From 5fb52ab7c7172b3dabbf0e42c2fc7788914e7ef2 Mon Sep 17 00:00:00 2001 From: itziakos Date: Sat, 18 Oct 2014 02:57:09 +0100 Subject: [PATCH 20/63] update the section methods --- refactordoc/sections/arguments.py | 6 +++--- refactordoc/sections/attributes.py | 8 +++++--- refactordoc/sections/item_list.py | 6 +++--- refactordoc/sections/notes.py | 2 +- refactordoc/sections/rubric.py | 2 +- 5 files changed, 13 insertions(+), 11 deletions(-) diff --git a/refactordoc/sections/arguments.py b/refactordoc/sections/arguments.py index 9475884..00d2269 100644 --- a/refactordoc/sections/arguments.py +++ b/refactordoc/sections/arguments.py @@ -11,7 +11,7 @@ from refactordoc.renderers.argument import Argument -def arguments(doc, header, renderer=None, item_class=DefinitionItem): +def arguments(doc, header, renderer=Argument, item_class=DefinitionItem): """ Refactor the argument section to sphinx friendly format. Arguments @@ -28,9 +28,9 @@ def arguments(doc, header, renderer=None, item_class=DefinitionItem): The item parser class to use. Default is :class:`~.DefinitionItem`. """ - items = doc.extract_items(item_class=item_class) + items = doc.extract_items(item_class) lines = [] - renderer = Argument if renderer is None else renderer + renderer = renderer() for item in items: renderer.item = item lines += renderer.to_rst() diff --git a/refactordoc/sections/attributes.py b/refactordoc/sections/attributes.py index 613a7b2..157ef2e 100644 --- a/refactordoc/sections/attributes.py +++ b/refactordoc/sections/attributes.py @@ -10,13 +10,15 @@ from refctordoc.renderers import Attribute -def attributes(doc, header, renderer=None, item_class=DefinitionItem): +def attributes(doc, header, renderer=Attribute, item_class=DefinitionItem): """Refactor the attributes section to sphinx friendly format. """ - items = doc.extract_items(item_class=DefinitionItem) + items = doc.extract_items(item_class) lines = [] + renderer = renderer() for item in items: - lines += renderer(item).to_rst() + renderer.item = item + lines += renderer.to_rst() return lines diff --git a/refactordoc/sections/item_list.py b/refactordoc/sections/item_list.py index b7c294a..96a28a5 100644 --- a/refactordoc/sections/item_list.py +++ b/refactordoc/sections/item_list.py @@ -12,7 +12,7 @@ from refactordoc.renderers import ListItem -def item_list(doc, header, renderer=None, item_class=DefinitionItem): +def item_list(doc, header, renderer=ListItem, item_class=DefinitionItem): """ Refactor the section to sphinx friendly item list. Arguments @@ -30,10 +30,10 @@ def item_list(doc, header, renderer=None, item_class=DefinitionItem): The item parser class to use. Default is :class:`~.DefinitionItem`. """ - items = doc.extract_items(item_class=item_class) + items = doc.extract_items(item_class) lines = [':{0}:'.format(header.lower())] prefix = None if len(items) == 1 else '-' - renderer = ListItem if renderer is None else renderer + renderer = renderer() for item in items: renderer.item = item lines += add_indent(renderer.to_rst(prefix)) diff --git a/refactordoc/sections/notes.py b/refactordoc/sections/notes.py index 4989986..222c942 100644 --- a/refactordoc/sections/notes.py +++ b/refactordoc/sections/notes.py @@ -9,7 +9,7 @@ from refactordoc.util import add_indent -def notes_paragraph(doc, header): +def notes_paragraph(doc, header, renderer=None, item_class=None): """Refactor the note section to use the rst ``.. note`` directive. The section is expected to be given as a paragraph. diff --git a/refactordoc/sections/rubric.py b/refactordoc/sections/rubric.py index 7547741..1e41603 100644 --- a/refactordoc/sections/rubric.py +++ b/refactordoc/sections/rubric.py @@ -9,7 +9,7 @@ from refactordoc.util import fix_backspace, EMPTY_LINE -def rubric(doc, header): +def rubric(doc, header, renderer=None, item_class=None): """ Refactor a header section using the rubric directive. The method supports refactoring of single word headers, two word headers From b5cb8ae20a773f5812dec01923a71e122553dadf Mon Sep 17 00:00:00 2001 From: itziakos Date: Tue, 21 Oct 2014 02:51:07 +0100 Subject: [PATCH 21/63] fix tests --- refactordoc/base_doc.py | 7 +- refactordoc/renderers/__init__.py | 16 +++ refactordoc/renderers/argument.py | 6 +- refactordoc/renderers/attribute.py | 4 +- refactordoc/renderers/list_item.py | 2 +- refactordoc/renderers/method.py | 2 +- refactordoc/renderers/renderer.py | 2 +- refactordoc/renderers/table_row.py | 2 +- refactordoc/sections/attributes.py | 2 +- refactordoc/sections/methods.py | 7 +- refactordoc/styles/old_style.py | 24 ++-- refactordoc/tests/test_definition_items.py | 106 +++++++++--------- ...t_old_style_class.py => test_old_style.py} | 0 13 files changed, 101 insertions(+), 79 deletions(-) rename refactordoc/tests/{test_old_style_class.py => test_old_style.py} (100%) diff --git a/refactordoc/base_doc.py b/refactordoc/base_doc.py index 361b20e..53e837b 100644 --- a/refactordoc/base_doc.py +++ b/refactordoc/base_doc.py @@ -98,8 +98,9 @@ def _refactor(self, section): """ self.remove_lines(self.index, 2) # Remove header self.remove_if_empty(self.index) # Remove space after header - method = self.sections.get(section, rubric) - lines = method(self, section) + method, renderer, item_class = self.sections.get( + section, (rubric, None, None)) + lines = method(self, section, renderer, item_class) self.insert_and_move(lines, self.index) def extract_items(self, item_class): @@ -155,7 +156,7 @@ def extract_items(self, item_class): """ item_type = DefinitionItem if (item_class is None) else item_class - is_item = item_type.is_definition + is_item = item_type.is_item item_blocks = [] while (not self.eod) and \ (is_item(self.peek()) or is_item(self.peek(1))): diff --git a/refactordoc/renderers/__init__.py b/refactordoc/renderers/__init__.py index e69de29..3d542ba 100644 --- a/refactordoc/renderers/__init__.py +++ b/refactordoc/renderers/__init__.py @@ -0,0 +1,16 @@ +__all__ = [ + 'Method', + 'Argument', + 'Renderer', + 'Attribute', + 'ListItem', + 'TableRow', + 'Definition'] + +from refactordoc.renderers.method import Method +from refactordoc.renderers.argument import Argument +from refactordoc.renderers.renderer import Renderer +from refactordoc.renderers.attribute import Attribute +from refactordoc.renderers.list_item import ListItem +from refactordoc.renderers.table_row import TableRow +from refactordoc.renderers.definition import Definition diff --git a/refactordoc/renderers/argument.py b/refactordoc/renderers/argument.py index e0409bf..6cdea1a 100644 --- a/refactordoc/renderers/argument.py +++ b/refactordoc/renderers/argument.py @@ -1,4 +1,4 @@ -from refactordoc.renderer.renderer import Renderer +from refactordoc.renderers.renderer import Renderer from refactordoc.util import add_indent, fix_star, fix_trailing_underscore @@ -7,12 +7,12 @@ class Argument(Renderer): """ templates = { - "normal": ":param {0}:\n{2}\n:type {0}: {1}", + "full": ":param {0}:\n{2}\n:type {0}: {1}", "no_definition": ":param {0}:\n:type {0}: {1}", "no_classifiers": ":param {0}:\n{2}", "only_term": ":param {0}:"} - def to_rst(self, item): + def to_rst(self): """ Render an item as an argument using the ``:param:`` role. diff --git a/refactordoc/renderers/attribute.py b/refactordoc/renderers/attribute.py index 5fca30e..bebda4f 100644 --- a/refactordoc/renderers/attribute.py +++ b/refactordoc/renderers/attribute.py @@ -8,9 +8,9 @@ class Attribute(Renderer): """ templates = { - "normal": ".. attribute:: {0}\n :annotation: = {1}\n\n{2}\n\n", + "full": ".. attribute:: {0}\n :annotation: = {1}\n\n{2}\n\n", "no_definition": ".. attribute:: {0}\n :annotation: = {1}\n\n", - "no_classifier": ".. attribute:: {0}\n\n{2}\n\n", + "no_classifiers": ".. attribute:: {0}\n\n{2}\n\n", "only_term": ".. attribute:: {0}\n\n"} def to_rst(self): diff --git a/refactordoc/renderers/list_item.py b/refactordoc/renderers/list_item.py index c2ede80..947fb71 100644 --- a/refactordoc/renderers/list_item.py +++ b/refactordoc/renderers/list_item.py @@ -11,7 +11,7 @@ class ListItem(Renderer): "full": "**{0}** (*{1}*) --\n{2}\n\n", "only_term": "**{0}**\n\n", "no_definition": "**{0}** (*{1}*)\n\n", - "no_classifier": "**{0}** --\n{2}\n\n"} + "no_classifiers": "**{0}** --\n{2}\n\n"} def to_rst(self, prefix=None): """ Renders an item as items in an rst list. diff --git a/refactordoc/renderers/method.py b/refactordoc/renderers/method.py index b470b8a..571bae7 100644 --- a/refactordoc/renderers/method.py +++ b/refactordoc/renderers/method.py @@ -31,7 +31,7 @@ def to_rst(self, columns=(0, 0)): item = self.item definition = ' '.join([line.strip() for line in item.definition]) method_role = ':meth:`{0}({1}) <{0}>`'.format( - self.term, ', '.join(item.classifiers)) + item.term, ', '.join(item.classifiers)) table_line = '{0:<{first}} {1:<{second}}' lines = [] lines += [table_line.format(method_role[:columns[0]], diff --git a/refactordoc/renderers/renderer.py b/refactordoc/renderers/renderer.py index 7066c1e..18855be 100644 --- a/refactordoc/renderers/renderer.py +++ b/refactordoc/renderers/renderer.py @@ -5,7 +5,7 @@ class Renderer(object): """ An item renderer. """ - def __init__(self, item): + def __init__(self, item=None): self.item = item @abc.abstractmethod diff --git a/refactordoc/renderers/table_row.py b/refactordoc/renderers/table_row.py index c555fda..ed95889 100644 --- a/refactordoc/renderers/table_row.py +++ b/refactordoc/renderers/table_row.py @@ -1,4 +1,4 @@ -from refactordoc.rendirexderers.renderer import Renderer +from refactordoc.renderers.renderer import Renderer class TableRow(Renderer): diff --git a/refactordoc/sections/attributes.py b/refactordoc/sections/attributes.py index 157ef2e..a5786e8 100644 --- a/refactordoc/sections/attributes.py +++ b/refactordoc/sections/attributes.py @@ -7,7 +7,7 @@ # All rights reserved. # ----------------------------------------------------------------------------- from refactordoc.items import DefinitionItem -from refctordoc.renderers import Attribute +from refactordoc.renderers import Attribute def attributes(doc, header, renderer=Attribute, item_class=DefinitionItem): diff --git a/refactordoc/sections/methods.py b/refactordoc/sections/methods.py index 3bc6ce1..4969ef6 100644 --- a/refactordoc/sections/methods.py +++ b/refactordoc/sections/methods.py @@ -11,11 +11,11 @@ from refactordoc.renderers import Method -def methods_table(doc, header): +def methods_table(doc, header, renderer=Method, item_class=MethodItem): """Refactor the methods section to sphinx friendly table format. """ - items = doc.extract_items(MethodItem) + items = doc.extract_items(item_class) lines = [] if len(items) > 0: columns = get_column_lengths(items) @@ -26,7 +26,8 @@ def methods_table(doc, header): lines += [heading] lines += [border] renderer = Method() - for items in items: + for item in items: + renderer.item = item lines += renderer.to_rst(columns) lines += [border] lines += [''] diff --git a/refactordoc/styles/old_style.py b/refactordoc/styles/old_style.py index f6be607..38bcec6 100644 --- a/refactordoc/styles/old_style.py +++ b/refactordoc/styles/old_style.py @@ -1,31 +1,29 @@ from refactordoc.base_doc import BaseDoc from refactordoc.sections import ( attributes, methods_table, notes_paragraph, item_list, arguments) - -# ----------------------------------------------------------------------------- -# Extension definition -# ----------------------------------------------------------------------------- +from refactordoc.renderers import Attribute, Method, Argument, ListItem +from refactordoc.items import DefinitionItem, MethodItem def refactor_class(lines): return BaseDoc( lines, sections={ - 'Attributes': attributes, - 'Methods': methods_table, - 'Notes': notes_paragraph}) + 'Attributes': (attributes, Attribute, DefinitionItem), + 'Methods': (methods_table, Method, MethodItem), + 'Notes': (notes_paragraph, None, None)}) def refactor_function(lines): return BaseDoc( lines, sections={ - 'Returns': item_list, - 'Arguments': arguments, - 'Parameters': arguments, - 'Raises': item_list, - 'Yields': item_list, - 'Notes': notes_paragraph}) + 'Returns': (item_list, ListItem, DefinitionItem), + 'Arguments': (arguments, Argument, DefinitionItem), + 'Parameters': (arguments, Argument, DefinitionItem), + 'Raises': (item_list, ListItem, DefinitionItem), + 'Yields': (item_list, ListItem, DefinitionItem), + 'Notes': (notes_paragraph, None, None)}) def refactor_docstring(app, what, name, obj, options, lines): diff --git a/refactordoc/tests/test_definition_items.py b/refactordoc/tests/test_definition_items.py index 780a652..f22f1f8 100644 --- a/refactordoc/tests/test_definition_items.py +++ b/refactordoc/tests/test_definition_items.py @@ -1,9 +1,6 @@ -from refactordoc.items.definition_item import DefinitionItem -from refactordoc.items.method_item import MethodItem -from refactordoc.items.argument_item import ArgumentItem -from refactordoc.items.attribute_item import AttributeItem -from refactordoc.items.list_item import ListItem -from refactordoc.items.table_row_item import TableRowItem +from refactordoc.items import DefinitionItem, MethodItem, Item +from refactordoc.renderers import ( + Argument, Attribute, Definition, ListItem, Method, TableRow) from refactordoc.tests._compat import unittest @@ -12,24 +9,24 @@ class TestDefinitionItem(unittest.TestCase): def setUp(self): self.maxDiff = None - def test_is_definition(self): - self.assertFalse(DefinitionItem.is_definition("term")) - self.assertFalse(DefinitionItem.is_definition("term ")) - self.assertTrue(DefinitionItem.is_definition("term :")) - self.assertTrue(DefinitionItem.is_definition("term : ")) - self.assertTrue(DefinitionItem.is_definition("term : classifier")) - self.assertFalse(DefinitionItem.is_definition(":term : classifier")) - self.assertFalse(DefinitionItem.is_definition("term : classifier:")) + def test_is_item(self): + self.assertFalse(DefinitionItem.is_item("term")) + self.assertFalse(DefinitionItem.is_item("term ")) + self.assertTrue(DefinitionItem.is_item("term :")) + self.assertTrue(DefinitionItem.is_item("term : ")) + self.assertTrue(DefinitionItem.is_item("term : classifier")) + self.assertFalse(DefinitionItem.is_item(":term : classifier")) + self.assertFalse(DefinitionItem.is_item("term : classifier:")) # special cases header_with_object = 'component : class.component.instance' - self.assertTrue(DefinitionItem.is_definition(header_with_object)) + self.assertTrue(DefinitionItem.is_item(header_with_object)) header_with_trait = 'properies : Dict(Str, Any)' - self.assertTrue(DefinitionItem.is_definition(header_with_trait)) + self.assertTrue(DefinitionItem.is_item(header_with_trait)) header_with_or = 'item : ModelIndex or None' - self.assertTrue(DefinitionItem.is_definition(header_with_or)) + self.assertTrue(DefinitionItem.is_item(header_with_or)) def test_parse(self): item = DefinitionItem.parse(['term', ' Definition.']) @@ -67,6 +64,9 @@ def test_parse(self): item, DefinitionItem( 'term', ['classifier'], ['Block.', ' Definition.'])) + +class TestDefintionRenderer(unittest.TestCase): + def test_to_rst(self): rst = """\ lines @@ -74,13 +74,13 @@ def test_to_rst(self): *(list)* -- A list of string lines rendered in rst. """ - item = DefinitionItem( + item = Item( 'lines', ['list'], ['A list of string lines rendered in rst.']) - rendered = '\n'.join(item.to_rst()) + rendered = '\n'.join(Definition(item).to_rst()) self.assertMultiLineEqual(rst, rendered) -class TestAttributeItem(unittest.TestCase): +class TestAttributeRenderer(unittest.TestCase): def setUp(self): self.maxDiff = None @@ -93,9 +93,11 @@ def test_to_rst(self): The indent to use for the description block. """ - item = AttributeItem('indent', ['int'], - ['The indent to use for the description block.']) - rendered = '\n'.join(item.to_rst()) + item = Item( + 'indent', + ['int'], + ['The indent to use for the description block.']) + rendered = '\n'.join(Attribute(item).to_rst()) self.assertMultiLineEqual(rst, rendered) # without annotation @@ -104,13 +106,13 @@ def test_to_rst(self): The indent to use for the description block. """ - item = AttributeItem('indent', [], - ['The indent to use for the description block.']) - rendered = '\n'.join(item.to_rst()) + item = Item( + 'indent', [], ['The indent to use for the description block.']) + rendered = '\n'.join(Attribute(item).to_rst()) self.assertMultiLineEqual(rst, rendered) -class TestArgumentItem(unittest.TestCase): +class TestArgumentRenderer(unittest.TestCase): def setUp(self): self.maxDiff = None @@ -122,11 +124,11 @@ def test_to_rst_with_one_classifier(self): This is the second paragraph of the argument definition. :type indent: int""" - item = ArgumentItem( + item = Item( 'indent', ['int'], [ 'The indent to use for the description block.', 'This is the second paragraph of the argument definition.']) - rendered = '\n'.join(item.to_rst()) + rendered = '\n'.join(Argument(item).to_rst()) self.assertMultiLineEqual(rst, rendered) def test_to_with_two_classifiers(self): @@ -136,15 +138,15 @@ def test_to_with_two_classifiers(self): This is the second paragraph of the argument definition. :type indent: int or float""" - item = ArgumentItem( + item = Item( 'indent', ['int', 'float'], [ 'The indent to use for the description block.', 'This is the second paragraph of the argument definition.']) - rendered = '\n'.join(item.to_rst()) + rendered = '\n'.join(Argument(item).to_rst()) self.assertMultiLineEqual(rst, rendered) -class TestListItem(unittest.TestCase): +class TestListItemRenderer(unittest.TestCase): def setUp(self): self.maxDiff = None @@ -156,11 +158,11 @@ def test_to_rst_normal(self): This is the second paragraph of the argument definition. """ - item = ListItem( + item = Item( 'indent', ['int'], [ 'The indent to use for the description block.', '', 'This is the second paragraph of the argument definition.']) - rendered = '\n'.join(item.to_rst(prefix='-')) + rendered = '\n'.join(ListItem(item).to_rst(prefix='-')) self.assertMultiLineEqual(rst, rendered) def test_to_rst_no_classifier(self): @@ -168,25 +170,25 @@ def test_to_rst_no_classifier(self): - **indent** -- The indent to use for the description block. """ - item = ListItem( + item = Item( 'indent', [], ['The indent to use for the description block.']) - rendered = '\n'.join(item.to_rst(prefix='-')) + rendered = '\n'.join(ListItem(item).to_rst(prefix='-')) self.assertMultiLineEqual(rst, rendered) def test_to_rst_only_term(self): rst = """\ - **indent** """ - item = ListItem('indent', [], ['']) - rendered = '\n'.join(item.to_rst(prefix='-')) + item = Item('indent', [], ['']) + rendered = '\n'.join(ListItem(item).to_rst(prefix='-')) self.assertMultiLineEqual(rst, rendered) def test_to_rst_no_defintition(self): rst = """\ - **indent** (*int*) """ - item = ListItem('indent', ['int'], ['']) - rendered = '\n'.join(item.to_rst(prefix='-')) + item = Item('indent', ['int'], ['']) + rendered = '\n'.join(ListItem(item).to_rst(prefix='-')) self.assertMultiLineEqual(rst, rendered) @@ -200,9 +202,9 @@ def test_to_rst(self): rst = """\ function(arg1, arg2) This is the best fun """ - item = TableRowItem( + item = Item( 'function(arg1, arg2)', 'and', ['This is the best function ever.']) - rendered = '\n'.join(item.to_rst(columns=(22, 0, 20))) + rendered = '\n'.join(TableRow(item).to_rst(columns=(22, 0, 20))) self.assertMultiLineEqual(rst, rendered) @@ -211,12 +213,12 @@ class TestMethodItem(unittest.TestCase): def setUp(self): self.maxDiff = None - def test_is_definition(self): - self.assertTrue(MethodItem.is_definition("term()")) + def test_is_item(self): + self.assertTrue(MethodItem.is_item("term()")) self.assertTrue( - MethodItem.is_definition("term(*args, my_keyword=None)")) - self.assertFalse(MethodItem.is_definition("term")) - self.assertFalse(MethodItem.is_definition("term : *args")) + MethodItem.is_item("term(*args, my_keyword=None)")) + self.assertFalse(MethodItem.is_item("term")) + self.assertFalse(MethodItem.is_item("term : *args")) def test_parse(self): item = MethodItem.parse( @@ -224,14 +226,18 @@ def test_parse(self): self.assertEqual(item, MethodItem( 'method', ['arguments'], ['Definition in a single line'])) + +class TestMethod(unittest.TestCase): + def test_to_rst(self): # with annotation rst = """\ :meth:`function(arg1, arg2) ` This is the best fun """ - item = MethodItem('function', ['arg1', 'arg2'], - ['This is the best function ever.']) - rendered = '\n'.join(item.to_rst(columns=(39, 20))) + '\n' + item = Item( + 'function', ['arg1', 'arg2'], + ['This is the best function ever.']) + rendered = '\n'.join(Method(item).to_rst(columns=(39, 20))) + '\n' self.assertMultiLineEqual(rst, rendered) diff --git a/refactordoc/tests/test_old_style_class.py b/refactordoc/tests/test_old_style.py similarity index 100% rename from refactordoc/tests/test_old_style_class.py rename to refactordoc/tests/test_old_style.py From 1ea891a94e51d132b64e0d63f1a3df61e21e024e Mon Sep 17 00:00:00 2001 From: Ioannis Tziakos Date: Tue, 21 Oct 2014 20:03:40 +0100 Subject: [PATCH 22/63] rework travis yml matrix to fix the failure to built in python 3 --- .travis.yml | 19 +++++++++++++++++-- python3_test_requirements.txt | 4 ++++ 2 files changed, 21 insertions(+), 2 deletions(-) create mode 100644 python3_test_requirements.txt diff --git a/.travis.yml b/.travis.yml index 7ea003b..4401034 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,14 +1,29 @@ language: python -python: +: - 2.6 - 2.7 - 3.2 - 3.3 - 3.4 +language: python +matrix: + include: + - python: "2.6" + env: REQUIREMENTS=test_requirements.txt + - python: "2.7" + env: REQUIREMENTS=test_requirements.txt + - python: "3.2" + env: REQUIREMENTS=python3_test_requirements.txt + - python: "3.3" + env: REQUIREMENTS=python3_test_requirements.txt + - python: "3.4" + env: REQUIREMENTS=python3_test_requirements.txt + before_install: - - pip install -r test_requirements.txt + - pip install -r $REQUIREMENTS + - pip python setup.py develop script: - coverage run -m haas -v - coverage report -m diff --git a/python3_test_requirements.txt b/python3_test_requirements.txt new file mode 100644 index 0000000..6d3c682 --- /dev/null +++ b/python3_test_requirements.txt @@ -0,0 +1,4 @@ +haas +unittest2py3k +coverage +coveralls From 05c8c760ade3868706484450bb4ecb8a3df3f44e Mon Sep 17 00:00:00 2001 From: Ioannis Tziakos Date: Tue, 21 Oct 2014 20:07:27 +0100 Subject: [PATCH 23/63] fix travis.yml --- .travis.yml | 9 --------- 1 file changed, 9 deletions(-) diff --git a/.travis.yml b/.travis.yml index 4401034..331dfe2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,13 +1,4 @@ language: python - -: - - 2.6 - - 2.7 - - 3.2 - - 3.3 - - 3.4 - -language: python matrix: include: - python: "2.6" From bbcc278ba0003e6909dd6f7ca4fc580cba731e19 Mon Sep 17 00:00:00 2001 From: Ioannis Tziakos Date: Tue, 21 Oct 2014 20:13:03 +0100 Subject: [PATCH 24/63] more typos --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 331dfe2..2534668 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,7 +14,7 @@ matrix: before_install: - pip install -r $REQUIREMENTS - - pip python setup.py develop + - python setup.py develop script: - coverage run -m haas -v - coverage report -m From 32261d900056ded92f07c3fe1b672a1d9ba0f3e6 Mon Sep 17 00:00:00 2001 From: Ioannis Tziakos Date: Tue, 21 Oct 2014 20:25:46 +0100 Subject: [PATCH 25/63] more cleanup --- .travis.yml | 6 +++--- test_requirements.txt => python2_test_requirements.txt | 0 2 files changed, 3 insertions(+), 3 deletions(-) rename test_requirements.txt => python2_test_requirements.txt (100%) diff --git a/.travis.yml b/.travis.yml index 2534668..c3c5929 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,9 +2,9 @@ language: python matrix: include: - python: "2.6" - env: REQUIREMENTS=test_requirements.txt + env: REQUIREMENTS=python2_test_requirements.txt - python: "2.7" - env: REQUIREMENTS=test_requirements.txt + env: REQUIREMENTS=python2_test_requirements.txt - python: "3.2" env: REQUIREMENTS=python3_test_requirements.txt - python: "3.3" @@ -12,7 +12,7 @@ matrix: - python: "3.4" env: REQUIREMENTS=python3_test_requirements.txt -before_install: +install: - pip install -r $REQUIREMENTS - python setup.py develop script: diff --git a/test_requirements.txt b/python2_test_requirements.txt similarity index 100% rename from test_requirements.txt rename to python2_test_requirements.txt From e1fe36b70e1342c0debb838a4493d0161f210c89 Mon Sep 17 00:00:00 2001 From: Ioannis Tziakos Date: Tue, 21 Oct 2014 20:41:42 +0100 Subject: [PATCH 26/63] group tests for old_style in one file --- refactordoc/tests/test_old_style.py | 306 +++++++++++++++++- refactordoc/tests/test_old_style_function.py | 317 ------------------- 2 files changed, 305 insertions(+), 318 deletions(-) delete mode 100644 refactordoc/tests/test_old_style_function.py diff --git a/refactordoc/tests/test_old_style.py b/refactordoc/tests/test_old_style.py index 800a4ab..5e0e9ce 100644 --- a/refactordoc/tests/test_old_style.py +++ b/refactordoc/tests/test_old_style.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -from refactordoc.styles.old_style import refactor_class +from refactordoc.styles.old_style import refactor_class, refactor_function from refactordoc.tests._compat import unittest @@ -135,5 +135,309 @@ def test_refactor_notes(self): output = '\n'.join(docstring_lines) + '\n' self.assertMultiLineEqual(rst, output) + +class TestOldStyleFunction(unittest.TestCase): + + def setUp(self): + self.maxDiff = None + + def test_refactor_returns(self): + docstring = \ + """ This is a sample function docstring. + +Returns +------- +myvalue : list + A list of important values. + But we need to say more things about it. +""" + + rst = \ + """ This is a sample function docstring. + +:returns: + **myvalue** (*list*) -- + A list of important values. + But we need to say more things about it. +""" + + docstring_lines = docstring.splitlines() + function_doc = refactor_function(docstring_lines) + function_doc.parse() + output = '\n'.join(docstring_lines) + self.assertMultiLineEqual(rst, output) + + def test_refactor_raises(self): + docstring = \ + """ This is a sample function docstring. + +Raises +------ +TypeError : + This is the first paragraph of the description. + More description. + +ValueError : + Description of another case where errors are raised. +""" + + rst = \ + """ This is a sample function docstring. + +:raises: + - **TypeError** -- + This is the first paragraph of the description. + More description. + + - **ValueError** -- + Description of another case where errors are raised. +""" + + docstring_lines = docstring.splitlines() + function_doc = refactor_function(docstring_lines) + function_doc.parse() + output = '\n'.join(docstring_lines) + self.assertMultiLineEqual(rst, output) + + def test_refactor_arguments(self): + docstring =\ + """ This is a sample function docstring + +Arguments +--------- +inputa : str + The first argument holds the first input!. + + This is the second paragraph. + +inputb : float + The second argument is a float. + the default value is 0. + + .. note:: this is an optional value. +""" + + rst = \ + """ This is a sample function docstring + +:param inputa: + The first argument holds the first input!. + + This is the second paragraph. +:type inputa: str +:param inputb: + The second argument is a float. + the default value is 0. + + .. note:: this is an optional value. +:type inputb: float +""" + + docstring_lines = docstring.splitlines() + function_doc = refactor_function(docstring_lines) + function_doc.parse() + output = '\n'.join(docstring_lines) + '\n' + self.assertMultiLineEqual(rst, output) + + def test_refactor_strange_arguments(self): + docstring = \ + """ This is a sample function docstring + +Parameters +---------- +*args : + Positional arguments with which this constructor was called + from the enaml source code. + +**kwards : + Keyword arguments with which this constructor was called + from the enaml source code. + +from_ : + Arguments with trailing underscore. +""" + rst = \ + """ This is a sample function docstring + +:param \*args: + Positional arguments with which this constructor was called + from the enaml source code. +:param \*\*kwards: + Keyword arguments with which this constructor was called + from the enaml source code. +:param from\_: + Arguments with trailing underscore. +""" + + docstring_lines = docstring.splitlines() + function_doc = refactor_function(docstring_lines) + function_doc.parse() + output = '\n'.join(docstring_lines) + '\n' + self.assertMultiLineEqual(rst, output) + + def test_refactor_notes(self): + docstring = \ + """ This is a sample function docstring. + +Notes +----- +This is the test. +Wait we have not finished. + +This should not be included. +""" + + rst = \ + """ This is a sample function docstring. + +.. note:: + This is the test. + Wait we have not finished. + +This should not be included. +""" + + docstring_lines = docstring.splitlines() + function_doc = refactor_function(docstring_lines) + function_doc.parse() + output = '\n'.join(docstring_lines) + '\n' + self.assertMultiLineEqual(rst, output) + + def test_docstring_cases_1(self): + docstring1 = \ + """ Sets the selection to the bounds of start and end. + +If the indices are invalid, no selection will be made, +and any current selection will be cleared. + +Arguments +--------- +start : Int + The start selection index, zero based. + +end : Int + The end selection index, zero based. + +Returns +------- +result : None +""" + + docstring2 = \ + """ Sets the selection to the bounds of start and end. + +If the indices are invalid, no selection will be made, +and any current selection will be cleared. + +Arguments +--------- +start : Int + The start selection index, zero based. +end : Int + The end selection index, zero based. + +Returns +------- +result : None +""" + + rst = \ + """ Sets the selection to the bounds of start and end. + +If the indices are invalid, no selection will be made, +and any current selection will be cleared. + +:param start: + The start selection index, zero based. +:type start: Int +:param end: + The end selection index, zero based. +:type end: Int + +:returns: + **result** (*None*) +""" + + docstring_lines = docstring1.splitlines() + function_doc = refactor_function(docstring_lines) + function_doc.parse() + output = '\n'.join(docstring_lines) + self.assertMultiLineEqual(rst, output) + + docstring_lines = docstring2.splitlines() + function_doc = refactor_function(docstring_lines) + function_doc.parse() + output = '\n'.join(docstring_lines) + self.assertMultiLineEqual(rst, output) + + def test_docstring_cases_2(self): + + docstring = \ + """ Verify that the requested attribute is properly set + +The method compares the attribute value in the Enaml object and +check if it is synchronized with the toolkit widget. The component +attribute is retrieved directly while the widget value is retrieved +through a call to a method function in the test case. + +Arguments +--------- +component : enaml.widgets.component.Component + The Enaml component to check. + +attribute_name : str + The string name of the Enaml attribute to check. + +value : + The expected value. + +.. note:: It is expected that the user has defined an appropriate + method get_(widget) or the extentded version + get_(component, widget) in the current test + case. The extended signature is commonly used because additional + information on the component's attributes is required to return + a sensible result (e.g. the component uses Converters to set + and retrieve the value of the attribute). The assert method + The get methods can raise assertion errors when it is not + possible to retrieve a sensible value for the attribute. + +""" + + rst = \ + """ Verify that the requested attribute is properly set + +The method compares the attribute value in the Enaml object and +check if it is synchronized with the toolkit widget. The component +attribute is retrieved directly while the widget value is retrieved +through a call to a method function in the test case. + +:param component: + The Enaml component to check. +:type component: enaml.widgets.component.Component +:param attribute_name: + The string name of the Enaml attribute to check. +:type attribute_name: str +:param value: + The expected value. + +.. note:: It is expected that the user has defined an appropriate + method get_(widget) or the extentded version + get_(component, widget) in the current test + case. The extended signature is commonly used because additional + information on the component's attributes is required to return + a sensible result (e.g. the component uses Converters to set + and retrieve the value of the attribute). The assert method + The get methods can raise assertion errors when it is not + possible to retrieve a sensible value for the attribute. + +""" + + docstring_lines = docstring.splitlines() + function_doc = refactor_function(docstring_lines) + function_doc.parse() + output = '\n'.join(docstring_lines) + '\n' + self.assertMultiLineEqual(rst, output) + + if __name__ == '__main__': unittest.main() diff --git a/refactordoc/tests/test_old_style_function.py b/refactordoc/tests/test_old_style_function.py deleted file mode 100644 index 00ca3cd..0000000 --- a/refactordoc/tests/test_old_style_function.py +++ /dev/null @@ -1,317 +0,0 @@ -# -*- coding: utf-8 -*- -# ----------------------------------------------------------------------------- -# file: test_function_doc.py -# License: LICENSE.TXT -# -# Copyright (c) 2011, Enthought, Inc. -# All rights reserved. -# ----------------------------------------------------------------------------- -from refactordoc.styles.old_style import refactor_function -from refactordoc.tests._compat import unittest - - -class TestOldStyleFunction(unittest.TestCase): - - def setUp(self): - self.maxDiff = None - - def test_refactor_returns(self): - docstring = \ - """ This is a sample function docstring. - -Returns -------- -myvalue : list - A list of important values. - But we need to say more things about it. -""" - - rst = \ - """ This is a sample function docstring. - -:returns: - **myvalue** (*list*) -- - A list of important values. - But we need to say more things about it. -""" - - docstring_lines = docstring.splitlines() - function_doc = refactor_function(docstring_lines) - function_doc.parse() - output = '\n'.join(docstring_lines) - self.assertMultiLineEqual(rst, output) - - def test_refactor_raises(self): - docstring = \ - """ This is a sample function docstring. - -Raises ------- -TypeError : - This is the first paragraph of the description. - More description. - -ValueError : - Description of another case where errors are raised. -""" - - rst = \ - """ This is a sample function docstring. - -:raises: - - **TypeError** -- - This is the first paragraph of the description. - More description. - - - **ValueError** -- - Description of another case where errors are raised. -""" - - docstring_lines = docstring.splitlines() - function_doc = refactor_function(docstring_lines) - function_doc.parse() - output = '\n'.join(docstring_lines) - self.assertMultiLineEqual(rst, output) - - def test_refactor_arguments(self): - docstring =\ - """ This is a sample function docstring - -Arguments ---------- -inputa : str - The first argument holds the first input!. - - This is the second paragraph. - -inputb : float - The second argument is a float. - the default value is 0. - - .. note:: this is an optional value. -""" - - rst = \ - """ This is a sample function docstring - -:param inputa: - The first argument holds the first input!. - - This is the second paragraph. -:type inputa: str -:param inputb: - The second argument is a float. - the default value is 0. - - .. note:: this is an optional value. -:type inputb: float -""" - - docstring_lines = docstring.splitlines() - function_doc = refactor_function(docstring_lines) - function_doc.parse() - output = '\n'.join(docstring_lines) + '\n' - self.assertMultiLineEqual(rst, output) - - def test_refactor_strange_arguments(self): - docstring = \ - """ This is a sample function docstring - -Parameters ----------- -*args : - Positional arguments with which this constructor was called - from the enaml source code. - -**kwards : - Keyword arguments with which this constructor was called - from the enaml source code. - -from_ : - Arguments with trailing underscore. -""" - rst = \ - """ This is a sample function docstring - -:param \*args: - Positional arguments with which this constructor was called - from the enaml source code. -:param \*\*kwards: - Keyword arguments with which this constructor was called - from the enaml source code. -:param from\_: - Arguments with trailing underscore. -""" - - docstring_lines = docstring.splitlines() - function_doc = refactor_function(docstring_lines) - function_doc.parse() - output = '\n'.join(docstring_lines) + '\n' - self.assertMultiLineEqual(rst, output) - - def test_refactor_notes(self): - docstring = \ - """ This is a sample function docstring. - -Notes ------ -This is the test. -Wait we have not finished. - -This should not be included. -""" - - rst = \ - """ This is a sample function docstring. - -.. note:: - This is the test. - Wait we have not finished. - -This should not be included. -""" - - docstring_lines = docstring.splitlines() - function_doc = refactor_function(docstring_lines) - function_doc.parse() - output = '\n'.join(docstring_lines) + '\n' - self.assertMultiLineEqual(rst, output) - - def test_docstring_cases_1(self): - docstring1 = \ - """ Sets the selection to the bounds of start and end. - -If the indices are invalid, no selection will be made, -and any current selection will be cleared. - -Arguments ---------- -start : Int - The start selection index, zero based. - -end : Int - The end selection index, zero based. - -Returns -------- -result : None -""" - - docstring2 = \ - """ Sets the selection to the bounds of start and end. - -If the indices are invalid, no selection will be made, -and any current selection will be cleared. - -Arguments ---------- -start : Int - The start selection index, zero based. -end : Int - The end selection index, zero based. - -Returns -------- -result : None -""" - - rst = \ - """ Sets the selection to the bounds of start and end. - -If the indices are invalid, no selection will be made, -and any current selection will be cleared. - -:param start: - The start selection index, zero based. -:type start: Int -:param end: - The end selection index, zero based. -:type end: Int - -:returns: - **result** (*None*) -""" - - docstring_lines = docstring1.splitlines() - function_doc = refactor_function(docstring_lines) - function_doc.parse() - output = '\n'.join(docstring_lines) - self.assertMultiLineEqual(rst, output) - - docstring_lines = docstring2.splitlines() - function_doc = refactor_function(docstring_lines) - function_doc.parse() - output = '\n'.join(docstring_lines) - self.assertMultiLineEqual(rst, output) - - def test_docstring_cases_2(self): - - docstring = \ - """ Verify that the requested attribute is properly set - -The method compares the attribute value in the Enaml object and -check if it is synchronized with the toolkit widget. The component -attribute is retrieved directly while the widget value is retrieved -through a call to a method function in the test case. - -Arguments ---------- -component : enaml.widgets.component.Component - The Enaml component to check. - -attribute_name : str - The string name of the Enaml attribute to check. - -value : - The expected value. - -.. note:: It is expected that the user has defined an appropriate - method get_(widget) or the extentded version - get_(component, widget) in the current test - case. The extended signature is commonly used because additional - information on the component's attributes is required to return - a sensible result (e.g. the component uses Converters to set - and retrieve the value of the attribute). The assert method - The get methods can raise assertion errors when it is not - possible to retrieve a sensible value for the attribute. - -""" - - rst = \ - """ Verify that the requested attribute is properly set - -The method compares the attribute value in the Enaml object and -check if it is synchronized with the toolkit widget. The component -attribute is retrieved directly while the widget value is retrieved -through a call to a method function in the test case. - -:param component: - The Enaml component to check. -:type component: enaml.widgets.component.Component -:param attribute_name: - The string name of the Enaml attribute to check. -:type attribute_name: str -:param value: - The expected value. - -.. note:: It is expected that the user has defined an appropriate - method get_(widget) or the extentded version - get_(component, widget) in the current test - case. The extended signature is commonly used because additional - information on the component's attributes is required to return - a sensible result (e.g. the component uses Converters to set - and retrieve the value of the attribute). The assert method - The get methods can raise assertion errors when it is not - possible to retrieve a sensible value for the attribute. - -""" - - docstring_lines = docstring.splitlines() - function_doc = refactor_function(docstring_lines) - function_doc.parse() - output = '\n'.join(docstring_lines) + '\n' - self.assertMultiLineEqual(rst, output) - - -if __name__ == '__main__': - unittest.main() From 30e8f6fe556f553d1e428674f495254a54d15102 Mon Sep 17 00:00:00 2001 From: Ioannis Tziakos Date: Tue, 21 Oct 2014 21:58:34 +0100 Subject: [PATCH 27/63] factor out a Style class --- refactordoc/styles/old_style.py | 17 +++-------------- refactordoc/styles/style.py | 10 ++++++++++ 2 files changed, 13 insertions(+), 14 deletions(-) create mode 100644 refactordoc/styles/style.py diff --git a/refactordoc/styles/old_style.py b/refactordoc/styles/old_style.py index 38bcec6..4b5d7d3 100644 --- a/refactordoc/styles/old_style.py +++ b/refactordoc/styles/old_style.py @@ -3,6 +3,7 @@ attributes, methods_table, notes_paragraph, item_list, arguments) from refactordoc.renderers import Attribute, Method, Argument, ListItem from refactordoc.items import DefinitionItem, MethodItem +from refactordoc.styles.style import Style def refactor_class(lines): @@ -26,19 +27,7 @@ def refactor_function(lines): 'Notes': (notes_paragraph, None, None)}) -def refactor_docstring(app, what, name, obj, options, lines): - - if 'class' in what: - refactor = refactor_class(lines) - elif 'function' in what or 'method' in what: - refactor = refactor_function(lines) - else: - refactor = None - - if refactor is not None: - refactor.parse() - - def setup(app): + style = Style({'class': refactor_class, 'function': refactor_function}) app.setup_extension('sphinx.ext.autodoc') - app.connect('autodoc-process-docstring', refactor_docstring) + app.connect('autodoc-process-docstring', style.refactor_docstring) diff --git a/refactordoc/styles/style.py b/refactordoc/styles/style.py new file mode 100644 index 0000000..7331c58 --- /dev/null +++ b/refactordoc/styles/style.py @@ -0,0 +1,10 @@ +class Style(object): + + def __init__(self, refactoring_map): + self.refactoring_map = refactoring_map + + def refactor_docstring(self, app, what, name, obj, options, lines): + docstring_renderer = self.refactoring_map.get(what, None) + if docstring_renderer is not None: + docstring_renderer(lines) + docstring_renderer.parse() From 85a93017d73f916b359ec0168581ee292d030463 Mon Sep 17 00:00:00 2001 From: Ioannis Tziakos Date: Wed, 22 Oct 2014 00:31:51 +0100 Subject: [PATCH 28/63] fix code so that the documentation compiles properly --- refactordoc/__init__.py | 10 +++++++++- refactordoc/styles/old_style.py | 5 ++++- refactordoc/styles/style.py | 6 +++--- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/refactordoc/__init__.py b/refactordoc/__init__.py index 7c5232c..2c34291 100644 --- a/refactordoc/__init__.py +++ b/refactordoc/__init__.py @@ -12,4 +12,12 @@ except ImportError: # pragma: no cover __version__ = "not-built" -from refactordoc.styles.old_style import setup + +def setup(app): + import warnings + from refactordoc.styles.old_style import setup + warnings.warn( + "This entry-point will be removed in the next release" + "Please use 'reafactordoc.styles.old_style' in conf.py", + DeprecationWarning) + setup(app) diff --git a/refactordoc/styles/old_style.py b/refactordoc/styles/old_style.py index 4b5d7d3..df19fac 100644 --- a/refactordoc/styles/old_style.py +++ b/refactordoc/styles/old_style.py @@ -28,6 +28,9 @@ def refactor_function(lines): def setup(app): - style = Style({'class': refactor_class, 'function': refactor_function}) + style = Style({ + 'class': refactor_class, + 'function': refactor_function, + 'method': refactor_function}) app.setup_extension('sphinx.ext.autodoc') app.connect('autodoc-process-docstring', style.refactor_docstring) diff --git a/refactordoc/styles/style.py b/refactordoc/styles/style.py index 7331c58..a28f433 100644 --- a/refactordoc/styles/style.py +++ b/refactordoc/styles/style.py @@ -4,7 +4,7 @@ def __init__(self, refactoring_map): self.refactoring_map = refactoring_map def refactor_docstring(self, app, what, name, obj, options, lines): - docstring_renderer = self.refactoring_map.get(what, None) - if docstring_renderer is not None: - docstring_renderer(lines) + renderer_factory = self.refactoring_map.get(what, None) + if renderer_factory is not None: + docstring_renderer = renderer_factory(lines) docstring_renderer.parse() From db6c8e1bbf7944c5f0dce63e572e2e60fb9d49de Mon Sep 17 00:00:00 2001 From: Ioannis Tziakos Date: Wed, 22 Oct 2014 00:32:23 +0100 Subject: [PATCH 29/63] some cleanup on the docstrings --- refactordoc/base_doc.py | 6 +++--- refactordoc/items/item.py | 10 +++++++--- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/refactordoc/base_doc.py b/refactordoc/base_doc.py index 53e837b..ebf75c0 100644 --- a/refactordoc/base_doc.py +++ b/refactordoc/base_doc.py @@ -222,15 +222,16 @@ def is_section(self): return '' def insert_lines(self, lines, index): - """ Insert refactored lines + """ Insert refactored lines. Arguments --------- - new_lines : list + lines : list The list of lines to insert index : int Index to start the insertion + """ docstring = self.docstring for line in reversed(lines): @@ -319,7 +320,6 @@ def peek(self, ahead=0): ahead : int The number of lines to look ahead. - """ position = self.index + ahead try: diff --git a/refactordoc/items/item.py b/refactordoc/items/item.py index 0dfe49e..dfdff51 100644 --- a/refactordoc/items/item.py +++ b/refactordoc/items/item.py @@ -8,7 +8,7 @@ class Item(namedtuple('Item', ['term', 'classifiers', 'definition'])): The Item class is responsible to check, parse and refactor a docstring item into sphinx friendly rst. - Syntax diagram: + Format diagram:: +-------------------------------------------------+ | header | @@ -26,7 +26,7 @@ class Item(namedtuple('Item', ['term', 'classifiers', 'definition'])): term : str The term usually reflects the name of a parameter or an attribute. - classifiers: list + classifiers : list The classifier(s) of the term. Commonly used to reflect the type of an argument or the signature of a function. @@ -37,7 +37,11 @@ class Item(namedtuple('Item', ['term', 'classifiers', 'definition'])): @property def mode(self): - """ The operational mode of the item based on the available info. + """ Property (`string`), the operational mode of the item based on the + available info. Possible values are ``{'only_term', 'no_classifiers', + 'no_definition', 'full'}``. + + """ if self.classifiers == [] and self.definition == ['']: mode = 'only_term' From 77590b0b9d4d07a6e3efd1a4f57761211063ada5 Mon Sep 17 00:00:00 2001 From: Ioannis Tziakos Date: Wed, 22 Oct 2014 00:32:54 +0100 Subject: [PATCH 30/63] some cleanup on the rst code --- docs/source/components.rst | 3 +-- docs/source/conf.py | 6 ++++-- docs/source/reference.rst | 41 ++++++++++++++------------------------ docs/source/usage.rst | 35 ++++---------------------------- 4 files changed, 24 insertions(+), 61 deletions(-) diff --git a/docs/source/components.rst b/docs/source/components.rst index 57b91ab..7ba23f4 100644 --- a/docs/source/components.rst +++ b/docs/source/components.rst @@ -27,8 +27,7 @@ parsed. Definition list ^^^^^^^^^^^^^^^ - Two of the most common formats are described -bellow: +Two of the most common formats are described bellow: The *standard definition item* format is based on the item of a variation of the definition list item as it defined in `restructured text diff --git a/docs/source/conf.py b/docs/source/conf.py index d9a02cd..192857a 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -28,11 +28,12 @@ extensions = ['refactordoc', 'sphinx.ext.intersphinx', 'sphinx.ext.todo', - 'sphinx.ext.viewcode' + 'sphinx.ext.viewcode', + 'sphinx.ext.autosummary', ] # Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] +templates_path = [] # The suffix of source filenames. source_suffix = '.rst' @@ -90,6 +91,7 @@ # A list of ignored prefixes for module index sorting. #modindex_common_prefix = [] +autodoc_member_order = 'groupwise' # -- Options for HTML output --------------------------------------------------- diff --git a/docs/source/reference.rst b/docs/source/reference.rst index c1aeb05..f433c5d 100644 --- a/docs/source/reference.rst +++ b/docs/source/reference.rst @@ -1,40 +1,29 @@ Library Reference ================= -The extension is separated into three main parts. +The extension is separated into four main parts. -Sphinx extension ----------------- -.. automodule:: refactordoc - :members: +.. default-role:: autolink +.. currentmodule:: refactordoc -Refactor classes ----------------- -.. automodule:: refactordoc.base_doc - :members: +Sections +-------- -.. automodule:: refactordoc.function_doc - :members: - :private-members: +.. automodule:: refactordoc.sections + :members: -.. automodule:: refactordoc.class_doc - :members: - :private-members: -Definition items ----------------- +Items +----- -.. automodule:: refactordoc.definition_items - :members: - - -Line functions --------------- - -.. automodule:: refactordoc.line_functions - :members: +.. automodule:: refactordoc.items + :members: +Renderers +--------- +.. automodule:: refactordoc.renderers + :members: diff --git a/docs/source/usage.rst b/docs/source/usage.rst index 55e1b01..bcd2f33 100644 --- a/docs/source/usage.rst +++ b/docs/source/usage.rst @@ -6,8 +6,7 @@ function doc-strings. A number of known (i.e. predefined) sections are processed by the ClassDoc and FunctionDoc classes and all unknown sections are re-factored using the ``.. rubric::`` directive by default. -For class objects the :class:`~refactordoc.class_doc.ClassDoc` includes code to -re-factor three types of sections. +For class objects the **default style** re-factors three types of sections: ========== ================================ ========== === ==================== Heading Description Item Max Rendered as @@ -18,8 +17,7 @@ Attributes Class attributes and their usage Attribute -- Sphinx attributes Notes Useful notes paragraph 1 Note admonition ========== ================================ ========== === ==================== -For function objects the :class:`~refactordoc.function_doc.FunctionDoc` includes -code to re-factor three types of sections. +For functions the **default style** re-factors four types of sections: ========= =========================== ============ === ===================== Heading Description Item Max Rendered as @@ -72,30 +70,6 @@ Argument sections :noindex: -Method sections -^^^^^^^^^^^^^^^ -:: - - Methods - ------- - _refactor_attributes(self, header): - Re-factor the attributes section to sphinx friendly format. - - _refactor_methods(self, header): - Re-factor the methods section to sphinx friendly format. - - _refactor_notes(self, header): - Re-factor the note section to use the rst ``.. note`` directive. - - -.. note:: The table that is created in this example does not have the links - enabled because the methods are not rendered by autodoc (the - ``:no-members`` option is set). - -.. autoclass:: refactordoc.class_doc.ClassDoc - :noindex: - :no-members: - Attribute sections ------------------ :: @@ -129,7 +103,7 @@ Returns sections result : list A new list of left striped strings. -.. autofunction:: refactordoc.line_functions.remove_indent +.. autofunction:: refactordoc.util.remove_indent :noindex: Raises section @@ -146,6 +120,5 @@ Notes ----- Empty strings are not changed. -.. autofunction:: refactordoc.line_functions.add_indent +.. autofunction:: refactordoc.util.add_indent :noindex: - From dc02f15ff5dc4762684f702bffc323eedb51d5c9 Mon Sep 17 00:00:00 2001 From: Ioannis Tziakos Date: Wed, 22 Oct 2014 02:26:55 +0100 Subject: [PATCH 31/63] fix Attribue docstring --- refactordoc/renderers/attribute.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/refactordoc/renderers/attribute.py b/refactordoc/renderers/attribute.py index bebda4f..137da4a 100644 --- a/refactordoc/renderers/attribute.py +++ b/refactordoc/renderers/attribute.py @@ -25,7 +25,7 @@ def to_rst(self): ... ['The indent to use for the description block.']) >>> Attribute(item).to_rst() .. attribute:: indent - :annotation: = int + :annotation: = `int` The indent to use for the description block >>> From f7e9b05eef263a72c3dc333dba63cecd2db64f00 Mon Sep 17 00:00:00 2001 From: Ioannis Tziakos Date: Wed, 22 Oct 2014 02:27:32 +0100 Subject: [PATCH 32/63] use the default role for the classifiers --- refactordoc/items/definition_item.py | 2 +- refactordoc/renderers/list_item.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/refactordoc/items/definition_item.py b/refactordoc/items/definition_item.py index 0fbca86..882a627 100644 --- a/refactordoc/items/definition_item.py +++ b/refactordoc/items/definition_item.py @@ -24,7 +24,7 @@ class DefinitionItem(Item): term : str The term usually reflects the name of a parameter or an attribute. - classifiers: list + classifiers : list The classifiers of the definition. Commonly used to reflect the type of an argument or the signature of a function. diff --git a/refactordoc/renderers/list_item.py b/refactordoc/renderers/list_item.py index 947fb71..a59052b 100644 --- a/refactordoc/renderers/list_item.py +++ b/refactordoc/renderers/list_item.py @@ -8,9 +8,9 @@ class ListItem(Renderer): """ templates = { - "full": "**{0}** (*{1}*) --\n{2}\n\n", + "full": "**{0}** (`{1}`) --\n{2}\n\n", "only_term": "**{0}**\n\n", - "no_definition": "**{0}** (*{1}*)\n\n", + "no_definition": "**{0}** (`{1}`)\n\n", "no_classifiers": "**{0}** --\n{2}\n\n"} def to_rst(self, prefix=None): From 3588096a94968e8411ae5dc630971fd3e3fb6cc8 Mon Sep 17 00:00:00 2001 From: itziakos Date: Wed, 22 Oct 2014 02:52:46 +0100 Subject: [PATCH 33/63] Revert "use the default role for the classifiers" This reverts commit f7e9b05eef263a72c3dc333dba63cecd2db64f00. --- refactordoc/items/definition_item.py | 2 +- refactordoc/renderers/list_item.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/refactordoc/items/definition_item.py b/refactordoc/items/definition_item.py index 882a627..0fbca86 100644 --- a/refactordoc/items/definition_item.py +++ b/refactordoc/items/definition_item.py @@ -24,7 +24,7 @@ class DefinitionItem(Item): term : str The term usually reflects the name of a parameter or an attribute. - classifiers : list + classifiers: list The classifiers of the definition. Commonly used to reflect the type of an argument or the signature of a function. diff --git a/refactordoc/renderers/list_item.py b/refactordoc/renderers/list_item.py index a59052b..947fb71 100644 --- a/refactordoc/renderers/list_item.py +++ b/refactordoc/renderers/list_item.py @@ -8,9 +8,9 @@ class ListItem(Renderer): """ templates = { - "full": "**{0}** (`{1}`) --\n{2}\n\n", + "full": "**{0}** (*{1}*) --\n{2}\n\n", "only_term": "**{0}**\n\n", - "no_definition": "**{0}** (`{1}`)\n\n", + "no_definition": "**{0}** (*{1}*)\n\n", "no_classifiers": "**{0}** --\n{2}\n\n"} def to_rst(self, prefix=None): From 57d63b4627cc3e1062368e009729c254bdcfd295 Mon Sep 17 00:00:00 2001 From: itziakos Date: Thu, 13 Nov 2014 02:12:35 +0000 Subject: [PATCH 34/63] use sectiondoc and fix tests --- refactordoc/tests/test_base_doc.py | 56 --- refactordoc/tests/test_line_functions.py | 75 ---- refactordoc/tests/test_old_style.py | 443 ---------------------- sectiondoc/__init__.py | 4 +- sectiondoc/items/__init__.py | 6 +- sectiondoc/items/definition_item.py | 8 +- sectiondoc/items/method_item.py | 6 +- sectiondoc/renderers/__init__.py | 14 +- sectiondoc/renderers/argument.py | 4 +- sectiondoc/renderers/attribute.py | 4 +- sectiondoc/renderers/definition.py | 8 +- sectiondoc/renderers/list_item.py | 4 +- sectiondoc/renderers/method.py | 2 +- sectiondoc/renderers/table_row.py | 2 +- sectiondoc/sections/__init__.py | 12 +- sectiondoc/sections/arguments.py | 9 +- sectiondoc/sections/attributes.py | 15 +- sectiondoc/sections/item_list.py | 9 +- sectiondoc/sections/methods.py | 8 +- sectiondoc/sections/notes.py | 4 +- sectiondoc/sections/rubric.py | 5 +- sectiondoc/sections/util.py | 2 +- sectiondoc/styles/__init__.py | 6 + sectiondoc/styles/base_doc.py | 350 +++++++++++++++++ sectiondoc/styles/old_style.py | 22 +- sectiondoc/styles/style.py | 8 +- sectiondoc/tests/test_base_doc.py | 17 +- sectiondoc/tests/test_definition_items.py | 6 +- sectiondoc/tests/test_line_functions.py | 20 +- sectiondoc/tests/test_old_style.py | 43 +-- sectiondoc/util.py | 157 ++++++++ setup.py | 2 +- 32 files changed, 612 insertions(+), 719 deletions(-) delete mode 100644 refactordoc/tests/test_base_doc.py delete mode 100644 refactordoc/tests/test_line_functions.py delete mode 100644 refactordoc/tests/test_old_style.py create mode 100644 sectiondoc/styles/base_doc.py create mode 100644 sectiondoc/util.py diff --git a/refactordoc/tests/test_base_doc.py b/refactordoc/tests/test_base_doc.py deleted file mode 100644 index f97470e..0000000 --- a/refactordoc/tests/test_base_doc.py +++ /dev/null @@ -1,56 +0,0 @@ -from refactordoc.base_doc import BaseDoc -from refactordoc.tests._compat import unittest - - -class TestBaseDoc(unittest.TestCase): - - def setUp(self): - self.maxDiff = None - - def test_refactor_header(self): - docstring =\ - """ This is a sample docstring. - -My Header ---------- -This is just some sample text. -""" - - rst =\ - """ This is a sample docstring. - -.. rubric:: My Header - -This is just some sample text. -""" - docstring_lines = docstring.splitlines() - base_doc = BaseDoc(docstring_lines) - base_doc.parse() - output = '\n'.join(docstring_lines) + '\n' - self.assertMultiLineEqual(rst, output) - - def test_refactor_complex_header(self): - docstring =\ - """ This is a sample docstring. - -Input\\Output header -------------------- - -This is just some sample text. -""" - - rst =\ - """ This is a sample docstring. - -.. rubric:: Input\\\\Output header - -This is just some sample text. -""" - docstring_lines = docstring.splitlines() - base_doc = BaseDoc(docstring_lines) - base_doc.parse() - output = '\n'.join(docstring_lines) + '\n' - self.assertMultiLineEqual(rst, output) - -if __name__ == '__main__': - unittest.main() diff --git a/refactordoc/tests/test_line_functions.py b/refactordoc/tests/test_line_functions.py deleted file mode 100644 index d962cdd..0000000 --- a/refactordoc/tests/test_line_functions.py +++ /dev/null @@ -1,75 +0,0 @@ -# -*- coding: utf-8 -*- -from refactordoc.util import ( - add_indent, remove_indent, get_indent, fix_star, fix_backspace, is_empty, - replace_at) -from refactordoc.tests._compat import unittest - - -class TestLineFunctions(unittest.TestCase): - - def test_add_indent(self): - input = ["This is the first line", "", " This is the third line"] - expected = [ - " This is the first line", "", " This is the third line"] - output = add_indent(input, indent=3) - self.assertEqual(output, expected) - - expected = [ - "This is the first line", "", " This is the third line"] - output = add_indent(input, indent=0) - self.assertEqual(output, expected) - - expected = [ - " This is the first line", "", " This is the third line"] - output = add_indent(input) - self.assertEqual(output, expected) - - def test_remove_indent(self): - input = [ - " This is the first line", "", " This is the third line"] - expected = [ - "This is the first line", "", "This is the third line"] - output = remove_indent(input) - self.assertEqual(output, expected) - - def test_get_indent(self): - output = get_indent('') - self.assertEqual(output, '') - - output = get_indent(' _dgsdg 44') - self.assertEqual(output, ' ') - - def test_is_empty(self): - output = is_empty(' ') - self.assertTrue(output) - output = is_empty(' . ') - self.assertFalse(output) - - def test_fix_star(self): - output = fix_star('*arg') - self.assertEqual(r'\*arg', output) - output = fix_star('**sfg') - self.assertEqual(r'\*\*sfg', output) - - def test_fix_backspace(self): - output = fix_backspace('Input\Output header') - self.assertEqual(r'Input\\Output header', output) - - def test_replace_at(self): - input = ' This is where the new starts' - expected = ' This is w 3 the new starts' - output = replace_at(' 3', input, 10) - self.assertEqual(expected, output) - - input = ' This is where the new starts' - expected = ' This is where the new start ' - output = replace_at(' 3', input, 28) - self.assertEqual(expected, output) - - input = ' This is where the new starts' - expected = ' This is where the new starts' - output = replace_at(' 3', input, 30) - self.assertEqual(expected, output) - -if __name__ == '__main__': - unittest.main() diff --git a/refactordoc/tests/test_old_style.py b/refactordoc/tests/test_old_style.py deleted file mode 100644 index 5e0e9ce..0000000 --- a/refactordoc/tests/test_old_style.py +++ /dev/null @@ -1,443 +0,0 @@ -# -*- coding: utf-8 -*- -from refactordoc.styles.old_style import refactor_class, refactor_function -from refactordoc.tests._compat import unittest - - -class TestOldStyleClass(unittest.TestCase): - - def setUp(self): - self.maxDiff = None - - def test_refactor_attributes(self): - docstring =\ - """Base abstract docstring refactoring class. - -The class' main purpose is to parse the dosctring and find the -sections that need to be refactored. It also provides a number of -methods to help with the refactoring. Subclasses should provide -the methods responsible for refactoring the sections. - -Attributes ----------- -docstring : list - A list of strings (lines) that holds docstrings - -index : int - The current zero-based line number of the docstring that is - proccessed. -""" - - rst = \ - """Base abstract docstring refactoring class. - -The class' main purpose is to parse the dosctring and find the -sections that need to be refactored. It also provides a number of -methods to help with the refactoring. Subclasses should provide -the methods responsible for refactoring the sections. - -.. attribute:: docstring - :annotation: = list - - A list of strings (lines) that holds docstrings - -.. attribute:: index - :annotation: = int - - The current zero-based line number of the docstring that is - proccessed. -""" - - docstring_lines = docstring.splitlines() - class_doc = refactor_class(docstring_lines) - class_doc.parse() - output = '\n'.join(docstring_lines) - self.assertMultiLineEqual(rst, output) - - def test_refactor_methods(self): - docstring = \ - """ This is a sample class docstring - -Methods -------- -extract_fields(indent='', field_check=None) - Extract the fields from the docstring - -get_field() - Get the field description. - -get_next_paragraph() - Get the next paragraph designated by an empty line. - -""" - - rst = \ - """ This is a sample class docstring - -==================================================================== =================================================== -Method Description -==================================================================== =================================================== -:meth:`extract_fields(indent='', field_check=None) ` Extract the fields from the docstring -:meth:`get_field() ` Get the field description. -:meth:`get_next_paragraph() ` Get the next paragraph designated by an empty line. -==================================================================== =================================================== - -""" - - docstring_lines = docstring.splitlines() - class_doc = refactor_class(docstring_lines) - class_doc.parse() - output = '\n'.join(docstring_lines) - self.assertMultiLineEqual(rst, output) - - def test_refactor_notes(self): - docstring1 =\ - """ This is a sample class docstring - -Notes ------ -This is the test. -Wait we have not finished. - -This is not a note. -""" - - docstring2 =\ - """ This is a sample class docstring - -Notes ------ - -This is the test. -Wait we have not finished. - -This is not a note. -""" - - rst = \ - """ This is a sample class docstring - -.. note:: - This is the test. - Wait we have not finished. - -This is not a note. -""" - - docstring_lines = docstring1.splitlines() - class_doc = refactor_class(docstring_lines) - class_doc.parse() - output = '\n'.join(docstring_lines) + '\n' - self.assertMultiLineEqual(rst, output) - - docstring_lines = docstring2.splitlines() - class_doc = refactor_class(docstring_lines) - class_doc.parse() - output = '\n'.join(docstring_lines) + '\n' - self.assertMultiLineEqual(rst, output) - - -class TestOldStyleFunction(unittest.TestCase): - - def setUp(self): - self.maxDiff = None - - def test_refactor_returns(self): - docstring = \ - """ This is a sample function docstring. - -Returns -------- -myvalue : list - A list of important values. - But we need to say more things about it. -""" - - rst = \ - """ This is a sample function docstring. - -:returns: - **myvalue** (*list*) -- - A list of important values. - But we need to say more things about it. -""" - - docstring_lines = docstring.splitlines() - function_doc = refactor_function(docstring_lines) - function_doc.parse() - output = '\n'.join(docstring_lines) - self.assertMultiLineEqual(rst, output) - - def test_refactor_raises(self): - docstring = \ - """ This is a sample function docstring. - -Raises ------- -TypeError : - This is the first paragraph of the description. - More description. - -ValueError : - Description of another case where errors are raised. -""" - - rst = \ - """ This is a sample function docstring. - -:raises: - - **TypeError** -- - This is the first paragraph of the description. - More description. - - - **ValueError** -- - Description of another case where errors are raised. -""" - - docstring_lines = docstring.splitlines() - function_doc = refactor_function(docstring_lines) - function_doc.parse() - output = '\n'.join(docstring_lines) - self.assertMultiLineEqual(rst, output) - - def test_refactor_arguments(self): - docstring =\ - """ This is a sample function docstring - -Arguments ---------- -inputa : str - The first argument holds the first input!. - - This is the second paragraph. - -inputb : float - The second argument is a float. - the default value is 0. - - .. note:: this is an optional value. -""" - - rst = \ - """ This is a sample function docstring - -:param inputa: - The first argument holds the first input!. - - This is the second paragraph. -:type inputa: str -:param inputb: - The second argument is a float. - the default value is 0. - - .. note:: this is an optional value. -:type inputb: float -""" - - docstring_lines = docstring.splitlines() - function_doc = refactor_function(docstring_lines) - function_doc.parse() - output = '\n'.join(docstring_lines) + '\n' - self.assertMultiLineEqual(rst, output) - - def test_refactor_strange_arguments(self): - docstring = \ - """ This is a sample function docstring - -Parameters ----------- -*args : - Positional arguments with which this constructor was called - from the enaml source code. - -**kwards : - Keyword arguments with which this constructor was called - from the enaml source code. - -from_ : - Arguments with trailing underscore. -""" - rst = \ - """ This is a sample function docstring - -:param \*args: - Positional arguments with which this constructor was called - from the enaml source code. -:param \*\*kwards: - Keyword arguments with which this constructor was called - from the enaml source code. -:param from\_: - Arguments with trailing underscore. -""" - - docstring_lines = docstring.splitlines() - function_doc = refactor_function(docstring_lines) - function_doc.parse() - output = '\n'.join(docstring_lines) + '\n' - self.assertMultiLineEqual(rst, output) - - def test_refactor_notes(self): - docstring = \ - """ This is a sample function docstring. - -Notes ------ -This is the test. -Wait we have not finished. - -This should not be included. -""" - - rst = \ - """ This is a sample function docstring. - -.. note:: - This is the test. - Wait we have not finished. - -This should not be included. -""" - - docstring_lines = docstring.splitlines() - function_doc = refactor_function(docstring_lines) - function_doc.parse() - output = '\n'.join(docstring_lines) + '\n' - self.assertMultiLineEqual(rst, output) - - def test_docstring_cases_1(self): - docstring1 = \ - """ Sets the selection to the bounds of start and end. - -If the indices are invalid, no selection will be made, -and any current selection will be cleared. - -Arguments ---------- -start : Int - The start selection index, zero based. - -end : Int - The end selection index, zero based. - -Returns -------- -result : None -""" - - docstring2 = \ - """ Sets the selection to the bounds of start and end. - -If the indices are invalid, no selection will be made, -and any current selection will be cleared. - -Arguments ---------- -start : Int - The start selection index, zero based. -end : Int - The end selection index, zero based. - -Returns -------- -result : None -""" - - rst = \ - """ Sets the selection to the bounds of start and end. - -If the indices are invalid, no selection will be made, -and any current selection will be cleared. - -:param start: - The start selection index, zero based. -:type start: Int -:param end: - The end selection index, zero based. -:type end: Int - -:returns: - **result** (*None*) -""" - - docstring_lines = docstring1.splitlines() - function_doc = refactor_function(docstring_lines) - function_doc.parse() - output = '\n'.join(docstring_lines) - self.assertMultiLineEqual(rst, output) - - docstring_lines = docstring2.splitlines() - function_doc = refactor_function(docstring_lines) - function_doc.parse() - output = '\n'.join(docstring_lines) - self.assertMultiLineEqual(rst, output) - - def test_docstring_cases_2(self): - - docstring = \ - """ Verify that the requested attribute is properly set - -The method compares the attribute value in the Enaml object and -check if it is synchronized with the toolkit widget. The component -attribute is retrieved directly while the widget value is retrieved -through a call to a method function in the test case. - -Arguments ---------- -component : enaml.widgets.component.Component - The Enaml component to check. - -attribute_name : str - The string name of the Enaml attribute to check. - -value : - The expected value. - -.. note:: It is expected that the user has defined an appropriate - method get_(widget) or the extentded version - get_(component, widget) in the current test - case. The extended signature is commonly used because additional - information on the component's attributes is required to return - a sensible result (e.g. the component uses Converters to set - and retrieve the value of the attribute). The assert method - The get methods can raise assertion errors when it is not - possible to retrieve a sensible value for the attribute. - -""" - - rst = \ - """ Verify that the requested attribute is properly set - -The method compares the attribute value in the Enaml object and -check if it is synchronized with the toolkit widget. The component -attribute is retrieved directly while the widget value is retrieved -through a call to a method function in the test case. - -:param component: - The Enaml component to check. -:type component: enaml.widgets.component.Component -:param attribute_name: - The string name of the Enaml attribute to check. -:type attribute_name: str -:param value: - The expected value. - -.. note:: It is expected that the user has defined an appropriate - method get_(widget) or the extentded version - get_(component, widget) in the current test - case. The extended signature is commonly used because additional - information on the component's attributes is required to return - a sensible result (e.g. the component uses Converters to set - and retrieve the value of the attribute). The assert method - The get methods can raise assertion errors when it is not - possible to retrieve a sensible value for the attribute. - -""" - - docstring_lines = docstring.splitlines() - function_doc = refactor_function(docstring_lines) - function_doc.parse() - output = '\n'.join(docstring_lines) + '\n' - self.assertMultiLineEqual(rst, output) - - -if __name__ == '__main__': - unittest.main() diff --git a/sectiondoc/__init__.py b/sectiondoc/__init__.py index 2c34291..804d947 100644 --- a/sectiondoc/__init__.py +++ b/sectiondoc/__init__.py @@ -8,14 +8,14 @@ __all__ = ['__version__', 'setup'] try: # pragma: no cover - from refactordoc._version import full_version as __version__ + from sectiondoc._version import full_version as __version__ except ImportError: # pragma: no cover __version__ = "not-built" def setup(app): import warnings - from refactordoc.styles.old_style import setup + from sectiondoc.styles.old_style import setup warnings.warn( "This entry-point will be removed in the next release" "Please use 'reafactordoc.styles.old_style' in conf.py", diff --git a/sectiondoc/items/__init__.py b/sectiondoc/items/__init__.py index 8bc2b54..de71f46 100644 --- a/sectiondoc/items/__init__.py +++ b/sectiondoc/items/__init__.py @@ -3,6 +3,6 @@ 'MethodItem', 'Item'] -from refactordoc.items.item import Item -from refactordoc.items.definition_item import DefinitionItem -from refactordoc.items.method_item import MethodItem +from sectiondoc.items.item import Item +from sectiondoc.items.definition_item import DefinitionItem +from sectiondoc.items.method_item import MethodItem diff --git a/sectiondoc/items/definition_item.py b/sectiondoc/items/definition_item.py index 0fbca86..01f8f64 100644 --- a/sectiondoc/items/definition_item.py +++ b/sectiondoc/items/definition_item.py @@ -1,6 +1,6 @@ -from refactordoc.items.regex import definition_regex, header_regex -from refactordoc.items.item import Item -from refactordoc.util import trim_indent +from sectiondoc.items.regex import definition_regex, header_regex +from sectiondoc.items.item import Item +from sectiondoc.util import trim_indent class DefinitionItem(Item): @@ -16,7 +16,7 @@ class DefinitionItem(Item): +--------------------------------------------------+ The Definition class is based on the nametuple class and is responsible - to check, parse and refactor a docstring definition item into sphinx + to check, parse a docstring definition item into sphinx friendly rst. Attributes diff --git a/sectiondoc/items/method_item.py b/sectiondoc/items/method_item.py index bfbc4e7..535fb97 100644 --- a/sectiondoc/items/method_item.py +++ b/sectiondoc/items/method_item.py @@ -1,6 +1,6 @@ -from refactordoc.items.item import Item -from refactordoc.items.regex import function_regex, signature_regex -from refactordoc.util import trim_indent +from sectiondoc.items.item import Item +from sectiondoc.items.regex import function_regex, signature_regex +from sectiondoc.util import trim_indent class MethodItem(Item): diff --git a/sectiondoc/renderers/__init__.py b/sectiondoc/renderers/__init__.py index 3d542ba..2ef037c 100644 --- a/sectiondoc/renderers/__init__.py +++ b/sectiondoc/renderers/__init__.py @@ -7,10 +7,10 @@ 'TableRow', 'Definition'] -from refactordoc.renderers.method import Method -from refactordoc.renderers.argument import Argument -from refactordoc.renderers.renderer import Renderer -from refactordoc.renderers.attribute import Attribute -from refactordoc.renderers.list_item import ListItem -from refactordoc.renderers.table_row import TableRow -from refactordoc.renderers.definition import Definition +from sectiondoc.renderers.method import Method +from sectiondoc.renderers.argument import Argument +from sectiondoc.renderers.renderer import Renderer +from sectiondoc.renderers.attribute import Attribute +from sectiondoc.renderers.list_item import ListItem +from sectiondoc.renderers.table_row import TableRow +from sectiondoc.renderers.definition import Definition diff --git a/sectiondoc/renderers/argument.py b/sectiondoc/renderers/argument.py index 6cdea1a..36adc20 100644 --- a/sectiondoc/renderers/argument.py +++ b/sectiondoc/renderers/argument.py @@ -1,5 +1,5 @@ -from refactordoc.renderers.renderer import Renderer -from refactordoc.util import add_indent, fix_star, fix_trailing_underscore +from sectiondoc.renderers.renderer import Renderer +from sectiondoc.util import add_indent, fix_star, fix_trailing_underscore class Argument(Renderer): diff --git a/sectiondoc/renderers/attribute.py b/sectiondoc/renderers/attribute.py index 137da4a..82c0ced 100644 --- a/sectiondoc/renderers/attribute.py +++ b/sectiondoc/renderers/attribute.py @@ -1,5 +1,5 @@ -from refactordoc.renderers.renderer import Renderer -from refactordoc.util import add_indent +from sectiondoc.renderers.renderer import Renderer +from sectiondoc.util import add_indent class Attribute(Renderer): diff --git a/sectiondoc/renderers/definition.py b/sectiondoc/renderers/definition.py index 02ba348..c9a8281 100644 --- a/sectiondoc/renderers/definition.py +++ b/sectiondoc/renderers/definition.py @@ -1,5 +1,5 @@ -from refactordoc.renderers.renderer import Renderer -from refactordoc.util import add_indent, EMPTY_LINE +from sectiondoc.renderers.renderer import Renderer +from sectiondoc.util import add_indent, NEW_LINE class Definition(Renderer): @@ -49,7 +49,7 @@ def to_rst(self, **kwards): postfix = ' --' if (len(item.definition) > 0) else '' lines = [] lines += [item.term] - lines += [EMPTY_LINE] + lines += [NEW_LINE] number_of_classifiers = len(item.classifiers) if number_of_classifiers == 1: lines += [' *({0[0]})*{1}'.format(item.classifiers, postfix)] @@ -58,5 +58,5 @@ def to_rst(self, **kwards): ' *({0[0]} or {0[1]})*{2}'.format( item.classifiers, postfix)] lines += add_indent(item.definition) # definition is already a list - lines += [EMPTY_LINE] + lines += [NEW_LINE] return lines diff --git a/sectiondoc/renderers/list_item.py b/sectiondoc/renderers/list_item.py index 947fb71..5ae62fa 100644 --- a/sectiondoc/renderers/list_item.py +++ b/sectiondoc/renderers/list_item.py @@ -1,5 +1,5 @@ -from refactordoc.renderers import Renderer -from refactordoc.util import add_indent +from sectiondoc.renderers import Renderer +from sectiondoc.util import add_indent class ListItem(Renderer): diff --git a/sectiondoc/renderers/method.py b/sectiondoc/renderers/method.py index 571bae7..4d09f6a 100644 --- a/sectiondoc/renderers/method.py +++ b/sectiondoc/renderers/method.py @@ -1,4 +1,4 @@ -from refactordoc.renderers.renderer import Renderer +from sectiondoc.renderers.renderer import Renderer class Method(Renderer): diff --git a/sectiondoc/renderers/table_row.py b/sectiondoc/renderers/table_row.py index ed95889..b1efb13 100644 --- a/sectiondoc/renderers/table_row.py +++ b/sectiondoc/renderers/table_row.py @@ -1,4 +1,4 @@ -from refactordoc.renderers.renderer import Renderer +from sectiondoc.renderers.renderer import Renderer class TableRow(Renderer): diff --git a/sectiondoc/sections/__init__.py b/sectiondoc/sections/__init__.py index ea771a6..7fa74a5 100644 --- a/sectiondoc/sections/__init__.py +++ b/sectiondoc/sections/__init__.py @@ -6,9 +6,9 @@ 'arguments', 'item_list'] -from refactordoc.sections.attributes import attributes -from refactordoc.sections.notes import notes_paragraph -from refactordoc.sections.methods import methods_table -from refactordoc.sections.rubric import rubric -from refactordoc.sections.arguments import arguments -from refactordoc.sections.item_list import item_list +from sectiondoc.sections.attributes import attributes +from sectiondoc.sections.notes import notes_paragraph +from sectiondoc.sections.methods import methods_table +from sectiondoc.sections.rubric import rubric +from sectiondoc.sections.arguments import arguments +from sectiondoc.sections.item_list import item_list diff --git a/sectiondoc/sections/arguments.py b/sectiondoc/sections/arguments.py index 00d2269..898c3e4 100644 --- a/sectiondoc/sections/arguments.py +++ b/sectiondoc/sections/arguments.py @@ -1,18 +1,17 @@ # -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- -# file: function_doc.py # License: LICENSE.TXT # Author: Ioannis Tziakos # -# Copyright (c) 2011, Enthought, Inc. +# Copyright (c) 2011-14, Enthought, Inc. # All rights reserved. # ----------------------------------------------------------------------------- -from refactordoc.items import DefinitionItem -from refactordoc.renderers.argument import Argument +from sectiondoc.items import DefinitionItem +from sectiondoc.renderers.argument import Argument def arguments(doc, header, renderer=Argument, item_class=DefinitionItem): - """ Refactor the argument section to sphinx friendly format. + """ Render the argument section to sphinx friendly format. Arguments --------- diff --git a/sectiondoc/sections/attributes.py b/sectiondoc/sections/attributes.py index a5786e8..3a9fe84 100644 --- a/sectiondoc/sections/attributes.py +++ b/sectiondoc/sections/attributes.py @@ -1,20 +1,19 @@ # -*- coding: utf-8 -*- -# ----------------------------------------------------------------------------- -# file: sections/attributes.py +#----------------------------------------------------------------------------- # License: LICENSE.TXT +# Author: Ioannis Tziakos # -# Copyright (c) 2011-14, Enthought, Inc. +# Copyright (c) 2011-2014, Enthought, Inc. # All rights reserved. -# ----------------------------------------------------------------------------- -from refactordoc.items import DefinitionItem -from refactordoc.renderers import Attribute +#----------------------------------------------------------------------------- +from sectiondoc.items import DefinitionItem +from sectiondoc.renderers import Attribute def attributes(doc, header, renderer=Attribute, item_class=DefinitionItem): - """Refactor the attributes section to sphinx friendly format. + """Render the attributes section to sphinx friendly format. """ - items = doc.extract_items(item_class) lines = [] renderer = renderer() diff --git a/sectiondoc/sections/item_list.py b/sectiondoc/sections/item_list.py index 96a28a5..6121a73 100644 --- a/sectiondoc/sections/item_list.py +++ b/sectiondoc/sections/item_list.py @@ -1,19 +1,18 @@ # -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- -# file: sections/item_list.py # License: LICENSE.TXT # Author: Ioannis Tziakos # # Copyright (c) 2011-14, Enthought, Inc. # All rights reserved. # ----------------------------------------------------------------------------- -from refactordoc.util import add_indent -from refactordoc.items import DefinitionItem -from refactordoc.renderers import ListItem +from sectiondoc.util import add_indent +from sectiondoc.items import DefinitionItem +from sectiondoc.renderers import ListItem def item_list(doc, header, renderer=ListItem, item_class=DefinitionItem): - """ Refactor the section to sphinx friendly item list. + """ Render the section to sphinx friendly item list. Arguments --------- diff --git a/sectiondoc/sections/methods.py b/sectiondoc/sections/methods.py index 4969ef6..3aaefd5 100644 --- a/sectiondoc/sections/methods.py +++ b/sectiondoc/sections/methods.py @@ -6,13 +6,13 @@ # Copyright (c) 2011-14, Enthought, Inc. # All rights reserved. # ----------------------------------------------------------------------------- -from refactordoc.items import MethodItem -from refactordoc.sections.util import get_column_lengths -from refactordoc.renderers import Method +from sectiondoc.items import MethodItem +from sectiondoc.sections.util import get_column_lengths +from sectiondoc.renderers import Method def methods_table(doc, header, renderer=Method, item_class=MethodItem): - """Refactor the methods section to sphinx friendly table format. + """ Render the methods section to sphinx friendly table format. """ items = doc.extract_items(item_class) diff --git a/sectiondoc/sections/notes.py b/sectiondoc/sections/notes.py index 222c942..ec3eb30 100644 --- a/sectiondoc/sections/notes.py +++ b/sectiondoc/sections/notes.py @@ -6,11 +6,11 @@ # Copyright (c) 2011-14, Enthought, Inc. # All rights reserved. # ----------------------------------------------------------------------------- -from refactordoc.util import add_indent +from sectiondoc.util import add_indent def notes_paragraph(doc, header, renderer=None, item_class=None): - """Refactor the note section to use the rst ``.. note`` directive. + """Render the note section to use the rst ``.. note`` directive. The section is expected to be given as a paragraph. diff --git a/sectiondoc/sections/rubric.py b/sectiondoc/sections/rubric.py index 1e41603..97e2a7e 100644 --- a/sectiondoc/sections/rubric.py +++ b/sectiondoc/sections/rubric.py @@ -1,12 +1,11 @@ # -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- -# file: sections/rubric.py # License: LICENSE.TXT # # Copyright (c) 2011-14, Enthought, Inc. # All rights reserved. # ----------------------------------------------------------------------------- -from refactordoc.util import fix_backspace, EMPTY_LINE +from sectiondoc.util import fix_backspace, NEW_LINE def rubric(doc, header, renderer=None, item_class=None): @@ -23,4 +22,4 @@ def rubric(doc, header, renderer=None, item_class=None): """ header = fix_backspace(header) directive = '.. rubric:: {0}'.format(header) - return [directive, EMPTY_LINE] + return [directive, NEW_LINE] diff --git a/sectiondoc/sections/util.py b/sectiondoc/sections/util.py index c01601a..4e718a0 100644 --- a/sectiondoc/sections/util.py +++ b/sectiondoc/sections/util.py @@ -7,7 +7,7 @@ # Copyright (c) 2011-14, Enthought, Inc. # All rights reserved. # ----------------------------------------------------------------------------- -from refactordoc.items.util import max_attribute_length, max_attribute_index +from sectiondoc.items.util import max_attribute_length, max_attribute_index def get_column_lengths(items): diff --git a/sectiondoc/styles/__init__.py b/sectiondoc/styles/__init__.py index e69de29..34c099b 100644 --- a/sectiondoc/styles/__init__.py +++ b/sectiondoc/styles/__init__.py @@ -0,0 +1,6 @@ +__all__ = [ + 'Style', + 'BaseDoc'] + +from sectiondoc.styles.style import Style +from sectiondoc.styles.base_doc import BaseDoc diff --git a/sectiondoc/styles/base_doc.py b/sectiondoc/styles/base_doc.py new file mode 100644 index 0000000..6c76a98 --- /dev/null +++ b/sectiondoc/styles/base_doc.py @@ -0,0 +1,350 @@ +# -*- coding: utf-8 -*- +# ----------------------------------------------------------------------------- +# file: base_doc.py +# License: LICENSE.TXT +# +# Copyright (c) 2011-14, Enthought, Inc. +# All rights reserved. +# ----------------------------------------------------------------------------- +import re + +from sectiondoc.items import DefinitionItem +from sectiondoc.util import is_empty, get_indent +from sectiondoc.sections import rubric + + +underline_regex = re.compile(r'\s*\S+\s*\Z') + + +class BaseDoc(object): + """Base abstract docstring refactoring class. + + The class' main purpose is to parse the docstring and find the + sections that need to be refactored. Subclasses should provide + the methods responsible for refactoring the sections. + + Attributes + ---------- + docstring : list + A list of strings (lines) that holds docstrings + + index : int + The current zero-based line number of the docstring that is currently + processed. + + headers : dict + The sections that the class will refactor. Each entry in the + dictionary should have as key the name of the section in the + form that it appears in the docstrings. The value should be + the postfix of the method, in the subclasses, that is + responsible for refactoring (e.g. {'Methods': 'method'}). + + BaseDoc also provides a number of methods that operate on the docstring to + help with the refactoring. This is necessary because the docstring has to + change inplace and thus it is better to live the docstring manipulation to + the class methods instead of accessing the lines directly. + + """ + + def __init__(self, lines, sections=None): + """ Initialize the class + + The method setups the class attributes and starts parsing the + docstring to find and refactor the sections. + + Arguments + --------- + lines : list of strings + The docstring to refactor + + headers : dict + The sections for which the class has custom refactor methods. + Each entry in the dictionary should have as key the name of + the section in the form that it appears in the docstrings. + The value should be a callable, which be responsible for rendering + the header (e.g. {'Methods': method}). + + """ + try: + self._docstring = lines.splitlines() + except AttributeError: + self._docstring = lines + self.sections = {} if sections is None else sections + self.bookmarks = [] + + def parse(self): + """ Parse the docstring. + + The docstring is parsed for sections. If a section is found then + the corresponding refactoring method is called. + + """ + self.index = 0 + self.seek_to_next_non_empty_line() + while not self.eod: + section = self.is_section() + if len(section) > 0: + self._refactor(section) + else: + self.index += 1 + self.seek_to_next_non_empty_line() + + def _refactor(self, section): + """Call the heading refactor method. + + The header is removed from the docstring and the docstring + refactoring is dispatched to the appropriate refactoring method. + + """ + self.remove_lines(self.index, 2) # Remove header + self.remove_if_empty(self.index) # Remove space after header + method, renderer, item_class = self.sections.get( + section, (rubric, None, None)) + lines = method(self, section, renderer, item_class) + self.insert_and_move(lines, self.index) + + def extract_items(self, item_class): + """ Extract the definition items from a docstring. + + Parse the items in the description of a section into items of the + provided class time. Given an Item or a subclass defined by + the ``item_class`` parameter. The method starts at the current index + position and checks if in the next two lines a valid header exists. + If successful, the lines that belong to the item description + block (i.e. item header + item body) are popped out from the docstring + and passed to the ``item_class`` parser to get an instance of + ``item_class``. + + The process is repeated until there is no compatible ``item_class`` + found or we run out of docstring lines, The collected item class + instances are return. + + The exit conditions allow for two valid section item layouts: + + 1. No lines between items:: + + + + + + + + + 2. One line between items:: + + + + + + + + + + + Arguments + --------- + item_class : Item + An Item or a subclass. This argument is used to check + if a line in the docstring is a valid item and to parse the + individual list items in the section. + + + Returns + ------- + parameters : list + List of the collected item instances of :class:`~.Item` type. + + """ + item_type = DefinitionItem if (item_class is None) else item_class + is_item = item_type.is_item + item_blocks = [] + while (not self.eod) and \ + (is_item(self.peek()) or is_item(self.peek(1))): + self.remove_if_empty(self.index) + item_blocks.append(self.get_next_block()) + items = [item_type.parse(block) for block in item_blocks] + return items + + def get_next_block(self): + """ Get the next item block from the docstring. + + The method reads the next item block in the docstring. The first line + is assumed to be the Item header and the following lines to + belong to the definition body:: + +
+ + + The end of the field is designated by a line with the same indent + as the field header or two empty lines are found in sequence. + + """ + item_header = self.pop() + sub_indent = get_indent(item_header) + ' ' + block = [item_header] + while not self.eod: + peek_0 = self.peek() + peek_1 = self.peek(1) + if is_empty(peek_0) and not peek_1.startswith(sub_indent): + break + elif not is_empty(peek_0) and not peek_0.startswith(sub_indent): + break + else: + line = self.pop() + block += [line.rstrip()] + return block + + def is_section(self): + """ Check if the current line defines a section. + + .. todo:: split and cleanup this method. + + """ + if self.eod: + return False + + header = self.peek() + line2 = self.peek(1) + + # check for underline type format + underline = underline_regex.match(line2) + if underline is None: + return '' + # is the next line an rst section underline? + striped_header = header.rstrip() + expected_underline1 = re.sub(r'[A-Za-z\\]|\b\s', '-', striped_header) + expected_underline2 = re.sub(r'[A-Za-z\\]|\b\s', '=', striped_header) + if ( + (underline.group().rstrip() == expected_underline1) or + (underline.group().rstrip() == expected_underline2)): + return header.strip() + else: + return '' + + def insert_lines(self, lines, index): + """ Insert refactored lines. + + Arguments + --------- + lines : list + The list of lines to insert + + index : int + Index to start the insertion + + """ + docstring = self.docstring + for line in reversed(lines): + docstring.insert(index, line) + + def insert_and_move(self, lines, index): + """ Insert refactored lines and move current index to the end. + + """ + self.insert_lines(lines, index) + self.index += len(lines) + + def seek_to_next_non_empty_line(self): + """ Goto the next non_empty line. + + """ + docstring = self.docstring + for line in docstring[self.index:]: + if not is_empty(line): + break + self.index += 1 + + def get_next_paragraph(self): + """ Get the next paragraph designated by an empty line. + + """ + lines = [] + while (not self.eod) and (not is_empty(self.peek())): + line = self.pop() + lines.append(line) + return lines + + def read(self): + """ Return the next line and advance the index. + + """ + index = self.index + line = self._docstring[index] + self.index += 1 + return line + + def remove_lines(self, index, count=1): + """ Removes the lines from the docstring + + """ + docstring = self.docstring + del docstring[index:(index + count)] + + def remove_if_empty(self, index=None): + """ Remove the line from the docstring if it is empty. + + """ + if is_empty(self.docstring[index]): + self.remove_lines(index) + + def bookmark(self): + """ append the current index to the end of the list of bookmarks. + + """ + self.bookmarks.append(self.index) + + def goto_bookmark(self, bookmark_index=-1): + """ Move to bookmark. + + Move the current index to the docstring line given my the + ``self.bookmarks[bookmark_index]`` and remove it from the bookmark + list. Default value will pop the last entry. + + Returns + ------- + bookmark : int + + """ + self.index = self.bookmarks[bookmark_index] + return self.bookmarks.pop(bookmark_index) + + def peek(self, ahead=0): + """ Peek ahead a number of lines + + The function retrieves the line that is ahead of the current + index. If the index is at the end of the list then it returns an + empty string. + + Arguments + --------- + ahead : int + The number of lines to look ahead. + + """ + position = self.index + ahead + try: + line = self.docstring[position] + except IndexError: + line = '' + return line + + def pop(self, index=None): + """ Pop a line from the dostrings. + + """ + index = self.index if index is None else index + return self._docstring.pop(index) + + @property + def eod(self): + """ End of docstring. + + """ + return self.index >= len(self.docstring) + + @property + def docstring(self): + """ Get the docstring lines. + + """ + return self._docstring diff --git a/sectiondoc/styles/old_style.py b/sectiondoc/styles/old_style.py index df19fac..7ba32d7 100644 --- a/sectiondoc/styles/old_style.py +++ b/sectiondoc/styles/old_style.py @@ -1,12 +1,12 @@ -from refactordoc.base_doc import BaseDoc -from refactordoc.sections import ( +from sectiondoc.sections import ( attributes, methods_table, notes_paragraph, item_list, arguments) -from refactordoc.renderers import Attribute, Method, Argument, ListItem -from refactordoc.items import DefinitionItem, MethodItem -from refactordoc.styles.style import Style +from sectiondoc.renderers import Attribute, Method, Argument, ListItem +from sectiondoc.items import DefinitionItem, MethodItem +from sectiondoc.styles.base_doc import BaseDoc +from sectiondoc.styles.style import Style -def refactor_class(lines): +def class_section(lines): return BaseDoc( lines, sections={ @@ -15,7 +15,7 @@ def refactor_class(lines): 'Notes': (notes_paragraph, None, None)}) -def refactor_function(lines): +def function_section(lines): return BaseDoc( lines, sections={ @@ -29,8 +29,8 @@ def refactor_function(lines): def setup(app): style = Style({ - 'class': refactor_class, - 'function': refactor_function, - 'method': refactor_function}) + 'class': class_section, + 'function': function_section, + 'method': function_section}) app.setup_extension('sphinx.ext.autodoc') - app.connect('autodoc-process-docstring', style.refactor_docstring) + app.connect('autodoc-process-docstring', style.section_docstring) diff --git a/sectiondoc/styles/style.py b/sectiondoc/styles/style.py index a28f433..891cef0 100644 --- a/sectiondoc/styles/style.py +++ b/sectiondoc/styles/style.py @@ -1,10 +1,10 @@ class Style(object): - def __init__(self, refactoring_map): - self.refactoring_map = refactoring_map + def __init__(self, rendering_map): + self.rendering_map = rendering_map - def refactor_docstring(self, app, what, name, obj, options, lines): - renderer_factory = self.refactoring_map.get(what, None) + def render_docstring(self, app, what, name, obj, options, lines): + renderer_factory = self.rendering_map.get(what, None) if renderer_factory is not None: docstring_renderer = renderer_factory(lines) docstring_renderer.parse() diff --git a/sectiondoc/tests/test_base_doc.py b/sectiondoc/tests/test_base_doc.py index 6198f04..4272528 100644 --- a/sectiondoc/tests/test_base_doc.py +++ b/sectiondoc/tests/test_base_doc.py @@ -1,18 +1,5 @@ -<<<<<<< HEAD:refactordoc/tests/test_base_doc.py -from refactordoc.base_doc import BaseDoc -from refactordoc.tests._compat import unittest -======= -# -*- coding: utf-8 -*- -#------------------------------------------------------------------------------ -# file: test_base_doc.py -# License: LICENSE.TXT -# -# Copyright (c) 2011, Enthought, Inc. -# All rights reserved. -#------------------------------------------------------------------------------ -from sectiondoc.base_doc import BaseDoc -from ._compat import unittest ->>>>>>> master:tests/test_base_doc.py +from sectiondoc.styles import BaseDoc +from sectiondoc.tests._compat import unittest class TestBaseDoc(unittest.TestCase): diff --git a/sectiondoc/tests/test_definition_items.py b/sectiondoc/tests/test_definition_items.py index f22f1f8..ccf2525 100644 --- a/sectiondoc/tests/test_definition_items.py +++ b/sectiondoc/tests/test_definition_items.py @@ -1,7 +1,7 @@ -from refactordoc.items import DefinitionItem, MethodItem, Item -from refactordoc.renderers import ( +from sectiondoc.items import DefinitionItem, MethodItem, Item +from sectiondoc.renderers import ( Argument, Attribute, Definition, ListItem, Method, TableRow) -from refactordoc.tests._compat import unittest +from sectiondoc.tests._compat import unittest class TestDefinitionItem(unittest.TestCase): diff --git a/sectiondoc/tests/test_line_functions.py b/sectiondoc/tests/test_line_functions.py index b1731c3..cabb478 100644 --- a/sectiondoc/tests/test_line_functions.py +++ b/sectiondoc/tests/test_line_functions.py @@ -1,23 +1,7 @@ -# -*- coding: utf-8 -*- -<<<<<<< HEAD:refactordoc/tests/test_line_functions.py -from refactordoc.util import ( +from sectiondoc.util import ( add_indent, remove_indent, get_indent, fix_star, fix_backspace, is_empty, replace_at) -from refactordoc.tests._compat import unittest -======= -#------------------------------------------------------------------------------ -# file: test_line_functions.py -# License: LICENSE.TXT -# Author: Ioannis Tziakos -# -# Copyright (c) 2011, Enthought, Inc. -# All rights reserved. -#------------------------------------------------------------------------------ -from sectiondoc.line_functions import (add_indent, remove_indent, get_indent, - fix_star, fix_backspace, is_empty, - replace_at) -from ._compat import unittest ->>>>>>> master:tests/test_line_functions.py +from sectiondoc.tests._compat import unittest class TestLineFunctions(unittest.TestCase): diff --git a/sectiondoc/tests/test_old_style.py b/sectiondoc/tests/test_old_style.py index 97a459d..3b9bb74 100644 --- a/sectiondoc/tests/test_old_style.py +++ b/sectiondoc/tests/test_old_style.py @@ -1,18 +1,5 @@ -# -*- coding: utf-8 -*- -<<<<<<< HEAD:refactordoc/tests/test_old_style.py -from refactordoc.styles.old_style import refactor_class, refactor_function -from refactordoc.tests._compat import unittest -======= -#------------------------------------------------------------------------------ -# file: test_function_doc.py -# License: LICENSE.TXT -# -# Copyright (c) 2011, Enthought, Inc. -# All rights reserved. -#------------------------------------------------------------------------------ -from sectiondoc.function_doc import FunctionDoc -from ._compat import unittest ->>>>>>> master:tests/test_function_doc.py +from sectiondoc.styles.old_style import class_section, function_section +from sectiondoc.tests._compat import unittest class TestOldStyleClass(unittest.TestCase): @@ -60,7 +47,7 @@ def test_refactor_attributes(self): """ docstring_lines = docstring.splitlines() - class_doc = refactor_class(docstring_lines) + class_doc = class_section(docstring_lines) class_doc.parse() output = '\n'.join(docstring_lines) self.assertMultiLineEqual(rst, output) @@ -93,10 +80,10 @@ def test_refactor_methods(self): :meth:`get_next_paragraph() ` Get the next paragraph designated by an empty line. ==================================================================== =================================================== -""" +""" # noqa docstring_lines = docstring.splitlines() - class_doc = refactor_class(docstring_lines) + class_doc = class_section(docstring_lines) class_doc.parse() output = '\n'.join(docstring_lines) self.assertMultiLineEqual(rst, output) @@ -136,13 +123,13 @@ def test_refactor_notes(self): """ docstring_lines = docstring1.splitlines() - class_doc = refactor_class(docstring_lines) + class_doc = class_section(docstring_lines) class_doc.parse() output = '\n'.join(docstring_lines) + '\n' self.assertMultiLineEqual(rst, output) docstring_lines = docstring2.splitlines() - class_doc = refactor_class(docstring_lines) + class_doc = class_section(docstring_lines) class_doc.parse() output = '\n'.join(docstring_lines) + '\n' self.assertMultiLineEqual(rst, output) @@ -174,7 +161,7 @@ def test_refactor_returns(self): """ docstring_lines = docstring.splitlines() - function_doc = refactor_function(docstring_lines) + function_doc = function_section(docstring_lines) function_doc.parse() output = '\n'.join(docstring_lines) self.assertMultiLineEqual(rst, output) @@ -206,7 +193,7 @@ def test_refactor_raises(self): """ docstring_lines = docstring.splitlines() - function_doc = refactor_function(docstring_lines) + function_doc = function_section(docstring_lines) function_doc.parse() output = '\n'.join(docstring_lines) self.assertMultiLineEqual(rst, output) @@ -246,7 +233,7 @@ def test_refactor_arguments(self): """ docstring_lines = docstring.splitlines() - function_doc = refactor_function(docstring_lines) + function_doc = function_section(docstring_lines) function_doc.parse() output = '\n'.join(docstring_lines) + '\n' self.assertMultiLineEqual(rst, output) @@ -282,7 +269,7 @@ def test_refactor_strange_arguments(self): """ docstring_lines = docstring.splitlines() - function_doc = refactor_function(docstring_lines) + function_doc = function_section(docstring_lines) function_doc.parse() output = '\n'.join(docstring_lines) + '\n' self.assertMultiLineEqual(rst, output) @@ -310,7 +297,7 @@ def test_refactor_notes(self): """ docstring_lines = docstring.splitlines() - function_doc = refactor_function(docstring_lines) + function_doc = function_section(docstring_lines) function_doc.parse() output = '\n'.join(docstring_lines) + '\n' self.assertMultiLineEqual(rst, output) @@ -371,13 +358,13 @@ def test_docstring_cases_1(self): """ docstring_lines = docstring1.splitlines() - function_doc = refactor_function(docstring_lines) + function_doc = function_section(docstring_lines) function_doc.parse() output = '\n'.join(docstring_lines) self.assertMultiLineEqual(rst, output) docstring_lines = docstring2.splitlines() - function_doc = refactor_function(docstring_lines) + function_doc = function_section(docstring_lines) function_doc.parse() output = '\n'.join(docstring_lines) self.assertMultiLineEqual(rst, output) @@ -445,7 +432,7 @@ def test_docstring_cases_2(self): """ docstring_lines = docstring.splitlines() - function_doc = refactor_function(docstring_lines) + function_doc = function_section(docstring_lines) function_doc.parse() output = '\n'.join(docstring_lines) + '\n' self.assertMultiLineEqual(rst, output) diff --git a/sectiondoc/util.py b/sectiondoc/util.py new file mode 100644 index 0000000..d041806 --- /dev/null +++ b/sectiondoc/util.py @@ -0,0 +1,157 @@ +# -*- coding: utf-8 -*- +#----------------------------------------------------------------------------- +# License: LICENSE.TXT +# Author: Ioannis Tziakos +# +# Copyright (c) 2011, Enthought, Inc. +# All rights reserved. +#----------------------------------------------------------------------------- +import re + + +#----------------------------------------------------------------------------- +# Pre-compiled regexes +#----------------------------------------------------------------------------- +indent_regex = re.compile(r'\s+') + + +#----------------------------------------------------------------------------- +# Constants +#----------------------------------------------------------------------------- +NEW_LINE = '' + + +#------------------------------------------------------------------------------ +# Functions to manage indention +#------------------------------------------------------------------------------ + +def add_indent(lines, indent=4): + """ Add spaces to indent a list of lines. + + Arguments + --------- + lines : list + The list of strings to indent. + + indent : int + The number of spaces to add. + + Returns + ------- + lines : list + The indented strings (lines). + + Notes + ----- + Empty strings are not changed. + + """ + indent_str = ' ' * indent if indent != 0 else '' + output = [] + for line in lines: + if is_empty(line): + output.append(line) + else: + output.append(indent_str + line) + return output + + +def remove_indent(lines): + """ Remove all indentation from the lines. + + Returns + ------- + result : list + A new list of left striped strings. + + """ + return [line.lstrip() for line in lines] + + +def trim_indent(lines): + """ Trim global intention level from lines. + + """ + non_empty_lines = filter(lambda x: not is_empty(x), lines) + indent = set(len(get_indent(line)) for line in non_empty_lines) + indent.discard(0) + global_indent = min(indent) + return [line[global_indent:] for line in lines] + + +def get_indent(line): + """ Return the indent portion of the line. + + """ + indent = indent_regex.match(line) + if indent is None: + return '' + else: + return indent.group() + + +#------------------------------------------------------------------------------ +# Functions to detect line type +#------------------------------------------------------------------------------ + +def is_empty(line): + return not line.strip() + + +#------------------------------------------------------------------------------ +# Functions to adjust strings +#------------------------------------------------------------------------------ + +def fix_star(word): + """ Replace ``*`` with ``\*`` so that is will be parse properly by + docutils. + + """ + return word.replace('*', '\*') + + +def fix_backspace(word): + """ Replace ``\\`` with ``\\\\`` so that it will printed properly in the + documentation. + + """ + return word.replace('\\', '\\\\') + + +def fix_trailing_underscore(word): + """ Replace the trailing ``_`` with ``\\_`` so that it will printed + properly in the documentation. + + """ + if word.endswith('_'): + word = word.replace('_', '\_') + return word + + +def replace_at(word, line, index): + """ Replace the text in-line. + + The text in line is replaced (not inserted) with the word. The + replacement starts at the provided index. The result is cliped to + the input length + + Arguments + --------- + word : str + The text to copy into the line. + + line : str + The line where the copy takes place. + + index : int + The index to start coping. + + Returns + ------- + result : str + line of text with the text replaced. + + """ + word_length = len(word) + result = line[:index] + word + line[(index + word_length):] + return result[:len(line)] diff --git a/setup.py b/setup.py index a6769e1..4379613 100644 --- a/setup.py +++ b/setup.py @@ -92,5 +92,5 @@ def write_version_py(filename='sectiondoc/_version.py'): packages=find_packages(), author="Enthought Ltd", author_email="info@enthought.com", - test_suite='refactordoc.tests', + test_suite='sectiondoc.tests', ) From d2797c96c286212618acabf8e9dd03db52796fb0 Mon Sep 17 00:00:00 2001 From: Ioannis Tziakos Date: Fri, 5 Dec 2014 22:06:59 +0000 Subject: [PATCH 35/63] fix typo --- sectiondoc/styles/old_style.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sectiondoc/styles/old_style.py b/sectiondoc/styles/old_style.py index 7ba32d7..42ad36d 100644 --- a/sectiondoc/styles/old_style.py +++ b/sectiondoc/styles/old_style.py @@ -33,4 +33,4 @@ def setup(app): 'function': function_section, 'method': function_section}) app.setup_extension('sphinx.ext.autodoc') - app.connect('autodoc-process-docstring', style.section_docstring) + app.connect('autodoc-process-docstring', style.render_docstring) From e3885780370a6482a028bcaf07a50e65db75fd50 Mon Sep 17 00:00:00 2001 From: Ioannis Tziakos Date: Fri, 5 Dec 2014 22:07:26 +0000 Subject: [PATCH 36/63] fix doc --- docs/source/reference.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/source/reference.rst b/docs/source/reference.rst index f433c5d..7bf1fc8 100644 --- a/docs/source/reference.rst +++ b/docs/source/reference.rst @@ -1,11 +1,12 @@ Library Reference ================= -The extension is separated into four main parts. +The extension is separated into three main parts. .. default-role:: autolink + .. currentmodule:: refactordoc From 6658434130fb5c66321dbf66f8475ed1e39ac82e Mon Sep 17 00:00:00 2001 From: Ioannis Tziakos Date: Fri, 5 Dec 2014 22:09:44 +0000 Subject: [PATCH 37/63] fix old package references --- docs/source/reference.rst | 8 ++++---- docs/source/usage.rst | 10 +++++----- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/source/reference.rst b/docs/source/reference.rst index 7bf1fc8..4c9a500 100644 --- a/docs/source/reference.rst +++ b/docs/source/reference.rst @@ -7,24 +7,24 @@ The extension is separated into three main parts. .. default-role:: autolink -.. currentmodule:: refactordoc +.. currentmodule:: sectiondoc Sections -------- -.. automodule:: refactordoc.sections +.. automodule:: sectiondoc.sections :members: Items ----- -.. automodule:: refactordoc.items +.. automodule:: sectiondoc.items :members: Renderers --------- -.. automodule:: refactordoc.renderers +.. automodule:: sectiondoc.renderers :members: diff --git a/docs/source/usage.rst b/docs/source/usage.rst index bcd2f33..b2dbdc7 100644 --- a/docs/source/usage.rst +++ b/docs/source/usage.rst @@ -1,7 +1,7 @@ Default refactoring ******************* -The base implementation of RefactorDoc provides refactoring for class and +The base implementation of Sectiondoc provides refactoring for class and function doc-strings. A number of known (i.e. predefined) sections are processed by the ClassDoc and FunctionDoc classes and all unknown sections are re-factored using the ``.. rubric::`` directive by default. @@ -66,7 +66,7 @@ Argument sections Index to start the insertion """ -.. automethod:: refactordoc.base_doc.BaseDoc.insert_lines +.. automethod:: sectiondoc.base_doc.BaseDoc.insert_lines :noindex: @@ -90,7 +90,7 @@ Attribute sections the postfix of the method, in the subclasses, that is responsible for refactoring (e.g. {'Methods': 'method'}). -.. autoclass:: refactordoc.base_doc.BaseDoc +.. autoclass:: sectiondoc.base_doc.BaseDoc :noindex: :no-members: @@ -103,7 +103,7 @@ Returns sections result : list A new list of left striped strings. -.. autofunction:: refactordoc.util.remove_indent +.. autofunction:: sectiondoc.util.remove_indent :noindex: Raises section @@ -120,5 +120,5 @@ Notes ----- Empty strings are not changed. -.. autofunction:: refactordoc.util.add_indent +.. autofunction:: sectiondoc.util.add_indent :noindex: From a8c18cd116020864f32626538917436f96d96585 Mon Sep 17 00:00:00 2001 From: itziakos Date: Thu, 11 Dec 2014 23:17:40 +0000 Subject: [PATCH 38/63] update warning message to use sectiondoc --- sectiondoc/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sectiondoc/__init__.py b/sectiondoc/__init__.py index 804d947..96532f0 100644 --- a/sectiondoc/__init__.py +++ b/sectiondoc/__init__.py @@ -17,7 +17,7 @@ def setup(app): import warnings from sectiondoc.styles.old_style import setup warnings.warn( - "This entry-point will be removed in the next release" - "Please use 'reafactordoc.styles.old_style' in conf.py", + "This entry-point will be removed in the next release. " + "Please use 'sectiondoc.styles.old_style' in conf.py", DeprecationWarning) setup(app) From bec17ce016a81710337efbcf02c10e16e7691019 Mon Sep 17 00:00:00 2001 From: itziakos Date: Thu, 11 Dec 2014 23:39:39 +0000 Subject: [PATCH 39/63] rename definition item -> to or definition item --- sectiondoc/items/__init__.py | 4 +- sectiondoc/items/item.py | 2 +- ...finition_item.py => or_definition_item.py} | 22 ++++----- sectiondoc/items/util.py | 9 ++-- sectiondoc/renderers/definition.py | 7 +-- sectiondoc/sections/arguments.py | 6 +-- sectiondoc/sections/attributes.py | 4 +- sectiondoc/sections/item_list.py | 6 +-- sectiondoc/styles/base_doc.py | 4 +- sectiondoc/styles/old_style.py | 14 +++--- sectiondoc/tests/test_definition_items.py | 48 +++++++++---------- 11 files changed, 62 insertions(+), 64 deletions(-) rename sectiondoc/items/{definition_item.py => or_definition_item.py} (86%) diff --git a/sectiondoc/items/__init__.py b/sectiondoc/items/__init__.py index de71f46..afca45f 100644 --- a/sectiondoc/items/__init__.py +++ b/sectiondoc/items/__init__.py @@ -1,8 +1,8 @@ __all__ = [ - 'DefinitionItem', + 'OrDefinitionItem', 'MethodItem', 'Item'] from sectiondoc.items.item import Item -from sectiondoc.items.definition_item import DefinitionItem +from sectiondoc.items.definition_item import OrDefinitionItem from sectiondoc.items.method_item import MethodItem diff --git a/sectiondoc/items/item.py b/sectiondoc/items/item.py index dfdff51..bdca593 100644 --- a/sectiondoc/items/item.py +++ b/sectiondoc/items/item.py @@ -68,7 +68,7 @@ def parse(cls, lines): """Parse a definition item from a set of lines. The class method parses the item from the list of docstring lines and - produces a DefinitionItem with the term, classifier and the definition. + produces a Item with the term, classifier and the definition. .. note:: The global indention in the definition lines is striped diff --git a/sectiondoc/items/definition_item.py b/sectiondoc/items/or_definition_item.py similarity index 86% rename from sectiondoc/items/definition_item.py rename to sectiondoc/items/or_definition_item.py index 01f8f64..58b9995 100644 --- a/sectiondoc/items/definition_item.py +++ b/sectiondoc/items/or_definition_item.py @@ -3,8 +3,11 @@ from sectiondoc.util import trim_indent -class DefinitionItem(Item): - """ A docstring definition item +class OrDefinitionItem(Item): + """ A docstring definition section item. + + In this section definition item there are two classifiers that are + separated by ``or``. Syntax diagram:: @@ -15,10 +18,6 @@ class DefinitionItem(Item): | (body elements)+ | +--------------------------------------------------+ - The Definition class is based on the nametuple class and is responsible - to check, parse a docstring definition item into sphinx - friendly rst. - Attributes ---------- term : str @@ -26,14 +25,13 @@ class DefinitionItem(Item): classifiers: list The classifiers of the definition. Commonly used to reflect the type - of an argument or the signature of a function. - - .. note:: Currently only one classifier is supported. + of an argument or the signature of a function. Only two classifiers + are accepted. definition : list The list of strings that holds the description the definition item. - .. note:: A Definition item is based on the item of a section definition + .. note:: An Or Definition item is based on the item of a section definition list as it defined in restructured text (_http://docutils.sourceforge.net/docs/ref/rst/restructuredtext.html#sections). @@ -95,9 +93,9 @@ def parse(cls, lines): docstring lines of the definition without any empty lines before or after. - Returns + Return ------- - definition : DefinitionItem + definition : OrDefinitionItem """ header = lines[0].strip() diff --git a/sectiondoc/items/util.py b/sectiondoc/items/util.py index 2958495..3590e16 100644 --- a/sectiondoc/items/util.py +++ b/sectiondoc/items/util.py @@ -1,10 +1,10 @@ def max_attribute_length(items, attr): - """ Find the max length of the attribute in a list of DefinitionItems. + """ Find the max length of the attribute in a list of Items. Arguments --------- items : list - The list of the DefinitionItem instances (or subclasses). + The list of the Item instances (or subclasses). attr : str Attribute to look at. @@ -18,13 +18,12 @@ def max_attribute_length(items, attr): def max_attribute_index(items, attr): - """ Find the index of the attribute with the maximum length in a list of - DefinitionItems. + """ Find the index of the field with the maximum length in a list of Items. Arguments --------- items : list - The list of the DefinitionItems (or subclasses). + The list of the Items (or subclasses). attr : str Attribute to look at. diff --git a/sectiondoc/renderers/definition.py b/sectiondoc/renderers/definition.py index c9a8281..9134493 100644 --- a/sectiondoc/renderers/definition.py +++ b/sectiondoc/renderers/definition.py @@ -5,7 +5,7 @@ class Definition(Renderer): def to_rst(self, **kwards): - """ Outputs the DefinitionItem in sphinx friendly rst. + """ Outputs the Item in sphinx friendly rst. The method renders the definition into a list of lines that follow the rst markup of a sphinx definition item:: @@ -30,8 +30,9 @@ def to_rst(self, **kwards): :: - >>> item = DefinitionItem('lines', 'list', - ['A list of string lines rendered in rst.']) + >>> item = Item( + 'lines', 'list', + ['A list of string lines rendered in rst.']) >>> renderer = Definition(item) >>> renderer.to_rst lines diff --git a/sectiondoc/sections/arguments.py b/sectiondoc/sections/arguments.py index 898c3e4..78d9f71 100644 --- a/sectiondoc/sections/arguments.py +++ b/sectiondoc/sections/arguments.py @@ -6,11 +6,11 @@ # Copyright (c) 2011-14, Enthought, Inc. # All rights reserved. # ----------------------------------------------------------------------------- -from sectiondoc.items import DefinitionItem +from sectiondoc.items import OrDefinitionItem from sectiondoc.renderers.argument import Argument -def arguments(doc, header, renderer=Argument, item_class=DefinitionItem): +def arguments(doc, header, renderer=Argument, item_class=OrDefinitionItem): """ Render the argument section to sphinx friendly format. Arguments @@ -24,7 +24,7 @@ def arguments(doc, header, renderer=Argument, item_class=DefinitionItem): A renderer instance to render the items. item_class : type - The item parser class to use. Default is :class:`~.DefinitionItem`. + The item parser class to use. Default is :class:`~.orDefinitionItem`. """ items = doc.extract_items(item_class) diff --git a/sectiondoc/sections/attributes.py b/sectiondoc/sections/attributes.py index 3a9fe84..1f31670 100644 --- a/sectiondoc/sections/attributes.py +++ b/sectiondoc/sections/attributes.py @@ -6,11 +6,11 @@ # Copyright (c) 2011-2014, Enthought, Inc. # All rights reserved. #----------------------------------------------------------------------------- -from sectiondoc.items import DefinitionItem +from sectiondoc.items import OrDefinitionItem from sectiondoc.renderers import Attribute -def attributes(doc, header, renderer=Attribute, item_class=DefinitionItem): +def attributes(doc, header, renderer=Attribute, item_class=OrDefinitionItem): """Render the attributes section to sphinx friendly format. """ diff --git a/sectiondoc/sections/item_list.py b/sectiondoc/sections/item_list.py index 6121a73..fbb1392 100644 --- a/sectiondoc/sections/item_list.py +++ b/sectiondoc/sections/item_list.py @@ -7,11 +7,11 @@ # All rights reserved. # ----------------------------------------------------------------------------- from sectiondoc.util import add_indent -from sectiondoc.items import DefinitionItem +from sectiondoc.items import OrDefinitionItem from sectiondoc.renderers import ListItem -def item_list(doc, header, renderer=ListItem, item_class=DefinitionItem): +def item_list(doc, header, renderer=ListItem, item_class=OrDefinitionItem): """ Render the section to sphinx friendly item list. Arguments @@ -26,7 +26,7 @@ def item_list(doc, header, renderer=ListItem, item_class=DefinitionItem): A renderer instance to render the items. item_class : type - The item parser class to use. Default is :class:`~.DefinitionItem`. + The item parser class to use. Default is :class:`~.OrDefinitionItem`. """ items = doc.extract_items(item_class) diff --git a/sectiondoc/styles/base_doc.py b/sectiondoc/styles/base_doc.py index 6c76a98..43a6df0 100644 --- a/sectiondoc/styles/base_doc.py +++ b/sectiondoc/styles/base_doc.py @@ -8,7 +8,7 @@ # ----------------------------------------------------------------------------- import re -from sectiondoc.items import DefinitionItem +from sectiondoc.items import OrDefinitionItem from sectiondoc.util import is_empty, get_indent from sectiondoc.sections import rubric @@ -155,7 +155,7 @@ def extract_items(self, item_class): List of the collected item instances of :class:`~.Item` type. """ - item_type = DefinitionItem if (item_class is None) else item_class + item_type = OrDefinitionItem if (item_class is None) else item_class is_item = item_type.is_item item_blocks = [] while (not self.eod) and \ diff --git a/sectiondoc/styles/old_style.py b/sectiondoc/styles/old_style.py index 42ad36d..aa35e91 100644 --- a/sectiondoc/styles/old_style.py +++ b/sectiondoc/styles/old_style.py @@ -1,7 +1,7 @@ from sectiondoc.sections import ( attributes, methods_table, notes_paragraph, item_list, arguments) from sectiondoc.renderers import Attribute, Method, Argument, ListItem -from sectiondoc.items import DefinitionItem, MethodItem +from sectiondoc.items import OrDefinitionItem, MethodItem from sectiondoc.styles.base_doc import BaseDoc from sectiondoc.styles.style import Style @@ -10,7 +10,7 @@ def class_section(lines): return BaseDoc( lines, sections={ - 'Attributes': (attributes, Attribute, DefinitionItem), + 'Attributes': (attributes, Attribute, OrDefinitionItem), 'Methods': (methods_table, Method, MethodItem), 'Notes': (notes_paragraph, None, None)}) @@ -19,11 +19,11 @@ def function_section(lines): return BaseDoc( lines, sections={ - 'Returns': (item_list, ListItem, DefinitionItem), - 'Arguments': (arguments, Argument, DefinitionItem), - 'Parameters': (arguments, Argument, DefinitionItem), - 'Raises': (item_list, ListItem, DefinitionItem), - 'Yields': (item_list, ListItem, DefinitionItem), + 'Returns': (item_list, ListItem, OrDefinitionItem), + 'Arguments': (arguments, Argument, OrDefinitionItem), + 'Parameters': (arguments, Argument, OrDefinitionItem), + 'Raises': (item_list, ListItem, OrDefinitionItem), + 'Yields': (item_list, ListItem, OrDefinitionItem), 'Notes': (notes_paragraph, None, None)}) diff --git a/sectiondoc/tests/test_definition_items.py b/sectiondoc/tests/test_definition_items.py index ccf2525..ad40873 100644 --- a/sectiondoc/tests/test_definition_items.py +++ b/sectiondoc/tests/test_definition_items.py @@ -1,67 +1,67 @@ -from sectiondoc.items import DefinitionItem, MethodItem, Item +from sectiondoc.items import OrDefinitionItem, MethodItem, Item from sectiondoc.renderers import ( Argument, Attribute, Definition, ListItem, Method, TableRow) from sectiondoc.tests._compat import unittest -class TestDefinitionItem(unittest.TestCase): +class TestOrDefinitionItem(unittest.TestCase): def setUp(self): self.maxDiff = None def test_is_item(self): - self.assertFalse(DefinitionItem.is_item("term")) - self.assertFalse(DefinitionItem.is_item("term ")) - self.assertTrue(DefinitionItem.is_item("term :")) - self.assertTrue(DefinitionItem.is_item("term : ")) - self.assertTrue(DefinitionItem.is_item("term : classifier")) - self.assertFalse(DefinitionItem.is_item(":term : classifier")) - self.assertFalse(DefinitionItem.is_item("term : classifier:")) + self.assertFalse(OrDefinitionItem.is_item("term")) + self.assertFalse(OrDefinitionItem.is_item("term ")) + self.assertTrue(OrDefinitionItem.is_item("term :")) + self.assertTrue(OrDefinitionItem.is_item("term : ")) + self.assertTrue(OrDefinitionItem.is_item("term : classifier")) + self.assertFalse(OrDefinitionItem.is_item(":term : classifier")) + self.assertFalse(OrDefinitionItem.is_item("term : classifier:")) # special cases header_with_object = 'component : class.component.instance' - self.assertTrue(DefinitionItem.is_item(header_with_object)) + self.assertTrue(OrDefinitionItem.is_item(header_with_object)) header_with_trait = 'properies : Dict(Str, Any)' - self.assertTrue(DefinitionItem.is_item(header_with_trait)) + self.assertTrue(OrDefinitionItem.is_item(header_with_trait)) header_with_or = 'item : ModelIndex or None' - self.assertTrue(DefinitionItem.is_item(header_with_or)) + self.assertTrue(OrDefinitionItem.is_item(header_with_or)) def test_parse(self): - item = DefinitionItem.parse(['term', ' Definition.']) - self.assertEqual(item, DefinitionItem('term', [], ['Definition.'])) + item = OrDefinitionItem.parse(['term', ' Definition.']) + self.assertEqual(item, OrDefinitionItem('term', [], ['Definition.'])) - item = DefinitionItem.parse([ + item = OrDefinitionItem.parse([ 'term', ' Definition, paragraph 1.', '', ' Definition, paragraph 2.']) self.assertEqual( item, - DefinitionItem( + OrDefinitionItem( 'term', [], [ 'Definition, paragraph 1.', '', 'Definition, paragraph 2.'])) - item = DefinitionItem.parse(['term :', ' Definition.']) - self.assertEqual(item, DefinitionItem('term', [], ['Definition.'])) + item = OrDefinitionItem.parse(['term :', ' Definition.']) + self.assertEqual(item, OrDefinitionItem('term', [], ['Definition.'])) - item = DefinitionItem.parse(['term : classifier', ' Definition.']) + item = OrDefinitionItem.parse(['term : classifier', ' Definition.']) self.assertEqual( - item, DefinitionItem('term', ['classifier'], ['Definition.'])) + item, OrDefinitionItem('term', ['classifier'], ['Definition.'])) - item = DefinitionItem.parse( + item = OrDefinitionItem.parse( ['term : classifier or classifier', ' Definition.']) self.assertEqual( item, - DefinitionItem( + OrDefinitionItem( 'term', ['classifier', 'classifier'], ['Definition.'])) - item = DefinitionItem.parse( + item = OrDefinitionItem.parse( ['term : classifier', ' Block.', ' Definition.']) self.assertEqual( - item, DefinitionItem( + item, OrDefinitionItem( 'term', ['classifier'], ['Block.', ' Definition.'])) From f7b83437032a180a2f3957fa53847325907d0268 Mon Sep 17 00:00:00 2001 From: Ioannis Tziakos Date: Wed, 11 Feb 2015 20:25:14 +0000 Subject: [PATCH 40/63] Update __init__.py --- sectiondoc/items/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sectiondoc/items/__init__.py b/sectiondoc/items/__init__.py index afca45f..b403aec 100644 --- a/sectiondoc/items/__init__.py +++ b/sectiondoc/items/__init__.py @@ -4,5 +4,5 @@ 'Item'] from sectiondoc.items.item import Item -from sectiondoc.items.definition_item import OrDefinitionItem +from sectiondoc.items.or_definition_item import OrDefinitionItem from sectiondoc.items.method_item import MethodItem From 0d6ab14d481e8d33ac044334420698a4238b66f9 Mon Sep 17 00:00:00 2001 From: Ioannis Tziakos Date: Fri, 27 Feb 2015 21:44:30 +0000 Subject: [PATCH 41/63] update docstring --- sectiondoc/renderers/definition.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sectiondoc/renderers/definition.py b/sectiondoc/renderers/definition.py index 9134493..9be24d4 100644 --- a/sectiondoc/renderers/definition.py +++ b/sectiondoc/renderers/definition.py @@ -7,18 +7,18 @@ class Definition(Renderer): def to_rst(self, **kwards): """ Outputs the Item in sphinx friendly rst. - The method renders the definition into a list of lines that follow - the rst markup of a sphinx definition item:: + The method renders the ``definition`` into a list of lines that + follow the rst markup of a sphinx definition item:: () -- - Subclasses will usually override the method to provide custom made - behaviour. However the signature of the method should hold only + Subclasses will usually override the method to provide custom + behaviour. However, the signature of the method should hold only keyword arguments which have default values. The keyword arguments - can be used to pass addition rendering information to subclasses. + can be used to pass additional rendering information to subclasses. Returns ------- From 6c1542c655070e004c3644efb1da3d45379820b2 Mon Sep 17 00:00:00 2001 From: Ioannis Tziakos Date: Fri, 27 Feb 2015 22:13:50 +0000 Subject: [PATCH 42/63] update docstrings --- sectiondoc/styles/base_doc.py | 101 ++++++++++++++++------------------ 1 file changed, 48 insertions(+), 53 deletions(-) diff --git a/sectiondoc/styles/base_doc.py b/sectiondoc/styles/base_doc.py index 43a6df0..db75fb6 100644 --- a/sectiondoc/styles/base_doc.py +++ b/sectiondoc/styles/base_doc.py @@ -17,52 +17,49 @@ class BaseDoc(object): - """Base abstract docstring refactoring class. + """ Base docstring rendering class. The class' main purpose is to parse the docstring and find the - sections that need to be refactored. Subclasses should provide - the methods responsible for refactoring the sections. + sections that need to be refactored. The operation take place in + two stages: + + - The class is instanciated with the appropriate section renderers + - The ``parse`` method is called to parse and render the sections + inplace. Attributes ---------- docstring : list - A list of strings (lines) that holds docstrings + A list of strings (lines) that holds docstrings. The lines are changed + inplace. index : int - The current zero-based line number of the docstring that is currently + The zero-based line number of the docstring that is currently processed. - headers : dict - The sections that the class will refactor. Each entry in the - dictionary should have as key the name of the section in the - form that it appears in the docstrings. The value should be - the postfix of the method, in the subclasses, that is - responsible for refactoring (e.g. {'Methods': 'method'}). - - BaseDoc also provides a number of methods that operate on the docstring to - help with the refactoring. This is necessary because the docstring has to - change inplace and thus it is better to live the docstring manipulation to - the class methods instead of accessing the lines directly. + sections : dict + The sections that will be detected and rendered. The dictionary + maps the section headers for detection to a tuple containing + the section rendering function and optional values for the item + renderer and parser. """ def __init__(self, lines, sections=None): """ Initialize the class - The method setups the class attributes and starts parsing the - docstring to find and refactor the sections. - Arguments --------- lines : list of strings The docstring to refactor - headers : dict - The sections for which the class has custom refactor methods. - Each entry in the dictionary should have as key the name of - the section in the form that it appears in the docstrings. - The value should be a callable, which be responsible for rendering - the header (e.g. {'Methods': method}). + sections : dict + The sections that will be detected and rendered. The dictionary + maps the section headers for detection to a tuple containing + the section rendering function and optional values for the item + renderer and parser. If on section rendering information is + provided the default behaviour of the class is to render + every section using the rubric rendering function. """ try: @@ -76,7 +73,7 @@ def parse(self): """ Parse the docstring. The docstring is parsed for sections. If a section is found then - the corresponding refactoring method is called. + the corresponding section rendering method is called. """ self.index = 0 @@ -84,16 +81,16 @@ def parse(self): while not self.eod: section = self.is_section() if len(section) > 0: - self._refactor(section) + self._render(section) else: self.index += 1 self.seek_to_next_non_empty_line() - def _refactor(self, section): - """Call the heading refactor method. + def _render(self, section): + """ Call the section rendering function. - The header is removed from the docstring and the docstring - refactoring is dispatched to the appropriate refactoring method. + The header is removed from the docstring and the appropriate + rendering function is executed. """ self.remove_lines(self.index, 2) # Remove header @@ -103,21 +100,20 @@ def _refactor(self, section): lines = method(self, section, renderer, item_class) self.insert_and_move(lines, self.index) - def extract_items(self, item_class): - """ Extract the definition items from a docstring. + def extract_items(self, item_type): + """ Extract the section items from a docstring. Parse the items in the description of a section into items of the - provided class time. Given an Item or a subclass defined by - the ``item_class`` parameter. The method starts at the current index - position and checks if in the next two lines a valid header exists. - If successful, the lines that belong to the item description - block (i.e. item header + item body) are popped out from the docstring - and passed to the ``item_class`` parser to get an instance of - ``item_class``. - - The process is repeated until there is no compatible ``item_class`` - found or we run out of docstring lines, The collected item class - instances are return. + provided itme type. The method starts at the current line index + position and checks if in the next two lines contain a valid item of + the desired type. If successful, the lines that belong to the item + description block (i.e. item header + item body) are popped out from + the docstring and passed to the ``item_type.parser`` class method to + get a new instance of ``item_type``. + + The process is repeated until there are no compatible ``item_type`` + items found in the section or we run out of docstring lines, + The collected item instances are returned The exit conditions allow for two valid section item layouts: @@ -143,15 +139,14 @@ def extract_items(self, item_class): Arguments --------- - item_class : Item - An Item or a subclass. This argument is used to check + item_type : Item + An Item type or a subclass. This argument is used to check if a line in the docstring is a valid item and to parse the individual list items in the section. - Returns ------- - parameters : list + items : list List of the collected item instances of :class:`~.Item` type. """ @@ -222,7 +217,7 @@ def is_section(self): return '' def insert_lines(self, lines, index): - """ Insert refactored lines. + """ Insert lines in the docstring. Arguments --------- @@ -238,7 +233,7 @@ def insert_lines(self, lines, index): docstring.insert(index, line) def insert_and_move(self, lines, index): - """ Insert refactored lines and move current index to the end. + """ Insert lines and move the current index to the end. """ self.insert_lines(lines, index) @@ -296,9 +291,9 @@ def bookmark(self): def goto_bookmark(self, bookmark_index=-1): """ Move to bookmark. - Move the current index to the docstring line given my the - ``self.bookmarks[bookmark_index]`` and remove it from the bookmark - list. Default value will pop the last entry. + Move the current index to the docstring line given by the + ``self.bookmarks[bookmark_index]`` and remove it from the + bookmark list. Default value will pop the last entry. Returns ------- From 1c44f5f04f0b4754713d283aab0c2743b09d43cf Mon Sep 17 00:00:00 2001 From: Ioannis Tziakos Date: Fri, 27 Feb 2015 23:12:31 +0000 Subject: [PATCH 43/63] update and rename the BaseDoc -> DocRender --- sectiondoc/styles/__init__.py | 4 ++-- .../styles/{base_doc.py => doc_render.py} | 22 +++++++++---------- sectiondoc/styles/old_style.py | 6 ++--- sectiondoc/tests/test_base_doc.py | 8 +++---- 4 files changed, 20 insertions(+), 20 deletions(-) rename sectiondoc/styles/{base_doc.py => doc_render.py} (97%) diff --git a/sectiondoc/styles/__init__.py b/sectiondoc/styles/__init__.py index 34c099b..fd69655 100644 --- a/sectiondoc/styles/__init__.py +++ b/sectiondoc/styles/__init__.py @@ -1,6 +1,6 @@ __all__ = [ 'Style', - 'BaseDoc'] + 'DocRender'] from sectiondoc.styles.style import Style -from sectiondoc.styles.base_doc import BaseDoc +from sectiondoc.styles.doc_render import DocRender diff --git a/sectiondoc/styles/base_doc.py b/sectiondoc/styles/doc_render.py similarity index 97% rename from sectiondoc/styles/base_doc.py rename to sectiondoc/styles/doc_render.py index db75fb6..6e8f3d9 100644 --- a/sectiondoc/styles/base_doc.py +++ b/sectiondoc/styles/doc_render.py @@ -16,13 +16,13 @@ underline_regex = re.compile(r'\s*\S+\s*\Z') -class BaseDoc(object): - """ Base docstring rendering class. +class DocRender(object): + """ Docstring rendering class. The class' main purpose is to parse the docstring and find the sections that need to be refactored. The operation take place in two stages: - + - The class is instanciated with the appropriate section renderers - The ``parse`` method is called to parse and render the sections inplace. @@ -57,7 +57,7 @@ def __init__(self, lines, sections=None): The sections that will be detected and rendered. The dictionary maps the section headers for detection to a tuple containing the section rendering function and optional values for the item - renderer and parser. If on section rendering information is + renderer and parser. If on section rendering information is provided the default behaviour of the class is to render every section using the rubric rendering function. @@ -105,14 +105,14 @@ def extract_items(self, item_type): Parse the items in the description of a section into items of the provided itme type. The method starts at the current line index - position and checks if in the next two lines contain a valid item of - the desired type. If successful, the lines that belong to the item - description block (i.e. item header + item body) are popped out from - the docstring and passed to the ``item_type.parser`` class method to + position and checks if in the next two lines contain a valid item of + the desired type. If successful, the lines that belong to the item + description block (i.e. item header + item body) are popped out from + the docstring and passed to the ``item_type.parser`` class method to get a new instance of ``item_type``. The process is repeated until there are no compatible ``item_type`` - items found in the section or we run out of docstring lines, + items found in the section or we run out of docstring lines, The collected item instances are returned The exit conditions allow for two valid section item layouts: @@ -150,7 +150,7 @@ def extract_items(self, item_type): List of the collected item instances of :class:`~.Item` type. """ - item_type = OrDefinitionItem if (item_class is None) else item_class + item_type = OrDefinitionItem if (item_type is None) else item_type is_item = item_type.is_item item_blocks = [] while (not self.eod) and \ @@ -292,7 +292,7 @@ def goto_bookmark(self, bookmark_index=-1): """ Move to bookmark. Move the current index to the docstring line given by the - ``self.bookmarks[bookmark_index]`` and remove it from the + ``self.bookmarks[bookmark_index]`` and remove it from the bookmark list. Default value will pop the last entry. Returns diff --git a/sectiondoc/styles/old_style.py b/sectiondoc/styles/old_style.py index aa35e91..c255224 100644 --- a/sectiondoc/styles/old_style.py +++ b/sectiondoc/styles/old_style.py @@ -2,12 +2,12 @@ attributes, methods_table, notes_paragraph, item_list, arguments) from sectiondoc.renderers import Attribute, Method, Argument, ListItem from sectiondoc.items import OrDefinitionItem, MethodItem -from sectiondoc.styles.base_doc import BaseDoc +from sectiondoc.styles.doc_render import DocRender from sectiondoc.styles.style import Style def class_section(lines): - return BaseDoc( + return DocRender( lines, sections={ 'Attributes': (attributes, Attribute, OrDefinitionItem), @@ -16,7 +16,7 @@ def class_section(lines): def function_section(lines): - return BaseDoc( + return DocRender( lines, sections={ 'Returns': (item_list, ListItem, OrDefinitionItem), diff --git a/sectiondoc/tests/test_base_doc.py b/sectiondoc/tests/test_base_doc.py index 4272528..a60f344 100644 --- a/sectiondoc/tests/test_base_doc.py +++ b/sectiondoc/tests/test_base_doc.py @@ -1,8 +1,8 @@ -from sectiondoc.styles import BaseDoc +from sectiondoc.styles import DocRender from sectiondoc.tests._compat import unittest -class TestBaseDoc(unittest.TestCase): +class TestDocRender(unittest.TestCase): def setUp(self): self.maxDiff = None @@ -24,7 +24,7 @@ def test_refactor_header(self): This is just some sample text. """ docstring_lines = docstring.splitlines() - base_doc = BaseDoc(docstring_lines) + base_doc = DocRender(docstring_lines) base_doc.parse() output = '\n'.join(docstring_lines) + '\n' self.assertMultiLineEqual(rst, output) @@ -47,7 +47,7 @@ def test_refactor_complex_header(self): This is just some sample text. """ docstring_lines = docstring.splitlines() - base_doc = BaseDoc(docstring_lines) + base_doc = DocRender(docstring_lines) base_doc.parse() output = '\n'.join(docstring_lines) + '\n' self.assertMultiLineEqual(rst, output) From 12deb9311f0289d7926cc8bd79ea485dee8f8c19 Mon Sep 17 00:00:00 2001 From: Ioannis Tziakos Date: Fri, 27 Feb 2015 23:12:55 +0000 Subject: [PATCH 44/63] update docstrings --- sectiondoc/items/item.py | 12 ++++++------ sectiondoc/items/method_item.py | 30 ++++++++++++++++++------------ sectiondoc/items/util.py | 4 ++-- sectiondoc/renderers/attribute.py | 2 +- sectiondoc/renderers/definition.py | 10 ++++------ sectiondoc/renderers/list_item.py | 2 +- sectiondoc/renderers/renderer.py | 2 +- 7 files changed, 33 insertions(+), 29 deletions(-) diff --git a/sectiondoc/items/item.py b/sectiondoc/items/item.py index bdca593..1b0cd63 100644 --- a/sectiondoc/items/item.py +++ b/sectiondoc/items/item.py @@ -3,9 +3,9 @@ class Item(namedtuple('Item', ['term', 'classifiers', 'definition'])): - """ A docstring item. + """ A section item. - The Item class is responsible to check, parse and refactor a docstring + The Item class is responsible to check, parse and render a docstring item into sphinx friendly rst. Format diagram:: @@ -18,7 +18,7 @@ class Item(namedtuple('Item', ['term', 'classifiers', 'definition'])): +--------------------------------------------------+ - Depending only the type of the list item the header is split into a + Depending only in the type of the list item the header is split into a term and one or more classifiers. Attributes @@ -31,7 +31,7 @@ class Item(namedtuple('Item', ['term', 'classifiers', 'definition'])): of an argument or the signature of a function. definition : list - The list of strings that holds the description the definition item. + The list of strings that holds the description of the definition item. """ @@ -58,14 +58,14 @@ def is_item(cls, line): """ Check if the line is describing an item. The method is used to check that a line is following the expected - format for the term and classifiers attributes. + format for the `term` and `classifiers` attributes. """ raise NotImplementedError() @classmethod def parse(cls, lines): - """Parse a definition item from a set of lines. + """ Parse a definition item from a set of lines. The class method parses the item from the list of docstring lines and produces a Item with the term, classifier and the definition. diff --git a/sectiondoc/items/method_item.py b/sectiondoc/items/method_item.py index 535fb97..3ec01c3 100644 --- a/sectiondoc/items/method_item.py +++ b/sectiondoc/items/method_item.py @@ -4,7 +4,7 @@ class MethodItem(Item): - """ A MethodItem that knows how to parse methods + """ A MethodItem for method descriptions. """ @@ -16,27 +16,33 @@ def signature(self): def is_item(cls, line): """ Check if the definition header is a function signature. + The expected header has the following format:: + + +------------------------------+ + | term "(" [ classifier ] ")" | + +------------------------------+ + """ return function_regex.match(line) @classmethod def parse(cls, lines): - """Parse a method definition item from a set of lines. + """ Parse a method definition item from a set of lines. - The class method parses the method signature and definition from the - list of docstring lines and produces a MethodItem where the term - is the method name and the classifier is arguments + Parse the method signature and definition from the list of docstring + lines and produce a MethodItem where the `term` is the method name and + the classifier is arguments. .. note:: The global indention in the definition lines is striped - The method definition item is assumed to be as follows:: + The format of the method definition item is expected to be as follows:: - +------------------------------+ - | term "(" [ classifier ] ")" | - +--+---------------------------+---+ - | definition | - | (body elements)+ | - +--------------------- ---------+ + +------------------------------+ + | term "(" [ classifier ] ")" | + +--+---------------------------+---+ + | definition | + | (body elements)+ | + +-------------------------------+ Arguments --------- diff --git a/sectiondoc/items/util.py b/sectiondoc/items/util.py index 3590e16..0bf2047 100644 --- a/sectiondoc/items/util.py +++ b/sectiondoc/items/util.py @@ -4,7 +4,7 @@ def max_attribute_length(items, attr): Arguments --------- items : list - The list of the Item instances (or subclasses). + The list of Item instances. attr : str Attribute to look at. @@ -23,7 +23,7 @@ def max_attribute_index(items, attr): Arguments --------- items : list - The list of the Items (or subclasses). + The list of Item instances. attr : str Attribute to look at. diff --git a/sectiondoc/renderers/attribute.py b/sectiondoc/renderers/attribute.py index 82c0ced..8a045d0 100644 --- a/sectiondoc/renderers/attribute.py +++ b/sectiondoc/renderers/attribute.py @@ -3,7 +3,7 @@ class Attribute(Renderer): - """ Definition that renders the rst output using the attribute directive. + """ Render an Item instance using the sphinx attribute directive. """ diff --git a/sectiondoc/renderers/definition.py b/sectiondoc/renderers/definition.py index 9be24d4..86e0fc8 100644 --- a/sectiondoc/renderers/definition.py +++ b/sectiondoc/renderers/definition.py @@ -3,11 +3,14 @@ class Definition(Renderer): + """ Render an Item instance as a sphinx definition term + + """ def to_rst(self, **kwards): """ Outputs the Item in sphinx friendly rst. - The method renders the ``definition`` into a list of lines that + The method renders the `definition` into a list of lines that follow the rst markup of a sphinx definition item:: @@ -15,11 +18,6 @@ def to_rst(self, **kwards): () -- - Subclasses will usually override the method to provide custom - behaviour. However, the signature of the method should hold only - keyword arguments which have default values. The keyword arguments - can be used to pass additional rendering information to subclasses. - Returns ------- lines : list diff --git a/sectiondoc/renderers/list_item.py b/sectiondoc/renderers/list_item.py index 5ae62fa..5e89c05 100644 --- a/sectiondoc/renderers/list_item.py +++ b/sectiondoc/renderers/list_item.py @@ -3,7 +3,7 @@ class ListItem(Renderer): - """ A definition item that is rendered as an ordered/unordered list + """ Rendered an item instance as an ordered/unordered list item. """ diff --git a/sectiondoc/renderers/renderer.py b/sectiondoc/renderers/renderer.py index 18855be..b70b1ae 100644 --- a/sectiondoc/renderers/renderer.py +++ b/sectiondoc/renderers/renderer.py @@ -10,7 +10,7 @@ def __init__(self, item=None): @abc.abstractmethod def to_rst(self, **kwards): - """ Outputs the definition item in sphinx friendly rst. + """ Outputs the `item` in sphinx friendly rst. The method renders the passed into a list of lines that follow the rst markup. From 637aafa22d5548aacd351edac7b989e7401a7ad1 Mon Sep 17 00:00:00 2001 From: Ioannis Tziakos Date: Fri, 27 Feb 2015 23:18:01 +0000 Subject: [PATCH 45/63] fix typo --- sectiondoc/items/or_definition_item.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sectiondoc/items/or_definition_item.py b/sectiondoc/items/or_definition_item.py index 58b9995..6088534 100644 --- a/sectiondoc/items/or_definition_item.py +++ b/sectiondoc/items/or_definition_item.py @@ -93,7 +93,7 @@ def parse(cls, lines): docstring lines of the definition without any empty lines before or after. - Return + Returns ------- definition : OrDefinitionItem From 3adc265c85e2c371b76a01ec3de88093f92a65ce Mon Sep 17 00:00:00 2001 From: Ioannis Tziakos Date: Sat, 28 Feb 2015 01:35:07 +0000 Subject: [PATCH 46/63] fix docstrings --- sectiondoc/sections/arguments.py | 2 +- sectiondoc/sections/item_list.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sectiondoc/sections/arguments.py b/sectiondoc/sections/arguments.py index 78d9f71..411d3d5 100644 --- a/sectiondoc/sections/arguments.py +++ b/sectiondoc/sections/arguments.py @@ -15,7 +15,7 @@ def arguments(doc, header, renderer=Argument, item_class=OrDefinitionItem): Arguments --------- - doc : BaseDoc + doc : DocRender The docstring container. header : string This parameter is ignored in this method. diff --git a/sectiondoc/sections/item_list.py b/sectiondoc/sections/item_list.py index fbb1392..b0e6d6f 100644 --- a/sectiondoc/sections/item_list.py +++ b/sectiondoc/sections/item_list.py @@ -16,7 +16,7 @@ def item_list(doc, header, renderer=ListItem, item_class=OrDefinitionItem): Arguments --------- - doc : BaseDoc + doc : DocRender The docstring container. header : str From 853fefef09a27add1d98492cedefb6c651a1c969 Mon Sep 17 00:00:00 2001 From: Ioannis Tziakos Date: Sat, 28 Feb 2015 01:35:27 +0000 Subject: [PATCH 47/63] update README.rst --- README.rst | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/README.rst b/README.rst index 1b37d3b..1b9d61f 100644 --- a/README.rst +++ b/README.rst @@ -20,9 +20,11 @@ Key aims of **sectiondoc** are: - Do not change the order of sections. - Allow sphinx directives between (and inside) section blocks. + - Custom rendering styles - Easier to debug (native support for debugging) and extend (future versions). + Repository ---------- @@ -35,14 +37,26 @@ using:: Installation ------------ -1. Install ``sectiondoc`` from pypi using pip:: +Install ``sectiondoc`` from pypi using pip:: $ pip install sectiondoc -2. Add sectiondoc to the extensions variable of your sphinx ``conf.py``:: +Usage +----- + +Add sectiondoc to the extensions variable of your sphinx ``conf.py``:: extensions = [ ..., 'sectiondoc', ..., ] + + +Styles can be selected by referencing the module they are defined at:: + + extensions = [ + ..., + 'sectiondoc.styles.old_style', + ..., + ] From 377bced27f799e61aaaf5ba07839c6990ead5b34 Mon Sep 17 00:00:00 2001 From: Ioannis Tziakos Date: Sat, 28 Feb 2015 01:35:58 +0000 Subject: [PATCH 48/63] remove old documentation --- docs/source/architecture.rst | 58 ---------------- docs/source/components.rst | 82 ----------------------- docs/source/extending.rst | 43 ------------ docs/source/usage.rst | 124 ----------------------------------- 4 files changed, 307 deletions(-) delete mode 100644 docs/source/architecture.rst delete mode 100644 docs/source/components.rst delete mode 100644 docs/source/extending.rst delete mode 100644 docs/source/usage.rst diff --git a/docs/source/architecture.rst b/docs/source/architecture.rst deleted file mode 100644 index 9416b60..0000000 --- a/docs/source/architecture.rst +++ /dev/null @@ -1,58 +0,0 @@ -Architecture -************ - -The are three different parts in the pipeline of **refactordoc**. - -(i) The autodoc event hook and object refactoring dispatch; -(ii) The docstring section detection and method dispatching and; -(iii) The second component parsing and refactor of the detected sections; - -The entry function -################## - -The entry function ``setup`` is located in the ``__init__.py`` file. Through -the setup function refactor doc is loading the autodoc extention and hooks -the :func:`~refactordoc.refactor_docstring` function to the -``autodoc-process-docstring`` event. - -The :func:`~refactordoc.refactor_docstring` function receives the list of -lines that compose the dostrings and based on the ``object`` initializes a -new class instance to do the main work. The final item in the process is to -execute the parse method of the created class. - -The refactoring class -##################### - -The refactoring classes are responsible for doing the actual work. These classes -are derived from the :class:`~refactordoc.BaseDoc` class. After initialization -refactoring takes place by executing the :meth:`~refactordoc.BaseDoc.parse` -method. The method looks for section headers by parsing the lines of the -docstring. For each section that is discovered the -:meth:`~refactordoc.BaseDoc._refactor` method is called with the name of -the discovered section to dispatch processing to the associated refactoring -method. The dispatcher constructs the name of the refactoring function by -looking up the ``headers`` dictionary for a key equal to the header string -found. If a key is found then the refactoring method name is composed from the -prefix ``_header_`` and the retrieved value. If a key with the header name is -not found then the default :meth:`~refactordoc.BaseDoc._refactor_header` is -used. - -The refactoring methods -####################### - -Depending on the section the associated method parses and extracts the section -definition block using the provided by the :class:`~refactordoc.BaseDoc` class -utility methods. - -When the definition block is a paragraph the -:meth:`~refactordoc.BaseDoc.extract_paragraph` will return the paragraph for -further processing. When the definition block is a list of definition items. -These items are parsed and extracted (i.e removed from the docstring) with the -help of the :meth:`~refactordoc.BaseDoc.extract_items` and a -:class:`~refactordoc.defintion_items.DefintionItem` (or a subclass). The list -of items that is returned holds all the information to produce a sequence of -sphinx friendly rst. - -After collecting the information in the section the refactoring method is -ready to produce the updated rst and return a list of lines to the -dispatching method so that they can be re-inserted in the docstring. diff --git a/docs/source/components.rst b/docs/source/components.rst deleted file mode 100644 index 7ba23f4..0000000 --- a/docs/source/components.rst +++ /dev/null @@ -1,82 +0,0 @@ -Section components -****************** - -Each section is composed into a number of components these components are -described below. - -Section header -^^^^^^^^^^^^^^ - -The start of the section is designated with the section header, which is -a standard rst header. The underline is however restricted to using only -``-`` or ``=``:: - - Section - ------- - -and:: - - Section - ======= - -Each section header is followed by a section definition block which can be -either a list of items or one or more definition items. In general, The number -and format of these items depends on the type of section that is currently -parsed. - -Definition list -^^^^^^^^^^^^^^^ - -Two of the most common formats are described bellow: - -The *standard definition item* format is based on the item of a variation -of the definition list item as it defined in `restructured text -`_ - -:: - - +-------------------------------------------------+ - | term [ " : " classifier [ " or " classifier] ] | - +--+----------------------------------------------+---+ - | definition | - | (body elements)+ | - +--------------------------------------------------+ - -where ```` is the single word (e.g. my_field) and -```` is a indented block of rst code. The item header can -optionally include the ```` attribute. This type of item is -commonly used to describe class attributes and function arguments. In this -documentation we will refer to this format as `variable` item to avoid -confusion with sphinx directives. - -A similar definition item format is the method item where the item header is -composed of a function signature:: - - +------------------------------+ - | term "(" [ classifier ] ")" | - +--+---------------------------+---+ - | definition | - | (body elements)+ | - +-------------------------------+ - -This item is commonly used to describe provided functions (or methods) and -thus is referred to as the `method item`. The -```` in this case is a list of arguments as it appears in the -signature and ```` the method summary (one sentence). All -`method` fields should be separated by a single empty line. - -Paragraph -^^^^^^^^^ - -Instead of a list of items the section can contain a paragraph:: - - +-------------------------+ - | definition | - | (body elements)+ | - +-------------------------+ - -This type of field is used for information sections like ``Notes``. - -.. note:: Currently the ```` is a single unindented block with no - empty lines. However, this will probably should change in future - versions of RefactorDoc. diff --git a/docs/source/extending.rst b/docs/source/extending.rst deleted file mode 100644 index 089401f..0000000 --- a/docs/source/extending.rst +++ /dev/null @@ -1,43 +0,0 @@ -Building your own suite -####################### - -While the default refactoring suite is enough for most cases. The user -might need to extent the section repertoire, process other object -types, allow more freedom in defining the definition list or restrict -the docstring style to improve consinstancy through his code. - -.. warning:: All the methods below require to change the refactordoc code and - even thought the changes might be small it is not considered the best way - since updating refactordoc becomes non-trivial. Future version will remove - this shortcoming. - - -Adding sections -############### - -New sections to be refactored can be simply added to the ``headers`` dictionary -when an appropriate refactoring method exists. For example in the default -suite that is shipped with refactordoc the -:class:`~refactordoc.function_doc.FunctionDoc` class sets the `Returns` -`Raises` and `Yields` section to use the `_refactor_as_item_list` method -in the class:: - - if headers is None: - headers = {'Returns': 'as_item_list', 'Arguments': 'arguments', - 'Parameters': 'arguments', 'Raises': 'as_item_list', - 'Yields': 'as_item_list', 'Notes':'notes'} - - -When such a method does not - -exist then the user has to augment the related class with that will -parse and extract the section definition block(s) and return the -refactored lines as a list of strings to replace the section in the -docstring. The signature of the method should be -``_header_(self, header)`` - -Where ```` is the value in the ``headers`` that corresponds to the -``header`` string that is found in the docstring. - - -.. note:: More to come diff --git a/docs/source/usage.rst b/docs/source/usage.rst deleted file mode 100644 index b2dbdc7..0000000 --- a/docs/source/usage.rst +++ /dev/null @@ -1,124 +0,0 @@ -Default refactoring -******************* - -The base implementation of Sectiondoc provides refactoring for class and -function doc-strings. A number of known (i.e. predefined) sections are processed -by the ClassDoc and FunctionDoc classes and all unknown sections are re-factored -using the ``.. rubric::`` directive by default. - -For class objects the **default style** re-factors three types of sections: - -========== ================================ ========== === ==================== -Heading Description Item Max Rendered as -========== ================================ ========== === ==================== -Methods Class methods with summary MethodItem -- Table with links to - the method -Attributes Class attributes and their usage Attribute -- Sphinx attributes -Notes Useful notes paragraph 1 Note admonition -========== ================================ ========== === ==================== - -For functions the **default style** re-factors four types of sections: - -========= =========================== ============ === ===================== -Heading Description Item Max Rendered as -========= =========================== ============ === ===================== -Arguments function arguments and type ArgumentItem -- Parameters field list -Returns Return value ListItem -- Unordered list -Raises Raised exceptions ListItem -- Unordered list -Notes Useful notes paragraph 1 Note admonition -========= =========================== ============ === ===================== - - -Usage rules -*********** - -To be able to re-factor the sections properly the doc-strings should follow -theses rules: - -.. admonition:: Rules - - - Between the section header and the first section item there can be at - most only one empty line. - - - The end of the section is designated by one of the following: - - - The allowed number of items by the section has been parsed. - - Two consecutive empty lines are found. - - The line is not identified as a possible header of the section item. - - .. hint:: Please check the doc-string of the specific definition item - class to have more information regarding the valid item header - format. - -Examples -******** - -Argument sections -^^^^^^^^^^^^^^^^^ -:: - - Arguments - --------- - new_lines : list - The list of lines to insert - - index : int - Index to start the insertion - """ - -.. automethod:: sectiondoc.base_doc.BaseDoc.insert_lines - :noindex: - - -Attribute sections ------------------- -:: - - Attributes - ---------- - docstring : list - A list of strings (lines) that holds doc-strings - - index : int - The current zero-based line number of the doc-string that is currently - processed. - - headers : dict - The sections that the class re-factors. Each entry in the - dictionary should have as key the name of the section in the - form that it appears in the doc-strings. The value should be - the postfix of the method, in the subclasses, that is - responsible for refactoring (e.g. {'Methods': 'method'}). - -.. autoclass:: sectiondoc.base_doc.BaseDoc - :noindex: - :no-members: - -Returns sections ----------------- -:: - - Returns - ------- - result : list - A new list of left striped strings. - -.. autofunction:: sectiondoc.util.remove_indent - :noindex: - -Raises section --------------- - -.. todo:: Add example - - -Notes ------ -:: - - Notes - ----- - Empty strings are not changed. - -.. autofunction:: sectiondoc.util.add_indent - :noindex: From 34ec491435d1b4a1411d29fffb58c8babd9fd50a Mon Sep 17 00:00:00 2001 From: Ioannis Tziakos Date: Sat, 28 Feb 2015 01:36:22 +0000 Subject: [PATCH 49/63] add documentation for the new design --- docs/source/old_style.rst | 124 ++++++++++++++++++++++++++++++++++++++ docs/source/rendering.rst | 52 ++++++++++++++++ docs/source/styles.rst | 52 ++++++++++++++++ 3 files changed, 228 insertions(+) create mode 100644 docs/source/old_style.rst create mode 100644 docs/source/rendering.rst create mode 100644 docs/source/styles.rst diff --git a/docs/source/old_style.rst b/docs/source/old_style.rst new file mode 100644 index 0000000..bc4778d --- /dev/null +++ b/docs/source/old_style.rst @@ -0,0 +1,124 @@ +Old Style +######### + +The base implementation of Sectiondoc provides rendering for class and +function/method doc-strings. A number of known (i.e. predefined) sections are +processed by the :func:`~.function_section` and :func:`~FunctionDoc` classes +and all unknown sections are rendered using the ``.. rubric::`` directive by +default. + +For class objects the **old style** renders three types of sections: + +========== ================================ ========== === ==================== +Heading Description Item Max Rendered as +========== ================================ ========== === ==================== +Methods Class methods with summary MethodItem -- Table with links to + the method +Attributes Class attributes and their usage Attribute -- Sphinx attributes +Notes Useful notes paragraph 1 Note admonition +========== ================================ ========== === ==================== + +For functions the **default style** re-factors four types of sections: + +========= =========================== ============ === ===================== +Heading Description Item Max Rendered as +========= =========================== ============ === ===================== +Arguments function arguments and type ArgumentItem -- Parameters field list +Returns Return value ListItem -- Unordered list +Raises Raised exceptions ListItem -- Unordered list +Yileds Yield values ListItem -- Unordered list +Notes Useful notes paragraph 1 Note admonition +========= =========================== ============ === ===================== + + +layout rules +************ + +To be able to detect and render the sections properly the docstrings should follow +the following rules: + +- Between the section header and the first section item there can be at + most only one empty line. + +- The end of the section is designated by one of the following: + + - The allowed number of items by the section has been parsed. + - Two consecutive empty lines are found. + - The line is not identified as a possible header of the section item. + + .. hint:: Please check the doc-string of the specific definition item + class to have more information regarding the valid item header + format. + +Examples +******** + +Argument sections +^^^^^^^^^^^^^^^^^ +:: + + Arguments + --------- + new_lines : list + The list of lines to insert + + index : int + Index to start the insertion + + +.. automethod:: sectiondoc.styles.doc_render.DocRender.insert_lines + :noindex: + + +Attribute sections +------------------ +:: + + Attributes + ---------- + docstring : list + A list of strings (lines) that holds docstrings. The lines are changed + inplace. + + index : int + The zero-based line number of the docstring that is currently + processed. + + sections : dict + The sections that will be detected and rendered. The dictionary + maps the section headers for detection to a tuple containing + the section rendering function and optional values for the item + renderer and parser. + +.. autoclass:: sectiondoc.styles.doc_render.DocRender + :noindex: + :no-members: + +Returns sections +---------------- +:: + + Returns + ------- + result : list + A new list of left striped strings. + +.. autofunction:: sectiondoc.util.remove_indent + :noindex: + +Raises section +-------------- + +.. todo:: Add example + + +Notes +----- +:: + + Notes + ----- + Empty strings are not changed. + +.. autofunction:: sectiondoc.util.add_indent + :noindex: diff --git a/docs/source/rendering.rst b/docs/source/rendering.rst new file mode 100644 index 0000000..18a30f3 --- /dev/null +++ b/docs/source/rendering.rst @@ -0,0 +1,52 @@ +Docstring rendering +******************* + +The are five different parts in the pipeline of **sectiondoc** docstring rendering. + +Style +##### + +The rendering :class:`~Style` is hooked with autodoc to receive the docstring +of the various objects and maps the objects types provided by autodoc to +:class:`~DocRender` instances which are responsible for rendering the provided +docstring. + +The DocRender +############# + +The DocRender is responsible for doing the actual work. At initialization +The class receives a dictionary mapping sections to a rendering function +and optional section item parsing and rendering classes. The actual +rendering starts by executing :meth:`~.DocRender.parse` to detect sections +in the docstring. For each section that is discovered the +:meth:`~.DocRender._render` is called with the name of the discovered section +to further dispatch processing to the associated section rendering function. +If a associated fuctntion to the section does not exist the default is to use +:func:`~.rubric`. + +Section rendering function +########################## + +The rendering fuctions is will use the utility methods of the the DocRender +instance to extract the section block. Depedending on the implementation +:meth:`~DocRender.extract_paragraph` will call to return the +paragraph for further processing or will call +:meth:`~DocRender.extract_items` to return the list of :class:`~.Item` +instances. After collecting the information in the section the rendering +function is ready to produce the updated rst using the appropriate +:class:`~.Renderer` and return a list of lines that will be re-inserted into +the docstring. + +Item +#### + +:class:`Item` instances contain the ``term``, ``classfier(s)`` and +``definition`` information of items in a section. Each :class:`Item` type +knows how to parse a set of lines grouping and filtering the information +ready to ber rendered inot sphinx friendly rst. + +Renderer +######## + +The :class:`Renderer` is used by the section renderer functions to render +a previously contructed :class:`Item` into sphinx friently rst. diff --git a/docs/source/styles.rst b/docs/source/styles.rst new file mode 100644 index 0000000..b309472 --- /dev/null +++ b/docs/source/styles.rst @@ -0,0 +1,52 @@ +Styles +------ + +SectionDoc comes with a number of predefined rendering styles + + +.. toctree:: + :maxdepth: 1 + + old_style + +.. note:: + + The default rendering style is currently :mod:`~.old_style` + + +Extending +--------- + +Custom styles can be created by instanciating a :class:`~.Style` +to map a :class:`~.DocRender` factory for each type of object sent +by autodoc. For example adding the following functions in you +conf.py defines a rendering style for functions and methods:: + + def function_section(lines): + return DocRender( + lines, + sections={ + 'Returns': (item_list, ListItem, OrDefinitionItem), + 'Arguments': (arguments, Argument, OrDefinitionItem), + 'Parameters': (arguments, Argument, OrDefinitionItem), + 'Raises': (item_list, ListItem, OrDefinitionItem), + 'Yields': (item_list, ListItem, OrDefinitionItem), + 'Notes': (notes_paragraph, None, None)}) + + + def setup(app): + style = Style({ + 'function': function_section, + 'method': function_section}) + app.setup_extension('sphinx.ext.autodoc') + app.connect('autodoc-process-docstring', style.render_docstring) + +Specifically the :class:`~.Style` instance will map the ``function`` +and ``method`` docstrings to the dostring rendering funtion +``function_section``. The :class:`~DocRender` will then detect the +sections ``Returns, Arguments, Parameters, Raises, Yields, Notes`` and +use the mapped combination of section rendering function, Item descreption +and item rendering type to render the detected section inplace. + +The rendering styles can be further extented by implemeting new Item, +Renderer instances or section rendering functions. From 42dea45c5dbdbafbd5f725196c276dfcf823225a Mon Sep 17 00:00:00 2001 From: Ioannis Tziakos Date: Sat, 28 Feb 2015 01:36:44 +0000 Subject: [PATCH 50/63] add styles to the api reference --- docs/source/reference.rst | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/source/reference.rst b/docs/source/reference.rst index 4c9a500..740ff80 100644 --- a/docs/source/reference.rst +++ b/docs/source/reference.rst @@ -7,7 +7,11 @@ The extension is separated into three main parts. .. default-role:: autolink -.. currentmodule:: sectiondoc +Styles +------ + +.. automodule:: sectiondoc.styles + :members: Sections From 41aa84ac7b2d79c020a6c3a9704ad8ef353c47e4 Mon Sep 17 00:00:00 2001 From: Ioannis Tziakos Date: Sat, 28 Feb 2015 01:37:01 +0000 Subject: [PATCH 51/63] update index toctree --- docs/source/index.rst | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/docs/source/index.rst b/docs/source/index.rst index d9374b7..ccfd3bf 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -8,10 +8,8 @@ Contents .. toctree:: :maxdepth: 2 - usage - architecture - components - extending + rendering + styles reference authors todo @@ -25,4 +23,3 @@ Indices and tables * :ref:`genindex` * :ref:`modindex` * :ref:`search` - From fd033c676d92d677b81ef252012b66c2e4ca4fc6 Mon Sep 17 00:00:00 2001 From: Ioannis Tziakos Date: Sat, 28 Feb 2015 01:40:16 +0000 Subject: [PATCH 52/63] use the travis dockers --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 276fe98..3b554fe 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,5 @@ language: python +sudo: False matrix: include: - python: "2.6" From 38421a0123098d190b3445ad6ea38bfac285898f Mon Sep 17 00:00:00 2001 From: Ioannis Tziakos Date: Mon, 2 Mar 2015 15:53:37 +0000 Subject: [PATCH 53/63] update conf.py to merge the class docstrings with the `__init__` method --- docs/source/conf.py | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/source/conf.py b/docs/source/conf.py index fa4086c..693b2f3 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -62,6 +62,7 @@ pygments_style = 'sphinx' autodoc_member_order = 'groupwise' +autoclass_content = 'both' # -- Options for HTML output -------------------------------------------------- From 507f434eda78df9e57ce1ad0401a6e4562eed596 Mon Sep 17 00:00:00 2001 From: Ioannis Tziakos Date: Mon, 2 Mar 2015 15:54:47 +0000 Subject: [PATCH 54/63] add support for parsing Arguments and Paramaters sections in class docstrings. --- docs/source/old_style.rst | 37 ++++++++++++++++++---------------- sectiondoc/styles/old_style.py | 2 ++ 2 files changed, 22 insertions(+), 17 deletions(-) diff --git a/docs/source/old_style.rst b/docs/source/old_style.rst index bc4778d..6558dc4 100644 --- a/docs/source/old_style.rst +++ b/docs/source/old_style.rst @@ -9,26 +9,29 @@ default. For class objects the **old style** renders three types of sections: -========== ================================ ========== === ==================== -Heading Description Item Max Rendered as -========== ================================ ========== === ==================== -Methods Class methods with summary MethodItem -- Table with links to - the method -Attributes Class attributes and their usage Attribute -- Sphinx attributes -Notes Useful notes paragraph 1 Note admonition -========== ================================ ========== === ==================== +========== ================================ ============ === ===================== +Heading Description Item Max Rendered as +========== ================================ ============ === ===================== +Methods Class methods with summary MethodItem -- Table with links to + the method +Attributes Class attributes and their usage Attribute -- Sphinx attributes +Arguments function arguments and type ArgumentItem -- Parameters field list +Parameters function arguments and type ArgumentItem -- Parameters field list +Notes Useful notes paragraph 1 Note admonition +========== ================================ ============ === ===================== For functions the **default style** re-factors four types of sections: -========= =========================== ============ === ===================== -Heading Description Item Max Rendered as -========= =========================== ============ === ===================== -Arguments function arguments and type ArgumentItem -- Parameters field list -Returns Return value ListItem -- Unordered list -Raises Raised exceptions ListItem -- Unordered list -Yileds Yield values ListItem -- Unordered list -Notes Useful notes paragraph 1 Note admonition -========= =========================== ============ === ===================== +========== =========================== ============ === ===================== +Heading Description Item Max Rendered as +========== =========================== ============ === ===================== +Arguments function arguments and type ArgumentItem -- Parameters field list +Parameters function arguments and type ArgumentItem -- Parameters field list +Returns Return value ListItem -- Unordered list +Raises Raised exceptions ListItem -- Unordered list +Yileds Yield values ListItem -- Unordered list +Notes Useful notes paragraph 1 Note admonition +========== =========================== ============ === ===================== layout rules diff --git a/sectiondoc/styles/old_style.py b/sectiondoc/styles/old_style.py index c255224..0839fe9 100644 --- a/sectiondoc/styles/old_style.py +++ b/sectiondoc/styles/old_style.py @@ -11,6 +11,8 @@ def class_section(lines): lines, sections={ 'Attributes': (attributes, Attribute, OrDefinitionItem), + 'Arguments': (arguments, Argument, OrDefinitionItem), + 'Parameters': (arguments, Argument, OrDefinitionItem), 'Methods': (methods_table, Method, MethodItem), 'Notes': (notes_paragraph, None, None)}) From d7d1d39db6f45dc9414a54f600f406567443870d Mon Sep 17 00:00:00 2001 From: Ioannis Tziakos Date: Mon, 2 Mar 2015 15:55:01 +0000 Subject: [PATCH 55/63] minor cleanup --- sectiondoc/styles/doc_render.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sectiondoc/styles/doc_render.py b/sectiondoc/styles/doc_render.py index 6e8f3d9..b2b6fac 100644 --- a/sectiondoc/styles/doc_render.py +++ b/sectiondoc/styles/doc_render.py @@ -46,7 +46,7 @@ class DocRender(object): """ def __init__(self, lines, sections=None): - """ Initialize the class + """ Arguments --------- From 56bfe4455cb6a53d15bd6f030fd182b69ca34a33 Mon Sep 17 00:00:00 2001 From: Ioannis Tziakos Date: Mon, 2 Mar 2015 23:29:58 +0000 Subject: [PATCH 56/63] fix docstrings --- sectiondoc/items/or_definition_item.py | 2 +- sectiondoc/styles/doc_render.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sectiondoc/items/or_definition_item.py b/sectiondoc/items/or_definition_item.py index 6088534..4884a87 100644 --- a/sectiondoc/items/or_definition_item.py +++ b/sectiondoc/items/or_definition_item.py @@ -23,7 +23,7 @@ class OrDefinitionItem(Item): term : str The term usually reflects the name of a parameter or an attribute. - classifiers: list + classifiers : list The classifiers of the definition. Commonly used to reflect the type of an argument or the signature of a function. Only two classifiers are accepted. diff --git a/sectiondoc/styles/doc_render.py b/sectiondoc/styles/doc_render.py index b2b6fac..9bcf6ec 100644 --- a/sectiondoc/styles/doc_render.py +++ b/sectiondoc/styles/doc_render.py @@ -50,8 +50,8 @@ def __init__(self, lines, sections=None): Arguments --------- - lines : list of strings - The docstring to refactor + lines : list + The docstring as a list of strings where to render the sections sections : dict The sections that will be detected and rendered. The dictionary From 8a0c2be6a211f1c88906cb5cd8148d2015fd8d69 Mon Sep 17 00:00:00 2001 From: Ioannis Tziakos Date: Mon, 2 Mar 2015 23:30:17 +0000 Subject: [PATCH 57/63] reduce the depth of the toctree --- docs/source/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/index.rst b/docs/source/index.rst index ccfd3bf..b3a08d1 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -6,7 +6,7 @@ Contents ======== .. toctree:: - :maxdepth: 2 + :maxdepth: 1 rendering styles From d7b85087939ba47c625d587cd529df6b8fdf57ae Mon Sep 17 00:00:00 2001 From: Ioannis Tziakos Date: Mon, 2 Mar 2015 23:43:06 +0000 Subject: [PATCH 58/63] Update old_style.rst --- docs/source/old_style.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/old_style.rst b/docs/source/old_style.rst index 6558dc4..188e19a 100644 --- a/docs/source/old_style.rst +++ b/docs/source/old_style.rst @@ -20,7 +20,7 @@ Parameters function arguments and type ArgumentItem -- Parameters field li Notes Useful notes paragraph 1 Note admonition ========== ================================ ============ === ===================== -For functions the **default style** re-factors four types of sections: +For functions the **old style** renders four types of sections: ========== =========================== ============ === ===================== Heading Description Item Max Rendered as From d94e9414e7144ee2a1218ded0d30aa709843c5af Mon Sep 17 00:00:00 2001 From: Ioannis Tziakos Date: Fri, 7 Aug 2015 11:34:45 +0100 Subject: [PATCH 59/63] rename old_style to legacy --- sectiondoc/__init__.py | 12 ++---------- sectiondoc/styles/{old_style.py => legacy.py} | 0 .../{test_old_style.py => test_legacy_style.py} | 4 ++-- 3 files changed, 4 insertions(+), 12 deletions(-) rename sectiondoc/styles/{old_style.py => legacy.py} (100%) rename sectiondoc/tests/{test_old_style.py => test_legacy_style.py} (99%) diff --git a/sectiondoc/__init__.py b/sectiondoc/__init__.py index 96532f0..1311c19 100644 --- a/sectiondoc/__init__.py +++ b/sectiondoc/__init__.py @@ -5,19 +5,11 @@ # Copyright (c) 2011-2014, Enthought, Inc. # All rights reserved. # ----------------------------------------------------------------------------- -__all__ = ['__version__', 'setup'] - try: # pragma: no cover from sectiondoc._version import full_version as __version__ except ImportError: # pragma: no cover __version__ = "not-built" +from sectiondoc.styles.legacy import setup -def setup(app): - import warnings - from sectiondoc.styles.old_style import setup - warnings.warn( - "This entry-point will be removed in the next release. " - "Please use 'sectiondoc.styles.old_style' in conf.py", - DeprecationWarning) - setup(app) +__all__ = ['__version__', 'setup'] diff --git a/sectiondoc/styles/old_style.py b/sectiondoc/styles/legacy.py similarity index 100% rename from sectiondoc/styles/old_style.py rename to sectiondoc/styles/legacy.py diff --git a/sectiondoc/tests/test_old_style.py b/sectiondoc/tests/test_legacy_style.py similarity index 99% rename from sectiondoc/tests/test_old_style.py rename to sectiondoc/tests/test_legacy_style.py index 3b9bb74..61ec1ca 100644 --- a/sectiondoc/tests/test_old_style.py +++ b/sectiondoc/tests/test_legacy_style.py @@ -1,8 +1,8 @@ -from sectiondoc.styles.old_style import class_section, function_section +from sectiondoc.styles.legacy import class_section, function_section from sectiondoc.tests._compat import unittest -class TestOldStyleClass(unittest.TestCase): +class TestLegacyStyleClass(unittest.TestCase): def setUp(self): self.maxDiff = None From 8d8b02f5b2cd511d4b5c18828bebd3dbcc9b9254 Mon Sep 17 00:00:00 2001 From: Ioannis Tziakos Date: Fri, 7 Aug 2015 11:52:23 +0100 Subject: [PATCH 60/63] update documentation --- .../{old_style.rst => legacy_style.rst} | 22 ++++++++++--------- docs/source/styles.rst | 19 ++++++++-------- 2 files changed, 21 insertions(+), 20 deletions(-) rename docs/source/{old_style.rst => legacy_style.rst} (86%) diff --git a/docs/source/old_style.rst b/docs/source/legacy_style.rst similarity index 86% rename from docs/source/old_style.rst rename to docs/source/legacy_style.rst index 188e19a..1dcbe21 100644 --- a/docs/source/old_style.rst +++ b/docs/source/legacy_style.rst @@ -1,13 +1,12 @@ -Old Style -######### +Legacy +###### -The base implementation of Sectiondoc provides rendering for class and -function/method doc-strings. A number of known (i.e. predefined) sections are -processed by the :func:`~.function_section` and :func:`~FunctionDoc` classes -and all unknown sections are rendered using the ``.. rubric::`` directive by -default. +Previous versions of Sectiondoc (and the even older refactordoc +package) supported a single style for rendering sections in +function/method doc-strings. The old style is still supported in +recent versions as a **legacy** style. -For class objects the **old style** renders three types of sections: +For class objects the **legacy** renders three types of sections: ========== ================================ ============ === ===================== Heading Description Item Max Rendered as @@ -20,7 +19,7 @@ Parameters function arguments and type ArgumentItem -- Parameters field li Notes Useful notes paragraph 1 Note admonition ========== ================================ ============ === ===================== -For functions the **old style** renders four types of sections: +For functions the **legacy** renders four types of sections: ========== =========================== ============ === ===================== Heading Description Item Max Rendered as @@ -29,10 +28,13 @@ Arguments function arguments and type ArgumentItem -- Parameters field list Parameters function arguments and type ArgumentItem -- Parameters field list Returns Return value ListItem -- Unordered list Raises Raised exceptions ListItem -- Unordered list -Yileds Yield values ListItem -- Unordered list +Yields Yield values ListItem -- Unordered list Notes Useful notes paragraph 1 Note admonition ========== =========================== ============ === ===================== +.. note:: + All other sections are rendered using the ``.. rubric::`` directive by + default. layout rules ************ diff --git a/docs/source/styles.rst b/docs/source/styles.rst index b309472..0228371 100644 --- a/docs/source/styles.rst +++ b/docs/source/styles.rst @@ -1,26 +1,25 @@ Styles ------ -SectionDoc comes with a number of predefined rendering styles - +SectionDoc comes with the following predefined rendering styles .. toctree:: :maxdepth: 1 - old_style + legacy_style .. note:: - The default rendering style is currently :mod:`~.old_style` + The default rendering style is currently :mod:`~.legacy` Extending --------- -Custom styles can be created by instanciating a :class:`~.Style` -to map a :class:`~.DocRender` factory for each type of object sent -by autodoc. For example adding the following functions in you -conf.py defines a rendering style for functions and methods:: +Custom styles can be created by instanciating a :class:`~.Style` to +map a :class:`~.DocRender` factory for each type of object rendered by +autodoc. For example adding the following functions in you conf.py +defines a rendering style for functions and methods:: def function_section(lines): return DocRender( @@ -45,8 +44,8 @@ Specifically the :class:`~.Style` instance will map the ``function`` and ``method`` docstrings to the dostring rendering funtion ``function_section``. The :class:`~DocRender` will then detect the sections ``Returns, Arguments, Parameters, Raises, Yields, Notes`` and -use the mapped combination of section rendering function, Item descreption -and item rendering type to render the detected section inplace. +use the mapped combination of section rendering function, Item description +and item rendering type to render the detected section in-place. The rendering styles can be further extented by implemeting new Item, Renderer instances or section rendering functions. From e75804f50c838ca7b01ff0a924c9da6c3be6dbd6 Mon Sep 17 00:00:00 2001 From: Ioannis Tziakos Date: Fri, 7 Aug 2015 11:52:37 +0100 Subject: [PATCH 61/63] use alabaster sphinx theme --- docs/source/conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index 693b2f3..dd84df4 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -68,7 +68,7 @@ # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. -html_theme = 'default' +html_theme = 'alabaster' # Output file base name for HTML help builder. htmlhelp_basename = 'SectionDocdoc' From 2cedb0608ae662d482d104bce930195e9cdcfee3 Mon Sep 17 00:00:00 2001 From: Ioannis Tziakos Date: Fri, 7 Aug 2015 11:53:04 +0100 Subject: [PATCH 62/63] simplify package versioning --- setup.py | 68 +++++++++----------------------------------------------- 1 file changed, 10 insertions(+), 58 deletions(-) diff --git a/setup.py b/setup.py index 4379613..11cd97e 100644 --- a/setup.py +++ b/setup.py @@ -1,85 +1,37 @@ # -*- coding: utf-8 -*- -#------------------------------------------------------------------------------ +# ----------------------------------------------------------------------------- # License: LICENSE.TXT # # Copyright (c) 2014, Enthought, Inc. # All rights reserved. -#------------------------------------------------------------------------------ +# ----------------------------------------------------------------------------- from setuptools import setup, find_packages -import os -import subprocess -MAJOR = 0 -MINOR = 4 +MAJOR = 1 +MINOR = 0 MICRO = 0 +DEV = 0 VERSION = '{0:d}.{1:d}.{2:d}'.format(MAJOR, MINOR, MICRO) +FULLVERSION = '{0:d}.{1:d}.{2:d}'.format(MAJOR, MINOR, MICRO, DEV) IS_RELEASED = False -# Return the git revision as a string -def git_version(): - def _minimal_ext_cmd(cmd): - # construct minimal environment - env = {} - for k in ['SYSTEMROOT', 'PATH']: - v = os.environ.get(k) - if v is not None: - env[k] = v - # LANGUAGE is used on win32 - env['LANGUAGE'] = 'C' - env['LANG'] = 'C' - env['LC_ALL'] = 'C' - out = subprocess.Popen( - cmd, stdout=subprocess.PIPE, env=env, - ).communicate()[0] - return out - - try: - out = _minimal_ext_cmd(['git', 'rev-parse', 'HEAD']) - git_revision = out.strip().decode('ascii') - except OSError: - git_revision = "Unknown" - - return git_revision - - def write_version_py(filename='sectiondoc/_version.py'): template = """\ # THIS FILE IS GENERATED FROM SECTIONDOC SETUP.PY version = '{version}' full_version = '{full_version}' -git_revision = '{git_revision}' is_released = {is_released} if not is_released: version = full_version """ - # Adding the git rev number needs to be done inside - # write_version_py(), otherwise the import of sectiondoc._version - # messes up the build under Python 3. - fullversion = VERSION - if os.path.exists('.git'): - git_rev = git_version() - elif os.path.exists('sectiondoc/_version.py'): - # must be a source distribution, use existing version file - try: - from sectiondoc._version import git_revision as git_rev - except ImportError: - raise ImportError("Unable to import git_revision. Try removing " - "sectiondoc/_version.py and the build " - "directory before building.") - else: - git_rev = "Unknown" - - if not IS_RELEASED: - fullversion += '.dev1-' + git_rev[:7] - with open(filename, "wt") as fp: - fp.write(template.format(version=VERSION, - full_version=fullversion, - git_revision=git_rev, - is_released=IS_RELEASED)) + fp.write(template.format( + version=VERSION, + full_version=FULLVERSION, + is_released=IS_RELEASED)) if __name__ == "__main__": From 10fb219fe704bba86f896b83abc69160f48945f8 Mon Sep 17 00:00:00 2001 From: Ioannis Tziakos Date: Fri, 7 Aug 2015 11:55:47 +0100 Subject: [PATCH 63/63] update README --- README.rst | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/README.rst b/README.rst index 1b9d61f..3e5f7a7 100644 --- a/README.rst +++ b/README.rst @@ -44,19 +44,11 @@ Install ``sectiondoc`` from pypi using pip:: Usage ----- -Add sectiondoc to the extensions variable of your sphinx ``conf.py``:: - extensions = [ - ..., - 'sectiondoc', - ..., - ] - - -Styles can be selected by referencing the module they are defined at:: +Styles can be selected by referencing in ``conf.py`` the module they are defined:: extensions = [ ..., - 'sectiondoc.styles.old_style', + 'sectiondoc.styles.legacy', ..., ]