diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs
index baf555516c4603b3bb88b6edf18786a734deae8d..fb971c175b7f03cad03c5dc5c2ecc5a4f3e376b4 100644
--- a/.git-blame-ignore-revs
+++ b/.git-blame-ignore-revs
@@ -1,2 +1,5 @@
+# pre-commit run -a (Guilhem Saurel, 2022-10-20)
+b04b074db9e058d06b5db27316afbb3d9eea9173
+
 # format (Guilhem Saurel, 2022-04-05)
 62b5dafa1a15795521ab3c31d321b37fd46ae69f
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 7f6fac1b5b8583732353a5193f0b01865ca35c64..fe4d445c05de63eb56145db64214773d578c512c 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -32,3 +32,7 @@ repos:
     rev: 5.0.4
     hooks:
     -   id: flake8
+-   repo: https://github.com/cheshirekow/cmake-format-precommit
+    rev: v0.6.13
+    hooks:
+    - id: cmake-format
diff --git a/CMakeLists.txt b/CMakeLists.txt
index de26a42b695ea75679f9948ffcd3f3e8a3d9b532..21f35b1d5e28b85139ace73c2eb3ccb74f912047 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,104 +1,100 @@
-# Copyright (c) 2014, 2020 CNRS
-# Author: Mathieu Geisert, Florent Lamiraux, Guilhem Saurel
+# Copyright (c) 2014, 2020 CNRS Author: Mathieu Geisert, Florent Lamiraux,
+# Guilhem Saurel
 #
-# This file is part of gepetto-viewer-corba.
-# gepetto-viewer-corba 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
-# 3 of the License, or (at your option) any later version.
+# This file is part of gepetto-viewer-corba. gepetto-viewer-corba 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 3 of the License, or (at your option) any later version.
 #
-# gepetto-viewer-corba 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
-# General Lesser Public License for more details.  You should have
-# received a copy of the GNU Lesser General Public License along with
-# gepetto-viewer-corba.  If not, see
+# gepetto-viewer-corba 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 General Lesser Public License
+# for more details.  You should have received a copy of the GNU Lesser General
+# Public License along with gepetto-viewer-corba.  If not, see
 # <http://www.gnu.org/licenses/>.
 
-CMAKE_MINIMUM_REQUIRED(VERSION 3.1)
+cmake_minimum_required(VERSION 3.1)
 
-SET(PROJECT_NAME gepetto-viewer-corba)
-SET(PROJECT_DESCRIPTION "Corba server for gepetto-viewer")
-SET(PROJECT_URL "https://github.com/Gepetto/${PROJECT_NAME}")
+set(PROJECT_NAME gepetto-viewer-corba)
+set(PROJECT_DESCRIPTION "Corba server for gepetto-viewer")
+set(PROJECT_URL "https://github.com/Gepetto/${PROJECT_NAME}")
 
-SET(PROJECT_USE_CMAKE_EXPORT TRUE)
-SET(PROJECT_USE_KEYWORD_LINK_LIBRARIES TRUE)
-SET(CXX_DISABLE_WERROR true)
-SET(DOXYGEN_USE_TEMPLATE_CSS TRUE)
+set(PROJECT_USE_CMAKE_EXPORT TRUE)
+set(PROJECT_USE_KEYWORD_LINK_LIBRARIES TRUE)
+set(CXX_DISABLE_WERROR true)
+set(DOXYGEN_USE_TEMPLATE_CSS TRUE)
 
-INCLUDE(cmake/base.cmake)
-INCLUDE(cmake/idl.cmake)
-INCLUDE(cmake/python.cmake)
-INCLUDE(cmake/apple.cmake)
+include(cmake/base.cmake)
+include(cmake/idl.cmake)
+include(cmake/apple.cmake)
 
-SET(CLIENT_ONLY FALSE CACHE BOOL "Set to true to install the client only")
+set(CLIENT_ONLY
+    FALSE
+    CACHE BOOL "Set to true to install the client only")
 
-COMPUTE_PROJECT_ARGS(PROJECT_ARGS LANGUAGES CXX)
-PROJECT(${PROJECT_NAME} ${PROJECT_ARGS})
+compute_project_args(PROJECT_ARGS LANGUAGES CXX)
+project(${PROJECT_NAME} ${PROJECT_ARGS})
 
-IF(APPLE)
-  APPLY_DEFAULT_APPLE_CONFIGURATION()
-ENDIF(APPLE)
+if(APPLE)
+  apply_default_apple_configuration()
+endif(APPLE)
 
-# {{{ C++ and Python client.
-# Dependencies
-FINDPYTHON()
-ADD_REQUIRED_DEPENDENCY("omniORB4 >= 4.1.4")
+# {{{ C++ and Python client. Dependencies
+add_required_dependency("omniORB4 >= 4.1.4")
 
-SET(${PROJECT_NAME}_HEADERS
-  include/gepetto/viewer/corba/api.hh
-  include/gepetto/viewer/corba/client.hh
-  include/gepetto/viewer/corba/conversions.hh
-  )
+set(${PROJECT_NAME}_HEADERS
+    include/gepetto/viewer/corba/api.hh include/gepetto/viewer/corba/client.hh
+    include/gepetto/viewer/corba/conversions.hh)
 # }}}
 
 # {{{ C++ server.
-IF(NOT CLIENT_ONLY)
+if(NOT CLIENT_ONLY)
   # {{{ Dependencies for the server.
-  ADD_PROJECT_DEPENDENCY("gepetto-viewer" REQUIRED)
+  add_project_dependency("gepetto-viewer" REQUIRED)
 
   # Get desired Qt version
   string(REPLACE "." ";" DESIRED_QT_VERSION_LIST ${GEPETTO_VIEWER_QTVERSION})
   list(GET DESIRED_QT_VERSION_LIST 0 DESIRED_QT_VERSION_MAJOR)
 
-  IF(${DESIRED_QT_VERSION_MAJOR} EQUAL 4)
-    SET(PROJECT_USE_QT4 True)
-  ELSEIF(${DESIRED_QT_VERSION_MAJOR} EQUAL 5)
-    SET(PROJECT_USE_QT4 False)
-  ELSE()
-    MESSAGE(FATAL_ERROR "This package is only compatible with Qt 4 and Qt 5")
-  ENDIF()
-
-  SET(CMAKE_INCLUDE_CURRENT_DIR ON)
-  SET(GEPETTO_VIEWER_CORBA_QTVERSION "${GEPETTO_VIEWER_QTVERSION}")
-  SET(PKG_CONFIG_EXTRA "qtversion=${GEPETTO_VIEWER_CORBA_QTVERSION}")
-  SET(PACKAGE_EXTRA_MACROS "set(GEPETTO_VIEWER_CORBA_QTVERSION ${GEPETTO_VIEWER_CORBA_QTVERSION})")
+  if(${DESIRED_QT_VERSION_MAJOR} EQUAL 4)
+    set(PROJECT_USE_QT4 True)
+  elseif(${DESIRED_QT_VERSION_MAJOR} EQUAL 5)
+    set(PROJECT_USE_QT4 False)
+  else()
+    message(FATAL_ERROR "This package is only compatible with Qt 4 and Qt 5")
+  endif()
+
+  set(CMAKE_INCLUDE_CURRENT_DIR ON)
+  set(GEPETTO_VIEWER_CORBA_QTVERSION "${GEPETTO_VIEWER_QTVERSION}")
+  set(PKG_CONFIG_EXTRA "qtversion=${GEPETTO_VIEWER_CORBA_QTVERSION}")
+  set(PACKAGE_EXTRA_MACROS
+      "set(GEPETTO_VIEWER_CORBA_QTVERSION ${GEPETTO_VIEWER_CORBA_QTVERSION})")
   # }}}
 
   # {{{ Packaging
-  PKG_CONFIG_APPEND_LIBS(${PROJECT_NAME})
+  pkg_config_append_libs(${PROJECT_NAME})
 
   # For backward compatibility
-  SET(PKG_CONFIG_EXTRA "${PKG_CONFIG_EXTRA}\ncmake_plugin=${GEPETTO_VIEWER_CMAKE_PLUGIN}")
+  set(PKG_CONFIG_EXTRA
+      "${PKG_CONFIG_EXTRA}\ncmake_plugin=${GEPETTO_VIEWER_CMAKE_PLUGIN}")
   # }}}
 
   # {{{ Set list of headers
-  LIST(APPEND ${PROJECT_NAME}_HEADERS
-    ${CMAKE_SOURCE_DIR}/include/gepetto/gui/omniorb/url.hh
-    )
+  list(APPEND ${PROJECT_NAME}_HEADERS
+       ${CMAKE_SOURCE_DIR}/include/gepetto/gui/omniorb/url.hh)
   # }}}
-ENDIF(NOT CLIENT_ONLY)
+endif(NOT CLIENT_ONLY)
 # }}}
 
-ADD_SUBDIRECTORY(src)
-ADD_SUBDIRECTORY(doc)
+add_subdirectory(src)
+add_subdirectory(doc)
 
-IF(NOT CLIENT_ONLY)
-  ADD_SUBDIRECTORY(plugins)
-  ADD_SUBDIRECTORY(blender)
-  ADD_SUBDIRECTORY(examples EXCLUDE_FROM_ALL)
-  ADD_SUBDIRECTORY(tests)
-ENDIF(NOT CLIENT_ONLY)
+if(NOT CLIENT_ONLY)
+  add_subdirectory(plugins)
+  add_subdirectory(blender)
+  add_subdirectory(examples EXCLUDE_FROM_ALL)
+  add_subdirectory(tests)
+endif(NOT CLIENT_ONLY)
 
-INSTALL(FILES package.xml DESTINATION share/${PROJECT_NAME})
+install(FILES package.xml DESTINATION share/${PROJECT_NAME})
 # vim: foldmethod=marker foldlevel=0
diff --git a/blender/CMakeLists.txt b/blender/CMakeLists.txt
index 39f042d2f3f6d73a698a9b1e7ff0f732dea63c62..72e191ecfc321fa6d0080c505ecd19c02494d267 100644
--- a/blender/CMakeLists.txt
+++ b/blender/CMakeLists.txt
@@ -1,35 +1,32 @@
-# Copyright (c) 2015 CNRS
-# Author: Joseph Mirabel
+# Copyright (c) 2015 CNRS Author: Joseph Mirabel
 #
-# This file is part of gepetto-viewer-corba.
-# gepetto-viewer-corba 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
-# 3 of the License, or (at your option) any later version.
+# This file is part of gepetto-viewer-corba. gepetto-viewer-corba 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 3 of the License, or (at your option) any later version.
 #
-# gepetto-viewer-corba 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
-# General Lesser Public License for more details.  You should have
-# received a copy of the GNU Lesser General Public License along with
-# gepetto-viewer-corba.  If not, see
+# gepetto-viewer-corba 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 General Lesser Public License
+# for more details.  You should have received a copy of the GNU Lesser General
+# Public License along with gepetto-viewer-corba.  If not, see
 # <http://www.gnu.org/licenses/>.
 
-SET (BLENDER_EXE "" CACHE FILEPATH "Path to the blender executable")
+set(BLENDER_EXE
+    ""
+    CACHE FILEPATH "Path to the blender executable")
 
-IF (EXISTS ${BLENDER_EXE})
-    CONFIGURE_FILE (install_addon.py.in ${CMAKE_CURRENT_BINARY_DIR}/install_addon.py)
-    # ADD_CUSTOM_COMMAND (OUTPUT nothing
-      # COMMAND echo "${BLENDER_EXE}"
-      # COMMENT "Installing the blender addon")
-      # COMMAND ${BLENDER_EXE}
-      # --background --enable-autoexec
-      # --python ${CMAKE_CURRENT_SOURCE_DIR}/install_addon.py
-    ADD_CUSTOM_TARGET (blender
-      PYTHONPATH=/usr/lib/python3/dist-packages/
-      ${BLENDER_EXE} --background --enable-autoexec
-      --python ${CMAKE_CURRENT_BINARY_DIR}/install_addon.py
-      COMMENT "Installing the blender addon")
-ENDIF (EXISTS ${BLENDER_EXE})
+if(EXISTS ${BLENDER_EXE})
+  configure_file(install_addon.py.in
+                 ${CMAKE_CURRENT_BINARY_DIR}/install_addon.py)
+  # ADD_CUSTOM_COMMAND (OUTPUT nothing COMMAND echo "${BLENDER_EXE}" COMMENT
+  # "Installing the blender addon") COMMAND ${BLENDER_EXE} --background
+  # --enable-autoexec --python ${CMAKE_CURRENT_SOURCE_DIR}/install_addon.py
+  add_custom_target(
+    blender
+    PYTHONPATH=/usr/lib/python3/dist-packages/ ${BLENDER_EXE} --background
+    --enable-autoexec --python ${CMAKE_CURRENT_BINARY_DIR}/install_addon.py
+    COMMENT "Installing the blender addon")
+endif(EXISTS ${BLENDER_EXE})
 
-INSTALL (PROGRAMS urdf_to_blender.py DESTINATION bin)
+install(PROGRAMS urdf_to_blender.py DESTINATION bin)
diff --git a/cmake b/cmake
index 9d20c6f79ef9f717ea9e8c549ec2d239b8d406a3..b5763ed91fd58343c001e26720253cd79c008d49 160000
--- a/cmake
+++ b/cmake
@@ -1 +1 @@
-Subproject commit 9d20c6f79ef9f717ea9e8c549ec2d239b8d406a3
+Subproject commit b5763ed91fd58343c001e26720253cd79c008d49
diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt
index 7595505dc954d764e9f0c00e7721408d7d386847..2be444462bfdf75e9e3424c1aaba2181031efcd1 100644
--- a/doc/CMakeLists.txt
+++ b/doc/CMakeLists.txt
@@ -1,63 +1,68 @@
-# Copyright (c) 2019 CNRS
-# Author: Joseph Mirabel
+# Copyright (c) 2019 CNRS Author: Joseph Mirabel
 #
-# This file is part of gepetto-viewer-corba.
-# gepetto-viewer-corba 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
-# 3 of the License, or (at your option) any later version.
+# This file is part of gepetto-viewer-corba. gepetto-viewer-corba 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 3 of the License, or (at your option) any later version.
 #
-# gepetto-viewer-corba 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
-# General Lesser Public License for more details.  You should have
-# received a copy of the GNU Lesser General Public License along with
-# gepetto-viewer-corba.  If not, see
+# gepetto-viewer-corba 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 General Lesser Public License
+# for more details.  You should have received a copy of the GNU Lesser General
+# Public License along with gepetto-viewer-corba.  If not, see
 # <http://www.gnu.org/licenses/>.
 
 # {{{ Find Qt tags
-SET(_use_qt_local_doc FALSE)
-SET(qt_online_doc "http://doc.qt.io")
+set(_use_qt_local_doc FALSE)
+set(qt_online_doc "http://doc.qt.io")
 
-IF(PROJECT_USE_QT4)
-  FIND_FILE(QT4_TAGFILE doc/html/qt.tags
+if(PROJECT_USE_QT4)
+  find_file(
+    QT4_TAGFILE doc/html/qt.tags
     HINTS / /usr
     PATH_SUFFIXES share/qt4)
   # Eventually, QT4_TAGFILE can be set manually to
-  # /usr/share/qt4/doc/html/qt.tags
-  # on ubuntu 16.04, from package qt4-doc-html
-  IF(QT4_TAGFILE)
-    IF(_use_qt_local_doc)
-      GET_FILENAME_COMPONENT(path_to_doc ${QT4_TAGFILE} DIRECTORY)
-      SET(QT_TAGFILES "\"${QT4_TAGFILE}=${path_to_doc}\"" PARENT_SCOPE)
-    ELSE(_use_qt_local_doc)
-      SET(QT_TAGFILES "\"${QT4_TAGFILE}=${qt_doc}/archives/qt-4.8\"" PARENT_SCOPE)
-    ENDIF(_use_qt_local_doc)
-  ENDIF()
-ELSE(PROJECT_USE_QT4)
-  SET(_QT_TAGFILES)
-  # Available components
-  # qtcore qtgui qtwidgets qtnetwork qtsql
-  # qtprintsupport qttestlib qtconcurrent qdoc qtxml
-  FOREACH (component "core" "widgets" "gui" "network")
-    STRING(TOUPPER ${component} _up_comp)
-    FIND_FILE(QT5_${_up_comp}_TAGFILE doc/qt${component}/qt${component}.tags
+  # /usr/share/qt4/doc/html/qt.tags on ubuntu 16.04, from package qt4-doc-html
+  if(QT4_TAGFILE)
+    if(_use_qt_local_doc)
+      get_filename_component(path_to_doc ${QT4_TAGFILE} DIRECTORY)
+      set(QT_TAGFILES
+          "\"${QT4_TAGFILE}=${path_to_doc}\""
+          PARENT_SCOPE)
+    else(_use_qt_local_doc)
+      set(QT_TAGFILES
+          "\"${QT4_TAGFILE}=${qt_doc}/archives/qt-4.8\""
+          PARENT_SCOPE)
+    endif(_use_qt_local_doc)
+  endif()
+else(PROJECT_USE_QT4)
+  set(_QT_TAGFILES)
+  # Available components qtcore qtgui qtwidgets qtnetwork qtsql qtprintsupport
+  # qttestlib qtconcurrent qdoc qtxml
+  foreach(component "core" "widgets" "gui" "network")
+    string(TOUPPER ${component} _up_comp)
+    find_file(
+      QT5_${_up_comp}_TAGFILE doc/qt${component}/qt${component}.tags
       HINTS / /usr
       PATH_SUFFIXES share/qt5)
     # Eventually, QT5_${_up_comp}_TAGFILE can be set manually to
-    # /usr/share/qt5/doc/qt${component}/qt${component}.tags
-    # on ubuntu 16.04, from package qtbase5-doc-html
-    IF(QT5_${_up_comp}_TAGFILE)
-      IF(_use_qt_local_doc)
-        GET_FILENAME_COMPONENT(path_to_doc ${QT5_${_up_comp}_TAGFILE} DIRECTORY)
-        SET(_QT_TAGFILES "${_QT_TAGFILES} \"${QT5_${_up_comp}_TAGFILE}=${path_to_doc}\"")
-      ELSE(_use_qt_local_doc)
-        SET(_QT_TAGFILES "${_QT_TAGFILES} \"${QT5_${_up_comp}_TAGFILE}=${qt_doc}/qt-5\"")
-      ENDIF(_use_qt_local_doc)
-    ENDIF()
-  ENDFOREACH()
-  SET(QT_TAGFILES ${_QT_TAGFILES} PARENT_SCOPE)
-ENDIF(PROJECT_USE_QT4)
+    # /usr/share/qt5/doc/qt${component}/qt${component}.tags on ubuntu 16.04,
+    # from package qtbase5-doc-html
+    if(QT5_${_up_comp}_TAGFILE)
+      if(_use_qt_local_doc)
+        get_filename_component(path_to_doc ${QT5_${_up_comp}_TAGFILE} DIRECTORY)
+        set(_QT_TAGFILES
+            "${_QT_TAGFILES} \"${QT5_${_up_comp}_TAGFILE}=${path_to_doc}\"")
+      else(_use_qt_local_doc)
+        set(_QT_TAGFILES
+            "${_QT_TAGFILES} \"${QT5_${_up_comp}_TAGFILE}=${qt_doc}/qt-5\"")
+      endif(_use_qt_local_doc)
+    endif()
+  endforeach()
+  set(QT_TAGFILES
+      ${_QT_TAGFILES}
+      PARENT_SCOPE)
+endif(PROJECT_USE_QT4)
 # }}}
 
 # vim: foldmethod=marker foldlevel=0
diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt
index 9e72699928ff76aae02854a56be83fb71d88f347..353ebb50b8dcb973f80d3632fd08128b1a5c9d4f 100644
--- a/examples/CMakeLists.txt
+++ b/examples/CMakeLists.txt
@@ -1,28 +1,25 @@
-# Copyright (c) 2015, 2020 LAAS-CNRS
-# Author: Joseph Mirabel, Guilhem Saurel
+# Copyright (c) 2015, 2020 LAAS-CNRS Author: Joseph Mirabel, Guilhem Saurel
 #
-# This file is part of SceneViewer-corba.
-# SceneViewer-corba 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
-# 3 of the License, or (at your option) any later version.
+# This file is part of SceneViewer-corba. SceneViewer-corba 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 3 of the License, or (at your option) any later version.
 #
-# SceneViewer-corba 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
-# General Lesser Public License for more details.  You should have
-# received a copy of the GNU Lesser General Public License along with
-# hpp-corbaserver.  If not, see
+# SceneViewer-corba 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 General Lesser Public License
+# for more details.  You should have received a copy of the GNU Lesser General
+# Public License along with hpp-corbaserver.  If not, see
 # <http://www.gnu.org/licenses/>.
 
-SET(LIBRARY_NAME ${PROJECT_NAME})
+set(LIBRARY_NAME ${PROJECT_NAME})
 
-MACRO(ADD_EXAMPLE NAME SOURCE)
-    ADD_EXECUTABLE (${NAME} ${SOURCE})
-    TARGET_LINK_LIBRARIES(${NAME} PRIVATE ${LIBRARY_NAME})
-    PKG_CONFIG_USE_DEPENDENCY(${NAME} omniORB4)
-ENDMACRO()
+macro(ADD_EXAMPLE NAME SOURCE)
+  add_executable(${NAME} ${SOURCE})
+  target_link_libraries(${NAME} PRIVATE ${LIBRARY_NAME})
+  pkg_config_use_dependency(${NAME} omniORB4)
+endmacro()
 
-ADD_EXAMPLE (basic-scene basic-scene.cc)
-ADD_EXAMPLE (display-urdf display-urdf.cc)
-ADD_EXAMPLE (free-functions free-functions.cc)
+add_example(basic-scene basic-scene.cc)
+add_example(display-urdf display-urdf.cc)
+add_example(free-functions free-functions.cc)
diff --git a/package.xml b/package.xml
index 71f7e130d3de51ff139b6edce9bb2e0e9ce9cc7d..a8b6ac956ba828fc1cf20d534ec820adc48c1193 100644
--- a/package.xml
+++ b/package.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0"?>
  <package format="3">
  <name>gepetto-viewer-corba</name>
- <version>5.7.1</version>
+ <version>5.7.2</version>
  <description>Corba server for gepetto-viewer </description>
 
  <maintainer email="hpp@laas.fr">Joseph Mirabel</maintainer>
diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt
index b42201d507d57fb8530e642d393f573698699ef2..01048cd30e8a9601c4d55fda2959228cbd28ccc9 100644
--- a/plugins/CMakeLists.txt
+++ b/plugins/CMakeLists.txt
@@ -1,20 +1,16 @@
 #
-# Copyright (c) 2018 CNRS
-# Authors: Joseph Mirabel
+# Copyright (c) 2018 CNRS Authors: Joseph Mirabel
 #
+# This file is part of gepetto-viewer-corba gepetto-viewer-corba 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 3 of the License, or (at your option) any later version.
 #
-# This file is part of gepetto-viewer-corba
-# gepetto-viewer-corba 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
-# 3 of the License, or (at your option) any later version.
-#
-# gepetto-viewer-corba 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
-# General Lesser Public License for more details.  You should have
-# received a copy of the GNU Lesser General Public License along with
-# gepetto-viewer-corba  If not, see
+# gepetto-viewer-corba 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 General Lesser Public License
+# for more details.  You should have received a copy of the GNU Lesser General
+# Public License along with gepetto-viewer-corba  If not, see
 # <http://www.gnu.org/licenses/>.
 
-ADD_SUBDIRECTORY(omniorbserver)
+add_subdirectory(omniorbserver)
diff --git a/plugins/omniorbserver/CMakeLists.txt b/plugins/omniorbserver/CMakeLists.txt
index bb48b6ecd207e76fff938cbe1e21553c80f91c7b..f9ab4a79308d43f74a41a26575961a75abee0aea 100644
--- a/plugins/omniorbserver/CMakeLists.txt
+++ b/plugins/omniorbserver/CMakeLists.txt
@@ -1,50 +1,40 @@
-# Copyright (c) 2018 CNRS
-# Authors: Joseph Mirabel
+# Copyright (c) 2018 CNRS Authors: Joseph Mirabel
 #
+# This file is part of gepetto-viewer-corba gepetto-viewer-corba 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 3 of the License, or (at your option) any later version.
 #
-# This file is part of gepetto-viewer-corba
-# gepetto-viewer-corba 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
-# 3 of the License, or (at your option) any later version.
-#
-# gepetto-viewer-corba 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
-# General Lesser Public License for more details.  You should have
-# received a copy of the GNU Lesser General Public License along with
-# gepetto-viewer-corba  If not, see
+# gepetto-viewer-corba 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 General Lesser Public License
+# for more details.  You should have received a copy of the GNU Lesser General
+# Public License along with gepetto-viewer-corba  If not, see
 # <http://www.gnu.org/licenses/>.
 
-IF(PROJECT_USE_QT4)
-  SET(QT4 "QT4")
-ELSE()
-  SET(QT4 "")
-ENDIF()
+if(PROJECT_USE_QT4)
+  set(QT4 "QT4")
+else()
+  set(QT4 "")
+endif()
 
-GEPETTO_GUI_PLUGIN(omniorbserver
+gepetto_gui_plugin(
+  omniorbserver
   INSIDE_GEPETTO_VIEWER_CORBA
-
   ${QT4}
-
   # List of headers that need not to be moced.
   HEADERS_NO_MOC
-
   # List of headers to be moced
   HEADERS
   plugin.hh
   omniorbthread.hh
-
   # List of source files
   SOURCES
   plugin.cc
   omniorbthread.cc
-
   # List of dependencies to be given to TARGET_LINK_LIBRARIES
   LINK_DEPENDENCIES
   "gepetto-viewer-corba"
-
   # List of dependencies to be given to PKG_CONFIG_USE_DEPENDENCY
   PKG_CONFIG_DEPENDENCIES
-  "omniORB4"
-  )
+  "omniORB4")
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 5ebf3c60270902edae19d14b1419ef46917b0b54..398475cb201645b0a5bb8246900c91d29f70ec24 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1,152 +1,133 @@
-# Copyright (c) 2014-2016, 2020 LAAS-CNRS
-# Author: Mathieu Geisert, Guilhem Saurel
+# Copyright (c) 2014-2016, 2020 LAAS-CNRS Author: Mathieu Geisert, Guilhem
+# Saurel
 #
-# This file is part of SceneViewer-corba.
-# SceneViewer-corba 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
-# 3 of the License, or (at your option) any later version.
+# This file is part of SceneViewer-corba. SceneViewer-corba 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 3 of the License, or (at your option) any later version.
 #
-# SceneViewer-corba 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
-# General Lesser Public License for more details.  You should have
-# received a copy of the GNU Lesser General Public License along with
-# hpp-corbaserver.  If not, see
+# SceneViewer-corba 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 General Lesser Public License
+# for more details.  You should have received a copy of the GNU Lesser General
+# Public License along with hpp-corbaserver.  If not, see
 # <http://www.gnu.org/licenses/>.
 
-SET(LIBRARY_NAME ${PROJECT_NAME})
+set(LIBRARY_NAME ${PROJECT_NAME})
 
 # {{{ Generate C++ and Python files from IDL files.
-SET(IDL_SOURCES
-  graphical-interface
-  )
+set(IDL_SOURCES graphical-interface)
 
-OMNIIDL_INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/idl)
+omniidl_include_directories(${CMAKE_SOURCE_DIR}/idl)
 
-FOREACH(IDL ${IDL_SOURCES})
+foreach(IDL ${IDL_SOURCES})
   # C++
-  GENERATE_IDL_CPP (gepetto/viewer/corba/${IDL}
-    ${CMAKE_SOURCE_DIR}/idl/gepetto/viewer)
-  INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/gepetto/viewer/corba/${IDL}.hh
-    DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/gepetto/viewer/corba)
+  generate_idl_cpp(gepetto/viewer/corba/${IDL}
+                   ${CMAKE_SOURCE_DIR}/idl/gepetto/viewer)
+  install(FILES ${CMAKE_CURRENT_BINARY_DIR}/gepetto/viewer/corba/${IDL}.hh
+          DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/gepetto/viewer/corba)
 
   # Python
-  SET(_IDL_PYTHON_ARGUMENTS
-    -C${CMAKE_CURRENT_BINARY_DIR}
-    -K
-    -Wbpackage=gepetto.corbaserver
-    )
-  IF(PYTHON_VERSION_MAJOR EQUAL 3)
-    SET(_IDL_PYTHON_ARGUMENTS
-      -p${CMAKE_SOURCE_DIR}/cmake/hpp/idl
-      -bomniidl_be_python_with_docstring
-      ${_IDL_PYTHON_ARGUMENTS}
-      )
-  ENDIF(PYTHON_VERSION_MAJOR EQUAL 3)
-  GENERATE_IDL_PYTHON (gepetto/viewer/corba/${IDL}
-    ${CMAKE_SOURCE_DIR}/idl/gepetto/viewer
-    ARGUMENTS ${_IDL_PYTHON_ARGUMENTS}
-    )
-
-  STRING(REGEX REPLACE "-" "_" IDL_UNDERSCORE "${IDL}")
-
-  INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/gepetto/corbaserver/${IDL_UNDERSCORE}_idl.py
-    DESTINATION ${PYTHON_SITELIB}/gepetto/corbaserver)
-  INSTALL(DIRECTORY
-    ${CMAKE_CURRENT_BINARY_DIR}/gepetto/corbaserver/gepetto
-    ${CMAKE_CURRENT_BINARY_DIR}/gepetto/corbaserver/gepetto__POA
+  set(_IDL_PYTHON_ARGUMENTS -C${CMAKE_CURRENT_BINARY_DIR} -K
+                            -Wbpackage=gepetto.corbaserver)
+  if(PYTHON_VERSION_MAJOR EQUAL 3)
+    set(_IDL_PYTHON_ARGUMENTS
+        -p${CMAKE_SOURCE_DIR}/cmake/hpp/idl -bomniidl_be_python_with_docstring
+        ${_IDL_PYTHON_ARGUMENTS})
+  endif(PYTHON_VERSION_MAJOR EQUAL 3)
+  generate_idl_python(
+    gepetto/viewer/corba/${IDL} ${CMAKE_SOURCE_DIR}/idl/gepetto/viewer
+    ARGUMENTS ${_IDL_PYTHON_ARGUMENTS})
+
+  string(REGEX REPLACE "-" "_" IDL_UNDERSCORE "${IDL}")
+
+  install(
+    FILES
+      ${CMAKE_CURRENT_BINARY_DIR}/gepetto/corbaserver/${IDL_UNDERSCORE}_idl.py
     DESTINATION ${PYTHON_SITELIB}/gepetto/corbaserver)
+  install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/gepetto/corbaserver/gepetto
+                    ${CMAKE_CURRENT_BINARY_DIR}/gepetto/corbaserver/gepetto__POA
+          DESTINATION ${PYTHON_SITELIB}/gepetto/corbaserver)
 
   # IDL
-  INSTALL(FILES ${CMAKE_SOURCE_DIR}/idl/gepetto/viewer/${IDL}.idl
-    DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/idl/gepetto/corbaserver)
-ENDFOREACH()
+  install(FILES ${CMAKE_SOURCE_DIR}/idl/gepetto/viewer/${IDL}.idl
+          DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/idl/gepetto/corbaserver)
+endforeach()
 
-ADD_CUSTOM_TARGET(generate_idl_cpp DEPENDS ${ALL_IDL_CPP_STUBS})
-ADD_CUSTOM_TARGET(generate_idl_python DEPENDS ${ALL_IDL_PYTHON_STUBS})
+add_custom_target(generate_idl_cpp DEPENDS ${ALL_IDL_CPP_STUBS})
+add_custom_target(generate_idl_python DEPENDS ${ALL_IDL_PYTHON_STUBS})
 # }}}
 
 # {{{ C++ client: generate the library
-SET (${PROJECT_NAME}_SOURCES
-  client.cc
-  ${CMAKE_CURRENT_BINARY_DIR}/gepetto/viewer/corba/graphical-interface.hh
-  ${CMAKE_CURRENT_BINARY_DIR}/gepetto/viewer/corba/graphical-interfaceSK.cc
-)
+set(${PROJECT_NAME}_SOURCES
+    client.cc
+    ${CMAKE_CURRENT_BINARY_DIR}/gepetto/viewer/corba/graphical-interface.hh
+    ${CMAKE_CURRENT_BINARY_DIR}/gepetto/viewer/corba/graphical-interfaceSK.cc)
 # }}}
 
 # {{{ C++ application: generate the executable if requested
-IF(NOT CLIENT_ONLY)
+if(NOT CLIENT_ONLY)
   # {{{ Configure Qt
-  SET(${PROJECT_NAME}_MOC
-    node-callback.hh)
+  set(${PROJECT_NAME}_MOC node-callback.hh)
   if(GEPETTO_VIEWER_QTVERSION VERSION_LESS 5)
-    QT4_WRAP_CPP(${PROJECT_NAME}_HEADERS_MOCED ${${PROJECT_NAME}_MOC})
-    #QT4_WRAP_UI(${PROJECT_NAME}_FORMS_HEADERS ${${PROJECT_NAME}_FORMS})
-    #QT4_ADD_RESOURCES(${PROJECT_NAME}_RESOURCES_RCC ${${PROJECT_NAME}_RESOURCES})
+    qt4_wrap_cpp(${PROJECT_NAME}_HEADERS_MOCED ${${PROJECT_NAME}_MOC})
+    # QT4_WRAP_UI(${PROJECT_NAME}_FORMS_HEADERS ${${PROJECT_NAME}_FORMS})
+    # QT4_ADD_RESOURCES(${PROJECT_NAME}_RESOURCES_RCC
+    # ${${PROJECT_NAME}_RESOURCES})
   else(GEPETTO_VIEWER_QTVERSION VERSION_LESS 5)
-    QT5_WRAP_CPP(${PROJECT_NAME}_HEADERS_MOCED ${${PROJECT_NAME}_MOC})
-    #QT5_WRAP_UI(${PROJECT_NAME}_FORMS_HEADERS ${${PROJECT_NAME}_FORMS})
-    #QT5_ADD_RESOURCES(${PROJECT_NAME}_RESOURCES_RCC ${${PROJECT_NAME}_RESOURCES})
+    qt5_wrap_cpp(${PROJECT_NAME}_HEADERS_MOCED ${${PROJECT_NAME}_MOC})
+    # QT5_WRAP_UI(${PROJECT_NAME}_FORMS_HEADERS ${${PROJECT_NAME}_FORMS})
+    # QT5_ADD_RESOURCES(${PROJECT_NAME}_RESOURCES_RCC
+    # ${${PROJECT_NAME}_RESOURCES})
   endif(GEPETTO_VIEWER_QTVERSION VERSION_LESS 5)
 
   # {{{ Setup source files
-  SET (${PROJECT_NAME}_SOURCES
-    ${${PROJECT_NAME}_SOURCES}
-    graphical-interface.impl.cpp
-    node-callback.cpp
-    server.cc
-    server-private.cc
-    ${${PROJECT_NAME}_HEADERS_MOCED}
-    )
-
-  ADD_DEFINITIONS(${QT_DEFINITIONS})
-# }}}
-
-  # Removes 5 warnings about anonymous variadic macros that were added from
-  # c++ 11.
-  SET_SOURCE_FILES_PROPERTIES(graphical-interface.impl.cpp
-    PROPERTIES
-    COMPILE_FLAGS "-Wno-variadic-macros")
+  set(${PROJECT_NAME}_SOURCES
+      ${${PROJECT_NAME}_SOURCES} graphical-interface.impl.cpp node-callback.cpp
+      server.cc server-private.cc ${${PROJECT_NAME}_HEADERS_MOCED})
+
+  add_definitions(${QT_DEFINITIONS})
+  # }}}
+
+  # Removes 5 warnings about anonymous variadic macros that were added from c++
+  # 11.
+  set_source_files_properties(graphical-interface.impl.cpp
+                              PROPERTIES COMPILE_FLAGS "-Wno-variadic-macros")
   # }}}
 
-ENDIF(NOT CLIENT_ONLY)
+endif(NOT CLIENT_ONLY)
 # }}}
 
-ADD_LIBRARY(${LIBRARY_NAME} SHARED ${${PROJECT_NAME}_SOURCES})
-TARGET_INCLUDE_DIRECTORIES(${LIBRARY_NAME} PRIVATE ${CMAKE_BINARY_DIR}/src)
-ADD_DEPENDENCIES (${LIBRARY_NAME} generate_idl_cpp)
-ADD_DEPENDENCIES (${LIBRARY_NAME} generate_idl_python)
-IF(NOT CLIENT_ONLY)
-  TARGET_LINK_LIBRARIES(${LIBRARY_NAME} PUBLIC gepetto-viewer::gepetto-viewer)
-ENDIF(NOT CLIENT_ONLY)
-PKG_CONFIG_USE_DEPENDENCY(${LIBRARY_NAME} omniORB4)
+add_library(${LIBRARY_NAME} SHARED ${${PROJECT_NAME}_SOURCES})
+target_include_directories(${LIBRARY_NAME} PRIVATE ${CMAKE_BINARY_DIR}/src)
+add_dependencies(${LIBRARY_NAME} generate_idl_cpp)
+add_dependencies(${LIBRARY_NAME} generate_idl_python)
+if(NOT CLIENT_ONLY)
+  target_link_libraries(${LIBRARY_NAME} PUBLIC gepetto-viewer::gepetto-viewer)
+endif(NOT CLIENT_ONLY)
+pkg_config_use_dependency(${LIBRARY_NAME} omniORB4)
 
-INSTALL(TARGETS ${PROJECT_NAME} EXPORT ${TARGETS_EXPORT_NAME} DESTINATION lib)
+install(
+  TARGETS ${PROJECT_NAME}
+  EXPORT ${TARGETS_EXPORT_NAME}
+  DESTINATION lib)
 
 # {{{ Python client: install Python files
-MAKE_DIRECTORY(${CMAKE_CURRENT_BINARY_DIR}/gepetto/viewer/corba)
-
-INSTALL(
-  FILES
-  ${CMAKE_CURRENT_SOURCE_DIR}/gepetto/__init__.py
-  ${CMAKE_CURRENT_SOURCE_DIR}/gepetto/quaternion.py
-  ${CMAKE_CURRENT_SOURCE_DIR}/gepetto/color.py
-  DESTINATION ${PYTHON_SITELIB}/gepetto
-  )
-INSTALL(
-  FILES
-  ${CMAKE_CURRENT_SOURCE_DIR}/gepetto/corbaserver/__init__.py
-  ${CMAKE_CURRENT_SOURCE_DIR}/gepetto/corbaserver/client.py
-  ${CMAKE_CURRENT_SOURCE_DIR}/gepetto/corbaserver/exporttoblender.py
-  ${CMAKE_CURRENT_SOURCE_DIR}/gepetto/corbaserver/tools.py
-  DESTINATION ${PYTHON_SITELIB}/gepetto/corbaserver
-  )
-INSTALL(
-  FILES
-  ${CMAKE_CURRENT_SOURCE_DIR}/../blender/gepettoimport.py
-  DESTINATION ${PYTHON_SITELIB}/gepetto/blender
-  )
+make_directory(${CMAKE_CURRENT_BINARY_DIR}/gepetto/viewer/corba)
+
+install(
+  FILES ${CMAKE_CURRENT_SOURCE_DIR}/gepetto/__init__.py
+        ${CMAKE_CURRENT_SOURCE_DIR}/gepetto/quaternion.py
+        ${CMAKE_CURRENT_SOURCE_DIR}/gepetto/color.py
+  DESTINATION ${PYTHON_SITELIB}/gepetto)
+install(
+  FILES ${CMAKE_CURRENT_SOURCE_DIR}/gepetto/corbaserver/__init__.py
+        ${CMAKE_CURRENT_SOURCE_DIR}/gepetto/corbaserver/client.py
+        ${CMAKE_CURRENT_SOURCE_DIR}/gepetto/corbaserver/exporttoblender.py
+        ${CMAKE_CURRENT_SOURCE_DIR}/gepetto/corbaserver/tools.py
+  DESTINATION ${PYTHON_SITELIB}/gepetto/corbaserver)
+install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/../blender/gepettoimport.py
+        DESTINATION ${PYTHON_SITELIB}/gepetto/blender)
 # }}}
 
 # vim: foldmethod=marker foldlevel=0
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 3e4ab9c3a118a4351c4eee928e2da0120f663180..e1cbc975b351b0d3469500272f340e5843354a45 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -2,39 +2,37 @@
 #
 # Authors: Joseph Mirabel, Guilhem Saurel
 #
-# This file is part of hpp-gui
-# hpp-gui 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 3 of the License, or
+# This file is part of hpp-gui hpp-gui 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 3 of the License, or
 # (at your option) any later version.
 #
-# hpp-gui 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 General Lesser Public License for more details.
-# You should have received a copy of the GNU Lesser General Public License
-# along with hpp-gui  If not, see <http://www.gnu.org/licenses/>.
+# hpp-gui 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 General Lesser Public License for more
+# details. You should have received a copy of the GNU Lesser General Public
+# License along with hpp-gui  If not, see <http://www.gnu.org/licenses/>.
 
 # ADD_TESTCASE(NAME)
 # ------------------------
 #
 # Define a test named `NAME'.
 #
-# This macro will create a binary from `NAME.cc', link it against
-# Boost and add it to the test suite.
+# This macro will create a binary from `NAME.cc', link it against Boost and add
+# it to the test suite.
 #
 
-IF(PROJECT_USE_QT4)
-  INCLUDE(${QT_USE_FILE})
-ENDIF(PROJECT_USE_QT4)
-ADD_DEFINITIONS(${QT_DEFINITIONS})
+if(PROJECT_USE_QT4)
+  include(${QT_USE_FILE})
+endif(PROJECT_USE_QT4)
+add_definitions(${QT_DEFINITIONS})
 
-MACRO(ADD_TESTCASE NAME)
-  ADD_UNIT_TEST(${NAME} ${NAME}.cc)
-  TARGET_LINK_LIBRARIES(${NAME} gepetto-viewer::gepetto-viewer)
-ENDMACRO(ADD_TESTCASE)
+macro(ADD_TESTCASE NAME)
+  add_unit_test(${NAME} ${NAME}.cc)
+  target_link_libraries(${NAME} gepetto-viewer::gepetto-viewer)
+endmacro(ADD_TESTCASE)
 
-ADD_TESTCASE(colormap)
+add_testcase(colormap)
 # ADD_TESTCASE(osgviewerQt)
 
-ADD_PYTHON_UNIT_TEST("py-trivial" "tests/trivial.py" "src")
+add_python_unit_test("py-trivial" "tests/trivial.py" "src")