473,695 Members | 2,788 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Class introspection and dynamically determining function arguments

I'd like to write a Tkinter app which, given a class, pops up a
window(s) with fields for each "attribute" of that class. The user could
enter values for the attributes and on closing the window would be
returned an instance of the class. The actual application I'm interested
in writing would either have simple type attributes (int, string, etc.),
or attributes using types already defined in a c-extension, although I'd
prefer not to restrict the functionality to these requirements.

The only way I can imagine to do this is to create an instance of the
class in question, and then start poking around in its attributes
dictionary (initially just using dir). So firstly, if there is instead a
way to do this without creating an instance I'd be interested.

Secondly, the code won't know exactly how to initialise the class
instance used to determinte the attributes. Do I need to make it a
prerequesite that all instances can be created with no arguments ?
Should I force/allow the user to pass an instance instead of a class ?
Should I be using inspect.getargs pec on the class __init__ method and
then a loop with a try and a lot of except clauses, or is there a nicer
way to do this ? Presumably the pickling code knows how do
serialise/deserialise class instances but I'm not sure how I'd use this
without already having a class instance to hand.

Lastly, does such an app already exist ?

Thanks for any help.
-----------------------------------------------------------------------
The information contained in this e-mail is confidential and solely
for the intended addressee(s). Unauthorised reproduction, disclosure,
modification, and/or distribution of this email may be unlawful. If you
have received this email in error, please notify the sender immediately
and delete it from your system. The views expressed in this message
do not necessarily reflect those of LIFFE Holdings Plc or any of its subsidiary companies.
-----------------------------------------------------------------------

Jul 18 '05 #1
8 2532
Mark English wrote:
The only way I can imagine to do this is to create an instance of the
class in question, and then start poking around in its attributes
dictionary (initially just using dir). So firstly, if there is instead a
way to do this without creating an instance I'd be interested.


This is the only way to go, as python has no attribute declarations as
static compiled languages have. But of course not all classes may feature
default constructors so that creating an instance is impossible. Or you
create unwanted sideeffects - think of the notorious class
DeleteMyHarddis k....

As youself already mentioned that maybe you have to impose certain
prerequisites, you maybe want to extend this to the point where for each
class you want to make dynamically instantiatable you need some
declaration. This of course depends on your desired application - whatfor
is it planned?

--
Regards,

Diez B. Roggisch
Jul 18 '05 #2
Diez B. Roggisch wrote:
Mark English wrote:
As youself already mentioned that maybe you have to impose certain
prerequisites, you maybe want to extend this to the point where for each
class you want to make dynamically instantiatable you need some
declaration. This of course depends on your desired application - whatfor
is it planned?


If this only has to work for classes created for the purpose (rather than for an
arbitrary class):

Py> class Buildable(objec t):
.... __slots__ = ["x", "y"]
.... def __init__(self, **kwds):
.... super(Buildable , self).__init__( self, **kwds)
.... for attr in Buildable.__slo ts__:
.... setattr(self, attr, kwds[attr])
....
Py> b = Buildable(x = 1 , y = 2)
Py> b.x
1
Py> b.y
2

(Note that you don't *have* to use slots, you can use a non-special class
attribute if you don't want the other side effects)

Cheers,
Nick.

--
Nick Coghlan | nc******@email. com | Brisbane, Australia
---------------------------------------------------------------
http://boredomandlaziness.skystorm.net
Jul 18 '05 #3
Nick Coghlan wrote:

If this only has to work for classes created for the purpose (rather than
for an arbitrary class):


Certainly a step into the direction I meant - but still missing type
declarations. And that's what at least I'd like to see - as otherwise you
don't know what kind of editing widget to use for a property.
--
Regards,

Diez B. Roggisch
Jul 18 '05 #4
Diez B. Roggisch wrote:
Nick Coghlan wrote:
If this only has to work for classes created for the purpose (rather than
for an arbitrary class):

Certainly a step into the direction I meant - but still missing type
declarations. And that's what at least I'd like to see - as otherwise you
don't know what kind of editing widget to use for a property.


Hmm, true. You really need a name:type dict to define each class that is going
to be generated.

Perhaps the simplest way is to require all such classes to have a "getExample "
class method that produces a fully populated example instance (making it a class
method means that you shouldn't need to override it in a subclass if you don't
change the signature of __init__).

Then the widget generator doesn't need to care about *how* that default example
gets generated, and can be something simple like:

build_widget(na me, data_type):
...

build_widget_li st(cls):
example = cls.getExample( )
widgets = []
for attr, value in example.__dict_ _:
widgets.append( build_widget(at tr, type(value)))
return widgets

Cheers,
Nick.

--
Nick Coghlan | nc******@email. com | Brisbane, Australia
---------------------------------------------------------------
http://boredomandlaziness.skystorm.net
Jul 18 '05 #5
On Thu, 20 Jan 2005 11:24:12 -0000, "Mark English" <Ma**********@l iffe.com> wrote:
I'd like to write a Tkinter app which, given a class, pops up a
window(s) with fields for each "attribute" of that class. The user could
enter values for the attributes and on closing the window would be
returned an instance of the class. The actual application I'm interested
in writing would either have simple type attributes (int, string, etc.),
or attributes using types already defined in a c-extension, although I'd
prefer not to restrict the functionality to these requirements. My first reaction is that if you can limit the problem, it could be done fairly simply.
[... having read to the end by now, I see you were thinking of inspecting the __init__
method, so you are close to what I was thinking, but maybe this will be useful anyway,
so since it's done, I'll post it ;-) ]

E.g., if the attributes of interest are all set by simple attribute assignment in
the __init__ method of the class, using __init__ arguments with default arguments,
then you could inspect the __init__ function for parameter names and infer types
from the default arguments.

If the instance attribute name are bound in the __new__ method, you could still conceivably
do something if you had a similar known signature, but the for unrestricted general case
your Tkinter app would have to supply too much information than can't be inferred or be known
by the user. E.g., how would a Tkinter app (or any other) know what to ask the user to supply
to set the attributes of

class WhatEver:
def __init__(self, attr):
self.attr = attr

?

The only way I can imagine to do this is to create an instance of the
class in question, and then start poking around in its attributes
dictionary (initially just using dir). So firstly, if there is instead a
way to do this without creating an instance I'd be interested. As above. IMO you will have to restrict the problem. But perhaps that is
no so bad.

Secondly, the code won't know exactly how to initialise the class
instance used to determinte the attributes. Do I need to make it a
prerequesite that all instances can be created with no arguments ? I think that is a byproduct of the approach I suggested (i.e., all args
having default values for type inference), but there's probably other
ways.
Should I force/allow the user to pass an instance instead of a class ? I would say no. Especially considering possible side effects.
Should I be using inspect.getargs pec on the class __init__ method and
then a loop with a try and a lot of except clauses, or is there a nicer I don't know if you need a _lot_ of except clauses, but yes, at least one,
and a loop to allow retrying after typos etc.
way to do this ? Presumably the pickling code knows how do
serialise/deserialise class instances but I'm not sure how I'd use this
without already having a class instance to hand.

Lastly, does such an app already exist ? Don't know. Wouldn't be surprised.

Thanks for any help.


This shows you are probably close to solving your own problem with inspect.getargs pec:
class C(object): ... def __init__(self, a=1, b='bee', c=1.2):
... self.a = a
... self.b = b
... self.c = c
... inspect.getargs pec(C.__init__) (['self', 'a', 'b', 'c'], None, None, (1, 'bee', 1.2)) print inspect.getargs pec.__doc__ Get the names and default values of a function's arguments.

A tuple of four things is returned: (args, varargs, varkw, defaults).
'args' is a list of the argument names (it may contain nested lists).
'varargs' and 'varkw' are the names of the * and ** arguments or None.
'defaults' is an n-tuple of the default values of the last n arguments.
args,_,_,defaul ts = inspect.getargs pec(C.__init__)
values = []
Obviously you need an inner loop for correcting typos etc., and try/except to catch relevant
errors, but I'm just typing interactively here, so her goes:
for name, defv in zip(args[-len(defaults):], defaults): ... vstr = raw_input('Plea se enter a string suitable for %s(s): '%type(defv).__ name__)
... values.append(t ype(defv)(vstr) )
...
Please enter a string suitable for int(s): 123
Please enter a string suitable for str(s): 'this is a string'
Please enter a string suitable for float(s): 1.5 values [123, "'this is a string'", 1.5] c = C(*values)
c.a 123 c.b "'this is a string'" c.c 1.5 cdef = C()
cdef.a, cdef.b, cdef.c (1, 'bee', 1.2)

I guess the single quotes on the str(s) entry shows that all the characters get entered ;-)
You might want to think about whether to process backslashes as escapes in your input. E.g.,
raw_input('Ente r some escape example: ') Enter some escape example: Not an newline: \n -- nor '\n' ;-)
"Not an newline: \\n -- nor '\\n' ;-)" print raw_input('Ente r some escape example: ') Enter some escape example: Not an newline: \n -- nor '\n' ;-)
Not an newline: \n -- nor '\n' ;-)

BTW, You can avoid importing inspect and get the data of
inspect.getargs pec(C.__init__) (['self', 'a', 'b', 'c'], None, None, (1, 'bee', 1.2))

that you want by looking at the unbound method C.__init__
(though im_func may be deprecated eventually?):
C.__init__.im_f unc.func_code.c o_varnames ('self', 'a', 'b', 'c') C.__init__.im_f unc.func_defaul ts (1, 'bee', 1.2)

or by getting the __init__ function as such, by avoiding the attribute
access that makes it and unbound or bound method
C.__dict__['__init__'].func_code.co_v arnames ('self', 'a', 'b', 'c') C.__dict__['__init__'].func_defaults

(1, 'bee', 1.2)

Regards,
Bengt Richter
Jul 18 '05 #6
On Thu, 20 Jan 2005 11:24:12 -0000, "Mark English" <Ma**********@l iffe.com> wrote:
I'd like to write a Tkinter app which, given a class, pops up a
window(s) with fields for each "attribute" of that class. The user could
enter values for the attributes and on closing the window would be
returned an instance of the class. The actual application I'm interested
in writing would either have simple type attributes (int, string, etc.),
or attributes using types already defined in a c-extension, although I'd
prefer not to restrict the functionality to these requirements.

Hmm, I missed the original post, but I'll jump in anyway:

This sounds a heck of a lot like a property-editing system. When
creating a property-modeled system, the best approach is normally to
use something that actually models the properties, rather than
trying to guess at the metadata involved by poking around in an
arbitrarily structured object.

My BasicProperty system allows for this kind of interaction
(property-sheets) using wxPython (rather than Tkinter) when using
wxoo. You declare classes as having a set of data-properties (which
can have defaults or not, constraints or not, restricted data-types
or not, friendly names or not, documentation or not). Normally you
create these classes as subclasses of a class that knows how to
automatically assign __init__ parameters to properties, and knows
how to tell (e.g.) wxoo about the properties of the class.

Those same property classes also allow for editing properties of
database rows in PyTable, but that isn't likely relevant to your
case. We've also used them internally to create a rather large
web-based property-editing mechanism (applied to such databases),
but again, not really relevant to the case at hand.

Anyway, if you aren't interested in BasicProperty for this task; another
project on which I work, PyDispatcher provides fairly robust mechanism
(called robustApply) for providing a set of possible arguments and using
inspect to pick out which names match the parameters for a function in
order to pass them in to the function/method/callable object. That
said, doing this for __init__'s with attribute values from an object's
dictionary doesn't really seem like the proper way to approach the problem.

Good luck,
Mike

_______________ _______________ _______________ ___
Mike C. Fletcher
Designer, VR Plumber, Coder
http://www.vrplumber.com
http://blog.vrplumber.com

Jul 18 '05 #7
On Fri, 21 Jan 2005 20:23:58 -0500, "Mike C. Fletcher" <mc******@roger s.com> wrote:
On Thu, 20 Jan 2005 11:24:12 -0000, "Mark English" <Ma**********@l iffe.com> wrote:
I'd like to write a Tkinter app which, given a class, pops up a
window(s) with fields for each "attribute" of that class. The user could
enter values for the attributes and on closing the window would be
returned an instance of the class. The actual application I'm interested
in writing would either have simple type attributes (int, string, etc.),
or attributes using types already defined in a c-extension, although I'd
prefer not to restrict the functionality to these requirements.
Hmm, I missed the original post, but I'll jump in anyway:

This sounds a heck of a lot like a property-editing system. When
creating a property-modeled system, the best approach is normally to
use something that actually models the properties, rather than
trying to guess at the metadata involved by poking around in an
arbitrarily structured object.

I agree that "poking around in an arbitrarily structured object" is not
a likely road to satisfaction, but sometimes the arbitrary can be taken out
an something pretty simple can be done ;-)

OTOH, I probably should have mentioned that there are ways to view these
kinds of problems from a longer perspective. E.g., I googled for
"model view controller" and found a nice wiki page at

http://wact.sourceforge.net/index.ph...ViewController

that may be worth reading for the OP, just for ideas. There is interesting discussion
of many MVC-related issues, but I don't know anything about the associated project.

My BasicProperty system allows for this kind of interaction
(property-sheets) using wxPython (rather than Tkinter) when using
wxoo. You declare classes as having a set of data-properties (which
can have defaults or not, constraints or not, restricted data-types
or not, friendly names or not, documentation or not). Normally you
create these classes as subclasses of a class that knows how to
automatically assign __init__ parameters to properties, and knows
how to tell (e.g.) wxoo about the properties of the class. Does the BasicProperty base class effectively register itself as an observer
of subclass properties and automatically update widgets etc., a la Delphi
data-driven visual components? I've thought of doing a light-weight form
extension class that would use a text (maybe CSV) definition to control
contruction, and easy programmatic manipulation by python of the definition
parameters, like a stripped-down version of the text view of Delphi forms.
It could also be done via Tkinter, to prototype it. It would be interesting
to allow dragging widgets and edges around in Tkinter and round-trip the parameter
changes automatically into the text representation. A little (well, ok, a fair amount ;-)
further and you'd have a drag-n-drop GUI design tool. But don't hold your breath ;-)

Those same property classes also allow for editing properties of
database rows in PyTable, but that isn't likely relevant to your
case. We've also used them internally to create a rather large
web-based property-editing mechanism (applied to such databases),
but again, not really relevant to the case at hand. Who knows, the OP may only be revealing his concerns about a small part of
his great tapestry ;-)

Anyway, if you aren't interested in BasicProperty for this task; another
project on which I work, PyDispatcher provides fairly robust mechanism
(called robustApply) for providing a set of possible arguments and using
inspect to pick out which names match the parameters for a function in
order to pass them in to the function/method/callable object. That
said, doing this for __init__'s with attribute values from an object's
dictionary doesn't really seem like the proper way to approach the problem.

Sounds like a workaround for parameter passing that maybe should have been
keyword-based?

Regards,
Bengt Richter
Jul 18 '05 #8
Diez B. Roggisch <de*********@we b.de> wrote:
Nick Coghlan wrote:

If this only has to work for classes created for the purpose (rather than
for an arbitrary class):


Certainly a step into the direction I meant - but still missing type
declarations. And that's what at least I'd like to see - as otherwise you
don't know what kind of editing widget to use for a property.


Though it may be overkill for your needs, you'll be interested in
Enthought's "Traits", I think; see, for example,
<http://python.fyxm.net/pycon/papers/traits.html>. Facilitating such
presentation tasks (no doubt including editing) appears to be a major
driving force for Traits.
Alex
Jul 18 '05 #9

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

0
1240
by: Stephen Nesbitt | last post by:
All: Here's my implementation problem. I have a base class which has the responsibility for providing entry into the logging system. Part of the class responsibility is to ensure that lagger names are consistent. For all intents and purposes this class should be considered abstract and will always be subclassed. What I want to do is the following: - allow the logger name to set explicitly. I've accomplished this by
15
9064
by: Steven T. Hatton | last post by:
The following may strike many of you as just plain silly, but it represents the kind of delelima I find myself in when trying to make a design decision. This really is a toy project written for the purpose of learning to work with C++. It therefore makes some sense for me to give the situation the amount of consideration presented below. To be quite honest, I'm amazed at the amount there is to say about such a seemingly simple...
3
12482
by: N. Demos | last post by:
How do you dynamically assign a function to an element's event with specific parameters? I know that the code is different for MSIE and Mozilla, and need to know how to do this for both. I have the following event handler functions defined and need to assign them to table elements (<TD>) created dynamically in another function. function handleMouseOver(elt, cssClass, strURL)
3
2207
by: Karsten W. | last post by:
Hello, with the zope.interface module I can query if my class claims to implement my API. This is what the method implementedBy is for. However, I find myself constantly changing the API and I am looking for a more reliable way to check my implementation classes. Is there a way to check if at least all function names of the API are defined by the class and if their parameter lists
2
1497
by: lcaamano | last post by:
We have a tracing decorator that automatically logs enter/exits to/from functions and methods and it also figures out by itself the function call arguments values and the class or module the function/method is defined on. Finding the name of the class where the method we just entered was defined in is a bit tricky. Here's a snippet of the test code: class Base: @tracelevel(1)
8
1985
by: Jackson | last post by:
I want a class that will determine its base class by the argument passed in. What I am about to write _does_not_work_, but it shows what I am trying to do. class ABC(some_super): def __init__(self,some_super): some_super.__init__(self) if some_super == list: self.append('ABC')
3
1490
by: Scott Lamb | last post by:
I'm trying to dynamically generate class methods which have access to some state passed in at creation time. (Basically as a workaround to twisted's trial not having a way to dynamically add stuff. Plain unittest seems to have TestSuite, but the trial runner doesn't know about it.) My first attempt might better illustrate this - class Foo: def generalized(self, ctx):
7
2527
by: Ron Goral | last post by:
Hello I am new to creating objects in javascript, so please no flames about my coding style. =) I am trying to create an object that will represent a "div" element as a menu. I have written several methods that are working fine. The problem is if I want to dynamically assign an event handler to the object, the event handler is not called. What am I doing wrong? Below is a sample HTML doc with everything in place. <!DOCTYPE HTML PUBLIC...
6
6265
by: Adam C. | last post by:
We have a situation where we want a Swig-generated Python class to have a different base (not object). It doesn't appear that we can coerce Swig into generating the class we want at present (but we are still enquiring). Is it possible to dynamically change the base class to something else? Initial experiments appear to show it is not: -------------------------------- snip -------------------------------- pass
0
8586
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
9137
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
9004
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
8864
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
8838
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
1
6506
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
5842
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
4351
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
2
2289
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.