Skip to content

Commit

Permalink
Fix linting warnings. Improve Python style
Browse files Browse the repository at this point in the history
  • Loading branch information
claudiodsf committed Jan 16, 2024
1 parent f7947c4 commit e8d8b83
Show file tree
Hide file tree
Showing 6 changed files with 88 additions and 57 deletions.
71 changes: 44 additions & 27 deletions seiscat/db.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
import sqlite3
import numpy as np
from obspy import UTCDateTime
from .utils import err_exit

# Current supported DB version
# Increment this number when changing the DB schema
Expand All @@ -26,15 +25,19 @@ def _get_db_connection(config, initdb=False):
:param config: config object
:return: database connection
:raises ValueError: if db_file is not set in config file
:raises FileNotFoundError: if database file does not exist
"""
db_file = config.get('db_file', None)
if db_file is None:
err_exit('db_file not set in config file')
raise ValueError('db_file not set in config file')
if not initdb:
try:
open(db_file, 'r')
except FileNotFoundError:
err_exit(f'Database file "{db_file}" not found.')
open(db_file, 'r', encoding='utf8')
except FileNotFoundError as e:
raise FileNotFoundError(
f'Database file "{db_file}" not found.') from e
return sqlite3.connect(db_file)


Expand All @@ -44,6 +47,8 @@ def _check_db_version(cursor, config):
:param cursor: database cursor
:param config: config object
:raises ValueError: if db_file version is not supported
"""
db_version = cursor.execute('PRAGMA user_version').fetchone()[0]
db_file = config['db_file']
Expand All @@ -54,7 +59,7 @@ def _check_db_version(cursor, config):
'Remove or rename your old database file, '
'so that a new one can be created.'
)
err_exit(msg)
raise ValueError(msg)


def _set_db_version(cursor):
Expand All @@ -63,7 +68,7 @@ def _set_db_version(cursor):
:param cursor: database cursor
"""
cursor.execute('PRAGMA user_version = {v:d}'.format(v=DB_VERSION))
cursor.execute(f'PRAGMA user_version = {DB_VERSION:d}')


def check_db_exists(config, initdb):
Expand All @@ -72,26 +77,30 @@ def check_db_exists(config, initdb):
:param config: config object
:param initdb: if True, create new database file
:raises ValueError: if db_file is not set in config file
:raises RuntimeError: if user does not want to overwrite existing database
:raises FileNotFoundError: if database file does not exist
"""
db_file = config.get('db_file', None)
if db_file is None:
err_exit('db_file not set in config file')
raise ValueError('db_file not set in config file')
if initdb and os.path.exists(db_file):
ans = input(
f'"{db_file}" already exists. '
'Do you want to overwrite it?\n'
f'(Current database will be saved as "{db_file}.bak") [y/N] '
)
if ans not in ['y', 'Y']:
err_exit('No database file created. Exiting.')
else:
os.rename(
db_file, f'{db_file}.bak')
print(
f'Backup of "{db_file}" saved to '
f'"{db_file}.bak"')
raise RuntimeError(
'Existing database file will not be overwritten. Exiting.')
os.rename(
db_file, f'{db_file}.bak')
print(
f'Backup of "{db_file}" saved to '
f'"{db_file}.bak"')
if not initdb and not os.path.exists(db_file):
err_exit(
raise FileNotFoundError(
f'Database file "{db_file}" does not exist.\n'
'Run "seiscat initdb" first.'
)
Expand Down Expand Up @@ -315,11 +324,14 @@ def replicate_event_in_db(config, eventid, version=1):
:param config: config object
:param eventid: event id of the original event
:param version: version of the original event
:raises ValueError: if eventid/version is not found in database
"""
fields, rows = read_fields_and_rows_from_db(
config, eventid=eventid, version=version)
if not rows:
err_exit(f'Event {eventid} version {version} not found in database')
raise ValueError(
f'Event {eventid} version {version} not found in database')
row = list(rows[0])
# increment version
ver_index = fields.index('ver')
Expand Down Expand Up @@ -380,15 +392,17 @@ def update_event_in_db(config, eventid, version, field, value):
:param version: version of the event to update
:param field: field to update
:param value: new value
:raises ValueError: if field is not found in database
"""
conn = _get_db_connection(config)
c = conn.cursor()
try:
c.execute(
f'UPDATE events SET {field} = ? WHERE evid = ? AND ver = ?',
(value, eventid, version))
except sqlite3.OperationalError:
err_exit(f'Field "{field}" not found in database')
except sqlite3.OperationalError as e:
raise ValueError(f'Field "{field}" not found in database') from e
# close database connection
conn.commit()
print(
Expand All @@ -405,14 +419,17 @@ def increment_event_in_db(config, eventid, version, field, value):
:param version: version of the event to update
:param field: field to update
:param value: value to increment, must be a number
:raises ValueError: if field is not found in database,
or if value is not a number
"""
conn = _get_db_connection(config)
c = conn.cursor()
# check if value is numeric
try:
value = float(value)
except ValueError:
err_exit(f'Value "{value}" is not a number')
except ValueError as e:
raise ValueError(f'Value "{value}" is not a number') from e
# if value is an integer, convert it to int
if value == int(value):
value = int(value)
Expand All @@ -426,18 +443,18 @@ def increment_event_in_db(config, eventid, version, field, value):
new_value = float(old_value) + value
if new_value == int(new_value):
new_value = int(new_value)
except ValueError:
err_exit(f'Field "{field}" is not a number')
except sqlite3.OperationalError:
err_exit(f'Field "{field}" not found in database')
except ValueError as e:
raise ValueError(f'Field "{field}" is not a number') from e
except sqlite3.OperationalError as e:
raise ValueError(f'Field "{field}" not found in database') from e
# update database
try:
c.execute(
f'UPDATE events SET {field} = ? '
'WHERE evid = ? AND ver = ?',
(new_value, eventid, version))
except sqlite3.OperationalError:
err_exit(f'Field "{field}" not found in database')
except sqlite3.OperationalError as e:
raise ValueError(f'Field "{field}" not found in database') from e
# close database connection
conn.commit()
print(
Expand Down
15 changes: 8 additions & 7 deletions seiscat/download_and_store.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"""
from .db import check_db_exists, write_catalog_to_db
from .fdsnws import open_fdsn_connection, query_events
from .utils import err_exit
from .utils import ExceptionExit


def download_and_store(config, initdb):
Expand All @@ -21,10 +21,11 @@ def download_and_store(config, initdb):
:param config: config object
:param initdb: if True, create new database file
"""
check_db_exists(config, initdb)
try:
with ExceptionExit():
check_db_exists(config, initdb)
with ExceptionExit(additional_msg='Error connecting to FDSN server'):
client = open_fdsn_connection(config)
except Exception as e:
err_exit(e)
cat = query_events(client, config, first_query=initdb)
write_catalog_to_db(cat, config, initdb)
with ExceptionExit(additional_msg='Error querying FDSN server'):
cat = query_events(client, config, first_query=initdb)
with ExceptionExit(additional_msg='Error writing to database'):
write_catalog_to_db(cat, config, initdb)
8 changes: 1 addition & 7 deletions seiscat/fdsnws.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
from obspy import Catalog
from obspy.clients.fdsn import Client
from obspy.clients.fdsn.header import FDSNNoDataException
from .utils import err_exit


def open_fdsn_connection(config):
Expand Down Expand Up @@ -194,10 +193,7 @@ def query_events(client, config, first_query=True):
:returns: obspy Catalog object
"""
print(f'Querying events from FDSN server "{config["fdsn_event_url"]}"...')
try:
cat = _query_box_or_circle(client, config, first_query=first_query)
except Exception as e:
err_exit(e)
cat = _query_box_or_circle(client, config, first_query=first_query)
# see if there are additional queries to be done
n = 1
while True:
Expand All @@ -206,8 +202,6 @@ def query_events(client, config, first_query=True):
client, config, suffix=f'_{n}', first_query=first_query)
except InvalidQuery:
break
except Exception as e:
err_exit(e)
cat += _cat
n += 1
print(f'Found {len(cat)} events.')
Expand Down
20 changes: 10 additions & 10 deletions seiscat/parse_arguments.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
import argparse
import argcomplete
from ._version import get_versions
_db_cursor = None


def _get_db_cursor(configfile):
Expand All @@ -24,7 +23,7 @@ def _get_db_cursor(configfile):
:return: cursor to the database
"""
try:
fp = open(configfile, 'r')
fp = open(configfile, 'r', encoding='utf-8')
except FileNotFoundError:
return None
try:
Expand All @@ -34,15 +33,16 @@ def _get_db_cursor(configfile):
except IndexError:
db_file = 'seiscat.sqlite'
try:
open(db_file, 'r')
open(db_file, 'r', encoding='utf-8')
except FileNotFoundError:
return None
# pylint: disable=import-outside-toplevel
import sqlite3 # lazy import to speed up startup time
conn = sqlite3.connect(db_file)
return conn.cursor()


def _evid_completer(prefix, parsed_args, **kwargs):
def _evid_completer(prefix, parsed_args, **_kwargs):
"""
Completer for event IDs.
Expand All @@ -51,15 +51,15 @@ def _evid_completer(prefix, parsed_args, **kwargs):
:param kwargs: keyword arguments
:return: list of event IDs
"""
global _db_cursor
if _db_cursor is None:
_db_cursor = _get_db_cursor(parsed_args.configfile)
if _db_cursor is None:
if _evid_completer.db_cursor is None:
_evid_completer.db_cursor = _get_db_cursor(parsed_args.configfile)
if _evid_completer.db_cursor is None:
return []
_db_cursor.execute(
_evid_completer.db_cursor.execute(
'SELECT evid FROM events WHERE evid LIKE ?', (f'{prefix}%',)
)
return [row[0] for row in _db_cursor.fetchall()]
return [row[0] for row in _evid_completer.db_cursor.fetchall()]
_evid_completer.db_cursor = None # noqa: E305


def parse_arguments():
Expand Down
1 change: 1 addition & 0 deletions seiscat/scripts/seiscat.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"""
import sys
# NOTE: other modules are lazy-imported to speed up startup time
# pylint: disable=import-outside-toplevel, relative-beyond-top-level


def run():
Expand Down
30 changes: 24 additions & 6 deletions seiscat/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"""
import os
import sys
import contextlib
from .configobj import ConfigObj
from .configobj.validate import Validator

Expand All @@ -26,6 +27,28 @@ def err_exit(msg):
sys.exit(1)


class ExceptionExit(contextlib.AbstractContextManager):
"""
Context manager to exit when an exception is raised.
"""

def __init__(self, additional_msg=None):
"""
Initialize the context manager.
:param additional_msg: additional message to print
"""
self.additional_msg = additional_msg

def __exit__(self, exc_type, exc_value, _traceback):
if exc_type:
if self.additional_msg is not None:
msg = f'{self.additional_msg}: {exc_value}'
else:
msg = exc_value
err_exit(msg)


def parse_configspec():
"""
Parse the configspec file.
Expand Down Expand Up @@ -86,13 +109,8 @@ def read_config(config_file, configspec=None):
if configspec is None:
kwargs.update(
dict(interpolation=False, list_values=False, _inspec=True))
try:
with ExceptionExit(additional_msg=f'Unable to read "{config_file}"'):
config_obj = ConfigObj(config_file, **kwargs)
except IOError as err:
err_exit(err)
except Exception as err:
msg = f'Unable to read "{config_file}": {err}'
err_exit(msg)
for k, v in config_obj.items():
if v == 'None':
config_obj[k] = None
Expand Down

0 comments on commit e8d8b83

Please sign in to comment.