apify 2.7.1b14__tar.gz → 2.7.1b16__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 (234) hide show
  1. {apify-2.7.1b14 → apify-2.7.1b16}/CHANGELOG.md +26 -0
  2. {apify-2.7.1b14 → apify-2.7.1b16}/PKG-INFO +2 -2
  3. {apify-2.7.1b14 → apify-2.7.1b16}/pyproject.toml +5 -5
  4. {apify-2.7.1b14 → apify-2.7.1b16}/src/apify/_actor.py +24 -12
  5. apify-2.7.1b16/src/apify/events/__init__.py +5 -0
  6. {apify-2.7.1b14 → apify-2.7.1b16}/src/apify/storage_clients/_apify/_dataset_client.py +38 -22
  7. {apify-2.7.1b14 → apify-2.7.1b16}/src/apify/storage_clients/_apify/_key_value_store_client.py +37 -22
  8. {apify-2.7.1b14 → apify-2.7.1b16}/src/apify/storage_clients/_apify/_request_queue_client.py +41 -27
  9. {apify-2.7.1b14 → apify-2.7.1b16}/src/apify/storage_clients/_apify/_storage_client.py +6 -3
  10. apify-2.7.1b16/src/apify/storage_clients/_apify/_utils.py +117 -0
  11. {apify-2.7.1b14 → apify-2.7.1b16}/src/apify/storage_clients/_file_system/_key_value_store_client.py +22 -1
  12. {apify-2.7.1b14 → apify-2.7.1b16}/src/apify/storage_clients/_file_system/_storage_client.py +7 -1
  13. {apify-2.7.1b14 → apify-2.7.1b16}/tests/integration/actor_source_base/requirements.txt +1 -1
  14. {apify-2.7.1b14 → apify-2.7.1b16}/tests/integration/test_actor_dataset.py +83 -0
  15. {apify-2.7.1b14 → apify-2.7.1b16}/tests/integration/test_actor_key_value_store.py +83 -0
  16. {apify-2.7.1b14 → apify-2.7.1b16}/tests/integration/test_actor_request_queue.py +88 -0
  17. {apify-2.7.1b14 → apify-2.7.1b16}/tests/unit/events/test_apify_event_manager.py +1 -1
  18. {apify-2.7.1b14 → apify-2.7.1b16}/tests/unit/scrapy/extensions/test_httpcache.py +1 -1
  19. {apify-2.7.1b14 → apify-2.7.1b16}/tests/unit/storage_clients/test_file_system.py +31 -3
  20. {apify-2.7.1b14 → apify-2.7.1b16}/tests/unit/test_crypto.py +2 -2
  21. {apify-2.7.1b14 → apify-2.7.1b16}/tests/unit/test_proxy_configuration.py +5 -5
  22. {apify-2.7.1b14 → apify-2.7.1b16}/uv.lock +112 -104
  23. apify-2.7.1b14/src/apify/events/__init__.py +0 -5
  24. {apify-2.7.1b14 → apify-2.7.1b16}/.editorconfig +0 -0
  25. {apify-2.7.1b14 → apify-2.7.1b16}/.github/CODEOWNERS +0 -0
  26. {apify-2.7.1b14 → apify-2.7.1b16}/.github/workflows/build_and_deploy_docs.yaml +0 -0
  27. {apify-2.7.1b14 → apify-2.7.1b16}/.github/workflows/check_pr_title.yaml +0 -0
  28. {apify-2.7.1b14 → apify-2.7.1b16}/.github/workflows/pre_release.yaml +0 -0
  29. {apify-2.7.1b14 → apify-2.7.1b16}/.github/workflows/release.yaml +0 -0
  30. {apify-2.7.1b14 → apify-2.7.1b16}/.github/workflows/run_code_checks.yaml +0 -0
  31. {apify-2.7.1b14 → apify-2.7.1b16}/.github/workflows/update_new_issue.yaml +0 -0
  32. {apify-2.7.1b14 → apify-2.7.1b16}/.gitignore +0 -0
  33. {apify-2.7.1b14 → apify-2.7.1b16}/.markdownlint.yaml +0 -0
  34. {apify-2.7.1b14 → apify-2.7.1b16}/.pre-commit-config.yaml +0 -0
  35. {apify-2.7.1b14 → apify-2.7.1b16}/CONTRIBUTING.md +0 -0
  36. {apify-2.7.1b14 → apify-2.7.1b16}/LICENSE +0 -0
  37. {apify-2.7.1b14 → apify-2.7.1b16}/Makefile +0 -0
  38. {apify-2.7.1b14 → apify-2.7.1b16}/README.md +0 -0
  39. {apify-2.7.1b14 → apify-2.7.1b16}/docs/01_overview/01_introduction.mdx +0 -0
  40. {apify-2.7.1b14 → apify-2.7.1b16}/docs/01_overview/02_running_actors_locally.mdx +0 -0
  41. {apify-2.7.1b14 → apify-2.7.1b16}/docs/01_overview/03_actor_structure.mdx +0 -0
  42. {apify-2.7.1b14 → apify-2.7.1b16}/docs/01_overview/code/01_introduction.py +0 -0
  43. {apify-2.7.1b14 → apify-2.7.1b16}/docs/01_overview/code/actor_structure/__init__.py +0 -0
  44. {apify-2.7.1b14 → apify-2.7.1b16}/docs/01_overview/code/actor_structure/__main__.py +0 -0
  45. {apify-2.7.1b14 → apify-2.7.1b16}/docs/01_overview/code/actor_structure/main.py +0 -0
  46. {apify-2.7.1b14 → apify-2.7.1b16}/docs/01_overview/code/actor_structure/py.typed +0 -0
  47. {apify-2.7.1b14 → apify-2.7.1b16}/docs/02_concepts/01_actor_lifecycle.mdx +0 -0
  48. {apify-2.7.1b14 → apify-2.7.1b16}/docs/02_concepts/02_actor_input.mdx +0 -0
  49. {apify-2.7.1b14 → apify-2.7.1b16}/docs/02_concepts/03_storages.mdx +0 -0
  50. {apify-2.7.1b14 → apify-2.7.1b16}/docs/02_concepts/04_actor_events.mdx +0 -0
  51. {apify-2.7.1b14 → apify-2.7.1b16}/docs/02_concepts/05_proxy_management.mdx +0 -0
  52. {apify-2.7.1b14 → apify-2.7.1b16}/docs/02_concepts/06_interacting_with_other_actors.mdx +0 -0
  53. {apify-2.7.1b14 → apify-2.7.1b16}/docs/02_concepts/07_webhooks.mdx +0 -0
  54. {apify-2.7.1b14 → apify-2.7.1b16}/docs/02_concepts/08_access_apify_api.mdx +0 -0
  55. {apify-2.7.1b14 → apify-2.7.1b16}/docs/02_concepts/09_running_webserver.mdx +0 -0
  56. {apify-2.7.1b14 → apify-2.7.1b16}/docs/02_concepts/10_logging.mdx +0 -0
  57. {apify-2.7.1b14 → apify-2.7.1b16}/docs/02_concepts/11_configuration.mdx +0 -0
  58. {apify-2.7.1b14 → apify-2.7.1b16}/docs/02_concepts/12_pay_per_event.mdx +0 -0
  59. {apify-2.7.1b14 → apify-2.7.1b16}/docs/02_concepts/code/01_context_manager.py +0 -0
  60. {apify-2.7.1b14 → apify-2.7.1b16}/docs/02_concepts/code/01_init_exit.py +0 -0
  61. {apify-2.7.1b14 → apify-2.7.1b16}/docs/02_concepts/code/01_reboot.py +0 -0
  62. {apify-2.7.1b14 → apify-2.7.1b16}/docs/02_concepts/code/01_status_message.py +0 -0
  63. {apify-2.7.1b14 → apify-2.7.1b16}/docs/02_concepts/code/02_input.py +0 -0
  64. {apify-2.7.1b14 → apify-2.7.1b16}/docs/02_concepts/code/03_dataset_exports.py +0 -0
  65. {apify-2.7.1b14 → apify-2.7.1b16}/docs/02_concepts/code/03_dataset_read_write.py +0 -0
  66. {apify-2.7.1b14 → apify-2.7.1b16}/docs/02_concepts/code/03_deleting_storages.py +0 -0
  67. {apify-2.7.1b14 → apify-2.7.1b16}/docs/02_concepts/code/03_kvs_iterating.py +0 -0
  68. {apify-2.7.1b14 → apify-2.7.1b16}/docs/02_concepts/code/03_kvs_public_url.py +0 -0
  69. {apify-2.7.1b14 → apify-2.7.1b16}/docs/02_concepts/code/03_kvs_read_write.py +0 -0
  70. {apify-2.7.1b14 → apify-2.7.1b16}/docs/02_concepts/code/03_opening_storages.py +0 -0
  71. {apify-2.7.1b14 → apify-2.7.1b16}/docs/02_concepts/code/03_rq.py +0 -0
  72. {apify-2.7.1b14 → apify-2.7.1b16}/docs/02_concepts/code/04_actor_events.py +0 -0
  73. {apify-2.7.1b14 → apify-2.7.1b16}/docs/02_concepts/code/05_apify_proxy.py +0 -0
  74. {apify-2.7.1b14 → apify-2.7.1b16}/docs/02_concepts/code/05_apify_proxy_config.py +0 -0
  75. {apify-2.7.1b14 → apify-2.7.1b16}/docs/02_concepts/code/05_custom_proxy.py +0 -0
  76. {apify-2.7.1b14 → apify-2.7.1b16}/docs/02_concepts/code/05_custom_proxy_function.py +0 -0
  77. {apify-2.7.1b14 → apify-2.7.1b16}/docs/02_concepts/code/05_proxy_actor_input.py +0 -0
  78. {apify-2.7.1b14 → apify-2.7.1b16}/docs/02_concepts/code/05_proxy_httpx.py +0 -0
  79. {apify-2.7.1b14 → apify-2.7.1b16}/docs/02_concepts/code/05_proxy_rotation.py +0 -0
  80. {apify-2.7.1b14 → apify-2.7.1b16}/docs/02_concepts/code/06_interacting_call.py +0 -0
  81. {apify-2.7.1b14 → apify-2.7.1b16}/docs/02_concepts/code/06_interacting_call_task.py +0 -0
  82. {apify-2.7.1b14 → apify-2.7.1b16}/docs/02_concepts/code/06_interacting_metamorph.py +0 -0
  83. {apify-2.7.1b14 → apify-2.7.1b16}/docs/02_concepts/code/06_interacting_start.py +0 -0
  84. {apify-2.7.1b14 → apify-2.7.1b16}/docs/02_concepts/code/07_webhook.py +0 -0
  85. {apify-2.7.1b14 → apify-2.7.1b16}/docs/02_concepts/code/07_webhook_preventing.py +0 -0
  86. {apify-2.7.1b14 → apify-2.7.1b16}/docs/02_concepts/code/08_actor_client.py +0 -0
  87. {apify-2.7.1b14 → apify-2.7.1b16}/docs/02_concepts/code/08_actor_new_client.py +0 -0
  88. {apify-2.7.1b14 → apify-2.7.1b16}/docs/02_concepts/code/09_webserver.py +0 -0
  89. {apify-2.7.1b14 → apify-2.7.1b16}/docs/02_concepts/code/10_log_config.py +0 -0
  90. {apify-2.7.1b14 → apify-2.7.1b16}/docs/02_concepts/code/10_logger_usage.py +0 -0
  91. {apify-2.7.1b14 → apify-2.7.1b16}/docs/02_concepts/code/10_redirect_log.py +0 -0
  92. {apify-2.7.1b14 → apify-2.7.1b16}/docs/02_concepts/code/10_redirect_log_existing_run.py +0 -0
  93. {apify-2.7.1b14 → apify-2.7.1b16}/docs/02_concepts/code/11_config.py +0 -0
  94. {apify-2.7.1b14 → apify-2.7.1b16}/docs/02_concepts/code/actor_charge.py +0 -0
  95. {apify-2.7.1b14 → apify-2.7.1b16}/docs/02_concepts/code/conditional_actor_charge.py +0 -0
  96. {apify-2.7.1b14 → apify-2.7.1b16}/docs/03_guides/01_beautifulsoup_httpx.mdx +0 -0
  97. {apify-2.7.1b14 → apify-2.7.1b16}/docs/03_guides/02_parsel_impit.mdx +0 -0
  98. {apify-2.7.1b14 → apify-2.7.1b16}/docs/03_guides/03_playwright.mdx +0 -0
  99. {apify-2.7.1b14 → apify-2.7.1b16}/docs/03_guides/04_selenium.mdx +0 -0
  100. {apify-2.7.1b14 → apify-2.7.1b16}/docs/03_guides/05_crawlee.mdx +0 -0
  101. {apify-2.7.1b14 → apify-2.7.1b16}/docs/03_guides/06_scrapy.mdx +0 -0
  102. {apify-2.7.1b14 → apify-2.7.1b16}/docs/03_guides/code/01_beautifulsoup_httpx.py +0 -0
  103. {apify-2.7.1b14 → apify-2.7.1b16}/docs/03_guides/code/02_parsel_impit.py +0 -0
  104. {apify-2.7.1b14 → apify-2.7.1b16}/docs/03_guides/code/03_playwright.py +0 -0
  105. {apify-2.7.1b14 → apify-2.7.1b16}/docs/03_guides/code/04_selenium.py +0 -0
  106. {apify-2.7.1b14 → apify-2.7.1b16}/docs/03_guides/code/05_crawlee_beautifulsoup.py +0 -0
  107. {apify-2.7.1b14 → apify-2.7.1b16}/docs/03_guides/code/05_crawlee_parsel.py +0 -0
  108. {apify-2.7.1b14 → apify-2.7.1b16}/docs/03_guides/code/05_crawlee_playwright.py +0 -0
  109. {apify-2.7.1b14 → apify-2.7.1b16}/docs/03_guides/code/scrapy_project/src/__init__.py +0 -0
  110. {apify-2.7.1b14 → apify-2.7.1b16}/docs/03_guides/code/scrapy_project/src/__main__.py +0 -0
  111. {apify-2.7.1b14 → apify-2.7.1b16}/docs/03_guides/code/scrapy_project/src/items.py +0 -0
  112. {apify-2.7.1b14 → apify-2.7.1b16}/docs/03_guides/code/scrapy_project/src/main.py +0 -0
  113. {apify-2.7.1b14 → apify-2.7.1b16}/docs/03_guides/code/scrapy_project/src/py.typed +0 -0
  114. {apify-2.7.1b14 → apify-2.7.1b16}/docs/03_guides/code/scrapy_project/src/settings.py +0 -0
  115. {apify-2.7.1b14 → apify-2.7.1b16}/docs/03_guides/code/scrapy_project/src/spiders/__init__.py +0 -0
  116. {apify-2.7.1b14 → apify-2.7.1b16}/docs/03_guides/code/scrapy_project/src/spiders/py.typed +0 -0
  117. {apify-2.7.1b14 → apify-2.7.1b16}/docs/03_guides/code/scrapy_project/src/spiders/title.py +0 -0
  118. {apify-2.7.1b14 → apify-2.7.1b16}/docs/04_upgrading/upgrading_to_v2.md +0 -0
  119. {apify-2.7.1b14 → apify-2.7.1b16}/docs/04_upgrading/upgrading_to_v3.md +0 -0
  120. {apify-2.7.1b14 → apify-2.7.1b16}/docs/pyproject.toml +0 -0
  121. {apify-2.7.1b14 → apify-2.7.1b16}/renovate.json +0 -0
  122. {apify-2.7.1b14 → apify-2.7.1b16}/src/apify/__init__.py +0 -0
  123. {apify-2.7.1b14 → apify-2.7.1b16}/src/apify/_charging.py +0 -0
  124. {apify-2.7.1b14 → apify-2.7.1b16}/src/apify/_configuration.py +0 -0
  125. {apify-2.7.1b14 → apify-2.7.1b16}/src/apify/_consts.py +0 -0
  126. {apify-2.7.1b14 → apify-2.7.1b16}/src/apify/_crypto.py +0 -0
  127. {apify-2.7.1b14 → apify-2.7.1b16}/src/apify/_models.py +0 -0
  128. {apify-2.7.1b14 → apify-2.7.1b16}/src/apify/_proxy_configuration.py +0 -0
  129. {apify-2.7.1b14 → apify-2.7.1b16}/src/apify/_utils.py +0 -0
  130. {apify-2.7.1b14 → apify-2.7.1b16}/src/apify/events/_apify_event_manager.py +0 -0
  131. {apify-2.7.1b14 → apify-2.7.1b16}/src/apify/events/_types.py +0 -0
  132. {apify-2.7.1b14 → apify-2.7.1b16}/src/apify/events/py.typed +0 -0
  133. {apify-2.7.1b14 → apify-2.7.1b16}/src/apify/log.py +0 -0
  134. {apify-2.7.1b14 → apify-2.7.1b16}/src/apify/py.typed +0 -0
  135. {apify-2.7.1b14 → apify-2.7.1b16}/src/apify/request_loaders/__init__.py +0 -0
  136. {apify-2.7.1b14 → apify-2.7.1b16}/src/apify/request_loaders/_apify_request_list.py +0 -0
  137. {apify-2.7.1b14 → apify-2.7.1b16}/src/apify/request_loaders/py.typed +0 -0
  138. {apify-2.7.1b14 → apify-2.7.1b16}/src/apify/scrapy/__init__.py +0 -0
  139. {apify-2.7.1b14 → apify-2.7.1b16}/src/apify/scrapy/_actor_runner.py +0 -0
  140. {apify-2.7.1b14 → apify-2.7.1b16}/src/apify/scrapy/_async_thread.py +0 -0
  141. {apify-2.7.1b14 → apify-2.7.1b16}/src/apify/scrapy/_logging_config.py +0 -0
  142. {apify-2.7.1b14 → apify-2.7.1b16}/src/apify/scrapy/extensions/__init__.py +0 -0
  143. {apify-2.7.1b14 → apify-2.7.1b16}/src/apify/scrapy/extensions/_httpcache.py +0 -0
  144. {apify-2.7.1b14 → apify-2.7.1b16}/src/apify/scrapy/middlewares/__init__.py +0 -0
  145. {apify-2.7.1b14 → apify-2.7.1b16}/src/apify/scrapy/middlewares/apify_proxy.py +0 -0
  146. {apify-2.7.1b14 → apify-2.7.1b16}/src/apify/scrapy/middlewares/py.typed +0 -0
  147. {apify-2.7.1b14 → apify-2.7.1b16}/src/apify/scrapy/pipelines/__init__.py +0 -0
  148. {apify-2.7.1b14 → apify-2.7.1b16}/src/apify/scrapy/pipelines/actor_dataset_push.py +0 -0
  149. {apify-2.7.1b14 → apify-2.7.1b16}/src/apify/scrapy/pipelines/py.typed +0 -0
  150. {apify-2.7.1b14 → apify-2.7.1b16}/src/apify/scrapy/py.typed +0 -0
  151. {apify-2.7.1b14 → apify-2.7.1b16}/src/apify/scrapy/requests.py +0 -0
  152. {apify-2.7.1b14 → apify-2.7.1b16}/src/apify/scrapy/scheduler.py +0 -0
  153. {apify-2.7.1b14 → apify-2.7.1b16}/src/apify/scrapy/utils.py +0 -0
  154. {apify-2.7.1b14 → apify-2.7.1b16}/src/apify/storage_clients/__init__.py +0 -0
  155. {apify-2.7.1b14 → apify-2.7.1b16}/src/apify/storage_clients/_apify/__init__.py +0 -0
  156. {apify-2.7.1b14 → apify-2.7.1b16}/src/apify/storage_clients/_apify/_models.py +0 -0
  157. {apify-2.7.1b14 → apify-2.7.1b16}/src/apify/storage_clients/_apify/py.typed +0 -0
  158. {apify-2.7.1b14 → apify-2.7.1b16}/src/apify/storage_clients/_file_system/__init__.py +0 -0
  159. {apify-2.7.1b14 → apify-2.7.1b16}/src/apify/storage_clients/py.typed +0 -0
  160. {apify-2.7.1b14 → apify-2.7.1b16}/src/apify/storages/__init__.py +0 -0
  161. {apify-2.7.1b14 → apify-2.7.1b16}/src/apify/storages/py.typed +0 -0
  162. {apify-2.7.1b14 → apify-2.7.1b16}/tests/integration/README.md +0 -0
  163. {apify-2.7.1b14 → apify-2.7.1b16}/tests/integration/__init__.py +0 -0
  164. {apify-2.7.1b14 → apify-2.7.1b16}/tests/integration/_utils.py +0 -0
  165. {apify-2.7.1b14 → apify-2.7.1b16}/tests/integration/actor_source_base/Dockerfile +0 -0
  166. {apify-2.7.1b14 → apify-2.7.1b16}/tests/integration/actor_source_base/server.py +0 -0
  167. {apify-2.7.1b14 → apify-2.7.1b16}/tests/integration/actor_source_base/src/__init__.py +0 -0
  168. {apify-2.7.1b14 → apify-2.7.1b16}/tests/integration/actor_source_base/src/__main__.py +0 -0
  169. {apify-2.7.1b14 → apify-2.7.1b16}/tests/integration/actor_source_base/src/main.py +0 -0
  170. {apify-2.7.1b14 → apify-2.7.1b16}/tests/integration/conftest.py +0 -0
  171. {apify-2.7.1b14 → apify-2.7.1b16}/tests/integration/test_actor_api_helpers.py +0 -0
  172. {apify-2.7.1b14 → apify-2.7.1b16}/tests/integration/test_actor_call_timeouts.py +0 -0
  173. {apify-2.7.1b14 → apify-2.7.1b16}/tests/integration/test_actor_charge.py +0 -0
  174. {apify-2.7.1b14 → apify-2.7.1b16}/tests/integration/test_actor_create_proxy_configuration.py +0 -0
  175. {apify-2.7.1b14 → apify-2.7.1b16}/tests/integration/test_actor_events.py +0 -0
  176. {apify-2.7.1b14 → apify-2.7.1b16}/tests/integration/test_actor_lifecycle.py +0 -0
  177. {apify-2.7.1b14 → apify-2.7.1b16}/tests/integration/test_actor_log.py +0 -0
  178. {apify-2.7.1b14 → apify-2.7.1b16}/tests/integration/test_actor_scrapy.py +0 -0
  179. {apify-2.7.1b14 → apify-2.7.1b16}/tests/integration/test_crawlers_with_storages.py +0 -0
  180. {apify-2.7.1b14 → apify-2.7.1b16}/tests/integration/test_fixtures.py +0 -0
  181. {apify-2.7.1b14 → apify-2.7.1b16}/tests/integration/test_request_queue.py +0 -0
  182. {apify-2.7.1b14 → apify-2.7.1b16}/tests/unit/__init__.py +0 -0
  183. {apify-2.7.1b14 → apify-2.7.1b16}/tests/unit/actor/__init__.py +0 -0
  184. {apify-2.7.1b14 → apify-2.7.1b16}/tests/unit/actor/test_actor_create_proxy_configuration.py +0 -0
  185. {apify-2.7.1b14 → apify-2.7.1b16}/tests/unit/actor/test_actor_dataset.py +0 -0
  186. {apify-2.7.1b14 → apify-2.7.1b16}/tests/unit/actor/test_actor_env_helpers.py +0 -0
  187. {apify-2.7.1b14 → apify-2.7.1b16}/tests/unit/actor/test_actor_helpers.py +0 -0
  188. {apify-2.7.1b14 → apify-2.7.1b16}/tests/unit/actor/test_actor_key_value_store.py +0 -0
  189. {apify-2.7.1b14 → apify-2.7.1b16}/tests/unit/actor/test_actor_lifecycle.py +0 -0
  190. {apify-2.7.1b14 → apify-2.7.1b16}/tests/unit/actor/test_actor_log.py +0 -0
  191. {apify-2.7.1b14 → apify-2.7.1b16}/tests/unit/actor/test_actor_non_default_instance.py +0 -0
  192. {apify-2.7.1b14 → apify-2.7.1b16}/tests/unit/actor/test_actor_request_queue.py +0 -0
  193. {apify-2.7.1b14 → apify-2.7.1b16}/tests/unit/actor/test_configuration.py +0 -0
  194. {apify-2.7.1b14 → apify-2.7.1b16}/tests/unit/actor/test_request_list.py +0 -0
  195. {apify-2.7.1b14 → apify-2.7.1b16}/tests/unit/conftest.py +0 -0
  196. {apify-2.7.1b14 → apify-2.7.1b16}/tests/unit/events/__init__.py +0 -0
  197. {apify-2.7.1b14 → apify-2.7.1b16}/tests/unit/scrapy/__init__.py +0 -0
  198. {apify-2.7.1b14 → apify-2.7.1b16}/tests/unit/scrapy/extensions/__init__.py +0 -0
  199. {apify-2.7.1b14 → apify-2.7.1b16}/tests/unit/scrapy/middlewares/__init__.py +0 -0
  200. {apify-2.7.1b14 → apify-2.7.1b16}/tests/unit/scrapy/middlewares/test_apify_proxy.py +0 -0
  201. {apify-2.7.1b14 → apify-2.7.1b16}/tests/unit/scrapy/pipelines/__init__.py +0 -0
  202. {apify-2.7.1b14 → apify-2.7.1b16}/tests/unit/scrapy/pipelines/test_actor_dataset_push.py +0 -0
  203. {apify-2.7.1b14 → apify-2.7.1b16}/tests/unit/scrapy/requests/__init__.py +0 -0
  204. {apify-2.7.1b14 → apify-2.7.1b16}/tests/unit/scrapy/requests/test_to_apify_request.py +0 -0
  205. {apify-2.7.1b14 → apify-2.7.1b16}/tests/unit/scrapy/requests/test_to_scrapy_request.py +0 -0
  206. {apify-2.7.1b14 → apify-2.7.1b16}/tests/unit/scrapy/utils/__init__.py +0 -0
  207. {apify-2.7.1b14 → apify-2.7.1b16}/tests/unit/scrapy/utils/test_apply_apify_settings.py +0 -0
  208. {apify-2.7.1b14 → apify-2.7.1b16}/tests/unit/scrapy/utils/test_get_basic_auth_header.py +0 -0
  209. {apify-2.7.1b14 → apify-2.7.1b16}/tests/unit/storage_clients/__init__.py +0 -0
  210. {apify-2.7.1b14 → apify-2.7.1b16}/tests/unit/storage_clients/test_apify_request_queue_client.py +0 -0
  211. {apify-2.7.1b14 → apify-2.7.1b16}/website/.eslintrc.json +0 -0
  212. {apify-2.7.1b14 → apify-2.7.1b16}/website/babel.config.js +0 -0
  213. {apify-2.7.1b14 → apify-2.7.1b16}/website/build_api_reference.sh +0 -0
  214. {apify-2.7.1b14 → apify-2.7.1b16}/website/docusaurus.config.js +0 -0
  215. {apify-2.7.1b14 → apify-2.7.1b16}/website/generate_module_shortcuts.py +0 -0
  216. {apify-2.7.1b14 → apify-2.7.1b16}/website/package-lock.json +0 -0
  217. {apify-2.7.1b14 → apify-2.7.1b16}/website/package.json +0 -0
  218. {apify-2.7.1b14 → apify-2.7.1b16}/website/sidebars.js +0 -0
  219. {apify-2.7.1b14 → apify-2.7.1b16}/website/src/components/ApiLink.jsx +0 -0
  220. {apify-2.7.1b14 → apify-2.7.1b16}/website/src/components/Gradients.jsx +0 -0
  221. {apify-2.7.1b14 → apify-2.7.1b16}/website/src/components/Highlights.jsx +0 -0
  222. {apify-2.7.1b14 → apify-2.7.1b16}/website/src/components/Highlights.module.css +0 -0
  223. {apify-2.7.1b14 → apify-2.7.1b16}/website/src/components/RunnableCodeBlock.jsx +0 -0
  224. {apify-2.7.1b14 → apify-2.7.1b16}/website/src/components/RunnableCodeBlock.module.css +0 -0
  225. {apify-2.7.1b14 → apify-2.7.1b16}/website/src/css/custom.css +0 -0
  226. {apify-2.7.1b14 → apify-2.7.1b16}/website/src/pages/home_page_example.py +0 -0
  227. {apify-2.7.1b14 → apify-2.7.1b16}/website/src/pages/index.js +0 -0
  228. {apify-2.7.1b14 → apify-2.7.1b16}/website/src/pages/index.module.css +0 -0
  229. {apify-2.7.1b14 → apify-2.7.1b16}/website/src/theme/DocItem/Content/index.js +0 -0
  230. {apify-2.7.1b14 → apify-2.7.1b16}/website/static/.nojekyll +0 -0
  231. {apify-2.7.1b14 → apify-2.7.1b16}/website/static/img/docs-og.png +0 -0
  232. {apify-2.7.1b14 → apify-2.7.1b16}/website/static/img/guides/redirected_logs_example.webp +0 -0
  233. {apify-2.7.1b14 → apify-2.7.1b16}/website/tools/docs-prettier.config.js +0 -0
  234. {apify-2.7.1b14 → apify-2.7.1b16}/website/tools/utils/externalLink.js +0 -0
@@ -9,6 +9,7 @@ All notable changes to this project will be documented in this file.
9
9
 
10
10
  - Add deduplication to `add_batch_of_requests` ([#534](https://github.com/apify/apify-sdk-python/pull/534)) ([dd03c4d](https://github.com/apify/apify-sdk-python/commit/dd03c4d446f611492adf35f1b5738648ee5a66f7)) by [@Pijukatel](https://github.com/Pijukatel), closes [#514](https://github.com/apify/apify-sdk-python/issues/514)
11
11
  - Add new methods to ChargingManager ([#580](https://github.com/apify/apify-sdk-python/pull/580)) ([54f7f8b](https://github.com/apify/apify-sdk-python/commit/54f7f8b29c5982be98b595dac11eceff915035c9)) by [@vdusek](https://github.com/vdusek)
12
+ - Add support for NDU storages ([#594](https://github.com/apify/apify-sdk-python/pull/594)) ([8721ef5](https://github.com/apify/apify-sdk-python/commit/8721ef5731bcb1a04ad63c930089bf83be29f308)) by [@vdusek](https://github.com/vdusek), closes [#1175](https://github.com/apify/apify-sdk-python/issues/1175)
12
13
 
13
14
  ### 🐛 Bug Fixes
14
15
 
@@ -16,6 +17,7 @@ All notable changes to this project will be documented in this file.
16
17
  - 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)
17
18
  - Resolve DeprecationWarning in ApifyEventManager ([#555](https://github.com/apify/apify-sdk-python/pull/555)) ([0c5111d](https://github.com/apify/apify-sdk-python/commit/0c5111dafe19796ec1fb9652a44c031bed9758df)) by [@vdusek](https://github.com/vdusek), closes [#343](https://github.com/apify/apify-sdk-python/issues/343)
18
19
  - Use same `client_key` for `Actor` created `request_queue` and improve its metadata estimation ([#552](https://github.com/apify/apify-sdk-python/pull/552)) ([7e4e5da](https://github.com/apify/apify-sdk-python/commit/7e4e5da81dd87e84ebeef2bd336c6c1d422cb9a7)) by [@Pijukatel](https://github.com/Pijukatel), closes [#536](https://github.com/apify/apify-sdk-python/issues/536)
20
+ - Properly process pre-existing Actor input file ([#591](https://github.com/apify/apify-sdk-python/pull/591)) ([cc5075f](https://github.com/apify/apify-sdk-python/commit/cc5075fab8c72ca5711cfd97932037b34e6997cd)) by [@Pijukatel](https://github.com/Pijukatel), closes [#590](https://github.com/apify/apify-sdk-python/issues/590)
19
21
 
20
22
  ### Chore
21
23
 
@@ -101,6 +103,30 @@ All notable changes to this project will be documented in this file.
101
103
  - 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)
102
104
 
103
105
 
106
+ ## [2.7.0](https://github.com/apify/apify-sdk-python/releases/tag/v2.7.0) (2025-07-14)
107
+
108
+ ### 🚀 Features
109
+
110
+ - **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)
111
+
112
+ ### 🐛 Bug Fixes
113
+
114
+ - Sync `@docusaurus` theme version [internal] ([#500](https://github.com/apify/apify-sdk-python/pull/500)) ([a7485e7](https://github.com/apify/apify-sdk-python/commit/a7485e7d2276fde464ce862573d5b95e7d4d836a)) by [@katzino](https://github.com/katzino)
115
+ - 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)
116
+
117
+
118
+ ## [2.7.0](https://github.com/apify/apify-sdk-python/releases/tag/v2.7.0) (2025-07-14)
119
+
120
+ ### 🚀 Features
121
+
122
+ - **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)
123
+
124
+ ### 🐛 Bug Fixes
125
+
126
+ - Sync `@docusaurus` theme version [internal] ([#500](https://github.com/apify/apify-sdk-python/pull/500)) ([a7485e7](https://github.com/apify/apify-sdk-python/commit/a7485e7d2276fde464ce862573d5b95e7d4d836a)) by [@katzino](https://github.com/katzino)
127
+ - 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)
128
+
129
+
104
130
 
105
131
  ## [2.7.3](https://github.com/apify/apify-sdk-python/releases/tag/v2.7.3) (2025-08-11)
106
132
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: apify
3
- Version: 2.7.1b14
3
+ Version: 2.7.1b16
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
@@ -228,7 +228,7 @@ Requires-Python: >=3.10
228
228
  Requires-Dist: apify-client<3.0.0,>=2.0.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==1.0.0rc1
231
+ Requires-Dist: crawlee==0.6.13b37
232
232
  Requires-Dist: cryptography>=42.0.0
233
233
  Requires-Dist: impit>=0.5.3
234
234
  Requires-Dist: lazy-object-proxy>=1.11.0
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "apify"
7
- version = "2.7.1b14"
7
+ version = "2.7.1b16"
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" }
@@ -36,7 +36,7 @@ keywords = [
36
36
  dependencies = [
37
37
  "apify-client>=2.0.0,<3.0.0",
38
38
  "apify-shared>=2.0.0,<3.0.0",
39
- "crawlee==1.0.0rc1",
39
+ "crawlee==0.6.13b37",
40
40
  "cachetools>=5.5.0",
41
41
  "cryptography>=42.0.0",
42
42
  "impit>=0.5.3",
@@ -66,16 +66,16 @@ dev = [
66
66
  "crawlee[parsel]",
67
67
  "dycw-pytest-only~=2.1.0",
68
68
  "griffe",
69
- "mypy~=1.17.0",
69
+ "mypy~=1.18.1",
70
70
  "pre-commit~=4.3.0",
71
71
  "pydoc-markdown~=4.8.0",
72
- "pytest-asyncio~=1.1.0",
72
+ "pytest-asyncio~=1.2.0",
73
73
  "pytest-cov~=7.0.0",
74
74
  "pytest-httpserver~=1.1.0",
75
75
  "pytest-timeout~=2.4.0",
76
76
  "pytest-xdist~=3.8.0",
77
77
  "pytest~=8.4.0",
78
- "ruff~=0.12.0",
78
+ "ruff~=0.13.0",
79
79
  "setuptools", # setuptools are used by pytest but not explicitly required
80
80
  "types-cachetools~=6.2.0.20250827",
81
81
  "uvicorn[standard]",
@@ -401,6 +401,7 @@ class _ActorType:
401
401
  self,
402
402
  *,
403
403
  id: str | None = None,
404
+ alias: str | None = None,
404
405
  name: str | None = None,
405
406
  force_cloud: bool = False,
406
407
  ) -> Dataset:
@@ -411,10 +412,12 @@ class _ActorType:
411
412
  the Apify cloud.
412
413
 
413
414
  Args:
414
- id: ID of the dataset to be opened. If neither `id` nor `name` are provided, the method returns
415
- the default dataset associated with the Actor run.
416
- name: Name of the dataset to be opened. If neither `id` nor `name` are provided, the method returns
417
- the default dataset associated with the Actor run.
415
+ id: The ID of the dataset to open. If provided, searches for existing dataset by ID.
416
+ Mutually exclusive with name and alias.
417
+ name: The name of the dataset to open (global scope, persists across runs).
418
+ Mutually exclusive with id and alias.
419
+ alias: The alias of the dataset to open (run scope, creates unnamed storage).
420
+ Mutually exclusive with id and name.
418
421
  force_cloud: If set to `True` then the Apify cloud storage is always used. This way it is possible
419
422
  to combine local and cloud storage.
420
423
 
@@ -428,6 +431,7 @@ class _ActorType:
428
431
 
429
432
  return await Dataset.open(
430
433
  id=id,
434
+ alias=alias,
431
435
  name=name,
432
436
  configuration=self._configuration,
433
437
  storage_client=storage_client,
@@ -437,6 +441,7 @@ class _ActorType:
437
441
  self,
438
442
  *,
439
443
  id: str | None = None,
444
+ alias: str | None = None,
440
445
  name: str | None = None,
441
446
  force_cloud: bool = False,
442
447
  ) -> KeyValueStore:
@@ -446,10 +451,12 @@ class _ActorType:
446
451
  and retrieved using a unique key. The actual data is stored either on a local filesystem or in the Apify cloud.
447
452
 
448
453
  Args:
449
- id: ID of the key-value store to be opened. If neither `id` nor `name` are provided, the method returns
450
- the default key-value store associated with the Actor run.
451
- name: Name of the key-value store to be opened. If neither `id` nor `name` are provided, the method
452
- returns the default key-value store associated with the Actor run.
454
+ id: The ID of the KVS to open. If provided, searches for existing KVS by ID.
455
+ Mutually exclusive with name and alias.
456
+ name: The name of the KVS to open (global scope, persists across runs).
457
+ Mutually exclusive with id and alias.
458
+ alias: The alias of the KVS to open (run scope, creates unnamed storage).
459
+ Mutually exclusive with id and name.
453
460
  force_cloud: If set to `True` then the Apify cloud storage is always used. This way it is possible
454
461
  to combine local and cloud storage.
455
462
 
@@ -462,6 +469,7 @@ class _ActorType:
462
469
 
463
470
  return await KeyValueStore.open(
464
471
  id=id,
472
+ alias=alias,
465
473
  name=name,
466
474
  configuration=self._configuration,
467
475
  storage_client=storage_client,
@@ -471,6 +479,7 @@ class _ActorType:
471
479
  self,
472
480
  *,
473
481
  id: str | None = None,
482
+ alias: str | None = None,
474
483
  name: str | None = None,
475
484
  force_cloud: bool = False,
476
485
  ) -> RequestQueue:
@@ -482,10 +491,12 @@ class _ActorType:
482
491
  crawling orders.
483
492
 
484
493
  Args:
485
- id: ID of the request queue to be opened. If neither `id` nor `name` are provided, the method returns
486
- the default request queue associated with the Actor run.
487
- name: Name of the request queue to be opened. If neither `id` nor `name` are provided, the method returns
488
- the default request queue associated with the Actor run.
494
+ id: The ID of the RQ to open. If provided, searches for existing RQ by ID.
495
+ Mutually exclusive with name and alias.
496
+ name: The name of the RQ to open (global scope, persists across runs).
497
+ Mutually exclusive with id and alias.
498
+ alias: The alias of the RQ to open (run scope, creates unnamed storage).
499
+ Mutually exclusive with id and name.
489
500
  force_cloud: If set to `True` then the Apify cloud storage is always used. This way it is possible
490
501
  to combine local and cloud storage.
491
502
 
@@ -499,6 +510,7 @@ class _ActorType:
499
510
 
500
511
  return await RequestQueue.open(
501
512
  id=id,
513
+ alias=alias,
502
514
  name=name,
503
515
  configuration=self._configuration,
504
516
  storage_client=storage_client,
@@ -0,0 +1,5 @@
1
+ from crawlee.events import Event, EventManager, LocalEventManager
2
+
3
+ from ._apify_event_manager import ApifyEventManager
4
+
5
+ __all__ = ['ApifyEventManager', 'Event', 'EventManager', 'LocalEventManager']
@@ -12,6 +12,8 @@ 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
 
15
+ from ._utils import resolve_alias_to_id, store_alias_mapping
16
+
15
17
  if TYPE_CHECKING:
16
18
  from collections.abc import AsyncIterator
17
19
 
@@ -66,6 +68,7 @@ class ApifyDatasetClient(DatasetClient):
66
68
  *,
67
69
  id: str | None,
68
70
  name: str | None,
71
+ alias: str | None,
69
72
  configuration: Configuration,
70
73
  ) -> ApifyDatasetClient:
71
74
  """Open an Apify dataset client.
@@ -74,22 +77,27 @@ class ApifyDatasetClient(DatasetClient):
74
77
  It handles authentication, storage lookup/creation, and metadata retrieval.
75
78
 
76
79
  Args:
77
- id: The ID of an existing dataset to open. If provided, the client will connect to this specific storage.
78
- Cannot be used together with `name`.
79
- name: The name of a dataset to get or create. If a storage with this name exists, it will be opened;
80
- otherwise, a new one will be created. Cannot be used together with `id`.
80
+ id: The ID of the dataset to open. If provided, searches for existing dataset by ID.
81
+ Mutually exclusive with name and alias.
82
+ name: The name of the dataset to open (global scope, persists across runs).
83
+ Mutually exclusive with id and alias.
84
+ alias: The alias of the dataset to open (run scope, creates unnamed storage).
85
+ Mutually exclusive with id and name.
81
86
  configuration: The configuration object containing API credentials and settings. Must include a valid
82
87
  `token` and `api_base_url`. May also contain a `default_dataset_id` for fallback when neither
83
- `id` nor `name` is provided.
88
+ `id`, `name`, nor `alias` is provided.
84
89
 
85
90
  Returns:
86
91
  An instance for the opened or created storage client.
87
92
 
88
93
  Raises:
89
- ValueError: If the configuration is missing required fields (token, api_base_url), if both `id` and `name`
90
- are provided, or if neither `id` nor `name` is provided and no default storage ID is available in
91
- the configuration.
94
+ ValueError: If the configuration is missing required fields (token, api_base_url), if more than one of
95
+ `id`, `name`, or `alias` is provided, or if none are provided and no default storage ID is available
96
+ in the configuration.
92
97
  """
98
+ if sum(1 for param in [id, name, alias] if param is not None) > 1:
99
+ raise ValueError('Only one of "id", "name", or "alias" can be specified, not multiple.')
100
+
93
101
  token = configuration.token
94
102
  if not token:
95
103
  raise ValueError(f'Apify storage client requires a valid token in Configuration (token={token}).')
@@ -115,27 +123,35 @@ class ApifyDatasetClient(DatasetClient):
115
123
  )
116
124
  apify_datasets_client = apify_client_async.datasets()
117
125
 
118
- # If both id and name are provided, raise an error.
119
- if id and name:
120
- raise ValueError('Only one of "id" or "name" can be specified, not both.')
126
+ # Normalize 'default' alias to None
127
+ alias = None if alias == 'default' else alias
121
128
 
122
- # If id is provided, get the storage by ID.
123
- if id and name is None:
124
- apify_dataset_client = apify_client_async.dataset(dataset_id=id)
129
+ # Handle alias resolution
130
+ if alias:
131
+ # Try to resolve alias to existing storage ID
132
+ resolved_id = await resolve_alias_to_id(alias, 'dataset', configuration)
133
+ if resolved_id:
134
+ id = resolved_id
135
+ else:
136
+ # Create a new storage and store the alias mapping
137
+ new_storage_metadata = DatasetMetadata.model_validate(
138
+ await apify_datasets_client.get_or_create(),
139
+ )
140
+ id = new_storage_metadata.id
141
+ await store_alias_mapping(alias, 'dataset', id, configuration)
125
142
 
126
143
  # If name is provided, get or create the storage by name.
127
- if name and id is None:
144
+ elif name:
128
145
  id = DatasetMetadata.model_validate(
129
146
  await apify_datasets_client.get_or_create(name=name),
130
147
  ).id
131
- apify_dataset_client = apify_client_async.dataset(dataset_id=id)
132
148
 
133
- # If both id and name are None, try to get the default storage ID from environment variables.
134
- # The default storage ID environment variable is set by the Apify platform. It also contains
135
- # a new storage ID after Actor's reboot or migration.
136
- if id is None and name is None:
149
+ # If none are provided, try to get the default storage ID from environment variables.
150
+ elif id is None:
137
151
  id = configuration.default_dataset_id
138
- apify_dataset_client = apify_client_async.dataset(dataset_id=id)
152
+
153
+ # Now create the client for the determined ID
154
+ apify_dataset_client = apify_client_async.dataset(dataset_id=id)
139
155
 
140
156
  # Fetch its metadata.
141
157
  metadata = await apify_dataset_client.get()
@@ -150,7 +166,7 @@ class ApifyDatasetClient(DatasetClient):
150
166
  # Verify that the storage exists by fetching its metadata again.
151
167
  metadata = await apify_dataset_client.get()
152
168
  if metadata is None:
153
- raise ValueError(f'Opening dataset with id={id} and name={name} failed.')
169
+ raise ValueError(f'Opening dataset with id={id}, name={name}, and alias={alias} failed.')
154
170
 
155
171
  return cls(
156
172
  api_client=apify_dataset_client,
@@ -12,6 +12,7 @@ from crawlee.storage_clients._base import KeyValueStoreClient
12
12
  from crawlee.storage_clients.models import KeyValueStoreRecord, KeyValueStoreRecordMetadata
13
13
 
14
14
  from ._models import ApifyKeyValueStoreMetadata, KeyValueStoreListKeysPage
15
+ from ._utils import resolve_alias_to_id, store_alias_mapping
15
16
  from apify._crypto import create_hmac_signature
16
17
 
17
18
  if TYPE_CHECKING:
@@ -58,6 +59,7 @@ class ApifyKeyValueStoreClient(KeyValueStoreClient):
58
59
  *,
59
60
  id: str | None,
60
61
  name: str | None,
62
+ alias: str | None,
61
63
  configuration: Configuration,
62
64
  ) -> ApifyKeyValueStoreClient:
63
65
  """Open an Apify key-value store client.
@@ -66,22 +68,27 @@ class ApifyKeyValueStoreClient(KeyValueStoreClient):
66
68
  It handles authentication, storage lookup/creation, and metadata retrieval.
67
69
 
68
70
  Args:
69
- id: The ID of an existing key-value store to open. If provided, the client will connect to this specific
70
- storage. Cannot be used together with `name`.
71
- name: The name of a key-value store to get or create. If a storage with this name exists, it will be
72
- opened; otherwise, a new one will be created. Cannot be used together with `id`.
71
+ id: The ID of the KVS to open. If provided, searches for existing KVS by ID.
72
+ Mutually exclusive with name and alias.
73
+ name: The name of the KVS to open (global scope, persists across runs).
74
+ Mutually exclusive with id and alias.
75
+ alias: The alias of the KVS to open (run scope, creates unnamed storage).
76
+ Mutually exclusive with id and name.
73
77
  configuration: The configuration object containing API credentials and settings. Must include a valid
74
78
  `token` and `api_base_url`. May also contain a `default_key_value_store_id` for fallback when
75
- neither `id` nor `name` is provided.
79
+ neither `id`, `name`, nor `alias` is provided.
76
80
 
77
81
  Returns:
78
82
  An instance for the opened or created storage client.
79
83
 
80
84
  Raises:
81
- ValueError: If the configuration is missing required fields (token, api_base_url), if both `id` and `name`
82
- are provided, or if neither `id` nor `name` is provided and no default storage ID is available
85
+ ValueError: If the configuration is missing required fields (token, api_base_url), if more than one of
86
+ `id`, `name`, or `alias` is provided, or if none are provided and no default storage ID is available
83
87
  in the configuration.
84
88
  """
89
+ if sum(1 for param in [id, name, alias] if param is not None) > 1:
90
+ raise ValueError('Only one of "id", "name", or "alias" can be specified, not multiple.')
91
+
85
92
  token = configuration.token
86
93
  if not token:
87
94
  raise ValueError(f'Apify storage client requires a valid token in Configuration (token={token}).')
@@ -107,27 +114,35 @@ class ApifyKeyValueStoreClient(KeyValueStoreClient):
107
114
  )
108
115
  apify_kvss_client = apify_client_async.key_value_stores()
109
116
 
110
- # If both id and name are provided, raise an error.
111
- if id and name:
112
- raise ValueError('Only one of "id" or "name" can be specified, not both.')
113
-
114
- # If id is provided, get the storage by ID.
115
- if id and name is None:
116
- apify_kvs_client = apify_client_async.key_value_store(key_value_store_id=id)
117
+ # Normalize 'default' alias to None
118
+ alias = None if alias == 'default' else alias
119
+
120
+ # Handle alias resolution
121
+ if alias:
122
+ # Try to resolve alias to existing storage ID
123
+ resolved_id = await resolve_alias_to_id(alias, 'kvs', configuration)
124
+ if resolved_id:
125
+ id = resolved_id
126
+ else:
127
+ # Create a new storage and store the alias mapping
128
+ new_storage_metadata = ApifyKeyValueStoreMetadata.model_validate(
129
+ await apify_kvss_client.get_or_create(),
130
+ )
131
+ id = new_storage_metadata.id
132
+ await store_alias_mapping(alias, 'kvs', id, configuration)
117
133
 
118
134
  # If name is provided, get or create the storage by name.
119
- if name and id is None:
135
+ elif name:
120
136
  id = ApifyKeyValueStoreMetadata.model_validate(
121
137
  await apify_kvss_client.get_or_create(name=name),
122
138
  ).id
123
- apify_kvs_client = apify_client_async.key_value_store(key_value_store_id=id)
124
139
 
125
- # If both id and name are None, try to get the default storage ID from environment variables.
126
- # The default storage ID environment variable is set by the Apify platform. It also contains
127
- # a new storage ID after Actor's reboot or migration.
128
- if id is None and name is None:
140
+ # If none are provided, try to get the default storage ID from environment variables.
141
+ elif id is None:
129
142
  id = configuration.default_key_value_store_id
130
- apify_kvs_client = apify_client_async.key_value_store(key_value_store_id=id)
143
+
144
+ # Now create the client for the determined ID
145
+ apify_kvs_client = apify_client_async.key_value_store(key_value_store_id=id)
131
146
 
132
147
  # Fetch its metadata.
133
148
  metadata = await apify_kvs_client.get()
@@ -142,7 +157,7 @@ class ApifyKeyValueStoreClient(KeyValueStoreClient):
142
157
  # Verify that the storage exists by fetching its metadata again.
143
158
  metadata = await apify_kvs_client.get()
144
159
  if metadata is None:
145
- raise ValueError(f'Opening key-value store with id={id} and name={name} failed.')
160
+ raise ValueError(f'Opening key-value store with id={id}, name={name}, and alias={alias} failed.')
146
161
 
147
162
  return cls(
148
163
  api_client=apify_kvs_client,
@@ -18,6 +18,7 @@ from crawlee.storage_clients._base import RequestQueueClient
18
18
  from crawlee.storage_clients.models import AddRequestsResponse, ProcessedRequest, RequestQueueMetadata
19
19
 
20
20
  from ._models import CachedRequest, ProlongRequestLockResponse, RequestQueueHead
21
+ from ._utils import resolve_alias_to_id, store_alias_mapping
21
22
  from apify import Request
22
23
 
23
24
  if TYPE_CHECKING:
@@ -135,6 +136,7 @@ class ApifyRequestQueueClient(RequestQueueClient):
135
136
  *,
136
137
  id: str | None,
137
138
  name: str | None,
139
+ alias: str | None,
138
140
  configuration: Configuration,
139
141
  ) -> ApifyRequestQueueClient:
140
142
  """Open an Apify request queue client.
@@ -144,22 +146,27 @@ class ApifyRequestQueueClient(RequestQueueClient):
144
146
  management structures.
145
147
 
146
148
  Args:
147
- id: The ID of an existing request queue to open. If provided, the client will connect to this specific
148
- storage. Cannot be used together with `name`.
149
- name: The name of a request queue to get or create. If a storage with this name exists, it will be opened;
150
- otherwise, a new one will be created. Cannot be used together with `id`.
149
+ id: The ID of the RQ to open. If provided, searches for existing RQ by ID.
150
+ Mutually exclusive with name and alias.
151
+ name: The name of the RQ to open (global scope, persists across runs).
152
+ Mutually exclusive with id and alias.
153
+ alias: The alias of the RQ to open (run scope, creates unnamed storage).
154
+ Mutually exclusive with id and name.
151
155
  configuration: The configuration object containing API credentials and settings. Must include a valid
152
156
  `token` and `api_base_url`. May also contain a `default_request_queue_id` for fallback when neither
153
- `id` nor `name` is provided.
157
+ `id`, `name`, nor `alias` is provided.
154
158
 
155
159
  Returns:
156
160
  An instance for the opened or created storage client.
157
161
 
158
162
  Raises:
159
- ValueError: If the configuration is missing required fields (token, api_base_url), if both `id` and `name`
160
- are provided, or if neither `id` nor `name` is provided and no default storage ID is available
163
+ ValueError: If the configuration is missing required fields (token, api_base_url), if more than one of
164
+ `id`, `name`, or `alias` is provided, or if none are provided and no default storage ID is available
161
165
  in the configuration.
162
166
  """
167
+ if sum(1 for param in [id, name, alias] if param is not None) > 1:
168
+ raise ValueError('Only one of "id", "name", or "alias" can be specified, not multiple.')
169
+
163
170
  token = configuration.token
164
171
  if not token:
165
172
  raise ValueError(f'Apify storage client requires a valid token in Configuration (token={token}).')
@@ -185,25 +192,32 @@ class ApifyRequestQueueClient(RequestQueueClient):
185
192
  )
186
193
  apify_rqs_client = apify_client_async.request_queues()
187
194
 
188
- match (id, name):
189
- case (None, None):
190
- # If both id and name are None, try to get the default storage ID from environment variables.
191
- # The default storage ID environment variable is set by the Apify platform. It also contains
192
- # a new storage ID after Actor's reboot or migration.
193
- id = configuration.default_request_queue_id
194
- case (None, name):
195
- # If only name is provided, get or create the storage by name.
196
- id = RequestQueueMetadata.model_validate(
197
- await apify_rqs_client.get_or_create(name=name),
198
- ).id
199
- case (_, None):
200
- # If only id is provided, use it.
201
- pass
202
- case (_, _):
203
- # If both id and name are provided, raise an error.
204
- raise ValueError('Only one of "id" or "name" can be specified, not both.')
205
- if id is None:
206
- raise RuntimeError('Unreachable code')
195
+ # Normalize 'default' alias to None
196
+ alias = None if alias == 'default' else alias
197
+
198
+ # Handle alias resolution
199
+ if alias:
200
+ # Try to resolve alias to existing storage ID
201
+ resolved_id = await resolve_alias_to_id(alias, 'rq', configuration)
202
+ if resolved_id:
203
+ id = resolved_id
204
+ else:
205
+ # Create a new storage and store the alias mapping
206
+ new_storage_metadata = RequestQueueMetadata.model_validate(
207
+ await apify_rqs_client.get_or_create(),
208
+ )
209
+ id = new_storage_metadata.id
210
+ await store_alias_mapping(alias, 'rq', id, configuration)
211
+
212
+ # If name is provided, get or create the storage by name.
213
+ elif name:
214
+ id = RequestQueueMetadata.model_validate(
215
+ await apify_rqs_client.get_or_create(name=name),
216
+ ).id
217
+
218
+ # If none are provided, try to get the default storage ID from environment variables.
219
+ elif id is None:
220
+ id = configuration.default_request_queue_id
207
221
 
208
222
  # Use suitable client_key to make `hadMultipleClients` response of Apify API useful.
209
223
  # It should persist across migrated or resurrected Actor runs on the Apify platform.
@@ -227,7 +241,7 @@ class ApifyRequestQueueClient(RequestQueueClient):
227
241
  # Verify that the storage exists by fetching its metadata again.
228
242
  metadata = await apify_rq_client.get()
229
243
  if metadata is None:
230
- raise ValueError(f'Opening request queue with id={id} and name={name} failed.')
244
+ raise ValueError(f'Opening request queue with id={id}, name={name}, and alias={alias} failed.')
231
245
 
232
246
  metadata_model = RequestQueueMetadata.model_validate(metadata)
233
247
 
@@ -25,6 +25,7 @@ class ApifyStorageClient(StorageClient):
25
25
  *,
26
26
  id: str | None = None,
27
27
  name: str | None = None,
28
+ alias: str | None = None,
28
29
  configuration: Configuration | None = None,
29
30
  ) -> ApifyDatasetClient:
30
31
  # Import here to avoid circular imports.
@@ -32,7 +33,7 @@ class ApifyStorageClient(StorageClient):
32
33
 
33
34
  configuration = configuration or ApifyConfiguration.get_global_configuration()
34
35
  if isinstance(configuration, ApifyConfiguration):
35
- return await ApifyDatasetClient.open(id=id, name=name, configuration=configuration)
36
+ return await ApifyDatasetClient.open(id=id, name=name, alias=alias, configuration=configuration)
36
37
 
37
38
  raise TypeError(
38
39
  f'Expected "configuration" to be an instance of "apify.Configuration", '
@@ -45,6 +46,7 @@ class ApifyStorageClient(StorageClient):
45
46
  *,
46
47
  id: str | None = None,
47
48
  name: str | None = None,
49
+ alias: str | None = None,
48
50
  configuration: Configuration | None = None,
49
51
  ) -> ApifyKeyValueStoreClient:
50
52
  # Import here to avoid circular imports.
@@ -52,7 +54,7 @@ class ApifyStorageClient(StorageClient):
52
54
 
53
55
  configuration = configuration or ApifyConfiguration.get_global_configuration()
54
56
  if isinstance(configuration, ApifyConfiguration):
55
- return await ApifyKeyValueStoreClient.open(id=id, name=name, configuration=configuration)
57
+ return await ApifyKeyValueStoreClient.open(id=id, name=name, alias=alias, configuration=configuration)
56
58
 
57
59
  raise TypeError(
58
60
  f'Expected "configuration" to be an instance of "apify.Configuration", '
@@ -65,6 +67,7 @@ class ApifyStorageClient(StorageClient):
65
67
  *,
66
68
  id: str | None = None,
67
69
  name: str | None = None,
70
+ alias: str | None = None,
68
71
  configuration: Configuration | None = None,
69
72
  ) -> ApifyRequestQueueClient:
70
73
  # Import here to avoid circular imports.
@@ -72,7 +75,7 @@ class ApifyStorageClient(StorageClient):
72
75
 
73
76
  configuration = configuration or ApifyConfiguration.get_global_configuration()
74
77
  if isinstance(configuration, ApifyConfiguration):
75
- return await ApifyRequestQueueClient.open(id=id, name=name, configuration=configuration)
78
+ return await ApifyRequestQueueClient.open(id=id, name=name, alias=alias, configuration=configuration)
76
79
 
77
80
  raise TypeError(
78
81
  f'Expected "configuration" to be an instance of "apify.Configuration", '