signature:
def delivery ( self , packageName , versionCode = None , offerType = 1 , downloadToken = None , expansion_files = False ) :
    """Download an already purchased app .
 Args :
 packageName ( str ) : app unique ID ( usually starting with ' com . ' )
 versionCode ( int ) : version to download
 offerType ( int ) : different type of downloads ( mostly unused for apks )
 downloadToken ( str ) : download token returned by ' purchase ' API
 progress _ bar ( bool ) : wether or not to print a progress bar to stdout
 Returns :
 Dictionary containing apk data and a list of expansion files . As stated
 in android documentation , there can be at most 2 expansion files , one with
 main content , and one for patching the main content . Their names should
 follow this format :
 [ main | patch ] . < expansion - version > . < package - name > . obb
 Data to build this name string is provided in the dict object . For more
 info check https : / / developer . android . com / google / play / expansion - files . html"""

implementation:
if versionCode is None : # pick up latest version
    versionCode = self . details ( packageName ) . get ( 'versionCode' )
params = { 'ot' : str ( offerType ) , 'doc' : packageName , 'vc' : str ( versionCode ) }
headers = self . getHeaders ( )
if downloadToken is not None :
    params [ 'dtok' ] = downloadToken
response = requests . get ( DELIVERY_URL , headers = headers , params = params , verify = ssl_verify , timeout = 60 , proxies = self . proxies_config )
response = googleplay_pb2 . ResponseWrapper . FromString ( response . content )
if response . commands . displayErrorMessage != "" :
    raise RequestError ( response . commands . displayErrorMessage )
elif response . payload . deliveryResponse . appDeliveryData . downloadUrl == "" :
    raise RequestError ( 'App not purchased' )
else :
    result = { }
    result [ 'docId' ] = packageName
    result [ 'additionalData' ] = [ ]
    downloadUrl = response . payload . deliveryResponse . appDeliveryData . downloadUrl
    cookie = response . payload . deliveryResponse . appDeliveryData . downloadAuthCookie [ 0 ]
    cookies = { str ( cookie . name ) : str ( cookie . value ) }
    result [ 'file' ] = self . _deliver_data ( downloadUrl , cookies )
    if not expansion_files :
        return result
    for obb in response . payload . deliveryResponse . appDeliveryData . additionalFile :
        a = { }
        # fileType = = 0 - > main
        # fileType = = 1 - > patch
        if obb . fileType == 0 :
            obbType = 'main'
        else :
            obbType = 'patch'
        a [ 'type' ] = obbType
        a [ 'versionCode' ] = obb . versionCode
        a [ 'file' ] = self . _deliver_data ( obb . downloadUrl , None )
        result [ 'additionalData' ] . append ( a )
    return result


signature:
def download ( self , packageName , versionCode = None , offerType = 1 , expansion_files = False ) :
    """Download an app and return its raw data ( APK file ) . Free apps need
 to be " purchased " first , in order to retrieve the download cookie .
 If you want to download an already purchased app , use * delivery * method .
 Args :
 packageName ( str ) : app unique ID ( usually starting with ' com . ' )
 versionCode ( int ) : version to download
 offerType ( int ) : different type of downloads ( mostly unused for apks )
 downloadToken ( str ) : download token returned by ' purchase ' API
 progress _ bar ( bool ) : wether or not to print a progress bar to stdout
 Returns
 Dictionary containing apk data and optional expansion files
 ( see * delivery * )"""

implementation:
if self . authSubToken is None :
    raise LoginError ( "You need to login before executing any request" )
if versionCode is None : # pick up latest version
    appDetails = self . details ( packageName ) . get ( 'details' ) . get ( 'appDetails' )
    versionCode = appDetails . get ( 'versionCode' )
headers = self . getHeaders ( )
params = { 'ot' : str ( offerType ) , 'doc' : packageName , 'vc' : str ( versionCode ) }
self . log ( packageName )
response = requests . post ( PURCHASE_URL , headers = headers , params = params , verify = ssl_verify , timeout = 60 , proxies = self . proxies_config )
response = googleplay_pb2 . ResponseWrapper . FromString ( response . content )
if response . commands . displayErrorMessage != "" :
    raise RequestError ( response . commands . displayErrorMessage )
else :
    dlToken = response . payload . buyResponse . downloadToken
    return self . delivery ( packageName , versionCode , offerType , dlToken , expansion_files = expansion_files )


signature:
def http_connection ( timeout ) :
    """Decorator function that injects a requests . Session instance into
 the decorated function ' s actual parameters if not given ."""

implementation:
def wrapper ( f ) :
    def wrapped ( * args , ** kwargs ) :
        if not ( 'connection' in kwargs ) or not kwargs [ 'connection' ] :
            connection = requests . Session ( )
            kwargs [ 'connection' ] = connection
        else :
            connection = kwargs [ 'connection' ]
        if not getattr ( connection , 'timeout' , False ) :
            connection . timeout = timeout
        connection . headers . update ( { 'Content-type' : 'application/json' } )
        return f ( * args , ** kwargs )
    return wraps ( f ) ( wrapped )
return wrapper


signature:
def create_token ( self , data , options = None ) :
    """Generates a secure authentication token .
 Our token format follows the JSON Web Token ( JWT ) standard :
 header . claims . signature
 Where :
 1 ) ' header ' is a stringified , base64 - encoded JSON object containing version and algorithm information .
 2 ) ' claims ' is a stringified , base64 - encoded JSON object containing a set of claims :
 Library - generated claims :
 ' iat ' - > The issued at time in seconds since the epoch as a number
 ' d ' - > The arbitrary JSON object supplied by the user .
 User - supplied claims ( these are all optional ) :
 ' exp ' ( optional ) - > The expiration time of this token , as a number of seconds since the epoch .
 ' nbf ' ( optional ) - > The ' not before ' time before which the token should be rejected ( seconds since the epoch )
 ' admin ' ( optional ) - > If set to true , this client will bypass all security rules ( use this to authenticate servers )
 ' debug ' ( optional ) - > ' set to true to make this client receive debug information about security rule execution .
 ' simulate ' ( optional , internal - only for now ) - > Set to true to neuter all API operations ( listens / puts
 will run security rules but not actually write or return data ) .
 3 ) A signature that proves the validity of this token ( see : http : / / tools . ietf . org / html / draft - ietf - jose - json - web - signature - 07)
 For base64 - encoding we use URL - safe base64 encoding . This ensures that the entire token is URL - safe
 and could , for instance , be placed as a query argument without any encoding ( and this is what the JWT spec requires ) .
 Args :
 data - a json serializable object of data to be included in the token
 options - An optional dictionary of additional claims for the token . Possible keys include :
 a ) ' expires ' - - A timestamp ( as a number of seconds since the epoch ) denoting a time after which
 this token should no longer be valid .
 b ) ' notBefore ' - - A timestamp ( as a number of seconds since the epoch ) denoting a time before
 which this token should be rejected by the server .
 c ) ' admin ' - - Set to true to bypass all security rules ( use this for your trusted servers ) .
 d ) ' debug ' - - Set to true to enable debug mode ( so you can see the results of Rules API operations )
 e ) ' simulate ' - - ( internal - only for now ) Set to true to neuter all API operations ( listens / puts
 will run security rules but not actually write or return data )
 Returns :
 A signed Firebase Authentication Token
 Raises :
 ValueError : if an invalid key is specified in options"""

implementation:
if not options :
    options = { }
options . update ( { 'admin' : self . admin , 'debug' : self . debug } )
claims = self . _create_options_claims ( options )
claims [ 'v' ] = self . TOKEN_VERSION
claims [ 'iat' ] = int ( time . mktime ( time . gmtime ( ) ) )
claims [ 'd' ] = data
return self . _encode_token ( self . secret , claims )


signature:
def make_get_request ( url , params , headers , connection ) :
    """Helper function that makes an HTTP GET request to the given firebase
 endpoint . Timeout is 60 seconds .
 ` url ` : The full URL of the firebase endpoint ( DSN appended . )
 ` params ` : Python dict that is appended to the URL like a querystring .
 ` headers ` : Python dict . HTTP request headers .
 ` connection ` : Predefined HTTP connection instance . If not given , it
 is supplied by the ` decorators . http _ connection ` function .
 The returning value is a Python dict deserialized by the JSON decoder . However ,
 if the status code is not 2x or 403 , an requests . HTTPError is raised .
 connection = connection _ pool . get _ available _ connection ( )
 response = make _ get _ request ( ' http : / / firebase . localhost / users ' , { ' print ' : silent ' } ,
 { ' X _ FIREBASE _ SOMETHING ' : ' Hi ' } , connection )
 response = > { ' 1 ' : ' John Doe ' , ' 2 ' : ' Jane Doe ' }"""

implementation:
timeout = getattr ( connection , 'timeout' )
response = connection . get ( url , params = params , headers = headers , timeout = timeout )
if response . ok or response . status_code == 403 :
    return response . json ( ) if response . content else None
else :
    response . raise_for_status ( )


signature:
def make_put_request ( url , data , params , headers , connection ) :
    """Helper function that makes an HTTP PUT request to the given firebase
 endpoint . Timeout is 60 seconds .
 ` url ` : The full URL of the firebase endpoint ( DSN appended . )
 ` data ` : JSON serializable dict that will be stored in the remote storage .
 ` params ` : Python dict that is appended to the URL like a querystring .
 ` headers ` : Python dict . HTTP request headers .
 ` connection ` : Predefined HTTP connection instance . If not given , it
 is supplied by the ` decorators . http _ connection ` function .
 The returning value is a Python dict deserialized by the JSON decoder . However ,
 if the status code is not 2x or 403 , an requests . HTTPError is raised .
 connection = connection _ pool . get _ available _ connection ( )
 response = make _ put _ request ( ' http : / / firebase . localhost / users ' ,
 ' { " 1 " : " Ozgur Vatansever " } ' ,
 { ' X _ FIREBASE _ SOMETHING ' : ' Hi ' } , connection )
 response = > { ' 1 ' : ' Ozgur Vatansever ' } or { ' error ' : ' Permission denied . ' }"""

implementation:
timeout = getattr ( connection , 'timeout' )
response = connection . put ( url , data = data , params = params , headers = headers , timeout = timeout )
if response . ok or response . status_code == 403 :
    return response . json ( ) if response . content else None
else :
    response . raise_for_status ( )


signature:
def make_post_request ( url , data , params , headers , connection ) :
    """Helper function that makes an HTTP POST request to the given firebase
 endpoint . Timeout is 60 seconds .
 ` url ` : The full URL of the firebase endpoint ( DSN appended . )
 ` data ` : JSON serializable dict that will be stored in the remote storage .
 ` params ` : Python dict that is appended to the URL like a querystring .
 ` headers ` : Python dict . HTTP request headers .
 ` connection ` : Predefined HTTP connection instance . If not given , it
 is supplied by the ` decorators . http _ connection ` function .
 The returning value is a Python dict deserialized by the JSON decoder . However ,
 if the status code is not 2x or 403 , an requests . HTTPError is raised .
 connection = connection _ pool . get _ available _ connection ( )
 response = make _ put _ request ( ' http : / / firebase . localhost / users / ' ,
 ' { " Ozgur Vatansever " } ' , { ' X _ FIREBASE _ SOMETHING ' : ' Hi ' } , connection )
 response = > { u ' name ' : u ' - Inw6zol _ 2f5ThHwVcSe ' } or { ' error ' : ' Permission denied . ' }"""

implementation:
timeout = getattr ( connection , 'timeout' )
response = connection . post ( url , data = data , params = params , headers = headers , timeout = timeout )
if response . ok or response . status_code == 403 :
    return response . json ( ) if response . content else None
else :
    response . raise_for_status ( )


signature:
def make_patch_request ( url , data , params , headers , connection ) :
    """Helper function that makes an HTTP PATCH request to the given firebase
 endpoint . Timeout is 60 seconds .
 ` url ` : The full URL of the firebase endpoint ( DSN appended . )
 ` data ` : JSON serializable dict that will be stored in the remote storage .
 ` params ` : Python dict that is appended to the URL like a querystring .
 ` headers ` : Python dict . HTTP request headers .
 ` connection ` : Predefined HTTP connection instance . If not given , it
 is supplied by the ` decorators . http _ connection ` function .
 The returning value is a Python dict deserialized by the JSON decoder . However ,
 if the status code is not 2x or 403 , an requests . HTTPError is raised .
 connection = connection _ pool . get _ available _ connection ( )
 response = make _ put _ request ( ' http : / / firebase . localhost / users / 1 ' ,
 ' { " Ozgur Vatansever " } ' , { ' X _ FIREBASE _ SOMETHING ' : ' Hi ' } , connection )
 response = > { ' Ozgur Vatansever ' } or { ' error ' : ' Permission denied . ' }"""

implementation:
timeout = getattr ( connection , 'timeout' )
response = connection . patch ( url , data = data , params = params , headers = headers , timeout = timeout )
if response . ok or response . status_code == 403 :
    return response . json ( ) if response . content else None
else :
    response . raise_for_status ( )


signature:
def make_delete_request ( url , params , headers , connection ) :
    """Helper function that makes an HTTP DELETE request to the given firebase
 endpoint . Timeout is 60 seconds .
 ` url ` : The full URL of the firebase endpoint ( DSN appended . )
 ` params ` : Python dict that is appended to the URL like a querystring .
 ` headers ` : Python dict . HTTP request headers .
 ` connection ` : Predefined HTTP connection instance . If not given , it
 is supplied by the ` decorators . http _ connection ` function .
 The returning value is NULL . However , if the status code is not 2x or 403,
 an requests . HTTPError is raised .
 connection = connection _ pool . get _ available _ connection ( )
 response = make _ put _ request ( ' http : / / firebase . localhost / users / 1 ' ,
 { ' X _ FIREBASE _ SOMETHING ' : ' Hi ' } , connection )
 response = > NULL or { ' error ' : ' Permission denied . ' }"""

implementation:
timeout = getattr ( connection , 'timeout' )
response = connection . delete ( url , params = params , headers = headers , timeout = timeout )
if response . ok or response . status_code == 403 :
    return response . json ( ) if response . content else None
else :
    response . raise_for_status ( )


signature:
def get_user ( self ) :
    """Method that gets the authenticated user . The returning user has
 the token , email and the provider data ."""

implementation:
token = self . authenticator . create_token ( self . extra )
user_id = self . extra . get ( 'id' )
return FirebaseUser ( self . email , token , self . provider , user_id )


signature:
def _build_endpoint_url ( self , url , name = None ) :
    """Method that constructs a full url with the given url and the
 snapshot name .
 Example :
 full _ url = _ build _ endpoint _ url ( ' / users ' , ' 1 ' )
 full _ url = > ' http : / / firebase . localhost / users / 1 . json '"""

implementation:
if not url . endswith ( self . URL_SEPERATOR ) :
    url = url + self . URL_SEPERATOR
if name is None :
    name = ''
return '%s%s%s' % ( urlparse . urljoin ( self . dsn , url ) , name , self . NAME_EXTENSION )


signature:
def _authenticate ( self , params , headers ) :
    """Method that simply adjusts authentication credentials for the
 request .
 ` params ` is the querystring of the request .
 ` headers ` is the header of the request .
 If auth instance is not provided to this class , this method simply
 returns without doing anything ."""

implementation:
if self . authentication :
    user = self . authentication . get_user ( )
    params . update ( { 'auth' : user . firebase_auth_token } )
    headers . update ( self . authentication . authenticator . HEADERS )


signature:
def get ( self , url , name , params = None , headers = None , connection = None ) :
    """Synchronous GET request ."""

implementation:
if name is None :
    name = ''
params = params or { }
headers = headers or { }
endpoint = self . _build_endpoint_url ( url , name )
self . _authenticate ( params , headers )
return make_get_request ( endpoint , params , headers , connection = connection )


signature:
def get_async ( self , url , name , callback = None , params = None , headers = None ) :
    """Asynchronous GET request with the process pool ."""

implementation:
if name is None :
    name = ''
params = params or { }
headers = headers or { }
endpoint = self . _build_endpoint_url ( url , name )
self . _authenticate ( params , headers )
process_pool . apply_async ( make_get_request , args = ( endpoint , params , headers ) , callback = callback )


signature:
def put ( self , url , name , data , params = None , headers = None , connection = None ) :
    """Synchronous PUT request . There will be no returning output from
 the server , because the request will be made with ` ` silent ` `
 parameter . ` ` data ` ` must be a JSONable value ."""

implementation:
assert name , 'Snapshot name must be specified'
params = params or { }
headers = headers or { }
endpoint = self . _build_endpoint_url ( url , name )
self . _authenticate ( params , headers )
data = json . dumps ( data , cls = JSONEncoder )
return make_put_request ( endpoint , data , params , headers , connection = connection )


signature:
def put_async ( self , url , name , data , callback = None , params = None , headers = None ) :
    """Asynchronous PUT request with the process pool ."""

implementation:
if name is None :
    name = ''
params = params or { }
headers = headers or { }
endpoint = self . _build_endpoint_url ( url , name )
self . _authenticate ( params , headers )
data = json . dumps ( data , cls = JSONEncoder )
process_pool . apply_async ( make_put_request , args = ( endpoint , data , params , headers ) , callback = callback )


signature:
def post ( self , url , data , params = None , headers = None , connection = None ) :
    """Synchronous POST request . ` ` data ` ` must be a JSONable value ."""

implementation:
params = params or { }
headers = headers or { }
endpoint = self . _build_endpoint_url ( url , None )
self . _authenticate ( params , headers )
data = json . dumps ( data , cls = JSONEncoder )
return make_post_request ( endpoint , data , params , headers , connection = connection )


signature:
def post_async ( self , url , data , callback = None , params = None , headers = None ) :
    """Asynchronous POST request with the process pool ."""

implementation:
params = params or { }
headers = headers or { }
endpoint = self . _build_endpoint_url ( url , None )
self . _authenticate ( params , headers )
data = json . dumps ( data , cls = JSONEncoder )
process_pool . apply_async ( make_post_request , args = ( endpoint , data , params , headers ) , callback = callback )


signature:
def patch ( self , url , data , params = None , headers = None , connection = None ) :
    """Synchronous POST request . ` ` data ` ` must be a JSONable value ."""

implementation:
params = params or { }
headers = headers or { }
endpoint = self . _build_endpoint_url ( url , None )
self . _authenticate ( params , headers )
data = json . dumps ( data , cls = JSONEncoder )
return make_patch_request ( endpoint , data , params , headers , connection = connection )


signature:
def delete ( self , url , name , params = None , headers = None , connection = None ) :
    """Synchronous DELETE request . ` ` data ` ` must be a JSONable value ."""

implementation:
if not name :
    name = ''
params = params or { }
headers = headers or { }
endpoint = self . _build_endpoint_url ( url , name )
self . _authenticate ( params , headers )
return make_delete_request ( endpoint , params , headers , connection = connection )


signature:
def delete_async ( self , url , name , callback = None , params = None , headers = None ) :
    """Asynchronous DELETE request with the process pool ."""

implementation:
if not name :
    name = ''
params = params or { }
headers = headers or { }
endpoint = self . _build_endpoint_url ( url , name )
self . _authenticate ( params , headers )
process_pool . apply_async ( make_delete_request , args = ( endpoint , params , headers ) , callback = callback )


signature:
def do_filter ( qs , keywords , exclude = False ) :
    """Filter queryset based on keywords .
 Support for multiple - selected parent values ."""

implementation:
and_q = Q ( )
for keyword , value in iteritems ( keywords ) :
    try :
        values = value . split ( "," )
        if len ( values ) > 0 :
            or_q = Q ( )
            for value in values :
                or_q |= Q ( ** { keyword : value } )
            and_q &= or_q
    except AttributeError : # value can be a bool
        and_q &= Q ( ** { keyword : value } )
if exclude :
    qs = qs . exclude ( and_q )
else :
    qs = qs . filter ( and_q )
return qs


signature:
def filterchain_all ( request , app , model , field , foreign_key_app_name , foreign_key_model_name , foreign_key_field_name , value ) :
    """Returns filtered results followed by excluded results below ."""

implementation:
model_class = get_model ( app , model )
keywords = get_keywords ( field , value )
# SECURITY : Make sure all smart selects requests are opt - in
foreign_model_class = get_model ( foreign_key_app_name , foreign_key_model_name )
if not any ( [ ( isinstance ( f , ChainedManyToManyField ) or isinstance ( f , ChainedForeignKey ) ) for f in foreign_model_class . _meta . get_fields ( ) ] ) :
    raise PermissionDenied ( "Smart select disallowed" )
# filter queryset using limit _ choices _ to
limit_choices_to = get_limit_choices_to ( foreign_key_app_name , foreign_key_model_name , foreign_key_field_name )
queryset = get_queryset ( model_class , limit_choices_to = limit_choices_to )
filtered = list ( do_filter ( queryset , keywords ) )
# Sort results if model doesn ' t include a default ordering .
if not getattr ( model_class . _meta , 'ordering' , False ) :
    sort_results ( list ( filtered ) )
excluded = list ( do_filter ( queryset , keywords , exclude = True ) )
# Sort results if model doesn ' t include a default ordering .
if not getattr ( model_class . _meta , 'ordering' , False ) :
    sort_results ( list ( excluded ) )
# Empty choice to separate filtered and excluded results .
empty_choice = { 'value' : "" , 'display' : "---------" }
serialized_results = ( serialize_results ( filtered ) + [ empty_choice ] + serialize_results ( excluded ) )
return JsonResponse ( serialized_results , safe = False )


signature:
def media ( self ) :
    """Media defined as a dynamic property instead of an inner class ."""

implementation:
media = super ( JqueryMediaMixin , self ) . media
js = [ ]
if JQUERY_URL :
    js . append ( JQUERY_URL )
elif JQUERY_URL is not False :
    vendor = '' if django . VERSION < ( 1 , 9 , 0 ) else 'vendor/jquery/'
    extra = '' if settings . DEBUG else '.min'
    jquery_paths = [ '{}jquery{}.js' . format ( vendor , extra ) , 'jquery.init.js' , ]
    if USE_DJANGO_JQUERY :
        jquery_paths = [ 'admin/js/{}' . format ( path ) for path in jquery_paths ]
    js . extend ( jquery_paths )
media += Media ( js = js )
return media


implementation:
media = super ( ChainedSelect , self ) . media
js = [ 'smart-selects/admin/js/chainedfk.js' , 'smart-selects/admin/js/bindfields.js' ]
media += Media ( js = js )
return media


signature:
def _get_available_choices ( self , queryset , value ) :
    """get possible choices for selection"""

implementation:
item = queryset . filter ( pk = value ) . first ( )
if item :
    try :
        pk = getattr ( item , self . chained_model_field + "_id" )
        filter = { self . chained_model_field : pk }
    except AttributeError :
        try : # maybe m2m ?
            pks = getattr ( item , self . chained_model_field ) . all ( ) . values_list ( 'pk' , flat = True )
            filter = { self . chained_model_field + "__in" : pks }
        except AttributeError :
            try : # maybe a set ?
                pks = getattr ( item , self . chained_model_field + "_set" ) . all ( ) . values_list ( 'pk' , flat = True )
                filter = { self . chained_model_field + "__in" : pks }
            except AttributeError : # give up
                filter = { }
    filtered = list ( get_model ( self . to_app_name , self . to_model_name ) . objects . filter ( ** filter ) . distinct ( ) )
    if self . sort :
        sort_results ( filtered )
else : # invalid value for queryset
    filtered = [ ]
return filtered


implementation:
media = super ( ChainedSelectMultiple , self ) . media
js = [ 'smart-selects/admin/js/chainedm2m.js' , 'smart-selects/admin/js/bindfields.js' ]
if self . horizontal : # For horizontal mode add django filter horizontal javascript code
    js . extend ( [ "admin/js/core.js" , "admin/js/SelectBox.js" , "admin/js/SelectFilter2.js" ] )
media += Media ( js = js )
return media


signature:
def unicode_sorter ( input ) :
    """This function implements sort keys for the german language according to
 DIN 5007."""

implementation:
# key1 : compare words lowercase and replace umlauts according to DIN 5007
key1 = input . lower ( )
key1 = key1 . replace ( u"ä" , u"a" )
key1 = key1 . replace ( u"ö" , u"o" )
key1 = key1 . replace ( u"ü" , u"u" )
key1 = key1 . replace ( u"ß" , u"ss" )
# key2 : sort the lowercase word before the uppercase word and sort
# the word with umlaut after the word without umlaut
# key2 = input . swapcase ( )
# in case two words are the same according to key1 , sort the words
# according to key2.
return key1


signature:
def get_raw_record ( self , instance , update_fields = None ) :
    """Gets the raw record .
 If ` update _ fields ` is set , the raw record will be build with only
 the objectID and the given fields . Also , ` _ geoloc ` and ` _ tags ` will
 not be included ."""

implementation:
tmp = { 'objectID' : self . objectID ( instance ) }
if update_fields :
    if isinstance ( update_fields , str ) :
        update_fields = ( update_fields , )
    for elt in update_fields :
        key = self . __translate_fields . get ( elt , None )
        if key :
            tmp [ key ] = self . __named_fields [ key ] ( instance )
else :
    for key , value in self . __named_fields . items ( ) :
        tmp [ key ] = value ( instance )
    if self . geo_field :
        loc = self . geo_field ( instance )
        if isinstance ( loc , tuple ) :
            tmp [ '_geoloc' ] = { 'lat' : loc [ 0 ] , 'lng' : loc [ 1 ] }
        elif isinstance ( loc , dict ) :
            self . _validate_geolocation ( loc )
            tmp [ '_geoloc' ] = loc
        elif isinstance ( loc , list ) :
            [ self . _validate_geolocation ( geo ) for geo in loc ]
            tmp [ '_geoloc' ] = loc
    if self . tags :
        if callable ( self . tags ) :
            tmp [ '_tags' ] = self . tags ( instance )
        if not isinstance ( tmp [ '_tags' ] , list ) :
            tmp [ '_tags' ] = list ( tmp [ '_tags' ] )
logger . debug ( 'BUILD %s FROM %s' , tmp [ 'objectID' ] , self . model )
return tmp


signature:
def _should_really_index ( self , instance ) :
    """Return True if according to should _ index the object should be indexed ."""

implementation:
if self . _should_index_is_method :
    is_method = inspect . ismethod ( self . should_index )
    try :
        count_args = len ( inspect . signature ( self . should_index ) . parameters )
    except AttributeError : # noinspection PyDeprecation
        count_args = len ( inspect . getargspec ( self . should_index ) . args )
    if is_method or count_args is 1 : # bound method , call with instance
        return self . should_index ( instance )
    else : # unbound method , simply call without arguments
        return self . should_index ( )
else : # property / attribute / Field , evaluate as bool
    attr_type = type ( self . should_index )
    if attr_type is DeferredAttribute :
        attr_value = self . should_index . __get__ ( instance , None )
    elif attr_type is str :
        attr_value = getattr ( instance , self . should_index )
    elif attr_type is property :
        attr_value = self . should_index . __get__ ( instance )
    else :
        raise AlgoliaIndexError ( '{} should be a boolean attribute or a method that returns a boolean.' . format ( self . should_index ) )
    if type ( attr_value ) is not bool :
        raise AlgoliaIndexError ( "%s's should_index (%s) should be a boolean" % ( instance . __class__ . __name__ , self . should_index ) )
    return attr_value


signature:
def save_record ( self , instance , update_fields = None , ** kwargs ) :
    """Saves the record .
 If ` update _ fields ` is set , this method will use partial _ update _ object ( )
 and will update only the given fields ( never ` _ geoloc ` and ` _ tags ` ) .
 For more information about partial _ update _ object :
 https : / / github . com / algolia / algoliasearch - client - python # update - an - existing - object - in - the - index"""

implementation:
if not self . _should_index ( instance ) : # Should not index , but since we don ' t now the state of the
# instance , we need to send a DELETE request to ensure that if
# the instance was previously indexed , it will be removed .
    self . delete_record ( instance )
    return
try :
    if update_fields :
        obj = self . get_raw_record ( instance , update_fields = update_fields )
        result = self . __index . partial_update_object ( obj )
    else :
        obj = self . get_raw_record ( instance )
        result = self . __index . save_object ( obj )
    logger . info ( 'SAVE %s FROM %s' , obj [ 'objectID' ] , self . model )
    return result
except AlgoliaException as e :
    if DEBUG :
        raise e
    else :
        logger . warning ( '%s FROM %s NOT SAVED: %s' , obj [ 'objectID' ] , self . model , e )


signature:
def delete_record ( self , instance ) :
    """Deletes the record ."""

implementation:
objectID = self . objectID ( instance )
try :
    self . __index . delete_object ( objectID )
    logger . info ( 'DELETE %s FROM %s' , objectID , self . model )
except AlgoliaException as e :
    if DEBUG :
        raise e
    else :
        logger . warning ( '%s FROM %s NOT DELETED: %s' , objectID , self . model , e )


signature:
def update_records ( self , qs , batch_size = 1000 , ** kwargs ) :
    """Updates multiple records .
 This method is optimized for speed . It takes a QuerySet and the same
 arguments as QuerySet . update ( ) . Optionnaly , you can specify the size
 of the batch send to Algolia with batch _ size ( default to 1000 ) .
 > > > from algoliasearch _ django import update _ records
 > > > qs = MyModel . objects . filter ( myField = False )
 > > > update _ records ( MyModel , qs , myField = True )
 > > > qs . update ( myField = True )"""

implementation:
tmp = { }
for key , value in kwargs . items ( ) :
    name = self . __translate_fields . get ( key , None )
    if name :
        tmp [ name ] = value
batch = [ ]
objectsIDs = qs . only ( self . custom_objectID ) . values_list ( self . custom_objectID , flat = True )
for elt in objectsIDs :
    tmp [ 'objectID' ] = elt
    batch . append ( dict ( tmp ) )
    if len ( batch ) >= batch_size :
        self . __index . partial_update_objects ( batch )
        batch = [ ]
if len ( batch ) > 0 :
    self . __index . partial_update_objects ( batch )


signature:
def raw_search ( self , query = '' , params = None ) :
    """Performs a search query and returns the parsed JSON ."""

implementation:
if params is None :
    params = { }
try :
    return self . __index . search ( query , params )
except AlgoliaException as e :
    if DEBUG :
        raise e
    else :
        logger . warning ( 'ERROR DURING SEARCH ON %s: %s' , self . index_name , e )


signature:
def get_settings ( self ) :
    """Returns the settings of the index ."""

implementation:
try :
    logger . info ( 'GET SETTINGS ON %s' , self . index_name )
    return self . __index . get_settings ( )
except AlgoliaException as e :
    if DEBUG :
        raise e
    else :
        logger . warning ( 'ERROR DURING GET_SETTINGS ON %s: %s' , self . model , e )


signature:
def set_settings ( self ) :
    """Applies the settings to the index ."""

implementation:
if not self . settings :
    return
try :
    self . __index . set_settings ( self . settings )
    logger . info ( 'APPLY SETTINGS ON %s' , self . index_name )
except AlgoliaException as e :
    if DEBUG :
        raise e
    else :
        logger . warning ( 'SETTINGS NOT APPLIED ON %s: %s' , self . model , e )


signature:
def reindex_all ( self , batch_size = 1000 ) :
    """Reindex all the records .
 By default , this method use Model . objects . all ( ) but you can implement
 a method ` get _ queryset ` in your subclass . This can be used to optimize
 the performance ( for example with select _ related or prefetch _ related ) ."""

implementation:
should_keep_synonyms = False
should_keep_rules = False
try :
    if not self . settings :
        self . settings = self . get_settings ( )
        logger . debug ( 'Got settings for index %s: %s' , self . index_name , self . settings )
    else :
        logger . debug ( "index %s already has settings: %s" , self . index_name , self . settings )
except AlgoliaException as e :
    if any ( "Index does not exist" in arg for arg in e . args ) :
        pass
        # Expected , let ' s clear and recreate from scratch
    else :
        raise e
        # Unexpected error while getting settings
try :
    if self . settings :
        replicas = self . settings . get ( 'replicas' , None )
        slaves = self . settings . get ( 'slaves' , None )
        should_keep_replicas = replicas is not None
        should_keep_slaves = slaves is not None
        if should_keep_replicas :
            self . settings [ 'replicas' ] = [ ]
            logger . debug ( "REMOVE REPLICAS FROM SETTINGS" )
        if should_keep_slaves :
            self . settings [ 'slaves' ] = [ ]
            logger . debug ( "REMOVE SLAVES FROM SETTINGS" )
        self . __tmp_index . wait_task ( self . __tmp_index . set_settings ( self . settings ) [ 'taskID' ] )
        logger . debug ( 'APPLY SETTINGS ON %s_tmp' , self . index_name )
    rules = [ ]
    synonyms = [ ]
    for r in self . __index . iter_rules ( ) :
        rules . append ( r )
    for s in self . __index . iter_synonyms ( ) :
        synonyms . append ( s )
    if len ( rules ) :
        logger . debug ( 'Got rules for index %s: %s' , self . index_name , rules )
        should_keep_rules = True
    if len ( synonyms ) :
        logger . debug ( 'Got synonyms for index %s: %s' , self . index_name , rules )
        should_keep_synonyms = True
    self . __tmp_index . clear_index ( )
    logger . debug ( 'CLEAR INDEX %s_tmp' , self . index_name )
    counts = 0
    batch = [ ]
    if hasattr ( self , 'get_queryset' ) :
        qs = self . get_queryset ( )
    else :
        qs = self . model . objects . all ( )
    for instance in qs :
        if not self . _should_index ( instance ) :
            continue
        # should not index
        batch . append ( self . get_raw_record ( instance ) )
        if len ( batch ) >= batch_size :
            self . __tmp_index . save_objects ( batch )
            logger . info ( 'SAVE %d OBJECTS TO %s_tmp' , len ( batch ) , self . index_name )
            batch = [ ]
        counts += 1
    if len ( batch ) > 0 :
        self . __tmp_index . save_objects ( batch )
        logger . info ( 'SAVE %d OBJECTS TO %s_tmp' , len ( batch ) , self . index_name )
    self . __client . move_index ( self . __tmp_index . index_name , self . __index . index_name )
    logger . info ( 'MOVE INDEX %s_tmp TO %s' , self . index_name , self . index_name )
    if self . settings :
        if should_keep_replicas :
            self . settings [ 'replicas' ] = replicas
            logger . debug ( "RESTORE REPLICAS" )
        if should_keep_slaves :
            self . settings [ 'slaves' ] = slaves
            logger . debug ( "RESTORE SLAVES" )
        if should_keep_replicas or should_keep_slaves :
            self . __index . set_settings ( self . settings )
        if should_keep_rules :
            response = self . __index . batch_rules ( rules , forward_to_replicas = True )
            self . __index . wait_task ( response [ 'taskID' ] )
            logger . info ( "Saved rules for index %s with response: {}" . format ( response ) , self . index_name )
        if should_keep_synonyms :
            response = self . __index . batch_synonyms ( synonyms , forward_to_replicas = True )
            self . __index . wait_task ( response [ 'taskID' ] )
            logger . info ( "Saved synonyms for index %s with response: {}" . format ( response ) , self . index_name )
    return counts
except AlgoliaException as e :
    if DEBUG :
        raise e
    else :
        logger . warning ( 'ERROR DURING REINDEXING %s: %s' , self . model , e )


signature:
def register ( model ) :
    """Register the given model class and wrapped AlgoliaIndex class with the Algolia engine :
 @ register ( Author )
 class AuthorIndex ( AlgoliaIndex ) :
 pass"""

implementation:
from algoliasearch_django import AlgoliaIndex , register
def _algolia_engine_wrapper ( index_class ) :
    if not issubclass ( index_class , AlgoliaIndex ) :
        raise ValueError ( 'Wrapped class must subclass AlgoliaIndex.' )
    register ( model , index_class )
    return index_class
return _algolia_engine_wrapper


signature:
def handle ( self , * args , ** options ) :
    """Run the management command ."""

implementation:
self . stdout . write ( 'Apply settings to index:' )
for model in get_registered_model ( ) :
    if options . get ( 'model' , None ) and not ( model . __name__ in options [ 'model' ] ) :
        continue
    get_adapter ( model ) . set_settings ( )
    self . stdout . write ( '\t* {}' . format ( model . __name__ ) )


signature:
def register ( self , model , index_cls = AlgoliaIndex , auto_indexing = None ) :
    """Registers the given model with Algolia engine .
 If the given model is already registered with Algolia engine , a
 RegistrationError will be raised ."""

implementation:
# Check for existing registration .
if self . is_registered ( model ) :
    raise RegistrationError ( '{} is already registered with Algolia engine' . format ( model ) )
# Perform the registration .
if not issubclass ( index_cls , AlgoliaIndex ) :
    raise RegistrationError ( '{} should be a subclass of AlgoliaIndex' . format ( index_cls ) )
index_obj = index_cls ( model , self . client , self . __settings )
self . __registered_models [ model ] = index_obj
if ( isinstance ( auto_indexing , bool ) and auto_indexing ) or self . __auto_indexing : # Connect to the signalling framework .
    post_save . connect ( self . __post_save_receiver , model )
    pre_delete . connect ( self . __pre_delete_receiver , model )
    logger . info ( 'REGISTER %s' , model )


signature:
def unregister ( self , model ) :
    """Unregisters the given model with Algolia engine .
 If the given model is not registered with Algolia engine , a
 RegistrationError will be raised ."""

implementation:
if not self . is_registered ( model ) :
    raise RegistrationError ( '{} is not registered with Algolia engine' . format ( model ) )
# Perform the unregistration .
del self . __registered_models [ model ]
# Disconnect from the signalling framework .
post_save . disconnect ( self . __post_save_receiver , model )
pre_delete . disconnect ( self . __pre_delete_receiver , model )
logger . info ( 'UNREGISTER %s' , model )


signature:
def get_adapter ( self , model ) :
    """Returns the adapter associated with the given model ."""

implementation:
if not self . is_registered ( model ) :
    raise RegistrationError ( '{} is not registered with Algolia engine' . format ( model ) )
return self . __registered_models [ model ]


signature:
def save_record ( self , instance , ** kwargs ) :
    """Saves the record .
 If ` update _ fields ` is set , this method will use partial _ update _ object ( )
 and will update only the given fields ( never ` _ geoloc ` and ` _ tags ` ) .
 For more information about partial _ update _ object :
 https : / / github . com / algolia / algoliasearch - client - python # update - an - existing - object - in - the - index"""

implementation:
adapter = self . get_adapter_from_instance ( instance )
adapter . save_record ( instance , ** kwargs )


implementation:
adapter = self . get_adapter_from_instance ( instance )
adapter . delete_record ( instance )


signature:
def update_records ( self , model , qs , batch_size = 1000 , ** kwargs ) :
    """Updates multiple records .
 This method is optimized for speed . It takes a QuerySet and the same
 arguments as QuerySet . update ( ) . Optionally , you can specify the size
 of the batch send to Algolia with batch _ size ( default to 1000 ) .
 > > > from algoliasearch _ django import update _ records
 > > > qs = MyModel . objects . filter ( myField = False )
 > > > update _ records ( MyModel , qs , myField = True )
 > > > qs . update ( myField = True )"""

implementation:
adapter = self . get_adapter ( model )
adapter . update_records ( qs , batch_size = batch_size , ** kwargs )


signature:
def raw_search ( self , model , query = '' , params = None ) :
    """Performs a search query and returns the parsed JSON ."""

implementation:
if params is None :
    params = { }
adapter = self . get_adapter ( model )
return adapter . raw_search ( query , params )


signature:
def reindex_all ( self , model , batch_size = 1000 ) :
    """Reindex all the records .
 By default , this method use Model . objects . all ( ) but you can implement
 a method ` get _ queryset ` in your subclass . This can be used to optimize
 the performance ( for example with select _ related or prefetch _ related ) ."""

implementation:
adapter = self . get_adapter ( model )
return adapter . reindex_all ( batch_size )


signature:
def __post_save_receiver ( self , instance , ** kwargs ) :
    """Signal handler for when a registered model has been saved ."""

implementation:
logger . debug ( 'RECEIVE post_save FOR %s' , instance . __class__ )
self . save_record ( instance , ** kwargs )


signature:
def __pre_delete_receiver ( self , instance , ** kwargs ) :
    """Signal handler for when a registered model has been deleted ."""

implementation:
logger . debug ( 'RECEIVE pre_delete FOR %s' , instance . __class__ )
self . delete_record ( instance )


implementation:
batch_size = options . get ( 'batchsize' , None )
if not batch_size : # py34 - django18 : batchsize is set to None if the user don ' t set
# the value , instead of not be present in the dict
    batch_size = 1000
self . stdout . write ( 'The following models were reindexed:' )
for model in get_registered_model ( ) :
    if options . get ( 'model' , None ) and not ( model . __name__ in options [ 'model' ] ) :
        continue
    counts = reindex_all ( model , batch_size = batch_size )
    self . stdout . write ( '\t* {} --> {}' . format ( model . __name__ , counts ) )


implementation:
self . stdout . write ( 'Clear index:' )
for model in get_registered_model ( ) :
    if options . get ( 'model' , None ) and not ( model . __name__ in options [ 'model' ] ) :
        continue
    clear_index ( model )
    self . stdout . write ( '\t* {}' . format ( model . __name__ ) )


signature:
def decode_exactly ( geohash ) :
    """Decode the geohash to its exact values , including the error
 margins of the result . Returns four float values : latitude ,
 longitude , the plus / minus error for latitude ( as a positive
 number ) and the plus / minus error for longitude ( as a positive
 number ) ."""

implementation:
lat_interval , lon_interval = ( - 90.0 , 90.0 ) , ( - 180.0 , 180.0 )
lat_err , lon_err = 90.0 , 180.0
is_even = True
for c in geohash :
    cd = __decodemap [ c ]
    for mask in [ 16 , 8 , 4 , 2 , 1 ] :
        if is_even : # adds longitude info
            lon_err /= 2
            if cd & mask :
                lon_interval = ( ( lon_interval [ 0 ] + lon_interval [ 1 ] ) / 2 , lon_interval [ 1 ] )
            else :
                lon_interval = ( lon_interval [ 0 ] , ( lon_interval [ 0 ] + lon_interval [ 1 ] ) / 2 )
        else : # adds latitude info
            lat_err /= 2
            if cd & mask :
                lat_interval = ( ( lat_interval [ 0 ] + lat_interval [ 1 ] ) / 2 , lat_interval [ 1 ] )
            else :
                lat_interval = ( lat_interval [ 0 ] , ( lat_interval [ 0 ] + lat_interval [ 1 ] ) / 2 )
        is_even = not is_even
lat = ( lat_interval [ 0 ] + lat_interval [ 1 ] ) / 2
lon = ( lon_interval [ 0 ] + lon_interval [ 1 ] ) / 2
return lat , lon , lat_err , lon_err


signature:
def decode ( geohash ) :
    """Decode geohash , returning two strings with latitude and longitude
 containing only relevant digits and with trailing zeroes removed ."""

implementation:
lat , lon , lat_err , lon_err = decode_exactly ( geohash )
# Format to the number of decimals that are known
lats = "%.*f" % ( max ( 1 , int ( round ( - log10 ( lat_err ) ) ) ) - 1 , lat )
lons = "%.*f" % ( max ( 1 , int ( round ( - log10 ( lon_err ) ) ) ) - 1 , lon )
if '.' in lats :
    lats = lats . rstrip ( '0' )
if '.' in lons :
    lons = lons . rstrip ( '0' )
return lats , lons


signature:
def encode ( latitude , longitude , precision = 12 ) :
    """Encode a position given in float arguments latitude , longitude to
 a geohash which will have the character count precision ."""

implementation:
lat_interval , lon_interval = ( - 90.0 , 90.0 ) , ( - 180.0 , 180.0 )
geohash = [ ]
bits = [ 16 , 8 , 4 , 2 , 1 ]
bit = 0
ch = 0
even = True
while len ( geohash ) < precision :
    if even :
        mid = ( lon_interval [ 0 ] + lon_interval [ 1 ] ) / 2
        if longitude > mid :
            ch |= bits [ bit ]
            lon_interval = ( mid , lon_interval [ 1 ] )
        else :
            lon_interval = ( lon_interval [ 0 ] , mid )
    else :
        mid = ( lat_interval [ 0 ] + lat_interval [ 1 ] ) / 2
        if latitude > mid :
            ch |= bits [ bit ]
            lat_interval = ( mid , lat_interval [ 1 ] )
        else :
            lat_interval = ( lat_interval [ 0 ] , mid )
    even = not even
    if bit < 4 :
        bit += 1
    else :
        geohash += __base32 [ ch ]
        bit = 0
        ch = 0
return '' . join ( geohash )


signature:
def pad_to ( unpadded , target_len ) :
    """Pad a string to the target length in characters , or return the original
 string if it ' s longer than the target length ."""

implementation:
under = target_len - len ( unpadded )
if under <= 0 :
    return unpadded
return unpadded + ( ' ' * under )


signature:
def normalize_cols ( table ) :
    """Pad short rows to the length of the longest row to help render " jagged "
 CSV files"""

implementation:
longest_row_len = max ( [ len ( row ) for row in table ] )
for row in table :
    while len ( row ) < longest_row_len :
        row . append ( '' )
return table


signature:
def pad_cells ( table ) :
    """Pad each cell to the size of the largest cell in its column ."""

implementation:
col_sizes = [ max ( map ( len , col ) ) for col in zip ( * table ) ]
for row in table :
    for cell_num , cell in enumerate ( row ) :
        row [ cell_num ] = pad_to ( cell , col_sizes [ cell_num ] )
return table


signature:
def horiz_div ( col_widths , horiz , vert , padding ) :
    """Create the column dividers for a table with given column widths .
 col _ widths : list of column widths
 horiz : the character to use for a horizontal divider
 vert : the character to use for a vertical divider
 padding : amount of padding to add to each side of a column"""

implementation:
horizs = [ horiz * w for w in col_widths ]
div = '' . join ( [ padding * horiz , vert , padding * horiz ] )
return div . join ( horizs )


signature:
def add_dividers ( row , divider , padding ) :
    """Add dividers and padding to a row of cells and return a string ."""

implementation:
div = '' . join ( [ padding * ' ' , divider , padding * ' ' ] )
return div . join ( row )


signature:
def md_table ( table , * , padding = DEFAULT_PADDING , divider = '|' , header_div = '-' ) :
    """Convert a 2D array of items into a Markdown table .
 padding : the number of padding spaces on either side of each divider
 divider : the vertical divider to place between columns
 header _ div : the horizontal divider to place between the header row and
 body cells"""

implementation:
table = normalize_cols ( table )
table = pad_cells ( table )
header = table [ 0 ]
body = table [ 1 : ]
col_widths = [ len ( cell ) for cell in header ]
horiz = horiz_div ( col_widths , header_div , divider , padding )
header = add_dividers ( header , divider , padding )
body = [ add_dividers ( row , divider , padding ) for row in body ]
table = [ header , horiz ]
table . extend ( body )
table = [ row . rstrip ( ) for row in table ]
return '\n' . join ( table )


signature:
def baseId ( resource_id , return_version = False ) :
    """Calculate base id and version from a resource id .
 : params resource _ id : Resource id .
 : params return _ version : ( optional ) True if You need version , returns ( resource _ id , version ) ."""

implementation:
version = 0
resource_id = resource_id + 0xC4000000
# 3288334336
# TODO : version is broken due ^ ^ , needs refactoring
while resource_id > 0x01000000 : # 16777216
    version += 1
    if version == 1 :
        resource_id -= 0x80000000
        # 2147483648 # 0x500000 # 1342177280 ? | | 0x200000 # 33554432
    elif version == 2 :
        resource_id -= 0x03000000
        # 50331648
    else :
        resource_id -= 0x01000000
# 16777216
if return_version :
    return resource_id , version - 67
# just correct " magic number "
return resource_id


signature:
def itemParse ( item_data , full = True ) :
    """Parser for item data . Returns nice dictionary .
 : params item _ data : Item data received from ea servers .
 : params full : ( optional ) False if you ' re sniping and don ' t need extended info . Anyone really use this ?"""

implementation:
# TODO : object
# TODO : dynamically parse all data
# TODO : make it less ugly
# ItemRareType = { NONE : 0 , RARE : 1 , LOCK : 2 , TOTW : 3 , PURPLE : 4 , TOTY : 5 , RB : 6 , GREEN : 7 , ORANGE : 8 , PINK : 9 , TEAL : 10 , TOTS : 11 , LEGEND : 12 , WC : 13 , UNICEF : 14 , OLDIMOTM : 15 , FUTTY : 16 , STORYMODE : 17 , CHAMPION : 18 , CMOTM : 19 , IMOTM : 20 , OTW : 21 , HALLOWEEN : 22 , MOVEMBER : 23 , SBC : 24 , SBCP : 25 , PROMOA : 26 , PROMOB : 27 , AWARD : 28 , BDAY : 30 , UNITED : 31 , FUTMAS : 32 , RTRC : 33 , PTGS : 34 , FOF : 35 , MARQUEE : 36 , CHAMPIONSHIP : 37 , EUMOTM : 38 , TOTT : 39 , RRC : 40 , RRR : 41}
return_data = { 'tradeId' : item_data . get ( 'tradeId' ) , 'buyNowPrice' : item_data . get ( 'buyNowPrice' ) , 'tradeState' : item_data . get ( 'tradeState' ) , 'bidState' : item_data . get ( 'bidState' ) , 'startingBid' : item_data . get ( 'startingBid' ) , 'id' : item_data . get ( 'itemData' , { 'id' : None } ) [ 'id' ] or item_data . get ( 'item' , { 'id' : None } ) [ 'id' ] , 'offers' : item_data . get ( 'offers' ) , 'currentBid' : item_data . get ( 'currentBid' ) , 'expires' : item_data . get ( 'expires' ) , # seconds left
'sellerEstablished' : item_data . get ( 'sellerEstablished' ) , 'sellerId' : item_data . get ( 'sellerId' ) , 'sellerName' : item_data . get ( 'sellerName' ) , 'watched' : item_data . get ( 'watched' ) , 'resourceId' : item_data . get ( 'resourceId' ) , # consumables only ?
'discardValue' : item_data . get ( 'discardValue' ) , # consumables only ?
}
if full :
    if 'itemData' in item_data :
        return_data . update ( { 'timestamp' : item_data [ 'itemData' ] . get ( 'timestamp' ) , # auction start
        'rating' : item_data [ 'itemData' ] . get ( 'rating' ) , 'assetId' : item_data [ 'itemData' ] . get ( 'assetId' ) , 'resourceId' : item_data [ 'itemData' ] . get ( 'resourceId' ) , 'itemState' : item_data [ 'itemData' ] . get ( 'itemState' ) , 'rareflag' : item_data [ 'itemData' ] . get ( 'rareflag' ) , 'formation' : item_data [ 'itemData' ] . get ( 'formation' ) , 'leagueId' : item_data [ 'itemData' ] . get ( 'leagueId' ) , 'injuryType' : item_data [ 'itemData' ] . get ( 'injuryType' ) , 'injuryGames' : item_data [ 'itemData' ] . get ( 'injuryGames' ) , 'lastSalePrice' : item_data [ 'itemData' ] . get ( 'lastSalePrice' ) , 'fitness' : item_data [ 'itemData' ] . get ( 'fitness' ) , 'training' : item_data [ 'itemData' ] . get ( 'training' ) , 'suspension' : item_data [ 'itemData' ] . get ( 'suspension' ) , 'contract' : item_data [ 'itemData' ] . get ( 'contract' ) , 'position' : item_data [ 'itemData' ] . get ( 'preferredPosition' ) , 'playStyle' : item_data [ 'itemData' ] . get ( 'playStyle' ) , # used only for players
        'discardValue' : item_data [ 'itemData' ] . get ( 'discardValue' ) , 'itemType' : item_data [ 'itemData' ] . get ( 'itemType' ) , 'cardType' : item_data [ 'itemData' ] . get ( 'cardsubtypeid' ) , # alias
        'cardsubtypeid' : item_data [ 'itemData' ] . get ( 'cardsubtypeid' ) , # used only for cards
        'owners' : item_data [ 'itemData' ] . get ( 'owners' ) , 'untradeable' : item_data [ 'itemData' ] . get ( 'untradeable' ) , 'morale' : item_data [ 'itemData' ] . get ( 'morale' ) , 'statsList' : item_data [ 'itemData' ] . get ( 'statsList' ) , # what is this ?
        'lifetimeStats' : item_data [ 'itemData' ] . get ( 'lifetimeStats' ) , 'attributeList' : item_data [ 'itemData' ] . get ( 'attributeList' ) , 'teamid' : item_data [ 'itemData' ] . get ( 'teamid' ) , 'assists' : item_data [ 'itemData' ] . get ( 'assists' ) , 'lifetimeAssists' : item_data [ 'itemData' ] . get ( 'lifetimeAssists' ) , 'loyaltyBonus' : item_data [ 'itemData' ] . get ( 'loyaltyBonus' ) , 'pile' : item_data [ 'itemData' ] . get ( 'pile' ) , 'nation' : item_data [ 'itemData' ] . get ( 'nation' ) , # nation _ id ?
        'year' : item_data [ 'itemData' ] . get ( 'resourceGameYear' ) , # alias
        'resourceGameYear' : item_data [ 'itemData' ] . get ( 'resourceGameYear' ) , 'marketDataMinPrice' : item_data [ 'itemData' ] . get ( 'marketDataMinPrice' ) , 'marketDataMaxPrice' : item_data [ 'itemData' ] . get ( 'marketDataMaxPrice' ) , 'loans' : item_data . get ( 'loans' ) , } )
    elif 'item' in item_data : # consumables only ( ? )
        return_data . update ( { 'cardassetid' : item_data [ 'item' ] . get ( 'cardassetid' ) , 'weightrare' : item_data [ 'item' ] . get ( 'weightrare' ) , 'gold' : item_data [ 'item' ] . get ( 'gold' ) , 'silver' : item_data [ 'item' ] . get ( 'silver' ) , 'bronze' : item_data [ 'item' ] . get ( 'bronze' ) , 'consumablesContractPlayer' : item_data [ 'item' ] . get ( 'consumablesContractPlayer' ) , 'consumablesContractManager' : item_data [ 'item' ] . get ( 'consumablesContractManager' ) , 'consumablesFormationPlayer' : item_data [ 'item' ] . get ( 'consumablesFormationPlayer' ) , 'consumablesFormationManager' : item_data [ 'item' ] . get ( 'consumablesFormationManager' ) , 'consumablesPosition' : item_data [ 'item' ] . get ( 'consumablesPosition' ) , 'consumablesTraining' : item_data [ 'item' ] . get ( 'consumablesTraining' ) , 'consumablesTrainingPlayer' : item_data [ 'item' ] . get ( 'consumablesTrainingPlayer' ) , 'consumablesTrainingManager' : item_data [ 'item' ] . get ( 'consumablesTrainingManager' ) , 'consumablesTrainingGk' : item_data [ 'item' ] . get ( 'consumablesTrainingGk' ) , 'consumablesTrainingPlayerPlayStyle' : item_data [ 'item' ] . get ( 'consumablesTrainingPlayerPlayStyle' ) , 'consumablesTrainingGkPlayStyle' : item_data [ 'item' ] . get ( 'consumablesTrainingGkPlayStyle' ) , 'consumablesTrainingManagerLeagueModifier' : item_data [ 'item' ] . get ( 'consumablesTrainingManagerLeagueModifier' ) , 'consumablesHealing' : item_data [ 'item' ] . get ( 'consumablesHealing' ) , 'consumablesTeamTalksPlayer' : item_data [ 'item' ] . get ( 'consumablesTeamTalksPlayer' ) , 'consumablesTeamTalksTeam' : item_data [ 'item' ] . get ( 'consumablesTeamTalksTeam' ) , 'consumablesFitnessPlayer' : item_data [ 'item' ] . get ( 'consumablesFitnessPlayer' ) , 'consumablesFitnessTeam' : item_data [ 'item' ] . get ( 'consumablesFitnessTeam' ) , 'consumables' : item_data [ 'item' ] . get ( 'consumables' ) , 'count' : item_data . get ( 'count' ) , # consumables only ( ? )
        'untradeableCount' : item_data . get ( 'untradeableCount' ) , # consumables only ( ? )
        } )
return return_data


signature:
def nations ( timeout = timeout ) :
    """Return all nations in dict { id0 : nation0 , id1 : nation1 } .
 : params year : Year ."""

implementation:
rc = requests . get ( messages_url , timeout = timeout )
rc . encoding = 'utf-8'
# guessing takes huge amount of cpu time
rc = rc . text
data = re . findall ( '"search.nationName.nation([0-9]+)": "(.+)"' , rc )
nations = { }
for i in data :
    nations [ int ( i [ 0 ] ) ] = i [ 1 ]
return nations


signature:
def players ( timeout = timeout ) :
    """Return all players in dict { id : c , f , l , n , r } .
 id , rank , nationality ( ? ) , first name , last name ."""

implementation:
rc = requests . get ( '{0}{1}.json' . format ( card_info_url , 'players' ) , timeout = timeout ) . json ( )
players = { }
for i in rc [ 'Players' ] + rc [ 'LegendsPlayers' ] :
    players [ i [ 'id' ] ] = { 'id' : i [ 'id' ] , 'firstname' : i [ 'f' ] , 'lastname' : i [ 'l' ] , 'surname' : i . get ( 'c' ) , 'rating' : i [ 'r' ] }
return players


signature:
def playstyles ( year = 2019 , timeout = timeout ) :
    """Return all playstyles in dict { id0 : playstyle0 , id1 : playstyle1 } .
 : params year : Year ."""

implementation:
rc = requests . get ( messages_url , timeout = timeout )
rc . encoding = 'utf-8'
# guessing takes huge amount of cpu time
rc = rc . text
data = re . findall ( '"playstyles.%s.playstyle([0-9]+)": "(.+)"' % year , rc )
playstyles = { }
for i in data :
    playstyles [ int ( i [ 0 ] ) ] = i [ 1 ]
return playstyles


signature:
def logout ( self , save = True ) :
    """Log out nicely ( like clicking on logout button ) .
 : params save : False if You don ' t want to save cookies ."""

implementation:
# self . r . get ( ' https : / / www . easports . com / signout ' , params = { ' ct ' : self . _ } )
# self . r . get ( ' https : / / accounts . ea . com / connect / clearsid ' , params = { ' ct ' : self . _ } )
# self . r . get ( ' https : / / beta . www . origin . com / views / logout . html ' , params = { ' ct ' : self . _ } )
# self . r . get ( ' https : / / help . ea . com / community / logout / ' , params = { ' ct ' : self . _ } )
self . r . delete ( 'https://%s/ut/auth' % self . fut_host , timeout = self . timeout )
if save :
    self . saveSession ( )
# needed ? https : / / accounts . ea . com / connect / logout ? client _ id = FIFA - 18 - WEBCLIENT & redirect _ uri = https : / / www . easports . com / fifa / ultimate - team / web - app / auth . html
return True


signature:
def playstyles ( self , year = 2019 ) :
    """Return all playstyles in dict { id0 : playstyle0 , id1 : playstyle1 } .
 : params year : Year ."""

implementation:
if not self . _playstyles :
    self . _playstyles = playstyles ( )
return self . _playstyles


signature:
def leagues ( self , year = 2019 ) :
    """Return all leagues in dict { id0 : league0 , id1 : league1 } .
 : params year : Year ."""

implementation:
if year not in self . _leagues :
    self . _leagues [ year ] = leagues ( year )
return self . _leagues [ year ]


signature:
def teams ( self , year = 2019 ) :
    """Return all teams in dict { id0 : team0 , id1 : team1 } .
 : params year : Year ."""

implementation:
if year not in self . _teams :
    self . _teams [ year ] = teams ( year )
return self . _teams [ year ]


signature:
def saveSession ( self ) :
    """Save cookies / session ."""

implementation:
if self . cookies_file :
    self . r . cookies . save ( ignore_discard = True )
    with open ( self . token_file , 'w' ) as f :
        f . write ( '%s %s' % ( self . token_type , self . access_token ) )


signature:
def cardInfo ( self , resource_id ) :
    """Return card info .
 : params resource _ id : Resource id ."""

implementation:
# TODO : add referer to headers ( futweb )
base_id = baseId ( resource_id )
if base_id in self . players :
    return self . players [ base_id ]
else : # not a player ?
    url = '{0}{1}.json' . format ( card_info_url , base_id )
    return requests . get ( url , timeout = self . timeout ) . json ( )


signature:
def searchDefinition ( self , asset_id , start = 0 , page_size = itemsPerPage [ 'transferMarket' ] , count = None ) :
    """Return variations of the given asset id , e . g . IF cards .
 : param asset _ id : Asset id / Definition id .
 : param start : ( optional ) Start page .
 : param count : ( optional ) Number of definitions you want to request ."""

implementation:
method = 'GET'
url = 'defid'
if count : # backward compatibility , will be removed in future
    page_size = count
base_id = baseId ( asset_id )
if base_id not in self . players :
    raise FutError ( reason = 'Invalid player asset/definition id.' )
params = { 'defId' : base_id , 'start' : start , 'type' : 'player' , 'count' : page_size }
rc = self . __request__ ( method , url , params = params )
# try :
# return [ itemParse ( { ' itemData ' : i } ) for i in rc [ ' itemData ' ] ]
# except :
# raise UnknownError ( ' Invalid definition response ' )
return [ itemParse ( { 'itemData' : i } ) for i in rc [ 'itemData' ] ]


signature:
def search ( self , ctype , level = None , category = None , assetId = None , defId = None , min_price = None , max_price = None , min_buy = None , max_buy = None , league = None , club = None , position = None , zone = None , nationality = None , rare = False , playStyle = None , start = 0 , page_size = itemsPerPage [ 'transferMarket' ] , fast = False ) :
    """Prepare search request , send and return parsed data as a dict .
 : param ctype : [ development / ? / ? ] Card type .
 : param level : ( optional ) [ ? / ? / gold ] Card level .
 : param category : ( optional ) [ fitness / ? / ? ] Card category .
 : param assetId : ( optional ) Asset id .
 : param defId : ( optional ) Definition id .
 : param min _ price : ( optional ) Minimal price .
 : param max _ price : ( optional ) Maximum price .
 : param min _ buy : ( optional ) Minimal buy now price .
 : param max _ buy : ( optional ) Maximum buy now price .
 : param league : ( optional ) League id .
 : param club : ( optional ) Club id .
 : param position : ( optional ) Position .
 : param nationality : ( optional ) Nation id .
 : param rare : ( optional ) [ boolean ] True for searching special cards .
 : param playStyle : ( optional ) Play style .
 : param start : ( optional ) Start page sent to server so it supposed to be 12/15 , 24/30 etc . ( default platform page _ size * n )
 : param page _ size : ( optional ) Page size ( items per page ) ."""

implementation:
# TODO : add " search " alias
# TODO : generator
method = 'GET'
url = 'transfermarket'
# pinEvents
if start == 0 :
    events = [ self . pin . event ( 'page_view' , 'Hub - Transfers' ) , self . pin . event ( 'page_view' , 'Transfer Market Search' ) ]
    self . pin . send ( events , fast = fast )
params = { 'start' : start , 'num' : page_size , 'type' : ctype , # " type " namespace is reserved in python
}
if level :
    params [ 'lev' ] = level
if category :
    params [ 'cat' ] = category
if assetId :
    params [ 'maskedDefId' ] = assetId
if defId :
    params [ 'definitionId' ] = defId
if min_price :
    params [ 'micr' ] = min_price
if max_price :
    params [ 'macr' ] = max_price
if min_buy :
    params [ 'minb' ] = min_buy
if max_buy :
    params [ 'maxb' ] = max_buy
if league :
    params [ 'leag' ] = league
if club :
    params [ 'team' ] = club
if position :
    params [ 'pos' ] = position
if zone :
    params [ 'zone' ] = zone
if nationality :
    params [ 'nat' ] = nationality
if rare :
    params [ 'rare' ] = 'SP'
if playStyle :
    params [ 'playStyle' ] = playStyle
rc = self . __request__ ( method , url , params = params , fast = fast )
# pinEvents
if start == 0 :
    events = [ self . pin . event ( 'page_view' , 'Transfer Market Results - List View' ) , self . pin . event ( 'page_view' , 'Item - Detail View' ) ]
    self . pin . send ( events , fast = fast )
return [ itemParse ( i ) for i in rc . get ( 'auctionInfo' , ( ) ) ]


signature:
def bid ( self , trade_id , bid , fast = False ) :
    """Make a bid .
 : params trade _ id : Trade id .
 : params bid : Amount of credits You want to spend .
 : params fast : True for fastest bidding ( skips trade status & credits check ) ."""

implementation:
method = 'PUT'
url = 'trade/%s/bid' % trade_id
if not fast :
    rc = self . tradeStatus ( trade_id ) [ 0 ]
    # don ' t bid if current bid is equal or greater than our max bid
    if rc [ 'currentBid' ] >= bid or self . credits < bid :
        return False
        # TODO : add exceptions
data = { 'bid' : bid }
try :
    rc = self . __request__ ( method , url , data = json . dumps ( data ) , params = { 'sku_b' : self . sku_b } , fast = fast ) [ 'auctionInfo' ] [ 0 ]
except PermissionDenied : # too slow , somebody took it already : - (
    return False
if rc [ 'bidState' ] == 'highest' or ( rc [ 'tradeState' ] == 'closed' and rc [ 'bidState' ] == 'buyNow' ) : # checking ' tradeState ' is required ?
    return True
else :
    return False


signature:
def club ( self , sort = 'desc' , ctype = 'player' , defId = '' , start = 0 , count = None , page_size = itemsPerPage [ 'club' ] , level = None , category = None , assetId = None , league = None , club = None , position = None , zone = None , nationality = None , rare = False , playStyle = None ) :
    """Return items in your club , excluding consumables .
 : param ctype : [ development / ? / ? ] Card type .
 : param level : ( optional ) [ ? / ? / gold ] Card level .
 : param category : ( optional ) [ fitness / ? / ? ] Card category .
 : param assetId : ( optional ) Asset id .
 : param defId : ( optional ) Definition id .
 : param min _ price : ( optional ) Minimal price .
 : param max _ price : ( optional ) Maximum price .
 : param min _ buy : ( optional ) Minimal buy now price .
 : param max _ buy : ( optional ) Maximum buy now price .
 : param league : ( optional ) League id .
 : param club : ( optional ) Club id .
 : param position : ( optional ) Position .
 : param nationality : ( optional ) Nation id .
 : param rare : ( optional ) [ boolean ] True for searching special cards .
 : param playStyle : ( optional ) Play style .
 : param start : ( optional ) Start page sent to server so it supposed to be 12/15 , 24/30 etc . ( default platform page _ size * n )
 : param page _ size : ( optional ) Page size ( items per page )"""

implementation:
method = 'GET'
url = 'club'
if count : # backward compatibility , will be removed in future
    page_size = count
params = { 'sort' : sort , 'type' : ctype , 'defId' : defId , 'start' : start , 'count' : page_size }
if level :
    params [ 'level' ] = level
if category :
    params [ 'cat' ] = category
if assetId :
    params [ 'maskedDefId' ] = assetId
if league :
    params [ 'leag' ] = league
if club :
    params [ 'team' ] = club
if position :
    params [ 'pos' ] = position
if zone :
    params [ 'zone' ] = zone
if nationality :
    params [ 'nat' ] = nationality
if rare :
    params [ 'rare' ] = 'SP'
if playStyle :
    params [ 'playStyle' ] = playStyle
rc = self . __request__ ( method , url , params = params )
# pinEvent
if start == 0 :
    if ctype == 'player' :
        pgid = 'Club - Players - List View'
    elif ctype == 'staff' :
        pgid = 'Club - Staff - List View'
    elif ctype in ( 'item' , 'kit' , 'ball' , 'badge' , 'stadium' ) :
        pgid = 'Club - Club Items - List View'
    # else : # TODO : THIS IS probably WRONG , detect all ctypes
    # pgid = ' Club - Club Items - List View '
    events = [ self . pin . event ( 'page_view' , 'Hub - Club' ) , self . pin . event ( 'page_view' , pgid ) ]
    if rc [ 'itemData' ] :
        events . append ( self . pin . event ( 'page_view' , 'Item - Detail View' ) )
    self . pin . send ( events )
return [ itemParse ( { 'itemData' : i } ) for i in rc [ 'itemData' ] ]


signature:
def clubStaff ( self ) :
    """Return staff in your club ."""

implementation:
method = 'GET'
url = 'club/stats/staff'
rc = self . __request__ ( method , url )
return rc


signature:
def clubConsumables ( self , fast = False ) :
    """Return all consumables from club ."""

implementation:
method = 'GET'
url = 'club/consumables/development'
rc = self . __request__ ( method , url )
events = [ self . pin . event ( 'page_view' , 'Hub - Club' ) ]
self . pin . send ( events , fast = fast )
events = [ self . pin . event ( 'page_view' , 'Club - Consumables' ) ]
self . pin . send ( events , fast = fast )
events = [ self . pin . event ( 'page_view' , 'Club - Consumables - List View' ) ]
self . pin . send ( events , fast = fast )
return [ itemParse ( i ) for i in rc . get ( 'itemData' , ( ) ) ]


signature:
def squad ( self , squad_id = 0 , persona_id = None ) :
    """Return a squad .
 : params squad _ id : Squad id ."""

implementation:
method = 'GET'
url = 'squad/%s/user/%s' % ( squad_id , persona_id or self . persona_id )
# pinEvents
events = [ self . pin . event ( 'page_view' , 'Hub - Squads' ) ]
self . pin . send ( events )
# TODO : ability to return other info than players only
rc = self . __request__ ( method , url )
# pinEvents
events = [ self . pin . event ( 'page_view' , 'Squad Details' ) , self . pin . event ( 'page_view' , 'Squads - Squad Overview' ) ]
self . pin . send ( events )
return [ itemParse ( i ) for i in rc . get ( 'players' , ( ) ) ]


signature:
def tradeStatus ( self , trade_id ) :
    """Return trade status .
 : params trade _ id : Trade id ."""

implementation:
method = 'GET'
url = 'trade/status'
if not isinstance ( trade_id , ( list , tuple ) ) :
    trade_id = ( trade_id , )
trade_id = ( str ( i ) for i in trade_id )
params = { 'tradeIds' : ',' . join ( trade_id ) }
# multiple trade _ ids not tested
rc = self . __request__ ( method , url , params = params )
return [ itemParse ( i , full = False ) for i in rc [ 'auctionInfo' ] ]


signature:
def tradepile ( self ) :
    """Return items in tradepile ."""

implementation:
method = 'GET'
url = 'tradepile'
rc = self . __request__ ( method , url )
# pinEvents
events = [ self . pin . event ( 'page_view' , 'Hub - Transfers' ) , self . pin . event ( 'page_view' , 'Transfer List - List View' ) ]
if rc . get ( 'auctionInfo' ) :
    events . append ( self . pin . event ( 'page_view' , 'Item - Detail View' ) )
self . pin . send ( events )
return [ itemParse ( i ) for i in rc . get ( 'auctionInfo' , ( ) ) ]


signature:
def sell ( self , item_id , bid , buy_now , duration = 3600 , fast = False ) :
    """Start auction . Returns trade _ id .
 : params item _ id : Item id .
 : params bid : Stard bid .
 : params buy _ now : Buy now price .
 : params duration : Auction duration in seconds ( Default : 3600 ) ."""

implementation:
method = 'POST'
url = 'auctionhouse'
# TODO : auto send to tradepile
data = { 'buyNowPrice' : buy_now , 'startingBid' : bid , 'duration' : duration , 'itemData' : { 'id' : item_id } }
rc = self . __request__ ( method , url , data = json . dumps ( data ) , params = { 'sku_b' : self . sku_b } )
if not fast : # tradeStatus check like webapp do
    self . tradeStatus ( rc [ 'id' ] )
return rc [ 'id' ]


signature:
def quickSell ( self , item_id ) :
    """Quick sell .
 : params item _ id : Item id ."""

implementation:
method = 'DELETE'
url = 'item'
if not isinstance ( item_id , ( list , tuple ) ) :
    item_id = ( item_id , )
item_id = ( str ( i ) for i in item_id )
params = { 'itemIds' : ',' . join ( item_id ) }
self . __request__ ( method , url , params = params )
# { " items " : [ { " id " : 280607437106 } ] , " totalCredits " : 18136}
return True


signature:
def watchlistDelete ( self , trade_id ) :
    """Remove cards from watchlist .
 : params trade _ id : Trade id ."""

implementation:
method = 'DELETE'
url = 'watchlist'
if not isinstance ( trade_id , ( list , tuple ) ) :
    trade_id = ( trade_id , )
trade_id = ( str ( i ) for i in trade_id )
params = { 'tradeId' : ',' . join ( trade_id ) }
self . __request__ ( method , url , params = params )
# returns nothing
return True


signature:
def tradepileDelete ( self , trade_id ) : # item _ id instead of trade _ id ?
    """Remove card from tradepile .
 : params trade _ id : Trade id ."""

implementation:
method = 'DELETE'
url = 'trade/%s' % trade_id
self . __request__ ( method , url )
# returns nothing
# TODO : validate status code
return True


signature:
def sendToTradepile ( self , item_id , safe = True ) :
    """Send to tradepile ( alias for _ _ sendToPile _ _ ) .
 : params item _ id : Item id .
 : params safe : ( optional ) False to disable tradepile free space check ."""

implementation:
if safe and len ( self . tradepile ( ) ) >= self . tradepile_size : # TODO ? : optimization ( don ' t parse items in tradepile )
    return False
return self . __sendToPile__ ( 'trade' , item_id = item_id )


signature:
def sendToWatchlist ( self , trade_id ) :
    """Send to watchlist .
 : params trade _ id : Trade id ."""

implementation:
method = 'PUT'
url = 'watchlist'
data = { 'auctionInfo' : [ { 'id' : trade_id } ] }
return self . __request__ ( method , url , data = json . dumps ( data ) )


signature:
def sendToSbs ( self , challenge_id , item_id ) :
    """Send card FROM CLUB to first free slot in sbs squad ."""

implementation:
# TODO ? : multiple item _ ids
method = 'PUT'
url = 'sbs/challenge/%s/squad' % challenge_id
squad = self . sbsSquad ( challenge_id )
players = [ ]
moved = False
n = 0
for i in squad [ 'squad' ] [ 'players' ] :
    if i [ 'itemData' ] [ 'id' ] == item_id : # item already in sbs # TODO ? : report reason
        return False
    if i [ 'itemData' ] [ 'id' ] == 0 and not moved :
        i [ 'itemData' ] [ 'id' ] = item_id
        moved = True
    players . append ( { "index" : n , "itemData" : { "id" : i [ 'itemData' ] [ 'id' ] , "dream" : False } } )
    n += 1
data = { 'players' : players }
if not moved :
    return False
else :
    self . __request__ ( method , url , data = json . dumps ( data ) )
    return True


signature:
def applyConsumable ( self , item_id , resource_id ) :
    """Apply consumable on player .
 : params item _ id : Item id of player .
 : params resource _ id : Resource id of consumable ."""

implementation:
# TODO : catch exception when consumable is not found etc .
# TODO : multiple players like in quickSell
method = 'POST'
url = 'item/resource/%s' % resource_id
data = { 'apply' : [ { 'id' : item_id } ] }
self . __request__ ( method , url , data = json . dumps ( data ) )


signature:
def messages ( self ) :
    """Return active messages ."""

implementation:
method = 'GET'
url = 'activeMessage'
rc = self . __request__ ( method , url )
# try :
# return rc [ ' activeMessage ' ]
# except :
# raise UnknownError ( ' Invalid activeMessage response ' ) # is it even possible ?
return rc [ 'activeMessage' ]


signature:
def packs ( self ) :
    """List all ( currently ? ) available packs ."""

implementation:
method = 'GET'
url = 'store/purchaseGroup/cardpack'
params = { 'ppInfo' : True }
return self . __request__ ( method , url , params = params )


signature:
def num2hex ( self , num ) :
    '''Convert a decimal number to hexadecimal'''

implementation:
temp = ''
for i in range ( 0 , 4 ) :
    x = self . hexChars [ ( num >> ( i * 8 + 4 ) ) & 0x0F ]
    y = self . hexChars [ ( num >> ( i * 8 ) ) & 0x0F ]
    temp += ( x + y )
return temp


signature:
def logger ( name = None , save = False ) :
    """Init and configure logger ."""

implementation:
logger = logging . getLogger ( name )
if save :
    logformat = '%(asctime)s [%(levelname)s] [%(name)s] %(funcName)s: %(message)s (line %(lineno)d)'
    log_file_path = 'fut.log'
    # TODO : define logpath
    open ( log_file_path , 'w' ) . write ( '' )
    # remove old logs
    logger . setLevel ( logging . DEBUG )
    logger_handler = logging . FileHandler ( log_file_path )
    logger_handler . setFormatter ( logging . Formatter ( logformat ) )
else :
    logger_handler = NullHandler ( )
logger . addHandler ( logger_handler )
return logger


signature:
def get_bits_per_pixel ( data_format ) :
    """Returns the number of ( used ) bits per pixel .
 So without padding .
 Returns None if format is not known ."""

implementation:
if data_format in component_8bit_formats :
    return 8
elif data_format in component_10bit_formats :
    return 10
elif data_format in component_12bit_formats :
    return 12
elif data_format in component_14bit_formats :
    return 14
elif data_format in component_16bit_formats :
    return 16
# format not known
return None


signature:
def run ( self ) :
    """Runs its worker method .
 This method will be terminated once its parent ' s is _ running
 property turns False ."""

implementation:
while self . _base . is_running :
    if self . _worker :
        self . _worker ( )
        time . sleep ( self . _sleep_duration )


signature:
def represent_pixel_location ( self ) :
    """Returns a NumPy array that represents the 2D pixel location ,
 which is defined by PFNC , of the original image data .
 You may use the returned NumPy array for a calculation to map the
 original image to another format .
 : return : A NumPy array that represents the 2D pixel location ."""

implementation:
if self . data is None :
    return None
return self . _data . reshape ( self . height + self . y_padding , int ( self . width * self . _num_components_per_pixel + self . x_padding ) )


signature:
def width ( self ) :
    """: return : The width of the data component in the buffer in number of pixels ."""

implementation:
try :
    if self . _part :
        value = self . _part . width
    else :
        value = self . _buffer . width
except InvalidParameterException :
    value = self . _node_map . Width . value
return value


signature:
def height ( self ) :
    """: return : The height of the data component in the buffer in number of pixels ."""

implementation:
try :
    if self . _part :
        value = self . _part . height
    else :
        value = self . _buffer . height
except InvalidParameterException :
    value = self . _node_map . Height . value
return value


signature:
def data_format_value ( self ) :
    """: return : The data type of the data component as integer value ."""

implementation:
try :
    if self . _part :
        value = self . _part . data_format
    else :
        value = self . _buffer . pixel_format
except InvalidParameterException :
    value = self . _node_map . PixelFormat . value
return value


signature:
def delivered_image_height ( self ) :
    """: return : The image height of the data component ."""

implementation:
try :
    if self . _part :
        value = self . _part . delivered_image_height
    else :
        value = self . _buffer . delivered_image_height
except InvalidParameterException :
    value = 0
return value


signature:
def x_offset ( self ) : # TODO : Check the naming convention .
    """: return : The X offset of the data in the buffer in number of pixels from the image origin to handle areas of interest ."""

implementation:
try :
    if self . _part :
        value = self . _part . x_offset
    else :
        value = self . _buffer . offset_x
except InvalidParameterException :
    value = self . _node_map . OffsetX . value
return value


signature:
def y_offset ( self ) :
    """: return : The Y offset of the data in the buffer in number of pixels from the image origin to handle areas of interest ."""

implementation:
try :
    if self . _part :
        value = self . _part . y_offset
    else :
        value = self . _buffer . offset_y
except InvalidParameterException :
    value = self . _node_map . OffsetY . value
return value


signature:
def x_padding ( self ) :
    """Returns
 : return : The X padding of the data component in the buffer in number of pixels ."""

implementation:
try :
    if self . _part :
        value = self . _part . x_padding
    else :
        value = self . _buffer . padding_x
except InvalidParameterException :
    value = 0
return value


signature:
def queue ( self ) :
    """Queues the buffer to prepare for the upcoming image acquisition . Once
 the buffer is queued , the : class : ` Buffer ` object will be obsolete .
 You ' ll have nothing to do with it .
 Note that you have to return the ownership of the fetched buffers to
 the : class : ` ImageAcquirer ` object before stopping image acquisition
 calling this method because the : class : ` ImageAcquirer ` object tries
 to clear the self - allocated buffers when it stops image acquisition ."""

implementation:
if _is_logging_buffer_manipulation :
    self . _logger . debug ( 'Queued Buffer module #{0}' ' containing frame #{1}' ' to DataStream module {2}' ' of Device module {3}' '.' . format ( self . _buffer . context , self . _buffer . frame_id , self . _buffer . parent . id_ , self . _buffer . parent . parent . id_ ) )
self . _buffer . parent . queue_buffer ( self . _buffer )


signature:
def start_image_acquisition ( self ) :
    """Starts image acquisition .
 : return : None ."""

implementation:
if not self . _create_ds_at_connection :
    self . _setup_data_streams ( )
num_required_buffers = self . _num_buffers
for data_stream in self . _data_streams :
    try :
        num_buffers = data_stream . buffer_announce_min
        if num_buffers < num_required_buffers :
            num_buffers = num_required_buffers
    except InvalidParameterException as e :
        num_buffers = num_required_buffers
        self . _logger . debug ( e , exc_info = True )
    if data_stream . defines_payload_size ( ) :
        buffer_size = data_stream . payload_size
    else :
        buffer_size = self . device . node_map . PayloadSize . value
    raw_buffers = self . _create_raw_buffers ( num_buffers , buffer_size )
    buffer_tokens = self . _create_buffer_tokens ( raw_buffers )
    self . _announced_buffers = self . _announce_buffers ( data_stream = data_stream , _buffer_tokens = buffer_tokens )
    self . _queue_announced_buffers ( data_stream = data_stream , buffers = self . _announced_buffers )
# Reset the number of images to acquire .
try :
    acq_mode = self . device . node_map . AcquisitionMode . value
    if acq_mode == 'Continuous' :
        num_images_to_acquire = - 1
    elif acq_mode == 'SingleFrame' :
        num_images_to_acquire = 1
    elif acq_mode == 'MultiFrame' :
        num_images_to_acquire = self . device . node_map . AcquisitionFrameCount . value
    else :
        num_images_to_acquire = - 1
except LogicalErrorException as e : # The node doesn ' t exist .
    num_images_to_acquire = - 1
    self . _logger . debug ( e , exc_info = True )
self . _num_images_to_acquire = num_images_to_acquire
try : # We ' re ready to start image acquisition . Lock the device ' s
# transport layer related features :
    self . device . node_map . TLParamsLocked . value = 1
except LogicalErrorException : # SFNC < 2.0
    pass
# Start image acquisition .
self . _is_acquiring_images = True
for data_stream in self . _data_streams :
    data_stream . start_acquisition ( ACQ_START_FLAGS_LIST . ACQ_START_FLAGS_DEFAULT , self . _num_images_to_acquire )
if self . thread_image_acquisition :
    self . thread_image_acquisition . start ( )
self . device . node_map . AcquisitionStart . execute ( )
self . _logger . info ( '{0} started image acquisition.' . format ( self . _device . id_ ) )
if self . _profiler :
    self . _profiler . print_diff ( )


signature:
def fetch_buffer ( self , * , timeout = 0 , is_raw = False ) :
    """Fetches the latest : class : ` Buffer ` object and returns it .
 : param timeout : Set timeout value in second .
 : param is _ raw : Set : const : ` True ` if you need a raw GenTL Buffer module .
 : return : A : class : ` Buffer ` object ."""

implementation:
if not self . is_acquiring_images :
    raise TimeoutException
watch_timeout = True if timeout > 0 else False
buffer = None
base = time . time ( )
while buffer is None :
    if watch_timeout and ( time . time ( ) - base ) > timeout :
        raise TimeoutException
    else :
        with MutexLocker ( self . thread_image_acquisition ) :
            if len ( self . _holding_filled_buffers ) > 0 :
                if is_raw :
                    buffer = self . _holding_filled_buffers . pop ( 0 )
                else : # Update the chunk data :
                    _buffer = self . _holding_filled_buffers . pop ( 0 )
                    self . _update_chunk_data ( buffer = _buffer )
                    buffer = Buffer ( buffer = _buffer , node_map = self . device . node_map , logger = self . _logger )
if _is_logging_buffer_manipulation :
    self . _logger . debug ( 'Fetched Buffer module #{0}' ' containing frame #{1}' ' of DataStream module {2}' ' of Device module {2}' '.' . format ( buffer . _buffer . context , buffer . _buffer . frame_id , buffer . _buffer . parent . id_ , buffer . _buffer . parent . parent . id_ ) )
return buffer


signature:
def stop_image_acquisition ( self ) :
    """Stops image acquisition .
 : return : None ."""

implementation:
if self . is_acquiring_images :
    self . _is_acquiring_images = False
    if self . thread_image_acquisition . is_running : # TODO
        self . thread_image_acquisition . stop ( )
    with MutexLocker ( self . thread_image_acquisition ) :
        self . device . node_map . AcquisitionStop . execute ( )
        try : # Unlock TLParamsLocked in order to allow full device
        # configuration :
            self . device . node_map . TLParamsLocked . value = 0
        except LogicalErrorException : # SFNC < 2.0
            pass
        for data_stream in self . _data_streams : # Stop image acquisition .
            try :
                data_stream . stop_acquisition ( ACQ_STOP_FLAGS_LIST . ACQ_STOP_FLAGS_KILL )
            except ( ResourceInUseException , TimeoutException ) as e :
                self . _logger . error ( e , exc_info = True )
            # Flash the queue for image acquisition process .
            data_stream . flush_buffer_queue ( ACQ_QUEUE_TYPE_LIST . ACQ_QUEUE_ALL_DISCARD )
        for event_manager in self . _event_new_buffer_managers :
            event_manager . flush_event_queue ( )
        if self . _create_ds_at_connection :
            self . _release_buffers ( )
        else :
            self . _release_data_streams ( )
    self . _has_acquired_1st_image = False
    self . _chunk_adapter . detach_buffer ( )
    self . _logger . info ( '{0} stopped image acquisition.' . format ( self . _device . id_ ) )
if self . _profiler :
    self . _profiler . print_diff ( )


signature:
def add_cti_file ( self , file_path : str ) :
    """Adds a CTI file to work with to the CTI file list .
 : param file _ path : Set a file path to the target CTI file .
 : return : None ."""

implementation:
if not os . path . exists ( file_path ) :
    self . _logger . warning ( 'Attempted to add {0} which does not exist.' . format ( file_path ) )
if file_path not in self . _cti_files :
    self . _cti_files . append ( file_path )
    self . _logger . info ( 'Added {0} to the CTI file list.' . format ( file_path ) )


signature:
def remove_cti_file ( self , file_path : str ) :
    """Removes the specified CTI file from the CTI file list .
 : param file _ path : Set a file path to the target CTI file .
 : return : None ."""

implementation:
if file_path in self . _cti_files :
    self . _cti_files . remove ( file_path )
    self . _logger . info ( 'Removed {0} from the CTI file list.' . format ( file_path ) )


signature:
def _reset ( self ) :
    """Initializes the : class : ` Harvester ` object . Once you reset the
 : class : ` Harvester ` object , all allocated resources , including buffers
 and remote device , will be released .
 : return : None ."""

implementation:
for ia in self . _ias :
    ia . _destroy ( )
self . _ias . clear ( )
self . _logger . info ( 'Started resetting the Harvester object.' )
self . remove_cti_files ( )
self . _release_gentl_producers ( )
if self . _profiler :
    self . _profiler . print_diff ( )
self . _logger . info ( 'Completed resetting the Harvester object.' )


signature:
def update_device_info_list ( self ) :
    """Updates the device information list . You ' ll have to call this method
 every time you added CTI files or plugged / unplugged devices .
 : return : None ."""

implementation:
self . _release_gentl_producers ( )
try :
    self . _open_gentl_producers ( )
    self . _open_systems ( )
    for system in self . _systems :
        system . update_interface_info_list ( self . timeout_for_update )
        for i_info in system . interface_info_list :
            iface = i_info . create_interface ( )
            try :
                iface . open ( )
            except ( NotInitializedException , ResourceInUseException , InvalidHandleException , InvalidHandleException , InvalidParameterException , AccessDeniedException , ) as e :
                self . _logger . debug ( e , exc_info = True )
            else :
                self . _logger . info ( 'Opened Interface module, {0}.' . format ( iface . id_ ) )
                iface . update_device_info_list ( self . timeout_for_update )
                self . _interfaces . append ( iface )
                for d_info in iface . device_info_list :
                    self . device_info_list . append ( d_info )
except LoadLibraryException as e :
    self . _logger . error ( e , exc_info = True )
    self . _has_revised_device_list = False
else :
    self . _has_revised_device_list = True
self . _logger . info ( 'Updated the device information list.' )


signature:
def _destroy_image_acquirer ( self , ia ) :
    """Releases all external resources including the controlling device ."""

implementation:
id_ = None
if ia . device :
    ia . stop_image_acquisition ( )
    ia . _release_data_streams ( )
    id_ = ia . _device . id_
    if ia . device . node_map :
        if ia . _chunk_adapter :
            ia . _chunk_adapter . detach_buffer ( )
            ia . _chunk_adapter = None
            self . _logger . info ( 'Detached a buffer from the chunk adapter of {0}.' . format ( id_ ) )
        ia . device . node_map . disconnect ( )
        self . _logger . info ( 'Disconnected the port from the NodeMap of {0}.' . format ( id_ ) )
    if ia . _device . is_open ( ) :
        ia . _device . close ( )
        self . _logger . info ( 'Closed Device module, {0}.' . format ( id_ ) )
ia . _device = None
if id_ :
    self . _logger . info ( 'Destroyed the ImageAcquirer object which {0} ' 'had belonged to.' . format ( id_ ) )
else :
    self . _logger . info ( 'Destroyed an ImageAcquirer.' )
if self . _profiler :
    self . _profiler . print_diff ( )
self . _ias . remove ( ia )


signature:
def is_running_on_macos ( ) :
    """Returns a truth value for a proposition : " the program is running on a
 macOS machine " .
 : rtype : bool"""

implementation:
pattern = re . compile ( 'darwin' , re . IGNORECASE )
return False if not pattern . search ( platform . platform ( ) ) else True


signature:
def get_sha1_signature ( token , timestamp , nonce , encrypt ) :
    """用 SHA1 算法生成安全签名
 @ param token : 票据
 @ param timestamp : 时间戳
 @ param encrypt : 密文
 @ param nonce : 随机字符串
 @ return : 安全签名"""

implementation:
try :
    sortlist = [ token , timestamp , nonce , to_binary ( encrypt ) ]
    sortlist . sort ( )
    sha = hashlib . sha1 ( )
    sha . update ( to_binary ( "" ) . join ( sortlist ) )
    return sha . hexdigest ( )
except Exception as e :
    raise CryptoComputeSignatureError ( e )


signature:
def login ( self , verify_code = '' ) :
    """登录微信公众平台
 注意在实例化 ` ` WechatExt ` ` 的时候 , 如果没有传入 ` ` token ` ` 及 ` ` cookies ` ` , 将会自动调用该方法 , 无需手动调用
 当且仅当捕获到 ` ` NeedLoginError ` ` 异常时才需要调用此方法进行登录重试
 : param verify _ code : 验证码 , 不传入则为无验证码
 : raises LoginVerifyCodeError : 需要验证码或验证码出错 , 该异常为 ` ` LoginError ` ` 的子类
 : raises LoginError : 登录出错异常 , 异常内容为微信服务器响应的内容 , 可作为日志记录下来"""

implementation:
url = 'https://mp.weixin.qq.com/cgi-bin/login'
payload = { 'username' : self . __username , 'pwd' : self . __password , 'imgcode' : verify_code , 'f' : 'json' , }
headers = { 'x-requested-with' : 'XMLHttpRequest' , 'referer' : 'https://mp.weixin.qq.com/cgi-bin/loginpage?t=wxm2-login&lang=zh_CN' , 'Cookie' : self . __cookies , }
r = requests . post ( url , data = payload , headers = headers )
s = re . search ( r'token=(\d+)' , r . text )
if not s :
    try :
        error_code = json . loads ( r . text ) [ 'base_resp' ] [ 'ret' ]
    except ( KeyError , ValueError ) :
        raise LoginError ( r . text )
    if error_code in [ - 8 , - 27 ] :
        raise LoginVerifyCodeError ( r . text )
    elif re . search ( r'readtemplate' , r . text ) :
        raise LoginError ( 'You need to turn off the safety protection of wechat.' )
    else :
        raise LoginError ( r . text )
self . __token = int ( s . group ( 1 ) )
self . __cookies = ''
for cookie in r . cookies :
    self . __cookies += cookie . name + '=' + cookie . value + ';'


signature:
def get_verify_code ( self , file_path ) :
    """获取登录验证码并存储
 : param file _ path : 将验证码图片保存的文件路径"""

implementation:
url = 'https://mp.weixin.qq.com/cgi-bin/verifycode'
payload = { 'username' : self . __username , 'r' : int ( random . random ( ) * 10000000000000 ) , }
headers = { 'referer' : 'https://mp.weixin.qq.com/' , }
r = requests . get ( url , data = payload , headers = headers , stream = True )
self . __cookies = ''
for cookie in r . cookies :
    self . __cookies += cookie . name + '=' + cookie . value + ';'
with open ( file_path , 'wb' ) as fd :
    for chunk in r . iter_content ( 1024 ) :
        fd . write ( chunk )


signature:
def send_message ( self , fakeid , content ) :
    """主动发送文本消息
 : param fakeid : 用户的 UID ( 即 fakeid )
 : param content : 发送的内容
 : raises NeedLoginError : 操作未执行成功 , 需要再次尝试登录 , 异常内容为服务器返回的错误数据
 : raises ValueError : 参数出错 , 具体内容有 ` ` fake id not exist ` `"""

implementation:
url = 'https://mp.weixin.qq.com/cgi-bin/singlesend?t=ajax-response'
payload = { 'tofakeid' : fakeid , 'type' : 1 , 'token' : self . __token , 'content' : content , 'ajax' : 1 , }
headers = { 'x-requested-with' : 'XMLHttpRequest' , 'referer' : 'https://mp.weixin.qq.com/cgi-bin/singlesendpage?t=message/send&action=index&tofakeid={fakeid}&token={token}&lang=zh_CN' . format ( fakeid = fakeid , token = self . __token , ) , 'cookie' : self . __cookies , }
r = requests . post ( url , data = payload , headers = headers )
try :
    message = json . loads ( r . text )
except ValueError :
    raise NeedLoginError ( r . text )
try :
    if message [ 'base_resp' ] [ 'ret' ] == - 21 :
        raise ValueError ( 'fake id not exist' )
    if message [ 'base_resp' ] [ 'ret' ] != 0 :
        raise NeedLoginError ( r . text )
except KeyError :
    raise NeedLoginError ( r . text )


signature:
def get_user_list ( self , page = 0 , pagesize = 10 , groupid = 0 ) :
    """获取用户列表
 返回JSON示例 : :
 " contacts " : [
 " id " : 2431798261,
 " nick _ name " : " Doraemonext " ,
 " remark _ name " : " " ,
 " group _ id " : 0
 " id " : 896229760,
 " nick _ name " : " 微信昵称 " ,
 " remark _ name " : " " ,
 " group _ id " : 0
 : param page : 页码 ( 从 0 开始 )
 : param pagesize : 每页大小
 : param groupid : 分组 ID
 : return : 返回的 JSON 数据
 : raises NeedLoginError : 操作未执行成功 , 需要再次尝试登录 , 异常内容为服务器返回的错误数据"""

implementation:
url = 'https://mp.weixin.qq.com/cgi-bin/contactmanage?t=user/index&pagesize={pagesize}&pageidx={page}&type=0&groupid={groupid}&lang=zh_CN&f=json&token={token}' . format ( pagesize = pagesize , page = page , groupid = groupid , token = self . __token , )
headers = { 'x-requested-with' : 'XMLHttpRequest' , 'referer' : 'https://mp.weixin.qq.com/cgi-bin/contactmanage?t=user/index&pagesize={pagesize}&pageidx={page}&type=0&groupid=0&lang=zh_CN&token={token}' . format ( pagesize = pagesize , page = page , token = self . __token , ) , 'cookie' : self . __cookies , }
r = requests . get ( url , headers = headers )
try :
    message = json . loads ( r . text ) [ 'contact_list' ]
except ( KeyError , ValueError ) :
    raise NeedLoginError ( r . text )
return message