diff --git a/dev-tools/python-bindings/README b/dev-tools/python-bindings/README deleted file mode 100644 index 3d19424c8a5d3cc1e313c6e863756940067f096d..0000000000000000000000000000000000000000 --- a/dev-tools/python-bindings/README +++ /dev/null @@ -1,9 +0,0 @@ -This directory contains the auxiliary program codegenerator.py -that generates wrapper code -that makes libBornAgainCore and libBornAgainFit accessible from Python. - -For more info, run - codegenerator.py help - -See also - http://apps.jcns.fz-juelich.de/redmine/projects/bornagain/wiki/Python_bindings diff --git a/dev-tools/python-bindings/codegenerator.py b/dev-tools/python-bindings/codegenerator.py deleted file mode 100755 index 1e1efd169ed07d5efe2e5baef14a1bed562d99d6..0000000000000000000000000000000000000000 --- a/dev-tools/python-bindings/codegenerator.py +++ /dev/null @@ -1,65 +0,0 @@ -#!/usr/bin/env python - -def help_short(): - print('Usage: ./codegenerator.py make|install|clean|help') - -def help_long(): - print(''' -C++ wrapper generator for exposing C++ libraries to Python. -''') - help_short() - print( ''' -Options: - make: generate python boost wrapping code in ./output subdirectory - install: install generated code to BornAgain/PythonAPI - clean: clean local directory - help: this help - -Dependencies: - - boost-python - - Python2.7 - - gccxml (github.com/gccxml) - - pygccxml (github.com/gccxml/pygccxml) - - Py++ (https://bitbucket.org/ompl/pyplusplus) - -Notes: - - Run codegenerator.py in the directory where it resides. - - More info at http://apps.jcns.fz-juelich.de/redmine/projects/bornagain/wiki/Python_bindings -''') - - -import sys -import os - -import utils_build -import utils_install - -import settings_core -import settings_fit - -projects = [ settings_core, settings_fit ] - -def main(): - if len(sys.argv)!=2: - help_short() - exit() - - if sys.argv[1] == 'make': - for prj in projects: - utils_build.MakePythonAPI(prj) - elif sys.argv[1] == 'install': - for prj in projects: - utils_install.InstallCode(prj) - elif sys.argv[1] == 'clean': - clean = ["output", "cache_*.xml", "*~", "named_tuple.py", "*.pyc", - "exposed_decl.pypp.txt", "tmp.pypp.cpp"] - for x in clean: - os.system("rm -rf "+x) - elif sys.argv[1] == 'help': - help_long() - else: - help_short() - - -if __name__ == '__main__': - main() diff --git a/dev-tools/python-bindings/settings_core.py b/dev-tools/python-bindings/settings_core.py deleted file mode 100644 index c338ff34d8ecebc2c2e86a65f4639192e8339257..0000000000000000000000000000000000000000 --- a/dev-tools/python-bindings/settings_core.py +++ /dev/null @@ -1,442 +0,0 @@ -# BornAgain Core library -# settings for Python API generation by codegenerator.py - -from pyplusplus.module_builder import call_policies -from pyplusplus import messages - -import utils_build - - -license = '''\ -// ************************************************************************** // -// -// BornAgain: simulate and fit scattering at grazing incidence -// -//! @file Automatically generated boost::python code for BornAgain Python bindings -//! @brief Automatically generated boost::python code for BornAgain Python bindings -//! -//! @homepage http://bornagainproject.org -//! @license GNU General Public License v3 or higher (see COPYING) -//! @copyright Forschungszentrum Juelich GmbH 2015 -//! @authors Scientific Computing Group at MLZ Garching -//! @authors C. Durniak, M. Ganeva, G. Pospelov, W. Van Herck, J. Wuttke -// -// ************************************************************************** // -''' - - -lib_name = 'libBornAgainCore' - -temp_dir = 'output/PyCore' -install_inc = '../../Core/PythonAPI/inc' -install_src = '../../Core/PythonAPI/src' - -master_include = "PythonCoreList.h" -cache_filename = "cache_core.xml" -special_flags = "-DBORNAGAIN_PYTHON" - -with_pure_virtual = True -with_Numpy = True -with_converter = True - - -include_dirs = [ - '../../Core/Samples/inc', - '../../Core/FormFactors/inc', - '../../Core/Algorithms/inc', - '../../Core/Tools/inc', - '../../Core/PythonAPI/inc', - '../../Core/Geometry/inc', - '../../Core/InputOutput', -] - -include_classes = [ - "AttLimits", - "FixedBinAxis", - "VariableBinAxis", - "ConstKBinAxis", - "CustomBinAxis", - "BasicVector3D<double>", - "BasicVector3D<std::complex<double> >", - "Beam", - "Bin1D", - "Bin1DCVector", - "Crystal", - "DistributionGate", - "DistributionLorentz", - "DistributionGaussian", - "DistributionLogNormal", - "DistributionCosine", - "FTDistribution1DCauchy", - "FTDistribution1DGauss", - "FTDistribution1DGate", - "FTDistribution1DTriangle", - "FTDistribution1DCosine", - "FTDistribution1DVoigt", - "FTDistribution2DCauchy", - "FTDistribution2DGauss", - "FTDistribution2DGate", - "FTDistribution2DCone", - "FTDistribution2DVoigt", - "FTDecayFunction1DCauchy", - "FTDecayFunction1DGauss", - "FTDecayFunction1DTriangle", - "FTDecayFunction1DVoigt", - "FTDecayFunction2DCauchy", - "FTDecayFunction2DGauss", - "FTDecayFunction2DVoigt", - "FormFactorAnisoPyramid", - "FormFactorBox", - "FormFactorCone", - "FormFactorCone6", - "FormFactorCuboctahedron", - "FormFactorCylinder", - "FormFactorCrystal", - "FormFactorDecoratorDebyeWaller", - "FormFactorEllipsoidalCylinder", - "FormFactorFullSphere", - "FormFactorFullSpheroid", - "FormFactorGauss", - "FormFactorHemiEllipsoid", - "FormFactorLongBoxGauss", - "FormFactorLongBoxLorentz", - "FormFactorLorentz", - "FormFactorPrism3", - "FormFactorPrism6", - "FormFactorPyramid", - "FormFactorRipple1", - "FormFactorRipple2", - "FormFactorSphereGaussianRadius", - "FormFactorSphereLogNormalRadius", - "FormFactorSphereUniformRadius", - "FormFactorTetrahedron", - "FormFactorTrivial", - "FormFactorTruncatedCube", - "FormFactorTruncatedSphere", - "FormFactorTruncatedSpheroid", - "FormFactorWeighted", - "GISASSimulation", - "HomogeneousMaterial", - "HomogeneousMagneticMaterial", - "IAbstractParticle", - "IAxis", - "ICloneable", - "IClusteredParticles", - "ICompositeSample", - "IDetector2D", - "ILayout", - "IDetectorResolution", - "IDistribution1D", - "IFTDecayFunction1D", - "IFTDecayFunction2D", - "IFTDistribution1D", - "IFTDistribution2D", - "IFormFactor", - "IFormFactorBorn", - "IFormFactorDecorator", - "IInterferenceFunction", - "IHistogram", - "Histogram1D", - "Histogram2D", - "IMaterial", - "IntensityDataFunctions", - "IObserver", - "IObservable", - "IParameterized", - "IParticle", - "IResolutionFunction2D", - "IRotation", - "ISample", - "ISampleBuilder", - "ISelectionRule", - "IsGISAXSDetector", - "Instrument", - "InterferenceFunction1DLattice", - "InterferenceFunctionRadialParaCrystal", - "InterferenceFunction2DLattice", - "InterferenceFunction2DParaCrystal", - "InterferenceFunctionNone", - "Lattice", - "Lattice1DParameters", - "Lattice2DParameters", - "Layer", - "LayerInterface", - "LayerRoughness", - "MesoCrystal", - "MultiLayer", - "OffSpecSimulation", - "OutputData<double>", - "IntensityDataIOFactory", - "ParameterDistribution", - "ParameterPool", - "Particle", - "ParticleComposition", - "ParticleDistribution", - "ParticleCoreShell", - "ParticleLayout", - "RealParameterWrapper", - "RectangularDetector", - "ResolutionFunction2DGaussian", - "RotationX", - "RotationY", - "RotationZ", - "RotationEuler", - "SpecularSimulation", - "SphericalDetector", - "Simulation", - "SimulationParameters", - "SimpleSelectionRule", - "ThreadInfo", - "cvector_t", - "kvector_t", - "IShape2D", - "Line", - "VerticalLine", - "HorizontalLine", - "Ellipse", - "Rectangle", - "Polygon", - "WavevectorInfo" -] - - -exclude_patterns = [] - - -# ----------------------------------------------------------------------------- -# AdditionalRules -# ----------------------------------------------------------------------------- -def ManualClassTunings(mb): - #mb.class_("AxisDouble").member_function("clone").exclude() - #mb.class_("AxisDouble").member_functions("createDoubleBinSize").exclude() - - axis_operators = mb.free_operators( lambda decl: 'IAxis' in decl.decl_string ) - axis_operators.include() - - # shared ptrs - shared_ptrs = mb.decls(lambda decl: decl.name.startswith('shared_ptr<' )) - shared_ptrs.disable_warnings(messages.W1040) - - # IDetector2D - cl = mb.class_('IDetector2D') - cl.member_functions("addAxis").exclude() - cl.member_functions("clone").exclude() - - # ISample - cl = mb.class_('ISample') - cl.member_function("accept").include() - cl.member_function("printSampleTree").include() - - # ICompositeSample - cl = mb.class_('ICompositeSample') - for f in cl.member_functions(): - if "shallow" in f.name: - f.exclude() - - # BasicVector3D - methods_to_exclude=[ - "phi", "theta", "cosTheta", "sin2Theta", "getPhi", "getTheta", "setPhi", "setTheta", "setR", - "setMag", "perp", "perp2", "setPerp", "angle", "unit", "orthogonal", "rotated", "rotatedX", - "rotatedY", "rotatedZ", "cross", "dot", "normalize", "complex" - ] - classes_to_exclude = ["BasicVector3D<std::complex<double> >", "BasicVector3D<double>", "BasicVector3D<int>"] - utils_build.ExcludeMemberFunctionsForClasses(mb, methods_to_exclude, classes_to_exclude) - # Pure virtual should always be included - mb.class_("IDetectorResolution").member_function("applyDetectorResolution").include() - # - cl = mb.class_("Lattice") - cl.member_functions().exclude() - cl.member_function("getBasisVectorA").include() - cl.member_function("getBasisVectorB").include() - cl.member_function("getBasisVectorC").include() - cl.member_function("createTrigonalLattice").include() - cl.member_function("createTrigonalLattice").call_policies = call_policies.return_value_policy(call_policies.return_by_value) - cl.member_function("setSelectionRule").include() - # - cl = mb.class_("ParticleComposition") - cl.constructors( lambda decl: bool( decl.arguments ) ).exclude() # exclude non-default constructors - cl.member_functions().exclude() - cl.member_function("addParticles").include() - cl.member_functions("addParticle").include() - # - cl = mb.class_('RealParameterWrapper') - cl.member_functions().exclude() - cl.member_function("setValue").include() - cl.member_function("getValue").include() - cl.member_function("isNull").include() - # - funs = mb.free_functions() - for ff in funs: - if 'SetLevel' in ff.name: - ff.alias = 'SetMessageLevel' - ff.include() - if 'CreateProduct' in ff.name: - ff.include() - # - cl = mb.class_("BasicVector3D<double>") - cl.add_code("def( bp::self - bp::self )") - cl.add_code("def( bp::self + bp::self )") - cl.add_code("def( bp::other< double >() * bp::self )") - cl.add_code("def( bp::self * bp::other< double >() )") - cl.add_code("def( +bp::self )") - cl.add_code("def( -bp::self )") - cl.add_code("def( bp::self / bp::other< double >() )") - cl.add_code("def( bp::self_ns::str( bp::self ) )") - # - cl = mb.class_("InterferenceFunction2DParaCrystal") - cl.member_function("getProbabilityDistributions").exclude() - # - cl = mb.class_("IParameterized") - cl.member_function("registerParameter").include() - cl.member_function("registerParameter").add_transformation( utils_build.from_address_custom( 1 ) ) - # - cl = mb.class_("ISampleBuilder") - #cl = mb.class_("SampleBuilder_t") - cl.member_functions().exclude() - cl.member_function("buildSample").include() - cl.member_function("buildSample").call_policies = call_policies.return_value_policy(call_policies.manage_new_object) - # - cl = mb.class_("IClusteredParticles") - cl.member_function("setAmbientMaterial").include() - # - cl = mb.class_("IDistribution1D") - for fun in cl.member_functions(): - print fun.name - if "generateSamples" in fun.name: - fun.exclude() - # - # cl = mb.class_("IObserver") - # cl.member_function("update").include() - - #cl = mb.class_("MaterialManager") - #cl.constructors().exclude() - # - cl = mb.class_("OutputData<double>") - cl.add_code('def("__setitem__", &pyplusplus_setitem<OutputData<double >,int,double> )') # [] operator for OutputData - cl.member_function("getArray").call_policies = call_policies.custom_call_policies("") - #cl.member_function("getArray").call_policies = call_policies.return_value_policy(call_policies.manage_new_object) - fun = cl.member_functions("getAxis").call_policies = call_policies.return_internal_reference() - - # - cl = mb.class_("Particle") - for cls in cl.constructors(): - if "( ::Particle::* )( ::IMaterial const *,::IFormFactor const & )" in cls.decl_string: - cls.include() - if "( ::Particle::* )( ::IMaterial const *,::IFormFactor const &,::IRotation const & )" in cls.decl_string: - cls.include() - - # - cl = mb.class_("ParticleDistribution") - cl.member_function("generateParticles").exclude() - # - cl = mb.class_("ParticleLayout") - #cl.constructors(lambda decl: bool(decl.arguments)).exclude() # exclude non-default constructors - # - cl = mb.class_("ParameterDistribution") - cl.member_function("generateSamples").exclude() - cl.member_function("getLinkedParameterNames").exclude() - # - cl = mb.class_("ParameterPool") - cl.member_function("registerParameter").add_transformation(utils_build.from_address_custom(1)) - # cl.member_function("getMatchedParameters").exclude() - # cl.member_function("getParameterNames").exclude() - # - mb.namespace("Units").include() - # - cl = mb.class_("Layer") - # including back methods which have been excluded by our pointer policy - for fun in cl.member_functions(): - if fun.name == "setMaterial": - fun.include() - for fun in cl.member_functions(): - if "void ( ::Layer::* )( ::ILayout * )" in fun.decl_string: - fun.exclude() - cl.constructors().include() # including back constructors with pointers - # - cl = mb.class_("Simulation") - cl.member_function("setSampleBuilder").include() - # cl.member_function("getIntensityData").call_policies = \ - # call_policies.return_value_policy(call_policies.manage_new_object) - # - cl = mb.class_("GISASSimulation") - cl.member_function("getOutputData").exclude() - cl.member_function("getIntensityData").call_policies = \ - call_policies.return_value_policy(call_policies.manage_new_object) - cl.member_function("getDetectorIntensity").call_policies = \ - call_policies.return_value_policy(call_policies.manage_new_object) - # - cl = mb.class_("SpecularSimulation") - cl.member_function("setSampleBuilder").include() - # cl.member_function("getEvanescentWaveIntensity").call_policies = \ - # call_policies.return_value_policy(call_policies.manage_new_object) - # - cl = mb.class_("OffSpecSimulation") - cl.member_function("getOutputData").exclude() - cl.member_function("getIntensityData").call_policies = \ - call_policies.return_value_policy(call_policies.manage_new_object) - cl.member_function("getDetectorIntensity").call_policies = \ - call_policies.return_value_policy(call_policies.manage_new_object) - # - cl = mb.class_("ParticleCoreShell") - cl.member_functions().exclude() - # - cl = mb.class_("MesoCrystal") - cl.member_functions().exclude() - # - mb.namespace("MathFunctions").free_function("GenerateNormalRandom").include() - # - mb.namespace("BornAgain").free_function("GetMajorVersionNumber").include() - mb.namespace("BornAgain").free_function("GetMinorVersionNumber").include() - mb.namespace("BornAgain").free_function("GetPatchVersionNumber").include() - mb.namespace("BornAgain").free_function("GetVersionNumber").include() - mb.namespace("BornAgain").free_function("GetName").include() - - cl = mb.class_("IHistogram") - cl.member_function("getArray").call_policies = call_policies.custom_call_policies("") - cl.member_function("getXaxis").call_policies = call_policies.return_internal_reference() - cl.member_function("getYaxis").call_policies = call_policies.return_internal_reference() - cl.member_function("createOutputData").call_policies = call_policies.return_value_policy(call_policies.manage_new_object) - cl.member_function("relativeDifferenceHistogram").call_policies = call_policies.return_value_policy(call_policies.manage_new_object) - - cl = mb.class_("Histogram1D") - cl.member_function("getBinCenters").exclude() - cl.member_function("getBinValues").exclude() - cl.member_function("getBinErrors").exclude() - cl.member_function("getBinCentersNumpy").call_policies = call_policies.custom_call_policies("") - cl.member_function("getBinValuesNumpy").call_policies = call_policies.custom_call_policies("") - cl.member_function("getBinErrorsNumpy").call_policies = call_policies.custom_call_policies("") - cl.member_function("getBinCentersNumpy").alias = "getBinCenters" - cl.member_function("getBinValuesNumpy").alias = "getBinValues" - cl.member_function("getBinErrorsNumpy").alias = "getBinErrors" - - # - cl = mb.class_("Histogram2D") - for fun in cl.member_functions(): - if "projection" in fun.name: - fun.call_policies = call_policies.return_value_policy(call_policies.manage_new_object) - - - cl = mb.class_("IntensityDataIOFactory") - - cl.member_function("readOutputData").call_policies = call_policies.return_value_policy(call_policies.manage_new_object) - # cl.member_function("readHistogram").call_policies = call_policies.return_value_policy(call_policies.manage_new_object) - cl.member_function("readIntensityData").call_policies = call_policies.return_value_policy(call_policies.manage_new_object) - - cl = mb.class_("IDetector2D") - cl.member_function("setDetectorParameters").exclude() - - -# excluding specific member functions -def ManualExcludeMemberFunctions(mb): - # with given name in function name - to_exclude=['Iterator', 'iterator', 'DWBASimulation'] - to_exclude_exact=['inverse', 'transformed', - 'getNearestLatticeVectorCoordinates', - 'getNearestReciprocalLatticeVectorCoordinates', - 'getKVectorContainer', 'begin', 'end' - ] - for f in mb.member_functions(): - for x in to_exclude: - if x in f.name: f.exclude() - for x in to_exclude_exact: - if x == f.name: f.exclude() diff --git a/dev-tools/python-bindings/settings_fit.py b/dev-tools/python-bindings/settings_fit.py deleted file mode 100644 index 972f68a9398ce3784db0f6c86686ce54d4fdbf2f..0000000000000000000000000000000000000000 --- a/dev-tools/python-bindings/settings_fit.py +++ /dev/null @@ -1,167 +0,0 @@ -# BornAgain Fit library -# settings for Python API generation by codegenerator.py - -from pyplusplus.module_builder import call_policies -#from pyplusplus import messages -import utils_build - -license = '''\ -// ************************************************************************** // -// -// BornAgain: simulate and fit scattering at grazing incidence -// -//! @file Automatically generated boost::python code for BornAgain Python bindings -//! @brief Automatically generated boost::python code for BornAgain Python bindings -//! -//! @homepage http://bornagainproject.org -//! @license GNU General Public License v3 or higher (see COPYING) -//! @copyright Forschungszentrum Juelich GmbH 2015 -//! @authors Scientific Computing Group at MLZ Garching -//! @authors C. Durniak, M. Ganeva, G. Pospelov, W. Van Herck, J. Wuttke -// -// ************************************************************************** // -''' - -lib_name = 'libBornAgainFit' - -temp_dir = 'output/PyFit' -install_inc = '../../Fit/PythonAPI/inc' -install_src = '../../Fit/PythonAPI/src' - -master_include = "PythonFitList.h" -cache_filename = "cache_fit.xml" -special_flags = "" - -with_pure_virtual = False -with_Numpy = False -with_converter = False - - -include_dirs = [ - '../../Core/Samples/inc', - '../../Core/Algorithms/inc', - '../../Core/Tools/inc', - '../../Core/Geometry/inc', - '../../Fit/FitKernel/inc', - '../../Fit/PythonAPI/inc', -] - -include_classes = [ - "INamed", - "IObservable", - "IObserver", - "IParameterized", - "FitOptions", - "ChiSquaredModule", - "FitSuite", - "FitObject", - "FitParameter", - "FitSuiteParameters", - "FitSuiteObjects", - "IChiSquaredModule", - "IMinimizer", - "IIntensityNormalizer", - "IIntensityFunction", - "IntensityFunctionLog", - "IntensityFunctionSqrt", - "ISquaredFunction", - "IFitStrategy", - "FitStrategyDefault", - "FitStrategyAdjustParameters", - "FitStrategyFixParameters", - "FitStrategyReleaseParameters", - "FitStrategyAdjustMinimizer", - "MinimizerFactory", - "MinimizerOptions", - "IntensityNormalizer", - "IntensityScaleAndShiftNormalizer", - "SquaredFunctionDefault", - "SquaredFunctionMeanSquaredError", - "SquaredFunctionGaussianError", - "SquaredFunctionSystematicError", - "SquaredFunctionSimError", - "IFitObserver", -] - - -exclude_patterns = [ - # already contained in Core API: - "vdouble1d_t", - "vcomplex1d_t", - "IObservable", - "IObserver", - "IParameterized", - "vector_string_t"] - - -# ----------------------------------------------------------------------------- -# AdditionalRules -# ----------------------------------------------------------------------------- -def ManualClassTunings(mb): - - # IMinimizer - cl = mb.class_("IMinimizer") - cl.member_function("setChiSquaredFunction").exclude() - cl.member_function("setGradientFunction").exclude() - for fun in cl.member_functions(): - if "getOptions" in fun.name: - if "::MinimizerOptions const & ( ::IMinimizer::* )( ) const" in fun.decl_string: - fun.exclude() - else: - fun.call_policies = call_policies.return_internal_reference() - - utils_build.InjectGetStringCustomCode(cl, "getAlgorithmName") - utils_build.InjectGetStringCustomCode(cl, "getMinimizerName") - - # - cl = mb.class_("FitSuite") - cl.member_function( "getOptions" ).exclude() - cl.member_function( "setOptions" ).exclude() - cl.member_function( "getMinimizer" ).call_policies= call_policies.return_internal_reference() # which one is correct ? - cl.member_function("getRealData").call_policies = call_policies.return_value_policy(call_policies.manage_new_object) - cl.member_function("getSimulationData").call_policies = call_policies.return_value_policy(call_policies.manage_new_object) - cl.member_function("getChiSquaredMap").call_policies = call_policies.return_value_policy(call_policies.manage_new_object) - - cl.member_function( "getFitObjects" ).call_policies = call_policies.return_internal_reference() - cl.member_function( "getFitParameters" ).call_policies = call_policies.return_internal_reference() - cl.member_function( "getFitStrategies" ).call_policies = call_policies.return_internal_reference() - - cl = mb.class_("MinimizerFactory") - for fun in cl.member_functions(): - if "createMinimizer" in fun.name: - fun.call_policies = call_policies.return_value_policy( call_policies.reference_existing_object ) - - cl = mb.class_("FitStrategyAdjustMinimizer") - cl.member_function( "getMinimizer" ).call_policies = call_policies.return_internal_reference() - cl.member_function( "getMinimizerOptions" ).call_policies = call_policies.return_internal_reference() - - cl = mb.class_("MinimizerOptions") # alternatively transformation can be used - for fun in cl.member_functions(): - if "getValue" in fun.name: - fun.exclude() - - cl = mb.class_("IFitObserver") - cl.member_function("update").include() - - cl = mb.class_("FitSuiteParameters") - for fun in cl.member_functions(): - if "__gnu_cxx::__normal_iterator" in fun.decl_string: - fun.exclude() - - cl = mb.class_("FitSuiteObjects") - cl.member_function("getChiSquaredMap").call_policies = \ - call_policies.return_value_policy(call_policies.manage_new_object) - - cl = mb.class_("ChiSquaredModule") - cl.member_function("processFitElements").exclude() - cl = mb.class_("IChiSquaredModule") - cl.member_function("processFitElements").exclude() - - cl = mb.class_("FitObject") - cl.member_function("prepareFitElements").exclude() - cl.member_function("getChiSquaredMap").exclude() - - -# excluding specific member functions -def ManualExcludeMemberFunctions(mb): - pass diff --git a/dev-tools/python-bindings/test_docstring.py b/dev-tools/python-bindings/test_docstring.py deleted file mode 100644 index 02c8341899e5f142db72c27746ef4f3074b3e8a3..0000000000000000000000000000000000000000 --- a/dev-tools/python-bindings/test_docstring.py +++ /dev/null @@ -1,157 +0,0 @@ - - - -class DocObject: - """ - The DocObject class holds continuous block of raw C++/Doxygen documentation strings related to some declaration. - This information is taken from BornAgain source file and later used to generate meaningful Python docstring. - - :Example: - For the constructor of FormFactorCone, member self.doc_lines will contain following lines. - "//! @brief Cone constructor" - "//! @param radius of Cone's base" - "//! @param height of Cone" - "//! @param angle in radians between base and facet" - while self.start_line, self.end_line will contain line numbers (starting from 0) of this block in the source file. - """ - def __init__(self): - self.start_line = 0 - self.end_line = 0 - self.doc_lines = [] - self.decl_string = "" - - def __len__(self): - return len(self.doc_lines) - - def addLine(self, line, line_number): - line = line.replace("//!", "").strip() - self.doc_lines.append(line) - if not self.start_line: - self.start_line = line_number - self.end_line = line_number - - def setDeclString(self, text): - """ - Sets declaration string. This is done from master class using information provided by pygccxml machinery. - Given string will be used later on to find out types of variables during python docstring generation - """ - self.decl_string = text - - def getBriefDescription(self): - """ - Parse @brief description from a multi line doxygen block - """ - brief = "" - for line in self.doc_lines: - brief += line - if brief[len(brief)-1] != ' ': - brief += ' ' - - if "@brief" in brief: - brief = brief.split("@brief")[1].strip() - - pos = brief.find('.') - if pos < 0: - pos = brief.find('@') - brief = brief[:pos].strip()+"." - - else: - if len(self.doc_lines) == 1: - brief = self.doc_lines[0] - if not brief[len(brief)-1] == ".": - brief += "." - - return brief - - def getParamList(self): - result = [] - for line in self.doc_lines: - if "@param" in line: - result.append(line.replace("@param", "").strip()) - return result - - def getPythonDocString(self): - """ - Constructs and returns Python doc string basing on gathered Doxygen comments. - - :Example: - For Cone constructor from example above it will be the following text: - - "Cone constructor\n" - "\n" - ":Parameters:\n" - " - radius (float) - of Cone's base\n" - " - height (float) - of Cone's base\n" - " - angle (float) - in radians between base and facet\n" - """ - brief = self.getBriefDescription() - - params = self.getParamList() - eol = "\n" - - result = "" - if len(brief): - result += brief - if len(params): - result += eol + eol - result += ":Parameters:" + eol - for p in params: - param_name = p.split()[0] - param_description = p[len(param_name):].strip() - result += " - \'" + param_name + "\' - " + param_description + eol - return result - - -class DoxygenDocExtractor: - """ - Extracts Doxygen styled documentation from source. As a result of extraction list of DocObjects will be created. - """ - - def __init__(self): - self.file_name = None - self.source = None - self.doc_list = [] - - def parse_file(self, filename): - self.file_name = filename - self.source = open(filename).readlines() - - docObject = DocObject() - for i_line in range(0, len(self.source)): - line = self.source[i_line] - if self.is_doxygen_comment(line): - docObject.addLine(line, i_line) - else: - if len(docObject): - self.doc_list.append(docObject) - docObject = DocObject() - - - def getDocObject(self, line_number): - """ - Returns DocObject which is located above given line number and the distance between given line number - and doc block is not larger than 1 line. - """ - for doc in self.doc_list: - diff = line_number - doc.end_line - print "line_number:", line_number, "doc_end_line", doc.end_line, diff - if diff >=0 and diff <= 2: - return doc - return None - - def is_doxygen_comment(self, text): - return text.lstrip()[:3] == "//!" - -if __name__ == '__main__': - - #filename = "/home/pospelov/development/BornAgain/source/Core/Tools/inc/CustomBinAxis.h" - # filename = "/home/pospelov/development/BornAgain/source/Core/FormFactors/inc/FormFactorCone.h" - - filename = "/home/pospelov/development/BornAgain/source/Core/Samples/inc/ParticleLayout.h" - - extractor = DoxygenDocExtractor() - extractor.parse_file(filename) - - print "---" - print extractor.getDocObject(27).getPythonDocString() - print "---" diff --git a/dev-tools/python-bindings/utils_build.py b/dev-tools/python-bindings/utils_build.py deleted file mode 100644 index dbd1b28346a85113187e7aa95c244efc4f3ad094..0000000000000000000000000000000000000000 --- a/dev-tools/python-bindings/utils_build.py +++ /dev/null @@ -1,326 +0,0 @@ -# common rules and utilities for boost python code generation - -import os -import sys -import subprocess -import platform - -from pygccxml import declarations -from pygccxml import parser - -from pyplusplus import module_builder -from pyplusplus.module_builder import call_policies -from pyplusplus import messages -from pyplusplus.function_transformers import transformers -from pyplusplus.file_writers.balanced_files import balanced_files_t -from pyplusplus.file_writers.multiple_files import multiple_files_t - -import utils_docstring - -balanced_files_t.HEADER_EXT = '.h' -balanced_files_t.SOURCE_EXT = '.cpp' -multiple_files_t.HEADER_EXT = '.pypp.h' -multiple_files_t.SOURCE_EXT = '.pypp.cpp' - - -incref_code = \ -""" -if( !this->m_pyobj) { - this->m_pyobj = boost::python::detail::wrapper_base_::get_owner(*this); - Py_INCREF(this->m_pyobj); -} -""" - - -extractor = utils_docstring.DoxygenDocExtractor() - -def my_doc_extractor( decl ): - # print "========================" - # print decl.name - # print decl.location.file_name + str(decl.location.line) - # print "-----------" - # print extractor(decl) - # print "-----------" - return extractor(decl) - -def ExcludeConstructorsArgPtr(mb): - '''Excludes constructors which have pointers in argument list.''' - for cl in mb.classes(): - for ctor in cl.constructors(allow_empty=True): - for arg in ctor.arguments: - if declarations.type_traits.is_pointer(arg.type): - ctor.exclude() - - -def ExcludeMemberFunctionsArgPtr(mb): - '''Excludes member functions if they have pointers in argument list.''' - for cl in mb.classes(): - for fun in cl.member_functions(allow_empty=True): - if any( declarations.type_traits.is_pointer(arg.type) - for arg in fun.arguments ): - fun.exclude(); - - -def IncludePureVirtualMethods(mb, include_classes): - '''Includes pure virtual methods.''' - for cl in mb.classes(): - if not any( name == cl.name or name == cl.alias - for name in include_classes ): - continue - query = declarations.virtuality_type_matcher_t( - declarations.VIRTUALITY_TYPES.PURE_VIRTUAL ) - fun = cl.member_functions( query, allow_empty=True ) - for f in fun: - f.include() - - -def IncludeClasses(mb, include_classes): - '''Includes list of defined classes.''' - # check if classes defined in list are presented in module builder - not_found_classes=[] - for name in include_classes: - if not any( name == cl.name or name == cl.alias - for cl in mb.classes() ): - not_found_classes.append(name) - if len(not_found_classes): - print( "Error! Can't find classes with requested names {0}".format(not_found_classes) ) - exit() - mb.classes( lambda cls: cls.name in include_classes ).include() - - -def ExcludeMemberFunctionsForClasses(mb, method_names, class_names): - '''If class name in 'class_names' then exclude 'method_names'.''' - for cl in mb.classes(): - if any( name in cl.decl_string for name in class_names ): - for fun in cl.member_functions(allow_empty=True): - if any( fun.name == name for name in method_names ): - fun.exclude() - - -def DefineGeneralRules(mb): - '''General rules.''' - mb.classes().always_expose_using_scope = True - #mb.always_expose_using_scope = True - # Generated code containing errors will not compile on - mem_funs = mb.calldefs () - mem_funs.create_with_signature = True - # Exclude protected and private that are not pure virtual - # (we still have to expose pure virtual functions to have them - # overriden in the wrapper) - query = declarations.access_type_matcher_t( 'private' ) & \ - ~declarations.virtuality_type_matcher_t( - declarations.VIRTUALITY_TYPES.PURE_VIRTUAL ) - mb.global_ns.calldefs( query, allow_empty=True ).exclude() - query = declarations.access_type_matcher_t( 'protected' ) & \ - ~declarations.virtuality_type_matcher_t( - declarations.VIRTUALITY_TYPES.PURE_VIRTUAL ) - mb.global_ns.calldefs( query, allow_empty=True ).exclude() - # excluding generation of methods for implicit conversion - mb.constructors().allow_implicit_conversion = False - - -def ManageNewReturnPolicy(mb): - '''Returns policy for singletons, clone and create methods.''' - for cl in mb.classes(): - cl.member_functions('instance', - allow_empty=True).call_policies = \ - call_policies.return_value_policy( call_policies.reference_existing_object ) - cl.member_functions('clone', - allow_empty=True).call_policies = \ - call_policies.return_value_policy( call_policies.manage_new_object ) - cl.member_functions( lambda x: x.name.startswith('create'), - allow_empty=True ).call_policies = \ - call_policies.return_value_policy( call_policies.manage_new_object ) - - -def ManageTransferOwnership(mb): - '''Increases reference count during transfer of ownership.''' - for clone_fun in mb.member_functions('clone'): - cl = clone_fun.parent - cl.add_wrapper_code('PyObject* m_pyobj;') - cl.set_constructors_body('m_pyobj = 0;') - cl.member_functions('transferToCPP', allow_empty=True).add_override_precall_code(incref_code) - cl.member_functions('transferToCPP', allow_empty=True).add_default_precall_code(incref_code) - cl.held_type = 'std::auto_ptr< %s >' % cl.wrapper_alias - - -def DefaultReturnPolicy(mb): - '''Sets the default return policies (for references/pointers) on classes - if it wasn't already been done for. Should be called last.''' - mem_funs = mb.calldefs() - for mem_fun in mem_funs: - if mem_fun.call_policies: - continue - if ( not mem_fun.call_policies and - (declarations.is_reference(mem_fun.return_type) or - declarations.is_pointer(mem_fun.return_type) ) ): - mem_fun.call_policies = call_policies.return_value_policy( call_policies.reference_existing_object ) - - -def InjectGetStringCustomCode(cls, method_name): - '''Injects custom wrapper for getString to deal with Windows and MSVC2012''' - cls.member_function(method_name).exclude() - wrapper_code = ''' - virtual ::std::string {1}( ) const {{ - if( bp::override func_{1} = this->get_override( \"{1}\" ) ) - return boost::python::call<std::string>(func_{1}( )); - else{{ - return this->{0}::{1}( ); - }} - }} - - ::std::string default_{1}( ) const {{ - return {0}::{1}( ); - }} - ''' - wrapper_code = wrapper_code.format(cls.name, method_name) - cls.add_wrapper_code(wrapper_code) - registration_code = """ - def( - \"{1}\" - , (::std::string ( ::{0}::*)( ) const)(&::{0}::{1}) - , (::std::string ( {0}_wrapper::*)( ) const)(&{0}_wrapper::default_{1}) ) - """ - registration_code = registration_code.format(cls.name, method_name) - cls.add_code(registration_code) - - - - -class from_address_custom_t(transformers.type_modifier_t): - - '''This is a patched version of pyplusplus.function_transformers classes to -pass address of ctype(double) into C++. The pointer is passed now in the form -of long unsigned, which correspond to 64 bit (before it was unsigned int)''' - - def __init__(self, function, arg_ref): - modifier = lambda type_: declarations.FUNDAMENTAL_TYPES[ - 'long unsigned int' ] - transformers.type_modifier_t.__init__( - self, function, arg_ref, modifier ) - if not transformers.is_ptr_or_array( self.arg.type ): - raise ValueError( '%s\nin order to use "from_address_t" transformation, argument %s type must be a pointer or a array (got %s).' % - ( function, self.arg_ref.name, self.arg.type) ) - - def __str__(self): - return "from_address(%s)"%(self.arg.name) - - -def from_address_custom( *args, **keywd ): - '''Returns creator function.''' - def creator( function ): - return from_address_custom_t( function, *args, **keywd ) - return creator - - -def get_python_path(): - '''Returns Python include directory.''' - return sys.prefix +"/include/python"+ sys.version[:3] - - -def get_gcc_path(): - '''Returns g++ include directory.''' - proc = subprocess.Popen(["which g++"], stdout=subprocess.PIPE, shell=True) - (out, err) = proc.communicate() - path = out.strip() - if not path.endswith("bin/g++"): - exit("Can't find g++") - return path[:-7]+"include" - - -def get_gccxml_path(): - '''Returns gccxml path.''' - proc = subprocess.Popen(["which gccxml"], stdout=subprocess.PIPE, shell=True) - (out, err) = proc.communicate() - path = out.strip() - if not path.endswith("/gccxml"): - exit("No gccxml!") - return path[:-7] - - -def MakePythonAPI(prj): - '''Produces boost-python code.''' - - if not os.path.exists(prj.temp_dir): - os.makedirs(prj.temp_dir) - - print( "Generating PythonAPI from %s." % ( prj.master_include ) ) - - #If the cache file cache_core.xml doesn't exist it gets created, otherwise it just gets loaded - print("NOTE: If you update the source library code, run 'codegenerator.py clean'") - - xml_cached_fc = parser.create_cached_source_fc( prj.master_include, prj.cache_filename) - arch_flag = "" - arch = platform.architecture()[0] - if arch == '64bit': - arch_flag = "-m64 " - elif arch == '32bit': - pass - else: - exit( "Unknown architecture" ) - - mb = module_builder.module_builder_t( - [xml_cached_fc], - include_paths = prj.include_dirs + [get_python_path(), get_gcc_path()], - gccxml_path = get_gccxml_path(), - cflags = arch_flag + "-DGCCXML_SKIP_THIS " + prj.special_flags) - - # general rules - - IncludeClasses(mb, prj.include_classes) - - DefineGeneralRules(mb) - - ExcludeConstructorsArgPtr(mb) - - ExcludeMemberFunctionsArgPtr(mb) - - ManageNewReturnPolicy(mb) - - ManageTransferOwnership(mb) - - # execute project-specific rules - - prj.ManualExcludeMemberFunctions(mb) - - prj.ManualClassTunings(mb) - - # default policies for what remained unchanged - - if prj.with_pure_virtual: - IncludePureVirtualMethods(mb, prj.include_classes) - - DefaultReturnPolicy(mb) - - # disable some warnings - - messages.disable( - messages.W1020, # Warnings 1020 - 1031 are all about why Py++ generates wrapper for class X - messages.W1021, - messages.W1022, - messages.W1023, - messages.W1024, - messages.W1025, - messages.W1026, - messages.W1027, - messages.W1028, - messages.W1029, - messages.W1030, - messages.W1031, - #messages.W1035, - #messages.W1040, - #messages.W1038, - #messages.W1041, - messages.W1036, # pointer to Python immutable member - #messages.W1033, # unnamed variables - #messages.W1018, # expose unnamed classes - #messages.W1049, # returns reference to local variable - #messages.W1014, # unsupported '=' operator - ) - - # generate output - mb.build_code_creator( module_name="PythonInterface", doc_extractor=my_doc_extractor) - mb.code_creator.license = prj.license - - mb.code_creator.user_defined_directories.append(os.path.abspath('./')) - mb.split_module(prj.temp_dir) diff --git a/dev-tools/python-bindings/utils_docstring.py b/dev-tools/python-bindings/utils_docstring.py deleted file mode 100644 index 291f5c75d2bb821d6b4212ddfc9d525fcf038090..0000000000000000000000000000000000000000 --- a/dev-tools/python-bindings/utils_docstring.py +++ /dev/null @@ -1,164 +0,0 @@ -""" -Collection of classes to parse Doxygen C++ comments from cpp file and generate from them nicely looking docstring. -""" - -class DocObject: - """ - The DocObject class holds continuous block of raw C++/Doxygen documentation strings related to some declaration. - This information is taken from BornAgain source file and later used to generate meaningful Python docstring. - - :Example: - For the constructor of FormFactorCone, member self.doc_lines will contain following lines. - "//! @brief Cone constructor" - "//! @param radius of Cone's base" - "//! @param height of Cone" - "//! @param angle in radians between base and facet" - while self.start_line, self.end_line will contain line numbers (starting from 0) of this block in the source file. - """ - def __init__(self): - self.start_line = 0 - self.end_line = 0 - self.doc_lines = [] - self.decl_string = "" - - def __len__(self): - return len(self.doc_lines) - - def addLine(self, line, line_number): - line = line.replace("//!", "").strip() - self.doc_lines.append(line) - if not self.start_line: - self.start_line = line_number - self.end_line = line_number - - def setDeclString(self, text): - """ - Sets declaration string. This is done from master class using information provided by pygccxml machinery. - Given string will be used later on to find out types of variables during python docstring generation. - Currently not used. - """ - self.decl_string = text - - def getBriefDescription(self): - """ - Parse @brief description from a multi line doxygen block - """ - brief = "" - for line in self.doc_lines: - brief += line - if brief[len(brief)-1] != ' ': - brief += ' ' - - if "@brief" in brief: - brief = brief.split("@brief")[1].strip() - - pos = brief.find('.') - if pos < 0: - pos = brief.find('@') - brief = brief[:pos].strip()+"." - - else: - if len(self.doc_lines) == 1: - brief = self.doc_lines[0] - if not brief[len(brief)-1] == ".": - brief += "." - - return brief - - def getParamList(self): - result = [] - for line in self.doc_lines: - if "@param" in line: - result.append(line.replace("@param", "").strip()) - return result - - def getPythonDocString(self): - """ - Constructs and returns Python doc string basing on gathered Doxygen comments. - - :Example: - For Cone constructor from example above it will be the following text: - - "Cone constructor\n" - "\n" - ":Parameters:\n" - " - radius - of Cone's base\n" - " - height - of Cone's base\n" - " - angle - in radians between base and facet\n" - - :TODO: - Make parameter line show type of variable. It can be parsed from the declaration string. - " - radius (float) - of Cone's base\n" - - """ - brief = self.getBriefDescription() - params = self.getParamList() - eol = "\\n" - - result = "" - if len(brief): - result += brief - if len(params): - result += eol + eol - result += ":Parameters:" + eol - for p in params: - param_name = p.split()[0] - param_description = p[len(param_name):].strip() - result += " - \'" + param_name + "\' - " + param_description + eol - return "\""+result+"\"" - - - -class DoxygenDocExtractor: - """ - Extracts Doxygen styled documentation from source or generates it from description. - """ - def __init__(self): - #for caching source - self.file_name = None - self.source = None - self.doc_list = [] - - def parse_file(self, filename): - self.file_name = filename - self.source = open(filename).readlines() - - docObject = DocObject() - for i_line in range(0, len(self.source)): - line = self.source[i_line] - if self.is_doxygen_comment(line): - docObject.addLine(line, i_line) - else: - if len(docObject): - self.doc_list.append(docObject) - docObject = DocObject() - - def getDocObject(self, line_number): - """ - Returns DocObject which is located above given line number and the distance between given line number - and doc block is not larger than 1 line. - """ - for doc in self.doc_list: - diff = line_number - doc.end_line - #print "line_number:", line_number, "doc_end_line", doc.end_line, diff - # We count lines starting from 0, pygccxml counts starting from 1. Where can be one empty line between - # Doxygen comment and declaration. Also pygccxml seems to rely on position of bracket "{" in class declaration. - # So to assign comment block to given declaration, we have to have the difference in line numbering - # between 2 and 4. - if diff >=2 and diff <= 4: - return doc - return None - - def is_doxygen_comment(self, text): - return text.lstrip()[:3] == "//!" - - def __call__(self, declaration): - if self.file_name != declaration.location.file_name: - self.doc_list = [] - self.file_name = declaration.location.file_name - self.parse_file(self.file_name) - - doc = self.getDocObject(declaration.location.line) - - if not doc == None: - return doc.getPythonDocString() diff --git a/dev-tools/python-bindings/utils_install.py b/dev-tools/python-bindings/utils_install.py deleted file mode 100644 index dd28a318021273b8634e8078fc6e38f18ea8b709..0000000000000000000000000000000000000000 --- a/dev-tools/python-bindings/utils_install.py +++ /dev/null @@ -1,189 +0,0 @@ -# common rules and utilities for PythonAPI installatin - -import os, glob, re, shutil, subprocess - -def FilesAreDifferent(file1, file2): - '''Returns True if files are different or absent.''' - - if not os.path.exists(file1) or not os.path.exists(file2): - return True - proc = subprocess.Popen(["diff "+file1+" "+file2], stdout=subprocess.PIPE, shell=True) - (out, err) = proc.communicate() - if len(out) or err!=None: - return True - return False - - -def PatchFiles(files): - '''Patches generated files to get rid from boost compilation warnings.''' - - n_patched_files = 0 - for ff in files: - - with open(ff, 'r') as fh: - txt = fh.read() - - if '#include "Macros.h"' in txt: - continue # file was already patched - - has_boost_suite_hpp = "vector_indexing_suite.hpp" in txt - if not ( has_boost_suite_hpp or "boost/python.hpp" in txt ): - continue - - # patch is required - with open(ff,"r") as fin: - with open("tmp.tmp","w") as fout: - for line in fin: - if "boost/python.hpp" in line: - - fout.write('''\ -#include "Macros.h" -GCC_DIAG_OFF(unused-parameter) -GCC_DIAG_OFF(missing-field-initializers) -#include "boost/python.hpp" -''') - - if has_boost_suite_hpp: - fout.write('''\ -#include "boost/python/suite/indexing/vector_indexing_suite.hpp" -''') - - fout.write('''\ -GCC_DIAG_ON(unused-parameter) -GCC_DIAG_ON(missing-field-initializers) -''') - elif "vector_indexing_suite.hpp" in line: - continue - else: - fout.write(line) - shutil.move("tmp.tmp", ff) - n_patched_files += 1 - print("PatchFiles() : %i files have been patched to get rid from compilation warnings" % - (n_patched_files)) - - -def CopyFiles(prj, files): - '''Copies modified files to the project directory.''' - - n_copied_files = 0 - for f in files: - fileName = os.path.basename(f) - - # different output directory for source and headers - outputName='' - if re.search( r'\.c(pp)?$', fileName ): - outputName = prj.install_src + "/" + fileName - elif re.search( r'\.h(pp)?$', fileName ): - outputName = prj.install_inc + "/" + fileName - - if FilesAreDifferent(outputName,f): - shutil.copy( f, outputName ) - n_copied_files += 1 - - print( "CopyFiles() : %i files out of %i have been replaced." % ( n_copied_files, len(files) ) ) - - -def ClearPythonAPI(prj, files): - '''Clears API from files that remain from previous installation.''' - - old_files = glob.glob(prj.install_inc + "/*.pypp.h") + \ - glob.glob(prj.install_inc + "/*.pypp.hpp") + \ - glob.glob(prj.install_src + "/*.pypp.c") + \ - glob.glob(prj.install_src + "/*.pypp.cpp") - list_to_erase = [] - for oldf in old_files: - if not any( os.path.basename(newf)==os.path.basename(oldf) for newf in files ): - list_to_erase.append(oldf) - print("ClearPythonAPI() : erasing obsolete files in source tree: %s " % (list_to_erase)) - for x in list_to_erase: - os.system("rm "+x) - - -def GenerateModuleFile(prj, files_inc, files_src, file_mod): - '''Generates Python module main cpp file.''' - - fout = open(file_mod, 'w') - fout.write('#include "Python.h"\n') - fout.write('#include "boost/python.hpp"\n') - - if prj.with_Numpy: - fout.write(''' -// Numpy (the order of the following three lines is important): -#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION -#define PY_ARRAY_UNIQUE_SYMBOL BORNAGAIN_PYTHONAPI_ARRAY -#include "numpy/arrayobject.h" -''') - - for ff in files_inc: - ff = ff.replace(prj.temp_dir+"/", "") - fout.write('#include "%s"\n' % (ff) ) - fout.write('\n') - - if prj.with_converter: - fout.write('#include "PythonListConverter.h"\n\n') - - fout.write('BOOST_PYTHON_MODULE(%s){\n' % (prj.lib_name) ) - - fout.write(' boost::python::docstring_options doc_options(true, true, false);\n\n') - - # copying register lines from automaticaly generated module file to our manually generated - old_python_module_file = prj.temp_dir+"/PythonInterface.main.cpp" - fin = open(old_python_module_file,'r') - for line in fin: - if any( pattern in line for pattern in prj.exclude_patterns ): - continue - if "register_" in line: - fout.write(line) - fin.close() - - if prj.with_converter: - fout.write("\n") - fout.write(" register_python2cpp_converters();\n\n") - - if prj.with_Numpy: - fout.write('''\ - import_array(); - /* IMPORTANT - this is initialisation function from C-API of python-numpy package. It has to be called once in the - initialisation section of the module (i.e. here), when module is going to use any of python numpy C-API. - Additional rule: when initialisation of the module, and functions that use python-numpy C-API are located in - different files (different compilation units) - and this is exactly our case - additional defines has - to be inserted before #include "numpy/arrayobject.h". See explanations - http://docs.scipy.org/doc/numpy/reference/c-api.array.html#import_array - */ -''') - - fout.write("}\n") - fout.close() - - -def InstallCode(prj ): - '''Installs the code.''' - - print( "Installing generated Python API." ) - - for pattern in prj.exclude_patterns: - files2remove = glob.glob(prj.temp_dir+"/"+pattern+".*") - print("...removing duplicated files %s" % " ".join(files2remove) ) - for ff in files2remove: - os.remove(ff) - - files_inc = glob.glob(prj.temp_dir+"/*.pypp.h") + \ - glob.glob(prj.temp_dir+"/*.pypp.hpp") + \ - glob.glob(prj.temp_dir+"/__call_policies.pypp.hpp") +\ - glob.glob(prj.temp_dir+"/__convenience.pypp.hpp") - files_src = glob.glob(prj.temp_dir+"/*.pypp.c") + \ - glob.glob(prj.temp_dir+"/*.pypp.cpp") - file_mod = prj.temp_dir+"/PythonModule.cpp" - - GenerateModuleFile(prj, files_inc, files_src, file_mod) - - files = files_inc + files_src + [file_mod] - - PatchFiles(files) - - CopyFiles(prj, files) - - ClearPythonAPI(prj, files) - - print("Done")