apify 2.7.1b6__tar.gz → 2.7.1b7__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.1b6 → apify-2.7.1b7}/.github/workflows/build_and_deploy_docs.yaml +1 -1
- {apify-2.7.1b6 → apify-2.7.1b7}/CHANGELOG.md +3 -7
- {apify-2.7.1b6 → apify-2.7.1b7}/PKG-INFO +1 -1
- {apify-2.7.1b6 → apify-2.7.1b7}/pyproject.toml +6 -4
- {apify-2.7.1b6 → apify-2.7.1b7}/src/apify/_configuration.py +9 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/tests/integration/test_crawlers_with_storages.py +3 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/tests/unit/actor/test_actor_create_proxy_configuration.py +37 -28
- {apify-2.7.1b6 → apify-2.7.1b7}/tests/unit/actor/test_request_list.py +35 -22
- {apify-2.7.1b6 → apify-2.7.1b7}/tests/unit/conftest.py +38 -1
- {apify-2.7.1b6 → apify-2.7.1b7}/tests/unit/test_proxy_configuration.py +72 -68
- {apify-2.7.1b6 → apify-2.7.1b7}/uv.lock +204 -182
- {apify-2.7.1b6 → apify-2.7.1b7}/website/docusaurus.config.js +14 -2
- {apify-2.7.1b6 → apify-2.7.1b7}/website/package-lock.json +338 -3
- {apify-2.7.1b6 → apify-2.7.1b7}/website/package.json +1 -0
- apify-2.7.1b7/website/src/components/RunnableCodeBlock.jsx +46 -0
- apify-2.7.1b6/website/src/components/RunnableCodeBlock.jsx +0 -44
- {apify-2.7.1b6 → apify-2.7.1b7}/.editorconfig +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/.github/CODEOWNERS +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/.github/workflows/check_pr_title.yaml +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/.github/workflows/pre_release.yaml +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/.github/workflows/release.yaml +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/.github/workflows/run_code_checks.yaml +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/.github/workflows/update_new_issue.yaml +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/.gitignore +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/.markdownlint.yaml +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/.pre-commit-config.yaml +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/CONTRIBUTING.md +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/LICENSE +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/Makefile +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/README.md +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/docs/01_overview/01_introduction.mdx +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/docs/01_overview/02_running_actors_locally.mdx +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/docs/01_overview/03_actor_structure.mdx +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/docs/01_overview/code/01_introduction.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/docs/01_overview/code/actor_structure/__init__.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/docs/01_overview/code/actor_structure/__main__.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/docs/01_overview/code/actor_structure/main.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/docs/01_overview/code/actor_structure/py.typed +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/docs/02_guides/01_beautifulsoup_httpx.mdx +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/docs/02_guides/02_crawlee.mdx +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/docs/02_guides/03_playwright.mdx +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/docs/02_guides/04_selenium.mdx +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/docs/02_guides/05_scrapy.mdx +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/docs/02_guides/code/01_beautifulsoup_httpx.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/docs/02_guides/code/02_crawlee_beautifulsoup.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/docs/02_guides/code/02_crawlee_playwright.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/docs/02_guides/code/03_playwright.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/docs/02_guides/code/04_selenium.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/docs/02_guides/code/scrapy_project/src/__init__.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/docs/02_guides/code/scrapy_project/src/__main__.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/docs/02_guides/code/scrapy_project/src/items.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/docs/02_guides/code/scrapy_project/src/main.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/docs/02_guides/code/scrapy_project/src/py.typed +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/docs/02_guides/code/scrapy_project/src/settings.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/docs/02_guides/code/scrapy_project/src/spiders/__init__.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/docs/02_guides/code/scrapy_project/src/spiders/py.typed +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/docs/02_guides/code/scrapy_project/src/spiders/title.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/docs/03_concepts/01_actor_lifecycle.mdx +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/docs/03_concepts/02_actor_input.mdx +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/docs/03_concepts/03_storages.mdx +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/docs/03_concepts/04_actor_events.mdx +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/docs/03_concepts/05_proxy_management.mdx +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/docs/03_concepts/06_interacting_with_other_actors.mdx +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/docs/03_concepts/07_webhooks.mdx +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/docs/03_concepts/08_access_apify_api.mdx +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/docs/03_concepts/09_running_webserver.mdx +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/docs/03_concepts/10_logging.mdx +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/docs/03_concepts/11_configuration.mdx +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/docs/03_concepts/12_pay_per_event.mdx +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/docs/03_concepts/code/01_context_manager.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/docs/03_concepts/code/01_init_exit.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/docs/03_concepts/code/01_reboot.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/docs/03_concepts/code/01_status_message.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/docs/03_concepts/code/02_input.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/docs/03_concepts/code/03_dataset_exports.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/docs/03_concepts/code/03_dataset_read_write.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/docs/03_concepts/code/03_deleting_storages.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/docs/03_concepts/code/03_kvs_iterating.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/docs/03_concepts/code/03_kvs_public_url.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/docs/03_concepts/code/03_kvs_read_write.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/docs/03_concepts/code/03_opening_storages.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/docs/03_concepts/code/03_rq.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/docs/03_concepts/code/04_actor_events.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/docs/03_concepts/code/05_apify_proxy.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/docs/03_concepts/code/05_apify_proxy_config.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/docs/03_concepts/code/05_custom_proxy.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/docs/03_concepts/code/05_custom_proxy_function.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/docs/03_concepts/code/05_proxy_actor_input.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/docs/03_concepts/code/05_proxy_httpx.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/docs/03_concepts/code/05_proxy_rotation.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/docs/03_concepts/code/06_interacting_call.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/docs/03_concepts/code/06_interacting_call_task.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/docs/03_concepts/code/06_interacting_metamorph.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/docs/03_concepts/code/06_interacting_start.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/docs/03_concepts/code/07_webhook.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/docs/03_concepts/code/07_webhook_preventing.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/docs/03_concepts/code/08_actor_client.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/docs/03_concepts/code/08_actor_new_client.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/docs/03_concepts/code/09_webserver.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/docs/03_concepts/code/10_log_config.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/docs/03_concepts/code/10_logger_usage.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/docs/03_concepts/code/10_redirect_log.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/docs/03_concepts/code/10_redirect_log_existing_run.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/docs/03_concepts/code/11_config.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/docs/03_concepts/code/actor_charge.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/docs/03_concepts/code/conditional_actor_charge.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/docs/04_upgrading/upgrading_to_v2.md +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/docs/pyproject.toml +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/renovate.json +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/src/apify/__init__.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/src/apify/_actor.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/src/apify/_charging.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/src/apify/_consts.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/src/apify/_crypto.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/src/apify/_models.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/src/apify/_platform_event_manager.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/src/apify/_proxy_configuration.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/src/apify/_utils.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/src/apify/apify_storage_client/__init__.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/src/apify/apify_storage_client/_apify_storage_client.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/src/apify/apify_storage_client/_dataset_client.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/src/apify/apify_storage_client/_dataset_collection_client.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/src/apify/apify_storage_client/_key_value_store_client.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/src/apify/apify_storage_client/_key_value_store_collection_client.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/src/apify/apify_storage_client/_request_queue_client.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/src/apify/apify_storage_client/_request_queue_collection_client.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/src/apify/apify_storage_client/py.typed +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/src/apify/log.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/src/apify/py.typed +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/src/apify/scrapy/__init__.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/src/apify/scrapy/_actor_runner.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/src/apify/scrapy/_async_thread.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/src/apify/scrapy/_logging_config.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/src/apify/scrapy/extensions/__init__.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/src/apify/scrapy/extensions/_httpcache.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/src/apify/scrapy/middlewares/__init__.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/src/apify/scrapy/middlewares/apify_proxy.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/src/apify/scrapy/middlewares/py.typed +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/src/apify/scrapy/pipelines/__init__.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/src/apify/scrapy/pipelines/actor_dataset_push.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/src/apify/scrapy/pipelines/py.typed +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/src/apify/scrapy/py.typed +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/src/apify/scrapy/requests.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/src/apify/scrapy/scheduler.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/src/apify/scrapy/utils.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/src/apify/storages/__init__.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/src/apify/storages/_request_list.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/src/apify/storages/py.typed +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/tests/integration/README.md +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/tests/integration/__init__.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/tests/integration/_utils.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/tests/integration/actor_source_base/Dockerfile +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/tests/integration/actor_source_base/requirements.txt +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/tests/integration/actor_source_base/server.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/tests/integration/actor_source_base/src/__init__.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/tests/integration/actor_source_base/src/__main__.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/tests/integration/actor_source_base/src/main.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/tests/integration/conftest.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/tests/integration/test_actor_api_helpers.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/tests/integration/test_actor_call_timeouts.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/tests/integration/test_actor_charge.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/tests/integration/test_actor_create_proxy_configuration.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/tests/integration/test_actor_dataset.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/tests/integration/test_actor_events.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/tests/integration/test_actor_key_value_store.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/tests/integration/test_actor_lifecycle.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/tests/integration/test_actor_log.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/tests/integration/test_actor_request_queue.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/tests/integration/test_actor_scrapy.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/tests/integration/test_fixtures.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/tests/integration/test_request_queue.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/tests/unit/__init__.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/tests/unit/actor/__init__.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/tests/unit/actor/test_actor_dataset.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/tests/unit/actor/test_actor_env_helpers.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/tests/unit/actor/test_actor_helpers.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/tests/unit/actor/test_actor_key_value_store.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/tests/unit/actor/test_actor_lifecycle.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/tests/unit/actor/test_actor_log.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/tests/unit/actor/test_actor_non_default_instance.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/tests/unit/actor/test_actor_request_queue.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/tests/unit/actor/test_configuration.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/tests/unit/scrapy/__init__.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/tests/unit/scrapy/extensions/__init__.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/tests/unit/scrapy/extensions/test_httpcache.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/tests/unit/scrapy/middlewares/__init__.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/tests/unit/scrapy/middlewares/test_apify_proxy.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/tests/unit/scrapy/pipelines/__init__.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/tests/unit/scrapy/pipelines/test_actor_dataset_push.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/tests/unit/scrapy/requests/__init__.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/tests/unit/scrapy/requests/test_to_apify_request.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/tests/unit/scrapy/requests/test_to_scrapy_request.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/tests/unit/scrapy/utils/__init__.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/tests/unit/scrapy/utils/test_apply_apify_settings.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/tests/unit/scrapy/utils/test_get_basic_auth_header.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/tests/unit/test_crypto.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/tests/unit/test_platform_event_manager.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/website/.eslintrc.json +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/website/babel.config.js +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/website/build_api_reference.sh +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/website/generate_module_shortcuts.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/website/sidebars.js +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/website/src/components/ApiLink.jsx +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/website/src/components/Gradients.jsx +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/website/src/components/Highlights.jsx +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/website/src/components/Highlights.module.css +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/website/src/components/RunnableCodeBlock.module.css +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/website/src/css/custom.css +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/website/src/pages/home_page_example.py +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/website/src/pages/index.js +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/website/src/pages/index.module.css +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/website/static/.nojekyll +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/website/static/img/docs-og.png +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/website/static/img/guides/redirected_logs_example.webp +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/website/tools/docs-prettier.config.js +0 -0
- {apify-2.7.1b6 → apify-2.7.1b7}/website/tools/utils/externalLink.js +0 -0
|
@@ -8,6 +8,7 @@ All notable changes to this project will be documented in this file.
|
|
|
8
8
|
### 🐛 Bug Fixes
|
|
9
9
|
|
|
10
10
|
- Restrict apify-shared and apify-client versions ([#523](https://github.com/apify/apify-sdk-python/pull/523)) ([b3ae5a9](https://github.com/apify/apify-sdk-python/commit/b3ae5a972a65454a4998eda59c9fcc3f6b7e8579)) by [@vdusek](https://github.com/vdusek)
|
|
11
|
+
- Expose `APIFY_USER_IS_PAYING` env var to the configuration ([#507](https://github.com/apify/apify-sdk-python/pull/507)) ([0801e54](https://github.com/apify/apify-sdk-python/commit/0801e54887317c1280cc6828ecd3f2cc53287e76)) by [@stepskop](https://github.com/stepskop)
|
|
11
12
|
|
|
12
13
|
|
|
13
14
|
<!-- git-cliff-unreleased-end -->
|
|
@@ -23,16 +24,11 @@ All notable changes to this project will be documented in this file.
|
|
|
23
24
|
- 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
25
|
|
|
25
26
|
|
|
26
|
-
## [2.7.
|
|
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)
|
|
27
|
+
## [2.7.3](https://github.com/apify/apify-sdk-python/releases/tag/v2.7.3) (2025-08-11)
|
|
31
28
|
|
|
32
29
|
### 🐛 Bug Fixes
|
|
33
30
|
|
|
34
|
-
-
|
|
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)
|
|
31
|
+
- Expose `APIFY_USER_IS_PAYING` env var to the configuration (#507) ([0de022c](https://github.com/apify/apify-sdk-python/commit/0de022c3435f24c821053c771e7b659433e3fb6e))
|
|
36
32
|
|
|
37
33
|
|
|
38
34
|
## [2.7.2](https://github.com/apify/apify-sdk-python/releases/tag/v2.7.2) (2025-07-30)
|
|
@@ -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.1b7"
|
|
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" }
|
|
@@ -65,19 +65,21 @@ dev = [
|
|
|
65
65
|
"build~=1.3.0",
|
|
66
66
|
"crawlee[parsel]",
|
|
67
67
|
"dycw-pytest-only>=2.1.1",
|
|
68
|
-
"griffe~=1.
|
|
68
|
+
"griffe~=1.11.0",
|
|
69
69
|
"mypy~=1.17.0",
|
|
70
|
-
"pre-commit~=4.
|
|
70
|
+
"pre-commit~=4.3.0",
|
|
71
71
|
"pydoc-markdown~=4.8.0",
|
|
72
72
|
"pytest-asyncio~=1.1.0",
|
|
73
73
|
"pytest-cov~=6.2.0",
|
|
74
|
+
"pytest-httpserver>=1.1.3",
|
|
74
75
|
"pytest-timeout>=2.4.0",
|
|
75
76
|
"pytest-xdist~=3.8.0",
|
|
76
77
|
"pytest~=8.4.0",
|
|
77
|
-
"respx~=0.22.0",
|
|
78
78
|
"ruff~=0.12.0",
|
|
79
79
|
"setuptools", # setuptools are used by pytest but not explicitly required
|
|
80
80
|
"uvicorn[standard]",
|
|
81
|
+
"werkzeug~=3.1.3", # Werkzeug is used by httpserver
|
|
82
|
+
"yarl~=1.20.0", # yarl is used by crawlee
|
|
81
83
|
]
|
|
82
84
|
|
|
83
85
|
[tool.hatch.build.targets.wheel]
|
|
@@ -334,6 +334,15 @@ class Configuration(CrawleeConfiguration):
|
|
|
334
334
|
),
|
|
335
335
|
] = None
|
|
336
336
|
|
|
337
|
+
user_is_paying: Annotated[
|
|
338
|
+
bool,
|
|
339
|
+
Field(
|
|
340
|
+
alias='apify_user_is_paying',
|
|
341
|
+
description='True if the user calling the Actor is paying user',
|
|
342
|
+
),
|
|
343
|
+
BeforeValidator(lambda val: False if val == '' else val),
|
|
344
|
+
] = False
|
|
345
|
+
|
|
337
346
|
web_server_port: Annotated[
|
|
338
347
|
int,
|
|
339
348
|
Field(
|
|
@@ -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
|
if TYPE_CHECKING:
|
|
6
8
|
from .conftest import MakeActorFunction, RunActorFunction
|
|
7
9
|
|
|
@@ -76,6 +78,7 @@ async def test_actor_on_platform_max_requests_per_crawl(
|
|
|
76
78
|
assert run_result.status == 'SUCCEEDED'
|
|
77
79
|
|
|
78
80
|
|
|
81
|
+
@pytest.mark.skip(reason='Sometimes crawler does not respect max_request_retries argument, see issue #540')
|
|
79
82
|
async def test_actor_on_platform_max_request_retries(
|
|
80
83
|
make_actor: MakeActorFunction,
|
|
81
84
|
run_actor: RunActorFunction,
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
from typing import TYPE_CHECKING
|
|
4
|
+
from unittest.mock import Mock
|
|
4
5
|
|
|
5
|
-
import httpx
|
|
6
6
|
import pytest
|
|
7
7
|
|
|
8
8
|
from apify_client import ApifyClientAsync
|
|
@@ -11,7 +11,8 @@ from apify_shared.consts import ApifyEnvVars
|
|
|
11
11
|
from apify import Actor
|
|
12
12
|
|
|
13
13
|
if TYPE_CHECKING:
|
|
14
|
-
from
|
|
14
|
+
from pytest_httpserver import HTTPServer
|
|
15
|
+
from werkzeug import Request, Response
|
|
15
16
|
|
|
16
17
|
from ..conftest import ApifyClientAsyncPatcher
|
|
17
18
|
|
|
@@ -24,25 +25,29 @@ def patched_apify_client(apify_client_async_patcher: ApifyClientAsyncPatcher) ->
|
|
|
24
25
|
return ApifyClientAsync()
|
|
25
26
|
|
|
26
27
|
|
|
28
|
+
@pytest.mark.usefixtures('patched_httpx_client')
|
|
27
29
|
async def test_basic_proxy_configuration_creation(
|
|
28
30
|
monkeypatch: pytest.MonkeyPatch,
|
|
29
|
-
|
|
31
|
+
httpserver: HTTPServer,
|
|
30
32
|
patched_apify_client: ApifyClientAsync,
|
|
31
33
|
) -> None:
|
|
32
|
-
dummy_proxy_status_url = '
|
|
34
|
+
dummy_proxy_status_url = str(httpserver.url_for('/')).removesuffix('/')
|
|
33
35
|
monkeypatch.setenv(ApifyEnvVars.TOKEN.value, 'DUMMY_TOKEN')
|
|
34
36
|
monkeypatch.setenv(ApifyEnvVars.PROXY_STATUS_URL.value, dummy_proxy_status_url)
|
|
35
37
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
38
|
+
call_mock = Mock()
|
|
39
|
+
|
|
40
|
+
def request_handler(request: Request, response: Response) -> Response:
|
|
41
|
+
call_mock(request.url)
|
|
42
|
+
return response
|
|
43
|
+
|
|
44
|
+
httpserver.expect_oneshot_request('/').with_post_hook(request_handler).respond_with_json(
|
|
45
|
+
{
|
|
46
|
+
'connected': True,
|
|
47
|
+
'connectionError': None,
|
|
48
|
+
'isManInTheMiddle': True,
|
|
49
|
+
},
|
|
50
|
+
status=200,
|
|
46
51
|
)
|
|
47
52
|
|
|
48
53
|
groups = ['GROUP1', 'GROUP2']
|
|
@@ -58,32 +63,36 @@ async def test_basic_proxy_configuration_creation(
|
|
|
58
63
|
assert proxy_configuration._country_code == country_code
|
|
59
64
|
|
|
60
65
|
assert len(patched_apify_client.calls['user']['get']) == 1 # type: ignore[attr-defined]
|
|
61
|
-
assert
|
|
66
|
+
assert call_mock.call_count == 1
|
|
62
67
|
|
|
63
68
|
await Actor.exit()
|
|
64
69
|
|
|
65
70
|
|
|
71
|
+
@pytest.mark.usefixtures('patched_httpx_client')
|
|
66
72
|
async def test_proxy_configuration_with_actor_proxy_input(
|
|
67
73
|
monkeypatch: pytest.MonkeyPatch,
|
|
68
|
-
|
|
74
|
+
httpserver: HTTPServer,
|
|
69
75
|
patched_apify_client: ApifyClientAsync,
|
|
70
76
|
) -> None:
|
|
71
|
-
dummy_proxy_status_url = '
|
|
77
|
+
dummy_proxy_status_url = str(httpserver.url_for('/')).removesuffix('/')
|
|
72
78
|
dummy_proxy_url = 'http://dummy-proxy.com:8000'
|
|
73
79
|
|
|
74
80
|
monkeypatch.setenv(ApifyEnvVars.TOKEN.value, 'DUMMY_TOKEN')
|
|
75
81
|
monkeypatch.setenv(ApifyEnvVars.PROXY_STATUS_URL.value, dummy_proxy_status_url)
|
|
76
82
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
83
|
+
call_mock = Mock()
|
|
84
|
+
|
|
85
|
+
def request_handler(request: Request, response: Response) -> Response:
|
|
86
|
+
call_mock(request.url)
|
|
87
|
+
return response
|
|
88
|
+
|
|
89
|
+
httpserver.expect_request('/').with_post_hook(request_handler).respond_with_json(
|
|
90
|
+
{
|
|
91
|
+
'connected': True,
|
|
92
|
+
'connectionError': None,
|
|
93
|
+
'isManInTheMiddle': True,
|
|
94
|
+
},
|
|
95
|
+
status=200,
|
|
87
96
|
)
|
|
88
97
|
|
|
89
98
|
await Actor.init()
|
|
@@ -138,6 +147,6 @@ async def test_proxy_configuration_with_actor_proxy_input(
|
|
|
138
147
|
)
|
|
139
148
|
|
|
140
149
|
assert len(patched_apify_client.calls['user']['get']) == 2 # type: ignore[attr-defined]
|
|
141
|
-
assert
|
|
150
|
+
assert call_mock.call_count == 2
|
|
142
151
|
|
|
143
152
|
await Actor.exit()
|
|
@@ -2,17 +2,21 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import re
|
|
4
4
|
from dataclasses import dataclass
|
|
5
|
-
from typing import Any, get_args
|
|
5
|
+
from typing import TYPE_CHECKING, Any, get_args
|
|
6
|
+
from unittest.mock import Mock
|
|
6
7
|
|
|
7
8
|
import pytest
|
|
8
|
-
import
|
|
9
|
-
from httpx import Response
|
|
9
|
+
from yarl import URL
|
|
10
10
|
|
|
11
11
|
from crawlee._request import UserData
|
|
12
12
|
from crawlee._types import HttpMethod
|
|
13
13
|
|
|
14
14
|
from apify.storages._request_list import URL_NO_COMMAS_REGEX, RequestList
|
|
15
15
|
|
|
16
|
+
if TYPE_CHECKING:
|
|
17
|
+
from pytest_httpserver import HTTPServer
|
|
18
|
+
from werkzeug import Request, Response
|
|
19
|
+
|
|
16
20
|
|
|
17
21
|
@pytest.mark.parametrize(
|
|
18
22
|
argnames='request_method',
|
|
@@ -67,20 +71,19 @@ async def test_request_list_open_request_types(
|
|
|
67
71
|
assert request.headers.root == optional_input.get('headers', {})
|
|
68
72
|
|
|
69
73
|
|
|
70
|
-
|
|
71
|
-
async def test_request_list_open_from_url_correctly_send_requests() -> None:
|
|
74
|
+
async def test_request_list_open_from_url_correctly_send_requests(httpserver: HTTPServer) -> None:
|
|
72
75
|
"""Test that requests are sent to expected urls."""
|
|
73
76
|
request_list_sources_input: list[dict[str, Any]] = [
|
|
74
77
|
{
|
|
75
|
-
'requestsFromUrl': '
|
|
78
|
+
'requestsFromUrl': httpserver.url_for('/file.txt'),
|
|
76
79
|
'method': 'GET',
|
|
77
80
|
},
|
|
78
81
|
{
|
|
79
|
-
'requestsFromUrl': '
|
|
82
|
+
'requestsFromUrl': httpserver.url_for('/file2'),
|
|
80
83
|
'method': 'PUT',
|
|
81
84
|
},
|
|
82
85
|
{
|
|
83
|
-
'requestsFromUrl': '
|
|
86
|
+
'requestsFromUrl': httpserver.url_for('/something'),
|
|
84
87
|
'method': 'POST',
|
|
85
88
|
'headers': {'key': 'value'},
|
|
86
89
|
'payload': 'some_payload',
|
|
@@ -88,16 +91,28 @@ async def test_request_list_open_from_url_correctly_send_requests() -> None:
|
|
|
88
91
|
},
|
|
89
92
|
]
|
|
90
93
|
|
|
91
|
-
routes
|
|
94
|
+
routes: dict[str, Mock] = {}
|
|
95
|
+
|
|
96
|
+
def request_handler(request: Request, response: Response) -> Response:
|
|
97
|
+
routes[request.url]()
|
|
98
|
+
return response
|
|
99
|
+
|
|
100
|
+
for entry in request_list_sources_input:
|
|
101
|
+
path = str(URL(entry['requestsFromUrl']).path)
|
|
102
|
+
httpserver.expect_oneshot_request(path).with_post_hook(request_handler).respond_with_data(status=200)
|
|
103
|
+
routes[entry['requestsFromUrl']] = Mock()
|
|
92
104
|
|
|
93
105
|
await RequestList.open(request_list_sources_input=request_list_sources_input)
|
|
94
106
|
|
|
95
|
-
|
|
96
|
-
assert route.called
|
|
107
|
+
assert len(routes) == len(request_list_sources_input)
|
|
97
108
|
|
|
109
|
+
for entity in request_list_sources_input:
|
|
110
|
+
entity_url = entity['requestsFromUrl']
|
|
111
|
+
assert entity_url in routes
|
|
112
|
+
assert routes[entity_url].called
|
|
98
113
|
|
|
99
|
-
|
|
100
|
-
async def test_request_list_open_from_url() -> None:
|
|
114
|
+
|
|
115
|
+
async def test_request_list_open_from_url(httpserver: HTTPServer) -> None:
|
|
101
116
|
"""Test that create_request_list is correctly reading urls from remote url sources and also from simple input."""
|
|
102
117
|
expected_simple_url = 'https://www.someurl.com'
|
|
103
118
|
expected_remote_urls_1 = {'http://www.something.com', 'https://www.somethingelse.com', 'http://www.bla.net'}
|
|
@@ -111,11 +126,11 @@ async def test_request_list_open_from_url() -> None:
|
|
|
111
126
|
|
|
112
127
|
mocked_urls = (
|
|
113
128
|
MockedUrlInfo(
|
|
114
|
-
'
|
|
129
|
+
httpserver.url_for('/file.txt'),
|
|
115
130
|
'blablabla{} more blablabla{} , even more blablabla. {} '.format(*expected_remote_urls_1),
|
|
116
131
|
),
|
|
117
132
|
MockedUrlInfo(
|
|
118
|
-
'
|
|
133
|
+
httpserver.url_for('/file2'),
|
|
119
134
|
'some stuff{} more stuff{} www.false_positive.com'.format(*expected_remote_urls_2),
|
|
120
135
|
),
|
|
121
136
|
)
|
|
@@ -132,7 +147,8 @@ async def test_request_list_open_from_url() -> None:
|
|
|
132
147
|
},
|
|
133
148
|
]
|
|
134
149
|
for mocked_url in mocked_urls:
|
|
135
|
-
|
|
150
|
+
path = str(URL(mocked_url.url).path)
|
|
151
|
+
httpserver.expect_oneshot_request(path).respond_with_data(status=200, response_data=mocked_url.response_text)
|
|
136
152
|
|
|
137
153
|
request_list = await RequestList.open(request_list_sources_input=request_list_sources_input)
|
|
138
154
|
generated_requests = []
|
|
@@ -143,23 +159,20 @@ async def test_request_list_open_from_url() -> None:
|
|
|
143
159
|
assert {generated_request.url for generated_request in generated_requests} == expected_urls
|
|
144
160
|
|
|
145
161
|
|
|
146
|
-
|
|
147
|
-
async def test_request_list_open_from_url_additional_inputs() -> None:
|
|
162
|
+
async def test_request_list_open_from_url_additional_inputs(httpserver: HTTPServer) -> None:
|
|
148
163
|
"""Test that all generated request properties are correctly populated from input values."""
|
|
149
164
|
expected_url = 'https://www.someurl.com'
|
|
150
165
|
example_start_url_input: dict[str, Any] = {
|
|
151
|
-
'requestsFromUrl': '
|
|
166
|
+
'requestsFromUrl': httpserver.url_for('/file.txt'),
|
|
152
167
|
'method': 'POST',
|
|
153
168
|
'headers': {'key': 'value'},
|
|
154
169
|
'payload': 'some_payload',
|
|
155
170
|
'userData': {'another_key': 'another_value'},
|
|
156
171
|
}
|
|
157
|
-
|
|
158
|
-
respx.get(example_start_url_input['requestsFromUrl']).mock(return_value=Response(200, text=expected_url))
|
|
172
|
+
httpserver.expect_oneshot_request('/file.txt').respond_with_data(status=200, response_data=expected_url)
|
|
159
173
|
|
|
160
174
|
request_list = await RequestList.open(request_list_sources_input=[example_start_url_input])
|
|
161
175
|
request = await request_list.fetch_next_request()
|
|
162
|
-
|
|
163
176
|
# Check all properties correctly created for request
|
|
164
177
|
assert request
|
|
165
178
|
assert request.url == expected_url
|
|
@@ -4,9 +4,12 @@ import asyncio
|
|
|
4
4
|
import inspect
|
|
5
5
|
import os
|
|
6
6
|
from collections import defaultdict
|
|
7
|
+
from logging import getLogger
|
|
7
8
|
from typing import TYPE_CHECKING, Any, get_type_hints
|
|
8
9
|
|
|
10
|
+
import httpx
|
|
9
11
|
import pytest
|
|
12
|
+
from pytest_httpserver import HTTPServer
|
|
10
13
|
|
|
11
14
|
from apify_client import ApifyClientAsync
|
|
12
15
|
from apify_shared.consts import ApifyEnvVars
|
|
@@ -18,7 +21,7 @@ from crawlee.storages import _creation_management
|
|
|
18
21
|
import apify._actor
|
|
19
22
|
|
|
20
23
|
if TYPE_CHECKING:
|
|
21
|
-
from collections.abc import Callable
|
|
24
|
+
from collections.abc import Callable, Iterator
|
|
22
25
|
from pathlib import Path
|
|
23
26
|
|
|
24
27
|
|
|
@@ -187,3 +190,37 @@ def memory_storage_client() -> MemoryStorageClient:
|
|
|
187
190
|
configuration.write_metadata = True
|
|
188
191
|
|
|
189
192
|
return MemoryStorageClient.from_config(configuration)
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
@pytest.fixture(scope='session')
|
|
196
|
+
def make_httpserver() -> Iterator[HTTPServer]:
|
|
197
|
+
werkzeug_logger = getLogger('werkzeug')
|
|
198
|
+
werkzeug_logger.disabled = True
|
|
199
|
+
|
|
200
|
+
server = HTTPServer(threaded=True, host='127.0.0.1')
|
|
201
|
+
server.start()
|
|
202
|
+
yield server
|
|
203
|
+
server.clear() # type: ignore[no-untyped-call]
|
|
204
|
+
if server.is_running():
|
|
205
|
+
server.stop() # type: ignore[no-untyped-call]
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
@pytest.fixture
|
|
209
|
+
def httpserver(make_httpserver: HTTPServer) -> Iterator[HTTPServer]:
|
|
210
|
+
server = make_httpserver
|
|
211
|
+
yield server
|
|
212
|
+
server.clear() # type: ignore[no-untyped-call]
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
@pytest.fixture
|
|
216
|
+
def patched_httpx_client(monkeypatch: pytest.MonkeyPatch) -> Iterator[None]:
|
|
217
|
+
"""Patch httpx client to drop proxy settings."""
|
|
218
|
+
|
|
219
|
+
class ProxylessAsyncClient(httpx.AsyncClient):
|
|
220
|
+
def __init__(self, *args: Any, **kwargs: Any) -> None:
|
|
221
|
+
kwargs.pop('proxy', None)
|
|
222
|
+
super().__init__(*args, **kwargs)
|
|
223
|
+
|
|
224
|
+
monkeypatch.setattr(httpx, 'AsyncClient', ProxylessAsyncClient)
|
|
225
|
+
yield
|
|
226
|
+
monkeypatch.undo()
|