def makedocindex(): """ Return a string with GPI Index. """ import pydoc sections = {} from Ganga.Utility.strings import ItemizedTextParagraph for sec, names in zip(_GPIhelp_sections.keys(), _GPIhelp_sections.values()): itbuf = ItemizedTextParagraph(sec + ":") for name, obj, docstring in names: # if docstring not provided when exporting the object to GPI then use the docstring generated by pydoc if not docstring: docstring = pydoc.splitdoc(pydoc.getdoc(obj))[0] itbuf.addLine(name, docstring) sections[sec] = itbuf.getString() return _GPIhelp % sections
def GPIProxyClassFactory(name, pluginclass): def helptext(f,s): f.__doc__ = s % {'classname':name,'objname':name.lower(),'shortvarname':name[0].lower()} # construct the class on-the-fly using the functions below as methods for the new class def _init(self,*args,**kwds): #if len(args) > 1: # logger.warning('extra arguments in the %s constructor ignored: %s',name,args[1:]) # at the object level _impl is a ganga plugin object self.__dict__['_impl'] = pluginclass() self._impl.__construct__(map(stripProxy,args)) # initialize all properties from keywords of the constructor for k in kwds: if self._impl._schema.hasAttribute(k): setattr(self,k,kwds[k]) else: logger.warning('keyword argument in the %s constructur ignored: %s=%s (not defined in the schema)',name,k,kwds[k]) self._impl._proxyObject = self self._impl._auto__init__() from Ganga.Utility.strings import ItemizedTextParagraph itbuf = ItemizedTextParagraph('Properties:',linesep='') for n,item in pluginclass._schema.allItems(): if not item['hidden']: itbuf.addLine(n,item.describe()) if not pluginclass.__doc__: pluginclass.__doc__ = 'Documentation missing.' pluginclass.__doc__.strip() pluginclass.__doc__ += "\n\n" publicdoc = pluginclass.__doc__ + itbuf.getString() helptext(pluginclass,'This is a Ganga.GPI.%(classname)s implementation class. Refer to Ganga.GPI.%(classname)s.__doc__ for documentation.') helptext(_init, """GPI %(classname)s object constructor: %(classname)s() : create %(objname)s with default settings; %(classname)s(%(shortvarname)s) : make a copy of %(shortvarname)s; %(classname)s(%(shortvarname)s,x=a,...): make a copy of %(shortvarname)s and set property 'x' to a, etc.. """) def _str(self): import StringIO sio = StringIO.StringIO() self._impl.printSummaryTree(0,0,'',out = sio) return sio.getvalue() helptext(_str,"""Return a printable string representing %(classname)s object as a tree of properties.""") def _repr(self): try: return self._impl._repr() except AttributeError: return '<'+repr(self._impl)+' PROXY at '+hex(abs(id(self)))+'>' helptext(_repr,"Return an short representation of %(classname)s object.") def _eq(self,x): result = False if isinstance(x, GPIProxyObject): result = self._impl.__eq__(x._impl) else: result = self._impl.__eq__(x) return result helptext(_eq,"Equality operator (==), compare the %(classname)s properties which are declared as [comparable].") def _ne(self,x): return self._impl.__ne__(x._impl) helptext(_ne,"Non-equality operator (!=).") def _copy(self, unprepare=None): logger.debug('unprepare is %s', str(unprepare)) if unprepare is None: if prepconfig['unprepare_on_copy'] is True: if hasattr(self,'is_prepared') or hasattr(self,'application'): unprepare = True if hasattr(self,'application'): if hasattr(self.application,'is_prepared'): if self.application.is_prepared is not None and self.application.is_prepared \ is not True and os.path.isdir(os.path.join(shared_path,self.application.is_prepared.name)): from Ganga.Core.GangaRepository import getRegistry shareref = GPIProxyObjectFactory(getRegistry("prep").getShareRef()) logger.debug('increasing counter from proxy.py') shareref.increase(self.application.is_prepared.name) logger.debug('Found ShareDir directory: %s' % self.application.is_prepared.name) elif self.application.is_prepared is not None and self.application.is_prepared \ is not True and not os.path.isdir(os.path.join(shared_path,self.application.is_prepared.name)): logger.error('ShareDir directory not found: %s' % self.application.is_prepared.name) logger.error('Unpreparing Job #%s' % self.id) from Ganga.Core.GangaRepository import getRegistry shareref = GPIProxyObjectFactory(getRegistry("prep").getShareRef()) shareref.increase(self.application.is_prepared.name) self.unprepare() if hasattr(self,'is_prepared') and self.is_prepared is not None and self.is_prepared \ is not True and not os.path.isdir(os.path.join(shared_path,self.is_prepared.name)): logger.error('ShareDir directory not found: %s' % self.is_prepared.name) logger.error('Unpreparing %s application' % self._impl._name) self.unprepare() if unprepare is True: c = self._impl.clone() if hasattr(c,'is_prepared') and c._getRegistry() is None: from Ganga.Core.GangaRepository import getRegistry shareref = GPIProxyObjectFactory(getRegistry("prep").getShareRef()) shareref.increase(self.is_prepared.name) c._auto__init__(unprepare=True) else: c = self._impl.clone() c._auto__init__() return GPIProxyObjectFactory(c) helptext(_copy,"Make an identical copy of self.") def _setattr(self,x,v): 'something' ## need to know about the types that require metadata attribute checking ## this allows derived types to get same behaviour for free. from Ganga.GPIDev.Lib.Job.Job import Job from Ganga.GPIDev.Lib.Tasks.Task import Task from Ganga.GPIDev.Lib.Tasks.Transform import Transform metadata_objects=[Job] if x == '_impl': raise AttributeError("Internal implementation object '_impl' cannot be reassigned") if not self._impl._schema.hasAttribute(x): if True in (isType(self,t) for t in metadata_objects) and x in self._impl.metadata.data.keys(): raise GangaAttributeError("Metadata item '%s' cannot be modified" % x) raise GangaAttributeError("'%s' has no attribute '%s'" % (self._impl._name,x)) object.__setattr__(self,x,v) helptext(_setattr,"""Set a property of %(classname)s with consistency and safety checks. Setting a [protected] or a unexisting property raises AttributeError.""") def _getattr(self,name): ## need to know about the types that require metadata attribute checking ## this allows derived types to get same behaviour for free. from Ganga.GPIDev.Lib.Job.Job import Job from Ganga.GPIDev.Lib.Tasks.Task import Task from Ganga.GPIDev.Lib.Tasks.Transform import Transform metadata_objects=[Job] if True in (isType(self,t) for t in metadata_objects): try: return self.metadata[name] except: return object.__getattribute__(self,name) return object.__getattribute__(self,name) # but at the class level _impl is a ganga plugin class d = { '_impl' : pluginclass, '__init__' : _init, '__str__' : _str, '__repr__': _repr, '__eq__': _eq, '__ne__': _ne, 'copy' : _copy, '__doc__' : publicdoc, '__setattr__': _setattr, '__getattr__': _getattr } ## TODO: this makes GangaList inherit from the list ## this is not tested and specifically the TestGangaList/testAllListMethodsExported should be verified ##if name == "GangaList": ## return type(name, (GPIProxyObject,list), d) return type(name, (GPIProxyObject,), d)
def GPIProxyClassFactory(name, pluginclass): # type: (str, type(GangaObject)) -> type(GPIProxyObject) """ Args: name: the name of the proxy class pluginclass: the ``GangaObject`` subclass to wrap Returns: a new type which wraps ``pluginclass`` """ def helptext(f, s): if name == '' or name is None: _name = ' ' else: _name = name f.__doc__ = s % {'classname': _name, 'objname': _name.lower(), 'shortvarname': _name[0].lower()} # construct the class on-the-fly using the functions below as methods for # the new class def _init(self, *args, **kwds): ## Zero-th fully initialize self before moving on GPIProxyObject.__init__(self) ## THE ORDER IN HOW AN OBJECT IS INITIALIZED IS IMPORTANT AND HAS BEEN DOUBLE CHECKED - rcurrie ## If we're only constructing a raw Proxy to wrap an existing object lets wrap that and return proxy_obj_str = '_proxy_impl_obj_to_wrap' if proxy_obj_str in kwds.keys(): instance = kwds[proxy_obj_str] ## Even if we're wrapping something such as here make sure we set all of the proxy related attributes correctly. ## Setting of these attributes shold be done here within this class and should probably be properly be done on proxy construction. aka. here else: ## FIRST INITALIZE A RAW OBJECT INSTANCE CORRESPONDING TO 'pluginclass' ## Object was not passed by construction so need to construct new object for internal use instance = pluginclass() ## Avoid intercepting any of the setter method associated with the implRef as they could trigger loading from disk setattr(self, implRef, instance) instance.__dict__[proxyObject] = self ## Need to avoid any setter methods for GangaObjects ## Would be very nice to remove this entirely as I'm not sure a GangaObject should worry about it's proxy (if any) if proxy_obj_str in kwds.keys(): # wrapping not constructing so can exit after determining that the proxy attributes are setup correctly return ## SECOND WE NEED TO MAKE SURE THAT OBJECT ID IS CORRECT AND THIS DOES THINGS LIKE REGISTER A JOB WITH THE REPO instance._auto__init__() ## All objects with an _auto__init__ method need to have that method called and we set the various node attributes here based upon the schema for key, _val in stripProxy(self)._schema.allItems(): if not _val['protected'] and not _val['hidden'] and isType(_val, ComponentItem) and key not in Node._ref_list: val = stripProxy(getattr(self, key)) if isinstance(val, GangaObject): val._auto__init__() instance.setNodeAttribute(key, stripProxy(val)) else: instance.setNodeAttribute(key, stripProxy(val)) ## THIRD(?) CONSTRUCT THE OBJECT USING THE ARGUMENTS WHICH HAVE BEEN PASSED ## e.g. Job(application=exe, name='myJob', ...) or myJob2 = Job(myJob1) ## THIS IS PRIMARILY FOR THE 2ND EXAMPLE ABOVE ## DOESN'T MAKE SENSE TO KEEP PROXIES HERE AS WE MAY BE PERFORMING A PSEUDO-COPY OP clean_args = [stripProxy(arg) for arg in args] try: stripProxy(self).__construct__(clean_args) except TypeError: stripProxy(self).__construct__([]) ## FOURTH ALLOW FOR APPLICATION AND IS_PREPARED etc TO TRIGGER RELAVENT CODE AND SET THE KEYWORDS FROM THE SCHEMA AGAIN ## THIS IS MAINLY FOR THE FIRST EXAMPLE ABOVE ## THIS CORRECTLY APPLIES A PROXY TO ALL OBJECT ATTRIBUTES OF AN OBJECT CREATED WITHIN THE GPI # initialize all properties from keywords of the constructor for k in kwds: if stripProxy(self)._schema.hasAttribute(k): this_arg = stripProxy(kwds[k]) if hasattr(this_arg, '_auto__init__'): this_arg._auto__init__() ## Copying this from the __set__ method in the Proxy descriptor if k == 'application': ProxyDataDescriptor.__app_set__(self, this_arg) if k == 'is_prepared': ProxyDataDescriptor.__prep_set__(self, this_arg) raw_self = stripProxy(self) if type(this_arg) is str: this_arg = stripProxy(runtimeEvalString(raw_self, k, this_arg)) if hasattr(this_arg, '_auto__init__'): this_arg._auto__init__() if type(this_arg) is str: raw_self.setNodeAttribute(k, this_arg) continue else: item = pluginclass._schema.getItem(k) # unwrap proxy if item.isA(ComponentItem): from .Filters import allComponentFilters cfilter = allComponentFilters[item['category']] stripper = lambda v: stripComponentObject(v, cfilter, item) else: stripper = None if item['sequence']: this_arg = ProxyDataDescriptor.__sequence_set__(stripper, raw_self, this_arg, k) else: if stripper is not None: this_arg = stripper(this_arg) # apply attribute filter to component items if item.isA(ComponentItem): this_arg = ProxyDataDescriptor._stripAttribute(raw_self, this_arg, k) if hasattr(this_arg, '_auto__init__'): this_arg._auto__init__() raw_self.setNodeAttribute(k, this_arg) else: logger.warning('keyword argument in the %s constructur ignored: %s=%s (not defined in the schema)', name, k, kwds[k]) ## end of _init return from Ganga.Utility.strings import ItemizedTextParagraph itbuf = ItemizedTextParagraph('Properties:', linesep='') for n, item in pluginclass._schema.allItems(): if not item['hidden']: itbuf.addLine(n, item.describe()) if not pluginclass.__doc__: pluginclass.__doc__ = 'Documentation missing.' pluginclass.__doc__.strip() pluginclass.__doc__ += "\n\n" publicdoc = pluginclass.__doc__ + itbuf.getString() helptext(_init, """GPI %(classname)s object constructor: %(classname)s() : create %(objname)s with default settings; %(classname)s(%(shortvarname)s) : make a copy of %(shortvarname)s; %(classname)s(%(shortvarname)s,x=a,...): make a copy of %(shortvarname)s and set property 'x' to a, etc.. """) def _str(self, interactive=False): import cStringIO sio = cStringIO.StringIO() stripProxy(self).printSummaryTree(0, 0, '', out=sio, interactive=interactive) returnable = str(sio.getvalue()).rstrip() return returnable helptext(_str, """Return a printable string representing %(classname)s object as a tree of properties.""") def _repr_pretty_(self, p, cycle): if cycle: p.text('proxy object...') return if hasattr(self, implRef): raw_self = stripProxy(self) if hasattr(raw_self, '_repr_pretty_'): raw_self._repr_pretty_(p, cycle) elif hasattr(raw_self, '_display'): p.text(raw_self._display()) else: #try: p.text(self.__str__(interactive=True)) #except: ## p.text(self.__str__()) else: #try: p.text(self.__str__(interactive=True)) #except: # p.text(self.__str__()) helptext(_repr_pretty_, """Return a nice string to be printed in the IPython termial""") def _repr(self): has_proxy = hasattr(self, implRef) if has_proxy: raw_proxy = stripProxy(self) else: raw_proxy = None if has_proxy and hasattr(raw_proxy, '_repr'): return raw_proxy._repr() else: return '<' + repr(stripProxy(self)) + ' PROXY at ' + hex(abs(id(self))) + '>' helptext(_repr, "Return an short representation of %(classname)s object.") def _eq(self, x): result = False if isType(x, GPIProxyObject) or hasattr(x, implRef): result = stripProxy(self).__eq__(stripProxy(x)) else: result = stripProxy(self).__eq__(x) return result helptext(_eq, "Equality operator (==), compare the %(classname)s properties which are declared as [comparable].") def _ne(self, x): result = True if isType(x, GPIProxyObject) or hasattr(x, implRef): result = stripProxy(self).__ne__(stripProxy(x)) else: result = stripProxy(self).__ne__(x) return result helptext(_ne, "Non-equality operator (!=).") def _copy(self, unprepare=None): logger.debug('unprepare is %s', str(unprepare)) if unprepare is None: if prepconfig['unprepare_on_copy'] is True: if hasattr(self, 'is_prepared') or hasattr(self, 'application'): unprepare = True def _getSharedPath(): Config_conf = getConfig('Configuration') return os.path.join(expandfilename(Config_conf['gangadir']), 'shared', Config_conf['user']) if hasattr(self, 'application'): if hasattr(self.application, 'is_prepared'): from Ganga.Utility.files import expandfilename if self.application.is_prepared not in [None, True]: if hasattr(self.application.is_prepared, 'name'): shared_path = _getSharedPath() if os.path.isdir(os.path.join(shared_path, self.application.is_prepared.name)): from Ganga.Core.GangaRepository import getRegistry shareref = GPIProxyObjectFactory(getRegistry("prep").getShareRef()) logger.debug('increasing counter from proxy.py') shareref.increase(self.application.is_prepared.name) logger.debug('Found ShareDir directory: %s' % self.application.is_prepared.name) elif self.application.is_prepared not in [None, True]: shared_path = _getSharedPath() if not os.path.isdir(os.path.join(shared_path, self.application.is_prepared.name)): logger.error('ShareDir directory not found: %s' % self.application.is_prepared.name) logger.error('Unpreparing Job #%s' % self.id) from Ganga.Core.GangaRepository import getRegistry shareref = GPIProxyObjectFactory(getRegistry("prep").getShareRef()) shareref.increase(self.application.is_prepared.name) self.unprepare() if unprepare is True: if hasattr(self, 'is_prepared'): from Ganga.Utility.files import expandfilename if self.is_prepared not in [None, True]: if hasattr(self.is_prepared, 'name'): shared_path = _getSharedPath() if not os.path.isdir(os.path.join(shared_path, self.is_prepared.name)): logger.error('ShareDir directory not found: %s' % self.is_prepared.name) logger.error('Unpreparing %s application' % getName(stripProxy(self))) self.unprepare() c = stripProxy(self).clone() if hasattr(c, 'is_prepared') and c._getRegistry() is None: from Ganga.Core.GangaRepository import getRegistry shareref = GPIProxyObjectFactory(getRegistry("prep").getShareRef()) shareref.increase(self.is_prepared.name) stripProxy(c)._auto__init__(unprepare=True) else: c = stripProxy(self).clone() stripProxy(c)._auto__init__() return addProxy(c) helptext(_copy, "Make an identical copy of self.") def _setattr(self, x, v): 'This is the setter method in the Proxied Objects' #logger.debug("_setattr") # need to know about the types that require metadata attribute checking # this allows derived types to get same behaviour for free. p_Ref = stripProxy(self) if p_Ref is not None: if not isclass(p_Ref): class_type = type(p_Ref) else: class_type = p_Ref else: class_type = p_Ref if x == implRef and not isinstance(v, class_type): raise AttributeError("Internal implementation object '%s' cannot be reassigned" % implRef) elif not stripProxy(self)._schema.hasAttribute(x): from Ganga.GPIDev.Lib.Job.MetadataDict import MetadataDict if hasattr(stripProxy(self), 'metadata') and isType(stripProxy(self).metadata, MetadataDict): if x in stripProxy(self).metadata.data.keys(): raise GangaAttributeError("Metadata item '%s' cannot be modified" % x) if x != implRef: raise GangaAttributeError("Can't assign '%s' as it does NOT appear in the object schema for class '%s'" % (x, getName(self))) new_v = stripProxy(runtimeEvalString(self, x, v)) GPIProxyObject.__setattr__(self, x, stripProxy(new_v)) helptext(_setattr, """Set a property of %(classname)s with consistency and safety checks. Setting a [protected] or a unexisting property raises AttributeError.""") # def _getattr(self, name): # if name == '_impl': return self._impl # if '_attribute_filter__get__' in dir(self._impl): # return self._impl._attribute_filter__get__(name) # return self.name # ## need to know about the types that require metadata attribute checking # ## this allows derived types to get same behaviour for free. # from Ganga.GPIDev.Lib.Job.Job import Job # from Ganga.GPIDev.Lib.Tasks.Task import Task # from Ganga.GPIDev.Lib.Tasks.Transform import Transform # metadata_objects=[Job] # if True in (isType(self,t) for t in metadata_objects): # try: # return self.metadata[name] # except: # return object.__getattribute__(self,name) # return object.__getattribute__(self,name) def _getattribute(self, name): #logger.debug("_getattribute: %s" % str(name)) if name.startswith('__') or name == implRef: return GPIProxyObject.__getattribute__(self, name) else: implInstance = stripProxy(self) if '_attribute_filter__get__' in dir(implInstance) and \ not isType(implInstance, ObjectMetaclass) and \ implInstance._schema.hasItem(name) and \ not implInstance._schema.getItem(name)['hidden']: returnable = addProxy(implInstance._attribute_filter__get__(name)) else: returnable = GPIProxyObject.__getattribute__(self, name) if isType(returnable, GangaObject): return addProxy(returnable) else: return returnable # but at the class level _impl is a ganga plugin class d = {implRef: pluginclass, '__init__': _init, '__str__': _str, '__repr__': _repr, '_repr_pretty_': _repr_pretty_, '__eq__': _eq, '__ne__': _ne, 'copy': _copy, '__doc__': publicdoc, '__setattr__': _setattr, # '__getattr__': _getattr, '__getattribute__': _getattribute, } if not hasattr(pluginclass, '_exportmethods'): pluginclass._exportmethods = [] exported_methods = pluginclass._exportmethods # export public methods of this class and also of all the bases # this class is scanned last to extract the most up-to-date docstring dicts = (b.__dict__ for b in reversed(pluginclass.__mro__)) for dct in dicts: for k in dct: if getattr(dct[k], 'exported', False): exported_methods.append(k) # Add all @export'd methods if k in exported_methods: internal_name = "_export_" + k if internal_name not in dct.keys(): internal_name = k try: method = dct[internal_name] except KeyError as err: logger.debug("ObjectMetaClass Error internal_name: %s,\t d: %s" % (internal_name, d)) logger.debug("ObjectMetaClass Error: %s" % err) raise err if not isinstance(method, types.FunctionType): continue f = ProxyMethodDescriptor(k, internal_name) f.__doc__ = method.__doc__ d[k] = f # export visible properties... do not export hidden properties for attr, item in pluginclass._schema.allItems(): if not item['hidden']: d[attr] = ProxyDataDescriptor(attr) def __getitem(self, arg): if not hasattr(stripProxy(self), '__getitem__'): raise AttributeError('I (%s) do not have a __getitem__ attribute' % str(getName(self))) output = stripProxy(self).__getitem__(args) if isType(output, GangaObject): return addProxy(output) else: return output ## NOT ENABLED YET rcurrie #if hasattr(pluginclass, '__getitem__'): # d['__getitem__'] = __getitem #d['__getitem__'] = __getitem # TODO: this makes GangaList inherit from the list # this is not tested and specifically the TestGangaList/testAllListMethodsExported should be verified # if name == "GangaList": # return type(name, (GPIProxyObject,list), d) return type(name, (GPIProxyObject,), d)
def GPIProxyClassFactory(name, pluginclass): def helptext(f, s): if name == '' or name is None: _name = ' ' else: _name = name f.__doc__ = s % {'classname': _name, 'objname': _name.lower(), 'shortvarname': _name[0].lower()} # construct the class on-the-fly using the functions below as methods for # the new class def _init(self, *args, **kwds): # if len(args) > 1: # logger.warning('extra arguments in the %s constructor ignored: %s',name,args[1:]) # at the object level _impl is a ganga plugin object self.__dict__[proxyRef] = pluginclass() clean_args = [stripProxy(arg) for arg in args] getattr(self, proxyRef).__construct__(tuple(clean_args)) # initialize all properties from keywords of the constructor for k in kwds: if getattr(self, proxyRef)._schema.hasAttribute(k): setattr(self, k, kwds[k]) else: logger.warning('keyword argument in the %s constructur ignored: %s=%s (not defined in the schema)', name, k, kwds[k]) getattr(self, proxyRef)._proxyObject = self getattr(self, proxyRef)._auto__init__() from Ganga.Utility.strings import ItemizedTextParagraph itbuf = ItemizedTextParagraph('Properties:', linesep='') for n, item in pluginclass._schema.allItems(): if not item['hidden']: itbuf.addLine(n, item.describe()) if not pluginclass.__doc__: pluginclass.__doc__ = 'Documentation missing.' pluginclass.__doc__.strip() pluginclass.__doc__ += "\n\n" publicdoc = pluginclass.__doc__ + itbuf.getString() helptext(pluginclass, 'This is a Ganga.GPI.%(classname)s implementation class. Refer to Ganga.GPI.%(classname)s.__doc__ for documentation.') helptext(_init, """GPI %(classname)s object constructor: %(classname)s() : create %(objname)s with default settings; %(classname)s(%(shortvarname)s) : make a copy of %(shortvarname)s; %(classname)s(%(shortvarname)s,x=a,...): make a copy of %(shortvarname)s and set property 'x' to a, etc.. """) def _str(self): import cStringIO sio = cStringIO.StringIO() getattr(self, proxyRef).printSummaryTree(0, 0, '', out=sio) return str(sio.getvalue()).rstrip() helptext(_str, """Return a printable string representing %(classname)s object as a tree of properties.""") def _repr_pretty_(self, p, cycle): if cycle: p.text('proxy object...') return p.text(self._display(True)) helptext(_repr_pretty_, """Return a nice string to be printed in the IPython termial""") def _repr(self): if hasattr(getattr(self, proxyRef), '_repr'): return getattr(self, proxyRef)._repr() else: return '<' + repr(getattr(self, proxyRef)) + ' PROXY at ' + hex(abs(id(self))) + '>' helptext(_repr, "Return an short representation of %(classname)s object.") def _eq(self, x): result = False if isType(x, GPIProxyObject) or hasattr(x, proxyRef): result = getattr(self, proxyRef).__eq__(getattr(x, proxyRef)) else: result = getattr(self, proxyRef).__eq__(x) return result helptext(_eq, "Equality operator (==), compare the %(classname)s properties which are declared as [comparable].") def _ne(self, x): result = True if isType(x, GPIProxyObject) or hasattr(x, proxyRef): result = getattr(self, proxyRef).__ne__(getattr(x, proxyRef)) else: result = getattr(self, proxyRef).__ne__(x) return result helptext(_ne, "Non-equality operator (!=).") def _copy(self, unprepare=None): logger.debug('unprepare is %s', str(unprepare)) if unprepare is None: if prepconfig['unprepare_on_copy'] is True: if hasattr(self, 'is_prepared') or hasattr(self, 'application'): unprepare = True def _getSharedPath(): Config_conf = getConfig('Configuration') return os.path.join(expandfilename(Config_conf['gangadir']), 'shared', Config_conf['user']) if hasattr(self, 'application'): if hasattr(self.application, 'is_prepared'): from Ganga.Utility.files import expandfilename if self.application.is_prepared not in [None, True]: if hasattr(self.application.is_prepared, 'name'): shared_path = _getSharedPath() if os.path.isdir(os.path.join(shared_path, self.application.is_prepared.name)): from Ganga.Core.GangaRepository import getRegistry shareref = GPIProxyObjectFactory(getRegistry("prep").getShareRef()) logger.debug('increasing counter from proxy.py') shareref.increase(self.application.is_prepared.name) logger.debug('Found ShareDir directory: %s' % self.application.is_prepared.name) elif self.application.is_prepared not in [None, True]: shared_path = _getSharedPath() if not os.path.isdir(os.path.join(shared_path, self.application.is_prepared.name)): logger.error('ShareDir directory not found: %s' % self.application.is_prepared.name) logger.error('Unpreparing Job #%s' % self.id) from Ganga.Core.GangaRepository import getRegistry shareref = GPIProxyObjectFactory(getRegistry("prep").getShareRef()) shareref.increase(self.application.is_prepared.name) self.unprepare() if unprepare is True: if hasattr(self, 'is_prepared'): from Ganga.Utility.files import expandfilename if self.is_prepared not in [None, True]: if hasattr(self.is_prepared, 'name'): shared_path = _getSharedPath() if not os.path.isdir(os.path.join(shared_path, self.is_prepared.name)): logger.error('ShareDir directory not found: %s' % self.is_prepared.name) logger.error('Unpreparing %s application' % getattr(self, proxyRef)._name) self.unprepare() c = getattr(self, proxyRef).clone() if hasattr(c, 'is_prepared') and c._getRegistry() is None: from Ganga.Core.GangaRepository import getRegistry shareref = GPIProxyObjectFactory(getRegistry("prep").getShareRef()) shareref.increase(self.is_prepared.name) c._auto__init__(unprepare=True) else: c = getattr(self, proxyRef).clone() c._auto__init__() return GPIProxyObjectFactory(c) helptext(_copy, "Make an identical copy of self.") def _setattr(self, x, v): 'something' # need to know about the types that require metadata attribute checking # this allows derived types to get same behaviour for free. if x == proxyRef: raise AttributeError("Internal implementation object '%s' cannot be reassigned" % proxyRef ) if not getattr(self, proxyRef)._schema.hasAttribute(x): if hasattr(getattr(self, proxyRef), 'metadata') and x in getattr(self, proxyRef).metadata.data.keys(): raise GangaAttributeError("Metadata item '%s' cannot be modified" % x) raise GangaAttributeError("'%s' has no attribute '%s'" % (getattr(self, proxyRef)._name, x)) object.__setattr__(self, x, v) helptext(_setattr, """Set a property of %(classname)s with consistency and safety checks. Setting a [protected] or a unexisting property raises AttributeError.""") # def _getattr(self, name): # print "HERE", type(self), name, type(name) # if name == '_impl': return self._impl # if '_attribute_filter__get__' in dir(self._impl): # return self._impl._attribute_filter__get__(name) # return self.name # ## need to know about the types that require metadata attribute checking # ## this allows derived types to get same behaviour for free. # from Ganga.GPIDev.Lib.Job.Job import Job # from Ganga.GPIDev.Lib.Tasks.Task import Task # from Ganga.GPIDev.Lib.Tasks.Transform import Transform # metadata_objects=[Job] # if True in (isType(self,t) for t in metadata_objects): # try: # return self.metadata[name] # except: # return object.__getattribute__(self,name) # return object.__getattribute__(self,name) def _getattribute(self, name): if name.startswith('__') or name in d.keys(): return object.__getattribute__(self, name) pluginclass = object.__getattribute__(self, proxyRef) if '_attribute_filter__get__' in dir(pluginclass) and \ pluginclass.__class__.__name__ != 'ObjectMetaclass' and \ name in dict(pluginclass._schema.allItems()).keys() and \ not dict(pluginclass._schema.allItems())[name]['hidden']: return addProxy(pluginclass._attribute_filter__get__(name)) else: return object.__getattribute__(self, name) # but at the class level _impl is a ganga plugin class d = {proxyRef: pluginclass, '__init__': _init, '__str__': _str, '__repr__': _repr, '__eq__': _eq, '__ne__': _ne, 'copy': _copy, '__doc__': publicdoc, '__setattr__': _setattr, # '__getattr__': _getattr, '__getattribute__': _getattribute } if hasattr(pluginclass, '_repr_pretty_'): d['_repr_pretty_'] = _repr_pretty_ # TODO: this makes GangaList inherit from the list # this is not tested and specifically the TestGangaList/testAllListMethodsExported should be verified # if name == "GangaList": # return type(name, (GPIProxyObject,list), d) return type(name, (GPIProxyObject,), d)
def GPIProxyClassFactory(name, pluginclass): def helptext(f, s): if name == "" or name is None: _name = " " else: _name = name f.__doc__ = s % {"classname": _name, "objname": _name.lower(), "shortvarname": _name[0].lower()} # construct the class on-the-fly using the functions below as methods for # the new class def _init(self, *args, **kwds): ## THE ORDER IN HOW AN OBJECT IS INITIALIZED IS IMPORTANT AND HAS BEEN DOUBLE CHECKED - rcurrie ## FIRST INITALIZE A RAW OBJECT INSTANCE CORRESPONDING TO 'pluginclass' # logger.debug("Proxy Object _init") global proxyRef, proxyClass # if len(args) > 1: # logger.warning('extra arguments in the %s constructor ignored: %s',name,args[1:]) instance = pluginclass() for this_attrib in [proxyRef, proxyClass]: if hasattr(instance, this_attrib): try: delattr(instance, this_attrib) except AttributeError: pass ## SECOND WE NEED TO MAKE SURE THAT OBJECT ID IS CORRECT AND THIS DOES THINGS LIKE REGISTER A JOB WITH THE REPO # at the object level _impl is a ganga plugin object instance.__dict__[proxyObject] = self assert id(getattr(instance, proxyObject)) == id(self) setattr(self, proxyRef, instance) self.__dict__[proxyObject] = self assert id(getattr(self, proxyObject)) == id(self) raw_obj = getattr(self, proxyRef) setattr(raw_obj, proxyObject, self) raw_obj._auto__init__() from Ganga.GPIDev.Base.Objects import Node for key, _val in getattr(self, proxyClass)._schema.allItems(): if ( not _val["protected"] and not _val["hidden"] and isType(_val, Schema.ComponentItem) and key not in Node._ref_list ): val = getattr(self, key) if isType(val, Node): stripProxy(val)._setParent(raw_obj) setattr(raw_obj, key, addProxy(val)) ## THIRD CONSTRUCT THE OBJECT USING THE ARGUMENTS WHICH HAVE BEEN PASSED ## e.g. Job(application=exe, name='myJob', ...) or myJob2 = Job(myJob1) ## THIS IS PRIMARILY FOR THE 2ND EXAMPLE ABOVE ## DOESN'T MAKE SENSE TO KEEP PROXIES HERE AS WE MAY BE PERFORMING A PSEUDO-COPY OP clean_args = [stripProxy(arg) for arg in args] getattr(self, proxyRef).__construct__(tuple(clean_args)) ## FOURTH ALLOW FOR APPLICATION AND IS_PREPARED etc TO TRIGGER RELAVENT CODE AND SET THE KEYWORDS FROM THE SCHEMA AGAIN ## THIS IS MAINLY FOR THE FIRST EXAMPLE ABOVE ## THIS CORRECTLY APPLIES A PROXY TO ALL OBJECT ATTRIBUTES OF AN OBJECT CREATED WITHIN THE GPI # initialize all properties from keywords of the constructor for k in kwds: if getattr(self, proxyClass)._schema.hasAttribute(k): this_arg = kwds[k] ## Copying this from the __set__ method in the Proxy descriptor if this_arg == "application": ProxyDataDescriptor.__app_set__(self, this_arg) if this_arg == "is_prepared": ProxyDataDescriptor.__prep_set__(self, this_arg) raw_self = getattr(self, proxyRef) if type(this_arg) is str: this_arg = runtimeEvalString(raw_self, k, this_arg) if type(this_arg) is str: setattr(raw_self, k, this_arg) continue else: item = pluginclass._schema.getItem(k) # unwrap proxy if item.isA(Schema.ComponentItem): from .Filters import allComponentFilters cfilter = allComponentFilters[item["category"]] stripper = lambda v: stripComponentObject(v, cfilter, item) else: stripper = None if item["sequence"]: this_arg = ProxyDataDescriptor.__sequence_set__(stripper, raw_self, this_arg, k) else: if stripper is not None: this_arg = stripper(this_arg) # apply attribute filter to component items if item.isA(Schema.ComponentItem): this_arg = ProxyDataDescriptor._stripAttribute(raw_self, this_arg, k) if isType(this_arg, Node): setattr(this_arg, proxyObject, None) stripProxy(this_arg)._setParent(raw_self) setattr(raw_self, k, addProxy(this_arg)) else: logger.warning( "keyword argument in the %s constructur ignored: %s=%s (not defined in the schema)", name, k, kwds[k], ) raw_obj = getattr(self, proxyRef) from Ganga.Utility.strings import ItemizedTextParagraph itbuf = ItemizedTextParagraph("Properties:", linesep="") for n, item in pluginclass._schema.allItems(): if not item["hidden"]: itbuf.addLine(n, item.describe()) if not pluginclass.__doc__: pluginclass.__doc__ = "Documentation missing." pluginclass.__doc__.strip() pluginclass.__doc__ += "\n\n" publicdoc = pluginclass.__doc__ + itbuf.getString() helptext( pluginclass, "This is a Ganga.GPI.%(classname)s implementation class. Refer to Ganga.GPI.%(classname)s.__doc__ for documentation.", ) helptext( _init, """GPI %(classname)s object constructor: %(classname)s() : create %(objname)s with default settings; %(classname)s(%(shortvarname)s) : make a copy of %(shortvarname)s; %(classname)s(%(shortvarname)s,x=a,...): make a copy of %(shortvarname)s and set property 'x' to a, etc.. """, ) def _str(self): global proxyRef import cStringIO sio = cStringIO.StringIO() getattr(self, proxyRef).printSummaryTree(0, 0, "", out=sio) return str(sio.getvalue()).rstrip() helptext(_str, """Return a printable string representing %(classname)s object as a tree of properties.""") def _repr_pretty_(self, p, cycle): if cycle: p.text("proxy object...") return global proxyRef if hasattr(self, proxyRef): raw_self = getattr(self, proxyRef) if hasattr(raw_self, "_repr_pretty_"): raw_self._repr_pretty_(p, cycle) elif hasattr(raw_self, "_display"): p.text(raw_self._display()) else: p.text(self.__str__()) else: p.text(self.__str__()) helptext(_repr_pretty_, """Return a nice string to be printed in the IPython termial""") def _repr(self): global proxyRef has_proxy = hasattr(self, proxyRef) if has_proxy: raw_proxy = getattr(self, proxyRef) else: raw_proxy = None if has_proxy and hasattr(raw_proxy, "_repr"): return raw_proxy._repr() else: return "<" + repr(getattr(self, proxyRef)) + " PROXY at " + hex(abs(id(self))) + ">" helptext(_repr, "Return an short representation of %(classname)s object.") def _eq(self, x): global proxyRef result = False if isType(x, GPIProxyObject) or hasattr(x, proxyRef): result = getattr(self, proxyRef).__eq__(getattr(x, proxyRef)) else: result = getattr(self, proxyRef).__eq__(x) return result helptext(_eq, "Equality operator (==), compare the %(classname)s properties which are declared as [comparable].") def _ne(self, x): global proxyRef result = True if isType(x, GPIProxyObject) or hasattr(x, proxyRef): result = getattr(self, proxyRef).__ne__(getattr(x, proxyRef)) else: result = getattr(self, proxyRef).__ne__(x) return result helptext(_ne, "Non-equality operator (!=).") def _copy(self, unprepare=None): global proxyRef logger.debug("unprepare is %s", str(unprepare)) if unprepare is None: if prepconfig["unprepare_on_copy"] is True: if hasattr(self, "is_prepared") or hasattr(self, "application"): unprepare = True def _getSharedPath(): Config_conf = getConfig("Configuration") return os.path.join(expandfilename(Config_conf["gangadir"]), "shared", Config_conf["user"]) if hasattr(self, "application"): if hasattr(self.application, "is_prepared"): from Ganga.Utility.files import expandfilename if self.application.is_prepared not in [None, True]: if hasattr(self.application.is_prepared, "name"): shared_path = _getSharedPath() if os.path.isdir(os.path.join(shared_path, self.application.is_prepared.name)): from Ganga.Core.GangaRepository import getRegistry shareref = GPIProxyObjectFactory(getRegistry("prep").getShareRef()) logger.debug("increasing counter from proxy.py") shareref.increase(self.application.is_prepared.name) logger.debug("Found ShareDir directory: %s" % self.application.is_prepared.name) elif self.application.is_prepared not in [None, True]: shared_path = _getSharedPath() if not os.path.isdir(os.path.join(shared_path, self.application.is_prepared.name)): logger.error("ShareDir directory not found: %s" % self.application.is_prepared.name) logger.error("Unpreparing Job #%s" % self.id) from Ganga.Core.GangaRepository import getRegistry shareref = GPIProxyObjectFactory(getRegistry("prep").getShareRef()) shareref.increase(self.application.is_prepared.name) self.unprepare() if unprepare is True: if hasattr(self, "is_prepared"): from Ganga.Utility.files import expandfilename if self.is_prepared not in [None, True]: if hasattr(self.is_prepared, "name"): shared_path = _getSharedPath() if not os.path.isdir(os.path.join(shared_path, self.is_prepared.name)): logger.error("ShareDir directory not found: %s" % self.is_prepared.name) logger.error("Unpreparing %s application" % getName(getattr(self, proxyRef))) self.unprepare() c = getattr(self, proxyRef).clone() if hasattr(c, "is_prepared") and c._getRegistry() is None: from Ganga.Core.GangaRepository import getRegistry shareref = GPIProxyObjectFactory(getRegistry("prep").getShareRef()) shareref.increase(self.is_prepared.name) c._auto__init__(unprepare=True) else: c = getattr(self, proxyRef).clone() c._auto__init__() return GPIProxyObjectFactory(c) helptext(_copy, "Make an identical copy of self.") def _setattr(self, x, v): "something" # logger.debug("_setattr") global proxyRef # need to know about the types that require metadata attribute checking # this allows derived types to get same behaviour for free. if x == proxyRef and not isinstance(v, getattr(self, proxyRef)): raise AttributeError("Internal implementation object '%s' cannot be reassigned" % proxyRef) if not getattr(self, proxyClass)._schema.hasAttribute(x): from Ganga.GPIDev.Lib.Job.MetadataDict import MetadataDict if hasattr(getattr(self, proxyClass), "metadata") and isType( getattr(self, proxyClass).metadata, MetadataDict ): if x in getattr(self, proxyClass).metadata.data.keys(): raise GangaAttributeError("Metadata item '%s' cannot be modified" % x) if x not in [proxyRef, proxyObject]: raise GangaAttributeError("'%s' has no attribute '%s'" % (getName(getattr(self, proxyClass)), x)) new_v = runtimeEvalString(self, x, v) object.__setattr__(self, x, new_v) # new_obj = getattr(self, x) # if hasattr(new_obj, '_setParent'): # new_obj._setParent(self) helptext( _setattr, """Set a property of %(classname)s with consistency and safety checks. Setting a [protected] or a unexisting property raises AttributeError.""", ) # def _getattr(self, name): # if name == '_impl': return self._impl # if '_attribute_filter__get__' in dir(self._impl): # return self._impl._attribute_filter__get__(name) # return self.name # ## need to know about the types that require metadata attribute checking # ## this allows derived types to get same behaviour for free. # from Ganga.GPIDev.Lib.Job.Job import Job # from Ganga.GPIDev.Lib.Tasks.Task import Task # from Ganga.GPIDev.Lib.Tasks.Transform import Transform # metadata_objects=[Job] # if True in (isType(self,t) for t in metadata_objects): # try: # return self.metadata[name] # except: # return object.__getattribute__(self,name) # return object.__getattribute__(self,name) def _getattribute(self, name): # logger.debug("_getattribute: %s" % str(name)) global proxyRef if name.startswith("__") or name in d.keys(): return object.__getattribute__(self, name) proxyInstance = object.__getattribute__(self, proxyRef) if ( "_attribute_filter__get__" in dir(proxyInstance) and proxyInstance.__class__.__name__ != "ObjectMetaclass" and proxyInstance._schema.hasItem(name) and not proxyInstance._schema.getItem(name)["hidden"] ): return addProxy(proxyInstance._attribute_filter__get__(name)) else: return object.__getattribute__(self, name) # but at the class level _impl is a ganga plugin class d = { proxyRef: pluginclass, "__init__": _init, "__str__": _str, "__repr__": _repr, "_repr_pretty_": _repr_pretty_, "__eq__": _eq, "__ne__": _ne, "copy": _copy, "__doc__": publicdoc, "__setattr__": _setattr, # '__getattr__': _getattr, "__getattribute__": _getattribute, proxyClass: pluginclass, proxyObject: None, } # TODO: this makes GangaList inherit from the list # this is not tested and specifically the TestGangaList/testAllListMethodsExported should be verified # if name == "GangaList": # return type(name, (GPIProxyObject,list), d) return type(name, (GPIProxyObject,), d)
def GPIProxyClassFactory(name, pluginclass): # type: (str, type(GangaObject)) -> type(GPIProxyObject) """ Args: name: the name of the proxy class pluginclass: the ``GangaObject`` subclass to wrap Returns: a new type which wraps ``pluginclass`` """ def helptext(f, s): if name == '' or name is None: _name = ' ' else: _name = name f.__doc__ = s % { 'classname': _name, 'objname': _name.lower(), 'shortvarname': _name[0].lower() } # construct the class on-the-fly using the functions below as methods for # the new class def _init(self, *args, **kwds): ## Zero-th fully initialize self before moving on GPIProxyObject.__init__(self) ## THE ORDER IN HOW AN OBJECT IS INITIALIZED IS IMPORTANT AND HAS BEEN DOUBLE CHECKED - rcurrie ## If we're only constructing a raw Proxy to wrap an existing object lets wrap that and return proxy_obj_str = '_proxy_impl_obj_to_wrap' if proxy_obj_str in kwds.keys(): instance = kwds[proxy_obj_str] ## Even if we're wrapping something such as here make sure we set all of the proxy related attributes correctly. ## Setting of these attributes shold be done here within this class and should probably be properly be done on proxy construction. aka. here else: ## FIRST INITALIZE A RAW OBJECT INSTANCE CORRESPONDING TO 'pluginclass' ## Object was not passed by construction so need to construct new object for internal use instance = pluginclass() ## Avoid intercepting any of the setter method associated with the implRef as they could trigger loading from disk setattr(self, implRef, instance) ## Need to avoid any setter methods for GangaObjects ## Would be very nice to remove this entirely as I'm not sure a GangaObject should worry about it's proxy (if any) instance.__dict__[proxyObject] = self ## THIS SHOLD BE DONE HERE BUT IS DONE IN GANAGOBJECT, PLEASE ADDRESS #instance.__dict__[proxyClass] = type(name, (GPIProxyObject,), d) if proxy_obj_str in kwds.keys(): # wrapping not constructing so can exit after determining that the proxy attributes are setup correctly return ## SECOND WE NEED TO MAKE SURE THAT OBJECT ID IS CORRECT AND THIS DOES THINGS LIKE REGISTER A JOB WITH THE REPO instance._auto__init__() ## All objects with an _auto__init__ method need to have that method called and we set the various node attributes here based upon the schema from Ganga.GPIDev.Base.Objects import GangaObject, Node for key, _val in stripProxy(self)._schema.allItems(): if not _val['protected'] and not _val['hidden'] and isType( _val, ComponentItem) and key not in Node._ref_list: val = stripProxy(getattr(self, key)) if isinstance(val, GangaObject): val._auto__init__() instance.setNodeAttribute(key, stripProxy(val)) else: instance.setNodeAttribute(key, stripProxy(val)) ## THIRD(?) CONSTRUCT THE OBJECT USING THE ARGUMENTS WHICH HAVE BEEN PASSED ## e.g. Job(application=exe, name='myJob', ...) or myJob2 = Job(myJob1) ## THIS IS PRIMARILY FOR THE 2ND EXAMPLE ABOVE ## DOESN'T MAKE SENSE TO KEEP PROXIES HERE AS WE MAY BE PERFORMING A PSEUDO-COPY OP clean_args = [stripProxy(arg) for arg in args] try: stripProxy(self).__construct__(clean_args) except TypeError: stripProxy(self).__construct__([]) ## FOURTH ALLOW FOR APPLICATION AND IS_PREPARED etc TO TRIGGER RELAVENT CODE AND SET THE KEYWORDS FROM THE SCHEMA AGAIN ## THIS IS MAINLY FOR THE FIRST EXAMPLE ABOVE ## THIS CORRECTLY APPLIES A PROXY TO ALL OBJECT ATTRIBUTES OF AN OBJECT CREATED WITHIN THE GPI # initialize all properties from keywords of the constructor for k in kwds: if stripProxy(self)._schema.hasAttribute(k): this_arg = stripProxy(kwds[k]) if hasattr(this_arg, '_auto__init__'): this_arg._auto__init__() ## Copying this from the __set__ method in the Proxy descriptor if k == 'application': ProxyDataDescriptor.__app_set__(self, this_arg) if k == 'is_prepared': ProxyDataDescriptor.__prep_set__(self, this_arg) raw_self = stripProxy(self) if type(this_arg) is str: this_arg = stripProxy( runtimeEvalString(raw_self, k, this_arg)) if hasattr(this_arg, '_auto__init__'): this_arg._auto__init__() if type(this_arg) is str: raw_self.setNodeAttribute(k, this_arg) continue else: item = pluginclass._schema.getItem(k) # unwrap proxy if item.isA(ComponentItem): from .Filters import allComponentFilters cfilter = allComponentFilters[item['category']] stripper = lambda v: stripComponentObject( v, cfilter, item) else: stripper = None if item['sequence']: this_arg = ProxyDataDescriptor.__sequence_set__( stripper, raw_self, this_arg, k) else: if stripper is not None: this_arg = stripper(this_arg) # apply attribute filter to component items if item.isA(ComponentItem): this_arg = ProxyDataDescriptor._stripAttribute( raw_self, this_arg, k) if hasattr(this_arg, '_auto__init__'): this_arg._auto__init__() raw_self.setNodeAttribute(k, this_arg) else: logger.warning( 'keyword argument in the %s constructur ignored: %s=%s (not defined in the schema)', name, k, kwds[k]) ## end of _init return from Ganga.Utility.strings import ItemizedTextParagraph itbuf = ItemizedTextParagraph('Properties:', linesep='') for n, item in pluginclass._schema.allItems(): if not item['hidden']: itbuf.addLine(n, item.describe()) if not pluginclass.__doc__: pluginclass.__doc__ = 'Documentation missing.' pluginclass.__doc__.strip() pluginclass.__doc__ += "\n\n" publicdoc = pluginclass.__doc__ + itbuf.getString() helptext( _init, """GPI %(classname)s object constructor: %(classname)s() : create %(objname)s with default settings; %(classname)s(%(shortvarname)s) : make a copy of %(shortvarname)s; %(classname)s(%(shortvarname)s,x=a,...): make a copy of %(shortvarname)s and set property 'x' to a, etc.. """) def _str(self, interactive=False): import cStringIO sio = cStringIO.StringIO() stripProxy(self).printSummaryTree(0, 0, '', out=sio, interactive=interactive) returnable = str(sio.getvalue()).rstrip() return returnable helptext( _str, """Return a printable string representing %(classname)s object as a tree of properties.""" ) def _repr_pretty_(self, p, cycle): if cycle: p.text('proxy object...') return if hasattr(self, implRef): raw_self = stripProxy(self) if hasattr(raw_self, '_repr_pretty_'): raw_self._repr_pretty_(p, cycle) elif hasattr(raw_self, '_display'): p.text(raw_self._display()) else: #try: p.text(self.__str__(interactive=True)) #except: ## p.text(self.__str__()) else: #try: p.text(self.__str__(interactive=True)) #except: # p.text(self.__str__()) helptext(_repr_pretty_, """Return a nice string to be printed in the IPython termial""") def _repr(self): has_proxy = hasattr(self, implRef) if has_proxy: raw_proxy = stripProxy(self) else: raw_proxy = None if has_proxy and hasattr(raw_proxy, '_repr'): return raw_proxy._repr() else: return '<' + repr(stripProxy(self)) + ' PROXY at ' + hex( abs(id(self))) + '>' helptext(_repr, "Return an short representation of %(classname)s object.") def _eq(self, x): result = False if isType(x, GPIProxyObject) or hasattr(x, implRef): result = stripProxy(self).__eq__(stripProxy(x)) else: result = stripProxy(self).__eq__(x) return result helptext( _eq, "Equality operator (==), compare the %(classname)s properties which are declared as [comparable]." ) def _ne(self, x): result = True if isType(x, GPIProxyObject) or hasattr(x, implRef): result = stripProxy(self).__ne__(stripProxy(x)) else: result = stripProxy(self).__ne__(x) return result helptext(_ne, "Non-equality operator (!=).") def _copy(self, unprepare=None): logger.debug('unprepare is %s', str(unprepare)) if unprepare is None: if prepconfig['unprepare_on_copy'] is True: if hasattr(self, 'is_prepared') or hasattr( self, 'application'): unprepare = True def _getSharedPath(): Config_conf = getConfig('Configuration') return os.path.join(expandfilename(Config_conf['gangadir']), 'shared', Config_conf['user']) if hasattr(self, 'application'): if hasattr(self.application, 'is_prepared'): from Ganga.Utility.files import expandfilename if self.application.is_prepared not in [None, True]: if hasattr(self.application.is_prepared, 'name'): shared_path = _getSharedPath() if os.path.isdir( os.path.join( shared_path, self.application.is_prepared.name)): from Ganga.Core.GangaRepository import getRegistry shareref = GPIProxyObjectFactory( getRegistry("prep").getShareRef()) logger.debug('increasing counter from proxy.py') shareref.increase( self.application.is_prepared.name) logger.debug('Found ShareDir directory: %s' % self.application.is_prepared.name) elif self.application.is_prepared not in [None, True]: shared_path = _getSharedPath() if not os.path.isdir( os.path.join(shared_path, self.application.is_prepared.name)): logger.error('ShareDir directory not found: %s' % self.application.is_prepared.name) logger.error('Unpreparing Job #%s' % self.id) from Ganga.Core.GangaRepository import getRegistry shareref = GPIProxyObjectFactory( getRegistry("prep").getShareRef()) shareref.increase(self.application.is_prepared.name) self.unprepare() if unprepare is True: if hasattr(self, 'is_prepared'): from Ganga.Utility.files import expandfilename if self.is_prepared not in [None, True]: if hasattr(self.is_prepared, 'name'): shared_path = _getSharedPath() if not os.path.isdir( os.path.join(shared_path, self.is_prepared.name)): logger.error('ShareDir directory not found: %s' % self.is_prepared.name) logger.error('Unpreparing %s application' % getName(stripProxy(self))) self.unprepare() c = stripProxy(self).clone() if hasattr(c, 'is_prepared') and c._getRegistry() is None: from Ganga.Core.GangaRepository import getRegistry shareref = GPIProxyObjectFactory( getRegistry("prep").getShareRef()) shareref.increase(self.is_prepared.name) stripProxy(c)._auto__init__(unprepare=True) else: c = stripProxy(self).clone() stripProxy(c)._auto__init__() return GPIProxyObjectFactory(c) helptext(_copy, "Make an identical copy of self.") def _setattr(self, x, v): 'something' #logger.debug("_setattr") # need to know about the types that require metadata attribute checking # this allows derived types to get same behaviour for free. p_Ref = stripProxy(self) if p_Ref is not None: if not isclass(p_Ref): class_type = type(p_Ref) else: class_type = p_Ref else: class_type = p_Ref if x == implRef and not isinstance(v, class_type): raise AttributeError( "Internal implementation object '%s' cannot be reassigned" % implRef) if not stripProxy(self)._schema.hasAttribute(x): from Ganga.GPIDev.Lib.Job.MetadataDict import MetadataDict if hasattr(stripProxy(self), 'metadata') and isType( stripProxy(self).metadata, MetadataDict): if x in stripProxy(self).metadata.data.keys(): raise GangaAttributeError( "Metadata item '%s' cannot be modified" % x) if x not in [implRef, proxyObject, proxyClass]: raise GangaAttributeError("'%s' has no attribute '%s'" % (getName(stripProxy(self)), x)) new_v = stripProxy(runtimeEvalString(self, x, v)) GPIProxyObject.__setattr__(self, x, stripProxy(new_v)) helptext( _setattr, """Set a property of %(classname)s with consistency and safety checks. Setting a [protected] or a unexisting property raises AttributeError.""") # def _getattr(self, name): # if name == '_impl': return self._impl # if '_attribute_filter__get__' in dir(self._impl): # return self._impl._attribute_filter__get__(name) # return self.name # ## need to know about the types that require metadata attribute checking # ## this allows derived types to get same behaviour for free. # from Ganga.GPIDev.Lib.Job.Job import Job # from Ganga.GPIDev.Lib.Tasks.Task import Task # from Ganga.GPIDev.Lib.Tasks.Transform import Transform # metadata_objects=[Job] # if True in (isType(self,t) for t in metadata_objects): # try: # return self.metadata[name] # except: # return object.__getattribute__(self,name) # return object.__getattribute__(self,name) def _getattribute(self, name): #logger.debug("_getattribute: %s" % str(name)) GangaObject = _getGangaObject() if name.startswith('__') or name == implRef: return GPIProxyObject.__getattribute__(self, name) else: implInstance = stripProxy(self) obj_meta = _getMetaClass() if '_attribute_filter__get__' in dir(implInstance) and \ not isType(implInstance, obj_meta) and \ implInstance._schema.hasItem(name) and \ not implInstance._schema.getItem(name)['hidden']: returnable = addProxy( implInstance._attribute_filter__get__(name)) else: returnable = GPIProxyObject.__getattribute__(self, name) if isType(returnable, GangaObject): return addProxy(returnable) else: return returnable # but at the class level _impl is a ganga plugin class d = { implRef: pluginclass, '__init__': _init, '__str__': _str, '__repr__': _repr, '_repr_pretty_': _repr_pretty_, '__eq__': _eq, '__ne__': _ne, 'copy': _copy, '__doc__': publicdoc, '__setattr__': _setattr, # '__getattr__': _getattr, '__getattribute__': _getattribute, } if not hasattr(pluginclass, '_exportmethods'): pluginclass._exportmethods = [] exported_methods = pluginclass._exportmethods # export public methods of this class and also of all the bases # this class is scanned last to extract the most up-to-date docstring dicts = (b.__dict__ for b in reversed(pluginclass.__mro__)) for dct in dicts: for k in dct: if getattr(dct[k], 'exported', False): exported_methods.append(k) # Add all @export'd methods if k in exported_methods: internal_name = "_export_" + k if internal_name not in dct.keys(): internal_name = k try: method = dct[internal_name] except KeyError as err: logger.debug( "ObjectMetaClass Error internal_name: %s,\t d: %s" % (internal_name, d)) logger.debug("ObjectMetaClass Error: %s" % err) raise err if not isinstance(method, types.FunctionType): continue f = ProxyMethodDescriptor(k, internal_name) f.__doc__ = method.__doc__ d[k] = f # export visible properties... do not export hidden properties for attr, item in pluginclass._schema.allItems(): if not item['hidden']: d[attr] = ProxyDataDescriptor(attr) def __getitem(self, arg): if not hasattr(stripProxy(self), '__getitem__'): raise AttributeError('I (%s) do not have a __getitem__ attribute' % str(getName(self))) output = stripProxy(self).__getitem__(args) if isType(output, _getGangaObject()): return addProxy(output) else: return output ## NOT ENABLED YET rcurrie #if hasattr(pluginclass, '__getitem__'): # d['__getitem__'] = __getitem #d['__getitem__'] = __getitem # TODO: this makes GangaList inherit from the list # this is not tested and specifically the TestGangaList/testAllListMethodsExported should be verified # if name == "GangaList": # return type(name, (GPIProxyObject,list), d) return type(name, (GPIProxyObject, ), d)