Skip to content
This repository has been archived by the owner on Nov 16, 2024. It is now read-only.

Commit

Permalink
Merge pull request #44 from eccentricOrange:raise-strings
Browse files Browse the repository at this point in the history
Raise-strings
  • Loading branch information
eccentricOrange authored Jul 13, 2022
2 parents 2b50387 + d311dea commit 7a661bb
Show file tree
Hide file tree
Showing 4 changed files with 145 additions and 114 deletions.
11 changes: 3 additions & 8 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@
// Set *default* container specific settings.json values on container create.
"settings": {
"python.defaultInterpreterPath": "/usr/local/bin/python",
"python.linting.enabled": true,
"python.linting.pylintEnabled": true,
"python.linting.enabled": false,
"python.linting.pylintEnabled": false,
"python.formatting.autopep8Path": "/usr/local/py-utils/bin/autopep8",
"python.formatting.blackPath": "/usr/local/py-utils/bin/black",
"python.formatting.yapfPath": "/usr/local/py-utils/bin/yapf",
Expand All @@ -37,10 +37,6 @@
"extensions": [
"ms-python.python",
"ms-python.vscode-pylance",
"GitHub.codespaces",
"GitHub.remotehub",
"ms-vscode-remote.vscode-remote-extensionpack",
"ms-vscode.remote-repositories",
"redhat.vscode-yaml",
"mtxr.sqltools-driver-sqlite",
"streetsidesoftware.code-spell-checker",
Expand All @@ -62,8 +58,7 @@
"features": {
"docker-in-docker": "latest",
"git": "os-provided",
"github-cli": "latest",
"jupyterlab": "latest"
"github-cli": "latest"
},
"remoteEnv": {
"NPBC_DATABASE_DIR": "data"
Expand Down
18 changes: 18 additions & 0 deletions npbc_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,8 @@ def status_print(success: bool, message: str) -> None:
colour = Fore.GREEN if success else Fore.RED
print(f"{colour}{Style.BRIGHT}{message}{Style.RESET_ALL}\n")

return


def calculate(parsed_arguments: ArgNamespace, connection: Connection) -> None:
"""calculate the cost for a given month and year
Expand Down Expand Up @@ -267,6 +269,7 @@ def calculate(parsed_arguments: ArgNamespace, connection: Connection) -> None:
# print the results
status_print(True, "Success!")
print(f"SUMMARY:\n\n{formatted}")
return


def addudl(parsed_arguments: ArgNamespace, connection: Connection) -> None:
Expand Down Expand Up @@ -315,6 +318,7 @@ def addudl(parsed_arguments: ArgNamespace, connection: Connection) -> None:
return

status_print(True, "Success!")
return


def deludl(parsed_arguments: ArgNamespace, connection: Connection) -> None:
Expand Down Expand Up @@ -356,6 +360,7 @@ def deludl(parsed_arguments: ArgNamespace, connection: Connection) -> None:
return

status_print(True, "Success!")
return


def getudl(parsed_arguments: ArgNamespace, connection: Connection) -> None:
Expand Down Expand Up @@ -399,6 +404,8 @@ def getudl(parsed_arguments: ArgNamespace, connection: Connection) -> None:
for items in undelivered_strings:
print(', '.join([str(item) for item in items]))

return


def extract_delivery_from_user_input(input_delivery: str) -> list[bool]:
"""convert the /[YN]{7}/ user input to a Boolean list"""
Expand Down Expand Up @@ -499,6 +506,7 @@ def editpaper(parsed_arguments: ArgNamespace, connection: Connection) -> None:
return

status_print(True, "Success!")
return


def addpaper(parsed_arguments: ArgNamespace, connection: Connection) -> None:
Expand Down Expand Up @@ -532,6 +540,7 @@ def addpaper(parsed_arguments: ArgNamespace, connection: Connection) -> None:
return

status_print(True, "Success!")
return


def delpaper(parsed_arguments: ArgNamespace, connection: Connection) -> None:
Expand All @@ -552,6 +561,7 @@ def delpaper(parsed_arguments: ArgNamespace, connection: Connection) -> None:
return

status_print(True, "Success!")
return


def getpapers(parsed_arguments: ArgNamespace, connection: Connection) -> None:
Expand Down Expand Up @@ -661,6 +671,8 @@ def getpapers(parsed_arguments: ArgNamespace, connection: Connection) -> None:

print()

return


def getlogs(parsed_arguments: ArgNamespace, connection: Connection) -> None:
"""get a list of all logs in the database
Expand Down Expand Up @@ -699,20 +711,24 @@ def getlogs(parsed_arguments: ArgNamespace, connection: Connection) -> None:
for row in data:
print(', '.join(str(item) for item in row))

return


def update(parsed_arguments: ArgNamespace, _: Connection) -> None:
"""update the application
- under normal operation, this function should never run
- if the update CLI argument is provided, this script will never run and the updater will be run instead"""

status_print(False, "Update failed.")
return


def init(parsed_arguments: ArgNamespace, _: Connection) -> None:
"""initialize the application
- this function should run only once, when the application is first installed"""

status_print(True, "Initialized successfully.")
return


def main(arguments: list[str]) -> None:
Expand Down Expand Up @@ -743,6 +759,8 @@ def main(arguments: list[str]) -> None:
finally:
connection.close() # type: ignore

return


if __name__ == "__main__":
main(argv[1:])
65 changes: 46 additions & 19 deletions npbc_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,17 +65,17 @@ def get_number_of_each_weekday(month: int, year: int) -> Generator[int, None, No
number_of_weeks = len(main_calendar)

# iterate over each possible weekday
for i in range(len(WEEKDAY_NAMES)):
for weekday_index in range(len(WEEKDAY_NAMES)):

# assume that the weekday occurs once per week in the month
number_of_weekday: int = number_of_weeks

# if the first week doesn't have the weekday, decrement its count
if main_calendar[0][i] == 0:
if main_calendar[0][weekday_index] == 0:
number_of_weekday -= 1

# if the last week doesn't have the weekday, decrement its count
if main_calendar[-1][i] == 0:
if main_calendar[-1][weekday_index] == 0:
number_of_weekday -= 1

yield number_of_weekday
Expand All @@ -101,8 +101,9 @@ def validate_undelivered_string(*strings: str) -> None:
raise npbc_exceptions.InvalidUndeliveredString(f'{string} is not a valid undelivered string.')

# if we get here, all strings passed the regex check
return

def extract_number(string: str, month: int, year: int) -> date | None:
def extract_number(string: str, month: int, year: int) -> date:
"""if the date is simply a number, it's a single day. so we just identify that date"""

day = int(string)
Expand All @@ -111,6 +112,9 @@ def extract_number(string: str, month: int, year: int) -> date | None:
if 0 < day <= monthrange(year, month)[1]:
return date(year, month, day)

# if we reach here, the check failed and it's not a valid date
raise npbc_exceptions.InvalidUndeliveredString(f'{string} is not a valid date for {datetime(year=year, month=month, day=1):%B %Y}.')


def extract_range(string: str, month: int, year: int) -> Generator[date, None, None]:
"""if the date is a range of numbers, it's a range of days. we identify all the dates in that range, bounds inclusive"""
Expand All @@ -122,6 +126,10 @@ def extract_range(string: str, month: int, year: int) -> Generator[date, None, N
for day in range(start, end + 1):
yield date(year, month, day)

else:
# if we reach here, the check failed and the month doesn't have that many days
raise npbc_exceptions.InvalidUndeliveredString(f'{datetime(year=year, month=month, day=1):%B %Y} does not have days between {start} and {end}.')


def extract_weekday(string: str, month: int, year: int) -> Generator[date, None, None]:
"""if the date is the plural of a weekday name, we identify all dates in that month which are the given weekday"""
Expand All @@ -133,7 +141,7 @@ def extract_weekday(string: str, month: int, year: int) -> Generator[date, None,
yield date(year, month, day)


def extract_nth_weekday(string: str, month: int, year: int) -> date | None:
def extract_nth_weekday(string: str, month: int, year: int) -> date:
"""if the date is a number and a weekday name (singular), we identify the date that is the nth occurrence of the given weekday in the month"""

n, weekday_name = npbc_regex.HYPHEN_SPLIT_REGEX.split(string)
Expand All @@ -156,6 +164,8 @@ def extract_nth_weekday(string: str, month: int, year: int) -> date | None:
# return the date that is the nth occurrence of the given weekday in the month
return valid_dates[n - 1]

# if we reach here, the check failed and the weekday does not occur n times in the month
raise npbc_exceptions.InvalidUndeliveredString(f'{datetime(year=year, month=month, day=1):%B %Y} does not have {n} {weekday_name}s.')

def extract_all(month: int, year: int) -> Generator[date, None, None]:
"""if the text is "all", we identify all the dates in the month"""
Expand Down Expand Up @@ -210,17 +220,19 @@ def parse_undelivered_strings(month: int, year: int, *strings: str) -> set[date]

# check for each of the patterns
for string in strings:
try:
dates.update(parse_undelivered_string(month, year, string))

except npbc_exceptions.InvalidUndeliveredString:
print(
f"""Congratulations! You broke the program!
You managed to write a string that the program considers valid, but isn't actually.
Please report it to the developer.
\nThe string you wrote was: {string}
This data has not been counted."""
)
if string:
try:
dates.update(parse_undelivered_string(month, year, string))

except npbc_exceptions.InvalidUndeliveredString as e:
print(
f"""Congratulations! You broke the program!
You managed to write a string that the program considers valid, but isn't actually.
Please report it to the developer.
\nThe string you wrote was: {string}
This data has not been counted.\n
Exact error message: {e}"""
)

return dates

Expand Down Expand Up @@ -262,9 +274,9 @@ def calculate_cost_of_one_paper(
for day in undelivered_dates:
number_of_days_per_weekday_not_received[day.weekday()] += 1

return numpy.sum(
return float(numpy.sum(
delivery_data * cost_data * (number_of_each_weekday - number_of_days_per_weekday_not_received)
)
))


def calculate_cost_of_all_papers(connection: Connection, undelivered_strings: dict[int, list[str]], month: int, year: int) -> tuple[
Expand Down Expand Up @@ -364,6 +376,8 @@ def save_results(
(log_ids[paper_id], day.strftime("%Y-%m-%d"))
)

return


def format_output(connection: Connection, costs: dict[int, float], total: float, month: int, year: int) -> Generator[str, None, None]:
"""format the output of calculating the cost of all papers"""
Expand Down Expand Up @@ -405,6 +419,8 @@ def add_new_paper(connection: Connection, name: str, days_delivered: list[bool],
(paper_id, day_id, delivered, cost)
)

return


def edit_existing_paper(
connection: Connection,
Expand Down Expand Up @@ -446,6 +462,8 @@ def edit_existing_paper(
(delivered, paper_id, day_id)
)

return


def delete_existing_paper(connection: Connection, paper_id: int) -> None:
"""delete an existing paper
Expand All @@ -470,6 +488,8 @@ def delete_existing_paper(connection: Connection, paper_id: int) -> None:
(paper_id,)
)

return


def add_undelivered_string(connection: Connection, month: int, year: int, paper_id: int | None = None, *undelivered_strings: str) -> None:
"""record strings for date(s) paper(s) were not delivered
Expand Down Expand Up @@ -515,6 +535,8 @@ def add_undelivered_string(connection: Connection, month: int, year: int, paper_

connection.executemany("INSERT INTO undelivered_strings (month, year, paper_id, string) VALUES (?, ?, ?, ?);", params)

return


def delete_undelivered_string(
connection: Connection,
Expand Down Expand Up @@ -572,6 +594,8 @@ def delete_undelivered_string(

connection.execute(f"{delete_query} WHERE {conditions};", values)

return


def get_papers(connection: Connection) -> tuple[Papers]:
"""get all papers
Expand Down Expand Up @@ -606,7 +630,7 @@ def get_undelivered_strings(
"""get undelivered strings
- the user may specify as many as they want parameters
- available parameters: string_id, month, year, paper_id, string
- returns a list of tuples containing the following fields:
- returns a tuple of tuples containing the following fields:
string_id, paper_id, year, month, string"""

# initialize parameters for the WHERE clause of the SQL query
Expand Down Expand Up @@ -753,3 +777,6 @@ def validate_month_and_year(month: int | None = None, year: int | None = None) -

if isinstance(year, int) and (year <= 0):
raise npbc_exceptions.InvalidMonthYear("Year must be greater than 0.")

# if we get here, the month and year are valid
return
Loading

0 comments on commit 7a661bb

Please sign in to comment.