Skip to content

Commit 03b5cae

Browse files
authored
Merge pull request #2200 from half-duplex/isupport-prefix-order
isupport: maintain PREFIX ordering
2 parents b1fed88 + 0848282 commit 03b5cae

File tree

2 files changed

+35
-3
lines changed

2 files changed

+35
-3
lines changed

sopel/irc/isupport.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,11 @@
1313
# Licensed under the Eiffel Forum License 2.
1414
from __future__ import generator_stop
1515

16+
from collections import OrderedDict
1617
import functools
1718
import itertools
1819
import re
20+
from typing import Dict
1921

2022

2123
def _optional(parser, default=None):
@@ -97,7 +99,7 @@ def _parse_prefix(value):
9799
if len(modes) != len(prefixes):
98100
raise ValueError('Mode list does not match for PREFIX: %r' % value)
99101

100-
return tuple(sorted(zip(modes, prefixes)))
102+
return tuple(zip(modes, prefixes))
101103

102104

103105
ISUPPORT_PARSERS = {
@@ -328,7 +330,7 @@ def MAXLIST(self):
328330
return dict(self['MAXLIST'])
329331

330332
@property
331-
def PREFIX(self):
333+
def PREFIX(self) -> Dict[str, str]:
332334
"""Expose ``PREFIX`` as a dict, if advertised by the server.
333335
334336
This exposes information about the modes and nick prefixes used for
@@ -343,6 +345,8 @@ def PREFIX(self):
343345
'v': '+',
344346
}
345347
348+
Entries are in order of descending privilege.
349+
346350
This attribute is not available if the server does not provide the
347351
right information, and accessing it will raise an
348352
:exc:`AttributeError`.
@@ -355,7 +359,10 @@ def PREFIX(self):
355359
if 'PREFIX' not in self:
356360
raise AttributeError('PREFIX')
357361

358-
return dict(self['PREFIX'])
362+
# This can use a normal dict once we drop python 3.6, as 3.7 promises
363+
# `dict` maintains insertion order. Since `OrderedDict` subclasses
364+
# `dict`, we'll not promise to always return the former.
365+
return OrderedDict(self['PREFIX'])
359366

360367
@property
361368
def TARGMAX(self):

test/irc/test_irc_isupport.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
"""Tests for core ``sopel.irc.isupport``"""
22
from __future__ import generator_stop
33

4+
from collections import OrderedDict
5+
46
import pytest
57

68
from sopel.irc import isupport
@@ -500,6 +502,29 @@ def test_parse_parameter_prefix_invalid_format():
500502
isupport.parse_parameter('PREFIX=(o)@+')
501503

502504

505+
def test_parse_parameter_prefix_order_parser():
506+
"""Ensure PREFIX order is maintained through parser.
507+
508+
https://modern.ircdocs.horse/#prefix-parameter
509+
"""
510+
key, value = isupport.parse_parameter('PREFIX=(qov)~@+')
511+
512+
assert value == (('q', '~'), ('o', '@'), ('v', '+'))
513+
514+
515+
def test_parse_parameter_prefix_order_property():
516+
"""Ensure PREFIX order is maintained in property."""
517+
instance = isupport.ISupport()
518+
519+
key, value = isupport.parse_parameter('PREFIX=(qov)~@+')
520+
new = instance.apply(
521+
prefix=value,
522+
)
523+
524+
assert new.PREFIX == OrderedDict((('q', '~'), ('o', '@'), ('v', '+')))
525+
assert tuple(new.PREFIX.keys()) == ('q', 'o', 'v')
526+
527+
503528
def test_parse_parameter_targmax():
504529
key, value = isupport.parse_parameter('TARGMAX=PRIVMSG:3')
505530

0 commit comments

Comments
 (0)