<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=us-ascii">
<META NAME="Generator" CONTENT="MS Exchange Server version 5.5.2653.12">
<TITLE>RE: Metaclasses</TITLE>
</HEAD>
<BODY>

<P><FONT SIZE=2>Robert Brewer wrote:</FONT>
<BR><FONT SIZE=2>>Okay. It depends on where you're getting that capability information from, but the simplest approach I can ></FONT>
<BR><FONT SIZE=2>>think of would be to stick it in the class:</FONT>
<BR><FONT SIZE=2>></FONT>
<BR><FONT SIZE=2>>class API(object):</FONT>
<BR><FONT SIZE=2>>    __metaclass__ = MetaAPI</FONT>
<BR><FONT SIZE=2>>    </FONT>
<BR><FONT SIZE=2>>    capmap = global_map_getter(usercontext_or_keyring)</FONT>
<BR><FONT SIZE=2>></FONT>
<BR><FONT SIZE=2>>...then "capmap" should be available within MetaAPI.__init__:</FONT>
<BR><FONT SIZE=2>></FONT>
<BR><FONT SIZE=2>>class MetaAPI(type):</FONT>
<BR><FONT SIZE=2>>    def __init__(cls, name, bases, dct):</FONT>
<BR><FONT SIZE=2>>        for name, method in dct['capmap']:</FONT>
<BR><FONT SIZE=2>>            setattr(cls, name, method)</FONT>
<BR><FONT SIZE=2>></FONT>
<BR><FONT SIZE=2>>Of course, all of this could be done without using a metaclass--just call setattr as needed right after your >class is defined. Another option would be to immediately follow your API class definition with a call like:</FONT></P>

<P><FONT SIZE=2>></FONT>
<BR><FONT SIZE=2>>from myframework import captools</FONT>
<BR><FONT SIZE=2>></FONT>
<BR><FONT SIZE=2>>class API(object):</FONT>
<BR><FONT SIZE=2>>    def foo():</FONT>
<BR><FONT SIZE=2>>        pass></FONT>
<BR><FONT SIZE=2>></FONT>
<BR><FONT SIZE=2>>captools.enable(API)</FONT>
<BR><FONT SIZE=2>></FONT>
<BR><FONT SIZE=2>></FONT>
<BR><FONT SIZE=2>>...the choice comes down IMO to what you think will be the most usable/maintainable by those who follow you.</FONT>
</P>
<BR>

<P><FONT SIZE=2>Thanks for your help Robert. I'm still not understanding what I am seeing. I've forgotten about the objective for the moment. I just want to understand metaclasses.</FONT></P>

<P><FONT SIZE=2>The code I have is below, in 3 separate files, the capability, the metaclass and the API class. Sorry it's a bit rubbish at the moment.</FONT></P>

<P><FONT SIZE=2>When I run this I get:</FONT>
</P>

<P><FONT SIZE=2>>>> import api</FONT>
<BR><FONT SIZE=2>{'_API__cap': {'MyRig': ['mode', 'mute'], 'SDR1000': ['mode', 'blanker', 'mute'], 'YourRig': ['mode', 'blanker']}, 'radio': 'SDR1000', '__module__': 'api', '__metaclass__': <class 'meta.autoprop'>}</FONT></P>

<P><FONT SIZE=2>Set property  SDR1000 mode</FONT>
<BR><FONT SIZE=2>Set property  SDR1000 blanker</FONT>
<BR><FONT SIZE=2>Set property  SDR1000 mute</FONT>
<BR><FONT SIZE=2>>>> a = api.API()</FONT>
<BR><FONT SIZE=2>>>> a.mode</FONT>
<BR><FONT SIZE=2>Traceback (most recent call last):</FONT>
<BR><FONT SIZE=2>  File "<pyshell#2>", line 1, in ?</FONT>
<BR><FONT SIZE=2>    a.mode</FONT>
<BR><FONT SIZE=2>AttributeError: 'API' object has no attribute 'mode'</FONT>
<BR><FONT SIZE=2>>>> a.mode = 10</FONT>
<BR><FONT SIZE=2>>>> a.mode</FONT>
<BR><FONT SIZE=2>10</FONT>
<BR><FONT SIZE=2>>>> </FONT>
</P>

<P><FONT SIZE=2>Two things I don't understand. __init__ gets called when I import api, not when I create an instance of API so the capability is set in stone on the import and I can't change it. Second when I try to read attribute 'mode' (or any other valid attribute) I get an error. If I set it to some value and read it it's there. I know I am not actually using the capability out of the dict at the moment because I just haven't looked to see how to dig it out yet but it is passed in because it prints out ok.</FONT></P>

<P><FONT SIZE=2>Regards</FONT>
<BR><FONT SIZE=2>Bob</FONT>
</P>

<P><FONT SIZE=2>Capability class ...</FONT>
<BR><FONT SIZE=2>class Capability(object):</FONT>
<BR><FONT SIZE=2>    </FONT>
<BR><FONT SIZE=2>    global m_radio</FONT>
<BR><FONT SIZE=2>    m_radio = '' </FONT>
<BR><FONT SIZE=2>    m_cap = {</FONT>
<BR><FONT SIZE=2>            'SDR1000': ['mode','blanker','mute'],</FONT>
<BR><FONT SIZE=2>            'MyRig': ['mode','mute'],</FONT>
<BR><FONT SIZE=2>            'YourRig': ['mode', 'blanker']</FONT>
<BR><FONT SIZE=2>            }          </FONT>
<BR><FONT SIZE=2>    def setRadio(radio):</FONT>
<BR><FONT SIZE=2>        global m_radio</FONT>
<BR><FONT SIZE=2>        m_radio = radio</FONT>
<BR><FONT SIZE=2>    </FONT>
<BR><FONT SIZE=2>    def getRadio():</FONT>
<BR><FONT SIZE=2>        global m_radio</FONT>
<BR><FONT SIZE=2>        return m_radio</FONT>
<BR><FONT SIZE=2>    </FONT>
<BR><FONT SIZE=2>    setRadio = staticmethod(setRadio)</FONT>
<BR><FONT SIZE=2>    getRadio = staticmethod(getRadio)</FONT>
</P>

<P><FONT SIZE=2>Metaclass class ...</FONT>
<BR><FONT SIZE=2>import capability</FONT>
</P>

<P><FONT SIZE=2>class autoprop(type):</FONT>
<BR><FONT SIZE=2>    def __init__(cls, name, bases, dict):</FONT>
<BR><FONT SIZE=2>        super(autoprop, cls).__init__(name, bases, dict)</FONT>
</P>

<P><FONT SIZE=2>        print dict</FONT>
</P>

<P><FONT SIZE=2>        def _get_mode(self):</FONT>
<BR><FONT SIZE=2>            return self.__mode</FONT>
<BR><FONT SIZE=2>        def _set_mode(self, mode):</FONT>
<BR><FONT SIZE=2>            self.__mode = mode</FONT>
<BR><FONT SIZE=2>        def _get_blanker(self):</FONT>
<BR><FONT SIZE=2>            return self.__blanker</FONT>
<BR><FONT SIZE=2>        def _set_blanker(self, blanker):</FONT>
<BR><FONT SIZE=2>            self.__blanker = blanker</FONT>
<BR><FONT SIZE=2>        def _get_mute(self):</FONT>
<BR><FONT SIZE=2>            return self.__mute</FONT>
<BR><FONT SIZE=2>        def _set_mute(self, mute):</FONT>
<BR><FONT SIZE=2>            self.__mute = mute</FONT>
<BR><FONT SIZE=2>                    </FONT>
<BR><FONT SIZE=2>        # need to dig this out the dict</FONT>
<BR><FONT SIZE=2>        radio = capability.Capability.getRadio()</FONT>
<BR><FONT SIZE=2>        __cap = capability.Capability.m_cap</FONT>
<BR><FONT SIZE=2>        # set capability as properties</FONT>
<BR><FONT SIZE=2>        for i in range(len(__cap[radio])):</FONT>
<BR><FONT SIZE=2>            if __cap[radio][i] == 'mode':</FONT>
<BR><FONT SIZE=2>                print 'Set property ', radio, 'mode'    </FONT>
<BR><FONT SIZE=2>                mode  = property (eval('_get_'+__cap[radio][i]), eval('_set_'+__cap[radio][i]))</FONT>
<BR><FONT SIZE=2>            elif __cap[radio][i] == 'blanker':</FONT>
<BR><FONT SIZE=2>                print 'Set property ', radio, 'blanker' </FONT>
<BR><FONT SIZE=2>                blanker  = property (eval('_get_'+__cap[radio][i]), eval('_set_'+__cap[radio][i]))</FONT>
<BR><FONT SIZE=2>            elif __cap[radio][i] == 'mute':</FONT>
<BR><FONT SIZE=2>                print 'Set property ', radio, 'mute'</FONT>
<BR><FONT SIZE=2>                mute  = property (eval('_get_'+__cap[radio][i]), eval('_set_'+__cap[radio][i]))</FONT>
</P>

<P><FONT SIZE=2>Api class ...</FONT>
<BR><FONT SIZE=2>import meta</FONT>
<BR><FONT SIZE=2>import capability</FONT>
<BR><FONT SIZE=2>capability.Capability.setRadio('SDR1000')</FONT>
</P>

<P><FONT SIZE=2>class API(object):</FONT>
<BR><FONT SIZE=2>    __metaclass__ = meta.autoprop</FONT>
<BR><FONT SIZE=2>    </FONT>
<BR><FONT SIZE=2>    # Get the capability context</FONT>
<BR><FONT SIZE=2>    radio = capability.Capability.getRadio()</FONT>
<BR><FONT SIZE=2>    __cap = capability.Capability.m_cap</FONT>
</P>
<BR>
<BR>

<P><FONT SIZE=2>Robert Brewer</FONT>
<BR><FONT SIZE=2>MIS</FONT>
<BR><FONT SIZE=2>Amor Ministries</FONT>
<BR><FONT SIZE=2>fumanchu@amor.org</FONT>
</P>


<P><STRONG>*** Confidentiality Notice ***</STRONG> 
Proprietary/Confidential<BR>Information belonging to CGI Group Inc. and its 
affiliates<BR>may be contained in this message. If you are not a 
recipient<BR>indicated or intended in this message (or responsible 
for<BR>delivery of this message to such person), or you think for<BR>any reason 
that this message may have been addressed to you<BR>in error, you may not use or 
copy or deliver this message<BR>to anyone else.  In such case, you should 
destroy this<BR>message and are asked to notify the sender by reply 
email.</P>
</BODY>
</HTML>