Metaclasses

Bob.Cowdery at CGI-Europe.com Bob.Cowdery at CGI-Europe.com
Thu Dec 23 10:51:16 CET 2004


Robert Brewer wrote:
>Okay. It depends on where you're getting that capability information from,
but the simplest approach I can >
>think of would be to stick it in the class:
>
>class API(object):
>    __metaclass__ = MetaAPI
>    
>    capmap = global_map_getter(usercontext_or_keyring)
>
>...then "capmap" should be available within MetaAPI.__init__:
>
>class MetaAPI(type):
>    def __init__(cls, name, bases, dct):
>        for name, method in dct['capmap']:
>            setattr(cls, name, method)
>
>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:
>
>from myframework import captools
>
>class API(object):
>    def foo():
>        pass>
>
>captools.enable(API)
>
>
>...the choice comes down IMO to what you think will be the most
usable/maintainable by those who follow you.


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.

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.

When I run this I get:

>>> import api
{'_API__cap': {'MyRig': ['mode', 'mute'], 'SDR1000': ['mode', 'blanker',
'mute'], 'YourRig': ['mode', 'blanker']}, 'radio': 'SDR1000', '__module__':
'api', '__metaclass__': <class 'meta.autoprop'>}
Set property  SDR1000 mode
Set property  SDR1000 blanker
Set property  SDR1000 mute
>>> a = api.API()
>>> a.mode
Traceback (most recent call last):
  File "<pyshell#2>", line 1, in ?
    a.mode
AttributeError: 'API' object has no attribute 'mode'
>>> a.mode = 10
>>> a.mode
10
>>> 

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.

Regards
Bob

Capability class ...
class Capability(object):
    
    global m_radio
    m_radio = '' 
    m_cap = {
            'SDR1000': ['mode','blanker','mute'],
            'MyRig': ['mode','mute'],
            'YourRig': ['mode', 'blanker']
            }          
    def setRadio(radio):
        global m_radio
        m_radio = radio
    
    def getRadio():
        global m_radio
        return m_radio
    
    setRadio = staticmethod(setRadio)
    getRadio = staticmethod(getRadio)

Metaclass class ...
import capability

class autoprop(type):
    def __init__(cls, name, bases, dict):
        super(autoprop, cls).__init__(name, bases, dict)

        print dict

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

Api class ...
import meta
import capability
capability.Capability.setRadio('SDR1000')

class API(object):
    __metaclass__ = meta.autoprop
    
    # Get the capability context
    radio = capability.Capability.getRadio()
    __cap = capability.Capability.m_cap



Robert Brewer
MIS
Amor Ministries
fumanchu at amor.org

*** Confidentiality Notice *** Proprietary/Confidential
Information belonging to CGI Group Inc. and its affiliates
may be contained in this message. If you are not a recipient
indicated or intended in this message (or responsible for
delivery of this message to such person), or you think for
any reason that this message may have been addressed to you
in error, you may not use or copy or deliver this message
to anyone else.  In such case, you should destroy this
message and are asked to notify the sender by reply email.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-list/attachments/20041223/dead4fad/attachment.html>


More information about the Python-list mailing list