def test_angelapreference(): # check default args pref = angelaPreference(1. / 3, 'docs') assert not pref.validator(1) assert pref.docs == 'docs' assert pref.default == 1. / 3 assert pref.representor(pref.default) == repr(1. / 3)
def test_str_repr(): # Just test whether str and repr do not throw an error and return something gp = angelaGlobalPreferences() gp.register_preferences('main', 'main category', name=angelaPreference(True, 'some preference')) assert len(str(gp)) assert len(repr(gp)) assert len(str(gp.main)) assert len(repr(gp.main))
def test_preference_name_checking(): ''' Test that you cannot set illegal preference names. ''' gp = angelaGlobalPreferences() # Name that starts with an underscore with pytest.raises(PreferenceError): gp.register_preferences('dummy', 'dummy doc', _notalegalname=angelaPreference( True, 'some preference')) # Name that clashes with a method name with pytest.raises(PreferenceError): gp.register_preferences('dummy', 'dummy doc', update=angelaPreference( True, 'some preference')) gp.register_preferences('a', 'dummy doc', b=angelaPreference(True, 'some preference')) #Trying to register a subcategory that would shadow a preference with pytest.raises(PreferenceError): gp.register_preferences('a.b', 'dummy doc', name=angelaPreference(True, 'some preference')) gp.register_preferences('b.c', 'dummy doc', name=angelaPreference(True, 'some preference')) #Trying to register a preference that clashes with an existing category with pytest.raises(PreferenceError): gp.register_preferences('b', 'dummy doc', c=angelaPreference(True, 'some preference'))
'ERROR': logging.ERROR, 'WARNING': logging.WARNING, 'INFO': logging.INFO, 'DEBUG': logging.DEBUG, 'DIAGNOSTIC': DIAGNOSTIC} logging.addLevelName(DIAGNOSTIC, 'DIAGNOSTIC') if 'logging' not in prefs.pref_register: # Duplicate import of this module can happen when the documentation is built prefs.register_preferences('logging', 'Logging system preferences', delete_log_on_exit=angelaPreference( default=True, docs=''' Whether to delete the log and script file on exit. If set to ``True`` (the default), log files (and the copy of the main script) will be deleted after the angela process has exited, unless an uncaught exception occurred. If set to ``False``, all log files will be kept. ''', ), file_log_level=angelaPreference( default='DIAGNOSTIC', docs=''' What log level to use for the log written to the log file. In case file logging is activated (see `logging.file_log`), which log level should be used for logging. Has to be one of CRITICAL, ERROR, WARNING, INFO, DEBUG or DIAGNOSTIC. ''', validator=log_level_validator),
get_numpy_dtype) from ...targets import codegen_targets from ...cpp_prefs import get_compiler_and_args from .extension_manager import cython_extension_manager __all__ = ['CythonCodeObject'] logger = get_logger(__name__) # Preferences prefs.register_preferences( 'codegen.runtime.cython', 'Cython runtime codegen preferences', multiprocess_safe=angelaPreference(default=True, docs=''' Whether to use a lock file to prevent simultaneous write access to cython .pyx and .so files. '''), cache_dir=angelaPreference( default=None, validator=lambda x: x is None or isinstance(x, str), docs=''' Location of the cache directory for Cython files. By default, will be stored in a ``angela_extensions`` subdirectory where Cython inline stores its temporary files (the result of ``get_cython_cache_dir()``). '''), delete_source_files=angelaPreference(default=True, docs=''' Whether to delete source files after compiling. The Cython source files can take a significant amount of disk space, and
def test_angelaglobalpreferences(): # test that pre-setting a nonexistent preference in a subsequently # existing base name raises an error at the correct point gp = angelaGlobalPreferences() # This shouldn't work, in user code only registered preferences can be set with pytest.raises(PreferenceError): gp.__setitem__('a.b', 5) # This uses the method that is used when reading preferences from a file gp._set_preference('a.b', 5) gp._set_preference('a.c', 5) with pytest.raises(PreferenceError): gp.register_preferences('a', 'docs for a', b=angelaPreference(5, 'docs for b')) # test that post-setting a nonexistent preference in an existing base # name raises an error gp = angelaGlobalPreferences() gp.register_preferences('a', 'docs for a', b=angelaPreference(5, 'docs for b')) with pytest.raises(PreferenceError): gp.__setitem__('a.c', 5) # Test pre and post-setting some correct names but valid and invalid values gp = angelaGlobalPreferences() gp._set_preference('a.b', 5) gp.register_preferences( 'a', 'docs for a', b=angelaPreference(5, 'docs for b'), c=angelaPreference(1 * volt, 'docs for c'), d=angelaPreference(0, 'docs for d', validator=lambda x: x >= 0), e=angelaPreference(float64, 'docs for e', representor=lambda x: x.__name__), ) assert gp['a.c'] == 1 * volt gp['a.c'] = 2 * volt with pytest.raises(PreferenceError): gp.__setitem__('a.c', 3 * amp) gp['a.d'] = 2.0 with pytest.raises(PreferenceError): gp.__setitem__('a.d', -1) gp['a.e'] = float32 with pytest.raises(PreferenceError): gp.__setitem__('a.e', 0) # test backup and restore gp._backup() gp['a.d'] = 10 assert gp['a.d'] == 10 gp._restore() assert gp['a.d'] == 2.0 # test that documentation and as_file generation runs without error, but # don't test for values because we might change the organisation of it assert len(gp.get_documentation()) gp.as_file gp.defaults_as_file # test that reading a preference file works as expected pref_file = StringIO(''' # a comment a.b = 10 [a] c = 5*volt d = 1 e = float64 ''') gp.read_preference_file(pref_file) assert gp['a.b'] == 10 assert gp['a.c'] == 5 * volt assert gp['a.d'] == 1 assert gp['a.e'] == float64 # test that reading a badly formatted prefs file fails pref_file = StringIO(''' [a b = 10 ''') with pytest.raises(PreferenceError): gp.read_preference_file(pref_file) # test that reading a well formatted prefs file with an invalid value fails pref_file = StringIO(''' a.b = 'oh no, not a string' ''') with pytest.raises(PreferenceError): gp.read_preference_file(pref_file) # assert that writing the prefs to a file and loading them gives the # same values gp = angelaGlobalPreferences() gp.register_preferences( 'a', 'docs for a', b=angelaPreference(5, 'docs for b'), ) gp._backup() gp['a.b'] = 10 str_modified = gp.as_file str_defaults = gp.defaults_as_file gp['a.b'] = 15 gp.read_preference_file(StringIO(str_modified)) assert gp['a.b'] == 10 gp.read_preference_file(StringIO(str_defaults)) assert gp['a.b'] == 5 # check that load_preferences works, but nothing about its values gp = angelaGlobalPreferences() gp.load_preferences()
from angela2.core.functions import Function from ...codeobject import CodeObject, constant_or_scalar, check_compiler_kwds from ...templates import Templater from ...generators.numpy_generator import NumpyCodeGenerator from ...targets import codegen_targets __all__ = ['NumpyCodeObject'] # Preferences prefs.register_preferences('codegen.runtime.numpy', 'Numpy runtime codegen preferences', discard_units=angelaPreference(default=False, docs=''' Whether to change the namespace of user-specifed functions to remove units. ''')) class LazyArange(Iterable): ''' A class that can be used as a `~numpy.arange` replacement (with an implied step size of 1) but does not actually create an array of values until necessary. It is somewhat similar to the ``range()`` function in Python 3, but does not use a generator. It is tailored to a special use case, the ``_vectorisation_idx`` variable in numpy templates, and not meant for general use. The ``_vectorisation_idx`` is used for stateless function calls such as ``rand()`` and for the numpy codegen target determines the number of values produced by such a call. This will often be the number of neurons or synapses, and this class avoids creating a new array of that size
def test_preference_name_access(): ''' Test various ways of accessing preferences ''' gp = angelaGlobalPreferences() gp.register_preferences('main', 'main category', name=angelaPreference(True, 'some preference')) gp.register_preferences('main.sub', 'subcategory', name2=angelaPreference(True, 'some preference')) gp.register_preferences('main.sub_no_pref', 'subcategory without preference') gp.register_preferences('main.sub_no_pref.sub', 'deep subcategory', name=angelaPreference(True, 'some preference')) # Keyword based access assert gp['main.name'] assert gp['main.sub.name2'] assert gp['main.sub_no_pref.sub.name'] gp['main.name'] = False gp['main.sub.name2'] = False gp['main.sub_no_pref.sub.name'] = False # Attribute based access assert not gp.main.name # we set it to False above assert not gp.main.sub.name2 assert not gp.main.sub_no_pref.sub.name gp.main.name = True gp.main.sub.name2 = True gp.main.sub_no_pref.sub.name = True # Mixed access assert gp.main['name'] assert gp['main'].name assert gp.main['sub'].name2 assert gp['main'].sub['name2'] # Accessing categories assert isinstance(gp['main'], angelaGlobalPreferencesView) assert isinstance(gp['main.sub'], angelaGlobalPreferencesView) assert isinstance(gp.main, angelaGlobalPreferencesView) assert isinstance(gp.main.sub, angelaGlobalPreferencesView) # Setting categories shouldn't work with pytest.raises(PreferenceError): gp.__setitem__('main', None) with pytest.raises(PreferenceError): gp.__setattr__('main', None) with pytest.raises(PreferenceError): gp.main.__setitem__('sub', None) with pytest.raises(PreferenceError): gp.main.__setattr__('sub', None) # Neither should deleting categories or preferences with pytest.raises(PreferenceError): gp.__delitem__('main') with pytest.raises(PreferenceError): gp.__delattr__('main') with pytest.raises(PreferenceError): gp.main.__delitem__('name') with pytest.raises(PreferenceError): gp.main.__delattr__('name') with pytest.raises(PreferenceError): gp.main.__delitem__('sub') with pytest.raises(PreferenceError): gp.main.__delattr__('sub') #Errors for accessing non-existing preferences with pytest.raises(KeyError): gp['main.doesnotexist'] with pytest.raises(KeyError): gp['nonexisting.name'] with pytest.raises(KeyError): gp.main.doesnotexist with pytest.raises(KeyError): gp.nonexisting.name # Check dictionary functionality for name, value in gp.items(): assert gp[name] == value for name, value in gp.main.items(): assert gp.main[name] == value assert len(gp) == 3 # three preferences in total assert len(gp['main']) == 3 # all preferences are in the main category assert len(gp['main.sub']) == 1 # one preference in main.sub assert 'main.name' in gp assert 'name' in gp['main'] assert 'name2' in gp['main.sub'] assert not 'name' in gp['main.sub'] gp['main.name'] = True gp.update({'main.name': False}) assert not gp['main.name'] gp.main.update({'name': True}) assert gp['main.name'] # Class based functionality assert 'main' in dir(gp) assert 'sub' in dir(gp.main) assert 'name' in dir(gp.main) # Check that the fiddling with getattr and setattr did not destroy the # access to standard attributes assert len(gp.prefs) assert gp.main._basename == 'main'
'has to be existing directory' % (val))) if any(not os.path.isfile(os.path.join(val, 'gsl', filename)) for filename in ['gsl_odeiv2.h', 'gsl_errno.h', 'gsl_matrix.h']): raise PreferenceError(('Illegal value for GSL directory: %s, ' 'has to contain gsl_odeiv2.h, gsl_errno.h ' 'and gsl_matrix.h' % (val))) return True prefs.register_preferences( 'GSL', 'Directory containing GSL code', directory=angelaPreference( validator=valid_gsl_dir, docs= ("Set path to directory containing GSL header files (gsl_odeiv2.h etc.)" "\nIf this directory is already in Python's include (e.g. because of " "conda installation), this path can be set to None."), default=None)) class GSLCodeGenerator(object): ''' GSL code generator. Notes ----- Approach is to first let the already existing code generator for a target language do the bulk of the translating from abstract_code to actual code. This generated code is slightly adapted to render it GSL compatible. The most critical part here is that the vector_code that is normally
elif dtype == numpy.bool_ or dtype is bool: dtype = 'char' else: raise ValueError("dtype " + str(dtype) + " not known.") return dtype # Preferences prefs.register_preferences( 'codegen.generators.cpp', 'C++ codegen preferences', restrict_keyword=angelaPreference( default='__restrict', docs=''' The keyword used for the given compiler to declare pointers as restricted. This keyword is different on different compilers, the default works for gcc and MSVS. ''', ), flush_denormals=angelaPreference( default=False, docs=''' Adds code to flush denormals to zero. The code is gcc and architecture specific, so may not compile on all platforms. The code, for reference is:: #define CSR_FLUSH_TO_ZERO (1 << 15) unsigned csr = __builtin_ia32_stmxcsr(); csr |= CSR_FLUSH_TO_ZERO;
msvc_arch_flag = '/arch:SSE' if 'sse2' in flags: msvc_arch_flag = '/arch:SSE2' if 'avx' in flags: msvc_arch_flag = '/arch:AVX' if 'avx2' in flags: msvc_arch_flag = '/arch:AVX2' # Preferences prefs.register_preferences( 'codegen.cpp', 'C++ compilation preferences', compiler = angelaPreference( default='', docs=''' Compiler to use (uses default if empty) Should be gcc or msvc. ''' ), extra_compile_args=angelaPreference( default=None, validator=lambda v: True, docs=''' Extra arguments to pass to compiler (if None, use either ``extra_compile_args_gcc`` or ``extra_compile_args_msvc``). ''' ), extra_compile_args_gcc=angelaPreference( default=['-w', '-O3', '-ffast-math', '-fno-finite-math-only', '-march=native', '-std=c++11'], docs=''' Extra compile arguments to pass to GCC compiler
__all__ = [] def dtype_repr(dtype): return dtype.__name__ def default_float_dtype_validator(dtype): return dtype in [float32, float64] prefs.register_preferences('core', 'Core angela preferences', default_float_dtype=angelaPreference( default=float64, docs=''' Default dtype for all arrays of scalars (state variables, weights, etc.). ''', representor=dtype_repr, validator=default_float_dtype_validator, ), default_integer_dtype=angelaPreference( default=int32, docs=''' Default dtype for all arrays of integer scalars. ''', representor=dtype_repr, ), outdated_dependency_error=angelaPreference( default=True, docs=''' Whether to raise an error for outdated dependencies (``True``) or just a warning (``False``).
from .codeobject import CodeObject # Preferences prefs.register_preferences( 'codegen', 'Code generation preferences', target=angelaPreference( default='auto', docs=''' Default target for code generation. Can be a string, in which case it should be one of: * ``'auto'`` the default, automatically chose the best code generation target available. * ``'cython'``, uses the Cython package to generate C++ code. Needs a working installation of Cython and a C++ compiler. * ``'numpy'`` works on all platforms and doesn't need a C compiler but is often less efficient. Or it can be a ``CodeObject`` class. ''', validator=lambda target: isinstance(target, str) or issubclass( target, CodeObject), ), string_expression_target=angelaPreference( default='numpy', docs=''' Default target for the evaluation of string expressions (e.g. when indexing state variables). Should normally not be changed from the default numpy target, because the overhead of compiling code is not