6

I want to see class attributes for a subclass of str in the debugger.

Example image

Refer to the picture - I want to have the dropdown arrow next to a (which is a POSString object). In other words, in the Pycharm debugger I want to have the option to doubleclick a and see the attribute bar with value "HELLO", exactly like for the foo object.

Is this possible in PyCharm, and if yes how?

The two classes:

class Foo:
    bar = "HELLO"


class POSString(str):
    bar = "HELLO"

    def __init__(self, pos="", *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.pos = pos

    def __hash__(self):
        return hash((str(self), self.pos))

    def __eq__(self, other):
        return super().__eq__(other) and self.pos == other.pos

And how I create my two objects:

foo = Foo()
a = POSString("banana")

I am using Python 3.7.1.

PyCharm:

PyCharm 2018.2.5 (Professional Edition)
Build #PY-182.5107.22, built on November 13, 2018
JRE: 1.8.0_152-release-1248-b22 amd64
JVM: OpenJDK 64-Bit Server VM by JetBrains s.r.o
Linux 4.15.0-43-generic
bad_coder
  • 11,289
  • 20
  • 44
  • 72
Lomtrur
  • 1,703
  • 2
  • 19
  • 35

2 Answers2

5

PyCharm doesn't currently have a setting to configure display in the Variables Tab of the Debug tool window with that detail. The IDE takes most display decision automatically based on the type of the object. The only option currently available is sorting values inside a single variable using the setting at File > Settings > Build, Execution, Deployment > Debugger > Data Views > Sort values alphabetically. (See this post for a more detailed explanation).

This can be inconvenient for purpose of debugging, the example class in the question is displayed exactly like a string because the class inherits from string. That's an IDE decision and there's currently no way to change it (apart from posting a feature request with JetBrains).

The alternatives are setting "Watches" in the Variables Tab or using the Console. The other more inconvenient alternative is changing the class itself to not inherit from string (in which case it will be displayed like regular classes are) however this can break any number of functionalities in your code, so the debugging convenience gained can be outweighed by the inconveniences caused.

bad_coder
  • 11,289
  • 20
  • 44
  • 72
2

Just assign a variable with the POSString objects __dict__ attribute:

a = POSString('HELLO')
_a = a.__dict__

Then you can access all the attributes of a through _a.

Other way around is not to inherit from str, add the str to an attribute and override the __getattribute__ method to forward calls to the str object.

class POSString():
    bar = "HELLO"

    def __init__(self, pos="", *args, **kwargs):
        #super().__init__(*args, **kwargs)
        self.str = str(*args, **kwargs)
        self.pos = pos

    def __hash__(self):
        #return hash((str(self), self.pos))
        return hash((self.str, self.pos)) 

    def __eq__(self, other):
        #return super().__eq__(other) and self.pos == other.pos
        return self.str.__eq__(other) and self.pos == other.pos  

    def __getattr__(self, attr):
        return getattr(self.str, attr)

I think, after all, that is not good practice to inherit from str

nadapez
  • 2,603
  • 2
  • 20
  • 26
  • sorry, it was a mistake, I already fixed it – nadapez Nov 02 '21 at 17:11
  • The reason this doesn't work is because it will break dependencies of the string type where your code uses the original `POSString` from the question. So it's not a solution unless the new object defined [the full interface](https://docs.python.org/3/library/stdtypes.html#string-methods) of `str` which is inherited by the original. For example `isinstance(POSString, str)` is `True` for the original but `False` for your implementation. I mention this in the linked post in my answer. So it would still be simpler to set the variable watches for what you need in the IDE than changing the code. – bad_coder Nov 05 '21 at 12:47
  • The only ideal solution is for JetBrains to implement a new display for this case in the Variables Tab of PyCharm. – bad_coder Nov 05 '21 at 12:48