# Path: liam2/data.py
# def index_table_light(table, index='period'):
#     """
#     table is an iterable of rows, each row is a mapping (name -> value)
#     Rows must contain the index column and must be sorted by that column.
#     Returns a dict: {index_value: start_row, stop_row}
#     """
#     rows_per_period = {}
#     current_value = None
#     start_row = None
#     # I don't know why but my attempts to only retrieve one column
#     # made the function slower, not faster (this is only used in diff_h5 &
#     # merge_h5 though).
#     for idx, row in enumerate(table):
#         value = row[index]
#         if value != current_value:
#             # 0 > None is True
#             if value < current_value:
#                 msg = "data is not ordered by {} ({} at data line {} is < {})"
#                 raise Exception(msg.format(index, value, idx + 1, current_value))
#             if start_row is not None:
#                 rows_per_period[current_value] = (start_row, idx)
#             start_row = idx
#             current_value = value
#     if current_value is not None:
#         rows_per_period[current_value] = (start_row, len(table))
#     return rows_per_period
# 
# def get_fields(array):
#     dtype = array.dtype
#     return [(name, normalize_type(dtype[name].type)) for name in dtype.names]
# 
# Path: liam2/utils.py
# class PrettyTable(object):
#     def __init__(self, data, missing=None):
#         assert isinstance(data, (tuple, list))
#         self.data = data
#         self.missing = missing
# 
#     def __iter__(self):
#         if self.missing is not None:
#             return iter(self.convert_nans())
#         else:
#             return iter(self.data)
# 
#     def __len__(self):
#         return len(self.data)
# 
#     def convert_nans(self):
#         missing = self.missing
#         for row in self.data:
#             formatted = [missing if value != value else value
#                          for value in row]
#             yield formatted
# 
#     def __repr__(self):
#         missing = self.missing
#         if missing is None:
#             missing = 'nan'
#         else:
#             missing = str(missing)
#         return '\n' + table2str(self.data, missing) + '\n'
# 
# def merge_items(item_sequences, merge_order='first_to_last', value_priority='first'):
#     """
#     Returns a list of (key, value) pairs which is the result of merging all sequences of (key, value) pairs passed as
#     arguments.
#     Order of keys is preserved on a "first" merged basis.
#     If merge_order is 'first_to_last', items will be merged from first to last, appending if not present, otherwise the
#     merge happens from last to first.
# 
#     value_priority determines which sequence items will have priority over the others. 'first' means the value of
#     a key will be from the earliest sequence (relative to the order given in item_sequences, independently of the
#     merge order).
#     """
#     assert merge_order in {'first_to_last', 'last_to_first'}
#     assert value_priority in {'first', 'last'}
# 
#     keep_first = value_priority == 'first'
#     if merge_order == 'last_to_first':
#         item_sequences = item_sequences[::-1]
#         keep_first = not keep_first
# 
#     result_keys = []
#     values = {}
#     for items in item_sequences:
#         if keep_first:
#             for k, v in items:
#                 if k not in values:
#                     result_keys.append(k)
#                     values[k] = v
#         else:
#             for k, v in items:
#                 if k not in values:
#                     result_keys.append(k)
#                 values[k] = v
# 
#     return [(k, values[k]) for k in result_keys]


import numpy as np
import tables
    import sys
    import platform
from liam2.data import index_table_light, get_fields
from liam2.utils import PrettyTable, merge_items

                                   for idx in diff]))
            if raiseondiff:
                raise Exception('different')


def diff_h5(input1_path, input2_path, numdiff=10):
    input1_file = tables.open_file(input1_path, mode="r")
    input2_file = tables.open_file(input2_path, mode="r")

    input1_entities = input1_file.root.entities
    input2_entities = input2_file.root.entities

    # noinspection PyProtectedMember
    ent_names1 = set(table._v_name for table in input1_entities)
    # noinspection PyProtectedMember
    ent_names2 = set(table._v_name for table in input2_entities)
    for ent_name in sorted(ent_names1 | ent_names2):
        print()
        print(ent_name)
        if ent_name not in ent_names1:
            print("missing in file 1")
            continue
        elif ent_name not in ent_names2:
            print("missing in file 2")
            continue

        table1 = getattr(input1_entities, ent_name)
        input1_rows = index_table_light(table1)

        table2 = getattr(input2_entities, ent_name)

# Path: liam2/data.py
# def index_table_light(table, index='period'):
#     """
#     table is an iterable of rows, each row is a mapping (name -> value)
#     Rows must contain the index column and must be sorted by that column.
#     Returns a dict: {index_value: start_row, stop_row}
#     """
#     rows_per_period = {}
#     current_value = None
#     start_row = None
#     # I don't know why but my attempts to only retrieve one column
#     # made the function slower, not faster (this is only used in diff_h5 &
#     # merge_h5 though).
#     for idx, row in enumerate(table):
#         value = row[index]
#         if value != current_value:
#             # 0 > None is True
#             if value < current_value:
#                 msg = "data is not ordered by {} ({} at data line {} is < {})"
#                 raise Exception(msg.format(index, value, idx + 1, current_value))
#             if start_row is not None:
#                 rows_per_period[current_value] = (start_row, idx)
#             start_row = idx
#             current_value = value
#     if current_value is not None:
#         rows_per_period[current_value] = (start_row, len(table))
#     return rows_per_period
# 
# def get_fields(array):
#     dtype = array.dtype
#     return [(name, normalize_type(dtype[name].type)) for name in dtype.names]
# 
# Path: liam2/utils.py
# class PrettyTable(object):
#     def __init__(self, data, missing=None):
#         assert isinstance(data, (tuple, list))
#         self.data = data
#         self.missing = missing
# 
#     def __iter__(self):
#         if self.missing is not None:
#             return iter(self.convert_nans())
#         else:
#             return iter(self.data)
# 
#     def __len__(self):
#         return len(self.data)
# 
#     def convert_nans(self):
#         missing = self.missing
#         for row in self.data:
#             formatted = [missing if value != value else value
#                          for value in row]
#             yield formatted
# 
#     def __repr__(self):
#         missing = self.missing
#         if missing is None:
#             missing = 'nan'
#         else:
#             missing = str(missing)
#         return '\n' + table2str(self.data, missing) + '\n'
# 
# def merge_items(item_sequences, merge_order='first_to_last', value_priority='first'):
#     """
#     Returns a list of (key, value) pairs which is the result of merging all sequences of (key, value) pairs passed as
#     arguments.
#     Order of keys is preserved on a "first" merged basis.
#     If merge_order is 'first_to_last', items will be merged from first to last, appending if not present, otherwise the
#     merge happens from last to first.
# 
#     value_priority determines which sequence items will have priority over the others. 'first' means the value of
#     a key will be from the earliest sequence (relative to the order given in item_sequences, independently of the
#     merge order).
#     """
#     assert merge_order in {'first_to_last', 'last_to_first'}
#     assert value_priority in {'first', 'last'}
# 
#     keep_first = value_priority == 'first'
#     if merge_order == 'last_to_first':
#         item_sequences = item_sequences[::-1]
#         keep_first = not keep_first
# 
#     result_keys = []
#     values = {}
#     for items in item_sequences:
#         if keep_first:
#             for k, v in items:
#                 if k not in values:
#                     result_keys.append(k)
#                     values[k] = v
#         else:
#             for k, v in items:
#                 if k not in values:
#                     result_keys.append(k)
#                 values[k] = v
# 
#     return [(k, values[k]) for k in result_keys]


# Path: liam2/diff_h5.py
import numpy as np
import tables
    import sys
    import platform
from liam2.data import index_table_light, get_fields
from liam2.utils import PrettyTable, merge_items

                                   for idx in diff]))
            if raiseondiff:
                raise Exception('different')


def diff_h5(input1_path, input2_path, numdiff=10):
    input1_file = tables.open_file(input1_path, mode="r")
    input2_file = tables.open_file(input2_path, mode="r")

    input1_entities = input1_file.root.entities
    input2_entities = input2_file.root.entities

    # noinspection PyProtectedMember
    ent_names1 = set(table._v_name for table in input1_entities)
    # noinspection PyProtectedMember
    ent_names2 = set(table._v_name for table in input2_entities)
    for ent_name in sorted(ent_names1 | ent_names2):
        print()
        print(ent_name)
        if ent_name not in ent_names1:
            print("missing in file 1")
            continue
        elif ent_name not in ent_names2:
            print("missing in file 2")
            continue

        table1 = getattr(input1_entities, ent_name)
        input1_rows = index_table_light(table1)

        table2 = getattr(input2_entities, ent_name)

        input2_rows = index_table_light(table2)
