[kupfer: 27/31] puid: Use a context manager for proper recursion blocking
- From: Ulrik Sverdrup <usverdrup src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [kupfer: 27/31] puid: Use a context manager for proper recursion blocking
- Date: Thu, 31 Dec 2009 12:56:43 +0000 (UTC)
commit 2e6738701ca27dc66b21eeed2c3f4592a9d50170
Author: Ulrik Sverdrup <ulrik sverdrup gmail com>
Date: Thu Dec 31 00:49:07 2009 +0100
puid: Use a context manager for proper recursion blocking
When seeking objects in the catalog, we must block recursion since we
can't in general re-enter a source we are already visiting. To do this
properly we use a context manager that tracks a "stack" of the places
we are currently visiting.
kupfer/puid.py | 45 +++++++++++++++++++++++++++++++++++++--------
1 files changed, 37 insertions(+), 8 deletions(-)
---
diff --git a/kupfer/puid.py b/kupfer/puid.py
index 9636fa6..d29e6ce 100644
--- a/kupfer/puid.py
+++ b/kupfer/puid.py
@@ -2,6 +2,10 @@
Persistent Globally Unique Indentifiers for KupferObjects.
"""
+from __future__ import with_statement
+
+import contextlib
+
try:
import cPickle as pickle
except ImportError:
@@ -34,22 +38,47 @@ def is_reference(puid):
"Return True if @puid is a reference-type ID"
return not isinstance(puid, SerializedObject)
-def _find_obj_in_catalog(puid, catalog, excluding=None):
+# A Context manager to block recursion when seeking inside a
+# catalog; we have a stack (@_excluding) of the sources we
+# are visiting, and nested context with the _exclusion
+# context manager
+
+_excluding = []
+ contextlib contextmanager
+def _exclusion(src):
+ try:
+ _excluding.append(src)
+ yield
+ finally:
+ _excluding.pop()
+
+def _is_currently_excluding(src):
+ return src is not None and src in _excluding
+
+def _find_obj_in_catalog(puid, catalog):
if puid.startswith(qfurl.QFURL_SCHEME):
qfu = qfurl.qfurl(url=puid)
return qfu.resolve_in_catalog(catalog)
for src in catalog:
- if excluding is not None and src == excluding:
+ if _is_currently_excluding(src):
continue
- for obj in src.get_leaves():
- if repr(obj) == puid:
- return obj
+ with _exclusion(src):
+ for obj in src.get_leaves():
+ if repr(obj) == puid:
+ return obj
return None
def resolve_unique_id(puid, excluding=None):
"""
- Resolve unique id @puid inside @catalog
+ Resolve unique id @puid
+
+ The caller (if a Source) should pass itself as @excluding,
+ so that recursion into itself is avoided.
"""
+ if excluding is not None:
+ with _exclusion(excluding):
+ return resolve_unique_id(puid, None)
+
if puid is None:
return None
if isinstance(puid, SerializedObject):
@@ -59,12 +88,12 @@ def resolve_unique_id(puid, excluding=None):
pretty.print_debug(__name__, type(exc).__name__, exc)
return None
sc = data.GetSourceController()
- obj = _find_obj_in_catalog(puid, sc._pre_root, excluding=excluding)
+ obj = _find_obj_in_catalog(puid, sc._pre_root)
if obj is not None:
pretty.print_debug(__name__, "Resolving %s to %s" % (puid, obj))
return obj
other_sources = set(sc.sources) - set(sc._pre_root)
- obj = _find_obj_in_catalog(puid, other_sources, excluding=excluding)
+ obj = _find_obj_in_catalog(puid, other_sources)
pretty.print_debug(__name__, "Resolving %s to %s" % (puid, obj))
return obj
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]