#!/usr/bin/python
# -*- coding: utf-8 -*-
"""common utilities utilized by mini-project-1"""
import argparse
import sqlite3
import sys
import pendulum
MINI_PROJECT_DATE_FMT = "%Y-%m-%d"
[docs]class ShellArgumentException(Exception):
"""Custom exception class noting a invalid argument within a
:class:`.shell.MiniProjectShell` command"""
def __init__(self, *args, **kwargs):
super().__init__(self, *args, **kwargs)
[docs]class ShellArgumentParser(argparse.ArgumentParser):
"""Custom argument parser for use in :class`.shell.MiniProjectShell`"""
def __init__(self, *args, **kwargs):
# set ``add_help`` to false to avoid conflicts with the shell
kwargs["add_help"] = False
super().__init__(*args, **kwargs)
[docs] def error(self, message):
self.print_help(sys.stderr)
raise ShellArgumentException(message)
[docs]def price(price_string: str) -> int:
price = int(price_string)
if price < 0:
raise argparse.ArgumentTypeError(
"invalid price: {} (please choose a non negative price)".format(
price_string
)
)
return price
[docs]def greater_than_zero_number(value: str) -> int:
value = int(value)
if value <= 0:
raise argparse.ArgumentTypeError("%s must be a greater than zero number" % value)
return value
[docs]def date(date_str: str) -> pendulum.DateTime:
return pendulum.parse(date_str)
[docs]class ValueNotFoundException(Exception):
"""Exception for queries with no results"""
def __init__(self, *args, **kwargs):
super().__init__(self, *args, **kwargs)
[docs]def get_selection(items: list, prompt: str= "Enter selection number: "):
"""Gets the user to select a item from a list, displaying up to 5 items
at a time.
:param items: list of items
:param prompt: a prompt for user input, default is "Enter selection number: "
:return: selected item from items
"""
index = 0
while True:
print("%i: %s" % (index, items[index]))
if index % 5 == 4:
print("Press Enter to see more\n")
selection = str(input(prompt))
if selection.isnumeric():
selection = int(selection)
if -1 < selection < len(items):
return items[selection]
elif selection == "exit":
return None
elif index + 1 == len(items):
print("Press Enter to return to the start of the list\n")
selection = str(input(prompt))
if selection.isnumeric():
selection = int(selection)
if -1 < selection < len(items):
return items[selection]
elif selection == "exit":
return None
index = -1
print("An entry must be selected")
index += 1
[docs]def get_location_id(dbcursor: sqlite3.Cursor, keyword: str, prompt: str = None):
"""Gets a location lcode from the user."""
# get exact match locde
dbcursor.execute(
"SELECT * "
"FROM locations WHERE lcode LIKE ?",
(keyword,)
)
location = dbcursor.fetchall()
if location:
return location[0][0]
# get matching locations, since it's not a lcode
kw = '%' + keyword + '%'
dbcursor.execute(
"SELECT * "
"FROM locations "
"WHERE city LIKE ? OR prov LIKE ? OR address LIKE ?",
(kw, kw, kw)
)
locations = dbcursor.fetchall()
# display and get user selection if more than one
if len(locations) > 1:
if prompt:
print(prompt)
return get_selection(locations)[0]
elif locations:
return locations[0][0]
else:
raise ValueNotFoundException("No location for " + keyword)
[docs]def send_message(database: sqlite3.Connection, recipient: str, sender: str, content: str, rno: int):
""""""
cur = database.cursor()
cur.execute(
"INSERT INTO inbox VALUES (?, ?, ?, ?, ?, ?);",
(recipient, pendulum.now().to_datetime_string(),
sender, content, rno, "n")
)
database.commit()
[docs]def check_valid_lcode(database: sqlite3.Connection, lcode: str) -> bool:
"""Checks whether a lcode is in the database"""
dbcursor = database.cursor()
dbcursor.execute(
"SELECT * "
"FROM locations "
"WHERE lcode LIKE ?",
(lcode,)
)
if dbcursor.fetchall():
return True
return False
[docs]def check_valid_email(database: sqlite3.Connection, email: str) -> bool:
"""Checks whether an email is in the database"""
dbcursor = database.cursor()
dbcursor.execute(
"SELECT * "
"FROM members "
"WHERE email = ?",
(email,)
)
if dbcursor.fetchall():
return True
return False