nodes: 0, module; 1, function_definition; 2, function_name:_getPattern; 3, parameters; 4, block; 5, identifier:self; 6, identifier:ipattern; 7, default_parameter; 8, expression_statement; 9, if_statement; 10, if_statement; 11, function_definition; 12, function_definition; 13, function_definition; 14, expression_statement; 15, expression_statement; 16, for_statement; 17, return_statement; 18, identifier:done; 19, None; 20, comment:"""Parses sort pattern.
  
          :ipattern: A pattern to parse.
          :done:  If :ipattern: refers to done|undone,
          use this to indicate proper state.
          :returns: A pattern suitable for Model.modify.
  
          """; 21, comparison_operator:ipattern is None; 22, block; 23, comparison_operator:ipattern is True; 24, block; 25, function_name:_getReverse; 26, parameters; 27, block; 28, function_name:_getIndex; 29, parameters; 30, block; 31, function_name:_getDone; 32, parameters; 33, block; 34, assignment; 35, assignment; 36, identifier:s; 37, call; 38, block; 39, tuple; 40, identifier:ipattern; 41, None; 42, return_statement; 43, identifier:ipattern; 44, True; 45, if_statement; 46, comment:# REMEMBER: This False is for sort reverse!; 47, return_statement; 48, identifier:pm; 49, return_statement; 50, identifier:k; 51, try_statement; 52, identifier:p; 53, expression_statement; 54, if_statement; 55, return_statement; 56, identifier:ipattern1; 57, call; 58, identifier:ipattern2; 59, call; 60, attribute; 61, argument_list; 62, if_statement; 63, expression_statement; 64, if_statement; 65, expression_statement; 66, identifier:ipattern1; 67, identifier:ipattern2; 68, None; 69, comparison_operator:done is not None; 70, block; 71, tuple; 72, comparison_operator:pm == '-'; 73, block; 74, except_clause; 75, assignment; 76, comparison_operator:len(v) == 2; 77, block; 78, tuple; 79, identifier:list; 80, argument_list; 81, identifier:dict; 82, argument_list; 83, identifier:ipattern; 84, identifier:split; 85, string; 86, comparison_operator:done is not None; 87, block; 88, else_clause; 89, assignment; 90, comparison_operator:len(k) == 1; 91, block; 92, elif_clause; 93, else_clause; 94, call; 95, identifier:done; 96, None; 97, return_statement; 98, list; 99, dictionary; 100, identifier:pm; 101, string; 102, return_statement; 103, identifier:ValueError; 104, block; 105, identifier:v; 106, call; 107, call; 108, integer:2; 109, try_statement; 110, None; 111, subscript; 112, identifier:done; 113, string_content:,; 114, identifier:done; 115, None; 116, expression_statement; 117, block; 118, identifier:k; 119, call; 120, call; 121, integer:1; 122, if_statement; 123, expression_statement; 124, try_statement; 125, expression_statement; 126, comparison_operator:len(k) == 2; 127, block; 128, block; 129, attribute; 130, argument_list; 131, tuple; 132, tuple; 133, string_content:-; 134, call; 135, raise_statement; 136, attribute; 137, argument_list; 138, identifier:len; 139, argument_list; 140, block; 141, except_clause; 142, identifier:v; 143, integer:0; 144, assignment; 145, expression_statement; 146, attribute; 147, argument_list; 148, identifier:len; 149, argument_list; 150, comparison_operator:done is not None; 151, block; 152, assignment; 153, block; 154, except_clause; 155, else_clause; 156, assignment; 157, call; 158, integer:2; 159, try_statement; 160, raise_statement; 161, call; 162, identifier:append; 163, identifier:v; 164, list; 165, dictionary; 166, integer:0; 167, False; 168, identifier:int; 169, argument_list; 170, call; 171, identifier:p; 172, identifier:split; 173, string; 174, identifier:v; 175, return_statement; 176, identifier:KeyError; 177, block; 178, identifier:v; 179, identifier:done; 180, assignment; 181, identifier:s; 182, identifier:split; 183, string; 184, identifier:k; 185, identifier:done; 186, None; 187, expression_statement; 188, continue_statement; 189, identifier:ko; 190, subscript; 191, if_statement; 192, identifier:KeyError; 193, block; 194, block; 195, identifier:v; 196, tuple; 197, identifier:len; 198, argument_list; 199, block; 200, except_clause; 201, call; 202, attribute; 203, argument_list; 204, tuple; 205, identifier:k; 206, identifier:InvalidPatternError; 207, argument_list; 208, string_content:=; 209, tuple; 210, raise_statement; 211, identifier:v; 212, call; 213, string_content::; 214, call; 215, subscript; 216, slice; 217, comparison_operator:len(k[0]) == 1; 218, block; 219, else_clause; 220, expression_statement; 221, expression_statement; 222, continue_statement; 223, integer:0; 224, identifier:v; 225, identifier:k; 226, if_statement; 227, expression_statement; 228, identifier:KeyError; 229, block; 230, identifier:InvalidPatternError; 231, argument_list; 232, identifier:ipattern2; 233, identifier:setdefault; 234, identifier:k; 235, list; 236, None; 237, None; 238, identifier:done; 239, identifier:k; 240, string:"Invalid level number"; 241, subscript; 242, subscript; 243, identifier:done; 244, call; 245, identifier:_getReverse; 246, argument_list; 247, attribute; 248, argument_list; 249, identifier:k; 250, integer:0; 251, unary_operator; 252, call; 253, integer:1; 254, expression_statement; 255, block; 256, assignment; 257, call; 258, comparison_operator:done is not None; 259, block; 260, else_clause; 261, assignment; 262, raise_statement; 263, identifier:s; 264, string; 265, attribute; 266, subscript; 267, identifier:v; 268, integer:1; 269, identifier:InvalidPatternError; 270, argument_list; 271, subscript; 272, identifier:ipattern1; 273, identifier:append; 274, call; 275, integer:1; 276, identifier:len; 277, argument_list; 278, assignment; 279, expression_statement; 280, identifier:k; 281, call; 282, attribute; 283, argument_list; 284, identifier:done; 285, None; 286, expression_statement; 287, block; 288, identifier:k; 289, call; 290, call; 291, string_content:Unrecognized token in; 292, identifier:Model; 293, identifier:indexes; 294, identifier:v; 295, integer:0; 296, subscript; 297, string; 298, identifier:s; 299, unary_operator; 300, identifier:_getDone; 301, argument_list; 302, subscript; 303, identifier:k; 304, integer:0; 305, assignment; 306, identifier:_getIndex; 307, argument_list; 308, identifier:ipattern1; 309, identifier:append; 310, tuple; 311, assignment; 312, expression_statement; 313, identifier:_getIndex; 314, argument_list; 315, identifier:InvalidPatternError; 316, argument_list; 317, identifier:v; 318, integer:0; 319, string_content:Invalid field name; 320, integer:1; 321, subscript; 322, identifier:k; 323, integer:0; 324, identifier:k; 325, subscript; 326, subscript; 327, identifier:k; 328, identifier:v; 329, identifier:v; 330, call; 331, assignment; 332, subscript; 333, subscript; 334, string; 335, identifier:k; 336, integer:0; 337, attribute; 338, identifier:ko; 339, subscript; 340, slice; 341, identifier:_getDone; 342, argument_list; 343, identifier:v; 344, tuple; 345, identifier:k; 346, integer:0; 347, subscript; 348, slice; 349, string_content:Invalid field name; 350, identifier:Model; 351, identifier:indexes; 352, identifier:k; 353, integer:0; 354, unary_operator; 355, subscript; 356, subscript; 357, identifier:v; 358, identifier:k; 359, integer:1; 360, unary_operator; 361, integer:1; 362, identifier:k; 363, integer:1; 364, attribute; 365, subscript; 366, integer:1; 367, identifier:Model; 368, identifier:indexes; 369, subscript; 370, slice; 371, identifier:k; 372, integer:1; 373, unary_operator; 374, integer:1
code: def _getPattern(self, ipattern, done=None):
          """Parses sort pattern.
  
          :ipattern: A pattern to parse.
          :done:  If :ipattern: refers to done|undone,
          use this to indicate proper state.
          :returns: A pattern suitable for Model.modify.
  
          """
          if ipattern is None:
              return None
          if ipattern is True:
              if done is not None:
                  return ([(None, None, done)], {})
              # REMEMBER: This False is for sort reverse!
              return ([(0, False)], {})
  
          def _getReverse(pm):
              return pm == '-'
  
          def _getIndex(k):
              try:
                  return int(k)
              except ValueError:
                  raise InvalidPatternError(k, "Invalid level number")
  
          def _getDone(p):
              v = p.split('=')
              if len(v) == 2:
                  try:
                      return (Model.indexes[v[0]], v[1], done)
                  except KeyError:
                      raise InvalidPatternError(v[0], 'Invalid field name')
              return (None, v[0], done)
          ipattern1 = list()
          ipattern2 = dict()
          for s in ipattern.split(','):
              if done is not None:
                  v = done
              else:
                  v = _getReverse(s[-1])
              k = s.split(':')
              if len(k) == 1:
                  if done is not None:
                      ipattern1.append(_getDone(k[0]))
                      continue
                  ko = k[0][:-1]
                  try:
                      if len(k[0]) == 1:
                          k = 0
                      else:
                          k = Model.indexes[ko]
                  except KeyError:
                      k = _getIndex(k[0][:-1])
                  else:
                      ipattern1.append((k, v))
                      continue
                  v = (0, v)
              elif len(k) == 2:
                  try:
                      if done is not None:
                          v = _getDone(k[1])
                      else:
                          v = (Model.indexes[k[1][:-1]], v)
                      k = _getIndex(k[0])
                  except KeyError:
                      raise InvalidPatternError(k[1][:-1], 'Invalid field name')
              else:
                  raise InvalidPatternError(s, 'Unrecognized token in')
              ipattern2.setdefault(k, []).append(v)
          return (ipattern1, ipattern2)