apify 3.0.2b7__tar.gz → 3.0.4__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 (252) hide show
  1. {apify-3.0.2b7 → apify-3.0.4}/CHANGELOG.md +20 -3
  2. {apify-3.0.2b7 → apify-3.0.4}/PKG-INFO +3 -3
  3. {apify-3.0.2b7 → apify-3.0.4}/docs/02_concepts/12_pay_per_event.mdx +1 -1
  4. {apify-3.0.2b7 → apify-3.0.4}/pyproject.toml +3 -3
  5. {apify-3.0.2b7 → apify-3.0.4}/src/apify/_actor.py +1 -9
  6. {apify-3.0.2b7 → apify-3.0.4}/src/apify/_charging.py +89 -37
  7. {apify-3.0.2b7 → apify-3.0.4}/src/apify/_configuration.py +30 -0
  8. {apify-3.0.2b7 → apify-3.0.4}/src/apify/request_loaders/_apify_request_list.py +2 -2
  9. {apify-3.0.2b7 → apify-3.0.4}/src/apify/storage_clients/_apify/_dataset_client.py +12 -29
  10. {apify-3.0.2b7 → apify-3.0.4}/src/apify/storage_clients/_apify/_key_value_store_client.py +13 -43
  11. {apify-3.0.2b7 → apify-3.0.4}/src/apify/storage_clients/_apify/_models.py +3 -3
  12. {apify-3.0.2b7 → apify-3.0.4}/src/apify/storage_clients/_apify/_request_queue_client.py +2 -25
  13. {apify-3.0.2b7 → apify-3.0.4}/src/apify/storage_clients/_apify/_request_queue_shared_client.py +45 -35
  14. {apify-3.0.2b7 → apify-3.0.4}/src/apify/storage_clients/_apify/_request_queue_single_client.py +73 -64
  15. apify-3.0.4/src/apify/storage_clients/_apify/_storage_client.py +132 -0
  16. {apify-3.0.2b7 → apify-3.0.4}/src/apify/storage_clients/_apify/_utils.py +27 -0
  17. {apify-3.0.2b7 → apify-3.0.4}/src/apify/storage_clients/_smart_apify/_storage_client.py +40 -33
  18. {apify-3.0.2b7 → apify-3.0.4}/tests/integration/README.md +20 -9
  19. {apify-3.0.2b7/tests/integration → apify-3.0.4/tests/integration/actor}/conftest.py +8 -103
  20. {apify-3.0.2b7/tests/integration → apify-3.0.4/tests/integration/actor}/test_actor_api_helpers.py +1 -1
  21. {apify-3.0.2b7/tests/integration → apify-3.0.4/tests/integration/actor}/test_actor_dataset.py +1 -1
  22. {apify-3.0.2b7/tests/integration → apify-3.0.4/tests/integration/actor}/test_actor_key_value_store.py +1 -1
  23. {apify-3.0.2b7/tests/integration → apify-3.0.4/tests/integration/actor}/test_actor_lifecycle.py +4 -2
  24. {apify-3.0.2b7/tests/integration → apify-3.0.4/tests/integration/actor}/test_actor_log.py +8 -10
  25. {apify-3.0.2b7/tests/integration → apify-3.0.4/tests/integration/actor}/test_actor_request_queue.py +156 -118
  26. apify-3.0.4/tests/integration/actor/test_apify_storages.py +28 -0
  27. apify-3.0.4/tests/integration/apify_api/conftest.py +70 -0
  28. {apify-3.0.2b7/tests/integration → apify-3.0.4/tests/integration/apify_api}/test_apify_storages.py +0 -27
  29. {apify-3.0.2b7/tests/integration → apify-3.0.4/tests/integration/apify_api}/test_request_queue.py +135 -161
  30. apify-3.0.4/tests/integration/conftest.py +28 -0
  31. {apify-3.0.2b7 → apify-3.0.4}/tests/unit/actor/test_actor_env_helpers.py +1 -1
  32. apify-3.0.4/tests/unit/actor/test_actor_log.py +107 -0
  33. apify-3.0.4/tests/unit/storage_clients/__init__.py +0 -0
  34. {apify-3.0.2b7 → apify-3.0.4}/uv.lock +605 -521
  35. {apify-3.0.2b7 → apify-3.0.4}/website/docusaurus.config.js +4 -0
  36. {apify-3.0.2b7 → apify-3.0.4}/website/package-lock.json +712 -711
  37. {apify-3.0.2b7 → apify-3.0.4}/website/src/pages/index.js +1 -1
  38. apify-3.0.4/website/static/.nojekyll +0 -0
  39. apify-3.0.2b7/src/apify/storage_clients/_apify/_storage_client.py +0 -106
  40. apify-3.0.2b7/tests/unit/actor/test_actor_log.py +0 -112
  41. {apify-3.0.2b7 → apify-3.0.4}/.editorconfig +0 -0
  42. {apify-3.0.2b7 → apify-3.0.4}/.github/CODEOWNERS +0 -0
  43. {apify-3.0.2b7 → apify-3.0.4}/.github/workflows/build_and_deploy_docs.yaml +0 -0
  44. {apify-3.0.2b7 → apify-3.0.4}/.github/workflows/check_pr_title.yaml +0 -0
  45. {apify-3.0.2b7 → apify-3.0.4}/.github/workflows/pre_release.yaml +0 -0
  46. {apify-3.0.2b7 → apify-3.0.4}/.github/workflows/release.yaml +0 -0
  47. {apify-3.0.2b7 → apify-3.0.4}/.github/workflows/run_code_checks.yaml +0 -0
  48. {apify-3.0.2b7 → apify-3.0.4}/.github/workflows/update_new_issue.yaml +0 -0
  49. {apify-3.0.2b7 → apify-3.0.4}/.gitignore +0 -0
  50. {apify-3.0.2b7 → apify-3.0.4}/.markdownlint.yaml +0 -0
  51. {apify-3.0.2b7 → apify-3.0.4}/.pre-commit-config.yaml +0 -0
  52. {apify-3.0.2b7 → apify-3.0.4}/CONTRIBUTING.md +0 -0
  53. {apify-3.0.2b7 → apify-3.0.4}/LICENSE +0 -0
  54. {apify-3.0.2b7 → apify-3.0.4}/Makefile +0 -0
  55. {apify-3.0.2b7 → apify-3.0.4}/README.md +0 -0
  56. {apify-3.0.2b7 → apify-3.0.4}/docs/01_overview/01_introduction.mdx +0 -0
  57. {apify-3.0.2b7 → apify-3.0.4}/docs/01_overview/02_running_actors_locally.mdx +0 -0
  58. {apify-3.0.2b7 → apify-3.0.4}/docs/01_overview/03_actor_structure.mdx +0 -0
  59. {apify-3.0.2b7 → apify-3.0.4}/docs/01_overview/code/01_introduction.py +0 -0
  60. {apify-3.0.2b7 → apify-3.0.4}/docs/01_overview/code/actor_structure/__init__.py +0 -0
  61. {apify-3.0.2b7 → apify-3.0.4}/docs/01_overview/code/actor_structure/__main__.py +0 -0
  62. {apify-3.0.2b7 → apify-3.0.4}/docs/01_overview/code/actor_structure/main.py +0 -0
  63. {apify-3.0.2b7 → apify-3.0.4}/docs/01_overview/code/actor_structure/py.typed +0 -0
  64. {apify-3.0.2b7 → apify-3.0.4}/docs/02_concepts/01_actor_lifecycle.mdx +0 -0
  65. {apify-3.0.2b7 → apify-3.0.4}/docs/02_concepts/02_actor_input.mdx +0 -0
  66. {apify-3.0.2b7 → apify-3.0.4}/docs/02_concepts/03_storages.mdx +0 -0
  67. {apify-3.0.2b7 → apify-3.0.4}/docs/02_concepts/04_actor_events.mdx +0 -0
  68. {apify-3.0.2b7 → apify-3.0.4}/docs/02_concepts/05_proxy_management.mdx +0 -0
  69. {apify-3.0.2b7 → apify-3.0.4}/docs/02_concepts/06_interacting_with_other_actors.mdx +0 -0
  70. {apify-3.0.2b7 → apify-3.0.4}/docs/02_concepts/07_webhooks.mdx +0 -0
  71. {apify-3.0.2b7 → apify-3.0.4}/docs/02_concepts/08_access_apify_api.mdx +0 -0
  72. {apify-3.0.2b7 → apify-3.0.4}/docs/02_concepts/09_running_webserver.mdx +0 -0
  73. {apify-3.0.2b7 → apify-3.0.4}/docs/02_concepts/10_logging.mdx +0 -0
  74. {apify-3.0.2b7 → apify-3.0.4}/docs/02_concepts/11_configuration.mdx +0 -0
  75. {apify-3.0.2b7 → apify-3.0.4}/docs/02_concepts/code/01_class_context.py +0 -0
  76. {apify-3.0.2b7 → apify-3.0.4}/docs/02_concepts/code/01_class_manual.py +0 -0
  77. {apify-3.0.2b7 → apify-3.0.4}/docs/02_concepts/code/01_context_manager.py +0 -0
  78. {apify-3.0.2b7 → apify-3.0.4}/docs/02_concepts/code/01_error_handling_context.py +0 -0
  79. {apify-3.0.2b7 → apify-3.0.4}/docs/02_concepts/code/01_error_handling_manual.py +0 -0
  80. {apify-3.0.2b7 → apify-3.0.4}/docs/02_concepts/code/01_init_exit.py +0 -0
  81. {apify-3.0.2b7 → apify-3.0.4}/docs/02_concepts/code/01_instance_context.py +0 -0
  82. {apify-3.0.2b7 → apify-3.0.4}/docs/02_concepts/code/01_instance_manual.py +0 -0
  83. {apify-3.0.2b7 → apify-3.0.4}/docs/02_concepts/code/01_reboot.py +0 -0
  84. {apify-3.0.2b7 → apify-3.0.4}/docs/02_concepts/code/01_status_message.py +0 -0
  85. {apify-3.0.2b7 → apify-3.0.4}/docs/02_concepts/code/02_input.py +0 -0
  86. {apify-3.0.2b7 → apify-3.0.4}/docs/02_concepts/code/03_dataset_exports.py +0 -0
  87. {apify-3.0.2b7 → apify-3.0.4}/docs/02_concepts/code/03_dataset_read_write.py +0 -0
  88. {apify-3.0.2b7 → apify-3.0.4}/docs/02_concepts/code/03_deleting_storages.py +0 -0
  89. {apify-3.0.2b7 → apify-3.0.4}/docs/02_concepts/code/03_kvs_iterating.py +0 -0
  90. {apify-3.0.2b7 → apify-3.0.4}/docs/02_concepts/code/03_kvs_public_url.py +0 -0
  91. {apify-3.0.2b7 → apify-3.0.4}/docs/02_concepts/code/03_kvs_read_write.py +0 -0
  92. {apify-3.0.2b7 → apify-3.0.4}/docs/02_concepts/code/03_opening_storages.py +0 -0
  93. {apify-3.0.2b7 → apify-3.0.4}/docs/02_concepts/code/03_rq.py +0 -0
  94. {apify-3.0.2b7 → apify-3.0.4}/docs/02_concepts/code/04_actor_events.py +0 -0
  95. {apify-3.0.2b7 → apify-3.0.4}/docs/02_concepts/code/05_apify_proxy.py +0 -0
  96. {apify-3.0.2b7 → apify-3.0.4}/docs/02_concepts/code/05_apify_proxy_config.py +0 -0
  97. {apify-3.0.2b7 → apify-3.0.4}/docs/02_concepts/code/05_custom_proxy.py +0 -0
  98. {apify-3.0.2b7 → apify-3.0.4}/docs/02_concepts/code/05_custom_proxy_function.py +0 -0
  99. {apify-3.0.2b7 → apify-3.0.4}/docs/02_concepts/code/05_proxy_actor_input.py +0 -0
  100. {apify-3.0.2b7 → apify-3.0.4}/docs/02_concepts/code/05_proxy_httpx.py +0 -0
  101. {apify-3.0.2b7 → apify-3.0.4}/docs/02_concepts/code/05_proxy_rotation.py +0 -0
  102. {apify-3.0.2b7 → apify-3.0.4}/docs/02_concepts/code/06_interacting_call.py +0 -0
  103. {apify-3.0.2b7 → apify-3.0.4}/docs/02_concepts/code/06_interacting_call_task.py +0 -0
  104. {apify-3.0.2b7 → apify-3.0.4}/docs/02_concepts/code/06_interacting_metamorph.py +0 -0
  105. {apify-3.0.2b7 → apify-3.0.4}/docs/02_concepts/code/06_interacting_start.py +0 -0
  106. {apify-3.0.2b7 → apify-3.0.4}/docs/02_concepts/code/07_webhook.py +0 -0
  107. {apify-3.0.2b7 → apify-3.0.4}/docs/02_concepts/code/07_webhook_preventing.py +0 -0
  108. {apify-3.0.2b7 → apify-3.0.4}/docs/02_concepts/code/08_actor_client.py +0 -0
  109. {apify-3.0.2b7 → apify-3.0.4}/docs/02_concepts/code/08_actor_new_client.py +0 -0
  110. {apify-3.0.2b7 → apify-3.0.4}/docs/02_concepts/code/09_webserver.py +0 -0
  111. {apify-3.0.2b7 → apify-3.0.4}/docs/02_concepts/code/10_log_config.py +0 -0
  112. {apify-3.0.2b7 → apify-3.0.4}/docs/02_concepts/code/10_logger_usage.py +0 -0
  113. {apify-3.0.2b7 → apify-3.0.4}/docs/02_concepts/code/10_redirect_log.py +0 -0
  114. {apify-3.0.2b7 → apify-3.0.4}/docs/02_concepts/code/10_redirect_log_existing_run.py +0 -0
  115. {apify-3.0.2b7 → apify-3.0.4}/docs/02_concepts/code/11_config.py +0 -0
  116. {apify-3.0.2b7 → apify-3.0.4}/docs/02_concepts/code/actor_charge.py +0 -0
  117. {apify-3.0.2b7 → apify-3.0.4}/docs/02_concepts/code/conditional_actor_charge.py +0 -0
  118. {apify-3.0.2b7 → apify-3.0.4}/docs/03_guides/01_beautifulsoup_httpx.mdx +0 -0
  119. {apify-3.0.2b7 → apify-3.0.4}/docs/03_guides/02_parsel_impit.mdx +0 -0
  120. {apify-3.0.2b7 → apify-3.0.4}/docs/03_guides/03_playwright.mdx +0 -0
  121. {apify-3.0.2b7 → apify-3.0.4}/docs/03_guides/04_selenium.mdx +0 -0
  122. {apify-3.0.2b7 → apify-3.0.4}/docs/03_guides/05_crawlee.mdx +0 -0
  123. {apify-3.0.2b7 → apify-3.0.4}/docs/03_guides/06_scrapy.mdx +0 -0
  124. {apify-3.0.2b7 → apify-3.0.4}/docs/03_guides/code/01_beautifulsoup_httpx.py +0 -0
  125. {apify-3.0.2b7 → apify-3.0.4}/docs/03_guides/code/02_parsel_impit.py +0 -0
  126. {apify-3.0.2b7 → apify-3.0.4}/docs/03_guides/code/03_playwright.py +0 -0
  127. {apify-3.0.2b7 → apify-3.0.4}/docs/03_guides/code/04_selenium.py +0 -0
  128. {apify-3.0.2b7 → apify-3.0.4}/docs/03_guides/code/05_crawlee_beautifulsoup.py +0 -0
  129. {apify-3.0.2b7 → apify-3.0.4}/docs/03_guides/code/05_crawlee_parsel.py +0 -0
  130. {apify-3.0.2b7 → apify-3.0.4}/docs/03_guides/code/05_crawlee_playwright.py +0 -0
  131. {apify-3.0.2b7 → apify-3.0.4}/docs/03_guides/code/scrapy_project/src/__init__.py +0 -0
  132. {apify-3.0.2b7 → apify-3.0.4}/docs/03_guides/code/scrapy_project/src/__main__.py +0 -0
  133. {apify-3.0.2b7 → apify-3.0.4}/docs/03_guides/code/scrapy_project/src/items.py +0 -0
  134. {apify-3.0.2b7 → apify-3.0.4}/docs/03_guides/code/scrapy_project/src/main.py +0 -0
  135. {apify-3.0.2b7 → apify-3.0.4}/docs/03_guides/code/scrapy_project/src/py.typed +0 -0
  136. {apify-3.0.2b7 → apify-3.0.4}/docs/03_guides/code/scrapy_project/src/settings.py +0 -0
  137. {apify-3.0.2b7 → apify-3.0.4}/docs/03_guides/code/scrapy_project/src/spiders/__init__.py +0 -0
  138. {apify-3.0.2b7 → apify-3.0.4}/docs/03_guides/code/scrapy_project/src/spiders/py.typed +0 -0
  139. {apify-3.0.2b7 → apify-3.0.4}/docs/03_guides/code/scrapy_project/src/spiders/title.py +0 -0
  140. {apify-3.0.2b7 → apify-3.0.4}/docs/04_upgrading/upgrading_to_v2.md +0 -0
  141. {apify-3.0.2b7 → apify-3.0.4}/docs/04_upgrading/upgrading_to_v3.md +0 -0
  142. {apify-3.0.2b7 → apify-3.0.4}/docs/pyproject.toml +0 -0
  143. {apify-3.0.2b7 → apify-3.0.4}/renovate.json +0 -0
  144. {apify-3.0.2b7 → apify-3.0.4}/src/apify/__init__.py +0 -0
  145. {apify-3.0.2b7 → apify-3.0.4}/src/apify/_consts.py +0 -0
  146. {apify-3.0.2b7 → apify-3.0.4}/src/apify/_crypto.py +0 -0
  147. {apify-3.0.2b7 → apify-3.0.4}/src/apify/_models.py +0 -0
  148. {apify-3.0.2b7 → apify-3.0.4}/src/apify/_proxy_configuration.py +0 -0
  149. {apify-3.0.2b7 → apify-3.0.4}/src/apify/_utils.py +0 -0
  150. {apify-3.0.2b7 → apify-3.0.4}/src/apify/events/__init__.py +0 -0
  151. {apify-3.0.2b7 → apify-3.0.4}/src/apify/events/_apify_event_manager.py +0 -0
  152. {apify-3.0.2b7 → apify-3.0.4}/src/apify/events/_types.py +0 -0
  153. {apify-3.0.2b7 → apify-3.0.4}/src/apify/events/py.typed +0 -0
  154. {apify-3.0.2b7 → apify-3.0.4}/src/apify/log.py +0 -0
  155. {apify-3.0.2b7 → apify-3.0.4}/src/apify/py.typed +0 -0
  156. {apify-3.0.2b7 → apify-3.0.4}/src/apify/request_loaders/__init__.py +0 -0
  157. {apify-3.0.2b7 → apify-3.0.4}/src/apify/request_loaders/py.typed +0 -0
  158. {apify-3.0.2b7 → apify-3.0.4}/src/apify/scrapy/__init__.py +0 -0
  159. {apify-3.0.2b7 → apify-3.0.4}/src/apify/scrapy/_actor_runner.py +0 -0
  160. {apify-3.0.2b7 → apify-3.0.4}/src/apify/scrapy/_async_thread.py +0 -0
  161. {apify-3.0.2b7 → apify-3.0.4}/src/apify/scrapy/_logging_config.py +0 -0
  162. {apify-3.0.2b7 → apify-3.0.4}/src/apify/scrapy/extensions/__init__.py +0 -0
  163. {apify-3.0.2b7 → apify-3.0.4}/src/apify/scrapy/extensions/_httpcache.py +0 -0
  164. {apify-3.0.2b7 → apify-3.0.4}/src/apify/scrapy/middlewares/__init__.py +0 -0
  165. {apify-3.0.2b7 → apify-3.0.4}/src/apify/scrapy/middlewares/apify_proxy.py +0 -0
  166. {apify-3.0.2b7 → apify-3.0.4}/src/apify/scrapy/middlewares/py.typed +0 -0
  167. {apify-3.0.2b7 → apify-3.0.4}/src/apify/scrapy/pipelines/__init__.py +0 -0
  168. {apify-3.0.2b7 → apify-3.0.4}/src/apify/scrapy/pipelines/actor_dataset_push.py +0 -0
  169. {apify-3.0.2b7 → apify-3.0.4}/src/apify/scrapy/pipelines/py.typed +0 -0
  170. {apify-3.0.2b7 → apify-3.0.4}/src/apify/scrapy/py.typed +0 -0
  171. {apify-3.0.2b7 → apify-3.0.4}/src/apify/scrapy/requests.py +0 -0
  172. {apify-3.0.2b7 → apify-3.0.4}/src/apify/scrapy/scheduler.py +0 -0
  173. {apify-3.0.2b7 → apify-3.0.4}/src/apify/scrapy/utils.py +0 -0
  174. {apify-3.0.2b7 → apify-3.0.4}/src/apify/storage_clients/__init__.py +0 -0
  175. {apify-3.0.2b7 → apify-3.0.4}/src/apify/storage_clients/_apify/__init__.py +0 -0
  176. {apify-3.0.2b7 → apify-3.0.4}/src/apify/storage_clients/_apify/py.typed +0 -0
  177. {apify-3.0.2b7 → apify-3.0.4}/src/apify/storage_clients/_file_system/__init__.py +0 -0
  178. {apify-3.0.2b7 → apify-3.0.4}/src/apify/storage_clients/_file_system/_key_value_store_client.py +0 -0
  179. {apify-3.0.2b7 → apify-3.0.4}/src/apify/storage_clients/_file_system/_storage_client.py +0 -0
  180. {apify-3.0.2b7 → apify-3.0.4}/src/apify/storage_clients/_smart_apify/__init__.py +0 -0
  181. {apify-3.0.2b7 → apify-3.0.4}/src/apify/storage_clients/py.typed +0 -0
  182. {apify-3.0.2b7 → apify-3.0.4}/src/apify/storages/__init__.py +0 -0
  183. {apify-3.0.2b7 → apify-3.0.4}/src/apify/storages/py.typed +0 -0
  184. {apify-3.0.2b7 → apify-3.0.4}/tests/integration/__init__.py +0 -0
  185. {apify-3.0.2b7 → apify-3.0.4}/tests/integration/_utils.py +0 -0
  186. {apify-3.0.2b7/tests/integration/actor_source_base/src → apify-3.0.4/tests/integration/actor}/__init__.py +0 -0
  187. {apify-3.0.2b7/tests/integration → apify-3.0.4/tests/integration/actor}/actor_source_base/Dockerfile +0 -0
  188. {apify-3.0.2b7/tests/integration → apify-3.0.4/tests/integration/actor}/actor_source_base/requirements.txt +0 -0
  189. {apify-3.0.2b7/tests/integration → apify-3.0.4/tests/integration/actor}/actor_source_base/server.py +0 -0
  190. {apify-3.0.2b7/tests/unit → apify-3.0.4/tests/integration/actor/actor_source_base/src}/__init__.py +0 -0
  191. {apify-3.0.2b7/tests/integration → apify-3.0.4/tests/integration/actor}/actor_source_base/src/__main__.py +0 -0
  192. {apify-3.0.2b7/tests/integration → apify-3.0.4/tests/integration/actor}/actor_source_base/src/main.py +0 -0
  193. {apify-3.0.2b7/tests/integration → apify-3.0.4/tests/integration/actor}/test_actor_call_timeouts.py +0 -0
  194. {apify-3.0.2b7/tests/integration → apify-3.0.4/tests/integration/actor}/test_actor_charge.py +0 -0
  195. {apify-3.0.2b7/tests/integration → apify-3.0.4/tests/integration/actor}/test_actor_create_proxy_configuration.py +0 -0
  196. {apify-3.0.2b7/tests/integration → apify-3.0.4/tests/integration/actor}/test_actor_events.py +0 -0
  197. {apify-3.0.2b7/tests/integration → apify-3.0.4/tests/integration/actor}/test_actor_scrapy.py +0 -0
  198. {apify-3.0.2b7/tests/integration → apify-3.0.4/tests/integration/actor}/test_crawlers_with_storages.py +0 -0
  199. {apify-3.0.2b7/tests/integration → apify-3.0.4/tests/integration/actor}/test_fixtures.py +0 -0
  200. {apify-3.0.2b7/tests/unit/actor → apify-3.0.4/tests/integration/apify_api}/__init__.py +0 -0
  201. {apify-3.0.2b7/tests/unit/events → apify-3.0.4/tests/unit}/__init__.py +0 -0
  202. {apify-3.0.2b7/tests/unit/scrapy → apify-3.0.4/tests/unit/actor}/__init__.py +0 -0
  203. {apify-3.0.2b7 → apify-3.0.4}/tests/unit/actor/test_actor_create_proxy_configuration.py +0 -0
  204. {apify-3.0.2b7 → apify-3.0.4}/tests/unit/actor/test_actor_dataset.py +0 -0
  205. {apify-3.0.2b7 → apify-3.0.4}/tests/unit/actor/test_actor_helpers.py +0 -0
  206. {apify-3.0.2b7 → apify-3.0.4}/tests/unit/actor/test_actor_key_value_store.py +0 -0
  207. {apify-3.0.2b7 → apify-3.0.4}/tests/unit/actor/test_actor_lifecycle.py +0 -0
  208. {apify-3.0.2b7 → apify-3.0.4}/tests/unit/actor/test_actor_non_default_instance.py +0 -0
  209. {apify-3.0.2b7 → apify-3.0.4}/tests/unit/actor/test_actor_request_queue.py +0 -0
  210. {apify-3.0.2b7 → apify-3.0.4}/tests/unit/actor/test_configuration.py +0 -0
  211. {apify-3.0.2b7 → apify-3.0.4}/tests/unit/actor/test_request_list.py +0 -0
  212. {apify-3.0.2b7 → apify-3.0.4}/tests/unit/conftest.py +0 -0
  213. {apify-3.0.2b7/tests/unit/scrapy/extensions → apify-3.0.4/tests/unit/events}/__init__.py +0 -0
  214. {apify-3.0.2b7 → apify-3.0.4}/tests/unit/events/test_apify_event_manager.py +0 -0
  215. {apify-3.0.2b7/tests/unit/scrapy/middlewares → apify-3.0.4/tests/unit/scrapy}/__init__.py +0 -0
  216. {apify-3.0.2b7/tests/unit/scrapy/pipelines → apify-3.0.4/tests/unit/scrapy/extensions}/__init__.py +0 -0
  217. {apify-3.0.2b7 → apify-3.0.4}/tests/unit/scrapy/extensions/test_httpcache.py +0 -0
  218. {apify-3.0.2b7/tests/unit/scrapy/requests → apify-3.0.4/tests/unit/scrapy/middlewares}/__init__.py +0 -0
  219. {apify-3.0.2b7 → apify-3.0.4}/tests/unit/scrapy/middlewares/test_apify_proxy.py +0 -0
  220. {apify-3.0.2b7/tests/unit/scrapy/utils → apify-3.0.4/tests/unit/scrapy/pipelines}/__init__.py +0 -0
  221. {apify-3.0.2b7 → apify-3.0.4}/tests/unit/scrapy/pipelines/test_actor_dataset_push.py +0 -0
  222. {apify-3.0.2b7/tests/unit/storage_clients → apify-3.0.4/tests/unit/scrapy/requests}/__init__.py +0 -0
  223. {apify-3.0.2b7 → apify-3.0.4}/tests/unit/scrapy/requests/test_to_apify_request.py +0 -0
  224. {apify-3.0.2b7 → apify-3.0.4}/tests/unit/scrapy/requests/test_to_scrapy_request.py +0 -0
  225. /apify-3.0.2b7/website/static/.nojekyll → /apify-3.0.4/tests/unit/scrapy/utils/__init__.py +0 -0
  226. {apify-3.0.2b7 → apify-3.0.4}/tests/unit/scrapy/utils/test_apply_apify_settings.py +0 -0
  227. {apify-3.0.2b7 → apify-3.0.4}/tests/unit/scrapy/utils/test_get_basic_auth_header.py +0 -0
  228. {apify-3.0.2b7 → apify-3.0.4}/tests/unit/storage_clients/test_apify_request_queue_client.py +0 -0
  229. {apify-3.0.2b7 → apify-3.0.4}/tests/unit/storage_clients/test_file_system.py +0 -0
  230. {apify-3.0.2b7 → apify-3.0.4}/tests/unit/test_apify_storages.py +0 -0
  231. {apify-3.0.2b7 → apify-3.0.4}/tests/unit/test_crypto.py +0 -0
  232. {apify-3.0.2b7 → apify-3.0.4}/tests/unit/test_proxy_configuration.py +0 -0
  233. {apify-3.0.2b7 → apify-3.0.4}/website/.eslintrc.json +0 -0
  234. {apify-3.0.2b7 → apify-3.0.4}/website/babel.config.js +0 -0
  235. {apify-3.0.2b7 → apify-3.0.4}/website/build_api_reference.sh +0 -0
  236. {apify-3.0.2b7 → apify-3.0.4}/website/generate_module_shortcuts.py +0 -0
  237. {apify-3.0.2b7 → apify-3.0.4}/website/package.json +0 -0
  238. {apify-3.0.2b7 → apify-3.0.4}/website/sidebars.js +0 -0
  239. {apify-3.0.2b7 → apify-3.0.4}/website/src/components/ApiLink.jsx +0 -0
  240. {apify-3.0.2b7 → apify-3.0.4}/website/src/components/Gradients.jsx +0 -0
  241. {apify-3.0.2b7 → apify-3.0.4}/website/src/components/Highlights.jsx +0 -0
  242. {apify-3.0.2b7 → apify-3.0.4}/website/src/components/Highlights.module.css +0 -0
  243. {apify-3.0.2b7 → apify-3.0.4}/website/src/components/RunnableCodeBlock.jsx +0 -0
  244. {apify-3.0.2b7 → apify-3.0.4}/website/src/components/RunnableCodeBlock.module.css +0 -0
  245. {apify-3.0.2b7 → apify-3.0.4}/website/src/css/custom.css +0 -0
  246. {apify-3.0.2b7 → apify-3.0.4}/website/src/pages/home_page_example.py +0 -0
  247. {apify-3.0.2b7 → apify-3.0.4}/website/src/pages/index.module.css +0 -0
  248. {apify-3.0.2b7 → apify-3.0.4}/website/src/theme/DocItem/Content/index.js +0 -0
  249. {apify-3.0.2b7 → apify-3.0.4}/website/static/img/docs-og.png +0 -0
  250. {apify-3.0.2b7 → apify-3.0.4}/website/static/img/guides/redirected_logs_example.webp +0 -0
  251. {apify-3.0.2b7 → apify-3.0.4}/website/tools/docs-prettier.config.js +0 -0
  252. {apify-3.0.2b7 → apify-3.0.4}/website/tools/utils/externalLink.js +0 -0
@@ -2,8 +2,26 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
- <!-- git-cliff-unreleased-start -->
6
- ## 3.0.2 - **not yet released**
5
+ ## [3.0.4](https://github.com/apify/apify-sdk-python/releases/tag/v3.0.4) (2025-11-03)
6
+
7
+ ### 🐛 Bug Fixes
8
+
9
+ - 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)
10
+ - Fix local charging log dataset name ([#649](https://github.com/apify/apify-sdk-python/pull/649)) ([fdb1276](https://github.com/apify/apify-sdk-python/commit/fdb1276264aee2687596d87c96d19033fe915823)) by [@vdusek](https://github.com/vdusek), closes [#648](https://github.com/apify/apify-sdk-python/issues/648)
11
+
12
+ ### ⚡ Performance
13
+
14
+ - Use Apify-provided environment variables to obtain PPE pricing information ([#644](https://github.com/apify/apify-sdk-python/pull/644)) ([0c32f29](https://github.com/apify/apify-sdk-python/commit/0c32f29d6a316f5bacc931595d694f262c925b2b)) by [@Mantisus](https://github.com/Mantisus), closes [#614](https://github.com/apify/apify-sdk-python/issues/614)
15
+
16
+
17
+ ## [3.0.3](https://github.com/apify/apify-sdk-python/releases/tag/v3.0.3) (2025-10-21)
18
+
19
+ ### 🐛 Bug Fixes
20
+
21
+ - 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)
22
+
23
+
24
+ ## [3.0.2](https://github.com/apify/apify-sdk-python/releases/tag/v3.0.2) (2025-10-17)
7
25
 
8
26
  ### 🐛 Bug Fixes
9
27
 
@@ -12,7 +30,6 @@ All notable changes to this project will be documented in this file.
12
30
  - Handle truncated `unique_key` in `list_head` by fetching full request data ([#631](https://github.com/apify/apify-sdk-python/pull/631)) ([4238086](https://github.com/apify/apify-sdk-python/commit/423808678d9155a84a266bf50bb09f1a56466174)) by [@vdusek](https://github.com/vdusek), closes [#627](https://github.com/apify/apify-sdk-python/issues/627)
13
31
 
14
32
 
15
- <!-- git-cliff-unreleased-end -->
16
33
  ## [3.0.1](https://github.com/apify/apify-sdk-python/releases/tag/v3.0.1) (2025-10-08)
17
34
 
18
35
  ### 🐛 Bug Fixes
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: apify
3
- Version: 3.0.2b7
3
+ Version: 3.0.4
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
@@ -225,10 +225,10 @@ Classifier: Programming Language :: Python :: 3.12
225
225
  Classifier: Programming Language :: Python :: 3.13
226
226
  Classifier: Topic :: Software Development :: Libraries
227
227
  Requires-Python: >=3.10
228
- Requires-Dist: apify-client<3.0.0,>=2.0.0
228
+ Requires-Dist: apify-client<3.0.0,>=2.2.0
229
229
  Requires-Dist: apify-shared<3.0.0,>=2.0.0
230
230
  Requires-Dist: cachetools>=5.5.0
231
- Requires-Dist: crawlee<2.0.0,>=1.0.2
231
+ Requires-Dist: crawlee<2.0.0,>=1.0.4
232
232
  Requires-Dist: cryptography>=42.0.0
233
233
  Requires-Dist: impit>=0.6.1
234
234
  Requires-Dist: lazy-object-proxy>=1.11.0
@@ -47,6 +47,6 @@ It is encouraged to test your monetization code on your machine before releasing
47
47
  ACTOR_TEST_PAY_PER_EVENT=true python -m youractor
48
48
  ```
49
49
 
50
- If you also wish to see a log of all the events charged throughout the run, the Apify SDK keeps a log of charged events in a so called charging dataset. Your charging dataset can be found under the `charging_log` name (unless you change your storage settings, this dataset is stored in `storage/datasets/charging_log/`). Please note that this log is not available when running the Actor in production on the Apify platform.
50
+ If you also wish to see a log of all the events charged throughout the run, the Apify SDK keeps a log of charged events in a so called charging dataset. Your charging dataset can be found under the `charging-log` name (unless you change your storage settings, this dataset is stored in `storage/datasets/charging-log/`). Please note that this log is not available when running the Actor in production on the Apify platform.
51
51
 
52
52
  Because pricing configuration is stored by the Apify platform, all events will have a default price of $1.
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "apify"
7
- version = "3.0.2b7"
7
+ version = "3.0.4"
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" }
@@ -34,9 +34,9 @@ keywords = [
34
34
  "scraping",
35
35
  ]
36
36
  dependencies = [
37
- "apify-client>=2.0.0,<3.0.0",
37
+ "apify-client>=2.2.0,<3.0.0",
38
38
  "apify-shared>=2.0.0,<3.0.0",
39
- "crawlee>=1.0.2,<2.0.0",
39
+ "crawlee>=1.0.4,<2.0.0",
40
40
  "cachetools>=5.5.0",
41
41
  "cryptography>=42.0.0",
42
42
  "impit>=0.6.1",
@@ -1,7 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import asyncio
4
- import os
5
4
  import sys
6
5
  from contextlib import suppress
7
6
  from datetime import datetime, timedelta, timezone
@@ -48,7 +47,6 @@ if TYPE_CHECKING:
48
47
  from typing_extensions import Self
49
48
 
50
49
  from crawlee.proxy_configuration import _NewUrlFunction
51
- from crawlee.storage_clients import StorageClient
52
50
 
53
51
  from apify._models import Webhook
54
52
 
@@ -140,7 +138,6 @@ class _ActorType:
140
138
  # `__init__` method should not be considered final.
141
139
 
142
140
  self._apify_client: ApifyClientAsync | None = None
143
- self._local_storage_client: StorageClient | None = None
144
141
 
145
142
  self._is_exiting = False
146
143
  self._is_initialized = False
@@ -1290,16 +1287,11 @@ class _ActorType:
1290
1287
  raise RuntimeError('The Actor was not initialized!')
1291
1288
 
1292
1289
  def _get_default_exit_process(self) -> bool:
1293
- """Return False for IPython, Pytest, and Scrapy environments, True otherwise."""
1290
+ """Return False for IPython and Scrapy environments, True otherwise."""
1294
1291
  if is_running_in_ipython():
1295
1292
  self.log.debug('Running in IPython, setting default `exit_process` to False.')
1296
1293
  return False
1297
1294
 
1298
- # Check if running in Pytest by detecting the relevant environment variable.
1299
- if os.getenv('PYTEST_CURRENT_TEST'):
1300
- self.log.debug('Running in Pytest, setting default `exit_process` to False.')
1301
- return False
1302
-
1303
1295
  # Check if running in Scrapy by attempting to import it.
1304
1296
  with suppress(ImportError):
1305
1297
  import scrapy # noqa: F401 PLC0415
@@ -4,13 +4,20 @@ import math
4
4
  from dataclasses import dataclass
5
5
  from datetime import datetime, timezone
6
6
  from decimal import Decimal
7
- from typing import TYPE_CHECKING, Protocol
7
+ from typing import TYPE_CHECKING, Protocol, TypedDict
8
8
 
9
9
  from pydantic import TypeAdapter
10
10
 
11
11
  from crawlee._utils.context import ensure_context
12
12
 
13
- from apify._models import ActorRun, PricingModel
13
+ from apify._models import (
14
+ ActorRun,
15
+ FlatPricePerMonthActorPricingInfo,
16
+ FreeActorPricingInfo,
17
+ PayPerEventActorPricingInfo,
18
+ PricePerDatasetItemActorPricingInfo,
19
+ PricingModel,
20
+ )
14
21
  from apify._utils import docs_group
15
22
  from apify.log import logger
16
23
  from apify.storages import Dataset
@@ -111,24 +118,16 @@ class ActorPricingInfo:
111
118
  class ChargingManagerImplementation(ChargingManager):
112
119
  """Implementation of the `ChargingManager` Protocol - this is only meant to be instantiated internally."""
113
120
 
114
- LOCAL_CHARGING_LOG_DATASET_NAME = 'charging_log'
121
+ LOCAL_CHARGING_LOG_DATASET_NAME = 'charging-log'
115
122
 
116
123
  def __init__(self, configuration: Configuration, client: ApifyClientAsync) -> None:
117
124
  self._max_total_charge_usd = configuration.max_total_charge_usd or Decimal('inf')
125
+ self._configuration = configuration
118
126
  self._is_at_home = configuration.is_at_home
119
127
  self._actor_run_id = configuration.actor_run_id
120
128
  self._purge_charging_log_dataset = configuration.purge_on_start
121
129
  self._pricing_model: PricingModel | None = None
122
130
 
123
- if configuration.test_pay_per_event:
124
- if self._is_at_home:
125
- raise ValueError(
126
- 'Using the ACTOR_TEST_PAY_PER_EVENT environment variable is only supported '
127
- 'in a local development environment'
128
- )
129
-
130
- self._pricing_model = 'PAY_PER_EVENT'
131
-
132
131
  self._client = client
133
132
  self._charging_log_dataset: Dataset | None = None
134
133
 
@@ -140,37 +139,46 @@ class ChargingManagerImplementation(ChargingManager):
140
139
 
141
140
  async def __aenter__(self) -> None:
142
141
  """Initialize the charging manager - this is called by the `Actor` class and shouldn't be invoked manually."""
143
- self.active = True
144
-
145
- if self._is_at_home:
146
- # Running on the Apify platform - fetch pricing info for the current run.
147
-
148
- if self._actor_run_id is None:
149
- raise RuntimeError('Actor run ID not found even though the Actor is running on Apify')
142
+ # Validate config
143
+ if self._configuration.test_pay_per_event and self._is_at_home:
144
+ raise ValueError(
145
+ 'Using the ACTOR_TEST_PAY_PER_EVENT environment variable is only supported '
146
+ 'in a local development environment'
147
+ )
150
148
 
151
- run = run_validator.validate_python(await self._client.run(self._actor_run_id).get())
152
- if run is None:
153
- raise RuntimeError('Actor run not found')
149
+ self.active = True
154
150
 
155
- if run.pricing_info is not None:
156
- self._pricing_model = run.pricing_info.pricing_model
151
+ # Retrieve pricing information from env vars or API
152
+ pricing_data = await self._fetch_pricing_info()
153
+ pricing_info = pricing_data['pricing_info']
154
+ charged_event_counts = pricing_data['charged_event_counts']
155
+ max_total_charge_usd = pricing_data['max_total_charge_usd']
157
156
 
158
- if run.pricing_info.pricing_model == 'PAY_PER_EVENT':
159
- for event_name, event_pricing in run.pricing_info.pricing_per_event.actor_charge_events.items():
160
- self._pricing_info[event_name] = PricingInfoItem(
161
- price=event_pricing.event_price_usd,
162
- title=event_pricing.event_title,
163
- )
157
+ # Set pricing model
158
+ if self._configuration.test_pay_per_event:
159
+ self._pricing_model = 'PAY_PER_EVENT'
160
+ else:
161
+ self._pricing_model = pricing_info.pricing_model if pricing_info else None
162
+
163
+ # Load per-event pricing information
164
+ if pricing_info and pricing_info.pricing_model == 'PAY_PER_EVENT':
165
+ for event_name, event_pricing in pricing_info.pricing_per_event.actor_charge_events.items():
166
+ self._pricing_info[event_name] = PricingInfoItem(
167
+ price=event_pricing.event_price_usd,
168
+ title=event_pricing.event_title,
169
+ )
164
170
 
165
- self._max_total_charge_usd = run.options.max_total_charge_usd or self._max_total_charge_usd
171
+ self._max_total_charge_usd = max_total_charge_usd
166
172
 
167
- for event_name, count in (run.charged_event_counts or {}).items():
168
- price = self._pricing_info.get(event_name, PricingInfoItem(Decimal(), title='')).price
169
- self._charging_state[event_name] = ChargingStateItem(
170
- charge_count=count,
171
- total_charged_amount=count * price,
172
- )
173
+ # Load charged event counts
174
+ for event_name, count in charged_event_counts.items():
175
+ price = self._pricing_info.get(event_name, PricingInfoItem(Decimal(), title='')).price
176
+ self._charging_state[event_name] = ChargingStateItem(
177
+ charge_count=count,
178
+ total_charged_amount=count * price,
179
+ )
173
180
 
181
+ # Set up charging log dataset for local development
174
182
  if not self._is_at_home and self._pricing_model == 'PAY_PER_EVENT':
175
183
  # We are not running on the Apify platform, but PPE is enabled for testing - open a dataset that
176
184
  # will contain a log of all charge calls for debugging purposes.
@@ -328,6 +336,38 @@ class ChargingManagerImplementation(ChargingManager):
328
336
  def get_max_total_charge_usd(self) -> Decimal:
329
337
  return self._max_total_charge_usd
330
338
 
339
+ async def _fetch_pricing_info(self) -> _FetchedPricingInfoDict:
340
+ """Fetch pricing information from environment variables or API."""
341
+ # Check if pricing info is available via environment variables
342
+ if self._configuration.actor_pricing_info is not None and self._configuration.charged_event_counts is not None:
343
+ return _FetchedPricingInfoDict(
344
+ pricing_info=self._configuration.actor_pricing_info,
345
+ charged_event_counts=self._configuration.charged_event_counts,
346
+ max_total_charge_usd=self._configuration.max_total_charge_usd or Decimal('inf'),
347
+ )
348
+
349
+ # Fall back to API call
350
+ if self._is_at_home:
351
+ if self._actor_run_id is None:
352
+ raise RuntimeError('Actor run ID not found even though the Actor is running on Apify')
353
+
354
+ run = run_validator.validate_python(await self._client.run(self._actor_run_id).get())
355
+ if run is None:
356
+ raise RuntimeError('Actor run not found')
357
+
358
+ return _FetchedPricingInfoDict(
359
+ pricing_info=run.pricing_info,
360
+ charged_event_counts=run.charged_event_counts or {},
361
+ max_total_charge_usd=run.options.max_total_charge_usd or Decimal('inf'),
362
+ )
363
+
364
+ # Local development without environment variables
365
+ return _FetchedPricingInfoDict(
366
+ pricing_info=None,
367
+ charged_event_counts={},
368
+ max_total_charge_usd=self._configuration.max_total_charge_usd or Decimal('inf'),
369
+ )
370
+
331
371
 
332
372
  @dataclass
333
373
  class ChargingStateItem:
@@ -339,3 +379,15 @@ class ChargingStateItem:
339
379
  class PricingInfoItem:
340
380
  price: Decimal
341
381
  title: str
382
+
383
+
384
+ class _FetchedPricingInfoDict(TypedDict):
385
+ pricing_info: (
386
+ FreeActorPricingInfo
387
+ | FlatPricePerMonthActorPricingInfo
388
+ | PricePerDatasetItemActorPricingInfo
389
+ | PayPerEventActorPricingInfo
390
+ | None
391
+ )
392
+ charged_event_counts: dict[str, int]
393
+ max_total_charge_usd: Decimal
@@ -1,5 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
+ import json
3
4
  from datetime import datetime, timedelta
4
5
  from decimal import Decimal
5
6
  from logging import getLogger
@@ -14,6 +15,12 @@ from crawlee._utils.models import timedelta_ms
14
15
  from crawlee._utils.urls import validate_http_url
15
16
  from crawlee.configuration import Configuration as CrawleeConfiguration
16
17
 
18
+ from apify._models import (
19
+ FlatPricePerMonthActorPricingInfo,
20
+ FreeActorPricingInfo,
21
+ PayPerEventActorPricingInfo,
22
+ PricePerDatasetItemActorPricingInfo,
23
+ )
17
24
  from apify._utils import docs_group
18
25
 
19
26
  logger = getLogger(__name__)
@@ -409,6 +416,29 @@ class Configuration(CrawleeConfiguration):
409
416
  ),
410
417
  ] = None
411
418
 
419
+ actor_pricing_info: Annotated[
420
+ FreeActorPricingInfo
421
+ | FlatPricePerMonthActorPricingInfo
422
+ | PricePerDatasetItemActorPricingInfo
423
+ | PayPerEventActorPricingInfo
424
+ | None,
425
+ Field(
426
+ alias='apify_actor_pricing_info',
427
+ description='JSON string with prising info of the actor',
428
+ discriminator='pricing_model',
429
+ ),
430
+ BeforeValidator(lambda data: json.loads(data) if isinstance(data, str) else data if data else None),
431
+ ] = None
432
+
433
+ charged_event_counts: Annotated[
434
+ dict[str, int] | None,
435
+ Field(
436
+ alias='apify_charged_actor_event_counts',
437
+ description='Counts of events that were charged for the actor',
438
+ ),
439
+ BeforeValidator(lambda data: json.loads(data) if isinstance(data, str) else data if data else None),
440
+ ] = None
441
+
412
442
  @model_validator(mode='after')
413
443
  def disable_browser_sandbox_on_platform(self) -> Self:
414
444
  """Disable the browser sandbox mode when running on the Apify platform.
@@ -22,8 +22,8 @@ URL_NO_COMMAS_REGEX = re.compile(
22
22
  class _RequestDetails(BaseModel):
23
23
  method: HttpMethod = 'GET'
24
24
  payload: str = ''
25
- headers: Annotated[dict[str, str], Field(default_factory=dict)] = {}
26
- user_data: Annotated[dict[str, str], Field(default_factory=dict, alias='userData')] = {}
25
+ headers: Annotated[dict[str, str], Field(default_factory=dict)]
26
+ user_data: Annotated[dict[str, str], Field(default_factory=dict, alias='userData')]
27
27
 
28
28
 
29
29
  class _RequestsFromUrlInput(_RequestDetails):
@@ -1,19 +1,19 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import asyncio
4
+ import warnings
4
5
  from logging import getLogger
5
6
  from typing import TYPE_CHECKING, Any
6
7
 
7
8
  from typing_extensions import override
8
9
 
9
- from apify_client import ApifyClientAsync
10
10
  from crawlee._utils.byte_size import ByteSize
11
11
  from crawlee._utils.file import json_dumps
12
12
  from crawlee.storage_clients._base import DatasetClient
13
13
  from crawlee.storage_clients.models import DatasetItemsListPage, DatasetMetadata
14
14
  from crawlee.storages import Dataset
15
15
 
16
- from ._utils import AliasResolver
16
+ from ._utils import AliasResolver, create_apify_client
17
17
 
18
18
  if TYPE_CHECKING:
19
19
  from collections.abc import AsyncIterator
@@ -52,12 +52,17 @@ class ApifyDatasetClient(DatasetClient):
52
52
  self._api_client = api_client
53
53
  """The Apify dataset client for API operations."""
54
54
 
55
- self._api_public_base_url = api_public_base_url
56
- """The public base URL for accessing the key-value store records."""
57
-
58
55
  self._lock = lock
59
56
  """A lock to ensure that only one operation is performed at a time."""
60
57
 
58
+ if api_public_base_url:
59
+ # Remove in version 4.0, https://github.com/apify/apify-sdk-python/issues/635
60
+ warnings.warn(
61
+ 'api_public_base_url argument is deprecated and will be removed in version 4.0.0',
62
+ DeprecationWarning,
63
+ stacklevel=2,
64
+ )
65
+
61
66
  @override
62
67
  async def get_metadata(self) -> DatasetMetadata:
63
68
  metadata = await self._api_client.get()
@@ -99,29 +104,7 @@ class ApifyDatasetClient(DatasetClient):
99
104
  if sum(1 for param in [id, name, alias] if param is not None) > 1:
100
105
  raise ValueError('Only one of "id", "name", or "alias" can be specified, not multiple.')
101
106
 
102
- token = configuration.token
103
- if not token:
104
- raise ValueError(f'Apify storage client requires a valid token in Configuration (token={token}).')
105
-
106
- api_url = configuration.api_base_url
107
- if not api_url:
108
- raise ValueError(f'Apify storage client requires a valid API URL in Configuration (api_url={api_url}).')
109
-
110
- api_public_base_url = configuration.api_public_base_url
111
- if not api_public_base_url:
112
- raise ValueError(
113
- 'Apify storage client requires a valid API public base URL in Configuration '
114
- f'(api_public_base_url={api_public_base_url}).'
115
- )
116
-
117
- # Create Apify client with the provided token and API URL.
118
- apify_client_async = ApifyClientAsync(
119
- token=token,
120
- api_url=api_url,
121
- max_retries=8,
122
- min_delay_between_retries_millis=500,
123
- timeout_secs=360,
124
- )
107
+ apify_client_async = create_apify_client(configuration)
125
108
  apify_datasets_client = apify_client_async.datasets()
126
109
 
127
110
  # Normalize unnamed default storage in cases where not defined in `configuration.default_dataset_id` to unnamed
@@ -178,7 +161,7 @@ class ApifyDatasetClient(DatasetClient):
178
161
 
179
162
  return cls(
180
163
  api_client=apify_dataset_client,
181
- api_public_base_url=api_public_base_url,
164
+ api_public_base_url='', # Remove in version 4.0, https://github.com/apify/apify-sdk-python/issues/635
182
165
  lock=asyncio.Lock(),
183
166
  )
184
167
 
@@ -1,20 +1,18 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import asyncio
4
+ import warnings
4
5
  from logging import getLogger
5
6
  from typing import TYPE_CHECKING, Any
6
7
 
7
8
  from typing_extensions import override
8
- from yarl import URL
9
9
 
10
- from apify_client import ApifyClientAsync
11
10
  from crawlee.storage_clients._base import KeyValueStoreClient
12
11
  from crawlee.storage_clients.models import KeyValueStoreRecord, KeyValueStoreRecordMetadata
13
12
  from crawlee.storages import KeyValueStore
14
13
 
15
14
  from ._models import ApifyKeyValueStoreMetadata, KeyValueStoreListKeysPage
16
- from ._utils import AliasResolver
17
- from apify._crypto import create_hmac_signature
15
+ from ._utils import AliasResolver, create_apify_client
18
16
 
19
17
  if TYPE_CHECKING:
20
18
  from collections.abc import AsyncIterator
@@ -43,12 +41,17 @@ class ApifyKeyValueStoreClient(KeyValueStoreClient):
43
41
  self._api_client = api_client
44
42
  """The Apify KVS client for API operations."""
45
43
 
46
- self._api_public_base_url = api_public_base_url
47
- """The public base URL for accessing the key-value store records."""
48
-
49
44
  self._lock = lock
50
45
  """A lock to ensure that only one operation is performed at a time."""
51
46
 
47
+ if api_public_base_url:
48
+ # Remove in version 4.0, https://github.com/apify/apify-sdk-python/issues/635
49
+ warnings.warn(
50
+ 'api_public_base_url argument is deprecated and will be removed in version 4.0.0',
51
+ DeprecationWarning,
52
+ stacklevel=2,
53
+ )
54
+
52
55
  @override
53
56
  async def get_metadata(self) -> ApifyKeyValueStoreMetadata:
54
57
  metadata = await self._api_client.get()
@@ -90,29 +93,7 @@ class ApifyKeyValueStoreClient(KeyValueStoreClient):
90
93
  if sum(1 for param in [id, name, alias] if param is not None) > 1:
91
94
  raise ValueError('Only one of "id", "name", or "alias" can be specified, not multiple.')
92
95
 
93
- token = configuration.token
94
- if not token:
95
- raise ValueError(f'Apify storage client requires a valid token in Configuration (token={token}).')
96
-
97
- api_url = configuration.api_base_url
98
- if not api_url:
99
- raise ValueError(f'Apify storage client requires a valid API URL in Configuration (api_url={api_url}).')
100
-
101
- api_public_base_url = configuration.api_public_base_url
102
- if not api_public_base_url:
103
- raise ValueError(
104
- 'Apify storage client requires a valid API public base URL in Configuration '
105
- f'(api_public_base_url={api_public_base_url}).'
106
- )
107
-
108
- # Create Apify client with the provided token and API URL.
109
- apify_client_async = ApifyClientAsync(
110
- token=token,
111
- api_url=api_url,
112
- max_retries=8,
113
- min_delay_between_retries_millis=500,
114
- timeout_secs=360,
115
- )
96
+ apify_client_async = create_apify_client(configuration)
116
97
  apify_kvss_client = apify_client_async.key_value_stores()
117
98
 
118
99
  # Normalize unnamed default storage in cases where not defined in `configuration.default_key_value_store_id` to
@@ -170,7 +151,7 @@ class ApifyKeyValueStoreClient(KeyValueStoreClient):
170
151
 
171
152
  return cls(
172
153
  api_client=apify_kvs_client,
173
- api_public_base_url=api_public_base_url,
154
+ api_public_base_url='', # Remove in version 4.0, https://github.com/apify/apify-sdk-python/issues/635
174
155
  lock=asyncio.Lock(),
175
156
  )
176
157
 
@@ -251,15 +232,4 @@ class ApifyKeyValueStoreClient(KeyValueStoreClient):
251
232
  Returns:
252
233
  A public URL that can be used to access the value of the given key in the KVS.
253
234
  """
254
- if self._api_client.resource_id is None:
255
- raise ValueError('resource_id cannot be None when generating a public URL')
256
-
257
- public_url = (
258
- URL(self._api_public_base_url) / 'v2' / 'key-value-stores' / self._api_client.resource_id / 'records' / key
259
- )
260
- metadata = await self.get_metadata()
261
-
262
- if metadata.url_signing_secret_key is not None:
263
- public_url = public_url.with_query(signature=create_hmac_signature(metadata.url_signing_secret_key, key))
264
-
265
- return str(public_url)
235
+ return await self._api_client.get_record_public_url(key=key)
@@ -94,8 +94,8 @@ class CachedRequest(BaseModel):
94
94
  Only internal structure.
95
95
  """
96
96
 
97
- unique_key: str
98
- """Unique key of the request."""
97
+ id: str
98
+ """Id of the request."""
99
99
 
100
100
  was_already_handled: bool
101
101
  """Whether the request was already handled."""
@@ -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."""
@@ -5,7 +5,6 @@ from typing import TYPE_CHECKING, Final, Literal
5
5
 
6
6
  from typing_extensions import override
7
7
 
8
- from apify_client import ApifyClientAsync
9
8
  from crawlee._utils.crypto import crypto_random_object_id
10
9
  from crawlee.storage_clients._base import RequestQueueClient
11
10
  from crawlee.storage_clients.models import AddRequestsResponse, ProcessedRequest, RequestQueueMetadata
@@ -14,7 +13,7 @@ from crawlee.storages import RequestQueue
14
13
  from ._models import ApifyRequestQueueMetadata, RequestQueueStats
15
14
  from ._request_queue_shared_client import ApifyRequestQueueSharedClient
16
15
  from ._request_queue_single_client import ApifyRequestQueueSingleClient
17
- from ._utils import AliasResolver
16
+ from ._utils import AliasResolver, create_apify_client
18
17
 
19
18
  if TYPE_CHECKING:
20
19
  from collections.abc import Sequence
@@ -228,29 +227,7 @@ class ApifyRequestQueueClient(RequestQueueClient):
228
227
  if sum(1 for param in [id, name, alias] if param is not None) > 1:
229
228
  raise ValueError('Only one of "id", "name", or "alias" can be specified, not multiple.')
230
229
 
231
- token = configuration.token
232
- if not token:
233
- raise ValueError(f'Apify storage client requires a valid token in Configuration (token={token}).')
234
-
235
- api_url = configuration.api_base_url
236
- if not api_url:
237
- raise ValueError(f'Apify storage client requires a valid API URL in Configuration (api_url={api_url}).')
238
-
239
- api_public_base_url = configuration.api_public_base_url
240
- if not api_public_base_url:
241
- raise ValueError(
242
- 'Apify storage client requires a valid API public base URL in Configuration '
243
- f'(api_public_base_url={api_public_base_url}).'
244
- )
245
-
246
- # Create Apify client with the provided token and API URL.
247
- apify_client_async = ApifyClientAsync(
248
- token=token,
249
- api_url=api_url,
250
- max_retries=8,
251
- min_delay_between_retries_millis=500,
252
- timeout_secs=360,
253
- )
230
+ apify_client_async = create_apify_client(configuration)
254
231
  apify_rqs_client = apify_client_async.request_queues()
255
232
 
256
233
  # Normalize unnamed default storage in cases where not defined in `configuration.default_request_queue_id` to