<s> from hashlib import md5 <EOL> from django . conf import settings <EOL> from django . db import models <EOL> from django . core import paginator <EOL> from django . core . cache import cache <EOL> from djangae . contrib . pagination . decorators import _field_name_for_ordering <EOL> from djangae . db . backends . appengine . query import extract_ordering <EOL> CACHE_TIME = getattr ( settings , "<STR_LIT>" , <NUM_LIT:30> * <NUM_LIT> ) <EOL> class PaginationOrderingRequired ( RuntimeError ) : <EOL> pass <EOL> def _marker_cache_key ( query_id , page_number ) : <EOL> cache_key = "<STR_LIT>" . format ( query_id , page_number ) <EOL> return cache_key <EOL> def _count_cache_key ( query_id ) : <EOL> cache_key = "<STR_LIT>" . format ( query_id ) <EOL> return cache_key <EOL> def _update_known_count ( query_id , count ) : <EOL> cache_key = _count_cache_key ( query_id ) <EOL> ret = cache . get ( cache_key ) <EOL> if ret and ret > count : <EOL> return <EOL> cache . set ( cache_key , count , CACHE_TIME ) <EOL> def _get_known_count ( query_id ) : <EOL> cache_key = _count_cache_key ( query_id ) <EOL> ret = cache . get ( cache_key ) <EOL> if ret : <EOL> return ret <EOL> return <NUM_LIT:0> <EOL> def _store_marker ( query_id , page_number , marker_value ) : <EOL> """<STR_LIT>""" <EOL> cache_key = _marker_cache_key ( query_id , page_number ) <EOL> cache . set ( cache_key , marker_value , CACHE_TIME ) <EOL> def _get_marker ( query_id , page_number ) : <EOL> """<STR_LIT>""" <EOL> counter = page_number - <NUM_LIT:1> <EOL> pages_skipped = <NUM_LIT:0> <EOL> while counter > <NUM_LIT:0> : <EOL> cache_key = _marker_cache_key ( query_id , counter ) <EOL> ret = cache . get ( cache_key ) <EOL> if ret : <EOL> return ret , pages_skipped <EOL> counter -= <NUM_LIT:1> <EOL> pages_skipped += <NUM_LIT:1> <EOL> return None , pages_skipped <EOL> def queryset_identifier ( queryset ) : <EOL> """<STR_LIT>""" <EOL> hasher = md5 ( ) <EOL> hasher . update ( queryset . model . _meta . db_table ) <EOL> hasher . update ( str ( queryset . query . where ) ) <EOL> hasher . update ( str ( queryset . query . order_by ) ) <EOL> return hasher . hexdigest ( ) <EOL> class Paginator ( paginator . Paginator ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , object_list , per_page , readahead = <NUM_LIT:10> , <EOL> allow_empty_first_page = True , ** kwargs ) : <EOL> if not object_list . ordered : <EOL> object_list . order_by ( "<STR_LIT>" ) <EOL> self . original_orderings = extract_ordering ( object_list . query ) <EOL> self . field_required = _field_name_for_ordering ( self . original_orderings [ : ] ) <EOL> self . readahead = readahead <EOL> self . allow_empty_first_page = allow_empty_first_page <EOL> try : <EOL> object_list . model . _meta . get_field ( self . field_required ) <EOL> except models . FieldDoesNotExist : <EOL> raise PaginationOrderingRequired ( "<STR_LIT>" . format ( self . original_orderings , self . field_required ) ) <EOL> object_list = object_list . order_by ( ) <EOL> if len ( self . original_orderings ) == <NUM_LIT:1> and self . original_orderings [ <NUM_LIT:0> ] . startswith ( "<STR_LIT:->" ) : <EOL> object_list = object_list . order_by ( "<STR_LIT:->" + self . field_required ) <EOL> else : <EOL> object_list = object_list . order_by ( self . field_required ) <EOL> self . queryset_id = queryset_identifier ( object_list ) <EOL> super ( Paginator , self ) . __init__ ( object_list , per_page , allow_empty_first_page = allow_empty_first_page , ** kwargs ) <EOL> @ property <EOL> def count ( self ) : <EOL> return _get_known_count ( self . queryset_id ) <EOL> def validate_number ( self , number ) : <EOL> """<STR_LIT>""" <EOL> try : <EOL> number = int ( number ) <EOL> except ( TypeError , ValueError ) : <EOL> raise paginator . PageNotAnInteger ( '<STR_LIT>' ) <EOL> if number < <NUM_LIT:1> : <EOL> raise paginator . EmptyPage ( '<STR_LIT>' ) <EOL> return number <EOL> def page ( self , number ) : <EOL> """<STR_LIT>""" <EOL> number = self . validate_number ( number ) <EOL> bottom = ( number - <NUM_LIT:1> ) * self . per_page <EOL> top = bottom + self . per_page <EOL> marker_value , pages = _get_marker ( <EOL> self . queryset_id , <EOL> number <EOL> ) <EOL> if marker_value : <EOL> if len ( self . original_orderings ) == <NUM_LIT:1> and self . original_orderings [ <NUM_LIT:0> ] . startswith ( "<STR_LIT:->" ) : <EOL> qs = self . object_list . all ( ) . filter ( ** { "<STR_LIT>" . format ( self . field_required ) : marker_value } ) <EOL> else : <EOL> qs = self . object_list . all ( ) . filter ( ** { "<STR_LIT>" . format ( self . field_required ) : marker_value } ) <EOL> bottom = pages * self . per_page <EOL> top = bottom + self . per_page <EOL> else : <EOL> qs = self . object_list <EOL> results = list ( qs [ bottom : top + ( self . per_page * self . readahead ) ] ) <EOL> next_page = results [ top : ] <EOL> next_page_counter = number + <NUM_LIT:1> <EOL> while next_page : <EOL> if len ( next_page ) > self . per_page - <NUM_LIT:1> : <EOL> index = self . per_page - <NUM_LIT:1> <EOL> else : <EOL> index = len ( next_page ) - <NUM_LIT:1> <EOL> _store_marker ( <EOL> self . queryset_id , <EOL> next_page_counter , <EOL> getattr ( next_page [ index ] , self . field_required ) <EOL> ) <EOL> next_page_counter += <NUM_LIT:1> <EOL> next_page = next_page [ self . per_page : ] <EOL> if not results and not self . allow_empty_first_page : <EOL> raise paginator . EmptyPage ( "<STR_LIT>" ) <EOL> known_count = ( ( number - <NUM_LIT:1> ) * self . per_page ) + len ( results ) <EOL> _update_known_count ( self . queryset_id , known_count ) <EOL> page = self . _get_page ( results [ : self . per_page ] , number , self ) <EOL> if len ( page . object_list ) > self . per_page - <NUM_LIT:1> : <EOL> index = self . per_page - <NUM_LIT:1> <EOL> else : <EOL> index = len ( page . object_list ) - <NUM_LIT:1> <EOL> if results : <EOL> _store_marker ( <EOL> self . queryset_id , <EOL> number , <EOL> getattr ( page . object_list [ index ] , self . field_required ) <EOL> ) <EOL> return page </s>
