Re: [pygtk] Gobject properties to PyObject attributes mapping

2003-08-14 Thread Jan Weil
Jan Weil schrieb:
I don't like this idea either.
Especially because it's quite easy to emulate this behaviour in Python 
(see example attached).

That's obviously not an option if you had to wrap every gtk widget by hand.
This one wouldn't let me sleep. But it's really fun (see example attached).
Good night,

Jan

import gobject
import gtk
import new
import types

class MyObject:
def __init__(self):
if issubclass(self.__class__, gobject.GObject):
self.properties = []
for param in gobject.list_properties(self):
self.properties.append(param.name)

def __setattr__(self, key, value):
self.__dict__[key] = value
if hasattr(self, "properties") and key in self.properties:
self.set_property(key, value)

def __getattr__(self, key):
if hasattr(self, "properties") and key in self.properties:
return self.get_property(key)
else:
return self.__dict__.get(key, None)

__dict__ = globals()

for _o in gtk.__dict__.values():
if type(_o) is types.TypeType and issubclass(_o, gtk.Widget):
def __init__(self, *args, **keys):
self.__gtk_class.__init__(self, *args, **keys)
MyObject.__init__(self)

__dict__[_o.__name__] = new.classobj(_o.__name__, (MyObject, _o), {"__init__": 
__init__, "__gtk_class": _o})
#!/usr/bin/env python

import gtk
import mygtk

b = mygtk.Button(label = "Hello, world!")

def on_clicked(*args):
b.label = b.label + "\nHello, world!"
print b.get_property("label")

b.connect("clicked", on_clicked)

w = mygtk.Window()
w.add(b)

w.show_all()

gtk.main()
___
pygtk mailing list   [EMAIL PROTECTED]
http://www.daa.com.au/mailman/listinfo/pygtk
Read the PyGTK FAQ: http://www.async.com.br/faq/pygtk/


Re: [pygtk] Gobject properties to PyObject attributes mapping

2003-08-14 Thread Jan Weil
Iñaki García Etxebarria schrieb:
But IMO the main question is whether it is really advantageously to map 
the properties to attributes.
I think so, it produces readable code, and many times is very natural.
And, to me at least, the design of the properties api in gobject is
thought with this kind of purposes in mind.
I totally agree that the code becomes more readable and even more beautiful.

I am by no means an expert of OOP but what I read is that public data 
members in the long run tend to be unflexible.
Thus you typically provide a pair of accessors like set_value, get_value 
(set_property/get_property).

But probably my view is not pythonesque (?) enough.
Eventually, these attributes only look like public data members and what 
happens internally if they are accessed is still under control.

Jan

___
pygtk mailing list   [EMAIL PROTECTED]
http://www.daa.com.au/mailman/listinfo/pygtk
Read the PyGTK FAQ: http://www.async.com.br/faq/pygtk/


Re: [pygtk] Gobject properties to PyObject attributes mapping

2003-08-14 Thread Jon Willeke
This may not be a democracy, but I would vote against this change. 
Merging namespaces like this is asking for trouble.  If it is done at
all, it should only be at the explicit request of the programmer (e.g.,
import gtk.__propertyHack__ as gtk).

On Fri, 2003-08-08 at 15:20, Iñaki García Etxebarria wrote:
> IMHO, there are more advantages than disadvantages [just put a big fat
> warning in the next few releases or something], but that is left to the
> maintainers to decide.

___
pygtk mailing list   [EMAIL PROTECTED]
http://www.daa.com.au/mailman/listinfo/pygtk
Read the PyGTK FAQ: http://www.async.com.br/faq/pygtk/


Re: [pygtk] Gobject properties to PyObject attributes mapping

2003-08-14 Thread Jan Weil
Christian Reis kiko at async.com.br wrote:
Ah; Note that this is wrong here. You should not return None from
getattr, or all lookups on the object for non-existent attributes will
return None. This should be:
try:
return self.__dict__[key]
except KeyError:
raise AttributeError, key
See http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52238

Thanks, I wasn't aware of that one!

You could skip the if self.__properties there, but since setattr can
potentially be called a lot and the list of properties is long, it might
save some (potentially infinitesimal ) time.
(PS: I'm not sharp on how the 'in' operator is implemented; if it's a
constant-time operation then this is silly and you can skip the
self.__properties check).
Well this code was by no means optimized. It was more something like a 
proof of concept (for myself).

But IMO the main question is whether it is really advantageously to map 
the properties to attributes.
What about read-only properties?
Can you control the access to certain properties?

Jan

___
pygtk mailing list   [EMAIL PROTECTED]
http://www.daa.com.au/mailman/listinfo/pygtk
Read the PyGTK FAQ: http://www.async.com.br/faq/pygtk/


Re: [pygtk] Gobject properties to PyObject attributes mapping

2003-08-14 Thread Christian Reis
On Mon, Aug 11, 2003 at 01:11:01AM +0200, Jan Weil wrote:
> I am by no means an expert of OOP but what I read is that public data 
> members in the long run tend to be unflexible.
> Thus you typically provide a pair of accessors like set_value, get_value 
> (set_property/get_property).

Well, it could be argued that providing accessors is only a more elegant
way of making private data public . 

The line is hard to draw, but I would say in the general case of a
*widget*, having properties as attributes makes a lot of sense and
simplifies code significantly. Yes, you get an increased change of a
namespace conflict with user code, but I find it sanitizes things if the
properties are well-named: 

dorothy_label.label = "This doesn't look like Kansas anymore" 
dorothy_label.justify = JUSTIFY_LEFT

-- should really do the obvious (and not set vaporous "label" and
"justify" attributes that have nothing to do with the label's
behaviour).

> Eventually, these attributes only look like public data members and what 
> happens internally if they are accessed is still under control.

Yes, you can always use Python properties to control access to instance
attributes.

Take care,
--
Christian Reis, Senior Engineer, Async Open Source, Brazil.
http://async.com.br/~kiko/ | [+55 16] 261 2331 | NMFL
___
pygtk mailing list   [EMAIL PROTECTED]
http://www.daa.com.au/mailman/listinfo/pygtk
Read the PyGTK FAQ: http://www.async.com.br/faq/pygtk/


Re: [pygtk] Gobject properties to PyObject attributes mapping

2003-08-14 Thread Christian Reis
On Sun, Aug 10, 2003 at 11:36:05AM +0200, Jan Weil wrote:
> Did you try this code?

Are you suggesting I don't test my code submissions? :o)

No; I don't have PyGTK2 available on my network.

> The problem is that if you assign to __properties in __init__, 
> __setattr__ is called which calls __getattr__ in the if clause but 
> __properties isn't set yet --> recursion
> Therefor you have to treat the internal properties list attribute in a 
> special manner and that's why I couldn't hide it (__*).

Yeah, my bad. Just do it a tiny bit differently:

> Christian Reis kiko at async.com.br wrote:
> > You could get away with something a bit simpler even:
> >
> > class MyObject:
> > def __init__(self):
> > if issubclass(self.__class__, gobject.GObject):
> > self.__properties = list(gobject.list_properties(self)
> > else:
> > self.__properties = []

 if isinstance(self, gobject.GObject): 
 props = list(gobject.list_properties(self)
 else:
 props = []
self.__dict__['_MyObject__properties'] = props

The name mangling needs to be done or else the lookup below will fail.

> > def __setattr__(self, key, value):
> > if self.__properties and key in self.__properties:
> > self.set_property(key, value)
> > else:
> > self.__dict__[key] = value
> >
> > def __getattr__(self, key):
> > if self.__properties and key in self.__properties:
> > return self.get_property(key)
> > else:
> > return self.__dict__.get(key, None)

Ah; Note that this is wrong here. You should not return None from
getattr, or all lookups on the object for non-existent attributes will
return None. This should be:

try:
return self.__dict__[key]
except KeyError:
raise AttributeError, key

See http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52238

You could skip the if self.__properties there, but since setattr can
potentially be called a lot and the list of properties is long, it might
save some (potentially infinitesimal ) time.

(PS: I'm not sharp on how the 'in' operator is implemented; if it's a
constant-time operation then this is silly and you can skip the
self.__properties check).

Take care,
--
Christian Reis, Senior Engineer, Async Open Source, Brazil.
http://async.com.br/~kiko/ | [+55 16] 261 2331 | NMFL
___
pygtk mailing list   [EMAIL PROTECTED]
http://www.daa.com.au/mailman/listinfo/pygtk
Read the PyGTK FAQ: http://www.async.com.br/faq/pygtk/


Re: [pygtk] Gobject properties to PyObject attributes mapping

2003-08-14 Thread Iñaki García Etxebarria
El vie, 08-08-2003 a las 15:07, Gustavo J. A. M. Carneiro escribió:
> > label = gtk.Label()
> > label.label = 'Hello World' # Changes the label in the gui
> > print label.label # prints 'Hello World'
> 
>   Perhaps it is wiser to add a small prefix to the python attribute, to
> avoid possible conflicts with user code? Example:
I agree there could be a conflict, honestly I don't know how can we
avoid this without adding the prefix (which sort of defeats the purpose
of the patch, which is transparent, elegant access to properties).

There's certainly code that will break, see for example
examples/gobject/properties.py in the pygtk distribution. On the other
hand, that's the only thing pygtk code I have seen that breaks, and it
is trivial to fix (prefix the internal class variable foo with prop_ to
avoid the recursion, for example).

IMHO, there are more advantages than disadvantages [just put a big fat
warning in the next few releases or something], but that is left to the
maintainers to decide.

Kind regards,
Iñaki

___
pygtk mailing list   [EMAIL PROTECTED]
http://www.daa.com.au/mailman/listinfo/pygtk
Read the PyGTK FAQ: http://www.async.com.br/faq/pygtk/


Re: [pygtk] Gobject properties to PyObject attributes mapping

2003-08-12 Thread Iñaki García Etxebarria
> But IMO the main question is whether it is really advantageously to map 
> the properties to attributes.
I think so, it produces readable code, and many times is very natural.
And, to me at least, the design of the properties api in gobject is
thought with this kind of purposes in mind.

> What about read-only properties?
It's easy to check this when __set__ is called. If the property is
readonly emit a Type Error and put an informative error description, as
done in other parts of Python. It wasn't in my patch, but it's
three-four lines if you want it.

> Can you control the access to certain properties?
What for? Sorry, I don't see the point in this, cannot you always use
the normal "function" api anyway?

Iñaki

___
pygtk mailing list   [EMAIL PROTECTED]
http://www.daa.com.au/mailman/listinfo/pygtk
Read the PyGTK FAQ: http://www.async.com.br/faq/pygtk/


Re: [pygtk] Gobject properties to PyObject attributes mapping

2003-08-11 Thread Christian Reis
On Sun, Aug 10, 2003 at 03:55:56AM +0200, Jan Weil wrote:
> Good night,
> 
> class MyObject:
> def __init__(self):
> if issubclass(self.__class__, gobject.GObject):
> self.properties = []
> for param in gobject.list_properties(self):
> self.properties.append(param.name)
> 
> def __setattr__(self, key, value):
> self.__dict__[key] = value
> if hasattr(self, "properties") and key in self.properties:
> self.set_property(key, value)
> 
> def __getattr__(self, key):
> if hasattr(self, "properties") and key in self.properties:
> return self.get_property(key)
> else:
> return self.__dict__.get(key, None)

You could get away with something a bit simpler even:

class MyObject:
def __init__(self):
if issubclass(self.__class__, gobject.GObject):
self.__properties = list(gobject.list_properties(self))
else:
self.__properties = []

def __setattr__(self, key, value):
if self.__properties and key in self.__properties:
self.set_property(key, value)
else:
self.__dict__[key] = value

def __getattr__(self, key):
if self.__properties and key in self.__properties:
return self.get_property(key)
else:
return self.__dict__.get(key, None)

Take care,
--
Christian Reis, Senior Engineer, Async Open Source, Brazil.
http://async.com.br/~kiko/ | [+55 16] 261 2331 | NMFL
___
pygtk mailing list   [EMAIL PROTECTED]
http://www.daa.com.au/mailman/listinfo/pygtk
Read the PyGTK FAQ: http://www.async.com.br/faq/pygtk/


Re: [pygtk] Gobject properties to PyObject attributes mapping

2003-08-11 Thread Jan Weil
I don't like this idea either.
Especially because it's quite easy to emulate this behaviour in Python 
(see example attached).

Jan

Jon Willeke schrieb:
This may not be a democracy, but I would vote against this change. 
Merging namespaces like this is asking for trouble.  If it is done at
all, it should only be at the explicit request of the programmer (e.g.,
import gtk.__propertyHack__ as gtk).

On Fri, 2003-08-08 at 15:20, Iñaki García Etxebarria wrote:

IMHO, there are more advantages than disadvantages [just put a big fat
warning in the next few releases or something], but that is left to the
maintainers to decide.

#!/usr/bin/env python

import gobject
import gtk

class MyObject:
def __init__(self):
if issubclass(self.__class__, gobject.GObject):
self.properties = []
for param in gobject.list_properties(self):
self.properties.append(param.name)

def __setattr__(self, key, value):
self.__dict__[key] = value
if hasattr(self, "properties") and key in self.properties:
self.set_property(key, value)

class MyLabel(MyObject, gtk.Label):
def __init__(self, str=None):
gtk.Label.__init__(self, str)
MyObject.__init__(self)

if __name__ == "__main__":
w = gtk.Window()
l = MyLabel()
l.label = "Hello, world!"
print l.label
w.add(l)
w.show_all()
gtk.main()
___
pygtk mailing list   [EMAIL PROTECTED]
http://www.daa.com.au/mailman/listinfo/pygtk
Read the PyGTK FAQ: http://www.async.com.br/faq/pygtk/


Re: [pygtk] Gobject properties to PyObject attributes mapping

2003-08-11 Thread Iñaki García Etxebarria
Hi,

El dom, 10-08-2003 a las 01:04, Jan Weil escribió:
> I don't like this idea either.
> Especially because it's quite easy to emulate this behaviour in Python 
> (see example attached).
Well, as long as I can write the Python code as I want, I don't care
much about the underlying implementation :-) So I'm OK if I can do what
you suggest (or if I have to do 'from gtk import iñaki_is_on_crack', as
another message suggested).

That said, and inspired by bug 81879 in gnome-python bugzilla, attached
goes a descriptor implementation of the same behavior (hey, we can all
have some fun coding weird stuff ;-)).

This should make the binding of the properties rather elegant, now you
can do help(gtk.Label) and you get a list with the attributes with their
corresponding documentation (in case gtk provides any),
gtk.Label.label.__doc__ works too, of course. This means less confusion
if things don't behave as expected.

dir(gtk.Label) lists the attributes as regular attributes, which it
didn't do in my previous patch.

In three words, completely transparent access.

I would do the 'from gtk import crack' thingie but I have no clue on how
to do that.

Enjoy,
Iñaki
--- ../pygobject.c  Thu Jul 31 15:10:16 2003
+++ pygobject.c Sun Aug 10 20:28:51 2003
@@ -80,6 +80,87 @@
 g_array_append_val(sink_funcs, sf);
 }
 
+static PyObject *
+pygobject_get_prop_descr(PyGObject *self, char *param_name)
+{
+GParamSpec *pspec;
+GValue value = { 0, };
+PyObject *ret;
+
+pspec = g_object_class_find_property(G_OBJECT_GET_CLASS(self->obj),
+param_name);
+if (!pspec) {
+   PyErr_SetString(PyExc_TypeError,
+   "the object does not support the given parameter");
+   return NULL;
+}
+g_value_init(&value, G_PARAM_SPEC_VALUE_TYPE(pspec));
+g_object_get_property(self->obj, param_name, &value);
+ret = pyg_value_as_pyobject(&value, TRUE);
+g_value_unset(&value);
+return ret;
+}
+
+static int
+pygobject_set_prop_descr(PyGObject *self, PyObject *pvalue, char *param_name)
+{
+GParamSpec *pspec;
+GValue value = { 0, };
+
+pspec = g_object_class_find_property(G_OBJECT_GET_CLASS(self->obj),
+param_name);
+if (!pspec) {
+   PyErr_SetString(PyExc_TypeError,
+   "the object does not support the given parameter");
+   return -1;
+}
+g_value_init(&value, G_PARAM_SPEC_VALUE_TYPE(pspec));
+if (pyg_value_from_pyobject(&value, pvalue) < 0) {
+   PyErr_SetString(PyExc_TypeError,
+   "could not convert argument to correct param type");
+   return -1;
+}
+g_object_set_property(self->obj, param_name, &value);
+g_value_unset(&value);
+return 0;
+}
+
+static void
+pygobject_add_class_properties_as_descriptors (GType gtype,
+  PyTypeObject *type)
+{
+GObjectClass *class;
+GParamSpec **props;
+guint n_props = 0, i;
+PyObject *descr;
+char *name, *prop_name;
+PyGetSetDef *def;
+
+class = g_type_class_ref(gtype);
+props = g_object_class_list_properties(class, &n_props);
+for (i=0; iowner_type != gtype)
+   continue;
+
+   /* Python won't make a copy so we need the strdup */
+   prop_name = g_strdup(g_param_spec_get_name(props[i]));
+   name = g_strdup(prop_name);
+   /* Convert '-' to '_' */
+   g_strdelimit(name, "-", '_');
+   def = g_new(struct PyGetSetDef, 1);
+   def->name = name;
+   def->doc = g_strdup(g_param_spec_get_blurb(props[i]));
+   def->closure = prop_name;
+   def->get = (getter)pygobject_get_prop_descr;
+   def->set = (setter)pygobject_set_prop_descr;
+   descr = PyDescr_NewGetSet(type, def);
+   PyDict_SetItemString(type->tp_dict, name, descr);
+   Py_DECREF(descr);
+}
+g_free (props);
+g_type_class_unref (class);
+}
+
 /**
  * pygobject_register_class:
  * @dict: the module dictionary.  A reference to the type will be stored here.
@@ -122,6 +203,7 @@
 type->tp_weaklistoffset = offsetof(PyGObject, weakreflist);
 type->tp_dictoffset = offsetof(PyGObject, inst_dict);
 
+
 if (PyType_Ready(type) < 0) {
g_warning ("couldn't make the type `%s' ready", type->tp_name);
return;
@@ -135,6 +217,9 @@
/* stash a pointer to the python class with the GType */
Py_INCREF(type);
g_type_set_qdata(gtype, pygobject_class_key, type);
+
+   /* add the class properties as member descriptors */
+   pygobject_add_class_properties_as_descriptors(gtype, type);
 }
 
 /* set up __doc__ descriptor on type */
@@ -508,52 +593,26 @@
 pygobject_get_property(PyGObject *self, PyObject *args)
 {
 gchar *param_name;
-GParamSpec *pspec;
-GValue value = { 0, };
-PyObject *ret;
 
 if (!PyArg_ParseTuple(args, "s:GObject.get_property", ¶m_name))
return NULL;
-pspec = g_object_class_find_pro

Re: [pygtk] Gobject properties to PyObject attributes mapping

2003-08-09 Thread Gustavo J. A. M. Carneiro
A Qui, 2003-08-07 às 19:22, Iñaki García Etxebarria escreveu:
> Howdy everyone,
> 
> Attached goes a patch against pygtk 1.99.17 that lets you do things like
> ---
> label = gtk.Label()
> label.label = 'Hello World' # Changes the label in the gui
> print label.label # prints 'Hello World'

  Perhaps it is wiser to add a small prefix to the python attribute, to
avoid possible conflicts with user code? Example:
label = gtk.Label()
label.prop_label = 'Hello World' # Changes the label in the gui
print label.prop_label # prints 'Hello World'

  Or maybe not... Either way is fine by me, I think this is a great
idea.

> ---
> for any gobject. I.e., setting gobject properties as if they were
> regular attributes. I hope this hasn't been decided against before, imho
> it is nice sugar.
> 
> I'm a novice with Python and not an expert with gtk2, so I don't expect
> it to be accepted (the method is certainly not optimal and probably not
> Pythonesque in style), but hopefully it will inspire someone to
> implement the feature properly.
> 
> Kind regards,
> Iñaki
> 
> __
> ___
> pygtk mailing list   [EMAIL PROTECTED]
> http://www.daa.com.au/mailman/listinfo/pygtk
> Read the PyGTK FAQ: http://www.async.com.br/faq/pygtk/
-- 
Gustavo João Alves Marques Carneiro
<[EMAIL PROTECTED]> <[EMAIL PROTECTED]>


___
pygtk mailing list   [EMAIL PROTECTED]
http://www.daa.com.au/mailman/listinfo/pygtk
Read the PyGTK FAQ: http://www.async.com.br/faq/pygtk/


Re: [pygtk] Gobject properties to PyObject attributes mapping

2003-08-07 Thread Christian Reis
On Thu, Aug 07, 2003 at 08:22:06PM +0200, Iñaki García Etxebarria wrote:
> Howdy everyone,
> 
> Attached goes a patch against pygtk 1.99.17 that lets you do things like
> ---
> label = gtk.Label()
> label.label = 'Hello World' # Changes the label in the gui
> print label.label # prints 'Hello World'
> ---
> for any gobject. I.e., setting gobject properties as if they were
> regular attributes. I hope this hasn't been decided against before, imho
> it is nice sugar.
> 
> I'm a novice with Python and not an expert with gtk2, so I don't expect
> it to be accepted (the method is certainly not optimal and probably not
> Pythonesque in style), but hopefully it will inspire someone to
> implement the feature properly.

+1 by me.

I'm for this change, and I've discussed it with other people on #pygtk
before (Joe Shaw, IIRC, and Johan).

Take care,
--
Christian Reis, Senior Engineer, Async Open Source, Brazil.
http://async.com.br/~kiko/ | [+55 16] 261 2331 | NMFL
___
pygtk mailing list   [EMAIL PROTECTED]
http://www.daa.com.au/mailman/listinfo/pygtk
Read the PyGTK FAQ: http://www.async.com.br/faq/pygtk/