nodes: 0, module; 1, function_definition; 2, function_name:get_members; 3, parameters; 4, block; 5, identifier:cls; 6, default_parameter; 7, default_parameter; 8, default_parameter; 9, default_parameter; 10, expression_statement; 11, if_statement; 12, expression_statement; 13, for_statement; 14, function_definition; 15, expression_statement; 16, if_statement; 17, return_statement; 18, identifier:member_class; 19, None; 20, identifier:is_member; 21, None; 22, identifier:sort_key; 23, None; 24, identifier:_parameter; 25, None; 26, comment:"""
          Collect all class level attributes matching the given criteria.
  
          :param class member_class: Class(es) to collect
          :param is_member: Function to determine if an object should be collected
          :param sort_key: Function to invoke on members to obtain ordering (Default is to use ordering from `creation_ordered`)
  
          :type is_member: (object) -> bool
          :type sort_key: (object) -> object
      """; 27, boolean_operator; 28, block; 29, assignment; 30, identifier:base; 31, attribute; 32, block; 33, function_name:generate_member_bindings; 34, parameters; 35, block; 36, assignment; 37, comparison_operator:sort_key is not None; 38, block; 39, else_clause; 40, identifier:members; 41, comparison_operator:member_class is None; 42, comparison_operator:is_member is None; 43, raise_statement; 44, identifier:members; 45, call; 46, identifier:cls; 47, identifier:__bases__; 48, if_statement; 49, expression_statement; 50, for_statement; 51, identifier:bindings; 52, call; 53, identifier:sort_key; 54, None; 55, try_statement; 56, expression_statement; 57, block; 58, identifier:member_class; 59, None; 60, identifier:is_member; 61, None; 62, call; 63, identifier:OrderedDict; 64, argument_list; 65, comparison_operator:_parameter is None; 66, block; 67, else_clause; 68, call; 69, identifier:name; 70, attribute; 71, block; 72, identifier:generate_member_bindings; 73, argument_list; 74, block; 75, except_clause; 76, call; 77, expression_statement; 78, identifier:TypeError; 79, argument_list; 80, identifier:_parameter; 81, None; 82, expression_statement; 83, comment:# When user by @declarative, only traverse up the class inheritance to the decorated class.; 84, block; 85, attribute; 86, argument_list; 87, identifier:cls; 88, identifier:__dict__; 89, if_statement; 90, expression_statement; 91, if_statement; 92, expression_statement; 93, identifier:AttributeError; 94, block; 95, attribute; 96, argument_list; 97, call; 98, string:"get_members either needs a member_class parameter or an is_member check function (or both)"; 99, assignment; 100, expression_statement; 101, identifier:members; 102, identifier:update; 103, identifier:inherited_members; 104, call; 105, block; 106, assignment; 107, boolean_operator; 108, block; 109, elif_clause; 110, elif_clause; 111, assignment; 112, if_statement; 113, identifier:members; 114, identifier:update; 115, identifier:sorted_bindings; 116, attribute; 117, argument_list; 118, identifier:inherited_members; 119, call; 120, assignment; 121, attribute; 122, argument_list; 123, continue_statement; 124, identifier:obj; 125, call; 126, comparison_operator:member_class is not None; 127, call; 128, expression_statement; 129, boolean_operator; 130, block; 131, boolean_operator; 132, block; 133, identifier:sorted_bindings; 134, call; 135, comparison_operator:sort_key is default_sort_key; 136, block; 137, else_clause; 138, identifier:members; 139, identifier:update; 140, identifier:bindings; 141, identifier:get_members; 142, argument_list; 143, identifier:inherited_members; 144, call; 145, identifier:name; 146, identifier:startswith; 147, string; 148, identifier:getattr; 149, argument_list; 150, identifier:member_class; 151, None; 152, identifier:isinstance; 153, argument_list; 154, yield; 155, comparison_operator:is_member is not None; 156, call; 157, expression_statement; 158, boolean_operator; 159, call; 160, raise_statement; 161, comment:# pragma: no mutate; 162, identifier:sorted; 163, argument_list; 164, identifier:sort_key; 165, identifier:default_sort_key; 166, raise_statement; 167, comment:# pragma: no covererage; 168, block; 169, identifier:base; 170, keyword_argument; 171, keyword_argument; 172, keyword_argument; 173, identifier:get_declared; 174, argument_list; 175, string_content:__; 176, identifier:cls; 177, identifier:name; 178, identifier:obj; 179, identifier:member_class; 180, expression_list; 181, identifier:is_member; 182, None; 183, identifier:is_member; 184, argument_list; 185, yield; 186, comparison_operator:type(obj) is tuple; 187, comparison_operator:len(obj) == 1; 188, identifier:isinstance; 189, argument_list; 190, call; 191, identifier:bindings; 192, keyword_argument; 193, call; 194, raise_statement; 195, identifier:member_class; 196, identifier:member_class; 197, identifier:is_member; 198, identifier:is_member; 199, identifier:sort_key; 200, identifier:sort_key; 201, identifier:base; 202, identifier:_parameter; 203, identifier:name; 204, identifier:obj; 205, identifier:obj; 206, expression_list; 207, call; 208, identifier:tuple; 209, call; 210, integer:1; 211, subscript; 212, identifier:member_class; 213, identifier:TypeError; 214, argument_list; 215, identifier:key; 216, lambda; 217, identifier:TypeError; 218, argument_list; 219, identifier:name; 220, identifier:obj; 221, identifier:type; 222, argument_list; 223, identifier:len; 224, argument_list; 225, identifier:obj; 226, integer:0; 227, binary_operator:"'%s' is a one-tuple containing what we are looking for.  Trailing comma much?  Don't... just don't." % name; 228, lambda_parameters; 229, call; 230, string; 231, identifier:obj; 232, identifier:obj; 233, string:"'%s' is a one-tuple containing what we are looking for.  Trailing comma much?  Don't... just don't."; 234, identifier:name; 235, identifier:x; 236, identifier:sort_key; 237, argument_list; 238, string_content:Missing member ordering definition. Use @creation_ordered or specify sort_key; 239, subscript; 240, identifier:x; 241, integer:1
code: def get_members(cls, member_class=None, is_member=None, sort_key=None, _parameter=None):
      """
          Collect all class level attributes matching the given criteria.
  
          :param class member_class: Class(es) to collect
          :param is_member: Function to determine if an object should be collected
          :param sort_key: Function to invoke on members to obtain ordering (Default is to use ordering from `creation_ordered`)
  
          :type is_member: (object) -> bool
          :type sort_key: (object) -> object
      """
      if member_class is None and is_member is None:
          raise TypeError("get_members either needs a member_class parameter or an is_member check function (or both)")
  
      members = OrderedDict()
      for base in cls.__bases__:
          if _parameter is None:
              inherited_members = get_members(base, member_class=member_class, is_member=is_member, sort_key=sort_key)
          else:
              # When user by @declarative, only traverse up the class inheritance to the decorated class.
              inherited_members = get_declared(base, _parameter)
          members.update(inherited_members)
  
      def generate_member_bindings():
          for name in cls.__dict__:
              if name.startswith('__'):
                  continue
              obj = getattr(cls, name)
              if member_class is not None and isinstance(obj, member_class):
                  yield name, obj
              elif is_member is not None and is_member(obj):
                  yield name, obj
              elif type(obj) is tuple and len(obj) == 1 and isinstance(obj[0], member_class):
                  raise TypeError("'%s' is a one-tuple containing what we are looking for.  Trailing comma much?  Don't... just don't." % name)  # pragma: no mutate
  
      bindings = generate_member_bindings()
  
      if sort_key is not None:
          try:
              sorted_bindings = sorted(bindings, key=lambda x: sort_key(x[1]))
          except AttributeError:
              if sort_key is default_sort_key:
                  raise TypeError('Missing member ordering definition. Use @creation_ordered or specify sort_key')
              else:  # pragma: no covererage
                  raise
          members.update(sorted_bindings)
      else:
          members.update(bindings)
  
      return members