cumulusci-plus 5.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of cumulusci-plus might be problematic. Click here for more details.

Files changed (744) hide show
  1. cumulusci/__about__.py +1 -0
  2. cumulusci/__init__.py +22 -0
  3. cumulusci/__main__.py +3 -0
  4. cumulusci/cli/__init__.py +0 -0
  5. cumulusci/cli/cci.py +244 -0
  6. cumulusci/cli/error.py +125 -0
  7. cumulusci/cli/flow.py +185 -0
  8. cumulusci/cli/logger.py +72 -0
  9. cumulusci/cli/org.py +692 -0
  10. cumulusci/cli/plan.py +181 -0
  11. cumulusci/cli/project.py +391 -0
  12. cumulusci/cli/robot.py +116 -0
  13. cumulusci/cli/runtime.py +190 -0
  14. cumulusci/cli/service.py +521 -0
  15. cumulusci/cli/task.py +295 -0
  16. cumulusci/cli/tests/__init__.py +0 -0
  17. cumulusci/cli/tests/test_cci.py +545 -0
  18. cumulusci/cli/tests/test_error.py +170 -0
  19. cumulusci/cli/tests/test_flow.py +276 -0
  20. cumulusci/cli/tests/test_logger.py +25 -0
  21. cumulusci/cli/tests/test_org.py +1438 -0
  22. cumulusci/cli/tests/test_plan.py +245 -0
  23. cumulusci/cli/tests/test_project.py +235 -0
  24. cumulusci/cli/tests/test_robot.py +177 -0
  25. cumulusci/cli/tests/test_runtime.py +197 -0
  26. cumulusci/cli/tests/test_service.py +853 -0
  27. cumulusci/cli/tests/test_task.py +266 -0
  28. cumulusci/cli/tests/test_ui.py +310 -0
  29. cumulusci/cli/tests/test_utils.py +122 -0
  30. cumulusci/cli/tests/utils.py +52 -0
  31. cumulusci/cli/ui.py +234 -0
  32. cumulusci/cli/utils.py +150 -0
  33. cumulusci/conftest.py +181 -0
  34. cumulusci/core/__init__.py +0 -0
  35. cumulusci/core/config/BaseConfig.py +5 -0
  36. cumulusci/core/config/BaseTaskFlowConfig.py +5 -0
  37. cumulusci/core/config/OrgConfig.py +5 -0
  38. cumulusci/core/config/ScratchOrgConfig.py +5 -0
  39. cumulusci/core/config/__init__.py +125 -0
  40. cumulusci/core/config/base_config.py +111 -0
  41. cumulusci/core/config/base_task_flow_config.py +82 -0
  42. cumulusci/core/config/marketing_cloud_service_config.py +83 -0
  43. cumulusci/core/config/oauth2_service_config.py +17 -0
  44. cumulusci/core/config/org_config.py +604 -0
  45. cumulusci/core/config/project_config.py +782 -0
  46. cumulusci/core/config/scratch_org_config.py +251 -0
  47. cumulusci/core/config/sfdx_org_config.py +220 -0
  48. cumulusci/core/config/tests/_test_config_backwards_compatibility.py +33 -0
  49. cumulusci/core/config/tests/test_config.py +1895 -0
  50. cumulusci/core/config/tests/test_config_expensive.py +839 -0
  51. cumulusci/core/config/tests/test_config_util.py +91 -0
  52. cumulusci/core/config/universal_config.py +88 -0
  53. cumulusci/core/config/util.py +18 -0
  54. cumulusci/core/datasets.py +303 -0
  55. cumulusci/core/debug.py +33 -0
  56. cumulusci/core/dependencies/__init__.py +55 -0
  57. cumulusci/core/dependencies/base.py +561 -0
  58. cumulusci/core/dependencies/dependencies.py +273 -0
  59. cumulusci/core/dependencies/github.py +177 -0
  60. cumulusci/core/dependencies/github_resolvers.py +244 -0
  61. cumulusci/core/dependencies/resolvers.py +580 -0
  62. cumulusci/core/dependencies/tests/__init__.py +0 -0
  63. cumulusci/core/dependencies/tests/conftest.py +385 -0
  64. cumulusci/core/dependencies/tests/test_dependencies.py +950 -0
  65. cumulusci/core/dependencies/tests/test_github.py +83 -0
  66. cumulusci/core/dependencies/tests/test_resolvers.py +1027 -0
  67. cumulusci/core/dependencies/utils.py +13 -0
  68. cumulusci/core/enums.py +11 -0
  69. cumulusci/core/exceptions.py +311 -0
  70. cumulusci/core/flowrunner.py +888 -0
  71. cumulusci/core/github.py +665 -0
  72. cumulusci/core/keychain/__init__.py +24 -0
  73. cumulusci/core/keychain/base_project_keychain.py +441 -0
  74. cumulusci/core/keychain/encrypted_file_project_keychain.py +945 -0
  75. cumulusci/core/keychain/environment_project_keychain.py +7 -0
  76. cumulusci/core/keychain/serialization.py +152 -0
  77. cumulusci/core/keychain/subprocess_keychain.py +24 -0
  78. cumulusci/core/keychain/tests/conftest.py +50 -0
  79. cumulusci/core/keychain/tests/test_base_project_keychain.py +299 -0
  80. cumulusci/core/keychain/tests/test_encrypted_file_project_keychain.py +1228 -0
  81. cumulusci/core/metadeploy/__init__.py +0 -0
  82. cumulusci/core/metadeploy/api.py +88 -0
  83. cumulusci/core/metadeploy/plans.py +25 -0
  84. cumulusci/core/metadeploy/tests/test_api.py +276 -0
  85. cumulusci/core/runtime.py +115 -0
  86. cumulusci/core/sfdx.py +162 -0
  87. cumulusci/core/source/__init__.py +16 -0
  88. cumulusci/core/source/github.py +50 -0
  89. cumulusci/core/source/local_folder.py +35 -0
  90. cumulusci/core/source_transforms/__init__.py +0 -0
  91. cumulusci/core/source_transforms/tests/test_transforms.py +1091 -0
  92. cumulusci/core/source_transforms/transforms.py +532 -0
  93. cumulusci/core/tasks.py +404 -0
  94. cumulusci/core/template_utils.py +59 -0
  95. cumulusci/core/tests/__init__.py +0 -0
  96. cumulusci/core/tests/cassettes/TestDatasetsE2E.test_datasets_e2e.yaml +215 -0
  97. cumulusci/core/tests/cassettes/TestDatasetsE2E.test_datasets_extract_standard_objects.yaml +199 -0
  98. cumulusci/core/tests/cassettes/TestDatasetsE2E.test_datasets_read_explicit_extract_declaration.yaml +3 -0
  99. cumulusci/core/tests/fake_remote_repo/cumulusci.yml +32 -0
  100. cumulusci/core/tests/fake_remote_repo/tasks/directory/example_2.py +6 -0
  101. cumulusci/core/tests/fake_remote_repo/tasks/example.py +43 -0
  102. cumulusci/core/tests/fake_remote_repo_2/cumulusci.yml +11 -0
  103. cumulusci/core/tests/fake_remote_repo_2/tasks/example_3.py +6 -0
  104. cumulusci/core/tests/test_datasets_e2e.py +386 -0
  105. cumulusci/core/tests/test_exceptions.py +11 -0
  106. cumulusci/core/tests/test_flowrunner.py +836 -0
  107. cumulusci/core/tests/test_github.py +942 -0
  108. cumulusci/core/tests/test_sfdx.py +138 -0
  109. cumulusci/core/tests/test_source.py +678 -0
  110. cumulusci/core/tests/test_tasks.py +262 -0
  111. cumulusci/core/tests/test_utils.py +141 -0
  112. cumulusci/core/tests/test_utils_merge_config.py +276 -0
  113. cumulusci/core/tests/test_versions.py +76 -0
  114. cumulusci/core/tests/untrusted_repo_child/cumulusci.yml +7 -0
  115. cumulusci/core/tests/untrusted_repo_child/tasks/untrusted_child.py +6 -0
  116. cumulusci/core/tests/untrusted_repo_parent/cumulusci.yml +26 -0
  117. cumulusci/core/tests/untrusted_repo_parent/tasks/untrusted_parent.py +6 -0
  118. cumulusci/core/tests/utils.py +116 -0
  119. cumulusci/core/tests/yaml/global.yaml +0 -0
  120. cumulusci/core/utils.py +402 -0
  121. cumulusci/core/versions.py +149 -0
  122. cumulusci/cumulusci.yml +1621 -0
  123. cumulusci/files/admin_profile.xml +20 -0
  124. cumulusci/files/delete_excludes.txt +424 -0
  125. cumulusci/files/templates/project/README.md +12 -0
  126. cumulusci/files/templates/project/cumulusci.yml +63 -0
  127. cumulusci/files/templates/project/dot-gitignore +60 -0
  128. cumulusci/files/templates/project/mapping.yml +45 -0
  129. cumulusci/files/templates/project/scratch_def.json +25 -0
  130. cumulusci/oauth/__init__.py +0 -0
  131. cumulusci/oauth/client.py +400 -0
  132. cumulusci/oauth/exceptions.py +9 -0
  133. cumulusci/oauth/salesforce.py +95 -0
  134. cumulusci/oauth/tests/__init__.py +0 -0
  135. cumulusci/oauth/tests/cassettes/test_get_device_code.yaml +22 -0
  136. cumulusci/oauth/tests/cassettes/test_get_device_oauth_token.yaml +74 -0
  137. cumulusci/oauth/tests/test_client.py +308 -0
  138. cumulusci/oauth/tests/test_salesforce.py +46 -0
  139. cumulusci/plugins/__init__.py +3 -0
  140. cumulusci/plugins/plugin_base.py +93 -0
  141. cumulusci/plugins/plugin_loader.py +59 -0
  142. cumulusci/robotframework/CumulusCI.py +340 -0
  143. cumulusci/robotframework/CumulusCI.robot +7 -0
  144. cumulusci/robotframework/Performance.py +165 -0
  145. cumulusci/robotframework/Salesforce.py +936 -0
  146. cumulusci/robotframework/Salesforce.robot +192 -0
  147. cumulusci/robotframework/SalesforceAPI.py +416 -0
  148. cumulusci/robotframework/SalesforcePlaywright.py +220 -0
  149. cumulusci/robotframework/SalesforcePlaywright.robot +40 -0
  150. cumulusci/robotframework/__init__.py +2 -0
  151. cumulusci/robotframework/base_library.py +39 -0
  152. cumulusci/robotframework/faker_mixin.py +89 -0
  153. cumulusci/robotframework/form_handlers.py +222 -0
  154. cumulusci/robotframework/javascript/cci_init.js +34 -0
  155. cumulusci/robotframework/javascript/cumulusci.js +4 -0
  156. cumulusci/robotframework/locator_manager.py +197 -0
  157. cumulusci/robotframework/locators_56.py +88 -0
  158. cumulusci/robotframework/locators_57.py +5 -0
  159. cumulusci/robotframework/pageobjects/BasePageObjects.py +433 -0
  160. cumulusci/robotframework/pageobjects/ObjectManagerPageObject.py +246 -0
  161. cumulusci/robotframework/pageobjects/PageObjectLibrary.py +45 -0
  162. cumulusci/robotframework/pageobjects/PageObjects.py +351 -0
  163. cumulusci/robotframework/pageobjects/__init__.py +12 -0
  164. cumulusci/robotframework/pageobjects/baseobjects.py +120 -0
  165. cumulusci/robotframework/perftests/short/collection_perf.robot +105 -0
  166. cumulusci/robotframework/tests/CustomObjectTestPage.py +10 -0
  167. cumulusci/robotframework/tests/FooTestPage.py +8 -0
  168. cumulusci/robotframework/tests/cumulusci/base.robot +40 -0
  169. cumulusci/robotframework/tests/cumulusci/bulkdata.robot +38 -0
  170. cumulusci/robotframework/tests/cumulusci/communities.robot +57 -0
  171. cumulusci/robotframework/tests/cumulusci/datagen.robot +84 -0
  172. cumulusci/robotframework/tests/salesforce/TestLibraryA.py +24 -0
  173. cumulusci/robotframework/tests/salesforce/TestLibraryB.py +20 -0
  174. cumulusci/robotframework/tests/salesforce/TestListener.py +93 -0
  175. cumulusci/robotframework/tests/salesforce/api.robot +178 -0
  176. cumulusci/robotframework/tests/salesforce/browsers.robot +143 -0
  177. cumulusci/robotframework/tests/salesforce/classic.robot +51 -0
  178. cumulusci/robotframework/tests/salesforce/create_contact.robot +59 -0
  179. cumulusci/robotframework/tests/salesforce/faker.robot +68 -0
  180. cumulusci/robotframework/tests/salesforce/forms.robot +172 -0
  181. cumulusci/robotframework/tests/salesforce/label_locator.robot +244 -0
  182. cumulusci/robotframework/tests/salesforce/labels.html +33 -0
  183. cumulusci/robotframework/tests/salesforce/locators.robot +149 -0
  184. cumulusci/robotframework/tests/salesforce/pageobjects/base_pageobjects.robot +100 -0
  185. cumulusci/robotframework/tests/salesforce/pageobjects/example_page_object.py +25 -0
  186. cumulusci/robotframework/tests/salesforce/pageobjects/listing_page.robot +115 -0
  187. cumulusci/robotframework/tests/salesforce/pageobjects/objectmanager.robot +74 -0
  188. cumulusci/robotframework/tests/salesforce/pageobjects/pageobjects.robot +171 -0
  189. cumulusci/robotframework/tests/salesforce/performance.robot +109 -0
  190. cumulusci/robotframework/tests/salesforce/playwright/javascript_keywords.robot +33 -0
  191. cumulusci/robotframework/tests/salesforce/playwright/open_test_browser.robot +48 -0
  192. cumulusci/robotframework/tests/salesforce/playwright/playwright.robot +24 -0
  193. cumulusci/robotframework/tests/salesforce/playwright/ui.robot +32 -0
  194. cumulusci/robotframework/tests/salesforce/populate.robot +89 -0
  195. cumulusci/robotframework/tests/salesforce/test_testlistener.py +37 -0
  196. cumulusci/robotframework/tests/salesforce/ui.robot +361 -0
  197. cumulusci/robotframework/tests/test_cumulusci_library.py +304 -0
  198. cumulusci/robotframework/tests/test_locator_manager.py +158 -0
  199. cumulusci/robotframework/tests/test_pageobjects.py +291 -0
  200. cumulusci/robotframework/tests/test_performance.py +38 -0
  201. cumulusci/robotframework/tests/test_salesforce.py +79 -0
  202. cumulusci/robotframework/tests/test_salesforce_locators.py +73 -0
  203. cumulusci/robotframework/tests/test_template_util.py +53 -0
  204. cumulusci/robotframework/tests/test_utils.py +106 -0
  205. cumulusci/robotframework/utils.py +283 -0
  206. cumulusci/salesforce_api/__init__.py +0 -0
  207. cumulusci/salesforce_api/exceptions.py +23 -0
  208. cumulusci/salesforce_api/filterable_objects.py +96 -0
  209. cumulusci/salesforce_api/mc_soap_envelopes.py +89 -0
  210. cumulusci/salesforce_api/metadata.py +721 -0
  211. cumulusci/salesforce_api/org_schema.py +571 -0
  212. cumulusci/salesforce_api/org_schema_models.py +226 -0
  213. cumulusci/salesforce_api/package_install.py +265 -0
  214. cumulusci/salesforce_api/package_zip.py +301 -0
  215. cumulusci/salesforce_api/rest_deploy.py +148 -0
  216. cumulusci/salesforce_api/retrieve_profile_api.py +301 -0
  217. cumulusci/salesforce_api/soap_envelopes.py +177 -0
  218. cumulusci/salesforce_api/tests/__init__.py +0 -0
  219. cumulusci/salesforce_api/tests/metadata_test_strings.py +24 -0
  220. cumulusci/salesforce_api/tests/test_metadata.py +1015 -0
  221. cumulusci/salesforce_api/tests/test_package_install.py +219 -0
  222. cumulusci/salesforce_api/tests/test_package_zip.py +380 -0
  223. cumulusci/salesforce_api/tests/test_rest_deploy.py +264 -0
  224. cumulusci/salesforce_api/tests/test_retrieve_profile_api.py +337 -0
  225. cumulusci/salesforce_api/tests/test_utils.py +124 -0
  226. cumulusci/salesforce_api/utils.py +51 -0
  227. cumulusci/schema/cumulusci.jsonschema.json +782 -0
  228. cumulusci/tasks/__init__.py +0 -0
  229. cumulusci/tasks/apex/__init__.py +0 -0
  230. cumulusci/tasks/apex/anon.py +157 -0
  231. cumulusci/tasks/apex/batch.py +180 -0
  232. cumulusci/tasks/apex/testrunner.py +835 -0
  233. cumulusci/tasks/apex/tests/cassettes/ManualEditTestApexIntegrationTests.test_run_tests__integration_test.yaml +703 -0
  234. cumulusci/tasks/apex/tests/test_apex_tasks.py +1558 -0
  235. cumulusci/tasks/base_source_control_task.py +17 -0
  236. cumulusci/tasks/bulkdata/__init__.py +15 -0
  237. cumulusci/tasks/bulkdata/base_generate_data_task.py +96 -0
  238. cumulusci/tasks/bulkdata/dates.py +97 -0
  239. cumulusci/tasks/bulkdata/delete.py +156 -0
  240. cumulusci/tasks/bulkdata/extract.py +441 -0
  241. cumulusci/tasks/bulkdata/extract_dataset_utils/calculate_dependencies.py +117 -0
  242. cumulusci/tasks/bulkdata/extract_dataset_utils/extract_yml.py +123 -0
  243. cumulusci/tasks/bulkdata/extract_dataset_utils/hardcoded_default_declarations.py +49 -0
  244. cumulusci/tasks/bulkdata/extract_dataset_utils/synthesize_extract_declarations.py +283 -0
  245. cumulusci/tasks/bulkdata/extract_dataset_utils/tests/test_extract_yml.py +142 -0
  246. cumulusci/tasks/bulkdata/extract_dataset_utils/tests/test_synthesize_extract_declarations.py +575 -0
  247. cumulusci/tasks/bulkdata/factory_utils.py +134 -0
  248. cumulusci/tasks/bulkdata/generate.py +4 -0
  249. cumulusci/tasks/bulkdata/generate_and_load_data.py +232 -0
  250. cumulusci/tasks/bulkdata/generate_and_load_data_from_yaml.py +19 -0
  251. cumulusci/tasks/bulkdata/generate_from_yaml.py +183 -0
  252. cumulusci/tasks/bulkdata/generate_mapping.py +434 -0
  253. cumulusci/tasks/bulkdata/generate_mapping_utils/dependency_map.py +169 -0
  254. cumulusci/tasks/bulkdata/generate_mapping_utils/extract_mapping_file_generator.py +45 -0
  255. cumulusci/tasks/bulkdata/generate_mapping_utils/generate_mapping_from_declarations.py +121 -0
  256. cumulusci/tasks/bulkdata/generate_mapping_utils/load_mapping_file_generator.py +127 -0
  257. cumulusci/tasks/bulkdata/generate_mapping_utils/mapping_generator_post_processes.py +53 -0
  258. cumulusci/tasks/bulkdata/generate_mapping_utils/mapping_transforms.py +139 -0
  259. cumulusci/tasks/bulkdata/generate_mapping_utils/tests/test_generate_extract_mapping_from_declarations.py +135 -0
  260. cumulusci/tasks/bulkdata/generate_mapping_utils/tests/test_generate_load_mapping_from_declarations.py +330 -0
  261. cumulusci/tasks/bulkdata/generate_mapping_utils/tests/test_mapping_generator_post_processes.py +60 -0
  262. cumulusci/tasks/bulkdata/generate_mapping_utils/tests/test_mapping_transforms.py +188 -0
  263. cumulusci/tasks/bulkdata/load.py +1196 -0
  264. cumulusci/tasks/bulkdata/mapping_parser.py +811 -0
  265. cumulusci/tasks/bulkdata/query_transformers.py +264 -0
  266. cumulusci/tasks/bulkdata/select_utils.py +792 -0
  267. cumulusci/tasks/bulkdata/snowfakery.py +753 -0
  268. cumulusci/tasks/bulkdata/snowfakery_utils/queue_manager.py +478 -0
  269. cumulusci/tasks/bulkdata/snowfakery_utils/snowfakery_run_until.py +141 -0
  270. cumulusci/tasks/bulkdata/snowfakery_utils/snowfakery_working_directory.py +53 -0
  271. cumulusci/tasks/bulkdata/snowfakery_utils/subtask_configurator.py +64 -0
  272. cumulusci/tasks/bulkdata/step.py +1242 -0
  273. cumulusci/tasks/bulkdata/tests/__init__.py +0 -0
  274. cumulusci/tasks/bulkdata/tests/cassettes/TestSelect.test_select_random_strategy.yaml +147 -0
  275. cumulusci/tasks/bulkdata/tests/cassettes/TestSelect.test_select_similarity_annoy_strategy.yaml +123 -0
  276. cumulusci/tasks/bulkdata/tests/cassettes/TestSelect.test_select_similarity_select_and_insert_strategy.yaml +313 -0
  277. cumulusci/tasks/bulkdata/tests/cassettes/TestSelect.test_select_similarity_select_and_insert_strategy_bulk.yaml +550 -0
  278. cumulusci/tasks/bulkdata/tests/cassettes/TestSelect.test_select_similarity_strategy.yaml +175 -0
  279. cumulusci/tasks/bulkdata/tests/cassettes/TestSelect.test_select_standard_strategy.yaml +147 -0
  280. cumulusci/tasks/bulkdata/tests/cassettes/TestSnowfakery.test_run_until_records_in_org__multiple_needed.yaml +69 -0
  281. cumulusci/tasks/bulkdata/tests/cassettes/TestSnowfakery.test_run_until_records_in_org__none_needed.yaml +22 -0
  282. cumulusci/tasks/bulkdata/tests/cassettes/TestSnowfakery.test_run_until_records_in_org__one_needed.yaml +24 -0
  283. cumulusci/tasks/bulkdata/tests/cassettes/TestSnowfakery.test_snowfakery_query_salesforce.yaml +25 -0
  284. cumulusci/tasks/bulkdata/tests/cassettes/TestUpdatesIntegrationTests.test_updates_task.yaml +80 -0
  285. cumulusci/tasks/bulkdata/tests/cassettes/TestUpsert.test_simple_upsert__rest.yaml +270 -0
  286. cumulusci/tasks/bulkdata/tests/cassettes/TestUpsert.test_upsert__rest.yaml +267 -0
  287. cumulusci/tasks/bulkdata/tests/cassettes/TestUpsert.test_upsert_complex_external_id_field__rest.yaml +369 -0
  288. cumulusci/tasks/bulkdata/tests/cassettes/TestUpsert.test_upsert_complex_external_id_field_rest__duplicate_error.yaml +204 -0
  289. cumulusci/tasks/bulkdata/tests/cassettes/TestUpsert.test_upsert_complex_fields__bulk.yaml +675 -0
  290. cumulusci/tasks/bulkdata/tests/dummy_data_factory.py +36 -0
  291. cumulusci/tasks/bulkdata/tests/integration_test_utils.py +49 -0
  292. cumulusci/tasks/bulkdata/tests/mapping-oid.yml +87 -0
  293. cumulusci/tasks/bulkdata/tests/mapping_after.yml +38 -0
  294. cumulusci/tasks/bulkdata/tests/mapping_poly.yml +34 -0
  295. cumulusci/tasks/bulkdata/tests/mapping_poly_incomplete.yml +20 -0
  296. cumulusci/tasks/bulkdata/tests/mapping_poly_wrong.yml +21 -0
  297. cumulusci/tasks/bulkdata/tests/mapping_select.yml +20 -0
  298. cumulusci/tasks/bulkdata/tests/mapping_select_invalid_strategy.yml +20 -0
  299. cumulusci/tasks/bulkdata/tests/mapping_select_invalid_threshold__invalid_number.yml +21 -0
  300. cumulusci/tasks/bulkdata/tests/mapping_select_invalid_threshold__invalid_strategy.yml +21 -0
  301. cumulusci/tasks/bulkdata/tests/mapping_select_invalid_threshold__non_float.yml +21 -0
  302. cumulusci/tasks/bulkdata/tests/mapping_select_missing_priority_fields.yml +22 -0
  303. cumulusci/tasks/bulkdata/tests/mapping_select_no_priority_fields.yml +18 -0
  304. cumulusci/tasks/bulkdata/tests/mapping_simple.yml +27 -0
  305. cumulusci/tasks/bulkdata/tests/mapping_v1.yml +28 -0
  306. cumulusci/tasks/bulkdata/tests/mapping_v2.yml +21 -0
  307. cumulusci/tasks/bulkdata/tests/mapping_v3.yml +32 -0
  308. cumulusci/tasks/bulkdata/tests/mapping_vanilla_sf.yml +69 -0
  309. cumulusci/tasks/bulkdata/tests/mock_data_factory_without_mapping.py +12 -0
  310. cumulusci/tasks/bulkdata/tests/person_accounts.yml +23 -0
  311. cumulusci/tasks/bulkdata/tests/person_accounts_minimal.yml +15 -0
  312. cumulusci/tasks/bulkdata/tests/recordtypes.yml +8 -0
  313. cumulusci/tasks/bulkdata/tests/recordtypes_2.yml +6 -0
  314. cumulusci/tasks/bulkdata/tests/recordtypes_with_ispersontype.yml +8 -0
  315. cumulusci/tasks/bulkdata/tests/snowfakery/child/child2.yml +3 -0
  316. cumulusci/tasks/bulkdata/tests/snowfakery/child.yml +4 -0
  317. cumulusci/tasks/bulkdata/tests/snowfakery/gen_npsp_standard_objects.recipe.yml +89 -0
  318. cumulusci/tasks/bulkdata/tests/snowfakery/include_parent.yml +3 -0
  319. cumulusci/tasks/bulkdata/tests/snowfakery/npsp_standard_objects_macros.yml +34 -0
  320. cumulusci/tasks/bulkdata/tests/snowfakery/options.recipe.yml +6 -0
  321. cumulusci/tasks/bulkdata/tests/snowfakery/query_snowfakery.recipe.yml +16 -0
  322. cumulusci/tasks/bulkdata/tests/snowfakery/sf_standard_object_macros.yml +83 -0
  323. cumulusci/tasks/bulkdata/tests/snowfakery/simple_snowfakery.load.yml +2 -0
  324. cumulusci/tasks/bulkdata/tests/snowfakery/simple_snowfakery.recipe.yml +13 -0
  325. cumulusci/tasks/bulkdata/tests/snowfakery/simple_snowfakery_2.load.yml +5 -0
  326. cumulusci/tasks/bulkdata/tests/snowfakery/simple_snowfakery_channels.load.yml +13 -0
  327. cumulusci/tasks/bulkdata/tests/snowfakery/simple_snowfakery_channels.recipe.yml +12 -0
  328. cumulusci/tasks/bulkdata/tests/snowfakery/simple_snowfakery_channels_2.load.yml +13 -0
  329. cumulusci/tasks/bulkdata/tests/snowfakery/unique_values.recipe.yml +4 -0
  330. cumulusci/tasks/bulkdata/tests/snowfakery/upsert.recipe.yml +23 -0
  331. cumulusci/tasks/bulkdata/tests/snowfakery/upsert_2.recipe.yml +29 -0
  332. cumulusci/tasks/bulkdata/tests/snowfakery/upsert_before.yml +10 -0
  333. cumulusci/tasks/bulkdata/tests/test_base_generate_data_tasks.py +61 -0
  334. cumulusci/tasks/bulkdata/tests/test_dates.py +99 -0
  335. cumulusci/tasks/bulkdata/tests/test_delete.py +404 -0
  336. cumulusci/tasks/bulkdata/tests/test_extract.py +1311 -0
  337. cumulusci/tasks/bulkdata/tests/test_factory_utils.py +55 -0
  338. cumulusci/tasks/bulkdata/tests/test_generate_and_load.py +252 -0
  339. cumulusci/tasks/bulkdata/tests/test_generate_from_snowfakery_task.py +343 -0
  340. cumulusci/tasks/bulkdata/tests/test_generatemapping.py +1039 -0
  341. cumulusci/tasks/bulkdata/tests/test_load.py +3175 -0
  342. cumulusci/tasks/bulkdata/tests/test_mapping_parser.py +1658 -0
  343. cumulusci/tasks/bulkdata/tests/test_query_db__joins_self_lookups.yml +12 -0
  344. cumulusci/tasks/bulkdata/tests/test_query_db_joins_lookups.yml +26 -0
  345. cumulusci/tasks/bulkdata/tests/test_query_db_joins_lookups_select.yml +48 -0
  346. cumulusci/tasks/bulkdata/tests/test_select.py +171 -0
  347. cumulusci/tasks/bulkdata/tests/test_select_utils.py +1057 -0
  348. cumulusci/tasks/bulkdata/tests/test_snowfakery.py +1153 -0
  349. cumulusci/tasks/bulkdata/tests/test_step.py +3957 -0
  350. cumulusci/tasks/bulkdata/tests/test_updates.py +513 -0
  351. cumulusci/tasks/bulkdata/tests/test_upsert.py +1015 -0
  352. cumulusci/tasks/bulkdata/tests/test_utils.py +158 -0
  353. cumulusci/tasks/bulkdata/tests/testdata.db +0 -0
  354. cumulusci/tasks/bulkdata/tests/update_describe.py +50 -0
  355. cumulusci/tasks/bulkdata/tests/update_person_accounts.yml +23 -0
  356. cumulusci/tasks/bulkdata/tests/utils.py +114 -0
  357. cumulusci/tasks/bulkdata/update_data.py +260 -0
  358. cumulusci/tasks/bulkdata/upsert_utils.py +130 -0
  359. cumulusci/tasks/bulkdata/utils.py +249 -0
  360. cumulusci/tasks/command.py +178 -0
  361. cumulusci/tasks/connectedapp.py +186 -0
  362. cumulusci/tasks/create_package_version.py +778 -0
  363. cumulusci/tasks/datadictionary.py +745 -0
  364. cumulusci/tasks/dx_convert_from.py +26 -0
  365. cumulusci/tasks/github/__init__.py +17 -0
  366. cumulusci/tasks/github/base.py +16 -0
  367. cumulusci/tasks/github/commit_status.py +13 -0
  368. cumulusci/tasks/github/merge.py +11 -0
  369. cumulusci/tasks/github/publish.py +11 -0
  370. cumulusci/tasks/github/pull_request.py +11 -0
  371. cumulusci/tasks/github/release.py +11 -0
  372. cumulusci/tasks/github/release_report.py +11 -0
  373. cumulusci/tasks/github/tag.py +11 -0
  374. cumulusci/tasks/github/tests/__init__.py +0 -0
  375. cumulusci/tasks/github/tests/test_util.py +202 -0
  376. cumulusci/tasks/github/tests/test_vcs_migration.py +44 -0
  377. cumulusci/tasks/github/tests/util_github_api.py +666 -0
  378. cumulusci/tasks/github/util.py +252 -0
  379. cumulusci/tasks/marketing_cloud/__init__.py +0 -0
  380. cumulusci/tasks/marketing_cloud/api.py +188 -0
  381. cumulusci/tasks/marketing_cloud/base.py +38 -0
  382. cumulusci/tasks/marketing_cloud/deploy.py +345 -0
  383. cumulusci/tasks/marketing_cloud/get_user_info.py +40 -0
  384. cumulusci/tasks/marketing_cloud/mc_constants.py +1 -0
  385. cumulusci/tasks/marketing_cloud/tests/__init__.py +0 -0
  386. cumulusci/tasks/marketing_cloud/tests/conftest.py +46 -0
  387. cumulusci/tasks/marketing_cloud/tests/expected-payload.json +110 -0
  388. cumulusci/tasks/marketing_cloud/tests/test_api.py +97 -0
  389. cumulusci/tasks/marketing_cloud/tests/test_api_soap_envelopes.py +145 -0
  390. cumulusci/tasks/marketing_cloud/tests/test_base.py +14 -0
  391. cumulusci/tasks/marketing_cloud/tests/test_deploy.py +400 -0
  392. cumulusci/tasks/marketing_cloud/tests/test_get_user_info.py +141 -0
  393. cumulusci/tasks/marketing_cloud/tests/validation-response.json +39 -0
  394. cumulusci/tasks/metadata/__init__.py +0 -0
  395. cumulusci/tasks/metadata/ee_src.py +94 -0
  396. cumulusci/tasks/metadata/managed_src.py +100 -0
  397. cumulusci/tasks/metadata/metadata_map.yml +868 -0
  398. cumulusci/tasks/metadata/modify.py +99 -0
  399. cumulusci/tasks/metadata/package.py +684 -0
  400. cumulusci/tasks/metadata/tests/__init__.py +0 -0
  401. cumulusci/tasks/metadata/tests/package_metadata/namespaced_report_folder/.hidden/.keep +0 -0
  402. cumulusci/tasks/metadata/tests/package_metadata/namespaced_report_folder/destructiveChanges.xml +9 -0
  403. cumulusci/tasks/metadata/tests/package_metadata/namespaced_report_folder/package.xml +9 -0
  404. cumulusci/tasks/metadata/tests/package_metadata/namespaced_report_folder/package_install_uninstall.xml +11 -0
  405. cumulusci/tasks/metadata/tests/package_metadata/namespaced_report_folder/reports/namespace__TestFolder/TestReport.report +3 -0
  406. cumulusci/tasks/metadata/tests/sample_package.xml +9 -0
  407. cumulusci/tasks/metadata/tests/test_ee_src.py +112 -0
  408. cumulusci/tasks/metadata/tests/test_managed_src.py +111 -0
  409. cumulusci/tasks/metadata/tests/test_modify.py +123 -0
  410. cumulusci/tasks/metadata/tests/test_package.py +476 -0
  411. cumulusci/tasks/metadata_etl/__init__.py +29 -0
  412. cumulusci/tasks/metadata_etl/base.py +436 -0
  413. cumulusci/tasks/metadata_etl/duplicate_rules.py +24 -0
  414. cumulusci/tasks/metadata_etl/field_sets.py +70 -0
  415. cumulusci/tasks/metadata_etl/help_text.py +92 -0
  416. cumulusci/tasks/metadata_etl/layouts.py +550 -0
  417. cumulusci/tasks/metadata_etl/objects.py +68 -0
  418. cumulusci/tasks/metadata_etl/permissions.py +167 -0
  419. cumulusci/tasks/metadata_etl/picklists.py +221 -0
  420. cumulusci/tasks/metadata_etl/remote_site_settings.py +99 -0
  421. cumulusci/tasks/metadata_etl/sharing.py +138 -0
  422. cumulusci/tasks/metadata_etl/tests/test_base.py +512 -0
  423. cumulusci/tasks/metadata_etl/tests/test_duplicate_rules.py +22 -0
  424. cumulusci/tasks/metadata_etl/tests/test_field_sets.py +156 -0
  425. cumulusci/tasks/metadata_etl/tests/test_help_text.py +387 -0
  426. cumulusci/tasks/metadata_etl/tests/test_ip_ranges.py +85 -0
  427. cumulusci/tasks/metadata_etl/tests/test_layouts.py +858 -0
  428. cumulusci/tasks/metadata_etl/tests/test_objects.py +236 -0
  429. cumulusci/tasks/metadata_etl/tests/test_permissions.py +223 -0
  430. cumulusci/tasks/metadata_etl/tests/test_picklists.py +547 -0
  431. cumulusci/tasks/metadata_etl/tests/test_remote_site_settings.py +46 -0
  432. cumulusci/tasks/metadata_etl/tests/test_sharing.py +333 -0
  433. cumulusci/tasks/metadata_etl/tests/test_value_sets.py +298 -0
  434. cumulusci/tasks/metadata_etl/value_sets.py +106 -0
  435. cumulusci/tasks/metadeploy.py +393 -0
  436. cumulusci/tasks/metaxml.py +88 -0
  437. cumulusci/tasks/preflight/__init__.py +0 -0
  438. cumulusci/tasks/preflight/dataset_load.py +49 -0
  439. cumulusci/tasks/preflight/licenses.py +86 -0
  440. cumulusci/tasks/preflight/packages.py +14 -0
  441. cumulusci/tasks/preflight/permsets.py +23 -0
  442. cumulusci/tasks/preflight/recordtypes.py +16 -0
  443. cumulusci/tasks/preflight/retrieve_tasks.py +30 -0
  444. cumulusci/tasks/preflight/settings.py +77 -0
  445. cumulusci/tasks/preflight/sobjects.py +202 -0
  446. cumulusci/tasks/preflight/tests/test_dataset_load.py +85 -0
  447. cumulusci/tasks/preflight/tests/test_licenses.py +174 -0
  448. cumulusci/tasks/preflight/tests/test_packages.py +14 -0
  449. cumulusci/tasks/preflight/tests/test_permset_preflights.py +51 -0
  450. cumulusci/tasks/preflight/tests/test_recordtypes.py +30 -0
  451. cumulusci/tasks/preflight/tests/test_retrieve_tasks.py +62 -0
  452. cumulusci/tasks/preflight/tests/test_settings.py +130 -0
  453. cumulusci/tasks/preflight/tests/test_sobjects.py +231 -0
  454. cumulusci/tasks/push/README.md +59 -0
  455. cumulusci/tasks/push/__init__.py +0 -0
  456. cumulusci/tasks/push/push_api.py +659 -0
  457. cumulusci/tasks/push/pushfails.py +136 -0
  458. cumulusci/tasks/push/tasks.py +476 -0
  459. cumulusci/tasks/push/tests/conftest.py +263 -0
  460. cumulusci/tasks/push/tests/test_push_api.py +951 -0
  461. cumulusci/tasks/push/tests/test_push_tasks.py +659 -0
  462. cumulusci/tasks/release_notes/README.md +63 -0
  463. cumulusci/tasks/release_notes/__init__.py +0 -0
  464. cumulusci/tasks/release_notes/exceptions.py +5 -0
  465. cumulusci/tasks/release_notes/generator.py +137 -0
  466. cumulusci/tasks/release_notes/parser.py +232 -0
  467. cumulusci/tasks/release_notes/provider.py +44 -0
  468. cumulusci/tasks/release_notes/task.py +300 -0
  469. cumulusci/tasks/release_notes/tests/__init__.py +0 -0
  470. cumulusci/tasks/release_notes/tests/change_notes/full/example1.md +17 -0
  471. cumulusci/tasks/release_notes/tests/change_notes/multi/1.txt +1 -0
  472. cumulusci/tasks/release_notes/tests/change_notes/multi/2.txt +1 -0
  473. cumulusci/tasks/release_notes/tests/change_notes/multi/3.txt +1 -0
  474. cumulusci/tasks/release_notes/tests/change_notes/single/1.txt +1 -0
  475. cumulusci/tasks/release_notes/tests/test_generator.py +582 -0
  476. cumulusci/tasks/release_notes/tests/test_parser.py +867 -0
  477. cumulusci/tasks/release_notes/tests/test_provider.py +512 -0
  478. cumulusci/tasks/release_notes/tests/test_task.py +461 -0
  479. cumulusci/tasks/release_notes/tests/utils.py +153 -0
  480. cumulusci/tasks/robotframework/__init__.py +3 -0
  481. cumulusci/tasks/robotframework/debugger/DebugListener.py +100 -0
  482. cumulusci/tasks/robotframework/debugger/__init__.py +10 -0
  483. cumulusci/tasks/robotframework/debugger/model.py +87 -0
  484. cumulusci/tasks/robotframework/debugger/ui.py +259 -0
  485. cumulusci/tasks/robotframework/libdoc.py +269 -0
  486. cumulusci/tasks/robotframework/robotframework.py +392 -0
  487. cumulusci/tasks/robotframework/stylesheet.css +130 -0
  488. cumulusci/tasks/robotframework/template.html +109 -0
  489. cumulusci/tasks/robotframework/tests/TestLibrary.py +18 -0
  490. cumulusci/tasks/robotframework/tests/TestPageObjects.py +31 -0
  491. cumulusci/tasks/robotframework/tests/TestResource.robot +8 -0
  492. cumulusci/tasks/robotframework/tests/failing_tests.robot +16 -0
  493. cumulusci/tasks/robotframework/tests/performance.robot +23 -0
  494. cumulusci/tasks/robotframework/tests/test_browser_proxies.py +137 -0
  495. cumulusci/tasks/robotframework/tests/test_debugger.py +360 -0
  496. cumulusci/tasks/robotframework/tests/test_robot_parallel.py +141 -0
  497. cumulusci/tasks/robotframework/tests/test_robotframework.py +860 -0
  498. cumulusci/tasks/salesforce/BaseRetrieveMetadata.py +58 -0
  499. cumulusci/tasks/salesforce/BaseSalesforceApiTask.py +45 -0
  500. cumulusci/tasks/salesforce/BaseSalesforceMetadataApiTask.py +18 -0
  501. cumulusci/tasks/salesforce/BaseSalesforceTask.py +4 -0
  502. cumulusci/tasks/salesforce/BaseUninstallMetadata.py +41 -0
  503. cumulusci/tasks/salesforce/CreateCommunity.py +124 -0
  504. cumulusci/tasks/salesforce/CreatePackage.py +29 -0
  505. cumulusci/tasks/salesforce/Deploy.py +240 -0
  506. cumulusci/tasks/salesforce/DeployBundles.py +88 -0
  507. cumulusci/tasks/salesforce/DescribeMetadataTypes.py +26 -0
  508. cumulusci/tasks/salesforce/EnsureRecordTypes.py +202 -0
  509. cumulusci/tasks/salesforce/GetInstalledPackages.py +8 -0
  510. cumulusci/tasks/salesforce/ListCommunities.py +40 -0
  511. cumulusci/tasks/salesforce/ListCommunityTemplates.py +19 -0
  512. cumulusci/tasks/salesforce/PublishCommunity.py +62 -0
  513. cumulusci/tasks/salesforce/RetrievePackaged.py +41 -0
  514. cumulusci/tasks/salesforce/RetrieveReportsAndDashboards.py +82 -0
  515. cumulusci/tasks/salesforce/RetrieveUnpackaged.py +36 -0
  516. cumulusci/tasks/salesforce/SOQLQuery.py +39 -0
  517. cumulusci/tasks/salesforce/UninstallLocal.py +15 -0
  518. cumulusci/tasks/salesforce/UninstallLocalBundles.py +28 -0
  519. cumulusci/tasks/salesforce/UninstallLocalNamespacedBundles.py +58 -0
  520. cumulusci/tasks/salesforce/UninstallPackage.py +32 -0
  521. cumulusci/tasks/salesforce/UninstallPackaged.py +56 -0
  522. cumulusci/tasks/salesforce/UpdateAdminProfile.py +8 -0
  523. cumulusci/tasks/salesforce/__init__.py +79 -0
  524. cumulusci/tasks/salesforce/activate_flow.py +74 -0
  525. cumulusci/tasks/salesforce/check_components.py +324 -0
  526. cumulusci/tasks/salesforce/composite.py +142 -0
  527. cumulusci/tasks/salesforce/create_permission_sets.py +35 -0
  528. cumulusci/tasks/salesforce/custom_settings.py +134 -0
  529. cumulusci/tasks/salesforce/custom_settings_wait.py +132 -0
  530. cumulusci/tasks/salesforce/enable_prediction.py +107 -0
  531. cumulusci/tasks/salesforce/insert_record.py +40 -0
  532. cumulusci/tasks/salesforce/install_package_version.py +242 -0
  533. cumulusci/tasks/salesforce/license_preflights.py +8 -0
  534. cumulusci/tasks/salesforce/network_member_group.py +178 -0
  535. cumulusci/tasks/salesforce/nonsourcetracking.py +228 -0
  536. cumulusci/tasks/salesforce/org_settings.py +193 -0
  537. cumulusci/tasks/salesforce/package_upload.py +328 -0
  538. cumulusci/tasks/salesforce/profiles.py +74 -0
  539. cumulusci/tasks/salesforce/promote_package_version.py +376 -0
  540. cumulusci/tasks/salesforce/retrieve_profile.py +195 -0
  541. cumulusci/tasks/salesforce/salesforce_files.py +244 -0
  542. cumulusci/tasks/salesforce/sourcetracking.py +507 -0
  543. cumulusci/tasks/salesforce/tests/__init__.py +3 -0
  544. cumulusci/tasks/salesforce/tests/test_CreateCommunity.py +278 -0
  545. cumulusci/tasks/salesforce/tests/test_CreatePackage.py +22 -0
  546. cumulusci/tasks/salesforce/tests/test_Deploy.py +470 -0
  547. cumulusci/tasks/salesforce/tests/test_DeployBundles.py +76 -0
  548. cumulusci/tasks/salesforce/tests/test_EnsureRecordTypes.py +345 -0
  549. cumulusci/tasks/salesforce/tests/test_ListCommunities.py +84 -0
  550. cumulusci/tasks/salesforce/tests/test_ListCommunityTemplates.py +49 -0
  551. cumulusci/tasks/salesforce/tests/test_PackageUpload.py +547 -0
  552. cumulusci/tasks/salesforce/tests/test_ProfileGrantAllAccess.py +699 -0
  553. cumulusci/tasks/salesforce/tests/test_PublishCommunity.py +181 -0
  554. cumulusci/tasks/salesforce/tests/test_RetrievePackaged.py +24 -0
  555. cumulusci/tasks/salesforce/tests/test_RetrieveReportsAndDashboards.py +56 -0
  556. cumulusci/tasks/salesforce/tests/test_RetrieveUnpackaged.py +21 -0
  557. cumulusci/tasks/salesforce/tests/test_SOQLQuery.py +30 -0
  558. cumulusci/tasks/salesforce/tests/test_UninstallLocal.py +15 -0
  559. cumulusci/tasks/salesforce/tests/test_UninstallLocalBundles.py +19 -0
  560. cumulusci/tasks/salesforce/tests/test_UninstallLocalNamespacedBundles.py +22 -0
  561. cumulusci/tasks/salesforce/tests/test_UninstallPackage.py +19 -0
  562. cumulusci/tasks/salesforce/tests/test_UninstallPackaged.py +66 -0
  563. cumulusci/tasks/salesforce/tests/test_UninstallPackagedIncremental.py +127 -0
  564. cumulusci/tasks/salesforce/tests/test_activate_flow.py +132 -0
  565. cumulusci/tasks/salesforce/tests/test_base_tasks.py +110 -0
  566. cumulusci/tasks/salesforce/tests/test_check_components.py +445 -0
  567. cumulusci/tasks/salesforce/tests/test_composite.py +250 -0
  568. cumulusci/tasks/salesforce/tests/test_create_permission_sets.py +41 -0
  569. cumulusci/tasks/salesforce/tests/test_custom_settings.py +227 -0
  570. cumulusci/tasks/salesforce/tests/test_custom_settings_wait.py +174 -0
  571. cumulusci/tasks/salesforce/tests/test_describemetadatatypes.py +18 -0
  572. cumulusci/tasks/salesforce/tests/test_enable_prediction.py +240 -0
  573. cumulusci/tasks/salesforce/tests/test_insert_record.py +110 -0
  574. cumulusci/tasks/salesforce/tests/test_install_package_version.py +464 -0
  575. cumulusci/tasks/salesforce/tests/test_network_member_group.py +444 -0
  576. cumulusci/tasks/salesforce/tests/test_nonsourcetracking.py +235 -0
  577. cumulusci/tasks/salesforce/tests/test_org_settings.py +407 -0
  578. cumulusci/tasks/salesforce/tests/test_profiles.py +202 -0
  579. cumulusci/tasks/salesforce/tests/test_retrieve_profile.py +287 -0
  580. cumulusci/tasks/salesforce/tests/test_salesforce_files.py +228 -0
  581. cumulusci/tasks/salesforce/tests/test_sourcetracking.py +350 -0
  582. cumulusci/tasks/salesforce/tests/test_trigger_handlers.py +300 -0
  583. cumulusci/tasks/salesforce/tests/test_update_dependencies.py +509 -0
  584. cumulusci/tasks/salesforce/tests/util.py +79 -0
  585. cumulusci/tasks/salesforce/trigger_handlers.py +119 -0
  586. cumulusci/tasks/salesforce/uninstall_packaged_incremental.py +136 -0
  587. cumulusci/tasks/salesforce/update_dependencies.py +290 -0
  588. cumulusci/tasks/salesforce/update_profile.py +339 -0
  589. cumulusci/tasks/salesforce/users/permsets.py +227 -0
  590. cumulusci/tasks/salesforce/users/photos.py +162 -0
  591. cumulusci/tasks/salesforce/users/tests/photo.mock.txt +1 -0
  592. cumulusci/tasks/salesforce/users/tests/test_permsets.py +950 -0
  593. cumulusci/tasks/salesforce/users/tests/test_photos.py +373 -0
  594. cumulusci/tasks/sample_data/capture_sample_data.py +77 -0
  595. cumulusci/tasks/sample_data/load_sample_data.py +85 -0
  596. cumulusci/tasks/sample_data/test_capture_sample_data.py +117 -0
  597. cumulusci/tasks/sample_data/test_load_sample_data.py +121 -0
  598. cumulusci/tasks/sfdx.py +83 -0
  599. cumulusci/tasks/tests/__init__.py +1 -0
  600. cumulusci/tasks/tests/conftest.py +30 -0
  601. cumulusci/tasks/tests/test_command.py +129 -0
  602. cumulusci/tasks/tests/test_connectedapp.py +236 -0
  603. cumulusci/tasks/tests/test_create_package_version.py +847 -0
  604. cumulusci/tasks/tests/test_datadictionary.py +1575 -0
  605. cumulusci/tasks/tests/test_dx_convert_from.py +60 -0
  606. cumulusci/tasks/tests/test_metadeploy.py +624 -0
  607. cumulusci/tasks/tests/test_metaxml.py +99 -0
  608. cumulusci/tasks/tests/test_promote_package_version.py +488 -0
  609. cumulusci/tasks/tests/test_pushfails.py +96 -0
  610. cumulusci/tasks/tests/test_salesforce.py +72 -0
  611. cumulusci/tasks/tests/test_sfdx.py +105 -0
  612. cumulusci/tasks/tests/test_util.py +207 -0
  613. cumulusci/tasks/util.py +261 -0
  614. cumulusci/tasks/vcs/__init__.py +19 -0
  615. cumulusci/tasks/vcs/commit_status.py +58 -0
  616. cumulusci/tasks/vcs/create_commit_status.py +37 -0
  617. cumulusci/tasks/vcs/download_extract.py +199 -0
  618. cumulusci/tasks/vcs/merge.py +298 -0
  619. cumulusci/tasks/vcs/publish.py +207 -0
  620. cumulusci/tasks/vcs/pull_request.py +9 -0
  621. cumulusci/tasks/vcs/release.py +134 -0
  622. cumulusci/tasks/vcs/release_report.py +105 -0
  623. cumulusci/tasks/vcs/tag.py +31 -0
  624. cumulusci/tasks/vcs/tests/github/test_commit_status.py +196 -0
  625. cumulusci/tasks/vcs/tests/github/test_download_extract.py +896 -0
  626. cumulusci/tasks/vcs/tests/github/test_merge.py +1118 -0
  627. cumulusci/tasks/vcs/tests/github/test_publish.py +823 -0
  628. cumulusci/tasks/vcs/tests/github/test_pull_request.py +29 -0
  629. cumulusci/tasks/vcs/tests/github/test_release.py +390 -0
  630. cumulusci/tasks/vcs/tests/github/test_release_report.py +109 -0
  631. cumulusci/tasks/vcs/tests/github/test_tag.py +90 -0
  632. cumulusci/tasks/vlocity/exceptions.py +2 -0
  633. cumulusci/tasks/vlocity/tests/test_vlocity.py +283 -0
  634. cumulusci/tasks/vlocity/vlocity.py +342 -0
  635. cumulusci/tests/__init__.py +1 -0
  636. cumulusci/tests/cassettes/GET_sobjects_Account_PersonAccount_describe.yaml +18 -0
  637. cumulusci/tests/cassettes/TestIntegrationInfrastructure.test_integration_tests.yaml +19 -0
  638. cumulusci/tests/pytest_plugins/pytest_sf_orgconnect.py +307 -0
  639. cumulusci/tests/pytest_plugins/pytest_sf_vcr.py +275 -0
  640. cumulusci/tests/pytest_plugins/pytest_sf_vcr_serializer.py +160 -0
  641. cumulusci/tests/pytest_plugins/pytest_typeguard.py +5 -0
  642. cumulusci/tests/pytest_plugins/test_vcr_string_compressor.py +49 -0
  643. cumulusci/tests/pytest_plugins/vcr_string_compressor.py +97 -0
  644. cumulusci/tests/shared_cassettes/GET_sobjects_Account_describe.yaml +18 -0
  645. cumulusci/tests/shared_cassettes/GET_sobjects_Case_describe.yaml +18 -0
  646. cumulusci/tests/shared_cassettes/GET_sobjects_Contact_describe.yaml +4838 -0
  647. cumulusci/tests/shared_cassettes/GET_sobjects_Custom__c_describe.yaml +242 -0
  648. cumulusci/tests/shared_cassettes/GET_sobjects_Event_describe.yaml +19 -0
  649. cumulusci/tests/shared_cassettes/GET_sobjects_Global_describe.yaml +1338 -0
  650. cumulusci/tests/shared_cassettes/GET_sobjects_Lead_describe.yaml +18 -0
  651. cumulusci/tests/shared_cassettes/GET_sobjects_OpportunityContactRole_describe.yaml +34 -0
  652. cumulusci/tests/shared_cassettes/GET_sobjects_Opportunity_describe.yaml +1261 -0
  653. cumulusci/tests/shared_cassettes/GET_sobjects_Organization.yaml +49 -0
  654. cumulusci/tests/shared_cassettes/vcr_string_templates/batchInfoList_xml.tpl +15 -0
  655. cumulusci/tests/shared_cassettes/vcr_string_templates/batchInfo_xml.tpl +13 -0
  656. cumulusci/tests/shared_cassettes/vcr_string_templates/jobInfo_insert_xml.tpl +24 -0
  657. cumulusci/tests/shared_cassettes/vcr_string_templates/jobInfo_upsert_xml.tpl +25 -0
  658. cumulusci/tests/test_entry_points.py +20 -0
  659. cumulusci/tests/test_integration_infrastructure.py +131 -0
  660. cumulusci/tests/test_main.py +9 -0
  661. cumulusci/tests/test_schema.py +32 -0
  662. cumulusci/tests/test_utils.py +657 -0
  663. cumulusci/tests/test_vcr_serializer.py +134 -0
  664. cumulusci/tests/uncompressed_cassette.yaml +83 -0
  665. cumulusci/tests/util.py +344 -0
  666. cumulusci/utils/__init__.py +731 -0
  667. cumulusci/utils/classutils.py +9 -0
  668. cumulusci/utils/collections.py +32 -0
  669. cumulusci/utils/deprecation.py +11 -0
  670. cumulusci/utils/encryption.py +31 -0
  671. cumulusci/utils/fileutils.py +295 -0
  672. cumulusci/utils/git.py +142 -0
  673. cumulusci/utils/http/multi_request.py +214 -0
  674. cumulusci/utils/http/requests_utils.py +103 -0
  675. cumulusci/utils/http/tests/cassettes/ManualEditTestCompositeParallelSalesforce.test_http_headers.yaml +32 -0
  676. cumulusci/utils/http/tests/cassettes/TestCompositeParallelSalesforce.test_composite_parallel_salesforce.yaml +65 -0
  677. cumulusci/utils/http/tests/cassettes/TestCompositeParallelSalesforce.test_errors.yaml +24 -0
  678. cumulusci/utils/http/tests/cassettes/TestCompositeParallelSalesforce.test_reference_ids.yaml +49 -0
  679. cumulusci/utils/http/tests/test_multi_request.py +255 -0
  680. cumulusci/utils/iterators.py +21 -0
  681. cumulusci/utils/logging.py +128 -0
  682. cumulusci/utils/metaprogramming.py +10 -0
  683. cumulusci/utils/options.py +138 -0
  684. cumulusci/utils/parallel/queries_in_parallel/run_queries_in_parallel.py +29 -0
  685. cumulusci/utils/parallel/queries_in_parallel/tests/test_run_queries_in_parallel.py +50 -0
  686. cumulusci/utils/parallel/task_worker_queues/parallel_worker.py +238 -0
  687. cumulusci/utils/parallel/task_worker_queues/parallel_worker_queue.py +243 -0
  688. cumulusci/utils/parallel/task_worker_queues/tests/test_parallel_worker.py +353 -0
  689. cumulusci/utils/salesforce/count_sobjects.py +46 -0
  690. cumulusci/utils/salesforce/soql.py +17 -0
  691. cumulusci/utils/salesforce/tests/cassettes/ManualEdit_TestCountSObjects.test_count_sobjects__network_errors.yaml +23 -0
  692. cumulusci/utils/salesforce/tests/cassettes/TestCountSObjects.test_count_sobjects__errors.yaml +33 -0
  693. cumulusci/utils/salesforce/tests/cassettes/TestCountSObjects.test_count_sobjects_simple.yaml +29 -0
  694. cumulusci/utils/salesforce/tests/test_count_sobjects.py +29 -0
  695. cumulusci/utils/salesforce/tests/test_soql.py +30 -0
  696. cumulusci/utils/tests/cassettes/ManualEditTestDescribeOrg.test_minimal_schema.yaml +36 -0
  697. cumulusci/utils/tests/cassettes/ManualEdit_test_describe_to_sql.yaml +191 -0
  698. cumulusci/utils/tests/test_fileutils.py +284 -0
  699. cumulusci/utils/tests/test_git.py +85 -0
  700. cumulusci/utils/tests/test_logging.py +70 -0
  701. cumulusci/utils/tests/test_option_parsing.py +188 -0
  702. cumulusci/utils/tests/test_org_schema.py +691 -0
  703. cumulusci/utils/tests/test_org_schema_models.py +79 -0
  704. cumulusci/utils/tests/test_waiting.py +25 -0
  705. cumulusci/utils/version_strings.py +391 -0
  706. cumulusci/utils/waiting.py +42 -0
  707. cumulusci/utils/xml/__init__.py +91 -0
  708. cumulusci/utils/xml/metadata_tree.py +299 -0
  709. cumulusci/utils/xml/robot_xml.py +114 -0
  710. cumulusci/utils/xml/salesforce_encoding.py +100 -0
  711. cumulusci/utils/xml/test/test_metadata_tree.py +251 -0
  712. cumulusci/utils/xml/test/test_salesforce_encoding.py +173 -0
  713. cumulusci/utils/yaml/cumulusci_yml.py +401 -0
  714. cumulusci/utils/yaml/model_parser.py +156 -0
  715. cumulusci/utils/yaml/safer_loader.py +74 -0
  716. cumulusci/utils/yaml/tests/bad_cci.yml +5 -0
  717. cumulusci/utils/yaml/tests/cassettes/TestCumulusciYml.test_validate_url__with_errors.yaml +20 -0
  718. cumulusci/utils/yaml/tests/test_cumulusci_yml.py +286 -0
  719. cumulusci/utils/yaml/tests/test_model_parser.py +175 -0
  720. cumulusci/utils/yaml/tests/test_safer_loader.py +88 -0
  721. cumulusci/utils/ziputils.py +61 -0
  722. cumulusci/vcs/base.py +143 -0
  723. cumulusci/vcs/bootstrap.py +272 -0
  724. cumulusci/vcs/github/__init__.py +24 -0
  725. cumulusci/vcs/github/adapter.py +689 -0
  726. cumulusci/vcs/github/release_notes/generator.py +219 -0
  727. cumulusci/vcs/github/release_notes/parser.py +151 -0
  728. cumulusci/vcs/github/release_notes/provider.py +143 -0
  729. cumulusci/vcs/github/service.py +569 -0
  730. cumulusci/vcs/github/tests/test_adapter.py +138 -0
  731. cumulusci/vcs/github/tests/test_service.py +408 -0
  732. cumulusci/vcs/models.py +586 -0
  733. cumulusci/vcs/tests/conftest.py +41 -0
  734. cumulusci/vcs/tests/dummy_service.py +241 -0
  735. cumulusci/vcs/tests/test_vcs_base.py +687 -0
  736. cumulusci/vcs/tests/test_vcs_bootstrap.py +727 -0
  737. cumulusci/vcs/utils/__init__.py +31 -0
  738. cumulusci/vcs/vcs_source.py +287 -0
  739. cumulusci_plus-5.0.0.dist-info/METADATA +145 -0
  740. cumulusci_plus-5.0.0.dist-info/RECORD +744 -0
  741. cumulusci_plus-5.0.0.dist-info/WHEEL +4 -0
  742. cumulusci_plus-5.0.0.dist-info/entry_points.txt +3 -0
  743. cumulusci_plus-5.0.0.dist-info/licenses/AUTHORS.rst +41 -0
  744. cumulusci_plus-5.0.0.dist-info/licenses/LICENSE +30 -0
@@ -0,0 +1,691 @@
1
+ import gzip
2
+ import json
3
+ import re
4
+ from itertools import chain
5
+ from pathlib import Path
6
+ from unittest.mock import patch
7
+
8
+ import pytest
9
+ import responses
10
+ import yaml
11
+ from sqlalchemy import create_engine
12
+
13
+ from cumulusci.salesforce_api.org_schema import (
14
+ BufferedSession,
15
+ Filters,
16
+ get_org_schema,
17
+ zip_database,
18
+ )
19
+ from cumulusci.salesforce_api.org_schema_models import Base, SObject
20
+ from cumulusci.tasks.bulkdata.tests.integration_test_utils import (
21
+ ensure_accounts,
22
+ ensure_records,
23
+ )
24
+ from cumulusci.tests.util import FakeUnreliableRequestHandler
25
+ from cumulusci.utils.http.multi_request import HTTPRequestError
26
+
27
+ ensure_accounts = ensure_accounts # fixes 4 lint errors at once. Don't hate the player, hate the game.
28
+ ensure_records = ensure_records
29
+
30
+
31
+ class FakeSF:
32
+ """A pretend version of Salesforce for composite testing"""
33
+
34
+ sf_version = "99.0"
35
+
36
+ base_url = "https://innovation-page-2420-dev-ed.cs50.my.salesforce.com/"
37
+ headers = {}
38
+
39
+ def describe(self):
40
+ defaults = {"createable": True, "deletable": True, "layoutable": True}
41
+
42
+ def fake_obj_desc(name, **props):
43
+ return {**defaults, **props, "name": name}
44
+
45
+ return {
46
+ "encoding": "UTF-8",
47
+ "maxBatchSize": 200,
48
+ "sobjects": [
49
+ fake_obj_desc("Account"),
50
+ fake_obj_desc("Contact"),
51
+ fake_obj_desc("PermissionSet", layoutable=False),
52
+ fake_obj_desc("Campaign"),
53
+ fake_obj_desc("Case"),
54
+ ],
55
+ }
56
+
57
+
58
+ def makeFakeCompositeParallelSalesforce(responses):
59
+ class FakeCompositeParallelSalesforce:
60
+ def __init__(self, sf, *args, **kwargs):
61
+ self.sf = sf
62
+
63
+ def __enter__(self, *args, **kwargs):
64
+ return self
65
+
66
+ def __exit__(self, *args, **kwargs):
67
+ pass
68
+
69
+ def do_composite_requests(self, requests):
70
+ refIds = set(req["referenceId"] for req in requests)
71
+ return (
72
+ response
73
+ for response in responses()
74
+ if response["referenceId"] in refIds
75
+ ), []
76
+
77
+ return FakeCompositeParallelSalesforce
78
+
79
+
80
+ def uncached_responses(responses):
81
+ """Pretend to load uncached responses. Use a VCR cassette instead"""
82
+
83
+ def parse_composite_response(interaction: dict):
84
+ response_body = interaction["response"]["body"]["string"]
85
+ struct = json.loads(response_body)
86
+ return struct["compositeResponse"]
87
+
88
+ return chain.from_iterable(
89
+ parse_composite_response(interaction)
90
+ for interaction in responses["interactions"]
91
+ if interaction["request"]["uri"].endswith("/composite")
92
+ )
93
+
94
+
95
+ cached_responses = [
96
+ {"body": None, "httpHeaders": {}, "httpStatusCode": 304, "referenceId": "noId"}
97
+ ] * 4
98
+
99
+
100
+ def mock_return_uncached_responses(cassette_data):
101
+ return patch(
102
+ "cumulusci.salesforce_api.org_schema.CompositeParallelSalesforce",
103
+ makeFakeCompositeParallelSalesforce(lambda: uncached_responses(cassette_data)),
104
+ )
105
+
106
+
107
+ def mock_return_cached_responses():
108
+ return patch(
109
+ "cumulusci.salesforce_api.org_schema.CompositeParallelSalesforce",
110
+ makeFakeCompositeParallelSalesforce(lambda: cached_responses.copy()),
111
+ )
112
+
113
+
114
+ class TestOrgSchema:
115
+ def setup_class(self):
116
+ cassette = (
117
+ Path(__file__).parent / "cassettes/ManualEdit_test_describe_to_sql.yaml"
118
+ )
119
+ with open(cassette) as f:
120
+ self.cassette_data = yaml.safe_load(f)
121
+
122
+ def validate_schema_data(self, schema):
123
+ assert len(list(schema.sobjects)) == 4, [obj.name for obj in schema.sobjects]
124
+ assert schema["Account"].createable is True
125
+ assert schema["Account"].fields["Id"].aggregatable is True
126
+ assert schema["Account"].labelPlural == "Accounts"
127
+ account_desc = schema["Account"]
128
+ for name, value in account_data.items():
129
+ if name != "fields":
130
+ assert account_desc[name] == value, (
131
+ name,
132
+ value,
133
+ account_desc[name],
134
+ )
135
+ for field in account_data["fields"]:
136
+ db_field = account_desc["fields"][field["name"]]
137
+ for name, value in field.items():
138
+ assert db_field[name] == value, (
139
+ name,
140
+ value,
141
+ db_field[name],
142
+ )
143
+
144
+ def test_describe_to_sql(self, fallback_org_config):
145
+ # Step 1: Pretend to download data from server
146
+ org_config = fallback_org_config()
147
+ with mock_return_uncached_responses(self.cassette_data):
148
+ with get_org_schema(FakeSF(), org_config) as schema:
149
+ self.validate_schema_data(schema)
150
+
151
+ # Step 2: Call the server again.
152
+ # This time it has nothing new to tell us so nothing
153
+ # should be written to the local database except an updated
154
+ # LastModifiedDate.
155
+ with mock_return_cached_responses(), patch(
156
+ "cumulusci.salesforce_api.org_schema.create_row"
157
+ ) as create_row, get_org_schema(FakeSF(), org_config) as schema:
158
+ self.validate_schema_data(schema)
159
+ for call in create_row.mock_calls:
160
+ assert call[1][1].__name__ == "FileMetadata"
161
+
162
+ def test_errors(self, org_config):
163
+ with mock_return_uncached_responses(self.cassette_data), get_org_schema(
164
+ FakeSF(), org_config
165
+ ) as schema:
166
+ with pytest.raises(KeyError):
167
+ schema["Foo"]
168
+
169
+ def test_forced_recache(self, org_config):
170
+ with mock_return_uncached_responses(self.cassette_data):
171
+ with get_org_schema(FakeSF(), org_config) as schema:
172
+ schema.session.execute("insert into sobjects (name) values ('Foo')")
173
+ assert "Foo" in [obj.name for obj in schema.session.query(SObject.name)]
174
+ schema.session._real_commit__()
175
+ dbpath = schema.engine.url.translate_connect_args()["database"]
176
+ zip_database(Path(dbpath), schema.path)
177
+ with get_org_schema(FakeSF(), org_config) as schema:
178
+ assert "Foo" in [obj.name for obj in schema.session.query(SObject.name)]
179
+ with get_org_schema(FakeSF(), org_config, force_recache=True) as schema:
180
+ assert "Foo" not in [
181
+ obj.name for obj in schema.session.query(SObject.name)
182
+ ]
183
+
184
+ def test_dict_like(self, org_config):
185
+ with mock_return_uncached_responses(self.cassette_data):
186
+ with get_org_schema(FakeSF(), org_config) as schema:
187
+ assert schema["Account"]
188
+ assert "Account" in schema
189
+ assert sorted(schema.keys())[0] == "Account"
190
+ assert (
191
+ sorted(schema.values(), key=lambda x: x.name)[0].name == "Account"
192
+ )
193
+ a, b = sorted(schema.items())[0]
194
+ assert a == "Account"
195
+ assert "Account" in schema.keys()
196
+ assert "<Schema" in repr(schema)
197
+
198
+ def test_misuse(self, org_config):
199
+ """What if the user keeps a reference to the schema"""
200
+ with mock_return_uncached_responses(self.cassette_data):
201
+ with get_org_schema(FakeSF(), org_config) as schema:
202
+ pass
203
+ with pytest.raises(IOError):
204
+ schema.session.commit()
205
+
206
+ def test_corrupted_schema(self, caplog, org_config):
207
+ "What if the schema GZip is corrupted?"
208
+ with mock_return_uncached_responses(self.cassette_data):
209
+ with get_org_schema(FakeSF(), org_config) as schema:
210
+ assert "Account" in schema
211
+ path = schema.path
212
+ assert not caplog.text
213
+ with open(path, "w") as p:
214
+ p.write("xxx")
215
+
216
+ with get_org_schema(FakeSF(), org_config) as schema:
217
+ assert "Account" in schema
218
+ assert caplog.text
219
+
220
+ def test_corrupted_schema__sqlite(self, caplog, org_config):
221
+ "What if the schema inside the gzip is corrupted"
222
+ with mock_return_uncached_responses(self.cassette_data):
223
+ with get_org_schema(FakeSF(), org_config) as schema:
224
+ assert "Account" in schema
225
+ path = schema.path
226
+ assert not caplog.text
227
+ with open(path, "wb") as p:
228
+ with gzip.GzipFile(fileobj=p, mode="w") as gzipped:
229
+ gzipped.write(b"xxx")
230
+
231
+ with get_org_schema(FakeSF(), org_config) as schema:
232
+ assert "Account" in schema
233
+ assert caplog.text
234
+
235
+ @responses.activate
236
+ def test_http_level_errors(self, sf, org_config, global_describe):
237
+ # This is a bit complex. We're trying to test what happens
238
+ # when a composite request fails. That should trigger a retry
239
+ # of each item in the request. So we have to provide responses
240
+ # at the level of the original describe, the composite request and
241
+ # the single requests.
242
+
243
+ # use just a subset for test perf reasons
244
+ responses.add("GET", f"{sf.base_url}sobjects", json=global_describe(50))
245
+
246
+ sobject_describes = json.loads(
247
+ self.cassette_data["interactions"][0]["response"]["body"]["string"]
248
+ )
249
+ composite_handler = FakeUnreliableRequestHandler(sobject_describes)
250
+ responses.add_callback(
251
+ method="POST",
252
+ url=f"{sf.base_url}composite",
253
+ callback=composite_handler.request_callback,
254
+ content_type="application/json",
255
+ )
256
+
257
+ class SingleSobjFakeUnreliableRequestHandler(FakeUnreliableRequestHandler):
258
+ def real_reliable_request_callback(self, request):
259
+ sobject = request.url.split("/")[-2]
260
+ fake_describe = sobject_describes["compositeResponse"][0]["body"].copy()
261
+ fake_describe["name"] = sobject
262
+ return fake_describe
263
+
264
+ single_sobj_handler = SingleSobjFakeUnreliableRequestHandler()
265
+ responses.add_callback(
266
+ method="GET",
267
+ url=re.compile(r"https://.*/sobjects/.*/describe"),
268
+ callback=single_sobj_handler.request_callback,
269
+ content_type="application/json",
270
+ )
271
+
272
+ with get_org_schema(sf, org_config) as schema:
273
+ assert "Account" in schema
274
+ assert schema["Account"].labelPlural
275
+
276
+ # check that the single_sobj_handler was called because of
277
+ # the timeout. If you comment out the branch line
278
+ # that raises the exception then this assertion will fail.
279
+ assert single_sobj_handler.counter > 0
280
+
281
+ @responses.activate
282
+ def test_http_level_errors_after_retries(self, sf, org_config, global_describe):
283
+ # This is a bit complex. We're trying to test what happens
284
+ # when a composite request fails. That should trigger a retry
285
+ # of each item in the request. So we have to provide responses
286
+ # at the level of the original describe, the composite request and
287
+ # the single requests.
288
+
289
+ # use just a subset for test perf reasons
290
+ responses.add("GET", f"{sf.base_url}sobjects", json=global_describe(50))
291
+
292
+ sobject_describes = json.loads(
293
+ self.cassette_data["interactions"][0]["response"]["body"]["string"]
294
+ )
295
+ composite_handler = FakeUnreliableRequestHandler(sobject_describes)
296
+ responses.add_callback(
297
+ method="POST",
298
+ url=f"{sf.base_url}composite",
299
+ callback=composite_handler.request_callback,
300
+ content_type="application/json",
301
+ )
302
+
303
+ def throw_exception(*args, **kwargs):
304
+ raise AssertionError()
305
+
306
+ responses.add_callback(
307
+ method="GET",
308
+ url=re.compile(r"https://.*/sobjects/.*/describe"),
309
+ callback=throw_exception,
310
+ content_type="application/json",
311
+ )
312
+
313
+ with pytest.raises(AssertionError):
314
+ with get_org_schema(sf, org_config):
315
+ pass
316
+
317
+ def test_minimal_schema(self, sf, org_config, vcr):
318
+ with vcr.use_cassette(
319
+ "ManualEditTestDescribeOrg.test_minimal_schema.yaml",
320
+ record_mode="none",
321
+ ), get_org_schema(
322
+ sf,
323
+ org_config,
324
+ included_objects=["Account", "Opportunity"],
325
+ force_recache=True,
326
+ ) as schema:
327
+ assert list(schema.keys()) == ["Account", "Opportunity"]
328
+
329
+ def test_filter_by_name(self, sf, org_config):
330
+ with mock_return_uncached_responses(self.cassette_data):
331
+ with get_org_schema(
332
+ FakeSF(),
333
+ org_config,
334
+ ) as schema:
335
+ assert "Account" in schema
336
+ assert "PermissionSet" in schema
337
+ with get_org_schema(
338
+ FakeSF(), org_config, patterns_to_ignore=["%accou%"]
339
+ ) as schema:
340
+ assert "Account" not in schema
341
+ assert "PermissionSet" in schema
342
+
343
+ def test_reuse_query(self, sf, org_config):
344
+ with mock_return_uncached_responses(self.cassette_data):
345
+ with get_org_schema(
346
+ FakeSF(), org_config, filters=[Filters.extractable]
347
+ ) as schema:
348
+ assert len(tuple(schema.sobjects)) == len(tuple(schema.sobjects))
349
+
350
+ def test_filter_not_extractable_implicit(self, sf, org_config):
351
+ """Permission Sets are an example of an object considered "not extractable" """
352
+ with mock_return_uncached_responses(self.cassette_data):
353
+ with get_org_schema(
354
+ FakeSF(), org_config, filters=[Filters.extractable]
355
+ ) as schema:
356
+ assert "Account" in schema
357
+ assert "PermissionSet" not in schema
358
+
359
+ def test_filter_by_arbitrary_property(self, sf, org_config):
360
+ """Permission Sets are an example of an object considered "not extractable" """
361
+ with mock_return_uncached_responses(self.cassette_data):
362
+ with get_org_schema(
363
+ FakeSF(), org_config, filters=[Filters.layoutable]
364
+ ) as schema:
365
+ assert "Account" in schema
366
+ assert "PermissionSet" not in schema
367
+
368
+ def test_cached_schema_can_be_filtered(self, sf, org_config):
369
+ """Permission Sets are an example of an object considered "not extractable" """
370
+ with mock_return_uncached_responses(self.cassette_data):
371
+ with get_org_schema(FakeSF(), org_config) as schema:
372
+ assert "Account" in schema
373
+ assert "PermissionSet" in schema
374
+
375
+ with get_org_schema(
376
+ FakeSF(), org_config, filters=[Filters.layoutable]
377
+ ) as schema:
378
+ assert schema.from_cache
379
+ assert "Account" in schema
380
+ assert "PermissionSet" not in schema
381
+ # it should be still in there but hidden
382
+ assert schema.session.query(SObject).filter(
383
+ SObject.name == "PermissionSet"
384
+ )
385
+
386
+ with get_org_schema(FakeSF(), org_config) as schema:
387
+ assert schema.from_cache
388
+ assert "Account" in schema
389
+ assert "PermissionSet" in schema
390
+
391
+ def test_error_populate_without_include_counts(self, sf, org_config):
392
+ with mock_return_uncached_responses(self.cassette_data):
393
+ with pytest.raises(AssertionError, match="include_counts"):
394
+ with get_org_schema(
395
+ FakeSF(), org_config, filters=[Filters.populated]
396
+ ) as schema:
397
+ assert "Account" in schema
398
+ assert "PermissionSet" not in schema
399
+
400
+ def test_filter_by_populated(self, sf, org_config):
401
+ with mock_return_uncached_responses(self.cassette_data):
402
+ with patch(
403
+ "cumulusci.salesforce_api.org_schema.count_sobjects",
404
+ lambda *args: (
405
+ {"Account": 10, "Contact": 5, "PermissionSet": 0},
406
+ [],
407
+ [],
408
+ ),
409
+ ), get_org_schema(
410
+ FakeSF(), org_config, include_counts=True, filters=[Filters.populated]
411
+ ) as schema:
412
+ assert "Account" in schema
413
+ assert "PermissionSet" not in schema
414
+
415
+ def test_error_while_counting(self, sf, org_config, caplog):
416
+ with mock_return_uncached_responses(self.cassette_data):
417
+ with patch(
418
+ "cumulusci.salesforce_api.org_schema.count_sobjects",
419
+ lambda *args: (
420
+ {"Account": 10, "Contact": 5, "PermissionSet": 0},
421
+ [],
422
+ [HTTPRequestError("Error! Apostasy!", None)] * 15,
423
+ ),
424
+ ), get_org_schema(
425
+ FakeSF(), org_config, include_counts=True, filters=[Filters.populated]
426
+ ):
427
+ pass
428
+ assert "Apostasy" in caplog.text
429
+ assert "more counting errors suppressed" in caplog.text
430
+
431
+ def test_old_schema_version(self, sf, org_config, caplog):
432
+ with mock_return_uncached_responses(self.cassette_data):
433
+ with patch(
434
+ "cumulusci.salesforce_api.org_schema.Schema.CurrentFormatVersion", 7
435
+ ), get_org_schema(
436
+ FakeSF(), org_config, include_counts=True, filters=[Filters.populated]
437
+ ) as schema:
438
+ assert schema.version == 7
439
+
440
+ class FakeSilentMigration(Exception):
441
+ called = False
442
+
443
+ def __init__(self, *args, **kwargs):
444
+ self.__class__.called = True
445
+
446
+ with patch(
447
+ "cumulusci.salesforce_api.org_schema.SilentMigration",
448
+ FakeSilentMigration,
449
+ ), patch(
450
+ "cumulusci.salesforce_api.org_schema.Schema.CurrentFormatVersion", 8
451
+ ), get_org_schema(
452
+ FakeSF(), org_config, include_counts=True, filters=[Filters.populated]
453
+ ) as schema:
454
+ assert schema.version == 8
455
+ assert FakeSilentMigration.called
456
+
457
+ @pytest.mark.needs_org()
458
+ def test_schema_populated_real(self, sf, org_config, ensure_records):
459
+ starting_records = {
460
+ "Entitlement": [], # Delete all entitlements so we can delete accounts
461
+ "Account": [{"Name": "XYZZY"}],
462
+ "Opportunity": [], # 0 opportunities
463
+ }
464
+ with ensure_records(starting_records):
465
+ with get_org_schema(
466
+ sf,
467
+ org_config,
468
+ include_counts=True,
469
+ filters=[Filters.populated],
470
+ included_objects=["Account", "Contact", "Opportunity"],
471
+ ) as schema:
472
+ assert "Account" in schema, schema.keys()
473
+ assert "Case" not in schema, schema.keys() # not in included_objects
474
+ assert (
475
+ "Opportunity" not in schema
476
+ ), schema.keys() # because not populated
477
+
478
+ # Create one case and ensure it is noticed.
479
+ with ensure_records({"Case": [{}]}):
480
+ with get_org_schema(
481
+ sf, org_config, include_counts=True, filters=[Filters.populated]
482
+ ) as schema:
483
+ assert "Account" in schema, schema.keys()
484
+ assert "Case" in schema, schema.keys()
485
+ assert (
486
+ "Opportunity" not in schema
487
+ ), schema.keys() # because not populated
488
+
489
+
490
+ @pytest.mark.needs_org() # too hard to make these VCR-compatible due to data volume
491
+ class TestOrgSchemaIntegration:
492
+ def validate_real_schema_data(self, schema):
493
+ assert len(list(schema.sobjects)) > 800
494
+ assert schema["Account"].createable is True
495
+ assert schema["Account"].fields["Id"].aggregatable is True
496
+ assert schema["Account"].labelPlural == "Accounts"
497
+ account_desc = schema["Account"]
498
+ assert account_desc.deletable is True
499
+ assert account_desc.undeletable is True
500
+ assert account_desc.keyPrefix == "001"
501
+
502
+ def test_cache_schema(self, sf, org_config):
503
+ with get_org_schema(sf, org_config, force_recache=True) as schema:
504
+ self.validate_real_schema_data(schema)
505
+ assert not schema.from_cache
506
+ with get_org_schema(sf, org_config) as schema:
507
+ self.validate_real_schema_data(schema)
508
+ assert schema.from_cache
509
+
510
+ def test_minimal_schema(self, sf, org_config):
511
+ with get_org_schema(
512
+ sf,
513
+ org_config,
514
+ included_objects=["Account", "Opportunity"],
515
+ force_recache=True,
516
+ ) as schema:
517
+ assert list(schema.keys()) == ["Account", "Opportunity"]
518
+
519
+
520
+ class TestBufferedSession:
521
+ def test_buffer_empties(self):
522
+ engine = create_engine("sqlite:///")
523
+ Base.metadata.bind = engine
524
+ Base.metadata.create_all()
525
+ bs = BufferedSession(engine, Base.metadata, 5)
526
+ with patch.object(bs, "flush") as flush:
527
+ for i in range(0, 3):
528
+ bs.write_single_row("sobjects", {"name": str(i)})
529
+ assert not flush.mock_calls
530
+ for i in range(0, 3):
531
+ bs.write_single_row("sobjects", {"name": str(i)})
532
+
533
+ assert flush.mock_calls
534
+
535
+
536
+ account_data = {
537
+ "actionOverrides": (),
538
+ "activateable": False,
539
+ "compactLayoutable": True,
540
+ "createable": True,
541
+ "custom": False,
542
+ "customSetting": False,
543
+ "deepCloneable": False,
544
+ "defaultImplementation": None,
545
+ "deletable": True,
546
+ "deprecatedAndHidden": False,
547
+ "extendedBy": None,
548
+ "extendsInterfaces": None,
549
+ "feedEnabled": True,
550
+ "fields": [
551
+ {
552
+ "aggregatable": True,
553
+ "aiPredictionField": False,
554
+ "autoNumber": False,
555
+ "byteLength": 18,
556
+ "calculated": False,
557
+ "calculatedFormula": None,
558
+ "cascadeDelete": False,
559
+ "caseSensitive": False,
560
+ "compoundFieldName": None,
561
+ "controllerName": None,
562
+ "createable": False,
563
+ "custom": False,
564
+ "defaultValue": None,
565
+ "defaultValueFormula": None,
566
+ "defaultedOnCreate": True,
567
+ "dependentPicklist": False,
568
+ "deprecatedAndHidden": False,
569
+ "digits": 0,
570
+ "displayLocationInDecimal": False,
571
+ "encrypted": False,
572
+ "externalId": False,
573
+ "extraTypeInfo": None,
574
+ "filterable": True,
575
+ "filteredLookupInfo": None,
576
+ "formulaTreatNullNumberAsZero": False,
577
+ "groupable": True,
578
+ "highScaleNumber": False,
579
+ "htmlFormatted": False,
580
+ "idLookup": True,
581
+ "inlineHelpText": None,
582
+ "label": "Account ID",
583
+ "length": 18,
584
+ "mask": None,
585
+ "maskType": None,
586
+ "name": "Id",
587
+ "nameField": False,
588
+ "namePointing": False,
589
+ "nillable": False,
590
+ "permissionable": False,
591
+ "picklistValues": [],
592
+ "polymorphicForeignKey": False,
593
+ "precision": 0,
594
+ "queryByDistance": False,
595
+ "referenceTargetField": None,
596
+ "referenceTo": [],
597
+ "relationshipName": None,
598
+ "relationshipOrder": None,
599
+ "restrictedDelete": False,
600
+ "restrictedPicklist": False,
601
+ "scale": 0,
602
+ "searchPrefilterable": False,
603
+ "soapType": "tns:ID",
604
+ "sortable": True,
605
+ "type": "id",
606
+ "unique": False,
607
+ "updateable": False,
608
+ "writeRequiresMasterRead": False,
609
+ }
610
+ ],
611
+ "hasSubtypes": False,
612
+ "implementedBy": None,
613
+ "implementsInterfaces": None,
614
+ "isInterface": False,
615
+ "isSubtype": False,
616
+ "keyPrefix": "001",
617
+ "label": "Account",
618
+ "labelPlural": "Accounts",
619
+ "layoutable": True,
620
+ "listviewable": None,
621
+ "lookupLayoutable": None,
622
+ "mergeable": True,
623
+ "mruEnabled": True,
624
+ "name": "Account",
625
+ "namedLayoutInfos": (),
626
+ "networkScopeFieldName": None,
627
+ "queryable": True,
628
+ "replicateable": True,
629
+ "retrieveable": True,
630
+ "searchLayoutable": True,
631
+ "searchable": True,
632
+ "sobjectDescribeOption": "FULL",
633
+ "triggerable": True,
634
+ "undeletable": True,
635
+ "updateable": True,
636
+ "urls": {"a": "b"},
637
+ }
638
+
639
+
640
+ ## These are helper functions for managing the sample data used above.
641
+ ## The functions aren't called above, but test maintainers could use
642
+ ## them to update sample data.
643
+
644
+
645
+ def reduce_data(filename):
646
+ """A function for reducing Casettes of Describes() to the bare minimum
647
+
648
+ Note that the deep_describe infrastructure uses threads and may not
649
+ always play nicely with vcr. It may take some experimentation and cutting
650
+ and pasting to get a decent vcr cassette to use as the input of this
651
+ function."""
652
+ relevant_objs = ["Account", "Contact", "Opportunity", "Campaign"]
653
+ data = yaml.safe_load(open(filename))
654
+
655
+ for interaction in data["interactions"]:
656
+ url = interaction["request"].get("uri")
657
+ if url and url.endswith("composite"):
658
+ reduce_composite(interaction)
659
+ elif url:
660
+ assert url.endswith("sobjects"), url
661
+ reduce_describe(interaction, relevant_objs)
662
+
663
+ yaml.safe_dump(data, open(filename + ".out.yaml", "w"))
664
+
665
+
666
+ def reduce_composite(interaction):
667
+ results = json.loads(interaction["response"]["body"]["string"])["compositeResponse"]
668
+ sobjs = [result["body"] for result in results]
669
+ for sobj in sobjs:
670
+ sobj["fields"] = sobj["fields"][0:1]
671
+ for key in ["urls", "childRelationships", "recordTypeInfos", "supportedScopes"]:
672
+ if sobj.get(key):
673
+ del sobj[key]
674
+
675
+ interaction["response"]["body"]["string"] = json.dumps(
676
+ {"compositeResponse": results}
677
+ )
678
+
679
+
680
+ def reduce_describe(interaction, relevant_objs):
681
+ sobjs = json.loads(interaction["response"]["body"]["string"])["sobjects"]
682
+ results = []
683
+ for sobj in sobjs:
684
+ if sobj["name"] not in relevant_objs:
685
+ continue
686
+ for key in ["urls", "childRelationships", "recordTypeInfos", "supportedScopes"]:
687
+ if sobj.get(key):
688
+ del sobj[key]
689
+ results.append(sobj)
690
+
691
+ interaction["response"]["body"]["string"] = json.dumps({"sobjects": results})