docs: def key(string):
      """Return a Czech sort key for the given string
  
      :param string: string (unicode in Python 2)
  
      Comparing the sort keys of two strings will give the result according
      to how the strings would compare in Czech collation order, i.e.
          ``key(s1) < key(s2)``  <=>  ``s1`` comes before ``s2``
  
      The structure of the sort key may change in the future.
      The only operations guaranteed to work on it are comparisons and equality
      checks (<, ==, etc.) against other keys.
      """
      # The multi-level key is a nested tuple containing strings and ints.
      # The tuple contains sub-keys that roughly correspond to levels in
      # UTS #10 (http://unicode.org/reports/tr10/). Except for fallback strings
      # at the end, each contains a tuple of typically one key per element/letter.
      # - Alphabet:
      #    Separators (0, p, l, w)
      #       p: -no. of paragraph separators
      #       l: -no. of line separators
      #       w: -no. of word separators (spaces)
      #    Letters (1, l); l is the base letter, lowercased
      #       Special letters: 'č' shows up as 'cx'; 'ř' as 'rx', etc.
      #                        the 'ch' digraph becomes 'hx'
      #    Numbers (2, n); n is int(numeric value * 100)
      #    Missing for non-letters
      # - Diacritics (p, n, s)
      #    p: position (above, below, behind, in front, in/over/around, unknown)
      #       (as a sorted tuple of indices)
      #    s: shape (dot, grave, breve, ..., unknown)
      #       (as a sorted tuple of indices)
      #    Missing for non-letters; empty if diacritics included in base (e.g. ř)
      # - Case: True for uppercased letters
      #    Missing for non-letters
      # - Punctuation: see PUNCTUATION_MAP below
      # - (fallback) NFKD-normalized string
      # - (fallback) original string
  
      subkeys = [], [], [], []
      add_alphabet = subkeys[0].append
      add_diacritic = subkeys[1].append
      add_case = subkeys[2].append
      add_punctuation = subkeys[3].append
      skip = 0
      normal = nfkd(string).rstrip()
      diacritics = []
      for i, char in enumerate(normal):
          if skip > 0:
              skip -= 1
              continue
          category = get_category(char)
          cat0, cat1 = category
          if cat0 == 'L':
              # Letter (Lowercase, Modifier, Other, Titlecase, Uppercase)
              char_lower = char.lower()
              found = False
              if char_lower in DECOMPOSING_EXTRAS:
                  # stuff like Ł doesn't decompose in Unicode; do it manually
                  char_lower, _extra_diacritics = DECOMPOSING_EXTRAS[char]
                  diacritics.extend(_extra_diacritics)
              for next in normal[i+1:]:
                  if next == HACEK and char_lower in ('c', 'r', 's', 'z'):
                      skip += 1
                      char_lower = char_lower + 'x'
                  elif char_lower == 'c' and next.lower() == 'h':
                      skip += 1
                      char_lower = 'hx'
                      break
                  elif next in DIACRITICS_MAP:
                      skip += 1
                      diacritics.extend(DIACRITICS_MAP[next])
                  elif unicodedata.category(char)[0] == 'M':
                      skip += 1
                      diacritics.append((POS_UNKNOWN, SH_UNKNOWN))
                  else:
                      break
              add_alphabet((1, char_lower))
              if diacritics:
                  add_diacritic(make_diacritics_key(diacritics))
              else:
                  add_diacritic(())
              add_case(cat1 in ('u', 't'))  # upper & title case
              add_punctuation((0, ))
              diacritics = []
          elif cat0 == 'Z':
              # Separator (Line, Paragraph, Space)
              counts = {'Zp': 0, 'Zl': 0, 'Zs': 0}
              counts[category] = 1
              for next in normal[i+1:]:
                  next_cat = get_category(next)
                  if next_cat[0] == 'Z':
                      counts[next_cat] += 1
                      skip += 1
                  else:
                      break
              add_alphabet((0, -counts['Zp'], -counts['Zl'], -counts['Zs']))
              add_diacritic(())
              add_case(False)
              add_punctuation((0, ))
          elif char in DIACRITICS_BEFORE_MAP:
              diacritics.extend(DIACRITICS_BEFORE_MAP[char])
          elif char in DIACRITICS_MAP:
              diacritics.extend(DIACRITICS_MAP[char])
          elif char in PUNCTUATION_MAP:
              add_punctuation(PUNCTUATION_MAP[char])
          elif cat0 == 'P':
              # Punctuation (Connector, Dash, Open/Close, Final/Initial Quote, Other)
              add_punctuation((3, ))
          elif cat0 == 'N':
              # Number (Decimal digit, Letter, Other)
              add_alphabet((2, int(unicodedata.numeric(char, 0)) * 100))
              add_diacritic(())
              add_case(False)
              add_punctuation((0, ))
          elif cat0 == 'S':
              # Symbol (Currency, Modifier, Math)
              add_punctuation((3, ))
          elif cat0 == 'C':
              # Other (Control, Format, Not Assigned, Private Use, Surrogate)
              pass
          elif cat0 == 'M':
              # Mark (Spacing Combining, Enclosing, Nonspacing)
              # TODO
              diacritics.append((POS_FRONT, SH_UNKNOWN))
          else:
              raise ValueError('Unknown Unicode category')
      if diacritics:
          add_diacritic(make_diacritics_key(diacritics))
          diacritics = []
      return tuple(tuple(k) for k in subkeys) + (normal, string)