1"""
2Py2/3 compatibility layer
3
4Mostly copied straight from six:
5    http://pypi.python.org/pypi/six/
6
7"""
8from __future__ import absolute_import
9import psycopg2
10from psycopg2 import extensions
11import json
12
13# If psycopg2 < 2.5, register json type
14psycopg2_version = tuple(psycopg2.__version__.split(' ')[0].split('.'))
15if psycopg2_version < ('2', '5'):
16    JSON_OID = 114
17    newtype = extensions.new_type(
18        (JSON_OID,), "JSON", lambda data, cursor: json.loads(data))
19    extensions.register_type(newtype)
20
21def with_metaclass(meta, *bases):
22    """Create a base class with a metaclass."""
23    # This requires a bit of explanation: the basic idea is to make a dummy
24    # metaclass for one level of class instantiation that replaces itself with
25    # the actual metaclass.
26    class metaclass(meta):
27        """The actual metaclass."""
28        def __new__(cls, name, _, d):
29            return meta(name, bases, d)
30    return type.__new__(metaclass, 'temporary_class', (), {})
31
32class classproperty(object):
33    """
34    A descriptor similar to property, but using the class.
35    """
36
37    def __init__(self, getter):
38        self.getter = getter
39
40    def __get__(self, instance, owner):
41        return self.getter(owner)
42
43
44class hybridmethod(object):
45    """
46    Decorator allowing to define method which behaves differently
47    if called at the instance or at the class level.
48    """
49
50    def __init__(self, class_method=None, instance_method=None):
51        self._class_method = class_method
52        self._instance_method = instance_method or class_method
53
54    def instance_method(self, instance_method):
55        """Setter for the instance method."""
56        self._instance_method = instance_method
57        return self
58
59    def class_method(self, class_method):
60        """Setter for class method."""
61        self._class_method = class_method
62        return self
63
64    def __get__(self, instance, owner):
65        if instance is None:
66            return self._class_method.__get__(owner, owner.__class__)
67        else:
68            return self._instance_method.__get__(instance, owner)
69