how to test a function inside a class [python, pyCharm] - python

i am teaching myself coding right now via the udacity.web_development course. my coding is geting allright but i regularly have problems that are related to the process and not the code.
like right now:
i dont know how to test this function (passwort_check) while it is inside a class. i cant call it.
when i put "print MainHandler.passwort_check((self or MainHandler), "string")" in the bottom it gives me a type error.
i know right now all this webhandlerstuff is useless. but i need it there for later. to comment everything out, but the one function i need cannot be the right solution.
this is my code:
import webapp2
import re
class MainHandler(webapp2.RequestHandler):
def get(self):
self.response.write('Hello world!')
def passwort_check(self, passwort_string):
if re.match("^[a-zA-Z0-9_-]{3,20}$", passwort_string):
print passwort_string
else: print "change pw"
print MainHandler.passwort_check(MainHandler,"hallo")
app = webapp2.WSGIApplication([
('/', MainHandler)
], debug=True)
this is my error:
TypeError: unbound method passwort_check() must be called with MainHandler instance as first > argument (got type instance instead)
but my question is more generall: how do you guys or professionals/experianced coders do codevalidation in this case

You need to create an instance of class MainHandler first. Like:
my_handler = MainHandler()
Then invoke function in it. Like:
my_handler.passwort_check('passwort_string')
If you need to do some unittest for this. Check this link. It will give you some instructions.
Hope it helps.:)

Given that MainHandler.passwort_check does nothing with the self parameter, you could -- at least for now -- define it as a static method. Unlike normal methods declared inside a class definition, static methods do not implicitly receive the instance upon which they are called as their first argument. In fact, they need not be called on any instance at all.
#staticmethod # This is called a "decorator"
def passwort_check(passwort_string) # Omit self from the parameters
# The rest of your code remains the same
Then you can simply call it the way you were doing, but you don't need to dummy an instance to pass as the first parameter.
MainHandler.passwort_check('string')
should work fine.
(Of course, if you just want to test the regex, it might be easier to simply use a regex tester site like Regex101.)

Related

How does the route decorator used in Flask work

I'm familiar with the basics of Python's decorators. However I don't understand how this specific decorator, as used for Flask routes, works.
Here is a code snippet from the Flask website:
from flask import Flask, escape, request
app = Flask(__name__)
#app.route('/')
def hello():
name = request.args.get("name", "World")
return f'Hello, {escape(name)}!'
.route('/') is the part which confuses me. The way I've seen decorators being used is that the decorator annoation is usually a function, which takes one argument, which is the decorated function itself, which can then be executed inside the decorator. But this seems to be different here.
Thank you.
Update: Thanks for the hint about self in my second code snippet. Being new to Python I totally forgot that something's first argument has to be self. At second glance, I don't think that the example helps to clarify the question and have therefore removed it.
It sounds like you have a couple misconceptions that we can hopefully clear up. Firstly, a decorator is just a term (and some language "sugar", the #decorator syntax) for a callable that accepts a callable and returns another callable. This callable can be a function (e.g., def foo(func)) or a method (e.g., obj.method(func)) -- it just needs to be something that accepts a callable and returns one.
In the case of Flask's #app.route decorator, you're passing your hello function to an object's (the flask.Flask object I believe) route method. In turn it adds your function and its associated configuration to its own "memory" for routing once the Flask application is told to begin serving requests.
Secondly, your example has def something(arg1, arg2): -- the first argument passed to an object's method when called is the object instance, usually called self
The Primer on Python Decorators article might be a good place to get started to read up on how/why they work the way they do.
A decorator is simply a function that accepts a function as a parameter and returns another function. A decorator that accepts arguments (like flask's route decorator) must return a function that can be used as a simple decorator.
For example, we could write that route decorator like this:
routes = {}
def route(path):
def inner(func):
global routes
routes[path] = func
return func
return inner
Calling route('/') returns a function that takes a function as an argument, which updates the global routes variable using the value of path passed to the outer function and the func value received by the inner function.
If we use that on a couple of functions:
#route('/')
def func1():
...
#route('/example')
def func2():
...
Then we can inspect the routes variable and see that it now maps paths to the appropriate functions. Running:
print(routes)
Produces something like:
{'/': <function func1 at 0x7f0c4aeac050>, '/example': <function func2 at 0x7f0c4aeb1e60>}

Why doesn't __name__ work in this case? AttributeError Raised

I am new to programming so when I wanted a command to turn a hard-coded function's name into a string, I looked it up and started using the built-in __name__ function. The problem is that I don't think I understand how __name__ retrieves the wanted name. I know it has something to do with what is currently visible with local() or dir() but that's about it... (my own research on this topic has been kinda of hard to understand for me) As a result, I stumbled across an error that I don't know how to solve.
Here is some code that recreates my error:
class Abc:
#staticmethod
def my_static_func():
return
def my_method(self):
return
class_list = [my_static_func]
method_list = [my_method]
#These calls work
Abc.my_static_func.__name__
Abc.my_method.__name__
Abc.method_list[0].__name__
#But This call raises an AttributeError
Abc.class_list[0].__name__
I get this error message:
AttributeError: 'staticmethod' object has no attribute '__name__'
So why is that when I put my static method into a list and then try to get the function's name from the list it doesn't work? Please forgive me if this question is dumb. As you can clearly see, I don't understand the underlying principle of how __name__ works (and other stuff that I just don't know about to even give these topics names!). An answer would be nice but a reference to some docs would be also welcome.
With this code
#staticmethod
def my_static_method(...):
....
The function my_static_method is wrapped in a staticmethod. When you access a staticmethod from a class some magic happens to the staticmethod and you actually get a proper function back. Thats why you can access its __name__
Putting the staticmethod in a list and accessing it from that list prevents the magic from happening and you get the staticmethod object back.
Abc.my_static_func # this is a function
Abc.class_list[0] # this is a staticmethod object
As a staticmethod does not have a __name__ you get an AttibuteError when accessing its __name__.
To solve your problem you could get the underlying function from the staticmethod
Abc.class_list[0].__func__ # the function
Abc.class_list[0].__func__.__name__ # its name
To find out more about the "magic" that happens when you access attributes/methods from a class/object look up descriptors

PyCharm not recognizing new class method without reload

I think this is a really silly / dumb question, but I am using PyCharm and constantly adding methods to a class or changing the body of the methods. When I test the class by importing the .py file and initiating the class object, it doesnt seem to recognize the changes to the class.
Is there some button I need to hit to make sure that the class code is changed.
The only thing that seems to work for me is to restart PyCharm.
When you import the class, it imports it as-is at the current time. If you make changes after that, you need to import it again. In this case, you should just be able to terminate the shell, and start it again.
This is not an error, or a bug.
There many variations of the issue you have stated.
One issue I have faced is having two classes in the module - one containing another's object.
e.g.
class y:
#classmethod
def f1():
print('old')
class x:
def __init__(self):
self.ref_cls = y()
def test():
self.ref_cls.f1() # <-- "line to change"
Now if I place a breakpoint over "line to change" and want to redef f1 to print 'new' instead of 'old', I open the evaluator and add following code:
class new: # <-- if you write 'y' instead of new it does not work
#classmethod
def f1():
print('new')
self.ref_cls = new
Evaluate this and then step over to confirm in the console.
This works for static methods and object methods as well.
Hope this helps.

How to access a function contained within a class in another module

This should be relatively simple, but I'm just missing something. I am trying to utilize a function from another module which is contained within a class. I can do it easily when there is no class involved.
# a.py
import b
b.name()
--
# b.py
def name():
print "What is your name?"
class details(object):
def age():
print "What is your age?"
When I run a i get the expected result of
What is your name?
However when i try to access "def age()" from another module it keeps giving me trouble.
Some of what I have tried so far...
# c.py
import b
b.details.age()
= TypeError: unbound method age() must be called with details instance as first argument (got nothing instead)
# c.py
from b import details
details.age()
= TypeError: unbound method age() must be called with details instance as first argument (got nothing instead)
# c.py
from b import details
b.details(age)
= NameError: name 'b' is not defined
I have tried a few others as well but too many to reasonably post. What am i doing wrong? What is the syntax to do do this? Is it even possible to execute a function when it is contained within a class in another module?
Thanks in advance
EDIT: Fixed all tabs to spaces as suggested by Mike Graham
The first parameter of all class methods in Python is a reference to the current object (normally this is called self). However, that said, you seem to be trying to use it as a static method and not as an instance method, so perhaps you meant to use the #staticmethod decorator:
class Details: # class names in Python should generally be CamelCased.
# please note the comments below
#staticmethod
def age():
print 'What is your age?'
Or, if you really want it to be an instance method, then you need to add self and change how you're referencing it:
class Details:
def age(self):
print 'What is your age?'
# c.py
from b import Details
#you must create an instance of the class before you can call methods on it.
d = Details()
d.age()
EDIT
As noted in the comments, it is rare that #staticmethod has a genuine use case (it is often better to organize your code with modules, for example). You will often come across #classmethod as an alternative. Please note, though, that methods decorated with #classmethod have a reference to the current class as the first parameter. This question addresses the major differences.

Function call in Google App Engine - Python

In main.py I have a display code that repeats several times. So I created a f1.py and placed the code in f1.py as a function display(query) and I am calling it from main.py as f1.display(query).
But display(query) has the line
self.response.out.write(
# some code
)
and I get the error message:
self.response.out.write(
NameError: global name 'self' is not defined
I tried to import from google.appengine.ext import webapp inside the display(query) function but that did not help.
What am I doing wrong and how can I fix it? Thanks!
self is a conventional name for the first argument passed to a class instance's methods. A class instance will pass a reference to itself as the first argument to all of it's methods when they are called. It's common practice to name the first parameter for instance methods self.
So, when you factored out part of your method's (presumably get or post on a sublcass of webapp.RequestHandler) functionality to another function, you can no longer refer to self and get the response property.
The easiest way to fix this would probably be to return the output you wish to write to the response in the function. Then you can call self.response.out.write with your function's return value from within in the method as you did before the refactor.

Categories