Change pprint strings to be prettier with nested structs
Nested types used to end up printed in a single line which is difficult to read. For improved readability, the following changes:
- Align the left edges instead of the equal signs
- Use double quotes for strings instead of single quotes
- Indent nested structures, and print over multiple lines
- Put closing bracket on a new line
- Add support for plain Python dicts, like we have in
DeviceInfo - Improve
DevErrorandDevFailed, including removing extra whitespace before and afterdescandoriginfields - Update
GroupReply,GroupAttrReplyandGroupCmdReplystring representations to actually show data/error messages - Changes only affects
strformatting, notrepr.repris still just a single line.
Overall, this makes the formatting a bit more like the output of the black autoformatter.
Examples below.
DeviceInfo
Old:
DeviceInfo[
dev_class = 'PowerSupply'
dev_type = 'PowerSupply'
doc_url = 'Doc URL = http://www.tango-controls.org'
server_host = 'host.domain'
server_id = 'PowerSupply/test'
server_version = 6
version_info = {'Build.PyTango.Boost': '1.87.0', 'Build.PyTango.NumPy': '2.1.3', 'Build.PyTango.Python': '3.13.0', 'Build.PyTango.cppTango': '10.0.2', 'NumPy': '2.1.3', 'PyTango': '10.1.0.dev0', 'Python': '3.13.0', 'cppTango': '10.0.2', 'cppTango.git_revision': 'unknown', 'cppzmq': '41000', 'idl': '6.0.2', 'omniORB': '4.3.2', 'opentelemetry-cpp': '1.18.0', 'zmq': '40305'}]
New:
DeviceInfo[
dev_class = "PowerSupply"
dev_type = "PowerSupply"
doc_url = "Doc URL = http://www.tango-controls.org"
server_host = "host.domain"
server_id = "PowerSupply/test"
server_version = 6
version_info = {
"Build.PyTango.Boost": "1.87.0",
"Build.PyTango.NumPy": "2.1.3",
"Build.PyTango.Python": "3.13.0",
"Build.PyTango.cppTango": "10.0.2",
"NumPy": "2.1.3",
"PyTango": "10.1.0.dev0",
"Python": "3.13.0",
"cppTango": "10.0.2",
"cppTango.git_revision": "unknown",
"cppzmq": "41000",
"idl": "6.0.2",
"omniORB": "4.3.2",
"opentelemetry-cpp": "1.18.0",
"zmq": "40305"
}
]
AttributeInfoEx
Old:
AttributeInfoEx[
alarms = AttributeAlarmInfo(delta_t = '', delta_val = '', extensions = [], max_alarm = '', max_warning = '', min_alarm = '', min_warning = '')
data_format = tango._tango.AttrDataFormat.SCALAR
data_type = tango._tango.CmdArgType.DevVoid
description = ''
disp_level = tango._tango.DispLevel.OPERATOR
display_unit = ''
enum_labels = []
events = AttributeEventInfo(arch_event = ArchiveEventInfo(archive_abs_change = '', archive_period = '', archive_rel_change = '', extensions = []), ch_event = ChangeEventInfo(abs_change = '', extensions = [], rel_change = ''), per_event = PeriodicEventInfo(extensions = [], period = ''))
extensions = []
format = ''
label = ''
max_alarm = ''
max_dim_x = 0
max_dim_y = 0
max_value = ''
memorized = tango._tango.AttrMemorizedType.NOT_KNOWN
min_alarm = ''
min_value = ''
name = ''
root_attr_name = ''
standard_unit = ''
sys_extensions = []
unit = ''
writable = tango._tango.AttrWriteType.READ
writable_attr_name = '']
New:
AttributeInfoEx[
alarms = AttributeAlarmInfo[
delta_t = ""
delta_val = ""
extensions = []
max_alarm = ""
max_warning = ""
min_alarm = ""
min_warning = ""
]
data_format = tango._tango.AttrDataFormat.SCALAR
data_type = tango._tango.CmdArgType.DevVoid
description = ""
disp_level = tango._tango.DispLevel.OPERATOR
display_unit = ""
enum_labels = []
events = AttributeEventInfo[
arch_event = ArchiveEventInfo[
archive_abs_change = ""
archive_period = ""
archive_rel_change = ""
extensions = []
]
ch_event = ChangeEventInfo[
abs_change = ""
extensions = []
rel_change = ""
]
per_event = PeriodicEventInfo[
extensions = []
period = ""
]
]
extensions = []
format = ""
label = ""
max_alarm = ""
max_dim_x = 0
max_dim_y = 0
max_value = ""
memorized = tango._tango.AttrMemorizedType.NOT_KNOWN
min_alarm = ""
min_value = ""
name = ""
root_attr_name = ""
standard_unit = ""
sys_extensions = []
unit = ""
writable = tango._tango.AttrWriteType.READ
writable_attr_name = ""
]
DevFailed and DevError
Old:
>>> dp = tango.DeviceProxy("train/ps/1")
>>> dp.calibrate()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/path/to/pytango/tango/device_proxy.py", line 363, in f
return dp.command_inout(name, *args, **kwds)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/path/to/pytango/tango/green.py", line 226, in greener
return executor.run(fn, args, kwargs, wait=wait, timeout=timeout)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/path/to/pytango/tango/green.py", line 116, in run
return fn(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^
File "/path/to/pytango/tango/connection.py", line 77, in __Connection__command_inout
r = Connection.command_inout_raw(self, name, *args, **kwds)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/path/to/pytango/tango/connection.py", line 111, in __Connection__command_inout_raw
return self.__command_inout(cmd_name, param)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
PyTango.DevFailed: DevFailed[
DevError[
desc = AssertionError: Oh no!
origin = Traceback (most recent call last):
File "/path/to/pytango/tango/server.py", line 1443, in wrapped_command_method
return get_worker().execute(cmd_method, self, *args, **kwargs)
~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/path/to/pytango/tango/green.py", line 113, in execute
return fn(*args, **kwargs)
File "/path/to/pytango/examples/training/server/ps0a.py", line 19, in calibrate
assert 0, "Oh no!"
^
AssertionError: Oh no!
reason = PyDs_PythonError
severity = ERR]
DevError[
desc = Cannot execute command
origin = virtual CORBA::Any *PyCmd::execute(Tango::DeviceImpl *, const CORBA::Any &) at (/path/to/pytango/ext/server/command.cpp:92)
reason = PyDs_UnexpectedFailure
severity = ERR]
DevError[
desc = Failed to execute command_inout on device train/ps/1, command calibrate
origin = virtual DeviceData Tango::Connection::command_inout(const std::string &, const DeviceData &) at (/Users/runner/miniforge3/conda-bld/cpptango_1739462625904/work/src/client/devapi_base.cpp:1432)
reason = API_CommandFailed
severity = ERR]
]
>>>
New:
>>> dp.calibrate()
Traceback (most recent call last):
File "<python-input-14>", line 1, in <module>
dp.calibrate()
~~~~~~~~~~~~^^
File "/path/to/pytango/tango/device_proxy.py", line 363, in f
return dp.command_inout(name, *args, **kwds)
~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^
File "/path/to/pytango/tango/green.py", line 226, in greener
return executor.run(fn, args, kwargs, wait=wait, timeout=timeout)
~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/path/to/pytango/tango/green.py", line 116, in run
return fn(*args, **kwargs)
File "/path/to/pytango/tango/connection.py", line 77, in __Connection__command_inout
r = Connection.command_inout_raw(self, name, *args, **kwds)
File "/path/to/pytango/tango/connection.py", line 111, in __Connection__command_inout_raw
return self.__command_inout(cmd_name, param)
~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^
PyTango.DevFailed: DevFailed[
DevError[
desc = AssertionError: Oh no!
origin = Traceback (most recent call last):
File "/path/to/pytango/tango/server.py", line 1443, in wrapped_command_method
return get_worker().execute(cmd_method, self, *args, **kwargs)
~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/path/to/pytango/tango/green.py", line 113, in execute
return fn(*args, **kwargs)
File "/path/to/pytango/examples/training/server/ps0a.py", line 19, in calibrate
assert 0, "Oh no!"
^
AssertionError: Oh no!
reason = PyDs_PythonError
severity = ERR
],
DevError[
desc = Cannot execute command
origin = virtual CORBA::Any *PyCmd::execute(Tango::DeviceImpl *, const CORBA::Any &) at (/path/to/pytango/ext/server/command.cpp:92)
reason = PyDs_UnexpectedFailure
severity = ERR
],
DevError[
desc = Failed to execute command_inout on device train/ps/1, command calibrate
origin = virtual DeviceData Tango::Connection::command_inout(const std::string &, const DeviceData &) at (/Users/runner/miniforge3/conda-bld/cpptango_1739462625904/work/src/client/devapi_base.cpp:1432)
reason = API_CommandFailed
severity = ERR
]
]
>>>
Group replies
Old:
GroupCmdReply[
]
GroupAttrReply[
]
GroupReply[
]
New:
GroupCmdReply[
dev_name = "tango://127.0.0.1:61774/test/device/1#dbase=no"
obj_name = "State"
enabled = True
has_failed = False
data = UNKNOWN
]
GroupAttrReply[
dev_name = "tango://127.0.0.1:61774/test/device/1#dbase=no"
obj_name = "attr"
enabled = True
has_failed = False
data = DeviceAttribute[
data_format = tango._tango.AttrDataFormat.SCALAR
dim_x = 1
dim_y = 0
has_failed = False
is_empty = False
name = "attr"
nb_read = 1
nb_written = 1
quality = tango._tango.AttrQuality.ATTR_VALID
r_dimension = AttributeDimension[
dim_x = 1
dim_y = 0
]
time = TimeVal(tv_nsec = 0, tv_sec = 1741759431, tv_usec = 455195)
type = tango._tango.CmdArgType.DevDouble
value = 12.3
w_dim_x = 1
w_dim_y = 0
w_dimension = AttributeDimension[
dim_x = 1
dim_y = 0
]
w_value = 0.0
]
]
GroupReply[
dev_name = "tango://127.0.0.1:61774/test/device/1#dbase=no"
obj_name = "attr"
enabled = True
has_failed = False
]
GroupCmdReply[
dev_name = "tango://127.0.0.1:61774/test/device/1#dbase=no"
obj_name = "cmd_fail"
enabled = True
has_failed = True
err_stack = [
DevError[
desc = RuntimeError: Fail for test
origin = Traceback (most recent call last):
File "/path/to/pytango/tango/utils.py", line 2507, in trace_wrapper
ret = fn(*args, **kwargs)
File "/path/to/pytango/tango/server.py", line 1796, in wrapped_command_method
return get_worker().execute(cmd_method, self, *args, **kwargs)
~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/path/to/pytango/tango/green.py", line 105, in execute
return fn(*args, **kwargs)
File "/path/to/pytango/tests/test_pprint.py", line 40, in cmd_fail
raise RuntimeError("Fail for test")
RuntimeError: Fail for test
reason = PyDs_PythonError
severity = ERR
],
DevError[
desc = Cannot execute command
origin = virtual CORBA::Any *PyCmd::execute(Tango::DeviceImpl *, const CORBA::Any &) at (/path/to/pytango/ext/server/command.cpp:316)
reason = PyDs_UnexpectedFailure
severity = ERR
],
DevError[
desc = Failed to execute command_inout_asynch on device test/device/1, command cmd_fail
origin = virtual DeviceData Tango::Connection::command_inout_reply(long, long) at (/Users/runner/miniforge3/conda-bld/cpptango_1739462625904/work/src/client/proxy_asyn.cpp:699)
reason = API_CommandFailed
severity = ERR
]
]
]
GroupAttrReply[
dev_name = "tango://127.0.0.1:61774/test/device/1#dbase=no"
obj_name = "attr_fail"
enabled = True
has_failed = True
err_stack = [
DevError[
desc = RuntimeError: Fail for test
origin = Traceback (most recent call last):
File "/path/to/pytango/tango/utils.py", line 2507, in trace_wrapper
ret = fn(*args, **kwargs)
File "/path/to/pytango/tango/server.py", line 100, in read_attr
ret = worker.execute(read_method, self)
File "/path/to/pytango/tango/green.py", line 105, in execute
return fn(*args, **kwargs)
File "/path/to/pytango/tests/test_pprint.py", line 32, in attr_fail
raise RuntimeError("Fail for test")
RuntimeError: Fail for test
reason = PyDs_PythonError
severity = ERR
],
DevError[
desc = Failed to read_attributes on device test/device/1, attribute attr_fail
origin = virtual DeviceAttribute *Tango::DeviceProxy::read_attribute_reply(long, long) at (/Users/runner/miniforge3/conda-bld/cpptango_1739462625904/work/src/client/proxy_asyn.cpp:1744)
reason = API_AttributeFailed
severity = ERR
]
]
]
GroupReply[
dev_name = "tango://127.0.0.1:61774/test/device/1#dbase=no"
obj_name = "attr_fail"
enabled = True
has_failed = True
err_stack = [
DevError[
desc = RuntimeError: Fail for test
origin = Traceback (most recent call last):
File "/path/to/pytango/tango/utils.py", line 2507, in trace_wrapper
ret = fn(*args, **kwargs)
File "/path/to/pytango/tango/server.py", line 155, in write_attr
return get_worker().execute(write_method, self, value)
~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/path/to/pytango/tango/green.py", line 105, in execute
return fn(*args, **kwargs)
File "/path/to/pytango/tests/test_pprint.py", line 36, in attr_fail
raise RuntimeError("Fail for test")
RuntimeError: Fail for test
reason = PyDs_PythonError
severity = ERR
],
DevError[
desc = Failed to execute write_attributes_asynch on device test/device/1
Attribute(s): attr_fail
origin = void Tango::DeviceProxy::write_attr_except(CORBA::Request_ptr, long, TgRequest::ReqType) at (/Users/runner/miniforge3/conda-bld/cpptango_1739462625904/work/src/client/proxy_asyn.cpp:2612)
reason = API_AttributeFailed
severity = ERR
]
]
]