apify 2.7.1b4__tar.gz → 2.7.1b6__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.7.1b4 → apify-2.7.1b6}/.github/workflows/pre_release.yaml +4 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/.github/workflows/release.yaml +4 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/.github/workflows/run_code_checks.yaml +1 -6
- {apify-2.7.1b4 → apify-2.7.1b6}/CHANGELOG.md +19 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/PKG-INFO +1 -1
- {apify-2.7.1b4 → apify-2.7.1b6}/pyproject.toml +4 -2
- {apify-2.7.1b4 → apify-2.7.1b6}/tests/integration/actor_source_base/Dockerfile +1 -1
- {apify-2.7.1b4 → apify-2.7.1b6}/tests/integration/actor_source_base/requirements.txt +2 -0
- apify-2.7.1b6/tests/integration/actor_source_base/server.py +101 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/tests/integration/test_actor_api_helpers.py +2 -2
- apify-2.7.1b6/tests/integration/test_crawlers_with_storages.py +111 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/tests/integration/test_request_queue.py +5 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/uv.lock +324 -101
- {apify-2.7.1b4 → apify-2.7.1b6}/website/docusaurus.config.js +4 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/website/package-lock.json +17 -3
- {apify-2.7.1b4 → apify-2.7.1b6}/.editorconfig +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/.github/CODEOWNERS +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/.github/workflows/build_and_deploy_docs.yaml +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/.github/workflows/check_pr_title.yaml +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/.github/workflows/update_new_issue.yaml +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/.gitignore +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/.markdownlint.yaml +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/.pre-commit-config.yaml +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/CONTRIBUTING.md +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/LICENSE +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/Makefile +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/README.md +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/docs/01_overview/01_introduction.mdx +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/docs/01_overview/02_running_actors_locally.mdx +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/docs/01_overview/03_actor_structure.mdx +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/docs/01_overview/code/01_introduction.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/docs/01_overview/code/actor_structure/__init__.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/docs/01_overview/code/actor_structure/__main__.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/docs/01_overview/code/actor_structure/main.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/docs/01_overview/code/actor_structure/py.typed +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/docs/02_guides/01_beautifulsoup_httpx.mdx +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/docs/02_guides/02_crawlee.mdx +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/docs/02_guides/03_playwright.mdx +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/docs/02_guides/04_selenium.mdx +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/docs/02_guides/05_scrapy.mdx +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/docs/02_guides/code/01_beautifulsoup_httpx.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/docs/02_guides/code/02_crawlee_beautifulsoup.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/docs/02_guides/code/02_crawlee_playwright.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/docs/02_guides/code/03_playwright.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/docs/02_guides/code/04_selenium.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/docs/02_guides/code/scrapy_project/src/__init__.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/docs/02_guides/code/scrapy_project/src/__main__.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/docs/02_guides/code/scrapy_project/src/items.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/docs/02_guides/code/scrapy_project/src/main.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/docs/02_guides/code/scrapy_project/src/py.typed +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/docs/02_guides/code/scrapy_project/src/settings.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/docs/02_guides/code/scrapy_project/src/spiders/__init__.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/docs/02_guides/code/scrapy_project/src/spiders/py.typed +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/docs/02_guides/code/scrapy_project/src/spiders/title.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/docs/03_concepts/01_actor_lifecycle.mdx +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/docs/03_concepts/02_actor_input.mdx +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/docs/03_concepts/03_storages.mdx +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/docs/03_concepts/04_actor_events.mdx +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/docs/03_concepts/05_proxy_management.mdx +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/docs/03_concepts/06_interacting_with_other_actors.mdx +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/docs/03_concepts/07_webhooks.mdx +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/docs/03_concepts/08_access_apify_api.mdx +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/docs/03_concepts/09_running_webserver.mdx +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/docs/03_concepts/10_logging.mdx +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/docs/03_concepts/11_configuration.mdx +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/docs/03_concepts/12_pay_per_event.mdx +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/docs/03_concepts/code/01_context_manager.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/docs/03_concepts/code/01_init_exit.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/docs/03_concepts/code/01_reboot.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/docs/03_concepts/code/01_status_message.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/docs/03_concepts/code/02_input.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/docs/03_concepts/code/03_dataset_exports.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/docs/03_concepts/code/03_dataset_read_write.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/docs/03_concepts/code/03_deleting_storages.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/docs/03_concepts/code/03_kvs_iterating.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/docs/03_concepts/code/03_kvs_public_url.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/docs/03_concepts/code/03_kvs_read_write.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/docs/03_concepts/code/03_opening_storages.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/docs/03_concepts/code/03_rq.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/docs/03_concepts/code/04_actor_events.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/docs/03_concepts/code/05_apify_proxy.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/docs/03_concepts/code/05_apify_proxy_config.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/docs/03_concepts/code/05_custom_proxy.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/docs/03_concepts/code/05_custom_proxy_function.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/docs/03_concepts/code/05_proxy_actor_input.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/docs/03_concepts/code/05_proxy_httpx.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/docs/03_concepts/code/05_proxy_rotation.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/docs/03_concepts/code/06_interacting_call.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/docs/03_concepts/code/06_interacting_call_task.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/docs/03_concepts/code/06_interacting_metamorph.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/docs/03_concepts/code/06_interacting_start.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/docs/03_concepts/code/07_webhook.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/docs/03_concepts/code/07_webhook_preventing.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/docs/03_concepts/code/08_actor_client.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/docs/03_concepts/code/08_actor_new_client.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/docs/03_concepts/code/09_webserver.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/docs/03_concepts/code/10_log_config.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/docs/03_concepts/code/10_logger_usage.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/docs/03_concepts/code/10_redirect_log.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/docs/03_concepts/code/10_redirect_log_existing_run.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/docs/03_concepts/code/11_config.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/docs/03_concepts/code/actor_charge.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/docs/03_concepts/code/conditional_actor_charge.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/docs/04_upgrading/upgrading_to_v2.md +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/docs/pyproject.toml +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/renovate.json +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/src/apify/__init__.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/src/apify/_actor.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/src/apify/_charging.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/src/apify/_configuration.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/src/apify/_consts.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/src/apify/_crypto.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/src/apify/_models.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/src/apify/_platform_event_manager.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/src/apify/_proxy_configuration.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/src/apify/_utils.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/src/apify/apify_storage_client/__init__.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/src/apify/apify_storage_client/_apify_storage_client.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/src/apify/apify_storage_client/_dataset_client.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/src/apify/apify_storage_client/_dataset_collection_client.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/src/apify/apify_storage_client/_key_value_store_client.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/src/apify/apify_storage_client/_key_value_store_collection_client.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/src/apify/apify_storage_client/_request_queue_client.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/src/apify/apify_storage_client/_request_queue_collection_client.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/src/apify/apify_storage_client/py.typed +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/src/apify/log.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/src/apify/py.typed +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/src/apify/scrapy/__init__.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/src/apify/scrapy/_actor_runner.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/src/apify/scrapy/_async_thread.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/src/apify/scrapy/_logging_config.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/src/apify/scrapy/extensions/__init__.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/src/apify/scrapy/extensions/_httpcache.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/src/apify/scrapy/middlewares/__init__.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/src/apify/scrapy/middlewares/apify_proxy.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/src/apify/scrapy/middlewares/py.typed +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/src/apify/scrapy/pipelines/__init__.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/src/apify/scrapy/pipelines/actor_dataset_push.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/src/apify/scrapy/pipelines/py.typed +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/src/apify/scrapy/py.typed +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/src/apify/scrapy/requests.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/src/apify/scrapy/scheduler.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/src/apify/scrapy/utils.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/src/apify/storages/__init__.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/src/apify/storages/_request_list.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/src/apify/storages/py.typed +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/tests/integration/README.md +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/tests/integration/__init__.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/tests/integration/_utils.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/tests/integration/actor_source_base/src/__init__.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/tests/integration/actor_source_base/src/__main__.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/tests/integration/actor_source_base/src/main.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/tests/integration/conftest.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/tests/integration/test_actor_call_timeouts.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/tests/integration/test_actor_charge.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/tests/integration/test_actor_create_proxy_configuration.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/tests/integration/test_actor_dataset.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/tests/integration/test_actor_events.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/tests/integration/test_actor_key_value_store.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/tests/integration/test_actor_lifecycle.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/tests/integration/test_actor_log.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/tests/integration/test_actor_request_queue.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/tests/integration/test_actor_scrapy.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/tests/integration/test_fixtures.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/tests/unit/__init__.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/tests/unit/actor/__init__.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/tests/unit/actor/test_actor_create_proxy_configuration.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/tests/unit/actor/test_actor_dataset.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/tests/unit/actor/test_actor_env_helpers.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/tests/unit/actor/test_actor_helpers.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/tests/unit/actor/test_actor_key_value_store.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/tests/unit/actor/test_actor_lifecycle.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/tests/unit/actor/test_actor_log.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/tests/unit/actor/test_actor_non_default_instance.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/tests/unit/actor/test_actor_request_queue.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/tests/unit/actor/test_configuration.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/tests/unit/actor/test_request_list.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/tests/unit/conftest.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/tests/unit/scrapy/__init__.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/tests/unit/scrapy/extensions/__init__.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/tests/unit/scrapy/extensions/test_httpcache.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/tests/unit/scrapy/middlewares/__init__.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/tests/unit/scrapy/middlewares/test_apify_proxy.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/tests/unit/scrapy/pipelines/__init__.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/tests/unit/scrapy/pipelines/test_actor_dataset_push.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/tests/unit/scrapy/requests/__init__.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/tests/unit/scrapy/requests/test_to_apify_request.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/tests/unit/scrapy/requests/test_to_scrapy_request.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/tests/unit/scrapy/utils/__init__.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/tests/unit/scrapy/utils/test_apply_apify_settings.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/tests/unit/scrapy/utils/test_get_basic_auth_header.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/tests/unit/test_crypto.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/tests/unit/test_platform_event_manager.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/tests/unit/test_proxy_configuration.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/website/.eslintrc.json +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/website/babel.config.js +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/website/build_api_reference.sh +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/website/generate_module_shortcuts.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/website/package.json +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/website/sidebars.js +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/website/src/components/ApiLink.jsx +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/website/src/components/Gradients.jsx +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/website/src/components/Highlights.jsx +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/website/src/components/Highlights.module.css +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/website/src/components/RunnableCodeBlock.jsx +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/website/src/components/RunnableCodeBlock.module.css +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/website/src/css/custom.css +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/website/src/pages/home_page_example.py +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/website/src/pages/index.js +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/website/src/pages/index.module.css +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/website/static/.nojekyll +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/website/static/img/docs-og.png +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/website/static/img/guides/redirected_logs_example.webp +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/website/tools/docs-prettier.config.js +0 -0
- {apify-2.7.1b4 → apify-2.7.1b6}/website/tools/utils/externalLink.js +0 -0
|
@@ -11,6 +11,10 @@ on:
|
|
|
11
11
|
# Or it can be triggered manually.
|
|
12
12
|
workflow_dispatch:
|
|
13
13
|
|
|
14
|
+
concurrency:
|
|
15
|
+
group: release
|
|
16
|
+
cancel-in-progress: false
|
|
17
|
+
|
|
14
18
|
jobs:
|
|
15
19
|
release_metadata:
|
|
16
20
|
if: "!startsWith(github.event.head_commit.message, 'docs') && !startsWith(github.event.head_commit.message, 'ci') && startsWith(github.repository, 'apify/')"
|
|
@@ -6,12 +6,7 @@ on:
|
|
|
6
6
|
# step required for PRs from forks. This prevents their potential exposure.
|
|
7
7
|
pull_request:
|
|
8
8
|
|
|
9
|
-
#
|
|
10
|
-
push:
|
|
11
|
-
branches:
|
|
12
|
-
- master
|
|
13
|
-
tags-ignore:
|
|
14
|
-
- "**" # Ignore all tags to prevent duplicate checks when tags are pushed.
|
|
9
|
+
# Trigger for pushing to the master branch is handled by the pre-release workflow.
|
|
15
10
|
|
|
16
11
|
# It should also be possible to trigger checks manually
|
|
17
12
|
workflow_dispatch:
|
|
@@ -23,6 +23,25 @@ All notable changes to this project will be documented in this file.
|
|
|
23
23
|
- Tagline overlap ([#501](https://github.com/apify/apify-sdk-python/pull/501)) ([bae8340](https://github.com/apify/apify-sdk-python/commit/bae8340c46fea756ea35ea4d591da84c09d478e2)) by [@katzino](https://github.com/katzino)
|
|
24
24
|
|
|
25
25
|
|
|
26
|
+
## [2.7.0](https://github.com/apify/apify-sdk-python/releases/tag/v2.7.0) (2025-07-14)
|
|
27
|
+
|
|
28
|
+
### 🚀 Features
|
|
29
|
+
|
|
30
|
+
- **crypto:** Decrypt secret objects ([#482](https://github.com/apify/apify-sdk-python/pull/482)) ([ce9daf7](https://github.com/apify/apify-sdk-python/commit/ce9daf7381212b8dc194e8a643e5ca0dedbc0078)) by [@MFori](https://github.com/MFori)
|
|
31
|
+
|
|
32
|
+
### 🐛 Bug Fixes
|
|
33
|
+
|
|
34
|
+
- Sync `@docusaurus` theme version [internal] ([#500](https://github.com/apify/apify-sdk-python/pull/500)) ([a7485e7](https://github.com/apify/apify-sdk-python/commit/a7485e7d2276fde464ce862573d5b95e7d4d836a)) by [@katzino](https://github.com/katzino)
|
|
35
|
+
- Tagline overlap ([#501](https://github.com/apify/apify-sdk-python/pull/501)) ([bae8340](https://github.com/apify/apify-sdk-python/commit/bae8340c46fea756ea35ea4d591da84c09d478e2)) by [@katzino](https://github.com/katzino)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
## [2.7.2](https://github.com/apify/apify-sdk-python/releases/tag/v2.7.2) (2025-07-30)
|
|
39
|
+
|
|
40
|
+
### 🐛 Bug Fixes
|
|
41
|
+
|
|
42
|
+
- Restrict apify-shared and apify-client versions ([#523](https://github.com/apify/apify-sdk-python/pull/523)) ([581ebae](https://github.com/apify/apify-sdk-python/commit/581ebae5752a984a34cbabc02c49945ae392db00)) by [@vdusek](https://github.com/vdusek)
|
|
43
|
+
|
|
44
|
+
|
|
26
45
|
## [2.7.1](https://github.com/apify/apify-sdk-python/releases/tag/v2.7.1) (2025-07-24)
|
|
27
46
|
|
|
28
47
|
### 🐛 Bug Fixes
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "apify"
|
|
7
|
-
version = "2.7.
|
|
7
|
+
version = "2.7.1b6"
|
|
8
8
|
description = "Apify SDK for Python"
|
|
9
9
|
authors = [{ name = "Apify Technologies s.r.o.", email = "support@apify.com" }]
|
|
10
10
|
license = { file = "LICENSE" }
|
|
@@ -62,7 +62,8 @@ scrapy = ["scrapy>=2.11.0"]
|
|
|
62
62
|
|
|
63
63
|
[dependency-groups]
|
|
64
64
|
dev = [
|
|
65
|
-
"build~=1.
|
|
65
|
+
"build~=1.3.0",
|
|
66
|
+
"crawlee[parsel]",
|
|
66
67
|
"dycw-pytest-only>=2.1.1",
|
|
67
68
|
"griffe~=1.9.0",
|
|
68
69
|
"mypy~=1.17.0",
|
|
@@ -76,6 +77,7 @@ dev = [
|
|
|
76
77
|
"respx~=0.22.0",
|
|
77
78
|
"ruff~=0.12.0",
|
|
78
79
|
"setuptools", # setuptools are used by pytest but not explicitly required
|
|
80
|
+
"uvicorn[standard]",
|
|
79
81
|
]
|
|
80
82
|
|
|
81
83
|
[tool.hatch.build.targets.wheel]
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Test server is infinite server http://localhost:8080/{any_number} and each page has links to the next 10 pages.
|
|
3
|
+
For example:
|
|
4
|
+
http://localhost:8080/ contains links:
|
|
5
|
+
http://localhost:8080/0, http://localhost:8080/1, ..., http://localhost:8080/9
|
|
6
|
+
|
|
7
|
+
http://localhost:8080/1 contains links:
|
|
8
|
+
http://localhost:8080/10, http://localhost:8080/11, ..., http://localhost:8080/19
|
|
9
|
+
|
|
10
|
+
... and so on.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
import asyncio
|
|
14
|
+
import logging
|
|
15
|
+
from collections.abc import Awaitable, Callable, Coroutine
|
|
16
|
+
from socket import socket
|
|
17
|
+
from typing import Any
|
|
18
|
+
|
|
19
|
+
from uvicorn import Config
|
|
20
|
+
from uvicorn.server import Server
|
|
21
|
+
from yarl import URL
|
|
22
|
+
|
|
23
|
+
Receive = Callable[[], Awaitable[dict[str, Any]]]
|
|
24
|
+
Send = Callable[[dict[str, Any]], Coroutine[None, None, None]]
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
async def send_html_response(send: Send, html_content: bytes, status: int = 200) -> None:
|
|
28
|
+
"""Send an HTML response to the client."""
|
|
29
|
+
await send(
|
|
30
|
+
{
|
|
31
|
+
'type': 'http.response.start',
|
|
32
|
+
'status': status,
|
|
33
|
+
'headers': [[b'content-type', b'text/html; charset=utf-8']],
|
|
34
|
+
}
|
|
35
|
+
)
|
|
36
|
+
await send({'type': 'http.response.body', 'body': html_content})
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
async def app(scope: dict[str, Any], _: Receive, send: Send) -> None:
|
|
40
|
+
"""Main ASGI application handler that routes requests to specific handlers.
|
|
41
|
+
|
|
42
|
+
Args:
|
|
43
|
+
scope: The ASGI connection scope.
|
|
44
|
+
_: The ASGI receive function.
|
|
45
|
+
send: The ASGI send function.
|
|
46
|
+
"""
|
|
47
|
+
assert scope['type'] == 'http'
|
|
48
|
+
path = scope['path']
|
|
49
|
+
|
|
50
|
+
links = '\n'.join(f'<a href="{path}{i}">{path}{i}</a>' for i in range(10))
|
|
51
|
+
await send_html_response(
|
|
52
|
+
send,
|
|
53
|
+
f"""\
|
|
54
|
+
<html><head>
|
|
55
|
+
<title>Title for {path} </title>
|
|
56
|
+
</head>
|
|
57
|
+
<body>
|
|
58
|
+
{links}
|
|
59
|
+
</body></html>""".encode(),
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
class TestServer(Server):
|
|
64
|
+
"""A test HTTP server implementation based on Uvicorn Server."""
|
|
65
|
+
|
|
66
|
+
@property
|
|
67
|
+
def url(self) -> URL:
|
|
68
|
+
"""Get the base URL of the server.
|
|
69
|
+
|
|
70
|
+
Returns:
|
|
71
|
+
A URL instance with the server's base URL.
|
|
72
|
+
"""
|
|
73
|
+
protocol = 'https' if self.config.is_ssl else 'http'
|
|
74
|
+
return URL(f'{protocol}://{self.config.host}:{self.config.port}/')
|
|
75
|
+
|
|
76
|
+
async def serve(self, sockets: list[socket] | None = None) -> None:
|
|
77
|
+
"""Run the server."""
|
|
78
|
+
if sockets:
|
|
79
|
+
raise RuntimeError('Simple TestServer does not support custom sockets')
|
|
80
|
+
self.restart_requested = asyncio.Event()
|
|
81
|
+
|
|
82
|
+
loop = asyncio.get_event_loop()
|
|
83
|
+
tasks = {
|
|
84
|
+
loop.create_task(super().serve()),
|
|
85
|
+
}
|
|
86
|
+
await asyncio.wait(tasks)
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
if __name__ == '__main__':
|
|
90
|
+
asyncio.run(
|
|
91
|
+
TestServer(
|
|
92
|
+
config=Config(
|
|
93
|
+
app=app,
|
|
94
|
+
lifespan='off',
|
|
95
|
+
loop='asyncio',
|
|
96
|
+
port=8080,
|
|
97
|
+
log_config=None,
|
|
98
|
+
log_level=logging.CRITICAL,
|
|
99
|
+
)
|
|
100
|
+
).serve()
|
|
101
|
+
)
|
|
@@ -400,12 +400,12 @@ async def test_actor_adds_webhook_and_receives_event(
|
|
|
400
400
|
async with Actor:
|
|
401
401
|
|
|
402
402
|
class WebhookHandler(BaseHTTPRequestHandler):
|
|
403
|
-
def do_GET(self) -> None:
|
|
403
|
+
def do_GET(self) -> None:
|
|
404
404
|
self.send_response(200)
|
|
405
405
|
self.end_headers()
|
|
406
406
|
self.wfile.write(bytes('Hello, world!', encoding='utf-8'))
|
|
407
407
|
|
|
408
|
-
def do_POST(self) -> None:
|
|
408
|
+
def do_POST(self) -> None:
|
|
409
409
|
nonlocal webhook_body
|
|
410
410
|
content_length = self.headers.get('content-length')
|
|
411
411
|
length = int(content_length) if content_length else 0
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
4
|
+
|
|
5
|
+
if TYPE_CHECKING:
|
|
6
|
+
from .conftest import MakeActorFunction, RunActorFunction
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
async def test_actor_on_platform_max_crawl_depth(
|
|
10
|
+
make_actor: MakeActorFunction,
|
|
11
|
+
run_actor: RunActorFunction,
|
|
12
|
+
) -> None:
|
|
13
|
+
"""Test that the actor respects max_crawl_depth."""
|
|
14
|
+
|
|
15
|
+
async def main() -> None:
|
|
16
|
+
"""The crawler entry point."""
|
|
17
|
+
import re
|
|
18
|
+
|
|
19
|
+
from crawlee.crawlers import ParselCrawler, ParselCrawlingContext
|
|
20
|
+
|
|
21
|
+
from apify import Actor
|
|
22
|
+
|
|
23
|
+
async with Actor:
|
|
24
|
+
crawler = ParselCrawler(max_crawl_depth=2)
|
|
25
|
+
finished = []
|
|
26
|
+
enqueue_pattern = re.compile(r'http://localhost:8080/2+$')
|
|
27
|
+
|
|
28
|
+
@crawler.router.default_handler
|
|
29
|
+
async def default_handler(context: ParselCrawlingContext) -> None:
|
|
30
|
+
"""Default request handler."""
|
|
31
|
+
context.log.info(f'Processing {context.request.url} ...')
|
|
32
|
+
await context.enqueue_links(include=[enqueue_pattern])
|
|
33
|
+
finished.append(context.request.url)
|
|
34
|
+
|
|
35
|
+
await crawler.run(['http://localhost:8080/'])
|
|
36
|
+
assert finished == ['http://localhost:8080/', 'http://localhost:8080/2', 'http://localhost:8080/22']
|
|
37
|
+
|
|
38
|
+
actor = await make_actor(label='crawler-max-depth', main_func=main)
|
|
39
|
+
run_result = await run_actor(actor)
|
|
40
|
+
|
|
41
|
+
assert run_result.status == 'SUCCEEDED'
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
async def test_actor_on_platform_max_requests_per_crawl(
|
|
45
|
+
make_actor: MakeActorFunction,
|
|
46
|
+
run_actor: RunActorFunction,
|
|
47
|
+
) -> None:
|
|
48
|
+
"""Test that the actor respects max_requests_per_crawl."""
|
|
49
|
+
|
|
50
|
+
async def main() -> None:
|
|
51
|
+
"""The crawler entry point."""
|
|
52
|
+
from crawlee import ConcurrencySettings
|
|
53
|
+
from crawlee.crawlers import ParselCrawler, ParselCrawlingContext
|
|
54
|
+
|
|
55
|
+
from apify import Actor
|
|
56
|
+
|
|
57
|
+
async with Actor:
|
|
58
|
+
crawler = ParselCrawler(
|
|
59
|
+
max_requests_per_crawl=3, concurrency_settings=ConcurrencySettings(max_concurrency=1)
|
|
60
|
+
)
|
|
61
|
+
finished = []
|
|
62
|
+
|
|
63
|
+
@crawler.router.default_handler
|
|
64
|
+
async def default_handler(context: ParselCrawlingContext) -> None:
|
|
65
|
+
"""Default request handler."""
|
|
66
|
+
context.log.info(f'Processing {context.request.url} ...')
|
|
67
|
+
await context.enqueue_links()
|
|
68
|
+
finished.append(context.request.url)
|
|
69
|
+
|
|
70
|
+
await crawler.run(['http://localhost:8080/'])
|
|
71
|
+
assert len(finished) == 3
|
|
72
|
+
|
|
73
|
+
actor = await make_actor(label='crawler-max-requests', main_func=main)
|
|
74
|
+
run_result = await run_actor(actor)
|
|
75
|
+
|
|
76
|
+
assert run_result.status == 'SUCCEEDED'
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
async def test_actor_on_platform_max_request_retries(
|
|
80
|
+
make_actor: MakeActorFunction,
|
|
81
|
+
run_actor: RunActorFunction,
|
|
82
|
+
) -> None:
|
|
83
|
+
"""Test that the actor respects max_request_retries."""
|
|
84
|
+
|
|
85
|
+
async def main() -> None:
|
|
86
|
+
"""The crawler entry point."""
|
|
87
|
+
from crawlee.crawlers import BasicCrawlingContext, ParselCrawler, ParselCrawlingContext
|
|
88
|
+
|
|
89
|
+
from apify import Actor
|
|
90
|
+
|
|
91
|
+
async with Actor:
|
|
92
|
+
max_retries = 3
|
|
93
|
+
crawler = ParselCrawler(max_request_retries=max_retries)
|
|
94
|
+
failed_counter = 0
|
|
95
|
+
|
|
96
|
+
@crawler.error_handler
|
|
97
|
+
async def error_handler(_: BasicCrawlingContext, __: Exception) -> None:
|
|
98
|
+
nonlocal failed_counter
|
|
99
|
+
failed_counter += 1
|
|
100
|
+
|
|
101
|
+
@crawler.router.default_handler
|
|
102
|
+
async def default_handler(_: ParselCrawlingContext) -> None:
|
|
103
|
+
raise RuntimeError('Some error')
|
|
104
|
+
|
|
105
|
+
await crawler.run(['http://localhost:8080/'])
|
|
106
|
+
assert failed_counter == max_retries, f'{failed_counter=}'
|
|
107
|
+
|
|
108
|
+
actor = await make_actor(label='crawler-max-retries', main_func=main)
|
|
109
|
+
run_result = await run_actor(actor)
|
|
110
|
+
|
|
111
|
+
assert run_result.status == 'SUCCEEDED'
|
|
@@ -2,6 +2,8 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
from typing import TYPE_CHECKING
|
|
4
4
|
|
|
5
|
+
import pytest
|
|
6
|
+
|
|
5
7
|
from apify import Actor
|
|
6
8
|
|
|
7
9
|
if TYPE_CHECKING:
|
|
@@ -742,6 +744,9 @@ async def test_mixed_string_and_request_objects(
|
|
|
742
744
|
assert run_result.status == 'SUCCEEDED'
|
|
743
745
|
|
|
744
746
|
|
|
747
|
+
@pytest.mark.skip(
|
|
748
|
+
reason='The Apify RQ client is not resilient to concurrent processing, making this test flaky. See issue #529.'
|
|
749
|
+
)
|
|
745
750
|
async def test_concurrent_processing_simulation(
|
|
746
751
|
make_actor: MakeActorFunction,
|
|
747
752
|
run_actor: RunActorFunction,
|