Onyx logo

Previous topic

Base

Next topic

onyx.doctestmod – Module for running of doctest on Onyx modules.

This Page

onyx.builtin – Low-level containers and mixin classes, candidates for being builtin.

class onyx.builtin.FrozenSetView(target)

Bases: _abcoll.Set, _abcoll.Hashable

Lightweight wrapper around target object, exposing immutable Set functionality of the target. This means target must support Python’s Container, Iterable, and Sized ABCs. See Python’s collections module.

Prompted by the frequent need to expose these semantics on a frozendict without exposing its contents.

>>> container = frozendict((x, 2*x) for x in xrange(10))
>>> fsv = FrozenSetView(container)
>>> isinstance(fsv, _collections.Set)
True
>>> len(fsv)
10
>>> 7 in fsv
True
>>> tuple(fsv)
(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
>>> print fsv
<FrozenSetView of frozendict of 10 items>
>>> fsv
FrozenSetView(frozenset([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]))

Generous set semantic (provided by Python’s collections.Set).

>>> fsv & (3, 5, 'a')
FrozenSetView(frozenset([3, 5]))
>>> fsv | 'abc'
FrozenSetView(frozenset([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 'c', 'b', 'a']))
>>> fsv - xrange(3, 20)
FrozenSetView(frozenset([0, 1, 2]))
>>> fsv ^ xrange(-3, 7)
FrozenSetView(frozenset([7, 8, 9, -1, -3, -2]))
>>> fsv is FrozenSetView(fsv)
True
>>> _checkutils.check_pickle(FrozenSetView(()))
>>> _checkutils.check_pickle(fsv)
isdisjoint(other)
class onyx.builtin.SizedIterableContainer(target)

Bases: _abcoll.Container, _abcoll.Iterable, _abcoll.Sized

Lightweight wrapper around target object, exposing Sized, Iterable, and Contains functionality of the target.

Prompted by the frequent need to expose these semantics on a dict without exposing its contents

>>> container = dict((x, 2*x) for x in xrange(10))
>>> sic = SizedIterableContainer(container)
>>> len(sic)
10
>>> 7 in sic
True
>>> tuple(sic)
(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
>>> sic
<SizedIterableContainer of dict of 10 items>
exception onyx.builtin.StrictError

Bases: exceptions.ValueError

args
message
class onyx.builtin.attrdict

Bases: onyx.builtin._rst_clean_dict, onyx.builtin.has

Creates a specialization of dict with the feature that dotted attribute syntax can be used to access items whose keys are strings that are valid Python identifiers. Also, the attribute hasattr supports attribute syntax to see if the instance has a particular attribute.

If a subclass has a __slots__ class attribute with symbol names that begin with underscore, these symbols will be treated as regular instance attributes and will not appear in the dictionary.

>>> d = attrdict({'foo':3})
>>> d.foo
3
>>> _checkutils.check_pickle(d)
>>> d.bar = 4
>>> d['bar']
4
>>> _checkutils.check_pickle(d)
>>> del d.foo
>>> d
attrdict({'bar': 4})
>>> _checkutils.check_pickle(d)
>>> d.hasattr.bar
True
>>> d.hasattr.foo
False
>>> class foo(attrdict):
...   __slots__ = '_foobar'
>>> f = foo()
>>> f.bar = 2
>>> f._foobar = 1
>>> f.hasattr.bar
True
>>> f.hasattr._foobar
True
>>> f
attrdict({'bar': 2})
>>> f.bar
2
>>> f._foobar
1
>>> del f._foobar
>>> f._foobar
Traceback (most recent call last):
  ...
AttributeError: _foobar
>>> del f.no_such_attr
Traceback (most recent call last):
  ...
AttributeError: 'foo' object has no attribute (or no key) 'no_such_attr'
>>> _checkutils.check_pickle(attrdict())
>>> _checkutils.check_pickle(attrdict({'yow':0, '_foo':1, '__bar__':2, '':3, 20:4, None:5}))
clear

D.clear() -> None. Remove all items from D.

copy()
static fromkeys()

dict.fromkeys(S[,v]) -> New dict with keys from S and values equal to v. v defaults to None.

get

D.get(k[,d]) -> D[k] if k in D, else d. d defaults to None.

has_key

D.has_key(k) -> True if D has a key k, else False

items

D.items() -> list of D’s (key, value) pairs, as 2-tuples

iteritems

D.iteritems() -> an iterator over the (key, value) items of D

iterkeys

D.iterkeys() -> an iterator over the keys of D

itervalues

D.itervalues() -> an iterator over the values of D

keys

D.keys() -> list of D’s keys

pop

D.pop(k[,d]) -> v, remove specified key and return the corresponding value. If key is not found, d is returned if given, otherwise KeyError is raised

popitem

D.popitem() -> (k, v), remove and return some (key, value) pair as a 2-tuple; but raise KeyError if D is empty.

setdefault

D.setdefault(k[,d]) -> D.get(k,d), also set D[k]=d if k not in D

update(E, **kwargs)

D.update(E, **F) -> None. Update D from dict/iterable E and F. If E has a .keys() method, does: for k in E: D[k] = E[k] If E lacks .keys() method, does: for (k, v) in E: D[k] = v In either case, this is followed by: for k in F: D[k] = F[k]

values

D.values() -> list of D’s values

viewitems

D.viewitems() -> a set-like object providing a view on D’s items

viewkeys

D.viewkeys() -> a set-like object providing a view on D’s keys

viewvalues

D.viewvalues() -> an object providing a view on D’s values

onyx.builtin.compose(*callables)

Return a function that is the composition of the input argument callables, an iterable of one or more callables.

Calling the returned function is equivalent to applying the rightmost argument function, followed by the next rightmost argument function, until the argument functions are exhausted.

>>> def f1(x): print 'applying f1'; return x + 3
>>> def f2(x): print 'applying f2'; return x / 3
>>> def f3(x): print 'applying f3'; return -x
>>> c1 = compose(f1, f2, f3)
>>> c1(3)
applying f3
applying f2
applying f1
2
>>> f1(f2(f3(3)))
applying f3
applying f2
applying f1
2

Edge case

>>> compose(f1)(4)
applying f1
7

Error cases

>>> compose()
Traceback (most recent call last):
  ...
ValueError: expected number of arguments to be to be greater than 0, got 0
>>> compose('a', 'b', 'c')
Traceback (most recent call last):
  ...
TypeError: expected all arguments to be callable, got a str
class onyx.builtin.dict_of(container_type, arg=())

Bases: onyx.builtin._rst_clean_dict

A dict specialization that maintians its items as instances of the container type that is the first argument to the constructor. It will automatically insert an empty instance of container when a missing key is used. Construction from an existing dict, as second constructor arument, will automatically convert items to a new instance of container. That is, copy construction goes one level deeper than ordinary dictionary copy construction.

>>> d = dict_of(set)
>>> d['a'].add(1)
>>> d['a'].add(2)
>>> len(d), len(d['a'])
(1, 2)
>>> d['a'].add(2)
>>> len(d), len(d['a'])
(1, 2)
>>> d['b'].update(xrange(10, 15))
>>> d[0] = set((1, 2, 3))
>>> d
dict_of(set, {'a': set([1, 2]), 0: set([1, 2, 3]), 'b': set([10, 11, 12, 13, 14])})
>>> #dict_of(set, frozendict_of(frozenset, d))
dict_of(set, {'a': set([1, 2]), 0: set([1, 2, 3]), 'b': set([10, 11, 12, 13, 14])})

Whenever you directly set an item at a key in the dictionary, the value you provide will be iterated over during the copy into the dict’s new container for that key. Thus, you can assign directly from a generator:

>>> d[10] = (x*x for x in xrange(-4, 4))
>>> d[10]
set([16, 9, 4, 0, 1])

But, this means you must be careful when you want to set the container for a key in the dict with a single new value. In this case you must make sure that the provided value is wrapped in a container. Failure to do so gives unintended results, and silently so if the value is itself an iterable object. E.g., when trying to make the item at key 0 be a set containing a single string, a simple assignment will not behave as intended:

>>> d[0] = 'abc'
>>> d[0]
set(['a', 'c', 'b'])

This rarely used, but effective, syntax will wrap the item in a tuple:

>>> d[0] = 'abc',
>>> d[0]
set(['abc'])

Or use a list:

>>> d[1] = ['def']
>>> d[1]
set(['def'])

If a non-iterable value is used in an incorrect assignment, you’ll get a some kind of error regarding the object:

>>> d[0] = 10
Traceback (most recent call last):
  ...
TypeError: 'int' object is not iterable

In addition to normal dict iterations, you can iterate through a ‘flattened’ view of the data in the dictionary. The first item in each yielded tuple is a key in the dict, and the second item is one of the values in the container at that key:

>>> for pair in d.iter_flat:
...   print pair
('a', 1)
('a', 2)
(0, 'abc')
(10, 16)
(10, 9)
(10, 4)
(10, 0)
(10, 1)
('b', 10)
('b', 11)
('b', 12)
('b', 13)
('b', 14)
(1, 'def')
clear

D.clear() -> None. Remove all items from D.

copy

D.copy() -> a shallow copy of D

static fromkeys()

dict.fromkeys(S[,v]) -> New dict with keys from S and values equal to v. v defaults to None.

get

D.get(k[,d]) -> D[k] if k in D, else d. d defaults to None.

has_key

D.has_key(k) -> True if D has a key k, else False

items

D.items() -> list of D’s (key, value) pairs, as 2-tuples

iter_flat
iteritems

D.iteritems() -> an iterator over the (key, value) items of D

iterkeys

D.iterkeys() -> an iterator over the keys of D

itervalues

D.itervalues() -> an iterator over the values of D

keys

D.keys() -> list of D’s keys

pop

D.pop(k[,d]) -> v, remove specified key and return the corresponding value. If key is not found, d is returned if given, otherwise KeyError is raised

popitem

D.popitem() -> (k, v), remove and return some (key, value) pair as a 2-tuple; but raise KeyError if D is empty.

setdefault(key, value)
update(E, **kwargs)

D.update(E, **F) -> None. Update D from dict/iterable E and F. If E has a .keys() method, does: for k in E: D[k] = E[k] If E lacks .keys() method, does: for (k, v) in E: D[k] = v In either case, this is followed by: for k in F: D[k] = F[k]

values

D.values() -> list of D’s values

viewitems

D.viewitems() -> a set-like object providing a view on D’s items

viewkeys

D.viewkeys() -> a set-like object providing a view on D’s keys

viewvalues

D.viewvalues() -> an object providing a view on D’s values

class onyx.builtin.dict_of_set(arg=())

Bases: onyx.builtin._rst_clean_dict

A dict specialization that requires its items to be instances of set. Will automatically insert an empty set when a missing key is used. Construction will convert a frozendict_of_set to a dict_of_set.

>>> d = dict_of_set()
>>> d['a'].add(1)
>>> d['a'].add(2)
>>> len(d), len(d['a'])
(1, 2)
>>> d['a'].add(2)
>>> len(d), len(d['a'])
(1, 2)
>>> d['b'].update(xrange(10, 15))
>>> d[0] = set((1, 2, 3))
>>> d
dict_of_set({'a': set([1, 2]), 0: set([1, 2, 3]), 'b': set([10, 11, 12, 13, 14])})
>>> dict_of_set(frozendict_of_set(d))
dict_of_set({'a': set([1, 2]), 0: set([1, 2, 3]), 'b': set([10, 11, 12, 13, 14])})
>>> _checkutils.check_pickle(dict_of_set())
>>> _checkutils.check_pickle(d)
>>> d[0] = 'abc'
Traceback (most recent call last):
  ...
TypeError: for key 0, expected a set object, got a str
clear

D.clear() -> None. Remove all items from D.

copy

D.copy() -> a shallow copy of D

static fromkeys()

dict.fromkeys(S[,v]) -> New dict with keys from S and values equal to v. v defaults to None.

get

D.get(k[,d]) -> D[k] if k in D, else d. d defaults to None.

has_key

D.has_key(k) -> True if D has a key k, else False

items

D.items() -> list of D’s (key, value) pairs, as 2-tuples

iteritems

D.iteritems() -> an iterator over the (key, value) items of D

iterkeys

D.iterkeys() -> an iterator over the keys of D

itervalues

D.itervalues() -> an iterator over the values of D

keys

D.keys() -> list of D’s keys

pop

D.pop(k[,d]) -> v, remove specified key and return the corresponding value. If key is not found, d is returned if given, otherwise KeyError is raised

popitem

D.popitem() -> (k, v), remove and return some (key, value) pair as a 2-tuple; but raise KeyError if D is empty.

setdefault(key, value)
update(E, **kwargs)

D.update(E, **F) -> None. Update D from dict/iterable E and F. If E has a .keys() method, does: for k in E: D[k] = E[k] If E lacks .keys() method, does: for (k, v) in E: D[k] = v In either case, this is followed by: for k in F: D[k] = F[k]

values

D.values() -> list of D’s values

viewitems

D.viewitems() -> a set-like object providing a view on D’s items

viewkeys

D.viewkeys() -> a set-like object providing a view on D’s keys

viewvalues

D.viewvalues() -> an object providing a view on D’s values

onyx.builtin.drop_from_map(drop_keys, mapping_object)

Given a collections.Mapping mapping_object, return a shallow copy of it ignoring the keys in drop_keys.

>>> import functools
>>> dropper = functools.partial(drop_from_map, set(['x', 'y']))
>>> dropper(dict(x=1, y=2, z=3))
{'z': 3}
>>> dropper(attrdict(x=1, y=2, z=3))
attrdict({'z': 3})
>>> dropper(wormattrdict(x=1, y=2, z=3))
wormattrdict({'z': 3})
onyx.builtin.empty_or_any(iterable)

Like Python’s any(), except that an empty iterable returns True.

Empty container example

>>> any('')
False
>>> empty_or_any('')
True
>>> empty_or_any((None, False, 0, (), ''))
False
>>> empty_or_any('abc')
True

Exhausted iteration example

>>> x = iter([])
>>> tuple(x)
()

The iter, x, is exhausted

>>> all(x)
True
>>> any(x)
False
>>> empty_or_any(x)
True
>>> bool(x)
True
class onyx.builtin.frozendict(arg=(), **kwargs)

Bases: onyx.builtin._rst_clean_dict

Creates a specialization of dict with the features that it cannot be modified and it ensures that all its contained items are immutable.

A frozendict is created and used like a dict. It can always be used as a dictionary key or as a set member. Unlike a dict, attempts to modify the object will raise a TypeError or AttributeError, and the constructor will raise a TypeError if any of the (recursively) contained items are mutable, i.e. cannot be hashed.

>>> d = dict((('a', 1), ('b', 2)))
>>> f = frozendict(d)
>>> f
frozendict({'a': 1, 'b': 2})
>>> f['a']
1
>>> dict(f)
{'a': 1, 'b': 2}

Copy construction is cheap

>>> frozendict(f) is f
True
>>> frozendict(f, foo=90, bar=89) is f
False

Can’t put a dict into a set

>>> s = set()
>>> s.add(d)
Traceback (most recent call last):
  ...
TypeError: unhashable type: 'dict'

Can put a frozendict into a set

>>> s.add(frozendict(d))
>>> s
set([frozendict({'a': 1, 'b': 2})])
>>> _checkutils.check_pickle(frozendict())
>>> _checkutils.check_pickle(frozendict({'a': 1, 'b': 2}))

Each item in the constructor iterable must be immutable

>>> frozendict((('a', 1), ('b', 2), ('c', ['mutable item is bad'])))
Traceback (most recent call last):
  ...
TypeError: unhashable type: 'list'
clear(*dummy_args)
copy()
static fromkeys()

dict.fromkeys(S[,v]) -> New dict with keys from S and values equal to v. v defaults to None.

get

D.get(k[,d]) -> D[k] if k in D, else d. d defaults to None.

has_key

D.has_key(k) -> True if D has a key k, else False

items

D.items() -> list of D’s (key, value) pairs, as 2-tuples

iteritems

D.iteritems() -> an iterator over the (key, value) items of D

iterkeys

D.iterkeys() -> an iterator over the keys of D

itervalues

D.itervalues() -> an iterator over the values of D

keys

D.keys() -> list of D’s keys

static of_frozenset(mapping)
static of_tuple(mapping)
static of_tuple_set(mapping)
static of_tuple_sorted(mapping)
static of_tuple_sorted_set(mapping)
pop(*dummy_args)
popitem(*dummy_args)
setdefault(*dummy_args)
update(*dummy_args)
values

D.values() -> list of D’s values

viewitems

D.viewitems() -> a set-like object providing a view on D’s items

viewkeys

D.viewkeys() -> a set-like object providing a view on D’s keys

viewvalues

D.viewvalues() -> an object providing a view on D’s values

class onyx.builtin.frozendict_of_set(arg=())

Bases: onyx.builtin._rst_clean_dict

A dict specialization that is immutable and that requires its items to be instances of frozenset. Construction will convert a dict_of_set to a frozendict_of_set.

>>> d = dict_of_set()
>>> d['a'].update(xrange(5, 10))
>>> d['b'].update(xrange(10, 15))
>>> f = frozendict_of_set(d)
>>> f
frozendict_of_set({'a': frozenset([8, 9, 5, 6, 7]), 'b': frozenset([10, 11, 12, 13, 14])})
>>> f[0] = frozenset((1, 2, 3))
Traceback (most recent call last):
  ...
TypeError: 'frozendict_of_set' instance does not support being modified this way
>>> _checkutils.check_pickle(frozendict_of_set())
>>> _checkutils.check_pickle(f)
clear(*dummy_args)
copy()
static fromkeys()

dict.fromkeys(S[,v]) -> New dict with keys from S and values equal to v. v defaults to None.

get

D.get(k[,d]) -> D[k] if k in D, else d. d defaults to None.

has_key

D.has_key(k) -> True if D has a key k, else False

items

D.items() -> list of D’s (key, value) pairs, as 2-tuples

iteritems

D.iteritems() -> an iterator over the (key, value) items of D

iterkeys

D.iterkeys() -> an iterator over the keys of D

itervalues

D.itervalues() -> an iterator over the values of D

keys

D.keys() -> list of D’s keys

pop(*dummy_args)
popitem(*dummy_args)
setdefault(*dummy_args)
update(*dummy_args)
values

D.values() -> list of D’s values

viewitems

D.viewitems() -> a set-like object providing a view on D’s items

viewkeys

D.viewkeys() -> a set-like object providing a view on D’s keys

viewvalues

D.viewvalues() -> an object providing a view on D’s values

class onyx.builtin.frozenlist(*arg)

Bases: list

Creates a specialization of list with the features that it cannot be modified and it ensures that all its contained items are immutable.

A frozenlist is created and used like a list. It can always be used as a dictionary key or as a set member. Unlike a list, attempts to modify the object will raise a TypeError or AttributeError, and the constructor will raise a TypeError if any of the (recursively) contained items are mutable, i.e. cannot be hashed.

>>> t = list('abc')
>>> f = frozenlist(t)
>>> f + frozenlist('def')
frozenlist(['a', 'b', 'c', 'd', 'e', 'f'])
>>> list(f)
['a', 'b', 'c']
>>> tuple(f)
('a', 'b', 'c')
>>> 3 * f
frozenlist(['a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c'])
>>> frozenlist(f) is f
True

Empty frozen list is ok

>>> frozenlist()
frozenlist([])

Can’t put a list into a set

>>> s = set()
>>> s.add(t)
Traceback (most recent call last):
  ...
TypeError: unhashable type: 'list'

Can put a frozenlist into a set

>>> s.add(frozenlist(f))
>>> s
set([frozenlist(['a', 'b', 'c'])])
>>> _checkutils.check_pickle(frozenlist())
>>> _checkutils.check_pickle(frozenlist('abc'))

Each item in the constructor iterable must be immutable

>>> frozenlist(['abc', [1, 2]])
Traceback (most recent call last):
  ...
TypeError: unhashable type: 'list'
append(*dummy_args)
count

L.count(value) -> integer – return number of occurrences of value

extend(*dummy_args)
index

L.index(value, [start, [stop]]) -> integer – return first index of value. Raises ValueError if the value is not present.

insert(*dummy_args)
pop(*dummy_args)
remove(*dummy_args)
reverse(*dummy_args)
sort(*dummy_args)
class onyx.builtin.frozentuple(*args)

Bases: tuple

Creates a specialization of tuple with the feature that it ensures that all its contained items are immutable.

A frozentuple is created and used just like a tuple, and it can always be used as a dictionary key or as a set member. Unlike tuple the constructor will raise a TypeError if any of the (recursively) contained items are mutable, i.e. cannot be hashed.

>>> t = tuple('abc')
>>> f = frozentuple(t)
>>> f + frozentuple('def')
frozentuple(('a', 'b', 'c', 'd', 'e', 'f'))
>>> tuple(f)
('a', 'b', 'c')
>>> list(f)
['a', 'b', 'c']
>>> 3 * f
frozentuple(('a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c'))

Show that copy construction is cheap

>>> frozentuple(f) is f
True

Empty frozen tuple is ok

>>> frozentuple()
frozentuple(())
>>> _checkutils.check_pickle(frozentuple())
>>> _checkutils.check_pickle(frozentuple('abc'))

Each item in the constructor iterable must be immutable

>>> frozentuple((('a', 'b', 'c'), [1, 2]))
Traceback (most recent call last):
  ...
TypeError: unhashable type: 'list'
count

T.count(value) -> integer – return number of occurrences of value

index

T.index(value, [start, [stop]]) -> integer – return first index of value. Raises ValueError if the value is not present.

class onyx.builtin.has

Bases: object

Mix-in baseclass which provides the property hasattr (a descriptor) that provides for attribute syntax on instances to introspectively see if an instance has a particular attribute.

>>> class X(has): pass
>>> x = X()
>>> x.hasattr.foo
False
>>> x.foo = 23
>>> x.hasattr.foo
True
>>> x.foo
23
>>> del x.foo
>>> x.hasattr.foo
False
onyx.builtin.izipstrict(*args)

XXX broken! this function does not always raise the error it claims to implement; it needs a layer of counters to see how much was used from each iterable....

Returns a generator very like the itertools izip function. The arguments are treated like arguments to izip. Unlike izip this function ensures that all the iterators finished after the same number of items. It raises a StrictError if not all the ierators have finished.

If StrictError is raised, in addition to a human-readable message, the exception will have attributes ‘finished’, ‘unfinished’ and ‘values’, all tuples corresponding respectively to the indices in the argument list of the iterators that had finished, the indices of the iterators that had not finished, and the initial yields from those unfinished iterators. Note that process of getting each initial yield can itself finish iterators in the unfinished set.

>>> tuple(izipstrict(xrange(5), xrange(5)))
((0, 0), (1, 1), (2, 2), (3, 3), (4, 4))

Uncaught error

>>> tuple(izipstrict(xrange(5), xrange(4), xrange(1,6), xrange(4)))
Traceback (most recent call last):
   ...
StrictError: out of 4 iterators, 2 were unfinished: at argument indices (0, 2)

Caught error and attributes

>>> try: tuple(izipstrict(xrange(5), xrange(4), xrange(1,6), xrange(4)))
... except StrictError, e: print e.finished, e.unfinished, e.values
(1, 3) (0, 2) (4, 5)
onyx.builtin.one_and_all(iterable)

Like Python’s all(), except that an empty iterable returns False.

Empty container example

>>> all('')
True
>>> one_and_all('')
False
>>> one_and_all('a')
True
>>> one_and_all('abc')
True

Exhausted iteration example

>>> x = iter([])
>>> tuple(x)
()

The iter, x, is exhausted

>>> any(x)
False
>>> all(x)
True
>>> one_and_all(x)
False
>>> bool(x)
True
class onyx.builtin.ordered_wormattrdict(*args, **kwds)

Bases: collections.OrderedDict, onyx.builtin.has

A specialization of OrderedDict with WORM and attr semantics.

The __str__() is overriden to format readably when str() is used, but not for creating an equivalent object, and not necessarily even as valid Python – use repr() for a string that will create an equivalent object if evaluated.

>>> d = ordered_wormattrdict()
>>> d.hasattr.foo
False
>>> d.foo = 20
>>> d.hasattr.foo
True
>>> d.foo
20
>>> d['foo']
20
>>> d['bar'] = 10
>>> d['bar']
10
>>> d.hasattr.bar
True
>>> d.bar
10
>>> setattr(d, 'foobar', 40)
>>> d.foobar
40
>>> d['foobar']
40
>>> getattr(d, 'foobar')
40

Update from iterable or Mapping

>>> d.update((x, x) for x in 'ABC')
>>> d.A, d.C
('A', 'C')
>>> d.update(dict(X=100, Y=1000))
>>> d.X, d.Y
(100, 1000)

But note that the above dict rendered them into the update() in Y, X order

>>> d.keys()
['foo', 'bar', 'foobar', 'A', 'B', 'C', 'Y', 'X']

Object is picklable:

>>> _checkutils.check_pickle(d)

Direct construction of a copy with one added field

>>> f = wormattrdict(d, baz=10)
>>> f
wormattrdict({'A': 'A',
 'B': 'B',
 'C': 'C',
 'X': 100,
 'Y': 1000,
 'bar': 10,
 'baz': 10,
 'foo': 20,
 'foobar': 40})

Note that this idiom can also be used to change the value of an existing field in the new dict:

>>> f = wormattrdict(d, baz=10, bar=1000)
>>> f
wormattrdict({'A': 'A',
 'B': 'B',
 'C': 'C',
 'X': 100,
 'Y': 1000,
 'bar': 1000,
 'baz': 10,
 'foo': 20,
 'foobar': 40})

Use of repr() and str()

>>> repr(d)
"ordered_wormattrdict([('foo', 20), ('bar', 10), ('foobar', 40), ('A', 'A'), ('B', 'B'), ('C', 'C'), ('Y', 1000), ('X', 100)])"
>>> d == eval(repr(d))
True

The result of str() is more readable, but always use repr() if you want an expression that preserves the order when it’s evaluated

>>> str(d)
"ordered_wormattrdict(foo=20, bar=10, foobar=40, A='A', B='B', C='C', Y=1000, X=100)"
>>> d == eval(str(d))
False
>>> d == eval(repr(d))
True

And note further limitations on the str() output

>>> e = d.copy()
>>> e['not.a.33.python.symbol!'] = 90
>>> e.keys()
['foo', 'bar', 'foobar', 'A', 'B', 'C', 'Y', 'X', 'not.a.33.python.symbol!']
>>> str(e)
"ordered_wormattrdict(foo=20, bar=10, foobar=40, A='A', B='B', C='C', Y=1000, X=100, not.a.33.python.symbol!=90)"
>>> eval(str(e))
Traceback (most recent call last):
  ...
    ordered_wormattrdict(foo=20, bar=10, foobar=40, A='A', B='B', C='C', Y=1000, X=100, not.a.33.python.symbol!=90)
                                                                                           ^
SyntaxError: invalid syntax
>>> repr(e)
"ordered_wormattrdict([('foo', 20), ('bar', 10), ('foobar', 40), ('A', 'A'), ('B', 'B'), ('C', 'C'), ('Y', 1000), ('X', 100), ('not.a.33.python.symbol!', 90)])"
>>> eval(repr(e))
ordered_wormattrdict([('foo', 20), ('bar', 10), ('foobar', 40), ('A', 'A'), ('B', 'B'), ('C', 'C'), ('Y', 1000), ('X', 100), ('not.a.33.python.symbol!', 90)])

Error cases: can’t change or delete existing keys

>>> d.bar = 30
Traceback (most recent call last):
  ...
KeyError: "ordered_wormattrdict expected key 'bar' to be unused, but it exists in the set of keys: 'foo' 'bar' 'foobar' 'A' 'B' 'C' 'Y' 'X'"
>>> d['bar'] = 35
Traceback (most recent call last):
  ...
KeyError: "ordered_wormattrdict expected key 'bar' to be unused, but it exists in the set of keys: 'foo' 'bar' 'foobar' 'A' 'B' 'C' 'Y' 'X'"
>>> d.update((x, x) for x in 'ABC')
Traceback (most recent call last):
  ...
KeyError: "ordered_wormattrdict expected key 'A' to be unused, but it exists in the set of keys: 'foo' 'bar' 'foobar' 'A' 'B' 'C' 'Y' 'X'"
>>> d.setdefault('a', 23)
Traceback (most recent call last):
  ...
TypeError: 'ordered_wormattrdict' instance does not support being modified this way
>>> del d['bar']
Traceback (most recent call last):
  ...
TypeError: 'ordered_wormattrdict' instance does not support being modified this way
>>> del d.bar
Traceback (most recent call last):
  ...
AttributeError: 'ordered_wormattrdict' object does not support modification of its attributes
>>> delattr(d, 'bar')
Traceback (most recent call last):
   ...
AttributeError: 'ordered_wormattrdict' object does not support modification of its attributes
>>> d.clear()
Traceback (most recent call last):
  ...
TypeError: 'ordered_wormattrdict' instance does not support being modified this way
>>> d.pop()
Traceback (most recent call last):
  ...
TypeError: 'ordered_wormattrdict' instance does not support being modified this way
>>> d.pop('bar')
Traceback (most recent call last):
  ...
TypeError: 'ordered_wormattrdict' instance does not support being modified this way
>>> d.popitem()
Traceback (most recent call last):
  ...
TypeError: 'ordered_wormattrdict' instance does not support being modified this way
>>> d.popitem('bar')
Traceback (most recent call last):
  ...
TypeError: 'ordered_wormattrdict' instance does not support being modified this way

Initialize an ordered dictionary. Signature is the same as for regular dictionaries, but keyword arguments are not recommended because their insertion order is arbitrary.

clear(*dummy_args)
copy()
classmethod fromkeys(iterable, value=None)

OD.fromkeys(S[, v]) -> New ordered dictionary with keys from S and values equal to v (which defaults to None).

get

D.get(k[,d]) -> D[k] if k in D, else d. d defaults to None.

has_key

D.has_key(k) -> True if D has a key k, else False

items()
iteritems()
iterkeys()
itervalues()
keys()
pop(*dummy_args)
popitem(*dummy_args)
setdefault(*dummy_args)
update(*args, **kwds)
values()
viewitems()

od.viewitems() -> a set-like object providing a view on od’s items

viewkeys()

od.viewkeys() -> a set-like object providing a view on od’s keys

viewvalues()

od.viewvalues() -> an object providing a view on od’s values

class onyx.builtin.wormattrdict

Bases: onyx.builtin.attrdict

A specialization of attrdict with write-once-read-many semantics for the underlying dictionary.

The __str__() is overriden to format readably, but not necessarily as valid Python

>>> d = wormattrdict()
>>> d.hasattr.foo
False
>>> d.foo = 20
>>> d.hasattr.foo
True
>>> d.foo
20
>>> d['foo']
20
>>> d['bar'] = 10
>>> d['bar']
10
>>> d.hasattr.bar
True
>>> d.bar
10
>>> setattr(d, 'foobar', 40)
>>> d.foobar
40
>>> d['foobar']
40
>>> getattr(d, 'foobar')
40

Update from iterable or Mapping

>>> d.update((x, x) for x in 'ABC')
>>> d.A, d.C
('A', 'C')
>>> d.update(dict(X=100, Y=1000))
>>> d.X, d.Y
(100, 1000)

Direct construction of a copy with one added field

>>> f = wormattrdict(d, baz=10)
>>> f
wormattrdict({'A': 'A',
 'B': 'B',
 'C': 'C',
 'X': 100,
 'Y': 1000,
 'bar': 10,
 'baz': 10,
 'foo': 20,
 'foobar': 40})

Note that this idiom can also be used to change the value of an existing field in the new dict:

>>> f = wormattrdict(d, baz=10, bar=1000)
>>> f
wormattrdict({'A': 'A',
 'B': 'B',
 'C': 'C',
 'X': 100,
 'Y': 1000,
 'bar': 1000,
 'baz': 10,
 'foo': 20,
 'foobar': 40})

Object is picklable:

>>> _checkutils.check_pickle(d)

Repr and str

>>> d
wormattrdict({'A': 'A',
 'B': 'B',
 'C': 'C',
 'X': 100,
 'Y': 1000,
 'bar': 10,
 'foo': 20,
 'foobar': 40})
>>> d == eval(repr(d))
True

The result of str is highly readable, and a repr if keys are valid Python symbols

>>> str(d)
"wormattrdict(A='A', B='B', C='C', X=100, Y=1000, bar=10, foo=20, foobar=40)"
>>> d == eval(str(d))
True

But note

>>> e = d.copy()
>>> e['not.a.python.symbol!'] = 90
>>> str(e)
"wormattrdict(A='A', B='B', C='C', X=100, Y=1000, bar=10, foo=20, foobar=40, not.a.python.symbol!=90)"
>>> sorted(e)
['A', 'B', 'C', 'X', 'Y', 'bar', 'foo', 'foobar', 'not.a.python.symbol!']
>>> eval(str(e))
Traceback (most recent call last):
  ...
     wormattrdict(A='A', B='B', C='C', X=100, Y=1000, bar=10, foo=20, foobar=40, not.a.python.symbol!=90)
                                                                                    ^
SyntaxError: invalid syntax

Error cases: can’t change or delete existing keys

>>> d.bar = 30
Traceback (most recent call last):
  ...
KeyError: "wormattrdict expected key 'bar' to be unused, but it exists in the set of keys: 'A' 'B' 'C' 'X' 'Y' 'bar' 'foo' 'foobar'"
>>> d['bar'] = 35
Traceback (most recent call last):
  ...
KeyError: "wormattrdict expected key 'bar' to be unused, but it exists in the set of keys: 'A' 'B' 'C' 'X' 'Y' 'bar' 'foo' 'foobar'"
>>> d.update((x, x) for x in 'ABC')
Traceback (most recent call last):
  ...
KeyError: "wormattrdict expected key 'A' to be unused, but it exists in the set of keys: 'A' 'B' 'C' 'X' 'Y' 'bar' 'foo' 'foobar'"
>>> d.setdefault('a', 23)
Traceback (most recent call last):
  ...
TypeError: 'wormattrdict' instance does not support being modified this way
>>> del d['bar']
Traceback (most recent call last):
  ...
TypeError: 'wormattrdict' instance does not support being modified this way
>>> del d.bar
Traceback (most recent call last):
  ...
AttributeError: 'wormattrdict' object does not support modification of its attributes
>>> delattr(d, 'bar')
Traceback (most recent call last):
   ...
AttributeError: 'wormattrdict' object does not support modification of its attributes
>>> d.clear()
Traceback (most recent call last):
  ...
TypeError: 'wormattrdict' instance does not support being modified this way
>>> d.pop()
Traceback (most recent call last):
  ...
TypeError: 'wormattrdict' instance does not support being modified this way
>>> d.pop('bar')
Traceback (most recent call last):
  ...
TypeError: 'wormattrdict' instance does not support being modified this way
>>> d.popitem()
Traceback (most recent call last):
  ...
TypeError: 'wormattrdict' instance does not support being modified this way
>>> d.popitem('bar')
Traceback (most recent call last):
  ...
TypeError: 'wormattrdict' instance does not support being modified this way
clear(*dummy_args)
copy()
static fromkeys()

dict.fromkeys(S[,v]) -> New dict with keys from S and values equal to v. v defaults to None.

get

D.get(k[,d]) -> D[k] if k in D, else d. d defaults to None.

has_key

D.has_key(k) -> True if D has a key k, else False

items

D.items() -> list of D’s (key, value) pairs, as 2-tuples

iteritems

D.iteritems() -> an iterator over the (key, value) items of D

iterkeys

D.iterkeys() -> an iterator over the keys of D

itervalues

D.itervalues() -> an iterator over the values of D

keys

D.keys() -> list of D’s keys

pop(*dummy_args)
popitem(*dummy_args)
setdefault(*dummy_args)
update(args, **kwds)
values

D.values() -> list of D’s values

viewitems

D.viewitems() -> a set-like object providing a view on D’s items

viewkeys

D.viewkeys() -> a set-like object providing a view on D’s keys

viewvalues

D.viewvalues() -> an object providing a view on D’s values