aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndré Erdmann <dywi@mailerd.de>2013-08-23 13:17:13 +0200
committerAndré Erdmann <dywi@mailerd.de>2013-08-23 13:17:13 +0200
commit1bd7938e8f3d9ba59fae9bdae378ec2120c3ca8b (patch)
treee88eafca608ec3b61d45e14e286bf049200074d2 /roverlay/util
parentroverlay/util: dictwalk (diff)
downloadR_overlay-1bd7938e8f3d9ba59fae9bdae378ec2120c3ca8b.tar.gz
R_overlay-1bd7938e8f3d9ba59fae9bdae378ec2120c3ca8b.tar.bz2
R_overlay-1bd7938e8f3d9ba59fae9bdae378ec2120c3ca8b.zip
roverlay/util/namespace:
This is (mostly) a copy of the package rules' namespace object, but aims to be generic. Supports creation of objects with hashable args / kwarg items only, currently.
Diffstat (limited to 'roverlay/util')
-rw-r--r--roverlay/util/namespace.py144
1 files changed, 144 insertions, 0 deletions
diff --git a/roverlay/util/namespace.py b/roverlay/util/namespace.py
new file mode 100644
index 0000000..86d102f
--- /dev/null
+++ b/roverlay/util/namespace.py
@@ -0,0 +1,144 @@
+# R overlay -- generic namespace
+# -*- coding: utf-8 -*-
+# Copyright (C) 2013 André Erdmann <dywi@mailerd.de>
+# Distributed under the terms of the GNU General Public License;
+# either version 2 of the License, or (at your option) any later version.
+
+#import weakref
+
+import roverlay.util.common
+import roverlay.util.objects
+
+DEBUG_GET_OBJECT = False
+
+
+if DEBUG_GET_OBJECT:
+ def debug_get_object ( msg, cls, args, kwargs ):
+ print (
+ "[ObjectNamespace] {:<17} :: {}, {}, {}".format (
+ msg, cls, args, kwargs
+ )
+ )
+ # --- end of debug_get_object (...) ---
+# -- end if
+
+
+class Namespaceable ( object ):
+ @classmethod
+ def from_namespace ( cls, namespace, *args, **kwargs ):
+ return namespace.get_object_v ( cls, args, kwargs )
+ # --- end of from_namespace (...) ---
+
+ def __init__ ( self, *args, **kwargs ):
+ super ( Namespaceable, self ).__init__()
+ # --- end of __init__ (...) ---
+
+# --- end of Namespaceable ---
+
+class AbstractNamespace ( object ):
+
+ def __init__ ( self, *args, **kwargs ):
+ super ( AbstractNamespace, self ).__init__()
+ # --- end of __init__ (...) ---
+
+ @roverlay.util.objects.abstractmethod
+ def zap ( self, zap_object_db=False ):
+ pass
+ # --- end of zap (...) ---
+
+ def get_dict_hash ( self, d ):
+ # note that this doesn't handle "recursive" dicts
+ return roverlay.util.common.get_dict_hash ( d )
+ # --- end of get_dict_hash (...) ---
+
+ @roverlay.util.objects.abstractmethod
+ def get_object_v ( self, cls, args, kwargs ):
+ """Returns the desired object.
+
+ The object will be created if it does not already exist in the
+ object db of this namespace.
+
+ !!! The object has to be "shareable", i.e. it must not be modified
+ after constructing it (unless such a side-effect is intentional).
+
+ arguments:
+ * cls --
+ * *args --
+ * **kwargs --
+ """
+ pass
+ # --- end of get_object_v (...) ---
+
+ def get_object ( self, cls, *args, **kwargs ):
+ """Like get_object_v(), but accepts a variable number of args."""
+ return self.get_object_v ( cls, args, kwargs )
+ # --- end of get_object (...) ---
+
+# --- end of AbstractNamespace ---
+
+
+class NullNamespace ( AbstractNamespace ):
+
+ def zap ( self, *args, **kwargs ):
+ pass
+ # --- end of zap (...) ---
+
+ def get_object_v ( self, cls, args, kwargs ):
+ return cls ( *args, **kwargs )
+ # --- end of get_object_v (...) ---
+
+# --- end of NullNamespace ---
+
+
+class SimpleNamespace ( AbstractNamespace ):
+ """A namespace that caches all created objects."""
+
+ def zap ( self, zap_object_db=False ):
+ if zap_object_db:
+ self._objects.clear()
+ # --- end of zap (...) ---
+
+ def __init__ ( self ):
+ super ( SimpleNamespace, self ).__init__()
+
+ # object db
+ # dict (
+ # class => dict (
+ # tuple(hash(args),hash(kwargs)) => instance
+ # )
+ # )
+ #
+ self._objects = dict()
+ # --- end of __init__ (...) ---
+
+ def get_object_v ( self, cls, args, kwargs ):
+ ident = (
+ hash ( args ) if args else 0,
+ self.get_dict_hash ( kwargs ) if kwargs else 0,
+ )
+
+ objects = self._objects.get ( cls, None )
+
+ if objects is None:
+ if DEBUG_GET_OBJECT:
+ debug_get_object ( "miss/new cls, obj", cls, args, kwargs )
+
+ c = cls ( *args, **kwargs )
+ self._objects [cls] = { ident : c }
+
+ else:
+ c = objects.get ( ident, None )
+
+ if c is None:
+ if DEBUG_GET_OBJECT:
+ debug_get_object ( "miss/new obj", cls, args, kwargs )
+
+ c = cls ( *args, **kwargs )
+ objects [ident] = c
+ elif DEBUG_GET_OBJECT:
+ debug_get_object ( "hit/exist", cls, args, kwargs )
+
+ return c
+ # --- end of get_object_v (...) ---
+
+# --- end of SimpleNamespace ---