How to have two outputs in a def - python-3.x

I can't add two output to def function.
I have tried many ways but it always outputs only one of them if true or false.
loan_True = True
loan_False = False
def message():
if loan_True == True:
print()
message = f"""\
Subject: Loan Application
Hello {Fn} {Ln}, {hurray}
"""
elif loan_False == False:
print()
message = f"""\
Subject: Loan Application
Hello {Fn} {Ln}, {sorry}
"""
return message
message()
Output of code that is correct and exactly what i wantThis is the email the code sends but its wrong. i want the output in the email to be the same exact in the first pic.
I want the output to be what it is assigned.

I would propose something like
def message(loan_allowed):
if loan_allowed:
return "hooray"
else
return "sorry"
I.e. use function parameters instead of global variables. If you want to use a variable in the function I would use
def message(loan_allowed):
text = None
if loan_allowed:
text = "hooray"
else
text = "sorry"
return text
I.e. first set it in function scope. And use a different name than the function.

Related

Unittesting for correct 'continue' behaviour

I have a function that asks a user for confirmation via a prompt. It accepts y or n as answers, otherwise it asks again.
Now, I want to write a unittest for this function. I can test the correct behaviour for y or n just fine, but how do I test that my function correctly rejects inacceptable input?
Here's the code for foo.py:
def get_input(text):
"""gets console input and returns it; needed for mocking during unittest
"""
return input(text)
def confirm(message='Confirm?', default=False):
"""prompts for yes or no response from the user. Returns True for yes and
False for no.
'default' should be set to the default value assumed by the caller when
user simply types ENTER, and is marked in the prompt with square brackets.
"""
if default:
message = '%s [y]|n: ' % (message) # default answer = yes
else:
message = '%s y|[n]: ' % (message) # default answer = no
while True:
answer = get_input(message).lower()
if not answer:
return default
if answer not in ['y', 'n']:
print('Please enter y or n!')
continue
if answer == "y":
return True
if answer == 'n':
return False
answer = confirm()
print(answer)
And here is my Test class:
import unittest
import foo
class TestFoo_confirm(unittest.TestCase):
"""testing confirm function
"""
#unittest.mock.patch('foo.get_input', return_value='y')
def test_answer_yes(self, _):
self.assertEqual(foo.confirm(), True) # confirmed if 'y' was entered
So, how do I write a similar test for an input-value like '1' (or how do I need to adjust my confirm() function to make it testeable)?
Currently, if I call foo.confirm() from the unittest file, it just gets stuck in an infinite loop and it doesn't return anything. (I understand why this is happening, just not how to circumvent it.)
Any ideas?
You could try this:
import unittest, unittest.mock
import foo
class TestFoo_confirm(unittest.TestCase):
"""testing confirm function
"""
#unittest.mock.patch('foo.get_input', return_value='y')
def test_answer_yes(self, _):
self.assertEqual(foo.confirm(), True) # confirmed if 'y' was entered
#unittest.mock.patch('builtins.print')
#unittest.mock.patch('foo.get_input', side_effect=['1','yn','yes','y']) # this will make the mock return '1', 'yn' and so on in sequence
def test_invalid_answer(self, mock_input, mock_print):
self.assertEqual(foo.confirm(), True) # it should eventually return True
self.assertEqual(mock_input.call_count, 4) # input should be called four times
mock_print.assert_called_with('Please enter y or n!')
In the second test case, we imitate a user who enters three invalid inputs, and, after being prompted again, finally enters 'y'. So we patch foo.get_input in such a way that it returns 1 the first time it's called, then yn, then yes and finally y. The first three examples should cause the confirm function to prompt the user again. I also patched the print function, so that the 'Please enter y or n!' message wouldn't show up when testing. This isn't necessary.
Then we assert that our mock input was called four times, meaning that the first three times, the confirm function reprompted.
Finally we assert that the print function was called (at least once) with 'Please enter y or n!'.
This does not test if the correct number of print statements were made or if they were in correct order, but I suspect this would be possible too

Function that to exit from other function

I wanted to create to a function which, when called in other function it exits the previous function based on the first function's input.
def function_2(checking):
if checking == 'cancel':
# I wanted to exit from the function_1
def function_1():
the_input = input("Enter the text: ")
function_2(the_input)
I wanted the code for the function_2 so that it exits from function_1, I know that I can put the if statement in function_1 itself but ill use this to check more than one in input in the same function or even in different function I cant put the if block everywhere it will look unorganized so i want to create a function and it will be convenient to check for more than one word like if cancel is entered i wanted to exit the programm if hello is entered i wanted to do something, to do something its ok but to exit from the current function with the help of other function code please :) if any doubts ask in the comment ill try to give you more info im using python 3.x.x on Windows8.
Why not simply:
def should_continue(checking):
if checking == 'cancel':
return False
return True
def function_1():
the_input = input("Enter the text: ")
if not should_continue(the_input):
return
This is the best solution I think.
Another alternative is to raise an Exception, for example:
def function_2(checking):
if checking == 'cancel':
raise KeyboardInterrupt
def function_1():
the_input = input("Enter the text: ")
function_2(the_input)
try:
function_1()
except KeyboardInterrupt:
print("cancelled by user")

How can I test a loop with multiple input calls?

I'm trying to test a fuction that dependets a of multiple user inputs to return some value.
I've already looked for multiples unswers here but none was able to resolve my problem. I saw things with parametrize, mock and monkey patch but none helped. I think a lot is because I don't clearly understood the concepts behind what was being done and I couldn't adapt to my problem. I saw suggestion of using external file for this but I don't wont to depend on that. I'm trying with pytest and python 3.7.3
The function that I want to test is something like this
def function():
usr_input = input('please enter a number: ')
while True:
if int(usr_input) < 5:
usr_input = input('please, enter a value less then 5: ')
else:
break
return usr_input
I want to know how can I pass two input values to test the function when the inserted value is not valid. Example: Send value 6 and 2, make an assert expecting value 2 and pass the test. My others tests look like this:
def test_input(monkeypatch):
monkeypatch.setattr('builtins.input', lambda x: 6)
test = function()
assert test == 2
but, for this case, they loop. It's possible to do this only with parametrize or other simple code?
EDIT
I added a int() in my "if", as wim pointed in the accepted answer, just to prevent any confusion for future readers. I'm assuming the cast is possible.
Two problems here, you need to convert the input into a number otherwise the comparison will fail, comparing a string with a number: usr_input < 5. Note that the real input will never return a number, only a string.
Once you've cleared that up, you can monkeypatch input with a callable that can return different values when called:
def fake_input(the_prompt):
prompt_to_return_val = {
'please enter a number: ': '6',
'please, enter a value less then 5: ': '2',
}
val = prompt_to_return_val[the_prompt]
return val
def test_input(monkeypatch):
monkeypatch.setattr('builtins.input', fake_input)
test = function()
assert test == 2
If you install the plugin pytest-mock, you can do this more easily with the mock API:
def test_input(mocker):
mocker.patch('builtins.input', side_effect=["6", "2"])
test = function()
assert test == 2

problems to handle more than one (return) parameter in main()

I'm rewriting an old keyword-scanner from Python2 to Python3 and have problems to handle more than one return parameter in my final main()-function.
def scanner_pref():
dork = input('Dork: ')
number = input('Number of sites: ')
return dork, number
So, I need to return dork and number to the next function
def scanner(dork, number):
url = "http://www.google.de/search"
payload = {'q': dork, 'start':'0', 'num': int(number) *10}
[..]
so the scanner can proceed with the given parameters of payload.
But when I try to write the main()-function, it can't handle the scanner-function, because it suddendly requires the numbers parameter. see below
def main():
pref = scanner_pref()
scan = scanner(pref) <--
parser(h3tag=scan)
I don't really understand why scan = scanner(pref, ?) requires the number parameter when it receives the information from the scanner(pref) above and doesn't really care about the dork-parameter.
If I remove "number" from scanner_pref(), move it back to scanner(..) it works fine and no error or warning message appears.
def scanner_pref():
dork = input('Dork: ')
return dork
#
def scanner(dork, number):
url = "http://www.google.de/search"
number = ("Number of sites: ")
payload = {'q': dork, 'start':'0', 'num': int(number) *10}
#
def main():
pref = scanner_pref()
scan = scanner(pref)
parser(h3tag=scan)
works fine and without problems
scanner(dork, number) takes two arguments.
When you call pref = scanner_pref() the values dork and number are stored in perf as a tuple. When you pass pref to scanner you are still only passing one argument, a tuple with two values.
you have two easy options
pref_dork, pref_number = scanner_pref()
scan = scanner(pref_dork, pref_number)
or
pref = scanner_pref()
scan = scanner(pref[0],perf[1])

how compare a str object with None

I have meet a problem, when I develop a web use python3+flask, when name has no in put, I am confused, the result is True in print
name = request.args.get('name')
if name is not None:
print('True')
else:
print('False')
I refer to python documents, "A is not B" means A and B is not same object.
And I make the following test:
print(name) #None
print(type(name)) #<class "str">
print(type(None)) #<class "NoneType">
I found the answer, but when I use the following format
if name:
print('True')
else:
print('False')
it prints True and print(name) I get None
I have to write like the following:
if name != str(None):
print('True')
else:
print('False')
I feel it a little uncomfortable when use it like this, how I can compare it in a elegant way.
Getting a string "None" as part of a request commonly happens when you return a None value as part of a previous response.
Example:
# given a variable that is passed to a jinja template as None
# instead of as an empty string
name = None
Will result in a link with "None" as a string.
<a href="/some/link?name={{ name }}>click here</a>
Instead of trying to handle for a string "None" in any given request where you expect a string, you should output the original variable as an empty string:
name = None
...
# convert Nones to empty strings right before sending to jinja
if not name:
name = ''
print(True if "None" not in name else False)
I think that's more elegant way of printing out in your case.

Resources