Skip to content

Commit 6be8148

Browse files
eric-s-sdrvinceknight
authored andcommitted
branch switch
1 parent 8fb9fde commit 6be8148

File tree

3 files changed

+145
-78
lines changed

3 files changed

+145
-78
lines changed

axelrod/strategy_transformers.py

+77-69
Original file line numberDiff line numberDiff line change
@@ -92,22 +92,25 @@ def __call__(self, PlayerClass):
9292
pass
9393

9494
# Is the original strategy method a static method?
95-
signature = inspect.signature(PlayerClass.strategy)
96-
strategy_args = [p.name for p in signature.parameters.values()
97-
if p.kind == inspect.Parameter.POSITIONAL_OR_KEYWORD]
98-
is_static = True
99-
if len(strategy_args) > 1:
100-
is_static = False
95+
# signature = inspect.signature(PlayerClass.strategy)
96+
# strategy_args = [p.name for p in signature.parameters.values()
97+
# if p.kind == inspect.Parameter.POSITIONAL_OR_KEYWORD]
98+
# is_static = True
99+
# if len(strategy_args) > 1:
100+
# is_static = False
101101

102102
# Define the new strategy method, wrapping the existing method
103103
# with `strategy_wrapper`
104104
def strategy(self, opponent):
105-
106-
if is_static:
107-
# static method
108-
proposed_action = PlayerClass.strategy(opponent)
105+
if strategy_wrapper != dual_wrapper:
106+
if is_strategy_static(PlayerClass):
107+
# static method
108+
proposed_action = PlayerClass.strategy(opponent)
109+
else:
110+
proposed_action = PlayerClass.strategy(self, opponent)
109111
else:
110-
proposed_action = PlayerClass.strategy(self, opponent)
112+
# dummy Action for dual_wrapper to avoid calling class
113+
proposed_action = C
111114

112115
# Apply the wrapper
113116
return strategy_wrapper(self, opponent, proposed_action,
@@ -148,41 +151,29 @@ def __repr__(self):
148151
prefix = ', '
149152
return name
150153

151-
# Define a new class and wrap the strategy method
152-
# Dynamically create the new class
153-
def new_init(self, *args_, **kwargs_):
154-
super(self, PlayerClass).__init__(*args_, **kwargs_)
155-
self.original_player = self.original_class(**self.init_kwargs)
156-
157-
def reducer(self_):
154+
def new_class_reduce(self_):
158155
class_module = import_module(self_.__module__)
159-
if self_.__class__.__name__ in dir(class_module):
160-
156+
import_name = self_.__class__.__name__
157+
if import_name in dir(class_module):
161158
return self_.__class__, (), self_.__dict__
162159

163160
else:
164-
decorators = [self_.decorator]
165-
pc = self_.original_class
166-
original_name = pc.__name__
167-
for klass in pc.mro():
168-
if not hasattr(klass, 'decorator'):
169-
pc = klass
170-
original_name = pc.__name__
171-
# if hasattr(klass, 'decorator'):
172-
# decorators.append(klass.decorator)
173-
# if klass in axelrod.strategies:
174-
# pc = klass
175-
# break
176-
# if klass is axelrod.Player:
177-
178-
return (NewRecon(),
179-
(decorators, original_name, self_.__module__),
180-
self_.__dict__)
181-
return (Reconstitutor(),
182-
(decorators, pc, original_name),
183-
self_.__dict__)
184-
161+
decorators = []
162+
for klass in self_.__class__.mro():
163+
if hasattr(klass, 'decorator'):
164+
decorators.append(klass.decorator)
165+
else:
166+
import_name = klass.__name__
167+
break
168+
169+
return (
170+
NewRecon(),
171+
(decorators, import_name, self_.__module__),
172+
self_.__dict__
173+
)
185174

175+
# Define a new class and wrap the strategy method
176+
# Dynamically create the new class
186177
new_class = type(
187178
new_class_name, (PlayerClass,),
188179
{
@@ -194,41 +185,43 @@ def reducer(self_):
194185
"__module__": PlayerClass.__module__,
195186
"classifier": classifier,
196187
"__doc__": PlayerClass.__doc__,
197-
"__reduce__": reducer,
188+
"__reduce__": new_class_reduce,
198189
})
199-
# if strategy_wrapper == dual_wrapper:
200-
# new_class.__init__ = new_init
190+
201191
return new_class
202192
return Decorator
203193

204-
class NewRecon(object):
205-
def __init__(self):
206194

207-
pass
208-
209-
def __call__(self, decorators, original_name, mod):
210-
use_module = import_module(mod)
211-
use_class = getattr(use_module, original_name)
212-
213-
# for decorator, args, kwargs in decorators:
214-
# use_class = decorator(*args, **kwargs)(use_class)
215-
obj = use_class()
216-
# obj.__class__.__name__ = original_name
217-
return obj
218-
219-
class Reconstitutor(object):
195+
class NewRecon(object):
220196
def __init__(self):
221-
222197
pass
223198

224-
def __call__(self, decorators, player_class, original_name):
225-
use_class = player_class
226-
227-
for decorator, args, kwargs in decorators:
228-
use_class = decorator(*args, **kwargs)(use_class)
229-
obj = use_class()
230-
obj.__class__.__name__ = original_name
231-
return obj
199+
def __call__(self, decorators, import_name, module_name):
200+
module_ = import_module(module_name)
201+
import_class = getattr(module_, import_name)
202+
203+
if hasattr(import_class, 'decorator'):
204+
return import_class()
205+
else:
206+
generated_class = import_class
207+
for decorator, args, kwargs in decorators:
208+
generated_class = decorator(*args, **kwargs)(generated_class)
209+
return generated_class()
210+
211+
212+
# class Reconstitutor(object):
213+
# def __init__(self):
214+
#
215+
# pass
216+
#
217+
# def __call__(self, decorators, player_class, original_name):
218+
# use_class = player_class
219+
#
220+
# for decorator, args, kwargs in decorators:
221+
# use_class = decorator(*args, **kwargs)(use_class)
222+
# obj = use_class()
223+
# obj.__class__.__name__ = original_name
224+
# return obj
232225

233226
def compose_transformers(t1, t2):
234227
"""Compose transformers without having to invoke the first on
@@ -300,13 +293,14 @@ def dual_wrapper(player, opponent, proposed_action):
300293
-------
301294
action: an axelrod.Action, C or D
302295
"""
296+
303297
if not player.history:
304298
player.use_history = []
305299

306300
temp = player.history[:]
307301
player.history = player.use_history[:]
308302

309-
if 'self' not in player.original_class.strategy.__code__.co_varnames:
303+
if is_strategy_static(player.original_class):
310304
action = player.original_class.strategy(opponent)
311305
else:
312306
action = player.original_class.strategy(player, opponent)
@@ -317,6 +311,20 @@ def dual_wrapper(player, opponent, proposed_action):
317311
return action.flip()
318312

319313

314+
def is_strategy_static(player_class):
315+
# signature = inspect.signature(player_class.strategy)
316+
# strategy_args = [p.name for p in signature.parameters.values()
317+
# if p.kind == inspect.Parameter.POSITIONAL_OR_KEYWORD]
318+
# is_static = True
319+
# if len(strategy_args) > 1:
320+
# is_static = False
321+
# return is_static
322+
for klass in player_class.mro():
323+
method = inspect.getattr_static(klass, 'strategy', default=None)
324+
if method is not None:
325+
return isinstance(method, staticmethod)
326+
327+
320328
DualTransformer = StrategyTransformerFactory(dual_wrapper, name_prefix="Dual")
321329

322330

axelrod/tests/classes_for_testing_pickling.py

+15-1
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,25 @@
44
C, D = axl.Action.C, axl.Action.D
55

66

7-
VariableAsClassPointer = st.FlipTransformer()(
7+
PointerToWrappedStrategy = st.FlipTransformer()(
88
st.FlipTransformer()(axl.Cooperator)
99
)
1010

1111

12+
class MyDefector(axl.Player):
13+
def __init__(self):
14+
super(MyDefector, self).__init__()
15+
16+
def strategy(self, opponent):
17+
return D
18+
19+
20+
PointerToWrappedClassNotInStrategies = st.FlipTransformer()(
21+
st.FlipTransformer()(MyDefector)
22+
)
23+
24+
25+
1226
@st.FlipTransformer()
1327
class MyCooperator(axl.Player):
1428
def strategy(self, opponent):

axelrod/tests/unit/test_pickling.py

+53-8
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@
22
import unittest
33

44
import axelrod as axl
5-
from axelrod.strategy_transformers import FlipTransformer
6-
from axelrod.tests.classes_for_testing_pickling import (transformed, DoubleFlip,
7-
SingleFlip, MyCooperator,
8-
VariableAsClassPointer,
9-
Dual, Flip)
5+
from axelrod.strategy_transformers import FlipTransformer, DualTransformer, is_strategy_static
6+
from axelrod.tests.classes_for_testing_pickling import (
7+
transformed, DoubleFlip, SingleFlip, MyCooperator, PointerToWrappedStrategy,
8+
PointerToWrappedClassNotInStrategies, Flip)
9+
10+
from axelrod import AshlockFingerprint, LookerUp, EvolvedLookerUp1_1_1
11+
1012

1113
C, D = axl.Action.C, axl.Action.D
1214

@@ -118,6 +120,49 @@ def test_class_and_instance_name_different_built_from_player_class(self):
118120
self.assert_original_plays_same_as_pickled(player, turns=10)
119121
self.assert_instance_with_history_equality(player)
120122

121-
def test_pointer_to_made_class(self):
122-
player = VariableAsClassPointer()
123-
self.assertEqual(player.__class__.__name__, 'FlippedFlippedCooperator')
123+
def test_pointer_to_class_derived_from_strategy(self):
124+
player = PointerToWrappedStrategy()
125+
126+
class_names = [klass.__name__ for klass in player.__class__.mro()]
127+
self.assertEqual(
128+
class_names,
129+
['FlippedFlippedCooperator', 'FlippedCooperator', 'Cooperator',
130+
'Player', 'object']
131+
)
132+
133+
self.assert_original_plays_same_as_pickled(player, turns=10)
134+
self.assert_instance_with_history_equality(player)
135+
136+
def test_pointer_to_class_derived_from_Player(self):
137+
player = PointerToWrappedClassNotInStrategies()
138+
139+
class_names = [klass.__name__ for klass in player.__class__.mro()]
140+
self.assertEqual(
141+
class_names,
142+
['FlippedFlippedMyDefector', 'FlippedMyDefector', 'MyDefector',
143+
'Player', 'object']
144+
)
145+
146+
self.assert_original_plays_same_as_pickled(player, turns=10)
147+
148+
self.assert_instance_with_history_equality(player)
149+
150+
def test_regression_dual_transformer_with_lookerup(self):
151+
player = DualTransformer()(LookerUp)()
152+
self.assert_instance_with_history_equality(player)
153+
154+
fp = AshlockFingerprint(axl.Cooperator, probe=LookerUp())
155+
fp.fingerprint(turns=10, repetitions=2, step=0.2)
156+
157+
fp = AshlockFingerprint(EvolvedLookerUp1_1_1)
158+
fp.fingerprint(turns=10, repetitions=2, step=0.2)
159+
160+
strategy = axl.WinStayLoseShift
161+
probe = axl.TitForTat
162+
af = axl.AshlockFingerprint(strategy, probe)
163+
data = af.fingerprint(turns=50, repetitions=2, step=0.01)
164+
p = af.plot()
165+
p.show()
166+
167+
168+

0 commit comments

Comments
 (0)