direct-cli 0.3.10__tar.gz → 0.3.11__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.
Files changed (230) hide show
  1. {direct_cli-0.3.10 → direct_cli-0.3.11}/CHANGELOG.md +41 -0
  2. {direct_cli-0.3.10 → direct_cli-0.3.11}/PKG-INFO +27 -7
  3. {direct_cli-0.3.10 → direct_cli-0.3.11}/README.md +26 -6
  4. {direct_cli-0.3.10 → direct_cli-0.3.11}/direct_cli/commands/campaigns.py +103 -1
  5. direct_cli-0.3.11/direct_cli/commands/v4account.py +747 -0
  6. {direct_cli-0.3.10 → direct_cli-0.3.11}/direct_cli/commands/v4events.py +2 -0
  7. {direct_cli-0.3.10 → direct_cli-0.3.11}/direct_cli/commands/v4finance.py +10 -5
  8. {direct_cli-0.3.10 → direct_cli-0.3.11}/direct_cli/commands/v4forecast.py +2 -0
  9. {direct_cli-0.3.10 → direct_cli-0.3.11}/direct_cli/commands/v4goals.py +2 -0
  10. {direct_cli-0.3.10 → direct_cli-0.3.11}/direct_cli/commands/v4tags.py +2 -0
  11. {direct_cli-0.3.10 → direct_cli-0.3.11}/direct_cli/commands/v4wordstat.py +2 -0
  12. {direct_cli-0.3.10 → direct_cli-0.3.11}/direct_cli/v4/money.py +11 -6
  13. {direct_cli-0.3.10 → direct_cli-0.3.11}/direct_cli/v4_contracts.py +22 -11
  14. {direct_cli-0.3.10 → direct_cli-0.3.11}/direct_cli.egg-info/PKG-INFO +27 -7
  15. {direct_cli-0.3.10 → direct_cli-0.3.11}/direct_cli.egg-info/SOURCES.txt +1 -0
  16. {direct_cli-0.3.10 → direct_cli-0.3.11}/pyproject.toml +1 -1
  17. {direct_cli-0.3.10 → direct_cli-0.3.11}/scripts/test_safe_commands.sh +1 -1
  18. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/API_COVERAGE.md +33 -0
  19. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/test_dry_run.py +170 -0
  20. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/test_v4_contracts.py +64 -10
  21. direct_cli-0.3.11/tests/test_v4_exit_codes.py +125 -0
  22. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/test_v4_live_contracts.py +1 -1
  23. direct_cli-0.3.11/tests/test_v4account.py +1026 -0
  24. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/test_v4finance_read.py +11 -22
  25. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/test_wsdl_parity_gate.py +26 -0
  26. direct_cli-0.3.10/direct_cli/commands/v4account.py +0 -281
  27. direct_cli-0.3.10/tests/test_v4account.py +0 -410
  28. {direct_cli-0.3.10 → direct_cli-0.3.11}/.env.example +0 -0
  29. {direct_cli-0.3.10 → direct_cli-0.3.11}/.github/copilot-instructions.md +0 -0
  30. {direct_cli-0.3.10 → direct_cli-0.3.11}/.github/workflows/api-coverage.yml +0 -0
  31. {direct_cli-0.3.10 → direct_cli-0.3.11}/.github/workflows/claude.yml +0 -0
  32. {direct_cli-0.3.10 → direct_cli-0.3.11}/.github/workflows/quality.yml +0 -0
  33. {direct_cli-0.3.10 → direct_cli-0.3.11}/.gitignore +0 -0
  34. {direct_cli-0.3.10 → direct_cli-0.3.11}/AGENTS.md +0 -0
  35. {direct_cli-0.3.10 → direct_cli-0.3.11}/CLAUDE.md +0 -0
  36. {direct_cli-0.3.10 → direct_cli-0.3.11}/MANIFEST.in +0 -0
  37. {direct_cli-0.3.10 → direct_cli-0.3.11}/direct_cli/__init__.py +0 -0
  38. {direct_cli-0.3.10 → direct_cli-0.3.11}/direct_cli/_deprecated.py +0 -0
  39. {direct_cli-0.3.10 → direct_cli-0.3.11}/direct_cli/_smoke_probes.py +0 -0
  40. {direct_cli-0.3.10 → direct_cli-0.3.11}/direct_cli/_vendor/__init__.py +0 -0
  41. {direct_cli-0.3.10 → direct_cli-0.3.11}/direct_cli/_vendor/tapi_yandex_direct/__init__.py +0 -0
  42. {direct_cli-0.3.10 → direct_cli-0.3.11}/direct_cli/_vendor/tapi_yandex_direct/endpoints.py +0 -0
  43. {direct_cli-0.3.10 → direct_cli-0.3.11}/direct_cli/_vendor/tapi_yandex_direct/exceptions.py +0 -0
  44. {direct_cli-0.3.10 → direct_cli-0.3.11}/direct_cli/_vendor/tapi_yandex_direct/resource_mapping.py +0 -0
  45. {direct_cli-0.3.10 → direct_cli-0.3.11}/direct_cli/_vendor/tapi_yandex_direct/tapi_yandex_direct.py +0 -0
  46. {direct_cli-0.3.10 → direct_cli-0.3.11}/direct_cli/_vendor/tapi_yandex_direct/tapi_yandex_direct.pyi +0 -0
  47. {direct_cli-0.3.10 → direct_cli-0.3.11}/direct_cli/_vendor/tapi_yandex_direct/v4/__init__.py +0 -0
  48. {direct_cli-0.3.10 → direct_cli-0.3.11}/direct_cli/_vendor/tapi_yandex_direct/v4/adapter.py +0 -0
  49. {direct_cli-0.3.10 → direct_cli-0.3.11}/direct_cli/_vendor/tapi_yandex_direct/v4/adapter.pyi +0 -0
  50. {direct_cli-0.3.10 → direct_cli-0.3.11}/direct_cli/_vendor/tapi_yandex_direct/v4/resource_mapping.py +0 -0
  51. {direct_cli-0.3.10 → direct_cli-0.3.11}/direct_cli/api.py +0 -0
  52. {direct_cli-0.3.10 → direct_cli-0.3.11}/direct_cli/auth.py +0 -0
  53. {direct_cli-0.3.10 → direct_cli-0.3.11}/direct_cli/cli.py +0 -0
  54. {direct_cli-0.3.10 → direct_cli-0.3.11}/direct_cli/commands/__init__.py +0 -0
  55. {direct_cli-0.3.10 → direct_cli-0.3.11}/direct_cli/commands/adextensions.py +0 -0
  56. {direct_cli-0.3.10 → direct_cli-0.3.11}/direct_cli/commands/adgroups.py +0 -0
  57. {direct_cli-0.3.10 → direct_cli-0.3.11}/direct_cli/commands/adimages.py +0 -0
  58. {direct_cli-0.3.10 → direct_cli-0.3.11}/direct_cli/commands/ads.py +0 -0
  59. {direct_cli-0.3.10 → direct_cli-0.3.11}/direct_cli/commands/advideos.py +0 -0
  60. {direct_cli-0.3.10 → direct_cli-0.3.11}/direct_cli/commands/agencyclients.py +0 -0
  61. {direct_cli-0.3.10 → direct_cli-0.3.11}/direct_cli/commands/audiencetargets.py +0 -0
  62. {direct_cli-0.3.10 → direct_cli-0.3.11}/direct_cli/commands/auth.py +0 -0
  63. {direct_cli-0.3.10 → direct_cli-0.3.11}/direct_cli/commands/balance.py +0 -0
  64. {direct_cli-0.3.10 → direct_cli-0.3.11}/direct_cli/commands/bidmodifiers.py +0 -0
  65. {direct_cli-0.3.10 → direct_cli-0.3.11}/direct_cli/commands/bids.py +0 -0
  66. {direct_cli-0.3.10 → direct_cli-0.3.11}/direct_cli/commands/businesses.py +0 -0
  67. {direct_cli-0.3.10 → direct_cli-0.3.11}/direct_cli/commands/changes.py +0 -0
  68. {direct_cli-0.3.10 → direct_cli-0.3.11}/direct_cli/commands/clients.py +0 -0
  69. {direct_cli-0.3.10 → direct_cli-0.3.11}/direct_cli/commands/creatives.py +0 -0
  70. {direct_cli-0.3.10 → direct_cli-0.3.11}/direct_cli/commands/dictionaries.py +0 -0
  71. {direct_cli-0.3.10 → direct_cli-0.3.11}/direct_cli/commands/dynamicads.py +0 -0
  72. {direct_cli-0.3.10 → direct_cli-0.3.11}/direct_cli/commands/dynamicfeedadtargets.py +0 -0
  73. {direct_cli-0.3.10 → direct_cli-0.3.11}/direct_cli/commands/feeds.py +0 -0
  74. {direct_cli-0.3.10 → direct_cli-0.3.11}/direct_cli/commands/keywordbids.py +0 -0
  75. {direct_cli-0.3.10 → direct_cli-0.3.11}/direct_cli/commands/keywords.py +0 -0
  76. {direct_cli-0.3.10 → direct_cli-0.3.11}/direct_cli/commands/keywordsresearch.py +0 -0
  77. {direct_cli-0.3.10 → direct_cli-0.3.11}/direct_cli/commands/leads.py +0 -0
  78. {direct_cli-0.3.10 → direct_cli-0.3.11}/direct_cli/commands/negativekeywordsharedsets.py +0 -0
  79. {direct_cli-0.3.10 → direct_cli-0.3.11}/direct_cli/commands/reports.py +0 -0
  80. {direct_cli-0.3.10 → direct_cli-0.3.11}/direct_cli/commands/retargeting.py +0 -0
  81. {direct_cli-0.3.10 → direct_cli-0.3.11}/direct_cli/commands/sitelinks.py +0 -0
  82. {direct_cli-0.3.10 → direct_cli-0.3.11}/direct_cli/commands/smartadtargets.py +0 -0
  83. {direct_cli-0.3.10 → direct_cli-0.3.11}/direct_cli/commands/strategies.py +0 -0
  84. {direct_cli-0.3.10 → direct_cli-0.3.11}/direct_cli/commands/turbopages.py +0 -0
  85. {direct_cli-0.3.10 → direct_cli-0.3.11}/direct_cli/commands/v4shells.py +0 -0
  86. {direct_cli-0.3.10 → direct_cli-0.3.11}/direct_cli/commands/vcards.py +0 -0
  87. {direct_cli-0.3.10 → direct_cli-0.3.11}/direct_cli/output.py +0 -0
  88. {direct_cli-0.3.10 → direct_cli-0.3.11}/direct_cli/reports_coverage.py +0 -0
  89. {direct_cli-0.3.10 → direct_cli-0.3.11}/direct_cli/smoke_matrix.py +0 -0
  90. {direct_cli-0.3.10 → direct_cli-0.3.11}/direct_cli/utils.py +0 -0
  91. {direct_cli-0.3.10 → direct_cli-0.3.11}/direct_cli/v4/__init__.py +0 -0
  92. {direct_cli-0.3.10 → direct_cli-0.3.11}/direct_cli/wsdl_coverage.py +0 -0
  93. {direct_cli-0.3.10 → direct_cli-0.3.11}/direct_cli.egg-info/dependency_links.txt +0 -0
  94. {direct_cli-0.3.10 → direct_cli-0.3.11}/direct_cli.egg-info/entry_points.txt +0 -0
  95. {direct_cli-0.3.10 → direct_cli-0.3.11}/direct_cli.egg-info/requires.txt +0 -0
  96. {direct_cli-0.3.10 → direct_cli-0.3.11}/direct_cli.egg-info/top_level.txt +0 -0
  97. {direct_cli-0.3.10 → direct_cli-0.3.11}/docs/audits/issue-198-mutating-wsdl-audit.md +0 -0
  98. {direct_cli-0.3.10 → direct_cli-0.3.11}/docs/superpowers/plans/2026-04-12-issue-32-completion.md +0 -0
  99. {direct_cli-0.3.10 → direct_cli-0.3.11}/docs/superpowers/specs/2026-04-23-vendor-tapi-yandex-direct-design.md +0 -0
  100. {direct_cli-0.3.10 → direct_cli-0.3.11}/scripts/anonymize_cassettes.py +0 -0
  101. {direct_cli-0.3.10 → direct_cli-0.3.11}/scripts/build_api_coverage_checklist.py +0 -0
  102. {direct_cli-0.3.10 → direct_cli-0.3.11}/scripts/build_api_coverage_report.py +0 -0
  103. {direct_cli-0.3.10 → direct_cli-0.3.11}/scripts/check_reports_drift.py +0 -0
  104. {direct_cli-0.3.10 → direct_cli-0.3.11}/scripts/check_wsdl_drift.py +0 -0
  105. {direct_cli-0.3.10 → direct_cli-0.3.11}/scripts/patch_vendor_imports.py +0 -0
  106. {direct_cli-0.3.10 → direct_cli-0.3.11}/scripts/refresh_reports_cache.py +0 -0
  107. {direct_cli-0.3.10 → direct_cli-0.3.11}/scripts/refresh_wsdl_cache.py +0 -0
  108. {direct_cli-0.3.10 → direct_cli-0.3.11}/scripts/release_pypi.sh +0 -0
  109. {direct_cli-0.3.10 → direct_cli-0.3.11}/scripts/sandbox_write_audit.py +0 -0
  110. {direct_cli-0.3.10 → direct_cli-0.3.11}/scripts/sandbox_write_live.py +0 -0
  111. {direct_cli-0.3.10 → direct_cli-0.3.11}/scripts/test_dangerous_commands.sh +0 -0
  112. {direct_cli-0.3.10 → direct_cli-0.3.11}/scripts/test_sandbox_write.sh +0 -0
  113. {direct_cli-0.3.10 → direct_cli-0.3.11}/scripts/update_vendor.sh +0 -0
  114. {direct_cli-0.3.10 → direct_cli-0.3.11}/setup.cfg +0 -0
  115. {direct_cli-0.3.10 → direct_cli-0.3.11}/setup.py +0 -0
  116. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/API_ISSUE_AUDIT.md +0 -0
  117. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/MANUAL_COVERAGE.md +0 -0
  118. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/__init__.py +0 -0
  119. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/_orphan_store.py +0 -0
  120. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/api_coverage_payloads.py +0 -0
  121. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/cassettes/test_integration_write/TestWriteAdExtensions.test_add_delete.yaml +0 -0
  122. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/cassettes/test_integration_write/TestWriteAdGroups.test_add_update_delete.yaml +0 -0
  123. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/cassettes/test_integration_write/TestWriteAdImages.test_add_delete.yaml +0 -0
  124. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/cassettes/test_integration_write/TestWriteAds.test_add_text_ad_update_delete.yaml +0 -0
  125. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/cassettes/test_integration_write/TestWriteAudienceTargets.test_add_delete.yaml +0 -0
  126. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/cassettes/test_integration_write/TestWriteBidModifiersAdd.test_add_delete_mobile.yaml +0 -0
  127. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/cassettes/test_integration_write/TestWriteBidModifiersSet.test_set_without_id_is_rejected.yaml +0 -0
  128. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/cassettes/test_integration_write/TestWriteBids.test_set_bid.yaml +0 -0
  129. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/cassettes/test_integration_write/TestWriteBidsRead.test_bids_get.yaml +0 -0
  130. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/cassettes/test_integration_write/TestWriteBidsRead.test_bids_set_auto.yaml +0 -0
  131. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/cassettes/test_integration_write/TestWriteCampaignDraftLifecycle.test_draft_create_get_delete.yaml +0 -0
  132. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/cassettes/test_integration_write/TestWriteCampaigns.test_campaign_lifecycle.yaml +0 -0
  133. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/cassettes/test_integration_write/TestWriteDynamicAds.test_add_update_delete.yaml +0 -0
  134. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/cassettes/test_integration_write/TestWriteFeeds.test_add_update_delete.yaml +0 -0
  135. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/cassettes/test_integration_write/TestWriteKeywordBids.test_set_keyword_bid.yaml +0 -0
  136. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/cassettes/test_integration_write/TestWriteKeywords.test_add_update_delete.yaml +0 -0
  137. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/cassettes/test_integration_write/TestWriteNegativeKeywordSharedSets.test_add_update_delete.yaml +0 -0
  138. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/cassettes/test_integration_write/TestWriteRetargeting.test_add_delete.yaml +0 -0
  139. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/cassettes/test_integration_write/TestWriteRetargetingUpdate.test_retargeting_update.yaml +0 -0
  140. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/cassettes/test_integration_write/TestWriteSitelinks.test_add_delete.yaml +0 -0
  141. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/cassettes/test_integration_write/TestWriteSmartAdTargets.test_add_update_delete.yaml +0 -0
  142. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/cassettes/test_integration_write/TestWriteStrategies.test_strategies_lifecycle.yaml +0 -0
  143. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/cassettes/test_integration_write/TestWriteVCards.test_add_delete.yaml +0 -0
  144. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/cassettes/test_v5_live_write/test_v5_live_draft_adgroups_add_update_delete.yaml +0 -0
  145. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/cassettes/test_v5_live_write/test_v5_live_draft_adimages_add_get_delete.yaml +0 -0
  146. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/cassettes/test_v5_live_write/test_v5_live_draft_ads_add_update_delete.yaml +0 -0
  147. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/cassettes/test_v5_live_write/test_v5_live_draft_ads_suspend_resume_archive_unarchive.yaml +0 -0
  148. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/cassettes/test_v5_live_write/test_v5_live_draft_advideos_add_get.yaml +0 -0
  149. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/cassettes/test_v5_live_write/test_v5_live_draft_audiencetargets_add_delete.yaml +0 -0
  150. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/cassettes/test_v5_live_write/test_v5_live_draft_audiencetargets_suspend_resume.yaml +0 -0
  151. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/cassettes/test_v5_live_write/test_v5_live_draft_bids_set.yaml +0 -0
  152. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/cassettes/test_v5_live_write/test_v5_live_draft_campaign_create_get_delete.yaml +0 -0
  153. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/cassettes/test_v5_live_write/test_v5_live_draft_creatives_chain_advideo_to_creative.yaml +0 -0
  154. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/cassettes/test_v5_live_write/test_v5_live_draft_dynamicads_add_delete.yaml +0 -0
  155. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/cassettes/test_v5_live_write/test_v5_live_draft_dynamicads_suspend_resume.yaml +0 -0
  156. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/cassettes/test_v5_live_write/test_v5_live_draft_keywordbids_set.yaml +0 -0
  157. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/cassettes/test_v5_live_write/test_v5_live_draft_keywords_add_update_delete.yaml +0 -0
  158. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/cassettes/test_v5_live_write/test_v5_live_draft_keywords_suspend_resume.yaml +0 -0
  159. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/cassettes/test_v5_live_write/test_v5_live_draft_sitelinks_add_get_delete.yaml +0 -0
  160. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/cassettes/test_v5_live_write/test_v5_live_draft_smartadtargets_add_update_delete.yaml +0 -0
  161. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/cassettes/test_v5_live_write/test_v5_live_draft_smartadtargets_suspend_resume.yaml +0 -0
  162. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/conftest.py +0 -0
  163. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/fixtures/test-video.mp4 +0 -0
  164. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/reports_cache/raw/fields-list.html +0 -0
  165. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/reports_cache/raw/headers.html +0 -0
  166. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/reports_cache/raw/period.html +0 -0
  167. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/reports_cache/raw/spec.html +0 -0
  168. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/reports_cache/raw/type.html +0 -0
  169. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/reports_cache/spec.json +0 -0
  170. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/test_api_coverage.py +0 -0
  171. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/test_auth_bw.py +0 -0
  172. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/test_auth_oauth.py +0 -0
  173. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/test_auth_op.py +0 -0
  174. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/test_auth_write_json.py +0 -0
  175. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/test_balance.py +0 -0
  176. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/test_changes.py +0 -0
  177. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/test_cli.py +0 -0
  178. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/test_cli_contract.py +0 -0
  179. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/test_comprehensive.py +0 -0
  180. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/test_integration.py +0 -0
  181. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/test_integration_write.py +0 -0
  182. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/test_low_coverage_payloads.py +0 -0
  183. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/test_reports_drift.py +0 -0
  184. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/test_reports_parsing.py +0 -0
  185. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/test_sandbox_write_audit.py +0 -0
  186. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/test_smoke_matrix.py +0 -0
  187. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/test_transport_contract.py +0 -0
  188. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/test_v4_foundation.py +0 -0
  189. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/test_v4_runtime_shape.py +0 -0
  190. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/test_v4_safety.py +0 -0
  191. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/test_v4events.py +0 -0
  192. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/test_v4finance_money.py +0 -0
  193. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/test_v4forecast.py +0 -0
  194. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/test_v4goals.py +0 -0
  195. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/test_v4tags.py +0 -0
  196. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/test_v4wordstat.py +0 -0
  197. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/test_v5_live_write.py +0 -0
  198. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/test_vendor_imports.py +0 -0
  199. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/wsdl_cache/adextensions.xml +0 -0
  200. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/wsdl_cache/adgroups.xml +0 -0
  201. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/wsdl_cache/adimages.xml +0 -0
  202. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/wsdl_cache/ads.xml +0 -0
  203. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/wsdl_cache/advideos.xml +0 -0
  204. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/wsdl_cache/agencyclients.xml +0 -0
  205. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/wsdl_cache/audiencetargets.xml +0 -0
  206. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/wsdl_cache/bidmodifiers.xml +0 -0
  207. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/wsdl_cache/bids.xml +0 -0
  208. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/wsdl_cache/businesses.xml +0 -0
  209. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/wsdl_cache/campaigns.xml +0 -0
  210. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/wsdl_cache/changes.xml +0 -0
  211. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/wsdl_cache/clients.xml +0 -0
  212. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/wsdl_cache/creatives.xml +0 -0
  213. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/wsdl_cache/dictionaries.xml +0 -0
  214. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/wsdl_cache/dynamicfeedadtargets.xml +0 -0
  215. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/wsdl_cache/dynamictextadtargets.xml +0 -0
  216. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/wsdl_cache/feeds.xml +0 -0
  217. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/wsdl_cache/imports/adextensiontypes.xsd +0 -0
  218. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/wsdl_cache/imports/general.xsd +0 -0
  219. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/wsdl_cache/imports/generalclients.xsd +0 -0
  220. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/wsdl_cache/keywordbids.xml +0 -0
  221. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/wsdl_cache/keywords.xml +0 -0
  222. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/wsdl_cache/keywordsresearch.xml +0 -0
  223. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/wsdl_cache/leads.xml +0 -0
  224. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/wsdl_cache/negativekeywordsharedsets.xml +0 -0
  225. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/wsdl_cache/retargetinglists.xml +0 -0
  226. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/wsdl_cache/sitelinks.xml +0 -0
  227. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/wsdl_cache/smartadtargets.xml +0 -0
  228. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/wsdl_cache/strategies.xml +0 -0
  229. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/wsdl_cache/turbopages.xml +0 -0
  230. {direct_cli-0.3.10 → direct_cli-0.3.11}/tests/wsdl_cache/vcards.xml +0 -0
@@ -1,5 +1,46 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.3.11
4
+
5
+ **Added:**
6
+
7
+ - `direct campaigns add` and `direct campaigns update` now expose
8
+ `--tracking-params` for the campaign-level tracking query string
9
+ (`TextCampaign` / `DynamicTextCampaign` / `SmartCampaign` `.TrackingParams`).
10
+ `campaigns update` gained an optional `--type` discriminator —
11
+ required when `--tracking-params` is set, validated against
12
+ the three subtypes supported by the CLI. Backward compatible:
13
+ existing `campaigns update --id N --name X` calls without `--type`
14
+ keep working unchanged. Closes #230.
15
+ - `direct v4account account-management` now supports `--action Get`,
16
+ `Deposit`, `Invoice`, and `TransferMoney` in addition to `Update`,
17
+ matching the official v4 Live docs
18
+ (<https://yandex.ru/dev/direct/doc/dg-v4/reference/AccountManagement-docpage/>).
19
+ `Get` is read-only and accepts optional `--logins` / `--account-ids`
20
+ filters. `Deposit`, `Invoice`, and `TransferMoney` are financial
21
+ mutations: they need `--finance-token` (or `--master-token` +
22
+ `--operation-num` + `--finance-login`) and respect the existing
23
+ dry-run-unless-sandbox rule. A Click-side allow-list rejects flags
24
+ that do not belong to the chosen action before any body is built.
25
+ Refs #125.
26
+
27
+ **Fixed:**
28
+
29
+ - `direct v4 *` command wrappers now let `click.ClickException`
30
+ (including `UsageError` from `call_v4` shape validation) propagate to
31
+ Click instead of swallowing it in the generic `except Exception`.
32
+ Shape-validation errors keep their usage hint and exit with code 2,
33
+ matching Click's contract; non-Click runtime errors still surface
34
+ through `print_error` + `Abort` (exit 1). Closes #227.
35
+
36
+ **Breaking changes:**
37
+
38
+ - `direct v4finance get-credit-limits` no longer accepts `--logins`; the
39
+ request body now omits `param` per the official v4 Live docs
40
+ (<https://yandex.ru/dev/direct/doc/dg-v4/reference/GetCreditLimits.html>),
41
+ which define the body as `method`, `finance_token`, and `operation_num`
42
+ only. Refs #125.
43
+
3
44
  ## 0.3.10
4
45
 
5
46
  **Added:**
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: direct-cli
3
- Version: 0.3.10
3
+ Version: 0.3.11
4
4
  Summary: Command-line interface for Yandex Direct API
5
5
  Author: axisrow
6
6
  License: MIT
@@ -228,8 +228,7 @@ is omitted. Dry-run output masks the financial token.
228
228
 
229
229
  ```bash
230
230
  direct v4finance get-clients-units --logins client-login,other-client --format table
231
- direct v4finance get-credit-limits --logins client-login --master-token MASTER_TOKEN --operation-num 123 --finance-login agency-login
232
- direct v4finance get-credit-limits --logins client-login,other-client --format table
231
+ direct v4finance get-credit-limits --master-token MASTER_TOKEN --operation-num 123 --finance-login agency-login
233
232
  direct v4finance create-invoice --payment 123=100.50 --payment 456=25 --currency RUB --master-token MASTER_TOKEN --operation-num 124 --finance-login agency-login --dry-run
234
233
  direct v4finance check-payment --custom-transaction-id A123456789012345678901234567890B
235
234
  direct v4finance transfer-money --from-campaign-id 123 --to-campaign-id 456 --amount 100.50 --currency RUB --master-token MASTER_TOKEN --operation-num 123 --finance-login agency-login --dry-run
@@ -238,14 +237,27 @@ direct v4finance pay-campaigns --campaign-ids 123,456 --amount 100.50 --currency
238
237
 
239
238
  ### V4 Live Shared Account
240
239
 
241
- Shared-account mutations require `--dry-run` in production and can be sent live
242
- only with top-level `--sandbox`. These commands follow the official v4 Live
243
- shared-account method shapes: `EnableSharedAccount` accepts one client `Login`,
244
- and `AccountManagement` updates shared-account settings through `Accounts`.
240
+ `EnableSharedAccount` accepts one client `Login` (agencies only).
241
+ `AccountManagement` exposes the five official v4 Live actions:
242
+ `Get`, `Update`, `Deposit`, `Invoice`, and `TransferMoney`. `Get` is
243
+ read-only and runs against production without `--dry-run`. `Update`,
244
+ `Deposit`, `Invoice`, and `TransferMoney` are mutations: they require
245
+ `--dry-run` in production and can be sent live only with top-level
246
+ `--sandbox`. `Deposit`, `Invoice`, and `TransferMoney` are financial
247
+ operations that need `--finance-token` (or `--master-token` +
248
+ `--operation-num` + `--finance-login`); dry-run output masks the
249
+ financial token.
245
250
 
246
251
  ```bash
247
252
  direct v4account enable-shared-account --client-login client-login --dry-run
253
+ direct v4account account-management --action Get
254
+ direct v4account account-management --action Get --logins client-a,client-b
255
+ direct v4account account-management --action Get --account-ids 1327944,1327945
248
256
  direct v4account account-management --action Update --account-id 1327944 --day-budget 100.50 --spend-mode Default --money-in-sms Yes --money-out-sms No --email ops@example.com --money-warning-value 25 --dry-run
257
+ direct v4account account-management --action Deposit --payment 1327944=100.50 --currency RUB --master-token MASTER_TOKEN --operation-num 124 --finance-login agency-login --dry-run
258
+ direct v4account account-management --action Deposit --payment 1327944=100.50 --currency RUB --origin Overdraft --contract CONTRACT_ID --master-token MASTER_TOKEN --operation-num 125 --finance-login agency-login --dry-run
259
+ direct v4account account-management --action Invoice --payment 1327944=100.50 --currency RUB --master-token MASTER_TOKEN --operation-num 126 --finance-login agency-login --dry-run
260
+ direct v4account account-management --action TransferMoney --from-account-id 1327944 --to-account-id 1327945 --amount 50.00 --currency RUB --master-token MASTER_TOKEN --operation-num 127 --finance-login agency-login --dry-run
249
261
  direct --sandbox v4account enable-shared-account --client-login client-login
250
262
  ```
251
263
 
@@ -393,8 +405,12 @@ direct campaigns add --name "Multi-Goal CPA" --start-date 2026-06-01 --type TEXT
393
405
  # Notification (Sms/Email) and TimeTargeting accept JSON with WSDL CamelCase keys
394
406
  direct campaigns add --name "Notify+Schedule" --start-date 2026-06-01 --type TEXT_CAMPAIGN --search-strategy HIGHEST_POSITION --network-strategy SERVING_OFF --notification '{"EmailSettings":{"Email":"ops@example.com","SendWarnings":"YES"}}' --time-targeting '{"Schedule":["1A0123456789ABCDEFGHIJKL"],"ConsiderWorkingWeekends":"YES"}' --dry-run
395
407
 
408
+ # TrackingParams (campaign-level UTM / tracking query string)
409
+ direct campaigns add --name "UTM" --start-date 2026-06-01 --type TEXT_CAMPAIGN --tracking-params "utm_source=direct&utm_campaign={campaign_id}" --dry-run
410
+
396
411
  # Update / lifecycle
397
412
  direct campaigns update --id 12345 --name "New Name" --status SUSPENDED --budget 100000000 --start-date 2024-02-10 --end-date 2024-03-01
413
+ direct campaigns update --id 12345 --type TEXT_CAMPAIGN --tracking-params "utm_source=direct&utm_medium=cpc" --dry-run
398
414
  direct campaigns suspend --id 12345
399
415
  direct campaigns resume --id 12345
400
416
  direct campaigns archive --id 12345
@@ -1083,8 +1099,12 @@ direct campaigns add --name "Мульти-целевой CPA" --start-date 2026-
1083
1099
  # Notification (Sms/Email) и TimeTargeting принимают JSON с CamelCase ключами WSDL
1084
1100
  direct campaigns add --name "Уведомления+Расписание" --start-date 2026-06-01 --type TEXT_CAMPAIGN --search-strategy HIGHEST_POSITION --network-strategy SERVING_OFF --notification '{"EmailSettings":{"Email":"ops@example.com","SendWarnings":"YES"}}' --time-targeting '{"Schedule":["1A0123456789ABCDEFGHIJKL"],"ConsiderWorkingWeekends":"YES"}' --dry-run
1085
1101
 
1102
+ # TrackingParams — UTM/трекинг на уровне кампании (TextCampaign/DynamicTextCampaign/SmartCampaign.TrackingParams)
1103
+ direct campaigns add --name "UTM" --start-date 2026-06-01 --type TEXT_CAMPAIGN --tracking-params "utm_source=direct&utm_campaign={campaign_id}" --dry-run
1104
+
1086
1105
  # Обновление и управление статусом
1087
1106
  direct campaigns update --id 12345 --name "Новое название" --status SUSPENDED --budget 100000000 --start-date 2024-02-10 --end-date 2024-03-01
1107
+ direct campaigns update --id 12345 --type TEXT_CAMPAIGN --tracking-params "utm_source=direct&utm_medium=cpc" --dry-run
1088
1108
  direct campaigns suspend --id 12345
1089
1109
  direct campaigns resume --id 12345
1090
1110
  direct campaigns archive --id 12345
@@ -185,8 +185,7 @@ is omitted. Dry-run output masks the financial token.
185
185
 
186
186
  ```bash
187
187
  direct v4finance get-clients-units --logins client-login,other-client --format table
188
- direct v4finance get-credit-limits --logins client-login --master-token MASTER_TOKEN --operation-num 123 --finance-login agency-login
189
- direct v4finance get-credit-limits --logins client-login,other-client --format table
188
+ direct v4finance get-credit-limits --master-token MASTER_TOKEN --operation-num 123 --finance-login agency-login
190
189
  direct v4finance create-invoice --payment 123=100.50 --payment 456=25 --currency RUB --master-token MASTER_TOKEN --operation-num 124 --finance-login agency-login --dry-run
191
190
  direct v4finance check-payment --custom-transaction-id A123456789012345678901234567890B
192
191
  direct v4finance transfer-money --from-campaign-id 123 --to-campaign-id 456 --amount 100.50 --currency RUB --master-token MASTER_TOKEN --operation-num 123 --finance-login agency-login --dry-run
@@ -195,14 +194,27 @@ direct v4finance pay-campaigns --campaign-ids 123,456 --amount 100.50 --currency
195
194
 
196
195
  ### V4 Live Shared Account
197
196
 
198
- Shared-account mutations require `--dry-run` in production and can be sent live
199
- only with top-level `--sandbox`. These commands follow the official v4 Live
200
- shared-account method shapes: `EnableSharedAccount` accepts one client `Login`,
201
- and `AccountManagement` updates shared-account settings through `Accounts`.
197
+ `EnableSharedAccount` accepts one client `Login` (agencies only).
198
+ `AccountManagement` exposes the five official v4 Live actions:
199
+ `Get`, `Update`, `Deposit`, `Invoice`, and `TransferMoney`. `Get` is
200
+ read-only and runs against production without `--dry-run`. `Update`,
201
+ `Deposit`, `Invoice`, and `TransferMoney` are mutations: they require
202
+ `--dry-run` in production and can be sent live only with top-level
203
+ `--sandbox`. `Deposit`, `Invoice`, and `TransferMoney` are financial
204
+ operations that need `--finance-token` (or `--master-token` +
205
+ `--operation-num` + `--finance-login`); dry-run output masks the
206
+ financial token.
202
207
 
203
208
  ```bash
204
209
  direct v4account enable-shared-account --client-login client-login --dry-run
210
+ direct v4account account-management --action Get
211
+ direct v4account account-management --action Get --logins client-a,client-b
212
+ direct v4account account-management --action Get --account-ids 1327944,1327945
205
213
  direct v4account account-management --action Update --account-id 1327944 --day-budget 100.50 --spend-mode Default --money-in-sms Yes --money-out-sms No --email ops@example.com --money-warning-value 25 --dry-run
214
+ direct v4account account-management --action Deposit --payment 1327944=100.50 --currency RUB --master-token MASTER_TOKEN --operation-num 124 --finance-login agency-login --dry-run
215
+ direct v4account account-management --action Deposit --payment 1327944=100.50 --currency RUB --origin Overdraft --contract CONTRACT_ID --master-token MASTER_TOKEN --operation-num 125 --finance-login agency-login --dry-run
216
+ direct v4account account-management --action Invoice --payment 1327944=100.50 --currency RUB --master-token MASTER_TOKEN --operation-num 126 --finance-login agency-login --dry-run
217
+ direct v4account account-management --action TransferMoney --from-account-id 1327944 --to-account-id 1327945 --amount 50.00 --currency RUB --master-token MASTER_TOKEN --operation-num 127 --finance-login agency-login --dry-run
206
218
  direct --sandbox v4account enable-shared-account --client-login client-login
207
219
  ```
208
220
 
@@ -350,8 +362,12 @@ direct campaigns add --name "Multi-Goal CPA" --start-date 2026-06-01 --type TEXT
350
362
  # Notification (Sms/Email) and TimeTargeting accept JSON with WSDL CamelCase keys
351
363
  direct campaigns add --name "Notify+Schedule" --start-date 2026-06-01 --type TEXT_CAMPAIGN --search-strategy HIGHEST_POSITION --network-strategy SERVING_OFF --notification '{"EmailSettings":{"Email":"ops@example.com","SendWarnings":"YES"}}' --time-targeting '{"Schedule":["1A0123456789ABCDEFGHIJKL"],"ConsiderWorkingWeekends":"YES"}' --dry-run
352
364
 
365
+ # TrackingParams (campaign-level UTM / tracking query string)
366
+ direct campaigns add --name "UTM" --start-date 2026-06-01 --type TEXT_CAMPAIGN --tracking-params "utm_source=direct&utm_campaign={campaign_id}" --dry-run
367
+
353
368
  # Update / lifecycle
354
369
  direct campaigns update --id 12345 --name "New Name" --status SUSPENDED --budget 100000000 --start-date 2024-02-10 --end-date 2024-03-01
370
+ direct campaigns update --id 12345 --type TEXT_CAMPAIGN --tracking-params "utm_source=direct&utm_medium=cpc" --dry-run
355
371
  direct campaigns suspend --id 12345
356
372
  direct campaigns resume --id 12345
357
373
  direct campaigns archive --id 12345
@@ -1040,8 +1056,12 @@ direct campaigns add --name "Мульти-целевой CPA" --start-date 2026-
1040
1056
  # Notification (Sms/Email) и TimeTargeting принимают JSON с CamelCase ключами WSDL
1041
1057
  direct campaigns add --name "Уведомления+Расписание" --start-date 2026-06-01 --type TEXT_CAMPAIGN --search-strategy HIGHEST_POSITION --network-strategy SERVING_OFF --notification '{"EmailSettings":{"Email":"ops@example.com","SendWarnings":"YES"}}' --time-targeting '{"Schedule":["1A0123456789ABCDEFGHIJKL"],"ConsiderWorkingWeekends":"YES"}' --dry-run
1042
1058
 
1059
+ # TrackingParams — UTM/трекинг на уровне кампании (TextCampaign/DynamicTextCampaign/SmartCampaign.TrackingParams)
1060
+ direct campaigns add --name "UTM" --start-date 2026-06-01 --type TEXT_CAMPAIGN --tracking-params "utm_source=direct&utm_campaign={campaign_id}" --dry-run
1061
+
1043
1062
  # Обновление и управление статусом
1044
1063
  direct campaigns update --id 12345 --name "Новое название" --status SUSPENDED --budget 100000000 --start-date 2024-02-10 --end-date 2024-03-01
1064
+ direct campaigns update --id 12345 --type TEXT_CAMPAIGN --tracking-params "utm_source=direct&utm_medium=cpc" --dry-run
1045
1065
  direct campaigns suspend --id 12345
1046
1066
  direct campaigns resume --id 12345
1047
1067
  direct campaigns archive --id 12345
@@ -601,6 +601,15 @@ def get(
601
601
  '({"Schedule":[...], "ConsiderWorkingWeekends":"YES|NO", ...})'
602
602
  ),
603
603
  )
604
+ @click.option(
605
+ "--tracking-params",
606
+ "tracking_params",
607
+ help=(
608
+ "Tracking params query-string for "
609
+ "TextCampaign/DynamicTextCampaign/SmartCampaign.TrackingParams "
610
+ '(e.g. "utm_source=direct&utm_campaign={campaign_id}")'
611
+ ),
612
+ )
604
613
  @click.option("--dry-run", is_flag=True, help="Show request without sending")
605
614
  @click.pass_context
606
615
  def add(
@@ -623,6 +632,7 @@ def add(
623
632
  bid_ceiling,
624
633
  notification_json,
625
634
  time_targeting_json,
635
+ tracking_params,
626
636
  dry_run,
627
637
  ):
628
638
  """Add new campaign"""
@@ -664,12 +674,14 @@ def add(
664
674
  "--setting",
665
675
  "--search-strategy",
666
676
  "--network-strategy",
677
+ "--tracking-params",
667
678
  }
668
679
  | text_dynamic_extras,
669
680
  "DYNAMIC_TEXT_CAMPAIGN": {
670
681
  "--setting",
671
682
  "--search-strategy",
672
683
  "--network-strategy",
684
+ "--tracking-params",
673
685
  }
674
686
  | text_dynamic_extras,
675
687
  "SMART_CAMPAIGN": {
@@ -678,6 +690,7 @@ def add(
678
690
  "--network-strategy",
679
691
  "--filter-average-cpc",
680
692
  "--counter-id",
693
+ "--tracking-params",
681
694
  },
682
695
  }
683
696
  _reject_incompatible_flags(
@@ -695,6 +708,7 @@ def add(
695
708
  "--average-cpa": average_cpa,
696
709
  "--crr": crr,
697
710
  "--bid-ceiling": bid_ceiling,
711
+ "--tracking-params": tracking_params,
698
712
  },
699
713
  )
700
714
 
@@ -753,6 +767,8 @@ def add(
753
767
  priority_goals_items=priority_goals_items,
754
768
  sub_campaign_block=text_block,
755
769
  )
770
+ if tracking_params:
771
+ text_block["TrackingParams"] = tracking_params
756
772
  campaign_data["TextCampaign"] = text_block
757
773
  elif campaign_type_norm == "DYNAMIC_TEXT_CAMPAIGN":
758
774
  dyn_block = {
@@ -779,6 +795,8 @@ def add(
779
795
  priority_goals_items=priority_goals_items,
780
796
  sub_campaign_block=dyn_block,
781
797
  )
798
+ if tracking_params:
799
+ dyn_block["TrackingParams"] = tracking_params
782
800
  campaign_data["DynamicTextCampaign"] = dyn_block
783
801
  elif campaign_type_norm == "SMART_CAMPAIGN":
784
802
  # WSDL SmartCampaignAddItem.CounterId is minOccurs=1
@@ -815,6 +833,8 @@ def add(
815
833
  }
816
834
  if parsed_settings:
817
835
  smart_campaign["Settings"] = parsed_settings
836
+ if tracking_params:
837
+ smart_campaign["TrackingParams"] = tracking_params
818
838
  campaign_data["SmartCampaign"] = smart_campaign
819
839
 
820
840
  if budget:
@@ -863,9 +883,37 @@ def add(
863
883
  @click.option("--budget", type=MICRO_RUBLES, help="New daily budget in micro-rubles")
864
884
  @click.option("--start-date", help="New start date (YYYY-MM-DD)")
865
885
  @click.option("--end-date", help="New end date (YYYY-MM-DD)")
886
+ @click.option(
887
+ "--type",
888
+ "campaign_type",
889
+ help=(
890
+ "Campaign subtype "
891
+ "(TEXT_CAMPAIGN | DYNAMIC_TEXT_CAMPAIGN | SMART_CAMPAIGN). "
892
+ "Required when updating subtype-specific fields."
893
+ ),
894
+ )
895
+ @click.option(
896
+ "--tracking-params",
897
+ "tracking_params",
898
+ help=(
899
+ "Tracking params query-string for "
900
+ "TextCampaign/DynamicTextCampaign/SmartCampaign.TrackingParams"
901
+ ),
902
+ )
866
903
  @click.option("--dry-run", is_flag=True, help="Show request without sending")
867
904
  @click.pass_context
868
- def update(ctx, campaign_id, name, status, budget, start_date, end_date, dry_run):
905
+ def update(
906
+ ctx,
907
+ campaign_id,
908
+ name,
909
+ status,
910
+ budget,
911
+ start_date,
912
+ end_date,
913
+ campaign_type,
914
+ tracking_params,
915
+ dry_run,
916
+ ):
869
917
  """Update campaign"""
870
918
  try:
871
919
  campaign_data = {"Id": campaign_id}
@@ -886,6 +934,60 @@ def update(ctx, campaign_id, name, status, budget, start_date, end_date, dry_run
886
934
  if end_date:
887
935
  campaign_data["EndDate"] = end_date
888
936
 
937
+ subtype_supported = {
938
+ "TEXT_CAMPAIGN",
939
+ "DYNAMIC_TEXT_CAMPAIGN",
940
+ "SMART_CAMPAIGN",
941
+ }
942
+ campaign_type_norm = (
943
+ campaign_type.upper().replace("-", "_") if campaign_type else None
944
+ )
945
+ subtype_flag_values = {
946
+ "--tracking-params": tracking_params,
947
+ }
948
+ subtype_flags_provided = [
949
+ flag for flag, value in subtype_flag_values.items() if value is not None
950
+ ]
951
+ if (
952
+ campaign_type_norm is not None
953
+ and campaign_type_norm not in subtype_supported
954
+ ):
955
+ raise click.UsageError(
956
+ "Invalid value for '--type': "
957
+ f"{campaign_type!r} is not one of "
958
+ "'TEXT_CAMPAIGN', 'DYNAMIC_TEXT_CAMPAIGN', 'SMART_CAMPAIGN'."
959
+ )
960
+ if subtype_flags_provided and campaign_type_norm is None:
961
+ raise click.UsageError(
962
+ f"{', '.join(sorted(subtype_flags_provided))} requires --type "
963
+ "(TEXT_CAMPAIGN | DYNAMIC_TEXT_CAMPAIGN | SMART_CAMPAIGN)."
964
+ )
965
+ if campaign_type_norm is not None:
966
+ allowed_subtype_flags_by_type = {
967
+ "TEXT_CAMPAIGN": {"--tracking-params"},
968
+ "DYNAMIC_TEXT_CAMPAIGN": {"--tracking-params"},
969
+ "SMART_CAMPAIGN": {"--tracking-params"},
970
+ }
971
+ _reject_incompatible_flags(
972
+ campaign_type_norm,
973
+ allowed_subtype_flags_by_type[campaign_type_norm],
974
+ subtype_flag_values,
975
+ )
976
+ sub_block: Dict[str, object] = {}
977
+ if tracking_params:
978
+ sub_block["TrackingParams"] = tracking_params
979
+ if not sub_block:
980
+ raise click.UsageError(
981
+ f"--type {campaign_type_norm} requires at least one "
982
+ "subtype-specific field to update."
983
+ )
984
+ subtype_container = {
985
+ "TEXT_CAMPAIGN": "TextCampaign",
986
+ "DYNAMIC_TEXT_CAMPAIGN": "DynamicTextCampaign",
987
+ "SMART_CAMPAIGN": "SmartCampaign",
988
+ }[campaign_type_norm]
989
+ campaign_data[subtype_container] = sub_block
990
+
889
991
  if len(campaign_data) == 1:
890
992
  raise click.UsageError("Provide at least one field to update")
891
993