docs: def merge_profile(self, profile, filter_func=None):
      """Copy all namespace items from profile to self.
  
      Namespace items are: 'iterargs', 'derived_iterables', 'aliases',
                           'conditions', 'expected_values'
  
      Don't change any contents of profile ever!
      That means sections are cloned not used directly
  
      filter_func: see description in auto_register
      """
      # 'iterargs', 'derived_iterables', 'aliases', 'conditions', 'expected_values'
      for ns_type in self._valid_namespace_types:
        # this will raise a NamespaceError if an item of profile.{ns_type}
        # is already registered.
        ns_dict = getattr(profile, ns_type)
        if filter_func:
          ns_type_singular = self._valid_namespace_types[ns_type]
          ns_dict = {name:item for name,item in ns_dict.items()
                          if filter_func(ns_type_singular, name, item)}
        self._add_dict_to_namespace(ns_type, ns_dict)
  
      check_filter_func = None if not filter_func else \
                        lambda check: filter_func('check', check.id, check)
      for section in profile.sections:
        my_section = self._sections.get(str(section), None)
        if not len(section.checks):
          continue
        if my_section is None:
          # create a new section: don't change other module/profile contents
          my_section = section.clone(check_filter_func)
          self.add_section(my_section)
        else:
          # order, description are not updated
          my_section.merge_section(section, check_filter_func)