Python Object contains list of another object throws AttributeError - list

Python version 3.3 w/ Aptana IDE
I'm teaching myself python in my spare time at work so I decided to recreate a poker game that my friends and I play. To facilitate the various calls to different functions I created two objects. One object contains the data for the entire game, GameData, and the second object contains a single player, Player, that I am attempting to add to GameData.
The below code loops and attempts to add Player to a list in GameData but I get an error stating:
AttributeError: type object 'GameData' has no attribute 'players'
class Player(object):
def __init__(self, seat):
self.seat = seat
self.chips = 0
self.wins = 0
self.card = 0
self.isDealer = False
class GameData(object):
def __init__(self):
self.games = 0
self.numPlayers = 0
self.chips = 0
self.players = []
self.deck = []
The below function throws the error
def testDealCards():
gd = nuts.GameData #declare GameData object
gd.deck = [7,5,5,5,3,1,5,6,1,2] #assign values to deck list
for x in range(2): #loop to create player objects in GameData
gd.players.append(Player)
gd.players[0].isDealer = True
gd.players[1].isDealer = False
print(gd.players)
nuts.dealCards(gd)
assert gd.players[0].card == 5
assert gd.players[1].card == 7
pass

You are accessing the GameData class type instead of creating an object.
Try this:
gd = nuts.GameData()

Related

Testing a function with a #cache.memoize gives PicklingError

I have some tests for functions that use cache, for example:
Function:
#retry(stop=stop_after_attempt(3))
#cache.cached(timeout=60, key_prefix='resouce_group_list')
def get_azure_resource_groups():
data = []
resource_client = get_azure_resource_client()
for item in resource_client.resource_groups.list():
data.append(item)
return data
Test:
#patch("dev_maintenance.machines.get_azure_resource_client")
def test_get_azure_list_rg(get_azure_resource_client):
cache.clear()
data = []
with app.app_context():
ret = get_azure_resource_groups()
get_azure_resource_client.assert_called_once()
expected = get_azure_resource_client.return_value.resource_groups.list.return_value
assert len(get_azure_resource_client.return_value.method_calls) == 1
for item in expected:
data.append(item)
assert ret == data
cache.clear()
The above test works fine, it passes, no errors and the test is using cache.
But i got other tests, and the decorator here does not matter, it will give the same error if i change the decorator to #cache.cache:
Function:
#retry(stop=stop_after_attempt(3))
#cache.memoize(60)
def get_azure_machine_info(rg_name, machine_name, expand="instanceView"):
try:
compute_client = get_azure_compute_client()
return compute_client.virtual_machines.get(rg_name, machine_name, expand=expand)
except CloudError:
return None
Test:
#patch("dev_maintenance.machines.get_azure_compute_client")
def test_get_azure_machine_info (get_azure_compute_client):
cache.delete_memoized(get_azure_machine_info)
with app.app_context():
ret = get_azure_machine_info("rg1", "m1")
print(ret)
get_azure_compute_client.assert_called_once()
assert len(get_azure_compute_client.return_value.method_calls) == 1
assert (
ret == get_azure_compute_client.return_value.virtual_machines.get.return_value
)
get_azure_compute_client.return_value.virtual_machines.get.assert_called_once_with(
"rg1", "m1", expand="instanceView"
)
cache.delete_memoized(get_azure_machine_info)
Now here the test fails with the error on this line ret = get_azure_machine_info("rg1", "m1"):
value = None, from_value = PicklingError("Can't pickle <class 'unittest.mock.MagicMock'>: it's not the same object as unittest.mock.MagicMock")
> ???
E tenacity.RetryError: RetryError[<Future at 0x105c7c3d0 state=finished raised PicklingError>]
<string>:3: RetryError
I tried to mock the cache passing a patch decorator like:
#patch("dev_maintenance.machines.cache") or #patch("dev_maintenance.cache")
I tried to set the CACHE_TYPE to null in the test case, instantiating the cache object and passing the config:
cache = Cache()
cache.init_app(app, config={"CACHE_TYPE": "redis"})
but no success so far, any help?
This is a reference to an old answer, but I think that generally MagicMock objects aren't meant to be pickled: https://github.com/thadeusb/flask-cache/issues/52
That error message is different though, and this is more similar to what you are seeing:
Is there a way to make python pickle ignore "it's not the same object " errors
Maybe you could replace the domain prefix to the class like the answer above, but I am not sure it will overcome the other difficulties of pickling a MagicMock class:
`#patch("__main__.get_azure_compute_client")`
I'am writing the answer here for people that need to test functions that are cached with flask-caching and have the same error then me.
What i needed was to create an Object inside the test and make the mock_value = Object like this:
First i create a simple class:
class MachineInfo(object):
pass
Then in my test:
#patch("dev_maintenance.machines.get_azure_compute_client")
def test_get_azure_machine_info (get_azure_compute_client):
cache.clear()
expected_res = MachineInfo()
expected_res.id = "id"
expected_res.name = "machine1"
expected_res.location = "location"
expected_res.hardware_profile = "hardware"
expected_res.storage_profile = "storage"
expected_res.network_profile = "network_profile"
get_azure_compute_client.return_value.virtual_machines.get.return_value = expected_res
res = get_azure_machine_info("rg1", "m1")
assert res == expected_res
cache.clear()
Then i could assert function_call() == Object or function_call() == mock.return_value
This simulates what the actual azure returns, an object, so i just make the mock return the object that i created so i can simulate the function itself.

Adding a variable in the global scope to a specific class - Python

class PhysCon:
def __init__(self):
self.tfrz = 273.15
self.cwat = 4188.0
self.cice = 2117.27
self.rhowat = 1000.0
I want to add "PhysCon().ke = 2.9". I calculated "ke" in another function that occurs after "PhysCon". How do I add "ke" to the "PhysCon" class and still have it be connected to the entire class when PhysCon() is called?

Type Error Python

I am currently working on a game and I tried to make an image move and I keep getting this error right here
TypeError: unbound method put_here() must be called with create_entity instance as first argument (got int instance instead)
Here is the code for the PlayerEntity.py file the I made.
class create_entity:
def __init__(self, image, name, armor, skills, weapons):
self.entity_image = image
self.entity_name = name
self.entity_armor = armor
self.entity_skills = skills
self.entity_weapons = weapons
def put_here(self,x,y):
screen.blit(self.entity_image, (x,y))
Now here is the main Game file that I was testing this in
if __name__ == '__main__':
import PlayerEntity as p_entity
p_entity.create_entity('test_img.png', 'Default', [], [], [])
p_entity.create_entity.put_here(300,300)
You should save the instantiated object into a variable and use it to call its function:
entity = p_entity.create_entity('test_img.png', 'Default', [], [], [])
entity.put_here(300,300)
This code assumes that import PlayerEntity as p_entity returns a module p_entity that contains the class create_entity (bad name for a class - by the way)

How to correctly create a second window in pyqt4

I'm trying to open a second window beside my mainwindow on a button click and display a tablewidget on it with some data. When I open the window it raises
AttributeError: 'Ui_MainWindow' object has no attribute 'openTable'
The mainwindow was created with Qt Designer and converted the ui file with pyuic4. How do I do this correctly correct so that the error is not raised?
The button calls function:
def showCliplist(self):
data = self.metadata_list
luts = self.lutlist
selected_lut = self.LUTBox.currentIndex()
openTable = ClipListViewer(data,luts,selected_lut)
self.openTable.show()
New window class:
class ClipListViewer(QtGui.QWidget):
def __init__(self, data, luts, selected_lut, parent = None):
super(ClipListViewer,self).__init__()
self.setWindowTitle('Cliplist')
self.resize(900,600)
self.metadata = data
self.curentluts = luts
self.choosenlut = selected_lut
y_count = len(self.metadata)
self.table = QtGui.QTableWidget(y_count,6)
self.table.setHorizontalHeaderLabels(['Clip', 'Videocodec', 'FPS', 'Audiocodec', 'Start Timecode', 'LUT'])
x = y = 0
for items in self.metadata:
for entry in items:
#print entry
self.table.setItem(y, x, QtGui.QTableWidgetItem(entry))
self.table.resizeColumnToContents(x)
x += 1
self.comb = QtGui.QComboBox()
for lutname in self.curentluts:
self.comb.addItem(lutname)
self.comb.setCurrentIndex(self.choosenlut)
self.table.setCellWidget(y, 5, self.comb)
self.table.setColumnWidth(5, 230)
y += 1
x = 0
self.table.resizeRowsToContents()
layout = QtGui.QHBoxLayout()
layout.addWidget(self.table)
self.setLayout(layout)
self.show()
def closeEvent(self, event): #check if window was closed
print "Cliplist Window was closed! "
I reviews your code completed, OK, let's me explain.
AttributeError: 'Ui_MainWindow' object has no attribute 'openTable'
This error says, "I not have self.openTable in class Ui_MainWindow (That true because your have create own method)".
Why ? : Because a problem is in line this;
def showCliplist(self):
data = self.metadata_list
luts = self.lutlist
selected_lut = self.LUTBox.currentIndex()
openTable = ClipListViewer(data,luts,selected_lut) # <- (1) THIS LINE
self.openTable.show() # <- (2) THIS LINE
In (1), your create your second widget in to openTable (Not self.openTable).
This line we have this object in openTable (Not self.openTable).
Then (2), your call QtGui.QWidget.show(self) to show widget of self.openTable (Not openTable). It's should be error because we don't have variable self.openTable. To fix it your should use same name variable, Like this;
def showCliplist(self):
data = self.metadata_list
luts = self.lutlist
selected_lut = self.LUTBox.currentIndex()
self.openTable = ClipListViewer(data,luts,selected_lut) # <- FIX THIS LINE !
self.openTable.show() # <- (2) THIS LINE
Why second widget is show before I call self.openTable.show()?
Answer : Your can see in second widget initiate in last line of code your see QtGui.QWidget.show(self) has be call before end of initiate;
class ClipListViewer(QtGui.QWidget):
def __init__(self, data, luts, selected_lut, parent = None):
super(ClipListViewer,self).__init__()
.
.
.
self.show() # <- THIS LINE
Regards,

Is it dangerous to define __contains__ on a metaclass?

I'm writing a custom EnumMeta class in Python 2.7 that will collect enum keys and values from some class and augment that class with some additional fields.
class EnumMeta(type):
def __init__(cls, name, bases, props):
cls.__all_values__ = [...] # collect all interesting properties
def __contains__(cls, value):
return value in cls.__all_values__
class TheFellowshipOfTheRing(object):
__metaclass__ = EnumMeta
FRODO = 'Frodo Baggins'
SAM = 'Samwise "Sam" Gamgee'
MERRY = 'Meriadoc "Merry" Brandybuck'
PIPPIN = 'Peregrin "Pippin" Took'
GANDALF = 'Gandalf the Grey'
ARAGORN = 'Aragorn (Strider)'
LEGOLAS = 'Legolas'
GIMLI = 'Gimli'
BOROMIR = 'Boromir'
print 'Gandalf the Grey' in TheFellowshipOfTheRing
# True
print 'Saruman' in TheFellowshipOfTheRing
# False
I'm wondering if implementing container-specific functions, such as __contains__, on a metaclass is a dangerous thing to do, and if so, why?