-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathutils.py
More file actions
188 lines (144 loc) · 5.66 KB
/
utils.py
File metadata and controls
188 lines (144 loc) · 5.66 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
import os
import sqlite3
import sys
from typing import List, Union
class Quote(object):
"""Represents a row in the quotes table"""
def __init__(self, id: int, author: str, quote: str, created_at: str):
self.id = id
self.author = author
self.quote = quote
self.created_at = created_at
def __str__(self):
return f'{self.id} | {self.author} | {self.quote} | {self.created_at}'
def to_dict(self):
return {
'id': self.id,
'author': self.author,
'quote': self.quote,
'created_at': self.created_at
}
class DBClient(object):
"""Client for interacting with database for the application"""
def __init__(self, database_name: str):
self.conn = self.__connect_to_database(database_name)
self.__set_up_database(database_name)
def __execute_query(self, query: str, params: Union[None, tuple] = None) -> sqlite3.Cursor:
"""
Execute a SQL query using the instance connection to the database
:param query: (str) SQL statement to execute
:param params: (None|tuple) Optional params to pass in query
:return: (sqlite3.Cursor)
"""
if params is None:
params = ()
with self.conn:
return self.conn.execute(query, params)
def __connect_to_database(self, database_name: str) -> sqlite3.Connection:
"""
Open a connection to the sqlite3 database specified by `database_name`.
:param database_name: (str) Name of sqlite3 database file to open
:return: (sqlite3.Connection)
"""
conn = sqlite3.connect(database_name)
conn.row_factory = sqlite3.Row
return conn
def __set_up_database(self, database_name: str) -> None:
try:
self.__create_quotes_table()
except sqlite3.DatabaseError:
self.__handle_invalid_database_file(database_name)
def __handle_invalid_database_file(self, database_name: str) -> None:
"""
If the file specified by `database_name` is not a valid sqlite3 database, prompt
user to delete the file. If the user allows it, delete the file and create a new
sqlite3 database file. If the user rejects, exit with error code.
:param database_name: (str) Name of sqlite3 database file to open
"""
print(f'ERROR: {database_name} is not a sqlite3 file!')
delete_file = input('Would you like to delete the old file? (y/n): ')
if delete_file.lower() == 'y':
print(f'Deleting {database_name}...')
os.unlink(database_name)
print('Creating new database file...')
self.conn = self.__connect_to_database(database_name)
self.__set_up_database(database_name)
else:
print(
'\nERROR: Cannot continue with invalid database file.\n'
'Please delete or rename the file to continue.'
)
sys.exit(1)
def __create_quotes_table(self) -> None:
"""
Create the table used for storing quotes if it does not exist already
"""
query = '''
CREATE TABLE IF NOT EXISTS quotes (
id INTEGER PRIMARY KEY,
author TEXT,
quote TEXT,
created_at TEXT
);
'''
self.__execute_query(query)
def __build_quotes_from_query_result(self, rows: List[sqlite3.Row]) -> List[Quote]:
"""
Build the list of quote objects returned by a query
:param rows: (list[sqlite3.Row]) Row objects returned from a query
:return: (list[Quote])
"""
quotes = []
for row in rows:
quotes.append(Quote(row['id'], row['author'], row['quote'], row['created_at']))
return quotes
def close_connection(self) -> None:
"""
Close connection to the database
"""
self.conn.close()
def insert_quote(self, author: str, quote: str, created_at: str) -> None:
"""
Insert a quote into the database
:param author: (str) Name of the author that said the quote
:param quote: (str) The quote for the author
:param created_at: (str) Timestamp for when the quote was saved to database
"""
params = (author, quote, created_at)
query = 'INSERT INTO quotes (author, quote, created_at) VALUES (?, ?, ?)'
self.__execute_query(query, params)
def get_all_quotes(self) -> List[Quote]:
"""
Get all quotes in the database
:return: (list[Quotes])
"""
query = '''
SELECT *
FROM quotes
ORDER BY created_at DESC
'''
ret = self.__execute_query(query)
return self.__build_quotes_from_query_result(ret.fetchall())
def get_quotes_for_author(self, author: str) -> List[Quote]:
"""
Retrieve quotes from the database for the given author
:param author: (str) Name of author to retrieve quotes for
:return: (list[Quotes])
"""
params = (f'%{author}%',)
query = '''
SELECT *
FROM quotes
WHERE author LIKE ?
ORDER BY created_at DESC
'''
ret = self.__execute_query(query, params)
return self.__build_quotes_from_query_result(ret.fetchall())
def delete_quote_from_database(self, id: int) -> None:
"""
Delete a quote from the database for the given row
:param id: (int) Primary key of row to delete from database
"""
params = (id,)
query = 'DELETE FROM quotes WHERE id=?'
self.__execute_query(query, params)