2020-08-08 14:43:02 +02:00
|
|
|
"""Provide package-wide configuration.
|
|
|
|
|
|
2020-08-09 17:14:23 +02:00
|
|
|
This module provides utils to create new `Config` objects
|
|
|
|
|
on the fly, mainly for testing and migrating!
|
2020-08-08 14:43:02 +02:00
|
|
|
|
2020-08-09 17:14:23 +02:00
|
|
|
Within this package, use the `config` proxy at the package's top level
|
|
|
|
|
to access the current configuration!
|
2020-08-08 14:43:02 +02:00
|
|
|
"""
|
2020-08-09 17:14:23 +02:00
|
|
|
|
2020-08-08 14:43:02 +02:00
|
|
|
import datetime
|
|
|
|
|
import os
|
2020-08-09 03:45:19 +02:00
|
|
|
import random
|
|
|
|
|
import string
|
2020-08-08 14:43:02 +02:00
|
|
|
import warnings
|
|
|
|
|
|
|
|
|
|
|
2020-08-09 03:45:19 +02:00
|
|
|
def random_schema_name() -> str:
|
|
|
|
|
"""Generate a random PostgreSQL schema name for testing."""
|
2020-08-09 17:14:23 +02:00
|
|
|
return 'temp_{name}'.format(
|
|
|
|
|
name=''.join(
|
|
|
|
|
(random.choice(string.ascii_lowercase) for _ in range(10)), # noqa:S311
|
|
|
|
|
),
|
2020-08-09 03:45:19 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
2020-08-08 14:43:02 +02:00
|
|
|
class Config:
|
|
|
|
|
"""Configuration that applies in all situations."""
|
|
|
|
|
|
|
|
|
|
CUTOFF_DAY = datetime.datetime(2017, 2, 1)
|
|
|
|
|
|
|
|
|
|
# If a scheduled pre-order is made within this
|
|
|
|
|
# time horizon, we treat it as an ad-hoc order.
|
|
|
|
|
QUASI_AD_HOC_LIMIT = datetime.timedelta(minutes=45)
|
|
|
|
|
|
|
|
|
|
DATABASE_URI = os.getenv('DATABASE_URI')
|
|
|
|
|
|
|
|
|
|
# The PostgreSQL schema that holds the tables with the original data.
|
|
|
|
|
ORIGINAL_SCHEMA = os.getenv('ORIGINAL_SCHEMA') or 'public'
|
|
|
|
|
|
|
|
|
|
# The PostgreSQL schema that holds the tables with the cleaned data.
|
|
|
|
|
CLEAN_SCHEMA = os.getenv('CLEAN_SCHEMA') or 'clean'
|
|
|
|
|
|
2020-08-09 17:14:23 +02:00
|
|
|
ALEMBIC_TABLE = 'alembic_version'
|
|
|
|
|
ALEMBIC_TABLE_SCHEMA = 'public'
|
|
|
|
|
|
2020-08-08 14:43:02 +02:00
|
|
|
def __repr__(self) -> str:
|
|
|
|
|
"""Non-literal text representation."""
|
|
|
|
|
return '<configuration>'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class ProductionConfig(Config):
|
|
|
|
|
"""Configuration for the real dataset."""
|
|
|
|
|
|
|
|
|
|
TESTING = False
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class TestingConfig(Config):
|
|
|
|
|
"""Configuration for the test suite."""
|
|
|
|
|
|
|
|
|
|
TESTING = True
|
|
|
|
|
|
|
|
|
|
DATABASE_URI = os.getenv('DATABASE_URI_TESTING') or Config.DATABASE_URI
|
2020-08-09 03:45:19 +02:00
|
|
|
CLEAN_SCHEMA = os.getenv('CLEAN_SCHEMA_TESTING') or random_schema_name()
|
2020-08-08 14:43:02 +02:00
|
|
|
|
|
|
|
|
|
2020-08-09 17:14:23 +02:00
|
|
|
def make_config(env: str = 'production') -> Config:
|
|
|
|
|
"""Create a new `Config` object.
|
2020-08-08 14:43:02 +02:00
|
|
|
|
|
|
|
|
Args:
|
2020-12-14 15:15:08 +01:00
|
|
|
env: either 'production' or 'testing'
|
2020-08-08 14:43:02 +02:00
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
config: a namespace with all configurations
|
|
|
|
|
|
|
|
|
|
Raises:
|
|
|
|
|
ValueError: if `env` is not as specified
|
|
|
|
|
""" # noqa:DAR203
|
2020-12-14 15:15:08 +01:00
|
|
|
config: Config # otherwise mypy is confused
|
|
|
|
|
|
2020-08-08 14:43:02 +02:00
|
|
|
if env.strip().lower() == 'production':
|
|
|
|
|
config = ProductionConfig()
|
|
|
|
|
elif env.strip().lower() == 'testing':
|
|
|
|
|
config = TestingConfig()
|
|
|
|
|
else:
|
|
|
|
|
raise ValueError("Must be either 'production' or 'testing'")
|
|
|
|
|
|
|
|
|
|
# Without a PostgreSQL database the package cannot work.
|
2021-01-04 18:50:26 +01:00
|
|
|
# As pytest sets the "TESTING" environment variable explicitly,
|
|
|
|
|
# the warning is only emitted if the code is not run by pytest.
|
|
|
|
|
# We see the bad configuration immediately as all "db" tests fail.
|
|
|
|
|
if config.DATABASE_URI is None and not os.getenv('TESTING'):
|
2020-08-08 14:43:02 +02:00
|
|
|
warnings.warn('Bad configurartion: no DATABASE_URI set in the environment')
|
|
|
|
|
|
|
|
|
|
return config
|
2020-12-14 15:15:08 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
config = make_config('testing' if os.getenv('TESTING') else 'production')
|