Skip to content

Commit

Permalink
Added tests to proto_to_pybind11
Browse files Browse the repository at this point in the history
  • Loading branch information
arturmiller committed Feb 2, 2019
1 parent 2276c73 commit a1f4544
Show file tree
Hide file tree
Showing 10 changed files with 229 additions and 2 deletions.
2 changes: 0 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
# ROS specific
build/
devel/
.catkin_tools/

Expand All @@ -17,7 +16,6 @@ __pycache__/

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
Expand Down
Empty file.
21 changes: 21 additions & 0 deletions alpyca_sim/build/pybind/pybind_block.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@

class PybindBlock():
def __init__(self, writer, braces=None):
self.writer = writer
self.braces = braces

def new_write_line(self, text):
self.org_write_line(' ' + text)

def __enter__(self):
if self.braces is not None:
self.writer.write_line(self.braces[0])

self.org_write_line = self.writer.write_line
self.writer.write_line = self.new_write_line

def __exit__(self, *args):
self.writer.write_line = self.org_write_line

if self.braces is not None:
self.writer.write_line(self.braces[1])
13 changes: 13 additions & 0 deletions alpyca_sim/build/pybind/pybind_class.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@

class PybindClass():
def __init__(self, writer):
self.writer = writer

def __enter__(self):
pass

def __exit__(self, *args):
self.writer.remove_last_char()
self.writer.write(';')
self.writer.new_line()
self.writer.new_line()
15 changes: 15 additions & 0 deletions alpyca_sim/build/pybind/pybind_file.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from pybind_writer import PybindWriter


class PybindFile():
def __init__(self, path):
self.path = path

def __enter__(self):
self.writer = PybindWriter()
return self.writer

def __exit__(self, *args):
pybind_file = open(self.path, 'w')
pybind_file.write(self.writer.text)
pybind_file.close()
73 changes: 73 additions & 0 deletions alpyca_sim/build/pybind/pybind_writer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
from pybind_class import PybindClass
from pybind_block import PybindBlock


class PybindWriter():
def __init__(self):
self.text = ''
self.repeated_types = set()

def write(self, text):
self.text += text

def remove_last_char(self):
self.text = self.text[:-1]

def write_line(self, text):
self.write(text)
self.new_line()

def include(self, text):
self.write_line('#include ' + text)

def new_line(self):
self.write('\n')

def includes(self):
self.include('<string>')
self.new_line()

self.include('<pybind11/pybind11.h>')
self.include('<pybind11/functional.h>')
self.include('<pybind11/stl.h>')
self.include('<gazebo/gazebo.hh>')
self.new_line()

self.include('\"alpyca/sim/repeated.h\"')
self.new_line()

def add_class(self, clsname, clsmember):
normalized_clsname = clsname.replace('::', '_')
self.write_line('py::class_<{clsname}>(m, \"{normalized_clsname}\")'.format(clsname=clsname, normalized_clsname=normalized_clsname))

with PybindClass(self):
for field in clsmember.DESCRIPTOR.fields:
if field.label == field.LABEL_REPEATED:
if field.message_type is not None:
attr_type = field.message_type.name
else:
dtype_mapper = {field.CPPTYPE_BOOL: 'bool',
field.CPPTYPE_DOUBLE: 'double',
field.CPPTYPE_FLOAT: 'float',
field.CPPTYPE_INT32: 'int32_t',
field.CPPTYPE_INT64: 'int64_t',
field.CPPTYPE_STRING: 'std::string',
field.CPPTYPE_UINT32: 'uint32_t',
field.CPPTYPE_UINT64: 'int64_t'}
attr_type = dtype_mapper[field.cpp_type]
if attr_type in dir(clsmember):
attr_type = '::'.join([clsname, attr_type])
self.repeated_types.add(attr_type)

self.write_line('.def_property_readonly(\"{attr}\", []({clsname} *obj) -> Repeated<{attr_type}>'.format(attr=field.name, clsname=clsname, attr_type=attr_type))
with PybindBlock(self, braces=('{', '})')):
self.write_line('std::function<{attr_type}(int)> func = [obj](int index) {{ return obj->{attr}(index); }};'.format(attr=field.name, attr_type=attr_type))
self.write_line('return Repeated<{attr_type}>(func, obj->{attr}_size());'.format(attr=field.name, attr_type=attr_type))
else:
self.write_line('.def_property_readonly(\"{attr}\", &{clsname}::{attr})'.format(attr=field.name, clsname=clsname))

def add_repeated(self, attr_type):
normalized_attr_type = attr_type.replace('::', '_')
self.write_line('py::class_<Repeated<{attr_type}>>(m, \"Repeated_{normalized_attr_type}\")'.format(attr_type=attr_type, normalized_attr_type=normalized_attr_type))
self.write_line('.def(\"__getitem__\", &Repeated<{}>::getitem);'.format(attr_type))
self.new_line()
25 changes: 25 additions & 0 deletions alpyca_sim/build/pybind/test_pybind_block.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import unittest

from pybind_block import PybindBlock
from pybind_writer import PybindWriter


class TestPybindBlock(unittest.TestCase):

def test_context_manager(self):
writer = PybindWriter()
with PybindBlock(writer):
writer.write_line('test')

self.assertEqual(writer.text, ' test\n')

def test_context_manager_with_braces(self):
writer = PybindWriter()
with PybindBlock(writer, braces=('{', '}')):
writer.write_line('test')

self.assertEqual(writer.text, '{\n test\n}\n')


if __name__ == '__main__':
unittest.main()
18 changes: 18 additions & 0 deletions alpyca_sim/build/pybind/test_pybind_class.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import unittest

from pybind_class import PybindClass
from pybind_writer import PybindWriter


class TestPybindClass(unittest.TestCase):

def test_context_manager(self):
writer = PybindWriter()
with PybindClass(writer):
writer.write_line('test')

self.assertEqual(writer.text, 'test;\n\n')


if __name__ == '__main__':
unittest.main()
22 changes: 22 additions & 0 deletions alpyca_sim/build/pybind/test_pybind_file.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import unittest
from mock import patch, mock_open

from pybind_file import PybindFile


class TestPybindFile(unittest.TestCase):

def test_context_manager(self):
with patch("__builtin__.open", mock_open()) as mock_file:
path = 'text.txt'
text = 'test'
with PybindFile(path) as writer:
writer.write(text)

mock_file.assert_called_once_with(path, 'w')
handle = mock_file()
handle.write.assert_called_once_with(text)


if __name__ == '__main__':
unittest.main()
42 changes: 42 additions & 0 deletions alpyca_sim/build/pybind/test_pybind_writer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import unittest

from pybind_writer import PybindWriter


class TestPybindWriter(unittest.TestCase):

def test_write(self):
writer = PybindWriter()
text = 'text'
writer.write(text)
self.assertEqual(writer.text, text)

def test_remove_last_char(self):
writer = PybindWriter()
writer.write('text')
writer.remove_last_char()
self.assertEqual(writer.text, 'tex')

def test_write_line(self):
writer = PybindWriter()
writer.write_line('text')
self.assertEqual(writer.text, 'text\n')

def test_include(self):
writer = PybindWriter()
writer.include('text')
self.assertEqual(writer.text, '#include text\n')

def test_new_line(self):
writer = PybindWriter()
writer.new_line()
self.assertEqual(writer.text, '\n')

def test_repeated(self):
writer = PybindWriter()
writer.add_repeated('text::123')
self.assertEqual(writer.text, 'py::class_<Repeated<text::123>>(m, \"Repeated_text_123\")\n'\
'.def(\"__getitem__\", &Repeated<text::123>::getitem);\n\n')

if __name__ == '__main__':
unittest.main()

0 comments on commit a1f4544

Please sign in to comment.