direct-cli 0.3.13__tar.gz → 0.3.15__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.13 → direct_cli-0.3.15}/CHANGELOG.md +280 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/CLAUDE.md +30 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/PKG-INFO +4 -4
- {direct_cli-0.3.13 → direct_cli-0.3.15}/README.md +3 -3
- {direct_cli-0.3.13 → direct_cli-0.3.15}/direct_cli/_bidding_strategy.py +0 -5
- {direct_cli-0.3.13 → direct_cli-0.3.15}/direct_cli/_vendor/tapi_yandex_direct/resource_mapping.py +8 -8
- {direct_cli-0.3.13 → direct_cli-0.3.15}/direct_cli/commands/adgroups.py +117 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/direct_cli/commands/ads.py +193 -7
- {direct_cli-0.3.13 → direct_cli-0.3.15}/direct_cli/commands/agencyclients.py +85 -1
- {direct_cli-0.3.13 → direct_cli-0.3.15}/direct_cli/commands/bidmodifiers.py +153 -1
- {direct_cli-0.3.13 → direct_cli-0.3.15}/direct_cli/commands/campaigns.py +113 -50
- {direct_cli-0.3.13 → direct_cli-0.3.15}/direct_cli/commands/clients.py +85 -1
- {direct_cli-0.3.13 → direct_cli-0.3.15}/direct_cli/commands/creatives.py +71 -2
- {direct_cli-0.3.13 → direct_cli-0.3.15}/direct_cli/commands/feeds.py +47 -2
- {direct_cli-0.3.13 → direct_cli-0.3.15}/direct_cli/commands/keywordbids.py +61 -3
- {direct_cli-0.3.13 → direct_cli-0.3.15}/direct_cli/commands/keywords.py +59 -1
- {direct_cli-0.3.13 → direct_cli-0.3.15}/direct_cli/commands/sitelinks.py +37 -4
- {direct_cli-0.3.13 → direct_cli-0.3.15}/direct_cli/commands/strategies.py +256 -10
- {direct_cli-0.3.13 → direct_cli-0.3.15}/direct_cli/commands/v4finance.py +4 -35
- {direct_cli-0.3.13 → direct_cli-0.3.15}/direct_cli/reports_coverage.py +23 -1
- {direct_cli-0.3.13 → direct_cli-0.3.15}/direct_cli/utils.py +35 -1
- {direct_cli-0.3.13 → direct_cli-0.3.15}/direct_cli/v4_contracts.py +28 -18
- {direct_cli-0.3.13 → direct_cli-0.3.15}/direct_cli/wsdl_coverage.py +57 -1
- {direct_cli-0.3.13 → direct_cli-0.3.15}/direct_cli.egg-info/PKG-INFO +4 -4
- {direct_cli-0.3.13 → direct_cli-0.3.15}/direct_cli.egg-info/SOURCES.txt +2 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/pyproject.toml +1 -1
- direct_cli-0.3.15/scripts/check_all_docs_urls.py +166 -0
- direct_cli-0.3.15/scripts/preflight_check.sh +62 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/scripts/release_pypi.sh +8 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/scripts/test_dangerous_commands.sh +1 -1
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/API_COVERAGE.md +6 -5
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/api_coverage_payloads.py +9 -6
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/reports_cache/raw/fields-list.html +6 -6
- direct_cli-0.3.15/tests/reports_cache/raw/headers.html +88 -0
- direct_cli-0.3.15/tests/reports_cache/raw/period.html +119 -0
- direct_cli-0.3.15/tests/reports_cache/raw/spec.html +643 -0
- direct_cli-0.3.15/tests/reports_cache/raw/type.html +279 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/reports_cache/spec.json +1 -1
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/test_api_coverage.py +191 -19
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/test_comprehensive.py +7 -20
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/test_dry_run.py +1263 -117
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/test_integration.py +84 -9
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/test_low_coverage_payloads.py +1 -1
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/test_sandbox_write_audit.py +7 -3
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/test_smoke_matrix.py +49 -7
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/test_v4_contracts.py +4 -4
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/test_v4finance_money.py +15 -20
- direct_cli-0.3.13/tests/reports_cache/raw/headers.html +0 -88
- direct_cli-0.3.13/tests/reports_cache/raw/period.html +0 -119
- direct_cli-0.3.13/tests/reports_cache/raw/spec.html +0 -660
- direct_cli-0.3.13/tests/reports_cache/raw/type.html +0 -279
- {direct_cli-0.3.13 → direct_cli-0.3.15}/.env.example +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/.github/copilot-instructions.md +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/.github/workflows/api-coverage.yml +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/.github/workflows/claude.yml +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/.github/workflows/quality.yml +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/.gitignore +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/AGENTS.md +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/MANIFEST.in +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/direct_cli/__init__.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/direct_cli/_deprecated.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/direct_cli/_smoke_probes.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/direct_cli/_vendor/__init__.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/direct_cli/_vendor/tapi_yandex_direct/__init__.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/direct_cli/_vendor/tapi_yandex_direct/endpoints.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/direct_cli/_vendor/tapi_yandex_direct/exceptions.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/direct_cli/_vendor/tapi_yandex_direct/tapi_yandex_direct.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/direct_cli/_vendor/tapi_yandex_direct/tapi_yandex_direct.pyi +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/direct_cli/_vendor/tapi_yandex_direct/v4/__init__.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/direct_cli/_vendor/tapi_yandex_direct/v4/adapter.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/direct_cli/_vendor/tapi_yandex_direct/v4/adapter.pyi +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/direct_cli/_vendor/tapi_yandex_direct/v4/resource_mapping.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/direct_cli/api.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/direct_cli/auth.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/direct_cli/cli.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/direct_cli/commands/__init__.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/direct_cli/commands/adextensions.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/direct_cli/commands/adimages.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/direct_cli/commands/advideos.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/direct_cli/commands/audiencetargets.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/direct_cli/commands/auth.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/direct_cli/commands/balance.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/direct_cli/commands/bids.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/direct_cli/commands/businesses.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/direct_cli/commands/changes.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/direct_cli/commands/dictionaries.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/direct_cli/commands/dynamicads.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/direct_cli/commands/dynamicfeedadtargets.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/direct_cli/commands/keywordsresearch.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/direct_cli/commands/leads.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/direct_cli/commands/negativekeywordsharedsets.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/direct_cli/commands/reports.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/direct_cli/commands/retargeting.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/direct_cli/commands/smartadtargets.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/direct_cli/commands/turbopages.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/direct_cli/commands/v4account.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/direct_cli/commands/v4events.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/direct_cli/commands/v4forecast.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/direct_cli/commands/v4goals.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/direct_cli/commands/v4shells.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/direct_cli/commands/v4tags.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/direct_cli/commands/v4wordstat.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/direct_cli/commands/vcards.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/direct_cli/output.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/direct_cli/smoke_matrix.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/direct_cli/v4/__init__.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/direct_cli/v4/money.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/direct_cli.egg-info/dependency_links.txt +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/direct_cli.egg-info/entry_points.txt +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/direct_cli.egg-info/requires.txt +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/direct_cli.egg-info/top_level.txt +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/docs/audits/issue-198-mutating-wsdl-audit.md +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/docs/superpowers/plans/2026-04-12-issue-32-completion.md +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/docs/superpowers/specs/2026-04-23-vendor-tapi-yandex-direct-design.md +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/scripts/anonymize_cassettes.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/scripts/build_api_coverage_checklist.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/scripts/build_api_coverage_report.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/scripts/build_wsdl_optional_field_audit.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/scripts/check_reports_drift.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/scripts/check_wsdl_drift.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/scripts/patch_vendor_imports.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/scripts/refresh_reports_cache.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/scripts/refresh_wsdl_cache.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/scripts/sandbox_write_audit.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/scripts/sandbox_write_live.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/scripts/test_safe_commands.sh +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/scripts/test_sandbox_write.sh +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/scripts/update_vendor.sh +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/setup.cfg +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/setup.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/API_ISSUE_AUDIT.md +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/MANUAL_COVERAGE.md +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/WSDL_OPTIONAL_FIELD_AUDIT.md +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/__init__.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/_orphan_store.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/cassettes/test_integration_write/TestWriteAdExtensions.test_add_delete.yaml +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/cassettes/test_integration_write/TestWriteAdGroups.test_add_update_delete.yaml +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/cassettes/test_integration_write/TestWriteAdImages.test_add_delete.yaml +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/cassettes/test_integration_write/TestWriteAds.test_add_text_ad_update_delete.yaml +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/cassettes/test_integration_write/TestWriteAudienceTargets.test_add_delete.yaml +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/cassettes/test_integration_write/TestWriteBidModifiersAdd.test_add_delete_mobile.yaml +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/cassettes/test_integration_write/TestWriteBidModifiersSet.test_set_without_id_is_rejected.yaml +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/cassettes/test_integration_write/TestWriteBids.test_set_bid.yaml +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/cassettes/test_integration_write/TestWriteBidsRead.test_bids_get.yaml +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/cassettes/test_integration_write/TestWriteBidsRead.test_bids_set_auto.yaml +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/cassettes/test_integration_write/TestWriteCampaignDraftLifecycle.test_draft_create_get_delete.yaml +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/cassettes/test_integration_write/TestWriteCampaigns.test_campaign_lifecycle.yaml +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/cassettes/test_integration_write/TestWriteDynamicAds.test_add_update_delete.yaml +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/cassettes/test_integration_write/TestWriteFeeds.test_add_update_delete.yaml +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/cassettes/test_integration_write/TestWriteKeywordBids.test_set_keyword_bid.yaml +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/cassettes/test_integration_write/TestWriteKeywords.test_add_update_delete.yaml +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/cassettes/test_integration_write/TestWriteNegativeKeywordSharedSets.test_add_update_delete.yaml +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/cassettes/test_integration_write/TestWriteRetargeting.test_add_delete.yaml +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/cassettes/test_integration_write/TestWriteRetargetingUpdate.test_retargeting_update.yaml +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/cassettes/test_integration_write/TestWriteSitelinks.test_add_delete.yaml +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/cassettes/test_integration_write/TestWriteSmartAdTargets.test_add_update_delete.yaml +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/cassettes/test_integration_write/TestWriteStrategies.test_strategies_lifecycle.yaml +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/cassettes/test_integration_write/TestWriteVCards.test_add_delete.yaml +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/cassettes/test_v5_live_write/test_v5_live_draft_adgroups_add_update_delete.yaml +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/cassettes/test_v5_live_write/test_v5_live_draft_adimages_add_get_delete.yaml +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/cassettes/test_v5_live_write/test_v5_live_draft_ads_add_update_delete.yaml +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/cassettes/test_v5_live_write/test_v5_live_draft_ads_suspend_resume_archive_unarchive.yaml +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/cassettes/test_v5_live_write/test_v5_live_draft_advideos_add_get.yaml +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/cassettes/test_v5_live_write/test_v5_live_draft_audiencetargets_add_delete.yaml +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/cassettes/test_v5_live_write/test_v5_live_draft_audiencetargets_suspend_resume.yaml +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/cassettes/test_v5_live_write/test_v5_live_draft_bids_set.yaml +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/cassettes/test_v5_live_write/test_v5_live_draft_campaign_create_get_delete.yaml +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/cassettes/test_v5_live_write/test_v5_live_draft_creatives_chain_advideo_to_creative.yaml +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/cassettes/test_v5_live_write/test_v5_live_draft_dynamicads_add_delete.yaml +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/cassettes/test_v5_live_write/test_v5_live_draft_dynamicads_suspend_resume.yaml +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/cassettes/test_v5_live_write/test_v5_live_draft_keywordbids_set.yaml +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/cassettes/test_v5_live_write/test_v5_live_draft_keywords_add_update_delete.yaml +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/cassettes/test_v5_live_write/test_v5_live_draft_keywords_suspend_resume.yaml +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/cassettes/test_v5_live_write/test_v5_live_draft_sitelinks_add_get_delete.yaml +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/cassettes/test_v5_live_write/test_v5_live_draft_smartadtargets_add_update_delete.yaml +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/cassettes/test_v5_live_write/test_v5_live_draft_smartadtargets_suspend_resume.yaml +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/conftest.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/fixtures/test-video.mp4 +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/test_auth_bw.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/test_auth_oauth.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/test_auth_op.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/test_auth_write_json.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/test_balance.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/test_changes.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/test_cli.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/test_cli_contract.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/test_env_loading.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/test_integration_write.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/test_reports_drift.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/test_reports_parsing.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/test_transport_contract.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/test_unknown_option_hints.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/test_v4_exit_codes.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/test_v4_foundation.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/test_v4_live_contracts.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/test_v4_runtime_shape.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/test_v4_safety.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/test_v4account.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/test_v4events.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/test_v4finance_read.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/test_v4forecast.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/test_v4goals.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/test_v4tags.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/test_v4wordstat.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/test_v5_live_write.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/test_vendor_imports.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/test_wsdl_parity_gate.py +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/wsdl_cache/adextensions.xml +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/wsdl_cache/adgroups.xml +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/wsdl_cache/adimages.xml +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/wsdl_cache/ads.xml +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/wsdl_cache/advideos.xml +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/wsdl_cache/agencyclients.xml +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/wsdl_cache/audiencetargets.xml +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/wsdl_cache/bidmodifiers.xml +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/wsdl_cache/bids.xml +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/wsdl_cache/businesses.xml +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/wsdl_cache/campaigns.xml +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/wsdl_cache/changes.xml +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/wsdl_cache/clients.xml +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/wsdl_cache/creatives.xml +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/wsdl_cache/dictionaries.xml +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/wsdl_cache/dynamicfeedadtargets.xml +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/wsdl_cache/dynamictextadtargets.xml +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/wsdl_cache/feeds.xml +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/wsdl_cache/imports/adextensiontypes.xsd +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/wsdl_cache/imports/general.xsd +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/wsdl_cache/imports/generalclients.xsd +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/wsdl_cache/keywordbids.xml +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/wsdl_cache/keywords.xml +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/wsdl_cache/keywordsresearch.xml +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/wsdl_cache/leads.xml +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/wsdl_cache/negativekeywordsharedsets.xml +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/wsdl_cache/retargetinglists.xml +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/wsdl_cache/sitelinks.xml +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/wsdl_cache/smartadtargets.xml +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/wsdl_cache/strategies.xml +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/wsdl_cache/turbopages.xml +0 -0
- {direct_cli-0.3.13 → direct_cli-0.3.15}/tests/wsdl_cache/vcards.xml +0 -0
|
@@ -1,5 +1,285 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.3.15
|
|
4
|
+
|
|
5
|
+
**BREAKING CHANGES:**
|
|
6
|
+
|
|
7
|
+
- `direct v4finance transfer-money` no longer accepts `--currency`, and
|
|
8
|
+
the wire-body no longer carries `Currency` on `FromCampaigns`/
|
|
9
|
+
`ToCampaigns` items. The official v4 docs
|
|
10
|
+
(`dg-v4/reference/TransferMoney`) define `PayCampElement` with only
|
|
11
|
+
`CampaignID` and `Sum`; `Sum` is in conventional units. The CLI now
|
|
12
|
+
matches the docs 1:1. Closes #432.
|
|
13
|
+
- `direct v4finance pay-campaigns` no longer accepts `--currency`. The
|
|
14
|
+
v4 documentation (`dg-v4/reference/PayCampaigns`) defines
|
|
15
|
+
`PayCampElement` with only `CampaignID` and `Sum` — `Currency` is not
|
|
16
|
+
part of the wire-body and was never forwarded to the API. The option
|
|
17
|
+
is removed entirely to make the CLI surface 1:1 with the docs.
|
|
18
|
+
- `direct v4finance pay-campaigns` no longer accepts `--pay-method
|
|
19
|
+
Overdraft`. The v4 documentation
|
|
20
|
+
(`dg-v4/reference/PayCampaigns#PayMethod`) lists only `"Bank"` as a
|
|
21
|
+
supported value; `Overdraft` was a historical undocumented value
|
|
22
|
+
retained by the CLI for sandbox flow. Strict 1:1 docs alignment
|
|
23
|
+
drops it.
|
|
24
|
+
- `direct v4finance create-invoice` no longer accepts `--currency`. The
|
|
25
|
+
v4 documentation (`dg-v4/reference/CreateInvoice`) defines
|
|
26
|
+
`PayCampElement` with only `CampaignID` and `Sum` — `Currency` is not
|
|
27
|
+
part of the wire-body and was never forwarded to the API. The option
|
|
28
|
+
is removed entirely to make the CLI surface 1:1 with the docs.
|
|
29
|
+
|
|
30
|
+
## 0.3.14
|
|
31
|
+
|
|
32
|
+
**Fixed:**
|
|
33
|
+
|
|
34
|
+
- Reports drift checker now points at the canonical Yandex docs URLs
|
|
35
|
+
(`/ru/type`, `/ru/period`, `/ru/fields-list`, `/ru/spec`) after Yandex
|
|
36
|
+
retired the `/ru/reports/<page>` path layout and renamed `spec.html`
|
|
37
|
+
to `spec`. The pre-existing `tests/reports_cache/raw/` had silently
|
|
38
|
+
been captcha-poisoned for three of those pages (~14.6 KB Yandex
|
|
39
|
+
SmartCaptcha gateway in place of real docs); cache is now refetched
|
|
40
|
+
from the live canonical URLs and `spec.json` is byte-equivalent to
|
|
41
|
+
the pre-migration snapshot except for one updated description string.
|
|
42
|
+
- Five `RESOURCE_MAPPING_V5[*]["docs"]` URLs that Yandex moved from the
|
|
43
|
+
legacy `…/ru/<group>/<group>` to `…/ru/<group>` single-segment form
|
|
44
|
+
(`dynamictextadtargets`, `dynamicfeedadtargets`, `reports`,
|
|
45
|
+
`smartadtargets`, `vcards`). Closes #426.
|
|
46
|
+
|
|
47
|
+
**Added (drift protection):**
|
|
48
|
+
|
|
49
|
+
- `direct_cli/reports_coverage.py::fetch_reports_spec` and
|
|
50
|
+
`direct_cli/wsdl_coverage.py::fetch_wsdl` / `fetch_live_wsdl` now
|
|
51
|
+
refuse responses that look like a Yandex SmartCaptcha gateway (markers
|
|
52
|
+
`showcaptcha`, `smartcaptcha`, `<title>Captcha`) or are suspiciously
|
|
53
|
+
short. This prevents silently poisoning the docs/WSDL cache with
|
|
54
|
+
rate-limited captcha HTML.
|
|
55
|
+
- `tests/test_api_coverage.py::TestReportsCoverage::test_reports_cache_files_are_real_content`
|
|
56
|
+
and `TestWsdlCacheFreshness::test_wsdl_cache_files_are_real_content`
|
|
57
|
+
guard the committed cache files against the same poisoning.
|
|
58
|
+
- `scripts/check_all_docs_urls.py` — health-checks every URL in
|
|
59
|
+
`RESOURCE_MAPPING_V5` and `REPORTS_SPEC_URLS`. Hard-fails on
|
|
60
|
+
redirect-to-captcha, canonical move (`Location` with a different path
|
|
61
|
+
segment), 4xx, or captcha body; soft-warns on 5xx; paces requests to
|
|
62
|
+
avoid Yandex rate-limit. Wired into `scripts/release_pypi.sh` as a
|
|
63
|
+
mandatory pre-release gate together with `refresh_reports_cache.py`
|
|
64
|
+
and a focused pytest pass.
|
|
65
|
+
|
|
66
|
+
**Contract** (`CLAUDE.md`):
|
|
67
|
+
|
|
68
|
+
- New rule "No URL literals outside the registry" — every Yandex
|
|
69
|
+
docs/API URL is declared once in `RESOURCE_MAPPING_V5` or
|
|
70
|
+
`REPORTS_SPEC_URLS`; importers reference the constant.
|
|
71
|
+
- New rule "Docs/cache freshness guard" — fetchers and cache files
|
|
72
|
+
enforce minimum-size and no-captcha invariants.
|
|
73
|
+
- New section "PyPI Release" — documents the three pre-release health
|
|
74
|
+
checks executed by `release_pypi.sh`.
|
|
75
|
+
|
|
76
|
+
**Breaking changes:**
|
|
77
|
+
|
|
78
|
+
- `direct ads get` flag `--text-ad-fields` is **renamed** to the
|
|
79
|
+
WSDL-canonical `--text-ad-field-names` form matching the
|
|
80
|
+
`TextAdFieldNames` request parameter declared by `AdsGetRequest`.
|
|
81
|
+
The old `--text-ad-fields` form is no longer accepted — update
|
|
82
|
+
scripts and automation accordingly. Closes #406.
|
|
83
|
+
- `direct campaigns add` / `direct campaigns update` and `direct
|
|
84
|
+
strategies add` / `direct strategies update` now reject `--priority-goals`
|
|
85
|
+
/ `--priority-goal` values below 100,000 (0.1 unit in micro-currency).
|
|
86
|
+
Per Yandex Direct API (add-text-campaign, strategies-types),
|
|
87
|
+
`PriorityGoalsItem.Value` is `xsd:long` in advertiser currency
|
|
88
|
+
multiplied by 1,000,000 — the same contract as `--budget`,
|
|
89
|
+
`--average-cpa`, and other money flags after #399/#400. The error
|
|
90
|
+
message suggests the micro-currency conversion (e.g. `Did you mean
|
|
91
|
+
500000000?`). Negative values are also rejected up-front rather than
|
|
92
|
+
reaching the API. Both parsers share a single
|
|
93
|
+
`validate_priority_goal_value` helper. Closes #387.
|
|
94
|
+
|
|
95
|
+
**Added:**
|
|
96
|
+
|
|
97
|
+
- `direct sitelinks get` now exposes `--sitelink-field-names` for the
|
|
98
|
+
separate WSDL `SitelinkFieldNames` request parameter
|
|
99
|
+
(`SitelinkFieldEnum`: `Title`, `Href`, `Description`, `TurboPageId`).
|
|
100
|
+
Previously only the top-level `--fields` (mapping to `FieldNames`)
|
|
101
|
+
was available, so the nested `Sitelinks[]` projection could not be
|
|
102
|
+
controlled from CLI.
|
|
103
|
+
- `direct keywordbids get` now exposes `--fields`,
|
|
104
|
+
`--search-field-names`, and `--network-field-names` for the
|
|
105
|
+
separate `FieldNames`, `SearchFieldNames`, and `NetworkFieldNames`
|
|
106
|
+
request parameters declared by `KeywordBidsGetRequest`. Defaults
|
|
107
|
+
from `COMMON_FIELDS` are preserved when flags are absent.
|
|
108
|
+
- Regression test `test_every_nested_fieldnames_param_has_cli_option`
|
|
109
|
+
(`tests/test_api_coverage.py`) scans every cached WSDL `get`
|
|
110
|
+
request type for `*FieldNames` parameters and verifies that each
|
|
111
|
+
one has a matching kebab-case CLI option. Acknowledged remaining
|
|
112
|
+
gaps are tracked in `NESTED_FIELDNAMES_EXCLUSIONS` and #402 so
|
|
113
|
+
future additions cannot silently slip in.
|
|
114
|
+
- `direct feeds get` now exposes `--file-feed-field-names` and
|
|
115
|
+
`--url-feed-field-names` for the separate WSDL `FileFeedFieldNames`
|
|
116
|
+
(`FileFeedFieldEnum`: `Filename`) and `UrlFeedFieldNames`
|
|
117
|
+
(`UrlFeedFieldEnum`: `Login`, `Url`, `RemoveUtmTags`) request
|
|
118
|
+
parameters declared by `FeedsGetRequest`. Previously only the
|
|
119
|
+
top-level `--fields` (mapping to `FieldNames`) was available, so
|
|
120
|
+
the nested `FileFeed` / `UrlFeed` projections could not be
|
|
121
|
+
controlled from CLI. Closes #412.
|
|
122
|
+
- `direct keywords get` now exposes
|
|
123
|
+
`--autotargeting-settings-brand-options-field-names`
|
|
124
|
+
(`AutotargetingBrandOptionsFieldEnum`: `WithoutBrands`,
|
|
125
|
+
`WithAdvertiserBrand`, `WithCompetitorsBrand`) and
|
|
126
|
+
`--autotargeting-settings-categories-field-names`
|
|
127
|
+
(`AutotargetingCategoriesFieldEnum`: `Exact`, `Narrow`,
|
|
128
|
+
`Alternative`, `Accessory`, `Broader`) for the separate WSDL
|
|
129
|
+
`*FieldNames` request parameters declared by
|
|
130
|
+
`KeywordsGetRequest`. Previously only the top-level `--fields`
|
|
131
|
+
(mapping to `FieldNames`) was available, so the nested
|
|
132
|
+
`AutotargetingSettings.BrandOptions` / `Categories` projections
|
|
133
|
+
could not be controlled from CLI. Closes #413.
|
|
134
|
+
- `direct creatives get` now exposes
|
|
135
|
+
`--cpc-video-creative-field-names`,
|
|
136
|
+
`--cpm-video-creative-field-names`,
|
|
137
|
+
`--smart-creative-field-names`, and
|
|
138
|
+
`--video-extension-creative-field-names` for the four nested
|
|
139
|
+
WSDL `*FieldNames` request parameters declared by
|
|
140
|
+
`CreativesGetRequest` (`CpcVideoCreativeFieldEnum`,
|
|
141
|
+
`CpmVideoCreativeFieldEnum`, `SmartCreativeFieldEnum`,
|
|
142
|
+
`VideoExtensionCreativeFieldEnum`). Previously only the top-level
|
|
143
|
+
`--fields` (mapping to `FieldNames`) was available, so the
|
|
144
|
+
per-subtype projections could not be controlled from CLI.
|
|
145
|
+
Closes #411.
|
|
146
|
+
- `direct clients get` now exposes `--contract-field-names`,
|
|
147
|
+
`--contragent-field-names`, `--contragent-tin-info-field-names`,
|
|
148
|
+
`--organization-field-names`, and `--tin-info-field-names` for
|
|
149
|
+
the five nested WSDL `*FieldNames` request parameters declared
|
|
150
|
+
by `ClientsGetRequest` (`ContractInfoFieldEnum`,
|
|
151
|
+
`ContragentInfoFieldEnum`, `TinInfoFieldEnum`,
|
|
152
|
+
`OrgInfoFieldEnum`, `TinInfoFieldEnum`). The command also gains
|
|
153
|
+
`--dry-run` for parity with other read-path commands.
|
|
154
|
+
Previously only the top-level `--fields` (mapping to `FieldNames`)
|
|
155
|
+
was available, so the per-subtype ERIR projections could not be
|
|
156
|
+
controlled from CLI. Closes #410.
|
|
157
|
+
- `direct agencyclients get` now exposes `--contract-field-names`,
|
|
158
|
+
`--contragent-field-names`, `--contragent-tin-info-field-names`,
|
|
159
|
+
`--organization-field-names`, and `--tin-info-field-names` for
|
|
160
|
+
the five nested WSDL `*FieldNames` request parameters declared
|
|
161
|
+
by `AgencyClientsGetRequest` (`ContractInfoFieldEnum`,
|
|
162
|
+
`ContragentInfoFieldEnum`, `TinInfoFieldEnum`,
|
|
163
|
+
`OrgInfoFieldEnum`, `TinInfoFieldEnum`). The command also gains
|
|
164
|
+
`--dry-run` for parity with other read-path commands.
|
|
165
|
+
Previously only the top-level `--fields` (mapping to `FieldNames`)
|
|
166
|
+
was available, so the per-subtype ERIR projections could not be
|
|
167
|
+
controlled from CLI. Closes #407.
|
|
168
|
+
- `direct adgroups get` now exposes eight additional
|
|
169
|
+
`--*-field-names` flags for the separate WSDL `*FieldNames`
|
|
170
|
+
request parameters declared by `AdGroupsGetRequest`:
|
|
171
|
+
`--autotargeting-settings-brand-options-field-names`,
|
|
172
|
+
`--autotargeting-settings-categories-field-names`,
|
|
173
|
+
`--dynamic-text-ad-group-field-names`,
|
|
174
|
+
`--dynamic-text-feed-ad-group-field-names`,
|
|
175
|
+
`--mobile-app-ad-group-field-names`,
|
|
176
|
+
`--smart-ad-group-field-names`,
|
|
177
|
+
`--text-ad-group-feed-params-field-names`, and
|
|
178
|
+
`--unified-ad-group-field-names`. Previously only the top-level
|
|
179
|
+
`--fields` (mapping to `FieldNames`) was available, so the
|
|
180
|
+
per-subtype ad-group projections could not be controlled from
|
|
181
|
+
CLI. Closes #405.
|
|
182
|
+
- `direct ads get` now exposes sixteen additional `--*-field-names`
|
|
183
|
+
flags for the separate WSDL `*FieldNames` request parameters
|
|
184
|
+
declared by `AdsGetRequest`: `--cpc-video-ad-builder-ad-field-names`,
|
|
185
|
+
`--cpm-banner-ad-builder-ad-field-names`,
|
|
186
|
+
`--cpm-video-ad-builder-ad-field-names`,
|
|
187
|
+
`--dynamic-text-ad-field-names`, `--listing-ad-field-names`,
|
|
188
|
+
`--mobile-app-ad-builder-ad-field-names`,
|
|
189
|
+
`--mobile-app-ad-field-names`,
|
|
190
|
+
`--mobile-app-cpc-video-ad-builder-ad-field-names`,
|
|
191
|
+
`--mobile-app-image-ad-field-names`,
|
|
192
|
+
`--responsive-ad-field-names`, `--shopping-ad-field-names`,
|
|
193
|
+
`--smart-ad-builder-ad-field-names`,
|
|
194
|
+
`--text-ad-builder-ad-field-names`,
|
|
195
|
+
`--text-ad-field-names`,
|
|
196
|
+
`--text-ad-price-extension-field-names`, and
|
|
197
|
+
`--text-image-ad-field-names`. Previously only the top-level
|
|
198
|
+
`--fields` (mapping to `FieldNames`) and non-canonical
|
|
199
|
+
`--text-ad-fields` were available, so the per-ad-subtype projections
|
|
200
|
+
could not be controlled from CLI. Closes #406.
|
|
201
|
+
|
|
202
|
+
**BREAKING CHANGES:**
|
|
203
|
+
|
|
204
|
+
- `direct campaigns get` flags `--text-campaign-fields`,
|
|
205
|
+
`--mobile-app-campaign-fields`, `--dynamic-text-campaign-fields`,
|
|
206
|
+
`--cpm-banner-campaign-fields`, `--smart-campaign-fields`,
|
|
207
|
+
`--unified-campaign-fields`,
|
|
208
|
+
`--text-campaign-search-strategy-placement-types-fields`,
|
|
209
|
+
`--dynamic-text-campaign-search-strategy-placement-types-fields`,
|
|
210
|
+
`--unified-campaign-search-strategy-placement-types-fields`, and
|
|
211
|
+
`--unified-campaign-package-bidding-strategy-platforms-fields`
|
|
212
|
+
are **renamed** to their kebab-case WSDL-canonical `*-field-names`
|
|
213
|
+
form (`--text-campaign-field-names`,
|
|
214
|
+
`--mobile-app-campaign-field-names`, ...), matching the parameter
|
|
215
|
+
names declared by `CampaignsGetRequest`. The old `--*-fields`
|
|
216
|
+
forms are no longer accepted — update scripts and automation
|
|
217
|
+
accordingly. Closes #409.
|
|
218
|
+
|
|
219
|
+
**Additional features:**
|
|
220
|
+
|
|
221
|
+
- `direct bidmodifiers get` now exposes thirteen additional
|
|
222
|
+
`--*-adjustment-field-names` flags for the per-adjustment-subtype
|
|
223
|
+
WSDL `*FieldNames` request parameters declared by
|
|
224
|
+
`BidModifiersGetRequest`: `--ad-group-adjustment-field-names`,
|
|
225
|
+
`--demographics-adjustment-field-names`,
|
|
226
|
+
`--desktop-adjustment-field-names`,
|
|
227
|
+
`--desktop-only-adjustment-field-names`,
|
|
228
|
+
`--income-grade-adjustment-field-names`,
|
|
229
|
+
`--mobile-adjustment-field-names`,
|
|
230
|
+
`--regional-adjustment-field-names`,
|
|
231
|
+
`--retargeting-adjustment-field-names`,
|
|
232
|
+
`--serp-layout-adjustment-field-names`,
|
|
233
|
+
`--smart-ad-adjustment-field-names`,
|
|
234
|
+
`--smart-tv-adjustment-field-names`,
|
|
235
|
+
`--tablet-adjustment-field-names`, and
|
|
236
|
+
`--video-adjustment-field-names`. Previously only the top-level
|
|
237
|
+
`--fields` (mapping to `FieldNames`) was available, so the
|
|
238
|
+
per-adjustment projections could not be controlled from CLI.
|
|
239
|
+
Closes #408.
|
|
240
|
+
- `direct strategies get` now exposes sixteen additional
|
|
241
|
+
`--strategy-*-field-names` flags for the separate WSDL
|
|
242
|
+
`*FieldNames` request parameters declared by `StrategiesGetRequest`,
|
|
243
|
+
including `--strategy-average-cpa-field-names`,
|
|
244
|
+
`--strategy-average-cpa-multiple-goals-field-names`,
|
|
245
|
+
`--strategy-average-cpc-field-names`,
|
|
246
|
+
`--strategy-maximum-clicks-field-names`,
|
|
247
|
+
`--strategy-maximum-conversion-rate-field-names`,
|
|
248
|
+
`--strategy-pay-for-conversion-field-names`, and the remaining
|
|
249
|
+
per-campaign / per-filter strategy projections. The command also
|
|
250
|
+
gains `--dry-run` for read-path payload tests. Previously only the
|
|
251
|
+
top-level `--fields` (mapping to `FieldNames`) was available, so
|
|
252
|
+
per-strategy-subtype projections could not be controlled from CLI.
|
|
253
|
+
Closes #414.
|
|
254
|
+
|
|
255
|
+
Closes #360.
|
|
256
|
+
|
|
257
|
+
**Tests:**
|
|
258
|
+
|
|
259
|
+
- `tests/test_integration.py` now gracefully skips the seven read-only
|
|
260
|
+
classes that rely on live-API probes (`TestReadOnlyAdGroups`,
|
|
261
|
+
`TestReadOnlyAds`, `TestReadOnlyKeywords`,
|
|
262
|
+
`TestReadOnlyDynamicFeedAdTargets`, `TestReadOnlyLeads`,
|
|
263
|
+
`TestReadOnlyBusinesses`, `TestReadOnlyAdVideos`) when the probe
|
|
264
|
+
raises — previously a temporary API outage crashed `setUpClass`
|
|
265
|
+
with an opaque traceback.
|
|
266
|
+
- `invoke_get` in `tests/test_integration.py` now passes the resolved
|
|
267
|
+
test credentials as explicit `--token`/`--login` flags so the
|
|
268
|
+
integration suite cannot silently fall through to a developer's
|
|
269
|
+
active `direct auth` profile (priority 1 in the CLI credential
|
|
270
|
+
chain wins over the profile, matching CLAUDE.md guidance).
|
|
271
|
+
- `tests/test_comprehensive.py` slimmed down: `TestCLIHelp` (full
|
|
272
|
+
duplicate of `tests/test_cli.py`) removed; the unique
|
|
273
|
+
`TestCommandsRegistered`, `TestUtils`, `TestOutputFormatters`,
|
|
274
|
+
`TestAuth`, and `TestErrorHandling` classes are kept.
|
|
275
|
+
- `tests/test_smoke_matrix.py` no longer hard-codes
|
|
276
|
+
`total_cli_subcommands == 144` or `wsdl_operations == 112`. Counts
|
|
277
|
+
are derived from the live Click registry and parsed WSDLs.
|
|
278
|
+
- `tests/test_sandbox_write_audit.py` no longer hard-codes
|
|
279
|
+
`total == 83`. The count derives from `commands_for_category`.
|
|
280
|
+
|
|
281
|
+
Closes #396.
|
|
282
|
+
|
|
3
283
|
## 0.3.13
|
|
4
284
|
|
|
5
285
|
**Breaking changes:**
|
|
@@ -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.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: direct-cli
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.15
|
|
4
4
|
Summary: Command-line interface for Yandex Direct API
|
|
5
5
|
Author: axisrow
|
|
6
6
|
License: MIT
|
|
@@ -232,10 +232,10 @@ is omitted. Dry-run output masks the financial token.
|
|
|
232
232
|
```bash
|
|
233
233
|
direct v4finance get-clients-units --logins client-login,other-client --format table
|
|
234
234
|
direct v4finance get-credit-limits --master-token MASTER_TOKEN --operation-num 123 --finance-login agency-login
|
|
235
|
-
direct v4finance create-invoice --payment 123=100.50 --payment 456=25 --
|
|
235
|
+
direct v4finance create-invoice --payment 123=100.50 --payment 456=25 --master-token MASTER_TOKEN --operation-num 124 --finance-login agency-login --dry-run
|
|
236
236
|
direct v4finance check-payment --custom-transaction-id A123456789012345678901234567890B
|
|
237
|
-
direct v4finance transfer-money --from-campaign-id 123 --to-campaign-id 456 --amount 100.50 --
|
|
238
|
-
direct v4finance pay-campaigns --campaign-ids 123,456 --amount 100.50 --
|
|
237
|
+
direct v4finance transfer-money --from-campaign-id 123 --to-campaign-id 456 --amount 100.50 --master-token MASTER_TOKEN --operation-num 123 --finance-login agency-login --dry-run
|
|
238
|
+
direct v4finance pay-campaigns --campaign-ids 123,456 --amount 100.50 --contract-id CONTRACT_ID --pay-method Bank --master-token MASTER_TOKEN --operation-num 123 --finance-login agency-login --dry-run
|
|
239
239
|
```
|
|
240
240
|
|
|
241
241
|
### V4 Live Shared Account
|
|
@@ -189,10 +189,10 @@ is omitted. Dry-run output masks the financial token.
|
|
|
189
189
|
```bash
|
|
190
190
|
direct v4finance get-clients-units --logins client-login,other-client --format table
|
|
191
191
|
direct v4finance get-credit-limits --master-token MASTER_TOKEN --operation-num 123 --finance-login agency-login
|
|
192
|
-
direct v4finance create-invoice --payment 123=100.50 --payment 456=25 --
|
|
192
|
+
direct v4finance create-invoice --payment 123=100.50 --payment 456=25 --master-token MASTER_TOKEN --operation-num 124 --finance-login agency-login --dry-run
|
|
193
193
|
direct v4finance check-payment --custom-transaction-id A123456789012345678901234567890B
|
|
194
|
-
direct v4finance transfer-money --from-campaign-id 123 --to-campaign-id 456 --amount 100.50 --
|
|
195
|
-
direct v4finance pay-campaigns --campaign-ids 123,456 --amount 100.50 --
|
|
194
|
+
direct v4finance transfer-money --from-campaign-id 123 --to-campaign-id 456 --amount 100.50 --master-token MASTER_TOKEN --operation-num 123 --finance-login agency-login --dry-run
|
|
195
|
+
direct v4finance pay-campaigns --campaign-ids 123,456 --amount 100.50 --contract-id CONTRACT_ID --pay-method Bank --master-token MASTER_TOKEN --operation-num 123 --finance-login agency-login --dry-run
|
|
196
196
|
```
|
|
197
197
|
|
|
198
198
|
### V4 Live Shared Account
|
|
@@ -1718,11 +1718,6 @@ def build_text_campaign_search_strategy(
|
|
|
1718
1718
|
# the caller has already placed PriorityGoals via the dedicated
|
|
1719
1719
|
# ``PriorityGoalsUpdateSetting`` shape (with ``Operation: SET``) so
|
|
1720
1720
|
# we only validate the strategy/subtype combination here.
|
|
1721
|
-
#
|
|
1722
|
-
# KNOWN ISSUE (#387): ``parse_priority_goals_spec`` forwards
|
|
1723
|
-
# ``Value`` as a raw integer. Per Yandex docs ``Value`` is
|
|
1724
|
-
# advertiser currency × 1,000,000; the cross-cutting fix is
|
|
1725
|
-
# tracked in issue #387 and intentionally NOT bundled into #361.
|
|
1726
1721
|
if priority_goals_items is not None:
|
|
1727
1722
|
if subtype not in _TEXT_SEARCH_REQUIRES_PRIORITY_GOALS:
|
|
1728
1723
|
raise click.UsageError(
|
{direct_cli-0.3.13 → direct_cli-0.3.15}/direct_cli/_vendor/tapi_yandex_direct/resource_mapping.py
RENAMED
|
@@ -78,12 +78,12 @@ RESOURCE_MAPPING_V5 = {
|
|
|
78
78
|
},
|
|
79
79
|
"dynamicads": {
|
|
80
80
|
"resource": "json/v5/dynamictextadtargets",
|
|
81
|
-
"docs": "https://yandex.ru/dev/direct/doc/ru/dynamictextadtargets
|
|
81
|
+
"docs": "https://yandex.ru/dev/direct/doc/ru/dynamictextadtargets",
|
|
82
82
|
"methods": ["get", "add", "delete", "suspend", "resume", "setBids"],
|
|
83
83
|
},
|
|
84
84
|
"dynamicfeedadtargets": {
|
|
85
85
|
"resource": "json/v5/dynamicfeedadtargets",
|
|
86
|
-
"docs": "https://yandex.ru/dev/direct/doc/ru/dynamicfeedadtargets
|
|
86
|
+
"docs": "https://yandex.ru/dev/direct/doc/ru/dynamicfeedadtargets",
|
|
87
87
|
"methods": ["get", "add", "delete", "suspend", "resume", "setBids"],
|
|
88
88
|
},
|
|
89
89
|
"keywordbids": {
|
|
@@ -118,7 +118,7 @@ RESOURCE_MAPPING_V5 = {
|
|
|
118
118
|
},
|
|
119
119
|
"vcards": {
|
|
120
120
|
"resource": "json/v5/vcards",
|
|
121
|
-
"docs": "https://yandex.ru/dev/direct/doc/ru/vcards
|
|
121
|
+
"docs": "https://yandex.ru/dev/direct/doc/ru/vcards",
|
|
122
122
|
"methods": ["get", "add", "delete"],
|
|
123
123
|
},
|
|
124
124
|
"turbopages": {
|
|
@@ -133,12 +133,12 @@ RESOURCE_MAPPING_V5 = {
|
|
|
133
133
|
},
|
|
134
134
|
"reports": {
|
|
135
135
|
"resource": "json/v5/reports",
|
|
136
|
-
"docs": "https://yandex.ru/dev/direct/doc/ru/reports
|
|
136
|
+
"docs": "https://yandex.ru/dev/direct/doc/ru/reports",
|
|
137
137
|
"methods": ["get"],
|
|
138
138
|
"docs_pages": {
|
|
139
|
-
"type": "https://yandex.ru/dev/direct/doc/ru/
|
|
140
|
-
"period": "https://yandex.ru/dev/direct/doc/ru/
|
|
141
|
-
"fields-list": "https://yandex.ru/dev/direct/doc/ru/
|
|
139
|
+
"type": "https://yandex.ru/dev/direct/doc/ru/type",
|
|
140
|
+
"period": "https://yandex.ru/dev/direct/doc/ru/period",
|
|
141
|
+
"fields-list": "https://yandex.ru/dev/direct/doc/ru/fields-list",
|
|
142
142
|
"headers": "https://yandex.ru/dev/direct/doc/ru/headers",
|
|
143
143
|
},
|
|
144
144
|
},
|
|
@@ -154,7 +154,7 @@ RESOURCE_MAPPING_V5 = {
|
|
|
154
154
|
},
|
|
155
155
|
"smartadtargets": {
|
|
156
156
|
"resource": "json/v5/smartadtargets",
|
|
157
|
-
"docs": "https://yandex.ru/dev/direct/doc/ru/smartadtargets
|
|
157
|
+
"docs": "https://yandex.ru/dev/direct/doc/ru/smartadtargets",
|
|
158
158
|
"methods": ["get", "add", "update", "delete", "suspend", "resume", "setBids"],
|
|
159
159
|
},
|
|
160
160
|
"strategies": {
|
|
@@ -473,6 +473,77 @@ def _post_adgroups(client: Any, body: dict[str, Any]) -> Any:
|
|
|
473
473
|
@click.option("--format", "output_format", default="json", help="Output format")
|
|
474
474
|
@click.option("--output", help="Output file")
|
|
475
475
|
@click.option("--fields", help="Comma-separated field names")
|
|
476
|
+
@click.option(
|
|
477
|
+
"--autotargeting-settings-brand-options-field-names",
|
|
478
|
+
help=(
|
|
479
|
+
"Comma-separated AutotargetingSettingsBrandOptionsFieldNames "
|
|
480
|
+
"(e.g. WithoutBrands,WithAdvertiserBrand,WithCompetitorsBrand). "
|
|
481
|
+
"Sent as separate top-level request parameter per the "
|
|
482
|
+
"AdGroupsGetRequest WSDL."
|
|
483
|
+
),
|
|
484
|
+
)
|
|
485
|
+
@click.option(
|
|
486
|
+
"--autotargeting-settings-categories-field-names",
|
|
487
|
+
help=(
|
|
488
|
+
"Comma-separated AutotargetingSettingsCategoriesFieldNames "
|
|
489
|
+
"(e.g. Exact,Narrow,Alternative,Accessory,Broader). "
|
|
490
|
+
"Sent as separate top-level request parameter per the "
|
|
491
|
+
"AdGroupsGetRequest WSDL."
|
|
492
|
+
),
|
|
493
|
+
)
|
|
494
|
+
@click.option(
|
|
495
|
+
"--dynamic-text-ad-group-field-names",
|
|
496
|
+
help=(
|
|
497
|
+
"Comma-separated DynamicTextAdGroupFieldNames "
|
|
498
|
+
"(e.g. AutotargetingSettings,DomainUrl). "
|
|
499
|
+
"Sent as separate top-level request parameter per the "
|
|
500
|
+
"AdGroupsGetRequest WSDL."
|
|
501
|
+
),
|
|
502
|
+
)
|
|
503
|
+
@click.option(
|
|
504
|
+
"--dynamic-text-feed-ad-group-field-names",
|
|
505
|
+
help=(
|
|
506
|
+
"Comma-separated DynamicTextFeedAdGroupFieldNames "
|
|
507
|
+
"(e.g. Source,FeedId,SourceType). "
|
|
508
|
+
"Sent as separate top-level request parameter per the "
|
|
509
|
+
"AdGroupsGetRequest WSDL."
|
|
510
|
+
),
|
|
511
|
+
)
|
|
512
|
+
@click.option(
|
|
513
|
+
"--mobile-app-ad-group-field-names",
|
|
514
|
+
help=(
|
|
515
|
+
"Comma-separated MobileAppAdGroupFieldNames "
|
|
516
|
+
"(e.g. StoreUrl,TargetDeviceType,AppOperatingSystemType). "
|
|
517
|
+
"Sent as separate top-level request parameter per the "
|
|
518
|
+
"AdGroupsGetRequest WSDL."
|
|
519
|
+
),
|
|
520
|
+
)
|
|
521
|
+
@click.option(
|
|
522
|
+
"--smart-ad-group-field-names",
|
|
523
|
+
help=(
|
|
524
|
+
"Comma-separated SmartAdGroupFieldNames "
|
|
525
|
+
"(e.g. FeedId,AdTitleSource,AdBodySource). "
|
|
526
|
+
"Sent as separate top-level request parameter per the "
|
|
527
|
+
"AdGroupsGetRequest WSDL."
|
|
528
|
+
),
|
|
529
|
+
)
|
|
530
|
+
@click.option(
|
|
531
|
+
"--text-ad-group-feed-params-field-names",
|
|
532
|
+
help=(
|
|
533
|
+
"Comma-separated TextAdGroupFeedParamsFieldNames "
|
|
534
|
+
"(e.g. FeedId,FeedCategoryIds). "
|
|
535
|
+
"Sent as separate top-level request parameter per the "
|
|
536
|
+
"AdGroupsGetRequest WSDL."
|
|
537
|
+
),
|
|
538
|
+
)
|
|
539
|
+
@click.option(
|
|
540
|
+
"--unified-ad-group-field-names",
|
|
541
|
+
help=(
|
|
542
|
+
"Comma-separated UnifiedAdGroupFieldNames (e.g. OfferRetargeting). "
|
|
543
|
+
"Sent as separate top-level request parameter per the "
|
|
544
|
+
"AdGroupsGetRequest WSDL."
|
|
545
|
+
),
|
|
546
|
+
)
|
|
476
547
|
@click.option("--dry-run", is_flag=True, help="Show request without sending")
|
|
477
548
|
@click.pass_context
|
|
478
549
|
def get(
|
|
@@ -492,6 +563,14 @@ def get(
|
|
|
492
563
|
output_format,
|
|
493
564
|
output,
|
|
494
565
|
fields,
|
|
566
|
+
autotargeting_settings_brand_options_field_names,
|
|
567
|
+
autotargeting_settings_categories_field_names,
|
|
568
|
+
dynamic_text_ad_group_field_names,
|
|
569
|
+
dynamic_text_feed_ad_group_field_names,
|
|
570
|
+
mobile_app_ad_group_field_names,
|
|
571
|
+
smart_ad_group_field_names,
|
|
572
|
+
text_ad_group_feed_params_field_names,
|
|
573
|
+
unified_ad_group_field_names,
|
|
495
574
|
dry_run,
|
|
496
575
|
):
|
|
497
576
|
"""Get ad groups"""
|
|
@@ -507,6 +586,41 @@ def get(
|
|
|
507
586
|
|
|
508
587
|
field_names = fields.split(",") if fields else get_default_fields("adgroups")
|
|
509
588
|
|
|
589
|
+
raw_nested = (
|
|
590
|
+
(
|
|
591
|
+
"AutotargetingSettingsBrandOptionsFieldNames",
|
|
592
|
+
autotargeting_settings_brand_options_field_names,
|
|
593
|
+
),
|
|
594
|
+
(
|
|
595
|
+
"AutotargetingSettingsCategoriesFieldNames",
|
|
596
|
+
autotargeting_settings_categories_field_names,
|
|
597
|
+
),
|
|
598
|
+
(
|
|
599
|
+
"DynamicTextAdGroupFieldNames",
|
|
600
|
+
dynamic_text_ad_group_field_names,
|
|
601
|
+
),
|
|
602
|
+
(
|
|
603
|
+
"DynamicTextFeedAdGroupFieldNames",
|
|
604
|
+
dynamic_text_feed_ad_group_field_names,
|
|
605
|
+
),
|
|
606
|
+
("MobileAppAdGroupFieldNames", mobile_app_ad_group_field_names),
|
|
607
|
+
("SmartAdGroupFieldNames", smart_ad_group_field_names),
|
|
608
|
+
(
|
|
609
|
+
"TextAdGroupFeedParamsFieldNames",
|
|
610
|
+
text_ad_group_feed_params_field_names,
|
|
611
|
+
),
|
|
612
|
+
("UnifiedAdGroupFieldNames", unified_ad_group_field_names),
|
|
613
|
+
)
|
|
614
|
+
parsed_nested = {}
|
|
615
|
+
for wsdl_key, raw_value in raw_nested:
|
|
616
|
+
parsed = parse_csv_strings(raw_value)
|
|
617
|
+
if raw_value is not None and not parsed:
|
|
618
|
+
raise click.UsageError(
|
|
619
|
+
f"Provide a non-empty comma-separated {wsdl_key} list."
|
|
620
|
+
)
|
|
621
|
+
if parsed:
|
|
622
|
+
parsed_nested[wsdl_key] = parsed
|
|
623
|
+
|
|
510
624
|
criteria = {}
|
|
511
625
|
if ids:
|
|
512
626
|
criteria["Ids"] = parse_ids(ids)
|
|
@@ -529,6 +643,7 @@ def get(
|
|
|
529
643
|
)
|
|
530
644
|
|
|
531
645
|
params = {"SelectionCriteria": criteria, "FieldNames": field_names}
|
|
646
|
+
params.update(parsed_nested)
|
|
532
647
|
|
|
533
648
|
if limit:
|
|
534
649
|
params["Page"] = {"Limit": limit}
|
|
@@ -550,6 +665,8 @@ def get(
|
|
|
550
665
|
data = result().extract()
|
|
551
666
|
format_output(data, output_format, output)
|
|
552
667
|
|
|
668
|
+
except click.UsageError:
|
|
669
|
+
raise
|
|
553
670
|
except Exception as e:
|
|
554
671
|
print_error(str(e))
|
|
555
672
|
raise click.Abort()
|