# Path: peru/cache.py
# def compute_key(data):
#     # To hash this dictionary of fields, serialize it as a JSON string, and
#     # take the SHA1 of that string. Dictionary key order is unspecified, so
#     # "sort_keys" keeps our hash stable. Specifying separators makes the
#     # JSON slightly more compact, and protects us against changes in the
#     # default.  "ensure_ascii" defaults to true, so specifying it just
#     # protects us from changes in the default.
#     json_representation = json.dumps(
#         data, sort_keys=True, ensure_ascii=True, separators=(',', ':'))
#     sha1 = hashlib.sha1()
#     sha1.update(json_representation.encode("utf8"))
#     return sha1.hexdigest()
# 
# class MergeConflictError(PrintableError):
#     pass


import textwrap
from .cache import compute_key, MergeConflictError



async def merge_imports_tree(cache, imports, target_trees, base_tree=None):
    '''Take an Imports struct and a dictionary of resolved trees and merge the
    unified imports tree. If base_tree is supplied, merge that too. There are a
    couple reasons for structuring this function the way it is:
        - We want to cache merged trees, so that we don't have to do expensive
          git operations just to check whether a module is in cache.
        - We want tree merging to know about target names, so that it can write
          good error messages when there are conflicts.
        - We need to use this for both toplevel imports and recursive module
          imports.
    '''
    key = _cache_key(imports, target_trees, base_tree)
    if key in cache.keyval:
        return cache.keyval[key]
    # We always want to merge imports in the same order, so that any conflicts
    # we run into will be deterministic. Sort the imports alphabetically by
    # target name.
    unified_tree = base_tree or (await cache.get_empty_tree())
    for target, paths in imports.items():
        for path in paths:
            try:
                unified_tree = await cache.merge_trees(
                    unified_tree, target_trees[target], path)

# Path: peru/cache.py
# def compute_key(data):
#     # To hash this dictionary of fields, serialize it as a JSON string, and
#     # take the SHA1 of that string. Dictionary key order is unspecified, so
#     # "sort_keys" keeps our hash stable. Specifying separators makes the
#     # JSON slightly more compact, and protects us against changes in the
#     # default.  "ensure_ascii" defaults to true, so specifying it just
#     # protects us from changes in the default.
#     json_representation = json.dumps(
#         data, sort_keys=True, ensure_ascii=True, separators=(',', ':'))
#     sha1 = hashlib.sha1()
#     sha1.update(json_representation.encode("utf8"))
#     return sha1.hexdigest()
# 
# class MergeConflictError(PrintableError):
#     pass


# Path: peru/merge.py
import textwrap
from .cache import compute_key, MergeConflictError




async def merge_imports_tree(cache, imports, target_trees, base_tree=None):
    '''Take an Imports struct and a dictionary of resolved trees and merge the
    unified imports tree. If base_tree is supplied, merge that too. There are a
    couple reasons for structuring this function the way it is:
        - We want to cache merged trees, so that we don't have to do expensive
          git operations just to check whether a module is in cache.
        - We want tree merging to know about target names, so that it can write
          good error messages when there are conflicts.
        - We need to use this for both toplevel imports and recursive module
          imports.
    '''
    key = _cache_key(imports, target_trees, base_tree)
    if key in cache.keyval:
        return cache.keyval[key]
    # We always want to merge imports in the same order, so that any conflicts
    # we run into will be deterministic. Sort the imports alphabetically by
    # target name.
    unified_tree = base_tree or (await cache.get_empty_tree())
    for target, paths in imports.items():
        for path in paths:
            try:
                unified_tree = await cache.merge_trees(
                    unified_tree, target_trees[target], path)

            except MergeConflictError as e: