Can Factory Boy fields be set to require user input? - python

I thought this was a trivial question but to my surprise, I couldn't find an answer.
Consider I have a factory named Foo. It has a normal field named "name" and another field named user_input for which I want to force the user to pass a value on initialization, and get an error if they don't do so. How can I achieve this?
import factory
class FooFactory(factory.Factory):
name = factory.Faker("name")
user_input = ?
# I want this to work:
foo = FooFactory(user_input="blah blah")
# and this to throw an error:
foo = FooFactory()

The solution would be to use a factory.lazy_attribute:
class FooFactory(factory.Factory):
name = factory.Faker("name")
#factory.lazy_attribute
def user_input(self):
raise ValueError("FooFactory.user_input is required")
>>> FooFactory()
Traceback (most recent call last):
File "...py", line 7, in user_input
ValueError: FooFactory.user_input is required
>>> FooFactory(user_input=42)
{"name": "John Doe", "user_input": 42}

Related

how to make a method for a string in python

Im looking to create something that I can use to check if a string meets a condition like so:
var = "hello"
check = var.checkconditions()
Im just curious as to if its possible as I have never seen it done before.
How would the function/whatever I need to use be set out?
String is a build in class/object and can not be changed. However you can make a personal new class:
class str_class:
def __init__ (self, str):
self.str = str
def checkconditions(self):
# Enter your conditions
var = str_class('hello')
check = var.checkconditions()
Or you could simply make a funtion that takes the string as input and outputs if the condition is met or not:
def checkconditions(str):
# Enter conditions
var = 'Hello'
check = checkconditions(var)
Edit: From other comments it seems as though it is possible but not recommended.
You can use a Class and then use the method check_conditions.
class Check:
def __init__(self):
pass
def check_conditions(string):
#Do whatever you need in here
print(string)
c = Check
c.check_conditions("hello")
This should hopefully do what you need!
You can't directly add the method to the original type.what you can do is subclass the type like
class mystring(str):
def checkconditions(self):
#condition
and then you can instantiate your new class
var = mystring('hello')
var.checkcondition()
but that's still no too practical, if you want to make it more proper you can do this
import __builtin__
__builtin__.str = mystring
var = str("hello")
check = var.checkconditions()
which achieves most of the effect desired.
Unfortunately, objects created by literal syntax will continue to be of the vanilla type and won't have your new methods/attributes.
var = 'hello'
var.checkconditions()
# Output
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'str' object has no attribute 'checkconditions'
"""

Python exercise problem - Name error when running function

I am doing a python course and one of the exercises is to write a function that adds "Doctor" to a name. The instructions are:
Define function make_doctor() that takes a parameter name
get user input for variable full_name
call the function using full_name as argument
print the return value
My code is:
def make_doctor(name):
full_name = input("Doctor ")
return full_name
print(make_doctor(full_name))
However, I keep getting the below error:
NameError Traceback (most recent call last)
<ipython-input-25-da98f29e6ceb> in <module>()
5 return full_name
6
----> 7 print(make_doctor(full_name))
NameError: name 'full_name' is not defined
Can you anybody help please?
Thanks
You code has lots of issues.
Have the input be outside the function. Pass the input to make_doctor to add "Doctor" to it, and then print that.
Very important side note: Use raw_input() if python2 and input() if python3. dont use input() in python 2 its an expression evaluator rather than a string.
def make_doctor(name):
return "Doctor {}".format(name)
name = raw_input("Enter your name here!!") # if python2
# name = input("Enter your name here!!") # if python3
print(make_doctor(name=name))
In your code the variable full_name is a local variable to the function make_doctor
Try this :
def make_doctor(name):
return "Doctor "+name
full_name = input()
print(make_doctor(full_name))

Can I access a class without an __init__? - Python

I want to be able to print "hello harry" from a module. This is my module (called test23):
class tool:
def handle(self,name):
self.name = "hello " + name
This is my script:
import test23
harry= test23.tool().handle(" harry")
print harry.name
I can't seem to print "hello harry" inside my script idle. How would I go about doing this?
handle doesn't return anything, so harry will be NoneType.
Do it in two times: first assign the instance, then call the method:
>>> class tool:
... def hello(self,name):
... self.name="hello "+name
...
>>> a=tool()
>>> a.hello('i')
>>> a.name
'hello i'
>>> b=tool().hello('b')
>>> b.name
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'name'
>>> type(b)
<type 'NoneType'>
I think this will do it.
from test23 import tool
harry = tool()
harry.handle("harry")
print harry.name
tool.handle() doesn't return an object, so you need to store the object before you call the method:
import test23
harry = test23.tool()
harry.handle("harry")
print harry.name
What you wanted to do is:
harry = test23.tool() # Ok harry is a tool object
harry.handle(" harry") # Ok harry.name has been set to " harry"
print harry.name # Ok print successfully "hello harry"
But what you did is: harry= test23.tool().handle(" harry")
Let's look one pass at a time:
test23.tool() : builds a new (temporary) tool object
test23.tool().handle(" harry") : sets the attribute name of the temporary and returns... None!
harry= test23.tool().handle(" harry") : sets the attribute name of a temporary tool object, set harry to the return value of the handle method which is None => same as harry = None
Alternatively, you should change handle to return the tool object:
class tool:
def handle(self,name):
self.name = "hello " + name
return self

Python: how to print detailed error messages about errors?

I'd like to get detailed info about each variable treatment error.
Example 1:
user = User()
print(user.name)
...
AttributeError: variable 'user' (class User) doesn't have field 'name', there are only: full_name, address, telephone, email
Example 2:
some_nums = [1, 2, 3]
print(some_nums[3])
...
IndexError: attempt to get #4 'some_nums' list's elem; it has only 3 elems
I known i can wrap each method in my program in individual try-expect block and print such message in the except clause in each of them.
But it there any way to collect local variables data, automatically pass it to top single try-except block and print such messages there?
I saw something like in py.test library. It overrides builtin python assert's and prints detailed message in stack trace when assert falls
https://pytest.org/latest/assert.html
You can override the magic method __getattribute__ if you want to
class HelpfulErrors(object):
def __getattribute__(self, name):
try:
return object.__getattribute__(self, name)
except:
raise AttributeError("class {} doesn't have field '{}', there are only: {}".format(self.__class__.__name__, name, ", ".join(self.__dict__.keys())))
class User(HelpfulErrors):
def __init__(self, age=21):
self.age = age
self.can_drink = self.age >= 21
u = User()
print(u.age)
print(u.can_drink)
print(u.name)
OUTPUT
21
True
Traceback (most recent call last):
File "mes.py", line 18, in <module>
print(u.name)
File "mes.py", line 6, in __getattribute__
raise AttributeError("class {} doesn't have field '{}', there are only: {}".format(self.__class__.__name__, name, ", ".join(self.__dict__.keys())))
AttributeError: class User doesn't have field 'name', there are only: can_drink, age
This really only tells you what is currently in the classes __dict__ though, so this could change over time unless all instance members that will ever be available are defined by the time __init__ is finished.

Python: creating a temporary name for a specific function

I'm learning Python. I'm reading some code containing something like this:
class Menu:
'''Display a menu and respond to choices when run.'''
def __init__(self):
self.notebook = Notebook()
self.choices = {
"1": self.show_notes,
"2": self.search_notes,
"3": self.add_note,
"4": self.modify_note,
"5": self.quit
}
def display_menu(self):
print("""
Notebook Menu
1. Show all Notes
2. Search Notes
3. Add Note
4. Modify Note
5. Quit
""")
def run(self):
"""Display the menu and respond to choices."""
while True:
self.display_menu()
choice = input("Enter an option: ")
action = self.choice.get(choice)
if action:
action()
else:
print("{0} is not a valid choice".format(choice))
def show_notes(self):
pass
def search_notes(self):
pass
def add_note(self):
pass
def modify_note(self):
pass
def quit(self):
pass
There are some lines very interesting:
action = self.choice.get(choice)
if action:
action()
Seems it's creating a temporary name for a specific function.
So I did the following test for it to learn more:
>>> def show_notes():
print("show notes")
>>> def search_notes():
print("search notes")
>>> choice = {"1": show_notes, "2": search_notes}
>>> action = choice.get(1)
>>> action()
But I get the following error:
Traceback (most recent call last):
File "<pyshell#64>", line 1, in <module>
action()
TypeError: 'NoneType' object is not callable
Can someone tell me what the technique is and what principle is behind?
Functions are first class objects, and you can create additional references to them. These are just as temporary as you need to them to be, but they can be permanent too.
Your own attempt confused strings and integers however; you used 1 (an integer) where the actual key is '1' (a string). Because you used the wrong key, the dict.get() method returned a default instead, None. None is not a function object and the call fails.
Had you used the right key your code would have worked too:
>>> def show_notes():
... print("show notes")
...
>>> def search_notes():
... print("search notes")
...
>>> choice = {"1": show_notes, "2": search_notes}
>>> choice['1']
<function show_notes at 0x10b1fae18>
>>> choice['1']()
show notes
You can make use of dict.get() returning a default here too, by giving the method a better default to return:
>>> choice.get('none-such-key', search_notes)()
search notes
It seems there's an error in your test. You should be getting "1" and not 1. Getting 1 is returning None because there's nothing defined for key 1. Therefore when you call it like a function it's not valid.
To clarify, "1" is a string and 1 is an integer, which are different keys.
Example:
>>> a = {"1": "yes"}
>>> a.get(1)
>>> a.get("1")
'yes'
Example II (using function):
>>> def hello():
... print "hello"
...
>>> hello()
hello
>>> a = {"1": hello}
>>> b = a.get(1)
>>> b()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'NoneType' object is not callable
>>> b = a.get("1")
>>> b()
hello
It's not creating a random name for a function. The class method choice is selecting a function and returning it, and it is subsequently being assigned to the variable action. The function is then called by calling action, like you would any function.
Here's an example:
def foo():
print(5)
def getFunction():
return foo
x = getFunction()
x()
The output from this will be 5.
Taking a step back from all of this, you can assign any object to any variable. So consider the following example (I think this will help you understand a little bit more):
def foo():
print(5)
bar = foo
foo = 5
foo()
This will produce an error along the lines of integer objects are not callable. The way this works is that the function object contained in foo is being assigned to variable bar, and the integer 5 is being assigned to foo. The function hasn't changed, but the variable containing it has.
The very first part of defining a function def foo is letting the interpreter know that you are defining a function object and storing in the variable foo. The name and the mechanics of the function are separate.
Does this make sense?

Categories