1

My question is, after this line: -> self.__serverUrl = serverUrl

Why is this the case?: *** AttributeError: Client instance has no attribute '__serverUrl'

Details

I'm using Beatbox to interact with Salesforce and I was getting an error

*** AttributeError: Client instance has no attribute '_Client__serverUrl'

I wondered why this field was being accessed before it was set, so I added pdb.set_trace() thinking I could find some answers. This is what I saw (note line 67):

(Pdb)
--Call--
> /app/env/local/lib/python2.7/site-packages/beatbox/_beatbox.py(65)useSession()
-> def useSession(self, sessionId, serverUrl):
(Pdb) l
 64         # initialize from an existing sessionId & serverUrl, useful if we're being launched via a custom link
 65  ->     def useSession(self, sessionId, serverUrl):
 66             self.sessionId = sessionId
 67             self.__serverUrl = serverUrl
 68             (scheme, host, path, params, query, frag) = urlparse(self.__serverUrl)
 69             self.__conn = makeConnection(scheme, host)
 70

I check the value of serverUrl, and all is as it should be. Then I get to line 67, let it execute and think that the value of serverUrl would be in self.__serverUrl. Apparently not....

> /app/env/local/lib/python2.7/site-packages/beatbox/_beatbox.py(67)useSession()
-> self.__serverUrl = serverUrl
(Pdb) n
> /app/env/local/lib/python2.7/site-packages/beatbox/_beatbox.py(68)useSession()
-> (scheme, host, path, params, query, frag) = urlparse(self.__serverUrl)
(Pdb) self.__serverUrl
*** AttributeError: Client instance has no attribute '__serverUrl'

What is happening here!? This shouldn't be happening. It looks like the assignment is just quietly failing. Why is this value not being assigned here?

The Source

The source code I'm working with is here

I create a beatbox client and login

svc = PythonClient()
svc.login(username, password)

This calls the login method of python_client.Client. python_client.Client.login calls the login method of it's superclass _beatbox.Client, which looks like this:

class Client:
    def __init__(self, serverUrl=None):
       ...

    # login, the serverUrl and sessionId are automatically handled, returns the loginResult structure       
    def login(self, username, password):
        lr = LoginRequest(self.serverUrl, username, password).post()
        self.useSession(str(lr[_tPartnerNS.sessionId]), str(lr[_tPartnerNS.serverUrl]))
        return lr

    # initialize from an existing sessionId & serverUrl, useful if we're being launched via a custom link   
    def useSession(self, sessionId, serverUrl):
        self.sessionId = sessionId
        self.__serverUrl = serverUrl
        (scheme, host, path, params, query, frag) = urlparse(self.__serverUrl)
        self.__conn = makeConnection(scheme, host)

The assginment happens in _beatbox.Client.useSession, which is the superclass of the object svc

2
  • 1
    which is it? is it '_Client__serverUrl' or __serverUrl? You might be a victim of name mangling ... Commented Mar 7, 2013 at 19:21
  • Outside of this method, it's _Client_serverUrl, inside the method it's _serverUrl. Name mangling doesn't happen inside class methods does it? Commented Mar 7, 2013 at 19:21

1 Answer 1

3

Names prefixed by a double underscore (and not suffixed by a double underscore) are mangled when they appear within a class scope. The names are mangled by prefixing _<classname>.

If you declare a function at global scope which sets a double-underscore-prefixed name, you will set the wrong attribute because the name mangling will not occur. If you declare such a function in a derived class, you will also access the wrong attribute because the name mangling will add the derived class's name instead of the base class (hence, name mangling implements a weak form of private attributes).

The proper thing to do would be to avoid name mangling altogether if subclasses need to access the attribute, or use a property. If you can't avoid it, you will have to use this kludge:

self._Client__serverUrl = ...
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.