summaryrefslogtreecommitdiff
path: root/gr-howto-write-a-block/docs/doxygen/doxyxml/base.py
diff options
context:
space:
mode:
Diffstat (limited to 'gr-howto-write-a-block/docs/doxygen/doxyxml/base.py')
-rw-r--r--gr-howto-write-a-block/docs/doxygen/doxyxml/base.py219
1 files changed, 219 insertions, 0 deletions
diff --git a/gr-howto-write-a-block/docs/doxygen/doxyxml/base.py b/gr-howto-write-a-block/docs/doxygen/doxyxml/base.py
new file mode 100644
index 000000000..097e3f15b
--- /dev/null
+++ b/gr-howto-write-a-block/docs/doxygen/doxyxml/base.py
@@ -0,0 +1,219 @@
+#
+# Copyright 2010 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio 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 3, or (at your option)
+# any later version.
+#
+# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+"""
+A base class is created.
+
+Classes based upon this are used to make more user-friendly interfaces
+to the doxygen xml docs than the generated classes provide.
+"""
+
+import os
+import pdb
+
+from xml.parsers.expat import ExpatError
+
+from generated import compound
+
+
+class Base(object):
+
+ class Duplicate(StandardError):
+ pass
+
+ class NoSuchMember(StandardError):
+ pass
+
+ class ParsingError(StandardError):
+ pass
+
+ def __init__(self, parse_data, top=None):
+ self._parsed = False
+ self._error = False
+ self._parse_data = parse_data
+ self._members = []
+ self._dict_members = {}
+ self._in_category = {}
+ self._data = {}
+ if top is not None:
+ self._xml_path = top._xml_path
+ # Set up holder of references
+ else:
+ top = self
+ self._refs = {}
+ self._xml_path = parse_data
+ self.top = top
+
+ @classmethod
+ def from_refid(cls, refid, top=None):
+ """ Instantiate class from a refid rather than parsing object. """
+ # First check to see if its already been instantiated.
+ if top is not None and refid in top._refs:
+ return top._refs[refid]
+ # Otherwise create a new instance and set refid.
+ inst = cls(None, top=top)
+ inst.refid = refid
+ inst.add_ref(inst)
+ return inst
+
+ @classmethod
+ def from_parse_data(cls, parse_data, top=None):
+ refid = getattr(parse_data, 'refid', None)
+ if refid is not None and top is not None and refid in top._refs:
+ return top._refs[refid]
+ inst = cls(parse_data, top=top)
+ if refid is not None:
+ inst.refid = refid
+ inst.add_ref(inst)
+ return inst
+
+ def add_ref(self, obj):
+ if hasattr(obj, 'refid'):
+ self.top._refs[obj.refid] = obj
+
+ mem_classes = []
+
+ def get_cls(self, mem):
+ for cls in self.mem_classes:
+ if cls.can_parse(mem):
+ return cls
+ raise StandardError(("Did not find a class for object '%s'." \
+ % (mem.get_name())))
+
+ def convert_mem(self, mem):
+ try:
+ cls = self.get_cls(mem)
+ converted = cls.from_parse_data(mem, self.top)
+ if converted is None:
+ raise StandardError('No class matched this object.')
+ self.add_ref(converted)
+ return converted
+ except StandardError, e:
+ print e
+
+ @classmethod
+ def includes(cls, inst):
+ return isinstance(inst, cls)
+
+ @classmethod
+ def can_parse(cls, obj):
+ return False
+
+ def _parse(self):
+ self._parsed = True
+
+ def _get_dict_members(self, cat=None):
+ """
+ For given category a dictionary is returned mapping member names to
+ members of that category. For names that are duplicated the name is
+ mapped to None.
+ """
+ self.confirm_no_error()
+ if cat not in self._dict_members:
+ new_dict = {}
+ for mem in self.in_category(cat):
+ if mem.name() not in new_dict:
+ new_dict[mem.name()] = mem
+ else:
+ new_dict[mem.name()] = self.Duplicate
+ self._dict_members[cat] = new_dict
+ return self._dict_members[cat]
+
+ def in_category(self, cat):
+ self.confirm_no_error()
+ if cat is None:
+ return self._members
+ if cat not in self._in_category:
+ self._in_category[cat] = [mem for mem in self._members
+ if cat.includes(mem)]
+ return self._in_category[cat]
+
+ def get_member(self, name, cat=None):
+ self.confirm_no_error()
+ # Check if it's in a namespace or class.
+ bits = name.split('::')
+ first = bits[0]
+ rest = '::'.join(bits[1:])
+ member = self._get_dict_members(cat).get(first, self.NoSuchMember)
+ # Raise any errors that are returned.
+ if member in set([self.NoSuchMember, self.Duplicate]):
+ raise member()
+ if rest:
+ return member.get_member(rest, cat=cat)
+ return member
+
+ def has_member(self, name, cat=None):
+ try:
+ mem = self.get_member(name, cat=cat)
+ return True
+ except self.NoSuchMember:
+ return False
+
+ def data(self):
+ self.confirm_no_error()
+ return self._data
+
+ def members(self):
+ self.confirm_no_error()
+ return self._members
+
+ def process_memberdefs(self):
+ mdtss = []
+ for sec in self._retrieved_data.compounddef.sectiondef:
+ mdtss += sec.memberdef
+ # At the moment we lose all information associated with sections.
+ # Sometimes a memberdef is in several sectiondef.
+ # We make sure we don't get duplicates here.
+ uniques = set([])
+ for mem in mdtss:
+ converted = self.convert_mem(mem)
+ pair = (mem.name, mem.__class__)
+ if pair not in uniques:
+ uniques.add(pair)
+ self._members.append(converted)
+
+ def retrieve_data(self):
+ filename = os.path.join(self._xml_path, self.refid + '.xml')
+ try:
+ self._retrieved_data = compound.parse(filename)
+ except ExpatError:
+ print('Error in xml in file %s' % filename)
+ self._error = True
+ self._retrieved_data = None
+
+ def check_parsed(self):
+ if not self._parsed:
+ self._parse()
+
+ def confirm_no_error(self):
+ self.check_parsed()
+ if self._error:
+ raise self.ParsingError()
+
+ def error(self):
+ self.check_parsed()
+ return self._error
+
+ def name(self):
+ # first see if we can do it without processing.
+ if self._parse_data is not None:
+ return self._parse_data.name
+ self.check_parsed()
+ return self._retrieved_data.compounddef.name