Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Showing class attributes in the PyCharm debugger when subclassing str

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
like image 236
Lomtrur Avatar asked Jan 24 '19 09:01

Lomtrur


People also ask

How do you show variables in PyCharm?

Right-click on the file and click Run file in console. Everytime you run it, the variables will show in the console until you click the stop button.

How do I enable debugging actions in PyCharm?

Just right-click any line in the editor and select the Debug <filename> command from the context menu. After the program has been suspended, use the debugger to get the information about the state of the program and how it changes during running.

How does debugger work in PyCharm?

Starting a debugger session is very similar to running the program in normal mode. The debugger is attached behind the scenes, so you don't have to configure anything specific to start a debugger session. If you are able to run your program from PyCharm, you will also be able to debug it using the same configuration.

What does the lightning bolt mean in PyCharm?

button to resume the script execution. The exception is here. Another breakpoint appeared as well: by default PyCharm will halt for any exception that wasn't caught in your code, and it'll show an icon of a breakpoint with a lightning bolt. The debugger also shows the error message.


2 Answers

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.

like image 175
bad_coder Avatar answered Sep 23 '22 19:09

bad_coder


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

like image 30
nadapez Avatar answered Sep 22 '22 19:09

nadapez