How to use Gtk.Widget.set_template() - python

I am trying to use the Gtk.Widget.set_template() method but I am not sure how to use it without Gio.Resource. I am using python3 with gi.repository.
Let's say I have a foowidget.ui and then I would like to have a class:
class FooWidget(Gtk.Box):
Gtk.Box.__init__(self)
#set_template here with 'foowidget.ui'
self.init_template()

It is not possible right now to use set_template with python. There is an open bug for it here.
EDIT:
By now, it is possible to use templates with python. It looks like this:
from gi.repository import Gtk
#Gtk.Template(resource_path='/path/to/resource/window.ui')
class Window(Gtk.Window):
__gtype_name__ = 'Window'
button = Gtk.Template.Child()
def __init__(self, **kwargs):
super().__init__(**kwargs)
#Gtk.Template.Callback('clicked')
def on_button_clicked(self, widget):
pass

There is a package called pygi-composite-templates you can install via pip (or just copy to your project) that implements all of the necessary pieces to use composite templates using PyGObject. There is a working example project that uses Gio.Resource and and example that loads directly from a file too.
Find it on github.
Disclaimer: I'm the author of pygi-composite-templates

Related

Is it possible to have Python IDEs offer autocompletion for dynamically generated class attributes?

Are there any tricks I can employ to get IDEs to offer code completion for dynamically generated class attributes? For instance
class A:
def __init__(self):
setattr(self, "a", 5)
This code will set the class attribute of A called a to the value of 5. But IDEs do not know about a and therefore you do not get code completion for it. I've read that the __dir__ method can be hooked, but the suggestion made in that answer has not worked for me. Does anybody have any ideas?
I believe you will find the answer here. In short, Pycharm currently does not (and probably in the observable future will not) support dynamic attributes. That's because it analyzes code statically, and can't "see" what attributes a class might have. On the other hand, when you run your code in (say) iPython, once an instance of such class is created, the editor can get the attributes of the specific instance that resides in the memory, and thus show them in autocomplete. In such cases __dir__ helps. I assume that would be the case also with other IDEs.
So if you really need the autocompletion feature, you may want to try using Jupyter notebook. Still, you will have to instantiate your variable prior to getting autocomplete.
Another possible solution is to exploit that IDE supports .pyi files (Python interface file stub). You can add to your code a little snippet that instantiate the class with dynamic attributes, and writes down a class interface file (.pyi). Then IDE will use it for autocompletion. Obviously, this solution will have a "one run delay", but as in PyCharm you can switch to such file just by clicking on the asterisk near the class name, you can manually update it when having massive changes.
For this, I had to use Union type to get all the possible autocomplete options. It takes some extra time to write it, but when my program is huge, it is worth it.
from typing import Union
class dynamic1(object):
def __init__(self):
self.b = 5
self.c = 0
class dynamic2(dynamic1):
def __init__(self):
self.e = 10
self.d = 11
class dynamic3:
def __init__(self):
self.f = 12
def func(li):
return li[1]
def func() -> Union[dynamic1, dynamic2, dynamic3]:
a = [dynamic1(), dynamic2(), dynamic3()]
b = func(a)
return b
Spyder gives autosuggestion option rather than autocompletion. Kite integration might help setting up code faster. Kite is actually a autocompletion plugin. You can also use it with Visual studio code.

Python: How to define a class attribute's value dynamically?

I need to set a class attribute dynamically at run time. How can this be achieved? There is no way that I have found to set a class attribute outside of the instance init which means that it runs each time a an instance is created. This only needs to happen one time (when the class definition is loaded).
REVISED EXAMPLE.
Ideally i need to do something like this, but it seems this is not possible:
# Note modules are python modules which extend the functionality of my reusable app.
class Test():
active_modules = Test.get_active_moduels()
#classmethod
def get_active_moduels(cls):
#logic for collecting installed modules
return installed
I could get the job done like this, but it seems silly and causes major problems. If i try to access active_modules before a Test class is instantiated i get [] even though there are active_modules.
# Note modules are python modules which extend the functionality of my reusable app.
class Test():
active_modules = []
def __init__ (self):
Test.get_active_moduels()
#classmethod
def get_active_moduels(cls):
if not cls.active_modules:
#logic for collecting installed modules
.....
cls.active_modules = installed_modules
else:
return cls.active_modules
I could get this done by creating another registry of active_modules, but I would think there is a way to accomplish this within the class...
It would be much easier to help if you used concrete terminology. What is a "sub"? In any case, your code can be simplified to:
def compute_defaults():
they = []
they.append('default_1')
they.append('default_2')
return they
class Test():
active_subs = compute_defaults()
def __init__(self, sub=None):
if sub:
self.active_subs.append(sub)
Then you can use your code as you wish:
t1 = Test()
#active will have the installed subs.
active = t1.active_subs
Don't over-complicate your code with getters and setters needlessly.

QStandardItemEditorCreator in PySide

I'm trying to implement Qt's Color Editor Factory Example (http://doc-snapshot.qt-project.org/4.8/itemviews-coloreditorfactory.html) in PySide.
The problem I'm facing is that QStandardItemEditorCreator class is not in PySide, or I haven't been able to find it after searching the docs for a long time. The only reference to it in the PySide documentation can be found in the following page (http://www.pyside.org/docs/pyside/PySide/QtGui/QItemEditorCreatorBase.html), the relevant part being the following:
QStandardItemEditorCreator is a convenience template class that can be used to register widgets without the need to subclass PySide.QtGui.QItemEditorCreatorBase .
Without any link to QStandardItemEditorCreator.
In short, how may I get QStandardItemEditorCreator's functionality in PySide?
Thanks.
I ended up implementing QStandardItemEditorCreator in python. Here's my implementation:
class QStandardItemEditorCreator(QItemEditorCreatorBase):
def __init__(self, cls):
super(QStandardItemEditorCreator, self).__init__()
self.propertyName = cls.staticMetaObject.userProperty().name()
self.cls = cls
def createWidget(self, parent):
return self.cls(parent)
def valuePropertyName(self):
return self.propertyName
If anyone has a better answer I'll gladly choose yours over mine.

Python global/package alias implementation class

I have that strange feeling this is an easy question.
I want to be able to "alias" a class type so i can swap out the implementation at a package level. I dont want to have X amount of import X as bah scattered throughout my code...
Aka. How can I do something like the below:
class BaseClass(object):
def __init__(self): pass
def mymthod(self): pass
def mymthod1(self): pass
def mymthod2(self): pass
class Implementation(BaseClass):
def __init__(self):
BaseClass.__init__()
Seperate package...
#I dont want thse scattered through out modules,
#i want them in one place where i can change one and change implementations
#I tried putting it in the package init but no luck
import Implementation as BaseClassProxy
class Client(BaseClassImpl):
def __init__(self):
BaseClassImpl.__init__(self)
In any file (where this fits best is up to you, probably wherever Implementation was defined):
BaseClassProxy = Implementation
Since classes are first class objects in Python, you can pretty much bind them to any variable and use them the same way. In this case, you can make an alias for the class.
just put something like
BaseClassProxy = Implementation
in the module, then do:
from module import BaseClassProxy

Laying out MVC classes in Python

I'm working on a project in Python, and I'm trying to follow a somewhat-strict MVC pattern for practice. My idea was to separate things out into packages named model, view and controller, plus have a Model, View and Controller class for each. Each package would have the supporting files for each piece.
My problem is that I want to be able to use them like:
from controller import Controller
And then in the file with the Controller class I can:
from controller.someclass import SomeClass
But if I put them in packages with the same name, I get problems. I read up about how modules work, and realized I needed to name them controller/__init__.py, model/__init__.py and view/__init__.py, but it seems weird to put them in that file, and it's kind of annoying that all of them show up gedit as __init__.py
Is there any better way of doing this? Am I going about this the right way?
I've seen some black magic in the django source that pulls classes from a base.py file into the __init__.py namespace. However I'm not sure how that's done. ( See comments for how to do this. )
From what I do know, you can do one of two things.
A -
inside bar/controller/__init__.py
import os,sys
# Make sure the interpreter knows were your files are.
sys.path.append(os.path.join(os.path.dirname(__file__),'../')
from bar.controller import Controller
from bar.model import Model
from bar.view import View
class Controller(object):
model = Model()
view = View()
And now you make bar/model/__init__.py and bar/view/__init__.py
B -
inside bar/controller/__init__.py
class Model(object):
pass
class View(object):
pass
class Controller(object):
model = Model()
view = View()
Edit:...
After reading your comment, a third option comes to mind. A package doesn't litertly translate into a module in python. I think your desired result is to create a directory structure like this:
bar/
__init__.py
controller.py
model.py
view.py
Then inside controller.py
import os,sys
from bar.controller import Controller
from bar.model import Model
from bar.view import View
class Controller(object):
model = Model()
view = View()
This was a huge hurdle for me to get coming from java. Your class file names do not have to match the class name. Think of them as a step, you step into the folder(module) and then into the file(.py) and then you import your class.(Model(object))
If I understand correctly, all you're interested in doing here is having this happen:
from controller import Controller
without having the Controller class defined in controller/__init__.py is that right?
If so, then just do this:
In controller/base.py: (notice there is a file called base.py or something else)
class Controller(BaseClass):
# define Controller here
In controller/__init__.py:
from base import Controller
Now you can have the exact syntax you are looking for.

Categories