Weird Python error - python

This error: cancel_agreement() missing 1 required positional argument: 'agreement_id'
appeared while executing this method:
def force_cancel(self):
api = model_from_ref(self.processor.api)
api.cancel_agreement(self.subscription_reference)
# transaction.cancel_subscription() # runs in the callback
Here is cancel_agreement() method:
def cancel_agreement(self, agreement_id, is_upgrade=False):
note = _("Upgrading billing plan") if is_upgrade else _("Canceling a service")
r = self.session.post(self.server + '/v1/payments/billing-agreements/%s/cancel' % agreement_id,
data='{"note": "%s"}' % note,
headers={'content-type': 'application/json'})
if r.status_code != requests.codes.ok:
raise RuntimeError(_("Cannot cancel a billing agreement at PayPal. Please contact support."))
I don't understand why the error happens: It is calling a two-argument function (api and self.subscription_reference) and its definition is also two required arguments (self and agreement_id).
Sadly I can't show the entire code, because my business partner is against releasing it open source.

It should be:
def force_cancel(self):
klass = model_from_ref(self.processor.api)
api = klass()
api.cancel_agreement(self.subscription_reference)

Related

Response generated while mocking is not correct in python tests

I am trying to unit test some of my functions using mocks in python. Few of them seems to be working as expected but I am trouble with the response of one the test case. Which it not returning the ideal response which it should.
###############motpenrichreceiverinfo.py##################
import requests
def getReceiverInfo(fundId):
print('Inside fetchReceiverInfo',fundId)
response = requests.get("REST URL FOR RECEIVER INFO")
if response.ok:
return response
else:
return None
def getMotpTrade(trade_id):
response = requests.get("REST URL")
if response.ok:
return response
else:
return None
def getMotpCanonical(trade_id):
response = requests.get("REST URL")
if response.ok:
return response
else:
return None
def EnrichTradeWithReceiverInfo(event, context):
#print('Lambda function started..')
trade_id = event['tradeId']
motpTrade = getMotpTrade(trade_id)
canonicalTrade = getMotpCanonical(trade_id)
fundId = motpTrade['Account']
#print(fundId)
data = getReceiverInfo(fundId)
print(data)
return data
##########################test_motptrade.py##############################
# Standard library imports
from unittest.mock import Mock, patch
# Third-party imports...
from nose.tools import assert_true
from nose.tools import assert_is_not_none, assert_list_equal, assert_dict_equal
# Local imports
from motpenrichreceiverinfo import getMotpTrade, getReceiverInfo, EnrichTradeWithReceiverInfo
#patch('motpenrichreceiverinfo.requests.get')
def test_motptraderequest_response(mock_get):
motpTrade = [{
"motpTrade":"motpTrade"
}]
# Configure the mock to return a response with an OK status code.
mock_get.return_value.ok = True
mock_get.return_value.json.return_value = motpTrade
# Send a request to the API server and store the response.
response = getMotpTrade('tradeId')
# If the request is sent successfully, then I expect a response to be returned.
assert_list_equal(response.json(), motpTrade)
#patch('motpenrichreceiverinfo.requests.get')
def test_getReceiverInfo_respose_ok(mock_get):
receiverInfo = [{
"reciever":"reciever"
}]
# Configure the mock to return a response with an OK status code.
mock_get.return_value.ok = True
mock_get.return_value.json.return_value = receiverInfo
# Send a request to the API server and store the response.
response = getReceiverInfo("1110")
# If the request is sent successfully, then I expect a response to be returned.
assert_list_equal(response.json(), receiverInfo)
#patch('motpenrichreceiverinfo.getMotpTrade')
#patch('motpenrichreceiverinfo.getMotpCanonical')
#patch('motpenrichreceiverinfo.getReceiverInfo')
def test_EnrichTradeWithReceiverInfo_ok(mock_get,mock_canonical,mock_receiverinfo):
motpTrade = [{
"motpTrade":"motpTrade"
}]
receiverInfo = [{
"reciever":"reciever"
}]
event = {"tradeId":"123456"}
# Configure the mock to return a response with an OK status code.
mock_get.return_value = Mock(ok=True)
mock_get.return_value.json.return_value = motpTrade
mock_canonical.return_value.ok = True
mock_canonical.return_value.json.return_value = [{}]
mock_receiverinfo.return_value.ok = True
mock_receiverinfo.return_value.json.return_value = receiverInfo
data = EnrichTradeWithReceiverInfo(event,"")
assert_true(mock_get.called)
assert_true(mock_receiverinfo.called)
assert_list_equal(data.json(),receiverInfo)
Here my first two cases are working as expected. But my last test case(test_EnrichTradeWithReceiverInfo_ok) is somehow not working. Ideally it should have response equal to receiverInfo object.But when I run it gives below error. It would be really helpful someone can help me understand what I am doing wrong here.
(venv) C:\Development\motplambdas>nosetests -v test_motptrade.py
test_motptrade.test_EnrichTradeWithReceiverInfo_ok ... FAIL
test_motptrade.test_getReceiverInfo_respose_ok ... ok
test_motptrade.test_motptraderequest_response ... ok
======================================================================
FAIL: test_motptrade.test_EnrichTradeWithReceiverInfo_ok
----------------------------------------------------------------------
Traceback (most recent call last):
File "c:\development\motplambdas\venv\lib\site-packages\nose\case.py", line 198, in runTest
self.test(*self.arg)
File "c:\program files\python38\lib\unittest\mock.py", line 1325, in patched
return func(*newargs, **newkeywargs)
File "C:\Development\motplambdas\test_motptrade.py", line 69, in test_EnrichTradeWithReceiverInfo_ok
assert_list_equal(data.json(),receiverInfo)
AssertionError: Lists differ: [{'motpTrade': 'motpTrade'}] != [{'reciever': 'reciever'}]
First differing element 0:
{'motpTrade': 'motpTrade'}
{'reciever': 'reciever'}
- [{'motpTrade': 'motpTrade'}]
+ [{'reciever': 'reciever'}]
----------------------------------------------------------------------
Ran 3 tests in 0.011s
FAILED (failures=1)
The issue is the order of which you are passing your Mock objects into the function call.
#patch('motpenrichreceiverinfo.getMotpTrade')
#patch('motpenrichreceiverinfo.getMotpCanonical')
#patch('motpenrichreceiverinfo.getReceiverInfo')
def test_EnrichTradeWithReceiverInfo_ok(mock_get,mock_canonical,mock_receiverinfo)
Mock objects are passed from the bottom up, meaning #patch('motpenrichreceiverinfo.getReceiverInfo') is the first Mock passed in to the function call, not the last as you have it listed. Due to this you end up setting getReceiverInfo to return the wrong value. The solution is to switch the function call to look like this:
def test_EnrichTradeWithReceiverInfo_ok(mock_receiverinfo, mock_canonical, mock_get)
You can read more about this here where it explains how nesting decorators works.
Note that the decorators are applied from the bottom upwards. This is the standard way that Python applies decorators. The order of the created mocks passed into your test function matches this order.

python __init__() takes 1 positional argument but 2 were given newbie

I have an attribute error in a little spotify-api program i am trying to run
my run file contains the following
import os
from spotify_client import AddSongs
def run():
spotify_client = AddSongs('spotify_token')
random_tracks = spotify_client.get_random_tracks()
track_ids = [track['id'] for track in random_tracks]
was_added_to_queue = spotify_client.add_tracks_to_queue()
if was_added_to_queue:
for track in random_tracks:
print(f"Added {track['name']} to your library")
if __name__ == '__main__':
run()
then in spotify_client is the following class
class AddSongs(object):
def __init__(self,):
self.spotify_token = ""
self.uri = ""
def get_random_tracks(self):
wildcard = f'%{random.choice(string.ascii_lowercase)}%'
query = urllib.parse.quote(wildcard)
offset = random.randint(0, 2000)
url = f"https://api.spotify.com/v1/search?q={query}&offset={offset}&type=track&limit=1"
response = requests.get(
url,
headers={
"Content-Type": "application/json",
"Authorization": f"Bearer {self.spotify_token}"
}
)
response_json = response.json()
print(response)
tracks = [
track for track in response_json['tracks']['items']
]
self.uri = response_json["tracks"]["items"][0]["uri"]
print(f'Found {len(tracks)} tracks to add to your queue')
return tracks
return self.uri
def add_tracks_to_queue(self,):
print('adding to queue...')
url =f"https://api.spotify.com/v1/me/player/queue?uri={self.uri}"
response = requests.post(
url,
headers={
"Content-Type": "application/json",
"Authorization": f"Bearer {self.spotify_token}"
}
)
print(f"Added {track['name']} to your queue")
return response.ok
def callrefresh(self):
print("Refreshing token")
refreshCaller = Refresh()
self.spotify_token = refreshCaller.refresh()
self.get_random_tracks()
a = AddSongs()
a. callrefresh()
As you can see it runs the code fine up untill add_tracks_to_queue
this is giving me the following traceback
Refreshing token
<Response [200]>
Found 1 tracks to add to your queue
Traceback (most recent call last):
File "/Users/shakabediako/Documents/free_streams/run.py", line 18, in <module>
run()
File "/Users/shakabediako/Documents/free_streams/run.py", line 7, in run
spotify_client = AddSongs('spotify_token')
TypeError: __init__() takes 1 positional argument but 2 were given
>>>
I know there are multiple threads about this error but after reading most of them i haven't been able to understand the concept or find the answer.
I think it has something to do with me calling the function from another file but i do not understand why this creates another "positional argument"
I know this because if i just run the spotify_client file i get the following response
Refreshing token
<Response [200]>
Found 1 tracks to add to your queue
>>>
which are just my print values up until def add_tracks_to_queue (which i also don't understand why it is not running)
I really hope someone can help me with this
Thanks in advance
Your AddSongs class doesn't accept any variables as input (also there's a stray comma in the __init__ which doesn't seem to serve any purpose):
class AddSongs(object):
def __init__(self,):
Yet you're calling it as if it does accept a variable:
spotify_client = AddSongs('spotify_token')
The self parameter has to be in there, but if you want to accept any other variables, you need to actually define them. The solution could therefore be to add a token parameter:
class AddSongs(object):
def __init__(self, token=""): # defaults to an empty string if token is not passed in
self.spotify_token = token
That way, if you call AddSongs('spotify_token'), the class's self.spotify_token will get set to 'spotify_token'.

Python method missing an argument but all seems to be there [duplicate]

This question already has answers here:
TypeError: Missing 1 required positional argument: 'self'
(8 answers)
Closed 3 years ago.
What i'm trying to do is run a piece of code that did work at one time, but when i loaded up the project the captcha solving function is saying i'm missing an argument in a function but i don't see where.
Code:
This piece of code:
elif action_to_take == "RECAPTCHA_V2":
selenium_field = self.execute_recaptcha_v2_solver(captcha_key, url_or_field_identifier)
self.write_to_debug_file("--> SOLVING RECAPTCHA V2 ...", _filename)
Then executes:
# this function executes the ReCaptcha solver ...
def execute_recaptcha_v2_solver(self, api_key, url_or_field_identifier):
solve_recaptcha_v2 = CaptchaReCaptchaSolver.solve_recaptcha(api_key,
self.extract_data_site_key(self.driver.page_source),
url_or_field_identifier)
javascript_code = 'document.getElementById("g-recaptcha-response").innerHTML = "{}"'.format(solve_recaptcha_v2)
return self.driver.execute_script(javascript_code)
Which runs the Class:
class CaptchaReCaptchaSolver(object):
# noinspection PyMethodMayBeStatic
def solve_recaptcha(self, _captcha_api_key, _site_key, _url):
print(_captcha_api_key, _site_key, _url)
""" this function solves recaptcha using 2captcha.com """
try:
# p = '127.0.0.1:6969'
# p = {'http': 'http://' + p, 'https': 'https://' + p}
# send off requests ...
s = requests.Session()
cap_id = s.post('http://2captcha.com/in.php?key={}&method=userrecaptcha&googlekey={}&pageurl={}'.format(
_captcha_api_key, _site_key, _url)).text.split('|')[1]
rec_an = s.get("http://2captcha.com/res.php?key={}&action=get&id={}".format(_captcha_api_key, cap_id)).text
# tell us what is going on ...
print("--> ReCAPTCHA V2 SOLVING")
print("--> SOLVING ...")
while "CAPTCHA_NOT_READY" in rec_an:
sleep(5)
rec_an = s.get("http://2captcha.com/res.php?key={}&action=get&id={}".format(_captcha_api_key, cap_id)).text
rec_an = rec_an.split('|')[1]
# solved ...
print("--> " + rec_an)
print("--> SOLVED ...")
print("--> ReCAPTCHA V2 RESPONSE")
# payload ...
payload = {'key': 'value', 'gresponse': rec_an}
s.post(_url, payload)
# return ReCaptcha answer ...
return rec_an
except Exception as e:
print("2CAPTCHA.COM [ReCAPTCHA] ERROR: ", e)
The error is:
LINE 222 "selenium_field = self.execute_recaptcha_v2_solver(captcha_key, url_or_field_identifier)"): solve_recaptcha() missing 1 required positional argument: '_url'
The class method solve_recaptcha() is missing an argument it is saying, but i have printed them out and they are all there, am i missing something obvious? i cannot see what the issue could be, any help would be appreciated.
Notice here... CaptchaReCaptchaSolver.solve_recaptcha this is how you would call a static class member not an instance. Since the method's first param is self then it requires the function be called on an instance of the object.
This should fix.
CaptchaReCaptchaSolver().solve_recaptch(...
Now your final code is
# this function executes the ReCaptcha solver ...
def execute_recaptcha_v2_solver(self, api_key, url_or_field_identifier):
solve_recaptcha_v2 = CaptchaReCaptchaSolver().solve_recaptcha(api_key,
self.extract_data_site_key(self.driver.page_source),
url_or_field_identifier)
javascript_code = 'document.getElementById("g-recaptcha-response").innerHTML = "{}"'.format(solve_recaptcha_v2)
return self.driver.execute_script(javascript_code)

forward return value of x-apikeyInfoFunc to operation

I'm using openapi to define my API. I just added this security schema:
securitySchemes:
api_key:
type: apiKey
name: X-Auth
in: header
x-apikeyInfoFunc: apikey_auth
where apikey_auth is defined like this
def apikey_auth(token, required_scopes):
decrypted_token = None
try:
decrypted_token = mydecrypter.decrypt(token)
except InvalidToken:
raise OAuthProblem('Invalid token')
return {'decrypted_token': decrypted_token}
Now i'd like to use this authentication for my actual endpoints which are defined in openapi like this:
/myendpoint
get:
operationId: operation
#more stuff
security:
- api_key: []
When now calling myendpoint the authentication is being done and works as expected. What I would like to have now is the return value of apikey_auth being passed into the call of operation so i can access decrypted_token in operation like this:
def operation(decrypted_token):
data = get_data_for_token(decrypted_token)
return data
Does anyone have an idea if this is possible somehow without having an extra parameter in the endpoint defintion?
Solved. For whatever reasons with these changes it works:
def apikey_auth(token, required_scopes):
decrypted_token = None
try:
decrypted_token = mydecrypter.decrypt(token)
except InvalidToken:
raise OAuthProblem('Invalid token')
return {'sub': decrypted_token}
def operation(user):
data = get_data_for_token(user)
return data

How to resolve TypeError get() takes exactly 2 arguments (3 given) in Python request using get method

I am getting an error while using Request object in Python.
Below is my code.
class APIDOC(Document):
def request_api(self):
method_type = self.method_type
api = self.api
parameters = self.parameters
session_object = requests.session()
self.get_login(session_object)
if method_type == "POST":
data = {}
for param in parameters:
data[param.key] = param.value
response = session_object.post(api,data)
if response.status_code == 200:
return response.text
else:
return "Error while getting response error code:{0}".format(response.status_code)
elif method_type == "GET":
data = {}
for param in parameters:
data[param.key] = param.value
print("____________________________",data)
response = session_object.get(api,data)
if response.status_code == 200:
return response.text
else:
return "Error while getting response error code:{0}".format(response.status_code)
After reffering one document on requests in python I found below things for "GET" method
r = requests.get('http://httpbin.org/get', params=payload)
But on executing the same I got an error
response = session_object.get(api,data)
TypeError: get() takes exactly 2 arguments (3 given)
To send parameters with a GET, you'll need to specify them by keyword:
session_object.get(api, params=data)

Categories