jquast / blessed

Blessed is an easy, practical library for making python terminal apps

Home Page:http://pypi.python.org/pypi/blessed

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Blessed converting integer to parameterized string.

SystematicError opened this issue · comments

Hello recently I've been working on a prototype terminal app and I've been facing some issues. Blessed seems to convert my int type variable into blessed.formatters.ParameterizingString when passing it through StatusBar.render. My code is provided down below:

from .config_loader import config
from .gui.components import Border, StatusBar
from .gui.core import App


class FileManager(App):
    def __init__(self):
        super().__init__()
        self.current_workspace = 0

    def on_load(self):
        keybinds = config.keybinds

        self.keybinds[keybinds["quit"]] = quit

        # for workspace_keybind in keybinds["workspaces"]:
        #    self.keybinds[workspace_keybind] = lambda: setattr(self, "current_workspace", int(workspace_keybind))

    def render(self):
        StatusBar(self).render(self.current_workspace)
        Border(self).render(20)


FileManager()
class App(Terminal):
    def __init__(self):
        super().__init__()

        self.keybinds = {}

        def handle_resize(*args):
            print(self.clear)
            self.render()

        with self.fullscreen(), self.cbreak(), self.hidden_cursor():
            signal(SIGWINCH, handle_resize)

            self.on_load()
            self.render()

            while True:
                key = self.inkey()

                if key in self.keybinds:
                    self.keybinds[key]()

                self.render()

Can you provide some a simplified example that illustrates the issue? It should be standalone code that we can copy and paste to execute.

Sure, here is a simplified version:

from blessed import Terminal


class BaseApp(Terminal):
    def __init__(self):
        super().__init__()
        self.my_int_1 = 0
        self.render()


class App(BaseApp):
    def __init__(self):
        super().__init__()
        self.my_int_2 = 0

    def render(self):
        print(f"Integer defined in parent class is of type {type(self.my_int_1)}")
        print(f"Integer defined in child class is of type {type(self.my_int_2)}")


App()

And here is the output:

Integer defined in parent class is of type <class 'int'>
Integer defined in parent class is of type <class 'blessed.formatters.ParameterizingString'>

The issue is you're not referencing App.my_int_2 since you're calling render() before you've declared it, so it's going to Terminal.getattr() which will return an empty ParameterizingString if an attribute can't be resolved.

>>> term = Terminal()
>>> my_int = term.my_int_2
>>> my_int
''
>>> type(my_int)
<class 'blessed.formatters.ParameterizingString'>

I would suggest not subclassing Terminal and instead create an attribute to store the terminal object. Generally it's best to create one Terminal instance and use it for the life of the program. There are a lot of cached lookups so you can save a lot of overhead depending on what you're doing.

Here's a simplified case, or you can see what I did in Enlighten.

class BaseApp:
    def __init__(self, term=None):
            self.term = term or blessed.Terminal()

Thanks for the help!