diff --git a/pyxnat/core/interfaces.py b/pyxnat/core/interfaces.py index 3ad9f967..5bcfa545 100644 --- a/pyxnat/core/interfaces.py +++ b/pyxnat/core/interfaces.py @@ -4,11 +4,6 @@ import json import requests -try: - import socks -except ImportError: - socks = None - from urllib.parse import urlparse from .select import Select @@ -21,11 +16,38 @@ from .array import ArrayData from .xpath_store import XpathStore from . import xpass +from . import derivatives + DEBUG = False STUBBORN = False +# generic classes +def __get_modules__(m): + import pkgutil + modules = [] + prefix = m.__name__ + '.' + for importer, modname, ispkg in pkgutil.iter_modules(m.__path__, prefix): + module = __import__(modname, fromlist='dummy') + if not ispkg: + modules.append(module) + else: + modules.extend(__get_modules__(module)) + return modules + + +def __find_all_functions__(m): + import inspect + functions = {} + modules = __get_modules__(m) + for m in modules: + for name, obj in inspect.getmembers(m): + if inspect.isfunction(obj): + functions.setdefault(m, []).append(obj) + return functions + + # main entry point class Interface(object): """ Main entry point to access an XNAT server. @@ -174,6 +196,16 @@ def __init__(self, server=None, user=None, password=None, config=None, self.manage = GlobalManager(self) self.xpath = XpathStore(self) + functions = __find_all_functions__(derivatives) + d = {} + for m, mod_functions in functions.items(): + if hasattr(m, 'XNAT_RESOURCE_NAME'): + d[m.XNAT_RESOURCE_NAME] = mod_functions + elif hasattr(m, 'XNAT_RESOURCE_NAMES'): + for each in m.XNAT_RESOURCE_NAMES: + d[each] = mod_functions + self._mod_functions = d + if _DRAW_GRAPHS: self._get_graph = GraphData(self) self.draw = PaintGraph(self) diff --git a/pyxnat/core/resources.py b/pyxnat/core/resources.py index 82237cb0..4d1f175f 100644 --- a/pyxnat/core/resources.py +++ b/pyxnat/core/resources.py @@ -30,10 +30,7 @@ from . import schema from . import httputil from . import downloadutils -from . import derivatives import types -import pkgutil -import inspect from urllib.parse import quote, unquote DEBUG = False @@ -121,29 +118,6 @@ def __init__(cls, name, bases, dct): super(CollectionType, cls).__init__(name, bases, dct) -# generic classes -def __get_modules__(m): - modules = [] - prefix = m.__name__ + '.' - for importer, modname, ispkg in pkgutil.iter_modules(m.__path__, prefix): - module = __import__(modname, fromlist='dummy') - if not ispkg: - modules.append(module) - else: - modules.extend(__get_modules__(module)) - return modules - - -def __find_all_functions__(m): - functions = {} - modules = __get_modules__(m) - for m in modules: - for name, obj in inspect.getmembers(m): - if inspect.isfunction(obj): - functions.setdefault(m, []).append(obj) - return functions - - class EObject(object): """ Generic Object for an element URI. """ @@ -165,20 +139,6 @@ def __init__(self, uri, interface): self._intf = interface self.attrs = EAttrs(self) - functions = __find_all_functions__(derivatives) - - for m, mod_functions in functions.items(): - is_resource = False - if (hasattr(m, 'XNAT_RESOURCE_NAME') and - self._urn == m.XNAT_RESOURCE_NAME) or \ - (hasattr(m, 'XNAT_RESOURCE_NAMES') and - self._urn in m.XNAT_RESOURCE_NAMES): - is_resource = True - - if is_resource: - for f in mod_functions: - setattr(self, f.__name__, types.MethodType(f, self)) - def __getstate__(self): return {'uri': self._uri, 'interface': self._intf} @@ -1793,14 +1753,12 @@ def __repr__(self): return output else: return '<%s Object> %s' % (self.__class__.__name__, - unquote(uri_last(self._uri)) - ) + unquote(uri_last(self._uri))) def set_param(self, key, value): self.attrs.set('%s/parameters/addParam[name=%s]/addField' % (self.datatype(), key), - value - ) + value) def get_param(self, key): return self.xpath( @@ -1815,6 +1773,25 @@ def params(self): class Resource(EObject, metaclass=ElementType): + def __init__(self, cbase, interface): + from pyxnat.core.errors import DatabaseError + super(Resource, self).__init__(cbase, interface) + + mf = interface._mod_functions.get(self._urn, []) + if len(mf) == 0: + uri = uri_parent(self._uri) + try: + d = self._intf._get_json(uri) + r = [e for e in d if e['xnat_abstractresource_id'] == self._urn] + if len(r) == 1: + label = r[0]['label'] + mf = interface._mod_functions.get(label, []) + except DatabaseError: + print('Warning:', self._uri, 'raising DatabaseError') + + for f in mf: + setattr(self, f.__name__, types.MethodType(f, self)) + def __repr__(self): def sizeof_fmt(num, suffix='B'):