Skip to content

Commit

Permalink
Merge pull request tango-controls#214 from tango-controls/issue-213
Browse files Browse the repository at this point in the history
 DevEncoded attribute should produce a bytes object in python 3
  • Loading branch information
ajoubertza committed Sep 7, 2018
2 parents 7cb7b30 + aa87ae5 commit 66a68bb
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 22 deletions.
49 changes: 28 additions & 21 deletions ext/device_attribute.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ try { \
if (strcmp(e.errors[0].reason.in(),"API_EmptyDeviceAttribute") != 0) \
throw; \
}


namespace PyDeviceAttribute
{
Expand Down Expand Up @@ -133,11 +133,11 @@ namespace PyDeviceAttribute
Tango::DevVarEncodedArray* value_ptr;
EXTRACT_VALUE(self, value_ptr)
unique_pointer<Tango::DevVarEncodedArray> guard(value_ptr);

Tango::DevEncoded* buffer = value_ptr->get_buffer();
Tango::DevEncoded& r_buffer = buffer[0];
bopy::str r_encoded_format(r_buffer.encoded_format);

Tango::DevVarCharArray& r_encoded_data_array = r_buffer.encoded_data;
char* r_ch_ptr = (char*) r_encoded_data_array.get_buffer();
Py_ssize_t r_size = r_encoded_data_array.length();
Expand Down Expand Up @@ -165,7 +165,7 @@ namespace PyDeviceAttribute
py_value.attr(w_value_attr_name) =
bopy::make_tuple(w_encoded_format, w_encoded_data);
}
else
else
{
Tango::DevEncoded& w_buffer = buffer[1];
bopy::str w_encoded_format(w_buffer.encoded_format);
Expand Down Expand Up @@ -238,17 +238,20 @@ namespace PyDeviceAttribute
Tango::DevVarEncodedArray* value_ptr;
EXTRACT_VALUE(self, value_ptr)
unique_pointer<Tango::DevVarEncodedArray> guard(value_ptr);

Tango::DevEncoded* buffer = value_ptr->get_buffer();

Tango::DevEncoded& r_buffer = buffer[0];
bopy::str r_encoded_format(r_buffer.encoded_format);

Tango::DevVarCharArray& r_encoded_data_array = r_buffer.encoded_data;
char* r_ch_ptr = (char*)r_encoded_data_array.get_buffer();
bopy::str r_encoded_data(r_ch_ptr, r_encoded_data_array.length());

py_value.attr(value_attr_name) =

bopy::object r_encoded_data(
bopy::handle<>(PyBytes_FromStringAndSize(
r_ch_ptr, r_encoded_data_array.length())));

py_value.attr(value_attr_name) =
bopy::make_tuple(r_encoded_format, r_encoded_data);

if (self.get_written_dim_x() > 0)
Expand All @@ -268,8 +271,12 @@ namespace PyDeviceAttribute

Tango::DevVarCharArray& w_encoded_data_array = w_buffer.encoded_data;
char* w_ch_ptr = (char*)w_encoded_data_array.get_buffer();
bopy::str w_encoded_data(w_ch_ptr, w_encoded_data_array.length());
py_value.attr(w_value_attr_name) =

bopy::object w_encoded_data(
bopy::handle<>(PyBytes_FromStringAndSize(
w_ch_ptr, w_encoded_data_array.length())));

py_value.attr(w_value_attr_name) =
bopy::make_tuple(w_encoded_format, w_encoded_data);
}
}
Expand All @@ -290,7 +297,7 @@ namespace PyDeviceAttribute
_update_scalar_values(Tango::DeviceAttribute &self, bopy::object py_value)
{
typedef typename TANGO_const2type(tangoTypeConst) TangoScalarType;

if (self.get_written_dim_x() > 0)
{
std::vector<TangoScalarType> val;
Expand All @@ -312,7 +319,7 @@ namespace PyDeviceAttribute
}
}

template<> inline void
template<> inline void
_update_scalar_values<Tango::DEV_ENCODED>(Tango::DeviceAttribute &self,
bopy::object py_value)
{
Expand Down Expand Up @@ -340,7 +347,7 @@ namespace PyDeviceAttribute
}
}

template<> inline void
template<> inline void
_update_scalar_values<Tango::DEV_PIPE_BLOB>(Tango::DeviceAttribute &self,
bopy::object py_value)
{
Expand Down Expand Up @@ -368,7 +375,7 @@ namespace PyDeviceAttribute

TangoScalarType* buffer = value_ptr->get_buffer();
int total_length = value_ptr->length();

// Determine if the attribute is AttrWriteType.WRITE
int read_size =0, write_size = 0;
if (isImage) {
Expand All @@ -379,7 +386,7 @@ namespace PyDeviceAttribute
write_size = self.get_written_dim_x();
}
bool is_write_type = (read_size + write_size) > total_length;

// Convert to a list of lists
long offset = 0;
for(int it=1; it>=0; --it) { // 2 iterations: read part/write part
Expand All @@ -388,11 +395,11 @@ namespace PyDeviceAttribute
continue;
}
bopy::list result;

if (isImage) {
const int dim_x = it? self.get_dim_x() : self.get_written_dim_x();
const int dim_y = it? self.get_dim_y() : self.get_written_dim_y();

for (int y=0; y < dim_y; ++y) {
bopy::list row;
for (int x=0; x < dim_x; ++x)
Expand Down Expand Up @@ -439,7 +446,7 @@ namespace PyDeviceAttribute

TangoScalarType* buffer = value_ptr->get_buffer();
int total_length = value_ptr->length();

// Determine if the attribute is AttrWriteType.WRITE
int read_size =0, write_size = 0;
if (isImage) {
Expand All @@ -450,15 +457,15 @@ namespace PyDeviceAttribute
write_size = self.get_written_dim_x();
}
bool is_write_type = (read_size + write_size) > total_length;

// Convert to a tuple of tuples
long offset = 0;
for(int it=1; it>=0; --it) { // 2 iterations: read part/write part
if ((!it) && is_write_type) {
py_value.attr(w_value_attr_name) = py_value.attr(value_attr_name);
continue;
}

object result_guard;
if (isImage) {
const int dim_x = it? self.get_dim_x() : self.get_written_dim_x();
Expand Down Expand Up @@ -516,7 +523,7 @@ namespace PyDeviceAttribute
{
// We do not want is_empty to launch an exception!!
self.reset_exceptions(Tango::DeviceAttribute::isempty_flag);

// self.get_type() already does self.is_empty()
const int data_type = self.get_type();
const bool is_empty = data_type < 0;
Expand Down
18 changes: 17 additions & 1 deletion tests/test_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import pytest
import enum

from tango import DevState, AttrWriteType, GreenMode, DevFailed
from tango import DevState, AttrWriteType, GreenMode, DevFailed, DevEncoded
from tango.server import Device
from tango.server import command, attribute, device_property
from tango.test_utils import DeviceTestContext, assert_close, \
Expand Down Expand Up @@ -392,3 +392,19 @@ def test_get_enum_labels_success(good_enum):
def test_get_enum_labels_fail(bad_enum):
with pytest.raises(EnumTypeError):
get_enum_labels(bad_enum)


# DevEncoded

def test_read_write_dev_encoded(server_green_mode):

class TestDevice(Device):
green_mode = server_green_mode

@attribute(dtype=DevEncoded,
access=AttrWriteType.READ)
def attr(self):
return ("uint8", b"\xd2\xd3")

with DeviceTestContext(TestDevice) as proxy:
assert proxy.attr == ("uint8", b"\xd2\xd3")

0 comments on commit 66a68bb

Please sign in to comment.