diff --git a/camb/baseconfig.py b/camb/baseconfig.py index 27aa6e43..b892077c 100644 --- a/camb/baseconfig.py +++ b/camb/baseconfig.py @@ -1,4 +1,3 @@ -import os import os.path as osp import sys import platform @@ -48,50 +47,38 @@ def __getitem__(self, name_or_ordinal): return res -mock_load = os.environ.get('CAMB_MOCK_LOAD', None) -if mock_load: - # noinspection PyCompatibility - from unittest.mock import MagicMock +if not osp.isfile(CAMBL): + sys.exit( + 'Library file %s does not exist.\nMake sure you have installed or built the camb package ' + '(e.g. using "python setup.py make"); or remove any old conflicting installation and install again.' + % CAMBL) - camblib = MagicMock() - import_property = MagicMock() -else: - - if not osp.isfile(CAMBL): - sys.exit( - 'Library file %s does not exist.\nMake sure you have installed or built the camb package ' - '(e.g. using "python setup.py make"); or remove any old conflicting installation and install again.' - % CAMBL) +camblib = ctypes.LibraryLoader(IfortGfortranLoader).LoadLibrary(CAMBL) - camblib = ctypes.LibraryLoader(IfortGfortranLoader).LoadLibrary(CAMBL) +try: + c_int.in_dll(camblib, "handles_mp_set_cls_template_") + gfortran = False +except Exception: + pass - try: - c_int.in_dll(camblib, "handles_mp_set_cls_template_") - gfortran = False - except Exception: - pass +class _dll_value: + __slots__ = ['f'] - class _dll_value: - __slots__ = ['f'] + def __init__(self, f): + self.f = f - def __init__(self, f): - self.f = f + def __get__(self, instance, owner): + return self.f.value - def __get__(self, instance, owner): - return self.f.value + def __set__(self, instance, value): + self.f.value = value - def __set__(self, instance, value): - self.f.value = value - - def import_property(tp, module, func): - if gfortran: - f = tp.in_dll(camblib, "__%s_MOD_%s" % (module.lower(), func.lower())) - else: - f = tp.in_dll(camblib, "%s_mp_%s_" % (module.lower(), func.lower())) - - return _dll_value(f) +def import_property(tp, module, func): + name = "__%s_MOD_%s" if gfortran else "%s_mp_%s_" + f = tp.in_dll(camblib, name % (module.lower(), func.lower())) + return _dll_value(f) def lib_import(module_name, class_name, func_name, restype=None): @@ -122,8 +109,6 @@ def set_cl_template_file(cl_template_file=None): def check_fortran_version(version): - if mock_load: - return func = camblib.__camb_MOD_camb_getversion func.argtypes = [ctypes.c_char_p, ctypes.c_long] s = ctypes.create_string_buffer(33) @@ -189,7 +174,7 @@ def get_allocatable(self): def set_allocatable(self, instance, name): if instance and not isinstance(instance, self._baseclass): raise TypeError( - '%s expects object that is an instance of %s' % (name, self._baseclass.__name__)) + '%s expects an object that is an instance of %s' % (name, self._baseclass.__name__)) _set_allocatable(byref(self), byref(instance.fortran_self) if instance else None) @@ -243,14 +228,18 @@ def __setitem__(self, key, value): def __len__(self): return len(self.allocatables) - def __repr__(self): + def __str__(self): s = '' for i in range(len(self.allocatables)): item = self[i] - content = item._as_string() if isinstance(item, CAMB_Structure) else repr(item) - s += ('%s: <%s>\n ' % (i, item.__class__.__name__) + content.replace('\n', '\n ')).strip(' ') + content = item._as_string() if isinstance(item, CAMB_Structure) else str(item) + s += ('%s: <%s>\n ' % (i, item.__class__.__name__) + + content.replace('\n', '\n ')).strip(' ') return s + def __repr__(self): + return repr(list(self)) + def _make_array_class(baseclass, size): res = _class_cache.get((baseclass, size), None) @@ -285,7 +274,7 @@ def set_allocatable(self, array, name): for i, instance in enumerate(array): if not isinstance(instance, self._baseclass): raise TypeError( - '%s expects object that is an instance of %s' % (name, self._baseclass.__name__)) + '%s expects an object that is an instance of %s' % (name, self._baseclass.__name__)) pointers[i] = instance.fortran_self self._set_allocatable_object_1D_array(byref(self), byref(pointers), byref(c_int(len(array)))) @@ -646,7 +635,7 @@ def __getstate__(self) -> dict: state = {} for field_name, field_type in self.get_all_fields(): obj = getattr(self, field_name) - if isinstance(obj, (ctypes.Array, np.ndarray, FortranAllocatable)): + if isinstance(obj, (ctypes.Array, np.ndarray, _ArrayOfAllocatable)): state[field_name] = list(obj[:len(obj)]) elif isinstance(obj, ctypes.c_void_p): if obj.value is not None: @@ -724,9 +713,9 @@ def _new_copy(cls, source=None): def copy(self): """ - Make independent copy of this object. + Make an independent copy of this object. - :return: deep copy of self + :return: a deep copy of self """ return self._new_copy(source=self) @@ -771,7 +760,7 @@ def replace(self, instance): :param instance: instance of the same class to replace this instance with """ - if type(instance) != type(self): + if type(instance) is not type(self): raise TypeError( 'Cannot assign non-identical types (%s to %s, non-allocatable)' % (type(instance), type(self))) self.call_method('Replace', extra_args=[POINTER(f_pointer)], allow_inherit=False, @@ -795,8 +784,6 @@ def make_class_named(name, base_class=None): # Decorator to get function to get class pointers to each class type, and build index of classes # that allocatables could have def fortran_class(cls, optional=False): - if mock_load: - return cls class_module = getattr(cls, "_fortran_class_module_", None) if not class_module: msg = "F2003Class %s must define _fortran_class_module_" % cls.__name__ diff --git a/camb/model.py b/camb/model.py index b24f4c80..236c3b20 100644 --- a/camb/model.py +++ b/camb/model.py @@ -170,6 +170,7 @@ class in model.py to add the new parameter in the corresponding location of the In python, to set cosmology parameters it is usually best to use :meth:`set_cosmology` and equivalent methods for most other parameters. Alternatively the convenience function :func:`.camb.set_params` can construct a complete instance from a dictionary of relevant parameters. + You can also save and restore a CAMBparams instance using the repr and eval functions, or pickle it. """ _fields_ = [