Strony

środa, 8 sierpnia 2012

one type list in python

Handy list-like class holding only one type of items.
########################################################################
# $HeadURL $
# File: TypedList.py
# Author: Krzysztof.Ciba@NOSPAMgmail.com
# Date: 2012/07/19 08:21:16
########################################################################
""" :mod: TypedList
=======================
.. module: TypedList
:synopsis: typed list
.. moduleauthor:: Krzysztof.Ciba@NOSPAMgmail.com
typed list
"""
##
# @file TypedList.py
# @author Krzysztof.Ciba@NOSPAMgmail.com
# @date 2012/07/19 08:21:22
# @brief Definition of TypedList class.
class Unsortable( list ):
def sort( self, *args, **kwargs ):
return
class TypedList( list ):
"""
.. class:: TypedList
A list-like class holding only objects of specified type(s).
"""
def __init__( self, iterable=None, allowedTypes=None ):
""" c'tor
:param self: self reference
:param mixed iterable: initial values
:param tuple allowedTypes: alowed types tuple
"""
iterable = list() if not iterable else iterable
## make sure it is iterable
iter(iterable)
types = allowedTypes if isinstance( allowedTypes, tuple ) else ( allowedTypes, )
for item in types:
if not isinstance( item, type ):
raise TypeError("%s is not a type" % repr(item) )
self._allowedTypes = allowedTypes
map( self._typeCheck, iterable )
list.__init__( self, iterable )
def allowedTypes( self ):
""" allowed types getter """
return self._allowedTypes
def _typeCheck( self, val ):
""" check type of :val:
:param self: self reference
:param mixed val: obj to check
"""
if not self._allowedTypes:
return
if not isinstance( val, self._allowedTypes ):
raise TypeError("Wrong type %s, this list can hold only instances of %s" % ( type(val),
str(self._allowedTypes) ) )
def __iadd__( self, other ):
""" += operator
:param self: self reference
:param mixed other: itarable to add
:raises: TypeError
"""
map( self._typeCheck, other )
list.__iadd__( self, other )
return self
def __add__( self, other ):
""" plus lvalue operator
:param self: self reference
:param mixed other: rvalue iterable
:return: TypedList
:raises: TypeError
"""
iterable = [ item for item in self ] + [ item for item in other ]
return TypedList( iterable, self._allowedTypes )
def __radd__( self, other ):
""" plus rvalue operator
:param self: self reference
:param mixed other: lvalue iterable
:raises: TypeError
:return: TypedList
"""
iterable = [ item for item in other ] + [ item for item in self ]
if isinstance( other, TypedList ):
return self.__class__( iterable , other.allowedTypes() )
return TypedList( iterable, self._allowedTypes )
def __setitem__( self, key, value ):
""" setitem operator
:param self: self reference
:param int or slice key: index
:param mixed value: a value to set
:raises: TypeError
"""
itervalue = ( value, )
if isinstance( key, slice ):
iter( value )
itervalue = value
map( self._typeCheck, itervalue )
list.__setitem__( self, key, value )
def __setslice__( self, i, j, iterable ):
""" setslice slot, only for python 2.6
:param self: self reference
:param int i: start index
:param int j: end index
:param mixed iterable: iterable
"""
iter(iterable)
map( self._typeCheck, iterable )
list.__setslice__( self, i, j, iterable )
def append( self, val ):
""" append :val: to list
:param self: self reference
:param mixed val: value
"""
self._typeCheck( val )
list.append( self, val )
def extend( self, iterable ):
""" extend list with :iterable:
:param self: self referenace
:param mixed iterable: an interable
"""
iter(iterable)
map( self._typeCheck, iterable )
list.extend( self, iterable )
def insert( self, i, val ):
""" insert :val: at index :i:
:param self: self reference
:param int i: index
:param mixed val: value to set
"""
self._typeCheck( val )
list.insert( self, i, val )
class BooleanList( TypedList ):
"""
.. class:: BooleanList
A list holding only True or False items.
"""
def __init__( self, iterable = None ):
""" c'tor
:param self: self reference
:param mixed iterable: initial values
"""
TypedList.__init__( self, iterable, allowedTypes = bool )
class IntList( TypedList ):
"""
.. class:: IntList
A list holding only int type items.
"""
def __init__( self, iterable = None ):
""" c'tor
:param self: self reference
:param mixed iterable: initial values
"""
TypedList.__init__( self, iterable, allowedTypes = int )
class LongList( TypedList ):
"""
.. class:: LongList
A list holding only long type items.
"""
def __init__( self, iterable = None ):
""" c'tor
:param self: self reference
:param mixed iterable: initial values
"""
TypedList.__init__( self, iterable, allowedTypes = long )
class FloatList( TypedList ):
"""
.. class:: FloatList
A list holding only float type items.
"""
def __init__( self, iterable = None ):
""" c'tor
:param self: self reference
:param mixed iterable: initial values
"""
TypedList.__init__( self, iterable, allowedTypes = float )
class NumericList( TypedList ):
"""
.. class:: NumericList
A list holding only int, long or float type items.
"""
def __init__( self, iterable = None ):
""" c'tor
:param self: self reference
:param mixed iterable: initial values
"""
TypedList.__init__( self, iterable, allowedTypes = ( int, long, float ) )
class StrList( TypedList ):
"""
.. class:: StrList
A list holding only str type items.
"""
def __init__( self, iterable = None ):
""" c'tor
:param self: self reference
:param mixed iterable: initial values
"""
TypedList.__init__( self, iterable, allowedTypes = str )
class StringsList( TypedList ):
"""
.. class:: StringsList
A list holding only str or unicode type items.
"""
def __init__( self, iterable = None ):
""" c'tor
:param self: self reference
:param mixed iterable: initial values
"""
TypedList.__init__( self, iterable, allowedTypes = ( str, unicode ) )
view raw TypedList.py hosted with ❤ by GitHub

python traced class

With metaclass programming in python you can easily created a class tracing all updates to its attributes:
########################################################################
# $HeadURL $
# File: Traced.py
# Author: Krzysztof.Ciba@NOSPAMgmail.com
# Date: 2012/08/08 13:29:18
########################################################################
""" :mod: Traced
============
.. module: Traced
:synopsis: watched mutable metaclass
.. moduleauthor:: Krzysztof.Ciba@NOSPAMgmail.com
watched mutable metaclass tracing all updated indexes or keys
"""
##
# @file Traced.py
# @author Krzysztof.Ciba@NOSPAMgmail.com
# @date 2012/08/08 13:29:27
# @brief Definition of Traced metaclass.
########################################################################
class Traced( type ):
"""
.. class:: Traced
metaclass telling if some attrs was updated
1. overwrites __setattr__ and __setitem__
2. adds updated member function and __updated__ attribute
"""
def __new__( cls, cls_name, bases, classdict ):
""" prepare new class instance """
def updated( self, element=None, reset=False ):
""" updates and returns __updated__ list
:param self: self reference
:param mixed element: key name or list index
:param bool reset: flag to zero __updated__ list
:return: __updated__ list when called without arguments
"""
if not self.__update__ or reset:
self.__update__ = list()
if element and element not in self.__update__:
self.__update__.append( element )
return self.__update__
def trace_setattr( self, name, value ):
""" __setattr__ tracing value update """
if name != "__update__":
if not hasattr( self, name ) or getattr( self, name ) != value:
self.updated( name )
bases[0].__setattr__( self, name, value )
def trace_setitem( self, ind, item ):
""" __setitem__ tracing value update """
try:
if bases[0].__getitem__( self, ind ) != item:
self.updated( ind )
except KeyError:
self.updated( ind )
bases[0].__setitem__( self, ind, item )
classdict["__setattr__"] = trace_setattr
classdict["__setitem__"] = trace_setitem
classdict["updated"] = updated
classdict["__update__"] = None
return type.__new__( cls, cls_name, bases, classdict )
class TracedDict(dict):
""" traced dict """
__metaclass__ = Traced
class TracedList(list):
""" traced list """
__metaclass__ = Traced
class TracedTest( object )
""" test class
:param classAttribute: name says it all
:param instanceAttribute: ditto
"""
__metaclass__ = Traced
classAttribute = None
def __init__( self ):
self.instanceAttribute = None
#self.updated( reset=True )
view raw Traced.py hosted with ❤ by GitHub
All objects using Traced metaclass are able to tell you which attributes have been changed. To get list of updated attributes (or keys when using TracedDict or indexes in case of TracedList) just call updated member function. There is only one shortage: attributes defined and set inside __init__ (real instance attributes like instanceAttribute in TracedTest class) will be put into updated list when calling constructor. To avoid this behavior and trace changed during lifetime of object you need at call at ther very last line in constructor self.updated( reset = True ) (or uncomment last line in above example).