Skip to content

[Binding/Sofa.Config] Add Sofa.future & Sofa.Config #184

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ if (NOT SP3_COMPILED_AS_SUBPROJECT)
message(STATUS "SOFA Framework:\n\tVersion: ${SofaFramework_VERSION}\n\tLocation: ${SOFA_ROOT_DIR}")
endif()

add_subdirectory(Lifecycle)
add_subdirectory(Plugin)
add_subdirectory(bindings)
add_subdirectory(examples)
Expand Down
27 changes: 27 additions & 0 deletions Lifecycle/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
project(Lifecycle VERSION 1.0)

set(HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/src/SofaPython3/lifecycle/features.h
)

set(SOURCE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/src/SofaPython3/lifecycle/features.cpp
)

find_package(SofaFramework REQUIRED)

add_library(${PROJECT_NAME} SHARED ${HEADER_FILES} ${SOURCE_FILES})
add_library(SofaPython3::${PROJECT_NAME} ALIAS ${PROJECT_NAME})

target_link_libraries(${PROJECT_NAME} PUBLIC SofaCore)

sofa_create_component_in_package_with_targets(
COMPONENT_NAME ${PROJECT_NAME}
COMPONENT_VERSION ${SofaPython3_VERSION}
PACKAGE_NAME SofaPython3
TARGETS ${PROJECT_NAME} AUTO_SET_TARGET_PROPERTIES
INCLUDE_SOURCE_DIR "src"
INCLUDE_INSTALL_DIR "."
OPTIMIZE_BUILD_DIR FALSE
RELOCATABLE ".."
)
22 changes: 22 additions & 0 deletions Lifecycle/LifecycleConfig.cmake.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# CMake package configuration file for the @PROJECT_NAME@ module
@PACKAGE_GUARD@
@PACKAGE_INIT@

set(SP3_BUILD_TEST @SP3_BUILD_TEST@)

find_package(pybind11 CONFIG REQUIRED)
find_package(SofaFramework REQUIRED)
find_package(SofaSimulationGraph REQUIRED)

if(SP3_BUILD_TEST)
find_package(Sofa.Testing REQUIRED)
endif()

# If we are importing this config file and the target is not yet there this is indicating that
# target is an imported one. So we include it
if(NOT TARGET @PROJECT_NAME@)
include("${CMAKE_CURRENT_LIST_DIR}/PluginTargets.cmake")
endif()

# Check that the component/target is there.
check_required_components(@PROJECT_NAME@)
62 changes: 62 additions & 0 deletions Lifecycle/src/SofaPython3/lifecycle/features.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/******************************************************************************
* SofaPython3 plugin *
* (c) 2021 CNRS, University of Lille, INRIA *
* *
* This program is free software; you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as published by *
* the Free Software Foundation; either version 2.1 of the License, or (at *
* your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
* for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
*******************************************************************************
* Contact information: [email protected] *
******************************************************************************/
#include <iostream>
#include <map>
#include <stdexcept>
#include <SofaPython3/lifecycle/features.h>

namespace sofapython3::lifecycle::features
{

std::map<std::string, bool> features;

bool get(const std::string& name)
{
auto f = features.find(name);
if(f == features.end())
throw std::runtime_error("Missing attribute '"+name+"'");

return (f->second);
}

void set(const std::string& name, bool value)
{
auto f = features.find(name);
if(f == features.end())
throw std::runtime_error("Missing attribute '"+name+"'");

(f->second) = value;
}

void init(const std::string& name, bool value)
{
features[name] = value;
}


std::vector<std::string> list_features()
{
std::vector<std::string> v;
for(auto& it : features)
v.push_back(it.first);
return v;
}

} //namespace sofapython3::futurefeatures
43 changes: 43 additions & 0 deletions Lifecycle/src/SofaPython3/lifecycle/features.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/******************************************************************************
* SofaPython3 plugin *
* (c) 2021 CNRS, University of Lille, INRIA *
* *
* This program is free software; you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as published by *
* the Free Software Foundation; either version 2.1 of the License, or (at *
* your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
* for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
*******************************************************************************
* Contact information: [email protected] *
******************************************************************************/
#pragma once

#include <sofa/config.h>
#include <string>
#include <vector>

namespace sofapython3::lifecycle::features
{

/// Retrieve the value associated with the feature "name"
/// raise an exception if "name" is not existing.
SOFA_EXPORT_DYNAMIC_LIBRARY bool get(const std::string& name);

/// Change the value associated with the feature "name"
/// raise an exception if "name" is not existing.
SOFA_EXPORT_DYNAMIC_LIBRARY void set(const std::string& name, bool value);

/// Create and set a new value for feature with "name"
SOFA_EXPORT_DYNAMIC_LIBRARY void init(const std::string& name, bool value);

/// Returns the list of registered features names
SOFA_EXPORT_DYNAMIC_LIBRARY std::vector<std::string> list_features();

} ///namespace sofapython3::futurefeatures
1 change: 1 addition & 0 deletions bindings/Sofa/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
project(Bindings.Sofa)

set(SOFABINDINGS_MODULE_LIST
Lifecycle
Components
Core
Helper
Expand Down
44 changes: 44 additions & 0 deletions bindings/Sofa/package/Lifecycle.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
"""
Activate/deactive some feature of sofa python

Use that to control how some part of the binding should behave.

Usage:
from Sofa.Lifecycle import __new_feature__

with __new_feature__("feature_name", True):
do_something()

with __new_feature__("feature_name", False):
do_something()
"""
import Sofa.__Lifecycle__
from contextlib import ContextDecorator

### Initialize the feature set.
# Add your own feature by un-commenting the following line
Sofa.__Lifecycle__.init("my_feature", False)

def register_feature(feature_name, default_state):
Sofa.__Lifecycle__.init(feature_name, default_state)

def get_feature_status(name):
return Sofa.__Lifecycle__.get(name)

def list_features():
return Sofa.__Lifecycle__.list_features()

class __new_feature__(ContextDecorator):
def __init__(self, name, value):
self.name=name
self.new_value=value
self.old_value=None

def __enter__(self):
self.old_value=Sofa.__Lifecycle__.get(self.name)
Sofa.__Lifecycle__.set(self.name, self.new_value)
return self

def __exit__(self, *exc):
Sofa.__Lifecycle__.set(self.name, self.old_value)
return False
7 changes: 3 additions & 4 deletions bindings/Sofa/package/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,15 @@
import Sofa.constants
import Sofa.Helper
import Sofa.Core
import Sofa.Lifecycle
import Sofa.Simulation
import Sofa.Types
import Sofa.Components
import SofaTypes

from .prefab import *
from .Lifecycle import __new_feature__

__all__=["constants", "Helper", "Core", "Simulation", "Types", "SofaTypes", "prefab"]
__all__=["constants", "Helper", "Core", "Simulation", "Types", "SofaTypes", "prefab", "future"]

# Keep a list of the modules always imported in the Sofa-PythonEnvironment
try:
Expand All @@ -56,7 +57,6 @@
# e.g. plugin's modules defined from c++
__SofaPythonEnvironment_modulesExcludedFromReload = []


def unloadModules():
""" call this function to unload python modules and to force their reload
(useful to take into account their eventual modifications since
Expand Down Expand Up @@ -109,7 +109,6 @@ def sendMessageFromException(e):
exc_type, exc_value, exc_tb = sys.exc_info()
sofaExceptHandler(exc_type, exc_value, exc_tb)


def sofaFormatHandler(type, value, tb):
global oldexcepthook
"""This exception handler, convert python exceptions & traceback into more classical sofa error messages of the form:
Expand Down
2 changes: 1 addition & 1 deletion bindings/Sofa/src/SofaPython3/Sofa/Core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -85,5 +85,5 @@ SP3_add_python_module(
DESTINATION Sofa
SOURCES ${SOURCE_FILES}
HEADERS ${HEADER_FILES}
DEPENDS SofaBaseUtils SofaBaseCollision Sofa.Core Sofa.Helper Sofa.SimulationCore Sofa.DefaultType SofaBaseVisual SofaPython3::Plugin
DEPENDS SofaBaseUtils SofaBaseCollision Sofa.Core Sofa.Helper Sofa.SimulationCore Sofa.DefaultType SofaBaseVisual SofaPython3::Lifecycle SofaPython3::Plugin
)
26 changes: 26 additions & 0 deletions bindings/Sofa/src/SofaPython3/Sofa/Lifecycle/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
project(Bindings.Sofa.Lifecycle)

set(SOURCE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/Submodule_Lifecycle.cpp
)

if (NOT TARGET SofaPython3::Plugin)
find_package(SofaPython3 REQUIRED)
endif()

find_package(Sofa.Config REQUIRED)
find_package(SofaFramework REQUIRED)
find_package(SofaBaseCollision REQUIRED)
find_package(SofaBaseVisual REQUIRED)
find_package(SofaBaseUtils REQUIRED)

SP3_add_python_module(
TARGET ${PROJECT_NAME}
PACKAGE Bindings
MODULE __Lifecycle__
DESTINATION Sofa
SOURCES ${SOURCE_FILES}
HEADERS ${HEADER_FILES}
DEPENDS Sofa.Config SofaBaseUtils SofaBaseCollision SofaCore SofaHelper SofaSimulationCore SofaDefaultType SofaBaseVisual SofaPython3::Lifecycle SofaPython3::Plugin
)

Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/******************************************************************************
* SofaPython3 plugin *
* (c) 2021 CNRS, University of Lille, INRIA *
* *
* This program is free software; you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as published by *
* the Free Software Foundation; either version 2.1 of the License, or (at *
* your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
* for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
*******************************************************************************
* Contact information: [email protected] *
******************************************************************************/

#include <iostream>
#include <map>
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <SofaPython3/lifecycle/features.h>

namespace py { using namespace pybind11; }

namespace sofapython3
{

/// The first parameter must be named the same as the module file to load.
PYBIND11_MODULE(__Lifecycle__, ffmodule)
{
ffmodule.doc() = R"doc(
Control the the activation of new features
------------------------------------------
Sofa.__Lifecycle__.object_auto_init = True
)doc";
ffmodule.def("init", sofapython3::lifecycle::features::init);
ffmodule.def("set", sofapython3::lifecycle::features::set);
ffmodule.def("get", sofapython3::lifecycle::features::get);
ffmodule.def("list_features", sofapython3::lifecycle::features::list_features);
}

} ///namespace sofapython3
2 changes: 2 additions & 0 deletions bindings/Sofa/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ set(SOURCE_FILES

set(PYTHON_FILES
${CMAKE_CURRENT_SOURCE_DIR}/Components/Components.py
${CMAKE_CURRENT_SOURCE_DIR}/Lifecycle/Lifecycle.py
${CMAKE_CURRENT_SOURCE_DIR}/Core/BaseData.py
${CMAKE_CURRENT_SOURCE_DIR}/Core/Base.py
${CMAKE_CURRENT_SOURCE_DIR}/Core/BaseObject.py
Expand Down Expand Up @@ -51,6 +52,7 @@ add_test(NAME ${PROJECT_NAME} COMMAND ${PROJECT_NAME})

set(DIR_BINDING_LIST
Components
Lifecycle
Core
Helper
Simulation
Expand Down
15 changes: 15 additions & 0 deletions bindings/Sofa/tests/Lifecycle/Lifecycle.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# coding: utf8

import Sofa
from Sofa.Lifecycle import __new_feature__
import unittest

class Test(unittest.TestCase):
def test_init_feature(self):
Sofa.Lifecycle.register_feature("new_feature", False)
self.assertFalse(Sofa.Lifecycle.get_feature_status("new_feature"), False)

with __new_feature__("new_feature", True):
self.assertEquals(Sofa.Lifecycle.get_feature_status("new_feature"), True)

self.assertFalse(Sofa.Lifecycle.get_feature_status("new_feature"), False)
3 changes: 2 additions & 1 deletion bindings/Sofa/tests/PythonModule_Sofa_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,12 @@ static struct PythonModule_Sofa_tests : public PythonTestExtractor
PythonModule_Sofa_tests()
{
const std::string executable_directory = sofa::helper::Utils::getExecutableDirectory();
addTestDirectory(executable_directory+"/Bindings.Sofa.Tests.d/Components", "Sofa_Components_");
addTestDirectory(executable_directory+"/Bindings.Sofa.Tests.d/Core", "Sofa_Core_");
addTestDirectory(executable_directory+"/Bindings.Sofa.Tests.d/Helper", "Sofa_Helper_");
addTestDirectory(executable_directory+"/Bindings.Sofa.Tests.d/Lifecycle", "Sofa_Core_");
addTestDirectory(executable_directory+"/Bindings.Sofa.Tests.d/Simulation", "Sofa_Simulation_");
addTestDirectory(executable_directory+"/Bindings.Sofa.Tests.d/Types", "Sofa_Types_");
addTestDirectory(executable_directory+"/Bindings.Sofa.Tests.d/Components", "Sofa_Components_");
}
} python_tests;

Expand Down