Skip to content

Commit f1d38ed

Browse files
committed
- Fixed exception when attempting to parse highscores with no results (e.g. a new world on its first day).
1 parent 3b6ac87 commit f1d38ed

File tree

8 files changed

+36
-6
lines changed

8 files changed

+36
-6
lines changed

CHANGELOG.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,27 @@ Changelog
66
Due to this library relying on external content, older versions are not guaranteed to work.
77
Try to always use the latest version.
88

9+
.. _v2.4.2:
10+
11+
2.4.2 (2020-02-26)
12+
==================
13+
- Fixed exception when attempting to parse highscores with no results (e.g. a new world on its first day).
14+
915
.. _v2.4.1:
16+
1017
2.4.1 (2019-11-20)
1118
==================
1219
- Fixed incorrect argument name (house) in ``Character`` constructor.
1320

1421
.. _v2.4.0:
22+
1523
2.4.0 (2019-11-20)
1624
==================
1725
- Added support for multiple houses per character. Accessible on ``Character.houses`` field.
1826
- ``Character.house`` is now deprecated. It will contain the character's first house or ``None``.
1927

2028
.. _v2.3.4:
29+
2130
2.3.4 (2019-11-14)
2231
==================
2332
- Fixed bug with deaths not being parsed when a killer had ``and`` in their name.

serve.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,11 @@ async def get_guilds(request):
4242
return web.Response(text=json.dumps(guild_list, default=dict))
4343

4444

45-
@routes.get('/highscores/{world}/{category}/{vocations}/{page}')
45+
@routes.get(r'/highscores/{world}/{category}/{vocations:\d+}/{page}')
4646
async def get_highscores(request):
4747
world = request.match_info['world']
4848
category = request.match_info['category']
49-
vocations = request.match_info['vocations']
49+
vocations = int(request.match_info['vocations'])
5050
page = request.match_info['page']
5151
highscores = await app["tibiapy"].fetch_highscores_page(world,
5252
try_enum(tibiapy.Category, category,

tests/resources/README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ with the bare minimum (no description, no guildhall, no homepage)
4747
- [tibiacom_status_rented.txt](house/tibiacom_status_rented.txt) - The status string of a rented house.
4848
- [tibiacom_status_transfer.txt](house/tibiacom_status_transfer.txt) - The status string of a rented house that is set
4949
for transfer.
50-
- [tibiacom_status_with_bids.txt](house/tibiacom_status_with_bids.txt) - The status string of a auctioned house with
50+
- [tibiacom_status_with_bids.txt](house/tibiacom_status_with_bids.txt) - The status string of a auctioned house with
5151
bids.
5252
- [tibiacom_not_found.txt](house/tibiacom_not_found.txt) - The content of a page for a house not found.
5353
- [tibiacom_list.txt](house/tibiacom_list.txt) - The house list of a world.
@@ -63,6 +63,7 @@ doesn't exist.
6363
## Highscores resources
6464
- [tibiacom_full.txt](highscores/tibiacom_full.txt) - The content of a correct highscore's page.
6565
- [tibiacom_empty.txt](highscores/tibiacom_empty.txt) - The content of the highscores page of a nonexistent world.
66+
- [tibiacom_no_results.txt](highscores/tibiacom_no_results.txt) - The content of the highscores page of a new world (no results shown).
6667
- [tibiacom_experience.txt](highscores/tibiacom_experience.txt) - The content of an experience highscores page.
6768
- [tibiacom_loyalty.txt](highscores/tibiacom_loyalty.txt) - The content of a loyalty highscores page.
6869
- [tibiadata_full.json](highscores/tibiadata_full.json) - A highscores response from TibiaData.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<div class="BoxContent" style="background-image:url(https://static.tibia.com/images/global/content/scroll.gif);">
2+
<form action="https://www.tibia.com/community/?subtopic=highscores" method="post"><div class="TableContainer"> <table class="Table1" cellpadding="0" cellspacing="0"> <div class="CaptionContainer"> <div class="CaptionInnerContainer"> <span class="CaptionEdgeLeftTop" style="background-image:url(https://static.tibia.com/images/global/content/box-frame-edge.gif);" /></span> <span class="CaptionEdgeRightTop" style="background-image:url(https://static.tibia.com/images/global/content/box-frame-edge.gif);" /></span> <span class="CaptionBorderTop" style="background-image:url(https://static.tibia.com/images/global/content/table-headline-border.gif);"></span> <span class="CaptionVerticalLeft" style="background-image:url(https://static.tibia.com/images/global/content/box-frame-vertical.gif);" /></span> <div class="Text">Highscores Filter</div> <span class="CaptionVerticalRight" style="background-image:url(https://static.tibia.com/images/global/content/box-frame-vertical.gif);" /></span> <span class="CaptionBorderBottom" style="background-image:url(https://static.tibia.com/images/global/content/table-headline-border.gif);"></span> <span class="CaptionEdgeLeftBottom" style="background-image:url(https://static.tibia.com/images/global/content/box-frame-edge.gif);" /></span> <span class="CaptionEdgeRightBottom" style="background-image:url(https://static.tibia.com/images/global/content/box-frame-edge.gif);" /></span> </div> </div> <tr> <td> <div class="InnerTableContainer"> <table style="width:100%;"><tr><td>World:</td><td><select size="1" name="world" style="width:165px;"><option value="Antica">Antica</option><option value="Assombra">Assombra</option><option value="Astera">Astera</option><option value="Belluma">Belluma</option><option value="Belobra">Belobra</option><option value="Bona">Bona</option><option value="Calmera">Calmera</option><option value="Carnera">Carnera</option><option value="Celebra">Celebra</option><option value="Celesta">Celesta</option><option value="Concorda">Concorda</option><option value="Cosera">Cosera</option><option value="Damora">Damora</option><option value="Descubra">Descubra</option><option value="Dibra">Dibra</option><option value="Duna">Duna</option><option value="Emera">Emera</option><option value="Epoca">Epoca</option><option value="Estela">Estela</option><option value="Faluna">Faluna</option><option value="Ferobra">Ferobra</option><option value="Firmera">Firmera</option><option value="Funera">Funera</option><option value="Furia">Furia</option><option value="Garnera">Garnera</option><option value="Gentebra">Gentebra</option><option value="Gladera">Gladera</option><option value="Harmonia">Harmonia</option><option value="Helera">Helera</option><option value="Honbra">Honbra</option><option value="Impera">Impera</option><option value="Inabra">Inabra</option><option value="Javibra">Javibra</option><option value="Jonera">Jonera</option><option value="Kalibra">Kalibra</option><option value="Kenora">Kenora</option><option value="Lobera">Lobera</option><option value="Luminera">Luminera</option><option value="Lutabra">Lutabra</option><option value="Macabra">Macabra</option><option value="Menera">Menera</option><option value="Mitigera">Mitigera</option><option value="Monza">Monza</option><option value="Nefera">Nefera</option><option value="Noctera">Noctera</option><option value="Nossobra">Nossobra</option><option value="Olera">Olera</option><option value="Ombra">Ombra</option><option value="Pacera">Pacera</option><option value="Peloria">Peloria</option><option value="Premia">Premia</option><option value="Pyra">Pyra</option><option value="Quelibra">Quelibra</option><option value="Quintera">Quintera</option><option value="Refugia">Refugia</option><option value="Relania">Relania</option><option value="Relembra">Relembra</option><option value="Secura">Secura</option><option value="Serdebra">Serdebra</option><option value="Serenebra">Serenebra</option><option value="Solidera">Solidera</option><option value="Talera">Talera</option><option value="Torpera">Torpera</option><option value="Tortura">Tortura</option><option value="Unica" selected="selected">Unica</option><option value="Venebra">Venebra</option><option value="Vita">Vita</option><option value="Vunira">Vunira</option><option value="Wintera">Wintera</option><option value="Zuna">Zuna</option><option value="Zunera">Zunera</option></select></td><td rowspan="3"><div class="BigButton" style="background-image:url(https://static.tibia.com/images/global/buttons/sbutton.gif)"><div onMouseOver="MouseOverBigButton(this);" onMouseOut="MouseOutBigButton(this);"><div class="BigButtonOver" style="background-image:url(https://static.tibia.com/images/global/buttons/sbutton_over.gif);"></div><input class="ButtonText" type="image" name="Submit" alt="Submit" src="https://static.tibia.com/images/global/buttons/_sbutton_submit.gif"></div></div></td></tr><tr><td>Vocation:</td><td><select name="profession"><option value="0" selected="selected">(all)</option><option value="1">Knights</option><option value="2">Paladins</option><option value="3">Sorcerers</option><option value="4">Druids</option></select></td></tr><tr><td>Category:</td><td><select name="list"><option value="achievements">Achievements</option><option value="axe">Axe Fighting</option><option value="club">Club Fighting</option><option value="distance">Distance Fighting</option><option value="experience" selected="selected">Experience Points</option><option value="fishing">Fishing</option><option value="fist">Fist Fighting</option><option value="loyalty">Loyalty Points</option><option value="magic">Magic Level</option><option value="shielding">Shielding</option><option value="sword">Sword Fighting</option></select></td></tr> </table> </div> </td> </tr> </table></div></form><p><i>Skills displayed in the Highscores do not include any bonuses (loyalty, equipment etc.).</i></p><div class="TableContainer"> <table class="Table3" cellpadding="0" cellspacing="0"> <div class="CaptionContainer"> <div class="CaptionInnerContainer"> <span class="CaptionEdgeLeftTop" style="background-image:url(https://static.tibia.com/images/global/content/box-frame-edge.gif);" /></span> <span class="CaptionEdgeRightTop" style="background-image:url(https://static.tibia.com/images/global/content/box-frame-edge.gif);" /></span> <span class="CaptionBorderTop" style="background-image:url(https://static.tibia.com/images/global/content/table-headline-border.gif);"></span> <span class="CaptionVerticalLeft" style="background-image:url(https://static.tibia.com/images/global/content/box-frame-vertical.gif);" /></span> <div class="Text">Highscores</div> <span class="CaptionVerticalRight" style="background-image:url(https://static.tibia.com/images/global/content/box-frame-vertical.gif);" /></span> <span class="CaptionBorderBottom" style="background-image:url(https://static.tibia.com/images/global/content/table-headline-border.gif);"></span> <span class="CaptionEdgeLeftBottom" style="background-image:url(https://static.tibia.com/images/global/content/box-frame-edge.gif);" /></span> <span class="CaptionEdgeRightBottom" style="background-image:url(https://static.tibia.com/images/global/content/box-frame-edge.gif);" /></span> </div> </div> <tr> <td> <div class="InnerTableContainer"> <table style="width:100%;"><tr><td><div class="TableShadowContainerRightTop"> <div class="TableShadowRightTop" style="background-image:url(https://static.tibia.com/images/global/content/table-shadow-rt.gif);"></div></div><div class="TableContentAndRightShadow" style="background-image:url(https://static.tibia.com/images/global/content/table-shadow-rm.gif);"> <div class="TableContentContainer"> <table class="TableContent" width="100%" style="border:1px solid #faf0d7;"><TR class="LabelH"><td style="width: 5%;">Rank</td><td style="width: 45%;">Name</td><td style="width: 20%;">Vocation</td><td style="width: 10%; text-align: right;">Level</td><td style="width: 20%; text-align: right;">Points</td></tr><tr style="background-color:#F1E0C6;"><td colspan="5">There is currently no data.</td></tr><tr><td style="padding-right: 10px;" colspan="5"><small><div style="float: left;"><b>&raquo; Pages: 1</b></div><div style="float: right;"><b>&raquo; Results: 0</b></div></small></td></tr> </table> </div></div><div class="TableShadowContainer"> <div class="TableBottomShadow" style="background-image:url(https://static.tibia.com/images/global/content/table-shadow-bm.gif);"> <div class="TableBottomLeftShadow" style="background-image:url(https://static.tibia.com/images/global/content/table-shadow-bl.gif);"></div> <div class="TableBottomRightShadow" style="background-image:url(https://static.tibia.com/images/global/content/table-shadow-br.gif);"></div> </div></div></td></tr> </table> </div> </td> </tr> </table></div> </div>
3+
</div>
4+
</div>

tests/tests_highscores.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
FILE_HIGHSCORES_EXPERIENCE = "highscores/tibiacom_experience.txt"
1010
FILE_HIGHSCORES_LOYALTY = "highscores/tibiacom_loyalty.txt"
1111
FILE_HIGHSCORES_EMPTY = "highscores/tibiacom_empty.txt"
12+
FILE_HIGHSCORES_NO_RESULTS = "highscores/tibiacom_no_results.txt"
1213

1314
FILE_HIGHSCORES_TIBIADATA_FULL = "highscores/tibiadata_full.json"
1415
FILE_HIGHSCORES_TIBIADATA_EXPERIENCE = "highscores/tibiadata_experience.json"
@@ -79,12 +80,24 @@ def test_highscores_from_content_loyalty(self):
7980
self.assertIsInstance(entry.title, str)
8081

8182
def test_highscores_from_content_empty(self):
82-
"""Testing parsing highscores empty highscores"""
83+
"""Testing parsing highscores when empty (world doesn't exist)"""
8384
content = self._load_resource(FILE_HIGHSCORES_EMPTY)
8485
highscores = Highscores.from_content(content)
8586

8687
self.assertIsNone(highscores)
8788

89+
def test_highscores_from_content_no_results(self):
90+
"""Testing parsing highscores with no results (first day of a new world)"""
91+
content = self._load_resource(FILE_HIGHSCORES_NO_RESULTS)
92+
highscores = Highscores.from_content(content)
93+
94+
self.assertIsInstance(highscores, Highscores)
95+
self.assertEqual(highscores.world, "Unica")
96+
self.assertEqual(highscores.category, Category.EXPERIENCE)
97+
self.assertEqual(highscores.vocation, VocationFilter.ALL)
98+
self.assertEqual(highscores.total_pages, 0)
99+
self.assertEqual(len(highscores.entries), 0)
100+
88101
def test_highscores_from_content_unrelated_section(self):
89102
"""Testing parsing an unrelated section"""
90103
content = self._load_resource(self.FILE_UNRELATED_SECTION)

tests/tests_utils.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ def test_try_enum(self):
156156
self.assertEqual(utils.try_enum(enums.Sex, "male"), enums.Sex.MALE)
157157
self.assertEqual(utils.try_enum(enums.TransferType, "", enums.TransferType.REGULAR), enums.TransferType.REGULAR)
158158
self.assertEqual(utils.try_enum(enums.WorldLocation, enums.WorldLocation.EUROPE), enums.WorldLocation.EUROPE)
159+
self.assertEqual(utils.try_enum(enums.VocationFilter, 4), enums.VocationFilter.DRUIDS)
159160

160161
def test_enum_str(self):
161162
self.assertEqual(str(enums.Sex.MALE), enums.Sex.MALE.value)

tibiapy/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
from tibiapy.creature import *
1414
from tibiapy.client import *
1515

16-
__version__ = '2.4.1'
16+
__version__ = '2.4.2'
1717

1818
from logging import NullHandler
1919

tibiapy/highscores.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ def __init__(self, world, category, **kwargs):
5050

5151
__slots__ = (
5252
'world',
53-
'categroy',
53+
'category',
5454
'vocation',
5555
'entries',
5656
'results_count',
@@ -133,6 +133,8 @@ def from_content(cls, content):
133133
highscores.results_count = int(results_pattern.search(info_row.text).group(1))
134134
for row in rows:
135135
cols_raw = row.find_all('td')
136+
if "There is currently no data" in cols_raw[0].text:
137+
break
136138
highscores._parse_entry(cols_raw)
137139
return highscores
138140

0 commit comments

Comments
 (0)