0

I get a NameError: global name 'valid_username' is not defined which confuses me. Why does that happen? I declared the valid_username function before actually calling it so what's the problem?

Here's the code full code:

import webapp2
import cgi
import re

class WelcomeHandler(webapp2.RequestHandler):
    def get(self):
        self.response.out.write("Welcome, ")


class MainPage(webapp2.RequestHandler):
    def write_form(self, username="", username_error="", password_error="", verify_password_error="", email="",
                   email_error=""):
        self.response.out.write(form % {
            "username": username, "username_error": username_error,
            "password_error": password_error,
            "verify_password_error": verify_password_error,
            "email": email, "email_error": email_error})

    def checkEscaped(text):
        return cgi.escape(text, quote="True")

    def valid_username(username):
        USER_RE = re.compile(r"^[a-zA-Z0-9_-]{3,20}$")
        return USER_RE.match(checkEscaped(username))

    def valid_password(password):
        PASSWORD_RE = re.compile(r"^.{3,20}$")
        return PASSWORD_RE.match(checkEscaped(password))

    def valid_email(email):
        if len(email) > 0:
            EMAIL_RE = re.compile(r"^[\S]+@[\S]+\.[\S]+$")
            return EMAIL_RE.match(checkEscaped(email))
        else:
            return True

    def password_match(password, confirmPassword):
        return password == confirmPassword

    def get(self):
        self.write_form()

    def post(self):
        input_username = self.request.get('username')
        input_password = self.request.get('password')
        input_verify_password = self.request.get('verify_password')
        input_email = self.request.get('email')

        username_error = ""
        is_valid_name = valid_username(input_username)
        if not is_valid_name:
            username_error = "That's not a valid username."

        password_error = ""
        is_valid_password = valid_password(input_password)
        if not is_valid_password:
            password_error = "That wasn't a valid password."

        verify_password_error = ""
        is_valid_verify_password = password_match(input_password, input_verify_password)
        if not is_valid_verify_password:
            verify_password_error = "the passwords don't match"

        email_error = ""
        is_valid_email = valid_email(input_email)
        if not is_valid_email:
            email_error = "that's not a valid email"

        if not (is_valid_name and is_valid_password and is_valid_verify_password and is_valid_email):
            self.write_form(name, username_error, password_error, verify_password_error, email, email_error)
        else:
            self.redirect("/welcome")


app = webapp2.WSGIApplication([
    ('/', MainPage), ('/welcome', WelcomeHandler)], debug=True)
nsmirosh
  • 45
  • 2
  • 8

1 Answers1

3

You need to reference methods on the instance via the self object:

is_valid_password = self.valid_password(input_password)

You have the same problem in other places too; checkEscaped() should be self.checkEscaped(), password_match() should be self.password_match(), etc.

Methods are not globals or locals.

Next, your methods should accept a self reference too; each of your own methods is missing the required parameter:

def checkEscaped(self, text):
    # ...

def valid_username(self, username):
    # ...

def valid_password(self, password):
    # ...

def valid_email(self, email):
    # ...

def password_match(self, password, confirmPassword):
    # ...

Of course, you could just move those four methods out of the class and actually make them global functions instead of methods. In that case, leave off the self arguments again.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • And most of the OP code's method definitions are missing `self` args, too. – PM 2Ring Jul 25 '15 at 14:34
  • @PM2Ring yep, you're right. Coming from java - these function calls are implicit there – nsmirosh Jul 25 '15 at 14:36
  • @nsmirosh: Fair enough. We do OOP a little differently in Python. But I'm sure you'll soon get the hang of it. :) – PM 2Ring Jul 25 '15 at 14:40
  • @PM2Ring Why do you need to pass 'self' everywhere in functions? – nsmirosh Jul 25 '15 at 14:42
  • @nsmirosh Take a look at [What is the purpose of self in Python?](http://stackoverflow.com/q/2709821/4014959). Also [Why must ‘self’ be used explicitly in method definitions and calls?](https://docs.python.org/3/faq/design.html#why-must-self-be-used-explicitly-in-method-definitions-and-calls) – PM 2Ring Jul 25 '15 at 14:49
  • 1
    @nsmirosh: you only need those in *methods*, because that's how Python gives you access to the current instance. – Martijn Pieters Jul 25 '15 at 14:50