Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/pydict #1

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
212 changes: 212 additions & 0 deletions lass/python/pydict_ptr.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
/** @file
* @author Bram de Greve ([email protected])
* @author Tom De Muer ([email protected])
*
* *** BEGIN LICENSE INFORMATION ***
*
* The contents of this file are subject to the Common Public Attribution License
* Version 1.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://lass.sourceforge.net/cpal-license. The License is based on the
* Mozilla Public License Version 1.1 but Sections 14 and 15 have been added to cover
* use of software over a computer network and provide for limited attribution for
* the Original Developer. In addition, Exhibit A has been modified to be consistent
* with Exhibit B.
*
* Software distributed under the License is distributed on an "AS IS" basis, WITHOUT
* WARRANTY OF ANY KIND, either express or implied. See the License for the specific
* language governing rights and limitations under the License.
*
* The Original Code is LASS - Library of Assembled Shared Sources.
*
* The Initial Developer of the Original Code is Bram de Greve and Tom De Muer.
* The Original Developer is the Initial Developer.
*
* All portions of the code written by the Initial Developer are:
* Copyright (C) 2004-2011 the Initial Developer.
* All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of the
* GNU General Public License Version 2 or later (the GPL), in which case the
* provisions of GPL are applicable instead of those above. If you wish to allow use
* of your version of this file only under the terms of the GPL and not to allow
* others to use your version of this file under the CPAL, indicate your decision by
* deleting the provisions above and replace them with the notice and other
* provisions required by the GPL License. If you do not delete the provisions above,
* a recipient may use your version of this file under either the CPAL or the GPL.
*
* *** END LICENSE INFORMATION ***
*/

#include "python_common.h"
#include "pydict_ptr.h"

namespace lass
{
namespace python
{
namespace experimental
{

PyDictPtr::PyDictPtr() :
obj_(0)
{
}


/**
* steals a reference to obj.
*/
PyDictPtr::PyDictPtr(PyObject* obj):
obj_(obj)
{
if (obj && !PyDict_Check(obj))
throw PythonException(PyExc_TypeError, "Not a dict", LASS_HERE);
}


/**
* returns a borrowed reference
*/
PyObject* PyDictPtr::get() const
{
return obj_.get();
}


bool PyDictPtr::operator!() const
{
return !obj_;
}


PyDictPtr::operator num::SafeBool() const
{
return obj_ ? num::safeTrue : num::safeFalse;
}


void PyDictPtr::setItem(PyObject* key, PyObject* val)
{
LockGIL LASS_UNUSED(lock);
PY_ENFORCE_ZERO(PyDict_SetItem(get(), key, val));
}


void PyDictPtr::setItem(const TPyObjPtr& key, const TPyObjPtr& val)
{
setItem(key.get(), val.get());
}


TPyObjPtr PyDictPtr::getItem(PyObject* key) const
{
LockGIL LASS_UNUSED(lock);
#if PY_MAJOR_VERSION >= 3
PyObject* const borrowed = PyDict_GetItemWithError(get(), key);
#else
// for historical reasons, PyDict_GetItem PyDict_GetItem() suppresses all
// errors that may occur (like hash errors, or stack depth errors)
PyObject* const borrowed = PyDict_GetItem(get(), key);
#endif
if (!borrowed)
{
if (PyErr_Occurred())
{
impl::fetchAndThrowPythonException(LASS_HERE);
}
throw PythonException(PyExc_KeyError, "Key error", LASS_HERE);
}
return fromNakedToSharedPtrCast<PyObject>(borrowed);
}


TPyObjPtr PyDictPtr::getItem(const TPyObjPtr& key) const
{
return getItem(key.get());
}


void PyDictPtr::delItem(PyObject* key)
{
LockGIL LASS_UNUSED(lock);
if (PyDict_DelItem(get(), key) != 0)
impl::fetchAndThrowPythonException(LASS_HERE);
}


void PyDictPtr::delItem(const TPyObjPtr& key)
{
delItem(key.get());
}


bool PyDictPtr::contains(PyObject* key) const
{
LockGIL LASS_UNUSED(lock);
switch (PyDict_Contains(get(), key))
{
case -1:
impl::fetchAndThrowPythonException(LASS_HERE);
break;
case 0:
return false;
case 1:
return true;
}
// this should be unreachable.
throw PythonException(PyExc_SystemError, "bad internal call.", LASS_HERE);
}


bool PyDictPtr::contains(const TPyObjPtr& key) const
{
return contains(key.get());
}


Py_ssize_t PyDictPtr::size() const
{
LockGIL LASS_UNUSED(lock);
const Py_ssize_t ret = PyDict_Size(get());
if (ret == -1)
impl::fetchAndThrowPythonException(LASS_HERE);
return ret;
}


}


PyObject* PyExportTraits<experimental::PyDictPtr>::build(const experimental::PyDictPtr& v)
{
if (PyObject* const obj = v.get())
{
Py_INCREF(obj);
return obj;
}
Py_RETURN_NONE;
}


int PyExportTraits<experimental::PyDictPtr>::get(PyObject* obj, experimental::PyDictPtr& v)
{
if (obj == Py_None)
{
v = experimental::PyDictPtr(0);
}
if (!PyDict_Check(obj))
{
PyErr_SetString(PyExc_TypeError, "not a dict");
return 1;
}
Py_INCREF(obj); // obj is borrowed, but PyDictPtr steals a reference
v = experimental::PyDictPtr(obj);
return 0;
}


}
}
127 changes: 127 additions & 0 deletions lass/python/pydict_ptr.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
/** @file
* @author Bram de Greve ([email protected])
* @author Tom De Muer ([email protected])
*
* *** BEGIN LICENSE INFORMATION ***
*
* The contents of this file are subject to the Common Public Attribution License
* Version 1.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://lass.sourceforge.net/cpal-license. The License is based on the
* Mozilla Public License Version 1.1 but Sections 14 and 15 have been added to cover
* use of software over a computer network and provide for limited attribution for
* the Original Developer. In addition, Exhibit A has been modified to be consistent
* with Exhibit B.
*
* Software distributed under the License is distributed on an "AS IS" basis, WITHOUT
* WARRANTY OF ANY KIND, either express or implied. See the License for the specific
* language governing rights and limitations under the License.
*
* The Original Code is LASS - Library of Assembled Shared Sources.
*
* The Initial Developer of the Original Code is Bram de Greve and Tom De Muer.
* The Original Developer is the Initial Developer.
*
* All portions of the code written by the Initial Developer are:
* Copyright (C) 2004-2018 the Initial Developer.
* All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of the
* GNU General Public License Version 2 or later (the GPL), in which case the
* provisions of GPL are applicable instead of those above. If you wish to allow use
* of your version of this file only under the terms of the GPL and not to allow
* others to use your version of this file under the CPAL, indicate your decision by
* deleting the provisions above and replace them with the notice and other
* provisions required by the GPL License. If you do not delete the provisions above,
* a recipient may use your version of this file under either the CPAL or the GPL.
*
* *** END LICENSE INFORMATION ***
*/

#ifndef LASS_GUARDIAN_OF_INCLUSION_PYTHON_PYDICT_PTR_H
#define LASS_GUARDIAN_OF_INCLUSION_PYTHON_PYDICT_PTR_H

#include "python_common.h"
#include "pyobject_ptr.h"
#include "pyobject_plus.h"

namespace lass
{
namespace python
{
namespace experimental
{

class LASS_PYTHON_DLL PyDictPtr
{
public:
PyDictPtr();
explicit PyDictPtr(PyObject* obj);

PyObject* get() const;
bool operator!() const;
operator num::SafeBool() const;

TPyObjPtr getItem(PyObject* key) const;
TPyObjPtr getItem(const TPyObjPtr& key) const;
template <typename K>
TPyObjPtr getItem(const K& key) const
{
TPyObjPtr k(pyBuildSimpleObject(key));
return getItem(k.get());
}

void setItem(PyObject* key, PyObject* val);
void setItem(const TPyObjPtr& key, const TPyObjPtr& val);
template <typename K, typename V>
void setItem(const K& key, const V& val)
{
TPyObjPtr k(pyBuildSimpleObject(key));
TPyObjPtr v(pyBuildSimpleObject(val));
setItem(k.get(), v.get());
}

void delItem(PyObject* key);
void delItem(const TPyObjPtr& key);
template <typename K>
void delItem(const K& key)
{
TPyObjPtr k(pyBuildSimpleObject(key));
return delItem(k.get());
}

bool contains(PyObject* key) const;
bool contains(const TPyObjPtr& key) const;
template <typename K>
bool contains(const K& key) const
{
TPyObjPtr k(pyBuildSimpleObject(key));
return getItem(k.get());
}

Py_ssize_t size() const;

private:
TPyObjPtr obj_;
};


}


template <>
struct PyExportTraits<experimental::PyDictPtr>
{
LASS_PYTHON_DLL static PyObject* build(const experimental::PyDictPtr& v);
LASS_PYTHON_DLL static int get(PyObject* obj, experimental::PyDictPtr& v);
};


}
}

#endif

// EOF
25 changes: 21 additions & 4 deletions lass/python/utilities.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,19 +65,36 @@ TPyObjPtr runString(const char *code, int start)
/** @ingroup Python
* @brief retrieve pointer to PyObject by its name in the script.
* @return
* new reference to PyObject @a iName or NULL if
* @a iName does not exist (_without_ setting an exception!)
* new reference to PyObject @a name or NULL if
* @a name does not exist (_without_ setting an exception!)
*/
TPyObjPtr getPyObjectByName(const std::string& iName)
TPyObjPtr getPyObjectByName(const std::string& name)
{
LockGIL LASS_UNUSED(lock);
const TPyObjPtr dict = globals();
const TPyObjPtr key(PY_ENFORCE_POINTER(pyBuildSimpleObject(iName)));
const TPyObjPtr key(PY_ENFORCE_POINTER(pyBuildSimpleObject(name)));
PyObject* const object = PyDict_GetItem(dict.get(), key.get());
return fromNakedToSharedPtrCast<PyObject>(object);
}


/** @ingroup Python
* @brief retrieve pointer to PyObject by its name in a module
* The module is imported by absolute import.
* @return
* new reference to PyObject @a name or NULL if
* @a name does not exist (_without_ setting an exception!)
*/
TPyObjPtr getPyObjectByName(const std::string& module, const std::string& name)
{
LockGIL LASS_UNUSED(lock);
const TPyObjPtr mod(PyImport_ImportModule(module.c_str()));
PyObject* const dict = PY_ENFORCE_POINTER(PyModule_GetDict(mod.get())); // borrowed
const TPyObjPtr key(PY_ENFORCE_POINTER(pyBuildSimpleObject(name)));
PyObject* const object = PyDict_GetItem(dict, key.get());
return fromNakedToSharedPtrCast<PyObject>(object);
}


/** @ingroup Python
*/
Expand Down
3 changes: 2 additions & 1 deletion lass/python/utilities.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ namespace lass
namespace python
{

LASS_PYTHON_DLL TPyObjPtr LASS_CALL getPyObjectByName(const std::string& iName);
LASS_PYTHON_DLL TPyObjPtr LASS_CALL getPyObjectByName(const std::string& name);
LASS_PYTHON_DLL TPyObjPtr LASS_CALL getPyObjectByName(const std::string& module, const std::string& name);
LASS_PYTHON_DLL TPyObjPtr LASS_CALL globals();

LASS_PYTHON_DLL void LASS_CALL execute(const std::string& code);
Expand Down
Loading