Formats updating repeatedly in Flask app despite 14-day threshold

I wrote a Flask app to update MTG formats automatically. It’s supposed to update only once 14 days after a Standard-legal set release. I save the latest updated set in a JSON file and check both the last update timestamp and the latest set name before updating again.

I originally thought Flask’s auto-reloader was causing the updates to run multiple times, so I added this check to app.py:

if __name__ == "__main__" and os.environ.get("WERKZEUG_RUN_MAIN") == "true":
    update_formats_if_needed()

Here’s the relevant part of my update logic:

import os
import json
import requests
import subprocess
from datetime import datetime, timezone, timedelta

from shared.configuration import LAST_UPDATED_FILE, WIS_SETS_API, UPDATE_THRESHOLD_DAYS


def fetch_sets_data():
    response = requests.get(WIS_SETS_API)
    response.raise_for_status()
    return response.json()["sets"]


def load_saved_update(file_path=LAST_UPDATED_FILE):
    """Return a dict with 'updated_at' (datetime) and 'latest_set' (str)"""
    if os.path.exists(file_path):
        with open(file_path, "r") as f:
            data = json.load(f)
            updated_at = datetime.fromisoformat(data.get("updated_at"))
            latest_set = data.get("latest_set")
            return {"updated_at": updated_at, "latest_set": latest_set}
    return {"updated_at": None, "latest_set": None}


def save_update(updated_at, latest_set, file_path=LAST_UPDATED_FILE):
    with open(file_path, "w") as f:
        json.dump({"updated_at": updated_at.isoformat(), "latest_set": latest_set}, f)


def check_for_update(latest_set_name, latest_updated_at, saved_data):
    now = datetime.now(timezone.utc)
    saved_updated_at = saved_data["updated_at"]
    saved_set_name = saved_data["latest_set"]

    # Update if no previous update
    if saved_updated_at is None:
        return True

    # Update if set changed
    if latest_set_name != saved_set_name:
        return True

    # Update if threshold of days exceeded
    if now - saved_updated_at >= timedelta(days=UPDATE_THRESHOLD_DAYS):
        return True

    return False


def git_commit_push():
    try:
        subprocess.run(["git", "add", "."], check=True)
        subprocess.run(["git", "commit", "-m", "Auto-update MTG formats"], check=True)
        subprocess.run(["git", "push"], check=True)
        print("Changes committed and pushed to remote.")
    except subprocess.CalledProcessError:
        print("No changes to commit or git error.")


def update_formats_if_needed():
    now = datetime.now(timezone.utc)
    sets = fetch_sets_data()

    released_sets = [
        s
        for s in sets
        if s.get("enterDate", {}).get("exact")
        and datetime.fromisoformat(s["enterDate"]["exact"]).replace(tzinfo=timezone.utc)
        <= now
    ]

    if not released_sets:
        print("No sets released yet")
        return

    latest_set = max(
        released_sets,
        key=lambda s: datetime.fromisoformat(s["enterDate"]["exact"]).replace(
            tzinfo=timezone.utc
        ),
    )
    latest_updated_at = datetime.fromisoformat(
        latest_set["enterDate"]["exact"]
    ).replace(tzinfo=timezone.utc)
    saved_data = load_saved_update()

    if check_for_update(latest_set["name"], latest_updated_at, saved_data):
        print(f"Updating to latest released set: {latest_set['name']}")
        os.system("python -m scripts.build_format_jsons")
        os.system("python -m scripts.build_filtered_formats")
        os.system("python -m scripts.build_heirloom_format")
        save_update(latest_updated_at, latest_set["name"])
        git_commit_push()
    else:
        print(f"No update needed. Latest applied set: {saved_data['latest_set']}")


if __name__ == "__main__":
    update_formats_if_needed()

But whenever I run python app.py, the updates run again and again, even though the JSON file correctly stores the last updated set and timestamp.

Why might the app still update repeatedly instead of respecting the 14-day threshold? Could this be related to Flask’s debug mode or the way I’m calling these three similar scripts?

os.system("python -m scripts.build_format_jsons")
os.system("python -m scripts.build_filtered_formats")
os.system("python -m scripts.build_heirloom_format")

Thanks in advance!

update_formats_if_needed calls check_for_update, passing latest_updated_at.

What is the value of latest_updated_at?

It comes from latest_set["enterDate"]["exact"], which is the maximum from released_sets.

Where are those datetimes updated, because I don’t see them being updated anywhere in the given script.

I’m getting latest_set["enterDate"]["exact"] directly from the API at https://whatsinstandard.com/api/v6/standard.json. Every time update_formats_if_needed() runs, it fetches all Standard-legal sets from that endpoint, filters the ones already released, and picks the latest set. The ["exact"] field of that set is what I should be using as release_date in check_for_update instead of saved_updated_at.

Here’s the fixed code:

def check_for_update(
    latest_set: Dict[str, Any],
    saved_data: Dict[str, Any],
    threshold_days: int = UPDATE_THRESHOLD_DAYS,
) -> bool:
    """
    Determine whether an update should be performed based on the latest set and saved data.

    Updates are triggered if:
        - No previous update exists.
        - The latest set differs from the last applied set and threshold days have passed since its release.

    Args:
        latest_set (Dict[str, Any]): The latest released set information.
        saved_data (Dict[str, Any]): Previously saved update information.
        threshold_days (int, optional): Minimum days after release before updating. Defaults to UPDATE_THRESHOLD_DAYS.

    Returns:
        bool: True if an update should be performed, False otherwise.
    """
    now = datetime.now(timezone.utc)
    saved_updated_at = saved_data.get("updated_at")
    saved_set_name = saved_data.get("latest_set")

    if saved_updated_at is None or saved_set_name is None:
        return True

    latest_set_name = latest_set.get("name")
    if not latest_set_name:
        return False

    if saved_set_name == latest_set_name:
        return False

    release_iso = latest_set.get("enterDate", {}).get("exact")
    if not release_iso:
        return False

    release_date = datetime.fromisoformat(release_iso).replace(tzinfo=timezone.utc)
    if now - release_date >= timedelta(days=threshold_days):
        return True

    return False

Tests:

import pytest
from datetime import datetime, timedelta, timezone
import utils.update_formats as uf


# -------------------------------
# Unit Tests for check_for_update
# -------------------------------


def test_check_for_update_no_previous_data():
    now = datetime.now(timezone.utc)
    latest_set = {"name": "SetNew", "enterDate": {"exact": now.isoformat()}}
    saved = {"updated_at": None, "latest_set": None}
    assert uf.check_for_update(latest_set, saved)


def test_check_for_update_wait_for_next_release():
    now = datetime.now(timezone.utc)
    latest_set = {
        "name": "SetA",
        "enterDate": {"exact": (now - timedelta(days=5)).isoformat()},
    }
    saved = {"updated_at": now, "latest_set": "SetA"}
    assert not uf.check_for_update(latest_set, saved)


def test_check_for_update_threshold_exceeded():
    now = datetime.now(timezone.utc)
    latest_set = {
        "name": "SetA",
        "enterDate": {"exact": (now - timedelta(days=15)).isoformat()},
    }
    saved = {"updated_at": now - timedelta(days=1), "latest_set": "OldSet"}
    assert uf.check_for_update(latest_set, saved)


def test_check_for_update_missing_name():
    """Returns False if latest_set has no 'name'."""
    now = datetime.now(timezone.utc)
    latest_set = {"enterDate": {"exact": now.isoformat()}}
    saved = {"updated_at": now, "latest_set": "OldSet"}
    assert not uf.check_for_update(latest_set, saved)


def test_check_for_update_missing_enterDate():
    """Returns False if latest_set has no 'enterDate'."""
    now = datetime.now(timezone.utc)
    latest_set = {"name": "SetX"}
    saved = {"updated_at": now, "latest_set": "OldSet"}
    assert not uf.check_for_update(latest_set, saved)


def test_check_for_update_missing_exact_in_enterDate():
    """Returns False if latest_set['enterDate'] exists but has no 'exact'."""
    now = datetime.now(timezone.utc)
    latest_set = {"name": "SetX", "enterDate": {}}
    saved = {"updated_at": now, "latest_set": "OldSet"}
    assert not uf.check_for_update(latest_set, saved)