Skip to content

Commit

Permalink
Metaclass for caching instances
Browse files Browse the repository at this point in the history
  • Loading branch information
koterpillar committed Aug 9, 2015
1 parent 6f9da8b commit 7022c95
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 14 deletions.
15 changes: 1 addition & 14 deletions aloe/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,6 @@
from codecs import open
from copy import deepcopy
from collections import OrderedDict
try:
from functools import lru_cache # pylint:disable=no-name-in-module
except ImportError:
from repoze.lru import lru_cache
from warnings import warn

import pyparsing
Expand Down Expand Up @@ -840,15 +836,6 @@ class Gherkin(object):
Gherkin parser
"""

@classmethod
@lru_cache(20)
def get_parser(cls, language):
"""
Get a parser for a specific language.
"""

return cls(language=language)

def __init__(self, language):
self.language = language

Expand Down Expand Up @@ -1017,7 +1004,7 @@ def parse(string=None,
if not language:
language = guess_language(string, filename)

parser = parser_class.get_parser(language)
parser = parser_class(language)

#
# Try parsing the string
Expand Down
15 changes: 15 additions & 0 deletions aloe/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@
import re
import sys

try:
from functools import lru_cache # pylint:disable=no-name-in-module
except ImportError:
from repoze.lru import lru_cache
from contextlib import contextmanager


Expand Down Expand Up @@ -98,3 +102,14 @@ def __get__(self, instance, owner):
result = self.func(instance)
instance.__dict__[self.name] = result
return result


class memoizedtype(type): # pylint:disable=invalid-name
"""
A type that caches the created instances.
"""

@lru_cache(20)
def __call__(cls, *args, **kwargs):
# On Python 2, newsuper can't deal with metaclasses
return super(memoizedtype, cls).__call__(*args, **kwargs)
34 changes: 34 additions & 0 deletions tests/unit/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
from __future__ import absolute_import
from future import standard_library
standard_library.install_aliases()
from future.utils import with_metaclass

import sys
import unittest
Expand All @@ -34,6 +35,7 @@
from aloe.utils import (
unwrap_function,
memoizedproperty,
memoizedtype,
)


Expand Down Expand Up @@ -109,3 +111,35 @@ def prop(self):
# Test that different objects aren't sharing the value
self.assertEqual(second.prop, 11)
self.assertEqual(second.prop, 11)

def test_memoizedtype(self):
"""Test memoizedtype."""

class Memoized(with_metaclass(memoizedtype, object)):
"""A class to test memoizedtype."""

counter = 0

def __init__(self, value):
"""
A constructor that intentionally modifies the class state.
"""

self.value = value
type(self).counter += 1

first = Memoized(5)
second = Memoized(10)

# Check the objects are created properly
self.assertEqual(first.value, 5)
self.assertEqual(second.value, 10)

# Try to create the same object again
another_first = Memoized(5)

# It should be the same as before
self.assertIs(first, another_first)

# Only two objects should have been created
self.assertEqual(Memoized.counter, 2)

0 comments on commit 7022c95

Please sign in to comment.