"""
Python 2/3 compatibility layer

http://lucumr.pocoo.org/2013/5/21/porting-to-python-3-redux/

"""

import sys

PY2 = sys.version_info[0] == 2
PY3 = sys.version_info[0] == 3

if PY2:
    text_type = unicode
    binary_type = str
    string_types = (basestring,)
    xrange = xrange
    unichr = unichr
    int_types = (int, long)
    py2bytes = lambda s: s.encode('utf-8')
    raw_input = raw_input
else:
    text_type = str
    binary_type = bytes
    xrange = range
    string_types = (str, bytes)
    unichr = chr
    int_types = (int,)
    py2bytes = lambda s: s
    raw_input = input

if PY2:
    iterkeys = lambda d: d.iterkeys()
    itervalues = lambda d: d.itervalues()
    iteritems = lambda d: d.iteritems()
else:
    iterkeys = lambda d: iter(d.keys())
    itervalues = lambda d: iter(d.values())
    iteritems = lambda d: iter(d.items())


if PY2:
    import urlparse
    from urlparse import urlparse, parse_qs, urlunparse
    from urllib import urlencode, quote
    from itertools import izip_longest as zip_longest
    #import cookie
    from urllib import urlopen
else:
    from urllib.parse import urlparse, parse_qs, urlunparse
    from urllib.parse import urlencode, quote
    from itertools import zip_longest
    #from http import cookies as cookie
    from urllib.request import urlopen


if PY2:
    import cPickle as pickle
else:
    import pickle


if PY2:
    def implements_to_string(cls):
        cls.__unicode__ = cls.__str__
        cls.__str__ = lambda x: x.__unicode__().encode('utf-8')
        return cls
else:
    implements_to_string = lambda x: x


if PY2:
    def implements_iterator(cls):
        cls.next = cls.__next__
        del cls.__next__
        return cls
else:
    implements_iterator = lambda x: x

if PY2:
    def implements_bool(cls):
        cls.__nonzero__ = cls.__bool__
        del cls.__bool__
        return cls
else:
    def implements_bool(cls):
        return cls


if PY2:
    number_types = (int, long, float)
else:
    number_types = (int, float)

if PY2:
    next_method_name = "next"
else:
    next_method_name = "__next__"


class string(object):
    lowercase = 'abcdefghijklmnopqrstuvwxyz'
    uppercase = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
    digits = '0123456789'
    punctuation = '!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~'



def with_metaclass(meta, *bases):
    class metaclass(meta):
        __call__ = type.__call__
        __init__ = type.__init__

        def __new__(cls, name, this_bases, d):
            if this_bases is None:
                return type.__new__(cls, name, (), d)
            return meta(name, bases, d)
    return metaclass('temporary_class', None, {})
