summaryrefslogtreecommitdiff
path: root/grc/core/base.py
diff options
context:
space:
mode:
Diffstat (limited to 'grc/core/base.py')
-rw-r--r--grc/core/base.py164
1 files changed, 164 insertions, 0 deletions
diff --git a/grc/core/base.py b/grc/core/base.py
new file mode 100644
index 0000000000..e5ff657d85
--- /dev/null
+++ b/grc/core/base.py
@@ -0,0 +1,164 @@
+# Copyright 2008, 2009, 2015, 2016 Free Software Foundation, Inc.
+# This file is part of GNU Radio
+#
+# GNU Radio Companion is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# GNU Radio Companion is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+
+import weakref
+
+from .utils.descriptors import lazy_property
+
+
+class Element(object):
+
+ def __init__(self, parent=None):
+ self._parent = weakref.ref(parent) if parent else lambda: None
+ self._error_messages = []
+
+ ##################################################
+ # Element Validation API
+ ##################################################
+ def validate(self):
+ """
+ Validate this element and call validate on all children.
+ Call this base method before adding error messages in the subclass.
+ """
+ del self._error_messages[:]
+
+ for child in self.children():
+ child.validate()
+
+ def is_valid(self):
+ """
+ Is this element valid?
+
+ Returns:
+ true when the element is enabled and has no error messages or is bypassed
+ """
+ if not self.enabled or self.get_bypassed():
+ return True
+ return not next(self.iter_error_messages(), False)
+
+ def add_error_message(self, msg):
+ """
+ Add an error message to the list of errors.
+
+ Args:
+ msg: the error message string
+ """
+ self._error_messages.append(msg)
+
+ def get_error_messages(self):
+ """
+ Get the list of error messages from this element and all of its children.
+ Do not include the error messages from disabled or bypassed children.
+ Cleverly indent the children error messages for printing purposes.
+
+ Returns:
+ a list of error message strings
+ """
+ return [msg if elem is self else "{}:\n\t{}".format(elem, msg.replace("\n", "\n\t"))
+ for elem, msg in self.iter_error_messages()]
+
+ def iter_error_messages(self):
+ """
+ Iterate over error messages. Yields tuples of (element, message)
+ """
+ for msg in self._error_messages:
+ yield self, msg
+ for child in self.children():
+ if not child.enabled or child.get_bypassed():
+ continue
+ for element_msg in child.iter_error_messages():
+ yield element_msg
+
+ def rewrite(self):
+ """
+ Rewrite this element and call rewrite on all children.
+ Call this base method before rewriting the element.
+ """
+ for child in self.children():
+ child.rewrite()
+
+ @property
+ def enabled(self):
+ return True
+
+ def get_bypassed(self):
+ return False
+
+ ##############################################
+ # Tree-like API
+ ##############################################
+ @property
+ def parent(self):
+ return self._parent()
+
+ def get_parent_by_type(self, cls):
+ parent = self.parent
+ if parent is None:
+ return None
+ elif isinstance(parent, cls):
+ return parent
+ else:
+ return parent.get_parent_by_type(cls)
+
+ @lazy_property
+ def parent_platform(self):
+ from .platform import Platform
+ return self.get_parent_by_type(Platform)
+
+ @lazy_property
+ def parent_flowgraph(self):
+ from .FlowGraph import FlowGraph
+ return self.get_parent_by_type(FlowGraph)
+
+ @lazy_property
+ def parent_block(self):
+ from .blocks import Block
+ return self.get_parent_by_type(Block)
+
+ def reset_parents_by_type(self):
+ """Reset all lazy properties"""
+ for name, obj in vars(Element): # explicitly only in Element, not subclasses
+ if isinstance(obj, lazy_property):
+ delattr(self, name)
+
+ def children(self):
+ return
+ yield # empty generator
+
+ ##############################################
+ # Type testing
+ ##############################################
+ is_flow_graph = False
+ is_block = False
+ is_dummy_block = False
+ is_connection = False
+ is_port = False
+ is_param = False
+ is_variable = False
+ is_import = False
+
+ def get_raw(self, name):
+ descriptor = getattr(self.__class__, name, None)
+ if not descriptor:
+ raise ValueError("No evaluated property '{}' found".format(name))
+ return getattr(self, descriptor.name_raw, None) or getattr(self, descriptor.name, None)
+
+ def set_evaluated(self, name, value):
+ descriptor = getattr(self.__class__, name, None)
+ if not descriptor:
+ raise ValueError("No evaluated property '{}' found".format(name))
+ self.__dict__[descriptor.name] = value