Changeset 282

Show
Ignore:
Timestamp:
12/08/05 19:10:06 (3 years ago)
Author:
athomas
Message:
  • Fixes for text wrapping.
  • Added crash.classmaker which is used for resolving metaclass base conflicts. Thanks to Michele Simionato for his ASPN contribution.
  • Added get_implementors() to Component Manager?, which returns a list of classes implementing an interface.
Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • pycrash/trunk/crash/component.py

    r281 r282  
    218218        """ 
    219219        return True 
     220 
     221    def get_implementors(self, interface): 
     222        """ Get all component classes that implement a particular interface as 
     223        a dictionary, with the class name as the key and the class itself as 
     224        the value. Does not instantiate the component. """ 
     225        return dict((c.__name__, c) for c in ComponentMeta._components \ 
     226            if hasattr(c, '_implements') and interface in c._implements) 
  • pycrash/trunk/crash/console.py

    r280 r282  
    127127    return out 
    128128 
    129 __cwrap_re = re.compile(r'''(\n)|(\s+)|((?:\^[N0-7BU]|\S)+\b[^^\w]*)''') 
    130 def cwraptext(text, width = termwidth(), subsequent_indent = ''): 
     129__cwrap_re = re.compile(r'''(\n)|(\s+)|((?:\^[N0-7BU]|\S)+\b[^\n^\w]*)''') 
     130def cwraptext(rtext, width = termwidth(), subsequent_indent = ''): 
    131131    """ Wrap multi-line text to width (defaults to termwidth()) """ 
    132132    out = [] 
    133     tokens = [t.group(0) for t in __cwrap_re.finditer(text)] + [' ' * width] 
    134     line = tokens.pop(0) 
    135     first_line = 1 
    136  
    137  
    138     def add_line(line, first_line): 
    139         if clen(line.rstrip()) > width: 
    140             tokens.insert(0, csplice(line, width)) 
    141             line = csplice(line, 0, width) 
    142         out.append((not first_line and subsequent_indent or '') + line.rstrip()) 
    143         first_line = 0 
    144         if not out[-1]: 
    145             out.pop() 
    146         return first_line 
    147  
    148     while tokens: 
    149         if clen(line) + clen(tokens[0].rstrip()) > width: 
    150             first_line = add_line(line, first_line) 
    151             line = tokens.pop(0) 
     133    for text in rtext.splitlines(): 
     134        tokens = [t.group(0) for t in __cwrap_re.finditer(text)] + [' ' * width] 
     135        line = tokens.pop(0) 
     136        first_line = 1 
     137 
     138        def add_line(line, first_line): 
     139            if clen(line.rstrip()) > width: 
     140                tokens.insert(0, csplice(line, width)) 
     141                line = csplice(line, 0, width) 
     142            out.append((not first_line and subsequent_indent or '') + line.rstrip()) 
     143            first_line = 0 
     144            if not out[-1]: 
     145                out.pop() 
     146            return first_line 
     147 
     148        if tokens: 
     149            while tokens: 
     150                if clen(line) + clen(tokens[0].rstrip()) > width: 
     151                    first_line = add_line(line, first_line) 
     152                    line = tokens.pop(0) 
     153                else: 
     154                    line += tokens.pop(0) 
     155            if line: 
     156                add_line(line, first_line) 
    152157        else: 
    153             line += tokens.pop(0) 
    154     if line: 
    155         add_line(line, first_line) 
     158            out.append('') 
    156159    return out 
    157160 
     
    176179    return out.rstrip() 
    177180 
    178 def print_table(table, header = None, sep = ' ', auto_format = ['^B^U', '^6', '^B^6']): 
     181def print_table(table, header = None, sep = ' ', auto_format = ['^B^U', '^6', '^B^6'], expand_to_fit = 1): 
    179182    """Print a list of lists as a table, so that columns line up nicely. 
    180183    header, if specified, will be printed as the first row. sep is the 
     
    184187    row. The first element is the header colour, subsequent elements are 
    185188    for alternating rows. eg. [ '^B', '^1', '^2' ] 
     189 
     190    expand_to_fit signifies whether print_table should expand the table to the 
     191    width of the terminal. 
    186192     
    187     Note: print_table supports an additional formatting code, ^R, which 
    188     corresponds to the colour formatting of the current table row. """ 
     193    Note: print_table supports the ^R formatting code, in addition to those 
     194    supported by cprint, which corresponds to the colour formatting of the 
     195    current table row. """ 
    189196    def ctlen(s): 
    190197        return clen(s.replace('^R', '')) 
    191198 
     199    seplen = len(sep) 
    192200    # Find column scale factor 
    193201    if header: 
     
    195203    rows, cols = len(table), len(table[0]) 
    196204    colwidths = [0] * cols 
    197     #minwidth = termwidth() / cols 
    198205    for i in range(0, cols): 
    199206        colwidths[i] = max(map(lambda c: max(map(ctlen, c[i].splitlines())), table)) 
    200207        if i < cols - 1: 
    201             colwidths[i] += len(sep) 
    202     twidth = sum(colwidths) 
    203     scale = float(termwidth() - 1) / float(twidth) 
    204     colwidths = [int(float(x) * scale) for x in colwidths] 
     208            colwidths[i] += seplen 
     209    # Scale columns if total width is less than the terminal width, or user requested 
     210    if termwidth() < sum(colwidths) or expand_to_fit: 
     211        scale = float(termwidth() - 1) / float(sum(colwidths)) 
     212        colwidths = [int(float(x) * scale) for x in colwidths] 
     213        mincol = min(colwidths) 
     214        for i, col in enumerate(colwidths): 
     215            if col == mincol: 
     216                colwidths[0] += termwidth() - sum(colwidths) 
     217         
    205218    auto_format = auto_format[:] 
    206219 
     
    218231        else: 
    219232            fmt = auto_format[rowalt % len(auto_format)] 
    220         xrow = [cwraptext(col.replace('^R', fmt), colwidths[i]) for i, col in enumerate(row)] 
     233        # Perform wrapping 
     234        xrow = [cwraptext(col.replace('^R', fmt), colwidths[i] - (i < cols - 1 and seplen or 0)) for i, col in enumerate(row)] 
     235        # Pad column rows out to the maximum of all columns 
     236        maxrows = max(map(len, xrow)) 
     237        for col in xrow: 
     238            col += [''] * (maxrows - len(col)) 
    221239        realrows = max(map(len, xrow)) 
    222         xrow = [x + [''] * (realrows - len(x)) for x in xrow] 
     240        # Emit 
    223241        for i in range(0, realrows): 
    224242            cwrite(sys.stdout, fmt) 
    225243            for j, col in enumerate(xrow): 
    226                 cwrite(sys.stdout, col[i].replace('^R', fmt) + sep * (colwidths[j] - ctlen(col[i]))) 
    227                 if j < cols - 1: 
     244                slen = j < cols - 1 and seplen or 0 
     245                cwrite(sys.stdout, col[i] + ' ' * (colwidths[j] - ctlen(col[i]) - slen)) 
     246                if slen: 
    228247                    cwrite(sys.stdout, sep) 
    229248            cwrite(sys.stdout, '^N\n') 
  • pycrash/trunk/crash/decorators.py

    r279 r282  
    6969    #import inspect 
    7070    #caller = inspect.getouterframes(inspect.currentframe())[1][3] 
    71     return DelayedAbstractException(NotImplementedError(func.__name__ + ' must be implemented in subclass'), func.__doc__) 
     71    return DelayedAbstractException(NotImplementedError('%s() must be implemented in subclass' % func.__name__), func.__doc__) 
    7272 
    7373# Based on code from http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/438819 
     
    7676        make all members 'private' (prefixed by an underscore)""" 
    7777    def outer(func): 
    78         def inner(*args, **kwargs): 
     78        def inner(self, *args, **kwargs): 
    7979            A = {} 
    80             self = args[0] 
    81             args = args[1:] 
     80            args = list(args) 
     81            argc = len(args) 
    8282            for i, arg in enumerate(func.func_code.co_varnames[1:func.func_code.co_argcount]): 
    83                 if i < len(args): 
    84                     A[arg] = args[i] 
     83                if len(args): 
     84                    A[arg] = args[0] 
     85                    del args[0] 
    8586                elif kwargs.has_key(arg): 
    8687                    A[arg] = kwargs[arg] 
     88                    del kwargs[arg] 
    8789                else: 
    8890                    the_default_arg = i - func.func_code.co_argcount + 1 
     
    9092            for name, value in A.items(): 
    9193                setattr(self, (private and '_' or '') + name, value) 
     94            # Do some basic sanity checking on any remaining arguments 
     95            if args: 
     96                raise TypeError("%s() takes at most %i arguments (%i given)" % (func.__name__, func.func_code.co_argcount, argc)) 
     97            if kwargs: 
     98                raise TypeError("%s() got an unexpected keyword argument '%s'" % (func.__name__, kwargs.keys()[0])) 
    9299            return func(self, **A) 
    93100        inner.__doc__ = func.__doc__