apify 3.0.1b1__tar.gz → 3.0.1b2__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 (240) hide show
  1. {apify-3.0.1b1 → apify-3.0.1b2}/CHANGELOG.md +4 -0
  2. {apify-3.0.1b1 → apify-3.0.1b2}/PKG-INFO +2 -2
  3. {apify-3.0.1b1 → apify-3.0.1b2}/pyproject.toml +3 -3
  4. {apify-3.0.1b1 → apify-3.0.1b2}/src/apify/_configuration.py +9 -0
  5. apify-3.0.1b2/src/apify/storage_clients/_file_system/_key_value_store_client.py +103 -0
  6. {apify-3.0.1b1 → apify-3.0.1b2}/tests/unit/storage_clients/test_file_system.py +23 -10
  7. {apify-3.0.1b1 → apify-3.0.1b2}/uv.lock +28 -28
  8. apify-3.0.1b1/src/apify/storage_clients/_file_system/_key_value_store_client.py +0 -57
  9. {apify-3.0.1b1 → apify-3.0.1b2}/.editorconfig +0 -0
  10. {apify-3.0.1b1 → apify-3.0.1b2}/.github/CODEOWNERS +0 -0
  11. {apify-3.0.1b1 → apify-3.0.1b2}/.github/workflows/build_and_deploy_docs.yaml +0 -0
  12. {apify-3.0.1b1 → apify-3.0.1b2}/.github/workflows/check_pr_title.yaml +0 -0
  13. {apify-3.0.1b1 → apify-3.0.1b2}/.github/workflows/pre_release.yaml +0 -0
  14. {apify-3.0.1b1 → apify-3.0.1b2}/.github/workflows/release.yaml +0 -0
  15. {apify-3.0.1b1 → apify-3.0.1b2}/.github/workflows/run_code_checks.yaml +0 -0
  16. {apify-3.0.1b1 → apify-3.0.1b2}/.github/workflows/update_new_issue.yaml +0 -0
  17. {apify-3.0.1b1 → apify-3.0.1b2}/.gitignore +0 -0
  18. {apify-3.0.1b1 → apify-3.0.1b2}/.markdownlint.yaml +0 -0
  19. {apify-3.0.1b1 → apify-3.0.1b2}/.pre-commit-config.yaml +0 -0
  20. {apify-3.0.1b1 → apify-3.0.1b2}/CONTRIBUTING.md +0 -0
  21. {apify-3.0.1b1 → apify-3.0.1b2}/LICENSE +0 -0
  22. {apify-3.0.1b1 → apify-3.0.1b2}/Makefile +0 -0
  23. {apify-3.0.1b1 → apify-3.0.1b2}/README.md +0 -0
  24. {apify-3.0.1b1 → apify-3.0.1b2}/docs/01_overview/01_introduction.mdx +0 -0
  25. {apify-3.0.1b1 → apify-3.0.1b2}/docs/01_overview/02_running_actors_locally.mdx +0 -0
  26. {apify-3.0.1b1 → apify-3.0.1b2}/docs/01_overview/03_actor_structure.mdx +0 -0
  27. {apify-3.0.1b1 → apify-3.0.1b2}/docs/01_overview/code/01_introduction.py +0 -0
  28. {apify-3.0.1b1 → apify-3.0.1b2}/docs/01_overview/code/actor_structure/__init__.py +0 -0
  29. {apify-3.0.1b1 → apify-3.0.1b2}/docs/01_overview/code/actor_structure/__main__.py +0 -0
  30. {apify-3.0.1b1 → apify-3.0.1b2}/docs/01_overview/code/actor_structure/main.py +0 -0
  31. {apify-3.0.1b1 → apify-3.0.1b2}/docs/01_overview/code/actor_structure/py.typed +0 -0
  32. {apify-3.0.1b1 → apify-3.0.1b2}/docs/02_concepts/01_actor_lifecycle.mdx +0 -0
  33. {apify-3.0.1b1 → apify-3.0.1b2}/docs/02_concepts/02_actor_input.mdx +0 -0
  34. {apify-3.0.1b1 → apify-3.0.1b2}/docs/02_concepts/03_storages.mdx +0 -0
  35. {apify-3.0.1b1 → apify-3.0.1b2}/docs/02_concepts/04_actor_events.mdx +0 -0
  36. {apify-3.0.1b1 → apify-3.0.1b2}/docs/02_concepts/05_proxy_management.mdx +0 -0
  37. {apify-3.0.1b1 → apify-3.0.1b2}/docs/02_concepts/06_interacting_with_other_actors.mdx +0 -0
  38. {apify-3.0.1b1 → apify-3.0.1b2}/docs/02_concepts/07_webhooks.mdx +0 -0
  39. {apify-3.0.1b1 → apify-3.0.1b2}/docs/02_concepts/08_access_apify_api.mdx +0 -0
  40. {apify-3.0.1b1 → apify-3.0.1b2}/docs/02_concepts/09_running_webserver.mdx +0 -0
  41. {apify-3.0.1b1 → apify-3.0.1b2}/docs/02_concepts/10_logging.mdx +0 -0
  42. {apify-3.0.1b1 → apify-3.0.1b2}/docs/02_concepts/11_configuration.mdx +0 -0
  43. {apify-3.0.1b1 → apify-3.0.1b2}/docs/02_concepts/12_pay_per_event.mdx +0 -0
  44. {apify-3.0.1b1 → apify-3.0.1b2}/docs/02_concepts/code/01_context_manager.py +0 -0
  45. {apify-3.0.1b1 → apify-3.0.1b2}/docs/02_concepts/code/01_init_exit.py +0 -0
  46. {apify-3.0.1b1 → apify-3.0.1b2}/docs/02_concepts/code/01_reboot.py +0 -0
  47. {apify-3.0.1b1 → apify-3.0.1b2}/docs/02_concepts/code/01_status_message.py +0 -0
  48. {apify-3.0.1b1 → apify-3.0.1b2}/docs/02_concepts/code/02_input.py +0 -0
  49. {apify-3.0.1b1 → apify-3.0.1b2}/docs/02_concepts/code/03_dataset_exports.py +0 -0
  50. {apify-3.0.1b1 → apify-3.0.1b2}/docs/02_concepts/code/03_dataset_read_write.py +0 -0
  51. {apify-3.0.1b1 → apify-3.0.1b2}/docs/02_concepts/code/03_deleting_storages.py +0 -0
  52. {apify-3.0.1b1 → apify-3.0.1b2}/docs/02_concepts/code/03_kvs_iterating.py +0 -0
  53. {apify-3.0.1b1 → apify-3.0.1b2}/docs/02_concepts/code/03_kvs_public_url.py +0 -0
  54. {apify-3.0.1b1 → apify-3.0.1b2}/docs/02_concepts/code/03_kvs_read_write.py +0 -0
  55. {apify-3.0.1b1 → apify-3.0.1b2}/docs/02_concepts/code/03_opening_storages.py +0 -0
  56. {apify-3.0.1b1 → apify-3.0.1b2}/docs/02_concepts/code/03_rq.py +0 -0
  57. {apify-3.0.1b1 → apify-3.0.1b2}/docs/02_concepts/code/04_actor_events.py +0 -0
  58. {apify-3.0.1b1 → apify-3.0.1b2}/docs/02_concepts/code/05_apify_proxy.py +0 -0
  59. {apify-3.0.1b1 → apify-3.0.1b2}/docs/02_concepts/code/05_apify_proxy_config.py +0 -0
  60. {apify-3.0.1b1 → apify-3.0.1b2}/docs/02_concepts/code/05_custom_proxy.py +0 -0
  61. {apify-3.0.1b1 → apify-3.0.1b2}/docs/02_concepts/code/05_custom_proxy_function.py +0 -0
  62. {apify-3.0.1b1 → apify-3.0.1b2}/docs/02_concepts/code/05_proxy_actor_input.py +0 -0
  63. {apify-3.0.1b1 → apify-3.0.1b2}/docs/02_concepts/code/05_proxy_httpx.py +0 -0
  64. {apify-3.0.1b1 → apify-3.0.1b2}/docs/02_concepts/code/05_proxy_rotation.py +0 -0
  65. {apify-3.0.1b1 → apify-3.0.1b2}/docs/02_concepts/code/06_interacting_call.py +0 -0
  66. {apify-3.0.1b1 → apify-3.0.1b2}/docs/02_concepts/code/06_interacting_call_task.py +0 -0
  67. {apify-3.0.1b1 → apify-3.0.1b2}/docs/02_concepts/code/06_interacting_metamorph.py +0 -0
  68. {apify-3.0.1b1 → apify-3.0.1b2}/docs/02_concepts/code/06_interacting_start.py +0 -0
  69. {apify-3.0.1b1 → apify-3.0.1b2}/docs/02_concepts/code/07_webhook.py +0 -0
  70. {apify-3.0.1b1 → apify-3.0.1b2}/docs/02_concepts/code/07_webhook_preventing.py +0 -0
  71. {apify-3.0.1b1 → apify-3.0.1b2}/docs/02_concepts/code/08_actor_client.py +0 -0
  72. {apify-3.0.1b1 → apify-3.0.1b2}/docs/02_concepts/code/08_actor_new_client.py +0 -0
  73. {apify-3.0.1b1 → apify-3.0.1b2}/docs/02_concepts/code/09_webserver.py +0 -0
  74. {apify-3.0.1b1 → apify-3.0.1b2}/docs/02_concepts/code/10_log_config.py +0 -0
  75. {apify-3.0.1b1 → apify-3.0.1b2}/docs/02_concepts/code/10_logger_usage.py +0 -0
  76. {apify-3.0.1b1 → apify-3.0.1b2}/docs/02_concepts/code/10_redirect_log.py +0 -0
  77. {apify-3.0.1b1 → apify-3.0.1b2}/docs/02_concepts/code/10_redirect_log_existing_run.py +0 -0
  78. {apify-3.0.1b1 → apify-3.0.1b2}/docs/02_concepts/code/11_config.py +0 -0
  79. {apify-3.0.1b1 → apify-3.0.1b2}/docs/02_concepts/code/actor_charge.py +0 -0
  80. {apify-3.0.1b1 → apify-3.0.1b2}/docs/02_concepts/code/conditional_actor_charge.py +0 -0
  81. {apify-3.0.1b1 → apify-3.0.1b2}/docs/03_guides/01_beautifulsoup_httpx.mdx +0 -0
  82. {apify-3.0.1b1 → apify-3.0.1b2}/docs/03_guides/02_parsel_impit.mdx +0 -0
  83. {apify-3.0.1b1 → apify-3.0.1b2}/docs/03_guides/03_playwright.mdx +0 -0
  84. {apify-3.0.1b1 → apify-3.0.1b2}/docs/03_guides/04_selenium.mdx +0 -0
  85. {apify-3.0.1b1 → apify-3.0.1b2}/docs/03_guides/05_crawlee.mdx +0 -0
  86. {apify-3.0.1b1 → apify-3.0.1b2}/docs/03_guides/06_scrapy.mdx +0 -0
  87. {apify-3.0.1b1 → apify-3.0.1b2}/docs/03_guides/code/01_beautifulsoup_httpx.py +0 -0
  88. {apify-3.0.1b1 → apify-3.0.1b2}/docs/03_guides/code/02_parsel_impit.py +0 -0
  89. {apify-3.0.1b1 → apify-3.0.1b2}/docs/03_guides/code/03_playwright.py +0 -0
  90. {apify-3.0.1b1 → apify-3.0.1b2}/docs/03_guides/code/04_selenium.py +0 -0
  91. {apify-3.0.1b1 → apify-3.0.1b2}/docs/03_guides/code/05_crawlee_beautifulsoup.py +0 -0
  92. {apify-3.0.1b1 → apify-3.0.1b2}/docs/03_guides/code/05_crawlee_parsel.py +0 -0
  93. {apify-3.0.1b1 → apify-3.0.1b2}/docs/03_guides/code/05_crawlee_playwright.py +0 -0
  94. {apify-3.0.1b1 → apify-3.0.1b2}/docs/03_guides/code/scrapy_project/src/__init__.py +0 -0
  95. {apify-3.0.1b1 → apify-3.0.1b2}/docs/03_guides/code/scrapy_project/src/__main__.py +0 -0
  96. {apify-3.0.1b1 → apify-3.0.1b2}/docs/03_guides/code/scrapy_project/src/items.py +0 -0
  97. {apify-3.0.1b1 → apify-3.0.1b2}/docs/03_guides/code/scrapy_project/src/main.py +0 -0
  98. {apify-3.0.1b1 → apify-3.0.1b2}/docs/03_guides/code/scrapy_project/src/py.typed +0 -0
  99. {apify-3.0.1b1 → apify-3.0.1b2}/docs/03_guides/code/scrapy_project/src/settings.py +0 -0
  100. {apify-3.0.1b1 → apify-3.0.1b2}/docs/03_guides/code/scrapy_project/src/spiders/__init__.py +0 -0
  101. {apify-3.0.1b1 → apify-3.0.1b2}/docs/03_guides/code/scrapy_project/src/spiders/py.typed +0 -0
  102. {apify-3.0.1b1 → apify-3.0.1b2}/docs/03_guides/code/scrapy_project/src/spiders/title.py +0 -0
  103. {apify-3.0.1b1 → apify-3.0.1b2}/docs/04_upgrading/upgrading_to_v2.md +0 -0
  104. {apify-3.0.1b1 → apify-3.0.1b2}/docs/04_upgrading/upgrading_to_v3.md +0 -0
  105. {apify-3.0.1b1 → apify-3.0.1b2}/docs/pyproject.toml +0 -0
  106. {apify-3.0.1b1 → apify-3.0.1b2}/renovate.json +0 -0
  107. {apify-3.0.1b1 → apify-3.0.1b2}/src/apify/__init__.py +0 -0
  108. {apify-3.0.1b1 → apify-3.0.1b2}/src/apify/_actor.py +0 -0
  109. {apify-3.0.1b1 → apify-3.0.1b2}/src/apify/_charging.py +0 -0
  110. {apify-3.0.1b1 → apify-3.0.1b2}/src/apify/_consts.py +0 -0
  111. {apify-3.0.1b1 → apify-3.0.1b2}/src/apify/_crypto.py +0 -0
  112. {apify-3.0.1b1 → apify-3.0.1b2}/src/apify/_models.py +0 -0
  113. {apify-3.0.1b1 → apify-3.0.1b2}/src/apify/_proxy_configuration.py +0 -0
  114. {apify-3.0.1b1 → apify-3.0.1b2}/src/apify/_utils.py +0 -0
  115. {apify-3.0.1b1 → apify-3.0.1b2}/src/apify/events/__init__.py +0 -0
  116. {apify-3.0.1b1 → apify-3.0.1b2}/src/apify/events/_apify_event_manager.py +0 -0
  117. {apify-3.0.1b1 → apify-3.0.1b2}/src/apify/events/_types.py +0 -0
  118. {apify-3.0.1b1 → apify-3.0.1b2}/src/apify/events/py.typed +0 -0
  119. {apify-3.0.1b1 → apify-3.0.1b2}/src/apify/log.py +0 -0
  120. {apify-3.0.1b1 → apify-3.0.1b2}/src/apify/py.typed +0 -0
  121. {apify-3.0.1b1 → apify-3.0.1b2}/src/apify/request_loaders/__init__.py +0 -0
  122. {apify-3.0.1b1 → apify-3.0.1b2}/src/apify/request_loaders/_apify_request_list.py +0 -0
  123. {apify-3.0.1b1 → apify-3.0.1b2}/src/apify/request_loaders/py.typed +0 -0
  124. {apify-3.0.1b1 → apify-3.0.1b2}/src/apify/scrapy/__init__.py +0 -0
  125. {apify-3.0.1b1 → apify-3.0.1b2}/src/apify/scrapy/_actor_runner.py +0 -0
  126. {apify-3.0.1b1 → apify-3.0.1b2}/src/apify/scrapy/_async_thread.py +0 -0
  127. {apify-3.0.1b1 → apify-3.0.1b2}/src/apify/scrapy/_logging_config.py +0 -0
  128. {apify-3.0.1b1 → apify-3.0.1b2}/src/apify/scrapy/extensions/__init__.py +0 -0
  129. {apify-3.0.1b1 → apify-3.0.1b2}/src/apify/scrapy/extensions/_httpcache.py +0 -0
  130. {apify-3.0.1b1 → apify-3.0.1b2}/src/apify/scrapy/middlewares/__init__.py +0 -0
  131. {apify-3.0.1b1 → apify-3.0.1b2}/src/apify/scrapy/middlewares/apify_proxy.py +0 -0
  132. {apify-3.0.1b1 → apify-3.0.1b2}/src/apify/scrapy/middlewares/py.typed +0 -0
  133. {apify-3.0.1b1 → apify-3.0.1b2}/src/apify/scrapy/pipelines/__init__.py +0 -0
  134. {apify-3.0.1b1 → apify-3.0.1b2}/src/apify/scrapy/pipelines/actor_dataset_push.py +0 -0
  135. {apify-3.0.1b1 → apify-3.0.1b2}/src/apify/scrapy/pipelines/py.typed +0 -0
  136. {apify-3.0.1b1 → apify-3.0.1b2}/src/apify/scrapy/py.typed +0 -0
  137. {apify-3.0.1b1 → apify-3.0.1b2}/src/apify/scrapy/requests.py +0 -0
  138. {apify-3.0.1b1 → apify-3.0.1b2}/src/apify/scrapy/scheduler.py +0 -0
  139. {apify-3.0.1b1 → apify-3.0.1b2}/src/apify/scrapy/utils.py +0 -0
  140. {apify-3.0.1b1 → apify-3.0.1b2}/src/apify/storage_clients/__init__.py +0 -0
  141. {apify-3.0.1b1 → apify-3.0.1b2}/src/apify/storage_clients/_apify/__init__.py +0 -0
  142. {apify-3.0.1b1 → apify-3.0.1b2}/src/apify/storage_clients/_apify/_dataset_client.py +0 -0
  143. {apify-3.0.1b1 → apify-3.0.1b2}/src/apify/storage_clients/_apify/_key_value_store_client.py +0 -0
  144. {apify-3.0.1b1 → apify-3.0.1b2}/src/apify/storage_clients/_apify/_models.py +0 -0
  145. {apify-3.0.1b1 → apify-3.0.1b2}/src/apify/storage_clients/_apify/_request_queue_client.py +0 -0
  146. {apify-3.0.1b1 → apify-3.0.1b2}/src/apify/storage_clients/_apify/_request_queue_shared_client.py +0 -0
  147. {apify-3.0.1b1 → apify-3.0.1b2}/src/apify/storage_clients/_apify/_request_queue_single_client.py +0 -0
  148. {apify-3.0.1b1 → apify-3.0.1b2}/src/apify/storage_clients/_apify/_storage_client.py +0 -0
  149. {apify-3.0.1b1 → apify-3.0.1b2}/src/apify/storage_clients/_apify/_utils.py +0 -0
  150. {apify-3.0.1b1 → apify-3.0.1b2}/src/apify/storage_clients/_apify/py.typed +0 -0
  151. {apify-3.0.1b1 → apify-3.0.1b2}/src/apify/storage_clients/_file_system/__init__.py +0 -0
  152. {apify-3.0.1b1 → apify-3.0.1b2}/src/apify/storage_clients/_file_system/_storage_client.py +0 -0
  153. {apify-3.0.1b1 → apify-3.0.1b2}/src/apify/storage_clients/_smart_apify/__init__.py +0 -0
  154. {apify-3.0.1b1 → apify-3.0.1b2}/src/apify/storage_clients/_smart_apify/_storage_client.py +0 -0
  155. {apify-3.0.1b1 → apify-3.0.1b2}/src/apify/storage_clients/py.typed +0 -0
  156. {apify-3.0.1b1 → apify-3.0.1b2}/src/apify/storages/__init__.py +0 -0
  157. {apify-3.0.1b1 → apify-3.0.1b2}/src/apify/storages/py.typed +0 -0
  158. {apify-3.0.1b1 → apify-3.0.1b2}/tests/integration/README.md +0 -0
  159. {apify-3.0.1b1 → apify-3.0.1b2}/tests/integration/__init__.py +0 -0
  160. {apify-3.0.1b1 → apify-3.0.1b2}/tests/integration/_utils.py +0 -0
  161. {apify-3.0.1b1 → apify-3.0.1b2}/tests/integration/actor_source_base/Dockerfile +0 -0
  162. {apify-3.0.1b1 → apify-3.0.1b2}/tests/integration/actor_source_base/requirements.txt +0 -0
  163. {apify-3.0.1b1 → apify-3.0.1b2}/tests/integration/actor_source_base/server.py +0 -0
  164. {apify-3.0.1b1 → apify-3.0.1b2}/tests/integration/actor_source_base/src/__init__.py +0 -0
  165. {apify-3.0.1b1 → apify-3.0.1b2}/tests/integration/actor_source_base/src/__main__.py +0 -0
  166. {apify-3.0.1b1 → apify-3.0.1b2}/tests/integration/actor_source_base/src/main.py +0 -0
  167. {apify-3.0.1b1 → apify-3.0.1b2}/tests/integration/conftest.py +0 -0
  168. {apify-3.0.1b1 → apify-3.0.1b2}/tests/integration/test_actor_api_helpers.py +0 -0
  169. {apify-3.0.1b1 → apify-3.0.1b2}/tests/integration/test_actor_call_timeouts.py +0 -0
  170. {apify-3.0.1b1 → apify-3.0.1b2}/tests/integration/test_actor_charge.py +0 -0
  171. {apify-3.0.1b1 → apify-3.0.1b2}/tests/integration/test_actor_create_proxy_configuration.py +0 -0
  172. {apify-3.0.1b1 → apify-3.0.1b2}/tests/integration/test_actor_dataset.py +0 -0
  173. {apify-3.0.1b1 → apify-3.0.1b2}/tests/integration/test_actor_events.py +0 -0
  174. {apify-3.0.1b1 → apify-3.0.1b2}/tests/integration/test_actor_key_value_store.py +0 -0
  175. {apify-3.0.1b1 → apify-3.0.1b2}/tests/integration/test_actor_lifecycle.py +0 -0
  176. {apify-3.0.1b1 → apify-3.0.1b2}/tests/integration/test_actor_log.py +0 -0
  177. {apify-3.0.1b1 → apify-3.0.1b2}/tests/integration/test_actor_request_queue.py +0 -0
  178. {apify-3.0.1b1 → apify-3.0.1b2}/tests/integration/test_actor_scrapy.py +0 -0
  179. {apify-3.0.1b1 → apify-3.0.1b2}/tests/integration/test_apify_storages.py +0 -0
  180. {apify-3.0.1b1 → apify-3.0.1b2}/tests/integration/test_crawlers_with_storages.py +0 -0
  181. {apify-3.0.1b1 → apify-3.0.1b2}/tests/integration/test_fixtures.py +0 -0
  182. {apify-3.0.1b1 → apify-3.0.1b2}/tests/integration/test_request_queue.py +0 -0
  183. {apify-3.0.1b1 → apify-3.0.1b2}/tests/unit/__init__.py +0 -0
  184. {apify-3.0.1b1 → apify-3.0.1b2}/tests/unit/actor/__init__.py +0 -0
  185. {apify-3.0.1b1 → apify-3.0.1b2}/tests/unit/actor/test_actor_create_proxy_configuration.py +0 -0
  186. {apify-3.0.1b1 → apify-3.0.1b2}/tests/unit/actor/test_actor_dataset.py +0 -0
  187. {apify-3.0.1b1 → apify-3.0.1b2}/tests/unit/actor/test_actor_env_helpers.py +0 -0
  188. {apify-3.0.1b1 → apify-3.0.1b2}/tests/unit/actor/test_actor_helpers.py +0 -0
  189. {apify-3.0.1b1 → apify-3.0.1b2}/tests/unit/actor/test_actor_key_value_store.py +0 -0
  190. {apify-3.0.1b1 → apify-3.0.1b2}/tests/unit/actor/test_actor_lifecycle.py +0 -0
  191. {apify-3.0.1b1 → apify-3.0.1b2}/tests/unit/actor/test_actor_log.py +0 -0
  192. {apify-3.0.1b1 → apify-3.0.1b2}/tests/unit/actor/test_actor_non_default_instance.py +0 -0
  193. {apify-3.0.1b1 → apify-3.0.1b2}/tests/unit/actor/test_actor_request_queue.py +0 -0
  194. {apify-3.0.1b1 → apify-3.0.1b2}/tests/unit/actor/test_configuration.py +0 -0
  195. {apify-3.0.1b1 → apify-3.0.1b2}/tests/unit/actor/test_request_list.py +0 -0
  196. {apify-3.0.1b1 → apify-3.0.1b2}/tests/unit/conftest.py +0 -0
  197. {apify-3.0.1b1 → apify-3.0.1b2}/tests/unit/events/__init__.py +0 -0
  198. {apify-3.0.1b1 → apify-3.0.1b2}/tests/unit/events/test_apify_event_manager.py +0 -0
  199. {apify-3.0.1b1 → apify-3.0.1b2}/tests/unit/scrapy/__init__.py +0 -0
  200. {apify-3.0.1b1 → apify-3.0.1b2}/tests/unit/scrapy/extensions/__init__.py +0 -0
  201. {apify-3.0.1b1 → apify-3.0.1b2}/tests/unit/scrapy/extensions/test_httpcache.py +0 -0
  202. {apify-3.0.1b1 → apify-3.0.1b2}/tests/unit/scrapy/middlewares/__init__.py +0 -0
  203. {apify-3.0.1b1 → apify-3.0.1b2}/tests/unit/scrapy/middlewares/test_apify_proxy.py +0 -0
  204. {apify-3.0.1b1 → apify-3.0.1b2}/tests/unit/scrapy/pipelines/__init__.py +0 -0
  205. {apify-3.0.1b1 → apify-3.0.1b2}/tests/unit/scrapy/pipelines/test_actor_dataset_push.py +0 -0
  206. {apify-3.0.1b1 → apify-3.0.1b2}/tests/unit/scrapy/requests/__init__.py +0 -0
  207. {apify-3.0.1b1 → apify-3.0.1b2}/tests/unit/scrapy/requests/test_to_apify_request.py +0 -0
  208. {apify-3.0.1b1 → apify-3.0.1b2}/tests/unit/scrapy/requests/test_to_scrapy_request.py +0 -0
  209. {apify-3.0.1b1 → apify-3.0.1b2}/tests/unit/scrapy/utils/__init__.py +0 -0
  210. {apify-3.0.1b1 → apify-3.0.1b2}/tests/unit/scrapy/utils/test_apply_apify_settings.py +0 -0
  211. {apify-3.0.1b1 → apify-3.0.1b2}/tests/unit/scrapy/utils/test_get_basic_auth_header.py +0 -0
  212. {apify-3.0.1b1 → apify-3.0.1b2}/tests/unit/storage_clients/__init__.py +0 -0
  213. {apify-3.0.1b1 → apify-3.0.1b2}/tests/unit/storage_clients/test_apify_request_queue_client.py +0 -0
  214. {apify-3.0.1b1 → apify-3.0.1b2}/tests/unit/test_apify_storages.py +0 -0
  215. {apify-3.0.1b1 → apify-3.0.1b2}/tests/unit/test_crypto.py +0 -0
  216. {apify-3.0.1b1 → apify-3.0.1b2}/tests/unit/test_proxy_configuration.py +0 -0
  217. {apify-3.0.1b1 → apify-3.0.1b2}/website/.eslintrc.json +0 -0
  218. {apify-3.0.1b1 → apify-3.0.1b2}/website/babel.config.js +0 -0
  219. {apify-3.0.1b1 → apify-3.0.1b2}/website/build_api_reference.sh +0 -0
  220. {apify-3.0.1b1 → apify-3.0.1b2}/website/docusaurus.config.js +0 -0
  221. {apify-3.0.1b1 → apify-3.0.1b2}/website/generate_module_shortcuts.py +0 -0
  222. {apify-3.0.1b1 → apify-3.0.1b2}/website/package-lock.json +0 -0
  223. {apify-3.0.1b1 → apify-3.0.1b2}/website/package.json +0 -0
  224. {apify-3.0.1b1 → apify-3.0.1b2}/website/sidebars.js +0 -0
  225. {apify-3.0.1b1 → apify-3.0.1b2}/website/src/components/ApiLink.jsx +0 -0
  226. {apify-3.0.1b1 → apify-3.0.1b2}/website/src/components/Gradients.jsx +0 -0
  227. {apify-3.0.1b1 → apify-3.0.1b2}/website/src/components/Highlights.jsx +0 -0
  228. {apify-3.0.1b1 → apify-3.0.1b2}/website/src/components/Highlights.module.css +0 -0
  229. {apify-3.0.1b1 → apify-3.0.1b2}/website/src/components/RunnableCodeBlock.jsx +0 -0
  230. {apify-3.0.1b1 → apify-3.0.1b2}/website/src/components/RunnableCodeBlock.module.css +0 -0
  231. {apify-3.0.1b1 → apify-3.0.1b2}/website/src/css/custom.css +0 -0
  232. {apify-3.0.1b1 → apify-3.0.1b2}/website/src/pages/home_page_example.py +0 -0
  233. {apify-3.0.1b1 → apify-3.0.1b2}/website/src/pages/index.js +0 -0
  234. {apify-3.0.1b1 → apify-3.0.1b2}/website/src/pages/index.module.css +0 -0
  235. {apify-3.0.1b1 → apify-3.0.1b2}/website/src/theme/DocItem/Content/index.js +0 -0
  236. {apify-3.0.1b1 → apify-3.0.1b2}/website/static/.nojekyll +0 -0
  237. {apify-3.0.1b1 → apify-3.0.1b2}/website/static/img/docs-og.png +0 -0
  238. {apify-3.0.1b1 → apify-3.0.1b2}/website/static/img/guides/redirected_logs_example.webp +0 -0
  239. {apify-3.0.1b1 → apify-3.0.1b2}/website/tools/docs-prettier.config.js +0 -0
  240. {apify-3.0.1b1 → apify-3.0.1b2}/website/tools/utils/externalLink.js +0 -0
@@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file.
5
5
  <!-- git-cliff-unreleased-start -->
6
6
  ## 3.0.1 - **not yet released**
7
7
 
8
+ ### 🐛 Bug Fixes
9
+
10
+ - Also load input from a file with a .json extension in file system storage ([#617](https://github.com/apify/apify-sdk-python/pull/617)) ([b62804c](https://github.com/apify/apify-sdk-python/commit/b62804c170069cd7aa77572bb9682a156581cbac)) by [@janbuchar](https://github.com/janbuchar)
11
+
8
12
 
9
13
  <!-- git-cliff-unreleased-end -->
10
14
  ## [3.0.0](https://github.com/apify/apify-sdk-python/releases/tag/v3.0.0) (2025-09-29)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: apify
3
- Version: 3.0.1b1
3
+ Version: 3.0.1b2
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<2.0.0,>=1.0.0
231
+ Requires-Dist: crawlee<2.0.0,>=1.0.2
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
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "apify"
7
- version = "3.0.1b1"
7
+ version = "3.0.1b2"
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.0,<2.0.0",
39
+ "crawlee>=1.0.2,<2.0.0",
40
40
  "cachetools>=5.5.0",
41
41
  "cryptography>=42.0.0",
42
42
  "impit>=0.6.1",
@@ -75,7 +75,7 @@ dev = [
75
75
  "pytest-timeout~=2.4.0",
76
76
  "pytest-xdist~=3.8.0",
77
77
  "pytest~=8.4.0",
78
- "ruff~=0.13.0",
78
+ "ruff~=0.14.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]",
@@ -3,6 +3,7 @@ from __future__ import annotations
3
3
  from datetime import datetime, timedelta
4
4
  from decimal import Decimal
5
5
  from logging import getLogger
6
+ from pathlib import Path
6
7
  from typing import Annotated, Any
7
8
 
8
9
  from pydantic import AliasChoices, BeforeValidator, Field, model_validator
@@ -421,6 +422,14 @@ class Configuration(CrawleeConfiguration):
421
422
  logger.warning('Actor is running on the Apify platform, `disable_browser_sandbox` was changed to True.')
422
423
  return self
423
424
 
425
+ @property
426
+ def canonical_input_key(self) -> str:
427
+ return str(Path(self.input_key).with_suffix('.json'))
428
+
429
+ @property
430
+ def input_key_candidates(self) -> set[str]:
431
+ return {self.input_key, self.canonical_input_key, Path(self.canonical_input_key).stem}
432
+
424
433
  @classmethod
425
434
  def get_global_configuration(cls) -> Configuration:
426
435
  """Retrieve the global instance of the configuration.
@@ -0,0 +1,103 @@
1
+ import asyncio
2
+ import json
3
+ import logging
4
+
5
+ from more_itertools import flatten
6
+ from typing_extensions import Self, override
7
+
8
+ from crawlee._consts import METADATA_FILENAME
9
+ from crawlee.configuration import Configuration as CrawleeConfiguration
10
+ from crawlee.storage_clients._file_system import FileSystemKeyValueStoreClient
11
+ from crawlee.storage_clients.models import KeyValueStoreRecord
12
+
13
+ from apify._configuration import Configuration
14
+
15
+ logger = logging.getLogger(__name__)
16
+
17
+
18
+ class ApifyFileSystemKeyValueStoreClient(FileSystemKeyValueStoreClient):
19
+ """Apify-specific implementation of the `FileSystemKeyValueStoreClient`.
20
+
21
+ The only difference is that it overrides the `purge` method to delete all files in the key-value store
22
+ directory, except for the metadata file and the `INPUT.json` file.
23
+ """
24
+
25
+ @override
26
+ @classmethod
27
+ async def open(
28
+ cls,
29
+ *,
30
+ id: str | None,
31
+ name: str | None,
32
+ alias: str | None,
33
+ configuration: CrawleeConfiguration,
34
+ ) -> Self:
35
+ client = await super().open(id=id, name=name, alias=alias, configuration=configuration)
36
+
37
+ await client._sanitize_input_json_files() # noqa: SLF001 - it's okay, this is a factory method
38
+
39
+ return client
40
+
41
+ @override
42
+ async def purge(self) -> None:
43
+ """Purges the key-value store by deleting all its contents.
44
+
45
+ It deletes all files in the key-value store directory, except for the metadata file and
46
+ the `INPUT.json` file. It also updates the metadata to reflect that the store has been purged.
47
+ """
48
+ configuration = Configuration.get_global_configuration()
49
+
50
+ async with self._lock:
51
+ files_to_keep = set(
52
+ flatten([key, f'{key}.{METADATA_FILENAME}'] for key in configuration.input_key_candidates)
53
+ )
54
+ files_to_keep.add(METADATA_FILENAME)
55
+
56
+ for file_path in self.path_to_kvs.glob('*'):
57
+ if file_path.name in files_to_keep:
58
+ continue
59
+ if file_path.is_file():
60
+ await asyncio.to_thread(file_path.unlink, missing_ok=True)
61
+
62
+ await self._update_metadata(
63
+ update_accessed_at=True,
64
+ update_modified_at=True,
65
+ )
66
+
67
+ async def _sanitize_input_json_files(self) -> None:
68
+ """Handle missing metadata for input files."""
69
+ configuration = Configuration.get_global_configuration()
70
+ alternative_keys = configuration.input_key_candidates - {configuration.canonical_input_key}
71
+
72
+ if (self.path_to_kvs / configuration.canonical_input_key).exists():
73
+ # Refresh metadata to prevent inconsistencies
74
+ input_data = await asyncio.to_thread(
75
+ lambda: json.loads((self.path_to_kvs / configuration.canonical_input_key).read_text())
76
+ )
77
+ await self.set_value(key=configuration.canonical_input_key, value=input_data)
78
+
79
+ for alternative_key in alternative_keys:
80
+ if (alternative_input_file := self.path_to_kvs / alternative_key).exists():
81
+ logger.warning(f'Redundant input file found: {alternative_input_file}')
82
+ else:
83
+ for alternative_key in alternative_keys:
84
+ alternative_input_file = self.path_to_kvs / alternative_key
85
+
86
+ # Only process files that actually exist
87
+ if alternative_input_file.exists():
88
+ # Refresh metadata to prevent inconsistencies
89
+ with alternative_input_file.open() as f:
90
+ input_data = await asyncio.to_thread(lambda: json.load(f))
91
+ await self.set_value(key=alternative_key, value=input_data)
92
+
93
+ @override
94
+ async def get_value(self, *, key: str) -> KeyValueStoreRecord | None:
95
+ configuration = Configuration.get_global_configuration()
96
+
97
+ if key in configuration.input_key_candidates:
98
+ for candidate in configuration.input_key_candidates:
99
+ value = await super().get_value(key=candidate)
100
+ if value is not None:
101
+ return value
102
+
103
+ return await super().get_value(key=key)
@@ -2,16 +2,16 @@ from __future__ import annotations
2
2
 
3
3
  import asyncio
4
4
  import json
5
- from typing import TYPE_CHECKING
5
+ from pathlib import Path
6
6
 
7
+ import pytest
8
+
9
+ from crawlee import service_locator
7
10
  from crawlee._consts import METADATA_FILENAME
8
11
 
9
12
  from apify import Actor, Configuration
10
13
  from apify.storage_clients._file_system import ApifyFileSystemKeyValueStoreClient
11
14
 
12
- if TYPE_CHECKING:
13
- from pathlib import Path
14
-
15
15
 
16
16
  async def test_purge_preserves_input_file_and_metadata() -> None:
17
17
  """Test that purge() preserves INPUT.json and metadata files but removes other files."""
@@ -61,19 +61,32 @@ async def test_purge_preserves_input_file_and_metadata() -> None:
61
61
 
62
62
  # Verify INPUT.json content is unchanged
63
63
  input_content = await asyncio.to_thread(input_file.read_text)
64
- assert input_content == '{"test": "input"}'
64
+ assert json.loads(input_content) == json.loads('{"test": "input"}')
65
+
65
66
 
67
+ @pytest.mark.parametrize('input_file_name', ['INPUT', 'INPUT.json'])
68
+ async def test_pre_existing_input_used_by_actor(input_file_name: str) -> None:
69
+ configuration = Configuration()
70
+ service_locator.set_configuration(configuration)
71
+
72
+ # Create key-value store directory and make sure that it is empty
73
+ path_to_input = Path(configuration.storage_dir) / 'key_value_stores' / 'default'
74
+ path_to_input.mkdir(parents=True)
75
+ assert list(path_to_input.glob('*')) == []
66
76
 
67
- async def test_pre_existing_input_used_by_actor(tmp_path: Path) -> None:
68
77
  pre_existing_input = {
69
78
  'foo': 'bar',
70
79
  }
71
80
 
72
- configuration = Configuration.get_global_configuration()
73
81
  # Create pre-existing INPUT.json file
74
- path_to_input = tmp_path / 'key_value_stores' / 'default'
75
- path_to_input.mkdir(parents=True)
76
- (path_to_input / f'{configuration.input_key}.json').write_text(json.dumps(pre_existing_input))
82
+ (path_to_input / input_file_name).write_text(json.dumps(pre_existing_input))
77
83
 
78
84
  async with Actor():
79
85
  assert pre_existing_input == await Actor.get_input()
86
+
87
+ # Make sure that the input file doesn't get renamed in the process and metadata are added
88
+ assert set(path_to_input.glob('*')) == {
89
+ path_to_input / '__metadata__.json',
90
+ path_to_input / input_file_name,
91
+ path_to_input / f'{input_file_name}.__metadata__.json',
92
+ }
@@ -28,7 +28,7 @@ wheels = [
28
28
 
29
29
  [[package]]
30
30
  name = "apify"
31
- version = "3.0.1b1"
31
+ version = "3.0.1b2"
32
32
  source = { editable = "." }
33
33
  dependencies = [
34
34
  { name = "apify-client" },
@@ -76,7 +76,7 @@ requires-dist = [
76
76
  { name = "apify-client", specifier = ">=2.0.0,<3.0.0" },
77
77
  { name = "apify-shared", specifier = ">=2.0.0,<3.0.0" },
78
78
  { name = "cachetools", specifier = ">=5.5.0" },
79
- { name = "crawlee", specifier = ">=1.0.0,<2.0.0" },
79
+ { name = "crawlee", specifier = ">=1.0.2,<2.0.0" },
80
80
  { name = "cryptography", specifier = ">=42.0.0" },
81
81
  { name = "impit", specifier = ">=0.6.1" },
82
82
  { name = "lazy-object-proxy", specifier = ">=1.11.0" },
@@ -103,7 +103,7 @@ dev = [
103
103
  { name = "pytest-httpserver", specifier = "~=1.1.0" },
104
104
  { name = "pytest-timeout", specifier = "~=2.4.0" },
105
105
  { name = "pytest-xdist", specifier = "~=3.8.0" },
106
- { name = "ruff", specifier = "~=0.13.0" },
106
+ { name = "ruff", specifier = "~=0.14.0" },
107
107
  { name = "setuptools" },
108
108
  { name = "types-cachetools", specifier = "~=6.2.0.20250827" },
109
109
  { name = "uvicorn", extras = ["standard"] },
@@ -516,7 +516,7 @@ toml = [
516
516
 
517
517
  [[package]]
518
518
  name = "crawlee"
519
- version = "1.0.1"
519
+ version = "1.0.2"
520
520
  source = { registry = "https://pypi.org/simple" }
521
521
  dependencies = [
522
522
  { name = "cachetools" },
@@ -532,9 +532,9 @@ dependencies = [
532
532
  { name = "typing-extensions" },
533
533
  { name = "yarl" },
534
534
  ]
535
- sdist = { url = "https://files.pythonhosted.org/packages/4d/0a/713d5d45c9833a74beaf9f298081823eeef8dcbd5c25b8f87feebe7a4574/crawlee-1.0.1.tar.gz", hash = "sha256:01f7c9bfeace31bb3a175bfb954bc12214dd2fc3d4e9da30e566659f25015a67", size = 24897569, upload-time = "2025-10-06T08:28:36.367Z" }
535
+ sdist = { url = "https://files.pythonhosted.org/packages/93/68/45641208866a60176be4c5f2ab620c2122df18db956dc86a03471181e7c3/crawlee-1.0.2.tar.gz", hash = "sha256:522b52c1362d116b95ba85820f87001713f290a3ec690568adb862a4b29d7ca4", size = 24900937, upload-time = "2025-10-08T07:59:09.983Z" }
536
536
  wheels = [
537
- { url = "https://files.pythonhosted.org/packages/bb/46/5ab3edf0497dad3c6c02979609934f36e1bb934076e4401e5b5c7b060fbd/crawlee-1.0.1-py3-none-any.whl", hash = "sha256:a910f0c2e8fec57b3c800af4f60006e1906923f80e9301f0073a85aca7d16c62", size = 303586, upload-time = "2025-10-06T08:28:32.466Z" },
537
+ { url = "https://files.pythonhosted.org/packages/be/ac/860de31ca534adb1d6321f66c7d082ba735eff49090f67a316f8d60f1ee2/crawlee-1.0.2-py3-none-any.whl", hash = "sha256:57a63d0b22493297490a5836e6b1d47dee667004d95bbc01387dcfb00f6a8a7a", size = 304369, upload-time = "2025-10-08T07:59:07.475Z" },
538
538
  ]
539
539
 
540
540
  [package.optional-dependencies]
@@ -2064,28 +2064,28 @@ wheels = [
2064
2064
 
2065
2065
  [[package]]
2066
2066
  name = "ruff"
2067
- version = "0.13.3"
2068
- source = { registry = "https://pypi.org/simple" }
2069
- sdist = { url = "https://files.pythonhosted.org/packages/c7/8e/f9f9ca747fea8e3ac954e3690d4698c9737c23b51731d02df999c150b1c9/ruff-0.13.3.tar.gz", hash = "sha256:5b0ba0db740eefdfbcce4299f49e9eaefc643d4d007749d77d047c2bab19908e", size = 5438533, upload-time = "2025-10-02T19:29:31.582Z" }
2070
- wheels = [
2071
- { url = "https://files.pythonhosted.org/packages/d2/33/8f7163553481466a92656d35dea9331095122bb84cf98210bef597dd2ecd/ruff-0.13.3-py3-none-linux_armv6l.whl", hash = "sha256:311860a4c5e19189c89d035638f500c1e191d283d0cc2f1600c8c80d6dcd430c", size = 12484040, upload-time = "2025-10-02T19:28:49.199Z" },
2072
- { url = "https://files.pythonhosted.org/packages/b0/b5/4a21a4922e5dd6845e91896b0d9ef493574cbe061ef7d00a73c61db531af/ruff-0.13.3-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:2bdad6512fb666b40fcadb65e33add2b040fc18a24997d2e47fee7d66f7fcae2", size = 13122975, upload-time = "2025-10-02T19:28:52.446Z" },
2073
- { url = "https://files.pythonhosted.org/packages/40/90/15649af836d88c9f154e5be87e64ae7d2b1baa5a3ef317cb0c8fafcd882d/ruff-0.13.3-py3-none-macosx_11_0_arm64.whl", hash = "sha256:fc6fa4637284708d6ed4e5e970d52fc3b76a557d7b4e85a53013d9d201d93286", size = 12346621, upload-time = "2025-10-02T19:28:54.712Z" },
2074
- { url = "https://files.pythonhosted.org/packages/a5/42/bcbccb8141305f9a6d3f72549dd82d1134299177cc7eaf832599700f95a7/ruff-0.13.3-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c9e6469864f94a98f412f20ea143d547e4c652f45e44f369d7b74ee78185838", size = 12574408, upload-time = "2025-10-02T19:28:56.679Z" },
2075
- { url = "https://files.pythonhosted.org/packages/ce/19/0f3681c941cdcfa2d110ce4515624c07a964dc315d3100d889fcad3bfc9e/ruff-0.13.3-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5bf62b705f319476c78891e0e97e965b21db468b3c999086de8ffb0d40fd2822", size = 12285330, upload-time = "2025-10-02T19:28:58.79Z" },
2076
- { url = "https://files.pythonhosted.org/packages/10/f8/387976bf00d126b907bbd7725219257feea58650e6b055b29b224d8cb731/ruff-0.13.3-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:78cc1abed87ce40cb07ee0667ce99dbc766c9f519eabfd948ed87295d8737c60", size = 13980815, upload-time = "2025-10-02T19:29:01.577Z" },
2077
- { url = "https://files.pythonhosted.org/packages/0c/a6/7c8ec09d62d5a406e2b17d159e4817b63c945a8b9188a771193b7e1cc0b5/ruff-0.13.3-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:4fb75e7c402d504f7a9a259e0442b96403fa4a7310ffe3588d11d7e170d2b1e3", size = 14987733, upload-time = "2025-10-02T19:29:04.036Z" },
2078
- { url = "https://files.pythonhosted.org/packages/97/e5/f403a60a12258e0fd0c2195341cfa170726f254c788673495d86ab5a9a9d/ruff-0.13.3-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:17b951f9d9afb39330b2bdd2dd144ce1c1335881c277837ac1b50bfd99985ed3", size = 14439848, upload-time = "2025-10-02T19:29:06.684Z" },
2079
- { url = "https://files.pythonhosted.org/packages/39/49/3de381343e89364c2334c9f3268b0349dc734fc18b2d99a302d0935c8345/ruff-0.13.3-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6052f8088728898e0a449f0dde8fafc7ed47e4d878168b211977e3e7e854f662", size = 13421890, upload-time = "2025-10-02T19:29:08.767Z" },
2080
- { url = "https://files.pythonhosted.org/packages/ab/b5/c0feca27d45ae74185a6bacc399f5d8920ab82df2d732a17213fb86a2c4c/ruff-0.13.3-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dc742c50f4ba72ce2a3be362bd359aef7d0d302bf7637a6f942eaa763bd292af", size = 13444870, upload-time = "2025-10-02T19:29:11.234Z" },
2081
- { url = "https://files.pythonhosted.org/packages/50/a1/b655298a1f3fda4fdc7340c3f671a4b260b009068fbeb3e4e151e9e3e1bf/ruff-0.13.3-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:8e5640349493b378431637019366bbd73c927e515c9c1babfea3e932f5e68e1d", size = 13691599, upload-time = "2025-10-02T19:29:13.353Z" },
2082
- { url = "https://files.pythonhosted.org/packages/32/b0/a8705065b2dafae007bcae21354e6e2e832e03eb077bb6c8e523c2becb92/ruff-0.13.3-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:6b139f638a80eae7073c691a5dd8d581e0ba319540be97c343d60fb12949c8d0", size = 12421893, upload-time = "2025-10-02T19:29:15.668Z" },
2083
- { url = "https://files.pythonhosted.org/packages/0d/1e/cbe7082588d025cddbb2f23e6dfef08b1a2ef6d6f8328584ad3015b5cebd/ruff-0.13.3-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:6b547def0a40054825de7cfa341039ebdfa51f3d4bfa6a0772940ed351d2746c", size = 12267220, upload-time = "2025-10-02T19:29:17.583Z" },
2084
- { url = "https://files.pythonhosted.org/packages/a5/99/4086f9c43f85e0755996d09bdcb334b6fee9b1eabdf34e7d8b877fadf964/ruff-0.13.3-py3-none-musllinux_1_2_i686.whl", hash = "sha256:9cc48a3564423915c93573f1981d57d101e617839bef38504f85f3677b3a0a3e", size = 13177818, upload-time = "2025-10-02T19:29:19.943Z" },
2085
- { url = "https://files.pythonhosted.org/packages/9b/de/7b5db7e39947d9dc1c5f9f17b838ad6e680527d45288eeb568e860467010/ruff-0.13.3-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:1a993b17ec03719c502881cb2d5f91771e8742f2ca6de740034433a97c561989", size = 13618715, upload-time = "2025-10-02T19:29:22.527Z" },
2086
- { url = "https://files.pythonhosted.org/packages/28/d3/bb25ee567ce2f61ac52430cf99f446b0e6d49bdfa4188699ad005fdd16aa/ruff-0.13.3-py3-none-win32.whl", hash = "sha256:f14e0d1fe6460f07814d03c6e32e815bff411505178a1f539a38f6097d3e8ee3", size = 12334488, upload-time = "2025-10-02T19:29:24.782Z" },
2087
- { url = "https://files.pythonhosted.org/packages/cf/49/12f5955818a1139eed288753479ba9d996f6ea0b101784bb1fe6977ec128/ruff-0.13.3-py3-none-win_amd64.whl", hash = "sha256:621e2e5812b691d4f244638d693e640f188bacbb9bc793ddd46837cea0503dd2", size = 13455262, upload-time = "2025-10-02T19:29:26.882Z" },
2088
- { url = "https://files.pythonhosted.org/packages/fe/72/7b83242b26627a00e3af70d0394d68f8f02750d642567af12983031777fc/ruff-0.13.3-py3-none-win_arm64.whl", hash = "sha256:9e9e9d699841eaf4c2c798fa783df2fabc680b72059a02ca0ed81c460bc58330", size = 12538484, upload-time = "2025-10-02T19:29:28.951Z" },
2067
+ version = "0.14.0"
2068
+ source = { registry = "https://pypi.org/simple" }
2069
+ sdist = { url = "https://files.pythonhosted.org/packages/41/b9/9bd84453ed6dd04688de9b3f3a4146a1698e8faae2ceeccce4e14c67ae17/ruff-0.14.0.tar.gz", hash = "sha256:62ec8969b7510f77945df916de15da55311fade8d6050995ff7f680afe582c57", size = 5452071, upload-time = "2025-10-07T18:21:55.763Z" }
2070
+ wheels = [
2071
+ { url = "https://files.pythonhosted.org/packages/3a/4e/79d463a5f80654e93fa653ebfb98e0becc3f0e7cf6219c9ddedf1e197072/ruff-0.14.0-py3-none-linux_armv6l.whl", hash = "sha256:58e15bffa7054299becf4bab8a1187062c6f8cafbe9f6e39e0d5aface455d6b3", size = 12494532, upload-time = "2025-10-07T18:21:00.373Z" },
2072
+ { url = "https://files.pythonhosted.org/packages/ee/40/e2392f445ed8e02aa6105d49db4bfff01957379064c30f4811c3bf38aece/ruff-0.14.0-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:838d1b065f4df676b7c9957992f2304e41ead7a50a568185efd404297d5701e8", size = 13160768, upload-time = "2025-10-07T18:21:04.73Z" },
2073
+ { url = "https://files.pythonhosted.org/packages/75/da/2a656ea7c6b9bd14c7209918268dd40e1e6cea65f4bb9880eaaa43b055cd/ruff-0.14.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:703799d059ba50f745605b04638fa7e9682cc3da084b2092feee63500ff3d9b8", size = 12363376, upload-time = "2025-10-07T18:21:07.833Z" },
2074
+ { url = "https://files.pythonhosted.org/packages/42/e2/1ffef5a1875add82416ff388fcb7ea8b22a53be67a638487937aea81af27/ruff-0.14.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3ba9a8925e90f861502f7d974cc60e18ca29c72bb0ee8bfeabb6ade35a3abde7", size = 12608055, upload-time = "2025-10-07T18:21:10.72Z" },
2075
+ { url = "https://files.pythonhosted.org/packages/4a/32/986725199d7cee510d9f1dfdf95bf1efc5fa9dd714d0d85c1fb1f6be3bc3/ruff-0.14.0-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e41f785498bd200ffc276eb9e1570c019c1d907b07cfb081092c8ad51975bbe7", size = 12318544, upload-time = "2025-10-07T18:21:13.741Z" },
2076
+ { url = "https://files.pythonhosted.org/packages/9a/ed/4969cefd53315164c94eaf4da7cfba1f267dc275b0abdd593d11c90829a3/ruff-0.14.0-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:30a58c087aef4584c193aebf2700f0fbcfc1e77b89c7385e3139956fa90434e2", size = 14001280, upload-time = "2025-10-07T18:21:16.411Z" },
2077
+ { url = "https://files.pythonhosted.org/packages/ab/ad/96c1fc9f8854c37681c9613d825925c7f24ca1acfc62a4eb3896b50bacd2/ruff-0.14.0-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:f8d07350bc7af0a5ce8812b7d5c1a7293cf02476752f23fdfc500d24b79b783c", size = 15027286, upload-time = "2025-10-07T18:21:19.577Z" },
2078
+ { url = "https://files.pythonhosted.org/packages/b3/00/1426978f97df4fe331074baf69615f579dc4e7c37bb4c6f57c2aad80c87f/ruff-0.14.0-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:eec3bbbf3a7d5482b5c1f42d5fc972774d71d107d447919fca620b0be3e3b75e", size = 14451506, upload-time = "2025-10-07T18:21:22.779Z" },
2079
+ { url = "https://files.pythonhosted.org/packages/58/d5/9c1cea6e493c0cf0647674cca26b579ea9d2a213b74b5c195fbeb9678e15/ruff-0.14.0-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:16b68e183a0e28e5c176d51004aaa40559e8f90065a10a559176713fcf435206", size = 13437384, upload-time = "2025-10-07T18:21:25.758Z" },
2080
+ { url = "https://files.pythonhosted.org/packages/29/b4/4cd6a4331e999fc05d9d77729c95503f99eae3ba1160469f2b64866964e3/ruff-0.14.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eb732d17db2e945cfcbbc52af0143eda1da36ca8ae25083dd4f66f1542fdf82e", size = 13447976, upload-time = "2025-10-07T18:21:28.83Z" },
2081
+ { url = "https://files.pythonhosted.org/packages/3b/c0/ac42f546d07e4f49f62332576cb845d45c67cf5610d1851254e341d563b6/ruff-0.14.0-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:c958f66ab884b7873e72df38dcabee03d556a8f2ee1b8538ee1c2bbd619883dd", size = 13682850, upload-time = "2025-10-07T18:21:31.842Z" },
2082
+ { url = "https://files.pythonhosted.org/packages/5f/c4/4b0c9bcadd45b4c29fe1af9c5d1dc0ca87b4021665dfbe1c4688d407aa20/ruff-0.14.0-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:7eb0499a2e01f6e0c285afc5bac43ab380cbfc17cd43a2e1dd10ec97d6f2c42d", size = 12449825, upload-time = "2025-10-07T18:21:35.074Z" },
2083
+ { url = "https://files.pythonhosted.org/packages/4b/a8/e2e76288e6c16540fa820d148d83e55f15e994d852485f221b9524514730/ruff-0.14.0-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:4c63b2d99fafa05efca0ab198fd48fa6030d57e4423df3f18e03aa62518c565f", size = 12272599, upload-time = "2025-10-07T18:21:38.08Z" },
2084
+ { url = "https://files.pythonhosted.org/packages/18/14/e2815d8eff847391af632b22422b8207704222ff575dec8d044f9ab779b2/ruff-0.14.0-py3-none-musllinux_1_2_i686.whl", hash = "sha256:668fce701b7a222f3f5327f86909db2bbe99c30877c8001ff934c5413812ac02", size = 13193828, upload-time = "2025-10-07T18:21:41.216Z" },
2085
+ { url = "https://files.pythonhosted.org/packages/44/c6/61ccc2987cf0aecc588ff8f3212dea64840770e60d78f5606cd7dc34de32/ruff-0.14.0-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:a86bf575e05cb68dcb34e4c7dfe1064d44d3f0c04bbc0491949092192b515296", size = 13628617, upload-time = "2025-10-07T18:21:44.04Z" },
2086
+ { url = "https://files.pythonhosted.org/packages/73/e6/03b882225a1b0627e75339b420883dc3c90707a8917d2284abef7a58d317/ruff-0.14.0-py3-none-win32.whl", hash = "sha256:7450a243d7125d1c032cb4b93d9625dea46c8c42b4f06c6b709baac168e10543", size = 12367872, upload-time = "2025-10-07T18:21:46.67Z" },
2087
+ { url = "https://files.pythonhosted.org/packages/41/77/56cf9cf01ea0bfcc662de72540812e5ba8e9563f33ef3d37ab2174892c47/ruff-0.14.0-py3-none-win_amd64.whl", hash = "sha256:ea95da28cd874c4d9c922b39381cbd69cb7e7b49c21b8152b014bd4f52acddc2", size = 13464628, upload-time = "2025-10-07T18:21:50.318Z" },
2088
+ { url = "https://files.pythonhosted.org/packages/c6/2a/65880dfd0e13f7f13a775998f34703674a4554906167dce02daf7865b954/ruff-0.14.0-py3-none-win_arm64.whl", hash = "sha256:f42c9495f5c13ff841b1da4cb3c2a42075409592825dada7c5885c2c844ac730", size = 12565142, upload-time = "2025-10-07T18:21:53.577Z" },
2089
2089
  ]
2090
2090
 
2091
2091
  [[package]]
@@ -1,57 +0,0 @@
1
- import asyncio
2
- import json
3
- from pathlib import Path
4
-
5
- from typing_extensions import override
6
-
7
- from crawlee._consts import METADATA_FILENAME
8
- from crawlee.storage_clients._file_system import FileSystemKeyValueStoreClient
9
-
10
- from apify._configuration import Configuration
11
-
12
-
13
- class ApifyFileSystemKeyValueStoreClient(FileSystemKeyValueStoreClient):
14
- """Apify-specific implementation of the `FileSystemKeyValueStoreClient`.
15
-
16
- The only difference is that it overrides the `purge` method to delete all files in the key-value store
17
- directory, except for the metadata file and the `INPUT.json` file.
18
- """
19
-
20
- @override
21
- async def purge(self) -> None:
22
- """Purges the key-value store by deleting all its contents.
23
-
24
- It deletes all files in the key-value store directory, except for the metadata file and
25
- the `INPUT.json` file. It also updates the metadata to reflect that the store has been purged.
26
- """
27
- kvs_input_key = Configuration.get_global_configuration().input_key
28
-
29
- # First try to find the alternative format of the input file and process it if it exists.
30
- for file_path in self.path_to_kvs.glob('*'):
31
- if file_path.name == f'{kvs_input_key}.json':
32
- await self._process_input_json(file_path)
33
-
34
- async with self._lock:
35
- for file_path in self.path_to_kvs.glob('*'):
36
- if file_path.name in {METADATA_FILENAME, kvs_input_key, f'{kvs_input_key}.{METADATA_FILENAME}'}:
37
- continue
38
- if file_path.is_file():
39
- await asyncio.to_thread(file_path.unlink, missing_ok=True)
40
-
41
- await self._update_metadata(
42
- update_accessed_at=True,
43
- update_modified_at=True,
44
- )
45
-
46
- async def _process_input_json(self, path: Path) -> None:
47
- """Process simple input json file to format expected by the FileSystemKeyValueStoreClient.
48
-
49
- For example: INPUT.json -> INPUT, INPUT.json.metadata
50
- """
51
- try:
52
- f = await asyncio.to_thread(path.open)
53
- input_data = json.load(f)
54
- finally:
55
- f.close()
56
- await asyncio.to_thread(path.unlink, missing_ok=True)
57
- await self.set_value(key=path.stem, value=input_data)
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes