# Path: cachy/contracts/repository.py
# class Repository(object):
# 
#     def has(self, key):
#         """
#         Determine if an item exists in the cache.
# 
#         :param key: The cache key
#         :type key: str
# 
#         :rtype: bool
#         """
#         raise NotImplementedError()
# 
#     def get(self, key, default=None):
#         """
#         Retrieve an item from the cache by key.
# 
#         :param key: The cache key
#         :type key: str
# 
#         :param default: The default value to return
#         :type default: mixed
# 
#         :rtype: mixed
#         """
#         raise NotImplementedError()
# 
#     def pull(self, key, default=None):
#         """
#         Retrieve an item from the cache by key and delete ir.
# 
#         :param key: The cache key
#         :type key: str
# 
#         :param default: The default value to return
#         :type default: mixed
# 
#         :rtype: mixed
#         """
#         raise NotImplementedError()
# 
#     def put(self, key, value, minutes):
#         """
#         Store an item in the cache.
# 
#         :param key: The cache key
#         :type key: str
# 
#         :param value: The cache value
#         :type value: mixed
# 
#         :param minutes: The lifetime in minutes of the cached value
#         :type minutes: int or datetime
#         """
#         raise NotImplementedError()
# 
#     def add(self, key, value, minutes):
#         """
#         Store an item in the cache if it does not exist.
# 
#         :param key: The cache key
#         :type key: str
# 
#         :param value: The cache value
#         :type value: mixed
# 
#         :param minutes: The lifetime in minutes of the cached value
#         :type minutes: int or datetime
# 
#         :rtype: bool
#         """
#         raise NotImplementedError()
# 
#     def forever(self, key, value):
#         """
#         Store an item in the cache indefinitely.
# 
#         :param key: The cache key
#         :type key: str
# 
#         :param value: The cache value
#         :type value: mixed
#         """
#         raise NotImplementedError()
# 
#     def remember(self, key, minutes, callback):
#         """
#         Get an item from the cache, or store the default value.
# 
#         :param key: The cache key
#         :type key: str
# 
#         :param minutes: The lifetime in minutes of the cached value
#         :type minutes: int or datetime
# 
#         :param callback: The default function
#         :type callback: callable
# 
#         :rtype: mixed
#         """
#         raise NotImplementedError()
# 
#     def remember_forever(self, key, callback):
#         """
#         Get an item from the cache, or store the default value forever.
# 
#         :param key: The cache key
#         :type key: str
# 
#         :param callback: The default function
#         :type callback: callable
# 
#         :rtype: mixed
#         """
#         raise NotImplementedError()
# 
#     def forget(self, key):
#         """
#         Remove an item from the cache.
# 
#         :param key: The cache key
#         :type key: str
# 
#         :rtype: bool
#         """
#         raise NotImplementedError()
# 
# Path: cachy/helpers.py
# def value(val):
#     if callable(val):
#         return val()
# 
#     return val
# 
# Path: cachy/utils.py
# def encode(string, encodings=None):
#     if isinstance(string, bytes) or PY2 and isinstance(string, unicode):
#         return string
# 
#     if encodings is None:
#         encodings = ['utf-8', 'latin1', 'ascii']
# 
#     for encoding in encodings:
#         try:
#             return string.encode(encoding)
#         except UnicodeDecodeError:
#             pass
# 
#     return string.encode(encodings[0], errors='ignore')
# 
# def decode(string, encodings=None):
#     if not PY2 and not isinstance(string, bytes):
#         return string
# 
#     if encodings is None:
#         encodings = ['utf-8', 'latin1', 'ascii']
# 
#     for encoding in encodings:
#         try:
#             return string.decode(encoding)
#         except UnicodeDecodeError:
#             pass
# 
#     return string.decode(encodings[0], errors='ignore')


import math
import datetime
import types
import hashlib
from functools import wraps
from .contracts.repository import Repository as CacheContract
from .helpers import value
from .utils import encode, decode

    def __getitem__(self, item):
        return self.get(item)

    def __setitem__(self, key, val):
        self.put(key, val, self._default)

    def __delitem__(self, key):
        self.forget(key)

    def _get_minutes(self, duration):
        """
        Calculate the number of minutes with the given duration.

        :param duration: The duration
        :type duration: int or datetime

        :rtype: int or None
        """
        if isinstance(duration, datetime.datetime):
            from_now = (duration - datetime.datetime.now()).total_seconds()
            from_now = math.ceil(from_now / 60)

            if from_now > 0:
                return from_now

            return

        return duration


# Path: cachy/contracts/repository.py
# class Repository(object):
# 
#     def has(self, key):
#         """
#         Determine if an item exists in the cache.
# 
#         :param key: The cache key
#         :type key: str
# 
#         :rtype: bool
#         """
#         raise NotImplementedError()
# 
#     def get(self, key, default=None):
#         """
#         Retrieve an item from the cache by key.
# 
#         :param key: The cache key
#         :type key: str
# 
#         :param default: The default value to return
#         :type default: mixed
# 
#         :rtype: mixed
#         """
#         raise NotImplementedError()
# 
#     def pull(self, key, default=None):
#         """
#         Retrieve an item from the cache by key and delete ir.
# 
#         :param key: The cache key
#         :type key: str
# 
#         :param default: The default value to return
#         :type default: mixed
# 
#         :rtype: mixed
#         """
#         raise NotImplementedError()
# 
#     def put(self, key, value, minutes):
#         """
#         Store an item in the cache.
# 
#         :param key: The cache key
#         :type key: str
# 
#         :param value: The cache value
#         :type value: mixed
# 
#         :param minutes: The lifetime in minutes of the cached value
#         :type minutes: int or datetime
#         """
#         raise NotImplementedError()
# 
#     def add(self, key, value, minutes):
#         """
#         Store an item in the cache if it does not exist.
# 
#         :param key: The cache key
#         :type key: str
# 
#         :param value: The cache value
#         :type value: mixed
# 
#         :param minutes: The lifetime in minutes of the cached value
#         :type minutes: int or datetime
# 
#         :rtype: bool
#         """
#         raise NotImplementedError()
# 
#     def forever(self, key, value):
#         """
#         Store an item in the cache indefinitely.
# 
#         :param key: The cache key
#         :type key: str
# 
#         :param value: The cache value
#         :type value: mixed
#         """
#         raise NotImplementedError()
# 
#     def remember(self, key, minutes, callback):
#         """
#         Get an item from the cache, or store the default value.
# 
#         :param key: The cache key
#         :type key: str
# 
#         :param minutes: The lifetime in minutes of the cached value
#         :type minutes: int or datetime
# 
#         :param callback: The default function
#         :type callback: callable
# 
#         :rtype: mixed
#         """
#         raise NotImplementedError()
# 
#     def remember_forever(self, key, callback):
#         """
#         Get an item from the cache, or store the default value forever.
# 
#         :param key: The cache key
#         :type key: str
# 
#         :param callback: The default function
#         :type callback: callable
# 
#         :rtype: mixed
#         """
#         raise NotImplementedError()
# 
#     def forget(self, key):
#         """
#         Remove an item from the cache.
# 
#         :param key: The cache key
#         :type key: str
# 
#         :rtype: bool
#         """
#         raise NotImplementedError()
# 
# Path: cachy/helpers.py
# def value(val):
#     if callable(val):
#         return val()
# 
#     return val
# 
# Path: cachy/utils.py
# def encode(string, encodings=None):
#     if isinstance(string, bytes) or PY2 and isinstance(string, unicode):
#         return string
# 
#     if encodings is None:
#         encodings = ['utf-8', 'latin1', 'ascii']
# 
#     for encoding in encodings:
#         try:
#             return string.encode(encoding)
#         except UnicodeDecodeError:
#             pass
# 
#     return string.encode(encodings[0], errors='ignore')
# 
# def decode(string, encodings=None):
#     if not PY2 and not isinstance(string, bytes):
#         return string
# 
#     if encodings is None:
#         encodings = ['utf-8', 'latin1', 'ascii']
# 
#     for encoding in encodings:
#         try:
#             return string.decode(encoding)
#         except UnicodeDecodeError:
#             pass
# 
#     return string.decode(encodings[0], errors='ignore')


# Path: cachy/repository.py
import math
import datetime
import types
import hashlib
from functools import wraps
from .contracts.repository import Repository as CacheContract
from .helpers import value
from .utils import encode, decode


    def __getitem__(self, item):
        return self.get(item)

    def __setitem__(self, key, val):
        self.put(key, val, self._default)

    def __delitem__(self, key):
        self.forget(key)

    def _get_minutes(self, duration):
        """
        Calculate the number of minutes with the given duration.

        :param duration: The duration
        :type duration: int or datetime

        :rtype: int or None
        """
        if isinstance(duration, datetime.datetime):
            from_now = (duration - datetime.datetime.now()).total_seconds()
            from_now = math.ceil(from_now / 60)

            if from_now > 0:
                return from_now

            return

        return duration


    def _hash(self, value):