Implement config file loader
Changes: * Implement config file loader * Add config-based database connector
This commit is contained in:
parent
86ca31b445
commit
f40c1d14c6
9 changed files with 79 additions and 25 deletions
|
@ -2,22 +2,24 @@
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
|
|
||||||
from xmet.db import Database
|
from xmet.config import Config
|
||||||
from xmet.afos import AFOSMessageParser
|
from xmet.db import Database
|
||||||
from xmet.util import each_chunk
|
from xmet.afos import AFOSMessageParser
|
||||||
|
from xmet.util import each_chunk
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser(
|
||||||
description = 'Ingest National Weather Service text bulletin products'
|
description = 'Ingest National Weather Service text bulletin products'
|
||||||
)
|
)
|
||||||
|
|
||||||
parser.add_argument('--quiet', action='store_true', help='Suppress output')
|
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('--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')
|
parser.add_argument('afos-text-file', help='AFOS text bulletin product file')
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
db = Database.connect(args.db)
|
config = Config.load()
|
||||||
|
db = Database.from_config(config)
|
||||||
db.execute('begin transaction')
|
db.execute('begin transaction')
|
||||||
|
|
||||||
parser = AFOSMessageParser()
|
parser = AFOSMessageParser()
|
||||||
|
|
|
@ -2,8 +2,9 @@
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
|
|
||||||
from xmet.db import Database
|
from xmet.config import Config
|
||||||
from xmet.storm import StormEvent
|
from xmet.db import Database
|
||||||
|
from xmet.storm import StormEvent
|
||||||
|
|
||||||
parser = argparse.ArgumentParser(
|
parser = argparse.ArgumentParser(
|
||||||
description = 'Ingest events from StormEvent_details_*.csv.gz files'
|
description = 'Ingest events from StormEvent_details_*.csv.gz files'
|
||||||
|
@ -11,12 +12,12 @@ parser = argparse.ArgumentParser(
|
||||||
|
|
||||||
parser.add_argument('--quiet', action='store_true', help='Suppress output')
|
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('--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')
|
parser.add_argument('csv-event-details', nargs='+', help='Compressed storm event details CSV file')
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
db = Database.connect(args.db)
|
config = Config.load()
|
||||||
|
db = Database.from_config(config)
|
||||||
|
|
||||||
if not args.dry_run:
|
if not args.dry_run:
|
||||||
db.execute('begin transaction')
|
db.execute('begin transaction')
|
||||||
|
|
|
@ -2,8 +2,9 @@
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
|
|
||||||
from xmet.db import Database
|
from xmet.config import Config
|
||||||
from xmet.igra import IGRAReader
|
from xmet.db import Database
|
||||||
|
from xmet.igra import IGRAReader
|
||||||
|
|
||||||
parser = argparse.ArgumentParser(
|
parser = argparse.ArgumentParser(
|
||||||
description = 'Ingest IGRA soundings'
|
description = 'Ingest IGRA soundings'
|
||||||
|
@ -17,7 +18,8 @@ parser.add_argument('igra-sounding-file', nargs='+', help='IGRA sounding file')
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
db = Database.connect(args.db)
|
config = Config.load()
|
||||||
|
db = Database.from_config(config)
|
||||||
|
|
||||||
if not args.dry_run:
|
if not args.dry_run:
|
||||||
db.execute('begin transaction')
|
db.execute('begin transaction')
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
|
|
||||||
|
from xmet.config import Config
|
||||||
from xmet.db import Database
|
from xmet.db import Database
|
||||||
from xmet.s3 import S3Bucket
|
from xmet.s3 import S3Bucket
|
||||||
from xmet.storm import StormEvent
|
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('--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')
|
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('csv-event-details', nargs='+', help='Compressed storm event details CSV file')
|
||||||
parser.add_argument('archive-dir', help='Target archive directory')
|
parser.add_argument('archive-dir', help='Target archive directory')
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
db = Database.connect(args.db)
|
config = Config.load()
|
||||||
|
db = Database.from_config(config)
|
||||||
bucket = S3Bucket()
|
bucket = S3Bucket()
|
||||||
archive = Archive(getattr(args, 'archive-dir'), bucket)
|
archive = Archive(getattr(args, 'archive-dir'), bucket)
|
||||||
exclude = None
|
exclude = None
|
||||||
|
|
|
@ -2,9 +2,10 @@
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
|
|
||||||
from xmet.db import Database
|
from xmet.config import Config
|
||||||
from xmet.raob import RAOBReader
|
from xmet.db import Database
|
||||||
from xmet.igra import IGRAStation
|
from xmet.raob import RAOBReader
|
||||||
|
from xmet.igra import IGRAStation
|
||||||
|
|
||||||
parser = argparse.ArgumentParser(
|
parser = argparse.ArgumentParser(
|
||||||
description = 'Ingest RAOB soundings'
|
description = 'Ingest RAOB soundings'
|
||||||
|
@ -13,12 +14,12 @@ parser = argparse.ArgumentParser(
|
||||||
parser.add_argument('--quiet', action='store_true', help='Suppress output')
|
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('--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')
|
parser.add_argument('raob-sounding-file', nargs='+', help='RAOB sounding file')
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
db = Database.connect(args.db)
|
config = Config.load()
|
||||||
|
db = Database.from_config(config)
|
||||||
|
|
||||||
if not args.dry_run:
|
if not args.dry_run:
|
||||||
db.execute('begin transaction')
|
db.execute('begin transaction')
|
||||||
|
|
|
@ -4,6 +4,7 @@ import argparse
|
||||||
import cairo
|
import cairo
|
||||||
import shapely
|
import shapely
|
||||||
|
|
||||||
|
from xmet.config import Config
|
||||||
from xmet.db import Database
|
from xmet.db import Database
|
||||||
from xmet.sounding import Sounding
|
from xmet.sounding import Sounding
|
||||||
from xmet.skew_t import SkewTGraph, SkewTLegend
|
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('--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('--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('lat', help='Latitude')
|
||||||
parser.add_argument('lon', help='Longitude')
|
parser.add_argument('lon', help='Longitude')
|
||||||
parser.add_argument('timestamp', help='Timestamp in YYYY-MM-DD HH:MM:SS (UTC)')
|
parser.add_argument('timestamp', help='Timestamp in YYYY-MM-DD HH:MM:SS (UTC)')
|
||||||
|
|
||||||
args = parser.parse_args()
|
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))
|
location = shapely.Point(float(args.lon), float(args.lat))
|
||||||
sounding = Sounding.valid_by_location(db, location, args.timestamp)
|
sounding = Sounding.valid_by_location(db, location, args.timestamp)
|
||||||
|
|
|
@ -3,7 +3,8 @@
|
||||||
import argparse
|
import argparse
|
||||||
import cairo
|
import cairo
|
||||||
|
|
||||||
from xmet.db import Database
|
from xmet.config import Config
|
||||||
|
from xmet.db import Database
|
||||||
|
|
||||||
from xmet.spc import SPCOutlookParser, \
|
from xmet.spc import SPCOutlookParser, \
|
||||||
SPCOutlook, \
|
SPCOutlook, \
|
||||||
|
@ -25,7 +26,8 @@ ASSETS = {
|
||||||
def render_categorical(conus: SPCOutlookMap,
|
def render_categorical(conus: SPCOutlookMap,
|
||||||
outlook: SPCOutlook,
|
outlook: SPCOutlook,
|
||||||
args):
|
args):
|
||||||
db = Database.connect(args.db)
|
config = Config.load()
|
||||||
|
db = Database.from_config(config)
|
||||||
|
|
||||||
assets = ASSETS['dark'] if args.dark else ASSETS['light']
|
assets = ASSETS['dark'] if args.dark else ASSETS['light']
|
||||||
|
|
||||||
|
@ -48,7 +50,8 @@ def render_probabilistic(conus: SPCOutlookMap,
|
||||||
hazard: str,
|
hazard: str,
|
||||||
path: str,
|
path: str,
|
||||||
args):
|
args):
|
||||||
db = Database.connect(args.db)
|
config = Config.load()
|
||||||
|
db = Database.from_config(config)
|
||||||
|
|
||||||
assets = ASSETS['dark'] if args.dark else ASSETS['light']
|
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)
|
conus.draw_annotation(cr, outlook, SPCOutlookType.PROBABILISTIC, hazard)
|
||||||
|
|
||||||
argparser = argparse.ArgumentParser(description='Render graphical SPC outlooks from text file')
|
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('--dark', action='store_true', help='Output dark mode graphics')
|
||||||
argparser.add_argument('--categorical', type=str, help='Output categorical risk graphic file')
|
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')
|
argparser.add_argument('--any-severe', type=str, help='Output probabilistic severe risk graphic file')
|
||||||
|
|
36
lib/xmet/config.py
Normal file
36
lib/xmet/config.py
Normal 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
|
|
@ -1,6 +1,10 @@
|
||||||
import enum
|
import enum
|
||||||
import sqlite3
|
import sqlite3
|
||||||
|
|
||||||
|
from typing import Self
|
||||||
|
|
||||||
|
from xmet.config import Config
|
||||||
|
|
||||||
class DatabaseOrder(enum.Enum):
|
class DatabaseOrder(enum.Enum):
|
||||||
DEFAULT = 0
|
DEFAULT = 0
|
||||||
ASC = 1
|
ASC = 1
|
||||||
|
@ -112,6 +116,10 @@ class Database():
|
||||||
|
|
||||||
return Database(db)
|
return Database(db)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def from_config(config: Config) -> Self:
|
||||||
|
return Database.connect(config['database']['path'])
|
||||||
|
|
||||||
def column_placeholders(self, table, obj) -> list:
|
def column_placeholders(self, table, obj) -> list:
|
||||||
ret = list()
|
ret = list()
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue