Reduce boilerplate in db functions with context managers

This commit is contained in:
James Taylor 2019-06-08 02:32:13 -07:00
parent 60fe4b2e75
commit c8be729e6b

View File

@ -8,6 +8,7 @@ import gevent
import html import html
import json import json
import traceback import traceback
import contextlib
with open('yt_subscriptions_template.html', 'r', encoding='utf-8') as f: with open('yt_subscriptions_template.html', 'r', encoding='utf-8') as f:
subscriptions_template = Template(f.read()) subscriptions_template = Template(f.read())
@ -58,7 +59,8 @@ def open_database():
connection.close() connection.close()
raise raise
return connection # https://stackoverflow.com/questions/19522505/using-sqlite3-in-python-with-with-keyword
return contextlib.closing(connection)
def _subscribe(channels): def _subscribe(channels):
''' channels is a list of (channel_id, channel_name) ''' ''' channels is a list of (channel_id, channel_name) '''
@ -66,146 +68,88 @@ def _subscribe(channels):
# set time_last_checked to 0 on all channels being subscribed to # set time_last_checked to 0 on all channels being subscribed to
channels = ( (channel_id, channel_name, 0) for channel_id, channel_name in channels) channels = ( (channel_id, channel_name, 0) for channel_id, channel_name in channels)
connection = open_database() with open_database() as connection:
try: with connection as cursor:
cursor = connection.cursor() cursor.executemany('''INSERT OR IGNORE INTO subscribed_channels (yt_channel_id, channel_name, time_last_checked)
cursor.executemany("INSERT OR IGNORE INTO subscribed_channels (yt_channel_id, channel_name, time_last_checked) VALUES (?, ?, ?)", channels) VALUES (?, ?, ?)''', channels)
connection.commit()
except:
connection.rollback()
raise
finally:
connection.close()
# TODO: delete thumbnails # TODO: delete thumbnails
def _unsubscribe(channel_ids): def _unsubscribe(channel_ids):
''' channel_ids is a list of channel_ids ''' ''' channel_ids is a list of channel_ids '''
connection = open_database() with open_database() as connection:
try: with connection as cursor:
cursor = connection.cursor() cursor.executemany("DELETE FROM subscribed_channels WHERE yt_channel_id=?", ((channel_id, ) for channel_id in channel_ids))
cursor.executemany("DELETE FROM subscribed_channels WHERE yt_channel_id=?", ((channel_id, ) for channel_id in channel_ids))
connection.commit()
except:
connection.rollback()
raise
finally:
connection.close()
def _get_videos(number, offset): def _get_videos(number, offset):
connection = open_database() with open_database() as connection:
try: with connection as cursor:
cursor = connection.cursor() db_videos = cursor.execute('''SELECT video_id, title, duration, channel_name
db_videos = cursor.execute('''SELECT video_id, title, duration, channel_name FROM videos
FROM videos INNER JOIN subscribed_channels on videos.sql_channel_id = subscribed_channels.id
INNER JOIN subscribed_channels on videos.sql_channel_id = subscribed_channels.id ORDER BY time_published DESC
ORDER BY time_published DESC LIMIT ? OFFSET ?''', (number, offset))
LIMIT ? OFFSET ?''', (number, offset))
for db_video in db_videos: for db_video in db_videos:
yield { yield {
'id': db_video[0], 'id': db_video[0],
'title': db_video[1], 'title': db_video[1],
'duration': db_video[2], 'duration': db_video[2],
'author': db_video[3], 'author': db_video[3],
} }
except:
connection.rollback()
raise
finally:
connection.close()
def _get_subscribed_channels(): def _get_subscribed_channels():
connection = open_database() with open_database() as connection:
try: with connection as cursor:
cursor = connection.cursor() for item in cursor.execute('''SELECT channel_name, yt_channel_id
for item in cursor.execute('''SELECT channel_name, yt_channel_id FROM subscribed_channels
FROM subscribed_channels ORDER BY channel_name'''):
ORDER BY channel_name'''): yield item
yield item
except:
connection.rollback()
raise
finally:
connection.close()
def _add_tags(channel_ids, tags): def _add_tags(channel_ids, tags):
connection = open_database() with open_database() as connection:
try: with connection as cursor:
cursor = connection.cursor() pairs = [(tag, yt_channel_id) for tag in tags for yt_channel_id in channel_ids]
cursor.executemany('''INSERT OR IGNORE INTO tag_associations (tag, sql_channel_id)
pairs = [(tag, yt_channel_id) for tag in tags for yt_channel_id in channel_ids] SELECT ?, id FROM subscribed_channels WHERE yt_channel_id = ? ''', pairs)
cursor.executemany('''INSERT OR IGNORE INTO tag_associations (tag, sql_channel_id)
SELECT ?, id FROM subscribed_channels WHERE yt_channel_id = ? ''', pairs)
connection.commit()
except:
connection.rollback()
raise
finally:
connection.close()
def _remove_tags(channel_ids, tags): def _remove_tags(channel_ids, tags):
connection = open_database() with open_database() as connection:
try: with connection as cursor:
cursor = connection.cursor() pairs = [(tag, yt_channel_id) for tag in tags for yt_channel_id in channel_ids]
cursor.executemany('''DELETE FROM tag_associations
WHERE tag = ? AND sql_channel_id = (
SELECT id FROM subscribed_channels WHERE yt_channel_id = ?
)''', pairs)
pairs = [(tag, yt_channel_id) for tag in tags for yt_channel_id in channel_ids]
cursor.executemany('''DELETE FROM tag_associations WHERE tag = ? AND sql_channel_id = (
SELECT id FROM subscribed_channels WHERE yt_channel_id = ?
)''', pairs)
connection.commit()
except:
connection.rollback()
raise
finally:
connection.close()
def _get_tags(channel_id): def _get_tags(channel_id):
connection = open_database() with open_database() as connection:
try: with connection as cursor:
cursor = connection.cursor() return [row[0] for row in cursor.execute('''SELECT tag
FROM tag_associations
return [row[0] for row in cursor.execute('''SELECT tag WHERE sql_channel_id = (
FROM tag_associations SELECT id FROM subscribed_channels WHERE yt_channel_id = ?
WHERE sql_channel_id = ( )''', (channel_id,))]
SELECT id FROM subscribed_channels WHERE yt_channel_id = ?
)''', (channel_id,))]
except:
connection.rollback()
raise
finally:
connection.close()
def _get_all_tags(): def _get_all_tags():
connection = open_database() with open_database() as connection:
try: with connection as cursor:
cursor = connection.cursor() return [row[0] for row in cursor.execute('''SELECT DISTINCT tag FROM tag_associations''')]
return [row[0] for row in cursor.execute('''SELECT DISTINCT tag FROM tag_associations''')]
except:
connection.rollback()
raise
finally:
connection.close()
def _get_channel_names(channel_ids): def _get_channel_names(channel_ids):
''' returns list of (channel_id, channel_name) ''' ''' returns list of (channel_id, channel_name) '''
connection = open_database() with open_database() as connection:
try: with connection as cursor:
cursor = connection.cursor() result = []
result = [] for channel_id in channel_ids:
for channel_id in channel_ids: row = cursor.execute('''SELECT channel_name
row = cursor.execute('''SELECT channel_name FROM subscribed_channels WHERE yt_channel_id = ?''', (channel_id,)).fetchone() FROM subscribed_channels
result.append( (channel_id, row[0]) ) WHERE yt_channel_id = ?''', (channel_id,)).fetchone()
return result result.append( (channel_id, row[0]) )
except: return result
connection.rollback()
raise
finally:
connection.close()
units = { units = {
@ -464,20 +408,13 @@ def post_subscriptions_page(env, start_response):
_unsubscribe(params['channel_id']) _unsubscribe(params['channel_id'])
elif action == 'refresh': elif action == 'refresh':
connection = open_database() with open_database() as connection:
try: with connection as cursor:
cursor = connection.cursor() for sql_channel_id, yt_channel_id in cursor.execute('''SELECT id, yt_channel_id FROM subscribed_channels''').fetchall():
for sql_channel_id, yt_channel_id in cursor.execute('''SELECT id, yt_channel_id FROM subscribed_channels''').fetchall(): db_videos = ( (sql_channel_id, info['id'], info['title'], info['duration'], info['time_published'], info['description']) for info in _get_upstream_videos(yt_channel_id) )
db_videos = ( (sql_channel_id, info['id'], info['title'], info['duration'], info['time_published'], info['description']) for info in _get_upstream_videos(yt_channel_id) ) cursor.executemany('''INSERT OR IGNORE INTO videos (sql_channel_id, video_id, title, duration, time_published, description) VALUES (?, ?, ?, ?, ?, ?)''', db_videos)
cursor.executemany('''INSERT OR IGNORE INTO videos (sql_channel_id, video_id, title, duration, time_published, description) VALUES (?, ?, ?, ?, ?, ?)''', db_videos)
cursor.execute('''UPDATE subscribed_channels SET time_last_checked = ?''', ( int(time.time()), ) ) cursor.execute('''UPDATE subscribed_channels SET time_last_checked = ?''', ( int(time.time()), ) )
connection.commit()
except:
connection.rollback()
raise
finally:
connection.close()
start_response('303 See Other', [('Location', util.URL_ORIGIN + '/subscriptions'),] ) start_response('303 See Other', [('Location', util.URL_ORIGIN + '/subscriptions'),] )
return b'' return b''