Skip to content

Dropping support for Python 2 #818

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 19 commits into from
Jan 16, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
08b3ae8
Removed floating point division workaround for Python 2.7.
rkty13 Jan 9, 2017
482b8e8
Removed absolute_import future import.
rkty13 Jan 10, 2017
43224da
Removed check for Python 2.x in import.
rkty13 Jan 10, 2017
a5c0a26
Removed floating point division workaround for Python 2.
rkty13 Jan 10, 2017
1ef8875
Removed floating point division workaround for Python 2.
rkty13 Jan 10, 2017
c246706
Removed floating point division workaround for Python 2.
rkty13 Jan 10, 2017
db0d1f6
Removed use of 0.0 for floating point division for Python 2.
rkty13 Jan 10, 2017
67ee7a2
Removed Python 2 unicode strings in top level files.
rkty13 Jan 10, 2017
711a372
Removed Python 2 unicode strings from unit tests.
rkty13 Jan 10, 2017
9baab84
Removed Python 2 unicode strings from docs.
rkty13 Jan 10, 2017
9fd2dfb
Removed Python 2 future division import.
rkty13 Jan 10, 2017
e4e5d7a
Removed float casting in division.
rkty13 Jan 10, 2017
66ecec3
Removed float casting for division.
rkty13 Jan 10, 2017
265ef9d
Changed all calls to superclass methods to preferred zero argument Py…
rkty13 Jan 12, 2017
ce4e8b7
Changed all calls to superclass methods in strategies to preferred ze…
rkty13 Jan 12, 2017
632aee6
Removed for floating point workarounds for Python 2.
rkty13 Jan 12, 2017
db658e5
Removed import check for Python 2 version of MagicMock.
rkty13 Jan 12, 2017
1ef5c24
Merge branch 'master' of github.com:Axelrod-Python/Axelrod into current
rkty13 Jan 15, 2017
4e9ab4b
Removed direct reference to Player and changed to super().
rkty13 Jan 15, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion axelrod/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
from __future__ import absolute_import
import os

on_windows = os.name == 'nt'
Expand Down
17 changes: 6 additions & 11 deletions axelrod/deterministic_cache.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@
try:
# Python 2.x
from UserDict import UserDict
except ImportError:
# Python 3.x
from collections import UserDict
from collections import UserDict
import pickle

from axelrod import Player
Expand Down Expand Up @@ -41,7 +36,7 @@ def __init__(self, file_name=None):
file_name : string
Path to a previously saved cache file
"""
UserDict.__init__(self)
super().__init__()
self.mutable = True
if file_name is not None:
self.load(file_name)
Expand All @@ -56,13 +51,13 @@ def _key_transform(self, key):
return key[0].name, key[1].name, key[2]

def __delitem__(self, key):
return UserDict.__delitem__(self, self._key_transform(key))
return super().__delitem__(self._key_transform(key))

def __getitem__(self, key):
return UserDict.__getitem__(self, self._key_transform(key))
return super().__getitem__(self._key_transform(key))

def __contains__(self, key):
return UserDict.__contains__(self, self._key_transform(key))
return super().__contains__(self._key_transform(key))

def __setitem__(self, key, value):
"""Overrides the UserDict.__setitem__ method in order to validate
Expand All @@ -78,7 +73,7 @@ def __setitem__(self, key, value):
raise ValueError(
'Value must be a list with length equal to turns attribute')

UserDict.__setitem__(self, self._key_transform(key), value)
super().__setitem__(self._key_transform(key), value)

def _is_valid_key(self, key):
"""Validate a proposed dictionary key
Expand Down
4 changes: 2 additions & 2 deletions axelrod/ecosystem.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ def __init__(self, results, fitness=None, population=None):
elif len(population) != self.nplayers:
raise TypeError("Population vector must be same size as number of players")
else:
norm = float(sum(population))
norm = sum(population)
self.population_sizes = [[p / norm for p in population]]
else:
self.population_sizes = [[1.0 / self.nplayers for i in range(self.nplayers)]]
self.population_sizes = [[1 / self.nplayers for i in range(self.nplayers)]]

# This function is quite arbitrary and probably only influences the
# kinetics for the current code.
Expand Down
17 changes: 7 additions & 10 deletions axelrod/interaction_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ def compute_final_score_per_turn(interactions, game=None):
return None

final_score_per_turn = tuple(
sum([score[player_index] for score in scores]) / (float(num_turns))
sum([score[player_index] for score in scores]) / num_turns
for player_index in [0, 1])
return final_score_per_turn

Expand Down Expand Up @@ -83,7 +83,7 @@ def compute_normalised_cooperation(interactions):
num_turns = len(interactions)
cooperation = compute_cooperations(interactions)

normalised_cooperation = tuple([c / float(num_turns) for c in cooperation])
normalised_cooperation = tuple([c / num_turns for c in cooperation])

return normalised_cooperation

Expand Down Expand Up @@ -129,30 +129,27 @@ def compute_normalised_state_distribution(interactions):
return None

interactions_count = Counter(interactions)
total = sum(interactions_count.values(), 0.0)
# By starting the sum with 0.0 we make sure total is a floating point value,
# avoiding the Python 2 floor division behaviour of / with integer operands
# (Stack Overflow)
total = sum(interactions_count.values(), 0)

normalized_count = Counter({key: value / total for key, value in
interactions_count.items()})
return normalized_count


def sparkline(actions, c_symbol=u'█', d_symbol=u' '):
return u''.join([
def sparkline(actions, c_symbol='█', d_symbol=' '):
return ''.join([
c_symbol if play == 'C' else d_symbol for play in actions])


def compute_sparklines(interactions, c_symbol=u'█', d_symbol=u' '):
def compute_sparklines(interactions, c_symbol='█', d_symbol=' '):
"""Returns the sparklines for a set of interactions"""
if len(interactions) == 0:
return None

histories = list(zip(*interactions))
return (
sparkline(histories[0], c_symbol, d_symbol) +
u'\n' +
'\n' +
sparkline(histories[1], c_symbol, d_symbol))


Expand Down
2 changes: 1 addition & 1 deletion axelrod/match.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ def normalised_state_distribution(self):
"""
return iu.compute_normalised_state_distribution(self.result)

def sparklines(self, c_symbol=u'█', d_symbol=u' '):
def sparklines(self, c_symbol='█', d_symbol=' '):
return iu.compute_sparklines(self.result, c_symbol, d_symbol)

def __len__(self):
Expand Down
8 changes: 3 additions & 5 deletions axelrod/match_generator.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
from __future__ import division
from math import ceil, log
import random

Expand Down Expand Up @@ -113,7 +112,7 @@ def __init__(self, players, prob_end, game, repetitions, noise=0):
noise : float, 0
The probability that a player's intended action should be flipped
"""
super(ProbEndRoundRobinMatches, self).__init__(
super().__init__(
players, turns=float("inf"), game=game, repetitions=repetitions,
noise=noise)
self.prob_end = prob_end
Expand Down Expand Up @@ -165,7 +164,7 @@ def sample_length(self):

def estimated_size(self):
"""Rough estimate of the number of matches that will be generated."""
size = self.__len__() * (1. / self.prob_end) * self.repetitions
size = self.__len__() * (1 / self.prob_end) * self.repetitions
return size


Expand Down Expand Up @@ -221,8 +220,7 @@ def __init__(self, players, turns, game, repetitions, edges, noise=0):
if not graph_is_connected(edges, players):
raise ValueError("The graph edges do not include all players.")
self.edges = edges
super(SpatialMatches, self).__init__(players, turns, game, repetitions,
noise)
super().__init__(players, turns, game, repetitions, noise)

def build_match_chunks(self):
for edge in self.edges:
Expand Down
2 changes: 1 addition & 1 deletion axelrod/mock_player.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class MockPlayer(Player):
def __init__(self, player, move):
# Need to retain history for opponents that examine opponents history
# Do a deep copy just to be safe
Player.__init__(self)
super().__init__()
self.history = copy.deepcopy(player.history)
self.cooperations = player.cooperations
self.defections = player.defections
Expand Down
2 changes: 1 addition & 1 deletion axelrod/moran.py
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,7 @@ def __init__(self, players, interaction_graph, reproduction_graph=None,
match_class: subclass of Match
The match type to use for scoring
"""
MoranProcess.__init__(self, players, turns=turns, noise=noise,
super().__init__(players, turns=turns, noise=noise,
deterministic_cache=deterministic_cache,
mutation_rate=mutation_rate, mode=mode)
if not reproduction_graph:
Expand Down
2 changes: 1 addition & 1 deletion axelrod/plot.py
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ def stackplot(self, eco, title=None, logscale=True, ax=None):
ticks = []
for i, n in enumerate(self.result_set.ranked_names):
x = -0.01
y = (i + 0.5) * 1.0 / self.result_set.nplayers
y = (i + 0.5) * 1 / self.result_set.nplayers
ax.annotate(n, xy=(x, y), xycoords=trans, clip_on=False,
va='center', ha='right', fontsize=5)
ticks.append(y)
Expand Down
10 changes: 5 additions & 5 deletions axelrod/result_set.py
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ def _build_cooperating_rating(self):
enumerate(total_length_v_opponent)]

# Max is to deal with edge cases of matches that have no turns
return [sum(cs) / max(1, float(sum(ls))) for cs, ls
return [sum(cs) / max(1, sum(ls)) for cs, ls
in zip(self.cooperation, lengths)]

@update_progress_bar
Expand Down Expand Up @@ -354,7 +354,7 @@ def _build_normalised_state_distribution(self):
counters = []
for counter in player:
total = sum(counter.values())
counters.append(Counter({key: float(value) / total for
counters.append(Counter({key: value / total for
key, value in counter.items()}))
norm.append(counters)
return norm
Expand Down Expand Up @@ -622,7 +622,7 @@ def _build_good_partner_rating(self):
attribute
"""
return [sum(self.good_partner_matrix[player]) /
max(1, float(self.total_interactions[player]))
max(1, self.total_interactions[player])
for player in range(self.nplayers)]

@update_progress_bar
Expand All @@ -632,7 +632,7 @@ def _build_initial_cooperation_rate(self):
cooperation rate attribute
"""
return [self.initial_cooperation_count[player] /
max(1, float(self.total_interactions[player]))
max(1, self.total_interactions[player])
for player in range(self.nplayers)]

def _build_score_related_metrics(self, progress_bar=False,
Expand Down Expand Up @@ -783,7 +783,7 @@ def summarise(self):
p = sum([opp[state] for j, opp in enumerate(player) if i != j])
counts.append(p)
try:
counts = [float(c) / sum(counts) for c in counts]
counts = [c / sum(counts) for c in counts]
except ZeroDivisionError:
counts = [0 for c in counts]
state_prob.append(counts)
Expand Down
2 changes: 0 additions & 2 deletions axelrod/strategies/_strategies.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
from __future__ import absolute_import

from .alternator import Alternator
from .adaptive import Adaptive
from .ann import EvolvedANN, EvolvedANN5, EvolvedANNNoise05
Expand Down
4 changes: 2 additions & 2 deletions axelrod/strategies/adaptive.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class Adaptive(Player):

@init_args
def __init__(self, initial_plays=None):
Player.__init__(self)
super().__init__()
if not initial_plays:
initial_plays = [C] * 6 + [D] * 5
self.initial_plays = initial_plays
Expand All @@ -53,5 +53,5 @@ def strategy(self, opponent):
return D

def reset(self):
Player.reset(self)
super().reset()
self.scores = {C: 0, D: 0}
8 changes: 4 additions & 4 deletions axelrod/strategies/ann.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ class ANN(Player):

@init_args
def __init__(self, weights, num_features, num_hidden):
Player.__init__(self)
super().__init__()
(i2h, h2o, bias) = split_weights(weights, num_features, num_hidden)
self.input_to_hidden_layer_weights = i2h
self.hidden_to_output_layer_weights = h2o
Expand Down Expand Up @@ -192,7 +192,7 @@ class EvolvedANN(ANN):
@init_args
def __init__(self):
num_features, num_hidden, weights = nn_weights["Evolved ANN"]
ANN.__init__(self, weights, num_features, num_hidden)
super().__init__(weights, num_features, num_hidden)


class EvolvedANN5(ANN):
Expand All @@ -210,7 +210,7 @@ class EvolvedANN5(ANN):
@init_args
def __init__(self):
num_features, num_hidden, weights = nn_weights["Evolved ANN 5"]
ANN.__init__(self, weights, num_features, num_hidden)
super().__init__(weights, num_features, num_hidden)


class EvolvedANNNoise05(ANN):
Expand All @@ -228,4 +228,4 @@ class EvolvedANNNoise05(ANN):
@init_args
def __init__(self):
num_features, num_hidden, weights = nn_weights["Evolved ANN 5 Noise 05"]
ANN.__init__(self, weights, num_features, num_hidden)
super().__init__(weights, num_features, num_hidden)
8 changes: 4 additions & 4 deletions axelrod/strategies/apavlov.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class APavlov2006(Player):
}

def __init__(self):
Player.__init__(self)
super().__init__()
self.opponent_class = None

def strategy(self, opponent):
Expand Down Expand Up @@ -66,7 +66,7 @@ def strategy(self, opponent):
return C

def reset(self):
Player.reset(self)
super().reset()
self.opponent_class = None


Expand All @@ -93,7 +93,7 @@ class APavlov2011(Player):
}

def __init__(self):
Player.__init__(self)
super().__init__()
self.opponent_class = None

def strategy(self, opponent):
Expand Down Expand Up @@ -121,5 +121,5 @@ def strategy(self, opponent):
return D if opponent.history[-1:] == [D] else C

def reset(self):
Player.reset(self)
super().reset()
self.opponent_class = None
Loading