diff --git a/src/apify/_actor.py b/src/apify/_actor.py index 0e175c31..3fc99128 100644 --- a/src/apify/_actor.py +++ b/src/apify/_actor.py @@ -34,9 +34,8 @@ from apify._utils import docs_group, docs_name, get_system_info, is_running_in_ipython from apify.events import ApifyEventManager, EventManager, LocalEventManager from apify.log import _configure_logging, logger -from apify.storage_clients import ApifyStorageClient +from apify.storage_clients import ApifyStorageClient, SmartApifyStorageClient from apify.storage_clients._file_system import ApifyFileSystemStorageClient -from apify.storage_clients._smart_apify._storage_client import SmartApifyStorageClient from apify.storages import Dataset, KeyValueStore, RequestQueue if TYPE_CHECKING: @@ -95,12 +94,6 @@ async def main() -> None: ``` """ - _is_rebooting = False - """Whether the Actor is currently rebooting.""" - - _is_any_instance_initialized = False - """Whether any Actor instance was initialized.""" - def __init__( self, configuration: Configuration | None = None, @@ -139,8 +132,14 @@ def __init__( self._apify_client: ApifyClientAsync | None = None - self._is_exiting = False self._is_initialized = False + """Whether any Actor instance is currently initialized.""" + + self._is_rebooting = False + """Whether the Actor is currently rebooting.""" + + self._is_exiting = False + """Whether the Actor is currently exiting.""" async def __aenter__(self) -> Self: """Enter the Actor context. @@ -169,15 +168,11 @@ async def __aenter__(self) -> Self: # Configure logging based on the configuration, any logs before this point are lost. if self._configure_logging: _configure_logging() - self.log.debug('Logging configured') + self.log.debug('Logging configured') self.log.info('Initializing Actor', extra=get_system_info()) self.log.debug('Configuration initialized') - # Warn about non-standard usage patterns. - if _ActorType._is_any_instance_initialized: - self.log.warning('Repeated Actor initialization detected - this is non-standard usage, proceed with care.') - # Update the global Actor proxy to refer to this instance. cast('Proxy', Actor).__wrapped__ = self self._is_exiting = False @@ -197,7 +192,6 @@ async def __aenter__(self) -> Self: # Mark initialization as complete and update global state. self._is_initialized = True - _ActorType._is_any_instance_initialized = True return self async def __aexit__( @@ -1113,11 +1107,11 @@ async def reboot( self.log.error('Actor.reboot() is only supported when running on the Apify platform.') return - if _ActorType._is_rebooting: + if self._is_rebooting: self.log.debug('Actor is already rebooting, skipping the additional reboot call.') return - _ActorType._is_rebooting = True + self._is_rebooting = True if not custom_after_sleep: custom_after_sleep = self.configuration.metamorph_after_sleep diff --git a/tests/unit/actor/test_actor_log.py b/tests/unit/actor/test_actor_log.py index a09f1d9d..7bff15b4 100644 --- a/tests/unit/actor/test_actor_log.py +++ b/tests/unit/actor/test_actor_log.py @@ -36,72 +36,67 @@ async def test_actor_logs_messages_correctly(caplog: pytest.LogCaptureFixture) - # Test that exception in Actor.main is logged with the traceback raise RuntimeError('Dummy RuntimeError') - # We skip the first entry, as it is related to the initialization of `lazy_object_proxy.Proxy` for `Actor`. - records = caplog.records[1:] + records = caplog.records - # Updated expected number of log records (additional debug messages added) - assert len(records) == 14 + # Expected number of log records + assert len(records) == 13 - # Record 0: Logging configured - assert records[0].levelno == logging.DEBUG - assert records[0].message == 'Logging configured' + # Record 0: Initializing Actor + assert records[0].levelno == logging.INFO + assert records[0].message == 'Initializing Actor' - # Record 1: Initializing Actor - assert records[1].levelno == logging.INFO - assert records[1].message == 'Initializing Actor' + # Record 1: Configuration initialized + assert records[1].levelno == logging.DEBUG + assert records[1].message == 'Configuration initialized' - # Record 2: Configuration initialized + # Record 2: Storage client initialized assert records[2].levelno == logging.DEBUG - assert records[2].message == 'Configuration initialized' + assert records[2].message == 'Storage client initialized' - # Record 3: Storage client initialized + # Record 3: Event manager initialized assert records[3].levelno == logging.DEBUG - assert records[3].message == 'Storage client initialized' + assert records[3].message == 'Event manager initialized' - # Record 4: Event manager initialized + # Record 4: Charging manager initialized assert records[4].levelno == logging.DEBUG - assert records[4].message == 'Event manager initialized' + assert records[4].message == 'Charging manager initialized' - # Record 5: Charging manager initialized + # Record 5: Debug message assert records[5].levelno == logging.DEBUG - assert records[5].message == 'Charging manager initialized' + assert records[5].message == 'Debug message' - # Record 6: Debug message - assert records[6].levelno == logging.DEBUG - assert records[6].message == 'Debug message' + # Record 6: Info message + assert records[6].levelno == logging.INFO + assert records[6].message == 'Info message' - # Record 7: Info message - assert records[7].levelno == logging.INFO - assert records[7].message == 'Info message' + # Record 7: Warning message + assert records[7].levelno == logging.WARNING + assert records[7].message == 'Warning message' - # Record 8: Warning message - assert records[8].levelno == logging.WARNING - assert records[8].message == 'Warning message' + # Record 8: Error message + assert records[8].levelno == logging.ERROR + assert records[8].message == 'Error message' - # Record 9: Error message + # Record 9: Exception message with traceback (ValueError) assert records[9].levelno == logging.ERROR - assert records[9].message == 'Error message' - - # Record 10: Exception message with traceback (ValueError) - assert records[10].levelno == logging.ERROR - assert records[10].message == 'Exception message' - assert records[10].exc_info is not None - assert records[10].exc_info[0] is ValueError - assert isinstance(records[10].exc_info[1], ValueError) - assert str(records[10].exc_info[1]) == 'Dummy ValueError' - - # Record 11: Multiline log message - assert records[11].levelno == logging.INFO - assert records[11].message == 'Multi\nline\nlog\nmessage' - - # Record 12: Actor failed with an exception (RuntimeError) - assert records[12].levelno == logging.ERROR - assert records[12].message == 'Actor failed with an exception' - assert records[12].exc_info is not None - assert records[12].exc_info[0] is RuntimeError - assert isinstance(records[12].exc_info[1], RuntimeError) - assert str(records[12].exc_info[1]) == 'Dummy RuntimeError' - - # Record 13: Exiting Actor - assert records[13].levelno == logging.INFO - assert records[13].message == 'Exiting Actor' + assert records[9].message == 'Exception message' + assert records[9].exc_info is not None + assert records[9].exc_info[0] is ValueError + assert isinstance(records[9].exc_info[1], ValueError) + assert str(records[9].exc_info[1]) == 'Dummy ValueError' + + # Record 10: Multiline log message + assert records[10].levelno == logging.INFO + assert records[10].message == 'Multi\nline\nlog\nmessage' + + # Record 11: Actor failed with an exception (RuntimeError) + assert records[11].levelno == logging.ERROR + assert records[11].message == 'Actor failed with an exception' + assert records[11].exc_info is not None + assert records[11].exc_info[0] is RuntimeError + assert isinstance(records[11].exc_info[1], RuntimeError) + assert str(records[11].exc_info[1]) == 'Dummy RuntimeError' + + # Record 12: Exiting Actor + assert records[12].levelno == logging.INFO + assert records[12].message == 'Exiting Actor' diff --git a/tests/unit/conftest.py b/tests/unit/conftest.py index bd041b50..cf7f007f 100644 --- a/tests/unit/conftest.py +++ b/tests/unit/conftest.py @@ -62,7 +62,7 @@ def prepare_test_env(monkeypatch: pytest.MonkeyPatch, tmp_path: Path) -> Callabl def _prepare_test_env() -> None: if hasattr(apify._actor.Actor, '__wrapped__'): delattr(apify._actor.Actor, '__wrapped__') - apify._actor._ActorType._is_any_instance_initialized = False + apify._actor.Actor._is_initialized = False # Set the environment variable for the local storage directory to the temporary path. monkeypatch.setenv(ApifyEnvVars.LOCAL_STORAGE_DIR, str(tmp_path))