diff options
Diffstat (limited to 'lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h')
-rw-r--r-- | lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h | 202 |
1 files changed, 84 insertions, 118 deletions
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h b/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h index b794810c1b7..43ffd8d339b 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h +++ b/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h @@ -25,6 +25,25 @@ // Expected<> is considered deprecated and should not be // used in new code. If you need to use it, fix it first. // +// +// TODOs for this file +// +// * Make all methods safe for exceptions. +// +// * Eliminate method signatures that must translate exceptions into +// empty objects or NULLs. Almost everything here should return +// Expected<>. It should be acceptable for certain operations that +// can never fail to assert instead, such as the creation of +// PythonString from a string literal. +// +// * Elimintate Reset(), and make all non-default constructors private. +// Python objects should be created with Retain<> or Take<>, and they +// should be assigned with operator= +// +// * Eliminate default constructors, make python objects always +// nonnull, and use optionals where necessary. +// + #ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H #define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H @@ -170,20 +189,15 @@ public: rhs.m_py_obj = nullptr; } - virtual ~PythonObject() { Reset(); } + ~PythonObject() { Reset(); } void Reset() { - // Avoid calling the virtual method since it's not necessary - // to actually validate the type of the PyObject if we're - // just setting to null. if (m_py_obj && Py_IsInitialized()) Py_DECREF(m_py_obj); m_py_obj = nullptr; } void Reset(const PythonObject &rhs) { - // Avoid calling the virtual method if it's not necessary - // to actually validate the type of the PyObject. if (!rhs.IsValid()) Reset(); else @@ -196,9 +210,7 @@ public: // PyRefType doesn't make sense, and the copy constructor should be used. void Reset(PyRefType type, const PythonObject &ref) = delete; - // FIXME We shouldn't have virtual anything. PythonObject should be a - // strictly pass-by-value type. - virtual void Reset(PyRefType type, PyObject *py_obj) { + void Reset(PyRefType type, PyObject *py_obj) { if (py_obj == m_py_obj) return; @@ -376,21 +388,37 @@ llvm::Expected<long long> As<long long>(llvm::Expected<PythonObject> &&obj); } // namespace python -class PythonBytes : public PythonObject { +template <class T> class TypedPythonObject : public PythonObject { public: - PythonBytes(); - explicit PythonBytes(llvm::ArrayRef<uint8_t> bytes); - PythonBytes(const uint8_t *bytes, size_t length); - PythonBytes(PyRefType type, PyObject *o); + // override to perform implicit type conversions on Reset + // This can be eliminated once we drop python 2 support. + static void Convert(PyRefType &type, PyObject *&py_obj) {} - ~PythonBytes() override; + using PythonObject::Reset; - static bool Check(PyObject *py_obj); + void Reset(PyRefType type, PyObject *py_obj) { + Reset(); + if (!py_obj) + return; + T::Convert(type, py_obj); + if (T::Check(py_obj)) + PythonObject::Reset(type, py_obj); + else if (type == PyRefType::Owned) + Py_DECREF(py_obj); + } - // Bring in the no-argument base class version - using PythonObject::Reset; + TypedPythonObject(PyRefType type, PyObject *py_obj) { Reset(type, py_obj); } + + TypedPythonObject() {} +}; + +class PythonBytes : public TypedPythonObject<PythonBytes> { +public: + using TypedPythonObject::TypedPythonObject; + explicit PythonBytes(llvm::ArrayRef<uint8_t> bytes); + PythonBytes(const uint8_t *bytes, size_t length); - void Reset(PyRefType type, PyObject *py_obj) override; + static bool Check(PyObject *py_obj); llvm::ArrayRef<uint8_t> GetBytes() const; @@ -401,23 +429,15 @@ public: StructuredData::StringSP CreateStructuredString() const; }; -class PythonByteArray : public PythonObject { +class PythonByteArray : public TypedPythonObject<PythonByteArray> { public: - PythonByteArray(); + using TypedPythonObject::TypedPythonObject; explicit PythonByteArray(llvm::ArrayRef<uint8_t> bytes); PythonByteArray(const uint8_t *bytes, size_t length); - PythonByteArray(PyRefType type, PyObject *o); PythonByteArray(const PythonBytes &object); - ~PythonByteArray() override; - static bool Check(PyObject *py_obj); - // Bring in the no-argument base class version - using PythonObject::Reset; - - void Reset(PyRefType type, PyObject *py_obj) override; - llvm::ArrayRef<uint8_t> GetBytes() const; size_t GetSize() const; @@ -427,22 +447,17 @@ public: StructuredData::StringSP CreateStructuredString() const; }; -class PythonString : public PythonObject { +class PythonString : public TypedPythonObject<PythonString> { public: + using TypedPythonObject::TypedPythonObject; static llvm::Expected<PythonString> FromUTF8(llvm::StringRef string); - PythonString(); - explicit PythonString(llvm::StringRef string); // safe, null on error - PythonString(PyRefType type, PyObject *o); + PythonString() : TypedPythonObject() {} // MSVC requires this for some reason - ~PythonString() override; + explicit PythonString(llvm::StringRef string); // safe, null on error static bool Check(PyObject *py_obj); - - // Bring in the no-argument base class version - using PythonObject::Reset; - - void Reset(PyRefType type, PyObject *py_obj) override; + static void Convert(PyRefType &type, PyObject *&py_obj); llvm::StringRef GetString() const; // safe, empty string on error @@ -455,20 +470,16 @@ public: StructuredData::StringSP CreateStructuredString() const; }; -class PythonInteger : public PythonObject { +class PythonInteger : public TypedPythonObject<PythonInteger> { public: - PythonInteger(); - explicit PythonInteger(int64_t value); - PythonInteger(PyRefType type, PyObject *o); + using TypedPythonObject::TypedPythonObject; - ~PythonInteger() override; + PythonInteger() : TypedPythonObject() {} // MSVC requires this for some reason - static bool Check(PyObject *py_obj); - - // Bring in the no-argument base class version - using PythonObject::Reset; + explicit PythonInteger(int64_t value); - void Reset(PyRefType type, PyObject *py_obj) override; + static bool Check(PyObject *py_obj); + static void Convert(PyRefType &type, PyObject *&py_obj); int64_t GetInteger() const; @@ -477,21 +488,14 @@ public: StructuredData::IntegerSP CreateStructuredInteger() const; }; -class PythonBoolean : public PythonObject { +class PythonBoolean : public TypedPythonObject<PythonBoolean> { public: - PythonBoolean() = default; - explicit PythonBoolean(bool value); - PythonBoolean(PyRefType type, PyObject *o); + using TypedPythonObject::TypedPythonObject; - ~PythonBoolean() override = default; + explicit PythonBoolean(bool value); static bool Check(PyObject *py_obj); - // Bring in the no-argument base class version - using PythonObject::Reset; - - void Reset(PyRefType type, PyObject *py_obj) override; - bool GetValue() const; void SetValue(bool value); @@ -499,22 +503,17 @@ public: StructuredData::BooleanSP CreateStructuredBoolean() const; }; -class PythonList : public PythonObject { +class PythonList : public TypedPythonObject<PythonList> { public: - PythonList() {} + using TypedPythonObject::TypedPythonObject; + + PythonList() : TypedPythonObject() {} // MSVC requires this for some reason + explicit PythonList(PyInitialValue value); explicit PythonList(int list_size); - PythonList(PyRefType type, PyObject *o); - - ~PythonList() override; static bool Check(PyObject *py_obj); - // Bring in the no-argument base class version - using PythonObject::Reset; - - void Reset(PyRefType type, PyObject *py_obj) override; - uint32_t GetSize() const; PythonObject GetItemAtIndex(uint32_t index) const; @@ -526,24 +525,17 @@ public: StructuredData::ArraySP CreateStructuredArray() const; }; -class PythonTuple : public PythonObject { +class PythonTuple : public TypedPythonObject<PythonTuple> { public: - PythonTuple() {} + using TypedPythonObject::TypedPythonObject; + explicit PythonTuple(PyInitialValue value); explicit PythonTuple(int tuple_size); - PythonTuple(PyRefType type, PyObject *o); PythonTuple(std::initializer_list<PythonObject> objects); PythonTuple(std::initializer_list<PyObject *> objects); - ~PythonTuple() override; - static bool Check(PyObject *py_obj); - // Bring in the no-argument base class version - using PythonObject::Reset; - - void Reset(PyRefType type, PyObject *py_obj) override; - uint32_t GetSize() const; PythonObject GetItemAtIndex(uint32_t index) const; @@ -553,20 +545,15 @@ public: StructuredData::ArraySP CreateStructuredArray() const; }; -class PythonDictionary : public PythonObject { +class PythonDictionary : public TypedPythonObject<PythonDictionary> { public: - PythonDictionary() {} - explicit PythonDictionary(PyInitialValue value); - PythonDictionary(PyRefType type, PyObject *o); + using TypedPythonObject::TypedPythonObject; - ~PythonDictionary() override; + PythonDictionary() : TypedPythonObject() {} // MSVC requires this for some reason - static bool Check(PyObject *py_obj); - - // Bring in the no-argument base class version - using PythonObject::Reset; + explicit PythonDictionary(PyInitialValue value); - void Reset(PyRefType type, PyObject *py_obj) override; + static bool Check(PyObject *py_obj); uint32_t GetSize() const; @@ -578,12 +565,9 @@ public: StructuredData::DictionarySP CreateStructuredDictionary() const; }; -class PythonModule : public PythonObject { +class PythonModule : public TypedPythonObject<PythonModule> { public: - PythonModule(); - PythonModule(PyRefType type, PyObject *o); - - ~PythonModule() override; + using TypedPythonObject::TypedPythonObject; static bool Check(PyObject *py_obj); @@ -608,16 +592,13 @@ public: llvm::Expected<PythonObject> Get(const char *name); - // Bring in the no-argument base class version - using PythonObject::Reset; - - void Reset(PyRefType type, PyObject *py_obj) override; - PythonDictionary GetDictionary() const; }; -class PythonCallable : public PythonObject { +class PythonCallable : public TypedPythonObject<PythonCallable> { public: + using TypedPythonObject::TypedPythonObject; + struct ArgInfo { size_t count; bool is_bound_method : 1; @@ -625,18 +606,8 @@ public: bool has_kwargs : 1; }; - PythonCallable(); - PythonCallable(PyRefType type, PyObject *o); - - ~PythonCallable() override; - static bool Check(PyObject *py_obj); - // Bring in the no-argument base class version - using PythonObject::Reset; - - void Reset(PyRefType type, PyObject *py_obj) override; - ArgInfo GetNumArguments() const; // If the callable is a Py_Class, then find the number of arguments @@ -655,19 +626,14 @@ public: } }; -class PythonFile : public PythonObject { +class PythonFile : public TypedPythonObject<PythonFile> { public: - PythonFile(); - PythonFile(PyRefType type, PyObject *o); + using TypedPythonObject::TypedPythonObject; - ~PythonFile() override; + PythonFile() : TypedPythonObject() {} // MSVC requires this for some reason static bool Check(PyObject *py_obj); - using PythonObject::Reset; - - void Reset(PyRefType type, PyObject *py_obj) override; - static llvm::Expected<PythonFile> FromFile(File &file, const char *mode = nullptr); |