Skip to content

Commit 6317791

Browse files
committed
added support for set
1 parent 4f6d547 commit 6317791

File tree

4 files changed

+296
-0
lines changed

4 files changed

+296
-0
lines changed

include/boost/python/set.hpp

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
// Copyright Fady Essam 2019. Distributed under the Boost
2+
// Software License, Version 1.0. (See accompanying
3+
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
4+
#ifndef SET_BOOST_PYTHON_HH
5+
#define SET_BOOST_PYTHON_HH
6+
7+
#include <boost/python/ssize_t.hpp>
8+
#include <boost/python.hpp>
9+
10+
11+
namespace boost {
12+
namespace python {
13+
14+
namespace detail
15+
{
16+
struct BOOST_PYTHON_DECL set_base : object
17+
{
18+
void add(object_cref); // add object to set
19+
20+
object pop(); // remove and return item at top
21+
22+
void discard(object_cref x); // discard value from set
23+
24+
long __len__(); // length of set
25+
26+
void clear(); // empties set
27+
28+
protected:
29+
set_base();
30+
explicit set_base(object_cref sequence); // new set initialized from sequence's items
31+
32+
BOOST_PYTHON_FORWARD_OBJECT_CONSTRUCTORS(set_base, object)
33+
private:
34+
static detail::new_non_null_reference call(object const&);
35+
};
36+
37+
38+
}
39+
40+
41+
42+
43+
44+
45+
class set : public detail::set_base
46+
{
47+
typedef detail::set_base base;
48+
public:
49+
set() {}
50+
51+
template <class T>
52+
explicit set(T const& sequence)
53+
: base(object(sequence))
54+
{
55+
}
56+
57+
template <class T>
58+
void add(T const& x)
59+
{
60+
base::add(object(x));
61+
}
62+
63+
object pop() { return base::pop(); }
64+
65+
template <class T>
66+
void discard(T const& value)
67+
{
68+
base::discard(object(value));
69+
}
70+
71+
void clear() { base::clear(); }
72+
73+
long __len__() { return base::__len__(); }
74+
75+
76+
77+
public:
78+
BOOST_PYTHON_FORWARD_OBJECT_CONSTRUCTORS(set, base)
79+
};
80+
81+
82+
namespace converter
83+
{
84+
template <>
85+
struct object_manager_traits<set>
86+
: pytype_object_manager_traits<&PySet_Type, set>
87+
{
88+
};
89+
}
90+
91+
92+
}
93+
94+
}
95+
96+
97+
98+
99+
100+
#endif // !SET_BOOST_PYTHON_HH

src/set.cpp

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
// Copyright Fady Essam 2019. Distributed under the Boost
2+
// Software License, Version 1.0. (See accompanying
3+
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
4+
#include <boost/python/set.hpp>
5+
6+
7+
namespace boost {
8+
namespace python {
9+
namespace detail {
10+
11+
12+
detail::new_non_null_reference set_base::call(object_cref arg_)
13+
{
14+
return (detail::new_non_null_reference)
15+
(expect_non_null)(
16+
PySet_New(arg_.ptr())
17+
);
18+
}
19+
20+
set_base::set_base()
21+
: object(detail::new_reference(PySet_New(NULL)))
22+
{}
23+
24+
set_base::set_base(object_cref sequence)
25+
: object(set_base::call(sequence))
26+
{}
27+
28+
void set_base::add(object_cref x)
29+
{
30+
if (PyAnySet_CheckExact(this->ptr()))
31+
{
32+
if (PySet_Add(this->ptr(), x.ptr()) == -1)
33+
throw_error_already_set();
34+
}
35+
else
36+
{
37+
this->attr("add")(x);
38+
}
39+
}
40+
41+
42+
void set_base::discard(object_cref x)
43+
{
44+
if (PyAnySet_CheckExact(this->ptr()))
45+
{
46+
if (PySet_Discard(this->ptr(), x.ptr()) == -1)
47+
throw_error_already_set();
48+
}
49+
else
50+
{
51+
this->attr("discrad")(x);
52+
}
53+
}
54+
55+
object set_base::pop()
56+
{
57+
return this->attr("pop")();
58+
}
59+
60+
void set_base::clear()
61+
{
62+
this->attr("clear")();
63+
}
64+
65+
long set_base::__len__()
66+
{
67+
return extract<long>(object(PySet_Size(this->ptr())))();
68+
}
69+
70+
71+
static struct register_set_pytype_ptr
72+
{
73+
register_set_pytype_ptr()
74+
{
75+
const_cast<converter::registration &>(
76+
converter::registry::lookup(boost::python::type_id<boost::python::set>())
77+
).m_class_object = &PySet_Type;
78+
}
79+
}register_set_pytype_ptr_;
80+
81+
}
82+
}
83+
}

test/set.cpp

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
// Copyright Fady Essam 2019. Distributed under the Boost
2+
// Software License, Version 1.0. (See accompanying
3+
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
4+
#include <boost/python/module.hpp>
5+
#define BOOST_ENABLE_ASSERT_HANDLER
6+
#include <boost/assert.hpp>
7+
8+
#include <boost/python/def.hpp>
9+
#include <boost/python/class.hpp>
10+
#include <boost/python/set.hpp>
11+
#include <exception>
12+
#include <string>
13+
#include <iostream>
14+
15+
using namespace boost::python;
16+
17+
object new_set()
18+
{
19+
return set();
20+
}
21+
22+
object data_set()
23+
{
24+
set tmp1;
25+
tmp1.add("value1");
26+
27+
tmp1.add(2);
28+
return tmp1;
29+
}
30+
31+
object set_from_sequence(object sequence)
32+
{
33+
return set(sequence);
34+
}
35+
36+
37+
void work_with_set(set data1)
38+
{
39+
if (!data1.contains("k1")) {
40+
std::cout << "data1 doesn't have k1" << std::endl;
41+
}
42+
data1.add("k1");
43+
44+
if (data1.contains("k1")) {
45+
std::cout << "data1 now has k1" << std::endl;
46+
}
47+
48+
data1.discard("k1");
49+
if (!data1.contains("k1")) {
50+
std::cout << "data1 doesn't have k1 again" << std::endl;
51+
}
52+
53+
}
54+
55+
void test_templates(object print)
56+
{
57+
std::string key = "key";
58+
59+
set tmp;
60+
tmp.add("a test string");
61+
print(tmp);
62+
tmp.add(13);
63+
print(tmp.contains(1.5));
64+
print(tmp.contains(13));
65+
print(tmp);
66+
67+
BOOST_ASSERT(tmp.__len__() == 2);
68+
}
69+
70+
BOOST_PYTHON_MODULE(set_ext)
71+
{
72+
def("new_set", new_set);
73+
def("data_set", data_set);
74+
def("set_from_sequence", set_from_sequence);
75+
def("work_with_set", work_with_set);
76+
def("test_templates", test_templates);
77+
}
78+
79+
#include "module_tail.cpp"

test/set.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# Copyright Fady Essam 2019. Distributed under the Boost
2+
# Software License, Version 1.0. (See accompanying
3+
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
4+
from __future__ import print_function
5+
"""
6+
>>> import set_ext
7+
>>> set_ext.new_set()
8+
set()
9+
>>> set_ext.data_set()
10+
{2, 'value1'}
11+
>>> set_ext.set_from_sequence([1,2,3,3])
12+
{1, 2, 3}
13+
>>> s = set_ext.new_set()
14+
>>> set_ext.test_templates(print)
15+
{'a test string'}
16+
False
17+
True
18+
{'a test string', 13}
19+
"""
20+
21+
def run(args = None):
22+
import sys
23+
import doctest
24+
25+
if args is not None:
26+
sys.argv = args
27+
return doctest.testmod(sys.modules.get(__name__))
28+
29+
if __name__ == '__main__':
30+
print("running...")
31+
import sys
32+
status = run()[0]
33+
if (status == 0): print("Done.")
34+
sys.exit(status)

0 commit comments

Comments
 (0)