3
0
mirror of https://github.com/triqs/dft_tools synced 2024-12-25 13:53:40 +01:00

magic : redirect std::cout to python sys.out.write

- for all functions, except when GIL option (not implemented) is here
  we use a triqs::py_stream, which redirect the stream
  to python sys.write
- so that a simple C++ code with a std::cout
  print its output in the notebook...
- NB : it only works for the code within the cell.
  If it calls another function on the lib which uses cout,
  print is not redirected.
  Designed for simple tests....
- cerr not (yet) redirected. (useful ?).
This commit is contained in:
Olivier Parcollet 2014-06-11 15:47:29 +02:00
parent aa126e178b
commit f1c32012a6
6 changed files with 167 additions and 29 deletions

View File

@ -6,7 +6,7 @@ Triqs magic
{TRIQS_DOC} {TRIQS_DOC}
""" """
import imp,os,sys,subprocess, hashlib import imp,os,sys,subprocess, hashlib,re
from IPython.core.error import UsageError from IPython.core.error import UsageError
from IPython.core.magic import Magics, magics_class, line_magic, cell_magic from IPython.core.magic import Magics, magics_class, line_magic, cell_magic
from IPython.core import display, magic_arguments from IPython.core import display, magic_arguments
@ -53,6 +53,7 @@ def desc_file(c_decl, use) :
from wrap_generator import * from wrap_generator import *
module = module_(full_name = "ext", doc = "") module = module_(full_name = "ext", doc = "")
module.add_include("<triqs/arrays.hpp>") module.add_include("<triqs/arrays.hpp>")
module.add_include("<triqs/python_tools/py_stream.hpp>")
module.add_using("namespace triqs::arrays") module.add_using("namespace triqs::arrays")
module.add_preamble('#include "./ext.cpp"') module.add_preamble('#include "./ext.cpp"')
""" """
@ -137,9 +138,16 @@ class TriqsMagics(Magics):
if '-v' in line: if '-v' in line:
self.triqs.parser.set_defaults(verbosity=0) self.triqs.parser.set_defaults(verbosity=0)
## Add GIL argument ?
use_GIL = False
args = magic_arguments.parse_argstring(self.triqs, line) args = magic_arguments.parse_argstring(self.triqs, line)
code = cell if cell.endswith('\n') else cell + '\n' code = cell if cell.endswith('\n') else cell + '\n'
#if not GIL, we replace std::cout by triqs::py_out for capture in the notebook
if not use_GIL :
code = re.sub("std::cout", "triqs::py_stream()", code)
key = code, line, sys.version_info, sys.executable key = code, line, sys.version_info, sys.executable
c_decl = self.extract_signature(code) c_decl = self.extract_signature(code)

View File

@ -25,7 +25,7 @@
//#define CHECK_OR_THROW(Cond, Mess) //#define CHECK_OR_THROW(Cond, Mess)
#define CHECK_OR_THROW(Cond, Mess) \ #define CHECK_OR_THROW(Cond, Mess) \
if (!Cond) TRIQS_RUNTIME_ERROR << "Error in h5 (de)serialization " << Mess; if (!(Cond)) TRIQS_RUNTIME_ERROR << "Error in h5 (de)serialization " << Mess;
namespace triqs { namespace triqs {
namespace h5 { namespace h5 {

View File

@ -0,0 +1,36 @@
/*******************************************************************************
*
* TRIQS: a Toolbox for Research in Interacting Quantum Systems
*
* Copyright (C) 2014 by O. Parcollet
*
* TRIQS is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* TRIQS 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 Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* TRIQS. If not, see <http://www.gnu.org/licenses/>.
*
******************************************************************************/
#define TRIQS_LIB_CPP
#include "./py_stream.hpp"
#include "../utility/exceptions.hpp"
namespace triqs {
using py_tools::pyref;
py_stream::py_stream() {
if (!Py_IsInitialized()) TRIQS_RUNTIME_ERROR << "Construction of a py_stream before the interpreter is initialized !!";
sys = pyref::module("sys");
sys_out = sys.attr("stdout");
}
void py_stream::_write(const char* s) { pyref res = PyObject_CallMethod(sys_out, "write", "s", s); }
}

View File

@ -0,0 +1,58 @@
/*******************************************************************************
*
* TRIQS: a Toolbox for Research in Interacting Quantum Systems
*
* Copyright (C) 2014 by O. Parcollet
*
* TRIQS is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* TRIQS 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 Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* TRIQS. If not, see <http://www.gnu.org/licenses/>.
*
******************************************************************************/
#pragma once
#include <ostream>
#include <sstream>
#include "./pyref.hpp"
namespace triqs {
/**
*/
class py_stream {
py_tools::pyref sys, sys_out;
void _write(const char* s);
public:
py_stream();
template <class T> py_stream& operator<<(T const& x) {
std::stringstream fs;
fs << x;
_write(fs.str().c_str());
return *this;
}
// this is the type of std::cout
typedef std::basic_ostream<char, std::char_traits<char>> CoutType;
// this is the function signature of std::endl
typedef CoutType& (*StandardEndLine)(CoutType&);
// define an operator<< to take in std::endl
py_stream& operator<<(StandardEndLine manip) {
_write("\n");
return *this;
}
};
}

View File

@ -0,0 +1,62 @@
#pragma once
#include <Python.h>
namespace triqs {
namespace py_tools {
//--------------------- pyref -----------------------------
// a little class to hold an owned ref, make sure it is decref at destruction
class pyref {
PyObject *ob = NULL;
public:
pyref() = default;
pyref(PyObject *new_ref) : ob(new_ref) {}
~pyref() { Py_XDECREF(ob); }
operator PyObject *() const { return ob; }
PyObject *new_ref() const {
Py_XINCREF(ob);
return ob;
}
explicit operator bool() const { return (ob != NULL); }
bool is_null() const { return ob == NULL; }
bool is_None() const { return ob == Py_None; }
pyref attr(const char *s) {
return (ob ? PyObject_GetAttrString(ob, s) : NULL);
} // NULL : pass the error in chain call x.attr().attr()....
pyref operator()(PyObject *a1) {
return (ob ? PyObject_CallFunctionObjArgs(ob, a1, NULL) : NULL);
} // NULL : pass the error in chain call x.attr().attr()....
pyref operator()(PyObject *a1, PyObject *a2) {
return (ob ? PyObject_CallFunctionObjArgs(ob, a1, a2, NULL) : NULL);
} // NULL : pass the error in chain call x.attr().attr()....
pyref(pyref const &p) {
ob = p.ob;
Py_XINCREF(ob);
}
pyref(pyref &&p) {
ob = p.ob;
p.ob = NULL;
}
pyref &operator=(pyref const &) = delete;
pyref &operator=(pyref &&p) {
ob = p.ob;
p.ob = NULL;
return *this;
}
static pyref module(std::string const &module_name) { return PyImport_ImportModule(module_name.c_str()); }
static pyref string(std::string const &s) { return PyString_FromString(s.c_str()); }
};
inline pyref borrowed(PyObject *ob) {
Py_XINCREF(ob);
return {ob};
}
}
}

View File

@ -5,6 +5,7 @@
#include <complex> #include <complex>
#include <vector> #include <vector>
#include <triqs/utility/exceptions.hpp> #include <triqs/utility/exceptions.hpp>
#include "./pyref.hpp"
#pragma clang diagnostic ignored "-Wdeprecated-writable-strings" #pragma clang diagnostic ignored "-Wdeprecated-writable-strings"
#pragma GCC diagnostic ignored "-Wwrite-strings" #pragma GCC diagnostic ignored "-Wwrite-strings"
@ -26,33 +27,6 @@
namespace triqs { namespace py_tools { namespace triqs { namespace py_tools {
//--------------------- pyref -----------------------------
// a little class to hold an owned ref, make sure it is decref at destruction
class pyref {
PyObject * ob = NULL;
public:
pyref() = default;
pyref(PyObject *new_ref) : ob(new_ref){}
~pyref() { Py_XDECREF(ob);}
operator PyObject *() const { return ob;}
PyObject * new_ref() const { Py_XINCREF(ob); return ob;}
explicit operator bool() const { return (ob!=NULL);}
bool is_null() const { return ob==NULL;}
bool is_None() const { return ob==Py_None;}
pyref attr(const char * s) { return (ob ? PyObject_GetAttrString(ob,s) : NULL);} // NULL : pass the error in chain call x.attr().attr()....
pyref operator()(PyObject * a1) { return (ob ? PyObject_CallFunctionObjArgs(ob,a1,NULL) : NULL);} // NULL : pass the error in chain call x.attr().attr()....
pyref operator()(PyObject * a1,PyObject * a2) { return (ob ? PyObject_CallFunctionObjArgs(ob,a1,a2,NULL) : NULL);} // NULL : pass the error in chain call x.attr().attr()....
pyref(pyref const&p) {ob = p.ob; Py_XINCREF(ob);}
pyref(pyref && p){ ob = p.ob; p.ob=NULL;}
pyref& operator =(pyref const&) = delete;
pyref& operator =(pyref &&p) {ob = p.ob; p.ob=NULL; return *this;}
static pyref module(std::string const &module_name) { return PyImport_ImportModule(module_name.c_str()); }
static pyref string(std::string const &s) { return PyString_FromString(s.c_str());}
};
inline pyref borrowed(PyObject * ob) { Py_XINCREF(ob); return {ob};}
//--------------------- py_converters ----------------------------- //--------------------- py_converters -----------------------------
// default version for a wrapped type. To be specialized later. // default version for a wrapped type. To be specialized later.