<commit_before>#!/usr/bin/env python

'''
This module contains useful decorators for a variety of functions.
'''

from __future__ import division

__author__="<NAME>"
__copyright__ = "Copyright 2011, The Materials Project"
__version__ = "0.1"
__maintainer__ = "<NAME>"
__email__ = "<EMAIL>"
__date__ = "Dec 31, 2011"

from functools import wraps

def singleton(cls):
    """
    This decorator can be used to create a singleton out of a class.
    """
    
    instances = {}
    
    def getinstance():
        if cls not in instances:
            instances[cls] = cls()
        return instances[cls]
    return getinstance

def cached_class(klass):
    """
    Decorator to cache class instances by constructor arguments.
    This results in a class that behaves like a singleton for each
    set of constructor arguments, ensuring efficiency. 
    
    Note that this should be used for *immutable classes only*.  Having 
    a cached mutable class makes very little sense.  For efficiency,
    avoid using this decorator for situations where there are many 
    constructor arguments permutations.
      
    The keywords argument dictionary is converted to a tuple because
    dicts are mutable; keywords themselves are strings and 
    so are always hashable, but if any arguments (keyword
    or positional) are non-hashable, that set of arguments
    is not cached.
    """
    cache = {}
    
    @wraps(klass, assigned=('__name__', '__module__'), updated=())
    class _decorated(klass):
        # The wraps decorator can't do this because __doc__
        # isn't writable once the class is created
        __doc__ = klass.__doc__
        def __new__(cls, *args, **kwds):
            key = (cls,) + args + tuple(kwds.iteritems())
            if key not in cache:
                o = super(klass, cls).__new__(cls, *args, **kwds)
                cache[key] = o
            return cache[key]

    
    return _decorated

@cached_class
class A(object):
    
    def __init__(self, val=1):
        self.val = val

@cached_class
class B(A):
    
    def __init__(self, val, val2):
        self.val = val

<commit_msg>Add a new decorator to log function calls.<commit_after>#!/usr/bin/env python

'''
This module contains useful decorators for a variety of functions.
'''

from __future__ import division

__author__="<NAME>"
__copyright__ = "Copyright 2011, The Materials Project"
__version__ = "0.1"
__maintainer__ = "<NAME>"
__email__ = "<EMAIL>"
__date__ = "Dec 31, 2011"

import logging
import datetime
from functools import wraps

def singleton(cls):
    """
    This decorator can be used to create a singleton out of a class.
    """
    
    instances = {}
    
    def getinstance():
        if cls not in instances:
            instances[cls] = cls()
        return instances[cls]
    return getinstance

def cached_class(klass):
    """
    Decorator to cache class instances by constructor arguments.
    This results in a class that behaves like a singleton for each
    set of constructor arguments, ensuring efficiency. 
    
    Note that this should be used for *immutable classes only*.  Having 
    a cached mutable class makes very little sense.  For efficiency,
    avoid using this decorator for situations where there are many 
    constructor arguments permutations.
      
    The keywords argument dictionary is converted to a tuple because
    dicts are mutable; keywords themselves are strings and 
    so are always hashable, but if any arguments (keyword
    or positional) are non-hashable, that set of arguments
    is not cached.
    """
    cache = {}
    
    @wraps(klass, assigned=('__name__', '__module__'), updated=())
    class _decorated(klass):
        # The wraps decorator can't do this because __doc__
        # isn't writable once the class is created
        __doc__ = klass.__doc__
        def __new__(cls, *args, **kwds):
            key = (cls,) + args + tuple(kwds.iteritems())
            if key not in cache:
                o = super(klass, cls).__new__(cls, *args, **kwds)
                cache[key] = o
            return cache[key]

    
    return _decorated

def logged(logger = logging.getLogger(), level = logging.DEBUG):
    def wrap(f):
        def wrapped_f(*args, **kwargs):
            logger.log(level, "Function called at {} with args = {} and kwargs = {}".format(datetime.datetime.now(), args, kwargs))
            data = f(*args, **kwargs)
            logger.log(level, "Function done at {} with args = {} and kwargs = {}".format(datetime.datetime.now(), args, kwargs))
            return data
        return wrapped_f
    return wrap
{'fraction_non_alphanumeric': 0.08852245606422217, 'fraction_numerical': 0.0056411369060533735, 'mean_word_length': 2.6850519584332533, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5187901', 'n_tokens_mistral': 1308, 'n_tokens_neox': 1271, 'n_words': 497}