Hello,

I have a code file from the boto framework pasted below, all of the print statements are mine, and the one commented out line is also mine, all else belongs to the attributed author.

My question is what is the order in which instantiations and allocations occur in python when instantiating a class? The author's code below is under the assumption that 'DefaultDomainName' will exist when an instance of the class is created (e.g. __init__() is called), but this does not seem to be the case, at least in my testing in python 2.5 on OS X.

In the class Manager __init__() method, my print statements show DefaultDomainName as 'None'. And the print statements in the global function set_domain() further down show 'None' prior to setting Manager.DefaultDomainName, and shows the expected value of 'test_domain' after the assignment. But when creating an instance of Manager again after calling set_domain(), the __init__() method still shows 'None'.

Can anyone help me out, and explain what is going on here. It would be greatly appreciated. Thanks. - Mark (Code below)

# Copyright (c) 2006,2007,2008 Mitch Garnaat http://garnaat.org/
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish, dis-
# tribute, sublicense, and/or sell copies of the Software, and to permit
# persons to whom the Software is furnished to do so, subject to the fol-
# lowing conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.

import boto
from boto.utils import find_class

class Manager(object):

    DefaultDomainName = boto.config.get('Persist', 'default_domain', None)

    def __init__(self, domain_name=None, aws_access_key_id=None, aws_secret_access_key=None, debug=0):
        self.domain_name = domain_name
        self.aws_access_key_id = aws_access_key_id
        self.aws_secret_access_key = aws_secret_access_key
        self.domain = None
        self.sdb = None
        self.s3 = None
        if not self.domain_name:
            print "1: %s" % self.DefaultDomainName
            print "2: %s" % Manager.DefaultDomainName
            self.domain_name = self.DefaultDomainName
            #self.domain_name = 'test_domain'
            if self.domain_name:
                boto.log.info('No SimpleDB domain set, using default_domain: %s' % self.domain_name)
            else:
                boto.log.warning('No SimpleDB domain set, persistance is disabled')
        if self.domain_name:
            self.sdb = boto.connect_sdb(aws_access_key_id=self.aws_access_key_id,
                                        aws_secret_access_key=self.aws_secret_access_key,
                                        debug=debug)
            self.domain = self.sdb.lookup(self.domain_name)
            if not self.domain:
                self.domain = self.sdb.create_domain(self.domain_name)

    def get_s3_connection(self):
        if not self.s3:
            self.s3 = boto.connect_s3(self.aws_access_key_id, self.aws_secret_access_key)
        return self.s3

def get_manager(domain_name=None, aws_access_key_id=None, aws_secret_access_key=None, debug=0):
    return Manager(domain_name, aws_access_key_id, aws_secret_access_key, debug=debug)

def set_domain(domain_name):
    print "3: %s" % Manager.DefaultDomainName
    Manager.DefaultDomainName = domain_name
    print "4: %s" % Manager.DefaultDomainName

def get_domain():
    return Manager.DefaultDomainName

def revive_object_from_id(id, manager):
    if not manager.domain:
        return None
    attrs = manager.domain.get_attributes(id, ['__module__', '__type__', '__lineage__'])
    try:
        cls = find_class(attrs['__module__'], attrs['__type__'])
        return cls(id, manager=manager)
    except ImportError:
        return None

def object_lister(cls, query_lister, manager):
    for item in query_lister:
        if cls:
            yield cls(item.name)
        else:
            o = revive_object_from_id(item.name, manager)
            if o:
                yield o

My question is what is the order in which instantiations and allocations occur in python when instantiating a class? The author's code below is under the assumption that 'DefaultDomainName' will exist when an instance of the class is created (e.g. __init__() is called), but this does not seem to be the case, at least in my testing in python 2.5 on OS X.

This I can explain, but the boto framework is completely unknown to me.

When a new object is created, __new__() is called. I don't know all the details, but it seems from the documentation that __new__() allocates the memory for the object and initializes pointers to the methods. Then, __init__() is called. If an object does not define code for __init__(), then a stub __init__() is created for it which (seems to) contains the code pass.

If the DefaultDomainName were not set in __init__(), then the code above would have thrown an error -- that is, a variable that is not set is not the same as None.

So it seems that the __init__() method really does set the DefaultDomainName to None. You can confirm this by inspecting the code and looking in the __init__ method.

Then the next question would be, "Why did the author write the code in this way?" Clearly, None was intended to be a signal value, so it would be wise to understand what the signal means and treat it accordingly. Else, you run the risk of breaking something somewhere else.

Jeff

This article has been dead for over six months. Start a new discussion instead.