def test_recursive_reprs(self): # https://github.com/PyMVPA/PyMVPA/issues/122 from mvpa2.base.param import Parameter from mvpa2.base.state import ClassWithCollections class C1(ClassWithCollections): f = Parameter(None) class C2(ClassWithCollections): p = Parameter(None) def trouble(self, results): return results # provide non-default value of sl c1 = C1() c2 = C2(p=c1) # bind sl's results_fx to hsl's instance method c2.params.p.params.f = c2.trouble c1id = c2id = mod = '' # kaboom -- this should not crash now if __debug__: if 'ID_IN_REPR' in debug.active: from mvpa2.base.dochelpers import _strid c1id = _strid(c1) c2id = _strid(c2) if 'MODULE_IN_REPR' in debug.active: mod = 'mvpa2.tests.test_dochelpers.' raise SkipTest("TODO: needs similar handling in _saferepr") self.assertEqual( repr(c2), '%(mod)sC2(p=%(mod)sC1(f=<bound %(mod)sC2%(c2id)s.trouble>)%(c1id)s)%(c2id)s' % locals())
def test_recursive_reprs(self): # https://github.com/PyMVPA/PyMVPA/issues/122 from mvpa2.base.param import Parameter from mvpa2.base.state import ClassWithCollections class C1(ClassWithCollections): f = Parameter(None) class C2(ClassWithCollections): p = Parameter(None) def trouble(self, results): return results # provide non-default value of sl c1 = C1() c2 = C2(p=c1) # bind sl's results_fx to hsl's instance method c2.params.p.params.f = c2.trouble # kaboom -- this should not crash now if __debug__ and 'ID_IN_REPR' in debug.active: from mvpa2.base.dochelpers import _strid c1id = _strid(c1) c2id = _strid(c2) else: c1id = c2id = '' self.assertEqual( repr(c2), 'C2(p=C1(f=<bound C2%(c2id)s.trouble>)%(c1id)s)%(c2id)s' % locals())
def copy(self, deep=True, sa=None, fa=None, a=None, memo=None): """Create a copy of a dataset. By default this is going to return a deep copy of the dataset, hence no data would be shared between the original dataset and its copy. Parameters ---------- deep : boolean, optional If False, a shallow copy of the dataset is return instead. The copy contains only views of the samples, sample attributes and feature attributes, as well as shallow copies of all dataset attributes. sa : list or None List of attributes in the sample attributes collection to include in the copy of the dataset. If `None` all attributes are considered. If an empty list is given, all attributes are stripped from the copy. fa : list or None List of attributes in the feature attributes collection to include in the copy of the dataset. If `None` all attributes are considered If an empty list is given, all attributes are stripped from the copy. a : list or None List of attributes in the dataset attributes collection to include in the copy of the dataset. If `None` all attributes are considered If an empty list is given, all attributes are stripped from the copy. memo : dict Developers only: This argument is only useful if copy() is called inside the __deepcopy__() method and refers to the dict-argument `memo` in the Python documentation. """ if __debug__: debug('DS_', "Duplicating samples shaped %s" % str(self.samples.shape)) if deep: samples = copy.deepcopy(self.samples, memo) else: samples = self.samples.view() if __debug__: debug('DS_', "Create new dataset instance for copy") # call the generic init out = self.__class__(samples, sa=self.sa.copy(a=sa, deep=deep, memo=memo), fa=self.fa.copy(a=fa, deep=deep, memo=memo), a=self.a.copy(a=a, deep=deep, memo=memo)) if __debug__: debug( 'DS_', "Return dataset copy %s of source %s" % (_strid(out), _strid(self))) return out
def copy(self, deep=True, sa=None, fa=None, a=None, memo=None): """Create a copy of a dataset. By default this is going to return a deep copy of the dataset, hence no data would be shared between the original dataset and its copy. Parameters ---------- deep : boolean, optional If False, a shallow copy of the dataset is return instead. The copy contains only views of the samples, sample attributes and feature attributes, as well as shallow copies of all dataset attributes. sa : list or None List of attributes in the sample attributes collection to include in the copy of the dataset. If `None` all attributes are considered. If an empty list is given, all attributes are stripped from the copy. fa : list or None List of attributes in the feature attributes collection to include in the copy of the dataset. If `None` all attributes are considered If an empty list is given, all attributes are stripped from the copy. a : list or None List of attributes in the dataset attributes collection to include in the copy of the dataset. If `None` all attributes are considered If an empty list is given, all attributes are stripped from the copy. memo : dict Developers only: This argument is only useful if copy() is called inside the __deepcopy__() method and refers to the dict-argument `memo` in the Python documentation. """ if __debug__: debug('DS_', "Duplicating samples shaped %s" % str(self.samples.shape)) if deep: samples = copy.deepcopy(self.samples, memo) else: samples = self.samples.view() if __debug__: debug('DS_', "Create new dataset instance for copy") # call the generic init out = self.__class__(samples, sa=self.sa.copy(a=sa, deep=deep, memo=memo), fa=self.fa.copy(a=fa, deep=deep, memo=memo), a=self.a.copy(a=a, deep=deep, memo=memo)) if __debug__: debug('DS_', "Return dataset copy %s of source %s" % (_strid(out), _strid(self))) return out
def clone(self): """Create full copy of the classifier. It might require classifier to be untrained first due to present SWIG bindings. TODO: think about proper re-implementation, without enrollment of deepcopy """ if __debug__: debug("CLF", "Cloning %s%s", (self, _strid(self))) try: return deepcopy(self) except: self.untrain() return deepcopy(self)
def __repr__(self, prefixes=None, fullname=False): """String definition of the object of ClassWithCollections object Parameters ---------- prefixes : list of str What other prefixes to prepend to list of arguments fullname : bool Either to include full name of the module """ prefixes = prefixes or [] prefixes = prefixes[:] # copy list # filter using __init__doc__exclude__ for f in getattr(self, '__init__doc__exclude__', []): prefixes = [x for x in prefixes if not x.startswith(f+'=')] id_str = "" module_str = "" if __debug__: if 'MODULE_IN_REPR' in debug.active: fullname = True if 'ID_IN_REPR' in debug.active: id_str = _strid(self) if fullname: modulename = '%s' % self.__class__.__module__ if modulename != "__main__": module_str = "%s." % modulename # Collections' attributes collections = self._collections # we want them in this particular order for col in _COLLECTIONS_ORDER: collection = collections.get(col, None) if collection is None: continue prefixes += collection._cls_repr() # Description if present prefixes += _repr_attrs(self, ['descr']) out = "%s%s(%s)%s" % (module_str, self.__class__.__name__, ', '.join(prefixes), id_str) # To possibly debug mass repr/str-fication # print str(self), ' REPR: ', out return out
def __new__(cls, *args, **kwargs): """Instantiate ClassWithCollections object """ self = super(ClassWithCollections, cls).__new__(cls) s__dict__ = self.__dict__ # init variable # XXX: Added as pylint complained (rightfully) -- not sure if false # is the proper default self.__params_set = False # need to check to avoid override of enabled ca in the case # of multiple inheritance, like both ClassWithCollectionsl and # Harvestable (note: Harvestable was refactored away) if '_collections' not in s__dict__: s__class__ = self.__class__ collections = copy.deepcopy(s__class__._collections_template) s__dict__['_collections'] = collections s__dict__['_known_attribs'] = {} """Dictionary to contain 'links' to the collections from each known attribute. Is used to gain some speed up in lookup within __getattribute__ and __setattr__ """ # Assign owner to all collections for col, collection in collections.iteritems(): if col in s__dict__: raise ValueError, \ "Object %s has already attribute %s" % \ (self, col) s__dict__[col] = collection collection.name = col self.__params_set = False if __debug__: descr = kwargs.get('descr', None) debug( "COL", "ClassWithCollections.__new__ was done " "for %s%s with descr=%s", (s__class__.__name__, _strid(self), descr)) return self
def __new__(cls, *args, **kwargs): """Instantiate ClassWithCollections object """ self = super(ClassWithCollections, cls).__new__(cls) s__dict__ = self.__dict__ # init variable # XXX: Added as pylint complained (rightfully) -- not sure if false # is the proper default self.__params_set = False # need to check to avoid override of enabled ca in the case # of multiple inheritance, like both ClassWithCollectionsl and # Harvestable if '_collections' not in s__dict__: s__class__ = self.__class__ collections = copy.deepcopy(s__class__._collections_template) s__dict__['_collections'] = collections s__dict__['_known_attribs'] = {} """Dictionary to contain 'links' to the collections from each known attribute. Is used to gain some speed up in lookup within __getattribute__ and __setattr__ """ # Assign owner to all collections for col, collection in collections.iteritems(): if col in s__dict__: raise ValueError, \ "Object %s has already attribute %s" % \ (self, col) s__dict__[col] = collection collection.name = col self.__params_set = False if __debug__: descr = kwargs.get('descr', None) debug("COL", "ClassWithCollections.__new__ was done " "for %s%s with descr=%s", (s__class__.__name__, _strid(self), descr)) return self
def __init__(self, descr=None, **kwargs): """Initialize ClassWithCollections object Parameters ---------- descr : str Description of the instance """ # Note: __params_set was initialized in __new__ if not self.__params_set: self.__descr = descr """Set humane description for the object""" # To avoid double initialization in case of multiple inheritance self.__params_set = True collections = self._collections # Assign attributes values if they are given among # **kwargs for arg, argument in kwargs.items(): isset = False for collection in collections.itervalues(): if collection._is_initializable(arg): collection._initialize(arg, argument) isset = True break if isset: _ = kwargs.pop(arg) else: known_params = reduce( lambda x,y:x+y, [x.keys() for x in collections.itervalues() if not isinstance(x, ConditionalAttributesCollection) ], []) _, kwargs_list, _ = get_docstring_split(self.__init__) known_params = sorted(known_params + [x[0] for x in kwargs_list]) raise TypeError( "Unexpected keyword argument %s=%s for %s." % (arg, argument, self) + "\n\tValid parameters are: %s" % ', '.join(known_params)) ## Initialize other base classes ## commented out since it seems to be of no use for now #if init_classes is not None: # # return back stateful arguments since they might be # # processed by underlying classes # kwargs.update(kwargs_stateful) # for cls in init_classes: # cls.__init__(self, **kwargs) #else: # if len(kwargs)>0: # known_params = reduce(lambda x, y: x + y, \ # [x.keys() for x in collections], # []) # raise TypeError, \ # "Unknown parameters %s for %s." % (kwargs.keys(), # self) \ # + " Valid parameters are %s" % known_params if __debug__: debug("COL", "ClassWithCollections.__init__ was done " "for %s%s with descr=%s", (self.__class__.__name__, _strid(self), descr))
def __init__(self, descr=None, **kwargs): """Initialize ClassWithCollections object Parameters ---------- descr : str Description of the instance """ # Note: __params_set was initialized in __new__ if not self.__params_set: self.__descr = descr """Set humane description for the object""" # To avoid double initialization in case of multiple inheritance self.__params_set = True collections = self._collections # Assign attributes values if they are given among # **kwargs for arg, argument in self._custom_kwargs_sort_items(**kwargs): isset = False for collection in collections.itervalues(): if collection._is_initializable(arg): collection._initialize(arg, argument) isset = True break if isset: _ = kwargs.pop(arg) else: known_params = reduce( lambda x,y:x+y, [x.keys() for x in collections.itervalues() if not isinstance(x, ConditionalAttributesCollection) ], []) _, kwargs_list, _ = get_docstring_split(self.__init__) known_params = sorted(known_params + [x[0] for x in kwargs_list]) raise TypeError( "Unexpected keyword argument %s=%s for %s." % (arg, argument, self) + "\n\tValid parameters are: %s" % ', '.join(known_params)) ## Initialize other base classes ## commented out since it seems to be of no use for now #if init_classes is not None: # # return back stateful arguments since they might be # # processed by underlying classes # kwargs.update(kwargs_stateful) # for cls in init_classes: # cls.__init__(self, **kwargs) #else: # if len(kwargs)>0: # known_params = reduce(lambda x, y: x + y, \ # [x.keys() for x in collections], # []) # raise TypeError, \ # "Unknown parameters %s for %s." % (kwargs.keys(), # self) \ # + " Valid parameters are %s" % known_params if __debug__: debug("COL", "ClassWithCollections.__init__ was done " "for %s%s with descr=%s", (self.__class__.__name__, _strid(self), descr))