66import typing
77from typing import Optional , Iterable , Any , Generator
88
9- from .exceptions import GraphQlQueryFailed
9+ from .exceptions import GraphQlQueryError , GraphQlQueryFailed
1010from .utils import SortOrder
1111
1212if typing .TYPE_CHECKING :
@@ -304,7 +304,7 @@ def calculate_query(self) -> str:
304304 str: GraphQl string with variables and headers.
305305
306306 Raises:
307- ValueError: Query has no fiels .
307+ ValueError: Query has no fields .
308308
309309 """
310310 if not self ._children :
@@ -370,7 +370,7 @@ def query(self, con: ServerAPI) -> dict[str, Any]:
370370 variables = self .get_variables_values ()
371371 response = con .query_graphql (
372372 query_str ,
373- self . get_variables_values ()
373+ variables
374374 )
375375 if response .errors :
376376 raise GraphQlQueryFailed (response .errors , query_str , variables )
@@ -396,6 +396,7 @@ def continuous_query(
396396 while self .need_query :
397397 query_str = self .calculate_query ()
398398 variables = self .get_variables_values ()
399+
399400 response = con .query_graphql (query_str , variables )
400401 if response .errors :
401402 raise GraphQlQueryFailed (
@@ -902,8 +903,13 @@ def parse_result(
902903 progress_data [cursor_key ] = nodes_by_cursor
903904
904905 page_info = value ["pageInfo" ]
905- new_cursor = page_info ["endCursor" ]
906- self ._need_query = page_info ["hasNextPage" ]
906+ if self ._order == SortOrder .ascending :
907+ new_cursor = page_info ["endCursor" ]
908+ self ._need_query = page_info ["hasNextPage" ]
909+ else :
910+ new_cursor = page_info ["startCursor" ]
911+ self ._need_query = page_info ["hasPreviousPage" ]
912+
907913 edges = value ["edges" ]
908914 # Fake result parse
909915 if not edges :
@@ -931,15 +937,18 @@ def parse_result(
931937 for child in self ._children :
932938 child .parse_result (edge ["node" ], edge_value , progress_data )
933939
934- if not self ._need_query :
935- return
936-
937940 change_cursor = True
938941 for child in self ._children_iter ():
939942 if child .need_query :
940943 change_cursor = False
941944
942- if change_cursor :
945+ if change_cursor and self ._need_query :
946+ if new_cursor == self ._cursor :
947+ raise GraphQlQueryError (
948+ "Cursor didn't change during pagination."
949+ " This can cause infinite loop."
950+ )
951+
943952 for child in self ._children_iter ():
944953 child .reset_cursor ()
945954 self ._cursor = new_cursor
@@ -949,9 +958,7 @@ def _get_cursor_key(self) -> str:
949958
950959 def get_filters (self ) -> dict [str , Any ]:
951960 filters = super ().get_filters ()
952- limit_key = "first"
953- if self ._order == SortOrder .descending :
954- limit_key = "last"
961+ limit_key = "first" if self ._order == SortOrder .ascending else "last"
955962
956963 limit_amount = 300
957964 if self ._limit :
@@ -968,7 +975,10 @@ def get_filters(self) -> dict[str, Any]:
968975 filters [limit_key ] = limit_amount
969976
970977 if self ._cursor :
971- filters ["after" ] = self ._cursor
978+ cursor_key = (
979+ "after" if self ._order == SortOrder .ascending else "before"
980+ )
981+ filters [cursor_key ] = self ._cursor
972982 return filters
973983
974984 def calculate_query (self ) -> str :
@@ -1006,8 +1016,16 @@ def calculate_query(self) -> str:
10061016 # Add page information
10071017 output .append (edges_offset + "pageInfo {" )
10081018 for page_key in (
1009- "endCursor" ,
1010- "hasNextPage" ,
1019+ (
1020+ "endCursor"
1021+ if self ._order == SortOrder .ascending
1022+ else "startCursor"
1023+ ),
1024+ (
1025+ "hasNextPage"
1026+ if self ._order == SortOrder .ascending
1027+ else "hasPreviousPage"
1028+ ),
10111029 ):
10121030 output .append (node_offset + page_key )
10131031 output .append (edges_offset + "}" )
0 commit comments