mementos / test / test.py

Jonathan Eunice 815e05b 
Jonathan Eunice 5c534ec 
Jonathan Eunice 815e05b 
Jonathan Eunice 670ffad 






Jonathan Eunice 815e05b 











Jonathan Eunice 670ffad 
Jonathan Eunice 815e05b 















Jonathan Eunice 670ffad 









Jonathan Eunice 815e05b 
Jonathan Eunice 670ffad 







Jonathan Eunice 5c534ec 
Jonathan Eunice 670ffad 
Jonathan Eunice 5c534ec 






































































Jonathan Eunice b9d74ea 
Jonathan Eunice 5c534ec 
Jonathan Eunice b9d74ea 
Jonathan Eunice 5c534ec 

Jonathan Eunice b9d74ea 

Jonathan Eunice 5c534ec 
Jonathan Eunice b9d74ea 
Jonathan Eunice 5c534ec 
Jonathan Eunice b9d74ea 






































Jonathan Eunice 5c534ec 

Jonathan Eunice 154cea0 






Jonathan Eunice b9d74ea 

Jonathan Eunice 154cea0 
Jonathan Eunice b9d74ea 
Jonathan Eunice 5c534ec 
Jonathan Eunice b9d74ea 
Jonathan Eunice 5c534ec 

















Jonathan Eunice b9d74ea 





Jonathan Eunice 5c534ec 
from mementos import *
import sys, pytest

def with_metaclass(meta, base=object):
    """Create a base class with a metaclass."""
    return meta("NewBase", (base,), {})

def test_one():    
    class Thing(with_metaclass(MementoMetaclass, object)):
                
        def __init__(self, name):
            self.name = name
        

    t1 = Thing("one")
    t2 = Thing("one")
    assert t1 is t2
    
    o1 = Thing("lovely")
    o2 = Thing(name="lovely")
    assert o1 is not o2   # because the call signature is different
    
    class OtherThing(with_metaclass(MementoMetaclass, object)):
        
        def __init__(self, name):
            self.name = name
            self.color = None
            self.weight = None
            
        def set(self, color=None, weight=None):
            self.color = color or self.color
            self.weight = weight or self.weight
            return self
    
    ot1 = OtherThing("one").set(color='blue')
    ot2 = OtherThing("one").set(weight='light')
    assert ot1 is ot2
    assert ot1.color == ot2.color == 'blue'
    assert ot1.weight == ot2.weight == 'light'
    
def test_inline_with_metaclass():
    
    # Make sure you can do the metaclass specification directly.
    
    class Thing23(MementoMetaclass("NewBase", (object,), {})):
                
        def __init__(self, name):
            self.name = name
        

    t1 = Thing23("one")
    t2 = Thing23("one")
    assert t1 is t2
    
    o1 = Thing23("lovely")
    o2 = Thing23(name="lovely")
    assert o1 is not o2   # because the call signature is different
    
def test_id_metaclass():
    
    # Test the metaclass that uses the id of the first arg
    # but really as much a test of memento_factory, since IdMementoMetaclass not
    # part of base module
       
    IdMementoMetaclass = memento_factory("IdMementoMetaclass",
                                         lambda cls, args, kwargs: (cls, id(args[0])) )

    class IdTrack(with_metaclass(IdMementoMetaclass, object)):
        def __init__(self, name, *args):
            self.name = name
            self.args = args
            
    id1 = IdTrack("joe")
    id2 = IdTrack("joe")
    assert id1 is id2
    
    id3 = IdTrack("joe", 1, 4)
    assert id3 is id2
    
    id4 = IdTrack("Joe", 1, 4)
    id5 = IdTrack("Joe")
    assert id4 is id5
    assert id4 is not id3
    assert id5 is not id3
    
def test_id_metaclass_primitive():
    
    # Test the metaclass that uses the id of the first arg
    # but really as much a test of memento_factory, since IdMementoMetaclass not
    # part of base module
       
    IdMementoPrimitive = memento_factory("IdMementoMetaclass",
                                         lambda cls, args, kwargs: id(args[0]) )

    class IdTrackPrim(with_metaclass(IdMementoPrimitive, object)):
        def __init__(self, name, *args):
            self.name = name
            self.args = args
            
    id1 = IdTrackPrim("joe")
    id2 = IdTrackPrim("joe")
    assert id1 is id2
    
    id3 = IdTrackPrim("joe", 1, 4)
    assert id3 is id2
    
    id4 = IdTrackPrim("Joe", 1, 4)
    id5 = IdTrackPrim("Joe")
    assert id4 is id5
    assert id4 is not id3
    assert id5 is not id3
    
def test_metaclass_factory():
    
    mymeta = memento_factory("mymeta", lambda cls, args, kwargs: (cls, kwargs['b']))
    
    class BTrack(with_metaclass(mymeta, object)):
        def __init__(self, name, **kwargs):
            assert 'b' in kwargs
            self.name = name
            self.b = kwargs['b']
            
    b1 = BTrack('andy', b=1)
    b2 = BTrack('dave', b=1)
    assert b1 is b2
    assert b1.name == 'andy'  # because b1 got there first, defined object such that b=1
    
    b3 = BTrack('andy', b=2)
    assert b3 is not b1
    assert b3 is not b2
    assert b3.name == 'andy'

@pytest.mark.skipif("sys.version_info < (2,7)")
def test_hasher_signatures():
    # use inspect.getcallargs to make signatures that dont vary
    
    # alternate way of constructing hash key - seems more generally applicable
    
    from inspect import getcallargs
    from collections import Mapping, Iterable
    
    def hasher(c):
        """
        Return a hash for a collection, even if it's putatively unhashable (i.e.
        contains any dicts or lists). Does this by traversing the collection and
        accumulating the hash of its subvalues, then hashing a hashable
        collection of those sub-hashes. Works for basic types like strings,
        lists, dicts, and collections of same. Does not try to manage complex
        objects, unless they are already hashable. Works by hashing the current
        values; if the collection (or any sub-collection) is mutable and
        changes, the subsequent hasher() calls on the same object will return
        different values. Also, all collections of a given type (dict and OrderedDict,
        say, or list, tuple, and set) are collapsed to the same hash result.
        Whether this weaker, type-collapsing, value-oriented hash function
        suits your purposes will depend on the purposes.
        
        For canonicalizing call fingerprints for memoizing object creation, it
        works well, because such instantiation-time memoizing rarely needs to
        involve complex objects, and instantiation arguments are typically of
        simple-ish types (often literals), and they tend to crisply define the
        object's core 'identity'.
        
        If you need a slightly stronger version that differentiates dict from
        OrderedDict, say, you could create a variant that adds type(c) to the
        constructed tuple before returning the tuple hash.
        """
        try:
            return hash(c)
        except TypeError:
            if isinstance(c, Mapping):
                subhash = []
                for k in sorted(c.keys()):
                    subhash.append(hash(k))
                    subhash.append(hasher(c[k]))
                return hash(tuple(subhash))
            elif isinstance(c, Iterable):
                return hash(tuple(hasher(item) for item in c))
            else:
                raise TypeError('cant figure out ' + repr(c))
            
    def call_fingerprint(cls, args, kwargs):
        """
        Given a complex __init__ call with varied positional, keyward, variable,
        and variable keyword arguments, canonicalize the argument values and
        return a suitable hash key. NB this is suitable for cases where it is
        primarily the use of default values and keyword specification of args
        that might otherwise be given positionally that causes key signatures to
        vary, and in which the primary args (ie, not * or ** values) are simple
        scalars.
        """
        return hasher(getcallargs(cls.__init__, None, *args, **kwargs))
        
    Perfect2 = memento_factory("Perfect", call_fingerprint)
    
    class PerfectCall(with_metaclass(Perfect2, object)):
        def __init__(self, name, a=1, b=2, c=3, *args, **kwargs):
            self.vector = (name, a, b, c)
    
    p1 = PerfectCall('amy')
    p2 = PerfectCall('amy', b=2)
    p3 = PerfectCall('amy', c=3)
    p4 = PerfectCall('amy', c=3, a=1)
    p5 = PerfectCall(c=3, a=1, b=2, name='amy')
    assert p1 is p2
    assert p2 is p3
    assert p3 is p4
    assert p4 is p5
    
    p6 = PerfectCall('amy', b=33)
    assert p1 is not p6
    
    p7 = PerfectCall(**{'name': 'amy', 'b': 33})
    assert p6 is p7
    
    p8  = PerfectCall("bill", woot='more!', nixnax=3304)
    p9  = PerfectCall(**dict(woot='more!', nixnax=3304, name='bill'))
    p10 = PerfectCall(**dict([('nixnax', 3304), ('woot', 'more!'), ('name', 'bill')]))
    assert p8 is p9 is p10

    
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.