~homeworkprod/byceps

2c36ca1dd7ac5667b5d8502ae39f59d2a17e3e00 — Jochen Kupperschmidt 9 months ago 1911903
Use `flask.Config.from_envvar`, remove `byceps.util.system.get_config_filename_from_env[_or_exit]`

The application config filename is now optional. If it is not specified,
the environment variable `BYCEPS_CONFIG` is expected to be set.
M app.py => app.py +1 -4
@@ 21,12 21,9 @@ from byceps.services.ticketing.ticket_service import find_ticket_by_code
from byceps.services.user.dbmodels.detail import UserDetail
from byceps.services.user.dbmodels.user import User
from byceps.services.user.service import find_user_by_screen_name
from byceps.util.system import get_config_filename_from_env_or_exit


config_filename = get_config_filename_from_env_or_exit()

app = create_app(config_filename)
app = create_app()


if app.env == 'development':

M byceps/application.py => byceps/application.py +5 -2
@@ 28,15 28,18 @@ from .util.views import redirect_to


def create_app(
    config_filename: Union[Path, str],
    *,
    config_filename: Optional[Union[Path, str]] = None,
    config_overrides: Optional[Dict[str, Any]] = None,
) -> Flask:
    """Create the actual Flask application."""
    app = Flask('byceps')

    app.config.from_object(config_defaults)
    app.config.from_pyfile(str(config_filename))
    if config_filename is not None:
        app.config.from_pyfile(str(config_filename))
    else:
        app.config.from_envvar('BYCEPS_CONFIG')
    if config_overrides is not None:
        app.config.from_mapping(config_overrides)


M byceps/util/system.py => byceps/util/system.py +0 -29
@@ 7,14 7,10 @@ byceps.util.system
"""

import os
import sys

from ..config import ConfigurationError


CONFIG_VAR_NAME = 'BYCEPS_CONFIG'


def get_env_value(name: str, error_message: str) -> str:
    """Return the value of the environment variable.



@@ 26,28 22,3 @@ def get_env_value(name: str, error_message: str) -> str:
        raise ConfigurationError(error_message)

    return env


def get_config_filename_from_env() -> str:
    """Return the configuration filename set via environment variable.

    Raise an exception if it isn't set.
    """
    error_message = (
        "No configuration file was specified via the "
        f"'{CONFIG_VAR_NAME}' environment variable."
    )

    return get_env_value(CONFIG_VAR_NAME, error_message)


def get_config_filename_from_env_or_exit() -> str:
    """Return the configuration filename set via environment variable.

    Exit if it isn't set.
    """
    try:
        return get_config_filename_from_env()
    except ConfigurationError as e:
        sys.stderr.write(f"{e}\n")
        sys.exit(1)

M scripts/_util.py => scripts/_util.py +2 -2
@@ 14,10 14,10 @@ from byceps.application import create_app


@contextmanager
def app_context(config_filename):
def app_context():
    """Provide a context in which the application is available with the
    specified configuration.
    """
    app = create_app(config_filename)
    app = create_app()
    with app.app_context():
        yield app

M scripts/add_archived_attendance.py => scripts/add_archived_attendance.py +1 -3
@@ 10,7 10,6 @@ import click

from byceps.services.ticketing import attendance_service
from byceps.services.user import service as user_service
from byceps.util.system import get_config_filename_from_env_or_exit

from _util import app_context
from _validators import validate_party, validate_user_id


@@ 32,6 31,5 @@ def execute(user, party):


if __name__ == '__main__':
    config_filename = get_config_filename_from_env_or_exit()
    with app_context(config_filename):
    with app_context():
        execute()

M scripts/announce_orga_birthdays.py => scripts/announce_orga_birthdays.py +1 -3
@@ 14,7 14,6 @@ from byceps.announce.helpers import call_webhook
from byceps.services.orga import birthday_service
from byceps.services.webhooks import service as webhook_service
from byceps.services.webhooks.transfer.models import OutgoingWebhook, WebhookID
from byceps.util.system import get_config_filename_from_env_or_exit

from _util import app_context



@@ 41,6 40,5 @@ def execute(webhook: OutgoingWebhook):


if __name__ == '__main__':
    config_filename = get_config_filename_from_env_or_exit()
    with app_context(config_filename):
    with app_context():
        execute()

M scripts/clean_up_after_deleted_users.py => scripts/clean_up_after_deleted_users.py +1 -3
@@ 38,7 38,6 @@ from byceps.services.verification_token.dbmodels import (
    Token as VerificationToken,
)
from byceps.typing import UserID
from byceps.util.system import get_config_filename_from_env_or_exit

from _util import app_context



@@ 172,6 171,5 @@ def _execute_delete_for_users_query(model, user_ids: Set[UserID]) -> int:


if __name__ == '__main__':
    config_filename = get_config_filename_from_env_or_exit()
    with app_context(config_filename):
    with app_context():
        execute()

M scripts/copy_snippets.py => scripts/copy_snippets.py +1 -3
@@ 10,7 10,6 @@ import click

from byceps.services.snippet import service as snippet_service
from byceps.services.snippet.transfer.models import Scope, SnippetType
from byceps.util.system import get_config_filename_from_env_or_exit

from _util import app_context
from _validators import validate_site


@@ 92,6 91,5 @@ def scope_as_string(scope):


if __name__ == '__main__':
    config_filename = get_config_filename_from_env_or_exit()
    with app_context(config_filename):
    with app_context():
        execute()

M scripts/create_database_tables.py => scripts/create_database_tables.py +1 -3
@@ 11,7 11,6 @@ Existing tables will be ignored, and those not existing will be created.
import click

from byceps.database import db
from byceps.util.system import get_config_filename_from_env_or_exit

from _util import app_context



@@ 26,6 25,5 @@ def execute():


if __name__ == '__main__':
    config_filename = get_config_filename_from_env_or_exit()
    with app_context(config_filename):
    with app_context():
        execute()

M scripts/create_initial_admin_user.py => scripts/create_initial_admin_user.py +1 -3
@@ 11,7 11,6 @@ import click
from byceps.services.authorization import service as authorization_service
from byceps.services.user import command_service as user_command_service
from byceps.services.user import creation_service as user_creation_service
from byceps.util.system import get_config_filename_from_env_or_exit

from _util import app_context



@@ 57,6 56,5 @@ def _assign_roles_to_user(roles, user_id):


if __name__ == '__main__':
    config_filename = get_config_filename_from_env_or_exit()
    with app_context(config_filename):
    with app_context():
        execute()

M scripts/create_seating_area.py => scripts/create_seating_area.py +1 -3
@@ 9,7 9,6 @@
import click

from byceps.services.seating import area_service
from byceps.util.system import get_config_filename_from_env_or_exit

from _util import app_context
from _validators import validate_party


@@ 25,6 24,5 @@ def execute(party, slug, title):


if __name__ == '__main__':
    config_filename = get_config_filename_from_env_or_exit()
    with app_context(config_filename):
    with app_context():
        execute()

M scripts/create_terms_version.py => scripts/create_terms_version.py +1 -3
@@ 16,7 16,6 @@ from byceps.services.snippet.transfer.models import SnippetVersionID
from byceps.services.terms import document_service as terms_document_service
from byceps.services.terms.transfer.models import DocumentID
from byceps.services.terms import version_service as terms_version_service
from byceps.util.system import get_config_filename_from_env_or_exit

from _util import app_context
from _validators import validate_brand


@@ 72,6 71,5 @@ def _create_consent_subject(brand, title, consent_subject_name_suffix):


if __name__ == '__main__':
    config_filename = get_config_filename_from_env_or_exit()
    with app_context(config_filename):
    with app_context():
        execute()

M scripts/delete_old_user_login_events.py => scripts/delete_old_user_login_events.py +1 -3
@@ 11,7 11,6 @@ from datetime import datetime, timedelta
import click

from byceps.services.user import event_service as user_event_service
from byceps.util.system import get_config_filename_from_env_or_exit

from _util import app_context



@@ 33,6 32,5 @@ def execute(minimum_age_in_days):


if __name__ == '__main__':
    config_filename = get_config_filename_from_env_or_exit()
    with app_context(config_filename):
    with app_context():
        execute()

M scripts/export_permissions_and_roles.py => scripts/export_permissions_and_roles.py +1 -3
@@ 9,7 9,6 @@
import click

from byceps.services.authorization import impex_service
from byceps.util.system import get_config_filename_from_env_or_exit

from _util import app_context



@@ 20,6 19,5 @@ def execute():


if __name__ == '__main__':
    config_filename = get_config_filename_from_env_or_exit()
    with app_context(config_filename):
    with app_context():
        execute()

M scripts/export_ticket_user_email_addresses.py => scripts/export_ticket_user_email_addresses.py +1 -3
@@ 13,7 13,6 @@ import click
from byceps.services.ticketing import ticket_service
from byceps.services.user import service as user_service
from byceps.typing import PartyID
from byceps.util.system import get_config_filename_from_env_or_exit

from _util import app_context
from _validators import validate_party


@@ 41,6 40,5 @@ def _get_email_addresses(party_id: PartyID) -> Iterator[str]:


if __name__ == '__main__':
    config_filename = get_config_filename_from_env_or_exit()
    with app_context(config_filename):
    with app_context():
        execute()

M scripts/find_logins_for_ipaddress.py => scripts/find_logins_for_ipaddress.py +1 -3
@@ 14,7 14,6 @@ from byceps.services.user.dbmodels.event import UserEvent
from byceps.services.user import service as user_service
from byceps.services.user.transfer.models import User
from byceps.typing import PartyID, UserID
from byceps.util.system import get_config_filename_from_env_or_exit

from _util import app_context



@@ 45,6 44,5 @@ def get_users_by_id(events: List[UserEvent]) -> Dict[UserID, User]:


if __name__ == '__main__':
    config_filename = get_config_filename_from_env_or_exit()
    with app_context(config_filename):
    with app_context():
        execute()

M scripts/generate_sql_to_delete_user.py => scripts/generate_sql_to_delete_user.py +1 -3
@@ 17,7 17,6 @@ import click

from byceps.services.user import service as user_service
from byceps.typing import UserID
from byceps.util.system import get_config_filename_from_env_or_exit

from _util import app_context
from _validators import validate_user_id_format


@@ 71,6 70,5 @@ def generate_delete_statements_for_user(user_id: UserID) -> Iterator[str]:


if __name__ == '__main__':
    config_filename = get_config_filename_from_env_or_exit()
    with app_context(config_filename):
    with app_context():
        execute()

M scripts/grant_board_access.py => scripts/grant_board_access.py +1 -3
@@ 10,7 10,6 @@ import click

from byceps.services.board import access_control_service, board_service
from byceps.services.board.transfer.models import Board
from byceps.util.system import get_config_filename_from_env_or_exit

from _util import app_context
from _validators import validate_user_screen_name


@@ 49,6 48,5 @@ def execute(board, user):


if __name__ == '__main__':
    config_filename = get_config_filename_from_env_or_exit()
    with app_context(config_filename):
    with app_context():
        execute()

M scripts/import_permissions_and_roles.py => scripts/import_permissions_and_roles.py +1 -3
@@ 9,7 9,6 @@
import click

from byceps.services.authorization import impex_service
from byceps.util.system import get_config_filename_from_env_or_exit

from _util import app_context



@@ 25,6 24,5 @@ def execute(data_file):


if __name__ == '__main__':
    config_filename = get_config_filename_from_env_or_exit()
    with app_context(config_filename):
    with app_context():
        execute()

M scripts/occupy_seat_group.py => scripts/occupy_seat_group.py +1 -3
@@ 10,7 10,6 @@ import click

from byceps.services.seating import seat_group_service
from byceps.services.ticketing import ticket_bundle_service
from byceps.util.system import get_config_filename_from_env_or_exit

from _util import app_context



@@ 45,6 44,5 @@ def execute(seat_group, ticket_bundle):


if __name__ == '__main__':
    config_filename = get_config_filename_from_env_or_exit()
    with app_context(config_filename):
    with app_context():
        execute()

M scripts/remove_user_sessions.py => scripts/remove_user_sessions.py +1 -3
@@ 15,7 15,6 @@ Sessions will be recreated on demand after successful login.
import click

from byceps.services.authentication.session import service as session_service
from byceps.util.system import get_config_filename_from_env_or_exit

from _util import app_context



@@ 29,6 28,5 @@ def execute():


if __name__ == '__main__':
    config_filename = get_config_filename_from_env_or_exit()
    with app_context(config_filename):
    with app_context():
        execute()

M scripts/search_snippets.py => scripts/search_snippets.py +1 -3
@@ 10,7 10,6 @@ import click

from byceps.services.snippet import service as snippet_service
from byceps.services.snippet.transfer.models import Scope
from byceps.util.system import get_config_filename_from_env_or_exit

from _util import app_context
from _validators import validate_site


@@ 73,6 72,5 @@ def format_scope(scope):


if __name__ == '__main__':
    config_filename = get_config_filename_from_env_or_exit()
    with app_context(config_filename):
    with app_context():
        execute()

M scripts/set_current_terms_version.py => scripts/set_current_terms_version.py +1 -3
@@ 15,7 15,6 @@ from byceps.services.terms import document_service as terms_document_service
from byceps.services.terms.dbmodels.version import Version
from byceps.services.terms.transfer.models import DocumentID, VersionID
from byceps.services.terms import document_service, version_service
from byceps.util.system import get_config_filename_from_env_or_exit

from _util import app_context



@@ 97,6 96,5 @@ def _get_version_ids_latest_first(


if __name__ == '__main__':
    config_filename = get_config_filename_from_env_or_exit()
    with app_context(config_filename):
    with app_context():
        execute()

M serve.py => serve.py +1 -4
@@ 7,9 7,6 @@ an environment variable.
"""

from byceps.application import create_app
from byceps.util.system import get_config_filename_from_env_or_exit


config_filename = get_config_filename_from_env_or_exit()

app = create_app(config_filename)
app = create_app()

M tests/helpers.py => tests/helpers.py +5 -3
@@ 36,14 36,16 @@ CONFIG_FILENAME_TEST_ADMIN = _CONFIG_PATH / 'test_admin.py'

def create_admin_app(config_overrides: Optional[Dict[str, Any]] = None):
    app = create_app(
        CONFIG_FILENAME_TEST_ADMIN, config_overrides=config_overrides
        config_filename=CONFIG_FILENAME_TEST_ADMIN,
        config_overrides=config_overrides,
    )
    return app


def create_site_app(config_overrides: Optional[Dict[str, Any]] = None):
    app = create_app(
        CONFIG_FILENAME_TEST_SITE, config_overrides=config_overrides
        config_filename=CONFIG_FILENAME_TEST_SITE,
        config_overrides=config_overrides,
    )
    return app



@@ 54,7 56,7 @@ def generate_token() -> str:

@contextmanager
def app_context(*, config_filename=CONFIG_FILENAME_TEST_SITE):
    app = create_app(config_filename)
    app = create_app(config_filename=config_filename)

    with app.app_context():
        yield app

M tests/unit/util/test_system.py => tests/unit/util/test_system.py +1 -40
@@ 6,11 6,7 @@
import pytest

from byceps.config import ConfigurationError
from byceps.util.system import (
    get_config_filename_from_env,
    get_config_filename_from_env_or_exit,
    get_env_value,
)
from byceps.util.system import get_env_value


def test_get_env_value_with_value(monkeypatch):


@@ 35,38 31,3 @@ def test_get_env_value_without_value():
        get_env_value('LAUNCH_CODE', 'Invalid launch code')

    assert str(excinfo.value) == 'Invalid launch code'


# -------------------------------------------------------------------- #


def test_get_config_filename_from_env_with_value(monkeypatch):
    monkeypatch.setenv('BYCEPS_CONFIG', 'site01_prod')

    assert get_config_filename_from_env() == 'site01_prod'


def test_get_config_filename_from_env_without_value():
    with pytest.raises(ConfigurationError) as excinfo:
        get_config_filename_from_env()

    assert str(excinfo.value) == (
        "No configuration file was specified via the 'BYCEPS_CONFIG' "
        'environment variable.'
    )


# -------------------------------------------------------------------- #


def test_get_config_filename_from_env_or_exit_with_value(monkeypatch):
    monkeypatch.setenv('BYCEPS_CONFIG', 'site01_prod')

    assert get_config_filename_from_env_or_exit() == 'site01_prod'


def test_get_config_filename_from_env_or_exit_without_value():
    with pytest.raises(SystemExit) as excinfo:
        get_config_filename_from_env_or_exit()

    assert excinfo.value.code == 1

M worker.py => worker.py +1 -4
@@ 9,13 9,10 @@ from rq import Worker

from byceps.application import create_app
from byceps.util.jobqueue import connection, get_queue
from byceps.util.system import get_config_filename_from_env_or_exit


if __name__ == '__main__':
    config_filename = get_config_filename_from_env_or_exit()

    app = create_app(config_filename)
    app = create_app()

    with app.app_context():
        with connection():