Implement config file loader

Changes:

* Implement config file loader

* Add config-based database connector

* Remove database path argument from all tools in bin/
This commit is contained in:
XANTRONIX 2025-04-03 21:47:45 -04:00
parent 86ca31b445
commit 8b45d696a1
9 changed files with 79 additions and 25 deletions

View file

@ -2,22 +2,24 @@
import argparse
from xmet.config import Config
from xmet.db import Database
from xmet.afos import AFOSMessageParser
from xmet.util import each_chunk
parser = argparse.ArgumentParser(
description = 'Ingest National Weather Service text bulletin products'
)
parser.add_argument('--quiet', action='store_true', help='Suppress output')
parser.add_argument('--dry-run', action='store_true', help='Do not actually ingest products')
parser.add_argument('db', help='XMET SQLite3 database')
parser.add_argument('afos-text-file', help='AFOS text bulletin product file')
args = parser.parse_args()
db = Database.connect(args.db)
config = Config.load()
db = Database.from_config(config)
db.execute('begin transaction')
parser = AFOSMessageParser()

View file

@ -2,6 +2,7 @@
import argparse
from xmet.config import Config
from xmet.db import Database
from xmet.storm import StormEvent
@ -11,12 +12,12 @@ parser = argparse.ArgumentParser(
parser.add_argument('--quiet', action='store_true', help='Suppress output')
parser.add_argument('--dry-run', action='store_true', help='Do not actually ingest events')
parser.add_argument('db', help='XMET SQLite3 database')
parser.add_argument('csv-event-details', nargs='+', help='Compressed storm event details CSV file')
args = parser.parse_args()
db = Database.connect(args.db)
config = Config.load()
db = Database.from_config(config)
if not args.dry_run:
db.execute('begin transaction')

View file

@ -2,6 +2,7 @@
import argparse
from xmet.config import Config
from xmet.db import Database
from xmet.igra import IGRAReader
@ -17,7 +18,8 @@ parser.add_argument('igra-sounding-file', nargs='+', help='IGRA sounding file')
args = parser.parse_args()
db = Database.connect(args.db)
config = Config.load()
db = Database.from_config(config)
if not args.dry_run:
db.execute('begin transaction')

View file

@ -2,6 +2,7 @@
import argparse
from xmet.config import Config
from xmet.db import Database
from xmet.s3 import S3Bucket
from xmet.storm import StormEvent
@ -18,13 +19,13 @@ group = parser.add_mutually_exclusive_group()
group.add_argument('--exclude', action='append', type=str, help='Exclude types of events from ingest')
group.add_argument('--type', action='append', type=str, help='Specify only given types of events to ingest')
parser.add_argument('db', help='XMET SQLite3 database')
parser.add_argument('csv-event-details', nargs='+', help='Compressed storm event details CSV file')
parser.add_argument('archive-dir', help='Target archive directory')
args = parser.parse_args()
db = Database.connect(args.db)
config = Config.load()
db = Database.from_config(config)
bucket = S3Bucket()
archive = Archive(getattr(args, 'archive-dir'), bucket)
exclude = None

View file

@ -2,6 +2,7 @@
import argparse
from xmet.config import Config
from xmet.db import Database
from xmet.raob import RAOBReader
from xmet.igra import IGRAStation
@ -13,12 +14,12 @@ parser = argparse.ArgumentParser(
parser.add_argument('--quiet', action='store_true', help='Suppress output')
parser.add_argument('--dry-run', action='store_true', help='Do not actually ingest data')
parser.add_argument('db', help='XMET SQLite3 database')
parser.add_argument('raob-sounding-file', nargs='+', help='RAOB sounding file')
args = parser.parse_args()
db = Database.connect(args.db)
config = Config.load()
db = Database.from_config(config)
if not args.dry_run:
db.execute('begin transaction')

View file

@ -4,6 +4,7 @@ import argparse
import cairo
import shapely
from xmet.config import Config
from xmet.db import Database
from xmet.sounding import Sounding
from xmet.skew_t import SkewTGraph, SkewTLegend
@ -60,14 +61,14 @@ parser = argparse.ArgumentParser(
parser.add_argument('--skew-t', type=str, help='Plot a Skew-T chart to the specified SVG file')
parser.add_argument('--hodograph', type=str, help='Plot a hodograph to the specified SVG file')
parser.add_argument('db', help='XMET SQLite3 database')
parser.add_argument('lat', help='Latitude')
parser.add_argument('lon', help='Longitude')
parser.add_argument('timestamp', help='Timestamp in YYYY-MM-DD HH:MM:SS (UTC)')
args = parser.parse_args()
db = Database.connect(args.db)
config = Config.load()
db = Database.from_config(config)
location = shapely.Point(float(args.lon), float(args.lat))
sounding = Sounding.valid_by_location(db, location, args.timestamp)

View file

@ -3,6 +3,7 @@
import argparse
import cairo
from xmet.config import Config
from xmet.db import Database
from xmet.spc import SPCOutlookParser, \
@ -25,7 +26,8 @@ ASSETS = {
def render_categorical(conus: SPCOutlookMap,
outlook: SPCOutlook,
args):
db = Database.connect(args.db)
config = Config.load()
db = Database.from_config(config)
assets = ASSETS['dark'] if args.dark else ASSETS['light']
@ -48,7 +50,8 @@ def render_probabilistic(conus: SPCOutlookMap,
hazard: str,
path: str,
args):
db = Database.connect(args.db)
config = Config.load()
db = Database.from_config(config)
assets = ASSETS['dark'] if args.dark else ASSETS['light']
@ -69,7 +72,6 @@ def render_probabilistic(conus: SPCOutlookMap,
conus.draw_annotation(cr, outlook, SPCOutlookType.PROBABILISTIC, hazard)
argparser = argparse.ArgumentParser(description='Render graphical SPC outlooks from text file')
argparser.add_argument('db', help='Spatialite database file')
argparser.add_argument('--dark', action='store_true', help='Output dark mode graphics')
argparser.add_argument('--categorical', type=str, help='Output categorical risk graphic file')
argparser.add_argument('--any-severe', type=str, help='Output probabilistic severe risk graphic file')

36
lib/xmet/config.py Normal file
View file

@ -0,0 +1,36 @@
import os
import configparser
from typing import Optional, Self
class ConfigException(Exception):
...
class ConfigFileException(ConfigException):
...
class Config(configparser.ConfigParser):
SEARCH_PATHS = (
'./xmet.conf',
os.environ['HOME'] + '/.xmet.conf',
'/etc/xmet/xmet.conf',
)
@staticmethod
def find() -> str:
for path in Config.SEARCH_PATHS:
if os.path.isfile(path):
return path
@staticmethod
def load(path: Optional[str]=None) -> Self:
if path is None:
path = Config.find()
if path is None:
raise ConfigFileException("Could not locate xmet configuration file")
config = Config()
config.read(path)
return config

View file

@ -1,6 +1,10 @@
import enum
import sqlite3
from typing import Self
from xmet.config import Config
class DatabaseOrder(enum.Enum):
DEFAULT = 0
ASC = 1
@ -112,6 +116,10 @@ class Database():
return Database(db)
@staticmethod
def from_config(config: Config) -> Self:
return Database.connect(config['database']['path'])
def column_placeholders(self, table, obj) -> list:
ret = list()