From the docs at https://docs.python-requests.org/en/master/user/authentication/
I gathered that the __call__
function in my own Auth Class should have the r argument,
However when i go to call this class in requests.get(auth=MyClass), I get the error TypeError: __call__() missing 1 required positional argument: 'r'
The code for my class can be found here https://pastebin.com/YDZ2DeaT
import requests import time import base64 from requests.auth import AuthBase class TokenAuth(AuthBase): """Refreshes SkyKick token, for use with all Skykick requests""" def __init__(self, Username: str, SubKey: str): self.Username = Username self.SubKey = SubKey # Initialise with no token and instant expiry self.Token = None self.TokenExpiry = time.time() self.Headers = { # Request headers 'Content-Type' : 'application/x-www-form-urlencoded', 'Ocp-Apim-Subscription-Key': self.SubKey, } self.Body = { # Request body 'grant_type': 'client_credentials', 'scope' : 'Partner' } def regenToken(self): # Sends request to regenerate token try: # Get key from API response = requests.post("https://apis.skykick.com/auth/token", headers=self.Headers, auth=(self.Username, self.SubKey), data=self.Body, ).json() except: raise Exception("Sending request failed, check connection.") # API errors are inconsistent, easiest way to catch them if "error" in response or "statusCode" in response: raise Exception( "Token requesting failed, cannot proceed with any Skykick actions, exiting.n" f"Error raised was {response}") # Get token from response and set expiry self.Token = response["access_token"] self.TokenExpiry = time.time() + 82800 def __call__(self, r): # If token expiry is now or in past, call regenToken if self.TokenExpiry <= time.time(): self.regenToken() # Set headers and return complete requests.Request object r.headers["Authorization"] = f"Bearer {self.Token}" return r # Initialise our token class, so it is ready to call TokenClass = TokenAuth("test", "1234") #Send request with class as auth method. requests.get("https://apis.skykick.com/whoami", auth=TokenClass())
I’ve tried using the example code, which works, but I can’t figure out why mine won’t work.
python-requests version is 2.25.1
Advertisement
Answer
I think I know what is going on.
This line instantiates an object, called TokenClass
TokenClass = TokenAuth("test", "1234")
then here,
requests.get("https://apis.skykick.com/whoami", auth=TokenClass())
you are calling that object like a function
when you call an object like a function, python looks for the __call__
method of the object.
And you are not calling in any arguments here. What you have is roughly the same as this I think
requests.get("https://apis.skykick.com/whoami", auth=TokenClass.__call__())
and so it complains that you are missing the r
argument
This is their example:
import requests class MyAuth(requests.auth.AuthBase): def __call__(self, r): # Implement my authentication return r url = 'https://httpbin.org/get' requests.get(url, auth=MyAuth())
MyAuth
is a class that they define, and then MyAuth()
creates an instance of it that they pass in to get
.
Yours is more like this
import requests class MyAuth(requests.auth.AuthBase): def __call__(self, r): # Implement my authentication return r url = 'https://httpbin.org/get' myAuth = MyAuth() # create an instance of the class requests.get(url, auth=myAuth()) # call the instance and pass in result
It could also be written like this
import requests class MyAuth(requests.auth.AuthBase): def __call__(self, r): # Implement my authentication return r url = 'https://httpbin.org/get' requests.get(url, auth=MyAuth()())
This program with produce the same error you are getting
import requests class MyAuth(requests.auth.AuthBase): def __call__(self, r): # Implement my authentication return r url = 'https://httpbin.org/get' MyAuth()()
because when you put ()
after a class, you get an instance, and when you put ()
after an instance, you call the __call__
method