AttributeError: 'contactObject' object has no attribute - python

This is my function:
def get_content(self):
full_results = []
for res in self._get_data(): #function that returns suds object
final_dict = dict(res)
final_dict.pop('readOnlyContactData', None)
if res["readOnlyContactData"] is not None:
readOnlyContactData_dict = dict(res["readOnlyContactData"])
final_dict.update(readOnlyContactData_dict)
full_results.append(final_dict)
return full_results
However when runnning it I get:
INFO - if res["readOnlyContactData"] is not None:
INFO - File "/home/ubuntu/.local/lib/python3.6/site-packages/suds/sudsobject.py", line 154, in __getitem__
INFO - return getattr(self, name)
INFO - AttributeError: 'contactObject' object has no attribute 'readOnlyContactData'
INFO - Command exited with return code 1
I don't understand why it fails the if condition is suppose to check if res["readOnlyContactData"] exists. if it does process it and if not ignore it.
Why this condition fails?

In python, using variable['key'] syntax internally calls __getitem__('key') to retrieve the right element. In your case, the error indicates that __getitem__() internally calls getattr(), which is usually used to retrieve a class member or an instance variable.
File "/path/to/sudsobject.py", line 154, in __getitem__
return getattr(self, name)
AttributeError: 'contactObject' object has no attribute 'readOnlyContactData'
So, based on information you provided, calling res["readOnlyContactData"] seems equivalent to call res.readOnlyContactData. Since readOnlyContactData attribute is not found in your object (of type contactObject), you get this error.
Try the following statements to check wether your object has the member you are looking for or not:
>>> # this has to be implemented in your class
>>> "readOnlyContactData" in res
or
>>> hasattr(res, "readOnlyContactData")

That if condition checks whether the element residing in res["readOnlyContactData"] is None or not. So, if res does not have any index named "readOnlyContactData" Python returns the exception Object has no attribute. Instead of the if-statement you should try hasattr(res, "readOnlyContactData")

Related

Retrieve details from AttributeError object in Python

I am enumerating some objects in a list, which may or may not have certain properties. If a property does not exists, I get the AttributeError. What I want to do is to catch the exception object and retrieve the specific property that causes the error and set it to an empty string. I don't see any method in the AttributeError object to retrieve the said attribute.
Partial code here:
import wmi
c = wmi.WMI ()
for account in c.Win32_Account():
try:
print(f"Name: {account.Name}, FullName: {account.FullName}, LocalAccount: {account.LocalAccount}, Domain: {account.Domain}")
except AttributeError as error:
# How do I retreive the attribute in question from the exception object?
Per original post, you want to "retrieve the specific property that causes the error and set it to an empty string".
if you just wanted to print the string use getattr:
https://docs.python.org/3/library/functions.html#getattr
import wmi
c = wmi.WMI ()
for account in c.Win32_Account():
print(f"Name: {getattr(account, 'Name', "")}, FullName: {getattr(account, 'FullName', "")}, LocalAccount: {getattr(account, 'LocalAccount', "")}, Domain: {getattr(account, 'Domain', "")}")
if you want to actually overwrite the missing values use hasattr and setattr:
for account in c.Win32_Account():
for attr in ['Name', 'FullName', 'LocalAccount', 'Domain']:
if not hasattr(account, attr):
setattr(account, attr, "")
Every Exception object stores its arguments in the .args property. The argument to an AttributeError object is a string that contains the object on which the property access is being used and the property being accessed.
The format of this message looks like-
('|")object_name('|") object has no attribute ('|")property_name('|")
Where ('|") means "either matching double quotes or single quotes"
You can extract both the object name and property name using this regex-
(?:\'|")(\w+)(?:\'|")
So the final implementation would look like-
import wmi
import re
c = wmi.WMI ()
for account in c.Win32_Account():
try:
print(f"Name: {account.Name}, FullName: {account.FullName}, LocalAccount: {account.LocalAccount}, Domain: {account.Domain}")
except AttributeError as error:
property_name = re.findall(r'(?:\'|")(\w+)(?:\'|")', error.args[0])[-1]

python - assert_called_with where AttributeError is passed as arg

I am trying to unit test a custom exception called TargetException.
One of the arguments to this exception is itself an exception.
Here's the relevant part of my test:
mock_exception.assert_called_once_with(
id,
AttributeError('invalidAttribute',)
)
Here's the test failure message:
File "/usr/local/lib/python2.7/site-packages/mock/mock.py", line 948, in assert_called_once_with
return self.assert_called_with(*args, **kwargs)
File "/usr/local/lib/python2.7/site-packages/mock/mock.py", line 937, in assert_called_with
six.raise_from(AssertionError(_error_message(cause)), cause)
File "/usr/local/lib/python2.7/site-packages/six.py", line 718, in raise_from
raise value
AssertionError: Expected call: TargetException(<testrow.TestRow object at 0x7fa2611e7050>, AttributeError('invalidAttribute',))
Actual call: TargetException(<testrow.TestRow object at 0x7fa2611e7050>, AttributeError('invalidAttribute',))
In both the "Expected call" and the "Action call," the same arguments are present -- at least it appears that way to me.
Do I need to pass the AttributeError a different way to resolve the error?
The problem is that you compare the instances of the contained exception. As the AttributeError instance created in the tested function and the instance used for comparison in test are different, the assertion fails.
What you could do instead is testing the called arguments separately to ensure they are of the correct type:
#mock.patch('yourmodule.TargetException')
def test_exception(mock_exception):
# call the tested function
...
mock_exception.assert_called_once()
assert len(mock_exception.call_args[0]) == 2 # shall be called with 2 positional args
arg1 = mock_exception.call_args[0][0] # first argument
assert isinstance(arg1, testrow.TestRow) # type of the first arg
... # more tests for arg1
arg2 = mock_exception.call_args[0][1] # second argument
assert isinstance(arg2, AttributeError) # type of the second arg
assert str(arg2) == 'invalidAttribute' # string value of the AttributeError
E.g. you test for the class and for the relevant values of the arguments separately. Using assert_called_with works only for PODs, or if you already know the called instance (for example if it is a singleton, or a known mock).
Building on top of MrBean Bremen's answer.
Another way to solve this is to hold the exception in a var and check on the var:
ex = AttributeError('invalidAttribute',)
...
def foo():
raise ex
...
mock_exception.assert_called_once_with(
id,
ex
)

How can I see instance attributes of the object returned by app.request in web.py?

from bin.app import app
resp = app.request('/')
print resp.__dict__.keys()
print vars(resp)
print resp.__class__.__dict__.keys()
I know app.request returns an object with the data attributes 'headers', 'status' and 'data'. All I want to do is print them out, but none of the print statements above show that these exist.
Is there some way of finding these attributes (without using the help docs)?
The storage object resp has a __getattr__ method--which I found using dir(resp)--that you can use to list the attributes.

Exception using python 'shelve' dictionary assignment

Seeing an odd exception in the shelve module (well the shelve helper copy_reg module). Taking a look, it is trying to call a reference to what should be the __getstate__ method of the Pickler class. However, it would seem that this has returned None for some reason. Just wondered if anyone else has experienced this and if there is something that can be done to get shelve to work correctly?
Here is the return stack for the exception I am seeing:
File "/usr/local/lib/python2.7/dist-packages/libgsync/drive/__init__.py", line 497, in stat
self._pcache[search] = ent
File "/usr/lib/python2.7/shelve.py", line 132, in __setitem__
p.dump(value)
File "/usr/lib/python2.7/copy_reg.py", line 84, in _reduce_ex
dict = getstate()
DEBUG: libgsync/drive/__init__.py:387:walk(): Exception: 'NoneType' object is not callable
I took the liberty of looking at the code and here is where it is malfunctioning, in the _reduce_ex() function:
try:
getstate = self.__getstate__
except AttributeError:
if getattr(self, "__slots__", None):
raise TypeError("a class that defines __slots__ without "
"defining __getstate__ cannot be pickled")
try:
dict = self.__dict__
except AttributeError:
dict = None
else:
dict = getstate()
Initially, it assigns self.__getstate__ to getstat, so this should be callable at this point. It doesn't appear to have raised an exception, since it is executing with the context of the else block. Strange...
Here is the debug output from the line of code where the exception is occurring:
DEBUG: libgsync/drive/__init__.py:496:stat(): Updating path cache: /unittest
And here is the code causing the exception:
# Update path cache.
if self._pcache.get(search) is None:
debug("Updating path cache: %s" % search)
self._pcache[search] = ent
The value being assigned to the shelf dictionary was not a copyable object. I resolved the issue by deferring the class wrapping of the dictionary until after it had been cached.

AppEngine -> "AttributeError: 'unicode' object has no attribute 'has_key'" when using blobstore

There have been a number of other questions on AttributeErrors here, but I've read through them and am still not sure what's causing the type mismatch in my specific case.
Thanks in advance for any thoughts on this.
My model:
class Object(db.Model):
notes = db.StringProperty(multiline=False)
other_item = db.ReferenceProperty(Other)
time = db.DateTimeProperty(auto_now_add=True)
new_files = blobstore.BlobReferenceProperty(required=True)
email = db.EmailProperty()
is_purple = db.BooleanProperty()
My BlobstoreUploadHandler:
class FormUploadHandler(blobstore_handlers.BlobstoreUploadHandler):
def post(self):
try:
note = self.request.get('notes')
email_addr = self.request.get('email')
o = self.request.get('other')
upload_file = self.get_uploads()[0]
# Save the object record
new_object = Object(notes=note,
other=o,
email=email_addr,
is_purple=False,
new_files=upload_file.key())
db.put(new_object)
# Redirect to let user know everything's peachy.
self.redirect('/upload_success.html')
except:
self.redirect('/upload_failure.html')
And every time I submit the form that uploads the file, it throws the following exception:
ERROR 2010-10-30 21:31:01,045 __init__.py:391] 'unicode' object has no attribute 'has_key'
Traceback (most recent call last):
File "/home/user/Public/dir/google_appengine/google/appengine/ext/webapp/__init__.py", line 513, in __call__
handler.post(*groups)
File "/home/user/Public/dir/myapp/myapp.py", line 187, in post
new_files=upload_file.key())
File "/home/user/Public/dir/google_appengine/google/appengine/ext/db/__init__.py", line 813, in __init__
prop.__set__(self, value)
File "/home/user/Public/dir/google_appengine/google/appengine/ext/db/__init__.py", line 3216, in __set__
value = self.validate(value)
File "/home/user/Public/dir/google_appengine/google/appengine/ext/db/__init__.py", line 3246, in validate
if value is not None and not value.has_key():
AttributeError: 'unicode' object has no attribute 'has_key'
What perplexes me most is that this code is nearly straight out of the documentation, and jives with other examples of blob upload handler's I've found online in tutorials as well.
I've run --clear-datastore to ensure that any changes I've made to the DB schema aren't causing problems, and have tried casting upload_file as all sorts of things to see if it would appease Python - any ideas on what I've screwed up?
Edit: I've found a workaround, but it's suboptimal.
Altering the UploadHandler to this instead resolves the issue:
...
# Save the object record
new_object = Object()
new_object.notes = note
new_object.other = o
new_object.email = email.addr
new_object.is_purple = False
new_object.new_files = upload_file.key()
db.put(new_object)
...
I made this switch after noticing that commenting out the files line threw the same issues for the other line, and so on. This isn't an optimal solution, though, as I can't enforce validation this way (in the model, if I set anything as required, I can't declare an empty entity like above without throwing an exception).
Any thoughts on why I can't declare the entity and populate it at the same time?
You're passing in o as the value of other_item (in your sample code, you call it other, but I presume that's a typo). o is a string fetched from the request, though, and the model definition specifies that it's a ReferenceProperty, so it should either be an instance of the Other class, or a db.Key object.
If o is supposed to be a stringified key, pass in db.Key(o) instead, to deserialize it.
Object is a really terrible name for a datastore class (or any class, really), by the way - the Python base object is called object, and that's only one capitalized letter away - very easy to mistake.
has_key error is due to the ReferenceProperty other_items. You are most likely passing in '' for other_items when appengine's api expects a dict. In order to get around this, you need to convert other_items to hash.
[caveat lector: I know zilch about "google_app_engine"]
The message indicates that it is expecting a dict (the only known object that has a has_key attribute) or a work-alike object, not the unicode object that you supplied. Perhaps you should be passing upload_file, not upload_file.key() ...

Categories