Package epydoc :: Module docstringparser
[hide private]
[frames] | no frames]

Source Code for Module epydoc.docstringparser

   1  # epydoc -- Docstring processing 
   2  # 
   3  # Copyright (C) 2005 Edward Loper 
   4  # Author: Edward Loper <edloper@loper.org> 
   5  # URL: <http://epydoc.sf.net> 
   6  # 
   7  # $Id: docstringparser.py 1715 2008-02-13 19:19:47Z edloper $ 
   8   
   9  """ 
  10  Parse docstrings and handle any fields it defines, such as C{@type} 
  11  and C{@author}.  Fields are used to describe specific information 
  12  about an object.  There are two classes of fields: X{simple fields} 
  13  and X{special fields}. 
  14   
  15  Simple fields are fields that get stored directly in an C{APIDoc}'s 
  16  metadata dictionary, without any special processing.  The set of 
  17  simple fields is defined by the list L{STANDARD_FIELDS}, whose 
  18  elements are L{DocstringField}s. 
  19   
  20  Special fields are fields that perform some sort of processing on the 
  21  C{APIDoc}, or add information to attributes other than the metadata 
  22  dictionary.  Special fields are are handled by field handler 
  23  functions, which are registered using L{register_field_handler}. 
  24  """ 
  25  __docformat__ = 'epytext en' 
  26   
  27   
  28  ###################################################################### 
  29  ## Imports 
  30  ###################################################################### 
  31   
  32  import re, sys 
  33  from epydoc import markup 
  34  from epydoc.markup import epytext 
  35  from epydoc.apidoc import * 
  36  from epydoc.docintrospecter import introspect_docstring_lineno 
  37  from epydoc.util import py_src_filename 
  38  from epydoc import log 
  39  import epydoc.docparser 
  40  import __builtin__, exceptions 
  41   
  42  ###################################################################### 
  43  # Docstring Fields 
  44  ###################################################################### 
  45   
46 -class DocstringField:
47 """ 48 A simple docstring field, which can be used to describe specific 49 information about an object, such as its author or its version. 50 Simple docstring fields are fields that take no arguments, and 51 are displayed as simple sections. 52 53 @ivar tags: The set of tags that can be used to identify this 54 field. 55 @ivar singular: The label that should be used to identify this 56 field in the output, if the field contains one value. 57 @ivar plural: The label that should be used to identify this 58 field in the output, if the field contains multiple values. 59 @ivar short: If true, then multiple values should be combined 60 into a single comma-delimited list. If false, then 61 multiple values should be listed separately in a bulleted 62 list. 63 @ivar multivalue: If true, then multiple values may be given 64 for this field; if false, then this field can only take a 65 single value, and a warning should be issued if it is 66 redefined. 67 @ivar takes_arg: If true, then this field expects an argument; 68 and a separate field section will be constructed for each 69 argument value. The label (and plural label) should include 70 a '%s' to mark where the argument's string rep should be 71 added. 72 """
73 - def __init__(self, tags, label, plural=None, 74 short=0, multivalue=1, takes_arg=0, 75 varnames=None):
76 if type(tags) in (list, tuple): 77 self.tags = tuple(tags) 78 elif type(tags) is str: 79 self.tags = (tags,) 80 else: raise TypeError('Bad tags: %s' % tags) 81 self.singular = label 82 if plural is None: self.plural = label 83 else: self.plural = plural 84 self.multivalue = multivalue 85 self.short = short 86 self.takes_arg = takes_arg 87 self.varnames = varnames or []
88
89 - def __cmp__(self, other):
90 if not isinstance(other, DocstringField): return -1 91 return cmp(self.tags, other.tags)
92
93 - def __hash__(self):
94 return hash(self.tags)
95
96 - def __repr__(self):
97 return '<Field: %s>' % self.tags[0]
98 99 STANDARD_FIELDS = [ 100 #: A list of the standard simple fields accepted by epydoc. This 101 #: list can be augmented at run-time by a docstring with the special 102 #: C{@deffield} field. The order in which fields are listed here 103 #: determines the order in which they will be displayed in the 104 #: output. 105 106 # If it's deprecated, put that first. 107 DocstringField(['deprecated', 'depreciated'], 108 'Deprecated', multivalue=0, varnames=['__deprecated__']), 109 110 # Status info 111 DocstringField(['version'], 'Version', multivalue=0, 112 varnames=['__version__']), 113 DocstringField(['date'], 'Date', multivalue=0, 114 varnames=['__date__']), 115 DocstringField(['status'], 'Status', multivalue=0), 116 117 # Bibliographic Info 118 DocstringField(['author', 'authors'], 'Author', 'Authors', short=1, 119 varnames=['__author__', '__authors__']), 120 DocstringField(['contact'], 'Contact', 'Contacts', short=1, 121 varnames=['__contact__']), 122 DocstringField(['organization', 'org'], 123 'Organization', 'Organizations'), 124 DocstringField(['copyright', '(c)'], 'Copyright', multivalue=0, 125 varnames=['__copyright__']), 126 DocstringField(['license'], 'License', multivalue=0, 127 varnames=['__license__']), 128 129 # Various warnings etc. 130 DocstringField(['bug'], 'Bug', 'Bugs'), 131 DocstringField(['warning', 'warn'], 'Warning', 'Warnings'), 132 DocstringField(['attention'], 'Attention'), 133 DocstringField(['note'], 'Note', 'Notes'), 134 135 # Formal conditions 136 DocstringField(['requires', 'require', 'requirement'], 'Requires'), 137 DocstringField(['precondition', 'precond'], 138 'Precondition', 'Preconditions'), 139 DocstringField(['postcondition', 'postcond'], 140 'Postcondition', 'Postconditions'), 141 DocstringField(['invariant'], 'Invariant'), 142 143 # When was it introduced (version # or date) 144 DocstringField(['since'], 'Since', multivalue=0), 145 146 # Changes made 147 DocstringField(['change', 'changed'], 'Change Log'), 148 149 # Crossreferences 150 DocstringField(['see', 'seealso'], 'See Also', short=1), 151 152 # Future Work 153 DocstringField(['todo'], 'To Do', takes_arg=True), 154 155 # Permissions (used by zope-based projects) 156 DocstringField(['permission', 'permissions'], 'Permission', 'Permissions') 157 ] 158 159 ###################################################################### 160 #{ Docstring Parsing 161 ###################################################################### 162 163 DEFAULT_DOCFORMAT = 'epytext' 164 """The name of the default markup languge used to process docstrings.""" 165 166 # [xx] keep track of which ones we've already done, in case we're 167 # asked to process one twice? e.g., for @include we might have to 168 # parse the included docstring earlier than we might otherwise..?? 169
170 -def parse_docstring(api_doc, docindex, suppress_warnings=[]):
171 """ 172 Process the given C{APIDoc}'s docstring. In particular, populate 173 the C{APIDoc}'s C{descr} and C{summary} attributes, and add any 174 information provided by fields in the docstring. 175 176 @param docindex: A DocIndex, used to find the containing 177 module (to look up the docformat); and to find any 178 user docfields defined by containing objects. 179 @param suppress_warnings: A set of objects for which docstring 180 warnings should be suppressed. 181 """ 182 if api_doc.metadata is not UNKNOWN: 183 if not (isinstance(api_doc, RoutineDoc) 184 and api_doc.canonical_name[-1] == '__init__'): 185 log.debug("%s's docstring processed twice" % 186 api_doc.canonical_name) 187 return 188 189 initialize_api_doc(api_doc) 190 191 # If there's no docstring, then check for special variables (e.g., 192 # __version__), and then return -- there's nothing else to do. 193 if (api_doc.docstring in (None, UNKNOWN)): 194 if isinstance(api_doc, NamespaceDoc): 195 for field in STANDARD_FIELDS + user_docfields(api_doc, docindex): 196 add_metadata_from_var(api_doc, field) 197 return 198 199 # Remove leading indentation from the docstring. 200 api_doc.docstring = unindent_docstring(api_doc.docstring) 201 202 # Decide which docformat is used by this module. 203 docformat = get_docformat(api_doc, docindex) 204 205 # A list of markup errors from parsing. 206 parse_errors = [] 207 208 # Extract a signature from the docstring, if it has one. This 209 # overrides any signature we got via introspection/parsing. 210 if isinstance(api_doc, RoutineDoc): 211 parse_function_signature(api_doc, None, docformat, parse_errors) 212 213 # Parse the docstring. Any errors encountered are stored as 214 # `ParseError` objects in the errors list. 215 parsed_docstring = markup.parse(api_doc.docstring, docformat, 216 parse_errors) 217 218 # Divide the docstring into a description and a list of 219 # fields. 220 descr, fields = parsed_docstring.split_fields(parse_errors) 221 api_doc.descr = descr 222 223 field_warnings = [] 224 225 # Handle the constructor fields that have been defined in the class 226 # docstring. This code assumes that a class docstring is parsed before 227 # the same class __init__ docstring. 228 if isinstance(api_doc, ClassDoc): 229 230 # Parse ahead the __init__ docstring for this class 231 initvar = api_doc.variables.get('__init__') 232 if initvar and isinstance(initvar.value, RoutineDoc): 233 init_api_doc = initvar.value 234 parse_docstring(init_api_doc, docindex, suppress_warnings) 235 236 parse_function_signature(init_api_doc, api_doc, 237 docformat, parse_errors) 238 init_fields = split_init_fields(fields, field_warnings) 239 240 # Process fields 241 for field in init_fields: 242 try: 243 process_field(init_api_doc, docindex, field.tag(), 244 field.arg(), field.body()) 245 except ValueError, e: field_warnings.append(str(e)) 246 247 # Process fields 248 for field in fields: 249 try: 250 process_field(api_doc, docindex, field.tag(), 251 field.arg(), field.body()) 252 except ValueError, e: field_warnings.append(str(e)) 253 254 # Check to make sure that all type parameters correspond to 255 # some documented parameter. 256 check_type_fields(api_doc, field_warnings) 257 258 # Check for special variables (e.g., __version__) 259 if isinstance(api_doc, NamespaceDoc): 260 for field in STANDARD_FIELDS + user_docfields(api_doc, docindex): 261 add_metadata_from_var(api_doc, field) 262 263 # Extract a summary 264 if api_doc.summary is None and api_doc.descr is not None: 265 api_doc.summary, api_doc.other_docs = api_doc.descr.summary() 266 267 # If the summary is empty, but the return field is not, then use 268 # the return field to generate a summary description. 269 if (isinstance(api_doc, RoutineDoc) and api_doc.summary is None and 270 api_doc.return_descr is not None): 271 s, o = api_doc.return_descr.summary() 272 api_doc.summary = RETURN_PDS + s 273 api_doc.other_docs = o 274 275 # [XX] Make sure we don't have types/param descrs for unknown 276 # vars/params? 277 278 # Report any errors that occured 279 if api_doc in suppress_warnings: 280 if parse_errors or field_warnings: 281 log.info("Suppressing docstring warnings for %s, since it " 282 "is not included in the documented set." % 283 api_doc.canonical_name) 284 else: 285 report_errors(api_doc, docindex, parse_errors, field_warnings)
286
287 -def add_metadata_from_var(api_doc, field):
288 for varname in field.varnames: 289 # Check if api_doc has a variable w/ the given name. 290 if varname not in api_doc.variables: continue 291 292 # Check moved here from before the for loop because we expect to 293 # reach rarely this point. The loop below is to be performed more than 294 # once only for fields with more than one varname, which currently is 295 # only 'author'. 296 for md in api_doc.metadata: 297 if field == md[0]: 298 return # We already have a value for this metadata. 299 300 var_doc = api_doc.variables[varname] 301 if var_doc.value is UNKNOWN: continue 302 val_doc = var_doc.value 303 value = [] 304 305 # Try extracting the value from the pyval. 306 ok_types = (basestring, int, float, bool, type(None)) 307 if val_doc.pyval is not UNKNOWN: 308 if isinstance(val_doc.pyval, ok_types): 309 value = [val_doc.pyval] 310 elif field.multivalue: 311 if isinstance(val_doc.pyval, (tuple, list)): 312 for elt in val_doc.pyval: 313 if not isinstance(elt, ok_types): break 314 else: 315 value = list(val_doc.pyval) 316 317 # Try extracting the value from the parse tree. 318 elif val_doc.toktree is not UNKNOWN: 319 try: value = [epydoc.docparser.parse_string(val_doc.toktree)] 320 except KeyboardInterrupt: raise 321 except: pass 322 if field.multivalue and not value: 323 try: value = epydoc.docparser.parse_string_list(val_doc.toktree) 324 except KeyboardInterrupt: raise 325 except: pass 326 327 # Add any values that we found. 328 for elt in value: 329 if isinstance(elt, str): 330 elt = decode_with_backslashreplace(elt) 331 else: 332 elt = unicode(elt) 333 elt = epytext.ParsedEpytextDocstring( 334 epytext.parse_as_para(elt), inline=True) 335 336 # Add in the metadata and remove from the variables 337 api_doc.metadata.append( (field, varname, elt) ) 338 339 # Remove the variable itself (unless it's documented) 340 if var_doc.docstring in (None, UNKNOWN): 341 del api_doc.variables[varname] 342 if api_doc.sort_spec is not UNKNOWN: 343 try: api_doc.sort_spec.remove(varname) 344 except ValueError: pass
345
346 -def initialize_api_doc(api_doc):
347 """A helper function for L{parse_docstring()} that initializes 348 the attributes that C{parse_docstring()} will write to.""" 349 if api_doc.descr is UNKNOWN: 350 api_doc.descr = None 351 if api_doc.summary is UNKNOWN: 352 api_doc.summary = None 353 if api_doc.metadata is UNKNOWN: 354 api_doc.metadata = [] 355 if isinstance(api_doc, RoutineDoc): 356 if api_doc.arg_descrs is UNKNOWN: 357 api_doc.arg_descrs = [] 358 if api_doc.arg_types is UNKNOWN: 359 api_doc.arg_types = {} 360 if api_doc.return_descr is UNKNOWN: 361 api_doc.return_descr = None 362 if api_doc.return_type is UNKNOWN: 363 api_doc.return_type = None 364 if api_doc.exception_descrs is UNKNOWN: 365 api_doc.exception_descrs = [] 366 if isinstance(api_doc, (VariableDoc<