GNOME Bugzilla – Bug 338098
Add signal/property helpers
Last modified: 2007-05-01 15:54:02 UTC
Defining signals and properties for an object is quite tricky, some of the problems with the current situation: * The API is just horrible, __gsignals__ and __gproperties__ is plain ugly. * You need to specify reduntant information, in most cases it doesn't matter when the signal is run nor what the return value is * There's no way of getting good error messages, which makes it very frustrating to specify properties, eg, some pspecs requires more parameters than others, numeric types want maximum, minimum apart from the default
Created attachment 63244 [details] [review] v1: Add gsignal/gproperty in gobject.utils These are wrappers which I wrote some time ago and has been included in kiwi and various other places. I'd welcome suggestions for API changes and improvements. The gproperty needs to be improved to always throw errors before type_register does, which is currently not the case. However it's still better than the current situation.
My 0.02€ (for starting): - Strip the 'g' prefix and move the functions into gobject module; - Don't use gobject.type_is_a; it is deprecated. - Not sure "float : _max('f')," on _MAX_VALUES is correct: max value of a floating point number cannot be calculated like that.
> - Strip the 'g' prefix and move the functions into gobject module; I disagree mainly because of the following two reasons: * __init__.py should never do any aliasing, because it breaks the mapping of import statements to source files, eg if you see a line like: from foo.bar.baz import noogie You can be sure that noogie is defined in a file called baz.py in the directory foo/bar. * the gobject namespace should belong to gobject itself, not to python extensions or additions > - Don't use gobject.type_is_a; it is deprecated. It is not deprecated. And it is actually not the same as isinstance or issubclass. > - Not sure "float : _max('f')," on _MAX_VALUES is correct: max value of a > floating point number cannot be calculated like that. That's one of the improvements that needs to be done, but we can't access G_MAXFLOAT currently.
Having spent a bit of time thinking about the problem I don't have any better answer than these methods. At least they are documented.
Created attachment 63642 [details] [review] signals and properties alternative This patch adds an alternative, though similar, way of registering properties and signals. Examples: Register a property: foo = gobject.property(str, default='bar') Register a signal: my_signal = gobject.signal(int)
ping?
(In reply to comment #6) > ping? > okay, I think I generally like your patch, but I have a few questions: - I found out a way of calculating the max/minimum value for float, it can be found in the trunk of kiwi. - We need plenty of tests for this. - Can we move the code to a separate module, to keep __init__.py smaller? - It's a bit evil cleaning up all properties & signals. What are the disadvantages of leaving them there? [possible with more information stored such as args, max min etc] A: gobject.property('name', int) B: name = gobject.property(int) B is often preferred, but that implies that you can access the value after creating the class. [eg, no delattr as the patch does] Perhaps we should include a little bit more metaclass magic if you use gobject.property so that obj.prop is roughly the same as obj.props.prop. Signals are a little bit more complicated, perhaps we want to leave a reference to something which can be emitted and connected? obj.signal.emit() obj.signal.connect(func) Will there be name space collissions in case of overriding? If we want to do all this, should we also do it for signals/properties defined in __gsignals__/__gproperties__ ? API/ABI compatibilty might be too hard in that case.
Created attachment 87290 [details] [review] patch This adds a property helper similar to the one suggested by Gustavo in attachment 63642 [details] [review]. * custom getters & setters support * Much improved maximum/minimum checks * With unittests * Some documentation
Only a quick glance, but something jumps at me: you are removing unit testing of old style properties and replacing with new unit tests. I think we should continue to unit test even old properties because they need to continue working. Another comment is, we already have a highly efficient C based property descriptor. While I like a Python frontend for declaring and registering properties, once they're registered I would prefer to use the C descriptor. This can be easily done by iterating over the class attributes of type gobject.property and replacing them with equivalent C descriptors.
(In reply to comment #9) > Only a quick glance, but something jumps at me: you are removing unit testing > of old style properties and replacing with new unit tests. I think we should > continue to unit test even old properties because they need to continue > working. It was a good way to find bugs in the code. Not sure if it's worth keeping the tests as they used to be. I didn't remove the tests themselves, only the way of defining the properties. > Another comment is, we already have a highly efficient C based property > descriptor. While I like a Python frontend for declaring and registering > properties, once they're registered I would prefer to use the C descriptor. > This can be easily done by iterating over the class attributes of type > gobject.property and replacing them with equivalent C descriptors. I'd prefer porting over the property class to C instead, that'd make most sense since there are other performance critical path (do_set/get_property, the default setters). Keeping the current one as a reference implementation is probably a good idea. I'm also not convinced that a C based implementation is going to be worth the effort, but I won't stop you if you want to spend your time doing that.
(In reply to comment #10) > (In reply to comment #9) > > Only a quick glance, but something jumps at me: you are removing unit testing > > of old style properties and replacing with new unit tests. I think we should > > continue to unit test even old properties because they need to continue > > working. > > It was a good way to find bugs in the code. Not sure if it's worth keeping the > tests as they used to be. I didn't remove the tests themselves, only the way of defining the properties. But the old way properties are defined needs to keep working as usual, so it should continue to be tested IMHO. > > > Another comment is, we already have a highly efficient C based property > > descriptor. While I like a Python frontend for declaring and registering > > properties, once they're registered I would prefer to use the C descriptor. > > This can be easily done by iterating over the class attributes of type > > gobject.property and replacing them with equivalent C descriptors. > > I'd prefer porting over the property class to C instead, that'd make most sense > since there are other performance critical path (do_set/get_property, the > default setters). > Keeping the current one as a reference implementation is probably a good idea. > > I'm also not convinced that a C based implementation is going to be worth the > effort, but I won't stop you if you want to spend your time doing that. That's a good plan. I'll see what (if anything) I can do to optimise, after the python based design is finalized and committed. Too soon to worry about performance anyway. Anyway, looks great.
(In reply to comment #11) > But the old way properties are defined needs to keep working as usual, so it > should continue to be tested IMHO. Actually I disagree, since it's just syntactic sugar that is the difference. We end up populating __gproperties__ with identical values. The point of the tests are just to define properties, not the syntax used to define them! > That's a good plan. I'll see what (if anything) I can do to optimise, after > the python based design is finalized and committed. Too soon to worry about > performance anyway. Anyway, looks great. > Good, I'll write some more tests and commit it.
Committed as revision 662. I'll close this bug and open up a new one for a signal helper.