Source code for momxml.observationspecificationbase

r'''
A base class for classes that generate (part of) the xml needed to
enter information into MoM.
'''

from lofarobsxml.utilities import indent



[docs]class ObservationSpecificationBase(object): r''' A base class from which to derive instances which can generate specifications for observations and pipelines in formats that MoM, the XML Generator by Alwin de Jong, or users can read. **Parameters** name : string A free form string labelling the instance. parent : ObservationSpecificationBase instance The parent of the curent instance. children : None or a list of ObservationSpecificationBase The children of the current instance. initial_status : string Either 'opened' or 'approved' **Examples** >>> OSB = ObservationSpecificationBase ''' def __init__(self, name, parent = None, children = None, initial_status='opened'): self.name = name self.parent = parent self.children = None if children is not None: for child in children: self.append_child(child) self.initial_status = initial_status if initial_status not in ['opened', 'approved']: raise ValueError('ObservationSpecificationBase(): initial_status(%r) is neither \'opened\' nor \'approved\''% initial_status) def __repr__(self): name = self.__class__.__name__ as_dict = self.__dict__ members = sorted(as_dict.keys()) longest_member = sorted([len(s) for s in members])[-1] member_strings = [mem.ljust(longest_member)+' = '+repr(as_dict[mem]) for mem in members if mem != 'parent'] parent_string = 'parent'.ljust(longest_member) + ' = ' parent_string += self.parent.__class__.__name__ if self.parent: parent_string += '(\''+str(self.parent.name)+'\')' member_strings = [parent_string] + member_strings sep = '\n'+' '*(len(name)+1) indented_member_strings = [('\n'+ ' '*(longest_member+3)).join( member.split('\n')) for member in member_strings] unadjusted = ',\n'.join(indented_member_strings) return name+'('+sep.join(unadjusted.split('\n'))+')'
[docs] def xml_prefix(self, project_name): r''' Generate the XML content that goes before the child list. Should return a string. This is one of the two virtual methods. The other one is ``xml_suffix()``. ''' raise NotImplementedError( '%s.xml_prefix(self, project_name) not implemented' % self.__class__.__name__)
[docs] def xml_suffix(self, project_name): r''' Generate the XML content that goes after the child list. Should return a string. This is one of the two virtual methods. The other one is ``xml_prefix()``. ''' raise NotImplementedError( '%s.xml_suffix(self, project_name) not implemented' % self.__class__.__name__)
[docs] def xml(self, project_name): r''' Actually generate the required XML. This method calls two other methods, which may be overridden: xml_prefix() and xml_suffix(). ''' xml_string = self.xml_prefix(project_name) if self.children: childlist_format = '\n<children>%s\n</children>' child_format = '\n <item index="%d">\n%s\n </item>' children = [child_format % (index, indent(child.xml(project_name), 4)) for index, child in enumerate(self.children)] xml_string += indent(childlist_format % '\n'.join(children), 2) xml_string += self.xml_suffix(project_name) return xml_string
[docs] def label(self): r''' Returns an ascii label that reflects the full path of the current instance in the observation set specification. ''' string = str(self.name) if self.parent: str_format = '%s.%d.%s' string = str_format % (self.parent.label(), self.parent.child_id(self), str(self.name)) forbidden = '\'\";:?,\\<>$@#%^&*!()' string = ''.join([ch for ch in string if ch not in forbidden]) return string.replace(' ', '_')
[docs] def child_id(self, instance): r''' Return the child ID of object ``instance`` if it is in ``self.children`` **Parameters** instance : ObservationSpecificationBase The instance for which one wants the position in the ``self.children`` list. ''' if self.children is None or len(self.children) == 0: raise ValueError( 'ObservationSpecificationBase{%s}.child_id(): %r is not in list' % (self.__class__.__name__, instance)) return [id(child) for child in self.children].index(id(instance))
[docs] def append_child(self, instance): r''' Append a child to ``self.children``. This method also calls set_parent() on the the child, to ensure that the parent is set correctly. **Parameters** instance : ObservationSpecificationBase The object to add to self.children. ''' if self.children is None: self.children = [] instance.set_parent(self) self.children.append(instance)
[docs] def set_parent(self, instance): r''' Set self.parent to ``instance``. **Parameters** instance : ObservationSpecificationBase The instance of the parent node. ''' self.parent = instance return instance
[docs] def tree_depth(self): r''' Return the depth of the current node in the tree. A node without parent is automatically at depth 0. ''' if self.parent is None: return 0 else: return self.parent.tree_depth() + 1