# Path: pythoscope/compat.py
# 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):
# 
# Path: pythoscope/event.py
# 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)
# 
# Path: pythoscope/util.py
# def compact(lst):
# def counted(objects):
# def camelize(name):
#     def upcase(match):
# def underscore(name):
#     def capitalize(match):
#     def underscore(match):
# def pluralize(word, count):
# def string2id(string):
# def string2filename(string):
# def file_mode(base, binary):
# def read_file_contents(filename, binary=False):
# def write_content_to_file(string, filename, binary=False):
# def all_of_type(objects, type):
# def max_by_not_zero(func, collection):
#     def annotate(element):
# def get_names(objects):
# def map_values(function, dictionary):
# def ensure_directory(directory):
# def get_last_modification_time(path):
# def starts_with_path(path, prefix):
# def extract_subpath(path, prefix):
# def directories_under(path):
# def findfirst(pred, seq):
# def flatten(lst):
# def union(*sets):
# def key_for_value(dictionary, value):
# def get_generator_from_frame(frame):
# def is_generator_code(code):
# def generator_has_ended(generator):
#         def _generator_has_ended(generator):
#         def _generator_has_ended(generator):
# def is_method_wrapper(obj):
# def get_self_from_method(method):
# def compile_without_warnings(stmt):
# def callers_name():
# def type_names(types):
# def assert_argument_type(obj, expected_type):
# def quoted_block(text):
# def class_of(obj):
# def class_name(obj):
# def module_name(obj):
# def module_path_to_name(module_path, newsep="_"):
# def last_traceback():
# def last_exception_as_string():
# def regexp_flags_as_string(flags):
# def load_pickle_from(path):
# class DirectoryException(Exception):


import array
import exceptions
import re
import types
from pythoscope.compat import frozenset, set, sets
from pythoscope.event import Event
from pythoscope.util import RePatternType, class_name, class_of, \
    module_name, regexp_flags_as_string, string2id, underscore
    def __eq__(self, other):
        return isinstance(other, ImmutableObject) and \
            self.reconstructor == other.reconstructor and \
            self.imports == other.imports

    def __hash__(self):
        return hash(self.reconstructor)

    def __repr__(self):
        if self.imports:
            return "ImmutableObject(%r, imports=%r)" % (self.reconstructor, self.imports)
        return "ImmutableObject(%r)" % self.reconstructor

    # :: object -> (string, set)
    def get_reconstructor_with_imports(obj):
        """
        >>> reconstructor, imports = ImmutableObject.get_reconstructor_with_imports(re.compile('abcd'))
        >>> reconstructor
        "re.compile('abcd')"
        >>> imports == set(['re'])
        True
        >>> reconstructor, imports = ImmutableObject.get_reconstructor_with_imports(re.compile('abcd', re.I | re.M))
        >>> reconstructor
        "re.compile('abcd', re.IGNORECASE | re.MULTILINE)"
        >>> imports == set(['re'])
        True
        """
        if isinstance(obj, (int, long, float, str, unicode, types.NoneType)):
            # Bultin types has very convienient representation.
            return repr(obj), set()

# Path: pythoscope/compat.py
# 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):
# 
# Path: pythoscope/event.py
# 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)
# 
# Path: pythoscope/util.py
# def compact(lst):
# def counted(objects):
# def camelize(name):
#     def upcase(match):
# def underscore(name):
#     def capitalize(match):
#     def underscore(match):
# def pluralize(word, count):
# def string2id(string):
# def string2filename(string):
# def file_mode(base, binary):
# def read_file_contents(filename, binary=False):
# def write_content_to_file(string, filename, binary=False):
# def all_of_type(objects, type):
# def max_by_not_zero(func, collection):
#     def annotate(element):
# def get_names(objects):
# def map_values(function, dictionary):
# def ensure_directory(directory):
# def get_last_modification_time(path):
# def starts_with_path(path, prefix):
# def extract_subpath(path, prefix):
# def directories_under(path):
# def findfirst(pred, seq):
# def flatten(lst):
# def union(*sets):
# def key_for_value(dictionary, value):
# def get_generator_from_frame(frame):
# def is_generator_code(code):
# def generator_has_ended(generator):
#         def _generator_has_ended(generator):
#         def _generator_has_ended(generator):
# def is_method_wrapper(obj):
# def get_self_from_method(method):
# def compile_without_warnings(stmt):
# def callers_name():
# def type_names(types):
# def assert_argument_type(obj, expected_type):
# def quoted_block(text):
# def class_of(obj):
# def class_name(obj):
# def module_name(obj):
# def module_path_to_name(module_path, newsep="_"):
# def last_traceback():
# def last_exception_as_string():
# def regexp_flags_as_string(flags):
# def load_pickle_from(path):
# class DirectoryException(Exception):


# Path: pythoscope/serializer.py
import array
import exceptions
import re
import types
from pythoscope.compat import frozenset, set, sets
from pythoscope.event import Event
from pythoscope.util import RePatternType, class_name, class_of, \
    module_name, regexp_flags_as_string, string2id, underscore

    def __eq__(self, other):
        return isinstance(other, ImmutableObject) and \
            self.reconstructor == other.reconstructor and \
            self.imports == other.imports

    def __hash__(self):
        return hash(self.reconstructor)

    def __repr__(self):
        if self.imports:
            return "ImmutableObject(%r, imports=%r)" % (self.reconstructor, self.imports)
        return "ImmutableObject(%r)" % self.reconstructor

    # :: object -> (string, set)
    def get_reconstructor_with_imports(obj):
        """
        >>> reconstructor, imports = ImmutableObject.get_reconstructor_with_imports(re.compile('abcd'))
        >>> reconstructor
        "re.compile('abcd')"
        >>> imports == set(['re'])
        True
        >>> reconstructor, imports = ImmutableObject.get_reconstructor_with_imports(re.compile('abcd', re.I | re.M))
        >>> reconstructor
        "re.compile('abcd', re.IGNORECASE | re.MULTILINE)"
        >>> imports == set(['re'])
        True
        """
        if isinstance(obj, (int, long, float, str, unicode, types.NoneType)):
            # Bultin types has very convienient representation.
            return repr(obj), set()

        elif isinstance(obj, RePatternType):