Make the Builtin class available from Python

This commit is contained in:
Joakim Hove
2021-03-04 19:12:47 +01:00
parent f584901da4
commit 84d5dbde0e
12 changed files with 101 additions and 13 deletions

View File

@@ -119,6 +119,9 @@ macro (sources_hook)
foreach (name A B C D E F G H I J K L M N O P Q R S T U V W X Y Z)
list(INSERT opm-common_SOURCES 0 ${PROJECT_BINARY_DIR}/ParserKeywords/${name}.cpp)
endforeach()
if (OPM_ENABLE_PYTHON)
list(INSERT opm-common_SOURCES 0 ${PROJECT_BINARY_DIR}/python/cxx/builtin_pybind11.cpp)
endif()
endif()
set_source_files_properties(src/opm/parser/eclipse/Python/Python.cpp
PROPERTIES COMPILE_FLAGS -Wno-shadow)
@@ -377,11 +380,10 @@ if (OPM_ENABLE_PYTHON)
# -------------------------------------------------------------------------
# 2: Embed the Python interpreter for keywords like PYACTION and PYINPUT
add_subdirectory(python/pybind11)
target_include_directories(opmcommon SYSTEM PRIVATE "python/pybind11/include;${PYTHON_INCLUDE_DIRS}")
if (OPM_ENABLE_EMBEDDED_PYTHON)
add_subdirectory(python/pybind11)
target_include_directories(opmcommon SYSTEM PRIVATE "python/pybind11/include;${PYTHON_INCLUDE_DIRS}")
target_link_libraries(opmcommon PUBLIC ${PYTHON_LIBRARY})
add_definitions(-DEMBEDDED_PYTHON)
endif()
endif()

View File

@@ -6,6 +6,12 @@ execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different
${BASE_DIR}/tmp_gen/TestKeywords.cpp
${BASE_DIR}/TestKeywords.cpp)
if (EXISTS ${BASE_DIR}/python/cxx)
execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different
${BASE_DIR}/tmp_gen/builtin_pybind11.cpp
${BASE_DIR}/python/cxx/builtin_pybind11.cpp)
endif()
execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different
${BASE_DIR}/tmp_gen/include/opm/parser/eclipse/Parser/ParserKeywords/Builtin.hpp
${BASE_DIR}/include/opm/parser/eclipse/Parser/ParserKeywords/Builtin.hpp)

View File

@@ -41,6 +41,15 @@ configure_file(src/opm/parser/eclipse/keyword_list.argv.in keyword_list.argv)
# Generate keyword source
set( genkw_argv keyword_list.argv
${PROJECT_BINARY_DIR}/tmp_gen/ParserKeywords
${PROJECT_BINARY_DIR}/tmp_gen/ParserInit.cpp
${PROJECT_BINARY_DIR}/tmp_gen/include/
opm/parser/eclipse/Parser/ParserKeywords
${PROJECT_BINARY_DIR}/tmp_gen/TestKeywords.cpp
${PROJECT_BINARY_DIR}/tmp_gen/builtin_pybind11.cpp)
add_custom_command( OUTPUT
${PROJECT_BINARY_DIR}/tmp_gen/ParserKeywords/A.cpp
${PROJECT_BINARY_DIR}/tmp_gen/ParserKeywords/B.cpp
@@ -68,14 +77,10 @@ add_custom_command( OUTPUT
${PROJECT_BINARY_DIR}/tmp_gen/ParserKeywords/X.cpp
${PROJECT_BINARY_DIR}/tmp_gen/ParserKeywords/Y.cpp
${PROJECT_BINARY_DIR}/tmp_gen/ParserKeywords/Z.cpp
${PROJECT_BINARY_DIR}/tmp_gen/builtin_pybind11.cpp
${PROJECT_BINARY_DIR}/tmp_gen/TestKeywords.cpp
COMMAND genkw keyword_list.argv
${PROJECT_BINARY_DIR}/tmp_gen/ParserKeywords
${PROJECT_BINARY_DIR}/tmp_gen/ParserInit.cpp
${PROJECT_BINARY_DIR}/tmp_gen/include/
opm/parser/eclipse/Parser/ParserKeywords
${PROJECT_BINARY_DIR}/tmp_gen/TestKeywords.cpp
DEPENDS genkw ${keyword_files} src/opm/parser/eclipse/share/keywords/keyword_list.cmake
COMMAND genkw ${genkw_argv}
DEPENDS genkw ${keyword_files} src/opm/parser/eclipse/share/keywords/keyword_list.cmake
)
# To avoid some rebuilds
@@ -108,6 +113,7 @@ add_custom_command(OUTPUT
${PROJECT_BINARY_DIR}/ParserKeywords/Z.cpp
${PROJECT_BINARY_DIR}/TestKeywords.cpp
${PROJECT_BINARY_DIR}/ParserInit.cpp
${PROJECT_BINARY_DIR}/python/cxx/builtin_pybind11.cpp
DEPENDS ${PROJECT_BINARY_DIR}/tmp_gen/ParserKeywords/A.cpp
COMMAND ${CMAKE_COMMAND} -DBASE_DIR=${PROJECT_BINARY_DIR}
-P ${PROJECT_SOURCE_DIR}/CopyHeaders.cmake)

View File

@@ -41,6 +41,7 @@ namespace Opm {
void updateBuiltInHeader(const KeywordLoader& loader, const std::string& headerBuildPath, const std::string& headerPath) const;
void updateInitSource(const KeywordLoader& loader, const std::string& sourceFile ) const;
void updateKeywordSource(const KeywordLoader& loader, const std::string& sourceFile ) const;
void updatePybindSource(const KeywordLoader& loader , const std::string& sourceFile ) const;
void updateHeader(const KeywordLoader& loader, const std::string& headerBuildPath, const std::string& headerPath) const;
void updateTest(const KeywordLoader& loader , const std::string& testFile) const;
private:

View File

@@ -20,6 +20,7 @@ void python::common::export_all(py::module& module) {
export_Log(module);
export_IO(module);
export_SummaryState(module);
export_ParserKeywords(module);
}

View File

@@ -31,6 +31,10 @@ void export_Well(py::module& module);
void export_Log(py::module& module);
void export_IO(py::module& module);
void export_SummaryState(py::module& module);
// The export_ParserKeywords() function is implemented in the source file
// ${BUILD}/builtin_pybind11.cpp which is generated by the build system.
void export_ParserKeywords(py::module& module);
}
#endif //SUNBEAM_HPP

View File

@@ -4,6 +4,7 @@
#include <opm/json/JsonObject.hpp>
#include <opm/parser/eclipse/Parser/Parser.hpp>
#include <opm/parser/eclipse/Parser/ParserKeyword.hpp>
#include <opm/parser/eclipse/Parser/ParserKeywords/Builtin.hpp>
#include <opm/parser/eclipse/Deck/Deck.hpp>
#include <pybind11/stl.h>
#include <opm/parser/eclipse/Parser/ErrorGuard.hpp>
@@ -51,11 +52,12 @@ void python::common::export_Parser(py::module& module) {
py::class_<Parser>(module, "Parser")
.def(py::init<>())
.def(py::init<bool>(), py::arg("add_default") = true)
.def("parse", py::overload_cast<const std::string&>(&Parser::parseFile, py::const_))
.def("parse" , py::overload_cast<const std::string&, const ParseContext&>(&Parser::parseFile, py::const_))
.def("parse_string", py::overload_cast<const std::string&>(&Parser::parseString, py::const_))
.def("parse_string", py::overload_cast<const std::string&, const ParseContext&>(&Parser::parseString, py::const_))
.def("add_keyword", py::overload_cast<ParserKeyword>(&Parser::addParserKeyword))
.def("add_keyword", add_keyword)
.def("__getitem__", &Parser::getKeyword, ref_internal);

View File

@@ -11,7 +11,7 @@
from __future__ import absolute_import
from .libopmcommon_python import action
from .libopmcommon_python import Parser, ParseContext
from .libopmcommon_python import Parser, ParseContext, Builtin
from .libopmcommon_python import DeckKeyword
from .libopmcommon_python import DeckItem

View File

@@ -1,3 +1,4 @@
from opm._common import action
from opm._common import Parser
from opm._common import ParseContext
from opm._common import Builtin

View File

@@ -4,6 +4,7 @@ import sys
import numpy as np
from opm.io.parser import Builtin
from opm.io.parser import Parser
from opm.io.parser import ParseContext
from opm.io.deck import DeckKeyword
@@ -44,6 +45,33 @@ FIPNUM
self.spe3fn = test_path('spe3/SPE3CASE1.DATA')
self.norne_fname = test_path('../examples/data/norne/NORNE_ATW2013.DATA')
def test_dynamic_parser(self):
parser = Parser(add_default = False)
builtin = Builtin()
parser.add_keyword( builtin.START )
parser.add_keyword( builtin.RUNSPEC )
parser.add_keyword( builtin.FIELD )
parser.add_keyword( builtin.DIMENS )
parser.add_keyword( builtin.GRID )
parser.add_keyword( builtin.DX )
parser.add_keyword( builtin.DY )
parser.add_keyword( builtin.DZ )
parser.add_keyword( builtin.TOPS )
parser.add_keyword( builtin.REGIONS )
parser.add_keyword( builtin.OPERNUM )
parser.add_keyword( builtin.FIPNUM )
deck = parser.parse_string(self.REGIONDATA)
def test_dynamic_parser2(self):
parser = Parser(add_default = False)
builtin = Builtin()
kw_list = ["START", "RUNSPEC", "FIELD", "REGIONS", "DIMENS", "GRID", "DX", "DY", "DZ", "TOPS", "OPERNUM", "FIPNUM"]
for kw in kw_list:
parser.add_keyword( builtin[kw] )
deck = parser.parse_string(self.REGIONDATA)
def test_create(self):
parser = Parser()
deck = parser.parse(self.spe3fn)

View File

@@ -179,6 +179,42 @@ void Parser::addDefaultKeywords() {
write_file( newSource, sourceFile, m_verbose, "init" );
}
void KeywordGenerator::updatePybindSource(const KeywordLoader& loader , const std::string& sourceFile) const {
std::stringstream newSource;
newSource << R"(#include <string>
#include <exception>
#include <opm/json/JsonObject.hpp>
#include <opm/parser/eclipse/Parser/Parser.hpp>
#include <opm/parser/eclipse/Parser/ParserKeyword.hpp>
#include <opm/parser/eclipse/Parser/ParserKeywords/Builtin.hpp>
#include <opm/parser/eclipse/Deck/Deck.hpp>
#include <pybind11/stl.h>
#include <opm/parser/eclipse/Parser/ErrorGuard.hpp>
#include "export.hpp"
void python::common::export_ParserKeywords(py::module& module) {
py::class_<ParserKeywords::Builtin>(module, "Builtin")
.def(py::init<>())
)";
for(const auto& kw_pair : loader) {
const auto& keywords = kw_pair.second;
for (const auto& kw: keywords)
newSource << fmt::format(" .def_property_readonly(\"{0}\", &ParserKeywords::Builtin::get_{0})\n", kw.className());
}
newSource << R"( .def("__getitem__", &ParserKeywords::Builtin::operator[], ref_internal);
}
)";
fmt::print("Writing file: {}\n", sourceFile);
write_file( newSource, sourceFile, m_verbose, "source");
}
void KeywordGenerator::updateKeywordSource(const KeywordLoader& loader , const std::string& sourcePath ) const {
for(const auto& kw_pair : loader) {

View File

@@ -34,7 +34,7 @@ int main(int , char ** argv) {
const char * header_file_base_path = argv[4];
const char * header_file_path = argv[5];
const char * test_file_name = argv[6];
const char * builtin_pybind11_name = argv[7];
std::vector<std::string> keyword_list;
{
@@ -63,4 +63,5 @@ int main(int , char ** argv) {
generator.updateHeader(loader, header_file_base_path, header_file_path );
generator.updateBuiltInHeader(loader, header_file_base_path, header_file_path );
generator.updateTest( loader , test_file_name );
generator.updatePybindSource(loader , builtin_pybind11_name);
}