Skip to content

Commit

Permalink
Merge pull request #1 from mplanchard/memoize
Browse files Browse the repository at this point in the history
Version 1.1.0 Candidate
  • Loading branch information
mplanchard authored Sep 4, 2017
2 parents 7b73bd6 + 9d9709a commit d660801
Show file tree
Hide file tree
Showing 28 changed files with 1,443 additions and 236 deletions.
364 changes: 335 additions & 29 deletions README.rst

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,14 +65,14 @@ def get_setup_value(arg):
source_suffix = '.rst'

# The encoding of source files.
#source_encoding = 'utf-8-sig'
source_encoding = 'utf-8-sig'

# The master toctree document.
master_doc = 'index'

# General information about the project.
project = NAME
copyright = '2017, Ihiji'
copyright = '2017, {}'.format(AUTHOR)
author = AUTHOR

# The version info for the project you're documenting, acts as replacement for
Expand Down
8 changes: 8 additions & 0 deletions docs/pydecor._memoization.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
pydecor\.\_memoization module
=============================

.. automodule:: pydecor._memoization
:members:
:private-members:
:undoc-members:
:show-inheritance:
4 changes: 2 additions & 2 deletions docs/pydecor._util.rst → docs/pydecor.caches.rst
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
pydecor\.\_util module
pydecor\.caches module
======================

.. automodule:: pydecor._util
.. automodule:: pydecor.caches
:members:
:private-members:
:undoc-members:
Expand Down
8 changes: 8 additions & 0 deletions docs/pydecor.decorators._utility.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
pydecor\.decorators\.\_utility module
=====================================

.. automodule:: pydecor.decorators._utility
:members:
:private-members:
:undoc-members:
:show-inheritance:
8 changes: 8 additions & 0 deletions docs/pydecor.decorators.generic.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
pydecor\.decorators\.generic module
===================================

.. automodule:: pydecor.decorators.generic
:members:
:private-members:
:undoc-members:
:show-inheritance:
8 changes: 8 additions & 0 deletions docs/pydecor.decorators.ready_to_wear.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
pydecor\.decorators\.ready\_to\_wear module
===========================================

.. automodule:: pydecor.decorators.ready_to_wear
:members:
:private-members:
:undoc-members:
:show-inheritance:
16 changes: 14 additions & 2 deletions docs/pydecor.decorators.rst
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
pydecor\.decorators module
==========================
pydecor\.decorators package
===========================

Submodules
----------

.. toctree::

pydecor.decorators._utility
pydecor.decorators.generic
pydecor.decorators.ready_to_wear

Module contents
---------------

.. automodule:: pydecor.decorators
:members:
Expand Down
11 changes: 9 additions & 2 deletions docs/pydecor.rst
Original file line number Diff line number Diff line change
@@ -1,15 +1,22 @@
pydecor package
===============

Subpackages
-----------

.. toctree::

pydecor.decorators

Submodules
----------

.. toctree::

pydecor._util
pydecor._memoization
pydecor._version
pydecor.caches
pydecor.constants
pydecor.decorators
pydecor.functions

Module contents
Expand Down
11 changes: 2 additions & 9 deletions pydecor/__init__.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,7 @@
# -*- coding: UTF-8 -*-
"""
Main package
"""

from ._version import __version__, __version_info__
from .decorators import (
after,
before,
construct_decorator,
decorate,
instead,
intercept,
log_call,
)
from .decorators import *
29 changes: 29 additions & 0 deletions pydecor/_memoization.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# -*- coding: UTF-8 -*-
"""
Required functionality for the memoization function
"""

__all__ = (
'convert_to_hashable',
'hashable',
)

import dill as pickle


def convert_to_hashable(args, kwargs):
"""Return args and kwargs as a hashable tuple"""
return hashable(args), hashable(kwargs)


def hashable(item):
"""Get return a hashable version of an item
If the item is natively hashable, return the item itself. If
it is not, return it dumped to a pickle string.
"""
try:
hash(item)
except TypeError:
item = pickle.dumps(item)
return item
3 changes: 2 additions & 1 deletion pydecor/_version.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# -*- coding: UTF-8 -*-
"""
version.py module
Expand All @@ -7,5 +8,5 @@

from __future__ import absolute_import, unicode_literals

__version_info__ = (1, 0, 0)
__version_info__ = (1, 1, 0)
__version__ = '.'.join([str(ver) for ver in __version_info__])
116 changes: 116 additions & 0 deletions pydecor/caches.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
# -*- coding: UTF-8 -*-
"""
Caches for memoization
"""

from __future__ import absolute_import, unicode_literals


__all__ = (
'LRUCache',
'FIFOCache',
'TimedCache',
)


from collections import OrderedDict
from time import time


class LRUCache(OrderedDict):
"""Self-pruning cache using an LRU strategy
If instantiated with a ``max_size`` other than ``0``, will
automatically prune the least-recently-used (LRU) key/value
pair when inserting an item after reaching the specified size.
An item is considered to be "used" when it is inserted or
accessed, at which point its position in recently used
queue is updated to the most recent.
Supports all standard dictionary methods.
:param int max_size: maximum number of entries to save
before pruning
"""

def __init__(self, max_size=0, *args, **kwargs):
super(LRUCache, self).__init__(*args, **kwargs)
self._max_size = max_size

def __getitem__(self, key, **kwargs):
value = OrderedDict.__getitem__(self, key)
del self[key]
OrderedDict.__setitem__(self, key, value, **kwargs)
return value

def __setitem__(self, key, value, **kwargs):
if key in self:
del self[key]
OrderedDict.__setitem__(self, key, value, **kwargs)
if self._max_size and len(self) > self._max_size:
self.popitem(last=False)


class FIFOCache(OrderedDict):
"""Self-pruning cache using a FIFO strategy
If instantiated with a ``max_size`` other than ``0``, will
automatically prune the least-recently-inserted key/value
pair when inserting an item after reaching the specified
size.
Supports all standard dictionary methods.
:param int max_size: maximum number of entries to save
before pruning
"""

def __init__(self, max_size=0, *args, **kwargs):
super(FIFOCache, self).__init__(*args, **kwargs)
self._max_size = max_size

def __setitem__(self, key, value, **kwargs):
OrderedDict.__setitem__(self, key, value)
if self._max_size and len(self) > self._max_size:
self.popitem(last=False)


class TimedCache(dict):
"""Self-pruning cache whose entries can be set to expire
If instantiated with a ``max_age`` other than ``0``, will
consider entries older than the specified age to be invalid,
removing them from the cache upon an attempt to access them
and returning as though they do not exist.
Supports all standard dictionary methods.
:param int max_age: age in seconds beyond which entries
should be considered invalid. The default is 0, which
means that entries should be stored forever.
"""

def __init__(self, max_age=0, *args, **kwargs):
super(TimedCache, self).__init__(*args, **kwargs)
self._max_age = max_age

def __getitem__(self, key):
value, last_time = dict.__getitem__(self, key)
now = time()
if self._max_age and now - last_time > self._max_age:
del self[key]
raise KeyError(key)
else:
return value

def __setitem__(self, key, value):
now = time()
dict.__setitem__(self, key, (value, now))

def __contains__(self, key):
try:
self.__getitem__(key)
except KeyError:
return False
return True
1 change: 1 addition & 0 deletions pydecor/constants.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# -*- coding: UTF-8 -*-
"""
This rather skinny module just contains constants for use elsewhere.
"""
Expand Down
20 changes: 20 additions & 0 deletions pydecor/decorators/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# -*- coding: UTF-8 -*-
"""
Public interface for decorators sub-package
"""

__all__ = (
'after',
'before',
'construct_decorator',
'decorate',
'instead',
'Decorated',
'DecoratorType',
'intercept',
'log_call',
'memoize',
)

from .generic import *
from .ready_to_wear import *
4 changes: 2 additions & 2 deletions pydecor/_util.py → pydecor/decorators/_utility.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# -*- coding: UTF-8 -*-
"""
Private interface utilities for PyDecor
"""
Expand All @@ -8,11 +9,10 @@
__all__ = ('ClassWrapper', )


from functools import partial
from functools import partial, wraps
from inspect import isclass
from logging import getLogger
from sys import version_info
from types import MethodType

from inspect import isfunction, ismethod

Expand Down
Loading

0 comments on commit d660801

Please sign in to comment.