Retrieve Method Issue? AttributeError Complaining about 'str' object - python

The issue: AttributeError: 'str' object has no attribute '_sa_instance_state' and I am uncertain how to fix it.
I believe it is related to the retrieve methods below. Someone on Stacks had a similar issue and it was a simple matter of changing the function...this has not the case for me.
Traceback:
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 132, in test1
api.retrieve_assessment_result('baseball', 'Becoming a Leader')
File "/Users/ack/code/venv/NotssDB/notssdb/api/object.py", line 324, 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'
object.py
def retrieve_assessment_result(self, *args):
id, owner, assessment = None, None, None
if len(args) == 1:
id, = args[0]
elif len(args) == 2:
owner, assessment = args
else:
raise ValueError('Value being passed is an object')
if id is not None:
return self.session.query(Assessment_Result).\
filter(Assessment_Result.id == id).one()
elif owner is not None:
print 'test1', owner
return self.session.query(Assessment_Result).\
filter(Assessment_Result.owner == owner).one()
elif assessment is not None:
print 'test2', assessment
return self.session.query(Assessment_Result).\
filter(Assessment_Result.assessment == assessment).one()
def create_category_rating(self, category_rating_int, category, assessment_result):
new_catrating = Category_Rating(category_rating_int, category, assessment_result)
self.session.add(new_catrating)
print(new_catrating)
self.session.commit()
return(new_catrating)
convenience.py
(inherits from object.py)
def create_category_rating(self, category_rating_int, category_name, username, name):
category = self.retrieve_category(category_name)
owner = self.retrieve_user(username)
assessment = self.retrieve_assessment(name)
assessment_result = self.retrieve_assessment_result(owner, assessment)
return super(ConvenienceAPI, self).create_category_rating(category_rating_int, category, assessment_result)
model.py
class Category_Rating(Base):
__tablename__ = 'category_ratings'
id = Column(Integer, primary_key=True)
category_rating_int = Column(Integer)
category_id = Column(Integer, ForeignKey('categories.category_id'))
category = relationship('Category', backref='category_ratings')
assessment_result_id = Column(Integer, ForeignKey('assessment_results.id'))
assessment_result = relationship('Assessment_Result', backref='category_ratings')
def __init__(self, category_rating_int, category, assessment_result): #OBJECT
self.category_rating_int = category_rating_int
self.category = category
self.assessment_result = assessment_result
def __repr__(self):
return "<Category_Rating(category_rating_int='%s')>" % (self.category_rating_int)
test.py
api = ConvenienceAPI()
api.create_category_rating(2, 'Decision-Making', 'baseball', 'Becoming a Leader')

You problem is exactly as the one in the linked question:
You are assigning a list to a relationship where uselist=False. You should set the single model instance, rather than a list containing it.
In your case property assessment_results is defined as many-to-one relationship (e.g. single Category_Rating can have single Assessment_Results instance, but single Assessment_Results can have multiple Category_Rating instances). If you do following renames previous statements will make much more sense for you:
assessment_results -> assessment_result
assessment_results_id -> assessment_result_id
Assessment_Results -> Assessment_Result
The problem is that assessment_results property expects single instance of Assessment_Results model, but you set it to result of the method retrieve_assessment_results(), which returns list of Assessment_Results. That's why it fails.
UPD
The second problem is in this string filter(Assessment_Result.owner == owner).one(). You try to compare Owner instance with string. You probably want to replace it with something like filter(Owner.name == owner).one(). Can't tell you exactly without seeing these models definitions.

Working with Yaroslav Admin, I did something similar to his suggestion... I added a retrieve method for assessment_result(..) in the convenience.py (api) that would check for strings:
working code:
(this inherits from the object.py file -- shown above)
def retrieve_assessment_result(self, username, name):
owner = self.retrieve_user(username)
assessment = self.retrieve_assessment(name)
return super(ConvenienceAPI, self).retrieve_assessment_result(owner, assessment)

Related

Error saying that an object is a NoneType?

So I am writing a program for Python where a "User" object is created and manipulated.
I have a Linked List of objects with the Nodes representing User objects.
When I set a variable x as a User object, by searching through the list and setting the variable equal to the returned Node data, (for example x = List.search("a username") where search returns the User object with the searched name) I get a User object (verified using type(x))
However I get a NoneType error when attempting to use methods from the User class on this x variable.
What could be causing this?
It works when x is assigned to User object directly (i.e. x = User()) but doesn't work in the former case.
Notes for code: Takes in commands from a .txt file, these commands being "Add" and "Friend" among others. Friend is supposed to add each User object to a LinkedList in another User object and vice versa
Code:
class Node (object):
def __init__(self,initdata):
self.data = initdata
self.next = None # always do this – saves a lot
# of headaches later!
def getData (self):
return self.data # returns a POINTER
def getNext (self):
return self.next # returns a POINTER
def setData (self, newData):
self.data = newData # changes a POINTER
def setNext (self,newNext):
self.next = newNext # changes a POINTER
class UnorderedList ():
def __init__(self):
self.head = None
def isEmpty (self):
return self.head == None
def add (self,item):
# add a new Node to the beginning of an existing list
temp = Node(item)
temp.setNext(self.head)
self.head = temp
def length (self):
current = self.head
count = 0
while current != None:
count += 1
current = current.getNext()
return count
def search (self,item): #NOW RETURNS OBJECT IN LIST
current = self.head
while current != None:
if current.getData().name == item:
return current.getData()
else:
current = current.getNext()
return None
def remove (self,item):
current = self.head
previous = None
found = False
while not found:
if current.getData() == item:
found = True
else:
previous = current
current = current.getNext()
if previous == None:
self.head = current.getNext()
else:
previous.setNext(current.getNext() )
class User():
def __init__(self):
self.name = ""
self.friendsList = UnorderedList()
def setName(self,info):
self.name = info
def getName(self):
return self.name
def removeFriend(self, item):
self.friendsList.remove(item)
def addFriend(self, item):
self.friendsList.add(item)
def searchList(self, item):
self.friendsList.search(item)
def __str__(self):
return self.name
def main():
inFile = open("FriendData.txt")
peopleList = UnorderedList()
for line in inFile:
textList = line.split()
if "Person" in textList:
newUser = User()
newUser.setName(textList[1])
if peopleList.search(newUser.getName()) != None:
print("This user is already in the program")
else:
peopleList.add(newUser)
print(newUser.getName(),"now has an account")
elif "Friend" in textList:
#PROBLEM OBJECTS a AND b BELOW
a = peopleList.search(textList[1]) #returns user1 object
b = peopleList.search(textList[2]) # return user2 object
b.getName()
if peopleList.search(textList[1]) == None:
print("A person with the name", textList[1], "does not currently exist")
elif peopleList.search(textList[2]) == None:
print("A person with the name", textList[2], "does not currently exist")
elif textList[1]==textList[2]:
print("A person cannot friend him/herself")
elif peopleList.search(textList[1]).searchList(textList[2])!= None:
print(textList[1],"and",textList[2],"are already friends")
elif peopleList.search(textList[2]).searchList(textList[1]) != None:
print(textList[2],"and",textList[1],"are already friends")
#else:
#a.friendsList.add(b) #adds user 2 to user1 friendlist
#b.addFriend(a)
#print(a.getName(),"and",b.getName(),"are now friends")
main()
Error:
Traceback (most recent call last):
File "C:/Users/rsaen/Desktop/Python Prgms/Friends.py", line 137, in <module>
main()
File "C:/Users/rsaen/Desktop/Python Prgms/Friends.py", line 119, in main
b.getName()
AttributeError: 'NoneType' object has no attribute 'getName'
Parsed .txt file
['Person', 'Rachel']
['Person', 'Monica']
['Friend', 'Rachel', 'Monica']
['Friend', 'Monica', 'Rachel']
['Friend', 'Rachel', 'Ross']
['Person', 'Ross']
['Friend', 'Rachel', 'Ross']
['Person', 'Joey']
['Person', 'Joey']
['Friend', 'Joey', 'Joey']
['Friend', 'Joey', 'Rachel']
['Person', 'Chandler']
['Friend', 'Chandler', 'Monica']
['Friend', 'Chandler', 'Rachel']
['Friend', 'Ross', 'Chandler']
['Friend', 'Phoebe', 'Rachel']
['Person', 'Phoebe']
['Friend', 'Phoebe', 'Rachel']
['Exit']
From the code and the error message, it looks as if textList[2] is not in the friendsList attribute. In fact, it looks like it would not be; it looks like the only User in the friendsList attribute would be textList[1], because friendsList is instantiated without any arguments, and only textList[1] is added afterwards.
Important to know: There are no pointers in Python. See here for more details: https://ubuntuforums.org/showthread.php?t=895804
Also important to know: The following is how to test if an object is None in Python:
if x is not None:
print(x)
The problem is that, on line 5 of your input, you try to add the friendship between Rachel and Ross, before the person Ross is added. The program can not find Ross, variable b is None, and b.getName() crashes.
Two things I noticed: in the search method of your User class, you need to return the result from the search. I also see that you are using getters and setters, which may be part of the assignment (?), but these are not needed in Python, as it has a milder form of encapsulation.

python adding a class object to a list

Im trying to create an empty instance of my class object and add it to a list, however, as soon as i try to create the object add new data i get an error for it as seen below:
error
Traceback (most recent call last):
File "pagerduty.py", line 96, in <module>
UserData = User()
TypeError: 'dict' object is not callable
code
class User(object):
__attrs = ['Policy','Level', 'StartDate', 'EndDate', 'StartTime',
'EndTime', 'Name', 'Mobile']
def __init__(self, **kwargs):
for attr in self.__attrs:
setattr(self, attr, kwargs.get(attr, None))
def __repr__(self):
return ', '.join(
['%s: %r' % (attr, getattr(self, attr)) for attr in self.__attrs])
OnCallData = []
for User in objPolicyData['users']:
UserData = User()
UserData.Name = User['name']
UserData.Mobile = UserMobile = getUserMobile(User['id'])
for OnCall in User['on_call']:
UserPolicy = OnCall['escalation_policy']
PolicyName = UserPolicy['name']
if PolicyName.lower().find('test') == -1:
UserData.Policy = PolicyName
UserData.Level = OnCall['level']
UserData.StartDate = getDate(OnCall['start'])
UserData.EndDate = getDate(OnCall['end'])
UserData.StartTime = getTime(OnCall['start'])
UserData.EndTime = getTime(OnCall['end'])
OnCallData.append(UserData)
in your for scope, the User identifier is the iterated value from objPolicyData['users'] (as you used it in UserData.Name = User['name'])
you need to use a diffierent name for the iteration.
something like that:
for userI in objPolicyData['users']:
UserData = User()
UserData.Name = userI['name']
UserData.Mobile = UserMobile = getUserMobile(userI['id'])
for OnCall in userI['on_call']:
UserPolicy = OnCall['escalation_policy']
PolicyName = UserPolicy['name']
if PolicyName.lower().find('test') == -1:
UserData.Policy = PolicyName
UserData.Level = OnCall['level']
UserData.StartDate = getDate(OnCall['start'])
UserData.EndDate = getDate(OnCall['end'])
UserData.StartTime = getTime(OnCall['start'])
UserData.EndTime = getTime(OnCall['end'])
Note that using the conventions could prevent this bug for you. meaning, starting the name of a variable with lower case letter (user) and a class with capital letter (User).
this is relevant for most of your variables names
Both your class and the variable you are iterating over is called User. Change one of them to a different name.
By convention in python variable names are lowercase. So I suggest the following change:
for user in objPolicyData['users']:
user_data = User()
user_data.name = User['name']
user_data.mobile = UserMobile = getUserMobile(User['id'])
for on_call in User['on_call']:
user_policy = on_call['escalation_policy']
policy_name = user_policy['name']
if policy_name.lower().find('test') == -1:
user_data.policy = policy_name
user_data.level = on_call['level']
user_data.start_date = get_date(on_call['start'])
and so on. This follows the naming conventions in pep8. This will also take care of your error.
Of course if there is already an established style guide you should follow it and decide for a different name of User (the iteration variable).

Python AttributeError 'str' object has no attribute '_sID'

I get an error in python ecplise and i didn't found the solution to solve it..
Class:
class Student:
'''
This class is used to store data about the students
It contains:
sID - id of student
sName - name of student
'''
def __init__(self, sID, sName):
'''
Initialized the student
'''
self._sID = sID
self._sName = sName
def getID(self):
'''
Return student id
'''
return self._sID
def setID(self, ID):
self._sID = ID
def setName(self, name):
self._sName = name
def getName(self):
'''
Return student name
'''
return self._sName
def __str__(self):
'''
Converts the student into printable text
'''
msg ='ID: ' + str(self._sID) + ', Name: ' + self._sName
return msg
def __eq__(self, s):
'''
Checks if two students have the same ID and name
'''
return self._sID == s._sID and self._sName == s._sName
Below is the erorr with attribute:
Traceback (most recent call last):
File "C:\Users\crist\workspace\lab5_7\appStart.py", line 16, in <module>
ui.mainMenu()
File "C:\Users\crist\workspace\lab5_7\UI\ui.py", line 80, in mainMenu
self._searchElementMenu(cmd[1])
File "C:\Users\crist\workspace\lab5_7\UI\ui.py", line 57, in _searchElementMenu
self._controller.searchElement(cType, cSearch)
File "C:\Users\crist\workspace\lab5_7\controller\controller.py", line 27, in searchElement
if isinstance(lst[i], Student) == True and lst[i] == eSearch:
File "C:\Users\crist\workspace\lab5_7\domain\student.py", line 55, in __eq__
return self._sID == s._sID and self._sName == s._sName
AttributeError: 'str' object has no attribute '_sID'
Can someone help me?
I can give u more code if is necessary.
The sID is the unique id for every student, and i need this function to verify if more students have the same id.
Thank you so much !
You are trying to use the = operator, with an Student instance and a string.
The error tells that a string instance does not have a _sID variable like:
"test"._sID
I had the same problem - getting the same error message when setting environment in PythonWin. I haven't changed anything, but restarted PythonWin and it was working again as usual.

Class Attribute is clearly there, but python cant find it

Why am i getting this attribute error?
class GameState(object):
"""Keeps track game state variables"""
def __init__(self, convo_flag=0, characters_talked_to=0, convo_log=(None)):
self.convo_flag = convo_flag
self.characters_talked_to = characters_talked_to
self.convo_log = convo_log
def welcome_screen():
global LAST_NAME
global BULLY
global DAY
raw_input(messages.WELCOME)
LAST_NAME = raw_input(messages.LAST_NAME)
BULLY = characters.random_character(cclass='Camper', gender='m')
print 'Your name is Pickett %s' % LAST_NAME
messages.print_messages([
messages.EXPLANATION,
messages.BUS_LOADING,
messages.CRACK,
messages.GAME_KID_LOST])
return week_one(DAY)
def week_one(day):
if day == 1:
messages.print_messages(messages.WEEK_ONE[day])
campers = characters.random_character_sample(cclass='Camper', count=5)
people_outside_theater = campers + [characters.TROID]
while GameState.characters_talked_to != 3:
I dont get why im getting this attribute error, i totally declared it in that constructor, is there something i am missing were i need to declare it outside the constructor? This is really racking my brain.
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "pickett.py", line 44, in welcome_screen
return week_one(DAY)
File "pickett.py", line 52, in week_one
while GameState.characters_talked_to != 3:
AttributeError: type object 'GameState' has no attribute 'characters_talked_to'
You need to create an instance in order you use your class like this:
gameState = GameState()
while gameState.characters_talked_to != 3:
In your code you were trying to access class-level attribute which is not defined in your class.
Your __init__ function sets characters_talked_to on self, which is an instance of GameState.
You did not set it on GameState, which is a class.
Neither did you create any instances of GameState, so in any case __init__ is never called by your program.

Django model class decorator

I have a need to track changes on Django model instances. I'm aware of solutions like django-reversion but they are overkill for my cause.
I had the idea to create a parameterized class decorator to fit this purpose. The arguments are the field names and a callback function. Here is the code I have at this time:
def audit_fields(fields, callback_fx):
def __init__(self, *args, **kwargs):
self.__old_init(*args, **kwargs)
self.__old_state = self.__get_state_helper()
def save(self, *args, **kwargs):
new_state = self.__get_state_helper()
for k,v in new_state.items():
if (self.__old_state[k] != v):
callback_fx(self, k, self.__old_state[k], v)
val = self.__old_save(*args, **kwargs)
self.__old_state = self.__get_state_helper()
return val
def __get_state_helper(self):
# make a list of field/values.
state_dict = dict()
for k,v in [(field.name, field.value_to_string(self)) for field in self._meta.fields if field.name in fields]:
state_dict[k] = v
return state_dict
def fx(clazz):
# Stash originals
clazz.__old_init = clazz.__init__
clazz.__old_save = clazz.save
# Override (and add helper)
clazz.__init__ = __init__
clazz.__get_state_helper = __get_state_helper
clazz.save = save
return clazz
return fx
And use it as follows (only relevant part):
#audit_fields(["status"], fx)
class Order(models.Model):
BASKET = "BASKET"
OPEN = "OPEN"
PAID = "PAID"
SHIPPED = "SHIPPED"
CANCELED = "CANCELED"
ORDER_STATES = ( (BASKET, 'BASKET'),
(OPEN, 'OPEN'),
(PAID, 'PAID'),
(SHIPPED, 'SHIPPED'),
(CANCELED, 'CANCELED') )
status = models.CharField(max_length=16, choices=ORDER_STATES, default=BASKET)
And test on the Django shell with:
from store.models import Order
o=Order()
o.status=Order.OPEN
o.save()
The error I receive then is:
TypeError: int() argument must be a string or a number, not 'Order'
The full stacktrace is here: https://gist.github.com/4020212
Thanks in advance and let me know if you would need more info!
EDIT: Question answered by randomhuman, code edited and usable as shown!
You do not need to explicitly pass a reference to self on this line:
val = self.__old_save(self, *args, **kwargs)
It is a method being called on an object reference. Passing it explicitly in this way is causing it to be seen as one of the other parameters of the save method, one which is expected to be a string or a number.

Categories