It is currently Sat Jun 29, 2024 10:08 pm


All times are UTC - 5 hours [ DST ]



Post new topic Reply to topic  [ 5 posts ] 
Author Message
 Post subject: Convert GIMP plugin from Python 2 to Python 3
PostPosted: Sat Aug 26, 2023 12:37 pm  (#1) 
Offline
GimpChat Member
User avatar

Joined: Aug 22, 2017
Posts: 72
I want to convert my plugin from Python 2 to Python 3 using "Python 2 to 3 converter (https://python2to3.com/)".
The converter wants to convert the following Python 2 code
def pluginGestartet():
  if (shelf.has_key(pluginName) and shelf[pluginName]):
    return True
  return False
to the following Python 3 code
def pluginGestartet():
  if (pluginName in shelf and shelf[pluginName]):
    return True
  return False
When I swap out the code in my plugin, GIMP reports the following error:
Quote:
Traceback (most recent call last):
File "C:\Program Files\GIMP 2\lib\gimp\2.0\python/gimpplugin.py", line 76, in _run
return apply(getattr(self, name), params)
File "C:\Users\Herbert\AppData\Roaming\GIMP\2.10\plug-ins\HN-Pfeil-zeichnen\HN-Pfeil-zeichnen.py", line 3488, in HN_Pfeil_zeichnen
if pluginGestartet():
File "C:\Users\Herbert\AppData\Roaming\GIMP\2.10\plug-ins\HN-Pfeil-zeichnen\HN-Pfeil-zeichnen.py", line 3186, in pluginGestartet
if (pluginName in shelf and shelf[pluginName]):
File "C:\Program Files\GIMP 2\lib\gimp\2.0\python/gimpshelf.py", line 75, in __getitem__
s = gimp.get_data(key)
TypeError: get_data() argument 1 must be string, not int
I do not understand why! The object "pluginName" is of type "str".

Can someone help me?


Share on Facebook Share on Twitter Share on Orkut Share on Digg Share on MySpace Share on Delicious Share on Technorati
Top
 Post subject: Re: Convert GIMP plugin from Python 2 to Python 3
PostPosted: Sat Aug 26, 2023 2:19 pm  (#2) 
Offline
GimpChat Member
User avatar

Joined: Jan 13, 2011
Posts: 2260
Location: Poland
Hi Herbie.

I'm not a programmer so I can't help You.
Just wanted to point out that in addition to the change from Python2 to Python3 in Gimp 2.99, gtk-2.0 is also changed to gtk-3.0 and Gimp procedures (at the moment Gimp-2.99 compared to Gimp-2.10 changed 181 procedures).

_________________
Image

Slava
Ukraini!


Top
 Post subject: Re: Convert GIMP plugin from Python 2 to Python 3
PostPosted: Sat Aug 26, 2023 4:39 pm  (#3) 
Offline
Script Coder
User avatar

Joined: Oct 25, 2010
Posts: 4752
Herbie wrote:
I want to convert my plugin from Python 2 to Python 3 using "Python 2 to 3 converter (https://python2to3.com/)".
The converter wants to convert the following Python 2 code
def pluginGestartet():
  if (shelf.has_key(pluginName) and shelf[pluginName]):
    return True
  return False
to the following Python 3 code
def pluginGestartet():
  if (pluginName in shelf and shelf[pluginName]):
    return True
  return False
When I swap out the code in my plugin, GIMP reports the following error:
Quote:
Traceback (most recent call last):
File "C:\Program Files\GIMP 2\lib\gimp\2.0\python/gimpplugin.py", line 76, in _run
return apply(getattr(self, name), params)
File "C:\Users\Herbert\AppData\Roaming\GIMP\2.10\plug-ins\HN-Pfeil-zeichnen\HN-Pfeil-zeichnen.py", line 3488, in HN_Pfeil_zeichnen
if pluginGestartet():
File "C:\Users\Herbert\AppData\Roaming\GIMP\2.10\plug-ins\HN-Pfeil-zeichnen\HN-Pfeil-zeichnen.py", line 3186, in pluginGestartet
if (pluginName in shelf and shelf[pluginName]):
File "C:\Program Files\GIMP 2\lib\gimp\2.0\python/gimpshelf.py", line 75, in __getitem__
s = gimp.get_data(key)
TypeError: get_data() argument 1 must be string, not int
I do not understand why! The object "pluginName" is of type "str".

Can someone help me?


I don' t see anything in the code above that demonstrates that the erroneous "key" is the pluginName.

In Gimp 2.99, the various directories have a ../2.99/.. component and not a ../2.0/.. so I don't know where that gimpshelf.py comes from (and as far as I cant tell there is no gimpshelf.py in either 2.10 or 2.99...)

And as a side note the if/else in the function is totally superfluous:
def pluginGestartet():
      return pluginName in shelf and shelf[pluginName]

and since the get() method on a dictionary returns a null if the key doesn't exist, there is the hackish
def pluginGestartet():
      # second "not" makes a True of empty string or None, and a False of an existing string
      # first "not" invert this
      return not not shelf.get(pluginName)

_________________
Image


Top
 Post subject: Re: Convert GIMP plugin from Python 2 to Python 3
PostPosted: Tue Aug 29, 2023 9:40 am  (#4) 
Offline
GimpChat Member
User avatar

Joined: Mar 23, 2012
Posts: 7315
Location: Göteborg at last!
vitforlinux wrote:
You may be the hero who initiates the change, but the road is full of obstacles, you have to overcome mountains, slay dragons, and keep away from the thumping trees... and hope there is nothing else new in Gimp 2.99.18.

Be brave.

Your sig says "Excuse my spaghetti english" but you have a wonderful way of expressing yourself in english. ;) :bigthup


Top
 Post subject: Re: Convert GIMP plugin from Python 2 to Python 3
PostPosted: Tue Apr 23, 2024 11:21 am  (#5) 
Offline
GimpChat Member

Joined: Aug 30, 2020
Posts: 5
I know this is a very old post, but... since there will be a lot of Python-converting happening in the coming years, it's worth documenting these kinds of issues and the reasons behind them. (Fair warning, up front: This is going to get a bit into the Python weeds. I'll drop a TL;DR at the end for those who don't care about the hows and whys.)

The problem with the auto-conversion Herbie was provided is that it assumes the object being accessed (in this case, shelf) is an instance of a standard Python collection datatype (a dict), with all of the appropriate methods defined for an object of that type.

Unfortunately, in this case, shelf is an instance of Gimpshelf (which can be found at the gimp repository in the file gimp/plugins/pygimp/gimpshelf.py), and Gimpshelf is NOT a complete implementation of the Python dict interface.

In particular, Gimpshelf implements has_key() (a Python 2 method used to determine whether a key is present in a dict), and it implements the Python standard __getitem__, __setitem__, and __delitem__ methods for manipulating the contents of the collection. But that's ALL — it's not a subclass of any standard Python type, so it doesn't have any of the other standard methods.

The in operator, in particular, has several methods for determining whether an item is a member of a collection. As each preferred method fails, it falls back on less efficient/compatible alternatives.

in looks first for a __contains__ method, which it can call to request a direct answer to the question "do you contain this item?" Gimpshelf doesn't provide __contains__.

in then falls back to trying an __iter__ method, which will produce each of the member items in sequence so it can compare them to its target item. If any of them match, the result is True. Gimpshelf doesn't provide __iter__.

• As a last resort, in falls back to trying __getitem__, which it calls using increasing numerical indices, attempting to find an index i for which shelf[i] == target.

Since Gimpshelf provides __getitem__ and only __getitem__, of the methods in supports, it's using it to attempt to access the keys of shelf via numerical indices — something shelf does not support. That's why you're seeing __getitem__ calling gimp.get_data() with numerical arguments.

TL;DR: Because shelf is not a Python standard data type, but rather a Gimp class which itself hasn't been upgraded for Python 3, you should continue to use shelf.has_key() to examine its contents. Attempting to switch to the unsupported (for that class, regardless of Python version) in operator will lead to unsupported uses of the class's interface.

The interface provided by any datatypes implemented by Gimp code (rather than in Python itself) won't change simply by running them in Python 3. Until such changes are made, the code to access them shouldn't be "upgraded".

This would be a correct Python 3 version of the OP's snippet, when accessing an unmodified pygimp Gimpshelf instance:

def pluginGestartet():
  if (shelf.has_key(pluginName) and shelf[pluginName]):
    return True
  return False


(Yes, it's unchanged from the original. The original code was already Python 3 compatible.)

Or, as ofnuts suggested, it could be streamlined as

def pluginGestartet():
  return shelf.has_key(pluginName) and shelf[pluginName]


But you need to keep using shelf.has_key() until such time as the Gimpshelf code itself is upgraded.


Top
Post new topic Reply to topic  [ 5 posts ] 

All times are UTC - 5 hours [ DST ]


   Similar Topics   Replies 
No new posts Attachment(s) Can someone please convert these two python scripts for Gimp 2.99.19

10

No new posts Attachment(s) Macbook User and Python plugin

14

No new posts Unable to get simple python plugin to show up

8

No new posts Difference between "Python-Fu" and "Python" plugin

6

No new posts Please make a python plugin to combine my GEGL filters with GMIC

1



* Login  



Powered by phpBB3 © phpBB Group