nodes: 0, module; 1, function_definition; 2, function_name:image_list_detailed; 3, parameters; 4, block; 5, identifier:request; 6, default_parameter; 7, default_parameter; 8, default_parameter; 9, default_parameter; 10, default_parameter; 11, default_parameter; 12, dictionary_splat_pattern; 13, expression_statement; 14, expression_statement; 15, expression_statement; 16, if_statement; 17, expression_statement; 18, expression_statement; 19, if_statement; 20, expression_statement; 21, if_statement; 22, expression_statement; 23, expression_statement; 24, expression_statement; 25, if_statement; 26, comment:# TODO(jpichon): Do it better; 27, expression_statement; 28, for_statement; 29, return_statement; 30, identifier:marker; 31, None; 32, identifier:sort_dir; 33, string; 34, identifier:sort_key; 35, string; 36, identifier:filters; 37, None; 38, identifier:paginate; 39, False; 40, identifier:reversed_order; 41, False; 42, identifier:kwargs; 43, comment:"""Thin layer above glanceclient, for handling pagination issues.
  
      It provides iterating both forward and backward on top of ascetic
      OpenStack pagination API - which natively supports only iterating forward
      through the entries. Thus in order to retrieve list of objects at previous
      page, a request with the reverse entries order had to be made to Glance,
      using the first object id on current page as the marker - restoring
      the original items ordering before sending them back to the UI.
  
      :param request:
  
          The request object coming from browser to be passed further into
          Glance service.
  
      :param marker:
  
          The id of an object which defines a starting point of a query sent to
          Glance service.
  
      :param sort_dir:
  
          The direction by which the resulting image list throughout all pages
          (if pagination is enabled) will be sorted. Could be either 'asc'
          (ascending) or 'desc' (descending), defaults to 'desc'.
  
      :param sort_key:
  
          The name of key by by which the resulting image list throughout all
          pages (if pagination is enabled) will be sorted. Defaults to
          'created_at'.
  
      :param filters:
  
          A dictionary of filters passed as is to Glance service.
  
      :param paginate:
  
          Whether the pagination is enabled. If it is, then the number of
          entries on a single page of images table is limited to the specific
          number stored in browser cookies.
  
      :param reversed_order:
  
          Set this flag to True when it's necessary to get a reversed list of
          images from Glance (used for navigating the images list back in UI).
      """; 44, assignment; 45, assignment; 46, identifier:paginate; 47, block; 48, else_clause; 49, call; 50, assignment; 51, identifier:marker; 52, block; 53, assignment; 54, not_operator; 55, block; 56, else_clause; 57, assignment; 58, assignment; 59, assignment; 60, identifier:paginate; 61, block; 62, else_clause; 63, assignment; 64, identifier:image; 65, identifier:images; 66, block; 67, expression_list; 68, string_content:desc; 69, string_content:created_at; 70, identifier:limit; 71, call; 72, identifier:page_size; 73, call; 74, expression_statement; 75, block; 76, identifier:_normalize_list_input; 77, argument_list; 78, identifier:kwargs; 79, dictionary; 80, expression_statement; 81, subscript; 82, identifier:sort_key; 83, identifier:reversed_order; 84, expression_statement; 85, block; 86, identifier:images_iter; 87, call; 88, identifier:has_prev_data; 89, False; 90, identifier:has_more_data; 91, False; 92, expression_statement; 93, comment:# first and middle page condition; 94, if_statement; 95, comment:# restore the original ordering here; 96, if_statement; 97, block; 98, identifier:wrapped_images; 99, list; 100, expression_statement; 101, identifier:wrapped_images; 102, identifier:has_more_data; 103, identifier:has_prev_data; 104, identifier:getattr; 105, argument_list; 106, attribute; 107, argument_list; 108, assignment; 109, expression_statement; 110, identifier:filters; 111, dictionary_splat; 112, pair; 113, assignment; 114, identifier:kwargs; 115, string; 116, assignment; 117, expression_statement; 118, attribute; 119, argument_list; 120, assignment; 121, comparison_operator:len(images) > page_size; 122, block; 123, comment:# first page condition when reached via prev back; 124, elif_clause; 125, comment:# last page condition; 126, elif_clause; 127, identifier:reversed_order; 128, block; 129, expression_statement; 130, call; 131, identifier:settings; 132, string; 133, integer:1000; 134, identifier:utils; 135, identifier:get_page_size; 136, identifier:request; 137, identifier:request_size; 138, binary_operator:page_size + 1; 139, assignment; 140, identifier:kwargs; 141, string; 142, boolean_operator; 143, subscript; 144, identifier:marker; 145, string_content:sort_key; 146, subscript; 147, identifier:sort_dir; 148, assignment; 149, attribute; 150, identifier:list; 151, keyword_argument; 152, keyword_argument; 153, dictionary_splat; 154, identifier:images; 155, call; 156, call; 157, identifier:page_size; 158, expression_statement; 159, expression_statement; 160, comment:# middle page condition; 161, if_statement; 162, boolean_operator; 163, block; 164, comparison_operator:marker is not None; 165, block; 166, expression_statement; 167, assignment; 168, attribute; 169, argument_list; 170, string_content:API_RESULT_LIMIT; 171, identifier:page_size; 172, integer:1; 173, identifier:request_size; 174, identifier:limit; 175, string_content:filters; 176, identifier:filters; 177, dictionary; 178, identifier:kwargs; 179, string; 180, identifier:kwargs; 181, string; 182, subscript; 183, conditional_expression:'desc' if sort_dir == 'asc' else 'asc'; 184, call; 185, identifier:images; 186, identifier:page_size; 187, identifier:request_size; 188, identifier:limit; 189, identifier:limit; 190, identifier:kwargs; 191, identifier:list; 192, argument_list; 193, identifier:len; 194, argument_list; 195, call; 196, assignment; 197, comparison_operator:marker is not None; 198, block; 199, identifier:reversed_order; 200, comparison_operator:marker is not None; 201, expression_statement; 202, identifier:marker; 203, None; 204, expression_statement; 205, assignment; 206, identifier:images; 207, call; 208, identifier:wrapped_images; 209, identifier:append; 210, call; 211, string_content:marker; 212, string_content:sort_dir; 213, identifier:kwargs; 214, string; 215, string; 216, comparison_operator:sort_dir == 'asc'; 217, string; 218, identifier:glanceclient; 219, argument_list; 220, call; 221, identifier:images; 222, attribute; 223, argument_list; 224, identifier:has_more_data; 225, True; 226, identifier:marker; 227, None; 228, expression_statement; 229, identifier:marker; 230, None; 231, assignment; 232, assignment; 233, identifier:images; 234, call; 235, identifier:list; 236, argument_list; 237, identifier:Image; 238, argument_list; 239, string_content:sort_dir; 240, string_content:desc; 241, identifier:sort_dir; 242, string; 243, string_content:asc; 244, identifier:request; 245, attribute; 246, argument_list; 247, identifier:images; 248, identifier:pop; 249, unary_operator; 250, assignment; 251, identifier:has_more_data; 252, True; 253, identifier:has_prev_data; 254, True; 255, identifier:sorted; 256, argument_list; 257, identifier:images_iter; 258, identifier:image; 259, string_content:asc; 260, identifier:itertools; 261, identifier:islice; 262, identifier:images_iter; 263, identifier:request_size; 264, integer:1; 265, identifier:has_prev_data; 266, True; 267, identifier:images; 268, keyword_argument; 269, keyword_argument; 270, identifier:key; 271, lambda; 272, identifier:reverse; 273, parenthesized_expression; 274, lambda_parameters; 275, call; 276, comparison_operator:sort_dir == 'desc'; 277, identifier:image; 278, attribute; 279, argument_list; 280, identifier:sort_dir; 281, string; 282, parenthesized_expression; 283, identifier:lower; 284, string_content:desc; 285, boolean_operator; 286, call; 287, string; 288, identifier:getattr; 289, argument_list; 290, identifier:image; 291, identifier:sort_key
code: def image_list_detailed(request, marker=None, sort_dir='desc',
                          sort_key='created_at', filters=None, paginate=False,
                          reversed_order=False, **kwargs):
      """Thin layer above glanceclient, for handling pagination issues.
  
      It provides iterating both forward and backward on top of ascetic
      OpenStack pagination API - which natively supports only iterating forward
      through the entries. Thus in order to retrieve list of objects at previous
      page, a request with the reverse entries order had to be made to Glance,
      using the first object id on current page as the marker - restoring
      the original items ordering before sending them back to the UI.
  
      :param request:
  
          The request object coming from browser to be passed further into
          Glance service.
  
      :param marker:
  
          The id of an object which defines a starting point of a query sent to
          Glance service.
  
      :param sort_dir:
  
          The direction by which the resulting image list throughout all pages
          (if pagination is enabled) will be sorted. Could be either 'asc'
          (ascending) or 'desc' (descending), defaults to 'desc'.
  
      :param sort_key:
  
          The name of key by by which the resulting image list throughout all
          pages (if pagination is enabled) will be sorted. Defaults to
          'created_at'.
  
      :param filters:
  
          A dictionary of filters passed as is to Glance service.
  
      :param paginate:
  
          Whether the pagination is enabled. If it is, then the number of
          entries on a single page of images table is limited to the specific
          number stored in browser cookies.
  
      :param reversed_order:
  
          Set this flag to True when it's necessary to get a reversed list of
          images from Glance (used for navigating the images list back in UI).
      """
      limit = getattr(settings, 'API_RESULT_LIMIT', 1000)
      page_size = utils.get_page_size(request)
  
      if paginate:
          request_size = page_size + 1
      else:
          request_size = limit
  
      _normalize_list_input(filters, **kwargs)
      kwargs = {'filters': filters or {}}
  
      if marker:
          kwargs['marker'] = marker
      kwargs['sort_key'] = sort_key
  
      if not reversed_order:
          kwargs['sort_dir'] = sort_dir
      else:
          kwargs['sort_dir'] = 'desc' if sort_dir == 'asc' else 'asc'
  
      images_iter = glanceclient(request).images.list(page_size=request_size,
                                                      limit=limit,
                                                      **kwargs)
      has_prev_data = False
      has_more_data = False
      if paginate:
          images = list(itertools.islice(images_iter, request_size))
          # first and middle page condition
          if len(images) > page_size:
              images.pop(-1)
              has_more_data = True
              # middle page condition
              if marker is not None:
                  has_prev_data = True
          # first page condition when reached via prev back
          elif reversed_order and marker is not None:
              has_more_data = True
          # last page condition
          elif marker is not None:
              has_prev_data = True
  
          # restore the original ordering here
          if reversed_order:
              images = sorted(images, key=lambda image:
                              (getattr(image, sort_key) or '').lower(),
                              reverse=(sort_dir == 'desc'))
      else:
          images = list(images_iter)
  
      # TODO(jpichon): Do it better
      wrapped_images = []
      for image in images:
          wrapped_images.append(Image(image))
  
      return wrapped_images, has_more_data, has_prev_data