Skip to content

Commit

Permalink
added support for set
Browse files Browse the repository at this point in the history
  • Loading branch information
FadyEssam committed Mar 3, 2019
1 parent 4f6d547 commit 6317791
Show file tree
Hide file tree
Showing 4 changed files with 296 additions and 0 deletions.
100 changes: 100 additions & 0 deletions include/boost/python/set.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
// Copyright Fady Essam 2019. Distributed under the Boost
// Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef SET_BOOST_PYTHON_HH
#define SET_BOOST_PYTHON_HH

#include <boost/python/ssize_t.hpp>
#include <boost/python.hpp>


namespace boost {
namespace python {

namespace detail
{
struct BOOST_PYTHON_DECL set_base : object
{
void add(object_cref); // add object to set

object pop(); // remove and return item at top

void discard(object_cref x); // discard value from set

long __len__(); // length of set

void clear(); // empties set

protected:
set_base();
explicit set_base(object_cref sequence); // new set initialized from sequence's items

BOOST_PYTHON_FORWARD_OBJECT_CONSTRUCTORS(set_base, object)
private:
static detail::new_non_null_reference call(object const&);
};


}






class set : public detail::set_base
{
typedef detail::set_base base;
public:
set() {}

template <class T>
explicit set(T const& sequence)
: base(object(sequence))
{
}

template <class T>
void add(T const& x)
{
base::add(object(x));
}

object pop() { return base::pop(); }

template <class T>
void discard(T const& value)
{
base::discard(object(value));
}

void clear() { base::clear(); }

long __len__() { return base::__len__(); }



public:
BOOST_PYTHON_FORWARD_OBJECT_CONSTRUCTORS(set, base)
};


namespace converter
{
template <>
struct object_manager_traits<set>
: pytype_object_manager_traits<&PySet_Type, set>
{
};
}


}

}





#endif // !SET_BOOST_PYTHON_HH
83 changes: 83 additions & 0 deletions src/set.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
// Copyright Fady Essam 2019. Distributed under the Boost
// Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/python/set.hpp>


namespace boost {
namespace python {
namespace detail {


detail::new_non_null_reference set_base::call(object_cref arg_)
{
return (detail::new_non_null_reference)
(expect_non_null)(
PySet_New(arg_.ptr())
);
}

set_base::set_base()
: object(detail::new_reference(PySet_New(NULL)))
{}

set_base::set_base(object_cref sequence)
: object(set_base::call(sequence))
{}

void set_base::add(object_cref x)
{
if (PyAnySet_CheckExact(this->ptr()))
{
if (PySet_Add(this->ptr(), x.ptr()) == -1)
throw_error_already_set();
}
else
{
this->attr("add")(x);
}
}


void set_base::discard(object_cref x)
{
if (PyAnySet_CheckExact(this->ptr()))
{
if (PySet_Discard(this->ptr(), x.ptr()) == -1)
throw_error_already_set();
}
else
{
this->attr("discrad")(x);
}
}

object set_base::pop()
{
return this->attr("pop")();
}

void set_base::clear()
{
this->attr("clear")();
}

long set_base::__len__()
{
return extract<long>(object(PySet_Size(this->ptr())))();
}


static struct register_set_pytype_ptr
{
register_set_pytype_ptr()
{
const_cast<converter::registration &>(
converter::registry::lookup(boost::python::type_id<boost::python::set>())
).m_class_object = &PySet_Type;
}
}register_set_pytype_ptr_;

}
}
}
79 changes: 79 additions & 0 deletions test/set.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// Copyright Fady Essam 2019. Distributed under the Boost
// Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/python/module.hpp>
#define BOOST_ENABLE_ASSERT_HANDLER
#include <boost/assert.hpp>

#include <boost/python/def.hpp>
#include <boost/python/class.hpp>
#include <boost/python/set.hpp>
#include <exception>
#include <string>
#include <iostream>

using namespace boost::python;

object new_set()
{
return set();
}

object data_set()
{
set tmp1;
tmp1.add("value1");

tmp1.add(2);
return tmp1;
}

object set_from_sequence(object sequence)
{
return set(sequence);
}


void work_with_set(set data1)
{
if (!data1.contains("k1")) {
std::cout << "data1 doesn't have k1" << std::endl;
}
data1.add("k1");

if (data1.contains("k1")) {
std::cout << "data1 now has k1" << std::endl;
}

data1.discard("k1");
if (!data1.contains("k1")) {
std::cout << "data1 doesn't have k1 again" << std::endl;
}

}

void test_templates(object print)
{
std::string key = "key";

set tmp;
tmp.add("a test string");
print(tmp);
tmp.add(13);
print(tmp.contains(1.5));
print(tmp.contains(13));
print(tmp);

BOOST_ASSERT(tmp.__len__() == 2);
}

BOOST_PYTHON_MODULE(set_ext)
{
def("new_set", new_set);
def("data_set", data_set);
def("set_from_sequence", set_from_sequence);
def("work_with_set", work_with_set);
def("test_templates", test_templates);
}

#include "module_tail.cpp"
34 changes: 34 additions & 0 deletions test/set.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Copyright Fady Essam 2019. Distributed under the Boost
# Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
from __future__ import print_function
"""
>>> import set_ext
>>> set_ext.new_set()
set()
>>> set_ext.data_set()
{2, 'value1'}
>>> set_ext.set_from_sequence([1,2,3,3])
{1, 2, 3}
>>> s = set_ext.new_set()
>>> set_ext.test_templates(print)
{'a test string'}
False
True
{'a test string', 13}
"""

def run(args = None):
import sys
import doctest

if args is not None:
sys.argv = args
return doctest.testmod(sys.modules.get(__name__))

if __name__ == '__main__':
print("running...")
import sys
status = run()[0]
if (status == 0): print("Done.")
sys.exit(status)

0 comments on commit 6317791

Please sign in to comment.