22"""
33Collects common base functionality
44"""
5-
5+ import collections
66import posixpath
77
88from . import terminology
9- from .tools .doc_inherit import inherit_docstring , allow_inherit_docstring
9+ from .tools .doc_inherit import allow_inherit_docstring
1010
1111
1212class _baseobj (object ):
@@ -169,20 +169,20 @@ def append(self, *obj_tuple):
169169@allow_inherit_docstring
170170class sectionable (baseobject ):
171171 def __init__ (self ):
172- from odml .section import Section
173- self ._sections = SmartList (Section )
172+ from odml .section import BaseSection
173+ self ._sections = SmartList (BaseSection )
174174 self ._repository = None
175175
176176 @property
177177 def document (self ):
178178 """
179179 Returns the parent-most node (if its a document instance) or None
180180 """
181+ from odml .doc import BaseDocument
181182 p = self
182183 while p .parent :
183184 p = p .parent
184- import odml .doc as doc
185- if isinstance (p , doc .Document ):
185+ if isinstance (p , BaseDocument ):
186186 return p
187187
188188 @property
@@ -192,29 +192,57 @@ def sections(self):
192192
193193 def insert (self , position , section ):
194194 """
195- Adds the section to the section -list and makes this document the
196- section’s parent .
195+ Insert a Section at the child -list position. A ValueError will be raised,
196+ if a Section with the same name already exists in the child-list .
197197
198- Currently just appends the section and does not insert at the
199- specified *position*
198+ :param position: index at which the object should be inserted.
199+ :param section: odML Section object.
200200 """
201- self ._sections .append (section )
202- section ._parent = self
201+ from odml .section import BaseSection
202+ if isinstance (section , BaseSection ):
203+ if section .name in self ._sections :
204+ raise ValueError ("Section with name '%s' already exists." % section .name )
203205
204- def append (self , * vsection_tuple ):
206+ self ._sections .insert (position , section )
207+ section ._parent = self
208+ else :
209+ raise ValueError ("Can only insert objects of type Section." )
210+
211+ def append (self , section ):
205212 """
206- Adds the section to the section-list and makes this document the
207- section’s parent.
213+ Method appends a single Section to the section child-lists of the current Object.
214+
215+ :param section: odML Section object.
208216 """
209217 from odml .section import BaseSection
210- from odml .doc import BaseDocument
211- for vsection in vsection_tuple :
212- if (not isinstance (vsection , BaseSection )) & \
213- isinstance (self , BaseDocument ):
214- raise KeyError ("Object " + str (vsection ) +
215- " is not a Section." )
216- self ._sections .append (vsection )
217- vsection ._parent = self
218+ if isinstance (section , BaseSection ):
219+ self ._sections .append (section )
220+ section ._parent = self
221+ elif isinstance (section , collections .Iterable ) and not isinstance (section , str ):
222+ raise ValueError ("Use extend to add a list of Sections." )
223+ else :
224+ raise ValueError ("Can only append objects of type Section." )
225+
226+ def extend (self , sec_list ):
227+ """
228+ Method adds Sections to the section child-list of the current object.
229+
230+ :param sec_list: Iterable containing odML Section entries.
231+ """
232+ from odml .section import BaseSection
233+ if not isinstance (sec_list , collections .Iterable ):
234+ raise TypeError ("'%s' object is not iterable" % type (sec_list ).__name__ )
235+
236+ # Make sure only Sections with unique names will be added.
237+ for sec in sec_list :
238+ if not isinstance (sec , BaseSection ):
239+ raise ValueError ("Can only extend objects of type Section." )
240+
241+ elif isinstance (sec , BaseSection ) and sec .name in self ._sections :
242+ raise KeyError ("Section with name '%s' already exists." % sec .name )
243+
244+ for sec in sec_list :
245+ self .append (sec )
218246
219247 def remove (self , section ):
220248 """ Removes the specified child-section """
@@ -254,7 +282,7 @@ def itersections(self, recursive=True, yield_self=False,
254282 if self == self .document and ((max_depth is None ) or (max_depth > 0 )):
255283 for sec in self .sections :
256284 stack .append ((sec , 1 )) # (<section>, <level in a tree>)
257- elif not self = = self .document :
285+ elif self ! = self .document :
258286 stack .append ((self , 0 )) # (<section>, <level in a tree>)
259287
260288 while len (stack ) > 0 :
@@ -319,12 +347,11 @@ def contains(self, obj):
319347 if obj .name == i .name and obj .type == i .type :
320348 return i
321349
322- # FIXME type arguments renamed to dtype?
323- def _matches (self , obj , key = None , type = None , include_subtype = False ):
350+ def _matches (self , obj , key = None , otype = None , include_subtype = False ):
324351 """
325352 Find out
326353 * if the *key* matches obj.name (if key is not None)
327- * or if *type * matches obj.type (if type is not None)
354+ * or if *otype * matches obj.type (if type is not None)
328355 * if type does not match exactly, test for subtype.
329356 (e.g.stimulus/white_noise)
330357 comparisons are case-insensitive, however both key and type
@@ -333,18 +360,16 @@ def _matches(self, obj, key=None, type=None, include_subtype=False):
333360 name_match = (key is None or (
334361 key is not None and hasattr (obj , "name" ) and obj .name == key ))
335362
336- exact_type_match = (type is None or (type is not None and
337- hasattr (obj , "type" ) and
338- obj .type .lower () == type ))
363+ exact_type_match = (otype is None or (otype is not None and
364+ hasattr (obj , "type" ) and
365+ obj .type .lower () == otype ))
339366
340367 if not include_subtype :
341368 return name_match and exact_type_match
342369
343- subtype_match = type is None or (type is not None and
344- hasattr (obj , "type" ) and
345- type in obj .type
346- .lower ().split ('/' )[:- 1 ])
347- # TODO : Break the above line more elegantly
370+ subtype_match = (otype is None or
371+ (otype is not None and hasattr (obj , "type" ) and
372+ otype in obj .type .lower ().split ('/' )[:- 1 ]))
348373
349374 return name_match and (exact_type_match or subtype_match )
350375
@@ -539,10 +564,10 @@ def clone(self, children=True):
539564 Clone this object recursively allowing to copy it independently
540565 to another document
541566 """
542- from odml .section import Section
567+ from odml .section import BaseSection
543568 obj = super (sectionable , self ).clone (children )
544569 obj ._parent = None
545- obj ._sections = SmartList (Section )
570+ obj ._sections = SmartList (BaseSection )
546571 if children :
547572 for s in self ._sections :
548573 obj .append (s .clone ())
0 commit comments