Skip to content
Snippets Groups Projects
Commit 5654b0a7 authored by Andreas Dedner's avatar Andreas Dedner
Browse files

Merge branch 'master' of ../dune-python

parents 9ad18ff4 0f7472e5
Branches
Tags
1 merge request!790Feature/add python bindings
add_python_targets(common
__init__
compatibility
deprecated
module
checkconfiguration
hashit
pickle
project
)
import logging
import os
logger = logging.getLogger(__name__)
loglevel = None
try:
loglevel = getattr(logging, os.environ['DUNE_LOG_LEVEL'].upper())
except KeyError:
pass
except AttributeError:
logger.warn('Invalid log level in environment variable DUNE_LOG_LEVEL')
logformat = os.environ.get('DUNE_LOG_FORMAT')
logging.basicConfig(format=logformat, level=loglevel)
try:
from mpi4py import MPI
if MPI.COMM_WORLD.Get_rank() == 0:
logger.info('MPI initialized successfully')
except ImportError:
logger.info('mpi4py not found, MPI not initialized')
from .._common import *
from .deprecated import DeprecatedObject
import numpy
def fvgetitem(self,index):
try:
return self._getitem(index)
except TypeError:
return numpy.array(self,copy=False)[index]
finished = False
nr = 1
while not finished:
try:
cls = globals()["FieldVector_"+str(nr)]
setattr(cls, "_getitem", cls.__getitem__)
setattr(cls, "__getitem__", fvgetitem)
nr += 1
except KeyError:
finished = True
def loadvec(includes ,typeName ,constructors=None, methods=None):
from dune.generator.generator import SimpleGenerator
from dune.common.hashit import hashIt
generatorvec = SimpleGenerator("FieldVector","Dune::Python")
includes = includes + ["dune/python/common/fvector.hh"]
typeHash = "fieldvector_" + hashIt(typeName)
return generatorvec.load(includes ,typeName ,typeHash,
constructors ,methods, bufferProtocol=True)
def FieldVector(values):
values = list(values)
fv = "FieldVector_" + str(len(values))
try:
return globals()[fv](values)
except KeyError:
typeName = "Dune::FieldVector< double ," + str(len(values)) + " >"
includes = []
cls = loadvec(includes, typeName).FieldVector
setattr(cls, "_getitem", cls.__getitem__)
setattr(cls, "__getitem__", fvgetitem)
globals().update({fv:cls})
return globals()[fv](values)
def FieldMatrix(values):
fm = "FieldMatrix_" + str(len(values)) + "_" + str(len(values[0]))
return globals()[fm](values)
def _raise(exception):
raise exception
from __future__ import print_function, unicode_literals
import logging
import os
import re
import subprocess
import dune.common.module
from dune.common.compatibility import buffer_to_str
from dune.generator import builder, ConfigurationError
logger = logging.getLogger(__name__)
def assertHave(identifier):
'''check if an identifier is defined equal to 1 in the dune-py config.h file.
use this to check if for example #define HAVE_DUNE_COMMON 1 is
provided the config file by calling
assertHave("HAVE_DUNE_COMMON")
'''
config = os.path.join(dune.common.module.get_dune_py_dir(), "config.h")
matches = [match for match in [re.match('^[ ]*#define[ ]+' + identifier.strip() + '[ ]+1$', line) for line in open(config)] if match is not None]
if not matches:
matches = [match for match in [re.match('^[ ]*#define[ ]+' + identifier.strip() + '[ ]+ENABLE', line) for line in open(config)] if match is not None]
if not matches:
# logger.info("checkconfiguration.have(" + identifier + ") failed - identifier not defined in " + config)
raise ConfigurationError(identifier + " is not set in dune-py's config.h")
elif matches.__len__() > 1:
# logger.info("checkconfiguration.have(" + identifier + ") failed - multiple definitions in " + config)
raise ConfigurationError(identifier + " found multiple times in dune-py's config.h")
def preprocessorAssert(tests):
'''perform preprocessore checks.
A list of checks can be provided each should contain a pair, the
first being the preprocessor check to perform (e.g. #if or #ifdef)
and the second being the message to print if the check fails. The
generated code is of the form:
tests[i][0]
#else
test failed
#endif
so the first argument of each test has to make this piece of code
valid C++ code assuming config.h is included.
'''
source = "#include <config.h>\nint main() {\n"
i = 0
for t in tests:
source = source + t[0]+"\n#else\nreturn "+str(i+1)+";\n#endif\n"
i += 1
source = source + "return 0;\n}\n"
with open(os.path.join(builder.generated_dir, "generated_module.hh"), 'w') as out:
out.write(source)
builder.compile("generated_test")
test_args = ["./generated_test"]
test = subprocess.Popen(test_args, cwd=builder.generated_dir, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = test.communicate()
logger.debug(buffer_to_str(stdout))
returncode = test.returncode
if returncode > 0:
logger.debug("failed testing:\n"+source)
logger.critical("checking "+tests[returncode-1][0]+" failed: "+tests[returncode-1][1])
raise ConfigurationError(tests[returncode-1][1])
import importlib
import sys
if sys.version_info.major == 2:
def buffer_to_str(b):
return b
else:
def buffer_to_str(b):
return b.decode('utf-8')
if sys.version_info.major == 2:
def isString(s):
return isinstance(s, (str, unicode))
def isInteger(i):
return isinstance(i, (int, long))
else:
def isString(s):
return isinstance(s, str)
def isInteger(i):
return isinstance(i, int)
if sys.version_info.major == 2:
def reload_module(module):
reload(module)
return module
else:
reload_module = importlib.reload
if sys.version_info.major == 2:
from inspect import getargspec
def getNumberOfParameters(func):
return len( getargspec(func).args )
else:
from inspect import signature
def getNumberOfParameters(func):
return len( signature(func).parameters )
import logging
class DeprecatedObject(object):
def __init__(self, real, message):
self.real = real
self.logger = logging.getLogger(real.__module__)
self.message = message
def __call__(self, *args, **kwargs):
object.__getattribute__(self, "logger").warning(object.__getattribute__(self, "message"))
return object.__getattribute__(self, "real")(*args, **kwargs)
def __getattribute__(self, name):
object.__getattribute__(self, "logger").warning(object.__getattribute__(self, "message"))
return getattr(object.__getattribute__(self, "real"), name)
def __repr__(self):
object.__getattribute__(self, "logger").warning(object.__getattribute__(self, "message"))
return repr(object.__getattribute__(self, "real"))
import hashlib
def hashIt(typeName):
if hasattr(typeName, '__iter__'):
return hashlib.md5("".join(t for t in typeName).encode('utf-8')).hexdigest()
else:
return hashlib.md5(typeName.encode('utf-8')).hexdigest()
This diff is collapsed.
import sys
if sys.version_info.major == 2:
from cPickle import *
else:
from pickle import *
from __future__ import absolute_import, division, print_function, unicode_literals
import os
def write_cmake_file(dir, content=None, subdirs=None, install=None):
if not os.path.isdir(dir):
raise ValueError('Directory \'' + dir + '\' does not exist.')
append = []
if subdirs is not None:
append += ['add_subdirectory("' + d + '")' for d in subdirs]
if install is not None and install[0]:
append += ['install(FILES'] + [' ' + f for f in install[0]] + [' DESTINATION "' + install[1] + '")']
with open(os.path.join(dir, 'CMakeLists.txt'), 'w') as file:
if content is not None:
file.write('\n'.join(content) + '\n')
if append:
file.write('\n'.join(append) + '\n')
def write_config_h_cmake(dir, project, public_content=None):
if not os.path.isdir(dir):
raise ValueError('Directory \'' + dir + '\' does not exist.')
project_up = project.upper().replace('-', '_')
with open(os.path.join(dir, 'config.h.cmake'), 'w') as file:
file.write('/* begin ' + project + '\n put the definitions for config.h specific to\n your project here. Everything above will be\n overwritten\n*/\n\n')
file.write('/* begin private */\n')
file.write('\n/* Name of package */\n#define PACKAGE "${DUNE_MOD_NAME}"\n')
file.write('\n/* Define to the full name of this package */\n#define PACKAGE_NAME "${DUNE_MOD_NAME}"\n')
file.write('\n/* Define to the version of this package */\n#define PACKAGE_VERSION "${DUNE_MOD_VERSION}"\n')
file.write('\n/* Define to the full name and version of this package */\n#define PACKAGE_STRING "${DUNE_MOD_NAME} ${DUNE_MOD_VERSION}"\n')
file.write('\n/* Define to the address where bug reports for this package should be sent */\n#define PACKAGE_BUGREPORT "${DUNE_MAINTAINER}"\n')
file.write('\n/* Define to the one symbol short name of this package */\n#define PACKAGE_TARNAME "${DUNE_MOD_NAME}"\n')
file.write('\n/* Define to the home page for this package */\n#define PACKAGE_URL "${DUNE_MOD_URL}"\n')
file.write('\n/* end private */\n')
file.write('\n/* Define to the version of ' + project + ' */\n#define ' + project_up + '_VERSION "${' + project_up + '_VERSION}"\n')
file.write('\n/* Define to the major version of ' + project + ' */\n#define ' + project_up + '_VERSION_MAJOR "${' + project_up + '_VERSION_MAJOR}"\n')
file.write('\n/* Define to the minor version of ' + project + ' */\n#define ' + project_up + '_VERSION_MINOR "${' + project_up + '_VERSION_MINOR}"\n')
file.write('\n/* Define to the revision of ' + project + ' */\n#define ' + project_up + '_VERSION_REVISION "${' + project_up + '_VERSION_REVISION}"\n')
if public_content is not None:
file.write('\n'.join(public_content) + '\n\n')
file.write('\n/* end ' + project + '\n Everything below here will be overwritten.\n*/\n')
def make_cmake_modules(dir, description, macros):
if not os.path.isdir(dir):
raise ValueError('Directory \'' + dir + '\' does not exist.')
cmake_dir_rel = os.path.join('cmake', 'modules')
cmake_dir = os.path.join(dir, cmake_dir_rel)
if not os.path.isdir(cmake_dir):
os.makedirs(cmake_dir)
macroFileName = ''.join([word[0].upper() + word[1:] for word in description.name.split('-')]) + 'Macros.cmake'
write_cmake_file(cmake_dir, install=([macroFileName], '${DUNE_INSTALL_MODULEDIR}'))
with open(os.path.join(cmake_dir, macroFileName), 'w') as file:
file.write('\n'.join(macros) + '\n')
return cmake_dir_rel
def make_project(dir, description, subdirs=None, enable_all_packages=True):
if not os.path.isdir(dir):
raise ValueError('Directory \'' + dir + '\' does not exist.')
with open(os.path.join(dir, 'dune.module'), 'w') as file:
file.write(repr(description))
cmake_content = ['cmake_minimum_required(VERSION 3.1)', 'project(' + description.name + ' C CXX)']
cmake_content += ['',
'if(NOT (dune-common_DIR OR dune-common_ROOT OR "${CMAKE_PREFIX_PATH}" MATCHES ".*dune-common.*"))',
' string(REPLACE ${CMAKE_PROJECT_NAME} dune-common dune-common_DIR ${PROJECT_BINARY_DIR})',
'endif()']
cmake_content += ['', 'find_package(dune-common REQUIRED)']
if subdirs is not None and 'cmake/modules' in subdirs:
cmake_content += ['list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake/modules" "${dune-common_MODULE_PATH}")']
else:
cmake_content += ['list(APPEND CMAKE_MODULE_PATH ${dune-common_MODULE_PATH})']
cmake_content += ['', 'include(DuneMacros)', 'dune_project()']
if enable_all_packages:
cmake_content += ['dune_enable_all_packages()']
cmake_content += ['',
'if( dune-uggrid_FOUND )',
' if( NOT BUILD_SHARED_LIBS )',
' message(SEND_ERROR "dune-uggrid found but shared libs disabled! Python bindings for UGGrid will only work with shared -DBUILD_SHARED_LIBS=ON")',
' endif()',
'endif()']
if subdirs is not None:
cmake_content += [''] + ['add_subdirectory("' + d + '")' for d in subdirs]
cmake_content += ['', 'finalize_dune_project(GENERATE_CONFIG_H_CMAKE)']
write_cmake_file(dir, cmake_content)
with open(os.path.join(dir, description.name + '.pc.in'), 'w') as file:
file.write('prefix=@prefix@\nexec_prefix=@exec_prefix@\n')
file.write('libdir=@libdir@\nincludedir=@includedir@\n')
file.write('CXX=@CXX@\nCC=@CC@\n')
file.write('DEPENDENCIES=@REQUIRES@\n\n')
file.write('Name: @PACKAGE_NAME@\n')
file.write('Version: @VERSION@\n')
file.write('Description: DUNE module "' + description.name + '"\n')
file.write('URL: http://dune-project.org\n')
file.write('Requires: ${DEPENDENCIES}\n')
file.write('Libs: -L${libdir}\n')
file.write('Cflags: -I${includedir}\n')
write_config_h_cmake(dir, description.name)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment