epics-base/p4p

flipping __str__ and __repr__ for ntstr

Opened this issue · 2 comments

Hi,

Thanks for preparing this library. I just started using it for my code.

I have one PV I was using in my script which is a string, and I am wondering if there is perhaps a different use of __str__ and __repr__ from what I expect.

I had a pseudo code doing something like:

ctxt = Context("pva")
pv_name = 'MY_PV_NAME'
value = ctxt.get(pv_name)
print(f"My value is {value}")

This returned My value is Thu Apr 20 04:01:09 2023 'HELLO'. I further noticed that if I instead did print("My value is " + value) then I got the expected My value is HELLO

Looking through what __str__, __repr__, __add__ etc normally are supposed to represent, I am wondering if it should perhaps rather be __repr__ (if any) that also returns the time stamp with the value, while __str__ should just return HELLO. One description I found from stack overflow was that

  • __repr__ goal is to be unambiguous
  • __str__ goal is to be readable

I think a python coder would normally expect that f"a {VAR}" == "a " + VAR.

This is a bit outside of my expertise so I might also just have wrong anticipation of how a python object should behave.

The perhaps somewhat unexpected behavior of __str__ which you describe is my attempt to encourage new users to discover the presence of PVA meta-data.

What you are describing is the current behavior of the p4p.nt.scalar.ntwrappercommon mixin, in your example specifically p4p.nt.scalar.ntstr (also a sub-class of str). These appear because of Automatic Value unwrapping, which can be disabled. So your value is more than "just the value", and includes the time meta-data being shown, along with other meta-data (alarm, description, units, etc.).

My goal with the Automatic Value unwrapping feature is to allow new users to treat the result of GET and MONITOR operations as mostly equivalent to "just the value" while preserving the meta-data for when it is eventually needed. Perhaps after the first time your script receives data with an INVALID alarm, and behaves accordingly :)

Hi Michael, I was discussing this issue with Yngve at ESS, and I agree with him that the behavior with f-strings is a bit confusing.

I agree with you that the default behavior when doing print(value) makes sense, and I always found it useful to get the timestamp.
But in f-strings it would be nicer to get a string representation of the value. That's probably the most common use case, and one would get the same result as using a string concatenation with the + operator.