SBFile::GetFile: convert SBFile back into python native files.

Summary:
This makes SBFile::GetFile public and adds a SWIG typemap to convert
the result back into a python native file.

If the underlying File itself came from a python file, it is returned
identically.   Otherwise a new python file object is created using
the file descriptor.

Reviewers: JDevlieghere, jasonmolenda, labath

Reviewed By: labath

Subscribers: lldb-commits

Tags: #lldb

Differential Revision: https://reviews.llvm.org/D68737

llvm-svn: 374911
This commit is contained in:
Lawrence D'Anna
2019-10-15 16:46:27 +00:00
parent 1184c27fa5
commit d9b553ec99
9 changed files with 200 additions and 26 deletions

View File

@@ -22,6 +22,7 @@
#include "lldb/Utility/Stream.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/Errno.h"
@@ -1012,8 +1013,6 @@ operator()(std::initializer_list<PythonObject> args) {
PythonFile::PythonFile() : PythonObject() {}
PythonFile::PythonFile(File &file, const char *mode) { Reset(file, mode); }
PythonFile::PythonFile(PyRefType type, PyObject *o) { Reset(type, o); }
PythonFile::~PythonFile() {}
@@ -1063,25 +1062,6 @@ void PythonFile::Reset(PyRefType type, PyObject *py_obj) {
PythonObject::Reset(PyRefType::Borrowed, result.get());
}
void PythonFile::Reset(File &file, const char *mode) {
if (!file.IsValid()) {
Reset();
return;
}
char *cmode = const_cast<char *>(mode);
#if PY_MAJOR_VERSION >= 3
Reset(PyRefType::Owned, PyFile_FromFd(file.GetDescriptor(), nullptr, cmode,
-1, nullptr, "ignore", nullptr, 0));
#else
// Read through the Python source, doesn't seem to modify these strings
Reset(PyRefType::Owned,
PyFile_FromFile(file.GetStream(), const_cast<char *>(""), cmode,
nullptr));
#endif
}
FileUP PythonFile::GetUnderlyingFile() const {
if (!IsValid())
return nullptr;
@@ -1238,6 +1218,13 @@ public:
return base_error;
};
PyObject *GetPythonObject() const {
assert(m_py_obj.IsValid());
return m_py_obj.get();
}
static bool classof(const File *file) = delete;
protected:
PythonFile m_py_obj;
bool m_borrowed;
@@ -1252,7 +1239,14 @@ public:
SimplePythonFile(const PythonFile &file, bool borrowed, int fd,
File::OpenOptions options)
: OwnedPythonFile(file, borrowed, fd, options, false) {}
static char ID;
bool isA(const void *classID) const override {
return classID == &ID || NativeFile::isA(classID);
}
static bool classof(const File *file) { return file->isA(&ID); }
};
char SimplePythonFile::ID = 0;
} // namespace
#if PY_MAJOR_VERSION >= 3
@@ -1321,7 +1315,18 @@ public:
return Status();
}
Expected<File::OpenOptions> GetOptions() const override {
GIL takeGIL;
return GetOptionsForPyObject(m_py_obj);
}
static char ID;
bool isA(const void *classID) const override {
return classID == &ID || File::isA(classID);
}
static bool classof(const File *file) { return file->isA(&ID); }
};
char PythonIOFile::ID = 0;
} // namespace
namespace {
@@ -1542,4 +1547,42 @@ PythonFile::ConvertToFileForcingUseOfScriptingIOMethods(bool borrowed) {
#endif
}
Expected<PythonFile> PythonFile::FromFile(File &file, const char *mode) {
if (!file.IsValid())
return llvm::createStringError(llvm::inconvertibleErrorCode(),
"invalid file");
if (auto *simple = llvm::dyn_cast<SimplePythonFile>(&file))
return Retain<PythonFile>(simple->GetPythonObject());
#if PY_MAJOR_VERSION >= 3
if (auto *pythonio = llvm::dyn_cast<PythonIOFile>(&file))
return Retain<PythonFile>(pythonio->GetPythonObject());
#endif
if (!mode) {
auto m = file.GetOpenMode();
if (!m)
return m.takeError();
mode = m.get();
}
PyObject *file_obj;
#if PY_MAJOR_VERSION >= 3
file_obj = PyFile_FromFd(file.GetDescriptor(), nullptr, mode, -1, nullptr,
"ignore", nullptr, 0);
#else
// Read through the Python source, doesn't seem to modify these strings
char *cmode = const_cast<char *>(mode);
// We pass ::flush instead of ::fclose here so we borrow the FILE* --
// the lldb_private::File still owns it.
file_obj =
PyFile_FromFile(file.GetStream(), const_cast<char *>(""), cmode, ::fflush);
#endif
if (!file_obj)
return exception();
return Take<PythonFile>(file_obj);
}
#endif