Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions lean/click.py
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,9 @@ def invoke(self, ctx: Context):
update_manager = container.update_manager
update_manager.show_announcements()

if ctx.params.get("update", False):
update_manager.force_refresh_modules_json()

result = super().invoke(ctx)

update_manager.warn_if_cli_outdated()
Expand Down
17 changes: 17 additions & 0 deletions lean/components/util/update_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,23 @@ def show_announcements(self) -> None:

self._logger.info(Panel.fit(table, title="Announcements", box=box.SQUARE))

def force_refresh_modules_json(self) -> None:
"""Forces a re-download of the modules JSON file, bypassing the 24-hour cache interval."""
from lean.models import url as modules_url, file_path as modules_file_path
from requests import get
try:
res = get(modules_url, timeout=5)
if res.ok:
from json import dump
modules_file_path.parent.mkdir(parents=True, exist_ok=True)
with open(modules_file_path, 'w', encoding='utf-8') as f:
dump(res.json(), f, ensure_ascii=False, indent=4)
else:
res.raise_for_status()
except Exception:
# No need to do anything if file isn't available
pass

def _should_check_for_updates(self, key: str, interval_hours: int) -> bool:
"""Returns whether an update check should be performed.

Expand Down
25 changes: 25 additions & 0 deletions tests/components/util/test_update_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,31 @@ def test_show_announcements_does_nothing_when_latest_announcements_shown_before(
logger.info.assert_not_called()


def test_force_refresh_modules_json_downloads_file(requests_mock: RequestsMock) -> None:
from lean.models import url as modules_url, file_path as modules_file_path
modules_json = {"modules": {"SomeModule": {"version": "1.0"}}}
requests_mock.add(requests_mock.GET, modules_url, json=modules_json)

logger, storage, docker_manager, update_manager = create_objects()

update_manager.force_refresh_modules_json()

assert modules_file_path.is_file()
with open(modules_file_path) as f:
assert json.load(f) == modules_json


def test_force_refresh_modules_json_does_nothing_when_offline(requests_mock: RequestsMock) -> None:
from lean.models import url as modules_url
from requests.exceptions import ConnectionError as RequestsConnectionError
requests_mock.add(requests_mock.GET, modules_url, body=RequestsConnectionError())

logger, storage, docker_manager, update_manager = create_objects()

# Should not raise
update_manager.force_refresh_modules_json()


def test_show_announcements_does_nothing_when_there_are_no_announcements(requests_mock: RequestsMock) -> None:
requests_mock.add(requests_mock.GET,
"https://raw.githubusercontent.com/QuantConnect/lean-cli/master/announcements.json",
Expand Down
Loading