I am using pySide and try to internationalize my project. The problem is that none of the Strings get translated if I do not translate them through the constructor.
I would like to translate the Strings in other methods as well. What could be the problem?
Here is my module:
class InterpolationView(QWidget):
def __init__(self, parent=None, flags=Qt.Widget):
super(InterpolationView, self).__init__(parent, flags)
load_ui('ui/wizards/interpolation/interpolation_view.ui', self)
self.stepGroupBox.setTitle(Dictionary.map_interpolation_view["step_planning"])
I translate my Strings from the injected .ui file in the init method. The translations come from a module called Dictionary that includes all the necessary translations:
class Dictionary(object):
map_interpolation_view = None
def __init__(self):
super(Dictionary, self).__init__()
self.initialize_dictionary()
def initialize_dictionary(self):
Dictionary.map_interpolation_view = dict()
Dictionary.map_interpolation_view["step_planning"] = QApplication.translate("Dictionary", "Step Planning")
The Dictionary is initialized in the MyPlugin module which is a python plugin.This is where I also initialize my translator.
class MyPlugin(Plugin):
def __init__(self, context):
super(MyPlugin, self).__init__(context)
translate_to_german = True
if(translate_to_german):
translator = load_translation('de')
application = QCoreApplication.instance()
application.installTranslator(translator)
self.__dictionary = Dictionary()
I would like to get rid of this special Dictionary module and just translate the Strings like this:
class InterpolationView(QWidget):
def __init__(self, parent=None, flags=Qt.Widget):
super(InterpolationView, self).__init__(parent, flags)
load_ui('ui/wizards/interpolation/interpolation_view.ui', self)
def translate(self):
self.stepGroupBox.setTitle(QApplication.translate("InterpolationView", "Step Planning"))
and be able to call the translate method from any other class. This does not work however, the Strings are not translated then. Why?
Related
Using python 2.7.6, I have been trying to write a class that can extract pieces of xml data from a couple of xml files within a given zip file. I want to be able to use any of the methods in any order once I am working with the class, so wanted the unzip stage to be behind the scenes, in the class.
It is the first time I have really tried to make real use of a class as I am quite new to python, so I am learning as I go.
I defined methods to unzip the data to memory and was using those methods in other methods - then realised it would be horribly inefficient when using multiple methods. Since the unzipping step is necessary for any method in the class, is there a way to build it into the init definition so it is only done once when the class is first created?
Example of what I currently have:
class XMLzip(object):
def __init__(self, xzipfile):
self.xzipfile = xzipfile
def extract_xml1(self):
#extract the xmlfile to a variable
def extract_xml2(self):
#extract xmlfile2 to a variable
def do_stuff(self):
self.extract_xml1()
....
def do_domethingelse(self):
self.extract_xml1()
Is there a way to do something like I have shown below? And if so, what is it called - my searches haven't been very effective.
class XMLzip(object):
def __init__(self, xzipfile):
self.xzipfile = xzipfile
def extract_xml1()
# extract it here
def extract_xml2()
# extract it here
# Now carry on with normal methods
def do_stuff(self):
...
in the __init__ you can do whatever you want in order to initialize your class, in this case look like what you need is something like this
class XMLzip(object):
def __init__(self, xzipfile):
self.xzipfile = xzipfile
self.xml1 = #extract xml1 here
self.xml2 = #extract xml2 here
def do_stuff(self):
...
if you want to do the extract part only once, then do it and save result in a additional attribute in the instance of your class.
I suspect that the extract procedure is very similar, so you can make it a function be inside your class or outside, that is up to your preference, and give additional arguments to handle the specificity, for example something like this
the outside version
def extract_xml_from_zip(zip_file,this_xml):
# extract the request xml file from the given zip_file
return result
class XMLzip(object):
def __init__(self, xzipfile):
self.xzipfile = xzipfile
self.xml1 = extract_xml_from_zip(xzipfile,"xml1")
self.xml2 = extract_xml_from_zip(xzipfile,"xml2")
def do_stuff(self):
...
the inside version
class XMLzip(object):
def __init__(self, xzipfile):
self.xzipfile = xzipfile
self.xml1 = self.extract_xml_from_zip("xml1")
self.xml2 = self.extract_xml_from_zip("xml2")
def extract_xml_from_zip(self,this_xml):
# extract the request xml file from the zip_file in self.xzipfile
return result
def do_stuff(self):
...
You can call any method you have defined in your class in your initializer.
Demo:
>>> class Foo(object):
... def __init__(self):
... self.some_method()
... def some_method(self):
... print('hi')
...
>>> f = Foo()
hi
I take from your question that you need to extract the files only once. Leave your class as is and use your extract methods in __init__ and set the required attributes/variables for the extracted content.
For example
def __init__(self, xzipfile):
self.xzipfile = xzipfile
self.extract1 = self.extract_xml1()
self.extract2 = self.extract_xml2()
This of course requires your extract methods to have a return value, don't forget that.
I would like to extend an object with new attributes and methods, but in run-time. Basically I would prefer to just inherit and extend a class, but new objects of the base class are not usually created using it's constructor but by using fairly complex function.
Instead of...
from win32com import client
excel = client.Dispatch("Excel.Application")
excel.Visible = 1
excel.Workbooks.Add()
print(excel.Range("A1").value)
...I need something like (obviously broken):
from win32com import client
class Excel(client.CDispatch):
def __init__(self):
self = client.Dispatch("Excel.Application")
def get(self, cell):
return self.Range(cell).value
def show(self):
self.Visible = 1
excel = Excel()
excel.show()
excel.Workbooks.Add() # I want this to be still working
print(excel.get("A1"))
I still would like to be able to use original methods and attributes, but also my new ones. I have trouble wrapping my head around the concept, I am even not sure how to call the principle. Any ideas?
Another way to get desired functionality is like this:
from win32com import client
class Excel():
def __init__(self):
self.excel = client.Dispatch("Excel.Application")
self.Workbooks = self.excel.Workbooks
# I do not really want to repeat all base class
# functionality here to bind it to my new class
def get(self, cell):
return self.excel.Range(cell).value
def show(self):
self.excel.Visible = 1
excel = Excel()
excel.show()
excel.Workbooks.Add()
print(excel.get("A1"))
That works, however requires me to do a lot of lines similar to self.Workbooks = self.excel.Workbooks.
Implementation inheritence is mostly a variant of the composition / delegation pattern. The good news is that Python makes delegation quite easy. I've not tried (not working on Windows) but the following snippet might just work:
from win32com import client
class Excel(object):
def __init__(self):
self._app = client.Dispatch("Excel.Application")
def get(self, cell):
return self._app.Range(cell).value
def show(self):
self._app.Visible = 1
def __getattr__(self, name):
try:
return getattr(self._app, name)
except AttributeError:
raise AttributeError(
"'%s' object has no attribute '%s'" % (type(self).__name__, name))
My question refers to the accepted answer of the question How to capture output of Python's interpreter and show in a Text widget? which shows how to redirect standard output to a QTextEdit.
The author, Ferdinand Beyer, defines a class EmittingStream as such:
from PyQt4 import QtCore
class EmittingStream(QtCore.QObject):
textWritten = QtCore.pyqtSignal(str)
def write(self, text):
self.textWritten.emit(str(text))
He uses the class like this:
# Within your main window class...
def __init__(self, parent=None, **kwargs):
# ...
# Install the custom output stream
sys.stdout = EmittingStream(textWritten=self.normalOutputWritten)
def __del__(self):
# Restore sys.stdout
sys.stdout = sys.__stdout__
def normalOutputWritten(self, text):
"""Append text to the QTextEdit."""
# Maybe QTextEdit.append() works as well, but this is how I do it:
cursor = self.textEdit.textCursor()
cursor.movePosition(QtGui.QTextCursor.End)
cursor.insertText(text)
self.textEdit.setTextCursor(cursor)
self.textEdit.ensureCursorVisible()
I don't understand the line that instantiates the EmittingStream class. It looks as if the keyword argument textWritten=self.normalOutputWritten connects the textWritten-signal to the normalOutputWritten-slot, but I do not understand why this works.
This feature is documented here:
It is also possible to connect signals by passing a slot as a keyword
argument corresponding to the name of the signal when creating an
object, or using the pyqtConfigure() method of QObject. For example
the following three fragments are equivalent:
act = QtGui.QAction("Action", self)
act.triggered.connect(self.on_triggered)
act = QtGui.QAction("Action", self, triggered=self.on_triggered)
act = QtGui.QAction("Action", self)
act.pyqtConfigure(triggered=self.on_triggered)
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions concerning problems with code you've written must describe the specific problem — and include valid code to reproduce it — in the question itself. See SSCCE.org for guidance.
Closed 9 years ago.
Improve this question
File engine.py:
class Engine(object):
def __init__(self, variable):
self.variable = variable
class Event(object):
def process(self):
variable = '123' # this should be the value of engine.variable
Python
>>> from engine import Engine, Event
>>> engine = Engine('123')
>>> e = Event()
>>> e.process()
What's the best way to accomplish this? Because of limitations with the Event class (it's actually a subclass of a third-party library that I'm splicing new functionality into) I can't do something like e = Event(engine).
In depth explanation:
Why am I not using e = Event(engine)?
Because Event is actually a subclass of a third-party library. Additionally, process() is an internal method. So the class actually looks like this:
class Event(third_party_library_Event):
def __init__(*args, **kwargs):
super(Event, self).__init__(*args, **kwargs)
def _process(*args, **kwargs):
variable = engine.variable
# more of my functionality here
super(Event, self)._process(*args, **kwargs)
My new module also has to run seamlessly with existing code that uses the Event class already. So I can't add pass the engine object to each _process() call or to the init method either.
functools.partial might help:
#UNTESTED
class Engine(object):
def __init__(self, variable):
self.variable = variable
class Event(object):
def __init__(self, engine):
super().__init__()
self.engine = engine
def process(self):
print self.engine.variable
engine = Engine('123')
Event = functools.partial(Event, engine)
ThirdPartyApiThatNeedsAnEventClass(Event)
Now, when the 3rd-party library creates an Event, it is automatically passed engine.
"Because of limitations with the Event class (it's actually a subclass
of a third-party library that I'm splicing new functionality into) I
can't do something like e = Event(engine)."
It appears that you're concerned that Event is inheriting some other class and you are therefore unable to alter the constructor method for the class.
Your question is similar to this other one. Fortunately, the super().__init__() method does this for you.
Consider the following example:
>>> class C(object):
def __init__(self):
self.b = 1
>>> class D(C):
def __init__(self):
super().__init__()
self.a = 1
>>> d = D()
>>> d.a
1
>>> d.b # This works because of the call to super's init
1
Why not pass the variable in to the process function? You said the class's constructor can't be changed, but it seems like you are defining process. Just make it:
def process(self, engine):
variable = engine.variable
<do stuff>
or
def process(self, variable):
<do stuff>
I am updating some code from using libglade to GtkBuilder, which is supposed to be the way of the future.
With gtk.glade, you could call glade_xml.signal_autoconnect(...) repeatedly to connect signals onto objects of different classes corresponding to different windows in the program. However Builder.connect_signals seems to work only once, and (therefore) to give warnings about any handlers that aren't defined in the first class that's passed in.
I realize I can connect them manually but this seems a bit laborious. (Or for that matter I could use some getattr hackery to let it connect them through a proxy to all the objects...)
Is it a bug there's no function to hook up handlers across multiple objects? Or am I missing something?
Someone else has a similar problem http://www.gtkforums.com/about1514.html which I assume means this can't be done.
Here's what I currently have. Feel free to use it, or to suggest something better:
class HandlerFinder(object):
"""Searches for handler implementations across multiple objects.
"""
# See <http://stackoverflow.com/questions/4637792> for why this is
# necessary.
def __init__(self, backing_objects):
self.backing_objects = backing_objects
def __getattr__(self, name):
for o in self.backing_objects:
if hasattr(o, name):
return getattr(o, name)
else:
raise AttributeError("%r not found on any of %r"
% (name, self.backing_objects))
I have been looking for a solution to this for some time and found that it can be done by passing a dict of all the handlers to connect_signals.
The inspect module can extract methods using
inspect.getmembers(instance, predicate=inspect.ismethod
These can then be concatenated into a dictionary using d.update(d3), watching out for duplicate functions such as on_delete.
Example code:
import inspect
...
handlers = {}
for c in [win2, win3, win4, self]: # self is the main window
methods = inspect.getmembers(c, predicate=inspect.ismethod)
handlers.update(methods)
builder.connect_signals(handlers)
This will not pick up alias method names declared using #alias. For an example of how to do that, see the code for Builder.py, at def dict_from_callback_obj.
I'm only a novice but this is what I do, maybe it can inspire;-)
I instantiate the major components from a 'control' and pass the builder object so that the instantiated object can make use of any of the builder objects (mainwindow in example) or add to the builder (aboutDialog example). I also pass a dictionary (dic) where each component adds "signals" to it.
Then the 'connect_signals(dic)' is executed.
Of course I need to do some manual signal connecting when I need to pass user arguments to the callback method, but those are few.
#modules.control.py
class Control:
def __init__(self):
# Load the builder obj
guibuilder = gtk.Builder()
guibuilder.add_from_file("gui/mainwindow.ui")
# Create a dictionnary to store signal from loaded components
dic = {}
# Instanciate the components...
aboutdialog = modules.aboutdialog.AboutDialog(guibuilder, dic)
mainwin = modules.mainwindow.MainWindow(guibuilder, dic, self)
...
guibuilder.connect_signals(dic)
del dic
#modules/aboutdialog.py
class AboutDialog:
def __init__(self, builder, dic):
dic["on_OpenAboutWindow_activate"] = self.on_OpenAboutWindow_activate
self.builder = builder
def on_OpenAboutWindow_activate(self, menu_item):
self.builder.add_from_file("gui/aboutdialog.ui")
self.aboutdialog = self.builder.get_object("aboutdialog")
self.aboutdialog.run()
self.aboutdialog.destroy()
#modules/mainwindow.py
class MainWindow:
def __init__(self, builder, dic, controller):
self.control = controller
# get gui xml and/or signals
dic["on_file_new_activate"] = self.control.newFile
dic["on_file_open_activate"] = self.control.openFile
dic["on_file_save_activate"] = self.control.saveFile
dic["on_file_close_activate"] = self.control.closeFile
...
# get needed gui objects
self.mainWindow = builder.get_object("mainWindow")
...
Edit: alternative to auto attach signals to callbacks:
Untested code
def start_element(name, attrs):
if name == "signal":
if attrs["handler"]:
handler = attrs["handler"]
#Insert code to verify if handler is part of the collection
#we want.
self.handlerList.append(handler)
def extractSignals(uiFile)
import xml.parsers.expat
p = xml.parsers.expat.ParserCreate()
p.StartElementHandler = self.start_element
p.ParseFile(uiFile)
self.handlerList = []
extractSignals(uiFile)
for handler in handlerList:
dic[handler] = eval(''. join(["self.", handler, "_cb"]))
builder.connect_signals
({
"on_window_destroy" : gtk.main_quit,
"on_buttonQuit_clicked" : gtk.main_quit
})