Skip to content

Commit fe705e1

Browse files
committed
Fix a bug for Player.__init__ and Player.__del__ where, if a bad strategy name is supplied, the object doesn't teardown correctly
1 parent 721fc91 commit fe705e1

File tree

2 files changed

+28
-13
lines changed

2 files changed

+28
-13
lines changed

src/axelrod_fortran/player.py

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,15 @@ def __init__(self, original_name):
4242
A instance of an axelrod Game
4343
"""
4444
super().__init__()
45+
# The order of the next 4 lines is important. We must first check that
46+
# the player name is valid, then grab a copy of the shared library,
47+
# and then setup the actual strategy function.
48+
self.original_name = original_name
4549
self.index, self.shared_library_filename = \
46-
shared_library_manager.get_filename_for_player(original_name)
50+
shared_library_manager.get_filename_for_player(self.original_name)
4751
self.shared_library = load_library(self.shared_library_filename)
48-
self.__original_name = original_name
4952
self.original_function = self.original_name
53+
5054
is_stochastic = characteristics[self.original_name]['stochastic']
5155
if is_stochastic is not None:
5256
self.classifier['stochastic'] = is_stochastic
@@ -62,11 +66,11 @@ def original_name(self):
6266
return self.__original_name
6367

6468
@original_name.setter
65-
def original_name(self, value):
66-
if value in characteristics:
67-
self.__original_name = value
69+
def original_name(self, key):
70+
if key in characteristics:
71+
self.__original_name = key
6872
else:
69-
raise ValueError('{} is not a valid Fortran function'.format(value))
73+
raise ValueError('{} is not a valid Fortran function'.format(key))
7074

7175
@property
7276
def original_function(self):
@@ -118,7 +122,16 @@ def _release_shared_library(self):
118122
# thread closes before the player class is garbage collected, which
119123
# tends to happen at the end of a script.
120124
try:
121-
shared_library_manager.release(self.original_name, self.index)
125+
name = self.original_name
126+
index = self.index
127+
except AttributeError:
128+
# If the Player does finish __init__, because the name of a
129+
# non-existent strategy is supplied, a copy of the shared library
130+
# won't be loaded, nor will self.original_name or self.index
131+
# exist. In that case there's nothing to do.
132+
return
133+
try:
134+
shared_library_manager.release(name, index)
122135
except FileNotFoundError:
123136
pass
124137

tests/test_player.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ def test_init():
2222
POINTER(c_int), POINTER(c_int), POINTER(c_int), POINTER(c_int),
2323
POINTER(c_float))
2424
assert player.original_function.restype == c_int
25-
with pytest.raises(AttributeError):
25+
with pytest.raises(ValueError):
2626
player = Player('test')
2727

2828

@@ -186,19 +186,21 @@ def test_multiple_copies(recwarn):
186186

187187

188188
def test_match_reproducibility():
189-
for _ in range(10):
189+
for _ in range(100):
190190
rng = RandomGenerator()
191191
seed = rng.random_seed_int()
192192
strategies = rng.choice(all_strategies, size=2)
193-
print(strategies)
194193
players1 = [Player(strategy) for strategy in strategies]
195-
# players1 = (p() for p in strategies)
196194
match1 = Match(players1, turns=200, noise=0.1, seed=seed)
197195
results1 = match1.play()
196+
198197
players2 = [Player(strategy) for strategy in strategies]
199-
# players2 = (p() for p in strategies)
200198
match2 = Match(players2, turns=200, noise=0.1, seed=seed)
201199
results2 = match2.play()
200+
if results1 != results2:
201+
print(strategies)
202+
print(results1)
203+
print(results2)
202204
assert (results1 == results2)
203205

204206

@@ -221,6 +223,6 @@ def test_tournament_reproducibility():
221223
test_init()
222224
test_matches()
223225
test_noisy_matches()
224-
test_implemented_strategies()
226+
# test_implemented_strategies()
225227
test_match_reproducibility()
226228
test_tournament_reproducibility()

0 commit comments

Comments
 (0)