Skip to content

Commit b4efbff

Browse files
committed
Properly set implicit ApifyFileSystemStorageClient
1 parent c89fd73 commit b4efbff

File tree

2 files changed

+44
-11
lines changed

2 files changed

+44
-11
lines changed

src/apify/_actor.py

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
from apify.events import ApifyEventManager, EventManager, LocalEventManager
3636
from apify.log import _configure_logging, logger
3737
from apify.storage_clients import ApifyStorageClient
38+
from apify.storage_clients._file_system import ApifyFileSystemStorageClient
3839
from apify.storages import Dataset, KeyValueStore, RequestQueue
3940

4041
if TYPE_CHECKING:
@@ -128,6 +129,7 @@ def __init__(
128129
self._configuration = configuration
129130
self._configure_logging = configure_logging
130131
self._apify_client: ApifyClientAsync | None = None
132+
self._local_storage_client: StorageClient | None = None
131133

132134
# Set the event manager based on whether the Actor is running on the platform or locally.
133135
self._event_manager: EventManager | None = None
@@ -215,17 +217,35 @@ def _finalize_implicit_configuration(self) -> Configuration:
215217
try:
216218
# Set implicit default Apify configuration, unless configuration was already set.
217219
implicit_configuration = Configuration()
218-
service_locator.set_configuration(Configuration())
220+
service_locator.set_configuration(implicit_configuration)
219221
self._configuration = implicit_configuration
220222
except ServiceConflictError:
221-
self.log.info(
223+
self.log.debug(
222224
'Configuration in service locator was set explicitly before Actor.init was called.'
223225
'Using the existing configuration as implicit configuration for the Actor.'
224226
)
225227
# Use the configuration from the service locator
226228
self._configuration = Configuration.get_global_configuration()
227229
return self.configuration
228230

231+
def _finalize_implicit_local_storage_client(self) -> StorageClient:
232+
"""Set implicit local storage client in the actor and return it.
233+
234+
Changing Actor or service_locator storage client after this method was run is not possible.
235+
"""
236+
try:
237+
# Set implicit default local storage client, unless local storage client was already set.
238+
implicit_storage_client = ApifyFileSystemStorageClient()
239+
service_locator.set_storage_client(implicit_storage_client)
240+
self._local_storage_client = implicit_storage_client
241+
except ServiceConflictError:
242+
self.log.debug(
243+
'Storage client in service locator was set explicitly before Actor.init was called.'
244+
'Using the existing storage client as implicit storage client for the Actor.'
245+
)
246+
self._local_storage_client = service_locator.get_storage_client()
247+
return self._local_storage_client
248+
229249
@property
230250
def event_manager(self) -> EventManager:
231251
"""The EventManager instance the Actor instance uses."""
@@ -248,10 +268,11 @@ def log(self) -> logging.Logger:
248268
"""The logging.Logger instance the Actor uses."""
249269
return logger
250270

251-
@property
252-
def _local_storage_client(self) -> StorageClient:
253-
"""The local storage client the Actor instance uses."""
254-
return service_locator.get_storage_client()
271+
def _get_local_storage_client(self) -> StorageClient:
272+
"""Get the local storage client the Actor instance uses."""
273+
if self._local_storage_client:
274+
return self._local_storage_client
275+
return self._finalize_implicit_local_storage_client()
255276

256277
def _raise_if_not_initialized(self) -> None:
257278
if not self._is_initialized:
@@ -303,7 +324,7 @@ async def init(self) -> None:
303324
# If the Actor is running on the Apify platform, we set the cloud storage client.
304325
if self.is_at_home():
305326
service_locator.set_storage_client(self._cloud_storage_client)
306-
327+
self._finalize_implicit_local_storage_client()
307328
service_locator.set_event_manager(self.event_manager)
308329

309330
# The logging configuration has to be called after all service_locator set methods.
@@ -461,7 +482,7 @@ async def open_dataset(
461482
self._raise_if_not_initialized()
462483
self._raise_if_cloud_requested_but_not_configured(force_cloud=force_cloud)
463484

464-
storage_client = self._cloud_storage_client if force_cloud else self._local_storage_client
485+
storage_client = self._cloud_storage_client if force_cloud else self._get_local_storage_client()
465486

466487
return await Dataset.open(
467488
id=id,
@@ -494,7 +515,7 @@ async def open_key_value_store(
494515
"""
495516
self._raise_if_not_initialized()
496517
self._raise_if_cloud_requested_but_not_configured(force_cloud=force_cloud)
497-
storage_client = self._cloud_storage_client if force_cloud else self._local_storage_client
518+
storage_client = self._cloud_storage_client if force_cloud else self._get_local_storage_client()
498519

499520
return await KeyValueStore.open(
500521
id=id,
@@ -530,7 +551,7 @@ async def open_request_queue(
530551
self._raise_if_not_initialized()
531552
self._raise_if_cloud_requested_but_not_configured(force_cloud=force_cloud)
532553

533-
storage_client = self._cloud_storage_client if force_cloud else self._local_storage_client
554+
storage_client = self._cloud_storage_client if force_cloud else self._get_local_storage_client()
534555

535556
return await RequestQueue.open(
536557
id=id,

tests/unit/actor/test_configuration.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
from apify import Actor
1212
from apify import Configuration as ApifyConfiguration
13+
from apify.storage_clients._file_system import ApifyFileSystemStorageClient
1314

1415

1516
@pytest.mark.parametrize(
@@ -107,9 +108,20 @@ async def test_crawler_implicit_configuration() -> None:
107108
"""Test that crawler and Actor use implicit service_locator based configuration unless explicit configuration
108109
was passed to them."""
109110
async with Actor():
111+
assert Actor.config is service_locator.get_configuration()
110112
crawler = BasicCrawler()
111113

112-
assert Actor.config is service_locator.get_configuration() is crawler._service_locator.get_configuration()
114+
assert Actor.config is service_locator.get_configuration()
115+
assert Actor.config is crawler._service_locator.get_configuration()
116+
117+
118+
async def test_crawler_implicit_local_storage() -> None:
119+
"""Test that crawler and Actor use implicit ApifyFileSystemStorageClient."""
120+
async with Actor():
121+
crawler = BasicCrawler()
122+
123+
assert isinstance(service_locator.get_storage_client(), ApifyFileSystemStorageClient)
124+
assert isinstance(crawler._service_locator.get_storage_client(), ApifyFileSystemStorageClient)
113125

114126

115127
async def test_crawlers_own_configuration(tmp_path: Path) -> None:

0 commit comments

Comments
 (0)