Thread: [Epydoc-commits] SF.net SVN: epydoc: [1160] trunk/epydoc/src/epydoc/apidoc.py
Brought to you by:
edloper
From: <ed...@us...> - 2006-04-05 01:51:37
|
Revision: 1160 Author: edloper Date: 2006-04-04 18:51:34 -0700 (Tue, 04 Apr 2006) ViewCVS: http://svn.sourceforge.net/epydoc/?rev=1160&view=rev Log Message: ----------- - Docstring updates - Removed some debug printfs - APIDoc objects are now ordered by canonical name (with __cmp__) - Removed sorted_by_name arg from reachable_valdocs; use sorted() on the result instead Modified Paths: -------------- trunk/epydoc/src/epydoc/apidoc.py Modified: trunk/epydoc/src/epydoc/apidoc.py =================================================================== --- trunk/epydoc/src/epydoc/apidoc.py 2006-04-04 16:28:13 UTC (rev 1159) +++ trunk/epydoc/src/epydoc/apidoc.py 2006-04-05 01:51:34 UTC (rev 1160) @@ -8,7 +8,6 @@ """ Classes for encoding API documentation about Python programs. - These classes are used as a common representation for combining information derived from introspection and from parsing. @@ -48,10 +47,6 @@ # Dotted Names ###################################################################### -# [xx] define a new exception specifically for bad dotted names? -# ValueError is a bit generic, and there are a couple places where -# I catch this a bit far from where it gets raised. - class DottedName: """ A sequence of identifiers, separated by periods, used to name a @@ -100,12 +95,10 @@ elif isinstance(piece, basestring): for subpiece in piece.split('.'): if not self._IDENTIFIER_RE.match(subpiece): - log.debug('Bad identifier %r' % (piece,)) raise DottedName.InvalidDottedName( 'Bad identifier %r' % (piece,)) self._identifiers.append(subpiece) else: - log.debug('Bad identifier %r' % (piece,)) raise DottedName.InvalidDottedName( 'Bad identifier %r' % (piece,)) self._identifiers = tuple(self._identifiers) @@ -135,6 +128,10 @@ return DottedName(self, *other) def __radd__(self, other): + """ + Return a new C{DottedName} whose identifier sequence is formed + by adding C{self}'s identifier sequence to C{other}'s. + """ if isinstance(other, (basestring, DottedName)): return DottedName(other, self) else: @@ -143,7 +140,9 @@ def __getitem__(self, i): """ Return the C{i}th identifier in this C{DottedName}. If C{i} is - a slice, then return a C{DottedName} + a non-empty slice, then return a C{DottedName} built from the + identifiers selected by the slice. If C{i} is an empty slice, + return an empty list (since empty C{DottedName}s are not valid). """ if isinstance(i, types.SliceType): pieces = self._identifiers[i.start:i.stop] @@ -159,6 +158,8 @@ """ Compare this dotted name to C{other}. Two dotted names are considered equal if their identifier subsequences are equal. + Ordering between dotted names is lexicographic, in order of + identifier from left to right. """ if not isinstance(other, DottedName): return -1 @@ -183,16 +184,31 @@ return DottedName(*self._identifiers[:-1]) def dominates(self, name, strict=False): + """ + Return true if this dotted name is equal to a prefix of + C{name}. If C{strict} is true, then also require that + C{self!=name}. + + >>> DottedName('a.b').dominates(DottedName('a.b.c.d')) + True + """ if strict and len(self._identifiers)==len(name._identifiers): return False return self._identifiers == name._identifiers[:len(self)] def contextualize(self, context): """ - Return a reduced version of a dotted name. This name may be ambigious - (it is if its name is the same of the context), but is should be - explicit enough for humans, and may be considerably shorter and more - readable than a fully qualified one. + If C{self} and C{context} share a common ancestor, then return + a name for C{self}, relative to that ancestor. If they do not + share a common ancestor (or if C{context} is C{UNKNOWN}), then + simply return C{self}. + + This is used to generate shorter versions of dotted names in + cases where users can infer the intended target from the + context. + + @type context: L{DottedName} + @rtype: L{DottedName} """ if context is UNKNOWN or not context or len(self) <= 1: return self @@ -317,18 +333,23 @@ not correspond to a valid attribute for this (sub)class of C{APIDoc}. """ - for key in kwargs: - if not hasattr(self, key): - raise TypeError('%s got unexpected arg %r' % - (self.__class__.__name__, key)) + if epydoc.DEBUG: + for key in kwargs: + if not hasattr(self.__class__, key): + raise TypeError('%s got unexpected arg %r' % + (self.__class__.__name__, key)) self.__dict__.update(kwargs) def _debug_setattr(self, attr, val): """ - Modify an C{APIDoc}'s attribute. + Modify an C{APIDoc}'s attribute. This is used when + L{epydoc.DEBUG} is true, to make sure we don't accidentally + set any inappropriate attributes on C{APIDoc} objects. @raise AttributeError: If C{attr} is not a valid attribute for - this (sub)class of C{APIDoc}. + this (sub)class of C{APIDoc}. (C{attr} is considered a + valid attribute iff C{self.__class__} defines an attribute + with that name.) """ # Don't intercept special assignments like __class__, or # assignments to private variables. @@ -351,20 +372,32 @@ information contained in this C{APIDoc}. """ return pp_apidoc(self, doublespace, depth, exclude, include) - - def __str__(self): - return self.pp() + __str__ = pp def specialize_to(self, cls): + """ + Change C{self}'s class to C{cls}. C{cls} must be a subclass + of C{self}'s current class. For example, if a generic + C{ValueDoc} was created for a value, and it is determined that + the value is a routine, you can update its class with: + + >>> valdoc.specialize_to(RoutineDoc) + """ if not issubclass(cls, self.__class__): - raise ValueError, 'xxx' + raise ValueError('Can not specialize to %r' % cls) + # Update the class. self.__class__ = cls - - # DO THIS [xx]? + # Update the class of any other apidoc's in the mergeset. + if self.__mergeset is not None: + for apidoc in self.__mergeset: + apidoc.__class__ = cls + # Re-initialize self, in case the subclass constructor does + # any special processing on its arguments. self.__init__(**self.__dict__) - # [xx] consider making them un-hashable?? __has_been_hashed = False + """True iff L{self.__hash__()} has ever been called.""" + def __hash__(self): self.__has_been_hashed = True return id(self.__dict__) @@ -372,9 +405,15 @@ def __cmp__(self, other): if not isinstance(other, APIDoc): return -1 if self.__dict__ is other.__dict__: return 0 - else: return -1 - + name_cmp = cmp(self.canonical_name, other.canonical_name) + if name_cmp == 0: return -1 + else: return name_cmp + __mergeset = None + """The set of all C{APIDoc} objects that have been merged with + this C{APIDoc} (using L{merge_and_overwrite()}). Each C{APIDoc} + in this set shares a common instance dictionary (C{__dict__}).""" + def merge_and_overwrite(self, other, ignore_hash_conflict=False): """ Combine C{self} and C{other} into a X{merged object}, such @@ -443,15 +482,11 @@ """ return [] -# [xx] use sorted() to replace sorted_by_name, and make -# APIDoc.__cmp__ use the name?? -def reachable_valdocs(root, sorted_by_name=False, **filters): +def reachable_valdocs(root, **filters): """ Return a list of all C{ValueDoc}s that can be reached, directly or indirectly from the given root list of C{ValueDoc}s. - @param sorted_by_name: If true, then sort the list of reachable - C{ValueDoc}s by name before returning it. @param filters: A set of filters that can be used to prevent C{reachable_valdocs} from following specific link types when looking for C{ValueDoc}s that can be reached from the root @@ -461,9 +496,7 @@ apidoc_queue = list(root) val_set = set() var_set = set() - #if 'private' in filters: log.debug('RR', root) while apidoc_queue: - #if 'private' in filters: log.debug(' ', apidoc_queue) api_doc = apidoc_queue.pop() if isinstance(api_doc, ValueDoc): val_set.add(api_doc) @@ -471,10 +504,7 @@ var_set.add(api_doc) apidoc_queue.extend([v for v in api_doc.apidoc_links(**filters) if v not in val_set and v not in var_set]) - if sorted_by_name: - return sorted(val_set, key=lambda d:d.canonical_name) - else: - return val_set + return val_set ###################################################################### # Variable Documentation Objects @@ -1542,20 +1572,18 @@ # etc #//////////////////////////////////////////////////////////// - def reachable_valdocs(self, sorted_by_name=False, **filters): + def reachable_valdocs(self, **filters): """ Return a list of all C{ValueDoc}s that can be reached, directly or indirectly from this C{DocIndex}'s root set. - @param sorted_by_name: If true, then sort the list of - reachable C{ValueDoc}s by name before returning it. @param filters: A set of filters that can be used to prevent C{reachable_valdocs} from following specific link types when looking for C{ValueDoc}s that can be reached from the root set. See C{APIDoc.apidoc_links} for a more complete description. """ - return reachable_valdocs(self.root, sorted_by_name, **filters) + return reachable_valdocs(self.root, **filters) def container(self, api_doc): """ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2006-04-05 16:52:44
|
Revision: 1167 Author: edloper Date: 2006-04-05 09:52:41 -0700 (Wed, 05 Apr 2006) ViewCVS: http://svn.sourceforge.net/epydoc/?rev=1167&view=rev Log Message: ----------- - Added RoutineDoc.lineno - Added DocIndex.callers and DocIndex.callees, which record which functions have called which other functions. These variables are initialized from pstat profiling information, via the function DocIndex.read_profiling_info() - Fixed grouping comment typo Modified Paths: -------------- trunk/epydoc/src/epydoc/apidoc.py Modified: trunk/epydoc/src/epydoc/apidoc.py =================================================================== --- trunk/epydoc/src/epydoc/apidoc.py 2006-04-05 16:49:40 UTC (rev 1166) +++ trunk/epydoc/src/epydoc/apidoc.py 2006-04-05 16:52:41 UTC (rev 1167) @@ -36,12 +36,12 @@ ## Imports ###################################################################### -import types, re +import types, re, os.path from epydoc import log import epydoc import __builtin__ from epydoc.compat import * # Backwards compatibility -from epydoc.util import decode_with_backslashreplace +from epydoc.util import decode_with_backslashreplace, py_src_filename ###################################################################### # Dotted Names @@ -695,7 +695,7 @@ by the imported value's C{ValueDoc} by L{link_imports()<docbuilder.link_imports>}. @type: L{DottedName}""" - #{ end of "information about imported variables" group + #} end of "information about imported variables" group #: @ivar: #: This is currently used to extract values from __all__, etc, in @@ -1292,6 +1292,12 @@ """@ivar: The name of the routine's keyword argument, or C{None} if it has no keyword argument. @type: C{string} or C{None}""" + lineno = UNKNOWN # used to look up profiling info from pstats. + """@ivar: The line number of the first line of the function's + signature. For Python functions, this is equal to + C{func.func_code.co_firstlineno}. The first line of a file + is considered line 1. + @type: C{int}""" #} end of "signature" group #{ Information Extracted from Docstrings @@ -1448,6 +1454,20 @@ # submodules when appropriate.) self.root = sorted(root, key=lambda d:len(d.canonical_name)) + self.callers = None + """A dictionary mapping from C{RoutineDoc}s in this index + to lists of C{RoutineDoc}s for the routine's callers. + This dictionary is initialized by calling + L{read_profiling_info()}. + @type: C{list} of L{RoutineDoc}""" + + self.callees = None + """A dictionary mapping from C{RoutineDoc}s in this index + to lists of C{RoutineDoc}s for the routine's callees. + This dictionary is initialized by calling + L{read_profiling_info()}. + @type: C{list} of L{RoutineDoc}""" + #//////////////////////////////////////////////////////////// # Lookup methods #//////////////////////////////////////////////////////////// @@ -1611,6 +1631,60 @@ parent = api_doc.canonical_name.container() return self.get_valdoc(parent) + #//////////////////////////////////////////////////////////// + # Profiling information + #//////////////////////////////////////////////////////////// + + def read_profiling_info(self, profile_stats): + """ + Initialize the L{callers} and L{callees} variables, given a + C{Stat} object from the C{pstats} module. + + @warning: This method uses undocumented data structures inside + of C{profile_stats}. + """ + if self.callers is None: self.callers = {} + if self.callees is None: self.callees = {} + + # The Stat object encodes functions using `funcid`s, or + # tuples of (filename, lineno, funcname). Create a mapping + # from these `funcid`s to `RoutineDoc`s. + funcid_to_doc = self._get_funcid_to_doc_mapping(profile_stats) + + for callee, (cc, nc, tt, ct, callers) in profile_stats.stats.items(): + callee = funcid_to_doc.get(callee) + if callee is None: continue + for caller in callers: + caller = funcid_to_doc.get(caller) + if caller is None: continue + self.callers.setdefault(callee, []).append(caller) + self.callees.setdefault(caller, []).append(callee) + + def _get_funcid_to_doc_mapping(self, profile_stats): + """ + Return a dictionary mapping from C{pstat.Stat} funciton ids to + C{RoutineDoc}s. C{pstat.Stat} function ids are tuples of + C{(filename, lineno, funcname)}. + """ + # Maps (filename, lineno, funcname) -> RoutineDoc + funcid_to_doc = {} + for val_doc in self.reachable_valdocs(): + # We only care about routines. + if not isinstance(val_doc, RoutineDoc): continue + # Get the filename from the defining module. + module = val_doc.defining_module + if module is UNKNOWN or module.filename is UNKNOWN: continue + # Normalize the filename. + filename = os.path.abspath(module.filename) + try: filename = py_src_filename(filename) + except: pass + # Look up the stat_func_id + funcid = (filename, val_doc.lineno, val_doc.canonical_name[-1]) + if funcid in profile_stats.stats: + funcid_to_doc[funcid] = val_doc + + return funcid_to_doc + ###################################################################### ## Pretty Printing ###################################################################### This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2006-08-21 14:13:19
|
Revision: 1280 Author: edloper Date: 2006-08-21 07:13:15 -0700 (Mon, 21 Aug 2006) ViewCVS: http://svn.sourceforge.net/epydoc/?rev=1280&view=rev Log Message: ----------- - Fixed a but in pyval_repr (failed when given a tuple value.) Modified Paths: -------------- trunk/epydoc/src/epydoc/apidoc.py Modified: trunk/epydoc/src/epydoc/apidoc.py =================================================================== --- trunk/epydoc/src/epydoc/apidoc.py 2006-08-21 14:05:00 UTC (rev 1279) +++ trunk/epydoc/src/epydoc/apidoc.py 2006-08-21 14:13:15 UTC (rev 1280) @@ -725,7 +725,7 @@ if self.pyval is UNKNOWN: return UNKNOWN try: - s = '%r' % self.pyval + s = '%r' % (self.pyval,) if isinstance(s, str): s = decode_with_backslashreplace(s) return s This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2006-08-23 14:58:37
|
Revision: 1302 Author: edloper Date: 2006-08-23 07:58:34 -0700 (Wed, 23 Aug 2006) ViewCVS: http://svn.sourceforge.net/epydoc/?rev=1302&view=rev Log Message: ----------- - Added __setstate__/__getstate__ to ValueDoc, to make them pickle-able. - Added caches for DocIndex.container() and DocIndex.get() functions. (Based on a patch provided by Daniel von Dincklage.) Modified Paths: -------------- trunk/epydoc/src/epydoc/apidoc.py Modified: trunk/epydoc/src/epydoc/apidoc.py =================================================================== --- trunk/epydoc/src/epydoc/apidoc.py 2006-08-23 07:03:09 UTC (rev 1301) +++ trunk/epydoc/src/epydoc/apidoc.py 2006-08-23 14:58:34 UTC (rev 1302) @@ -36,7 +36,7 @@ ## Imports ###################################################################### -import types, re, os.path +import types, re, os.path, pickle from epydoc import log import epydoc import __builtin__ @@ -735,9 +735,31 @@ return '<%s %s>' % (self.__class__.__name__, self.pyval_repr()) elif self.parse_repr is not UNKNOWN: return '<%s %s>' % (self.__class__.__name__, self.parse_repr) - else: + else: return '<%s>' % self.__class__.__name__ + def __setstate__(self, state): + self.__dict__ = state + + def __getstate__(self): + """ + State serializer for the pickle module. This is necessary + because sometimes the C{pyval} attribute contains an + un-pickleable value. + """ + # Construct our pickled dictionary. Maintain this dictionary + # as a private attribute, so we can reuse it later, since + # merged objects need to share a single dictionary. + if not hasattr(self, '_ValueDoc__pickle_state'): + self.__pickle_state = self.__dict__.copy() + self.__pickle_state['pyval'] = UNKNOWN + self.__pickle_state['_ValueDoc__pyval_repr'] = self.pyval_repr() + + if not isinstance(self, GenericValueDoc): + assert self.__pickle_state != {} + # Return the pickle state. + return self.__pickle_state + def pyval_repr(self): """ Return a string representation of this value based on its pyval; @@ -745,6 +767,8 @@ be replaced by more of a safe-repr variant. """ if self.pyval is UNKNOWN: + if hasattr(self, '_ValueDoc__pyval_repr'): + return self.__pyval_repr # used after unpickling. return UNKNOWN try: s = '%r' % (self.pyval,) @@ -1502,7 +1526,18 @@ @type: C{list} of L{RoutineDoc}""" self._funcid_to_doc = {} + """A mapping from C{profile} function ids to corresponding + C{APIDoc} objects. A function id is a tuple of the form + C{(filename, lineno, funcname)}. This is used to update + the L{callers} and L{calleeds} variables.""" + self._container_cache = {} + """A cache for the L{container()} method, to increase speed.""" + + self._get_cache = {} + """A cache for the L{get_vardoc()} and L{get_valdoc()} methods, + to increase speed.""" + #//////////////////////////////////////////////////////////// # Lookup methods #//////////////////////////////////////////////////////////// @@ -1535,8 +1570,13 @@ and L{get_valdoc()}. """ # Convert name to a DottedName, if necessary. - name = DottedName(name) + if not isinstance(name, DottedName): + name = DottedName(name) + # Check if the result is cached. + val = self._get_cache.get(name) + if val is not None: return val + # Look for an element in the root set whose name is a prefix # of `name`. If we can't find one, then return None. for root_valdoc in self.root: @@ -1551,9 +1591,11 @@ else: # If we found it, then return. if var_doc is not None or val_doc is not None: + self._get_cache[name] = (var_doc, val_doc) return var_doc, val_doc # We didn't find it. + self._get_cache[name] = (None, None) return None, None def _get_from(self, val_doc, identifier): @@ -1655,17 +1697,26 @@ Return the C{ValueDoc} that contains the given C{APIDoc}, or C{None} if its container is not in the index. """ + # Check if the result is cached. + val = self._container_cache.get(api_doc) + if val is not None: return val + if isinstance(api_doc, GenericValueDoc): + self._container_cache[api_doc] = None return None # [xx] unknown. if isinstance(api_doc, VariableDoc): + self._container_cache[api_doc] = api_doc.container return api_doc.container if len(api_doc.canonical_name) == 1: + self._container_cache[api_doc] = None return None elif isinstance(api_doc, ModuleDoc) and api_doc.package is not UNKNOWN: + self._container_cache[api_doc] = api_doc.package return api_doc.package else: - parent = api_doc.canonical_name.container() - return self.get_valdoc(parent) + parent = self.get_valdoc(api_doc.canonical_name.container()) + self._container_cache[api_doc] = parent + return parent #//////////////////////////////////////////////////////////// # Profiling information This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2006-08-23 15:47:15
|
Revision: 1308 Author: edloper Date: 2006-08-23 08:47:09 -0700 (Wed, 23 Aug 2006) ViewCVS: http://svn.sourceforge.net/epydoc/?rev=1308&view=rev Log Message: ----------- - Changed DocIndex.find() to return the VariableDoc instead of the ValueDoc for variables with GenericValueDoc values. Modified Paths: -------------- trunk/epydoc/src/epydoc/apidoc.py Modified: trunk/epydoc/src/epydoc/apidoc.py =================================================================== --- trunk/epydoc/src/epydoc/apidoc.py 2006-08-23 15:38:56 UTC (rev 1307) +++ trunk/epydoc/src/epydoc/apidoc.py 2006-08-23 15:47:09 UTC (rev 1308) @@ -29,6 +29,8 @@ because several variables can contain the same value: each variable should be described by a separate C{VariableDoc}; but we only need one C{ValueDoc}, since they share a single value. + +@todo: Add a cache to canonical name lookup? """ __docformat__ = 'epytext en' @@ -1621,8 +1623,8 @@ def find(self, name, context): """ - Look for a C{ValueDoc} named C{name}, relative to C{context}. - Return the C{ValueDoc} if one is found; otherwise, return + Look for an C{APIDoc} named C{name}, relative to C{context}. + Return the C{APIDoc} if one is found; otherwise, return C{None}. C{find} looks in the following places, in order: - Function parameters (if one matches, return C{None}) - All enclosing namespaces, from closest to furthest. @@ -1632,7 +1634,7 @@ - Parameter attributes @type name: C{str} or L{DottedName} - @type context: L{ValueDoc} + @type context: L{APIDoc} """ if isinstance(name, basestring): name = re.sub(r'\(.*\)$', '', name.strip()) @@ -1653,8 +1655,11 @@ for i in range(len(container_name), -1, -1): relative_name = container_name[:i]+name # Is `name` the absolute name of a documented value? + # (excepting GenericValueDoc values.) val_doc = self.get_valdoc(relative_name) - if val_doc is not None: return val_doc + if (val_doc is not None and + not isinstance(val_doc, GenericValueDoc)): + return val_doc # Is `name` the absolute name of a documented variable? var_doc = self.get_vardoc(relative_name) if var_doc is not None: return var_doc This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2006-09-03 03:40:02
|
Revision: 1346 http://svn.sourceforge.net/epydoc/?rev=1346&view=rev Author: edloper Date: 2006-09-02 20:39:58 -0700 (Sat, 02 Sep 2006) Log Message: ----------- - Various optimizations to make epydoc run faster: - DottedName slicing is now faster - Cache VariableDoc.canonical_name (perhaps I should just assign them all when doing canonical name assignment, and then get rid of the property version?) - Cache pyval_repr - Made submodule check in DocIndex._get_from faster. Modified Paths: -------------- trunk/epydoc/src/epydoc/apidoc.py Modified: trunk/epydoc/src/epydoc/apidoc.py =================================================================== --- trunk/epydoc/src/epydoc/apidoc.py 2006-09-02 01:46:11 UTC (rev 1345) +++ trunk/epydoc/src/epydoc/apidoc.py 2006-09-03 03:39:58 UTC (rev 1346) @@ -87,7 +87,15 @@ contains a string, then it is divided into substrings by splitting on periods, and each substring is checked to see if it is a valid identifier. + + As an optimization, C{pieces} may also contain a single tuple + of values. In that case, that tuple will be used as the + C{DottedName}'s identifiers; it will I{not} be checked to + see if it's valid. """ + if len(pieces) == 1 and isinstance(pieces[0], tuple): + self._identifiers = pieces[0] # Optimization + return if len(pieces) == 0: raise DottedName.InvalidDottedName('Empty DottedName') self._identifiers = [] @@ -148,7 +156,7 @@ """ if isinstance(i, types.SliceType): pieces = self._identifiers[i.start:i.stop] - if pieces: return DottedName(*pieces) + if pieces: return DottedName(pieces) else: return [] else: return self._identifiers[i] @@ -613,28 +621,30 @@ self.name.endswith('_')) def __repr__(self): - if (self.container is not UNKNOWN and - self.container.canonical_name is not UNKNOWN): - return '<%s %s.%s>' % (self.__class__.__name__, - self.container.canonical_name, self.name) + if self.canonical_name is not UNKNOWN: + return '<%s %s>' % (self.__class__.__name__, self.canonical_name) if self.name is not UNKNOWN: return '<%s %s>' % (self.__class__.__name__, self.name) else: return '<%s>' % self.__class__.__name__ def _get_canonical_name(self): - if self.container is UNKNOWN: - raise ValueError, `self` + # Check cache. + canonical_name = getattr(self, '_canonical_name', None) + if canonical_name is not None: return canonical_name + # Otherwise, compute it. if (self.container is UNKNOWN or self.container.canonical_name is UNKNOWN): return UNKNOWN else: - return self.container.canonical_name + self.name - canonical_name = property(_get_canonical_name, doc=""" - A read-only property that can be used to get the variable's - canonical name. This is formed by taking the varaible's - container's cannonical name, and adding the variable's name - to it.""") + self._canonical_name = self.container.canonical_name + self.name + return self._canonical_name + canonical_name = property(_get_canonical_name, + doc="""A read-only property that can be used to get the variable's + canonical name. This is formed by taking the varaible's + container's cannonical name, and adding the variable's name + to it. (The value is cached upon the first successful + look-up.)""") def _get_defining_module(self): if self.container is UNKNOWN: @@ -763,6 +773,11 @@ return self.__pickle_state def pyval_repr(self): + if not hasattr(self, '_pyval_repr'): + self._pyval_repr = self._get_pyval_repr() + return self._pyval_repr + + def _get_pyval_repr(self): """ Return a string representation of this value based on its pyval; or UNKNOWN if we don't succeed. This should probably eventually @@ -1036,9 +1051,10 @@ whose values have the specified type. If C{group} is given, then only return variables that belong to the specified group. - @require: The L{sorted_variables} and L{groups} attributes - must be initialized before this method can be used. See - L{init_sorted_variables()} and L{init_groups()}. + @require: The L{sorted_variables}, L{variable_groups}, and + L{submodule_groups} attributes must be initialized before + this method can be used. See L{init_sorted_variables()} + and L{init_groups()}. @param value_type: A string specifying the value type for which variables should be returned. Valid values are: @@ -1211,9 +1227,10 @@ If C{inherited} is True, then only return inherited variables; if C{inherited} is False, then only return local variables. - @require: The L{sorted_variables} and L{groups} attributes - must be initialized before this method can be used. See - L{init_sorted_variables()} and L{init_groups()}. + @require: The L{sorted_variables} and L{variable_groups} + attributes must be initialized before this method can be + used. See L{init_sorted_variables()} and + L{init_groups()}. @param value_type: A string specifying the value type for which variables should be returned. Valid values are: @@ -1612,8 +1629,7 @@ if (isinstance(val_doc, ModuleDoc) and val_doc.submodules is not UNKNOWN): for submodule in val_doc.submodules: - if (submodule.canonical_name == - DottedName(val_doc.canonical_name, identifier)): + if submodule.canonical_name[-1] == identifier: var_doc = None val_doc = submodule if val_doc is UNKNOWN: val_doc = None This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2006-09-04 04:09:56
|
Revision: 1350 http://svn.sourceforge.net/epydoc/?rev=1350&view=rev Author: edloper Date: 2006-09-03 21:09:52 -0700 (Sun, 03 Sep 2006) Log Message: ----------- - Added DottedName._ok_identifiers cache. (As a profile-driven optimization) Modified Paths: -------------- trunk/epydoc/src/epydoc/apidoc.py Modified: trunk/epydoc/src/epydoc/apidoc.py =================================================================== --- trunk/epydoc/src/epydoc/apidoc.py 2006-09-03 05:31:31 UTC (rev 1349) +++ trunk/epydoc/src/epydoc/apidoc.py 2006-09-04 04:09:52 UTC (rev 1350) @@ -76,6 +76,10 @@ An exception raised by the DottedName constructor when one of its arguments is not a valid dotted name. """ + + _ok_identifiers = set() + """A cache of identifier strings that have been checked against + _IDENTIFIER_RE and found to be acceptable.""" def __init__(self, *pieces): """ @@ -104,13 +108,16 @@ self._identifiers += piece._identifiers elif isinstance(piece, basestring): for subpiece in piece.split('.'): - if not self._IDENTIFIER_RE.match(subpiece): - raise DottedName.InvalidDottedName( - 'Bad identifier %r' % (piece,)) + if piece not in self._ok_identifiers: + if self._IDENTIFIER_RE.match(subpiece): + self._ok_identifiers.add(piece) + else: + raise DottedName.InvalidDottedName( + 'Bad identifier %r' % (piece,)) self._identifiers.append(subpiece) else: - raise DottedName.InvalidDottedName( - 'Bad identifier %r' % (piece,)) + raise TypeError('Bad identifier %r: expected ' + 'DottedName or str' % (piece,)) self._identifiers = tuple(self._identifiers) def __repr__(self): This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2006-09-06 23:45:03
|
Revision: 1359 http://svn.sourceforge.net/epydoc/?rev=1359&view=rev Author: edloper Date: 2006-09-06 16:44:59 -0700 (Wed, 06 Sep 2006) Log Message: ----------- - Changed APIDoc.pp() to display full names for variables. Modified Paths: -------------- trunk/epydoc/src/epydoc/apidoc.py Modified: trunk/epydoc/src/epydoc/apidoc.py =================================================================== --- trunk/epydoc/src/epydoc/apidoc.py 2006-09-06 20:06:18 UTC (rev 1358) +++ trunk/epydoc/src/epydoc/apidoc.py 2006-09-06 23:44:59 UTC (rev 1359) @@ -1809,8 +1809,15 @@ api_doc.canonical_name not in (None, UNKNOWN)): name = '%s for %s' % (api_doc.__class__.__name__, api_doc.canonical_name) - elif hasattr(api_doc, 'name') and api_doc.name not in (UNKNOWN, None): - name = '%s for %s' % (api_doc.__class__.__name__, api_doc.name) + elif getattr(api_doc, 'name', None) not in (UNKNOWN, None): + if (getattr(api_doc, 'container', None) not in (UNKNOWN, None) and + getattr(api_doc.container, 'canonical_name', None) + not in (UNKNOWN, None)): + name ='%s for %s' % (api_doc.__class__.__name__, + api_doc.container.canonical_name+ + api_doc.name) + else: + name = '%s for %s' % (api_doc.__class__.__name__, api_doc.name) else: name = api_doc.__class__.__name__ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <dva...@us...> - 2007-02-10 20:34:08
|
Revision: 1446 http://svn.sourceforge.net/epydoc/?rev=1446&view=rev Author: dvarrazzo Date: 2007-02-10 12:34:07 -0800 (Sat, 10 Feb 2007) Log Message: ----------- - Still more relaxed regexpr to identify valid dotted names, to allow names such 'badguy.00_evilinside'. See SF bug #1649347. Modified Paths: -------------- trunk/epydoc/src/epydoc/apidoc.py Modified: trunk/epydoc/src/epydoc/apidoc.py =================================================================== --- trunk/epydoc/src/epydoc/apidoc.py 2007-02-10 19:55:33 UTC (rev 1445) +++ trunk/epydoc/src/epydoc/apidoc.py 2007-02-10 20:34:07 UTC (rev 1446) @@ -63,9 +63,11 @@ """ UNREACHABLE = "??" _IDENTIFIER_RE = re.compile("""(?x) - (%s | # UNREACHABLE marker, or... - script-\w+ | # Script name, or ... - [a-zA-Z_]\w*'?) # Identifier. (' used for shadowing submodules) + (%s | # UNREACHABLE marker, or.. + (script-)? # Prefix: script (not a module) + \w+ # Identifier (yes, identifiers starting with a + # digit are allowed. See SF bug #1649347) + '?) # Suffix: submodule that is shadowed by a var (-\d+)? # Suffix: unreachable vals with the same name $""" % re.escape(UNREACHABLE)) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2007-02-14 06:15:19
|
Revision: 1500 http://svn.sourceforge.net/epydoc/?rev=1500&view=rev Author: edloper Date: 2007-02-13 22:15:18 -0800 (Tue, 13 Feb 2007) Log Message: ----------- - Fixed SF bug #1659520 (although I'm not entirely happy with the fix) Modified Paths: -------------- trunk/epydoc/src/epydoc/apidoc.py Modified: trunk/epydoc/src/epydoc/apidoc.py =================================================================== --- trunk/epydoc/src/epydoc/apidoc.py 2007-02-14 06:12:22 UTC (rev 1499) +++ trunk/epydoc/src/epydoc/apidoc.py 2007-02-14 06:15:18 UTC (rev 1500) @@ -679,6 +679,16 @@ def is_detailed(self): if (self.value in (None, UNKNOWN)): return super(VariableDoc, self).is_detailed() + if isinstance(self.value, GenericValueDoc): + # [XX] This is a little hackish -- we assume that the + # summary lines will have SUMMARY_REPR_LINELEN chars, + # that len(name) of those will be taken up by the name, + # and that 3 of those will be taken up by " = " between + # the name & val. Note that if any docwriter uses a + # different formula for maxlen for this, then it will + # not get the right value for is_detailed(). + maxlen = self.value.SUMMARY_REPR_LINELEN-3-len(self.name) + return (not self.value.summary_pyval_repr(maxlen).is_complete) else: return self.value.is_detailed() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <dva...@us...> - 2007-03-25 13:37:16
|
Revision: 1588 http://svn.sourceforge.net/epydoc/?rev=1588&view=rev Author: dvarrazzo Date: 2007-03-25 06:37:13 -0700 (Sun, 25 Mar 2007) Log Message: ----------- - `init_sorted_variables()` really called. Currently the docbuilder always calls it before, so this row is actually never reached. Modified Paths: -------------- trunk/epydoc/src/epydoc/apidoc.py Modified: trunk/epydoc/src/epydoc/apidoc.py =================================================================== --- trunk/epydoc/src/epydoc/apidoc.py 2007-03-20 00:58:51 UTC (rev 1587) +++ trunk/epydoc/src/epydoc/apidoc.py 2007-03-25 13:37:13 UTC (rev 1588) @@ -1010,7 +1010,7 @@ L{sorted_variables} and L{group_specs} attributes. """ if self.sorted_variables is UNKNOWN: - self.init_sorted_variables + self.init_sorted_variables() assert len(self.sorted_variables) == len(self.variables) elts = [(v.name, v) for v in self.sorted_variables] This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2007-09-23 02:17:27
|
Revision: 1606 http://epydoc.svn.sourceforge.net/epydoc/?rev=1606&view=rev Author: edloper Date: 2007-09-22 19:17:25 -0700 (Sat, 22 Sep 2007) Log Message: ----------- - If we find a name that violated DottedName._IDENTIFIER_RE, then issue a warning rather than raising an exception. This shouldn't *normally* happen, but it can happen, eg if someone directly modifies globals() or uses __import__. Fixes debian bug #433424, and SF bugs 1760011, 1796723 (partial). Modified Paths: -------------- trunk/epydoc/src/epydoc/apidoc.py Modified: trunk/epydoc/src/epydoc/apidoc.py =================================================================== --- trunk/epydoc/src/epydoc/apidoc.py 2007-09-23 01:48:58 UTC (rev 1605) +++ trunk/epydoc/src/epydoc/apidoc.py 2007-09-23 02:17:25 UTC (rev 1606) @@ -111,11 +111,12 @@ elif isinstance(piece, basestring): for subpiece in piece.split('.'): if piece not in self._ok_identifiers: - if self._IDENTIFIER_RE.match(subpiece): - self._ok_identifiers.add(piece) - else: - raise DottedName.InvalidDottedName( - 'Bad identifier %r' % (piece,)) + if not self._IDENTIFIER_RE.match(subpiece): + #raise DottedName.InvalidDottedName( + # 'Bad identifier %r' % (piece,)) + log.warning("Identifier %r looks suspicious; " + "using it anyway." % piece) + self._ok_identifiers.add(piece) self._identifiers.append(subpiece) else: raise TypeError('Bad identifier %r: expected ' This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2007-09-26 04:00:56
|
Revision: 1651 http://epydoc.svn.sourceforge.net/epydoc/?rev=1651&view=rev Author: edloper Date: 2007-09-25 21:00:55 -0700 (Tue, 25 Sep 2007) Log Message: ----------- - Don't issue @sort warnings for special vars __all__, __docformat__, and __path__, since they get supressed by epydoc.docparser. Modified Paths: -------------- trunk/epydoc/src/epydoc/apidoc.py Modified: trunk/epydoc/src/epydoc/apidoc.py =================================================================== --- trunk/epydoc/src/epydoc/apidoc.py 2007-09-26 03:48:06 UTC (rev 1650) +++ trunk/epydoc/src/epydoc/apidoc.py 2007-09-26 04:00:55 UTC (rev 1651) @@ -1007,8 +1007,9 @@ self.sorted_variables.append(unsorted.pop(name)) unused_idents.discard(ident) for ident in unused_idents: - log.warning("@sort: %s.%s not found" % - (self.canonical_name, ident)) + if ident not in ['__all__', '__docformat__', '__path__']: + log.warning("@sort: %s.%s not found" % + (self.canonical_name, ident)) # Add any remaining variables in alphabetical order. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <dva...@us...> - 2007-11-07 15:23:47
|
Revision: 1662 http://epydoc.svn.sourceforge.net/epydoc/?rev=1662&view=rev Author: dvarrazzo Date: 2007-11-07 07:23:41 -0800 (Wed, 07 Nov 2007) Log Message: ----------- - Don't crash with a group containing only submodules which are not variables (because they are contained in but not imported by a package). Modified Paths: -------------- trunk/epydoc/src/epydoc/apidoc.py Modified: trunk/epydoc/src/epydoc/apidoc.py =================================================================== --- trunk/epydoc/src/epydoc/apidoc.py 2007-11-07 12:59:34 UTC (rev 1661) +++ trunk/epydoc/src/epydoc/apidoc.py 2007-11-07 15:23:41 UTC (rev 1662) @@ -1201,7 +1201,7 @@ if group is None: var_list = self.sorted_variables else: - var_list = self.variable_groups[group] + var_list = self.variable_groups.get(group, self.sorted_variables) # Public/private filter (Count UNKNOWN as public) if public is True: This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2008-01-29 17:13:08
|
Revision: 1675 http://epydoc.svn.sourceforge.net/epydoc/?rev=1675&view=rev Author: edloper Date: 2008-01-29 09:12:56 -0800 (Tue, 29 Jan 2008) Log Message: ----------- - Added 'overrides' filter, which is False by default. Modified Paths: -------------- trunk/epydoc/src/epydoc/apidoc.py Modified: trunk/epydoc/src/epydoc/apidoc.py =================================================================== --- trunk/epydoc/src/epydoc/apidoc.py 2008-01-29 06:03:36 UTC (rev 1674) +++ trunk/epydoc/src/epydoc/apidoc.py 2008-01-29 17:12:56 UTC (rev 1675) @@ -544,6 +544,8 @@ - C{subclasses}: Subclasses for classes. - C{variables}: All variables. - C{private}: Private variables. + - C{overrides}: Points from class variables to the variables + they override. This filter is False by default. """ return [] @@ -677,10 +679,16 @@ of the variable's container.""") def apidoc_links(self, **filters): + # nb: overrides filter is *False* by default. + if (filters.get('overrides', False) and + (self.overrides not in (None, UNKNOWN))): + overrides = [self.overrides] + else: + overrides = [] if self.value in (None, UNKNOWN): - return [] + return []+overrides else: - return [self.value] + return [self.value]+overrides def is_detailed(self): pval = super(VariableDoc, self).is_detailed() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2008-02-16 04:51:01
|
Revision: 1727 http://epydoc.svn.sourceforge.net/epydoc/?rev=1727&view=rev Author: edloper Date: 2008-02-15 20:50:59 -0800 (Fri, 15 Feb 2008) Log Message: ----------- - In mro calculation: if there's an inconsistent base class hierarchy, then print an error and recover using depth first search. Modified Paths: -------------- trunk/epydoc/src/epydoc/apidoc.py Modified: trunk/epydoc/src/epydoc/apidoc.py =================================================================== --- trunk/epydoc/src/epydoc/apidoc.py 2008-02-16 04:49:50 UTC (rev 1726) +++ trunk/epydoc/src/epydoc/apidoc.py 2008-02-16 04:50:59 UTC (rev 1727) @@ -1297,7 +1297,13 @@ def mro(self, warn_about_bad_bases=False): if self.is_newstyle_class(): - return self._c3_mro(warn_about_bad_bases) + try: + return self._c3_mro(warn_about_bad_bases) + except ValueError, e: # (inconsistent hierarchy) + log.error('Error finding mro for %s: %s' % + (self.canonical_name, e)) + # Better than nothing: + return self._dfs_bases([], set(), warn_about_bad_bases) else: return self._dfs_bases([], set(), warn_about_bad_bases) @@ -1355,7 +1361,7 @@ nothead=[s for s in nonemptyseqs if cand in s[1:]] if nothead: cand=None #reject candidate else: break - if not cand: raise "Inconsistent hierarchy" + if not cand: raise ValueError("Inconsistent hierarchy") res.append(cand) for seq in nonemptyseqs: # remove cand if seq[0] == cand: del seq[0] This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2008-02-19 16:49:21
|
Revision: 1729 http://epydoc.svn.sourceforge.net/epydoc/?rev=1729&view=rev Author: edloper Date: 2008-02-19 08:49:16 -0800 (Tue, 19 Feb 2008) Log Message: ----------- - Fixed typo in error message Modified Paths: -------------- trunk/epydoc/src/epydoc/apidoc.py Modified: trunk/epydoc/src/epydoc/apidoc.py =================================================================== --- trunk/epydoc/src/epydoc/apidoc.py 2008-02-18 18:25:40 UTC (rev 1728) +++ trunk/epydoc/src/epydoc/apidoc.py 2008-02-19 16:49:16 UTC (rev 1729) @@ -506,7 +506,7 @@ if other.__has_been_hashed and not ignore_hash_conflict: raise ValueError("%r has already been hashed! Merging it " - "would cause its has value to change." % other) + "would cause its hash value to change." % other) # If other was itself already merged with anything, # then we need to merge those too. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2006-04-06 04:29:08
|
Revision: 1176 Author: edloper Date: 2006-04-05 21:29:04 -0700 (Wed, 05 Apr 2006) ViewCVS: http://svn.sourceforge.net/epydoc/?rev=1176&view=rev Log Message: ----------- - Minor changes to profiling info reader function (so that read_profiling_info) can be called multiple times) Modified Paths: -------------- trunk/epydoc/src/epydoc/apidoc.py Modified: trunk/epydoc/src/epydoc/apidoc.py =================================================================== --- trunk/epydoc/src/epydoc/apidoc.py 2006-04-05 22:05:32 UTC (rev 1175) +++ trunk/epydoc/src/epydoc/apidoc.py 2006-04-06 04:29:04 UTC (rev 1176) @@ -1468,6 +1468,8 @@ L{read_profiling_info()}. @type: C{list} of L{RoutineDoc}""" + self._funcid_to_doc = {} + #//////////////////////////////////////////////////////////// # Lookup methods #//////////////////////////////////////////////////////////// @@ -1649,25 +1651,24 @@ # The Stat object encodes functions using `funcid`s, or # tuples of (filename, lineno, funcname). Create a mapping # from these `funcid`s to `RoutineDoc`s. - funcid_to_doc = self._get_funcid_to_doc_mapping(profile_stats) + self._update_funcid_to_doc(profile_stats) for callee, (cc, nc, tt, ct, callers) in profile_stats.stats.items(): - callee = funcid_to_doc.get(callee) + callee = self._funcid_to_doc.get(callee) if callee is None: continue for caller in callers: - caller = funcid_to_doc.get(caller) + caller = self._funcid_to_doc.get(caller) if caller is None: continue self.callers.setdefault(callee, []).append(caller) self.callees.setdefault(caller, []).append(callee) - def _get_funcid_to_doc_mapping(self, profile_stats): + def _update_funcid_to_doc(self, profile_stats): """ - Return a dictionary mapping from C{pstat.Stat} funciton ids to + Update the dictionary mapping from C{pstat.Stat} funciton ids to C{RoutineDoc}s. C{pstat.Stat} function ids are tuples of C{(filename, lineno, funcname)}. """ # Maps (filename, lineno, funcname) -> RoutineDoc - funcid_to_doc = {} for val_doc in self.reachable_valdocs(): # We only care about routines. if not isinstance(val_doc, RoutineDoc): continue @@ -1681,10 +1682,8 @@ # Look up the stat_func_id funcid = (filename, val_doc.lineno, val_doc.canonical_name[-1]) if funcid in profile_stats.stats: - funcid_to_doc[funcid] = val_doc + self._funcid_to_doc[funcid] = val_doc - return funcid_to_doc - ###################################################################### ## Pretty Printing ###################################################################### This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2006-04-09 21:17:20
|
Revision: 1203 Author: edloper Date: 2006-04-09 14:17:16 -0700 (Sun, 09 Apr 2006) ViewCVS: http://svn.sourceforge.net/epydoc/?rev=1203&view=rev Log Message: ----------- - Fixed minor bug in pp() Modified Paths: -------------- trunk/epydoc/src/epydoc/apidoc.py Modified: trunk/epydoc/src/epydoc/apidoc.py =================================================================== --- trunk/epydoc/src/epydoc/apidoc.py 2006-04-09 20:57:52 UTC (rev 1202) +++ trunk/epydoc/src/epydoc/apidoc.py 2006-04-09 21:17:16 UTC (rev 1203) @@ -1705,10 +1705,10 @@ pyid = id(api_doc.__dict__) if backpointers is None: backpointers = {} if (hasattr(api_doc, 'canonical_name') and - api_doc.canonical_name is not UNKNOWN): + api_doc.canonical_name not in (None, UNKNOWN)): name = '%s for %s' % (api_doc.__class__.__name__, api_doc.canonical_name) - elif hasattr(api_doc, 'name') and api_doc.name is not UNKNOWN: + elif hasattr(api_doc, 'name') and api_doc.name not in (UNKNOWN, None): name = '%s for %s' % (api_doc.__class__.__name__, api_doc.name) else: name = api_doc.__class__.__name__ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2006-08-21 11:00:21
|
Revision: 1266 Author: edloper Date: 2006-08-21 04:00:15 -0700 (Mon, 21 Aug 2006) ViewCVS: http://svn.sourceforge.net/epydoc/?rev=1266&view=rev Log Message: ----------- - Added RoutineDoc.decorators Modified Paths: -------------- trunk/epydoc/src/epydoc/apidoc.py Modified: trunk/epydoc/src/epydoc/apidoc.py =================================================================== --- trunk/epydoc/src/epydoc/apidoc.py 2006-08-21 10:33:55 UTC (rev 1265) +++ trunk/epydoc/src/epydoc/apidoc.py 2006-08-21 11:00:15 UTC (rev 1266) @@ -1300,6 +1300,14 @@ @type: C{int}""" #} end of "signature" group + #{ Decorators + decorators = UNKNOWN + """@ivar: A list of names of decorators that were applied to this + routine, in the order that they are listed in the source code. + (I.e., in the reverse of the order that they were applied in.) + @type: C{list} of L{string}""" + #} end of "decorators" group + #{ Information Extracted from Docstrings arg_descrs = UNKNOWN """@ivar: A list of descriptions of the routine's This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2006-08-22 21:46:30
|
Revision: 1297 Author: edloper Date: 2006-08-22 14:46:27 -0700 (Tue, 22 Aug 2006) ViewCVS: http://svn.sourceforge.net/epydoc/?rev=1297&view=rev Log Message: ----------- - optimized DottedName.contextualize() and DottedName.dominates() for speed (based on patch provided by Daniel von Dincklage) Modified Paths: -------------- trunk/epydoc/src/epydoc/apidoc.py Modified: trunk/epydoc/src/epydoc/apidoc.py =================================================================== --- trunk/epydoc/src/epydoc/apidoc.py 2006-08-22 16:46:03 UTC (rev 1296) +++ trunk/epydoc/src/epydoc/apidoc.py 2006-08-22 21:46:27 UTC (rev 1297) @@ -192,9 +192,15 @@ >>> DottedName('a.b').dominates(DottedName('a.b.c.d')) True """ - if strict and len(self._identifiers)==len(name._identifiers): + len_self = len(self._identifiers) + len_name = len(name._identifiers) + + if (len_self > len_name) or (strict and len_self == len_name): return False - return self._identifiers == name._identifiers[:len(self)] + # The following is redundant (the first clause is implied by + # the second), but is done as an optimization. + return ((self._identifiers[0] == name._identifiers[0]) and + self._identifiers == name._identifiers[:len_self]) def contextualize(self, context): """ @@ -217,6 +223,22 @@ else: return self + # Find the first index where self & context differ. + for i in range(min(len(context), len(self))): + if self._identifiers[i] != context._identifiers[i]: + first_difference = i + break + else: + first_difference = i+1 + + # Strip off anything before that index. + if first_difference == 0: + return self + elif first_difference == len(self): + return self[-1:] + else: + return self[first_difference:] + ###################################################################### # UNKNOWN Value ###################################################################### This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2006-09-07 15:54:38
|
Revision: 1365 http://svn.sourceforge.net/epydoc/?rev=1365&view=rev Author: edloper Date: 2006-09-07 08:54:31 -0700 (Thu, 07 Sep 2006) Log Message: ----------- - Updated the description of RoutineDoc.arg_descrs to be more accurate Modified Paths: -------------- trunk/epydoc/src/epydoc/apidoc.py Modified: trunk/epydoc/src/epydoc/apidoc.py =================================================================== --- trunk/epydoc/src/epydoc/apidoc.py 2006-09-07 02:17:59 UTC (rev 1364) +++ trunk/epydoc/src/epydoc/apidoc.py 2006-09-07 15:54:31 UTC (rev 1365) @@ -1371,9 +1371,9 @@ #{ Information Extracted from Docstrings arg_descrs = UNKNOWN """@ivar: A list of descriptions of the routine's - arguments. Each element of this list is a tuple C{(arg, - descr)}, where C{arg} is an argument name (or a tuple of - of argument names); and C{descr} is a L{ParsedDocstring + arguments. Each element of this list is a tuple C{(args, + descr)}, where C{args} is a list of argument names; and + C{descr} is a L{ParsedDocstring <epydoc.markup.ParsedDocstring>} describing the argument(s) specified by C{arg}. @type: C{list}""" This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2006-09-10 22:43:05
|
Revision: 1381 http://svn.sourceforge.net/epydoc/?rev=1381&view=rev Author: edloper Date: 2006-09-10 15:43:02 -0700 (Sun, 10 Sep 2006) Log Message: ----------- - When checking keyword args to APIDoc constructor, don't complain about args that begin with '_'. - Minor docstring changes Modified Paths: -------------- trunk/epydoc/src/epydoc/apidoc.py Modified: trunk/epydoc/src/epydoc/apidoc.py =================================================================== --- trunk/epydoc/src/epydoc/apidoc.py 2006-09-10 16:31:38 UTC (rev 1380) +++ trunk/epydoc/src/epydoc/apidoc.py 2006-09-10 22:43:02 UTC (rev 1381) @@ -374,7 +374,7 @@ """ if epydoc.DEBUG: for key in kwargs: - if not hasattr(self.__class__, key): + if key[0] != '_' and not hasattr(self.__class__, key): raise TypeError('%s got unexpected arg %r' % (self.__class__.__name__, key)) self.__dict__.update(kwargs) @@ -850,7 +850,7 @@ names, and the values are lists of C{VariableDoc}s. The order that groups should be listed in should be taken from L{group_specs}. - @type: C{dict} from C{str} to C{list} of L{APIDoc}""" + @type: C{dict} from C{str} to C{list} of L{VariableDoc}""" #} end of group "information about variables" def __init__(self, **kwargs): @@ -996,7 +996,7 @@ names, and the values are lists of C{ModuleDoc}s. The order that groups should be listed in should be taken from L{group_specs}. - @type: C{dict} from C{str} to C{list} of L{APIDoc}""" + @type: C{dict} from C{str} to C{list} of L{ModuleDoc}""" #{ Information about Packages package = UNKNOWN """@ivar: API documentation for the module's containing package. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2007-02-03 03:51:07
|
Revision: 1429 http://svn.sourceforge.net/epydoc/?rev=1429&view=rev Author: edloper Date: 2007-02-02 19:51:05 -0800 (Fri, 02 Feb 2007) Log Message: ----------- - Relaxed the regular expression DottedName._IDENTIFIER_RE, to allow for names like "script-00_info_py". (sf bug #1649347) Modified Paths: -------------- trunk/epydoc/src/epydoc/apidoc.py Modified: trunk/epydoc/src/epydoc/apidoc.py =================================================================== --- trunk/epydoc/src/epydoc/apidoc.py 2007-01-30 11:35:50 UTC (rev 1428) +++ trunk/epydoc/src/epydoc/apidoc.py 2007-02-03 03:51:05 UTC (rev 1429) @@ -63,10 +63,9 @@ """ UNREACHABLE = "??" _IDENTIFIER_RE = re.compile("""(?x) - (%s | # UNREACHABLE marker, or.. - (script-)? # Prefix: script (not a module) - [a-zA-Z_]\w* # Identifier - '?) # Suffix: submodule that is shadowed by a var + (%s | # UNREACHABLE marker, or... + script-\w+ | # Script name, or ... + [a-zA-Z_]\w*'?) # Identifier. (' used for shadowing submodules) (-\d+)? # Suffix: unreachable vals with the same name $""" % re.escape(UNREACHABLE)) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <dva...@us...> - 2007-02-11 00:05:36
|
Revision: 1448 http://svn.sourceforge.net/epydoc/?rev=1448&view=rev Author: dvarrazzo Date: 2007-02-10 16:05:34 -0800 (Sat, 10 Feb 2007) Log Message: ----------- - if find() fails, also look for classes name defined in each module and return them if not ambiguous. Modified Paths: -------------- trunk/epydoc/src/epydoc/apidoc.py Modified: trunk/epydoc/src/epydoc/apidoc.py =================================================================== --- trunk/epydoc/src/epydoc/apidoc.py 2007-02-10 22:19:35 UTC (rev 1447) +++ trunk/epydoc/src/epydoc/apidoc.py 2007-02-11 00:05:34 UTC (rev 1448) @@ -1669,8 +1669,31 @@ # Initialize the root items list. We sort them by length in # ascending order. (This ensures that variables will shadow # submodules when appropriate.) - self.root = sorted(root, key=lambda d:len(d.canonical_name)) + # When the elements name is the same, list in alphabetical order: + # this is needed by the check for duplicates below. + self.root = sorted(root, + key=lambda d: (len(d.canonical_name), d.canonical_name)) + """The list of C{ValueDoc}s to document. + @type: C{list}""" + # Drop duplicated modules + # [xx] maybe what causes duplicates should be fixed instead. + # If fixed, adjust the sort here above: sorting by names will not + # be required anymore + i = 1 + while i < len(self.root): + if self.root[i-1] is self.root[i]: + del self.root[i] + else: + i += 1 + + self.mlclasses = self._get_module_classes(self.root) + """A mapping from class names to L{ClassDoc}. Contains + classes defined at module level for modules in L{root} + and which can be used as fallback by L{find()} if looking + in containing namespaces fails. + @type: C{dict} from C{str} to L{ClassDoc} or C{list}""" + self.callers = None """A dictionary mapping from C{RoutineDoc}s in this index to lists of C{RoutineDoc}s for the routine's callers. @@ -1789,6 +1812,7 @@ look for the remaining part of the name using C{find} - Builtins - Parameter attributes + - Classes at module level (if the name is not ambiguous) @type name: C{str} or L{DottedName} @type context: L{APIDoc} @@ -1837,6 +1861,57 @@ if all_args is not UNKNOWN and name[0] in all_args: return None + # Is this an object directly contained by any module? + doc = self.mlclasses.get(name[-1]) + if isinstance(doc, APIDoc): + return doc + elif isinstance(doc, list): + log.warning("%s is an ambiguous name: it may be %s" % ( + name[-1], + ", ".join([ "'%s'" % d.canonical_name for d in doc ]))) + + # Drop this item so that the warning is reported only once. + # fail() will fail anyway. + del self.mlclasses[name[-1]] + + def _get_module_classes(self, docs): + """ + Gather all the classes defined in a list of modules. + + Very often people refers to classes only by class name, + even if they are not imported in the namespace. Linking + to such classes will fail if we look for them only in nested + namespaces. Allow them to retrieve only by name. + + @param docs: containers of the objects to collect + @type docs: C{list} of C{APIDoc} + @return: mapping from objects name to the object(s) with that name + @rtype: C{dict} from C{str} to L{ClassDoc} or C{list} + """ + classes = {} + for doc in docs: + if not isinstance(doc, ModuleDoc): + continue + + for var in doc.variables.values(): + if not isinstance(var.value, ClassDoc): + continue + + val = var.value + if val in (None, UNKNOWN) or val.defining_module is not doc: + continue + + name = val.canonical_name[-1] + vals = classes.get(name) + if vals is None: + classes[name] = val + elif not isinstance(vals, list): + classes[name] = [ vals, val ] + else: + vals.append(val) + + return classes + #//////////////////////////////////////////////////////////// # etc #//////////////////////////////////////////////////////////// This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |