mirror of
https://git.yoctoproject.org/poky
synced 2026-06-15 05:40:00 +00:00
9501864db8
There are much better ways to handle this and most editors shouldn't need this in modern times, drop the noise from the files. Its not consitently applied anyway. (Bitbake rev: 5e43070e3087d09aea2f459b033d035c5ef747d0) Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
305 lines
7.1 KiB
Python
305 lines
7.1 KiB
Python
#
|
|
# This is a copy on write dictionary and set which abuses classes to try and be nice and fast.
|
|
#
|
|
# Copyright (C) 2006 Tim Ansell
|
|
#
|
|
#Please Note:
|
|
# Be careful when using mutable types (ie Dict and Lists) - operations involving these are SLOW.
|
|
# Assign a file to __warn__ to get warnings about slow operations.
|
|
#
|
|
|
|
|
|
import copy
|
|
import types
|
|
ImmutableTypes = (
|
|
bool,
|
|
complex,
|
|
float,
|
|
int,
|
|
tuple,
|
|
frozenset,
|
|
str
|
|
)
|
|
|
|
MUTABLE = "__mutable__"
|
|
|
|
class COWMeta(type):
|
|
pass
|
|
|
|
class COWDictMeta(COWMeta):
|
|
__warn__ = False
|
|
__hasmutable__ = False
|
|
__marker__ = tuple()
|
|
|
|
def __str__(cls):
|
|
# FIXME: I have magic numbers!
|
|
return "<COWDict Level: %i Current Keys: %i>" % (cls.__count__, len(cls.__dict__) - 3)
|
|
__repr__ = __str__
|
|
|
|
def cow(cls):
|
|
class C(cls):
|
|
__count__ = cls.__count__ + 1
|
|
return C
|
|
copy = cow
|
|
__call__ = cow
|
|
|
|
def __setitem__(cls, key, value):
|
|
if value is not None and not isinstance(value, ImmutableTypes):
|
|
if not isinstance(value, COWMeta):
|
|
cls.__hasmutable__ = True
|
|
key += MUTABLE
|
|
setattr(cls, key, value)
|
|
|
|
def __getmutable__(cls, key, readonly=False):
|
|
nkey = key + MUTABLE
|
|
try:
|
|
return cls.__dict__[nkey]
|
|
except KeyError:
|
|
pass
|
|
|
|
value = getattr(cls, nkey)
|
|
if readonly:
|
|
return value
|
|
|
|
if not cls.__warn__ is False and not isinstance(value, COWMeta):
|
|
print("Warning: Doing a copy because %s is a mutable type." % key, file=cls.__warn__)
|
|
try:
|
|
value = value.copy()
|
|
except AttributeError as e:
|
|
value = copy.copy(value)
|
|
setattr(cls, nkey, value)
|
|
return value
|
|
|
|
__getmarker__ = []
|
|
def __getreadonly__(cls, key, default=__getmarker__):
|
|
"""\
|
|
Get a value (even if mutable) which you promise not to change.
|
|
"""
|
|
return cls.__getitem__(key, default, True)
|
|
|
|
def __getitem__(cls, key, default=__getmarker__, readonly=False):
|
|
try:
|
|
try:
|
|
value = getattr(cls, key)
|
|
except AttributeError:
|
|
value = cls.__getmutable__(key, readonly)
|
|
|
|
# This is for values which have been deleted
|
|
if value is cls.__marker__:
|
|
raise AttributeError("key %s does not exist." % key)
|
|
|
|
return value
|
|
except AttributeError as e:
|
|
if not default is cls.__getmarker__:
|
|
return default
|
|
|
|
raise KeyError(str(e))
|
|
|
|
def __delitem__(cls, key):
|
|
cls.__setitem__(key, cls.__marker__)
|
|
|
|
def __revertitem__(cls, key):
|
|
if key not in cls.__dict__:
|
|
key += MUTABLE
|
|
delattr(cls, key)
|
|
|
|
def __contains__(cls, key):
|
|
return cls.has_key(key)
|
|
|
|
def has_key(cls, key):
|
|
value = cls.__getreadonly__(key, cls.__marker__)
|
|
if value is cls.__marker__:
|
|
return False
|
|
return True
|
|
|
|
def iter(cls, type, readonly=False):
|
|
for key in dir(cls):
|
|
if key.startswith("__"):
|
|
continue
|
|
|
|
if key.endswith(MUTABLE):
|
|
key = key[:-len(MUTABLE)]
|
|
|
|
if type == "keys":
|
|
yield key
|
|
|
|
try:
|
|
if readonly:
|
|
value = cls.__getreadonly__(key)
|
|
else:
|
|
value = cls[key]
|
|
except KeyError:
|
|
continue
|
|
|
|
if type == "values":
|
|
yield value
|
|
if type == "items":
|
|
yield (key, value)
|
|
return
|
|
|
|
def iterkeys(cls):
|
|
return cls.iter("keys")
|
|
def itervalues(cls, readonly=False):
|
|
if not cls.__warn__ is False and cls.__hasmutable__ and readonly is False:
|
|
print("Warning: If you arn't going to change any of the values call with True.", file=cls.__warn__)
|
|
return cls.iter("values", readonly)
|
|
def iteritems(cls, readonly=False):
|
|
if not cls.__warn__ is False and cls.__hasmutable__ and readonly is False:
|
|
print("Warning: If you arn't going to change any of the values call with True.", file=cls.__warn__)
|
|
return cls.iter("items", readonly)
|
|
|
|
class COWSetMeta(COWDictMeta):
|
|
def __str__(cls):
|
|
# FIXME: I have magic numbers!
|
|
return "<COWSet Level: %i Current Keys: %i>" % (cls.__count__, len(cls.__dict__) -3)
|
|
__repr__ = __str__
|
|
|
|
def cow(cls):
|
|
class C(cls):
|
|
__count__ = cls.__count__ + 1
|
|
return C
|
|
|
|
def add(cls, value):
|
|
COWDictMeta.__setitem__(cls, repr(hash(value)), value)
|
|
|
|
def remove(cls, value):
|
|
COWDictMeta.__delitem__(cls, repr(hash(value)))
|
|
|
|
def __in__(cls, value):
|
|
return repr(hash(value)) in COWDictMeta
|
|
|
|
def iterkeys(cls):
|
|
raise TypeError("sets don't have keys")
|
|
|
|
def iteritems(cls):
|
|
raise TypeError("sets don't have 'items'")
|
|
|
|
# These are the actual classes you use!
|
|
class COWDictBase(object, metaclass = COWDictMeta):
|
|
__count__ = 0
|
|
|
|
class COWSetBase(object, metaclass = COWSetMeta):
|
|
__count__ = 0
|
|
|
|
if __name__ == "__main__":
|
|
import sys
|
|
COWDictBase.__warn__ = sys.stderr
|
|
a = COWDictBase()
|
|
print("a", a)
|
|
|
|
a['a'] = 'a'
|
|
a['b'] = 'b'
|
|
a['dict'] = {}
|
|
|
|
b = a.copy()
|
|
print("b", b)
|
|
b['c'] = 'b'
|
|
|
|
print()
|
|
|
|
print("a", a)
|
|
for x in a.iteritems():
|
|
print(x)
|
|
print("--")
|
|
print("b", b)
|
|
for x in b.iteritems():
|
|
print(x)
|
|
print()
|
|
|
|
b['dict']['a'] = 'b'
|
|
b['a'] = 'c'
|
|
|
|
print("a", a)
|
|
for x in a.iteritems():
|
|
print(x)
|
|
print("--")
|
|
print("b", b)
|
|
for x in b.iteritems():
|
|
print(x)
|
|
print()
|
|
|
|
try:
|
|
b['dict2']
|
|
except KeyError as e:
|
|
print("Okay!")
|
|
|
|
a['set'] = COWSetBase()
|
|
a['set'].add("o1")
|
|
a['set'].add("o1")
|
|
a['set'].add("o2")
|
|
|
|
print("a", a)
|
|
for x in a['set'].itervalues():
|
|
print(x)
|
|
print("--")
|
|
print("b", b)
|
|
for x in b['set'].itervalues():
|
|
print(x)
|
|
print()
|
|
|
|
b['set'].add('o3')
|
|
|
|
print("a", a)
|
|
for x in a['set'].itervalues():
|
|
print(x)
|
|
print("--")
|
|
print("b", b)
|
|
for x in b['set'].itervalues():
|
|
print(x)
|
|
print()
|
|
|
|
a['set2'] = set()
|
|
a['set2'].add("o1")
|
|
a['set2'].add("o1")
|
|
a['set2'].add("o2")
|
|
|
|
print("a", a)
|
|
for x in a.iteritems():
|
|
print(x)
|
|
print("--")
|
|
print("b", b)
|
|
for x in b.iteritems(readonly=True):
|
|
print(x)
|
|
print()
|
|
|
|
del b['b']
|
|
try:
|
|
print(b['b'])
|
|
except KeyError:
|
|
print("Yay! deleted key raises error")
|
|
|
|
if 'b' in b:
|
|
print("Boo!")
|
|
else:
|
|
print("Yay - has_key with delete works!")
|
|
|
|
print("a", a)
|
|
for x in a.iteritems():
|
|
print(x)
|
|
print("--")
|
|
print("b", b)
|
|
for x in b.iteritems(readonly=True):
|
|
print(x)
|
|
print()
|
|
|
|
b.__revertitem__('b')
|
|
|
|
print("a", a)
|
|
for x in a.iteritems():
|
|
print(x)
|
|
print("--")
|
|
print("b", b)
|
|
for x in b.iteritems(readonly=True):
|
|
print(x)
|
|
print()
|
|
|
|
b.__revertitem__('dict')
|
|
print("a", a)
|
|
for x in a.iteritems():
|
|
print(x)
|
|
print("--")
|
|
print("b", b)
|
|
for x in b.iteritems(readonly=True):
|
|
print(x)
|
|
print()
|