0

I have completed pset7 and all functionality appears to be working as intended. However, check50 produces the following error:

enter image description here

Since I am unable to find an issues through testing, I am having trouble debugging this error. Any help would be greatly appreciated! My application.py and check50 link is below. Thanks!

check50: https://cs50.me/checks/ab1841b7dca40708a42e32b93fc7f3087666c8a1

import os

from cs50 import SQL
from flask import Flask, flash, redirect, render_template, request, session
from flask_session import Session
from tempfile import mkdtemp
from werkzeug.exceptions import default_exceptions
from werkzeug.security import check_password_hash, generate_password_hash

from helpers import apology, login_required, lookup, usd

# Configure application
app = Flask(__name__)

# Ensure templates are auto-reloaded
app.config["TEMPLATES_AUTO_RELOAD"] = True

# Ensure responses aren't cached
@app.after_request
def after_request(response):
    response.headers["Cache-Control"] = "no-cache, no-store, must-revalidate"
    response.headers["Expires"] = 0
    response.headers["Pragma"] = "no-cache"
    return response

# Custom filter
app.jinja_env.filters["usd"] = usd

# Configure session to use filesystem (instead of signed cookies)
app.config["SESSION_FILE_DIR"] = mkdtemp()
app.config["SESSION_PERMANENT"] = False
app.config["SESSION_TYPE"] = "filesystem"
Session(app)

# Configure CS50 Library to use SQLite database
db = SQL("sqlite:///finance.db")


@app.route("/")
@login_required
def index():
    """Show portfolio of stocks"""

    #update table with current price and value
    rows = db.execute("SELECT * from Transactions")

    for i in range(len(rows)):
        transid = i
        share = lookup(rows[i]["SYMBOL"])
        numshares = rows[i]["NUMSHARES"]
        db.execute("UPDATE Transactions SET CURRPRICE = :currprice, CURRTOTAL = :currtotal WHERE TRANSID = :transid AND id = :user", currprice=round(share["price"],2), currtotal=round((int(numshares) * float(share["price"])),2), transid=transid, user=session["user_id"])

    #Select Stock data
    stocks = db.execute("SELECT SYMBOL,SUM(NUMSHARES) AS sum1,CURRPRICE,SUM(CURRTOTAL) AS sum2 FROM Transactions WHERE id= :user GROUP BY SYMBOL HAVING SUM(NUMSHARES) >0", user=session["user_id"])

    #Select Cash Balance
    cash = db.execute("SELECT cash FROM users WHERE id = :user", user=session["user_id"])

    #Select Total Balance
    total = cash[0]["cash"]
    for t in range(len(stocks)):
       total = total + stocks[t]["sum2"]
    total = round(total,2)

    #render template
    return render_template("index.html", stocks=stocks, cash=cash, total=total)


@app.route("/buy", methods=["GET", "POST"])
@login_required
def buy():
    """Buy shares of stock"""

    # User reached route via POST (as by submitting a form via POST)
    if request.method == "POST":

        # Ensure symbol was submitted
        if not request.form.get("symbol"):
            return apology("must provide symbol", 403)

        # Ensure # of shares was submitted
        try:
            int(request.form.get("shares"))
        except ValueError:
            return apology("must provide shares as a positive integer", 403)

        if int(request.form.get("shares")) < 1:
            return apology("must provide shares as a positive integer", 403)

        #ensure valid symbol
        shares = lookup(request.form.get("symbol"))

        if shares is None:
            return apology("invalid symbol", 403)

        #lookup stock price
        buyprice = shares["price"] * int(request.form.get("shares"))

        #lookup available cash
        cash = db.execute("SELECT cash FROM users WHERE id = :user", user=session["user_id"])

        #determine if sufficient funds
        if buyprice > cash[0]["cash"]:
            return apology("insufficent funds", 403)

        #document transaction
        db.execute("INSERT INTO Transactions (id, SYMBOL, PRICE, NUMSHARES, TRANSPRICE, BUYSELL) VALUES (:user,:symbol,:price,:numshares,:transprice, 'Buy')", user=session["user_id"], symbol=request.form.get("symbol"), price=shares["price"], numshares=request.form.get("shares"),transprice=buyprice)

        #reduce cash value in users
        newcash = cash[0]["cash"] - buyprice
        db.execute("UPDATE users SET cash = :newcash WHERE id = :user", newcash=newcash, user=session["user_id"])

        #return to buy
        return render_template("buy.html")

    # User reached route via GET (as by clicking a link or via redirect)
    else:
        return render_template("buy.html")


@app.route("/history")
@login_required
def history():
    """Show history of transactions"""

    #Select Stock data
    stocks = db.execute("SELECT BUYSELL, SYMBOL, PRICE, NUMSHARES, TIME FROM Transactions WHERE id= :user", user=session["user_id"])

    #render template
    return render_template("history.html", stocks=stocks)


@app.route("/login", methods=["GET", "POST"])
def login():
    """Log user in"""

    # Forget any user_id
    session.clear()

    # User reached route via POST (as by submitting a form via POST)
    if request.method == "POST":

        # Ensure username was submitted
        if not request.form.get("username"):
            return apology("must provide username", 403)

        # Ensure password was submitted
        elif not request.form.get("password"):
            return apology("must provide password", 403)

        # Query database for username
        rows = db.execute("SELECT * FROM users WHERE username = :username",
                          username=request.form.get("username"))

        # Ensure username exists and password is correct
        if len(rows) != 1 or not check_password_hash(rows[0]["hash"], request.form.get("password")):
            return apology("invalid username and/or password", 403)

        # Remember which user has logged in
        session["user_id"] = rows[0]["id"]

        # Redirect user to home page
        return redirect("/")

    # User reached route via GET (as by clicking a link or via redirect)
    else:
        return render_template("login.html")


@app.route("/logout")
def logout():
    """Log user out"""

    # Forget any user_id
    session.clear()

    # Redirect user to login form
    return redirect("/")


@app.route("/quote", methods=["GET", "POST"])
@login_required
def quote():
    """Get stock quote."""

    # User reached route via POST (as by submitting a form via POST)
    if request.method == "POST":

        # Ensure symbol was submitted
        if not request.form.get("symbol"):
            return apology("must provide symbol", 403)

        quote = lookup(request.form.get("symbol"))

        if quote is None:
            return apology("invalid symbol", 403)

        #return quote
        return render_template("quoted.html", quote=quote)

    # User reached route via GET (as by clicking a link or via redirect)
    else:
        return render_template("quote.html")




@app.route("/register", methods=["GET", "POST"])
def register():
    """Register user"""

    # Forget any user_id
    session.clear()

    # User reached route via POST (as by submitting a form via POST)
    if request.method == "POST":

        # Ensure username was submitted
        if not request.form.get("username"):
            return apology("must provide username", 400)

        # Ensure password was submitted
        elif not request.form.get("password"):
            return apology("must provide password", 400)

        # Ensure password was submitted twice
        elif not request.form.get("confirmation"):
            return apology("must provide password twice", 400)

        # Ensure passwords match
        elif not request.form.get("password") == request.form.get("confirmation"):
            return apology("passwords must match", 400)

        # Query database for username
        rows = db.execute("SELECT * FROM users WHERE username = :username", username=request.form.get("username"))

        # Ensure username exists and password is correct
        if len(rows) == 1:
            return apology("username already exists", 400)

        db.execute("INSERT INTO users (username,hash) VALUES (:username,:hashed)", username=request.form.get("username"), hashed = generate_password_hash(request.form.get("password"), method='pbkdf2:sha256', salt_length=8))

        return render_template("login.html")

    # User reached route via GET (as by clicking a link or via redirect)
    else:
        return render_template("register.html")


@app.route("/sell", methods=["GET", "POST"])
@login_required
def sell():
    """Sell shares of stock"""

    # User reached route via POST (as by submitting a form via POST)
    if request.method == "POST":

        # Ensure symbol was submitted
        if not request.form.get("symbol"):
            return apology("must provide symbol", 403)

        # Ensure # of shares was submitted
        try:
            int(request.form.get("shares"))
        except ValueError:
            return apology("must provide shares as a positive integer", 403)

        if int(request.form.get("shares")) < 1:
            return apology("must provide shares as a positive integer", 403)

        if not request.form.get("shares"):
            return apology("must provide shares", 403)

        #ensure valid symbol
        shares = lookup(request.form.get("symbol"))

        if shares is None:
            return apology("invalid symbol", 403)

        #ensure user owns stock
        #Select Stock data
        stocks = db.execute("SELECT SYMBOL,SUM(NUMSHARES) AS sum1 FROM Transactions WHERE id= :user GROUP BY SYMBOL HAVING SUM(NUMSHARES) >0", user=session["user_id"])

        check = 0
        line = 0
        for s in range(len(stocks)):
            if request.form.get("symbol") == stocks[s]["SYMBOL"]:
                check = 1
                line = s

        if check == 0:
            return apology("Stock is not owned", 403)

        #ensure user owns enough shares to sell
        if int(request.form.get("shares")) > stocks[int(line)]["sum1"]:
            return apology("Not enough shares to sell", 403)

        #lookup stock price
        sellprice = shares["price"] * int(request.form.get("shares"))

        #document transaction
        db.execute("INSERT INTO Transactions (id, SYMBOL, PRICE, NUMSHARES, TRANSPRICE, BUYSELL) VALUES (:user,:symbol,:price,:numshares,:transprice, 'Sell')", user=session["user_id"], symbol=request.form.get("symbol"), price=shares["price"], numshares=request.form.get("shares"),transprice=sellprice)

        #lookup available cash
        cash = db.execute("SELECT cash FROM users WHERE id = :user", user=session["user_id"])

        #increse cash value in users
        newcash = cash[0]["cash"] + sellprice
        db.execute("UPDATE users SET cash = :newcash WHERE id = :user", newcash=newcash, user=session["user_id"])

        #return to sell
        return render_template("sell.html")

    # User reached route via GET (as by clicking a link or via redirect)
    else:
        return render_template("sell.html")

@app.route("/deposit", methods=["GET", "POST"])
@login_required
def deposit():
    """Deposit Cash"""

    # User reached route via POST (as by submitting a form via POST)
    if request.method == "POST":

        # Ensure symbol was submitted
        if not request.form.get("deposit"):
            return apology("must provide deposit", 403)

        #Select Cash Balance
        oldcash = db.execute("SELECT cash FROM users WHERE id = :user", user=session["user_id"])

        #Find New Balance
        newcash = int(oldcash[0]["cash"]) + int(request.form.get("deposit"))

        #Update Table
        db.execute("UPDATE users SET cash = :newcash WHERE id = :user", newcash=newcash, user=session["user_id"])

        #Return
        return render_template("deposit.html")

    # User reached route via GET (as by clicking a link or via redirect)
    else:
        return render_template("deposit.html")

def errorhandler(e):
    """Handle error"""
    return apology(e.name, e.code)


# listen for errors
for code in default_exceptions:
    app.errorhandler(code)(errorhandler)
3
  • I ran check50 cs50/2018/x/finance from the CS50 IDE v157 on this application.py and did not receive an error on logging in as registered user. I checked the cs50 status page; there is no indication there has been any recent problems with check50. Maybe a check50 hiccup? I avoid this advice whenever possible, but I think "try again" is the next thing to do. If the problem "goes away" Yay! If the problem persists, I believe you can email sysadmins@cs50.harvard.edu (however it is a holiday in US....) Jan 1 '19 at 16:12
  • lookup sometimes returns a None if the API does not work for whichever reason (like busy or call quota exceeded), more likely to hit people doing more calls than necessary. You could for example refactor your code in index to do a lookup per symbol, not per transaction. Also, current value is nothing one needs to store in the transaction table. If you need to pass the extra info to your template, the result of a database query is mutable (both the list and the dicts within), so you can augment it in between. That last part won't affect lookup problems, though.
    – Blauelf
    Jan 2 '19 at 10:26
  • This worked! I rewrote index to lookup by symbol and the error disappeared. Cleaned up the rest and submitted all green :). Thanks @Blauelf and @DinoCoderSaurus!
    – Josh
    Jan 2 '19 at 18:59
0

lookup sometimes returns a None if the API does not work for whichever reason (like busy or call quota exceeded), more likely to hit people doing more calls than necessary. You could for example refactor your code in index to do a lookup per symbol, not per transaction.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .