Skip to content
This repository was archived by the owner on Apr 8, 2026. It is now read-only.

Commit 88280d7

Browse files
authored
Python 3.11 fixes, pull in upstream
Python 3.11 fixes, pull in upstream
2 parents 073ae7b + f56cea0 commit 88280d7

14 files changed

Lines changed: 58 additions & 42 deletions

File tree

CHANGES.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
Version 0.3.0
2+
-------------
3+
(released on January 13th 2015)
4+
5+
- Added support for Python3
6+
17
Version 0.2.0
28
-------------
39
(released on October 15th 2012)

README.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,14 @@ For more details on how the algorithm works, see
1010

1111
http://www.moserware.com/2010/03/computing-your-skill.html
1212

13+
To install run the command::
14+
15+
pip install skills
16+
17+
The match quality function of TrueSkill will run much faster with NumPy than with the provided matrix implementation. Install with::
18+
19+
pip install numpy
20+
1321
For details on how to use this project, see the accompanying unit tests with
1422
this project. You can run the tests by running the commands::
1523

setup.cfg

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[bdist_wheel]
2+
universal=1

setup.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
setup(
44
name='skills',
5-
version='0.2.0',
5+
version='0.3.0',
66
author='Scott Hamilton',
77
author_email='mcleopold@gmail.com',
88
packages=['skills',
@@ -15,12 +15,14 @@
1515
description='Implementation of the TrueSkill, Glicko'
1616
' and Elo Ranking Algorithms',
1717
long_description=open('README.rst').read(),
18+
keywords='skill trueskill glicko elo',
1819
classifiers=[
1920
'Programming Language :: Python',
2021
'Programming Language :: Python :: 2',
22+
'Programming Language :: Python :: 3',
2123
'License :: OSI Approved :: BSD License',
2224
'Operating System :: OS Independent',
23-
'Development Status :: 4 - Beta',
25+
'Development Status :: 5 - Production/Stable',
2426
'Environment :: Other Environment',
2527
'Intended Audience :: Developers',
2628
'Intended Audience :: Science/Research',

skills/__init__.py

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
"""Ranking calculators implementing the Elo, Glicko and TrueSkill algorithms."""
2-
from __future__ import absolute_import
2+
from collections.abc import Sequence
33

4-
from collections import Sequence
54
from skills.numerics import Gaussian
65

76

@@ -40,6 +39,7 @@ class Match(list):
4039
"""Match is a list of Team objects"""
4140

4241
def __init__(self, teams=None, rank=None):
42+
super().__init__()
4343
if teams is not None:
4444
for team in teams:
4545
self.append(Team.ensure_team(team))
@@ -87,14 +87,14 @@ def player_rating(self):
8787
for player_rating in team.player_rating():
8888
yield player_rating
8989

90-
def sort(self):
90+
def sort(self, **kwargs):
9191
"""
9292
Performs an in-place sort of the items in accordance to the ranks in non-decreasing order
9393
"""
9494
if not self.rank:
9595
raise AttributeError("Match does not have a ranking")
9696

97-
rank_sorted, teams_sorted = map(list, zip(*sorted(zip(self.rank, self))))
97+
rank_sorted, teams_sorted = map(list, zip(*sorted(zip(self.rank, self), key=lambda x: x[0])))
9898

9999
if rank_sorted != self.rank:
100100
# in-place update part
@@ -126,6 +126,7 @@ class Matches(list):
126126
"""Matches is a list of Match objects"""
127127

128128
def __init__(self, matches):
129+
super().__init__()
129130
for match in matches:
130131
self.append(Match.ensure_match(match))
131132

@@ -194,9 +195,7 @@ def __init__(self, players=None):
194195
# or 1 list of player, rating tuples
195196
team = Team([(player1, rating1), (player2, rating2)])
196197
"""
197-
self.players = self.keys
198-
self.ratings = self.values
199-
self.player_rating = self.items
198+
super().__init__()
200199
if players is not None:
201200
try:
202201
player_rating_tuples = players.items()
@@ -209,6 +208,15 @@ def __init__(self, players=None):
209208
except (TypeError, ValueError):
210209
raise TypeError("Improper player dict or list")
211210

211+
def players(self):
212+
return list(self.keys())
213+
214+
def ratings(self):
215+
return list(self.values())
216+
217+
def player_rating(self):
218+
return list(self.items())
219+
212220
def add_player(self, player, rating):
213221
self[Player.ensure_player(player)] = RatingFactory.ensure_rating(rating)
214222
return self
@@ -237,6 +245,13 @@ def ensure_team(team):
237245
else:
238246
return team
239247

248+
def __lt__(self, other):
249+
"""
250+
In python3, you can't order dicts anymore. Since we do that in Match.sort
251+
we'll define a custom team sort based on the current contents for consistency
252+
"""
253+
return frozenset(self.items()) < frozenset(other.items())
254+
240255

241256
class Rating(object):
242257
"""
@@ -250,14 +265,14 @@ def __init__(self, mean):
250265
raise ValueError("Rating mean value must be numeric")
251266

252267
def __repr__(self):
253-
return "Rating(%s)" % (self.mean)
268+
return "Rating(%s)" % self.mean
254269

255270
def __str__(self):
256-
return "mean=%.5f" % (self.mean)
271+
return "mean=%.5f" % self.mean
257272

258273
@staticmethod
259274
def ensure_rating(rating):
260-
if (not hasattr(rating, 'mean')):
275+
if not hasattr(rating, 'mean'):
261276
try:
262277
return Rating(rating)
263278
except TypeError:
@@ -275,8 +290,9 @@ class RatingFactory(object):
275290

276291
rating_class = Rating
277292

278-
def __new__(cls):
279-
return RatingFactory.rating_class()
293+
# def __new__(cls):
294+
# TODO: Rating ctor requires a param
295+
# return RatingFactory.rating_class()
280296

281297
@staticmethod
282298
def ensure_rating(rating):

skills/elo.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
from __future__ import absolute_import
2-
3-
from collections import Sequence
1+
from collections.abc import Sequence
42

53
from skills import (
64
Calculator,

skills/factorgraph.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
from __future__ import absolute_import
2-
3-
41
class Factor(object):
52

63
def __init__(self, name):

skills/glicko.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
from __future__ import absolute_import
2-
3-
from collections import Sequence, defaultdict
1+
from collections import defaultdict
2+
from collections.abc import Sequence
43
from math import sqrt, log, pi
54

65
from skills import (

skills/matrix.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
from __future__ import absolute_import
2-
3-
41
class MatrixError(Exception):
52
pass
63

@@ -10,14 +7,15 @@ class Matrix(list):
107
ERROR_TOLERANCE = 0.00000000000001
118

129
def __init__(self, data):
10+
super().__init__()
1311
rows = len(data)
1412
cols = len(data[0]) if rows > 0 else 0
1513
self.shape = rows, cols
1614
for row in data:
1715
self.append(row[:])
1816

1917
def transpose(self):
20-
return Matrix(map(lambda * row: list(row), *self))
18+
return Matrix(list(map(lambda * row: list(row), *self)))
2119

2220
def is_square(self):
2321
return self.shape[0] == self.shape[1] and self.shape[0] > 0

skills/numerics.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
from __future__ import absolute_import
2-
31
from math import sqrt, pi, log, exp
42

53
try:
@@ -132,7 +130,7 @@ def log_product_normalization(left, right):
132130

133131
return -LOG_SQRT_2_PI - (log(variance_sum) / 2.0) - ((mean_difference ** 2.0) / (2.0 * variance_sum))
134132

135-
def __div__(self, other):
133+
def __truediv__(self, other):
136134
return Gaussian.from_precision_mean(
137135
self.precision_mean - other.precision_mean,
138136
self.precision - other.precision)

0 commit comments

Comments
 (0)