apify 3.0.1b1__tar.gz → 3.0.2b1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of apify might be problematic. Click here for more details.
- {apify-3.0.1b1 → apify-3.0.2b1}/CHANGELOG.md +12 -1
- {apify-3.0.1b1 → apify-3.0.2b1}/PKG-INFO +2 -2
- {apify-3.0.1b1 → apify-3.0.2b1}/pyproject.toml +3 -3
- {apify-3.0.1b1 → apify-3.0.2b1}/src/apify/_configuration.py +9 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/src/apify/storage_clients/_apify/_request_queue_single_client.py +10 -4
- apify-3.0.2b1/src/apify/storage_clients/_file_system/_key_value_store_client.py +103 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/tests/unit/storage_clients/test_file_system.py +23 -10
- {apify-3.0.1b1 → apify-3.0.2b1}/uv.lock +28 -28
- {apify-3.0.1b1 → apify-3.0.2b1}/website/package-lock.json +32 -14
- {apify-3.0.1b1 → apify-3.0.2b1}/website/package.json +1 -1
- apify-3.0.1b1/src/apify/storage_clients/_file_system/_key_value_store_client.py +0 -57
- {apify-3.0.1b1 → apify-3.0.2b1}/.editorconfig +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/.github/CODEOWNERS +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/.github/workflows/build_and_deploy_docs.yaml +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/.github/workflows/check_pr_title.yaml +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/.github/workflows/pre_release.yaml +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/.github/workflows/release.yaml +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/.github/workflows/run_code_checks.yaml +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/.github/workflows/update_new_issue.yaml +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/.gitignore +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/.markdownlint.yaml +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/.pre-commit-config.yaml +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/CONTRIBUTING.md +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/LICENSE +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/Makefile +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/README.md +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/01_overview/01_introduction.mdx +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/01_overview/02_running_actors_locally.mdx +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/01_overview/03_actor_structure.mdx +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/01_overview/code/01_introduction.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/01_overview/code/actor_structure/__init__.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/01_overview/code/actor_structure/__main__.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/01_overview/code/actor_structure/main.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/01_overview/code/actor_structure/py.typed +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/02_concepts/01_actor_lifecycle.mdx +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/02_concepts/02_actor_input.mdx +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/02_concepts/03_storages.mdx +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/02_concepts/04_actor_events.mdx +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/02_concepts/05_proxy_management.mdx +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/02_concepts/06_interacting_with_other_actors.mdx +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/02_concepts/07_webhooks.mdx +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/02_concepts/08_access_apify_api.mdx +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/02_concepts/09_running_webserver.mdx +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/02_concepts/10_logging.mdx +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/02_concepts/11_configuration.mdx +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/02_concepts/12_pay_per_event.mdx +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/02_concepts/code/01_context_manager.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/02_concepts/code/01_init_exit.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/02_concepts/code/01_reboot.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/02_concepts/code/01_status_message.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/02_concepts/code/02_input.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/02_concepts/code/03_dataset_exports.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/02_concepts/code/03_dataset_read_write.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/02_concepts/code/03_deleting_storages.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/02_concepts/code/03_kvs_iterating.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/02_concepts/code/03_kvs_public_url.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/02_concepts/code/03_kvs_read_write.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/02_concepts/code/03_opening_storages.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/02_concepts/code/03_rq.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/02_concepts/code/04_actor_events.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/02_concepts/code/05_apify_proxy.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/02_concepts/code/05_apify_proxy_config.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/02_concepts/code/05_custom_proxy.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/02_concepts/code/05_custom_proxy_function.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/02_concepts/code/05_proxy_actor_input.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/02_concepts/code/05_proxy_httpx.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/02_concepts/code/05_proxy_rotation.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/02_concepts/code/06_interacting_call.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/02_concepts/code/06_interacting_call_task.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/02_concepts/code/06_interacting_metamorph.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/02_concepts/code/06_interacting_start.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/02_concepts/code/07_webhook.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/02_concepts/code/07_webhook_preventing.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/02_concepts/code/08_actor_client.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/02_concepts/code/08_actor_new_client.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/02_concepts/code/09_webserver.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/02_concepts/code/10_log_config.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/02_concepts/code/10_logger_usage.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/02_concepts/code/10_redirect_log.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/02_concepts/code/10_redirect_log_existing_run.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/02_concepts/code/11_config.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/02_concepts/code/actor_charge.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/02_concepts/code/conditional_actor_charge.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/03_guides/01_beautifulsoup_httpx.mdx +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/03_guides/02_parsel_impit.mdx +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/03_guides/03_playwright.mdx +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/03_guides/04_selenium.mdx +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/03_guides/05_crawlee.mdx +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/03_guides/06_scrapy.mdx +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/03_guides/code/01_beautifulsoup_httpx.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/03_guides/code/02_parsel_impit.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/03_guides/code/03_playwright.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/03_guides/code/04_selenium.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/03_guides/code/05_crawlee_beautifulsoup.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/03_guides/code/05_crawlee_parsel.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/03_guides/code/05_crawlee_playwright.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/03_guides/code/scrapy_project/src/__init__.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/03_guides/code/scrapy_project/src/__main__.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/03_guides/code/scrapy_project/src/items.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/03_guides/code/scrapy_project/src/main.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/03_guides/code/scrapy_project/src/py.typed +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/03_guides/code/scrapy_project/src/settings.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/03_guides/code/scrapy_project/src/spiders/__init__.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/03_guides/code/scrapy_project/src/spiders/py.typed +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/03_guides/code/scrapy_project/src/spiders/title.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/04_upgrading/upgrading_to_v2.md +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/04_upgrading/upgrading_to_v3.md +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/docs/pyproject.toml +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/renovate.json +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/src/apify/__init__.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/src/apify/_actor.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/src/apify/_charging.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/src/apify/_consts.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/src/apify/_crypto.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/src/apify/_models.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/src/apify/_proxy_configuration.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/src/apify/_utils.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/src/apify/events/__init__.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/src/apify/events/_apify_event_manager.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/src/apify/events/_types.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/src/apify/events/py.typed +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/src/apify/log.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/src/apify/py.typed +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/src/apify/request_loaders/__init__.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/src/apify/request_loaders/_apify_request_list.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/src/apify/request_loaders/py.typed +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/src/apify/scrapy/__init__.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/src/apify/scrapy/_actor_runner.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/src/apify/scrapy/_async_thread.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/src/apify/scrapy/_logging_config.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/src/apify/scrapy/extensions/__init__.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/src/apify/scrapy/extensions/_httpcache.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/src/apify/scrapy/middlewares/__init__.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/src/apify/scrapy/middlewares/apify_proxy.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/src/apify/scrapy/middlewares/py.typed +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/src/apify/scrapy/pipelines/__init__.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/src/apify/scrapy/pipelines/actor_dataset_push.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/src/apify/scrapy/pipelines/py.typed +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/src/apify/scrapy/py.typed +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/src/apify/scrapy/requests.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/src/apify/scrapy/scheduler.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/src/apify/scrapy/utils.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/src/apify/storage_clients/__init__.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/src/apify/storage_clients/_apify/__init__.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/src/apify/storage_clients/_apify/_dataset_client.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/src/apify/storage_clients/_apify/_key_value_store_client.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/src/apify/storage_clients/_apify/_models.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/src/apify/storage_clients/_apify/_request_queue_client.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/src/apify/storage_clients/_apify/_request_queue_shared_client.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/src/apify/storage_clients/_apify/_storage_client.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/src/apify/storage_clients/_apify/_utils.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/src/apify/storage_clients/_apify/py.typed +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/src/apify/storage_clients/_file_system/__init__.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/src/apify/storage_clients/_file_system/_storage_client.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/src/apify/storage_clients/_smart_apify/__init__.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/src/apify/storage_clients/_smart_apify/_storage_client.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/src/apify/storage_clients/py.typed +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/src/apify/storages/__init__.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/src/apify/storages/py.typed +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/tests/integration/README.md +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/tests/integration/__init__.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/tests/integration/_utils.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/tests/integration/actor_source_base/Dockerfile +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/tests/integration/actor_source_base/requirements.txt +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/tests/integration/actor_source_base/server.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/tests/integration/actor_source_base/src/__init__.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/tests/integration/actor_source_base/src/__main__.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/tests/integration/actor_source_base/src/main.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/tests/integration/conftest.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/tests/integration/test_actor_api_helpers.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/tests/integration/test_actor_call_timeouts.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/tests/integration/test_actor_charge.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/tests/integration/test_actor_create_proxy_configuration.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/tests/integration/test_actor_dataset.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/tests/integration/test_actor_events.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/tests/integration/test_actor_key_value_store.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/tests/integration/test_actor_lifecycle.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/tests/integration/test_actor_log.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/tests/integration/test_actor_request_queue.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/tests/integration/test_actor_scrapy.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/tests/integration/test_apify_storages.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/tests/integration/test_crawlers_with_storages.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/tests/integration/test_fixtures.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/tests/integration/test_request_queue.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/tests/unit/__init__.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/tests/unit/actor/__init__.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/tests/unit/actor/test_actor_create_proxy_configuration.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/tests/unit/actor/test_actor_dataset.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/tests/unit/actor/test_actor_env_helpers.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/tests/unit/actor/test_actor_helpers.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/tests/unit/actor/test_actor_key_value_store.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/tests/unit/actor/test_actor_lifecycle.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/tests/unit/actor/test_actor_log.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/tests/unit/actor/test_actor_non_default_instance.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/tests/unit/actor/test_actor_request_queue.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/tests/unit/actor/test_configuration.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/tests/unit/actor/test_request_list.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/tests/unit/conftest.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/tests/unit/events/__init__.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/tests/unit/events/test_apify_event_manager.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/tests/unit/scrapy/__init__.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/tests/unit/scrapy/extensions/__init__.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/tests/unit/scrapy/extensions/test_httpcache.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/tests/unit/scrapy/middlewares/__init__.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/tests/unit/scrapy/middlewares/test_apify_proxy.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/tests/unit/scrapy/pipelines/__init__.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/tests/unit/scrapy/pipelines/test_actor_dataset_push.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/tests/unit/scrapy/requests/__init__.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/tests/unit/scrapy/requests/test_to_apify_request.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/tests/unit/scrapy/requests/test_to_scrapy_request.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/tests/unit/scrapy/utils/__init__.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/tests/unit/scrapy/utils/test_apply_apify_settings.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/tests/unit/scrapy/utils/test_get_basic_auth_header.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/tests/unit/storage_clients/__init__.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/tests/unit/storage_clients/test_apify_request_queue_client.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/tests/unit/test_apify_storages.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/tests/unit/test_crypto.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/tests/unit/test_proxy_configuration.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/website/.eslintrc.json +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/website/babel.config.js +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/website/build_api_reference.sh +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/website/docusaurus.config.js +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/website/generate_module_shortcuts.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/website/sidebars.js +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/website/src/components/ApiLink.jsx +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/website/src/components/Gradients.jsx +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/website/src/components/Highlights.jsx +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/website/src/components/Highlights.module.css +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/website/src/components/RunnableCodeBlock.jsx +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/website/src/components/RunnableCodeBlock.module.css +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/website/src/css/custom.css +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/website/src/pages/home_page_example.py +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/website/src/pages/index.js +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/website/src/pages/index.module.css +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/website/src/theme/DocItem/Content/index.js +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/website/static/.nojekyll +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/website/static/img/docs-og.png +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/website/static/img/guides/redirected_logs_example.webp +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/website/tools/docs-prettier.config.js +0 -0
- {apify-3.0.1b1 → apify-3.0.2b1}/website/tools/utils/externalLink.js +0 -0
|
@@ -3,10 +3,21 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
5
|
<!-- git-cliff-unreleased-start -->
|
|
6
|
-
## 3.0.
|
|
6
|
+
## 3.0.2 - **not yet released**
|
|
7
|
+
|
|
8
|
+
### 🐛 Bug Fixes
|
|
9
|
+
|
|
10
|
+
- Handle None result in single consumer request queue client ([#623](https://github.com/apify/apify-sdk-python/pull/623)) ([451284a](https://github.com/apify/apify-sdk-python/commit/451284a5c633bc5613bd1e9060df286a1c20b259)) by [@janbuchar](https://github.com/janbuchar), closes [#1472](https://github.com/apify/apify-sdk-python/issues/1472)
|
|
7
11
|
|
|
8
12
|
|
|
9
13
|
<!-- git-cliff-unreleased-end -->
|
|
14
|
+
## [3.0.1](https://github.com/apify/apify-sdk-python/releases/tag/v3.0.1) (2025-10-08)
|
|
15
|
+
|
|
16
|
+
### 🐛 Bug Fixes
|
|
17
|
+
|
|
18
|
+
- 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)
|
|
19
|
+
|
|
20
|
+
|
|
10
21
|
## [3.0.0](https://github.com/apify/apify-sdk-python/releases/tag/v3.0.0) (2025-09-29)
|
|
11
22
|
|
|
12
23
|
- Check out the [Upgrading guide](https://docs.apify.com/sdk/python/docs/upgrading/upgrading-to-v3) to ensure a smooth update.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: apify
|
|
3
|
-
Version: 3.0.
|
|
3
|
+
Version: 3.0.2b1
|
|
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.
|
|
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.
|
|
7
|
+
version = "3.0.2b1"
|
|
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.
|
|
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.
|
|
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.
|
{apify-3.0.1b1 → apify-3.0.2b1}/src/apify/storage_clients/_apify/_request_queue_single_client.py
RENAMED
|
@@ -247,10 +247,16 @@ class _ApifyRequestQueueSingleClient:
|
|
|
247
247
|
else:
|
|
248
248
|
# Only fetch the request if we do not know it yet.
|
|
249
249
|
if request.unique_key not in self._requests_cache:
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
250
|
+
request_id = unique_key_to_request_id(request.unique_key)
|
|
251
|
+
complete_request_data = await self._api_client.get_request(request_id)
|
|
252
|
+
|
|
253
|
+
if complete_request_data is not None:
|
|
254
|
+
request = Request.model_validate(complete_request_data)
|
|
255
|
+
self._requests_cache[request.unique_key] = request
|
|
256
|
+
else:
|
|
257
|
+
logger.warning(
|
|
258
|
+
f'Could not fetch request data for unique_key=`{request.unique_key}` (id=`{request_id}`)'
|
|
259
|
+
)
|
|
254
260
|
|
|
255
261
|
# Add new requests to the end of the head, unless already present in head
|
|
256
262
|
if request.unique_key not in self._head_requests:
|
|
@@ -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
|
|
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
|
|
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.
|
|
31
|
+
version = "3.0.2b1"
|
|
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.
|
|
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.
|
|
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.
|
|
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/
|
|
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/
|
|
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.
|
|
2068
|
-
source = { registry = "https://pypi.org/simple" }
|
|
2069
|
-
sdist = { url = "https://files.pythonhosted.org/packages/
|
|
2070
|
-
wheels = [
|
|
2071
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
2072
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
2073
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
2074
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
2075
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
2076
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
2077
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
2078
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
2079
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
2080
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
2081
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
2082
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
2083
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
2084
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
2085
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
2086
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
2087
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
2088
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
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]]
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"@typescript-eslint/parser": "^8.0.0",
|
|
30
30
|
"eslint": "^8.35.0",
|
|
31
31
|
"eslint-plugin-react": "^7.32.2",
|
|
32
|
-
"eslint-plugin-react-hooks": "^
|
|
32
|
+
"eslint-plugin-react-hooks": "^7.0.0",
|
|
33
33
|
"markdownlint": "^0.38.0",
|
|
34
34
|
"markdownlint-cli": "^0.45.0",
|
|
35
35
|
"path-browserify": "^1.0.1",
|
|
@@ -465,9 +465,9 @@
|
|
|
465
465
|
}
|
|
466
466
|
},
|
|
467
467
|
"node_modules/@apify/docs-search-modal": {
|
|
468
|
-
"version": "1.3.
|
|
469
|
-
"resolved": "https://registry.npmjs.org/@apify/docs-search-modal/-/docs-search-modal-1.3.
|
|
470
|
-
"integrity": "sha512-
|
|
468
|
+
"version": "1.3.3",
|
|
469
|
+
"resolved": "https://registry.npmjs.org/@apify/docs-search-modal/-/docs-search-modal-1.3.3.tgz",
|
|
470
|
+
"integrity": "sha512-QbcjdXCm/2PF3yoCLTC1hGY6YLH61DIt4+PRECauTbQs8iD8OKZpSvpgqdQ5z5f4Ix/7NEm3a/+ipEhgpQAv1Q==",
|
|
471
471
|
"license": "ISC",
|
|
472
472
|
"dependencies": {
|
|
473
473
|
"@algolia/autocomplete-js": "^1.10.0",
|
|
@@ -566,9 +566,9 @@
|
|
|
566
566
|
}
|
|
567
567
|
},
|
|
568
568
|
"node_modules/@apify/docs-search-modal/node_modules/@apify/ui-library": {
|
|
569
|
-
"version": "1.98.
|
|
570
|
-
"resolved": "https://registry.npmjs.org/@apify/ui-library/-/ui-library-1.98.
|
|
571
|
-
"integrity": "sha512-
|
|
569
|
+
"version": "1.98.3",
|
|
570
|
+
"resolved": "https://registry.npmjs.org/@apify/ui-library/-/ui-library-1.98.3.tgz",
|
|
571
|
+
"integrity": "sha512-CL5flSXQd38BahGNd5OnpShjGr89UxEB+B5Lc4x4tdrSJPT4RASHC9vdAVPycXrFUR4RX0D4Y2/9gxyiXukgxQ==",
|
|
572
572
|
"license": "Apache-2.0",
|
|
573
573
|
"dependencies": {
|
|
574
574
|
"@apify/ui-icons": "^1.19.0",
|
|
@@ -1671,12 +1671,12 @@
|
|
|
1671
1671
|
}
|
|
1672
1672
|
},
|
|
1673
1673
|
"node_modules/@apify/docs-theme": {
|
|
1674
|
-
"version": "1.0.
|
|
1675
|
-
"resolved": "https://registry.npmjs.org/@apify/docs-theme/-/docs-theme-1.0.
|
|
1676
|
-
"integrity": "sha512-
|
|
1674
|
+
"version": "1.0.216",
|
|
1675
|
+
"resolved": "https://registry.npmjs.org/@apify/docs-theme/-/docs-theme-1.0.216.tgz",
|
|
1676
|
+
"integrity": "sha512-dWGkZjHm5o75azlUg6sBbvCLamjWUW3nmgOIzTrqlPrKtacXLNIigLvb0vguKvol+tUZGL0f7cxUhuoBn02cmA==",
|
|
1677
1677
|
"license": "ISC",
|
|
1678
1678
|
"dependencies": {
|
|
1679
|
-
"@apify/docs-search-modal": "^1.
|
|
1679
|
+
"@apify/docs-search-modal": "^1.3.3",
|
|
1680
1680
|
"@apify/ui-icons": "^1.19.0",
|
|
1681
1681
|
"@apify/ui-library": "^1.97.2",
|
|
1682
1682
|
"@docusaurus/theme-common": "^3.7.0",
|
|
@@ -13167,14 +13167,15 @@
|
|
|
13167
13167
|
}
|
|
13168
13168
|
},
|
|
13169
13169
|
"node_modules/eslint-plugin-react-hooks": {
|
|
13170
|
-
"version": "
|
|
13171
|
-
"resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-
|
|
13172
|
-
"integrity": "sha512-
|
|
13170
|
+
"version": "7.0.0",
|
|
13171
|
+
"resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-7.0.0.tgz",
|
|
13172
|
+
"integrity": "sha512-fNXaOwvKwq2+pXiRpXc825Vd63+KM4DLL40Rtlycb8m7fYpp6efrTp1sa6ZbP/Ap58K2bEKFXRmhURE+CJAQWw==",
|
|
13173
13173
|
"dev": true,
|
|
13174
13174
|
"license": "MIT",
|
|
13175
13175
|
"dependencies": {
|
|
13176
13176
|
"@babel/core": "^7.24.4",
|
|
13177
13177
|
"@babel/parser": "^7.24.4",
|
|
13178
|
+
"hermes-parser": "^0.25.1",
|
|
13178
13179
|
"zod": "^3.22.4 || ^4.0.0",
|
|
13179
13180
|
"zod-validation-error": "^3.0.3 || ^4.0.0"
|
|
13180
13181
|
},
|
|
@@ -15160,6 +15161,23 @@
|
|
|
15160
15161
|
"he": "bin/he"
|
|
15161
15162
|
}
|
|
15162
15163
|
},
|
|
15164
|
+
"node_modules/hermes-estree": {
|
|
15165
|
+
"version": "0.25.1",
|
|
15166
|
+
"resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz",
|
|
15167
|
+
"integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==",
|
|
15168
|
+
"dev": true,
|
|
15169
|
+
"license": "MIT"
|
|
15170
|
+
},
|
|
15171
|
+
"node_modules/hermes-parser": {
|
|
15172
|
+
"version": "0.25.1",
|
|
15173
|
+
"resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.25.1.tgz",
|
|
15174
|
+
"integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==",
|
|
15175
|
+
"dev": true,
|
|
15176
|
+
"license": "MIT",
|
|
15177
|
+
"dependencies": {
|
|
15178
|
+
"hermes-estree": "0.25.1"
|
|
15179
|
+
}
|
|
15180
|
+
},
|
|
15163
15181
|
"node_modules/history": {
|
|
15164
15182
|
"version": "4.10.1",
|
|
15165
15183
|
"resolved": "https://registry.npmjs.org/history/-/history-4.10.1.tgz",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"@typescript-eslint/parser": "^8.0.0",
|
|
45
45
|
"eslint": "^8.35.0",
|
|
46
46
|
"eslint-plugin-react": "^7.32.2",
|
|
47
|
-
"eslint-plugin-react-hooks": "^
|
|
47
|
+
"eslint-plugin-react-hooks": "^7.0.0",
|
|
48
48
|
"markdownlint": "^0.38.0",
|
|
49
49
|
"markdownlint-cli": "^0.45.0",
|
|
50
50
|
"path-browserify": "^1.0.1",
|
|
@@ -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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|