Permalink
Browse files

Updated md.stm in a backwards-incompatible way. Use the 0.2 branch fo…

…r backward-compatibility.
  • Loading branch information...
1 parent fba959b commit b0c91dfabe4a1b58fd5a0a78f055760f6008cf0f Ben Weaver committed Mar 17, 2010
Showing with 349 additions and 466 deletions.
  1. +34 −103 docs/md.stm.rst
  2. +51 −14 md/_prelude.py
  3. +48 −1 md/collections.py
  4. +1 −1 md/stm/__init__.py
  5. +88 −89 md/stm/cursor.py
  6. +25 −40 md/stm/interfaces.py
  7. +69 −193 md/stm/journal.py
  8. +22 −4 md/stm/log.py
  9. +11 −21 md/stm/transaction.py
View
@@ -14,6 +14,7 @@ instance state.
.. doctest::
+ >>> import __builtin__
>>> from md.stm import *
.. doctest::
@@ -105,7 +106,7 @@ Default :class:`Cursor` Implementation
redefining the :attr:`cursor.StateType` attribute.
>>> class sequence(cursor):
- ... StateType = list
+ ... StateType = __builtin__.list
...
... def __init__(self, seq=()):
... self.extend(seq)
@@ -125,29 +126,34 @@ Default :class:`Cursor` Implementation
... def extend(self, seq):
... writable(self).extend(seq)
-.. class:: tdict(dict=None, **kwargs)
+.. class:: dict(dict=None, **kwargs)
A transactional :class:`dict`.
-.. class:: tlist(seq=None)
+.. class:: tree(seq=None, **kwargs)
+
+ A transactional :class:`tree`.
+
+.. class:: omap(seq=None, **kwargs)
+
+ A transactional :class:`omap`.
+
+.. class:: list(seq=None)
A transactional :class:`list`.
-.. class:: tset(seq=None)
+.. class:: set(seq=None)
A transactional :class:`set`.
Transactions
------------
-.. function:: transaction([name], autocommit=True, autosave=True)
+.. function:: transaction([name], autocommit=True)
A transaction provides a context for transactional memory
- operations. Saving changed data writes the changes to a
- transaction's save-log. Committing a transaction writes saved
- changes to the outer transaction's save-log. A top-level
- transaction operates against the transactional memory store.
- Transactions may be nested.
+ operations. Committing a transaction writes changes to the outer
+ transaction or memory. Transactions may be nested.
.. function:: transactionally(proc, *args, **kwargs)
@@ -158,89 +164,25 @@ Transactions
arguments and returns the result of calling :obj:`proc`.
:param __attempts__: The number of attempts to make (default: ``3``)
- :param autosave: Passed to :func:`transaction` (default: ``True``)
:param autocommit: Passed to :func:`transaction` (default: ``True``)
-.. function:: save([what]) -> what
-
- Transactions auto-commit and auto-save by default. Use
- :func:`save` to add changes that will be committed when auto-save
- is disabled or before calling a nested transaction. Unsaved
- changes are discarded when the transaction is completed. Without
- any arguments, all :func:`unsaved` changes are saved. Otherwise,
- ``what`` may be a cursor or sequence of cursors.
-
- .. doctest::
-
- >>> with transaction(autosave=False):
- ... s1 = save(tlist([1, 2, 3]))
- ... c1 = save(cell(s1))
- >>> c1.value
- tlist([1, 2, 3])
-
- >>> with transaction(autosave=False):
- ... c1.value[1] = 20
- >>> c1.value
- tlist([1, 2, 3])
-
- Save must be called on the cursor that's changed. Calling save on
- a cursor referring to a changed cursor won't work.
-
- .. doctest::
-
- >>> with transaction(autosave=False):
- ... c1.value[1] = 20
- ... save(c1.value)
- tlist([1, 20, 3])
- >>> c1.value
- tlist([1, 20, 3])
-
- >>> with transaction(autocommit=False, autosave=False):
- ... c1.value[2] = 30
- ... save(c1)
- <cell tlist([1, 20, 30])>
- >>> c1
- <cell tlist([1, 20, 3])>
+.. function:: rollback([what]) -> what
- Leaving the ``autosave`` argument set to ``True`` is convenient for
- "always commit everything" transactions.
+ Revert a cursor to its original state.
.. doctest::
>>> with transaction():
- ... c2 = cell(tlist(['a', 'b', 'c']))
- >>> c2.value
- tlist(['a', 'b', 'c'])
-
-.. function:: rollback([what]) -> what
-
- Revert a cursor to its last saved state (the opposite of
- :func:`save`). When called with no arguments, all :func:`unsaved`
- cursors are reverted.
+ ... c1 = cell(list(['a', 'b', 'c']))
- .. doctest::
-
- >>> with transaction(autosave=False):
- ... c2.value[0] = 'A'
- ... with transaction(autosave=False):
- ... print c2.value, '(nested)'
- ... c2.value[0] = 'Z'
- ... print c2.value, '(after nested; no save)'
- ... print rollback(c2.value), '(rollback)'
- ... c2.value[0] = 'Z'
- ... print save(c2.value), '(saved)'
- ... with transaction(autosave=False):
- ... print c2.value, '(nested2)'
- ... c2.value[1] = 'Y'
- ... print save(c2.value), '(nested2 save)'
- ... print c2.value, '(after nested2 save)'
- tlist(['a', 'b', 'c']) (nested)
- tlist(['A', 'b', 'c']) (after nested; no save)
- tlist(['a', 'b', 'c']) (rollback)
- tlist(['Z', 'b', 'c']) (saved)
- tlist(['Z', 'b', 'c']) (nested2)
- tlist(['Z', 'Y', 'c']) (nested2 save)
- tlist(['Z', 'Y', 'c']) (after nested2 save)
+ >>> with transaction():
+ ... print c1.value, '(originally)'
+ ... c1.value[0] = 'Z'
+ ... print c1.value, '(modified)'
+ ... print rollback(c1.value), '(rollback)'
+ list(['a', 'b', 'c']) (originally)
+ list(['Z', 'b', 'c']) (modified)
+ list(['a', 'b', 'c']) (rollback)
.. function:: commit()
@@ -262,28 +204,17 @@ Transactions
>>> c3.value
'apple'
-.. function:: saved()
+.. function:: changed()
- Produce an iterator over the items in a transaction's save-log.
-
-.. function:: unsaved()
-
- Produce an iterator over the items that need to be added to a
- transaction's save-log.
+ Produce an iterator over items that have been changed in the
+ current transaction.
.. doctest::
- >>> with transaction(autosave=False):
- ... c1.value[0] = 10
- ... c2.value[1] = 'B'
- ... print list(saved()), list(unsaved())
- ... save()
- ... print list(saved()), list(unsaved())
- [] [tlist([10, 20, 3]), tlist(['Z', 'B', 'c'])]
- [tlist([10, 20, 3]), tlist(['Z', 'B', 'c'])] []
-
- >>> c2.value
- tlist(['Z', 'B', 'c'])
+ >>> with transaction():
+ ... c1.value[1] = 'B'
+ ... print '\\n'.join(repr(c) for c in changed())
+ list(['a', 'B', 'c'])
Persistence
-----------
View
@@ -4,15 +4,16 @@
"""_prelude -- additional builtins for internal use (see prelude.py)"""
from __future__ import absolute_import
-import copy, collections as coll, itertools as it, functools as fn, \
- contextlib as ctx
+import copy, itertools as it, functools as fn, contextlib as ctx
+import collections; from collections import *
-__all__ = (
+__all__ = tuple(collections.__all__) + (
'partial', 'wraps', 'closing',
- 'Iterator', 'Sequence', 'chain', 'ichain', 'islice', 'takewhile',
- 'Mapping', 'MutableMapping', 'keys', 'values', 'items', 'chain_items',
+ 'chain', 'ichain', 'islice', 'imap', 'takewhile',
+ 'keys', 'values', 'items', 'chain_items',
'update', 'updated',
- 'namedtuple', 'deque', 'sentinal', 'Undefined'
+ 'sentinal', 'Sentinal', 'Undefined',
+ 'adapt'
)
@@ -25,9 +26,8 @@
### Sequences
-Iterator = coll.Iterator
-Sequence = coll.Sequence
chain = it.chain
+imap = it.imap
islice = it.islice
takewhile = it.takewhile
@@ -37,9 +37,6 @@ def ichain(seq):
### Mapping
-Mapping = coll.Mapping
-MutableMapping = coll.MutableMapping
-
def keys(obj):
if isinstance(obj, Mapping):
return obj.iterkeys()
@@ -66,9 +63,6 @@ def updated(obj, *args, **kw):
### Types
-namedtuple = coll.namedtuple
-deque = coll.deque
-
class Sentinal(object):
__slots__ = ('nonzero', )
@@ -81,8 +75,51 @@ def __nonzero__(self):
def __repr__(self):
return '%s' % type(self).__name__
+ def __copy__(self):
+ return self
+
+ def __deepcopy__(self, memo):
+ return self
+
def sentinal(name, **kw):
cls = type(name, (Sentinal,), {})
return cls(**kw)
Undefined = sentinal('<undefined>', nonzero=False)
+
+
+### Adaptation
+
+def adapt(obj, cls, default=None):
+ """Adapt (cast) obj to cls.
+
+ This is an implementation of the PEAK adaptation interface:
+ Adaptation <http://www.python.org/dev/peps/pep-0246/>
+ PEAK Protocols <http://peak.telecommunity.com/protocol_ref/module-protocols.html>
+ """
+
+ if obj is None or isinstance(obj, cls):
+ return obj
+
+ try:
+ conform = getattr(obj, '__conform__', None)
+ value = conform and conform(cls)
+ if value is not None:
+ return value
+ except TypeError:
+ pass
+
+ try:
+ adapt = getattr(cls, '__adapt__', None)
+ value = adapt and adapt(obj)
+ if value is not None:
+ return value
+ except TypeError:
+ pass
+
+ if default is not None:
+ return default
+
+ raise ValueError('Cannot adapt %r. %r does not implement %r.' % (
+ obj, type(obj), cls
+ ))
View
@@ -138,7 +138,7 @@ def iteritems(self, *offsets):
def keys(self, *offsets):
if not offsets:
return list(self._index)
- return list(self.keys(*offsets))
+ return list(self.iterkeys(*offsets))
def values(self, *offsets):
return list(self.itervalues(*offsets))
@@ -201,6 +201,53 @@ class MutableOrderedMap(OrderedMap, MutableMapping):
@abc.implements(MutableOrderedMap)
class omap(OrderedDict):
+ ## Extended iterators
+
+ def iterkeys(self, *offsets):
+ """Generate a list of all keys or keys in a certain range.
+ The offset semantics are the same as islice()."""
+
+ if not offsets:
+ return iter(self)
+ elif len(offsets) == 1:
+ start = None; (end,) = offsets
+ else:
+ (start, end) = offsets
+
+ if start is None:
+ ## One argument: assume it is "end". Generate the range
+ ## [leftmost, end)
+ keys = self
+ else:
+ keys = it.dropwhile(lambda k: k != start, keys)
+
+ if end is None:
+ ## Generate the range [start, rightmost]
+ return keys
+ ## Generate the range [start, end)
+ return it.takewhile(lambda k: k != end, keys)
+
+ def itervalues(self, *offsets):
+ if not offsets:
+ return (self[k] for k in self)
+ return (self[k] for k in self.iterkeys(*offsets))
+
+ def iteritems(self, *offsets):
+ if not offsets:
+ return ((k, self[k]) for k in self)
+ return ((k, self[k]) for k in self.iterkeys(*offsets))
+
+ def keys(self, *offsets):
+ if not offsets:
+ return list(self)
+ return list(self.iterkeys(*offsets))
+
+ def values(self, *offsets):
+ return list(self.itervalues(*offsets))
+
+ def items(self, *offsets):
+ return list(self.iteritems(*offsets))
+
## Sequence
def append(self, (key, value)):
View
@@ -2,6 +2,6 @@
from .transaction import *
from .interfaces import *
from .cursor import *
-from .journal import memory
+from .journal import *
initialize()
Oops, something went wrong.

0 comments on commit b0c91df

Please sign in to comment.