Reputation: 958
Issue: inheritance class is not checking for strings because it is being passed as None
.
The parent class (object.py) of the retrieve method was designed to retrieve objects from the database (e.g. id or user/assessment combo). The child class (convenience.py) is designed to accept the str
s of those objects.
object.py
def retrieve_assessment_result(self, *args):
id, owner, assessment = None, None, None
if len(args) == 1:
id, = args # or id = args[0]
elif len(args) == 2:
owner, assessment = args
print 'testa', owner, assessment, id
else:
raise ValueError('Value being passed is an object')
if id is not None:
print 'testi', id
return self.session.query(Assessment_Result).\
filter(Assessment_Result.id == id).one()
elif owner is not None:
print 'testo', owner
return self.session.query(Assessment_Result).\
filter(Assessment_Result.owner == owner).one()
elif assessment is not None:
print 'testa', assessment
return self.session.query(Assessment_Result).\
filter(Assessment_Result.assessment == assessment).one()
convenience.py
def retrieve_assessment_result(self, *args):
id, owner, assessment = None, None, None
if len(args) == 1:
id, = args # or id = args[0]
print " args = ", args
elif len(args) == 2:
username, name = args
print "api args = ", args
print 'type args', type(args)
print 'owner: ', owner
print 'assessment: ', assessment
if owner is not None:
owner = self.retrieve_user(username)
if assessment is not None:
assessment = self.retrieve_assessment(name)
return super(ConvenienceAPI, self).retrieve_assessment_result(*args)
test.py
api.retrieve_assessment_result('baseball', 'Becoming a Leader')
Traceback Error:
Traceback (most recent call last):
File "/usr/local/lib/python2.7/site-packages/nose/case.py", line 197, in runTest
self.test(*self.arg)
File "/Users/ack/code/venv/NotssDB/notssdb/test/test.py", line 133, in test1
api.retrieve_assessment_result('baseball', 'Becoming a Leader')
File "/Users/ack/code/venv/NotssDB/notssdb/api/convenience.py", line 42, in retrieve_assessment_result
return super(ConvenienceAPI, self).retrieve_assessment_result(*args)
File "/Users/ack/code/venv/NotssDB/notssdb/api/object.py", line 327, in retrieve_assessment_result
filter(Assessment_Result.owner == owner).one()
File "/usr/local/lib/python2.7/site-packages/sqlalchemy/sql/operators.py", line 301, in __eq__
return self.operate(eq, other)
File "/usr/local/lib/python2.7/site-packages/sqlalchemy/orm/attributes.py", line 175, in operate
return op(self.comparator, *other, **kwargs)
File "/usr/local/lib/python2.7/site-packages/sqlalchemy/orm/relationships.py", line 1011, in __eq__
other, adapt_source=self.adapter))
File "/usr/local/lib/python2.7/site-packages/sqlalchemy/orm/relationships.py", line 1338, in _optimized_compare
state = attributes.instance_state(state)
AttributeError: 'str' object has no attribute '_sa_instance_state'
------output--------
<Assessment_Result(owner='<User(username ='bambam', firstname ='Sean', lastname ='Cargo', email='[email protected]')>', assessment='<Assessment(name='Foo', text='this is foo')>')>
api args = ('baseball', 'Becoming a Leader')
type args <type 'tuple'>
owner: None
assessment: None
testa baseball Becoming a Leader None
testo baseball
-----updates after comment/suggestions:
object.py Updated:
def retrieve_assessment_result(self, id=None, owner=None, assessment=None):
print 'test_all_objects', owner, assessment, id
if id is not None:
print 'test_id_object', id
return self.session.query(Assessment_Result).\
filter(Assessment_Result.id == id).one()
elif owner is not None:
print 'test_owner_object', owner
return self.session.query(Assessment_Result).\
filter(Assessment_Result.owner.has(User.username == username)).one()
elif assessment is not None:
print 'test_assessment_object', assessment
return self.session.query(Assessment_Result).\
filter(Assessment_Result.assessment.has(Assessment.name == name)).one()
Convenience.py (inherited from object.py) change:
def retrieve_assessment_result(self, id=None, owner=username, assessment=name):
if owner is not None:
owner = self.retrieve_user(username)
if assessment is not None:
assessment = self.retrieve_assessment(name)
return super(ConvenienceAPI, self).retrieve_assessment_result(id=None, owner=owner, assessment=assessment)
Traceback:
File ".../api/convenience.py", line 6, in <module>
class ConvenienceAPI(BaseAPI):
File "../api/convenience.py", line 37, in ConvenienceAPI
def retrieve_assessment_result(self, id=None, owner=username, assessment=name):
NameError: name 'username' is not defined
Upvotes: 2
Views: 3145
Reputation: 21562
In my experience, the error '???' object has no attribute '_sa_instance_state
almost always indicates that you assigned something which is not a SQLAlchemy object (i.e. some basic type, as int, str, etc.) to a relationship
or dynamic_loader
.
relationship
example>>> result = db.query(Assessment_Result).first()
>>> # owner only accepts Owner objects
>>> result.owner = "Mr. Harvey Example"
Traceback (most recent call last):
...
AttributeError: 'str' object has no attribute '_sa_instance_state'
Furthermore, filtering with other types on a relationship
will also lead to this error:
>>> Assessment_Result.owner == "baseball"
Traceback (most recent call last):
...
AttributeError: 'str' object has no attribute '_sa_instance_state'
In your case the error is caused by having the string "baseball"
as the first entry in the 2-tuple args
which you pass on to Object.retrieve_assessment_result
, which in turn will be put in the variable owner
in the second if block.
>>> owner, assessment = args
As owner
now contains a str
this will fail when you filter with it.
I'd like to take this opportunity to point out that this code is not very readable and could be improved by the use of keyword arguments and generally making it more concise.
Upvotes: 3