Skip to content

Commit

Permalink
#270 fix the infinite calls to GEE by setting max attempts and add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
2320sharon committed Jul 10, 2024
1 parent cb08833 commit 0d8e4f1
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 11 deletions.
18 changes: 9 additions & 9 deletions src/coastseg/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -460,8 +460,7 @@ def initialize_gee(
# Authenticate and initialize
authenticate_and_initialize(print_mode, force, auth_args, kwargs)


def authenticate_and_initialize(print_mode:bool, force:bool, auth_args:dict, kwargs:dict):
def authenticate_and_initialize(print_mode: bool, force: bool, auth_args: dict, kwargs: dict, attempt: int = 1, max_attempts: int = 2):
"""
Handles the authentication and initialization of Google Earth Engine.
Expand All @@ -470,8 +469,10 @@ def authenticate_and_initialize(print_mode:bool, force:bool, auth_args:dict, kwa
force (bool): Flag indicating whether to force authentication.
auth_args (dict): Dictionary of authentication arguments for ee.Authenticate().
kwargs (dict): Dictionary of initialization arguments for ee.Initialize().
attempt (int): Current attempt number for authentication.
max_attempts (int): Maximum number of authentication attempts.
"""
logger.info(f"kwargs {kwargs} force {force} auth_args {auth_args} print_mode {print_mode}")
logger.info(f"kwargs {kwargs} force {force} auth_args {auth_args} print_mode {print_mode} attempt {attempt} max_attempts {max_attempts}")
if print_mode:
print(f"{'Forcing authentication and ' if force else ''}Initializing Google Earth Engine...\n")
try:
Expand All @@ -489,13 +490,12 @@ def authenticate_and_initialize(print_mode:bool, force:bool, auth_args:dict, kwa
else:
print(f"An error occurred: {error_message}\n")

# Re-attempt authentication only if not already attempted
if not force:
print("Re-attempting authentication...\n")
ee.Authenticate(**auth_args)
authenticate_and_initialize( print_mode, True, auth_args, kwargs) # Force re-authentication on retry
# Re-attempt authentication only if not already attempted and attempts are less than max_attempts
if attempt < max_attempts:
print(f"Re-attempting authentication (Attempt {attempt + 1}/{max_attempts})...\n")
authenticate_and_initialize(print_mode, True, auth_args, kwargs, attempt + 1, max_attempts) # Force re-authentication on retry
else:
raise Exception(f"Failed to initialize Google Earth Engine: {error_message}")
raise Exception(f"Failed to initialize Google Earth Engine after {attempt} attempts: {error_message}")


def create_new_config(roi_ids: list, settings: dict, roi_settings: dict) -> dict:
Expand Down
55 changes: 53 additions & 2 deletions tests/test_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,62 @@
from shapely import geometry
import pandas as pd
import pytest
from unittest.mock import patch
from unittest.mock import patch, call
import pytest
from coastseg import common
from typing import Dict, List, Union
from unittest.mock import patch


def test_authenticate_and_initialize_success():
with patch('coastseg.common.ee.Authenticate') as mock_authenticate, \
patch('coastseg.common.ee.Initialize') as mock_initialize:

# Mock successful initialization
mock_initialize.return_value = None

common.authenticate_and_initialize(print_mode=True, force=False, auth_args={}, kwargs={})

mock_authenticate.assert_called_once() # this will call once becase ee.credentials is None
mock_initialize.assert_called_once()

def test_authenticate_and_initialize_force_auth():
with patch('coastseg.common.ee.Authenticate') as mock_authenticate, \
patch('coastseg.common.ee.Initialize') as mock_initialize:

# Mock successful initialization
mock_initialize.return_value = None

common.authenticate_and_initialize(print_mode=True, force=True, auth_args={}, kwargs={})

mock_authenticate.assert_called_once_with(force=True)
mock_initialize.assert_called_once()

def test_authenticate_and_initialize_retry():
with patch('coastseg.common.ee.Authenticate') as mock_authenticate, \
patch('coastseg.common.ee.Initialize') as mock_initialize:

# Mock an exception on first initialize, then success
mock_initialize.side_effect = [Exception("Credentials file not found"), None]

common.authenticate_and_initialize(print_mode=True, force=False, auth_args={}, kwargs={})

assert mock_authenticate.call_count == 2
assert mock_initialize.call_count == 2

def test_authenticate_and_initialize_max_attempts():
with patch('coastseg.common.ee.Authenticate') as mock_authenticate, \
patch('coastseg.common.ee.Initialize') as mock_initialize:

# Mock an exception for all initialize attempts
mock_initialize.side_effect = Exception("Credentials file not found")

with pytest.raises(Exception) as excinfo:
common.authenticate_and_initialize(print_mode=True, force=False, auth_args={}, kwargs={})

assert "Failed to initialize Google Earth Engine after 3 attempts" in str(excinfo.value)
assert mock_authenticate.call_count == 3
assert mock_initialize.call_count == 3


def test_order_linestrings_gdf_empty():
gdf = gpd.GeoDataFrame({'geometry': []})
Expand Down

0 comments on commit 0d8e4f1

Please sign in to comment.