Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • ostasse/dynamic-graph-python
  • gsaurel/dynamic-graph-python
  • stack-of-tasks/dynamic-graph-python
3 results
Show changes
Showing
with 325 additions and 784 deletions
// Copyright (c) 2018, Joseph Mirabel
// Authors: Joseph Mirabel (joseph.mirabel@laas.fr)
#include <dynamic-graph/factory.h>
#include <dynamic-graph/command-bind.h>
#include "dynamic-graph/python/signal-wrapper.hh"
#include <dynamic-graph/command-bind.h>
#include <dynamic-graph/factory.h>
namespace dynamicgraph {
namespace python {
namespace signalWrapper {
void convert(PyObject* o, bool& v) { v = (o == Py_True); }
void convert(PyObject* o, int& v) { v = (int)PyLong_AsLong(o); }
void convert(PyObject* o, float& v) { v = (float)PyFloat_AS_DOUBLE(o); }
void convert(PyObject* o, double& v) { v = PyFloat_AS_DOUBLE(o); }
void convert(PyObject* o, Vector& v) {
v.resize(PyTuple_Size(o));
for (int i = 0; i < v.size(); ++i) convert(PyTuple_GetItem(o, i), v[i]);
}
} // namespace signalWrapper
PythonSignalContainer::PythonSignalContainer(const std::string& name) : Entity(name) {
std::string docstring;
docstring =
" \n"
" Remove a signal\n"
" \n"
" Input:\n"
" - name of the signal\n"
" \n";
addCommand("rmSignal", command::makeCommandVoid1(*this, &PythonSignalContainer::rmSignal, docstring));
}
void PythonSignalContainer::signalRegistration(const SignalArray<int>& signals) {
void PythonSignalContainer::signalRegistration(
const SignalArray<int>& signals) {
Entity::signalRegistration(signals);
}
void PythonSignalContainer::rmSignal(const std::string& name) { Entity::signalDeregistration(name); }
void PythonSignalContainer::rmSignal(const std::string& name) {
Entity::signalDeregistration(name);
}
DYNAMICGRAPH_FACTORY_ENTITY_PLUGIN(PythonSignalContainer, "PythonSignalContainer");
DYNAMICGRAPH_FACTORY_ENTITY_PLUGIN(PythonSignalContainer,
"PythonSignalContainer");
template <class T, class Time>
bool SignalWrapper<T, Time>::checkCallable(PyObject* c, std::string& error) {
if (PyCallable_Check(c) == 0) {
PyObject* str = PyObject_Str(c);
error = obj_to_str(str);
bool SignalWrapper<T, Time>::checkCallable(pyobject c, std::string& error) {
if (PyCallable_Check(c.ptr()) == 0) {
error = boost::python::extract<std::string>(c.attr("__str__")());
error += " is not callable";
Py_DECREF(str);
return false;
}
return true;
......
"""
Copyright (C) 2010 CNRS
Author: Florent Lamiraux
"""
# Copyright (C) 2020 CNRS
#
# Author: Joseph Mirabel
from __future__ import print_function
# I kept what follows for backward compatibility but I think it should be
# removed
import re
from .wrap import (create_signal_wrapper, signal_base_display, signal_base_display_dependencies,
signal_base_get_class_name, signal_base_get_name, signal_base_get_time, signal_base_get_value,
signal_base_getPlugged, signal_base_isPlugged, signal_base_recompute, signal_base_set_time,
signal_base_set_value, signal_base_unplug)
from .wrap import SignalBase # noqa
from .wrap import create_signal_wrapper as SignalWrapper # noqa
def stringToTuple(vector):
......@@ -19,17 +17,22 @@ def stringToTuple(vector):
Transform a string of format '[n](x_1,x_2,...,x_n)' into a tuple of numbers.
"""
# Find vector length
a = re.match(r'\[(\d+)\]', vector)
a = re.match(r"\[(\d+)\]", vector)
size = int(a.group(1))
# remove '[n]' prefix
vector = vector[len(a.group(0)):]
vector = vector[len(a.group(0)) :]
# remove '(' and ')' at beginning and end
vector = vector.lstrip('(').rstrip(')\n')
vector = vector.lstrip("(").rstrip(")\n")
# split string by ','
vector = vector.split(',')
vector = vector.split(",")
# check size
if len(vector) != size:
raise TypeError('displayed size ' + str(size) + ' of vector does not fit actual size: ' + str(len(vector)))
raise TypeError(
"displayed size "
+ str(size)
+ " of vector does not fit actual size: "
+ str(len(vector))
)
res = map(float, vector)
return tuple(res)
......@@ -39,10 +42,10 @@ def tupleToString(vector):
Transform a tuple of numbers into a string of format
'[n](x_1, x_2, ..., x_n)'
"""
string = '[%d](' % len(vector)
string = "[%d](" % len(vector)
for x in vector[:-1]:
string += '%f,' % x
string += '%f)' % vector[-1]
string += "%f," % x
string += "%f)" % vector[-1]
return string
......@@ -53,20 +56,30 @@ def stringToMatrix(string):
of tuple of numbers.
"""
# Find matrix size
a = re.search(r'\[(\d+),(\d+)]', string)
a = re.search(r"\[(\d+),(\d+)]", string)
nRows = int(a.group(1))
nCols = int(a.group(2))
# Remove '[n,m]' prefix
string = string[len(a.group(0)):]
rows = string.split('),(')
string = string[len(a.group(0)) :]
rows = string.split("),(")
if len(rows) != nRows:
raise TypeError('displayed nb rows ' + nRows + ' of matrix does not fit actual nb rows: ' + str(len(rows)))
raise TypeError(
"displayed nb rows "
+ nRows
+ " of matrix does not fit actual nb rows: "
+ str(len(rows))
)
m = []
for rstr in rows:
rstr = rstr.lstrip('(').rstrip(')\n')
r = map(float, rstr.split(','))
rstr = rstr.lstrip("(").rstrip(")\n")
r = map(float, rstr.split(","))
if len(r) != nCols:
raise TypeError('one row length ' + len(r) + ' of matrix does not fit displayed nb cols: ' + nCols)
raise TypeError(
"one row length "
+ len(r)
+ " of matrix does not fit displayed nb cols: "
+ nCols
)
m.append(tuple(r))
return tuple(m)
......@@ -78,19 +91,19 @@ def matrixToString(matrix):
"""
nRows = len(matrix)
if nRows == 0:
return '[0,0](())'
return "[0,0](())"
nCols = len(matrix[0])
string = '[%d,%d](' % (nRows, nCols)
string = "[%d,%d](" % (nRows, nCols)
for r in range(nRows):
string += '('
string += "("
for c in range(nCols):
string += str(float(matrix[r][c]))
if c != nCols - 1:
string += ','
string += ')'
string += ","
string += ")"
if r != nRows - 1:
string += ','
string += ')'
string += ","
string += ")"
return string
......@@ -104,18 +117,18 @@ def objectToString(obj):
- an integer,
- a boolean,
"""
if (hasattr(obj, "__iter__")):
if hasattr(obj, "__iter__"):
# matrix or vector
if len(obj) == 0:
return ""
else:
if (hasattr(obj[0], "__iter__")):
if hasattr(obj[0], "__iter__"):
# matrix
return matrixToString(obj)
else:
# vector
return tupleToString(obj)
elif hasattr(obj, 'name'):
elif hasattr(obj, "name"):
return obj.name
else:
return str(obj)
......@@ -153,136 +166,3 @@ def stringToObject(string):
return float(string)
except Exception:
return string
class SignalBase(object):
"""
This class binds dynamicgraph::SignalBase<int> C++ class
"""
obj = None
def __init__(self, name="", obj=None):
"""
Constructor: if not called by a child class, create and store a pointer
to a C++ SignalBase<int> object.
"""
if obj:
self.obj = obj
else:
raise RuntimeError("A pointer is required to create SignalBase object.")
if obj is None:
self.className = self.getClassName()
self.name = self.getName()
@property
def time(self):
"""
Get time of signal
"""
return signal_base_get_time(self.obj)
@time.setter
def time(self, val):
"""
Set Time of signal
Input:
- an integer
"""
return signal_base_set_time(self.obj, val)
@property
def value(self):
"""
Setter and getter for the value of a signal
Binds C++ SignalBase<int>::get() and set() methods. Values are passed
through string streams.
A string is interpreted as respectively:
* a matrix (tuple of tuple) if string fits '[n,m]((x_11,x_12,...,x_1m),...,(x_n1,x_n2,...,x_nm))' format where
n and m are integers, x_ij are floating point numbers,
* a tuple if string fits '[n](x_1, x_2, ..., x_n)' format,
* an integer,
* a floating point number.
If string fits none of the above formats, no conversion is performed.
For instance, is s binds a signal of type vector,
>>> s.value = (2.5, .1, 1e2)
will call SignalBase<int>::set("[3](2.5,0.1,100.0)") and
>>> s.value
(2.5, 0.1, 100.0)
"""
string = signal_base_get_value(self.obj)
return stringToObject(string)
@value.setter
def value(self, val):
"""
Set the signal as a constant signal with given value.
If the signal is plugged, it will be unplugged
"""
string = objectToString(val)
return signal_base_set_value(self.obj, string)
def getName(self):
"""
Get name of signal
"""
return signal_base_get_name(self.obj)
@property
def name(self):
"""
Get name of signal
"""
return signal_base_get_name(self.obj)
def getClassName(self):
"""
Get class name of signal
"""
return signal_base_get_class_name(self.obj)
def recompute(self, time):
"""
Force signal to recompute the value at given time.
"""
return signal_base_recompute(self.obj, time)
def unplug(self):
"""
Unplug a PTR signal.
"""
return signal_base_unplug(self.obj)
def isPlugged(self):
"""
Return whether a signal is plugged.
"""
return signal_base_isPlugged(self.obj)
def getPlugged(self):
"""
Return the plugged signal.
"""
return SignalBase(obj=signal_base_getPlugged(self.obj))
def __str__(self):
"""
Print signal in a string
"""
return signal_base_display(self.obj)
def displayDependencies(self, iter):
"""
Print signal dependencies in a string
"""
return (signal_base_display_dependencies(self.obj, iter))
class SignalWrapper(SignalBase):
def __init__(self, name, type, func):
super(SignalWrapper, self).__init__(name, create_signal_wrapper(name, type, func))
......@@ -8,8 +8,8 @@ def addTrace(robot, trace, entityName, signalName, autoRecompute=True):
"""
Add a signal to a tracer and recompute it automatically if necessary.
"""
signal = '{0}.{1}'.format(entityName, signalName)
filename = '{0}-{1}'.format(entityName, signalName)
signal = "{0}.{1}".format(entityName, signalName)
filename = "{0}-{1}".format(entityName, signalName).replace("/", "_")
trace.add(signal, filename)
if autoRecompute:
robot.device.after.addSignal(signal)
#include <dynamic-graph/tracer.h>
#include "dynamic-graph/python/module.hh"
BOOST_PYTHON_MODULE(wrap) {
using dynamicgraph::Tracer;
bp::import("dynamic_graph");
dynamicgraph::python::exposeEntity<Tracer>().def("addSignal",
&Tracer::addSignalToTrace);
}
#include <dynamic-graph/tracer-real-time.h>
#include "dynamic-graph/python/module.hh"
BOOST_PYTHON_MODULE(wrap) {
using dynamicgraph::Tracer;
using dynamicgraph::TracerRealTime;
bp::import("dynamic_graph.tracer");
dynamicgraph::python::exposeEntity<TracerRealTime, bp::bases<Tracer> >();
}
......@@ -8,30 +8,33 @@
#endif
#include <iostream>
#include "dynamic-graph/debug.h"
#include "dynamic-graph/python/interpreter.hh"
std::ofstream dg_debugfile("/tmp/dynamic-graph-traces.txt", std::ios::trunc& std::ios::out);
std::ofstream dg_debugfile("/tmp/dynamic-graph-traces.txt",
std::ios::trunc& std::ios::out);
// Python initialization commands
namespace dynamicgraph {
namespace python {
static const std::string pythonPrefix[8] = {"from __future__ import print_function\n",
"import traceback\n",
"class StdoutCatcher:\n"
" def __init__(self):\n"
" self.data = ''\n"
" def write(self, stuff):\n"
" self.data = self.data + stuff\n"
" def fetch(self):\n"
" s = self.data[:]\n"
" self.data = ''\n"
" return s\n",
"stdout_catcher = StdoutCatcher()\n",
"stderr_catcher = StdoutCatcher()\n",
"import sys\n",
"sys.stdout = stdout_catcher",
"sys.stderr = stderr_catcher"};
static const std::string pythonPrefix[8] = {
"from __future__ import print_function\n",
"import traceback\n",
"class StdoutCatcher:\n"
" def __init__(self):\n"
" self.data = ''\n"
" def write(self, stuff):\n"
" self.data = self.data + stuff\n"
" def fetch(self):\n"
" s = self.data[:]\n"
" self.data = ''\n"
" return s\n",
"stdout_catcher = StdoutCatcher()\n",
"stderr_catcher = StdoutCatcher()\n",
"import sys\n",
"sys.stdout = stdout_catcher",
"sys.stderr = stderr_catcher"};
bool HandleErr(std::string& err, PyObject* globals_, int PythonInputType) {
dgDEBUGIN(15);
......@@ -41,7 +44,8 @@ bool HandleErr(std::string& err, PyObject* globals_, int PythonInputType) {
if (PyErr_Occurred() != NULL) {
bool is_syntax_error = PyErr_ExceptionMatches(PyExc_SyntaxError);
PyErr_Print();
PyObject* stderr_obj = PyRun_String("stderr_catcher.fetch()", Py_eval_input, globals_, globals_);
PyObject* stderr_obj = PyRun_String("stderr_catcher.fetch()", Py_eval_input,
globals_, globals_);
err = obj_to_str(stderr_obj);
Py_DECREF(stderr_obj);
......@@ -69,7 +73,9 @@ Interpreter::Interpreter() {
dlopen(PYTHON_LIBRARY, RTLD_LAZY | RTLD_GLOBAL);
#endif
Py_Initialize();
#if PY_MAJOR_VERSION < 3 || PY_MINOR_VERSION < 7
PyEval_InitThreads();
#endif
mainmod_ = PyImport_AddModule("__main__");
Py_INCREF(mainmod_);
globals_ = PyModule_GetDict(mainmod_);
......@@ -95,7 +101,8 @@ Interpreter::~Interpreter() {
// Ideally, we should call Py_Finalize but this is not really supported by
// Python.
// Instead, we merelly remove variables.
// Code was taken here: https://github.com/numpy/numpy/issues/8097#issuecomment-356683953
// Code was taken here:
// https://github.com/numpy/numpy/issues/8097#issuecomment-356683953
{
PyObject* poAttrList = PyObject_Dir(mainmod_);
PyObject* poAttrIter = PyObject_GetIter(poAttrList);
......@@ -105,11 +112,13 @@ Interpreter::~Interpreter() {
std::string oAttrName(obj_to_str(poAttrName));
// Make sure we don't delete any private objects.
if (oAttrName.compare(0, 2, "__") != 0 || oAttrName.compare(oAttrName.size() - 2, 2, "__") != 0) {
if (oAttrName.compare(0, 2, "__") != 0 ||
oAttrName.compare(oAttrName.size() - 2, 2, "__") != 0) {
PyObject* poAttr = PyObject_GetAttr(mainmod_, poAttrName);
// Make sure we don't delete any module objects.
if (poAttr && poAttr->ob_type != mainmod_->ob_type) PyObject_SetAttr(mainmod_, poAttrName, NULL);
if (poAttr && poAttr->ob_type != mainmod_->ob_type)
PyObject_SetAttr(mainmod_, poAttrName, NULL);
Py_DECREF(poAttr);
}
......@@ -132,7 +141,8 @@ std::string Interpreter::python(const std::string& command) {
return lres;
}
void Interpreter::python(const std::string& command, std::string& res, std::string& out, std::string& err) {
void Interpreter::python(const std::string& command, std::string& res,
std::string& out, std::string& err) {
res = "";
out = "";
err = "";
......@@ -147,18 +157,21 @@ void Interpreter::python(const std::string& command, std::string& res, std::stri
PyEval_RestoreThread(_pyState);
std::cout << command.c_str() << std::endl;
PyObject* result = PyRun_String(command.c_str(), Py_eval_input, globals_, globals_);
PyObject* result =
PyRun_String(command.c_str(), Py_eval_input, globals_, globals_);
// Check if the result is null.
if (result == NULL) {
// Test if this is a syntax error (due to the evaluation of an expression)
// else just output the problem.
if (!HandleErr(err, globals_, Py_eval_input)) {
// If this is a statement, re-parse the command.
result = PyRun_String(command.c_str(), Py_single_input, globals_, globals_);
result =
PyRun_String(command.c_str(), Py_single_input, globals_, globals_);
// If there is still an error build the appropriate err string.
if (result == NULL) HandleErr(err, globals_, Py_single_input);
// If there is no error, make sure that the previous error message is erased.
// If there is no error, make sure that the previous error message is
// erased.
else
err = "";
} else
......@@ -166,7 +179,8 @@ void Interpreter::python(const std::string& command, std::string& res, std::stri
}
PyObject* stdout_obj = 0;
stdout_obj = PyRun_String("stdout_catcher.fetch()", Py_eval_input, globals_, globals_);
stdout_obj =
PyRun_String("stdout_catcher.fetch()", Py_eval_input, globals_, globals_);
out = obj_to_str(stdout_obj);
Py_DECREF(stdout_obj);
// Local display for the robot (in debug mode or for the logs)
......@@ -207,7 +221,8 @@ void Interpreter::runPythonFile(std::string filename, std::string& err) {
PyEval_RestoreThread(_pyState);
err = "";
PyObject* run = PyRun_File(pFile, filename.c_str(), Py_file_input, globals_, globals_);
PyObject* run =
PyRun_File(pFile, filename.c_str(), Py_file_input, globals_, globals_);
if (run == NULL) {
HandleErr(err, globals_, Py_file_input);
std::cerr << err << std::endl;
......
# Copyright 2010-2020, Florent Lamiraux, Thomas Moulard, Olivier Stasse, Guilhem Saurel, JRL, CNRS/AIST, LAAS-CNRS
# Copyright 2010-2020, Florent Lamiraux, Thomas Moulard, Olivier Stasse, Guilhem
# Saurel, JRL, CNRS/AIST, LAAS-CNRS
# Test the interpreter
ADD_UNIT_TEST(interpreter-test interpreter-test.cc)
TARGET_LINK_LIBRARIES(interpreter-test ${PROJECT_NAME})
add_unit_test(interpreter-test interpreter-test.cc)
target_link_libraries(interpreter-test PRIVATE ${PROJECT_NAME})
# Test runfile
ADD_UNIT_TEST(interpreter-test-runfile interpreter-test-runfile.cc)
TARGET_LINK_LIBRARIES(interpreter-test-runfile ${PYTHON_LIBRARY} ${Boost_LIBRARIES} ${PROJECT_NAME})
TARGET_COMPILE_DEFINITIONS(interpreter-test-runfile PRIVATE PATH="${CMAKE_CURRENT_LIST_DIR}/")
add_unit_test(interpreter-test-runfile interpreter-test-runfile.cc)
target_link_libraries(interpreter-test-runfile PRIVATE ${PROJECT_NAME})
target_include_directories(interpreter-test-runfile
PRIVATE Boost::unit_test_framework)
target_compile_definitions(interpreter-test-runfile
PRIVATE PATH="${CMAKE_CURRENT_LIST_DIR}/")
# Test the module generation
## Create an entity
# Test the module generation Create an entity
SET(LIBRARY_NAME "custom_entity")
ADD_LIBRARY(${LIBRARY_NAME} SHARED "${LIBRARY_NAME}.cpp")
IF(SUFFIX_SO_VERSION)
SET_TARGET_PROPERTIES(${LIBRARY_NAME}
PROPERTIES SOVERSION ${PROJECT_VERSION})
ENDIF(SUFFIX_SO_VERSION)
set(LIBRARY_NAME "custom_entity")
add_library(${LIBRARY_NAME} SHARED "${LIBRARY_NAME}.cpp")
if(SUFFIX_SO_VERSION)
set_target_properties(${LIBRARY_NAME} PROPERTIES SOVERSION ${PROJECT_VERSION})
endif(SUFFIX_SO_VERSION)
target_link_libraries(${LIBRARY_NAME} dynamic-graph::dynamic-graph)
target_link_libraries(${LIBRARY_NAME} PRIVATE dynamic-graph::dynamic-graph)
## Create its bindings
## This mimics DYNAMIC_GRAPH_PYTHON_MODULE(${LIBRARY_NAME} ${LIBRARY_NAME} "${LIBRARY_NAME}-wrap")
# Create its bindings This mimics DYNAMIC_GRAPH_PYTHON_MODULE(${LIBRARY_NAME}
# ${LIBRARY_NAME} "${LIBRARY_NAME}-wrap")
CONFIGURE_FILE(
configure_file(
${PROJECT_SOURCE_DIR}/cmake/dynamic_graph/submodule/__init__.py.cmake
${CMAKE_CURRENT_BINARY_DIR}/${LIBRARY_NAME}/__init__.py
)
SET(PYTHON_MODULE "${LIBRARY_NAME}-wrap")
SET(SOURCE_PYTHON_MODULE "cmake/dynamic_graph/python-module-py.cc")
ADD_LIBRARY(${PYTHON_MODULE} MODULE ${PROJECT_SOURCE_DIR}/${SOURCE_PYTHON_MODULE})
SET_TARGET_PROPERTIES(${PYTHON_MODULE} PROPERTIES
PREFIX ""
OUTPUT_NAME ${LIBRARY_NAME}/wrap)
IF(UNIX AND NOT APPLE)
TARGET_LINK_LIBRARIES(${PYTHON_MODULE} "-Wl,--no-as-needed")
ENDIF(UNIX AND NOT APPLE)
TARGET_LINK_LIBRARIES(${PYTHON_MODULE} ${LIBRARY_NAME} ${PYTHON_LIBRARY})
TARGET_INCLUDE_DIRECTORIES(${PYTHON_MODULE} SYSTEM PUBLIC ${PYTHON_INCLUDE_DIRS})
## Test it
ADD_PYTHON_UNIT_TEST("test-custom-entity" "tests/test_custom_entity.py" src tests)
${CMAKE_CURRENT_BINARY_DIR}/${LIBRARY_NAME}/__init__.py)
set(PYTHON_MODULE "${LIBRARY_NAME}-wrap")
set(DYNAMICGRAPH_MODULE_HEADER
"${CMAKE_SOURCE_DIR}/tests/custom_entity_module.h")
configure_file(${PROJECT_SOURCE_DIR}/cmake/dynamic_graph/python-module-py.cc.in
${CMAKE_CURRENT_BINARY_DIR}/python-module-py.cc @ONLY)
add_library(${PYTHON_MODULE} MODULE
${CMAKE_CURRENT_BINARY_DIR}/python-module-py.cc)
set_target_properties(${PYTHON_MODULE}
PROPERTIES PREFIX "" OUTPUT_NAME ${LIBRARY_NAME}/wrap)
if(UNIX AND NOT APPLE)
target_link_libraries(${PYTHON_MODULE} PRIVATE "-Wl,--no-as-needed")
endif(UNIX AND NOT APPLE)
target_link_libraries(${PYTHON_MODULE} PRIVATE ${LIBRARY_NAME} ${PROJECT_NAME})
# Test it
add_python_unit_test("test-custom-entity" "tests/test_custom_entity.py" src
tests)
# also test other bindings, using this custom entity
ADD_PYTHON_UNIT_TEST("test-bindings" "tests/test_bindings.py" src tests)
add_python_unit_test("test-bindings" "tests/test_bindings.py" src tests)
This diff is collapsed.
/* Copyright 2020 LAAS, CNRS
* Joseph Mirabel
*
*/
#define ENABLE_RT_LOG
#include <dynamic-graph/entity.h>
#include <dynamic-graph/signal-ptr.h>
#include <dynamic-graph/signal-time-dependent.h>
#include <sstream>
namespace dynamicgraph {
class CustomEntity : public Entity {
public:
dynamicgraph::SignalPtr<double, int> m_sigdSIN;
dynamicgraph::SignalTimeDependent<double, int> m_sigdTimeDepSOUT;
DYNAMIC_GRAPH_ENTITY_DECL();
CustomEntity(const std::string n);
void addSignal();
void rmValidSignal();
double &update(double &res, const int &inTime);
void act();
};
} // namespace dynamicgraph
#include "custom_entity.h"
typedef boost::mpl::vector<dynamicgraph::CustomEntity> entities_t;
......@@ -2,7 +2,10 @@
* Copyright
*/
#include <iostream>
#include "dynamic-graph-python-test.hh"
GraphTest::GraphTest() { std::cout << "Constructor of unitTesting object of class Graph." << std::endl; }
#include <iostream>
GraphTest::GraphTest() {
std::cout << "Constructor of unitTesting object of class Graph." << std::endl;
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -3,7 +3,7 @@ import os
pkgConfigPath = os.environ.get("PKG_CONFIG_PATH")
if pkgConfigPath is None:
pkgConfigPath = ''
pathList = re.split(':', pkgConfigPath) # noqa
pkgConfigPath = ""
pathList = re.split(":", pkgConfigPath) # noqa
print(pathList)
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.