Skip to content

Commit 841d89a

Browse files
committed
Update tests
1 parent 2a52cdc commit 841d89a

File tree

3 files changed

+55
-27
lines changed

3 files changed

+55
-27
lines changed

src/apify/_actor.py

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -204,10 +204,27 @@ def config(self) -> Configuration:
204204
"""The Configuration instance the Actor instance uses."""
205205
if self._configuration:
206206
return self._configuration
207-
raise RuntimeError(
208-
'Use of implicit configuration before entering Actor context is no longer allowed.'
209-
'Either pass explicit configuration or enter the Actor context.'
210-
)
207+
208+
return self._finalize_implicit_configuration()
209+
210+
def _finalize_implicit_configuration(self) -> Configuration:
211+
"""Set implicit configuration in the actor and return it.
212+
213+
Changing Actor or service_locator configuration after this method was run is not possible.
214+
"""
215+
try:
216+
# Set implicit default Apify configuration, unless configuration was already set.
217+
implicit_configuration = Configuration()
218+
service_locator.set_configuration(Configuration())
219+
self._configuration = implicit_configuration
220+
except ServiceConflictError:
221+
self.log.info(
222+
'Configuration in service locator was set explicitly before Actor.init was called.'
223+
'Using the existing configuration as implicit configuration for the Actor.'
224+
)
225+
# Use the configuration from the service locator
226+
self._configuration = Configuration.get_global_configuration()
227+
return self.configuration
211228

212229
@property
213230
def event_manager(self) -> EventManager:

src/apify/_configuration.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -434,14 +434,26 @@ def get_global_configuration(cls) -> Configuration:
434434
# If Apify configuration was already stored in service locator, return it.
435435
return global_configuration
436436

437-
apify_configuration = Configuration()
437+
return cls.from_configuration(global_configuration)
438+
439+
@classmethod
440+
def from_configuration(cls, configuration: CrawleeConfiguration) -> Configuration:
441+
"""Create Apify Configuration from existing Crawlee Configuration.
442+
443+
Args:
444+
configuration: The existing Crawlee Configuration.
445+
446+
Returns:
447+
The created Apify Configuration.
448+
"""
449+
apify_configuration = cls()
438450

439451
# Ensure the returned configuration is of type Apify Configuration.
440452
# Most likely crawlee configuration was already set. Create Apify configuration from it.
441453
# Due to known Pydantic issue https://github.com/pydantic/pydantic/issues/9516, creating new instance of
442454
# Configuration from existing one in situation where environment can have some fields set by alias is very
443455
# unpredictable. Use the stable workaround.
444-
for name in global_configuration.model_fields:
445-
setattr(apify_configuration, name, getattr(global_configuration, name))
456+
for name in configuration.model_fields:
457+
setattr(apify_configuration, name, getattr(configuration, name))
446458

447459
return apify_configuration

tests/unit/actor/test_configuration.py

Lines changed: 19 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,13 @@ def test_disable_browser_sandbox(
3232

3333

3434
def test_apify_configuration_is_always_used() -> None:
35-
"""Set Crawlee Configuration in service_locator and verify that Apify Configuration is returned."""
35+
"""Set Crawlee Configuration in Actor and verify that Apify Configuration is used."""
3636
max_used_cpu_ratio = 0.123456 # Some unique value to verify configuration
37+
3738
service_locator.set_configuration(CrawleeConfiguration(max_used_cpu_ratio=max_used_cpu_ratio))
3839

39-
returned_config = service_locator.get_configuration()
40-
assert returned_config.max_used_cpu_ratio == max_used_cpu_ratio
41-
assert isinstance(returned_config, ApifyConfiguration)
40+
assert Actor.config.max_used_cpu_ratio == max_used_cpu_ratio
41+
assert isinstance(Actor.config, ApifyConfiguration)
4242

4343

4444
async def test_existing_apify_config_respected_by_actor() -> None:
@@ -61,11 +61,10 @@ async def test_existing_crawlee_config_respected_by_actor() -> None:
6161
async with Actor:
6262
pass
6363

64-
returned_config = service_locator.get_configuration()
65-
assert returned_config is not crawlee_config
66-
assert isinstance(returned_config, ApifyConfiguration)
67-
# Make sure the Crawlee Configuration was used to create returned Apify Configuration
68-
assert returned_config.max_used_cpu_ratio == max_used_cpu_ratio
64+
assert Actor.config is not crawlee_config
65+
assert isinstance(Actor.config, ApifyConfiguration)
66+
# Make sure the Crawlee Configuration was used to create ApifyConfiguration in Actor
67+
assert Actor.config.max_used_cpu_ratio == max_used_cpu_ratio
6968

7069

7170
async def test_existing_apify_config_throws_error_when_set_in_actor() -> None:
@@ -109,7 +108,7 @@ async def test_crawler_implicit_configuration() -> None:
109108
async with Actor():
110109
crawler = BasicCrawler()
111110

112-
assert service_locator.get_configuration() is crawler._service_locator.get_configuration()
111+
assert Actor.config is service_locator.get_configuration() is crawler._service_locator.get_configuration()
113112

114113

115114
async def test_crawlers_own_configuration() -> None:
@@ -128,7 +127,7 @@ async def test_crawlers_own_configuration() -> None:
128127

129128

130129
async def test_crawler_global_configuration() -> None:
131-
"""Test that crawler and Actor use explicit service_locator based configuration unless explicit configuration
130+
"""Test that crawler and Actor use service_locator based configuration unless explicit configuration
132131
was passed to them."""
133132
config_global = ApifyConfiguration()
134133
service_locator.set_configuration(config_global)
@@ -140,18 +139,24 @@ async def test_crawler_global_configuration() -> None:
140139
assert crawler._service_locator.get_configuration() is config_global
141140

142141

142+
async def test_crawler_uses_implicit_apify_config() -> None:
143+
"""Test that Actor is using implicit ApifyConfiguration in Actor context."""
144+
async with Actor:
145+
assert isinstance(Actor.config, ApifyConfiguration)
146+
147+
143148
async def test_storage_retrieved_is_different_with_different_config(tmp_path: Path) -> None:
144149
"""Test that retrieving storage depends on used configuration."""
145150
dir_1 = tmp_path / 'dir_1'
146151
dir_2 = tmp_path / 'dir_2'
147152
config_actor = ApifyConfiguration()
148153
config_actor.storage_dir = str(dir_1)
149-
apify_crawler = ApifyConfiguration()
150-
apify_crawler.storage_dir = str(dir_2)
154+
config_crawler = ApifyConfiguration()
155+
config_crawler.storage_dir = str(dir_2)
151156

152157
async with Actor(configuration=config_actor):
153158
actor_kvs = await Actor.open_key_value_store()
154-
crawler = BasicCrawler(configuration=apify_crawler)
159+
crawler = BasicCrawler(configuration=config_crawler)
155160
crawler_kvs = await crawler.get_key_value_store()
156161

157162
assert actor_kvs is not crawler_kvs
@@ -179,9 +184,3 @@ async def test_storage_retrieved_is_same_with_same_config() -> None:
179184
crawler_kvs = await crawler.get_key_value_store()
180185

181186
assert actor_kvs is crawler_kvs
182-
183-
184-
async def test_crawler_uses_apify_config() -> None:
185-
"""Test that crawler is using ApifyConfiguration in SDK context."""
186-
crawler = BasicCrawler()
187-
assert isinstance(crawler._service_locator.get_configuration(), ApifyConfiguration)

0 commit comments

Comments
 (0)