apify 2.4.0b1__tar.gz → 2.4.0b3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of apify might be problematic. Click here for more details.
- {apify-2.4.0b1 → apify-2.4.0b3}/CHANGELOG.md +9 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/PKG-INFO +1 -1
- {apify-2.4.0b1 → apify-2.4.0b3}/pyproject.toml +1 -1
- {apify-2.4.0b1 → apify-2.4.0b3}/src/apify/_actor.py +38 -9
- apify-2.4.0b3/tests/unit/actor/test_actor_log.py +104 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/uv.lock +1 -1
- {apify-2.4.0b1 → apify-2.4.0b3}/website/package-lock.json +270 -261
- apify-2.4.0b1/tests/unit/actor/test_actor_log.py +0 -93
- {apify-2.4.0b1 → apify-2.4.0b3}/.editorconfig +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/.github/CODEOWNERS +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/.github/workflows/build_and_deploy_docs.yaml +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/.github/workflows/check_pr_title.yaml +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/.github/workflows/pre_release.yaml +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/.github/workflows/release.yaml +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/.github/workflows/run_code_checks.yaml +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/.github/workflows/update_new_issue.yaml +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/.gitignore +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/.markdownlint.yaml +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/.pre-commit-config.yaml +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/CONTRIBUTING.md +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/LICENSE +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/Makefile +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/README.md +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/docs/01_overview/01_introduction.mdx +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/docs/01_overview/02_running_actors_locally.mdx +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/docs/01_overview/03_actor_structure.mdx +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/docs/01_overview/code/01_introduction.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/docs/01_overview/code/actor_structure/__init__.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/docs/01_overview/code/actor_structure/__main__.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/docs/01_overview/code/actor_structure/main.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/docs/01_overview/code/actor_structure/py.typed +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/docs/02_guides/01_beautifulsoup_httpx.mdx +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/docs/02_guides/02_crawlee.mdx +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/docs/02_guides/03_playwright.mdx +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/docs/02_guides/04_selenium.mdx +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/docs/02_guides/05_scrapy.mdx +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/docs/02_guides/code/01_beautifulsoup_httpx.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/docs/02_guides/code/02_crawlee_beautifulsoup.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/docs/02_guides/code/02_crawlee_playwright.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/docs/02_guides/code/03_playwright.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/docs/02_guides/code/04_selenium.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/docs/02_guides/code/scrapy_project/src/__init__.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/docs/02_guides/code/scrapy_project/src/__main__.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/docs/02_guides/code/scrapy_project/src/items.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/docs/02_guides/code/scrapy_project/src/main.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/docs/02_guides/code/scrapy_project/src/py.typed +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/docs/02_guides/code/scrapy_project/src/settings.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/docs/02_guides/code/scrapy_project/src/spiders/__init__.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/docs/02_guides/code/scrapy_project/src/spiders/py.typed +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/docs/02_guides/code/scrapy_project/src/spiders/title.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/docs/03_concepts/01_actor_lifecycle.mdx +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/docs/03_concepts/02_actor_input.mdx +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/docs/03_concepts/03_storages.mdx +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/docs/03_concepts/04_actor_events.mdx +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/docs/03_concepts/05_proxy_management.mdx +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/docs/03_concepts/06_interacting_with_other_actors.mdx +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/docs/03_concepts/07_webhooks.mdx +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/docs/03_concepts/08_access_apify_api.mdx +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/docs/03_concepts/09_running_webserver.mdx +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/docs/03_concepts/10_logging.mdx +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/docs/03_concepts/11_configuration.mdx +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/docs/03_concepts/code/01_context_manager.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/docs/03_concepts/code/01_init_exit.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/docs/03_concepts/code/01_reboot.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/docs/03_concepts/code/01_status_message.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/docs/03_concepts/code/02_input.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/docs/03_concepts/code/03_dataset_exports.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/docs/03_concepts/code/03_dataset_read_write.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/docs/03_concepts/code/03_deleting_storages.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/docs/03_concepts/code/03_kvs_iterating.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/docs/03_concepts/code/03_kvs_public_url.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/docs/03_concepts/code/03_kvs_read_write.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/docs/03_concepts/code/03_opening_storages.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/docs/03_concepts/code/03_rq.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/docs/03_concepts/code/04_actor_events.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/docs/03_concepts/code/05_apify_proxy.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/docs/03_concepts/code/05_apify_proxy_config.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/docs/03_concepts/code/05_custom_proxy.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/docs/03_concepts/code/05_custom_proxy_function.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/docs/03_concepts/code/05_proxy_actor_input.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/docs/03_concepts/code/05_proxy_httpx.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/docs/03_concepts/code/05_proxy_rotation.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/docs/03_concepts/code/06_interacting_call.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/docs/03_concepts/code/06_interacting_call_task.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/docs/03_concepts/code/06_interacting_metamorph.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/docs/03_concepts/code/06_interacting_start.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/docs/03_concepts/code/07_webhook.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/docs/03_concepts/code/07_webhook_preventing.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/docs/03_concepts/code/08_actor_client.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/docs/03_concepts/code/08_actor_new_client.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/docs/03_concepts/code/09_webserver.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/docs/03_concepts/code/10_log_config.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/docs/03_concepts/code/10_logger_usage.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/docs/03_concepts/code/11_config.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/docs/04_upgrading/upgrading_to_v2.md +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/docs/pyproject.toml +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/renovate.json +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/src/apify/__init__.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/src/apify/_charging.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/src/apify/_configuration.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/src/apify/_consts.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/src/apify/_crypto.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/src/apify/_models.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/src/apify/_platform_event_manager.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/src/apify/_proxy_configuration.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/src/apify/_utils.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/src/apify/apify_storage_client/__init__.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/src/apify/apify_storage_client/_apify_storage_client.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/src/apify/apify_storage_client/_dataset_client.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/src/apify/apify_storage_client/_dataset_collection_client.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/src/apify/apify_storage_client/_key_value_store_client.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/src/apify/apify_storage_client/_key_value_store_collection_client.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/src/apify/apify_storage_client/_request_queue_client.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/src/apify/apify_storage_client/_request_queue_collection_client.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/src/apify/apify_storage_client/py.typed +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/src/apify/log.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/src/apify/py.typed +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/src/apify/scrapy/__init__.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/src/apify/scrapy/_actor_runner.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/src/apify/scrapy/_async_thread.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/src/apify/scrapy/_logging_config.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/src/apify/scrapy/middlewares/__init__.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/src/apify/scrapy/middlewares/apify_proxy.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/src/apify/scrapy/middlewares/py.typed +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/src/apify/scrapy/pipelines/__init__.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/src/apify/scrapy/pipelines/actor_dataset_push.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/src/apify/scrapy/pipelines/py.typed +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/src/apify/scrapy/py.typed +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/src/apify/scrapy/requests.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/src/apify/scrapy/scheduler.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/src/apify/scrapy/utils.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/src/apify/storages/__init__.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/src/apify/storages/_request_list.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/src/apify/storages/py.typed +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/tests/integration/README.md +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/tests/integration/__init__.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/tests/integration/_utils.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/tests/integration/actor_source_base/Dockerfile +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/tests/integration/actor_source_base/requirements.txt +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/tests/integration/actor_source_base/src/__init__.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/tests/integration/actor_source_base/src/__main__.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/tests/integration/actor_source_base/src/main.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/tests/integration/conftest.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/tests/integration/test_actor_api_helpers.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/tests/integration/test_actor_charge.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/tests/integration/test_actor_create_proxy_configuration.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/tests/integration/test_actor_dataset.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/tests/integration/test_actor_events.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/tests/integration/test_actor_key_value_store.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/tests/integration/test_actor_lifecycle.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/tests/integration/test_actor_log.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/tests/integration/test_actor_request_queue.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/tests/integration/test_actor_scrapy.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/tests/integration/test_fixtures.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/tests/integration/test_request_queue.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/tests/unit/__init__.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/tests/unit/actor/__init__.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/tests/unit/actor/test_actor_create_proxy_configuration.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/tests/unit/actor/test_actor_dataset.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/tests/unit/actor/test_actor_env_helpers.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/tests/unit/actor/test_actor_helpers.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/tests/unit/actor/test_actor_key_value_store.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/tests/unit/actor/test_actor_lifecycle.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/tests/unit/actor/test_actor_non_default_instance.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/tests/unit/actor/test_actor_request_queue.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/tests/unit/actor/test_request_list.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/tests/unit/conftest.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/tests/unit/scrapy/__init__.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/tests/unit/scrapy/middlewares/__init__.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/tests/unit/scrapy/middlewares/test_apify_proxy.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/tests/unit/scrapy/pipelines/__init__.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/tests/unit/scrapy/pipelines/test_actor_dataset_push.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/tests/unit/scrapy/requests/__init__.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/tests/unit/scrapy/requests/test_to_apify_request.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/tests/unit/scrapy/requests/test_to_scrapy_request.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/tests/unit/scrapy/utils/__init__.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/tests/unit/scrapy/utils/test_apply_apify_settings.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/tests/unit/scrapy/utils/test_get_basic_auth_header.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/tests/unit/test_crypto.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/tests/unit/test_platform_event_manager.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/tests/unit/test_proxy_configuration.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/website/.eslintrc.json +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/website/babel.config.js +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/website/build_api_reference.sh +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/website/docusaurus.config.js +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/website/generate_module_shortcuts.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/website/package.json +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/website/sidebars.js +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/website/src/css/custom.css +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/website/src/pages/home_page_example.py +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/website/src/pages/index.js +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/website/src/pages/index.module.css +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/website/static/.nojekyll +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/website/static/img/docs-og.png +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/website/tools/docs-prettier.config.js +0 -0
- {apify-2.4.0b1 → apify-2.4.0b3}/website/tools/utils/externalLink.js +0 -0
|
@@ -2,6 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
+
<!-- git-cliff-unreleased-start -->
|
|
6
|
+
## 2.4.0 - **not yet released**
|
|
7
|
+
|
|
8
|
+
### 🚀 Features
|
|
9
|
+
|
|
10
|
+
- Update to Crawlee v0.6 ([#420](https://github.com/apify/apify-sdk-python/pull/420)) ([9be4336](https://github.com/apify/apify-sdk-python/commit/9be433667231cc5739861fa693d7a726860d6aca)) by [@vdusek](https://github.com/vdusek)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
<!-- git-cliff-unreleased-end -->
|
|
5
14
|
## [2.3.1](https://github.com/apify/apify-sdk-python/releases/tag/v2.3.1) (2025-02-25)
|
|
6
15
|
|
|
7
16
|
### 🐛 Bug Fixes
|
|
@@ -3,6 +3,7 @@ from __future__ import annotations
|
|
|
3
3
|
import asyncio
|
|
4
4
|
import os
|
|
5
5
|
import sys
|
|
6
|
+
from contextlib import suppress
|
|
6
7
|
from datetime import timedelta
|
|
7
8
|
from typing import TYPE_CHECKING, Any, Callable, Literal, TypeVar, cast, overload
|
|
8
9
|
|
|
@@ -64,6 +65,7 @@ class _ActorType:
|
|
|
64
65
|
configuration: Configuration | None = None,
|
|
65
66
|
*,
|
|
66
67
|
configure_logging: bool = True,
|
|
68
|
+
exit_process: bool | None = None,
|
|
67
69
|
) -> None:
|
|
68
70
|
"""Create an Actor instance.
|
|
69
71
|
|
|
@@ -74,7 +76,10 @@ class _ActorType:
|
|
|
74
76
|
configuration: The Actor configuration to be used. If not passed, a new Configuration instance will
|
|
75
77
|
be created.
|
|
76
78
|
configure_logging: Should the default logging configuration be configured?
|
|
79
|
+
exit_process: Whether the Actor should call `sys.exit` when the context manager exits. The default is
|
|
80
|
+
True except for the IPython, Pytest and Scrapy environments.
|
|
77
81
|
"""
|
|
82
|
+
self._exit_process = self._get_default_exit_process() if exit_process is None else exit_process
|
|
78
83
|
self._is_exiting = False
|
|
79
84
|
|
|
80
85
|
self._configuration = configuration or Configuration.get_global_configuration()
|
|
@@ -141,9 +146,19 @@ class _ActorType:
|
|
|
141
146
|
|
|
142
147
|
return super().__repr__()
|
|
143
148
|
|
|
144
|
-
def __call__(
|
|
149
|
+
def __call__(
|
|
150
|
+
self,
|
|
151
|
+
configuration: Configuration | None = None,
|
|
152
|
+
*,
|
|
153
|
+
configure_logging: bool = True,
|
|
154
|
+
exit_process: bool | None = None,
|
|
155
|
+
) -> Self:
|
|
145
156
|
"""Make a new Actor instance with a non-default configuration."""
|
|
146
|
-
return self.__class__(
|
|
157
|
+
return self.__class__(
|
|
158
|
+
configuration=configuration,
|
|
159
|
+
configure_logging=configure_logging,
|
|
160
|
+
exit_process=exit_process,
|
|
161
|
+
)
|
|
147
162
|
|
|
148
163
|
@property
|
|
149
164
|
def apify_client(self) -> ApifyClientAsync:
|
|
@@ -281,13 +296,7 @@ class _ActorType:
|
|
|
281
296
|
await asyncio.wait_for(finalize(), cleanup_timeout.total_seconds())
|
|
282
297
|
self._is_initialized = False
|
|
283
298
|
|
|
284
|
-
if
|
|
285
|
-
self.log.debug(f'Not calling sys.exit({exit_code}) because Actor is running in IPython')
|
|
286
|
-
elif os.getenv('PYTEST_CURRENT_TEST', default=False): # noqa: PLW1508
|
|
287
|
-
self.log.debug(f'Not calling sys.exit({exit_code}) because Actor is running in an unit test')
|
|
288
|
-
elif os.getenv('SCRAPY_SETTINGS_MODULE'):
|
|
289
|
-
self.log.debug(f'Not calling sys.exit({exit_code}) because Actor is running with Scrapy')
|
|
290
|
-
else:
|
|
299
|
+
if self._exit_process:
|
|
291
300
|
sys.exit(exit_code)
|
|
292
301
|
|
|
293
302
|
async def fail(
|
|
@@ -1128,6 +1137,26 @@ class _ActorType:
|
|
|
1128
1137
|
|
|
1129
1138
|
return proxy_configuration
|
|
1130
1139
|
|
|
1140
|
+
def _get_default_exit_process(self) -> bool:
|
|
1141
|
+
"""Returns False for IPython, Pytest, and Scrapy environments, True otherwise."""
|
|
1142
|
+
if is_running_in_ipython():
|
|
1143
|
+
self.log.debug('Running in IPython, setting default `exit_process` to False.')
|
|
1144
|
+
return False
|
|
1145
|
+
|
|
1146
|
+
# Check if running in Pytest by detecting the relevant environment variable.
|
|
1147
|
+
if os.getenv('PYTEST_CURRENT_TEST'):
|
|
1148
|
+
self.log.debug('Running in Pytest, setting default `exit_process` to False.')
|
|
1149
|
+
return False
|
|
1150
|
+
|
|
1151
|
+
# Check if running in Scrapy by attempting to import it.
|
|
1152
|
+
with suppress(ImportError):
|
|
1153
|
+
import scrapy # noqa: F401
|
|
1154
|
+
|
|
1155
|
+
self.log.debug('Running in Scrapy, setting default `exit_process` to False.')
|
|
1156
|
+
return False
|
|
1157
|
+
|
|
1158
|
+
return True
|
|
1159
|
+
|
|
1131
1160
|
|
|
1132
1161
|
Actor = cast(_ActorType, Proxy(_ActorType))
|
|
1133
1162
|
"""The entry point of the SDK, through which all the Actor operations should be done."""
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import contextlib
|
|
4
|
+
import logging
|
|
5
|
+
from typing import TYPE_CHECKING
|
|
6
|
+
|
|
7
|
+
from apify import Actor
|
|
8
|
+
from apify.log import logger
|
|
9
|
+
|
|
10
|
+
if TYPE_CHECKING:
|
|
11
|
+
import pytest
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
async def test_actor_logs_messages_correctly(caplog: pytest.LogCaptureFixture) -> None:
|
|
15
|
+
caplog.set_level(logging.DEBUG, logger='apify')
|
|
16
|
+
|
|
17
|
+
with contextlib.suppress(RuntimeError):
|
|
18
|
+
async with Actor(configure_logging=False):
|
|
19
|
+
# Test Actor.log
|
|
20
|
+
Actor.log.debug('Debug message')
|
|
21
|
+
Actor.log.info('Info message')
|
|
22
|
+
|
|
23
|
+
# Test logger
|
|
24
|
+
logger.warning('Warning message')
|
|
25
|
+
logger.error('Error message')
|
|
26
|
+
|
|
27
|
+
# Test that exception is logged with the traceback
|
|
28
|
+
try:
|
|
29
|
+
raise ValueError('Dummy ValueError')
|
|
30
|
+
except Exception:
|
|
31
|
+
Actor.log.exception('Exception message')
|
|
32
|
+
|
|
33
|
+
# Test multiline message being indented correctly
|
|
34
|
+
logger.info('Multi\nline\nlog\nmessage')
|
|
35
|
+
|
|
36
|
+
# Test that exception in Actor.main is logged with the traceback
|
|
37
|
+
raise RuntimeError('Dummy RuntimeError')
|
|
38
|
+
|
|
39
|
+
# Updated expected number of log records (an extra record is now captured)
|
|
40
|
+
assert len(caplog.records) == 14
|
|
41
|
+
|
|
42
|
+
# Record 0: Extra Pytest context log
|
|
43
|
+
assert caplog.records[0].levelno == logging.DEBUG
|
|
44
|
+
assert caplog.records[0].message.startswith('Running in Pytest')
|
|
45
|
+
|
|
46
|
+
# Record 1: Duplicate Pytest context log
|
|
47
|
+
assert caplog.records[1].levelno == logging.DEBUG
|
|
48
|
+
assert caplog.records[0].message.startswith('Running in Pytest')
|
|
49
|
+
|
|
50
|
+
# Record 2: Initializing Actor...
|
|
51
|
+
assert caplog.records[2].levelno == logging.INFO
|
|
52
|
+
assert caplog.records[2].message == 'Initializing Actor...'
|
|
53
|
+
|
|
54
|
+
# Record 3: System info
|
|
55
|
+
assert caplog.records[3].levelno == logging.INFO
|
|
56
|
+
assert caplog.records[3].message == 'System info'
|
|
57
|
+
|
|
58
|
+
# Record 4: Event manager initialized
|
|
59
|
+
assert caplog.records[4].levelno == logging.DEBUG
|
|
60
|
+
assert caplog.records[4].message == 'Event manager initialized'
|
|
61
|
+
|
|
62
|
+
# Record 5: Charging manager initialized
|
|
63
|
+
assert caplog.records[5].levelno == logging.DEBUG
|
|
64
|
+
assert caplog.records[5].message == 'Charging manager initialized'
|
|
65
|
+
|
|
66
|
+
# Record 6: Debug message
|
|
67
|
+
assert caplog.records[6].levelno == logging.DEBUG
|
|
68
|
+
assert caplog.records[6].message == 'Debug message'
|
|
69
|
+
|
|
70
|
+
# Record 7: Info message
|
|
71
|
+
assert caplog.records[7].levelno == logging.INFO
|
|
72
|
+
assert caplog.records[7].message == 'Info message'
|
|
73
|
+
|
|
74
|
+
# Record 8: Warning message
|
|
75
|
+
assert caplog.records[8].levelno == logging.WARNING
|
|
76
|
+
assert caplog.records[8].message == 'Warning message'
|
|
77
|
+
|
|
78
|
+
# Record 9: Error message
|
|
79
|
+
assert caplog.records[9].levelno == logging.ERROR
|
|
80
|
+
assert caplog.records[9].message == 'Error message'
|
|
81
|
+
|
|
82
|
+
# Record 10: Exception message with traceback (ValueError)
|
|
83
|
+
assert caplog.records[10].levelno == logging.ERROR
|
|
84
|
+
assert caplog.records[10].message == 'Exception message'
|
|
85
|
+
assert caplog.records[10].exc_info is not None
|
|
86
|
+
assert caplog.records[10].exc_info[0] is ValueError
|
|
87
|
+
assert isinstance(caplog.records[10].exc_info[1], ValueError)
|
|
88
|
+
assert str(caplog.records[10].exc_info[1]) == 'Dummy ValueError'
|
|
89
|
+
|
|
90
|
+
# Record 11: Multiline log message
|
|
91
|
+
assert caplog.records[11].levelno == logging.INFO
|
|
92
|
+
assert caplog.records[11].message == 'Multi\nline\nlog\nmessage'
|
|
93
|
+
|
|
94
|
+
# Record 12: Actor failed with an exception (RuntimeError)
|
|
95
|
+
assert caplog.records[12].levelno == logging.ERROR
|
|
96
|
+
assert caplog.records[12].message == 'Actor failed with an exception'
|
|
97
|
+
assert caplog.records[12].exc_info is not None
|
|
98
|
+
assert caplog.records[12].exc_info[0] is RuntimeError
|
|
99
|
+
assert isinstance(caplog.records[12].exc_info[1], RuntimeError)
|
|
100
|
+
assert str(caplog.records[12].exc_info[1]) == 'Dummy RuntimeError'
|
|
101
|
+
|
|
102
|
+
# Record 13: Exiting Actor
|
|
103
|
+
assert caplog.records[13].levelno == logging.INFO
|
|
104
|
+
assert caplog.records[13].message == 'Exiting Actor'
|