nodes: 0, module; 1, function_definition; 2, function_name:keyed_helper; 3, parameters; 4, block; 5, identifier:helper; 6, expression_statement; 7, decorated_definition; 8, expression_statement; 9, return_statement; 10, comment:"""
      Decorator for helper functions that operate on direct values instead of model instances.
  
      A keyed helper is one that can be used normally in the view's own custom callbacks, but also
      supports direct access in the column declaration, such as in the example:
  
          datatable_options = {
              'columns': [
                  ('Field Name', 'fieldname', make_boolean_checkmark(key=attrgetter('fieldname'))),
              ],
          }
  
      With the help of a ``sort``-style ``key`` argument, the helper can receive all the information
      it requires in advance, so that the view doesn't have to go through the trouble of declaring
      a custom callback method that simply returns the value of the ``make_boolean_checkmark()``
      helper.
  
      If the attribute being fetched is identical to the one pointed to in the column declaration,
      even the ``key`` argument can be omitted:
  
          ('Field Name', 'fieldname', make_boolean_checkmark)),
  
      """; 11, decorator; 12, function_definition; 13, assignment; 14, identifier:wrapper; 15, call; 16, function_name:wrapper; 17, parameters; 18, block; 19, attribute; 20, True; 21, identifier:wraps; 22, argument_list; 23, default_parameter; 24, default_parameter; 25, default_parameter; 26, list_splat_pattern; 27, dictionary_splat_pattern; 28, if_statement; 29, if_statement; 30, if_statement; 31, if_statement; 32, comment:# Helper is used directly in the columns declaration.  A new callable is; 33, comment:# returned to take the place of a callback.; 34, decorated_definition; 35, return_statement; 36, identifier:wrapper; 37, identifier:_is_wrapped; 38, identifier:helper; 39, identifier:instance; 40, None; 41, identifier:key; 42, None; 43, identifier:attr; 44, None; 45, identifier:args; 46, identifier:kwargs; 47, comparison_operator:set((instance, key, attr)) == {None}; 48, comment:# helper was called in place with neither important arg; 49, block; 50, comparison_operator:instance is not None; 51, block; 52, boolean_operator; 53, block; 54, identifier:attr; 55, block; 56, decorator; 57, function_definition; 58, identifier:helper_wrapper; 59, call; 60, set; 61, raise_statement; 62, identifier:instance; 63, None; 64, return_statement; 65, comparison_operator:key is None; 66, comparison_operator:attr is None; 67, expression_statement; 68, if_statement; 69, call; 70, function_name:helper_wrapper; 71, parameters; 72, block; 73, identifier:set; 74, argument_list; 75, None; 76, call; 77, call; 78, identifier:key; 79, None; 80, identifier:attr; 81, None; 82, assignment; 83, comparison_operator:attr == 'self'; 84, block; 85, else_clause; 86, identifier:wraps; 87, argument_list; 88, identifier:instance; 89, list_splat_pattern; 90, dictionary_splat_pattern; 91, return_statement; 92, tuple; 93, identifier:ValueError; 94, argument_list; 95, identifier:helper; 96, argument_list; 97, identifier:attr; 98, string; 99, identifier:attr; 100, string; 101, expression_statement; 102, block; 103, identifier:helper; 104, identifier:args; 105, identifier:kwargs; 106, call; 107, identifier:instance; 108, identifier:key; 109, identifier:attr; 110, binary_operator:"If called directly, helper function '%s' requires either a model"
                               " instance, or a 'key' or 'attr' keyword argument." % helper.__name__; 111, identifier:instance; 112, list_splat; 113, dictionary_splat; 114, string_content:self; 115, string_content:self; 116, assignment; 117, expression_statement; 118, identifier:helper; 119, argument_list; 120, concatenated_string; 121, attribute; 122, identifier:args; 123, identifier:kwargs; 124, identifier:key; 125, lambda; 126, assignment; 127, call; 128, list_splat; 129, dictionary_splat; 130, string:"If called directly, helper function '%s' requires either a model"; 131, string:" instance, or a 'key' or 'attr' keyword argument."; 132, identifier:helper; 133, identifier:__name__; 134, lambda_parameters; 135, identifier:obj; 136, identifier:key; 137, call; 138, identifier:key; 139, argument_list; 140, identifier:args; 141, identifier:kwargs; 142, identifier:obj; 143, attribute; 144, argument_list; 145, identifier:instance; 146, identifier:operator; 147, identifier:attrgetter; 148, identifier:attr
code: def keyed_helper(helper):
      """
      Decorator for helper functions that operate on direct values instead of model instances.
  
      A keyed helper is one that can be used normally in the view's own custom callbacks, but also
      supports direct access in the column declaration, such as in the example:
  
          datatable_options = {
              'columns': [
                  ('Field Name', 'fieldname', make_boolean_checkmark(key=attrgetter('fieldname'))),
              ],
          }
  
      With the help of a ``sort``-style ``key`` argument, the helper can receive all the information
      it requires in advance, so that the view doesn't have to go through the trouble of declaring
      a custom callback method that simply returns the value of the ``make_boolean_checkmark()``
      helper.
  
      If the attribute being fetched is identical to the one pointed to in the column declaration,
      even the ``key`` argument can be omitted:
  
          ('Field Name', 'fieldname', make_boolean_checkmark)),
  
      """
  
      @wraps(helper)
      def wrapper(instance=None, key=None, attr=None, *args, **kwargs):
          if set((instance, key, attr)) == {None}:
              # helper was called in place with neither important arg
              raise ValueError("If called directly, helper function '%s' requires either a model"
                               " instance, or a 'key' or 'attr' keyword argument." % helper.__name__)
  
          if instance is not None:
              return helper(instance, *args, **kwargs)
  
          if key is None and attr is None:
              attr = 'self'
  
          if attr:
              if attr == 'self':
                  key = lambda obj: obj
              else:
                  key = operator.attrgetter(attr)
  
          # Helper is used directly in the columns declaration.  A new callable is
          # returned to take the place of a callback.
          @wraps(helper)
          def helper_wrapper(instance, *args, **kwargs):
              return helper(key(instance), *args, **kwargs)
          return helper_wrapper
  
      wrapper._is_wrapped = True
      return wrapper