# Path: liam2/compat.py
# PY2 = sys.version_info[0] == 2
# def with_metaclass(meta, *bases):
#         def __new__(cls, name, this_bases, d):
# def csv_open(filename, mode='r'):
#     class metaclass(meta):
# 
# Path: liam2/config.py



import ast
import itertools
import math
import re
import sys
import time
import warnings
import numpy as np
import numexpr as ne
import larray as la
from collections import defaultdict, deque, namedtuple
from textwrap import wrap
from liam2.compat import zip, basestring
from liam2 import config
    from liam2.data import ColumnArray
    from cutils import fromiter
# encoding: utf-8
from __future__ import absolute_import, division, print_function





def make_hashable(obj):
    if isinstance(obj, (list, tuple)):
        return tuple(make_hashable(e) for e in obj)
    elif isinstance(obj, slice):
        return (slice, obj.start, obj.stop, obj.step)
    else:
        return obj


class classproperty(property):

# Path: liam2/compat.py
# PY2 = sys.version_info[0] == 2
# def with_metaclass(meta, *bases):
#         def __new__(cls, name, this_bases, d):
# def csv_open(filename, mode='r'):
#     class metaclass(meta):
# 
# Path: liam2/config.py



# Path: liam2/utils.py
import ast
import itertools
import math
import re
import sys
import time
import warnings
import numpy as np
import numexpr as ne
import larray as la
from collections import defaultdict, deque, namedtuple
from textwrap import wrap
from liam2.compat import zip, basestring
from liam2 import config
    from liam2.data import ColumnArray
    from cutils import fromiter

# encoding: utf-8
from __future__ import absolute_import, division, print_function





def make_hashable(obj):
    if isinstance(obj, (list, tuple)):
        return tuple(make_hashable(e) for e in obj)
    elif isinstance(obj, slice):
        return (slice, obj.start, obj.stop, obj.step)
    else:
        return obj


class classproperty(property):

    def __get__(self, cls, owner):