From 8bf071afc5b868a182f1fa913259ca2dc6d32a6d Mon Sep 17 00:00:00 2001 From: Zach Aysan Date: Thu, 29 Feb 2024 14:37:09 +0000 Subject: [PATCH 1/6] Set the environment for local evaluation mode on init --- flagsmith/flagsmith.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/flagsmith/flagsmith.py b/flagsmith/flagsmith.py index 7a807af..0966730 100644 --- a/flagsmith/flagsmith.py +++ b/flagsmith/flagsmith.py @@ -167,6 +167,9 @@ def _initialise_local_evaluation(self) -> None: self.event_stream_thread.start() else: + # To ensure that the environment is set before allowing subsequent + # method calls, update the environment manually. + self.update_environment() self.environment_data_polling_manager_thread = ( EnvironmentDataPollingManager( main=self, From 297342b925cdec74dd2848342ded627a5240bdc3 Mon Sep 17 00:00:00 2001 From: Zach Aysan Date: Fri, 1 Mar 2024 15:08:28 +0000 Subject: [PATCH 2/6] Make tests pass with the update environment change --- tests/test_flagsmith.py | 8 ++++++-- tests/test_polling_manager.py | 18 ++++++++++++++++-- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/tests/test_flagsmith.py b/tests/test_flagsmith.py index 5c1cd3b..3ac172a 100644 --- a/tests/test_flagsmith.py +++ b/tests/test_flagsmith.py @@ -17,7 +17,11 @@ from pytest_mock import MockerFixture -def test_flagsmith_starts_polling_manager_on_init_if_enabled(mocker, server_api_key): +def test_flagsmith_starts_polling_manager_on_init_if_enabled( + mocker: MockerFixture, + server_api_key: str, + requests_session_response_ok: None, +) -> None: # Given mock_polling_manager = mocker.MagicMock() mocker.patch( @@ -408,7 +412,7 @@ def get_environment(self) -> "EnvironmentModel": @responses.activate() def test_flagsmith_uses_offline_handler_if_set_and_no_api_response( - mocker: "MockerFixture", environment_model: "EnvironmentModel" + mocker: MockerFixture, environment_model: "EnvironmentModel" ) -> None: # Given api_url = "http://some.flagsmith.com/api/v1/" diff --git a/tests/test_polling_manager.py b/tests/test_polling_manager.py index 6cfcffd..2570107 100644 --- a/tests/test_polling_manager.py +++ b/tests/test_polling_manager.py @@ -2,6 +2,7 @@ from unittest import mock import requests +from pytest_mock import MockerFixture from flagsmith import Flagsmith from flagsmith.polling_manager import EnvironmentDataPollingManager @@ -40,10 +41,16 @@ def test_polling_manager_calls_update_environment_on_each_refresh(): polling_manager.stop() -def test_polling_manager_is_resilient_to_api_errors(mocker, server_api_key): +def test_polling_manager_is_resilient_to_api_errors( + mocker: MockerFixture, + server_api_key: str, +) -> None: # Given session_mock = mocker.patch("requests.Session") session_mock.get.return_value = mock.MagicMock(status_code=500) + # Sidestep update_environment since it breaks with the above. + mocker.patch("flagsmith.Flagsmith.update_environment") + flagsmith = Flagsmith( environment_key=server_api_key, enable_local_evaluation=True, @@ -56,10 +63,17 @@ def test_polling_manager_is_resilient_to_api_errors(mocker, server_api_key): polling_manager.stop() -def test_polling_manager_is_resilient_to_request_exceptions(mocker, server_api_key): +def test_polling_manager_is_resilient_to_request_exceptions( + mocker: MockerFixture, + server_api_key: str, +) -> None: # Given session_mock = mocker.patch("requests.Session") session_mock.get.side_effect = requests.RequestException() + + # Sidestep update_environment since it breaks with the above. + mocker.patch("flagsmith.Flagsmith.update_environment") + flagsmith = Flagsmith( environment_key=server_api_key, enable_local_evaluation=True, From 905ec7bc220192bed8b77ebeaca317bc5bb9e1f1 Mon Sep 17 00:00:00 2001 From: Zach Aysan Date: Fri, 1 Mar 2024 16:04:22 +0000 Subject: [PATCH 3/6] Fix test failure --- tests/test_flagsmith.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_flagsmith.py b/tests/test_flagsmith.py index 3ac172a..f2eb9b5 100644 --- a/tests/test_flagsmith.py +++ b/tests/test_flagsmith.py @@ -6,6 +6,7 @@ import requests import responses from flag_engine.features.models import FeatureModel, FeatureStateModel +from pytest_mock import MockerFixture from flagsmith import Flagsmith from flagsmith.exceptions import FlagsmithAPIError @@ -14,7 +15,6 @@ if typing.TYPE_CHECKING: from flag_engine.environments.models import EnvironmentModel - from pytest_mock import MockerFixture def test_flagsmith_starts_polling_manager_on_init_if_enabled( From 050524cdbf434dcb1341df1aa23aafb3f4fef381 Mon Sep 17 00:00:00 2001 From: Zach Aysan Date: Tue, 12 Mar 2024 20:10:07 +0000 Subject: [PATCH 4/6] Make update environment update local document --- tests/test_polling_manager.py | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/tests/test_polling_manager.py b/tests/test_polling_manager.py index 2570107..4143abe 100644 --- a/tests/test_polling_manager.py +++ b/tests/test_polling_manager.py @@ -2,6 +2,7 @@ from unittest import mock import requests +import responses from pytest_mock import MockerFixture from flagsmith import Flagsmith @@ -41,21 +42,23 @@ def test_polling_manager_calls_update_environment_on_each_refresh(): polling_manager.stop() +@responses.activate() def test_polling_manager_is_resilient_to_api_errors( + flagsmith: Flagsmith, + environment_json: str, mocker: MockerFixture, server_api_key: str, ) -> None: # Given - session_mock = mocker.patch("requests.Session") - session_mock.get.return_value = mock.MagicMock(status_code=500) - # Sidestep update_environment since it breaks with the above. - mocker.patch("flagsmith.Flagsmith.update_environment") - + responses.add(method="GET", url=flagsmith.environment_url, body=environment_json) flagsmith = Flagsmith( environment_key=server_api_key, enable_local_evaluation=True, environment_refresh_interval_seconds=0.1, ) + + session_mock = mocker.patch("requests.Session") + session_mock.get.return_value = mock.MagicMock(status_code=500) polling_manager = flagsmith.environment_data_polling_manager_thread # Then @@ -63,22 +66,23 @@ def test_polling_manager_is_resilient_to_api_errors( polling_manager.stop() +@responses.activate() def test_polling_manager_is_resilient_to_request_exceptions( + flagsmith: Flagsmith, + environment_json: str, mocker: MockerFixture, server_api_key: str, ) -> None: # Given - session_mock = mocker.patch("requests.Session") - session_mock.get.side_effect = requests.RequestException() - - # Sidestep update_environment since it breaks with the above. - mocker.patch("flagsmith.Flagsmith.update_environment") - + responses.add(method="GET", url=flagsmith.environment_url, body=environment_json) flagsmith = Flagsmith( environment_key=server_api_key, enable_local_evaluation=True, environment_refresh_interval_seconds=0.1, ) + + session_mock = mocker.patch("requests.Session") + session_mock.get.side_effect = requests.RequestException() polling_manager = flagsmith.environment_data_polling_manager_thread # Then From 1ae13d2a34c9e4997d8386020017e3d7ebb88198 Mon Sep 17 00:00:00 2001 From: Zach Aysan Date: Wed, 13 Mar 2024 14:08:09 +0000 Subject: [PATCH 5/6] Use responses for polling manager tests --- tests/test_polling_manager.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/tests/test_polling_manager.py b/tests/test_polling_manager.py index 4143abe..7c8c059 100644 --- a/tests/test_polling_manager.py +++ b/tests/test_polling_manager.py @@ -57,10 +57,10 @@ def test_polling_manager_is_resilient_to_api_errors( environment_refresh_interval_seconds=0.1, ) - session_mock = mocker.patch("requests.Session") - session_mock.get.return_value = mock.MagicMock(status_code=500) + responses.add(method="GET", url=flagsmith.environment_url, status=500) polling_manager = flagsmith.environment_data_polling_manager_thread + # Then assert polling_manager.is_alive() polling_manager.stop() @@ -81,8 +81,12 @@ def test_polling_manager_is_resilient_to_request_exceptions( environment_refresh_interval_seconds=0.1, ) - session_mock = mocker.patch("requests.Session") - session_mock.get.side_effect = requests.RequestException() + responses.add( + method="GET", + url=flagsmith.environment_url, + body=requests.RequestException("Some exception"), + status=500, + ) polling_manager = flagsmith.environment_data_polling_manager_thread # Then From 239fc6c9fb61489ec8ce5f3d32266f724f6a8521 Mon Sep 17 00:00:00 2001 From: Zach Aysan Date: Wed, 13 Mar 2024 14:11:10 +0000 Subject: [PATCH 6/6] Lint --- tests/test_polling_manager.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/test_polling_manager.py b/tests/test_polling_manager.py index 7c8c059..ee4b0fa 100644 --- a/tests/test_polling_manager.py +++ b/tests/test_polling_manager.py @@ -60,7 +60,6 @@ def test_polling_manager_is_resilient_to_api_errors( responses.add(method="GET", url=flagsmith.environment_url, status=500) polling_manager = flagsmith.environment_data_polling_manager_thread - # Then assert polling_manager.is_alive() polling_manager.stop()