degal/utils.py
author Tero Marttila <terom@fixme.fi>
Sun, 14 Jun 2009 23:43:40 +0300
changeset 120 55cb7fc9c8fb
parent 109 66a01c0806f1
child 128 f66bb9f6126a
permissions -rw-r--r--
add new exif.py to abstract between different exif libraries, and add partially working support for pyexiv2 and EXIFpy
44
533b7e8b5d3b strip copyright/license boilerplate from modules, except dexif and formatbytes
Tero Marttila <terom@fixme.fi>
parents: 41
diff changeset
     1
"""
533b7e8b5d3b strip copyright/license boilerplate from modules, except dexif and formatbytes
Tero Marttila <terom@fixme.fi>
parents: 41
diff changeset
     2
    Miscellaneous utilities
533b7e8b5d3b strip copyright/license boilerplate from modules, except dexif and formatbytes
Tero Marttila <terom@fixme.fi>
parents: 41
diff changeset
     3
"""
533b7e8b5d3b strip copyright/license boilerplate from modules, except dexif and formatbytes
Tero Marttila <terom@fixme.fi>
parents: 41
diff changeset
     4
59
fbbe956229cc remove old utils and write some new ones
Tero Marttila <terom@fixme.fi>
parents: 44
diff changeset
     5
import functools
23
10841abbc01f taggr2, which is starting to shape up
terom
parents: 20
diff changeset
     6
96
d9cf1e272e90 fix LazyProperty to not inherit from property, so as to act as a non-data descriptor, which can then be overriden by per-instance __dict__ values
Tero Marttila <terom@fixme.fi>
parents: 84
diff changeset
     7
class LazyProperty (object) :
12
c2d8e9a754a1 Major code restructuring. Version is now 0.5, templates use Mako, and the code is split off into several files under lib/
terom
parents:
diff changeset
     8
    """
84
891545a38a2b change utils.LazyProperty to store the cached value using obj.__dict__
Tero Marttila <terom@fixme.fi>
parents: 75
diff changeset
     9
        Lazy-loaded cached properties.
891545a38a2b change utils.LazyProperty to store the cached value using obj.__dict__
Tero Marttila <terom@fixme.fi>
parents: 75
diff changeset
    10
891545a38a2b change utils.LazyProperty to store the cached value using obj.__dict__
Tero Marttila <terom@fixme.fi>
parents: 75
diff changeset
    11
        This functions by overriding the class's property attribute with the actual value attribute in the instance's
891545a38a2b change utils.LazyProperty to store the cached value using obj.__dict__
Tero Marttila <terom@fixme.fi>
parents: 75
diff changeset
    12
        dict, causing all future attribute lookups to return that directly.
96
d9cf1e272e90 fix LazyProperty to not inherit from property, so as to act as a non-data descriptor, which can then be overriden by per-instance __dict__ values
Tero Marttila <terom@fixme.fi>
parents: 84
diff changeset
    13
d9cf1e272e90 fix LazyProperty to not inherit from property, so as to act as a non-data descriptor, which can then be overriden by per-instance __dict__ values
Tero Marttila <terom@fixme.fi>
parents: 84
diff changeset
    14
        >>> class Foo (object) :
d9cf1e272e90 fix LazyProperty to not inherit from property, so as to act as a non-data descriptor, which can then be overriden by per-instance __dict__ values
Tero Marttila <terom@fixme.fi>
parents: 84
diff changeset
    15
        ...     counter = 0
d9cf1e272e90 fix LazyProperty to not inherit from property, so as to act as a non-data descriptor, which can then be overriden by per-instance __dict__ values
Tero Marttila <terom@fixme.fi>
parents: 84
diff changeset
    16
        ...     @lazy_load
d9cf1e272e90 fix LazyProperty to not inherit from property, so as to act as a non-data descriptor, which can then be overriden by per-instance __dict__ values
Tero Marttila <terom@fixme.fi>
parents: 84
diff changeset
    17
        ...     def foo (self) :
d9cf1e272e90 fix LazyProperty to not inherit from property, so as to act as a non-data descriptor, which can then be overriden by per-instance __dict__ values
Tero Marttila <terom@fixme.fi>
parents: 84
diff changeset
    18
        ...             self.counter += 1
d9cf1e272e90 fix LazyProperty to not inherit from property, so as to act as a non-data descriptor, which can then be overriden by per-instance __dict__ values
Tero Marttila <terom@fixme.fi>
parents: 84
diff changeset
    19
        ...             return self.counter
d9cf1e272e90 fix LazyProperty to not inherit from property, so as to act as a non-data descriptor, which can then be overriden by per-instance __dict__ values
Tero Marttila <terom@fixme.fi>
parents: 84
diff changeset
    20
        ... 
d9cf1e272e90 fix LazyProperty to not inherit from property, so as to act as a non-data descriptor, which can then be overriden by per-instance __dict__ values
Tero Marttila <terom@fixme.fi>
parents: 84
diff changeset
    21
        >>> foo = Foo(); foo.foo, foo.foo, foo.counter
d9cf1e272e90 fix LazyProperty to not inherit from property, so as to act as a non-data descriptor, which can then be overriden by per-instance __dict__ values
Tero Marttila <terom@fixme.fi>
parents: 84
diff changeset
    22
        (1, 1, 1)
d9cf1e272e90 fix LazyProperty to not inherit from property, so as to act as a non-data descriptor, which can then be overriden by per-instance __dict__ values
Tero Marttila <terom@fixme.fi>
parents: 84
diff changeset
    23
12
c2d8e9a754a1 Major code restructuring. Version is now 0.5, templates use Mako, and the code is split off into several files under lib/
terom
parents:
diff changeset
    24
    """
c2d8e9a754a1 Major code restructuring. Version is now 0.5, templates use Mako, and the code is split off into several files under lib/
terom
parents:
diff changeset
    25
59
fbbe956229cc remove old utils and write some new ones
Tero Marttila <terom@fixme.fi>
parents: 44
diff changeset
    26
    def __init__ (self, func) :
fbbe956229cc remove old utils and write some new ones
Tero Marttila <terom@fixme.fi>
parents: 44
diff changeset
    27
        """
fbbe956229cc remove old utils and write some new ones
Tero Marttila <terom@fixme.fi>
parents: 44
diff changeset
    28
            Initialize with no value
fbbe956229cc remove old utils and write some new ones
Tero Marttila <terom@fixme.fi>
parents: 44
diff changeset
    29
        """
75
18b3b1926720 fix utils.LazyProperty
Tero Marttila <terom@fixme.fi>
parents: 73
diff changeset
    30
        
84
891545a38a2b change utils.LazyProperty to store the cached value using obj.__dict__
Tero Marttila <terom@fixme.fi>
parents: 75
diff changeset
    31
        # the getter function
75
18b3b1926720 fix utils.LazyProperty
Tero Marttila <terom@fixme.fi>
parents: 73
diff changeset
    32
        self.func = func
84
891545a38a2b change utils.LazyProperty to store the cached value using obj.__dict__
Tero Marttila <terom@fixme.fi>
parents: 75
diff changeset
    33
891545a38a2b change utils.LazyProperty to store the cached value using obj.__dict__
Tero Marttila <terom@fixme.fi>
parents: 75
diff changeset
    34
        # the attribute name
75
18b3b1926720 fix utils.LazyProperty
Tero Marttila <terom@fixme.fi>
parents: 73
diff changeset
    35
        self.name = func.__name__
19
8d3ffd87cb0b * move cgi-bin to de-cgi-bin so it doesn't conflict with my default alias... need to come up with a real solution to this
terom
parents: 18
diff changeset
    36
73
8897352630a5 misc. stuff in gallery.py utils.py
Tero Marttila <terom@fixme.fi>
parents: 59
diff changeset
    37
    def run (self, obj) :
59
fbbe956229cc remove old utils and write some new ones
Tero Marttila <terom@fixme.fi>
parents: 44
diff changeset
    38
        """
84
891545a38a2b change utils.LazyProperty to store the cached value using obj.__dict__
Tero Marttila <terom@fixme.fi>
parents: 75
diff changeset
    39
            Run the background func and return the to-be-cached value.
891545a38a2b change utils.LazyProperty to store the cached value using obj.__dict__
Tero Marttila <terom@fixme.fi>
parents: 75
diff changeset
    40
891545a38a2b change utils.LazyProperty to store the cached value using obj.__dict__
Tero Marttila <terom@fixme.fi>
parents: 75
diff changeset
    41
            `obj` is the object instance
59
fbbe956229cc remove old utils and write some new ones
Tero Marttila <terom@fixme.fi>
parents: 44
diff changeset
    42
        """
28
70b6c13d084f fancy new log format
terom
parents: 27
diff changeset
    43
75
18b3b1926720 fix utils.LazyProperty
Tero Marttila <terom@fixme.fi>
parents: 73
diff changeset
    44
        return self.func(obj)
73
8897352630a5 misc. stuff in gallery.py utils.py
Tero Marttila <terom@fixme.fi>
parents: 59
diff changeset
    45
 
84
891545a38a2b change utils.LazyProperty to store the cached value using obj.__dict__
Tero Marttila <terom@fixme.fi>
parents: 75
diff changeset
    46
    def store (self, obj, value) :
73
8897352630a5 misc. stuff in gallery.py utils.py
Tero Marttila <terom@fixme.fi>
parents: 59
diff changeset
    47
        """
84
891545a38a2b change utils.LazyProperty to store the cached value using obj.__dict__
Tero Marttila <terom@fixme.fi>
parents: 75
diff changeset
    48
            Store the cached value, overring ourself
73
8897352630a5 misc. stuff in gallery.py utils.py
Tero Marttila <terom@fixme.fi>
parents: 59
diff changeset
    49
        """
96
d9cf1e272e90 fix LazyProperty to not inherit from property, so as to act as a non-data descriptor, which can then be overriden by per-instance __dict__ values
Tero Marttila <terom@fixme.fi>
parents: 84
diff changeset
    50
d9cf1e272e90 fix LazyProperty to not inherit from property, so as to act as a non-data descriptor, which can then be overriden by per-instance __dict__ values
Tero Marttila <terom@fixme.fi>
parents: 84
diff changeset
    51
#        print "[%x] %r.__dict__[%r] = %r" % (id(obj), obj, self.name, value)
d9cf1e272e90 fix LazyProperty to not inherit from property, so as to act as a non-data descriptor, which can then be overriden by per-instance __dict__ values
Tero Marttila <terom@fixme.fi>
parents: 84
diff changeset
    52
84
891545a38a2b change utils.LazyProperty to store the cached value using obj.__dict__
Tero Marttila <terom@fixme.fi>
parents: 75
diff changeset
    53
        obj.__dict__[self.name] = value
73
8897352630a5 misc. stuff in gallery.py utils.py
Tero Marttila <terom@fixme.fi>
parents: 59
diff changeset
    54
75
18b3b1926720 fix utils.LazyProperty
Tero Marttila <terom@fixme.fi>
parents: 73
diff changeset
    55
    def __get__ (self, obj, owner) :
59
fbbe956229cc remove old utils and write some new ones
Tero Marttila <terom@fixme.fi>
parents: 44
diff changeset
    56
        """
84
891545a38a2b change utils.LazyProperty to store the cached value using obj.__dict__
Tero Marttila <terom@fixme.fi>
parents: 75
diff changeset
    57
            Generate the value, store it as the attribute and return it.
59
fbbe956229cc remove old utils and write some new ones
Tero Marttila <terom@fixme.fi>
parents: 44
diff changeset
    58
        """
96
d9cf1e272e90 fix LazyProperty to not inherit from property, so as to act as a non-data descriptor, which can then be overriden by per-instance __dict__ values
Tero Marttila <terom@fixme.fi>
parents: 84
diff changeset
    59
84
891545a38a2b change utils.LazyProperty to store the cached value using obj.__dict__
Tero Marttila <terom@fixme.fi>
parents: 75
diff changeset
    60
        # compute value
891545a38a2b change utils.LazyProperty to store the cached value using obj.__dict__
Tero Marttila <terom@fixme.fi>
parents: 75
diff changeset
    61
        value = self.run(obj)
59
fbbe956229cc remove old utils and write some new ones
Tero Marttila <terom@fixme.fi>
parents: 44
diff changeset
    62
84
891545a38a2b change utils.LazyProperty to store the cached value using obj.__dict__
Tero Marttila <terom@fixme.fi>
parents: 75
diff changeset
    63
        # store it
891545a38a2b change utils.LazyProperty to store the cached value using obj.__dict__
Tero Marttila <terom@fixme.fi>
parents: 75
diff changeset
    64
        self.store(obj, value)
891545a38a2b change utils.LazyProperty to store the cached value using obj.__dict__
Tero Marttila <terom@fixme.fi>
parents: 75
diff changeset
    65
        
891545a38a2b change utils.LazyProperty to store the cached value using obj.__dict__
Tero Marttila <terom@fixme.fi>
parents: 75
diff changeset
    66
        # return it
891545a38a2b change utils.LazyProperty to store the cached value using obj.__dict__
Tero Marttila <terom@fixme.fi>
parents: 75
diff changeset
    67
        return value
96
d9cf1e272e90 fix LazyProperty to not inherit from property, so as to act as a non-data descriptor, which can then be overriden by per-instance __dict__ values
Tero Marttila <terom@fixme.fi>
parents: 84
diff changeset
    68
    
59
fbbe956229cc remove old utils and write some new ones
Tero Marttila <terom@fixme.fi>
parents: 44
diff changeset
    69
class LazyIteratorProperty (LazyProperty) :
fbbe956229cc remove old utils and write some new ones
Tero Marttila <terom@fixme.fi>
parents: 44
diff changeset
    70
    """
109
66a01c0806f1 backout config.read_only as a useless feature
Tero Marttila <terom@fixme.fi>
parents: 96
diff changeset
    71
        A lazy-loaded property that automatically converts an iterator/genexp into a non-mutable tuple.
59
fbbe956229cc remove old utils and write some new ones
Tero Marttila <terom@fixme.fi>
parents: 44
diff changeset
    72
    """
fbbe956229cc remove old utils and write some new ones
Tero Marttila <terom@fixme.fi>
parents: 44
diff changeset
    73
73
8897352630a5 misc. stuff in gallery.py utils.py
Tero Marttila <terom@fixme.fi>
parents: 59
diff changeset
    74
    def run (self, obj) :
109
66a01c0806f1 backout config.read_only as a useless feature
Tero Marttila <terom@fixme.fi>
parents: 96
diff changeset
    75
        return tuple(self.func(obj))
59
fbbe956229cc remove old utils and write some new ones
Tero Marttila <terom@fixme.fi>
parents: 44
diff changeset
    76
fbbe956229cc remove old utils and write some new ones
Tero Marttila <terom@fixme.fi>
parents: 44
diff changeset
    77
lazy_load = LazyProperty
fbbe956229cc remove old utils and write some new ones
Tero Marttila <terom@fixme.fi>
parents: 44
diff changeset
    78
lazy_load_iter = LazyIteratorProperty
fbbe956229cc remove old utils and write some new ones
Tero Marttila <terom@fixme.fi>
parents: 44
diff changeset
    79
120
55cb7fc9c8fb add new exif.py to abstract between different exif libraries, and add partially working support for pyexiv2 and EXIFpy
Tero Marttila <terom@fixme.fi>
parents: 109
diff changeset
    80
def first (iterable) :
55cb7fc9c8fb add new exif.py to abstract between different exif libraries, and add partially working support for pyexiv2 and EXIFpy
Tero Marttila <terom@fixme.fi>
parents: 109
diff changeset
    81
    """
55cb7fc9c8fb add new exif.py to abstract between different exif libraries, and add partially working support for pyexiv2 and EXIFpy
Tero Marttila <terom@fixme.fi>
parents: 109
diff changeset
    82
        Returns the first item from the iterable that evaluates to True, otherwise None.
55cb7fc9c8fb add new exif.py to abstract between different exif libraries, and add partially working support for pyexiv2 and EXIFpy
Tero Marttila <terom@fixme.fi>
parents: 109
diff changeset
    83
55cb7fc9c8fb add new exif.py to abstract between different exif libraries, and add partially working support for pyexiv2 and EXIFpy
Tero Marttila <terom@fixme.fi>
parents: 109
diff changeset
    84
        >>> first((0, 1))
55cb7fc9c8fb add new exif.py to abstract between different exif libraries, and add partially working support for pyexiv2 and EXIFpy
Tero Marttila <terom@fixme.fi>
parents: 109
diff changeset
    85
        1
55cb7fc9c8fb add new exif.py to abstract between different exif libraries, and add partially working support for pyexiv2 and EXIFpy
Tero Marttila <terom@fixme.fi>
parents: 109
diff changeset
    86
        >>> first("abc")
55cb7fc9c8fb add new exif.py to abstract between different exif libraries, and add partially working support for pyexiv2 and EXIFpy
Tero Marttila <terom@fixme.fi>
parents: 109
diff changeset
    87
        'a'
55cb7fc9c8fb add new exif.py to abstract between different exif libraries, and add partially working support for pyexiv2 and EXIFpy
Tero Marttila <terom@fixme.fi>
parents: 109
diff changeset
    88
        >>> first(('', list(), (), False))
55cb7fc9c8fb add new exif.py to abstract between different exif libraries, and add partially working support for pyexiv2 and EXIFpy
Tero Marttila <terom@fixme.fi>
parents: 109
diff changeset
    89
        None
55cb7fc9c8fb add new exif.py to abstract between different exif libraries, and add partially working support for pyexiv2 and EXIFpy
Tero Marttila <terom@fixme.fi>
parents: 109
diff changeset
    90
    """
55cb7fc9c8fb add new exif.py to abstract between different exif libraries, and add partially working support for pyexiv2 and EXIFpy
Tero Marttila <terom@fixme.fi>
parents: 109
diff changeset
    91
55cb7fc9c8fb add new exif.py to abstract between different exif libraries, and add partially working support for pyexiv2 and EXIFpy
Tero Marttila <terom@fixme.fi>
parents: 109
diff changeset
    92
    for item in iterable :
55cb7fc9c8fb add new exif.py to abstract between different exif libraries, and add partially working support for pyexiv2 and EXIFpy
Tero Marttila <terom@fixme.fi>
parents: 109
diff changeset
    93
        if item :
55cb7fc9c8fb add new exif.py to abstract between different exif libraries, and add partially working support for pyexiv2 and EXIFpy
Tero Marttila <terom@fixme.fi>
parents: 109
diff changeset
    94
            return item
55cb7fc9c8fb add new exif.py to abstract between different exif libraries, and add partially working support for pyexiv2 and EXIFpy
Tero Marttila <terom@fixme.fi>
parents: 109
diff changeset
    95
55cb7fc9c8fb add new exif.py to abstract between different exif libraries, and add partially working support for pyexiv2 and EXIFpy
Tero Marttila <terom@fixme.fi>
parents: 109
diff changeset
    96
    else :
55cb7fc9c8fb add new exif.py to abstract between different exif libraries, and add partially working support for pyexiv2 and EXIFpy
Tero Marttila <terom@fixme.fi>
parents: 109
diff changeset
    97
        return None
55cb7fc9c8fb add new exif.py to abstract between different exif libraries, and add partially working support for pyexiv2 and EXIFpy
Tero Marttila <terom@fixme.fi>
parents: 109
diff changeset
    98
55cb7fc9c8fb add new exif.py to abstract between different exif libraries, and add partially working support for pyexiv2 and EXIFpy
Tero Marttila <terom@fixme.fi>
parents: 109
diff changeset
    99
96
d9cf1e272e90 fix LazyProperty to not inherit from property, so as to act as a non-data descriptor, which can then be overriden by per-instance __dict__ values
Tero Marttila <terom@fixme.fi>
parents: 84
diff changeset
   100
# testing
d9cf1e272e90 fix LazyProperty to not inherit from property, so as to act as a non-data descriptor, which can then be overriden by per-instance __dict__ values
Tero Marttila <terom@fixme.fi>
parents: 84
diff changeset
   101
if __name__ == '__main__' :
d9cf1e272e90 fix LazyProperty to not inherit from property, so as to act as a non-data descriptor, which can then be overriden by per-instance __dict__ values
Tero Marttila <terom@fixme.fi>
parents: 84
diff changeset
   102
    import doctest
d9cf1e272e90 fix LazyProperty to not inherit from property, so as to act as a non-data descriptor, which can then be overriden by per-instance __dict__ values
Tero Marttila <terom@fixme.fi>
parents: 84
diff changeset
   103
d9cf1e272e90 fix LazyProperty to not inherit from property, so as to act as a non-data descriptor, which can then be overriden by per-instance __dict__ values
Tero Marttila <terom@fixme.fi>
parents: 84
diff changeset
   104
    doctest.testmod()
d9cf1e272e90 fix LazyProperty to not inherit from property, so as to act as a non-data descriptor, which can then be overriden by per-instance __dict__ values
Tero Marttila <terom@fixme.fi>
parents: 84
diff changeset
   105