Don't use "hello %1".arg("world") : arg() can't be used in Python 3 #2231

Open
opened 2024-05-17 08:44:15 +02:00 by kashikoibumi · 6 comments
kashikoibumi commented 2024-05-17 08:44:15 +02:00 (Migrated from github.com)

Don't use "hello %1".arg("world") : arg() can't be used in Python 3.

In my way to migrate PyBitmessage to the Python3 + PyQt6 environment, I found that arg() must be replaced to another method.
format() method can be used as the best replacement.
But format() uses a different format from arg().
Currently, arg() is used to translating strings.
I imagine If arg() is replaced to format(), all translation resources must be updated simultaneously.
Anyway, that can be a simple regex shell scripting work, but I don't know there are hidden obstacles to be exist or not.
Python 2.7 also support format(), so the migration can be done now.

Who prepares it?
...Me??

Don't use "hello %1".arg("world") : arg() can't be used in Python 3. In my way to migrate PyBitmessage to the Python3 + PyQt6 environment, I found that arg() must be replaced to another method. format() method can be used as the best replacement. But format() uses a different format from arg(). Currently, arg() is used to translating strings. I imagine If arg() is replaced to format(), all translation resources must be updated simultaneously. Anyway, that can be a simple regex shell scripting work, but I don't know there are hidden obstacles to be exist or not. Python 2.7 also support format(), so the migration can be done now. Who prepares it? ...Me??
kashikoibumi commented 2024-05-21 13:30:16 +02:00 (Migrated from github.com)

I found that this problem had been fixed in 'Porting bitmessageqt to Qt5 #1389', but it is not merged to v0.6 .

I found that this problem had been fixed in 'Porting bitmessageqt to Qt5 #1389', but it is not merged to v0.6 .
kashikoibumi commented 2024-05-22 10:23:19 +02:00 (Migrated from github.com)

Truth is a bit different.
The problem that arg() cannot be used is a problem on PyQt version differences, not in Python version differences.
PyQt4's translate() supports arg(), but PyQt5's doesn't.

Example programs follows:

$ cat qt4translate.py 
from PyQt4 import QtGui
print(QtGui.QApplication.translate("default", "hello %1").arg("world"))

$ python2 qt4translate.py 
hello world

$ cat qt5translate.py 
from PyQt5 import QtWidgets
print(QtWidgets.QApplication.translate("default", "hello %1").arg("world"))

$ python2 qt5translate.py 
Traceback (most recent call last):
  File "qt5translate.py", line 2, in <module>
    print(QtWidgets.QApplication.translate("default", "hello %1").arg("world"))
AttributeError: 'unicode' object has no attribute 'arg'

$ cat qtpytranslate.py 
from qtpy import QtWidgets
print(QtWidgets.QApplication.translate("default", "hello %1").arg("world"))

$ python2 qtpytranslate.py 
Traceback (most recent call last):
  File "qtpytranslate.py", line 2, in <module>
    print(QtWidgets.QApplication.translate("default", "hello %1").arg("world"))
AttributeError: 'unicode' object has no attribute 'arg'
Truth is a bit different. The problem that arg() cannot be used is a problem on PyQt version differences, not in Python version differences. PyQt4's translate() supports arg(), but PyQt5's doesn't. Example programs follows: ``` $ cat qt4translate.py from PyQt4 import QtGui print(QtGui.QApplication.translate("default", "hello %1").arg("world")) $ python2 qt4translate.py hello world $ cat qt5translate.py from PyQt5 import QtWidgets print(QtWidgets.QApplication.translate("default", "hello %1").arg("world")) $ python2 qt5translate.py Traceback (most recent call last): File "qt5translate.py", line 2, in <module> print(QtWidgets.QApplication.translate("default", "hello %1").arg("world")) AttributeError: 'unicode' object has no attribute 'arg' $ cat qtpytranslate.py from qtpy import QtWidgets print(QtWidgets.QApplication.translate("default", "hello %1").arg("world")) $ python2 qtpytranslate.py Traceback (most recent call last): File "qtpytranslate.py", line 2, in <module> print(QtWidgets.QApplication.translate("default", "hello %1").arg("world")) AttributeError: 'unicode' object has no attribute 'arg'
kashikoibumi commented 2024-05-22 10:39:12 +02:00 (Migrated from github.com)

Simply replacing arg() to format() works well with PyQt5, but it does not work with PyQt4.

$ cat qt5translate-format.py 
from PyQt5 import QtWidgets
print(QtWidgets.QApplication.translate("default", "hello {0}").format("world"))

$ python2 qt5translate-format.py 
hello world

$ cat qt4translate-format.py 
from PyQt4 import QtGui
print(QtGui.QApplication.translate("default", "hello {0}").format("world"))

$ python2 qt4translate-format.py 
Traceback (most recent call last):
  File "qt4translate-format.py", line 2, in <module>
    print(QtGui.QApplication.translate("default", "hello {0}").format("world"))
AttributeError: 'QString' object has no attribute 'format'

So in order to work with both PyQt5 and PyQt4, additional wrapping by str() is required.

$ cat qt5translate-format-str.py
from PyQt5 import QtWidgets
print(str(QtWidgets.QApplication.translate("default", "hello {0}")).format("world"))

$ python2 qt5translate-format-str.py
hello world

$ cat qt4translate-format-str.py 
from PyQt4 import QtGui
print(str(QtGui.QApplication.translate("default", "hello {0}")).format("world"))

$ python2 qt4translate-format-str.py 
hello world

This also works well with Python3.

$ python3 qt5translate-format-str.py
hello world

$ python3 qt4translate-format-str.py
hello world

The problem is that code becomes complex.
Perhaps it is better to modify the shortcut function _translate() internally apply str().

Simply replacing arg() to format() works well with PyQt5, but it does not work with PyQt4. ``` $ cat qt5translate-format.py from PyQt5 import QtWidgets print(QtWidgets.QApplication.translate("default", "hello {0}").format("world")) $ python2 qt5translate-format.py hello world $ cat qt4translate-format.py from PyQt4 import QtGui print(QtGui.QApplication.translate("default", "hello {0}").format("world")) $ python2 qt4translate-format.py Traceback (most recent call last): File "qt4translate-format.py", line 2, in <module> print(QtGui.QApplication.translate("default", "hello {0}").format("world")) AttributeError: 'QString' object has no attribute 'format' ``` So in order to work with both PyQt5 and PyQt4, additional wrapping by str() is required. ``` $ cat qt5translate-format-str.py from PyQt5 import QtWidgets print(str(QtWidgets.QApplication.translate("default", "hello {0}")).format("world")) $ python2 qt5translate-format-str.py hello world $ cat qt4translate-format-str.py from PyQt4 import QtGui print(str(QtGui.QApplication.translate("default", "hello {0}")).format("world")) $ python2 qt4translate-format-str.py hello world ``` This also works well with Python3. ``` $ python3 qt5translate-format-str.py hello world $ python3 qt4translate-format-str.py hello world ``` The problem is that code becomes complex. Perhaps it is better to modify the shortcut function _translate() internally apply str().
PeterSurda commented 2024-05-22 11:59:03 +02:00 (Migrated from github.com)

arg is needed for the grammar to work correctly. You don't have this issue in Japanese, but you can see it in English, e.g. "1 connection", "2 connections". In other languages it may be even more complex.

`arg` is needed for the grammar to work correctly. You don't have this issue in Japanese, but you can see it in English, e.g. "1 connection", "2 connections". In other languages it may be even more complex.
kashikoibumi commented 2024-05-22 16:18:12 +02:00 (Migrated from github.com)

I did not noticed it at all!!
Sorry, I don't understand it fully yet, I will investigate it more deeply.

I did not noticed it at all!! Sorry, I don't understand it fully yet, I will investigate it more deeply.
kashikoibumi commented 2024-05-22 18:04:32 +02:00 (Migrated from github.com)

As far as my additional research, QString's arg() is able to be used in only Python2 + PyQt4.
In configurations including Python3 or PyQt5, QString is mapped on Python's native string types (unicode in Python2, str in Python3), and they do not have arg() method.
So if you are going to step forward to Python3 or PyQt5, it is required to drop arg() and use format() instead.

There is no solution that respects compatibility among Python versions nor PyQt versions.

Then, what we should do?

As far as my additional research, QString's arg() is able to be used in only Python2 + PyQt4. In configurations including Python3 or PyQt5, QString is mapped on Python's native string types (unicode in Python2, str in Python3), and they do not have arg() method. So if you are going to step forward to Python3 or PyQt5, it is required to drop arg() and use format() instead. There is no solution that respects compatibility among Python versions nor PyQt versions. Then, what we should do?
This repo is archived. You cannot comment on issues.
No Milestone
No project
No Assignees
1 Participants
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: Bitmessage/PyBitmessage-2024-12-04#2231
No description provided.