direct-cli 0.3.12__tar.gz → 0.3.14__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.
- {direct_cli-0.3.12 → direct_cli-0.3.14}/AGENTS.md +6 -6
- {direct_cli-0.3.12 → direct_cli-0.3.14}/CHANGELOG.md +268 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/CLAUDE.md +30 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/PKG-INFO +50 -41
- {direct_cli-0.3.12 → direct_cli-0.3.14}/README.md +49 -40
- direct_cli-0.3.14/direct_cli/_bidding_strategy.py +5553 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/direct_cli/_vendor/tapi_yandex_direct/resource_mapping.py +8 -8
- {direct_cli-0.3.12 → direct_cli-0.3.14}/direct_cli/commands/adgroups.py +117 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/direct_cli/commands/ads.py +206 -50
- {direct_cli-0.3.12 → direct_cli-0.3.14}/direct_cli/commands/agencyclients.py +85 -1
- {direct_cli-0.3.12 → direct_cli-0.3.14}/direct_cli/commands/bidmodifiers.py +153 -1
- direct_cli-0.3.14/direct_cli/commands/campaigns.py +7547 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/direct_cli/commands/changes.py +11 -5
- {direct_cli-0.3.12 → direct_cli-0.3.14}/direct_cli/commands/clients.py +85 -1
- {direct_cli-0.3.12 → direct_cli-0.3.14}/direct_cli/commands/creatives.py +71 -2
- {direct_cli-0.3.12 → direct_cli-0.3.14}/direct_cli/commands/feeds.py +47 -2
- {direct_cli-0.3.12 → direct_cli-0.3.14}/direct_cli/commands/keywordbids.py +61 -3
- {direct_cli-0.3.12 → direct_cli-0.3.14}/direct_cli/commands/keywords.py +59 -1
- {direct_cli-0.3.12 → direct_cli-0.3.14}/direct_cli/commands/sitelinks.py +37 -4
- {direct_cli-0.3.12 → direct_cli-0.3.14}/direct_cli/commands/strategies.py +256 -10
- {direct_cli-0.3.12 → direct_cli-0.3.14}/direct_cli/reports_coverage.py +23 -1
- {direct_cli-0.3.12 → direct_cli-0.3.14}/direct_cli/utils.py +53 -7
- {direct_cli-0.3.12 → direct_cli-0.3.14}/direct_cli/v4/money.py +1 -1
- {direct_cli-0.3.12 → direct_cli-0.3.14}/direct_cli/wsdl_coverage.py +57 -1
- {direct_cli-0.3.12 → direct_cli-0.3.14}/direct_cli.egg-info/PKG-INFO +50 -41
- {direct_cli-0.3.12 → direct_cli-0.3.14}/direct_cli.egg-info/SOURCES.txt +2 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/pyproject.toml +1 -1
- {direct_cli-0.3.12 → direct_cli-0.3.14}/scripts/build_api_coverage_report.py +1 -1
- direct_cli-0.3.14/scripts/check_all_docs_urls.py +166 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/scripts/release_pypi.sh +8 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/scripts/test_safe_commands.sh +1 -1
- direct_cli-0.3.14/tests/WSDL_OPTIONAL_FIELD_AUDIT.md +3292 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/api_coverage_payloads.py +332 -1
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/reports_cache/raw/fields-list.html +6 -6
- direct_cli-0.3.14/tests/reports_cache/raw/headers.html +88 -0
- direct_cli-0.3.14/tests/reports_cache/raw/period.html +119 -0
- direct_cli-0.3.14/tests/reports_cache/raw/spec.html +643 -0
- direct_cli-0.3.14/tests/reports_cache/raw/type.html +279 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/reports_cache/spec.json +1 -1
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/test_api_coverage.py +191 -19
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/test_changes.py +29 -2
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/test_cli.py +3 -4
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/test_cli_contract.py +6 -1
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/test_comprehensive.py +7 -20
- direct_cli-0.3.14/tests/test_dry_run.py +22918 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/test_integration.py +85 -10
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/test_low_coverage_payloads.py +18 -6
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/test_sandbox_write_audit.py +7 -3
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/test_smoke_matrix.py +49 -7
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/test_wsdl_parity_gate.py +2598 -91
- direct_cli-0.3.12/direct_cli/commands/campaigns.py +0 -2678
- direct_cli-0.3.12/tests/WSDL_OPTIONAL_FIELD_AUDIT.md +0 -5239
- direct_cli-0.3.12/tests/reports_cache/raw/headers.html +0 -88
- direct_cli-0.3.12/tests/reports_cache/raw/period.html +0 -119
- direct_cli-0.3.12/tests/reports_cache/raw/spec.html +0 -660
- direct_cli-0.3.12/tests/reports_cache/raw/type.html +0 -279
- direct_cli-0.3.12/tests/test_dry_run.py +0 -11240
- {direct_cli-0.3.12 → direct_cli-0.3.14}/.env.example +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/.github/copilot-instructions.md +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/.github/workflows/api-coverage.yml +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/.github/workflows/claude.yml +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/.github/workflows/quality.yml +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/.gitignore +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/MANIFEST.in +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/direct_cli/__init__.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/direct_cli/_deprecated.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/direct_cli/_smoke_probes.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/direct_cli/_vendor/__init__.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/direct_cli/_vendor/tapi_yandex_direct/__init__.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/direct_cli/_vendor/tapi_yandex_direct/endpoints.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/direct_cli/_vendor/tapi_yandex_direct/exceptions.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/direct_cli/_vendor/tapi_yandex_direct/tapi_yandex_direct.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/direct_cli/_vendor/tapi_yandex_direct/tapi_yandex_direct.pyi +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/direct_cli/_vendor/tapi_yandex_direct/v4/__init__.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/direct_cli/_vendor/tapi_yandex_direct/v4/adapter.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/direct_cli/_vendor/tapi_yandex_direct/v4/adapter.pyi +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/direct_cli/_vendor/tapi_yandex_direct/v4/resource_mapping.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/direct_cli/api.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/direct_cli/auth.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/direct_cli/cli.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/direct_cli/commands/__init__.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/direct_cli/commands/adextensions.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/direct_cli/commands/adimages.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/direct_cli/commands/advideos.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/direct_cli/commands/audiencetargets.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/direct_cli/commands/auth.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/direct_cli/commands/balance.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/direct_cli/commands/bids.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/direct_cli/commands/businesses.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/direct_cli/commands/dictionaries.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/direct_cli/commands/dynamicads.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/direct_cli/commands/dynamicfeedadtargets.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/direct_cli/commands/keywordsresearch.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/direct_cli/commands/leads.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/direct_cli/commands/negativekeywordsharedsets.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/direct_cli/commands/reports.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/direct_cli/commands/retargeting.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/direct_cli/commands/smartadtargets.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/direct_cli/commands/turbopages.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/direct_cli/commands/v4account.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/direct_cli/commands/v4events.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/direct_cli/commands/v4finance.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/direct_cli/commands/v4forecast.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/direct_cli/commands/v4goals.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/direct_cli/commands/v4shells.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/direct_cli/commands/v4tags.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/direct_cli/commands/v4wordstat.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/direct_cli/commands/vcards.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/direct_cli/output.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/direct_cli/smoke_matrix.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/direct_cli/v4/__init__.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/direct_cli/v4_contracts.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/direct_cli.egg-info/dependency_links.txt +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/direct_cli.egg-info/entry_points.txt +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/direct_cli.egg-info/requires.txt +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/direct_cli.egg-info/top_level.txt +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/docs/audits/issue-198-mutating-wsdl-audit.md +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/docs/superpowers/plans/2026-04-12-issue-32-completion.md +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/docs/superpowers/specs/2026-04-23-vendor-tapi-yandex-direct-design.md +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/scripts/anonymize_cassettes.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/scripts/build_api_coverage_checklist.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/scripts/build_wsdl_optional_field_audit.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/scripts/check_reports_drift.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/scripts/check_wsdl_drift.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/scripts/patch_vendor_imports.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/scripts/refresh_reports_cache.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/scripts/refresh_wsdl_cache.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/scripts/sandbox_write_audit.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/scripts/sandbox_write_live.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/scripts/test_dangerous_commands.sh +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/scripts/test_sandbox_write.sh +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/scripts/update_vendor.sh +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/setup.cfg +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/setup.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/API_COVERAGE.md +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/API_ISSUE_AUDIT.md +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/MANUAL_COVERAGE.md +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/__init__.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/_orphan_store.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/cassettes/test_integration_write/TestWriteAdExtensions.test_add_delete.yaml +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/cassettes/test_integration_write/TestWriteAdGroups.test_add_update_delete.yaml +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/cassettes/test_integration_write/TestWriteAdImages.test_add_delete.yaml +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/cassettes/test_integration_write/TestWriteAds.test_add_text_ad_update_delete.yaml +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/cassettes/test_integration_write/TestWriteAudienceTargets.test_add_delete.yaml +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/cassettes/test_integration_write/TestWriteBidModifiersAdd.test_add_delete_mobile.yaml +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/cassettes/test_integration_write/TestWriteBidModifiersSet.test_set_without_id_is_rejected.yaml +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/cassettes/test_integration_write/TestWriteBids.test_set_bid.yaml +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/cassettes/test_integration_write/TestWriteBidsRead.test_bids_get.yaml +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/cassettes/test_integration_write/TestWriteBidsRead.test_bids_set_auto.yaml +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/cassettes/test_integration_write/TestWriteCampaignDraftLifecycle.test_draft_create_get_delete.yaml +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/cassettes/test_integration_write/TestWriteCampaigns.test_campaign_lifecycle.yaml +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/cassettes/test_integration_write/TestWriteDynamicAds.test_add_update_delete.yaml +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/cassettes/test_integration_write/TestWriteFeeds.test_add_update_delete.yaml +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/cassettes/test_integration_write/TestWriteKeywordBids.test_set_keyword_bid.yaml +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/cassettes/test_integration_write/TestWriteKeywords.test_add_update_delete.yaml +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/cassettes/test_integration_write/TestWriteNegativeKeywordSharedSets.test_add_update_delete.yaml +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/cassettes/test_integration_write/TestWriteRetargeting.test_add_delete.yaml +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/cassettes/test_integration_write/TestWriteRetargetingUpdate.test_retargeting_update.yaml +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/cassettes/test_integration_write/TestWriteSitelinks.test_add_delete.yaml +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/cassettes/test_integration_write/TestWriteSmartAdTargets.test_add_update_delete.yaml +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/cassettes/test_integration_write/TestWriteStrategies.test_strategies_lifecycle.yaml +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/cassettes/test_integration_write/TestWriteVCards.test_add_delete.yaml +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/cassettes/test_v5_live_write/test_v5_live_draft_adgroups_add_update_delete.yaml +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/cassettes/test_v5_live_write/test_v5_live_draft_adimages_add_get_delete.yaml +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/cassettes/test_v5_live_write/test_v5_live_draft_ads_add_update_delete.yaml +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/cassettes/test_v5_live_write/test_v5_live_draft_ads_suspend_resume_archive_unarchive.yaml +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/cassettes/test_v5_live_write/test_v5_live_draft_advideos_add_get.yaml +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/cassettes/test_v5_live_write/test_v5_live_draft_audiencetargets_add_delete.yaml +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/cassettes/test_v5_live_write/test_v5_live_draft_audiencetargets_suspend_resume.yaml +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/cassettes/test_v5_live_write/test_v5_live_draft_bids_set.yaml +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/cassettes/test_v5_live_write/test_v5_live_draft_campaign_create_get_delete.yaml +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/cassettes/test_v5_live_write/test_v5_live_draft_creatives_chain_advideo_to_creative.yaml +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/cassettes/test_v5_live_write/test_v5_live_draft_dynamicads_add_delete.yaml +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/cassettes/test_v5_live_write/test_v5_live_draft_dynamicads_suspend_resume.yaml +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/cassettes/test_v5_live_write/test_v5_live_draft_keywordbids_set.yaml +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/cassettes/test_v5_live_write/test_v5_live_draft_keywords_add_update_delete.yaml +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/cassettes/test_v5_live_write/test_v5_live_draft_keywords_suspend_resume.yaml +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/cassettes/test_v5_live_write/test_v5_live_draft_sitelinks_add_get_delete.yaml +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/cassettes/test_v5_live_write/test_v5_live_draft_smartadtargets_add_update_delete.yaml +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/cassettes/test_v5_live_write/test_v5_live_draft_smartadtargets_suspend_resume.yaml +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/conftest.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/fixtures/test-video.mp4 +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/test_auth_bw.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/test_auth_oauth.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/test_auth_op.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/test_auth_write_json.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/test_balance.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/test_env_loading.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/test_integration_write.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/test_reports_drift.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/test_reports_parsing.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/test_transport_contract.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/test_unknown_option_hints.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/test_v4_contracts.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/test_v4_exit_codes.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/test_v4_foundation.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/test_v4_live_contracts.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/test_v4_runtime_shape.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/test_v4_safety.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/test_v4account.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/test_v4events.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/test_v4finance_money.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/test_v4finance_read.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/test_v4forecast.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/test_v4goals.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/test_v4tags.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/test_v4wordstat.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/test_v5_live_write.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/test_vendor_imports.py +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/wsdl_cache/adextensions.xml +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/wsdl_cache/adgroups.xml +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/wsdl_cache/adimages.xml +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/wsdl_cache/ads.xml +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/wsdl_cache/advideos.xml +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/wsdl_cache/agencyclients.xml +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/wsdl_cache/audiencetargets.xml +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/wsdl_cache/bidmodifiers.xml +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/wsdl_cache/bids.xml +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/wsdl_cache/businesses.xml +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/wsdl_cache/campaigns.xml +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/wsdl_cache/changes.xml +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/wsdl_cache/clients.xml +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/wsdl_cache/creatives.xml +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/wsdl_cache/dictionaries.xml +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/wsdl_cache/dynamicfeedadtargets.xml +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/wsdl_cache/dynamictextadtargets.xml +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/wsdl_cache/feeds.xml +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/wsdl_cache/imports/adextensiontypes.xsd +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/wsdl_cache/imports/general.xsd +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/wsdl_cache/imports/generalclients.xsd +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/wsdl_cache/keywordbids.xml +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/wsdl_cache/keywords.xml +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/wsdl_cache/keywordsresearch.xml +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/wsdl_cache/leads.xml +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/wsdl_cache/negativekeywordsharedsets.xml +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/wsdl_cache/retargetinglists.xml +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/wsdl_cache/sitelinks.xml +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/wsdl_cache/smartadtargets.xml +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/wsdl_cache/strategies.xml +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/wsdl_cache/turbopages.xml +0 -0
- {direct_cli-0.3.12 → direct_cli-0.3.14}/tests/wsdl_cache/vcards.xml +0 -0
|
@@ -73,21 +73,22 @@ direct dictionaries get-geo-regions \
|
|
|
73
73
|
|
|
74
74
|
### Datetime Rules
|
|
75
75
|
|
|
76
|
-
-
|
|
76
|
+
- Changes timestamps must match Yandex Direct API format `YYYY-MM-DDTHH:MM:SSZ`.
|
|
77
|
+
- Other datetime parameters use their method-specific documented format.
|
|
77
78
|
- Datetime values must be passed as a single shell token.
|
|
78
|
-
- Canonical examples must
|
|
79
|
+
- Canonical `changes` examples must use the `Z` suffix.
|
|
79
80
|
- Canonical examples must not use quoted space-separated datetime values.
|
|
80
81
|
|
|
81
82
|
Use:
|
|
82
83
|
|
|
83
84
|
```bash
|
|
84
|
-
direct changes check-campaigns --timestamp 2026-04-14T00:00:
|
|
85
|
+
direct changes check-campaigns --timestamp 2026-04-14T00:00:00Z
|
|
85
86
|
```
|
|
86
87
|
|
|
87
88
|
Do not use:
|
|
88
89
|
|
|
89
90
|
```bash
|
|
90
|
-
direct changes check-campaigns --timestamp 2026-04-14T00:00:
|
|
91
|
+
direct changes check-campaigns --timestamp 2026-04-14T00:00:00
|
|
91
92
|
direct changes check-campaigns --timestamp "2026-04-14 00:00:00"
|
|
92
93
|
```
|
|
93
94
|
|
|
@@ -104,7 +105,7 @@ Valid canonical examples:
|
|
|
104
105
|
|
|
105
106
|
```bash
|
|
106
107
|
direct campaigns get --ids 1,2,3
|
|
107
|
-
direct changes check-campaigns --timestamp 2026-04-14T00:00:
|
|
108
|
+
direct changes check-campaigns --timestamp 2026-04-14T00:00:00Z
|
|
108
109
|
direct keywordsresearch has-search-volume --keywords "buy laptop,buy desktop"
|
|
109
110
|
direct smartadtargets update --id 456 --priority HIGH
|
|
110
111
|
direct dynamicads set-bids --id 789 --bid 12.5
|
|
@@ -119,7 +120,6 @@ direct dynamicads set-bids --id 789 --bid 12.5 --json '{"StrategyPriority":"HIGH
|
|
|
119
120
|
direct dictionaries get-geo-regions \
|
|
120
121
|
--region-ids 225 \
|
|
121
122
|
--fields GeoRegionId,GeoRegionName
|
|
122
|
-
direct changes check-campaigns --timestamp 2026-04-14T00:00:00Z
|
|
123
123
|
direct changes check-campaigns --timestamp "2026-04-14 00:00:00"
|
|
124
124
|
```
|
|
125
125
|
|
|
@@ -1,5 +1,273 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.3.14
|
|
4
|
+
|
|
5
|
+
**Fixed:**
|
|
6
|
+
|
|
7
|
+
- Reports drift checker now points at the canonical Yandex docs URLs
|
|
8
|
+
(`/ru/type`, `/ru/period`, `/ru/fields-list`, `/ru/spec`) after Yandex
|
|
9
|
+
retired the `/ru/reports/<page>` path layout and renamed `spec.html`
|
|
10
|
+
to `spec`. The pre-existing `tests/reports_cache/raw/` had silently
|
|
11
|
+
been captcha-poisoned for three of those pages (~14.6 KB Yandex
|
|
12
|
+
SmartCaptcha gateway in place of real docs); cache is now refetched
|
|
13
|
+
from the live canonical URLs and `spec.json` is byte-equivalent to
|
|
14
|
+
the pre-migration snapshot except for one updated description string.
|
|
15
|
+
- Five `RESOURCE_MAPPING_V5[*]["docs"]` URLs that Yandex moved from the
|
|
16
|
+
legacy `…/ru/<group>/<group>` to `…/ru/<group>` single-segment form
|
|
17
|
+
(`dynamictextadtargets`, `dynamicfeedadtargets`, `reports`,
|
|
18
|
+
`smartadtargets`, `vcards`). Closes #426.
|
|
19
|
+
|
|
20
|
+
**Added (drift protection):**
|
|
21
|
+
|
|
22
|
+
- `direct_cli/reports_coverage.py::fetch_reports_spec` and
|
|
23
|
+
`direct_cli/wsdl_coverage.py::fetch_wsdl` / `fetch_live_wsdl` now
|
|
24
|
+
refuse responses that look like a Yandex SmartCaptcha gateway (markers
|
|
25
|
+
`showcaptcha`, `smartcaptcha`, `<title>Captcha`) or are suspiciously
|
|
26
|
+
short. This prevents silently poisoning the docs/WSDL cache with
|
|
27
|
+
rate-limited captcha HTML.
|
|
28
|
+
- `tests/test_api_coverage.py::TestReportsCoverage::test_reports_cache_files_are_real_content`
|
|
29
|
+
and `TestWsdlCacheFreshness::test_wsdl_cache_files_are_real_content`
|
|
30
|
+
guard the committed cache files against the same poisoning.
|
|
31
|
+
- `scripts/check_all_docs_urls.py` — health-checks every URL in
|
|
32
|
+
`RESOURCE_MAPPING_V5` and `REPORTS_SPEC_URLS`. Hard-fails on
|
|
33
|
+
redirect-to-captcha, canonical move (`Location` with a different path
|
|
34
|
+
segment), 4xx, or captcha body; soft-warns on 5xx; paces requests to
|
|
35
|
+
avoid Yandex rate-limit. Wired into `scripts/release_pypi.sh` as a
|
|
36
|
+
mandatory pre-release gate together with `refresh_reports_cache.py`
|
|
37
|
+
and a focused pytest pass.
|
|
38
|
+
|
|
39
|
+
**Contract** (`CLAUDE.md`):
|
|
40
|
+
|
|
41
|
+
- New rule "No URL literals outside the registry" — every Yandex
|
|
42
|
+
docs/API URL is declared once in `RESOURCE_MAPPING_V5` or
|
|
43
|
+
`REPORTS_SPEC_URLS`; importers reference the constant.
|
|
44
|
+
- New rule "Docs/cache freshness guard" — fetchers and cache files
|
|
45
|
+
enforce minimum-size and no-captcha invariants.
|
|
46
|
+
- New section "PyPI Release" — documents the three pre-release health
|
|
47
|
+
checks executed by `release_pypi.sh`.
|
|
48
|
+
|
|
49
|
+
**Breaking changes:**
|
|
50
|
+
|
|
51
|
+
- `direct ads get` flag `--text-ad-fields` is **renamed** to the
|
|
52
|
+
WSDL-canonical `--text-ad-field-names` form matching the
|
|
53
|
+
`TextAdFieldNames` request parameter declared by `AdsGetRequest`.
|
|
54
|
+
The old `--text-ad-fields` form is no longer accepted — update
|
|
55
|
+
scripts and automation accordingly. Closes #406.
|
|
56
|
+
- `direct campaigns add` / `direct campaigns update` and `direct
|
|
57
|
+
strategies add` / `direct strategies update` now reject `--priority-goals`
|
|
58
|
+
/ `--priority-goal` values below 100,000 (0.1 unit in micro-currency).
|
|
59
|
+
Per Yandex Direct API (add-text-campaign, strategies-types),
|
|
60
|
+
`PriorityGoalsItem.Value` is `xsd:long` in advertiser currency
|
|
61
|
+
multiplied by 1,000,000 — the same contract as `--budget`,
|
|
62
|
+
`--average-cpa`, and other money flags after #399/#400. The error
|
|
63
|
+
message suggests the micro-currency conversion (e.g. `Did you mean
|
|
64
|
+
500000000?`). Negative values are also rejected up-front rather than
|
|
65
|
+
reaching the API. Both parsers share a single
|
|
66
|
+
`validate_priority_goal_value` helper. Closes #387.
|
|
67
|
+
|
|
68
|
+
**Added:**
|
|
69
|
+
|
|
70
|
+
- `direct sitelinks get` now exposes `--sitelink-field-names` for the
|
|
71
|
+
separate WSDL `SitelinkFieldNames` request parameter
|
|
72
|
+
(`SitelinkFieldEnum`: `Title`, `Href`, `Description`, `TurboPageId`).
|
|
73
|
+
Previously only the top-level `--fields` (mapping to `FieldNames`)
|
|
74
|
+
was available, so the nested `Sitelinks[]` projection could not be
|
|
75
|
+
controlled from CLI.
|
|
76
|
+
- `direct keywordbids get` now exposes `--fields`,
|
|
77
|
+
`--search-field-names`, and `--network-field-names` for the
|
|
78
|
+
separate `FieldNames`, `SearchFieldNames`, and `NetworkFieldNames`
|
|
79
|
+
request parameters declared by `KeywordBidsGetRequest`. Defaults
|
|
80
|
+
from `COMMON_FIELDS` are preserved when flags are absent.
|
|
81
|
+
- Regression test `test_every_nested_fieldnames_param_has_cli_option`
|
|
82
|
+
(`tests/test_api_coverage.py`) scans every cached WSDL `get`
|
|
83
|
+
request type for `*FieldNames` parameters and verifies that each
|
|
84
|
+
one has a matching kebab-case CLI option. Acknowledged remaining
|
|
85
|
+
gaps are tracked in `NESTED_FIELDNAMES_EXCLUSIONS` and #402 so
|
|
86
|
+
future additions cannot silently slip in.
|
|
87
|
+
- `direct feeds get` now exposes `--file-feed-field-names` and
|
|
88
|
+
`--url-feed-field-names` for the separate WSDL `FileFeedFieldNames`
|
|
89
|
+
(`FileFeedFieldEnum`: `Filename`) and `UrlFeedFieldNames`
|
|
90
|
+
(`UrlFeedFieldEnum`: `Login`, `Url`, `RemoveUtmTags`) request
|
|
91
|
+
parameters declared by `FeedsGetRequest`. Previously only the
|
|
92
|
+
top-level `--fields` (mapping to `FieldNames`) was available, so
|
|
93
|
+
the nested `FileFeed` / `UrlFeed` projections could not be
|
|
94
|
+
controlled from CLI. Closes #412.
|
|
95
|
+
- `direct keywords get` now exposes
|
|
96
|
+
`--autotargeting-settings-brand-options-field-names`
|
|
97
|
+
(`AutotargetingBrandOptionsFieldEnum`: `WithoutBrands`,
|
|
98
|
+
`WithAdvertiserBrand`, `WithCompetitorsBrand`) and
|
|
99
|
+
`--autotargeting-settings-categories-field-names`
|
|
100
|
+
(`AutotargetingCategoriesFieldEnum`: `Exact`, `Narrow`,
|
|
101
|
+
`Alternative`, `Accessory`, `Broader`) for the separate WSDL
|
|
102
|
+
`*FieldNames` request parameters declared by
|
|
103
|
+
`KeywordsGetRequest`. Previously only the top-level `--fields`
|
|
104
|
+
(mapping to `FieldNames`) was available, so the nested
|
|
105
|
+
`AutotargetingSettings.BrandOptions` / `Categories` projections
|
|
106
|
+
could not be controlled from CLI. Closes #413.
|
|
107
|
+
- `direct creatives get` now exposes
|
|
108
|
+
`--cpc-video-creative-field-names`,
|
|
109
|
+
`--cpm-video-creative-field-names`,
|
|
110
|
+
`--smart-creative-field-names`, and
|
|
111
|
+
`--video-extension-creative-field-names` for the four nested
|
|
112
|
+
WSDL `*FieldNames` request parameters declared by
|
|
113
|
+
`CreativesGetRequest` (`CpcVideoCreativeFieldEnum`,
|
|
114
|
+
`CpmVideoCreativeFieldEnum`, `SmartCreativeFieldEnum`,
|
|
115
|
+
`VideoExtensionCreativeFieldEnum`). Previously only the top-level
|
|
116
|
+
`--fields` (mapping to `FieldNames`) was available, so the
|
|
117
|
+
per-subtype projections could not be controlled from CLI.
|
|
118
|
+
Closes #411.
|
|
119
|
+
- `direct clients get` now exposes `--contract-field-names`,
|
|
120
|
+
`--contragent-field-names`, `--contragent-tin-info-field-names`,
|
|
121
|
+
`--organization-field-names`, and `--tin-info-field-names` for
|
|
122
|
+
the five nested WSDL `*FieldNames` request parameters declared
|
|
123
|
+
by `ClientsGetRequest` (`ContractInfoFieldEnum`,
|
|
124
|
+
`ContragentInfoFieldEnum`, `TinInfoFieldEnum`,
|
|
125
|
+
`OrgInfoFieldEnum`, `TinInfoFieldEnum`). The command also gains
|
|
126
|
+
`--dry-run` for parity with other read-path commands.
|
|
127
|
+
Previously only the top-level `--fields` (mapping to `FieldNames`)
|
|
128
|
+
was available, so the per-subtype ERIR projections could not be
|
|
129
|
+
controlled from CLI. Closes #410.
|
|
130
|
+
- `direct agencyclients get` now exposes `--contract-field-names`,
|
|
131
|
+
`--contragent-field-names`, `--contragent-tin-info-field-names`,
|
|
132
|
+
`--organization-field-names`, and `--tin-info-field-names` for
|
|
133
|
+
the five nested WSDL `*FieldNames` request parameters declared
|
|
134
|
+
by `AgencyClientsGetRequest` (`ContractInfoFieldEnum`,
|
|
135
|
+
`ContragentInfoFieldEnum`, `TinInfoFieldEnum`,
|
|
136
|
+
`OrgInfoFieldEnum`, `TinInfoFieldEnum`). The command also gains
|
|
137
|
+
`--dry-run` for parity with other read-path commands.
|
|
138
|
+
Previously only the top-level `--fields` (mapping to `FieldNames`)
|
|
139
|
+
was available, so the per-subtype ERIR projections could not be
|
|
140
|
+
controlled from CLI. Closes #407.
|
|
141
|
+
- `direct adgroups get` now exposes eight additional
|
|
142
|
+
`--*-field-names` flags for the separate WSDL `*FieldNames`
|
|
143
|
+
request parameters declared by `AdGroupsGetRequest`:
|
|
144
|
+
`--autotargeting-settings-brand-options-field-names`,
|
|
145
|
+
`--autotargeting-settings-categories-field-names`,
|
|
146
|
+
`--dynamic-text-ad-group-field-names`,
|
|
147
|
+
`--dynamic-text-feed-ad-group-field-names`,
|
|
148
|
+
`--mobile-app-ad-group-field-names`,
|
|
149
|
+
`--smart-ad-group-field-names`,
|
|
150
|
+
`--text-ad-group-feed-params-field-names`, and
|
|
151
|
+
`--unified-ad-group-field-names`. Previously only the top-level
|
|
152
|
+
`--fields` (mapping to `FieldNames`) was available, so the
|
|
153
|
+
per-subtype ad-group projections could not be controlled from
|
|
154
|
+
CLI. Closes #405.
|
|
155
|
+
- `direct ads get` now exposes sixteen additional `--*-field-names`
|
|
156
|
+
flags for the separate WSDL `*FieldNames` request parameters
|
|
157
|
+
declared by `AdsGetRequest`: `--cpc-video-ad-builder-ad-field-names`,
|
|
158
|
+
`--cpm-banner-ad-builder-ad-field-names`,
|
|
159
|
+
`--cpm-video-ad-builder-ad-field-names`,
|
|
160
|
+
`--dynamic-text-ad-field-names`, `--listing-ad-field-names`,
|
|
161
|
+
`--mobile-app-ad-builder-ad-field-names`,
|
|
162
|
+
`--mobile-app-ad-field-names`,
|
|
163
|
+
`--mobile-app-cpc-video-ad-builder-ad-field-names`,
|
|
164
|
+
`--mobile-app-image-ad-field-names`,
|
|
165
|
+
`--responsive-ad-field-names`, `--shopping-ad-field-names`,
|
|
166
|
+
`--smart-ad-builder-ad-field-names`,
|
|
167
|
+
`--text-ad-builder-ad-field-names`,
|
|
168
|
+
`--text-ad-field-names`,
|
|
169
|
+
`--text-ad-price-extension-field-names`, and
|
|
170
|
+
`--text-image-ad-field-names`. Previously only the top-level
|
|
171
|
+
`--fields` (mapping to `FieldNames`) and non-canonical
|
|
172
|
+
`--text-ad-fields` were available, so the per-ad-subtype projections
|
|
173
|
+
could not be controlled from CLI. Closes #406.
|
|
174
|
+
|
|
175
|
+
**BREAKING CHANGES:**
|
|
176
|
+
|
|
177
|
+
- `direct campaigns get` flags `--text-campaign-fields`,
|
|
178
|
+
`--mobile-app-campaign-fields`, `--dynamic-text-campaign-fields`,
|
|
179
|
+
`--cpm-banner-campaign-fields`, `--smart-campaign-fields`,
|
|
180
|
+
`--unified-campaign-fields`,
|
|
181
|
+
`--text-campaign-search-strategy-placement-types-fields`,
|
|
182
|
+
`--dynamic-text-campaign-search-strategy-placement-types-fields`,
|
|
183
|
+
`--unified-campaign-search-strategy-placement-types-fields`, and
|
|
184
|
+
`--unified-campaign-package-bidding-strategy-platforms-fields`
|
|
185
|
+
are **renamed** to their kebab-case WSDL-canonical `*-field-names`
|
|
186
|
+
form (`--text-campaign-field-names`,
|
|
187
|
+
`--mobile-app-campaign-field-names`, ...), matching the parameter
|
|
188
|
+
names declared by `CampaignsGetRequest`. The old `--*-fields`
|
|
189
|
+
forms are no longer accepted — update scripts and automation
|
|
190
|
+
accordingly. Closes #409.
|
|
191
|
+
|
|
192
|
+
**Additional features:**
|
|
193
|
+
|
|
194
|
+
- `direct bidmodifiers get` now exposes thirteen additional
|
|
195
|
+
`--*-adjustment-field-names` flags for the per-adjustment-subtype
|
|
196
|
+
WSDL `*FieldNames` request parameters declared by
|
|
197
|
+
`BidModifiersGetRequest`: `--ad-group-adjustment-field-names`,
|
|
198
|
+
`--demographics-adjustment-field-names`,
|
|
199
|
+
`--desktop-adjustment-field-names`,
|
|
200
|
+
`--desktop-only-adjustment-field-names`,
|
|
201
|
+
`--income-grade-adjustment-field-names`,
|
|
202
|
+
`--mobile-adjustment-field-names`,
|
|
203
|
+
`--regional-adjustment-field-names`,
|
|
204
|
+
`--retargeting-adjustment-field-names`,
|
|
205
|
+
`--serp-layout-adjustment-field-names`,
|
|
206
|
+
`--smart-ad-adjustment-field-names`,
|
|
207
|
+
`--smart-tv-adjustment-field-names`,
|
|
208
|
+
`--tablet-adjustment-field-names`, and
|
|
209
|
+
`--video-adjustment-field-names`. Previously only the top-level
|
|
210
|
+
`--fields` (mapping to `FieldNames`) was available, so the
|
|
211
|
+
per-adjustment projections could not be controlled from CLI.
|
|
212
|
+
Closes #408.
|
|
213
|
+
- `direct strategies get` now exposes sixteen additional
|
|
214
|
+
`--strategy-*-field-names` flags for the separate WSDL
|
|
215
|
+
`*FieldNames` request parameters declared by `StrategiesGetRequest`,
|
|
216
|
+
including `--strategy-average-cpa-field-names`,
|
|
217
|
+
`--strategy-average-cpa-multiple-goals-field-names`,
|
|
218
|
+
`--strategy-average-cpc-field-names`,
|
|
219
|
+
`--strategy-maximum-clicks-field-names`,
|
|
220
|
+
`--strategy-maximum-conversion-rate-field-names`,
|
|
221
|
+
`--strategy-pay-for-conversion-field-names`, and the remaining
|
|
222
|
+
per-campaign / per-filter strategy projections. The command also
|
|
223
|
+
gains `--dry-run` for read-path payload tests. Previously only the
|
|
224
|
+
top-level `--fields` (mapping to `FieldNames`) was available, so
|
|
225
|
+
per-strategy-subtype projections could not be controlled from CLI.
|
|
226
|
+
Closes #414.
|
|
227
|
+
|
|
228
|
+
Closes #360.
|
|
229
|
+
|
|
230
|
+
**Tests:**
|
|
231
|
+
|
|
232
|
+
- `tests/test_integration.py` now gracefully skips the seven read-only
|
|
233
|
+
classes that rely on live-API probes (`TestReadOnlyAdGroups`,
|
|
234
|
+
`TestReadOnlyAds`, `TestReadOnlyKeywords`,
|
|
235
|
+
`TestReadOnlyDynamicFeedAdTargets`, `TestReadOnlyLeads`,
|
|
236
|
+
`TestReadOnlyBusinesses`, `TestReadOnlyAdVideos`) when the probe
|
|
237
|
+
raises — previously a temporary API outage crashed `setUpClass`
|
|
238
|
+
with an opaque traceback.
|
|
239
|
+
- `invoke_get` in `tests/test_integration.py` now passes the resolved
|
|
240
|
+
test credentials as explicit `--token`/`--login` flags so the
|
|
241
|
+
integration suite cannot silently fall through to a developer's
|
|
242
|
+
active `direct auth` profile (priority 1 in the CLI credential
|
|
243
|
+
chain wins over the profile, matching CLAUDE.md guidance).
|
|
244
|
+
- `tests/test_comprehensive.py` slimmed down: `TestCLIHelp` (full
|
|
245
|
+
duplicate of `tests/test_cli.py`) removed; the unique
|
|
246
|
+
`TestCommandsRegistered`, `TestUtils`, `TestOutputFormatters`,
|
|
247
|
+
`TestAuth`, and `TestErrorHandling` classes are kept.
|
|
248
|
+
- `tests/test_smoke_matrix.py` no longer hard-codes
|
|
249
|
+
`total_cli_subcommands == 144` or `wsdl_operations == 112`. Counts
|
|
250
|
+
are derived from the live Click registry and parsed WSDLs.
|
|
251
|
+
- `tests/test_sandbox_write_audit.py` no longer hard-codes
|
|
252
|
+
`total == 83`. The count derives from `commands_for_category`.
|
|
253
|
+
|
|
254
|
+
Closes #396.
|
|
255
|
+
|
|
256
|
+
## 0.3.13
|
|
257
|
+
|
|
258
|
+
**Breaking changes:**
|
|
259
|
+
|
|
260
|
+
- `direct campaigns add` and `direct campaigns update` now require all
|
|
261
|
+
bidding-strategy money flags to be passed directly in micro-rubles,
|
|
262
|
+
matching the existing `--budget`, `--average-cpa`, `--bid-ceiling`, and
|
|
263
|
+
`--filter-average-cpc` contract. The CLI no longer accepts decimal currency
|
|
264
|
+
values or performs unit conversion for campaign money
|
|
265
|
+
inputs. Closes #399.
|
|
266
|
+
- `direct ads add` and `direct ads update` now apply the same API-native
|
|
267
|
+
micro-ruble contract to `--price-extension-price` and
|
|
268
|
+
`--price-extension-old-price`; price-extension values are no longer parsed
|
|
269
|
+
as decimal currency amounts.
|
|
270
|
+
|
|
3
271
|
## 0.3.12
|
|
4
272
|
|
|
5
273
|
**Added:**
|
|
@@ -41,6 +41,8 @@ Click group-of-groups. Each Yandex Direct API resource = one file in `direct_cli
|
|
|
41
41
|
|
|
42
42
|
**`--dry-run`:** `add`/`update` commands print request JSON without calling the API. Use as test seam.
|
|
43
43
|
|
|
44
|
+
**No legacy CLI flag aliases.** A CLI option must be exactly the kebab-case form of the WSDL request parameter (`SitelinkFieldNames` → `--sitelink-field-names`). If an existing flag uses a different name for the same WSDL parameter, rename it as a **breaking change** — do not keep the old form as a second `@click.option` name on the same variable. Document the rename in `CHANGELOG.md` under a `BREAKING CHANGES` heading and bump the version accordingly.
|
|
45
|
+
|
|
44
46
|
**Runtime-deprecated methods:** WSDL-visible methods that Yandex rejects at runtime belong in `RUNTIME_DEPRECATED_METHODS` (`direct_cli/wsdl_coverage.py`) and must fail with `click.UsageError` before request construction. `agencyclients add` is blocked this way; use `agencyclients add-passport-organization`.
|
|
45
47
|
|
|
46
48
|
**Strict WSDL parity:** `DRY_RUN_PAYLOAD_EXCLUSIONS` in `tests/api_coverage_payloads.py` must NOT contain any entry whose rationale claims the CLI surface is a «helper», «legacy», or «not part of strict WSDL parity». If the WSDL declares the operation, the CLI mirrors it 1:1 with a `PAYLOAD_CASES` fixture. Legitimate permanent exclusions are limited to:
|
|
@@ -72,6 +74,34 @@ Adding a new mutating command requires extending `COMMAND_WSDL_MAP` in `tests/te
|
|
|
72
74
|
|
|
73
75
|
**Smoke probes:** Live ID discovery for safe-smoke and integration tests lives in `direct_cli/_smoke_probes.py`. Functions like `advideo_probe_id()` query the live API to find a real resource ID (env override `YANDEX_DIRECT_TEST_ADVIDEO_ID`, fallback through `creatives.get`) and return `None` on any failure — smoke scripts treat `None` as a benign skip, not a fatal error. CLI entry: `python3 -m direct_cli._smoke_probes advideo`.
|
|
74
76
|
|
|
77
|
+
**No URL literals outside the registry.** Every Yandex docs/API URL is declared once — either in `direct_cli/_vendor/tapi_yandex_direct/resource_mapping.py` (`docs`, `docs_pages.*`) or in `direct_cli/reports_coverage.py::REPORTS_SPEC_URLS`. Tests and scripts import these constants; never write the URL as a string literal anywhere else. Captcha-poisoning of the docs cache (#426) was possible only because the same URL was duplicated in a hard-coded test assertion. Don't repeat that.
|
|
78
|
+
|
|
79
|
+
**Docs/cache freshness guard.** `direct_cli.reports_coverage.fetch_reports_spec` and `direct_cli.wsdl_coverage.fetch_wsdl` both refuse responses that look like a Yandex SmartCaptcha gate (markers `showcaptcha`, `smartcaptcha`, `<title>Captcha`) or are suspiciously short (<30 KB for HTML, <3 KB for WSDL). The matching tests `test_reports_cache_files_are_real_content` and `test_wsdl_cache_files_are_real_content` enforce the same invariant on committed cache files.
|
|
80
|
+
|
|
81
|
+
## PyPI Release
|
|
82
|
+
|
|
83
|
+
Release is two-phase on purpose. Yandex frequently rate-limits the docs host with a SmartCaptcha gateway, which is an external rate-limit on our IP — not evidence that an URL is gone. Mixing docs-health checks into the publish path made releases non-deterministic, so they live in a separate preflight script.
|
|
84
|
+
|
|
85
|
+
**Phase 1 — preflight (manual, network-dependent):**
|
|
86
|
+
|
|
87
|
+
```
|
|
88
|
+
bash scripts/preflight_check.sh
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Runs three checks:
|
|
92
|
+
|
|
93
|
+
1. `python scripts/check_all_docs_urls.py` — every Yandex docs URL in `RESOURCE_MAPPING_V5` and `REPORTS_SPEC_URLS` must be reachable. The probe falls back from `HEAD` to `GET` on 4xx (some CDNs reject `HEAD`), then verifies real content. **Hard fail:** confirmed 3xx-to-different-path or 4xx (canonical move / gone). **Soft warning (does not block):** 5xx or persistent captcha — treated as a transient Yandex rate-limit; re-run later to confirm.
|
|
94
|
+
2. `pytest TestReportsCoverage TestWsdlCacheFreshness -v` — read-only check that the committed Reports/WSDL/XSD caches are real content (not captcha).
|
|
95
|
+
3. `git diff --quiet -- tests/reports_cache tests/wsdl_cache` — refuses to proceed with an uncommitted cache refresh. If Yandex changed docs since the last snapshot, run `scripts/refresh_reports_cache.py` separately, review the diff, and commit it before releasing.
|
|
96
|
+
|
|
97
|
+
**Phase 2 — release (deterministic, no Yandex network calls):**
|
|
98
|
+
|
|
99
|
+
```
|
|
100
|
+
bash scripts/release_pypi.sh all
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Builds dist artifacts, runs twine checks, uploads to TestPyPI + PyPI. Does **not** re-run docs/cache checks — if the captcha rate-limit was active during preflight, that should not block a release of an already-verified artifact.
|
|
104
|
+
|
|
75
105
|
## Tests
|
|
76
106
|
|
|
77
107
|
- **Unit** (`test_cli.py`, `test_comprehensive.py`) — no API calls, no token needed.
|