apify 3.0.3b1__tar.gz → 3.0.4b1__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.

Files changed (246) hide show
  1. {apify-3.0.3b1 → apify-3.0.4b1}/CHANGELOG.md +9 -2
  2. {apify-3.0.3b1 → apify-3.0.4b1}/PKG-INFO +1 -1
  3. {apify-3.0.3b1 → apify-3.0.4b1}/pyproject.toml +1 -1
  4. {apify-3.0.3b1 → apify-3.0.4b1}/src/apify/_actor.py +0 -2
  5. {apify-3.0.3b1 → apify-3.0.4b1}/src/apify/storage_clients/_apify/_models.py +1 -1
  6. apify-3.0.4b1/src/apify/storage_clients/_apify/_storage_client.py +132 -0
  7. {apify-3.0.3b1 → apify-3.0.4b1}/src/apify/storage_clients/_smart_apify/_storage_client.py +40 -33
  8. {apify-3.0.3b1 → apify-3.0.4b1}/uv.lock +1 -1
  9. {apify-3.0.3b1 → apify-3.0.4b1}/website/docusaurus.config.js +4 -0
  10. {apify-3.0.3b1 → apify-3.0.4b1}/website/package-lock.json +3 -3
  11. apify-3.0.3b1/src/apify/storage_clients/_apify/_storage_client.py +0 -106
  12. {apify-3.0.3b1 → apify-3.0.4b1}/.editorconfig +0 -0
  13. {apify-3.0.3b1 → apify-3.0.4b1}/.github/CODEOWNERS +0 -0
  14. {apify-3.0.3b1 → apify-3.0.4b1}/.github/workflows/build_and_deploy_docs.yaml +0 -0
  15. {apify-3.0.3b1 → apify-3.0.4b1}/.github/workflows/check_pr_title.yaml +0 -0
  16. {apify-3.0.3b1 → apify-3.0.4b1}/.github/workflows/pre_release.yaml +0 -0
  17. {apify-3.0.3b1 → apify-3.0.4b1}/.github/workflows/release.yaml +0 -0
  18. {apify-3.0.3b1 → apify-3.0.4b1}/.github/workflows/run_code_checks.yaml +0 -0
  19. {apify-3.0.3b1 → apify-3.0.4b1}/.github/workflows/update_new_issue.yaml +0 -0
  20. {apify-3.0.3b1 → apify-3.0.4b1}/.gitignore +0 -0
  21. {apify-3.0.3b1 → apify-3.0.4b1}/.markdownlint.yaml +0 -0
  22. {apify-3.0.3b1 → apify-3.0.4b1}/.pre-commit-config.yaml +0 -0
  23. {apify-3.0.3b1 → apify-3.0.4b1}/CONTRIBUTING.md +0 -0
  24. {apify-3.0.3b1 → apify-3.0.4b1}/LICENSE +0 -0
  25. {apify-3.0.3b1 → apify-3.0.4b1}/Makefile +0 -0
  26. {apify-3.0.3b1 → apify-3.0.4b1}/README.md +0 -0
  27. {apify-3.0.3b1 → apify-3.0.4b1}/docs/01_overview/01_introduction.mdx +0 -0
  28. {apify-3.0.3b1 → apify-3.0.4b1}/docs/01_overview/02_running_actors_locally.mdx +0 -0
  29. {apify-3.0.3b1 → apify-3.0.4b1}/docs/01_overview/03_actor_structure.mdx +0 -0
  30. {apify-3.0.3b1 → apify-3.0.4b1}/docs/01_overview/code/01_introduction.py +0 -0
  31. {apify-3.0.3b1 → apify-3.0.4b1}/docs/01_overview/code/actor_structure/__init__.py +0 -0
  32. {apify-3.0.3b1 → apify-3.0.4b1}/docs/01_overview/code/actor_structure/__main__.py +0 -0
  33. {apify-3.0.3b1 → apify-3.0.4b1}/docs/01_overview/code/actor_structure/main.py +0 -0
  34. {apify-3.0.3b1 → apify-3.0.4b1}/docs/01_overview/code/actor_structure/py.typed +0 -0
  35. {apify-3.0.3b1 → apify-3.0.4b1}/docs/02_concepts/01_actor_lifecycle.mdx +0 -0
  36. {apify-3.0.3b1 → apify-3.0.4b1}/docs/02_concepts/02_actor_input.mdx +0 -0
  37. {apify-3.0.3b1 → apify-3.0.4b1}/docs/02_concepts/03_storages.mdx +0 -0
  38. {apify-3.0.3b1 → apify-3.0.4b1}/docs/02_concepts/04_actor_events.mdx +0 -0
  39. {apify-3.0.3b1 → apify-3.0.4b1}/docs/02_concepts/05_proxy_management.mdx +0 -0
  40. {apify-3.0.3b1 → apify-3.0.4b1}/docs/02_concepts/06_interacting_with_other_actors.mdx +0 -0
  41. {apify-3.0.3b1 → apify-3.0.4b1}/docs/02_concepts/07_webhooks.mdx +0 -0
  42. {apify-3.0.3b1 → apify-3.0.4b1}/docs/02_concepts/08_access_apify_api.mdx +0 -0
  43. {apify-3.0.3b1 → apify-3.0.4b1}/docs/02_concepts/09_running_webserver.mdx +0 -0
  44. {apify-3.0.3b1 → apify-3.0.4b1}/docs/02_concepts/10_logging.mdx +0 -0
  45. {apify-3.0.3b1 → apify-3.0.4b1}/docs/02_concepts/11_configuration.mdx +0 -0
  46. {apify-3.0.3b1 → apify-3.0.4b1}/docs/02_concepts/12_pay_per_event.mdx +0 -0
  47. {apify-3.0.3b1 → apify-3.0.4b1}/docs/02_concepts/code/01_class_context.py +0 -0
  48. {apify-3.0.3b1 → apify-3.0.4b1}/docs/02_concepts/code/01_class_manual.py +0 -0
  49. {apify-3.0.3b1 → apify-3.0.4b1}/docs/02_concepts/code/01_context_manager.py +0 -0
  50. {apify-3.0.3b1 → apify-3.0.4b1}/docs/02_concepts/code/01_error_handling_context.py +0 -0
  51. {apify-3.0.3b1 → apify-3.0.4b1}/docs/02_concepts/code/01_error_handling_manual.py +0 -0
  52. {apify-3.0.3b1 → apify-3.0.4b1}/docs/02_concepts/code/01_init_exit.py +0 -0
  53. {apify-3.0.3b1 → apify-3.0.4b1}/docs/02_concepts/code/01_instance_context.py +0 -0
  54. {apify-3.0.3b1 → apify-3.0.4b1}/docs/02_concepts/code/01_instance_manual.py +0 -0
  55. {apify-3.0.3b1 → apify-3.0.4b1}/docs/02_concepts/code/01_reboot.py +0 -0
  56. {apify-3.0.3b1 → apify-3.0.4b1}/docs/02_concepts/code/01_status_message.py +0 -0
  57. {apify-3.0.3b1 → apify-3.0.4b1}/docs/02_concepts/code/02_input.py +0 -0
  58. {apify-3.0.3b1 → apify-3.0.4b1}/docs/02_concepts/code/03_dataset_exports.py +0 -0
  59. {apify-3.0.3b1 → apify-3.0.4b1}/docs/02_concepts/code/03_dataset_read_write.py +0 -0
  60. {apify-3.0.3b1 → apify-3.0.4b1}/docs/02_concepts/code/03_deleting_storages.py +0 -0
  61. {apify-3.0.3b1 → apify-3.0.4b1}/docs/02_concepts/code/03_kvs_iterating.py +0 -0
  62. {apify-3.0.3b1 → apify-3.0.4b1}/docs/02_concepts/code/03_kvs_public_url.py +0 -0
  63. {apify-3.0.3b1 → apify-3.0.4b1}/docs/02_concepts/code/03_kvs_read_write.py +0 -0
  64. {apify-3.0.3b1 → apify-3.0.4b1}/docs/02_concepts/code/03_opening_storages.py +0 -0
  65. {apify-3.0.3b1 → apify-3.0.4b1}/docs/02_concepts/code/03_rq.py +0 -0
  66. {apify-3.0.3b1 → apify-3.0.4b1}/docs/02_concepts/code/04_actor_events.py +0 -0
  67. {apify-3.0.3b1 → apify-3.0.4b1}/docs/02_concepts/code/05_apify_proxy.py +0 -0
  68. {apify-3.0.3b1 → apify-3.0.4b1}/docs/02_concepts/code/05_apify_proxy_config.py +0 -0
  69. {apify-3.0.3b1 → apify-3.0.4b1}/docs/02_concepts/code/05_custom_proxy.py +0 -0
  70. {apify-3.0.3b1 → apify-3.0.4b1}/docs/02_concepts/code/05_custom_proxy_function.py +0 -0
  71. {apify-3.0.3b1 → apify-3.0.4b1}/docs/02_concepts/code/05_proxy_actor_input.py +0 -0
  72. {apify-3.0.3b1 → apify-3.0.4b1}/docs/02_concepts/code/05_proxy_httpx.py +0 -0
  73. {apify-3.0.3b1 → apify-3.0.4b1}/docs/02_concepts/code/05_proxy_rotation.py +0 -0
  74. {apify-3.0.3b1 → apify-3.0.4b1}/docs/02_concepts/code/06_interacting_call.py +0 -0
  75. {apify-3.0.3b1 → apify-3.0.4b1}/docs/02_concepts/code/06_interacting_call_task.py +0 -0
  76. {apify-3.0.3b1 → apify-3.0.4b1}/docs/02_concepts/code/06_interacting_metamorph.py +0 -0
  77. {apify-3.0.3b1 → apify-3.0.4b1}/docs/02_concepts/code/06_interacting_start.py +0 -0
  78. {apify-3.0.3b1 → apify-3.0.4b1}/docs/02_concepts/code/07_webhook.py +0 -0
  79. {apify-3.0.3b1 → apify-3.0.4b1}/docs/02_concepts/code/07_webhook_preventing.py +0 -0
  80. {apify-3.0.3b1 → apify-3.0.4b1}/docs/02_concepts/code/08_actor_client.py +0 -0
  81. {apify-3.0.3b1 → apify-3.0.4b1}/docs/02_concepts/code/08_actor_new_client.py +0 -0
  82. {apify-3.0.3b1 → apify-3.0.4b1}/docs/02_concepts/code/09_webserver.py +0 -0
  83. {apify-3.0.3b1 → apify-3.0.4b1}/docs/02_concepts/code/10_log_config.py +0 -0
  84. {apify-3.0.3b1 → apify-3.0.4b1}/docs/02_concepts/code/10_logger_usage.py +0 -0
  85. {apify-3.0.3b1 → apify-3.0.4b1}/docs/02_concepts/code/10_redirect_log.py +0 -0
  86. {apify-3.0.3b1 → apify-3.0.4b1}/docs/02_concepts/code/10_redirect_log_existing_run.py +0 -0
  87. {apify-3.0.3b1 → apify-3.0.4b1}/docs/02_concepts/code/11_config.py +0 -0
  88. {apify-3.0.3b1 → apify-3.0.4b1}/docs/02_concepts/code/actor_charge.py +0 -0
  89. {apify-3.0.3b1 → apify-3.0.4b1}/docs/02_concepts/code/conditional_actor_charge.py +0 -0
  90. {apify-3.0.3b1 → apify-3.0.4b1}/docs/03_guides/01_beautifulsoup_httpx.mdx +0 -0
  91. {apify-3.0.3b1 → apify-3.0.4b1}/docs/03_guides/02_parsel_impit.mdx +0 -0
  92. {apify-3.0.3b1 → apify-3.0.4b1}/docs/03_guides/03_playwright.mdx +0 -0
  93. {apify-3.0.3b1 → apify-3.0.4b1}/docs/03_guides/04_selenium.mdx +0 -0
  94. {apify-3.0.3b1 → apify-3.0.4b1}/docs/03_guides/05_crawlee.mdx +0 -0
  95. {apify-3.0.3b1 → apify-3.0.4b1}/docs/03_guides/06_scrapy.mdx +0 -0
  96. {apify-3.0.3b1 → apify-3.0.4b1}/docs/03_guides/code/01_beautifulsoup_httpx.py +0 -0
  97. {apify-3.0.3b1 → apify-3.0.4b1}/docs/03_guides/code/02_parsel_impit.py +0 -0
  98. {apify-3.0.3b1 → apify-3.0.4b1}/docs/03_guides/code/03_playwright.py +0 -0
  99. {apify-3.0.3b1 → apify-3.0.4b1}/docs/03_guides/code/04_selenium.py +0 -0
  100. {apify-3.0.3b1 → apify-3.0.4b1}/docs/03_guides/code/05_crawlee_beautifulsoup.py +0 -0
  101. {apify-3.0.3b1 → apify-3.0.4b1}/docs/03_guides/code/05_crawlee_parsel.py +0 -0
  102. {apify-3.0.3b1 → apify-3.0.4b1}/docs/03_guides/code/05_crawlee_playwright.py +0 -0
  103. {apify-3.0.3b1 → apify-3.0.4b1}/docs/03_guides/code/scrapy_project/src/__init__.py +0 -0
  104. {apify-3.0.3b1 → apify-3.0.4b1}/docs/03_guides/code/scrapy_project/src/__main__.py +0 -0
  105. {apify-3.0.3b1 → apify-3.0.4b1}/docs/03_guides/code/scrapy_project/src/items.py +0 -0
  106. {apify-3.0.3b1 → apify-3.0.4b1}/docs/03_guides/code/scrapy_project/src/main.py +0 -0
  107. {apify-3.0.3b1 → apify-3.0.4b1}/docs/03_guides/code/scrapy_project/src/py.typed +0 -0
  108. {apify-3.0.3b1 → apify-3.0.4b1}/docs/03_guides/code/scrapy_project/src/settings.py +0 -0
  109. {apify-3.0.3b1 → apify-3.0.4b1}/docs/03_guides/code/scrapy_project/src/spiders/__init__.py +0 -0
  110. {apify-3.0.3b1 → apify-3.0.4b1}/docs/03_guides/code/scrapy_project/src/spiders/py.typed +0 -0
  111. {apify-3.0.3b1 → apify-3.0.4b1}/docs/03_guides/code/scrapy_project/src/spiders/title.py +0 -0
  112. {apify-3.0.3b1 → apify-3.0.4b1}/docs/04_upgrading/upgrading_to_v2.md +0 -0
  113. {apify-3.0.3b1 → apify-3.0.4b1}/docs/04_upgrading/upgrading_to_v3.md +0 -0
  114. {apify-3.0.3b1 → apify-3.0.4b1}/docs/pyproject.toml +0 -0
  115. {apify-3.0.3b1 → apify-3.0.4b1}/renovate.json +0 -0
  116. {apify-3.0.3b1 → apify-3.0.4b1}/src/apify/__init__.py +0 -0
  117. {apify-3.0.3b1 → apify-3.0.4b1}/src/apify/_charging.py +0 -0
  118. {apify-3.0.3b1 → apify-3.0.4b1}/src/apify/_configuration.py +0 -0
  119. {apify-3.0.3b1 → apify-3.0.4b1}/src/apify/_consts.py +0 -0
  120. {apify-3.0.3b1 → apify-3.0.4b1}/src/apify/_crypto.py +0 -0
  121. {apify-3.0.3b1 → apify-3.0.4b1}/src/apify/_models.py +0 -0
  122. {apify-3.0.3b1 → apify-3.0.4b1}/src/apify/_proxy_configuration.py +0 -0
  123. {apify-3.0.3b1 → apify-3.0.4b1}/src/apify/_utils.py +0 -0
  124. {apify-3.0.3b1 → apify-3.0.4b1}/src/apify/events/__init__.py +0 -0
  125. {apify-3.0.3b1 → apify-3.0.4b1}/src/apify/events/_apify_event_manager.py +0 -0
  126. {apify-3.0.3b1 → apify-3.0.4b1}/src/apify/events/_types.py +0 -0
  127. {apify-3.0.3b1 → apify-3.0.4b1}/src/apify/events/py.typed +0 -0
  128. {apify-3.0.3b1 → apify-3.0.4b1}/src/apify/log.py +0 -0
  129. {apify-3.0.3b1 → apify-3.0.4b1}/src/apify/py.typed +0 -0
  130. {apify-3.0.3b1 → apify-3.0.4b1}/src/apify/request_loaders/__init__.py +0 -0
  131. {apify-3.0.3b1 → apify-3.0.4b1}/src/apify/request_loaders/_apify_request_list.py +0 -0
  132. {apify-3.0.3b1 → apify-3.0.4b1}/src/apify/request_loaders/py.typed +0 -0
  133. {apify-3.0.3b1 → apify-3.0.4b1}/src/apify/scrapy/__init__.py +0 -0
  134. {apify-3.0.3b1 → apify-3.0.4b1}/src/apify/scrapy/_actor_runner.py +0 -0
  135. {apify-3.0.3b1 → apify-3.0.4b1}/src/apify/scrapy/_async_thread.py +0 -0
  136. {apify-3.0.3b1 → apify-3.0.4b1}/src/apify/scrapy/_logging_config.py +0 -0
  137. {apify-3.0.3b1 → apify-3.0.4b1}/src/apify/scrapy/extensions/__init__.py +0 -0
  138. {apify-3.0.3b1 → apify-3.0.4b1}/src/apify/scrapy/extensions/_httpcache.py +0 -0
  139. {apify-3.0.3b1 → apify-3.0.4b1}/src/apify/scrapy/middlewares/__init__.py +0 -0
  140. {apify-3.0.3b1 → apify-3.0.4b1}/src/apify/scrapy/middlewares/apify_proxy.py +0 -0
  141. {apify-3.0.3b1 → apify-3.0.4b1}/src/apify/scrapy/middlewares/py.typed +0 -0
  142. {apify-3.0.3b1 → apify-3.0.4b1}/src/apify/scrapy/pipelines/__init__.py +0 -0
  143. {apify-3.0.3b1 → apify-3.0.4b1}/src/apify/scrapy/pipelines/actor_dataset_push.py +0 -0
  144. {apify-3.0.3b1 → apify-3.0.4b1}/src/apify/scrapy/pipelines/py.typed +0 -0
  145. {apify-3.0.3b1 → apify-3.0.4b1}/src/apify/scrapy/py.typed +0 -0
  146. {apify-3.0.3b1 → apify-3.0.4b1}/src/apify/scrapy/requests.py +0 -0
  147. {apify-3.0.3b1 → apify-3.0.4b1}/src/apify/scrapy/scheduler.py +0 -0
  148. {apify-3.0.3b1 → apify-3.0.4b1}/src/apify/scrapy/utils.py +0 -0
  149. {apify-3.0.3b1 → apify-3.0.4b1}/src/apify/storage_clients/__init__.py +0 -0
  150. {apify-3.0.3b1 → apify-3.0.4b1}/src/apify/storage_clients/_apify/__init__.py +0 -0
  151. {apify-3.0.3b1 → apify-3.0.4b1}/src/apify/storage_clients/_apify/_dataset_client.py +0 -0
  152. {apify-3.0.3b1 → apify-3.0.4b1}/src/apify/storage_clients/_apify/_key_value_store_client.py +0 -0
  153. {apify-3.0.3b1 → apify-3.0.4b1}/src/apify/storage_clients/_apify/_request_queue_client.py +0 -0
  154. {apify-3.0.3b1 → apify-3.0.4b1}/src/apify/storage_clients/_apify/_request_queue_shared_client.py +0 -0
  155. {apify-3.0.3b1 → apify-3.0.4b1}/src/apify/storage_clients/_apify/_request_queue_single_client.py +0 -0
  156. {apify-3.0.3b1 → apify-3.0.4b1}/src/apify/storage_clients/_apify/_utils.py +0 -0
  157. {apify-3.0.3b1 → apify-3.0.4b1}/src/apify/storage_clients/_apify/py.typed +0 -0
  158. {apify-3.0.3b1 → apify-3.0.4b1}/src/apify/storage_clients/_file_system/__init__.py +0 -0
  159. {apify-3.0.3b1 → apify-3.0.4b1}/src/apify/storage_clients/_file_system/_key_value_store_client.py +0 -0
  160. {apify-3.0.3b1 → apify-3.0.4b1}/src/apify/storage_clients/_file_system/_storage_client.py +0 -0
  161. {apify-3.0.3b1 → apify-3.0.4b1}/src/apify/storage_clients/_smart_apify/__init__.py +0 -0
  162. {apify-3.0.3b1 → apify-3.0.4b1}/src/apify/storage_clients/py.typed +0 -0
  163. {apify-3.0.3b1 → apify-3.0.4b1}/src/apify/storages/__init__.py +0 -0
  164. {apify-3.0.3b1 → apify-3.0.4b1}/src/apify/storages/py.typed +0 -0
  165. {apify-3.0.3b1 → apify-3.0.4b1}/tests/integration/README.md +0 -0
  166. {apify-3.0.3b1 → apify-3.0.4b1}/tests/integration/__init__.py +0 -0
  167. {apify-3.0.3b1 → apify-3.0.4b1}/tests/integration/_utils.py +0 -0
  168. {apify-3.0.3b1 → apify-3.0.4b1}/tests/integration/actor_source_base/Dockerfile +0 -0
  169. {apify-3.0.3b1 → apify-3.0.4b1}/tests/integration/actor_source_base/requirements.txt +0 -0
  170. {apify-3.0.3b1 → apify-3.0.4b1}/tests/integration/actor_source_base/server.py +0 -0
  171. {apify-3.0.3b1 → apify-3.0.4b1}/tests/integration/actor_source_base/src/__init__.py +0 -0
  172. {apify-3.0.3b1 → apify-3.0.4b1}/tests/integration/actor_source_base/src/__main__.py +0 -0
  173. {apify-3.0.3b1 → apify-3.0.4b1}/tests/integration/actor_source_base/src/main.py +0 -0
  174. {apify-3.0.3b1 → apify-3.0.4b1}/tests/integration/conftest.py +0 -0
  175. {apify-3.0.3b1 → apify-3.0.4b1}/tests/integration/test_actor_api_helpers.py +0 -0
  176. {apify-3.0.3b1 → apify-3.0.4b1}/tests/integration/test_actor_call_timeouts.py +0 -0
  177. {apify-3.0.3b1 → apify-3.0.4b1}/tests/integration/test_actor_charge.py +0 -0
  178. {apify-3.0.3b1 → apify-3.0.4b1}/tests/integration/test_actor_create_proxy_configuration.py +0 -0
  179. {apify-3.0.3b1 → apify-3.0.4b1}/tests/integration/test_actor_dataset.py +0 -0
  180. {apify-3.0.3b1 → apify-3.0.4b1}/tests/integration/test_actor_events.py +0 -0
  181. {apify-3.0.3b1 → apify-3.0.4b1}/tests/integration/test_actor_key_value_store.py +0 -0
  182. {apify-3.0.3b1 → apify-3.0.4b1}/tests/integration/test_actor_lifecycle.py +0 -0
  183. {apify-3.0.3b1 → apify-3.0.4b1}/tests/integration/test_actor_log.py +0 -0
  184. {apify-3.0.3b1 → apify-3.0.4b1}/tests/integration/test_actor_request_queue.py +0 -0
  185. {apify-3.0.3b1 → apify-3.0.4b1}/tests/integration/test_actor_scrapy.py +0 -0
  186. {apify-3.0.3b1 → apify-3.0.4b1}/tests/integration/test_apify_storages.py +0 -0
  187. {apify-3.0.3b1 → apify-3.0.4b1}/tests/integration/test_crawlers_with_storages.py +0 -0
  188. {apify-3.0.3b1 → apify-3.0.4b1}/tests/integration/test_fixtures.py +0 -0
  189. {apify-3.0.3b1 → apify-3.0.4b1}/tests/integration/test_request_queue.py +0 -0
  190. {apify-3.0.3b1 → apify-3.0.4b1}/tests/unit/__init__.py +0 -0
  191. {apify-3.0.3b1 → apify-3.0.4b1}/tests/unit/actor/__init__.py +0 -0
  192. {apify-3.0.3b1 → apify-3.0.4b1}/tests/unit/actor/test_actor_create_proxy_configuration.py +0 -0
  193. {apify-3.0.3b1 → apify-3.0.4b1}/tests/unit/actor/test_actor_dataset.py +0 -0
  194. {apify-3.0.3b1 → apify-3.0.4b1}/tests/unit/actor/test_actor_env_helpers.py +0 -0
  195. {apify-3.0.3b1 → apify-3.0.4b1}/tests/unit/actor/test_actor_helpers.py +0 -0
  196. {apify-3.0.3b1 → apify-3.0.4b1}/tests/unit/actor/test_actor_key_value_store.py +0 -0
  197. {apify-3.0.3b1 → apify-3.0.4b1}/tests/unit/actor/test_actor_lifecycle.py +0 -0
  198. {apify-3.0.3b1 → apify-3.0.4b1}/tests/unit/actor/test_actor_log.py +0 -0
  199. {apify-3.0.3b1 → apify-3.0.4b1}/tests/unit/actor/test_actor_non_default_instance.py +0 -0
  200. {apify-3.0.3b1 → apify-3.0.4b1}/tests/unit/actor/test_actor_request_queue.py +0 -0
  201. {apify-3.0.3b1 → apify-3.0.4b1}/tests/unit/actor/test_configuration.py +0 -0
  202. {apify-3.0.3b1 → apify-3.0.4b1}/tests/unit/actor/test_request_list.py +0 -0
  203. {apify-3.0.3b1 → apify-3.0.4b1}/tests/unit/conftest.py +0 -0
  204. {apify-3.0.3b1 → apify-3.0.4b1}/tests/unit/events/__init__.py +0 -0
  205. {apify-3.0.3b1 → apify-3.0.4b1}/tests/unit/events/test_apify_event_manager.py +0 -0
  206. {apify-3.0.3b1 → apify-3.0.4b1}/tests/unit/scrapy/__init__.py +0 -0
  207. {apify-3.0.3b1 → apify-3.0.4b1}/tests/unit/scrapy/extensions/__init__.py +0 -0
  208. {apify-3.0.3b1 → apify-3.0.4b1}/tests/unit/scrapy/extensions/test_httpcache.py +0 -0
  209. {apify-3.0.3b1 → apify-3.0.4b1}/tests/unit/scrapy/middlewares/__init__.py +0 -0
  210. {apify-3.0.3b1 → apify-3.0.4b1}/tests/unit/scrapy/middlewares/test_apify_proxy.py +0 -0
  211. {apify-3.0.3b1 → apify-3.0.4b1}/tests/unit/scrapy/pipelines/__init__.py +0 -0
  212. {apify-3.0.3b1 → apify-3.0.4b1}/tests/unit/scrapy/pipelines/test_actor_dataset_push.py +0 -0
  213. {apify-3.0.3b1 → apify-3.0.4b1}/tests/unit/scrapy/requests/__init__.py +0 -0
  214. {apify-3.0.3b1 → apify-3.0.4b1}/tests/unit/scrapy/requests/test_to_apify_request.py +0 -0
  215. {apify-3.0.3b1 → apify-3.0.4b1}/tests/unit/scrapy/requests/test_to_scrapy_request.py +0 -0
  216. {apify-3.0.3b1 → apify-3.0.4b1}/tests/unit/scrapy/utils/__init__.py +0 -0
  217. {apify-3.0.3b1 → apify-3.0.4b1}/tests/unit/scrapy/utils/test_apply_apify_settings.py +0 -0
  218. {apify-3.0.3b1 → apify-3.0.4b1}/tests/unit/scrapy/utils/test_get_basic_auth_header.py +0 -0
  219. {apify-3.0.3b1 → apify-3.0.4b1}/tests/unit/storage_clients/__init__.py +0 -0
  220. {apify-3.0.3b1 → apify-3.0.4b1}/tests/unit/storage_clients/test_apify_request_queue_client.py +0 -0
  221. {apify-3.0.3b1 → apify-3.0.4b1}/tests/unit/storage_clients/test_file_system.py +0 -0
  222. {apify-3.0.3b1 → apify-3.0.4b1}/tests/unit/test_apify_storages.py +0 -0
  223. {apify-3.0.3b1 → apify-3.0.4b1}/tests/unit/test_crypto.py +0 -0
  224. {apify-3.0.3b1 → apify-3.0.4b1}/tests/unit/test_proxy_configuration.py +0 -0
  225. {apify-3.0.3b1 → apify-3.0.4b1}/website/.eslintrc.json +0 -0
  226. {apify-3.0.3b1 → apify-3.0.4b1}/website/babel.config.js +0 -0
  227. {apify-3.0.3b1 → apify-3.0.4b1}/website/build_api_reference.sh +0 -0
  228. {apify-3.0.3b1 → apify-3.0.4b1}/website/generate_module_shortcuts.py +0 -0
  229. {apify-3.0.3b1 → apify-3.0.4b1}/website/package.json +0 -0
  230. {apify-3.0.3b1 → apify-3.0.4b1}/website/sidebars.js +0 -0
  231. {apify-3.0.3b1 → apify-3.0.4b1}/website/src/components/ApiLink.jsx +0 -0
  232. {apify-3.0.3b1 → apify-3.0.4b1}/website/src/components/Gradients.jsx +0 -0
  233. {apify-3.0.3b1 → apify-3.0.4b1}/website/src/components/Highlights.jsx +0 -0
  234. {apify-3.0.3b1 → apify-3.0.4b1}/website/src/components/Highlights.module.css +0 -0
  235. {apify-3.0.3b1 → apify-3.0.4b1}/website/src/components/RunnableCodeBlock.jsx +0 -0
  236. {apify-3.0.3b1 → apify-3.0.4b1}/website/src/components/RunnableCodeBlock.module.css +0 -0
  237. {apify-3.0.3b1 → apify-3.0.4b1}/website/src/css/custom.css +0 -0
  238. {apify-3.0.3b1 → apify-3.0.4b1}/website/src/pages/home_page_example.py +0 -0
  239. {apify-3.0.3b1 → apify-3.0.4b1}/website/src/pages/index.js +0 -0
  240. {apify-3.0.3b1 → apify-3.0.4b1}/website/src/pages/index.module.css +0 -0
  241. {apify-3.0.3b1 → apify-3.0.4b1}/website/src/theme/DocItem/Content/index.js +0 -0
  242. {apify-3.0.3b1 → apify-3.0.4b1}/website/static/.nojekyll +0 -0
  243. {apify-3.0.3b1 → apify-3.0.4b1}/website/static/img/docs-og.png +0 -0
  244. {apify-3.0.3b1 → apify-3.0.4b1}/website/static/img/guides/redirected_logs_example.webp +0 -0
  245. {apify-3.0.3b1 → apify-3.0.4b1}/website/tools/docs-prettier.config.js +0 -0
  246. {apify-3.0.3b1 → apify-3.0.4b1}/website/tools/utils/externalLink.js +0 -0
@@ -3,14 +3,21 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
5
  <!-- git-cliff-unreleased-start -->
6
- ## 3.0.3 - **not yet released**
6
+ ## 3.0.4 - **not yet released**
7
7
 
8
8
  ### 🐛 Bug Fixes
9
9
 
10
- - Cache requests in RQ implementations by `id` ([#633](https://github.com/apify/apify-sdk-python/pull/633)) ([76886ce](https://github.com/apify/apify-sdk-python/commit/76886ce496165346a01f67e018547287c211ea54)) by [@Pijukatel](https://github.com/Pijukatel), closes [#630](https://github.com/apify/apify-sdk-python/issues/630)
10
+ - Fix type of `cloud_storage_client` in `SmartApifyStorageClient` ([#642](https://github.com/apify/apify-sdk-python/pull/642)) ([3bf285d](https://github.com/apify/apify-sdk-python/commit/3bf285d60f507730954986a80c19ed2e27a38f9c)) by [@vdusek](https://github.com/vdusek)
11
11
 
12
12
 
13
13
  <!-- git-cliff-unreleased-end -->
14
+ ## [3.0.3](https://github.com/apify/apify-sdk-python/releases/tag/v3.0.3) (2025-10-21)
15
+
16
+ ### 🐛 Bug Fixes
17
+
18
+ - Cache requests in RQ implementations by `id` ([#633](https://github.com/apify/apify-sdk-python/pull/633)) ([76886ce](https://github.com/apify/apify-sdk-python/commit/76886ce496165346a01f67e018547287c211ea54)) by [@Pijukatel](https://github.com/Pijukatel), closes [#630](https://github.com/apify/apify-sdk-python/issues/630)
19
+
20
+
14
21
  ## [3.0.2](https://github.com/apify/apify-sdk-python/releases/tag/v3.0.2) (2025-10-17)
15
22
 
16
23
  ### 🐛 Bug Fixes
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: apify
3
- Version: 3.0.3b1
3
+ Version: 3.0.4b1
4
4
  Summary: Apify SDK for Python
5
5
  Project-URL: Apify Homepage, https://apify.com
6
6
  Project-URL: Changelog, https://docs.apify.com/sdk/python/docs/changelog
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "apify"
7
- version = "3.0.3b1"
7
+ version = "3.0.4b1"
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" }
@@ -48,7 +48,6 @@ if TYPE_CHECKING:
48
48
  from typing_extensions import Self
49
49
 
50
50
  from crawlee.proxy_configuration import _NewUrlFunction
51
- from crawlee.storage_clients import StorageClient
52
51
 
53
52
  from apify._models import Webhook
54
53
 
@@ -140,7 +139,6 @@ class _ActorType:
140
139
  # `__init__` method should not be considered final.
141
140
 
142
141
  self._apify_client: ApifyClientAsync | None = None
143
- self._local_storage_client: StorageClient | None = None
144
142
 
145
143
  self._is_exiting = False
146
144
  self._is_initialized = False
@@ -120,7 +120,7 @@ class RequestQueueStats(BaseModel):
120
120
  """The number of request queue reads."""
121
121
 
122
122
  storage_bytes: Annotated[int, Field(alias='storageBytes', default=0)]
123
- """Storage size in Bytes."""
123
+ """Storage size in bytes."""
124
124
 
125
125
  write_count: Annotated[int, Field(alias='writeCount', default=0)]
126
126
  """The number of request queue writes."""
@@ -0,0 +1,132 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING, Literal
4
+
5
+ from typing_extensions import override
6
+
7
+ from crawlee.storage_clients._base import StorageClient
8
+
9
+ from ._dataset_client import ApifyDatasetClient
10
+ from ._key_value_store_client import ApifyKeyValueStoreClient
11
+ from ._request_queue_client import ApifyRequestQueueClient
12
+ from ._utils import hash_api_base_url_and_token
13
+ from apify._configuration import Configuration as ApifyConfiguration
14
+ from apify._utils import docs_group
15
+
16
+ if TYPE_CHECKING:
17
+ from collections.abc import Hashable
18
+
19
+ from crawlee.configuration import Configuration as CrawleeConfiguration
20
+
21
+
22
+ @docs_group('Storage clients')
23
+ class ApifyStorageClient(StorageClient):
24
+ """Apify platform implementation of the storage client.
25
+
26
+ This storage client provides access to datasets, key-value stores, and request queues that persist data
27
+ to the Apify platform. Each storage type is implemented with its own specific Apify client that stores data
28
+ in the cloud, making it accessible from anywhere.
29
+
30
+ The communication with the Apify platform is handled via the Apify API client for Python, which is an HTTP API
31
+ wrapper. For maximum efficiency and performance of the storage clients, various caching mechanisms are used to
32
+ minimize the number of API calls made to the Apify platform. Data can be inspected and manipulated through
33
+ the Apify console web interface or via the Apify API.
34
+
35
+ The request queue client supports two access modes controlled by the `request_queue_access` parameter:
36
+
37
+ ### Single mode
38
+
39
+ The `single` mode is optimized for scenarios with only one consumer. It minimizes API calls, making it faster
40
+ and more cost-efficient compared to the `shared` mode. This option is ideal when a single Actor is responsible
41
+ for consuming the entire request queue. Using multiple consumers simultaneously may lead to inconsistencies
42
+ or unexpected behavior.
43
+
44
+ In this mode, multiple producers can safely add new requests, but forefront requests may not be processed
45
+ immediately, as the client relies on local head estimation instead of frequent forefront fetching. Requests can
46
+ also be added or marked as handled by other clients, but they must not be deleted or modified, since such changes
47
+ would not be reflected in the local cache. If a request is already fully cached locally, marking it as handled
48
+ by another client will be ignored by this client. This does not cause errors but can occasionally result in
49
+ reprocessing a request that was already handled elsewhere. If the request was not yet cached locally, marking
50
+ it as handled poses no issue.
51
+
52
+ ### Shared mode
53
+
54
+ The `shared` mode is designed for scenarios with multiple concurrent consumers. It ensures proper synchronization
55
+ and consistency across clients, at the cost of higher API usage and slightly worse performance. This mode is safe
56
+ for concurrent access from multiple processes, including Actors running in parallel on the Apify platform. It
57
+ should be used when multiple consumers need to process requests from the same queue simultaneously.
58
+ """
59
+
60
+ _LSP_ERROR_MSG = 'Expected "configuration" to be an instance of "apify.Configuration", but got {} instead.'
61
+ """This class (intentionally) violates the Liskov Substitution Principle.
62
+
63
+ It requires a specialized `Configuration` instance compared to its parent class.
64
+ """
65
+
66
+ def __init__(self, *, request_queue_access: Literal['single', 'shared'] = 'single') -> None:
67
+ """Initialize a new instance.
68
+
69
+ Args:
70
+ request_queue_access: Defines how the request queue client behaves. Use `single` mode for a single
71
+ consumer. It has fewer API calls, meaning better performance and lower costs. If you need multiple
72
+ concurrent consumers use `shared` mode, but expect worse performance and higher costs due to
73
+ the additional overhead.
74
+ """
75
+ self._request_queue_access = request_queue_access
76
+
77
+ @override
78
+ async def create_dataset_client(
79
+ self,
80
+ *,
81
+ id: str | None = None,
82
+ name: str | None = None,
83
+ alias: str | None = None,
84
+ configuration: CrawleeConfiguration | None = None,
85
+ ) -> ApifyDatasetClient:
86
+ configuration = configuration or ApifyConfiguration.get_global_configuration()
87
+ if isinstance(configuration, ApifyConfiguration):
88
+ return await ApifyDatasetClient.open(id=id, name=name, alias=alias, configuration=configuration)
89
+
90
+ raise TypeError(self._LSP_ERROR_MSG.format(type(configuration).__name__))
91
+
92
+ @override
93
+ async def create_kvs_client(
94
+ self,
95
+ *,
96
+ id: str | None = None,
97
+ name: str | None = None,
98
+ alias: str | None = None,
99
+ configuration: CrawleeConfiguration | None = None,
100
+ ) -> ApifyKeyValueStoreClient:
101
+ configuration = configuration or ApifyConfiguration.get_global_configuration()
102
+ if isinstance(configuration, ApifyConfiguration):
103
+ return await ApifyKeyValueStoreClient.open(id=id, name=name, alias=alias, configuration=configuration)
104
+
105
+ raise TypeError(self._LSP_ERROR_MSG.format(type(configuration).__name__))
106
+
107
+ @override
108
+ async def create_rq_client(
109
+ self,
110
+ *,
111
+ id: str | None = None,
112
+ name: str | None = None,
113
+ alias: str | None = None,
114
+ configuration: CrawleeConfiguration | None = None,
115
+ ) -> ApifyRequestQueueClient:
116
+ configuration = configuration or ApifyConfiguration.get_global_configuration()
117
+ if isinstance(configuration, ApifyConfiguration):
118
+ return await ApifyRequestQueueClient.open(
119
+ id=id, name=name, alias=alias, configuration=configuration, access=self._request_queue_access
120
+ )
121
+
122
+ raise TypeError(self._LSP_ERROR_MSG.format(type(configuration).__name__))
123
+
124
+ @override
125
+ def get_storage_client_cache_key(self, configuration: CrawleeConfiguration) -> Hashable:
126
+ if isinstance(configuration, ApifyConfiguration):
127
+ # It is not supported to open exactly same queue with 'single' and 'shared' client at the same time.
128
+ # Whichever client variation gets used first, wins.
129
+ return super().get_storage_client_cache_key(configuration), hash_api_base_url_and_token(configuration)
130
+
131
+ config_class = type(configuration)
132
+ raise TypeError(self._LSP_ERROR_MSG.format(f'{config_class.__module__}.{config_class.__name__}'))
@@ -8,8 +8,7 @@ from crawlee.storage_clients._base import DatasetClient, KeyValueStoreClient, Re
8
8
 
9
9
  from apify._configuration import Configuration as ApifyConfiguration
10
10
  from apify._utils import docs_group
11
- from apify.storage_clients import ApifyStorageClient
12
- from apify.storage_clients._file_system import ApifyFileSystemStorageClient
11
+ from apify.storage_clients import ApifyStorageClient, FileSystemStorageClient
13
12
 
14
13
  if TYPE_CHECKING:
15
14
  from collections.abc import Hashable
@@ -19,28 +18,36 @@ if TYPE_CHECKING:
19
18
 
20
19
  @docs_group('Storage clients')
21
20
  class SmartApifyStorageClient(StorageClient):
22
- """SmartApifyStorageClient that delegates to cloud_storage_client or local_storage_client.
21
+ """Storage client that automatically selects cloud or local storage client based on the environment.
23
22
 
24
- When running on Apify platform use cloud_storage_client, else use local_storage_client. This storage client is
25
- designed to work specifically in Actor context.
23
+ This storage client provides access to datasets, key-value stores, and request queues by intelligently
24
+ delegating to either the cloud or local storage client based on the execution environment and configuration.
25
+
26
+ When running on the Apify platform (which is detected via environment variables), this client automatically
27
+ uses the `cloud_storage_client` to store storage data there. When running locally, it uses the
28
+ `local_storage_client` to store storage data there. You can also force cloud storage usage from your
29
+ local machine by using the `force_cloud` argument.
30
+
31
+ This storage client is designed to work specifically in `Actor` context and provides a seamless development
32
+ experience where the same code works both locally and on the Apify platform without any changes.
26
33
  """
27
34
 
28
35
  def __init__(
29
36
  self,
30
37
  *,
31
- cloud_storage_client: ApifyStorageClient | None = None,
38
+ cloud_storage_client: StorageClient | None = None,
32
39
  local_storage_client: StorageClient | None = None,
33
40
  ) -> None:
34
- """Initialize the Apify storage client.
41
+ """Initialize a new instance.
35
42
 
36
43
  Args:
37
- cloud_storage_client: Client used to communicate with the Apify platform storage. Either through
38
- `force_cloud` argument when opening storages or automatically when running on the Apify platform.
39
- local_storage_client: Client used to communicate with the storage when not running on the Apify
40
- platform and not using `force_cloud` argument when opening storages.
44
+ cloud_storage_client: Storage client used when an Actor is running on the Apify platform, or when
45
+ explicitly enabled via the `force_cloud` argument. Defaults to `ApifyStorageClient`.
46
+ local_storage_client: Storage client used when an Actor is not running on the Apify platform and when
47
+ `force_cloud` flag is not set. Defaults to `FileSystemStorageClient`.
41
48
  """
42
- self._cloud_storage_client = cloud_storage_client or ApifyStorageClient(request_queue_access='single')
43
- self._local_storage_client = local_storage_client or ApifyFileSystemStorageClient()
49
+ self._cloud_storage_client = cloud_storage_client or ApifyStorageClient()
50
+ self._local_storage_client = local_storage_client or FileSystemStorageClient()
44
51
 
45
52
  def __str__(self) -> str:
46
53
  return (
@@ -48,26 +55,6 @@ class SmartApifyStorageClient(StorageClient):
48
55
  f' local_storage_client={self._local_storage_client.__class__.__name__})'
49
56
  )
50
57
 
51
- def get_suitable_storage_client(self, *, force_cloud: bool = False) -> StorageClient:
52
- """Get a suitable storage client based on the global configuration and the value of the force_cloud flag.
53
-
54
- Args:
55
- force_cloud: If True, return `cloud_storage_client`.
56
- """
57
- if ApifyConfiguration.get_global_configuration().is_at_home:
58
- return self._cloud_storage_client
59
-
60
- configuration = ApifyConfiguration.get_global_configuration()
61
- if force_cloud:
62
- if configuration.token is None:
63
- raise RuntimeError(
64
- 'In order to use the Apify cloud storage from your computer, '
65
- 'you need to provide an Apify token using the APIFY_TOKEN environment variable.'
66
- )
67
- return self._cloud_storage_client
68
-
69
- return self._local_storage_client
70
-
71
58
  @override
72
59
  def get_storage_client_cache_key(self, configuration: CrawleeConfiguration) -> Hashable:
73
60
  if ApifyConfiguration.get_global_configuration().is_at_home:
@@ -115,3 +102,23 @@ class SmartApifyStorageClient(StorageClient):
115
102
  return await self.get_suitable_storage_client().create_rq_client(
116
103
  id=id, name=id, alias=alias, configuration=configuration
117
104
  )
105
+
106
+ def get_suitable_storage_client(self, *, force_cloud: bool = False) -> StorageClient:
107
+ """Get a suitable storage client based on the global configuration and the value of the force_cloud flag.
108
+
109
+ Args:
110
+ force_cloud: If True, return `cloud_storage_client`.
111
+ """
112
+ if ApifyConfiguration.get_global_configuration().is_at_home:
113
+ return self._cloud_storage_client
114
+
115
+ configuration = ApifyConfiguration.get_global_configuration()
116
+ if force_cloud:
117
+ if configuration.token is None:
118
+ raise RuntimeError(
119
+ 'In order to use the Apify cloud storage from your computer, '
120
+ 'you need to provide an Apify token using the APIFY_TOKEN environment variable.'
121
+ )
122
+ return self._cloud_storage_client
123
+
124
+ return self._local_storage_client
@@ -28,7 +28,7 @@ wheels = [
28
28
 
29
29
  [[package]]
30
30
  name = "apify"
31
- version = "3.0.3b1"
31
+ version = "3.0.4b1"
32
32
  source = { editable = "." }
33
33
  dependencies = [
34
34
  { name = "apify-client" },
@@ -239,6 +239,10 @@ module.exports = {
239
239
  url: 'https://crawlee.dev/python/api/class/FileSystemStorageClient',
240
240
  group: 'Storage clients',
241
241
  },
242
+ {
243
+ url: 'https://crawlee.dev/python/api/class/SqlStorageClient',
244
+ group: 'Storage clients',
245
+ },
242
246
  // Request loaders
243
247
  {
244
248
  url: 'https://crawlee.dev/python/api/class/RequestLoader',
@@ -1671,9 +1671,9 @@
1671
1671
  }
1672
1672
  },
1673
1673
  "node_modules/@apify/docs-theme": {
1674
- "version": "1.0.218",
1675
- "resolved": "https://registry.npmjs.org/@apify/docs-theme/-/docs-theme-1.0.218.tgz",
1676
- "integrity": "sha512-2kAF+2CZmwGgK8Pq3SRk5cB2knZ5GLuNTW0sH1UohK4oFCtFFjh0HYyqeedRcf2Pk2mQSVgac4GNMB9E7+yBTQ==",
1674
+ "version": "1.0.221",
1675
+ "resolved": "https://registry.npmjs.org/@apify/docs-theme/-/docs-theme-1.0.221.tgz",
1676
+ "integrity": "sha512-bZBjMCnqPg04gf+ZfQaiRNXZGgnLKvsx5UvvDYWJdLu1O5otPtAZMrMDTprwaQ7ofhb+tk9CUgZCpuZZF0e5dg==",
1677
1677
  "license": "ISC",
1678
1678
  "dependencies": {
1679
1679
  "@apify/docs-search-modal": "^1.3.3",
@@ -1,106 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from typing import TYPE_CHECKING, Literal
4
-
5
- from typing_extensions import override
6
-
7
- from crawlee.storage_clients._base import StorageClient
8
-
9
- from ._dataset_client import ApifyDatasetClient
10
- from ._key_value_store_client import ApifyKeyValueStoreClient
11
- from ._request_queue_client import ApifyRequestQueueClient
12
- from ._utils import hash_api_base_url_and_token
13
- from apify._configuration import Configuration as ApifyConfiguration
14
- from apify._utils import docs_group
15
-
16
- if TYPE_CHECKING:
17
- from collections.abc import Hashable
18
-
19
- from crawlee.configuration import Configuration as CrawleeConfiguration
20
-
21
-
22
- @docs_group('Storage clients')
23
- class ApifyStorageClient(StorageClient):
24
- """Apify storage client."""
25
-
26
- def __init__(self, *, request_queue_access: Literal['single', 'shared'] = 'single') -> None:
27
- """Initialize the Apify storage client.
28
-
29
- Args:
30
- request_queue_access: Controls the implementation of the request queue client based on expected scenario:
31
- - 'single' is suitable for single consumer scenarios. It makes less API calls, is cheaper and faster.
32
- - 'shared' is suitable for multiple consumers scenarios at the cost of higher API usage.
33
- Detailed constraints for the 'single' access type:
34
- - Only one client is consuming the request queue at the time.
35
- - Multiple producers can put requests to the queue, but their forefront requests are not guaranteed to
36
- be handled so quickly as this client does not aggressively fetch the forefront and relies on local
37
- head estimation.
38
- - Requests are only added to the queue, never deleted by other clients. (Marking as handled is ok.)
39
- - Other producers can add new requests, but not modify existing ones.
40
- (Modifications would not be included in local cache)
41
- """
42
- self._request_queue_access = request_queue_access
43
-
44
- # This class breaches Liskov Substitution Principle. It requires specialized Configuration compared to its parent.
45
- _lsp_violation_error_message_template = (
46
- 'Expected "configuration" to be an instance of "apify.Configuration", but got {} instead.'
47
- )
48
-
49
- @override
50
- def get_storage_client_cache_key(self, configuration: CrawleeConfiguration) -> Hashable:
51
- if isinstance(configuration, ApifyConfiguration):
52
- # It is not supported to open exactly same queue with 'single' and 'shared' client at the same time.
53
- # Whichever client variation gets used first, wins.
54
- return super().get_storage_client_cache_key(configuration), hash_api_base_url_and_token(configuration)
55
-
56
- config_class = type(configuration)
57
- raise TypeError(
58
- self._lsp_violation_error_message_template.format(f'{config_class.__module__}.{config_class.__name__}')
59
- )
60
-
61
- @override
62
- async def create_dataset_client(
63
- self,
64
- *,
65
- id: str | None = None,
66
- name: str | None = None,
67
- alias: str | None = None,
68
- configuration: CrawleeConfiguration | None = None,
69
- ) -> ApifyDatasetClient:
70
- configuration = configuration or ApifyConfiguration.get_global_configuration()
71
- if isinstance(configuration, ApifyConfiguration):
72
- return await ApifyDatasetClient.open(id=id, name=name, alias=alias, configuration=configuration)
73
-
74
- raise TypeError(self._lsp_violation_error_message_template.format(type(configuration).__name__))
75
-
76
- @override
77
- async def create_kvs_client(
78
- self,
79
- *,
80
- id: str | None = None,
81
- name: str | None = None,
82
- alias: str | None = None,
83
- configuration: CrawleeConfiguration | None = None,
84
- ) -> ApifyKeyValueStoreClient:
85
- configuration = configuration or ApifyConfiguration.get_global_configuration()
86
- if isinstance(configuration, ApifyConfiguration):
87
- return await ApifyKeyValueStoreClient.open(id=id, name=name, alias=alias, configuration=configuration)
88
-
89
- raise TypeError(self._lsp_violation_error_message_template.format(type(configuration).__name__))
90
-
91
- @override
92
- async def create_rq_client(
93
- self,
94
- *,
95
- id: str | None = None,
96
- name: str | None = None,
97
- alias: str | None = None,
98
- configuration: CrawleeConfiguration | None = None,
99
- ) -> ApifyRequestQueueClient:
100
- configuration = configuration or ApifyConfiguration.get_global_configuration()
101
- if isinstance(configuration, ApifyConfiguration):
102
- return await ApifyRequestQueueClient.open(
103
- id=id, name=name, alias=alias, configuration=configuration, access=self._request_queue_access
104
- )
105
-
106
- raise TypeError(self._lsp_violation_error_message_template.format(type(configuration).__name__))
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes