# Path: implementation/primaries/ExtractMetadata/classes/hashdict.py
# class hashdict(dict):
#     """
#     hashable dict implementation, suitable for use as a key into
#     other dicts.
# 
#     based on answers from
#        http://stackoverflow.com/questions/1151658/python-hashable-dicts
# 
#     """
# 
#     def __key(self):
#         return tuple(sorted(self.items()))
# 
#     def __repr__(self):
#         return "{0}({1})".format(self.__class__.__name__, ", ".join(
#             "{0}={1}".format(str(i[0]), repr(i[1])) for i in self.__key()))
# 
#     def __hash__(self):
#         return hash(self.__key())
# 
#     def __setitem__(self, key, value):
#         raise TypeError("{0} does not support item assignment"
#                         .format(self.__class__.__name__))
# 
#     def __delitem__(self, key):
#         raise TypeError("{0} does not support item assignment"
#                         .format(self.__class__.__name__))
# 
#     def clear(self):
#         raise TypeError("{0} does not support item assignment"
#                         .format(self.__class__.__name__))
# 
#     def pop(self, *args, **kwargs):
#         raise TypeError("{0} does not support item assignment"
#                         .format(self.__class__.__name__))
# 
#     def popitem(self, *args, **kwargs):
#         raise TypeError("{0} does not support item assignment"
#                         .format(self.__class__.__name__))
# 
#     def setdefault(self, *args, **kwargs):
#         raise TypeError("{0} does not support item assignment"
#                         .format(self.__class__.__name__))
# 
#     def update(self, *args, **kwargs):
#         raise TypeError("{0} does not support item assignment"
#                         .format(self.__class__.__name__))
#     # update is not ok because it mutates the object
#     # __add__ is ok because it creates a new object
#     # while the new object is under construction, it's ok to mutate it
# 
#     def __add__(self, right):
#         result = hashdict(self)
#         dict.update(result, right)
#         return result
# 
# Path: implementation/primaries/ExtractMetadata/classes/DataLayer/helpers.py
# def get_if_exists(dict, key, default=0):
#     if dict is not None:
#         if key in dict:
#             return dict[key]
#     return default
# 
# Path: implementation/primaries/ExtractMetadata/classes/helpers.py
# def combine_dictionaries(dict1, dict2):
#     new_dict = dict1
#     for key in dict2:
#         if key not in new_dict:
#             new_dict[key] = dict2[key]
#         elif isinstance(new_dict[key], dict):
#             new_dict[key] = combine_dictionaries(new_dict[key], dict2[key])
#         elif isinstance(new_dict[key], dict):
#             new_dict[key]["other"] = dict2[key]
#         elif isinstance(dict2[key], dict):
#             cpy = new_dict[key]
#             new_dict[key] = {"other": cpy}
#             new_dict[key].update(dict2[key])
#         else:
#             new_dict[key].extend(dict2[key])
#     return new_dict
# 
# def init_kv(elem, key, init_value=list()):
#     """
#     Initialise a key in a dictionary with a default value if it doesn't exist already
#     """
#     if key not in elem:
#         elem[key] = init_value


import xml.sax
import copy
from xml.sax import handler, make_parser
from MuseParse import helpers
from implementation.primaries.ExtractMetadata.classes.hashdict import hashdict
from implementation.primaries.ExtractMetadata.classes.DataLayer.helpers import get_if_exists
from implementation.primaries.ExtractMetadata.classes.helpers import combine_dictionaries, init_kv
def update_or_append_entry(dictionary, tag, entry):
    """
    Method to check if a dictionary is empty, or if it's last entry contains the tag
    being added. If yes, create a new entry. If it doesn't contain the tag,
    add it. Used by clef and key creation queries, might be used by other handlers in future
    """
    if len(dictionary) == 0 or tag in dictionary[-1]:
        dictionary.append({tag: entry})
    elif tag not in dictionary[-1]:
        dictionary[-1][tag] = entry


def create_elem(chars, key1, key2, cast1=int, cast2=str):
    """
    select a return value from chars dictionary. Priority given to key 2 over key 1,
    both are cast to whatever value we need. Used by clef and key handlers as both
    need the first element, then the second, and both happen to be format int then str.
    Made generic as poss incase this is useful elsewhere.
    """
    return_value = 0
    if key1 in chars:
        return_value = cast1(chars[key1])
    if key2 in chars:
        return_value = cast2(chars[key2])
    return return_value


def handleTransposition(tags, attrs, chars, parts, data):
    id = helpers.GetID(attrs, "part", "id")
    if id is not None:

# Path: implementation/primaries/ExtractMetadata/classes/hashdict.py
# class hashdict(dict):
#     """
#     hashable dict implementation, suitable for use as a key into
#     other dicts.
# 
#     based on answers from
#        http://stackoverflow.com/questions/1151658/python-hashable-dicts
# 
#     """
# 
#     def __key(self):
#         return tuple(sorted(self.items()))
# 
#     def __repr__(self):
#         return "{0}({1})".format(self.__class__.__name__, ", ".join(
#             "{0}={1}".format(str(i[0]), repr(i[1])) for i in self.__key()))
# 
#     def __hash__(self):
#         return hash(self.__key())
# 
#     def __setitem__(self, key, value):
#         raise TypeError("{0} does not support item assignment"
#                         .format(self.__class__.__name__))
# 
#     def __delitem__(self, key):
#         raise TypeError("{0} does not support item assignment"
#                         .format(self.__class__.__name__))
# 
#     def clear(self):
#         raise TypeError("{0} does not support item assignment"
#                         .format(self.__class__.__name__))
# 
#     def pop(self, *args, **kwargs):
#         raise TypeError("{0} does not support item assignment"
#                         .format(self.__class__.__name__))
# 
#     def popitem(self, *args, **kwargs):
#         raise TypeError("{0} does not support item assignment"
#                         .format(self.__class__.__name__))
# 
#     def setdefault(self, *args, **kwargs):
#         raise TypeError("{0} does not support item assignment"
#                         .format(self.__class__.__name__))
# 
#     def update(self, *args, **kwargs):
#         raise TypeError("{0} does not support item assignment"
#                         .format(self.__class__.__name__))
#     # update is not ok because it mutates the object
#     # __add__ is ok because it creates a new object
#     # while the new object is under construction, it's ok to mutate it
# 
#     def __add__(self, right):
#         result = hashdict(self)
#         dict.update(result, right)
#         return result
# 
# Path: implementation/primaries/ExtractMetadata/classes/DataLayer/helpers.py
# def get_if_exists(dict, key, default=0):
#     if dict is not None:
#         if key in dict:
#             return dict[key]
#     return default
# 
# Path: implementation/primaries/ExtractMetadata/classes/helpers.py
# def combine_dictionaries(dict1, dict2):
#     new_dict = dict1
#     for key in dict2:
#         if key not in new_dict:
#             new_dict[key] = dict2[key]
#         elif isinstance(new_dict[key], dict):
#             new_dict[key] = combine_dictionaries(new_dict[key], dict2[key])
#         elif isinstance(new_dict[key], dict):
#             new_dict[key]["other"] = dict2[key]
#         elif isinstance(dict2[key], dict):
#             cpy = new_dict[key]
#             new_dict[key] = {"other": cpy}
#             new_dict[key].update(dict2[key])
#         else:
#             new_dict[key].extend(dict2[key])
#     return new_dict
# 
# def init_kv(elem, key, init_value=list()):
#     """
#     Initialise a key in a dictionary with a default value if it doesn't exist already
#     """
#     if key not in elem:
#         elem[key] = init_value


# Path: implementation/primaries/ExtractMetadata/classes/MetaParser.py
import xml.sax
import copy
from xml.sax import handler, make_parser
from MuseParse import helpers
from implementation.primaries.ExtractMetadata.classes.hashdict import hashdict
from implementation.primaries.ExtractMetadata.classes.DataLayer.helpers import get_if_exists
from implementation.primaries.ExtractMetadata.classes.helpers import combine_dictionaries, init_kv

def update_or_append_entry(dictionary, tag, entry):
    """
    Method to check if a dictionary is empty, or if it's last entry contains the tag
    being added. If yes, create a new entry. If it doesn't contain the tag,
    add it. Used by clef and key creation queries, might be used by other handlers in future
    """
    if len(dictionary) == 0 or tag in dictionary[-1]:
        dictionary.append({tag: entry})
    elif tag not in dictionary[-1]:
        dictionary[-1][tag] = entry


def create_elem(chars, key1, key2, cast1=int, cast2=str):
    """
    select a return value from chars dictionary. Priority given to key 2 over key 1,
    both are cast to whatever value we need. Used by clef and key handlers as both
    need the first element, then the second, and both happen to be format int then str.
    Made generic as poss incase this is useful elsewhere.
    """
    return_value = 0
    if key1 in chars:
        return_value = cast1(chars[key1])
    if key2 in chars:
        return_value = cast2(chars[key2])
    return return_value


def handleTransposition(tags, attrs, chars, parts, data):
    id = helpers.GetID(attrs, "part", "id")
    if id is not None:

        init_kv(parts, id, init_value={})