def regenerate(tree):
    """AST -> String

    Regenerate the source code from the AST tree.
    """
    if hasattr(tree, 'added_newline') and tree.added_newline:
        return str(tree)[:-1]
    else:
        return str(tree) def all(iterable):
def any(iterable):
def sorted(iterable, compare=cmp, key=None):
    def __init__(self, iterable, key=None):
    def __iter__(self):
    def next(self):
    def _grouper(self, tgtkey):
def samefile(file1, file2):
class groupby(object): class Event(object):
    _last_timestamp = 0

    def __init__(self):
        self.timestamp = Event.next_timestamp()

    def next_timestamp(cls):
        cls._last_timestamp += 1
        return cls._last_timestamp
    next_timestamp = classmethod(next_timestamp)

    def __eq__(self, other):
        return isinstance(other, Event) and \
            self.timestamp == other.timestamp

    def __hash__(self):
        return hash(self.timestamp) class Localizable(object):
    """An object which has a corresponding file belonging to some Project.

    Each Localizable has a 'path' attribute and an information when it was
    created, to be in sync with its file system counterpart. Path is always
    relative to the project this localizable belongs to.
    """
    def __init__(self, project, subpath, created=None):
        self.project = project
        self.subpath = subpath
        if created is None:
            created = time.time()
        self.created = created

    def _get_locator(self):
        return module_path_to_name(self.subpath, newsep=".")
    locator = property(_get_locator)

    def is_out_of_sync(self):
        """Is the object out of sync with its file.
        """
        return get_last_modification_time(self.get_path()) > self.created

    def is_up_to_date(self):
        return not self.is_out_of_sync()

    def get_path(self):
        """Return the full path to the file.
        """
        return os.path.join(self.project.path, self.subpath)

    def write(self, new_content):
        """Overwrite the file with new contents and update its created time.

        Creates the containing directories if needed.
        """
        ensure_directory(os.path.dirname(self.get_path()))
        write_content_to_file(new_content, self.get_path())
        self.created = time.time()

    def exists(self):
        return os.path.isfile(self.get_path()) class SerializedObject(Event):
    """An object captured during execution.

    This is an abstract class, see subclasses for descriptions of different
    types of serialized objects.

    :IVariables:
      timestamp : float
        Number marking creation time of this SerializedObject. This number
        cannot be converted to a meaningful time description. It should only
        be used to arrange objects' creation on a timeline.
      human_readable_id : str
        A human-readable description of an object, suitable to be used as
        an identifier.
      module_name : str
        Location of the module this object's class was defined in. Should be
        usable in import statements.
      type_import : tuple(str, str) or None
        An import needed for the type to be available in the testing
        environment. None if no import is needed.
      type_name : str
        A canonical representation of the type this object is an instance of.
    """
    def __init__(self, obj):
        super(SerializedObject, self).__init__()
        self.human_readable_id = get_human_readable_id(obj)
        self.module_name = module_name(obj)
        self.type_name = get_type_name(obj)

    def _get_type_import(self):
        if self.module_name not in ['__builtin__', 'exceptions']:
            return (self.module_name, self.type_name)
    type_import = property(_get_type_import) def all_of_type(objects, type):
    """Return all objects that are instances of a given type.
    """
    return [o for o in objects if isinstance(o, type)] def assert_argument_type(obj, expected_type):
    if not isinstance(obj, expected_type):
        raise TypeError("%s() should be called with a %s argument, not %s" %
            (callers_name(), type_names(expected_type), obj)) def class_name(obj):
    return class_of(obj).__name__ def directories_under(path):
    """Return names of directories under given path (not recursive).
    """
    for entry in os.listdir(path):
        if os.path.isdir(os.path.join(path, entry)):
            yield entry def extract_subpath(path, prefix):
    """Remove prefix from given path to generate subpath, so the following
    correspondence is preserved:

      path <=> os.path.join(prefix, subpath)

    in terms of physical path (i.e. not necessarily strict string
    equality).
    """
    prefix = os.path.realpath(prefix)
    prefix_length = len(prefix)
    if not prefix.endswith(os.path.sep):
        prefix_length += 1
    return os.path.realpath(path)[prefix_length:] def findfirst(pred, seq):
    """Return the first element of given sequence that matches predicate.
    """
    for item in seq:
        if pred(item):
            return item def load_pickle_from(path):
    fd = open(path, 'rb')
    obj = cPickle.load(fd)
    fd.close()
    return obj def starts_with_path(path, prefix):
    """Return True if given path starts with given prefix and False otherwise.
    """
    return os.path.realpath(path).startswith(os.path.realpath(prefix)) def write_content_to_file(string, filename, binary=False):
    fd = file(filename, file_mode('w', binary))
    fd.write(string)
    fd.close() class DirectoryException(Exception):
    pass
import cPickle
import os
import re
from pythoscope.astbuilder import regenerate
from pythoscope.code_trees_manager import FilesystemCodeTreesManager
from pythoscope.compat import any, set
from pythoscope.event import Event
from pythoscope.localizable import Localizable
from pythoscope.logger import log
from pythoscope.serializer import SerializedObject
from pythoscope.util import all_of_type, assert_argument_type, class_name,\
    directories_under, extract_subpath, findfirst, load_pickle_from,\
    starts_with_path, write_content_to_file, DirectoryException
        self.definition = definition
        self.input = args
        self.output = output
        self.exception = exception

        self.caller = None
        self.subcalls = []
        self.side_effects = []

    def add_subcall(self, call):
        if call.caller is not None:
            raise TypeError("This %s of %s already has a caller." % \
                                (class_name(call), call.definition.name))
        call.caller = self
        self.subcalls.append(call)

    def raised_exception(self):
        return self.exception is not None

    def set_output(self, output):
        self.output = output

    def set_exception(self, exception):
        self.exception = exception

    def clear_exception(self):
        self.exception = None

    def add_side_effect(self, side_effect):
        self.side_effects.append(side_effect)

    def __eq__(self, other):
        if type(self) != type(other):
            return False
        return self.definition == other.definition and \
               self.input == other.input and \
               self.output == other.output and \
               self.exception == other.exception and \
               self.side_effects == other.side_effects

    def __hash__(self):
        return hash((self.definition.name,
                     tuple(self.input.iteritems()),
                     self.output,
                     self.exception,
                     tuple(self.side_effects)))

    def __repr__(self):
        return "%s(definition=%s, input=%r, output=%r, exception=%r, side_effects=[..(%d)..])" % \
            (class_name(self), self.definition.name, self.input, self.output,
             self.exception, len(self.side_effects))

class CFunction(Definition):
    pass

class CallToC(Call):
    def __init__(self, name, side_effect=None):
        super(CallToC, self).__init__(CFunction(name), {})
        self.side_effect = side_effect

    def clear_side_effect(self):
        self.side_effect = None

class UnknownCall(Call):
    def __init__(self):
        super(UnknownCall, self).__init__(Function('<unknown>'), {})

class FunctionCall(Call):
    pass

class MethodCall(Call):
    pass

class Callable(object):
    """Dynamic aspect of a callable object. Tracks all calls made to given
    callable.

    Each Callable subclass tracks a different type of Calls.
    """
    calls_type = None

    def __init__(self, calls=None):
        if calls is None:
            calls = []
        self.calls = calls

    def add_call(self, call):
        assert_argument_type(call, self.calls_type)
        self.calls.append(call)

class Function(Definition, Callable):
    def __init__(self, name, args=None, code=None, calls=None, is_generator=False, module=None):
        Definition.__init__(self, name, args=args, code=code, is_generator=is_generator)
        Callable.__init__(self, calls)
        self.module = module
        if is_generator:
            self.calls_type = GeneratorObject
        else:
            self.calls_type = FunctionCall

    def get_unique_calls(self):
        return set(self.calls)

    def __repr__(self):
        return "Function(name=%s, args=%r, calls=%r)" % (self.name, self.args, self.calls)

class GeneratorObjectInvocation(Call):
    """Representation of a single generator invocation.

    Each time a generator is resumed a new GeneratorObjectInvocation is created.
    """

class GeneratorObject(Callable, SerializedObject):
    """Representation of a generator object - a callable with an input and many
    outputs (here called "yields").
    """
    calls_type = GeneratorObjectInvocation

    def __init__(self, obj, generator=None, args=None, callable=None):
        Callable.__init__(self)

        SerializedObject.__init__(self, obj)