text: #
  # Copyright 2010 Free Software Foundation, Inc.
  #
  # This file was generated by gr_modtool, a tool from the GNU Radio framework
  # This file is a part of gr-azure_software_radio
  #
  # SPDX-License-Identifier: GPL-3.0-or-later
  #
  #
  """
  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(Exception):
          pass
  
      class NoSuchMember(Exception):
          pass
  
      class ParsingError(Exception):
          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 Exception(("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 Exception('No class matched this object.')
              self.add_ref(converted)
              return converted
          except Exception as 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
  