buildframework/helium/external/python/lib/common/Sphinx-0.5.1-py2.5.egg/sphinx/util/__init__.py
changeset 179 d8ac696cc51f
equal deleted inserted replaced
1:be27ed110b50 179:d8ac696cc51f
       
     1 # -*- coding: utf-8 -*-
       
     2 """
       
     3     sphinx.util
       
     4     ~~~~~~~~~~~
       
     5 
       
     6     Utility functions for Sphinx.
       
     7 
       
     8     :copyright: 2007-2008 by Georg Brandl.
       
     9     :license: BSD.
       
    10 """
       
    11 
       
    12 import os
       
    13 import re
       
    14 import sys
       
    15 import time
       
    16 import fnmatch
       
    17 import tempfile
       
    18 import traceback
       
    19 from os import path
       
    20 
       
    21 
       
    22 # Generally useful regular expressions.
       
    23 ws_re = re.compile(r'\s+')
       
    24 caption_ref_re = re.compile(r'^([^<]+?)\s*<(.+)>$')
       
    25 
       
    26 
       
    27 # SEP separates path elements in the canonical file names
       
    28 #
       
    29 # Define SEP as a manifest constant, not so much because we expect it to change
       
    30 # in the future as to avoid the suspicion that a stray "/" in the code is a
       
    31 # hangover from more *nix-oriented origins.
       
    32 SEP = "/"
       
    33 
       
    34 def os_path(canonicalpath):
       
    35     return canonicalpath.replace(SEP, os.path.sep)
       
    36 
       
    37 
       
    38 def relative_uri(base, to):
       
    39     """Return a relative URL from ``base`` to ``to``."""
       
    40     b2 = base.split(SEP)
       
    41     t2 = to.split(SEP)
       
    42     # remove common segments
       
    43     for x, y in zip(b2, t2):
       
    44         if x != y:
       
    45             break
       
    46         b2.pop(0)
       
    47         t2.pop(0)
       
    48     return ('..' + SEP) * (len(b2)-1) + SEP.join(t2)
       
    49 
       
    50 
       
    51 def ensuredir(path):
       
    52     """Ensure that a path exists."""
       
    53     try:
       
    54         os.makedirs(path)
       
    55     except OSError, err:
       
    56         if not err.errno == 17:
       
    57             raise
       
    58 
       
    59 
       
    60 def walk(top, topdown=True, followlinks=False):
       
    61     """
       
    62     Backport of os.walk from 2.6, where the followlinks argument was added.
       
    63     """
       
    64     names = os.listdir(top)
       
    65 
       
    66     dirs, nondirs = [], []
       
    67     for name in names:
       
    68         if path.isdir(path.join(top, name)):
       
    69             dirs.append(name)
       
    70         else:
       
    71             nondirs.append(name)
       
    72 
       
    73     if topdown:
       
    74         yield top, dirs, nondirs
       
    75     for name in dirs:
       
    76         fullpath = path.join(top, name)
       
    77         if followlinks or not path.islink(fullpath):
       
    78             for x in walk(fullpath, topdown, followlinks):
       
    79                 yield x
       
    80     if not topdown:
       
    81         yield top, dirs, nondirs
       
    82 
       
    83 
       
    84 def get_matching_docs(dirname, suffix, exclude_docs=(), exclude_dirs=(),
       
    85                       exclude_trees=(), exclude_dirnames=()):
       
    86     """
       
    87     Get all file names (without suffix) matching a suffix in a
       
    88     directory, recursively.
       
    89 
       
    90     Exclude docs in *exclude_docs*, exclude dirs in *exclude_dirs*,
       
    91     prune dirs in *exclude_trees*, prune dirnames in *exclude_dirnames*.
       
    92     """
       
    93     pattern = '*' + suffix
       
    94     # dirname is a normalized absolute path.
       
    95     dirname = path.normpath(path.abspath(dirname))
       
    96     dirlen = len(dirname) + 1    # exclude slash
       
    97     for root, dirs, files in walk(dirname, followlinks=True):
       
    98         if root[dirlen:] in exclude_dirs:
       
    99             continue
       
   100         if root[dirlen:] in exclude_trees:
       
   101             del dirs[:]
       
   102             continue
       
   103         dirs.sort()
       
   104         files.sort()
       
   105         for prunedir in exclude_dirnames:
       
   106             if prunedir in dirs:
       
   107                 dirs.remove(prunedir)
       
   108         for sfile in files:
       
   109             if not fnmatch.fnmatch(sfile, pattern):
       
   110                 continue
       
   111             qualified_name = path.join(root[dirlen:], sfile[:-len(suffix)])
       
   112             qualified_name = qualified_name.replace(os.path.sep, SEP)
       
   113             if qualified_name in exclude_docs:
       
   114                 continue
       
   115             yield qualified_name
       
   116 
       
   117 
       
   118 def mtimes_of_files(dirnames, suffix):
       
   119     for dirname in dirnames:
       
   120         for root, dirs, files in os.walk(dirname):
       
   121             for sfile in files:
       
   122                 if sfile.endswith(suffix):
       
   123                     try:
       
   124                         yield path.getmtime(path.join(root, sfile))
       
   125                     except EnvironmentError:
       
   126                         pass
       
   127 
       
   128 
       
   129 def shorten_result(text='', keywords=[], maxlen=240, fuzz=60):
       
   130     if not text:
       
   131         text = ''
       
   132     text_low = text.lower()
       
   133     beg = -1
       
   134     for k in keywords:
       
   135         i = text_low.find(k.lower())
       
   136         if (i > -1 and i < beg) or beg == -1:
       
   137             beg = i
       
   138     excerpt_beg = 0
       
   139     if beg > fuzz:
       
   140         for sep in ('.', ':', ';', '='):
       
   141             eb = text.find(sep, beg - fuzz, beg - 1)
       
   142             if eb > -1:
       
   143                 eb += 1
       
   144                 break
       
   145         else:
       
   146             eb = beg - fuzz
       
   147         excerpt_beg = eb
       
   148     if excerpt_beg < 0:
       
   149         excerpt_beg = 0
       
   150     msg = text[excerpt_beg:beg+maxlen]
       
   151     if beg > fuzz:
       
   152         msg = '... ' + msg
       
   153     if beg < len(text)-maxlen:
       
   154         msg = msg + ' ...'
       
   155     return msg
       
   156 
       
   157 
       
   158 class attrdict(dict):
       
   159     def __getattr__(self, key):
       
   160         return self[key]
       
   161     def __setattr__(self, key, val):
       
   162         self[key] = val
       
   163     def __delattr__(self, key):
       
   164         del self[key]
       
   165 
       
   166 
       
   167 def fmt_ex(ex):
       
   168     """Format a single line with an exception description."""
       
   169     return traceback.format_exception_only(ex.__class__, ex)[-1].strip()
       
   170 
       
   171 
       
   172 def rpartition(s, t):
       
   173     """Similar to str.rpartition from 2.5, but doesn't return the separator."""
       
   174     i = s.rfind(t)
       
   175     if i != -1:
       
   176         return s[:i], s[i+len(t):]
       
   177     return '', s
       
   178 
       
   179 
       
   180 def format_exception_cut_frames(x=1):
       
   181     """
       
   182     Format an exception with traceback, but only the last x frames.
       
   183     """
       
   184     typ, val, tb = sys.exc_info()
       
   185     #res = ['Traceback (most recent call last):\n']
       
   186     res = []
       
   187     tbres = traceback.format_tb(tb)
       
   188     res += tbres[-x:]
       
   189     res += traceback.format_exception_only(typ, val)
       
   190     return ''.join(res)
       
   191 
       
   192 
       
   193 def save_traceback():
       
   194     """
       
   195     Save the current exception's traceback in a temporary file.
       
   196     """
       
   197     exc = traceback.format_exc()
       
   198     fd, path = tempfile.mkstemp('.log', 'sphinx-err-')
       
   199     os.write(fd, exc)
       
   200     os.close(fd)
       
   201     return path
       
   202 
       
   203 
       
   204 def _translate_pattern(pat):
       
   205     """
       
   206     Translate a shell-style glob pattern to a regular expression.
       
   207 
       
   208     Adapted from the fnmatch module, but enhanced so that single stars don't
       
   209     match slashes.
       
   210     """
       
   211     i, n = 0, len(pat)
       
   212     res = ''
       
   213     while i < n:
       
   214         c = pat[i]
       
   215         i += 1
       
   216         if c == '*':
       
   217             if i < n and pat[i] == '*':
       
   218                 # double star matches slashes too
       
   219                 i += 1
       
   220                 res = res + '.*'
       
   221             else:
       
   222                 # single star doesn't match slashes
       
   223                 res = res + '[^/]*'
       
   224         elif c == '?':
       
   225             # question mark doesn't match slashes too
       
   226             res = res + '[^/]'
       
   227         elif c == '[':
       
   228             j = i
       
   229             if j < n and pat[j] == '!':
       
   230                 j += 1
       
   231             if j < n and pat[j] == ']':
       
   232                 j += 1
       
   233             while j < n and pat[j] != ']':
       
   234                 j += 1
       
   235             if j >= n:
       
   236                 res = res + '\\['
       
   237             else:
       
   238                 stuff = pat[i:j].replace('\\', '\\\\')
       
   239                 i = j + 1
       
   240                 if stuff[0] == '!':
       
   241                     # negative pattern mustn't match slashes too
       
   242                     stuff = '^/' + stuff[1:]
       
   243                 elif stuff[0] == '^':
       
   244                     stuff = '\\' + stuff
       
   245                 res = '%s[%s]' % (res, stuff)
       
   246         else:
       
   247             res += re.escape(c)
       
   248     return res + '$'
       
   249 
       
   250 
       
   251 _pat_cache = {}
       
   252 
       
   253 def patfilter(names, pat):
       
   254     """
       
   255     Return the subset of the list NAMES that match PAT.
       
   256     Adapted from fnmatch module.
       
   257     """
       
   258     result = []
       
   259     if pat not in _pat_cache:
       
   260         _pat_cache[pat] = re.compile(_translate_pattern(pat))
       
   261     match = _pat_cache[pat].match
       
   262     return filter(match, names)
       
   263 
       
   264 
       
   265 no_fn_re = re.compile(r'[^a-zA-Z0-9_-]')
       
   266 
       
   267 def make_filename(string):
       
   268     return no_fn_re.sub('', string)
       
   269 
       
   270 
       
   271 def nested_parse_with_titles(state, content, node):
       
   272     # hack around title style bookkeeping
       
   273     surrounding_title_styles = state.memo.title_styles
       
   274     surrounding_section_level = state.memo.section_level
       
   275     state.memo.title_styles = []
       
   276     state.memo.section_level = 0
       
   277     state.nested_parse(content, 0, node, match_titles=1)
       
   278     state.memo.title_styles = surrounding_title_styles
       
   279     state.memo.section_level = surrounding_section_level
       
   280 
       
   281 
       
   282 def ustrftime(format, *args):
       
   283     # strftime for unicode strings
       
   284     return time.strftime(unicode(format).encode('utf-8'), *args).decode('utf-8')