Example #1
0
def apply_filters(hunk, filters, type, **kwargs):
    """Apply the given list of filters to the hunk, returning a new
    ``MemoryHunk`` object.

    ``kwargs`` are options that should be passed along to the filters.
    If ``hunk`` is a file hunk, a ``source_path`` key will automatically
    be added to ``kwargs``.
    """
    assert type in ('input', 'output')

    # Short-circuit
    # TODO: This can actually be improved by looking at "type" and
    # whether any of the existing filters handles this type.
    if not filters:
        return hunk

    cache = get_cache()
    key = make_key(hunk.key(), filters, type)
    content = cache.get(key)
    if not content in (False, None):
        return MemoryHunk(content)

    kwargs = kwargs.copy()
    if hasattr(hunk, 'filename'):
        kwargs.setdefault('source_path', hunk.filename)

    data = StringIO.StringIO(hunk.data())
    for filter in filters:
        func = getattr(filter, type, False)
        if func:
            out = StringIO.StringIO()
            func(data, out, **kwargs)
            data = out
            data.seek(0)

    # Note that the key used to cache this hunk is different from the key
    # the hunk will expose to subsequent merges, i.e. hunk.key() is always
    # based on the actual content, and does not match the key used to cache
    # the key. This latter key also includes information about for example
    # the filters used.
    #
    # It wouldn't have to be this way. Hunk could subsequently expose their
    # cache key through hunk.key(). This would work as well, but would be
    # an inferior solution: Imagine a source file which receives
    # non-substantial changes, in the sense that they do not affect the
    # filter output, for example whitespace. If a hunk's key is the cache
    # key, such a change would invalidate the caches for all subsequent
    # operations on this hunk as well, even though it didn't actually change
    # after all.
    content = data.getvalue()
    cache.set(key, content)
    return MemoryHunk(content)
Example #2
0
 def key(self):
     return make_key(self.data())