Applied auto pep 8 changes

This commit is contained in:
Luke Else 2024-01-21 22:06:06 +00:00
parent f227727c74
commit 44c1ee03ba
22 changed files with 156 additions and 100 deletions

3
app.py
View File

@ -7,6 +7,8 @@ from controllers.web.endpoints import blueprint
Initialises any components that are needed at runtime such as the Initialises any components that are needed at runtime such as the
Database manager... Database manager...
''' '''
def main(): def main():
app = Flask(__name__) app = Flask(__name__)
@ -23,5 +25,6 @@ def main():
app.register_blueprint(blueprint) app.register_blueprint(blueprint)
app.run(debug=True, host="0.0.0.0") app.run(debug=True, host="0.0.0.0")
if __name__ == "__main__": if __name__ == "__main__":
main() main()

View File

@ -1,6 +1,7 @@
from .database import DatabaseController from .database import DatabaseController
from models.category import Category from models.category import Category
class CategoryController(DatabaseController): class CategoryController(DatabaseController):
FIELDS = ['id', 'name'] FIELDS = ['id', 'name']
@ -18,7 +19,6 @@ class CategoryController(DatabaseController):
) )
self._conn.commit() self._conn.commit()
def read(self, id: int = 0) -> Category | None: def read(self, id: int = 0) -> Category | None:
params = [ params = [
id id
@ -38,7 +38,6 @@ class CategoryController(DatabaseController):
return obj return obj
def read_all(self) -> list[Category] | None: def read_all(self) -> list[Category] | None:
cursor = self._conn.execute( cursor = self._conn.execute(
"SELECT * FROM Categories", "SELECT * FROM Categories",

View File

@ -3,6 +3,7 @@ from typing import Mapping, Any
import sqlite3 import sqlite3
import os import os
class DatabaseController(ABC): class DatabaseController(ABC):
__data_dir = "./data/" __data_dir = "./data/"
__db_name = "wmgzon.db" __db_name = "wmgzon.db"
@ -13,13 +14,13 @@ class DatabaseController(ABC):
__sqlitefile = __data_dir + __db_name __sqlitefile = __data_dir + __db_name
def __init__(self): def __init__(self):
self._conn = None self._conn = None
try: try:
# Creates a connection and specifies a flag to parse all types back down into # Creates a connection and specifies a flag to parse all types back down into
# Python declared types e.g. date & time # Python declared types e.g. date & time
self._conn = sqlite3.connect(self.__sqlitefile, detect_types=sqlite3.PARSE_DECLTYPES) self._conn = sqlite3.connect(
self.__sqlitefile, detect_types=sqlite3.PARSE_DECLTYPES)
except sqlite3.Error as e: except sqlite3.Error as e:
# Close the connection if still open # Close the connection if still open
if self._conn: if self._conn:
@ -27,11 +28,12 @@ class DatabaseController(ABC):
print(e) print(e)
def __del__(self): def __del__(self):
if self._conn != None: if self._conn != None:
self._conn.close() self._conn.close()
""" Takes a dictionary of fields and returns the object """ Takes a dictionary of fields and returns the object
with those fields populated """ with those fields populated """
def new_instance(self, of: type, with_fields: Mapping[str, Any]): def new_instance(self, of: type, with_fields: Mapping[str, Any]):
obj = of.__new__(of) obj = of.__new__(of)
for attr, value in with_fields.items(): for attr, value in with_fields.items():

View File

@ -1,8 +1,10 @@
from .database import DatabaseController from .database import DatabaseController
from models.products.product import Product from models.products.product import Product
class ProductController(DatabaseController): class ProductController(DatabaseController):
FIELDS = ['id', 'name', 'image', 'description', 'cost', 'category', 'sellerID', 'postedDate', 'quantityAvailable'] FIELDS = ['id', 'name', 'image', 'description', 'cost',
'category', 'sellerID', 'postedDate', 'quantityAvailable']
def __init__(self): def __init__(self):
super().__init__() super().__init__()
@ -25,7 +27,6 @@ class ProductController(DatabaseController):
) )
self._conn.commit() self._conn.commit()
def read(self, name: str = "") -> list[Product] | None: def read(self, name: str = "") -> list[Product] | None:
params = [ params = [
"%" + name + "%" "%" + name + "%"
@ -50,7 +51,6 @@ class ProductController(DatabaseController):
return products return products
def read_all(self, category: str = "", search_term: str = "") -> list[Product] | None: def read_all(self, category: str = "", search_term: str = "") -> list[Product] | None:
params = [ params = [
"%" + category + "%", "%" + category + "%",

View File

@ -3,8 +3,10 @@ from models.users.user import User
from models.users.customer import Customer from models.users.customer import Customer
from models.users.seller import Seller from models.users.seller import Seller
class UserController(DatabaseController): class UserController(DatabaseController):
FIELDS = ['id', 'username', 'password', 'firstName', 'lastName', 'email', 'phone', 'role'] FIELDS = ['id', 'username', 'password', 'firstName',
'lastName', 'email', 'phone', 'role']
def __init__(self): def __init__(self):
super().__init__() super().__init__()
@ -50,7 +52,6 @@ class UserController(DatabaseController):
return None return None
def read_id(self, id: int) -> User | None: def read_id(self, id: int) -> User | None:
params = [ params = [
id id
@ -74,6 +75,7 @@ class UserController(DatabaseController):
return obj return obj
return None return None
def update(self): def update(self):
print("Doing work") print("Doing work")

View File

@ -16,7 +16,7 @@ blueprint.register_blueprint(product.blueprint)
# Function that returns a given user class based on the ID in the session # Function that returns a given user class based on the ID in the session
@blueprint.context_processor @blueprint.context_processor
def get_user() -> dict[User|None]: def get_user() -> dict[User | None]:
# Get the user based on the user ID # Get the user based on the user ID
user_id = session.get('user_id') user_id = session.get('user_id')
user = None user = None

View File

@ -15,14 +15,18 @@ import pathlib
ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg', 'gif'} ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg', 'gif'}
def allowed_file(filename): def allowed_file(filename):
return '.' in filename and \ return '.' in filename and \
filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
blueprint = Blueprint("products", __name__, url_prefix="/products") blueprint = Blueprint("products", __name__, url_prefix="/products")
# Global context to enable the categories to be accessed # Global context to enable the categories to be accessed
# from any view # from any view
@blueprint.context_processor @blueprint.context_processor
def category_list(): def category_list():
database = CategoryController() database = CategoryController()
@ -30,6 +34,8 @@ def category_list():
return dict(categories=categories) return dict(categories=categories)
# Loads the front product page # Loads the front product page
@blueprint.route('/') @blueprint.route('/')
def index(): def index():
database = ProductController() database = ProductController()
@ -39,9 +45,11 @@ def index():
if products == None: if products == None:
flash("No Products available") flash("No Products available")
return render_template('index.html', content="content.html", products = products) return render_template('index.html', content="content.html", products=products)
# Loads a given product category page # Loads a given product category page
@blueprint.route('/<string:category>') @blueprint.route('/<string:category>')
def category(category: str): def category(category: str):
database = ProductController() database = ProductController()
@ -58,9 +66,11 @@ def category(category: str):
if products == None: if products == None:
flash(f"No Products available in {category}") flash(f"No Products available in {category}")
return render_template('index.html', content="content.html", products = products, category = category) return render_template('index.html', content="content.html", products=products, category=category)
# Loads a given product based on ID # Loads a given product based on ID
@blueprint.route('/<int:id>') @blueprint.route('/<int:id>')
def id(id: int): def id(id: int):
return "ID: " + str(id) return "ID: " + str(id)

View File

@ -10,13 +10,17 @@ from hashlib import sha512
# Blueprint to append user endpoints to # Blueprint to append user endpoints to
blueprint = Blueprint("users", __name__) blueprint = Blueprint("users", __name__)
### LOGIN FUNCTIONALITY # LOGIN FUNCTIONALITY
# Function responsible for delivering the Login page for the site # Function responsible for delivering the Login page for the site
@blueprint.route('/login') @blueprint.route('/login')
def display_login(): def display_login():
return render_template('index.html', content="login.html") return render_template('index.html', content="login.html")
# Function responsible for handling logins to the site # Function responsible for handling logins to the site
@blueprint.post('/login') @blueprint.post('/login')
def login(): def login():
database = UserController() database = UserController()
@ -39,13 +43,15 @@ def login():
return redirect("/") return redirect("/")
### SIGNUP FUNCTIONALITY # SIGNUP FUNCTIONALITY
# Function responsible for delivering the Signup page for the site # Function responsible for delivering the Signup page for the site
@blueprint.route('/signup') @blueprint.route('/signup')
def display_signup(): def display_signup():
return render_template('index.html', content="signup.html") return render_template('index.html', content="signup.html")
# Function responsible for handling signups to the site # Function responsible for handling signups to the site
@blueprint.post('/signup') @blueprint.post('/signup')
def signup(): def signup():
database = UserController() database = UserController()
@ -60,7 +66,8 @@ def signup():
if request.form.get('seller'): if request.form.get('seller'):
user = Seller( user = Seller(
request.form['username'], request.form['username'],
sha512(request.form['password'].encode()).hexdigest(), # Hashed as soon as it is recieved on the backend # Hashed as soon as it is recieved on the backend
sha512(request.form['password'].encode()).hexdigest(),
request.form['firstname'], request.form['firstname'],
request.form['lastname'], request.form['lastname'],
request.form['email'], request.form['email'],
@ -69,7 +76,8 @@ def signup():
else: else:
user = Customer( user = Customer(
request.form['username'], request.form['username'],
sha512(request.form['password'].encode()).hexdigest(), # Hashed as soon as it is recieved on the backend # Hashed as soon as it is recieved on the backend
sha512(request.form['password'].encode()).hexdigest(),
request.form['firstname'], request.form['firstname'],
request.form['lastname'], request.form['lastname'],
request.form['email'], request.form['email'],
@ -82,7 +90,7 @@ def signup():
return redirect("/login", code=307) return redirect("/login", code=307)
### SIGN OUT FUNCTIONALITY # SIGN OUT FUNCTIONALITY
# Function responsible for handling logouts from the site # Function responsible for handling logouts from the site
@blueprint.route('/logout') @blueprint.route('/logout')
def logout(): def logout():

View File

@ -2,6 +2,7 @@ class Category:
''' '''
Constructor for a category object Constructor for a category object
''' '''
def __init__(self): def __init__(self):
self.id = 0 self.id = 0
self.name = "" self.name = ""

View File

@ -1,9 +1,11 @@
from datetime import datetime from datetime import datetime
class Order: class Order:
''' '''
Constructor for an order object Constructor for an order object
''' '''
def __init__(self): def __init__(self):
self.id = 0 self.id = 0
self.sellerID = 0 self.sellerID = 0

View File

@ -1,13 +1,14 @@
from product import Product from product import Product
class CarPart(Product): class CarPart(Product):
''' '''
Constructor for a car part Constructor for a car part
Contains additional information that is only relevant for car parts Contains additional information that is only relevant for car parts
''' '''
def __init__(self): def __init__(self):
super().__init__() super().__init__()
self.make = "" self.make = ""
self.compatibleVehicles = list() self.compatibleVehicles = list()

View File

@ -1,9 +1,11 @@
from datetime import datetime from datetime import datetime
class Product: class Product:
''' '''
Base class for a product Base class for a product
''' '''
def __init__(self): def __init__(self):
self.id = 0 self.id = 0
self.name = "" self.name = ""
@ -20,6 +22,7 @@ class Product:
No additional properties are assigned to the customer No additional properties are assigned to the customer
''' '''
def __init__(self, name: str, image: str, description: str, cost: float, category: int, def __init__(self, name: str, image: str, description: str, cost: float, category: int,
seller_id: int, posted_date: datetime, quantity_available: int): seller_id: int, posted_date: datetime, quantity_available: int):
self.id = 0 self.id = 0
@ -31,4 +34,3 @@ class Product:
self.sellerID = seller_id self.sellerID = seller_id
self.postedDate = posted_date self.postedDate = posted_date
self.quantityAvailable = quantity_available self.quantityAvailable = quantity_available

View File

@ -1,11 +1,13 @@
from .user import User from .user import User
class Admin(User): class Admin(User):
''' '''
Class constructor to instatiate an admin object Class constructor to instatiate an admin object
No additional properties are assigned to the admin No additional properties are assigned to the admin
''' '''
def __init__(self, username: str, password: str, firstname: str, def __init__(self, username: str, password: str, firstname: str,
lastname: str, email: str, phone: str): lastname: str, email: str, phone: str):
super().__init__( super().__init__(

View File

@ -1,14 +1,15 @@
from .user import User from .user import User
class Customer(User): class Customer(User):
''' '''
Class constructor to instatiate a customer object Class constructor to instatiate a customer object
No additional properties are assigned to the customer No additional properties are assigned to the customer
''' '''
def __init__(self, username: str, password: str, firstname: str, def __init__(self, username: str, password: str, firstname: str,
lastname: str, email: str, phone: str): lastname: str, email: str, phone: str):
super().__init__( super().__init__(
username, password, firstname, lastname, email, phone, "Customer" username, password, firstname, lastname, email, phone, "Customer"
) )

View File

@ -1,11 +1,13 @@
from .user import User from .user import User
class Seller(User): class Seller(User):
''' '''
Class constructor to instatiate a customer object Class constructor to instatiate a customer object
No additional properties are assigned to the customer No additional properties are assigned to the customer
''' '''
def __init__(self, username: str, password: str, firstname: str, def __init__(self, username: str, password: str, firstname: str,
lastname: str, email: str, phone: str): lastname: str, email: str, phone: str):
super().__init__( super().__init__(

View File

@ -1,8 +1,10 @@
from abc import ABC from abc import ABC
class User(ABC): class User(ABC):
""" Functional Class constructor to initialise all properties in the base object """ Functional Class constructor to initialise all properties in the base object
with a value """ with a value """
def __init__(self, username: str, password: str, firstname: str, def __init__(self, username: str, password: str, firstname: str,
lastname: str, email: str, phone: str, role: str): lastname: str, email: str, phone: str, role: str):
self.id = 0 self.id = 0
@ -12,4 +14,4 @@ class User(ABC):
self.lastName = lastname self.lastName = lastname
self.email = email self.email = email
self.phone = phone self.phone = phone
self.role= role self.role = role

View File

@ -14,14 +14,14 @@ def create_connection(path: str, filename: str):
print("Database file open") print("Database file open")
# Execute creation scripts # Execute creation scripts
sql = open("scripts/create_tables.sql", "r"); sql = open("scripts/create_tables.sql", "r")
conn.executescript(sql.read()) conn.executescript(sql.read())
print("Table creation complete") print("Table creation complete")
# Populate with test data if we are in Test Mode # Populate with test data if we are in Test Mode
if os.environ.get("ENVIRON") == "test": if os.environ.get("ENVIRON") == "test":
sql = open("scripts/test_data.sql", "r"); sql = open("scripts/test_data.sql", "r")
conn.executescript(sql.read()) conn.executescript(sql.read())
except sqlite3.Error as e: except sqlite3.Error as e:
@ -31,12 +31,15 @@ def create_connection(path: str, filename: str):
conn.close() conn.close()
# Ensure a directory is created given a path to it # Ensure a directory is created given a path to it
def create_directory(dir: str): def create_directory(dir: str):
try: try:
os.makedirs(dir) os.makedirs(dir)
except FileExistsError: except FileExistsError:
pass pass
def remove_file(dir: str): def remove_file(dir: str):
try: try:
os.remove(dir) os.remove(dir)
@ -44,7 +47,6 @@ def remove_file(dir: str):
pass pass
dir = r"./data/" dir = r"./data/"
db_name = r"wmgzon.db" db_name = r"wmgzon.db"

View File

@ -1 +0,0 @@

View File

@ -1,8 +1,8 @@
# Ensure test environment is set before using # Ensure test environment is set before using
import scripts.create_database
import os import os
# Setup test environment variables # Setup test environment variables
os.environ["ENVIRON"] = "test" os.environ["ENVIRON"] = "test"
# Runs the database creation scripts # Runs the database creation scripts
import scripts.create_database

View File

@ -5,22 +5,26 @@ from controllers.database.product import ProductController
from models.products.product import Product from models.products.product import Product
product = Product( product = Product(
"product", "product",
"image.png", "image.png",
"description", "description",
10.00, 10.00,
1, 1,
1, 1,
datetime.now(), datetime.now(),
1 1
) )
# Tests a new product can be created # Tests a new product can be created
def test_create_product(): def test_create_product():
db = ProductController() db = ProductController()
db.create(product) db.create(product)
# Tests the database maintains integrity when we try and add a product with the same details # Tests the database maintains integrity when we try and add a product with the same details
@pytest.mark.skip @pytest.mark.skip
def test_duplicate_product(): def test_duplicate_product():
db = ProductController() db = ProductController()
@ -28,11 +32,13 @@ def test_duplicate_product():
db.create(product) db.create(product)
# Tests that products can be refined by category # Tests that products can be refined by category
def test_search_category(): def test_search_category():
db = ProductController() db = ProductController()
# Check each category for correct amount of test products # Check each category for correct amount of test products
assert len(db.read_all("Car Parts")) == 9 + 1 # Added in previous test assert len(db.read_all("Car Parts")) == 9 + 1 # Added in previous test
assert len(db.read_all("Books")) == 9 assert len(db.read_all("Books")) == 9
assert db.read_all("Phones") == None assert db.read_all("Phones") == None
@ -48,6 +54,8 @@ def test_search_term():
assert db.read_all(search_term="not_test") == None assert db.read_all(search_term="not_test") == None
# Test we the same product details get returned from the database # Test we the same product details get returned from the database
def test_read_product(): def test_read_product():
db = ProductController() db = ProductController()

View File

@ -5,35 +5,41 @@ from models.users.customer import Customer
from models.users.seller import Seller from models.users.seller import Seller
customer = Customer( customer = Customer(
"testcustomer", "testcustomer",
"Password1", "Password1",
"firstname", "firstname",
"lastname", "lastname",
"test@test", "test@test",
"123456789" "123456789"
) )
seller = Seller( seller = Seller(
"testseller", "testseller",
"Password1", "Password1",
"firstname", "firstname",
"lastname", "lastname",
"seller@seller", "seller@seller",
"987654321" "987654321"
) )
# Tests a new user can be created # Tests a new user can be created
def test_create_user(): def test_create_user():
db = UserController() db = UserController()
db.create(customer) db.create(customer)
# Tests the database maintains integrity when we try and add a user with the same details # Tests the database maintains integrity when we try and add a user with the same details
def test_duplicate_user(): def test_duplicate_user():
db = UserController() db = UserController()
with pytest.raises(sqlite3.IntegrityError): with pytest.raises(sqlite3.IntegrityError):
db.create(customer) db.create(customer)
# Test we the same user details get returned from the database # Test we the same user details get returned from the database
def test_read_user(): def test_read_user():
db = UserController() db = UserController()
@ -52,6 +58,8 @@ def test_create_seller():
db.create(seller) db.create(seller)
# Test that the same seller details get returned from the database # Test that the same seller details get returned from the database
def test_read_seller(): def test_read_seller():
db = UserController() db = UserController()

View File

@ -1,6 +1,8 @@
import pycodestyle import pycodestyle
# Tests files to ensure they conform to pep8 standards # Tests files to ensure they conform to pep8 standards
def test_pep8_conformance(): def test_pep8_conformance():
"""Test that we conform to PEP8.""" """Test that we conform to PEP8."""
pep8style = pycodestyle.StyleGuide() pep8style = pycodestyle.StyleGuide()