After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 636043 - When using a separate build tree, GIR has incomplete type information
When using a separate build tree, GIR has incomplete type information
Status: RESOLVED FIXED
Product: gtk+
Classification: Platform
Component: .General
2.91.x
Other Linux
: Normal minor
: ---
Assigned To: gtk-bugs
gtk-bugs
Depends on:
Blocks:
 
 
Reported: 2010-11-29 08:39 UTC by Martin Pitt
Modified: 2015-03-07 23:29 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
fix building introspection with a separate build directory (989 bytes, patch)
2010-12-02 16:07 UTC, Martin Pitt
committed Details | Review

Description Martin Pitt 2010-11-29 08:39:33 UTC
When I call Gdk.Window.set_functions with just one flag, things work fine. However, when I combine them using |, python seems to convert these to int, which breaks:

python -c 'from gi.repository import Gdk, Gtk; Gtk.require_version("3.0"); d=Gtk.Dialog(); d.show(); d.get_window().set_functions(Gdk.WMFunction.MOVE|Gdk.WMFunction.RESIZE)'
Traceback (most recent call last):
  • File "<string>", line 1 in <module>
  • File "/home/martin/upstream/pygobject/gi/types.py", line 40 in function
    return info.invoke(*args)
TypeError: argument 1: Must be Gdk.WMFunction, not int

A workaround is to wrap the or'ed flags into a new constructor like

  d.get_window().set_functions(Gdk.WMFunction(Gdk.WMFunction.MOVE|Gdk.WMFunction.RESIZE))

This works, but looks a bit ugly and might not be obvious enough.

This is with pygobject git head (as of fd2c02), g-i git head (as of 1113955), and GTK 2.91.4.
Comment 1 johnp 2010-11-30 19:50:21 UTC
Enums should allow and int to be passed also.  Looking into it
Comment 2 johnp 2010-11-30 20:03:59 UTC
This works fine for me.  I don't get the traceback.
Comment 3 Martin Pitt 2010-12-01 06:37:22 UTC
Are you trying with python3? I only tried with 2.6 and 2.7.

If it doesn't happen for 3, we can probably ignore it.

Thanks!
Comment 4 johnp 2010-12-01 18:09:21 UTC
Nope, I've been in Python 2 world lately (2.7).  I would like to figure out why you are getting this error with up to date libraries.  Could it be a compile option is triggering a different code path?
Comment 5 Martin Pitt 2010-12-01 18:38:29 UTC
Can we compare what these two print for you?

$ python2.7 --version
Python 2.7.1

$ python2.7 -c 'from gi.repository import Gdk, Gtk; Gtk.require_version("3.0"); print type(Gdk.WMFunction.MOVE), type(Gdk.WMFunction.MOVE|Gdk.WMFunction.RESIZE)'
<class 'gi.repository.Gdk.Enum'> <type 'int'>

This would tell us whether it's staying a Gdk.Enum for you or whether set_functions() also takes an int. To confirm this, we can also check whether an explicit conversion to an int works for you or not:

$ python -c 'from gi.repository import Gdk, Gtk; Gtk.require_version("3.0"); d=Gtk.Dialog(); d.show(); d.get_window().set_functions(int(Gdk.WMFunction.MOVE|Gdk.WMFunction.RESIZE))'
Comment 6 johnp 2010-12-01 19:55:28 UTC
Weird:

$ python2.7 --version
Python 2.7

python2.7 -c 'from gi.repository import Gdk, Gtk; Gtk.require_version("3.0");
print type(Gdk.WMFunction.MOVE), type(Gdk.WMFunction.MOVE|Gdk.WMFunction.RESIZE)'

<class 'gi.repository.Gdk.GdkWMFunction'> <class 'gi.repository.Gdk.GdkWMFunction'>


print (Gdk.WMFunction.MOVE|Gdk.WMFunction.RESIZE)
<flags GDK_FUNC_RESIZE | GDK_FUNC_MOVE of type GdkWMFunction>



python2.7 -c 'from gi.repository import Gdk, Gtk; Gtk.require_version("3.0");
d=Gtk.Dialog(); d.show();
d.get_window().set_functions(6)'

Traceback (most recent call last):
  • File "<string>", line 3 in <module>
  • File "/home/johnp/devel/gnome-shell/install/lib64/python2.7/site-packages/gi/types.py", line 40 in function
    return info.invoke(*args)
TypeError: argument 1: Must be Gdk.WMFunction, not int


Ok, so there are two issues here.  First for some reason your version of Python does not create a new flag but instead returns an int.  Could be a compile flag or simply a change between 2.7  and 2.7.1.  Second it turns out that flags do not take ints while it should.

On the second issue I think we don't see this in the tests because we are only checking Enums not Flags.  I'm not sure why we handle Enums and Flags differently but I know before I was not looking at the Flags codepath.

Thanks for this test.  This gives me something to go on.  I'm not sure if we can fix the first discrepancy (or that we really care) but by accepting ints for flags we should be able to fix your issue.
Comment 7 johnp 2010-12-01 20:44:46 UTC
On further investigation we don't allow numbers to be used as flags and expect a TypeError to be raised in the tests:

======================================================================
FAIL: test_flags_in (test_gi.TestGFlags)
----------------------------------------------------------------------
Traceback (most recent call last):
  • File "/home/johnp/devel/gnome-shell/source/pygobject/tests/test_gi.py", line 1011 in test_flags_in
    self.assertRaises(TypeError, GIMarshallingTests.flags_in, 1 << 1)
AssertionError: TypeError not raised

----------------------------------------------------------------------

I'm guessing this is so you can't just throw a random number at it or "or" together two different flag types.  git blame says Tomeu wrote that code so I will talk to him about it in the morning.  

This means that we have to fix issue 1 which is the fact that "or"'ing two flags does not give you a flag type for some reason.  I'll take a look at that code path in the meantime.
Comment 8 johnp 2010-12-01 20:57:40 UTC
Can you run your test in comment 5 in gdb and break on - pyg_flags_or

$ gdb --args python2.7 -c 'from gi.repository import Gdk, Gtk; Gtk.require_version("3.0");
print type(Gdk.WMFunction.MOVE),type(Gdk.WMFunction.MOVE|Gdk.WMFunction.RESIZE)'

gdb> break pyg_flags_or
gdb> run


Let me know if that actually executes.  If not, Python is turning your flags into ints at some point before or'ing them.  Also, step through it and make sure it calls pyg_flags_from_gtype
Comment 9 Martin Pitt 2010-12-02 11:27:31 UTC
I built current git head again, with -g -O0 (as these are static functions) and tested this. (BTW - first time that all 449 test cases succeed, great job!)

I set a breakpoint on pyg_flags_new (just to see whether library loading and debugging works, etc.) and pyg_flags_or, and as you suspected the latter isn't called at all. To be 100% sure (and to increase test turnaround) I added a puts to both functions, which confirms this.

Just for the fun I also tried with & instead of |. Now this test actually runs and I see a dialog window blinking for a split second, and no error! However, pyg_flags_and() isn't called either; could this be because this just computes to 0 and 0 is treated specially? using ^ gives the same result as |, i. e. error and pyg_flags_xor isn't called.
Comment 10 Martin Pitt 2010-12-02 11:51:33 UTC
Oh, hang on. Comment 6 seems to indicate that there is a difference between "enum" and "flags", and that in your setup you get "flags". Not for me, though:

~/upstream/pygobject$ PYTHONPATH=. python2.7 -c 'from gi.repository import Gdk; print Gdk.WMFunction.MOVE, type(Gdk.WMFunction.MOVE)'
4 <class 'gi.repository.Gdk.Enum'>


But you get something like <class 'gi.repository.Gdk.GdkWMFunction'>.

Now, if I compare the GIR from our gtk 2.91.5 package with the one from git head, I see an important difference:

-    <bitfield name="WMFunction" c:type="GdkWMFunction">
+    <bitfield name="WMFunction"
+              glib:type-name="GdkWMFunction"
+              glib:get-type="gdk_wm_function_get_type"
+              c:type="GdkWMFunction">

I. e. in my currently installed system GIR I don't actually have a type assigned.

And sure enough, with GI_TYPELIB_PATH=/home/martin/upstream/gtk+/gdk it works just fine. So presumably this was fixed in gtk git head, or we built 2.91.5 with an older pygobject/gi, but I'll track that down on my end.

Thanks a lot for your assistance and sorry for the noise! At least I learned about the enum vs. flag typing, and will try with the typelib from gtk head right away next time.
Comment 11 Martin Pitt 2010-12-02 15:50:12 UTC
I'm getting closer to the root cause of this. Our packages use a separate build directory (because we need to build some different flavours). When I do that in git head with

 ./autogen.sh
  make distclean
  mkdir buildtree && cd buildtree
  ../configure --enable-introspection
  make -C gdk -j4

this fails with

  GISCAN Gdk-3.0.gir
In file included from <stdin>:4:0:
/home/martin/upstream/gtk+/gdk/gdk.h:42:30: fatal error: gdk/gdkenumtypes.h: No such file or directory

If I now copy gdkenumtypes.h from the 2.91.5 release tarball (it's in "EXTRA_DIST" and thus pre-built), I get a broken GIR:

  $ cp ~/ubuntu/build-area/gtk+3.0-2.91.5/gdk/gdkenumtypes.h ../gdk
  $ make -C gdk -j4
  $ grep -A3 bitfield.*WMFunction gdk/Gdk-3.0.gir
    <bitfield name="WMFunction" c:type="GdkWMFunction">
      <doc xml:whitespace="preserve">These are hints originally defined by the Motif toolkit. The window manager
can use them when determining the functions to offer for the window. The
hint must be set before mapping the window.</doc>

I. e. it's missing the glib:type-name and glib:get-type attributes, as I pointed out in the previous comment. This is the scenario that happens in a package build.

I now built without a separate build tree; it seems that the gir is correct now, but the generated gdkenumtypes.h didn't actually change:

$ diff -u /home/martin/ubuntu/build-area/gtk+3.0-2.91.5/gdk/gdkenumtypes.h gdk/gdkenumtypes.h
# (no output)
$ grep -A3 bitfield.*WMFunction gdk/Gdk-3.0.gir
    <bitfield name="WMFunction"
              glib:type-name="GdkWMFunction"
              glib:get-type="gdk_wm_function_get_type"
              c:type="GdkWMFunction">
Comment 12 Martin Pitt 2010-12-02 16:07:00 UTC
Created attachment 175719 [details] [review]
fix building introspection with a separate build directory

With this patch you can now properly build gtk+ from git head in a separate build tree (with the commands in comment 11), and the GDK gir has the correct type information.

This still doesn't actually fix our package build (it still produces a broken gir), but it's an useful fix to have on its own.
Comment 13 Martin Pitt 2010-12-02 16:13:48 UTC
For the record, the package build now works fine with above patch applied when I also remove gdkenumtypes.[hc] from the unpacked source tree before build. I don't know yet why, it might be sensitive to different configure options that we pass. But I need to stop working on this for today, I'll keep it as a workaround.

Just one question, what is the reason for shipping gdkenumtypes.[hc] in the dist tarballs?

Thanks,

Martin
Comment 14 Martin Pitt 2010-12-02 16:35:14 UTC
> it might be sensitive to different configure options that we pass

So that's not it. All the build trees that I have, upstream git, our installed version in /usr/include/ are all identical. For some reason the GIR scanner can't pick up genumtypes.h if it's outside the build tree.
Comment 15 Martin Pitt 2011-02-21 15:23:19 UTC
While the current patch doesn't solve the original problem, it's still good to have on its own right. OK for me to push?
Comment 16 Matthias Clasen 2015-03-07 23:29:16 UTC
Review of attachment 175719 [details] [review]:

this has been committed at some point