modes.py 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. from __future__ import absolute_import
  2. def parse_nick_modes(mode_string):
  3. """Parse a nick mode string.
  4. The function returns a list of lists with three members: sign,
  5. mode and argument. The sign is "+" or "-". The argument is
  6. always None.
  7. Example:
  8. >>> parse_nick_modes("+ab-c")
  9. [['+', 'a', None], ['+', 'b', None], ['-', 'c', None]]
  10. """
  11. return _parse_modes(mode_string, "")
  12. def parse_channel_modes(mode_string):
  13. """Parse a channel mode string.
  14. The function returns a list of lists with three members: sign,
  15. mode and argument. The sign is "+" or "-". The argument is
  16. None if mode isn't one of "b", "k", "l", "v", "o", "h", or "q".
  17. Example:
  18. >>> parse_channel_modes("+ab-c foo")
  19. [['+', 'a', None], ['+', 'b', 'foo'], ['-', 'c', None]]
  20. """
  21. return _parse_modes(mode_string, "bklvohq")
  22. def _parse_modes(mode_string, unary_modes=""):
  23. """
  24. Parse the mode_string and return a list of triples.
  25. If no string is supplied return an empty list.
  26. >>> _parse_modes('')
  27. []
  28. If no sign is supplied, return an empty list.
  29. >>> _parse_modes('ab')
  30. []
  31. Discard unused args.
  32. >>> _parse_modes('+a foo bar baz')
  33. [['+', 'a', None]]
  34. Return none for unary args when not provided
  35. >>> _parse_modes('+abc foo', unary_modes='abc')
  36. [['+', 'a', 'foo'], ['+', 'b', None], ['+', 'c', None]]
  37. This function never throws an error:
  38. >>> import random
  39. >>> import six
  40. >>> def random_text(min_len = 3, max_len = 80):
  41. ... len = random.randint(min_len, max_len)
  42. ... chars_to_choose = [six.unichr(x) for x in range(0,1024)]
  43. ... chars = (random.choice(chars_to_choose) for x in range(len))
  44. ... return ''.join(chars)
  45. >>> def random_texts(min_len = 3, max_len = 80):
  46. ... while True:
  47. ... yield random_text(min_len, max_len)
  48. >>> import itertools
  49. >>> texts = itertools.islice(random_texts(), 1000)
  50. >>> set(type(_parse_modes(text)) for text in texts) == set([list])
  51. True
  52. """
  53. # mode_string must be non-empty and begin with a sign
  54. if not mode_string or not mode_string[0] in '+-':
  55. return []
  56. modes = []
  57. parts = mode_string.split()
  58. mode_part, args = parts[0], parts[1:]
  59. for ch in mode_part:
  60. if ch in "+-":
  61. sign = ch
  62. continue
  63. arg = args.pop(0) if ch in unary_modes and args else None
  64. modes.append([sign, ch, arg])
  65. return modes