Back on Monday, I promised I'd share my
UnitTestUtilities
and DocMeta
modules. Hopefully you've already seen UnitTestUtilities
, since I posted that on Wednesday. Today's foray is into DocMeta
.I wrote
DocMeta
quite some time back, in order to provide a simple, annotation-based (e.g., decorator-based) way of adding additional/more specific documentation-information to functions and methods. You've already seen it in use in UnitTestUtilities
, at least from the code side of things, and if you've tried to take a look at the pydoc output for it, it's probably barfed at you, saying that it couldn't find DocMeta
. What DocMeta does, is provide decorators that add information to the docstring of a function or method. Consider the
HasTestFor
function from UnitTestUtilities
:
@ToDo( 'Unit-test the function' ) @ToDo( 'Document exceptions raised' ) @ToDo( 'Value-check arguments' ) @ToDo( 'Type-check arguments' ) @DocumentArgument( 'argument', 'testCase', None, '(unittest.TestCase, required) The TestCase instance to check for the named test-method in.' ) @DocumentArgument( 'argument', 'itemName', None, '(Class, required) The name of the property or method to look for a test-method for ("test[itemName]").' ) @DocumentReturn( types.BooleanType ) def HasTestFor( testCase, itemName ): """Returns true if the testCase provided has a test-method named 'test[itemName]'."""
Without the decorators, the pydoc documentation for the function would look something like so:
- HasTestFor(testCase, itemName)
Returns true if the testCase provided has a test-method named 'test[itemName]'.
With the decorators, the this is what it looks like:
- HasTestFor(testCase, itemName)
Returns true if the testCase provided has a test-method named 'test[itemName]'. ################### ## TO-DOs ## ################### - Type-check arguments - Value-check arguments - Document exceptions raised - Unit-test the function ################### ## Returns ## ################### bool ################### ## Arguments ## ################### + testCase ............ (unittest.TestCase, required) The TestCase instance to check for the named test-method in. + itemName ............ (Class, required) The name of the property or method to look for a test-method for ("test[itemName]").
The basic pattern that these decorators follow is to add the supplied meta-data to the item being decorated as protected attributes of the item (
_argumentDocumentation
, _configDocumentation
, etc.), with helper functions to assure that the meta-data structure exists, and to re-generate the item's docstring as needed.As I contine working on this module, I'm planning to add in classes and functionality to generate documentation as LaTeX/PDF, HTML and/or XML output from the additional meta-data, but for now, I'm just going to share/show the code for the decorators...
# DocMeta.py """Provides common documentation-metadata decorators, that facilitate in-code documentation of functions, classes, their methods, etc.""" __author__ = 'Brian D. Allbee' __licence__ = 'http://creativecommons.org/licenses/by-sa/3.0/' __version__ = '0.2' __copyright__ = "Copyright 2011, Brian D. Allbee" __credits__ = ["Brian D. Allbee"] __maintainer__ = "Brian D. Allbee" __email__ = "brian.allbee@gmail.com" __status__ = "Development" ##################################### # Build an "__all__" list to # # support # # "from Namespace.blah import *" # # syntax # ##################################### __all__ = [] ##################################### # Required imports # ##################################### import inspect ##################################### # Constants defined in the module # ##################################### SelfDocumentationString = 'The object-instance that the method is called against.' __all__ += [ 'SelfDocumentationString' ] ##################################### # Functions defined in the module # ##################################### def HangWrap( baseString, lineLength=80, indent=30 ): """Helper/formatting function that wraps a string to the specified line-length, with the specified hanging indent.""" remainder = baseString.split( ' ' ) result = '' line = '' while remainder: theWord = remainder[0] remainder = remainder[1:] if not theWord in [ '\n', '\r' ]: if len( line ) + len( theWord ) + 1 > lineLength: result += line + '\n' line = ' ' * ( indent + 1) line += theWord + ' ' result += line + '\n' return result __all__ += [ 'HangWrap' ] def InitializeDocMetadata( decoratedItem ): """Helper function that initializes all of the decorated item's documentation-metadata structures.""" if not hasattr( decoratedItem, '_configDocumentation' ): setattr( decoratedItem, '_configDocumentation', {} ) if not hasattr( decoratedItem, '_argumentDocumentation' ): setattr( decoratedItem, '_argumentDocumentation', { 'args':{}, 'arglist':{}, 'kwargs':{} } ) if not hasattr( decoratedItem, '_baseDocumentation' ): setattr( decoratedItem, '_baseDocumentation', decoratedItem.__doc__ ) if not getattr( decoratedItem, '_baseDocumentation' ): setattr( decoratedItem, '_baseDocumentation', '' ) if not hasattr( decoratedItem, '_exceptionDocumentation' ): setattr( decoratedItem, '_exceptionDocumentation', {} ) if not hasattr( decoratedItem, '_returnsDocumentation' ): setattr( decoratedItem, '_returnsDocumentation', [] ) if not hasattr( decoratedItem, '_todoDocumentation' ): setattr( decoratedItem, '_todoDocumentation', [] ) __all__ += [ 'InitializeDocMetadata' ] def RebuildDocumentation( decoratedItem ): """Helper function that rebuilds documentation metadata and stuffs it into the item's __doc__.""" # Base documentation, if any, first... tmpDocs = getattr( decoratedItem, '_baseDocumentation' ) if not tmpDocs: tmpDocs = 'No base documentation provided.' tmpDocs += '\n' # TODO documentation next toDoDocs = getattr( decoratedItem, '_todoDocumentation' ) if len( toDoDocs ) != 0: tmpDocs += """ ################### ## TO-DOs ## ################### """ for theToDo in toDoDocs: tmpDocs += HangWrap( ' - %s' % ( theToDo ), 80, 6 ) # Returns documentation next returnDocs = getattr( decoratedItem, '_returnsDocumentation' ) tag = '' if len( returnDocs ) > 1: tmpDocs += """ ################### ## Returns ## ################### Any of %s """ % ( returnDocs ) elif len( returnDocs ) == 1: tmpDocs += """ ################### ## Returns ## ################### %s """ % ( returnDocs[ 0 ] ) # Arguments next argDocs = getattr( decoratedItem, '_argumentDocumentation' ) argSpecs = inspect.getargspec( decoratedItem ) if argSpecs[0] or argSpecs[1] or argSpecs[2]: tmpDocs += """ ################### ## Arguments ## ################### """ if argSpecs[0]: for theArg in argSpecs[0]: if theArg in argDocs['args'].keys(): tmpDocs += HangWrap( ( ' + %s ........................' % ( theArg ) )[:24] + ' ' + argDocs['args'][theArg], 80, 24 ) if argSpecs[1]: tmpDocs += HangWrap( ( ' + %s ........................' % ( argSpecs[1] ) )[:24] + ' ' + argDocs['arglist'], 80, 24 ) if argSpecs[2] and argDocs['kwargs']: tmpDocs += ( ' + %s ........................' % ( argSpecs[2] ) )[:24] + ' Keyword-argument list. The following values are known/documented:\n' theKeys = argDocs['kwargs'].keys() theKeys.sort() for theKey in theKeys: tmpDocs += HangWrap( ( ' - %s ........................' % ( theKey ) )[:24] + ' ' + str( argDocs['kwargs'][theKey] ), 80, 24 ) exceptionDocs = getattr( decoratedItem, '_exceptionDocumentation' ) if exceptionDocs: tmpDocs += """ ################### ## Exceptions ## ################### """ exceptions = exceptionDocs.keys() exceptions.sort() for theException in exceptions: tmpDocs += 'Raises %s when:\n' % ( theException ) for details in exceptionDocs[ theException ]: tmpDocs += HangWrap( ' - %s;' % ( details ), 80, 6 ) configDocs = getattr( decoratedItem, '_configDocumentation' ) if configDocs: tmpDocs += """ ################### ## Configuration ## ################### The relevant configuration-file section(s) and values(s) are: """ sectionKeys = configDocs.keys() sectionKeys.sort() for theSection in sectionKeys: tmpDocs += '[%s]\n' % ( theSection ) items = configDocs[ theSection ] itemKeys = items.keys() itemKeys.sort() for theItem in itemKeys: tmpDocs += HangWrap( ( '%s .....................................' % ( theItem ) )[:29] + ' %s' % ( items[ theItem ] ), 80, 29 ) setattr( decoratedItem, '__doc__', tmpDocs ) __all__ += [ 'RebuildDocumentation' ] def DocumentArgument( argumentType, argumentName, keywordName, argumentDocumentation ): """Decorator function that documents a function- or method-argument.""" def decorator( decoratedItem ): InitializeDocMetadata( decoratedItem ) argSpecs = inspect.getargspec( decoratedItem ) if argSpecs[0]: for theName in argSpecs[0]: if theName != 'self': if not theName in decoratedItem._argumentDocumentation[ 'args' ].keys(): decoratedItem._argumentDocumentation[ 'args' ][ theName ] = 'Not documented.' else: decoratedItem._argumentDocumentation[ 'args' ][ theName ] = SelfDocumentationString if argSpecs[1]: if not decoratedItem._argumentDocumentation[ 'arglist' ]: decoratedItem._argumentDocumentation[ 'arglist' ] = argSpecs[1] if argSpecs[2]: if not decoratedItem._argumentDocumentation[ 'kwargs' ]: decoratedItem._argumentDocumentation[ 'kwargs' ] = {} if argumentType == "argument": argDocs = getattr( decoratedItem, '_argumentDocumentation' )[ 'args' ] argDocs[ argumentName ] = argumentDocumentation elif argumentType == "arglist": pass elif argumentType == "keyword": argDocs = getattr( decoratedItem, '_argumentDocumentation' )[ 'kwargs' ] if keywordName in argDocs.keys(): raise AttributeError( '"%s" has already been documented as a keyword value for the "%s" list of %s.' % ( keywordName, argumentName, decoratedItem.__name__ ) ) argDocs[ keywordName ] = argumentDocumentation else: raise AttributeError( '"%s" is not a recognized argumentType ("argument", "arglist", or "keyword" are allowed).' % ( argumentType ) ) # Re-create the item's docstring with the argument information: RebuildDocumentation( decoratedItem ) return decoratedItem return decorator __all__ += [ 'DocumentArgument' ] def DocumentConfiguration( configSection, configName, configDescription ): """Decorator function that documents the configuration-file section(s) relevant to instances of the object. Intended for use with ConfigParser instances, but may be valid for other configuration mechanisms.""" def decorator( decoratedItem ): InitializeDocMetadata( decoratedItem ) configDocs = getattr( decoratedItem, '_configDocumentation' ) if not configSection in configDocs.keys(): configDocs[ configSection ] = {} configDocs[ configSection ][ configName ] = configDescription # Re-create the item's docstring with the exception information: RebuildDocumentation( decoratedItem ) return decoratedItem return decorator __all__ += [ 'DocumentConfiguration' ] def DocumentException( exceptionType, exceptionCase ): """Decorator function that documents an exception that can be raised by a function or method.""" def decorator( decoratedItem ): InitializeDocMetadata( decoratedItem ) exceptionDocs = getattr( decoratedItem, '_exceptionDocumentation' ) if not exceptionType.__name__ in exceptionDocs.keys(): exceptionDocs[ exceptionType.__name__ ] = [] exceptionDocs[ exceptionType.__name__ ].append( exceptionCase ) # Re-create the item's docstring with the exception information: RebuildDocumentation( decoratedItem ) return decoratedItem return decorator __all__ += [ 'DocumentException' ] def DocumentReturn( *returnTypes ): """Decorator function that documents the return type(s) of a function or method.""" def decorator( decoratedItem ): InitializeDocMetadata( decoratedItem ) returnDocs = getattr( decoratedItem, '_returnsDocumentation' ) for theType in returnTypes: if theType != None: if not theType.__name__ in returnDocs: returnDocs.append( theType.__name__ ) else: if not 'None' in returnDocs: returnDocs.append( 'None' ) returnDocs.sort() # Re-create the item's docstring with the return information: RebuildDocumentation( decoratedItem ) return decoratedItem return decorator __all__ += [ 'DocumentReturn' ] def ToDo( todo ): """Decorator function that documents "To-do" items.""" def decorator( decoratedItem ): InitializeDocMetadata( decoratedItem ) toDoDocs = getattr( decoratedItem, '_todoDocumentation' ) toDoDocs.append( todo ) # Re-create the item's docstring with the todo information: RebuildDocumentation( decoratedItem ) return decoratedItem return decorator __all__ += [ 'ToDo' ] ##################################### # Decorate above functions # ##################################### # DocumentArgument DocumentArgument( 'argument', 'argumentType', None, '(\'argument\', \'arglist\' or \'keyword\') The argument-type for the argument.' )( DocumentArgument ) DocumentArgument( 'argument', 'argumentName', None, '(String, required) The name of the argument of the function or method being documented.' )( DocumentArgument ) DocumentArgument( 'argument', 'keywordName', None, '(String, required for keyword arguments, ignored for other types) The name of a keyword argument that is recognized by the function or method.' )( DocumentArgument ) DocumentArgument( 'argument', 'argumentDocumentation', None, '(String) The documentation for the argument.' )( DocumentArgument ) ToDo( 'Type-check arguments.' )( DocumentArgument ) ToDo( 'Value-check arguments(?).' )( DocumentArgument ) ToDo( 'Document exceptions' )( DocumentArgument ) # DocumentConfiguration DocumentArgument( 'argument', 'configSection', None, '(String, required) The name of the configuration-section that the configName argument will be found in.' )( DocumentConfiguration ) DocumentArgument( 'argument', 'configName', None, '(String, required) The name of the configuration-value.' )( DocumentConfiguration ) DocumentArgument( 'argument', 'configDescription', None, '(String) The documentation for the configuration name/value pair.' )( DocumentConfiguration ) ToDo( 'Type-check arguments.' )( DocumentConfiguration ) ToDo( 'Value-check arguments(?).' )( DocumentConfiguration ) ToDo( 'Document exceptions' )( DocumentConfiguration ) # DocumentException DocumentArgument( 'argument', 'exceptionType', None, '(Exception, required) The exception-type expected under the case in exceptionCase.' )( DocumentException ) DocumentArgument( 'argument', 'exceptionCase', None, '(String) The case that will raise the specified exception. Documentation will be built as a list of cases for each exception, in a format similar to "Raises [exceptionType] when:" followed by all exception-cases for that type.' )( DocumentException ) ToDo( 'Type-check arguments.' )( DocumentException ) ToDo( 'Value-check arguments(?).' )( DocumentException ) ToDo( 'Document exceptions' )( DocumentException ) # DocumentReturn DocumentArgument( 'arglist', 'returnTypes', None, 'The types returned by the function or method.' )( DocumentReturn ) ToDo( 'Type-check arguments.' )( DocumentReturn ) ToDo( 'Value-check arguments(?).' )( DocumentReturn ) ToDo( 'Document exceptions' )( DocumentReturn ) # HangWrap DocumentArgument( 'argument', 'baseString', None, '(String, required) The base string to re-format.' )( HangWrap ) DocumentArgument( 'argument', 'lineLength', None, '(Integer, optional, defaults to 80) The maximum length of a line in the re-formatted string.' )( HangWrap ) DocumentArgument( 'argument', 'indent', None, '(Integer, optional, defaults to 30) The number of spaces to indent second and subsequent lines in the re-formatted string' )( HangWrap ) ToDo( 'Type-check arguments.' )( HangWrap ) ToDo( 'Value-check arguments(?).' )( HangWrap ) ToDo( 'Document exceptions' )( HangWrap ) # InitializeDocMetadata DocumentArgument( 'argument', 'decoratedItem', None, 'The item to initialize documentation-meta-data structures on.' )( InitializeDocMetadata ) ToDo( 'Type-check arguments.' )( InitializeDocMetadata ) ToDo( 'Value-check arguments(?).' )( InitializeDocMetadata ) ToDo( 'Document exceptions' )( InitializeDocMetadata ) # RebuildDocumentation DocumentArgument( 'argument', 'decoratedItem', None, 'The item to rebuild __doc__ on, using current documentation-meta-data structure.' )( RebuildDocumentation ) ToDo( 'Type-check arguments.' )( RebuildDocumentation ) ToDo( 'Value-check arguments(?).' )( RebuildDocumentation ) ToDo( 'Document exceptions' )( RebuildDocumentation ) # ToDo DocumentArgument( 'argument', 'todo', None, '(String, required) The "To-do" item to attach.' )( ToDo ) ToDo( 'Type-check arguments.' )( ToDo ) ToDo( 'Value-check arguments(?).' )( ToDo ) ToDo( 'Document exceptions' )( ToDo ) ##################################### # Interfaces defined in the module # ##################################### ##################################### # Abstract Classes defined in the # # module # ##################################### ##################################### # Classes defined in the module # ##################################### ##################################### # Package sub-modules and -packages # ##################################### ##################################### # Unit-test the module on main # ##################################### if __name__ == '__main__': import inspect, os, sys, unittest from UnitTestUtilities import * testSuite = unittest.TestSuite() testResults = unittest.TestResult() ################################## # Unit-test Constants # ################################## class testConstants( unittest.TestCase ): """Unit-tests the constants defined in the module.""" def testConstants( self ): self.assertEquals( SelfDocumentationString, 'The object-instance that the method is called against.', 'SelfDocumentationString should be a constant, meaningful string.' ) testSuite.addTests( unittest.TestLoader().loadTestsFromTestCase( testConstants ) ) ################################## # Unit-test Functions # ################################## class testDocumentArgument( unittest.TestCase ): """Unit-tests the DocumentArgument function defined in the module.""" pass testSuite.addTests( unittest.TestLoader().loadTestsFromTestCase( testDocumentArgument ) ) class testDocumentConfiguration( unittest.TestCase ): """Unit-tests the DocumentConfiguration function defined in the module.""" pass testSuite.addTests( unittest.TestLoader().loadTestsFromTestCase( testDocumentConfiguration ) ) class testDocumentException( unittest.TestCase ): """Unit-tests the DocumentException function defined in the module.""" pass testSuite.addTests( unittest.TestLoader().loadTestsFromTestCase( testDocumentException ) ) class testDocumentReturn( unittest.TestCase ): """Unit-tests the DocumentReturn function defined in the module.""" pass testSuite.addTests( unittest.TestLoader().loadTestsFromTestCase( testDocumentReturn ) ) class testHangWrap( unittest.TestCase ): """Unit-tests the HangWrap function defined in the module.""" pass testSuite.addTests( unittest.TestLoader().loadTestsFromTestCase( testHangWrap ) ) class testInitializeDocMetadata( unittest.TestCase ): """Unit-tests the InitializeDocMetadata function defined in the module.""" pass testSuite.addTests( unittest.TestLoader().loadTestsFromTestCase( testInitializeDocMetadata ) ) class testRebuildDocumentation( unittest.TestCase ): """Unit-tests the RebuildDocumentation function defined in the module.""" pass testSuite.addTests( unittest.TestLoader().loadTestsFromTestCase( testRebuildDocumentation ) ) ################################## # Unit-test Interfaces # ################################## ################################## # Unit-test Abstract Classes # ################################## ################################## # Unit-test Classes # ################################## # Run unit-tests and install print '#'*79 print 'Running unit-tests' testSuite.run( testResults ) print '#'*79 if testResults.errors == [] and testResults.failures == []: print 'All unit-tests passed! Ready for build/copy!' import shutil sitePackagesDirs = [] for path in sys.path: if path.split( os.sep )[-1].lower() == 'site-packages': sitePackagesDirs.append( path ) for path in sitePackagesDirs: destinationFile = path + os.sep + __file__ try: shutil.copyfile( './%s' % __file__, destinationFile ) print 'Copied %s to %s' % ( __file__, path ) except: print 'Could not copy file %s to location %s' % ( __file__, path ) else: print 'Unit-tests failed (see items below)' print '#'*79 if testResults.errors: print 'Errors' print '#' + '-'*77 + '#' for error in testResults.errors: print error[1] print '#' + '-'*77 + '#' print if testResults.failures: if testResults.errors: print '#'*79 print 'Failures' print '#' + '-'*77 + '#' for failure in testResults.failures: print failure[1] print '#' + '-'*77 + '#' print print '#'*79
As with
UnitTestUtilities
, I didn't want to hold up sharing this code for the sake of writing a lot of unit-tests. In this case, I'm not quite sure what my testing strategy is going to be. But as I write out those tests, the updated version of the module will be shared at the location noted above, so keep watching if you have the interest...
Commentary:
- Line(s)
- 20, 34, 56, etc.
- This is my usual
__all__
set-up - 26
- The decorators use functionality from the
inspect
module, so we import it here - 32
- Rather than have a magic string embedded in the argument-decorator, though that would probably be OK, I opted to make the
SelfDocumentationString
constant, and use it elsewhere. The name could be changed, it's a long name to type over and over again, but since most of it's uses can be copied and pasted quickly and easily, I didn't think it was a big deal. - 40-54
HangWrap
is just a string-formatting function, that provides the nice, clean dot-leader-with-hanging-indent shown in the doc-string example forHasTestFor
, above. It's a convenience function, nothing more, and I may not bother with writing any significant unit-tests for it later (though I should, for the sake of completion).- 58-73
InitializeDocMetadata
is a critical function - it assures that the documentation-meta-data structure needed for most (all?) of the decorators here is created, but not disturbed if it already exists. I'm not completely happy with the function, but I couldn't come up with a better way to handle the need, and I expect that it will perform well (though since it's not called outside of the context of a decorator that runs once at "compile-time," even that's not much of a concern). The items it ensures exist are:
- _configDocumentation
- A dictionary that will eventually contain config-section keys to dictionaries of config-names/values.
- _argumentDocumentation
- A dictionary of argument-, argument-list- and keyword-dictionaries
- _baseDocumentation
- The original
__doc__
of the decorated item. - _exceptionDocumentation
- A dictionary of Exception keys to condition-string lists
- _returnDocumentation
- A list of types
- _todoDocumentation
- A list of to-do strings
- 77-172
- This is the function that generates the final, meta-data-inclusive docstring that we see when browsing decorated items with pydoc. It uses
HangWrap
to format long lines into hanging-indent lines, but is pretty straightforward, I believe. Just long, since there's a lot of stuff to look for and format, potentially. - 174-217
DocumentArgument
is (probably) the most commonly used decorator of this whole set, and likely deserves some in-depth commentary:
- Line(s)
- 177
- Makes sure that the meta-data structure is available on the decorated item.
- 179
- Gets ahold of the list of arguments that were defined by the code using
inspect
functionality. - 180-186
- Checks for the existence of the argument-name, documents it with the
SelfDocumentationString
value if it'sself
, or with "Not documented" by default, after checking to see that it hasn't already been documented. - 187-189
- Stuffs an inspected argument-list's name into the meta-data structure.
- 190-191
- Stuffs an inspected keyword-arument-list's name into the meta-data structure.
- 194-196
- Sets the documentation-string for the specified argument.
- 198-199
- Skips any further processing for an argument-list, since there can be only one, and it's done by the time we reach this section of the code.
- 201-205
- Adds the specified keyword-name and documentation-value to the keyword-argument's meta-data (a dictionary of known keywords, and their documentation, if you recall).
- 211
- Rebuilds the decorated item's
__doc__
.
The patterns of various branches of
DocumentArgument
are echoed in DocumentConfiguration
, DocumentException
, DocumentReturn
and ToDo
, albeit with different and shallower meta-data-structure targets - hopefully, their functionality is straightforward.
Lines 298 through 356 explicitly decorate all of the decorator functions after they have all been defined, in order to provide the (hopefully) expected documentation for them. The structure/syntax probably looks a bit weird if you aren't used to it, but it does the same thing as the typical @DecoratorFunction(args) call right before the item being decorated...
The final doc-strings of each of these items demonstrate that:
DocumentArgument(argumentType, argumentName, keywordName, argumentDocumentation) Decorator function that documents a function- or method-argument. ################### ## TO-DOs ## ################### - Type-check arguments. - Value-check arguments(?). - Document exceptions ################### ## Arguments ## ################### + argumentType ........ ('argument', 'arglist' or 'keyword') The argument-type for the argument. + argumentName ........ (String, required) The name of the argument of the function or method being documented. + keywordName ......... (String, required for keyword arguments, ignored for other types) The name of a keyword argument that is recognized by the function or method. + argumentDocumentation (String) The documentation for the argument. DocumentConfiguration(configSection, configName, configDescription) Decorator function that documents the configuration-file section(s) relevant to instances of the object. Intended for use with ConfigParser instances, but may be valid for other configuration mechanisms. ################### ## TO-DOs ## ################### - Type-check arguments. - Value-check arguments(?). - Document exceptions ################### ## Arguments ## ################### + configSection ....... (String, required) The name of the configuration-section that the configName argument will be found in. + configName .......... (String, required) The name of the configuration-value. + configDescription ... (String) The documentation for the configuration name/value pair. DocumentException(exceptionType, exceptionCase) Decorator function that documents an exception that can be raised by a function or method. ################### ## TO-DOs ## ################### - Type-check arguments. - Value-check arguments(?). - Document exceptions ################### ## Arguments ## ################### + exceptionType ....... (Exception, required) The exception-type expected under the case in exceptionCase. + exceptionCase ....... (String) The case that will raise the specified exception. Documentation will be built as a list of cases for each exception, in a format similar to "Raises [exceptionType] when:" followed by all exception-cases for that type. DocumentReturn(*returnTypes) Decorator function that documents the return type(s) of a function or method. ################### ## TO-DOs ## ################### - Type-check arguments. - Value-check arguments(?). - Document exceptions ################### ## Arguments ## ################### + returnTypes ......... returnTypes HangWrap(baseString, lineLength=80, indent=30) Helper/formatting function that wraps a string to the specified line-length, with the specified hanging indent. ################### ## TO-DOs ## ################### - Type-check arguments. - Value-check arguments(?). - Document exceptions ################### ## Arguments ## ################### + baseString .......... (String, required) The base string to re-format. + lineLength .......... (Integer, optional, defaults to 80) The maximum length of a line in the re-formatted string. + indent .............. (Integer, optional, defaults to 30) The number of spaces to indent second and subsequent lines in the re-formatted string InitializeDocMetadata(decoratedItem) Helper function that initializes all of the decorated item's documentation-metadata structures. ################### ## TO-DOs ## ################### - Type-check arguments. - Value-check arguments(?). - Document exceptions ################### ## Arguments ## ################### + decoratedItem ....... The item to initialize documentation-meta-data structures on. RebuildDocumentation(decoratedItem) Helper function that rebuilds documentation metadata and stuffs it into the item's __doc__. ################### ## TO-DOs ## ################### - Type-check arguments. - Value-check arguments(?). - Document exceptions ################### ## Arguments ## ################### + decoratedItem ....... The item to rebuild __doc__ on, using current documentation-meta-data structure. ToDo(todo) Decorator function that documents "To-do" items. ################### ## TO-DOs ## ################### - Type-check arguments. - Value-check arguments(?). - Document exceptions ################### ## Arguments ## ################### + todo ................ (String, required) The "To-do" item to attach.
No comments:
Post a Comment