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.
- cumulusci/__about__.py +1 -0
- cumulusci/__init__.py +22 -0
- cumulusci/__main__.py +3 -0
- cumulusci/cli/__init__.py +0 -0
- cumulusci/cli/cci.py +244 -0
- cumulusci/cli/error.py +125 -0
- cumulusci/cli/flow.py +185 -0
- cumulusci/cli/logger.py +72 -0
- cumulusci/cli/org.py +692 -0
- cumulusci/cli/plan.py +181 -0
- cumulusci/cli/project.py +391 -0
- cumulusci/cli/robot.py +116 -0
- cumulusci/cli/runtime.py +190 -0
- cumulusci/cli/service.py +521 -0
- cumulusci/cli/task.py +295 -0
- cumulusci/cli/tests/__init__.py +0 -0
- cumulusci/cli/tests/test_cci.py +545 -0
- cumulusci/cli/tests/test_error.py +170 -0
- cumulusci/cli/tests/test_flow.py +276 -0
- cumulusci/cli/tests/test_logger.py +25 -0
- cumulusci/cli/tests/test_org.py +1438 -0
- cumulusci/cli/tests/test_plan.py +245 -0
- cumulusci/cli/tests/test_project.py +235 -0
- cumulusci/cli/tests/test_robot.py +177 -0
- cumulusci/cli/tests/test_runtime.py +197 -0
- cumulusci/cli/tests/test_service.py +853 -0
- cumulusci/cli/tests/test_task.py +266 -0
- cumulusci/cli/tests/test_ui.py +310 -0
- cumulusci/cli/tests/test_utils.py +122 -0
- cumulusci/cli/tests/utils.py +52 -0
- cumulusci/cli/ui.py +234 -0
- cumulusci/cli/utils.py +150 -0
- cumulusci/conftest.py +181 -0
- cumulusci/core/__init__.py +0 -0
- cumulusci/core/config/BaseConfig.py +5 -0
- cumulusci/core/config/BaseTaskFlowConfig.py +5 -0
- cumulusci/core/config/OrgConfig.py +5 -0
- cumulusci/core/config/ScratchOrgConfig.py +5 -0
- cumulusci/core/config/__init__.py +125 -0
- cumulusci/core/config/base_config.py +111 -0
- cumulusci/core/config/base_task_flow_config.py +82 -0
- cumulusci/core/config/marketing_cloud_service_config.py +83 -0
- cumulusci/core/config/oauth2_service_config.py +17 -0
- cumulusci/core/config/org_config.py +604 -0
- cumulusci/core/config/project_config.py +782 -0
- cumulusci/core/config/scratch_org_config.py +251 -0
- cumulusci/core/config/sfdx_org_config.py +220 -0
- cumulusci/core/config/tests/_test_config_backwards_compatibility.py +33 -0
- cumulusci/core/config/tests/test_config.py +1895 -0
- cumulusci/core/config/tests/test_config_expensive.py +839 -0
- cumulusci/core/config/tests/test_config_util.py +91 -0
- cumulusci/core/config/universal_config.py +88 -0
- cumulusci/core/config/util.py +18 -0
- cumulusci/core/datasets.py +303 -0
- cumulusci/core/debug.py +33 -0
- cumulusci/core/dependencies/__init__.py +55 -0
- cumulusci/core/dependencies/base.py +561 -0
- cumulusci/core/dependencies/dependencies.py +273 -0
- cumulusci/core/dependencies/github.py +177 -0
- cumulusci/core/dependencies/github_resolvers.py +244 -0
- cumulusci/core/dependencies/resolvers.py +580 -0
- cumulusci/core/dependencies/tests/__init__.py +0 -0
- cumulusci/core/dependencies/tests/conftest.py +385 -0
- cumulusci/core/dependencies/tests/test_dependencies.py +950 -0
- cumulusci/core/dependencies/tests/test_github.py +83 -0
- cumulusci/core/dependencies/tests/test_resolvers.py +1027 -0
- cumulusci/core/dependencies/utils.py +13 -0
- cumulusci/core/enums.py +11 -0
- cumulusci/core/exceptions.py +311 -0
- cumulusci/core/flowrunner.py +888 -0
- cumulusci/core/github.py +665 -0
- cumulusci/core/keychain/__init__.py +24 -0
- cumulusci/core/keychain/base_project_keychain.py +441 -0
- cumulusci/core/keychain/encrypted_file_project_keychain.py +945 -0
- cumulusci/core/keychain/environment_project_keychain.py +7 -0
- cumulusci/core/keychain/serialization.py +152 -0
- cumulusci/core/keychain/subprocess_keychain.py +24 -0
- cumulusci/core/keychain/tests/conftest.py +50 -0
- cumulusci/core/keychain/tests/test_base_project_keychain.py +299 -0
- cumulusci/core/keychain/tests/test_encrypted_file_project_keychain.py +1228 -0
- cumulusci/core/metadeploy/__init__.py +0 -0
- cumulusci/core/metadeploy/api.py +88 -0
- cumulusci/core/metadeploy/plans.py +25 -0
- cumulusci/core/metadeploy/tests/test_api.py +276 -0
- cumulusci/core/runtime.py +115 -0
- cumulusci/core/sfdx.py +162 -0
- cumulusci/core/source/__init__.py +16 -0
- cumulusci/core/source/github.py +50 -0
- cumulusci/core/source/local_folder.py +35 -0
- cumulusci/core/source_transforms/__init__.py +0 -0
- cumulusci/core/source_transforms/tests/test_transforms.py +1091 -0
- cumulusci/core/source_transforms/transforms.py +532 -0
- cumulusci/core/tasks.py +404 -0
- cumulusci/core/template_utils.py +59 -0
- cumulusci/core/tests/__init__.py +0 -0
- cumulusci/core/tests/cassettes/TestDatasetsE2E.test_datasets_e2e.yaml +215 -0
- cumulusci/core/tests/cassettes/TestDatasetsE2E.test_datasets_extract_standard_objects.yaml +199 -0
- cumulusci/core/tests/cassettes/TestDatasetsE2E.test_datasets_read_explicit_extract_declaration.yaml +3 -0
- cumulusci/core/tests/fake_remote_repo/cumulusci.yml +32 -0
- cumulusci/core/tests/fake_remote_repo/tasks/directory/example_2.py +6 -0
- cumulusci/core/tests/fake_remote_repo/tasks/example.py +43 -0
- cumulusci/core/tests/fake_remote_repo_2/cumulusci.yml +11 -0
- cumulusci/core/tests/fake_remote_repo_2/tasks/example_3.py +6 -0
- cumulusci/core/tests/test_datasets_e2e.py +386 -0
- cumulusci/core/tests/test_exceptions.py +11 -0
- cumulusci/core/tests/test_flowrunner.py +836 -0
- cumulusci/core/tests/test_github.py +942 -0
- cumulusci/core/tests/test_sfdx.py +138 -0
- cumulusci/core/tests/test_source.py +678 -0
- cumulusci/core/tests/test_tasks.py +262 -0
- cumulusci/core/tests/test_utils.py +141 -0
- cumulusci/core/tests/test_utils_merge_config.py +276 -0
- cumulusci/core/tests/test_versions.py +76 -0
- cumulusci/core/tests/untrusted_repo_child/cumulusci.yml +7 -0
- cumulusci/core/tests/untrusted_repo_child/tasks/untrusted_child.py +6 -0
- cumulusci/core/tests/untrusted_repo_parent/cumulusci.yml +26 -0
- cumulusci/core/tests/untrusted_repo_parent/tasks/untrusted_parent.py +6 -0
- cumulusci/core/tests/utils.py +116 -0
- cumulusci/core/tests/yaml/global.yaml +0 -0
- cumulusci/core/utils.py +402 -0
- cumulusci/core/versions.py +149 -0
- cumulusci/cumulusci.yml +1621 -0
- cumulusci/files/admin_profile.xml +20 -0
- cumulusci/files/delete_excludes.txt +424 -0
- cumulusci/files/templates/project/README.md +12 -0
- cumulusci/files/templates/project/cumulusci.yml +63 -0
- cumulusci/files/templates/project/dot-gitignore +60 -0
- cumulusci/files/templates/project/mapping.yml +45 -0
- cumulusci/files/templates/project/scratch_def.json +25 -0
- cumulusci/oauth/__init__.py +0 -0
- cumulusci/oauth/client.py +400 -0
- cumulusci/oauth/exceptions.py +9 -0
- cumulusci/oauth/salesforce.py +95 -0
- cumulusci/oauth/tests/__init__.py +0 -0
- cumulusci/oauth/tests/cassettes/test_get_device_code.yaml +22 -0
- cumulusci/oauth/tests/cassettes/test_get_device_oauth_token.yaml +74 -0
- cumulusci/oauth/tests/test_client.py +308 -0
- cumulusci/oauth/tests/test_salesforce.py +46 -0
- cumulusci/plugins/__init__.py +3 -0
- cumulusci/plugins/plugin_base.py +93 -0
- cumulusci/plugins/plugin_loader.py +59 -0
- cumulusci/robotframework/CumulusCI.py +340 -0
- cumulusci/robotframework/CumulusCI.robot +7 -0
- cumulusci/robotframework/Performance.py +165 -0
- cumulusci/robotframework/Salesforce.py +936 -0
- cumulusci/robotframework/Salesforce.robot +192 -0
- cumulusci/robotframework/SalesforceAPI.py +416 -0
- cumulusci/robotframework/SalesforcePlaywright.py +220 -0
- cumulusci/robotframework/SalesforcePlaywright.robot +40 -0
- cumulusci/robotframework/__init__.py +2 -0
- cumulusci/robotframework/base_library.py +39 -0
- cumulusci/robotframework/faker_mixin.py +89 -0
- cumulusci/robotframework/form_handlers.py +222 -0
- cumulusci/robotframework/javascript/cci_init.js +34 -0
- cumulusci/robotframework/javascript/cumulusci.js +4 -0
- cumulusci/robotframework/locator_manager.py +197 -0
- cumulusci/robotframework/locators_56.py +88 -0
- cumulusci/robotframework/locators_57.py +5 -0
- cumulusci/robotframework/pageobjects/BasePageObjects.py +433 -0
- cumulusci/robotframework/pageobjects/ObjectManagerPageObject.py +246 -0
- cumulusci/robotframework/pageobjects/PageObjectLibrary.py +45 -0
- cumulusci/robotframework/pageobjects/PageObjects.py +351 -0
- cumulusci/robotframework/pageobjects/__init__.py +12 -0
- cumulusci/robotframework/pageobjects/baseobjects.py +120 -0
- cumulusci/robotframework/perftests/short/collection_perf.robot +105 -0
- cumulusci/robotframework/tests/CustomObjectTestPage.py +10 -0
- cumulusci/robotframework/tests/FooTestPage.py +8 -0
- cumulusci/robotframework/tests/cumulusci/base.robot +40 -0
- cumulusci/robotframework/tests/cumulusci/bulkdata.robot +38 -0
- cumulusci/robotframework/tests/cumulusci/communities.robot +57 -0
- cumulusci/robotframework/tests/cumulusci/datagen.robot +84 -0
- cumulusci/robotframework/tests/salesforce/TestLibraryA.py +24 -0
- cumulusci/robotframework/tests/salesforce/TestLibraryB.py +20 -0
- cumulusci/robotframework/tests/salesforce/TestListener.py +93 -0
- cumulusci/robotframework/tests/salesforce/api.robot +178 -0
- cumulusci/robotframework/tests/salesforce/browsers.robot +143 -0
- cumulusci/robotframework/tests/salesforce/classic.robot +51 -0
- cumulusci/robotframework/tests/salesforce/create_contact.robot +59 -0
- cumulusci/robotframework/tests/salesforce/faker.robot +68 -0
- cumulusci/robotframework/tests/salesforce/forms.robot +172 -0
- cumulusci/robotframework/tests/salesforce/label_locator.robot +244 -0
- cumulusci/robotframework/tests/salesforce/labels.html +33 -0
- cumulusci/robotframework/tests/salesforce/locators.robot +149 -0
- cumulusci/robotframework/tests/salesforce/pageobjects/base_pageobjects.robot +100 -0
- cumulusci/robotframework/tests/salesforce/pageobjects/example_page_object.py +25 -0
- cumulusci/robotframework/tests/salesforce/pageobjects/listing_page.robot +115 -0
- cumulusci/robotframework/tests/salesforce/pageobjects/objectmanager.robot +74 -0
- cumulusci/robotframework/tests/salesforce/pageobjects/pageobjects.robot +171 -0
- cumulusci/robotframework/tests/salesforce/performance.robot +109 -0
- cumulusci/robotframework/tests/salesforce/playwright/javascript_keywords.robot +33 -0
- cumulusci/robotframework/tests/salesforce/playwright/open_test_browser.robot +48 -0
- cumulusci/robotframework/tests/salesforce/playwright/playwright.robot +24 -0
- cumulusci/robotframework/tests/salesforce/playwright/ui.robot +32 -0
- cumulusci/robotframework/tests/salesforce/populate.robot +89 -0
- cumulusci/robotframework/tests/salesforce/test_testlistener.py +37 -0
- cumulusci/robotframework/tests/salesforce/ui.robot +361 -0
- cumulusci/robotframework/tests/test_cumulusci_library.py +304 -0
- cumulusci/robotframework/tests/test_locator_manager.py +158 -0
- cumulusci/robotframework/tests/test_pageobjects.py +291 -0
- cumulusci/robotframework/tests/test_performance.py +38 -0
- cumulusci/robotframework/tests/test_salesforce.py +79 -0
- cumulusci/robotframework/tests/test_salesforce_locators.py +73 -0
- cumulusci/robotframework/tests/test_template_util.py +53 -0
- cumulusci/robotframework/tests/test_utils.py +106 -0
- cumulusci/robotframework/utils.py +283 -0
- cumulusci/salesforce_api/__init__.py +0 -0
- cumulusci/salesforce_api/exceptions.py +23 -0
- cumulusci/salesforce_api/filterable_objects.py +96 -0
- cumulusci/salesforce_api/mc_soap_envelopes.py +89 -0
- cumulusci/salesforce_api/metadata.py +721 -0
- cumulusci/salesforce_api/org_schema.py +571 -0
- cumulusci/salesforce_api/org_schema_models.py +226 -0
- cumulusci/salesforce_api/package_install.py +265 -0
- cumulusci/salesforce_api/package_zip.py +301 -0
- cumulusci/salesforce_api/rest_deploy.py +148 -0
- cumulusci/salesforce_api/retrieve_profile_api.py +301 -0
- cumulusci/salesforce_api/soap_envelopes.py +177 -0
- cumulusci/salesforce_api/tests/__init__.py +0 -0
- cumulusci/salesforce_api/tests/metadata_test_strings.py +24 -0
- cumulusci/salesforce_api/tests/test_metadata.py +1015 -0
- cumulusci/salesforce_api/tests/test_package_install.py +219 -0
- cumulusci/salesforce_api/tests/test_package_zip.py +380 -0
- cumulusci/salesforce_api/tests/test_rest_deploy.py +264 -0
- cumulusci/salesforce_api/tests/test_retrieve_profile_api.py +337 -0
- cumulusci/salesforce_api/tests/test_utils.py +124 -0
- cumulusci/salesforce_api/utils.py +51 -0
- cumulusci/schema/cumulusci.jsonschema.json +782 -0
- cumulusci/tasks/__init__.py +0 -0
- cumulusci/tasks/apex/__init__.py +0 -0
- cumulusci/tasks/apex/anon.py +157 -0
- cumulusci/tasks/apex/batch.py +180 -0
- cumulusci/tasks/apex/testrunner.py +835 -0
- cumulusci/tasks/apex/tests/cassettes/ManualEditTestApexIntegrationTests.test_run_tests__integration_test.yaml +703 -0
- cumulusci/tasks/apex/tests/test_apex_tasks.py +1558 -0
- cumulusci/tasks/base_source_control_task.py +17 -0
- cumulusci/tasks/bulkdata/__init__.py +15 -0
- cumulusci/tasks/bulkdata/base_generate_data_task.py +96 -0
- cumulusci/tasks/bulkdata/dates.py +97 -0
- cumulusci/tasks/bulkdata/delete.py +156 -0
- cumulusci/tasks/bulkdata/extract.py +441 -0
- cumulusci/tasks/bulkdata/extract_dataset_utils/calculate_dependencies.py +117 -0
- cumulusci/tasks/bulkdata/extract_dataset_utils/extract_yml.py +123 -0
- cumulusci/tasks/bulkdata/extract_dataset_utils/hardcoded_default_declarations.py +49 -0
- cumulusci/tasks/bulkdata/extract_dataset_utils/synthesize_extract_declarations.py +283 -0
- cumulusci/tasks/bulkdata/extract_dataset_utils/tests/test_extract_yml.py +142 -0
- cumulusci/tasks/bulkdata/extract_dataset_utils/tests/test_synthesize_extract_declarations.py +575 -0
- cumulusci/tasks/bulkdata/factory_utils.py +134 -0
- cumulusci/tasks/bulkdata/generate.py +4 -0
- cumulusci/tasks/bulkdata/generate_and_load_data.py +232 -0
- cumulusci/tasks/bulkdata/generate_and_load_data_from_yaml.py +19 -0
- cumulusci/tasks/bulkdata/generate_from_yaml.py +183 -0
- cumulusci/tasks/bulkdata/generate_mapping.py +434 -0
- cumulusci/tasks/bulkdata/generate_mapping_utils/dependency_map.py +169 -0
- cumulusci/tasks/bulkdata/generate_mapping_utils/extract_mapping_file_generator.py +45 -0
- cumulusci/tasks/bulkdata/generate_mapping_utils/generate_mapping_from_declarations.py +121 -0
- cumulusci/tasks/bulkdata/generate_mapping_utils/load_mapping_file_generator.py +127 -0
- cumulusci/tasks/bulkdata/generate_mapping_utils/mapping_generator_post_processes.py +53 -0
- cumulusci/tasks/bulkdata/generate_mapping_utils/mapping_transforms.py +139 -0
- cumulusci/tasks/bulkdata/generate_mapping_utils/tests/test_generate_extract_mapping_from_declarations.py +135 -0
- cumulusci/tasks/bulkdata/generate_mapping_utils/tests/test_generate_load_mapping_from_declarations.py +330 -0
- cumulusci/tasks/bulkdata/generate_mapping_utils/tests/test_mapping_generator_post_processes.py +60 -0
- cumulusci/tasks/bulkdata/generate_mapping_utils/tests/test_mapping_transforms.py +188 -0
- cumulusci/tasks/bulkdata/load.py +1196 -0
- cumulusci/tasks/bulkdata/mapping_parser.py +811 -0
- cumulusci/tasks/bulkdata/query_transformers.py +264 -0
- cumulusci/tasks/bulkdata/select_utils.py +792 -0
- cumulusci/tasks/bulkdata/snowfakery.py +753 -0
- cumulusci/tasks/bulkdata/snowfakery_utils/queue_manager.py +478 -0
- cumulusci/tasks/bulkdata/snowfakery_utils/snowfakery_run_until.py +141 -0
- cumulusci/tasks/bulkdata/snowfakery_utils/snowfakery_working_directory.py +53 -0
- cumulusci/tasks/bulkdata/snowfakery_utils/subtask_configurator.py +64 -0
- cumulusci/tasks/bulkdata/step.py +1242 -0
- cumulusci/tasks/bulkdata/tests/__init__.py +0 -0
- cumulusci/tasks/bulkdata/tests/cassettes/TestSelect.test_select_random_strategy.yaml +147 -0
- cumulusci/tasks/bulkdata/tests/cassettes/TestSelect.test_select_similarity_annoy_strategy.yaml +123 -0
- cumulusci/tasks/bulkdata/tests/cassettes/TestSelect.test_select_similarity_select_and_insert_strategy.yaml +313 -0
- cumulusci/tasks/bulkdata/tests/cassettes/TestSelect.test_select_similarity_select_and_insert_strategy_bulk.yaml +550 -0
- cumulusci/tasks/bulkdata/tests/cassettes/TestSelect.test_select_similarity_strategy.yaml +175 -0
- cumulusci/tasks/bulkdata/tests/cassettes/TestSelect.test_select_standard_strategy.yaml +147 -0
- cumulusci/tasks/bulkdata/tests/cassettes/TestSnowfakery.test_run_until_records_in_org__multiple_needed.yaml +69 -0
- cumulusci/tasks/bulkdata/tests/cassettes/TestSnowfakery.test_run_until_records_in_org__none_needed.yaml +22 -0
- cumulusci/tasks/bulkdata/tests/cassettes/TestSnowfakery.test_run_until_records_in_org__one_needed.yaml +24 -0
- cumulusci/tasks/bulkdata/tests/cassettes/TestSnowfakery.test_snowfakery_query_salesforce.yaml +25 -0
- cumulusci/tasks/bulkdata/tests/cassettes/TestUpdatesIntegrationTests.test_updates_task.yaml +80 -0
- cumulusci/tasks/bulkdata/tests/cassettes/TestUpsert.test_simple_upsert__rest.yaml +270 -0
- cumulusci/tasks/bulkdata/tests/cassettes/TestUpsert.test_upsert__rest.yaml +267 -0
- cumulusci/tasks/bulkdata/tests/cassettes/TestUpsert.test_upsert_complex_external_id_field__rest.yaml +369 -0
- cumulusci/tasks/bulkdata/tests/cassettes/TestUpsert.test_upsert_complex_external_id_field_rest__duplicate_error.yaml +204 -0
- cumulusci/tasks/bulkdata/tests/cassettes/TestUpsert.test_upsert_complex_fields__bulk.yaml +675 -0
- cumulusci/tasks/bulkdata/tests/dummy_data_factory.py +36 -0
- cumulusci/tasks/bulkdata/tests/integration_test_utils.py +49 -0
- cumulusci/tasks/bulkdata/tests/mapping-oid.yml +87 -0
- cumulusci/tasks/bulkdata/tests/mapping_after.yml +38 -0
- cumulusci/tasks/bulkdata/tests/mapping_poly.yml +34 -0
- cumulusci/tasks/bulkdata/tests/mapping_poly_incomplete.yml +20 -0
- cumulusci/tasks/bulkdata/tests/mapping_poly_wrong.yml +21 -0
- cumulusci/tasks/bulkdata/tests/mapping_select.yml +20 -0
- cumulusci/tasks/bulkdata/tests/mapping_select_invalid_strategy.yml +20 -0
- cumulusci/tasks/bulkdata/tests/mapping_select_invalid_threshold__invalid_number.yml +21 -0
- cumulusci/tasks/bulkdata/tests/mapping_select_invalid_threshold__invalid_strategy.yml +21 -0
- cumulusci/tasks/bulkdata/tests/mapping_select_invalid_threshold__non_float.yml +21 -0
- cumulusci/tasks/bulkdata/tests/mapping_select_missing_priority_fields.yml +22 -0
- cumulusci/tasks/bulkdata/tests/mapping_select_no_priority_fields.yml +18 -0
- cumulusci/tasks/bulkdata/tests/mapping_simple.yml +27 -0
- cumulusci/tasks/bulkdata/tests/mapping_v1.yml +28 -0
- cumulusci/tasks/bulkdata/tests/mapping_v2.yml +21 -0
- cumulusci/tasks/bulkdata/tests/mapping_v3.yml +32 -0
- cumulusci/tasks/bulkdata/tests/mapping_vanilla_sf.yml +69 -0
- cumulusci/tasks/bulkdata/tests/mock_data_factory_without_mapping.py +12 -0
- cumulusci/tasks/bulkdata/tests/person_accounts.yml +23 -0
- cumulusci/tasks/bulkdata/tests/person_accounts_minimal.yml +15 -0
- cumulusci/tasks/bulkdata/tests/recordtypes.yml +8 -0
- cumulusci/tasks/bulkdata/tests/recordtypes_2.yml +6 -0
- cumulusci/tasks/bulkdata/tests/recordtypes_with_ispersontype.yml +8 -0
- cumulusci/tasks/bulkdata/tests/snowfakery/child/child2.yml +3 -0
- cumulusci/tasks/bulkdata/tests/snowfakery/child.yml +4 -0
- cumulusci/tasks/bulkdata/tests/snowfakery/gen_npsp_standard_objects.recipe.yml +89 -0
- cumulusci/tasks/bulkdata/tests/snowfakery/include_parent.yml +3 -0
- cumulusci/tasks/bulkdata/tests/snowfakery/npsp_standard_objects_macros.yml +34 -0
- cumulusci/tasks/bulkdata/tests/snowfakery/options.recipe.yml +6 -0
- cumulusci/tasks/bulkdata/tests/snowfakery/query_snowfakery.recipe.yml +16 -0
- cumulusci/tasks/bulkdata/tests/snowfakery/sf_standard_object_macros.yml +83 -0
- cumulusci/tasks/bulkdata/tests/snowfakery/simple_snowfakery.load.yml +2 -0
- cumulusci/tasks/bulkdata/tests/snowfakery/simple_snowfakery.recipe.yml +13 -0
- cumulusci/tasks/bulkdata/tests/snowfakery/simple_snowfakery_2.load.yml +5 -0
- cumulusci/tasks/bulkdata/tests/snowfakery/simple_snowfakery_channels.load.yml +13 -0
- cumulusci/tasks/bulkdata/tests/snowfakery/simple_snowfakery_channels.recipe.yml +12 -0
- cumulusci/tasks/bulkdata/tests/snowfakery/simple_snowfakery_channels_2.load.yml +13 -0
- cumulusci/tasks/bulkdata/tests/snowfakery/unique_values.recipe.yml +4 -0
- cumulusci/tasks/bulkdata/tests/snowfakery/upsert.recipe.yml +23 -0
- cumulusci/tasks/bulkdata/tests/snowfakery/upsert_2.recipe.yml +29 -0
- cumulusci/tasks/bulkdata/tests/snowfakery/upsert_before.yml +10 -0
- cumulusci/tasks/bulkdata/tests/test_base_generate_data_tasks.py +61 -0
- cumulusci/tasks/bulkdata/tests/test_dates.py +99 -0
- cumulusci/tasks/bulkdata/tests/test_delete.py +404 -0
- cumulusci/tasks/bulkdata/tests/test_extract.py +1311 -0
- cumulusci/tasks/bulkdata/tests/test_factory_utils.py +55 -0
- cumulusci/tasks/bulkdata/tests/test_generate_and_load.py +252 -0
- cumulusci/tasks/bulkdata/tests/test_generate_from_snowfakery_task.py +343 -0
- cumulusci/tasks/bulkdata/tests/test_generatemapping.py +1039 -0
- cumulusci/tasks/bulkdata/tests/test_load.py +3175 -0
- cumulusci/tasks/bulkdata/tests/test_mapping_parser.py +1658 -0
- cumulusci/tasks/bulkdata/tests/test_query_db__joins_self_lookups.yml +12 -0
- cumulusci/tasks/bulkdata/tests/test_query_db_joins_lookups.yml +26 -0
- cumulusci/tasks/bulkdata/tests/test_query_db_joins_lookups_select.yml +48 -0
- cumulusci/tasks/bulkdata/tests/test_select.py +171 -0
- cumulusci/tasks/bulkdata/tests/test_select_utils.py +1057 -0
- cumulusci/tasks/bulkdata/tests/test_snowfakery.py +1153 -0
- cumulusci/tasks/bulkdata/tests/test_step.py +3957 -0
- cumulusci/tasks/bulkdata/tests/test_updates.py +513 -0
- cumulusci/tasks/bulkdata/tests/test_upsert.py +1015 -0
- cumulusci/tasks/bulkdata/tests/test_utils.py +158 -0
- cumulusci/tasks/bulkdata/tests/testdata.db +0 -0
- cumulusci/tasks/bulkdata/tests/update_describe.py +50 -0
- cumulusci/tasks/bulkdata/tests/update_person_accounts.yml +23 -0
- cumulusci/tasks/bulkdata/tests/utils.py +114 -0
- cumulusci/tasks/bulkdata/update_data.py +260 -0
- cumulusci/tasks/bulkdata/upsert_utils.py +130 -0
- cumulusci/tasks/bulkdata/utils.py +249 -0
- cumulusci/tasks/command.py +178 -0
- cumulusci/tasks/connectedapp.py +186 -0
- cumulusci/tasks/create_package_version.py +778 -0
- cumulusci/tasks/datadictionary.py +745 -0
- cumulusci/tasks/dx_convert_from.py +26 -0
- cumulusci/tasks/github/__init__.py +17 -0
- cumulusci/tasks/github/base.py +16 -0
- cumulusci/tasks/github/commit_status.py +13 -0
- cumulusci/tasks/github/merge.py +11 -0
- cumulusci/tasks/github/publish.py +11 -0
- cumulusci/tasks/github/pull_request.py +11 -0
- cumulusci/tasks/github/release.py +11 -0
- cumulusci/tasks/github/release_report.py +11 -0
- cumulusci/tasks/github/tag.py +11 -0
- cumulusci/tasks/github/tests/__init__.py +0 -0
- cumulusci/tasks/github/tests/test_util.py +202 -0
- cumulusci/tasks/github/tests/test_vcs_migration.py +44 -0
- cumulusci/tasks/github/tests/util_github_api.py +666 -0
- cumulusci/tasks/github/util.py +252 -0
- cumulusci/tasks/marketing_cloud/__init__.py +0 -0
- cumulusci/tasks/marketing_cloud/api.py +188 -0
- cumulusci/tasks/marketing_cloud/base.py +38 -0
- cumulusci/tasks/marketing_cloud/deploy.py +345 -0
- cumulusci/tasks/marketing_cloud/get_user_info.py +40 -0
- cumulusci/tasks/marketing_cloud/mc_constants.py +1 -0
- cumulusci/tasks/marketing_cloud/tests/__init__.py +0 -0
- cumulusci/tasks/marketing_cloud/tests/conftest.py +46 -0
- cumulusci/tasks/marketing_cloud/tests/expected-payload.json +110 -0
- cumulusci/tasks/marketing_cloud/tests/test_api.py +97 -0
- cumulusci/tasks/marketing_cloud/tests/test_api_soap_envelopes.py +145 -0
- cumulusci/tasks/marketing_cloud/tests/test_base.py +14 -0
- cumulusci/tasks/marketing_cloud/tests/test_deploy.py +400 -0
- cumulusci/tasks/marketing_cloud/tests/test_get_user_info.py +141 -0
- cumulusci/tasks/marketing_cloud/tests/validation-response.json +39 -0
- cumulusci/tasks/metadata/__init__.py +0 -0
- cumulusci/tasks/metadata/ee_src.py +94 -0
- cumulusci/tasks/metadata/managed_src.py +100 -0
- cumulusci/tasks/metadata/metadata_map.yml +868 -0
- cumulusci/tasks/metadata/modify.py +99 -0
- cumulusci/tasks/metadata/package.py +684 -0
- cumulusci/tasks/metadata/tests/__init__.py +0 -0
- cumulusci/tasks/metadata/tests/package_metadata/namespaced_report_folder/.hidden/.keep +0 -0
- cumulusci/tasks/metadata/tests/package_metadata/namespaced_report_folder/destructiveChanges.xml +9 -0
- cumulusci/tasks/metadata/tests/package_metadata/namespaced_report_folder/package.xml +9 -0
- cumulusci/tasks/metadata/tests/package_metadata/namespaced_report_folder/package_install_uninstall.xml +11 -0
- cumulusci/tasks/metadata/tests/package_metadata/namespaced_report_folder/reports/namespace__TestFolder/TestReport.report +3 -0
- cumulusci/tasks/metadata/tests/sample_package.xml +9 -0
- cumulusci/tasks/metadata/tests/test_ee_src.py +112 -0
- cumulusci/tasks/metadata/tests/test_managed_src.py +111 -0
- cumulusci/tasks/metadata/tests/test_modify.py +123 -0
- cumulusci/tasks/metadata/tests/test_package.py +476 -0
- cumulusci/tasks/metadata_etl/__init__.py +29 -0
- cumulusci/tasks/metadata_etl/base.py +436 -0
- cumulusci/tasks/metadata_etl/duplicate_rules.py +24 -0
- cumulusci/tasks/metadata_etl/field_sets.py +70 -0
- cumulusci/tasks/metadata_etl/help_text.py +92 -0
- cumulusci/tasks/metadata_etl/layouts.py +550 -0
- cumulusci/tasks/metadata_etl/objects.py +68 -0
- cumulusci/tasks/metadata_etl/permissions.py +167 -0
- cumulusci/tasks/metadata_etl/picklists.py +221 -0
- cumulusci/tasks/metadata_etl/remote_site_settings.py +99 -0
- cumulusci/tasks/metadata_etl/sharing.py +138 -0
- cumulusci/tasks/metadata_etl/tests/test_base.py +512 -0
- cumulusci/tasks/metadata_etl/tests/test_duplicate_rules.py +22 -0
- cumulusci/tasks/metadata_etl/tests/test_field_sets.py +156 -0
- cumulusci/tasks/metadata_etl/tests/test_help_text.py +387 -0
- cumulusci/tasks/metadata_etl/tests/test_ip_ranges.py +85 -0
- cumulusci/tasks/metadata_etl/tests/test_layouts.py +858 -0
- cumulusci/tasks/metadata_etl/tests/test_objects.py +236 -0
- cumulusci/tasks/metadata_etl/tests/test_permissions.py +223 -0
- cumulusci/tasks/metadata_etl/tests/test_picklists.py +547 -0
- cumulusci/tasks/metadata_etl/tests/test_remote_site_settings.py +46 -0
- cumulusci/tasks/metadata_etl/tests/test_sharing.py +333 -0
- cumulusci/tasks/metadata_etl/tests/test_value_sets.py +298 -0
- cumulusci/tasks/metadata_etl/value_sets.py +106 -0
- cumulusci/tasks/metadeploy.py +393 -0
- cumulusci/tasks/metaxml.py +88 -0
- cumulusci/tasks/preflight/__init__.py +0 -0
- cumulusci/tasks/preflight/dataset_load.py +49 -0
- cumulusci/tasks/preflight/licenses.py +86 -0
- cumulusci/tasks/preflight/packages.py +14 -0
- cumulusci/tasks/preflight/permsets.py +23 -0
- cumulusci/tasks/preflight/recordtypes.py +16 -0
- cumulusci/tasks/preflight/retrieve_tasks.py +30 -0
- cumulusci/tasks/preflight/settings.py +77 -0
- cumulusci/tasks/preflight/sobjects.py +202 -0
- cumulusci/tasks/preflight/tests/test_dataset_load.py +85 -0
- cumulusci/tasks/preflight/tests/test_licenses.py +174 -0
- cumulusci/tasks/preflight/tests/test_packages.py +14 -0
- cumulusci/tasks/preflight/tests/test_permset_preflights.py +51 -0
- cumulusci/tasks/preflight/tests/test_recordtypes.py +30 -0
- cumulusci/tasks/preflight/tests/test_retrieve_tasks.py +62 -0
- cumulusci/tasks/preflight/tests/test_settings.py +130 -0
- cumulusci/tasks/preflight/tests/test_sobjects.py +231 -0
- cumulusci/tasks/push/README.md +59 -0
- cumulusci/tasks/push/__init__.py +0 -0
- cumulusci/tasks/push/push_api.py +659 -0
- cumulusci/tasks/push/pushfails.py +136 -0
- cumulusci/tasks/push/tasks.py +476 -0
- cumulusci/tasks/push/tests/conftest.py +263 -0
- cumulusci/tasks/push/tests/test_push_api.py +951 -0
- cumulusci/tasks/push/tests/test_push_tasks.py +659 -0
- cumulusci/tasks/release_notes/README.md +63 -0
- cumulusci/tasks/release_notes/__init__.py +0 -0
- cumulusci/tasks/release_notes/exceptions.py +5 -0
- cumulusci/tasks/release_notes/generator.py +137 -0
- cumulusci/tasks/release_notes/parser.py +232 -0
- cumulusci/tasks/release_notes/provider.py +44 -0
- cumulusci/tasks/release_notes/task.py +300 -0
- cumulusci/tasks/release_notes/tests/__init__.py +0 -0
- cumulusci/tasks/release_notes/tests/change_notes/full/example1.md +17 -0
- cumulusci/tasks/release_notes/tests/change_notes/multi/1.txt +1 -0
- cumulusci/tasks/release_notes/tests/change_notes/multi/2.txt +1 -0
- cumulusci/tasks/release_notes/tests/change_notes/multi/3.txt +1 -0
- cumulusci/tasks/release_notes/tests/change_notes/single/1.txt +1 -0
- cumulusci/tasks/release_notes/tests/test_generator.py +582 -0
- cumulusci/tasks/release_notes/tests/test_parser.py +867 -0
- cumulusci/tasks/release_notes/tests/test_provider.py +512 -0
- cumulusci/tasks/release_notes/tests/test_task.py +461 -0
- cumulusci/tasks/release_notes/tests/utils.py +153 -0
- cumulusci/tasks/robotframework/__init__.py +3 -0
- cumulusci/tasks/robotframework/debugger/DebugListener.py +100 -0
- cumulusci/tasks/robotframework/debugger/__init__.py +10 -0
- cumulusci/tasks/robotframework/debugger/model.py +87 -0
- cumulusci/tasks/robotframework/debugger/ui.py +259 -0
- cumulusci/tasks/robotframework/libdoc.py +269 -0
- cumulusci/tasks/robotframework/robotframework.py +392 -0
- cumulusci/tasks/robotframework/stylesheet.css +130 -0
- cumulusci/tasks/robotframework/template.html +109 -0
- cumulusci/tasks/robotframework/tests/TestLibrary.py +18 -0
- cumulusci/tasks/robotframework/tests/TestPageObjects.py +31 -0
- cumulusci/tasks/robotframework/tests/TestResource.robot +8 -0
- cumulusci/tasks/robotframework/tests/failing_tests.robot +16 -0
- cumulusci/tasks/robotframework/tests/performance.robot +23 -0
- cumulusci/tasks/robotframework/tests/test_browser_proxies.py +137 -0
- cumulusci/tasks/robotframework/tests/test_debugger.py +360 -0
- cumulusci/tasks/robotframework/tests/test_robot_parallel.py +141 -0
- cumulusci/tasks/robotframework/tests/test_robotframework.py +860 -0
- cumulusci/tasks/salesforce/BaseRetrieveMetadata.py +58 -0
- cumulusci/tasks/salesforce/BaseSalesforceApiTask.py +45 -0
- cumulusci/tasks/salesforce/BaseSalesforceMetadataApiTask.py +18 -0
- cumulusci/tasks/salesforce/BaseSalesforceTask.py +4 -0
- cumulusci/tasks/salesforce/BaseUninstallMetadata.py +41 -0
- cumulusci/tasks/salesforce/CreateCommunity.py +124 -0
- cumulusci/tasks/salesforce/CreatePackage.py +29 -0
- cumulusci/tasks/salesforce/Deploy.py +240 -0
- cumulusci/tasks/salesforce/DeployBundles.py +88 -0
- cumulusci/tasks/salesforce/DescribeMetadataTypes.py +26 -0
- cumulusci/tasks/salesforce/EnsureRecordTypes.py +202 -0
- cumulusci/tasks/salesforce/GetInstalledPackages.py +8 -0
- cumulusci/tasks/salesforce/ListCommunities.py +40 -0
- cumulusci/tasks/salesforce/ListCommunityTemplates.py +19 -0
- cumulusci/tasks/salesforce/PublishCommunity.py +62 -0
- cumulusci/tasks/salesforce/RetrievePackaged.py +41 -0
- cumulusci/tasks/salesforce/RetrieveReportsAndDashboards.py +82 -0
- cumulusci/tasks/salesforce/RetrieveUnpackaged.py +36 -0
- cumulusci/tasks/salesforce/SOQLQuery.py +39 -0
- cumulusci/tasks/salesforce/UninstallLocal.py +15 -0
- cumulusci/tasks/salesforce/UninstallLocalBundles.py +28 -0
- cumulusci/tasks/salesforce/UninstallLocalNamespacedBundles.py +58 -0
- cumulusci/tasks/salesforce/UninstallPackage.py +32 -0
- cumulusci/tasks/salesforce/UninstallPackaged.py +56 -0
- cumulusci/tasks/salesforce/UpdateAdminProfile.py +8 -0
- cumulusci/tasks/salesforce/__init__.py +79 -0
- cumulusci/tasks/salesforce/activate_flow.py +74 -0
- cumulusci/tasks/salesforce/check_components.py +324 -0
- cumulusci/tasks/salesforce/composite.py +142 -0
- cumulusci/tasks/salesforce/create_permission_sets.py +35 -0
- cumulusci/tasks/salesforce/custom_settings.py +134 -0
- cumulusci/tasks/salesforce/custom_settings_wait.py +132 -0
- cumulusci/tasks/salesforce/enable_prediction.py +107 -0
- cumulusci/tasks/salesforce/insert_record.py +40 -0
- cumulusci/tasks/salesforce/install_package_version.py +242 -0
- cumulusci/tasks/salesforce/license_preflights.py +8 -0
- cumulusci/tasks/salesforce/network_member_group.py +178 -0
- cumulusci/tasks/salesforce/nonsourcetracking.py +228 -0
- cumulusci/tasks/salesforce/org_settings.py +193 -0
- cumulusci/tasks/salesforce/package_upload.py +328 -0
- cumulusci/tasks/salesforce/profiles.py +74 -0
- cumulusci/tasks/salesforce/promote_package_version.py +376 -0
- cumulusci/tasks/salesforce/retrieve_profile.py +195 -0
- cumulusci/tasks/salesforce/salesforce_files.py +244 -0
- cumulusci/tasks/salesforce/sourcetracking.py +507 -0
- cumulusci/tasks/salesforce/tests/__init__.py +3 -0
- cumulusci/tasks/salesforce/tests/test_CreateCommunity.py +278 -0
- cumulusci/tasks/salesforce/tests/test_CreatePackage.py +22 -0
- cumulusci/tasks/salesforce/tests/test_Deploy.py +470 -0
- cumulusci/tasks/salesforce/tests/test_DeployBundles.py +76 -0
- cumulusci/tasks/salesforce/tests/test_EnsureRecordTypes.py +345 -0
- cumulusci/tasks/salesforce/tests/test_ListCommunities.py +84 -0
- cumulusci/tasks/salesforce/tests/test_ListCommunityTemplates.py +49 -0
- cumulusci/tasks/salesforce/tests/test_PackageUpload.py +547 -0
- cumulusci/tasks/salesforce/tests/test_ProfileGrantAllAccess.py +699 -0
- cumulusci/tasks/salesforce/tests/test_PublishCommunity.py +181 -0
- cumulusci/tasks/salesforce/tests/test_RetrievePackaged.py +24 -0
- cumulusci/tasks/salesforce/tests/test_RetrieveReportsAndDashboards.py +56 -0
- cumulusci/tasks/salesforce/tests/test_RetrieveUnpackaged.py +21 -0
- cumulusci/tasks/salesforce/tests/test_SOQLQuery.py +30 -0
- cumulusci/tasks/salesforce/tests/test_UninstallLocal.py +15 -0
- cumulusci/tasks/salesforce/tests/test_UninstallLocalBundles.py +19 -0
- cumulusci/tasks/salesforce/tests/test_UninstallLocalNamespacedBundles.py +22 -0
- cumulusci/tasks/salesforce/tests/test_UninstallPackage.py +19 -0
- cumulusci/tasks/salesforce/tests/test_UninstallPackaged.py +66 -0
- cumulusci/tasks/salesforce/tests/test_UninstallPackagedIncremental.py +127 -0
- cumulusci/tasks/salesforce/tests/test_activate_flow.py +132 -0
- cumulusci/tasks/salesforce/tests/test_base_tasks.py +110 -0
- cumulusci/tasks/salesforce/tests/test_check_components.py +445 -0
- cumulusci/tasks/salesforce/tests/test_composite.py +250 -0
- cumulusci/tasks/salesforce/tests/test_create_permission_sets.py +41 -0
- cumulusci/tasks/salesforce/tests/test_custom_settings.py +227 -0
- cumulusci/tasks/salesforce/tests/test_custom_settings_wait.py +174 -0
- cumulusci/tasks/salesforce/tests/test_describemetadatatypes.py +18 -0
- cumulusci/tasks/salesforce/tests/test_enable_prediction.py +240 -0
- cumulusci/tasks/salesforce/tests/test_insert_record.py +110 -0
- cumulusci/tasks/salesforce/tests/test_install_package_version.py +464 -0
- cumulusci/tasks/salesforce/tests/test_network_member_group.py +444 -0
- cumulusci/tasks/salesforce/tests/test_nonsourcetracking.py +235 -0
- cumulusci/tasks/salesforce/tests/test_org_settings.py +407 -0
- cumulusci/tasks/salesforce/tests/test_profiles.py +202 -0
- cumulusci/tasks/salesforce/tests/test_retrieve_profile.py +287 -0
- cumulusci/tasks/salesforce/tests/test_salesforce_files.py +228 -0
- cumulusci/tasks/salesforce/tests/test_sourcetracking.py +350 -0
- cumulusci/tasks/salesforce/tests/test_trigger_handlers.py +300 -0
- cumulusci/tasks/salesforce/tests/test_update_dependencies.py +509 -0
- cumulusci/tasks/salesforce/tests/util.py +79 -0
- cumulusci/tasks/salesforce/trigger_handlers.py +119 -0
- cumulusci/tasks/salesforce/uninstall_packaged_incremental.py +136 -0
- cumulusci/tasks/salesforce/update_dependencies.py +290 -0
- cumulusci/tasks/salesforce/update_profile.py +339 -0
- cumulusci/tasks/salesforce/users/permsets.py +227 -0
- cumulusci/tasks/salesforce/users/photos.py +162 -0
- cumulusci/tasks/salesforce/users/tests/photo.mock.txt +1 -0
- cumulusci/tasks/salesforce/users/tests/test_permsets.py +950 -0
- cumulusci/tasks/salesforce/users/tests/test_photos.py +373 -0
- cumulusci/tasks/sample_data/capture_sample_data.py +77 -0
- cumulusci/tasks/sample_data/load_sample_data.py +85 -0
- cumulusci/tasks/sample_data/test_capture_sample_data.py +117 -0
- cumulusci/tasks/sample_data/test_load_sample_data.py +121 -0
- cumulusci/tasks/sfdx.py +83 -0
- cumulusci/tasks/tests/__init__.py +1 -0
- cumulusci/tasks/tests/conftest.py +30 -0
- cumulusci/tasks/tests/test_command.py +129 -0
- cumulusci/tasks/tests/test_connectedapp.py +236 -0
- cumulusci/tasks/tests/test_create_package_version.py +847 -0
- cumulusci/tasks/tests/test_datadictionary.py +1575 -0
- cumulusci/tasks/tests/test_dx_convert_from.py +60 -0
- cumulusci/tasks/tests/test_metadeploy.py +624 -0
- cumulusci/tasks/tests/test_metaxml.py +99 -0
- cumulusci/tasks/tests/test_promote_package_version.py +488 -0
- cumulusci/tasks/tests/test_pushfails.py +96 -0
- cumulusci/tasks/tests/test_salesforce.py +72 -0
- cumulusci/tasks/tests/test_sfdx.py +105 -0
- cumulusci/tasks/tests/test_util.py +207 -0
- cumulusci/tasks/util.py +261 -0
- cumulusci/tasks/vcs/__init__.py +19 -0
- cumulusci/tasks/vcs/commit_status.py +58 -0
- cumulusci/tasks/vcs/create_commit_status.py +37 -0
- cumulusci/tasks/vcs/download_extract.py +199 -0
- cumulusci/tasks/vcs/merge.py +298 -0
- cumulusci/tasks/vcs/publish.py +207 -0
- cumulusci/tasks/vcs/pull_request.py +9 -0
- cumulusci/tasks/vcs/release.py +134 -0
- cumulusci/tasks/vcs/release_report.py +105 -0
- cumulusci/tasks/vcs/tag.py +31 -0
- cumulusci/tasks/vcs/tests/github/test_commit_status.py +196 -0
- cumulusci/tasks/vcs/tests/github/test_download_extract.py +896 -0
- cumulusci/tasks/vcs/tests/github/test_merge.py +1118 -0
- cumulusci/tasks/vcs/tests/github/test_publish.py +823 -0
- cumulusci/tasks/vcs/tests/github/test_pull_request.py +29 -0
- cumulusci/tasks/vcs/tests/github/test_release.py +390 -0
- cumulusci/tasks/vcs/tests/github/test_release_report.py +109 -0
- cumulusci/tasks/vcs/tests/github/test_tag.py +90 -0
- cumulusci/tasks/vlocity/exceptions.py +2 -0
- cumulusci/tasks/vlocity/tests/test_vlocity.py +283 -0
- cumulusci/tasks/vlocity/vlocity.py +342 -0
- cumulusci/tests/__init__.py +1 -0
- cumulusci/tests/cassettes/GET_sobjects_Account_PersonAccount_describe.yaml +18 -0
- cumulusci/tests/cassettes/TestIntegrationInfrastructure.test_integration_tests.yaml +19 -0
- cumulusci/tests/pytest_plugins/pytest_sf_orgconnect.py +307 -0
- cumulusci/tests/pytest_plugins/pytest_sf_vcr.py +275 -0
- cumulusci/tests/pytest_plugins/pytest_sf_vcr_serializer.py +160 -0
- cumulusci/tests/pytest_plugins/pytest_typeguard.py +5 -0
- cumulusci/tests/pytest_plugins/test_vcr_string_compressor.py +49 -0
- cumulusci/tests/pytest_plugins/vcr_string_compressor.py +97 -0
- cumulusci/tests/shared_cassettes/GET_sobjects_Account_describe.yaml +18 -0
- cumulusci/tests/shared_cassettes/GET_sobjects_Case_describe.yaml +18 -0
- cumulusci/tests/shared_cassettes/GET_sobjects_Contact_describe.yaml +4838 -0
- cumulusci/tests/shared_cassettes/GET_sobjects_Custom__c_describe.yaml +242 -0
- cumulusci/tests/shared_cassettes/GET_sobjects_Event_describe.yaml +19 -0
- cumulusci/tests/shared_cassettes/GET_sobjects_Global_describe.yaml +1338 -0
- cumulusci/tests/shared_cassettes/GET_sobjects_Lead_describe.yaml +18 -0
- cumulusci/tests/shared_cassettes/GET_sobjects_OpportunityContactRole_describe.yaml +34 -0
- cumulusci/tests/shared_cassettes/GET_sobjects_Opportunity_describe.yaml +1261 -0
- cumulusci/tests/shared_cassettes/GET_sobjects_Organization.yaml +49 -0
- cumulusci/tests/shared_cassettes/vcr_string_templates/batchInfoList_xml.tpl +15 -0
- cumulusci/tests/shared_cassettes/vcr_string_templates/batchInfo_xml.tpl +13 -0
- cumulusci/tests/shared_cassettes/vcr_string_templates/jobInfo_insert_xml.tpl +24 -0
- cumulusci/tests/shared_cassettes/vcr_string_templates/jobInfo_upsert_xml.tpl +25 -0
- cumulusci/tests/test_entry_points.py +20 -0
- cumulusci/tests/test_integration_infrastructure.py +131 -0
- cumulusci/tests/test_main.py +9 -0
- cumulusci/tests/test_schema.py +32 -0
- cumulusci/tests/test_utils.py +657 -0
- cumulusci/tests/test_vcr_serializer.py +134 -0
- cumulusci/tests/uncompressed_cassette.yaml +83 -0
- cumulusci/tests/util.py +344 -0
- cumulusci/utils/__init__.py +731 -0
- cumulusci/utils/classutils.py +9 -0
- cumulusci/utils/collections.py +32 -0
- cumulusci/utils/deprecation.py +11 -0
- cumulusci/utils/encryption.py +31 -0
- cumulusci/utils/fileutils.py +295 -0
- cumulusci/utils/git.py +142 -0
- cumulusci/utils/http/multi_request.py +214 -0
- cumulusci/utils/http/requests_utils.py +103 -0
- cumulusci/utils/http/tests/cassettes/ManualEditTestCompositeParallelSalesforce.test_http_headers.yaml +32 -0
- cumulusci/utils/http/tests/cassettes/TestCompositeParallelSalesforce.test_composite_parallel_salesforce.yaml +65 -0
- cumulusci/utils/http/tests/cassettes/TestCompositeParallelSalesforce.test_errors.yaml +24 -0
- cumulusci/utils/http/tests/cassettes/TestCompositeParallelSalesforce.test_reference_ids.yaml +49 -0
- cumulusci/utils/http/tests/test_multi_request.py +255 -0
- cumulusci/utils/iterators.py +21 -0
- cumulusci/utils/logging.py +128 -0
- cumulusci/utils/metaprogramming.py +10 -0
- cumulusci/utils/options.py +138 -0
- cumulusci/utils/parallel/queries_in_parallel/run_queries_in_parallel.py +29 -0
- cumulusci/utils/parallel/queries_in_parallel/tests/test_run_queries_in_parallel.py +50 -0
- cumulusci/utils/parallel/task_worker_queues/parallel_worker.py +238 -0
- cumulusci/utils/parallel/task_worker_queues/parallel_worker_queue.py +243 -0
- cumulusci/utils/parallel/task_worker_queues/tests/test_parallel_worker.py +353 -0
- cumulusci/utils/salesforce/count_sobjects.py +46 -0
- cumulusci/utils/salesforce/soql.py +17 -0
- cumulusci/utils/salesforce/tests/cassettes/ManualEdit_TestCountSObjects.test_count_sobjects__network_errors.yaml +23 -0
- cumulusci/utils/salesforce/tests/cassettes/TestCountSObjects.test_count_sobjects__errors.yaml +33 -0
- cumulusci/utils/salesforce/tests/cassettes/TestCountSObjects.test_count_sobjects_simple.yaml +29 -0
- cumulusci/utils/salesforce/tests/test_count_sobjects.py +29 -0
- cumulusci/utils/salesforce/tests/test_soql.py +30 -0
- cumulusci/utils/tests/cassettes/ManualEditTestDescribeOrg.test_minimal_schema.yaml +36 -0
- cumulusci/utils/tests/cassettes/ManualEdit_test_describe_to_sql.yaml +191 -0
- cumulusci/utils/tests/test_fileutils.py +284 -0
- cumulusci/utils/tests/test_git.py +85 -0
- cumulusci/utils/tests/test_logging.py +70 -0
- cumulusci/utils/tests/test_option_parsing.py +188 -0
- cumulusci/utils/tests/test_org_schema.py +691 -0
- cumulusci/utils/tests/test_org_schema_models.py +79 -0
- cumulusci/utils/tests/test_waiting.py +25 -0
- cumulusci/utils/version_strings.py +391 -0
- cumulusci/utils/waiting.py +42 -0
- cumulusci/utils/xml/__init__.py +91 -0
- cumulusci/utils/xml/metadata_tree.py +299 -0
- cumulusci/utils/xml/robot_xml.py +114 -0
- cumulusci/utils/xml/salesforce_encoding.py +100 -0
- cumulusci/utils/xml/test/test_metadata_tree.py +251 -0
- cumulusci/utils/xml/test/test_salesforce_encoding.py +173 -0
- cumulusci/utils/yaml/cumulusci_yml.py +401 -0
- cumulusci/utils/yaml/model_parser.py +156 -0
- cumulusci/utils/yaml/safer_loader.py +74 -0
- cumulusci/utils/yaml/tests/bad_cci.yml +5 -0
- cumulusci/utils/yaml/tests/cassettes/TestCumulusciYml.test_validate_url__with_errors.yaml +20 -0
- cumulusci/utils/yaml/tests/test_cumulusci_yml.py +286 -0
- cumulusci/utils/yaml/tests/test_model_parser.py +175 -0
- cumulusci/utils/yaml/tests/test_safer_loader.py +88 -0
- cumulusci/utils/ziputils.py +61 -0
- cumulusci/vcs/base.py +143 -0
- cumulusci/vcs/bootstrap.py +272 -0
- cumulusci/vcs/github/__init__.py +24 -0
- cumulusci/vcs/github/adapter.py +689 -0
- cumulusci/vcs/github/release_notes/generator.py +219 -0
- cumulusci/vcs/github/release_notes/parser.py +151 -0
- cumulusci/vcs/github/release_notes/provider.py +143 -0
- cumulusci/vcs/github/service.py +569 -0
- cumulusci/vcs/github/tests/test_adapter.py +138 -0
- cumulusci/vcs/github/tests/test_service.py +408 -0
- cumulusci/vcs/models.py +586 -0
- cumulusci/vcs/tests/conftest.py +41 -0
- cumulusci/vcs/tests/dummy_service.py +241 -0
- cumulusci/vcs/tests/test_vcs_base.py +687 -0
- cumulusci/vcs/tests/test_vcs_bootstrap.py +727 -0
- cumulusci/vcs/utils/__init__.py +31 -0
- cumulusci/vcs/vcs_source.py +287 -0
- cumulusci_plus-5.0.0.dist-info/METADATA +145 -0
- cumulusci_plus-5.0.0.dist-info/RECORD +744 -0
- cumulusci_plus-5.0.0.dist-info/WHEEL +4 -0
- cumulusci_plus-5.0.0.dist-info/entry_points.txt +3 -0
- cumulusci_plus-5.0.0.dist-info/licenses/AUTHORS.rst +41 -0
- cumulusci_plus-5.0.0.dist-info/licenses/LICENSE +30 -0
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from unittest import mock
|
|
3
|
+
|
|
4
|
+
import click
|
|
5
|
+
from click.testing import CliRunner
|
|
6
|
+
|
|
7
|
+
from cumulusci.cli.cci import cli
|
|
8
|
+
from cumulusci.core.tasks import BaseTask
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def run_click_command(cmd, *args, **kw):
|
|
12
|
+
"""Run a click command with a mock context and injected CCI runtime object."""
|
|
13
|
+
runtime = kw.pop("runtime", mock.Mock())
|
|
14
|
+
with click.Context(command=mock.Mock(), obj=runtime):
|
|
15
|
+
return cmd.callback(*args, **kw)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def run_cli_command(*args, runtime=None, input=None, **kw):
|
|
19
|
+
"""Run a click command with arg parsing and injected CCI runtime object."""
|
|
20
|
+
if tuple(map(int, click.__version__.split("."))) >= (8, 1, 0):
|
|
21
|
+
runner = CliRunner()
|
|
22
|
+
else:
|
|
23
|
+
runner = CliRunner(mix_stderr=False)
|
|
24
|
+
result = runner.invoke(
|
|
25
|
+
cli,
|
|
26
|
+
args,
|
|
27
|
+
obj=runtime,
|
|
28
|
+
input=input,
|
|
29
|
+
catch_exceptions=False,
|
|
30
|
+
standalone_mode=False,
|
|
31
|
+
)
|
|
32
|
+
return result
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def recursive_list_files(d="."):
|
|
36
|
+
result = []
|
|
37
|
+
for d, subdirs, files in os.walk(d):
|
|
38
|
+
d = d.replace(os.path.sep, "/")
|
|
39
|
+
if d != ".":
|
|
40
|
+
result.append("/".join([d, ""])[2:])
|
|
41
|
+
for f in files:
|
|
42
|
+
result.append("/".join([d, f])[2:])
|
|
43
|
+
result.sort()
|
|
44
|
+
return result
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class DummyTask(BaseTask):
|
|
48
|
+
task_docs = "Some task docs."
|
|
49
|
+
task_options = {"color": {"description": "It's a color!", "required": True}}
|
|
50
|
+
|
|
51
|
+
def _run_task(self):
|
|
52
|
+
click.echo(f"<{self.__class__}>\n\tcolor: {self.options['color']}")
|
cumulusci/cli/ui.py
ADDED
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""Format and display CLI output.
|
|
3
|
+
|
|
4
|
+
Classes:
|
|
5
|
+
CliTable: Pretty prints tabular data to stdout, via Rich's Console API
|
|
6
|
+
"""
|
|
7
|
+
import os
|
|
8
|
+
from typing import Any, List, Union
|
|
9
|
+
|
|
10
|
+
import rich
|
|
11
|
+
from rich import box, print
|
|
12
|
+
from rich.console import Console
|
|
13
|
+
from rich.style import Style
|
|
14
|
+
from rich.table import Column, Table
|
|
15
|
+
|
|
16
|
+
CHECKMARK = "[green]:heavy_check_mark:" if os.name == "posix" else "+"
|
|
17
|
+
CROSSMARK = "[red]:cross_mark:" if os.name == "posix" else "-"
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class CliTable:
|
|
21
|
+
"""Format and print data to the command line in tabular form.
|
|
22
|
+
Attributes:
|
|
23
|
+
|
|
24
|
+
* PICTOGRAM_TRUE: True boolean values are replaced with this string.
|
|
25
|
+
* PICTOGRAM_FALSE = False boolean values are replaced with this string.
|
|
26
|
+
|
|
27
|
+
Methods:
|
|
28
|
+
* echo: Print the table data to stdout using rich.Console.print
|
|
29
|
+
Class Methods:
|
|
30
|
+
* columnify_headers: Convert a list of strs to Columns
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
PICTOGRAM_TRUE = CHECKMARK
|
|
34
|
+
PICTOGRAM_FALSE = " "
|
|
35
|
+
|
|
36
|
+
def __init__(
|
|
37
|
+
self,
|
|
38
|
+
data: List[List[Any]],
|
|
39
|
+
title: str = None,
|
|
40
|
+
dim_rows: List[int] = None,
|
|
41
|
+
**kwargs,
|
|
42
|
+
):
|
|
43
|
+
"""Constructor.
|
|
44
|
+
Args:
|
|
45
|
+
data: Required. List[List] of data to format, with the heading as 0-th member.
|
|
46
|
+
title: String to use as the table's title.
|
|
47
|
+
dim_rows: List[int] of row indices to dim.
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
headers: List[Column] = self.columnify_headers(data[0])
|
|
51
|
+
rows = [self._stringify_row(r) for r in data[1:]]
|
|
52
|
+
self._table: Table = Table(*headers, title=title, box=box.SIMPLE, **kwargs)
|
|
53
|
+
|
|
54
|
+
for idx, row in enumerate(rows):
|
|
55
|
+
dim_row = idx + 1 in dim_rows if dim_rows else False
|
|
56
|
+
self._table.add_row(*row, style=Style(dim=dim_row))
|
|
57
|
+
|
|
58
|
+
def _stringify_row(self, row: list) -> List[str]:
|
|
59
|
+
return [self._stringify_cell(cell) for cell in row]
|
|
60
|
+
|
|
61
|
+
def _stringify_cell(self, cell: Any) -> str:
|
|
62
|
+
if isinstance(cell, bool):
|
|
63
|
+
cell = self.PICTOGRAM_TRUE if cell else self.PICTOGRAM_FALSE
|
|
64
|
+
elif cell is None:
|
|
65
|
+
cell = ""
|
|
66
|
+
else:
|
|
67
|
+
cell = str(cell)
|
|
68
|
+
return cell
|
|
69
|
+
|
|
70
|
+
def __rich__(self) -> str:
|
|
71
|
+
return self._table
|
|
72
|
+
|
|
73
|
+
def columnify_headers(self, headers: List[Union[str, Column]]) -> List[Column]:
|
|
74
|
+
"""
|
|
75
|
+
Given a List[str, Column], return a list of Columns.
|
|
76
|
+
|
|
77
|
+
Strings are instantiated with default styles, Columns are unchanged.
|
|
78
|
+
"""
|
|
79
|
+
cols: List[Column] = []
|
|
80
|
+
|
|
81
|
+
for header in headers:
|
|
82
|
+
if isinstance(header, Column):
|
|
83
|
+
cols.append(header)
|
|
84
|
+
else:
|
|
85
|
+
header: str = self._stringify_cell(header)
|
|
86
|
+
cols.append(Column(header=header, overflow="fold"))
|
|
87
|
+
return cols
|
|
88
|
+
|
|
89
|
+
def echo(self, plain=False, box_style: box.Box = None):
|
|
90
|
+
"""
|
|
91
|
+
Print this table to the global Console using console.print().
|
|
92
|
+
"""
|
|
93
|
+
orig_box = self._table.box
|
|
94
|
+
if plain:
|
|
95
|
+
self._table.box = box.ASCII2
|
|
96
|
+
else:
|
|
97
|
+
self._table.box = box_style or orig_box
|
|
98
|
+
console = rich.get_console()
|
|
99
|
+
console.print(self._table)
|
|
100
|
+
self._table.box = orig_box
|
|
101
|
+
|
|
102
|
+
@property
|
|
103
|
+
def table(self):
|
|
104
|
+
return self._table
|
|
105
|
+
|
|
106
|
+
def __str__(self):
|
|
107
|
+
from io import StringIO
|
|
108
|
+
|
|
109
|
+
console = Console(file=StringIO())
|
|
110
|
+
tab_width = console.size.width - 21
|
|
111
|
+
console.print(self._table, width=tab_width)
|
|
112
|
+
return console.file.getvalue()
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def _soql_table(results, truncated):
|
|
116
|
+
if results:
|
|
117
|
+
if truncated:
|
|
118
|
+
assert results[-1] == truncated
|
|
119
|
+
first_row = results[0]
|
|
120
|
+
fake_row = {k: "" for k, v in first_row.items()}
|
|
121
|
+
first_column = list(first_row)[0]
|
|
122
|
+
fake_row[first_column] = truncated
|
|
123
|
+
|
|
124
|
+
results[-1] = fake_row
|
|
125
|
+
|
|
126
|
+
headings = list(results[0].keys())
|
|
127
|
+
return CliTable(
|
|
128
|
+
[headings] + [list(map(str, r.values())) for r in results],
|
|
129
|
+
).echo()
|
|
130
|
+
else:
|
|
131
|
+
return CliTable([["No results"]]).echo()
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def _summarize(field):
|
|
135
|
+
if field["referenceTo"]:
|
|
136
|
+
allowed = field["referenceTo"]
|
|
137
|
+
elif field["picklistValues"]:
|
|
138
|
+
allowed = [value["value"] for value in field["picklistValues"]]
|
|
139
|
+
else:
|
|
140
|
+
allowed = field["type"]
|
|
141
|
+
return (field["name"], allowed)
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
class SimpleSalesforceUIHelpers:
|
|
145
|
+
def __init__(self, sf):
|
|
146
|
+
self._sf = sf
|
|
147
|
+
|
|
148
|
+
def query(self, query, format="table", include_deleted=False, max_rows=100):
|
|
149
|
+
"""Return the result of a Salesforce SOQL query.
|
|
150
|
+
|
|
151
|
+
Arguments:
|
|
152
|
+
|
|
153
|
+
* query -- the SOQL query to send to Salesforce, e.g.
|
|
154
|
+
SELECT Id FROM Lead WHERE Email = "waldo@somewhere.com"
|
|
155
|
+
* include_deleted -- True if deleted records should be included
|
|
156
|
+
* format -- one of these values:
|
|
157
|
+
- "table" -- printable ASCII table (the default)
|
|
158
|
+
- "obj" -- ordinary Python objects
|
|
159
|
+
- "pprint" -- string in easily readable Python dict shape
|
|
160
|
+
- "json" -- JSON
|
|
161
|
+
* max_rows -- maximum rows to output, defaults to 100
|
|
162
|
+
|
|
163
|
+
For example:
|
|
164
|
+
query("select Name, Id from Account", format="pprint")
|
|
165
|
+
contact_ids = query("select count(Id) from Contact", format="obj")
|
|
166
|
+
"""
|
|
167
|
+
results = self._sf.query_all(query, include_deleted=include_deleted)["records"]
|
|
168
|
+
|
|
169
|
+
if len(results) > max_rows:
|
|
170
|
+
truncated = f"... truncated {len(results) - max_rows} rows"
|
|
171
|
+
results = results[0:max_rows]
|
|
172
|
+
else:
|
|
173
|
+
truncated = False
|
|
174
|
+
|
|
175
|
+
for result in results:
|
|
176
|
+
if result.get("attributes"):
|
|
177
|
+
del result["attributes"]
|
|
178
|
+
|
|
179
|
+
if truncated:
|
|
180
|
+
results.append(truncated)
|
|
181
|
+
|
|
182
|
+
if format == "table":
|
|
183
|
+
help_message = "Type help(query) to learn about other return formats or assigning the result."
|
|
184
|
+
print(_soql_table(results, truncated))
|
|
185
|
+
print()
|
|
186
|
+
print(help_message)
|
|
187
|
+
rc = None
|
|
188
|
+
elif format == "obj":
|
|
189
|
+
rc = results
|
|
190
|
+
elif format == "pprint":
|
|
191
|
+
from rich.pretty import pprint
|
|
192
|
+
|
|
193
|
+
pprint(results)
|
|
194
|
+
rc = None
|
|
195
|
+
elif format == "json":
|
|
196
|
+
from json import dumps
|
|
197
|
+
|
|
198
|
+
rc = dumps(results, indent=2)
|
|
199
|
+
else:
|
|
200
|
+
raise TypeError(f"Unknown format `{format}`")
|
|
201
|
+
|
|
202
|
+
return rc
|
|
203
|
+
|
|
204
|
+
def describe(self, sobj_name, detailed=False, format="pprint"):
|
|
205
|
+
"""Describe an sobject.
|
|
206
|
+
|
|
207
|
+
Arguments:
|
|
208
|
+
|
|
209
|
+
sobj_name - sobject name to describe. e.g. "Account", "Contact"
|
|
210
|
+
detailed - set to `True` to get detailed information about object
|
|
211
|
+
format -- one of these values:
|
|
212
|
+
- "pprint" -- string in easily readable Python dict shape (default)
|
|
213
|
+
- "obj" -- ordinary Python objects
|
|
214
|
+
|
|
215
|
+
For example:
|
|
216
|
+
|
|
217
|
+
>>> describe("Account")
|
|
218
|
+
>>> data = describe("Account", detailed=True, format=obj)
|
|
219
|
+
"""
|
|
220
|
+
from pprint import pprint
|
|
221
|
+
|
|
222
|
+
data = getattr(self._sf, sobj_name).describe()
|
|
223
|
+
|
|
224
|
+
if detailed:
|
|
225
|
+
rc = data
|
|
226
|
+
else:
|
|
227
|
+
rc = dict(_summarize(field) for field in data["fields"])
|
|
228
|
+
|
|
229
|
+
if format == "pprint":
|
|
230
|
+
pprint(rc)
|
|
231
|
+
elif format == "obj":
|
|
232
|
+
return rc
|
|
233
|
+
else:
|
|
234
|
+
raise TypeError(f"Unknown format {format}")
|
cumulusci/cli/utils.py
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import contextlib
|
|
2
|
+
import os
|
|
3
|
+
import re
|
|
4
|
+
import sys
|
|
5
|
+
import time
|
|
6
|
+
from collections import defaultdict
|
|
7
|
+
from typing import Optional
|
|
8
|
+
|
|
9
|
+
import click
|
|
10
|
+
import requests
|
|
11
|
+
from packaging import version as packaging_version
|
|
12
|
+
from rich.console import Console
|
|
13
|
+
|
|
14
|
+
from cumulusci import __version__
|
|
15
|
+
from cumulusci.core.config import UniversalConfig
|
|
16
|
+
from cumulusci.utils import get_cci_upgrade_command
|
|
17
|
+
from cumulusci.utils.http.requests_utils import safe_json_from_response
|
|
18
|
+
|
|
19
|
+
LOWEST_SUPPORTED_VERSION = (3, 8, 0)
|
|
20
|
+
WIN_LONG_PATH_WARNING = """
|
|
21
|
+
WARNING: Long path support is not enabled. This can lead to errors with some
|
|
22
|
+
tasks. Your administrator will need to activate the "Enable Win32 long paths"
|
|
23
|
+
group policy, or set LongPathsEnabled to 1 in the registry key
|
|
24
|
+
HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\FileSystem.
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def group_items(items):
|
|
29
|
+
"""Given a list of dicts with 'group' keys,
|
|
30
|
+
returns those items in lists categorized group"""
|
|
31
|
+
groups = defaultdict(list)
|
|
32
|
+
for item in items:
|
|
33
|
+
group_name = item["group"] or "Other"
|
|
34
|
+
groups[group_name].append([item["name"], item["description"]])
|
|
35
|
+
|
|
36
|
+
return groups
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
@contextlib.contextmanager
|
|
40
|
+
def timestamp_file(
|
|
41
|
+
config_dir: Optional[str] = None, timestamp_file: str = "cumulus_timestamp"
|
|
42
|
+
):
|
|
43
|
+
"""Opens a file for tracking the time of the last version check"""
|
|
44
|
+
|
|
45
|
+
config_dir = (
|
|
46
|
+
UniversalConfig.default_cumulusci_dir() if config_dir is None else config_dir
|
|
47
|
+
)
|
|
48
|
+
timestamp_file = os.path.join(config_dir, timestamp_file)
|
|
49
|
+
|
|
50
|
+
try:
|
|
51
|
+
with open(timestamp_file, "r+") as f:
|
|
52
|
+
yield f
|
|
53
|
+
except IOError: # file does not exist
|
|
54
|
+
with open(timestamp_file, "w+") as f:
|
|
55
|
+
yield f
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
FINAL_VERSION_RE = re.compile(r"^[\d\.]+$")
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def is_final_release(version: str) -> bool:
|
|
62
|
+
"""Returns bool whether version string should be considered a final release.
|
|
63
|
+
|
|
64
|
+
cumulusci versions are considered final if they contain only digits and periods.
|
|
65
|
+
e.g. 1.0.1 is final but 2.0b1 and 2.0.dev0 are not.
|
|
66
|
+
"""
|
|
67
|
+
return bool(FINAL_VERSION_RE.match(version))
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def get_latest_final_version():
|
|
71
|
+
"""return the latest version of cumulusci in pypi, be defensive"""
|
|
72
|
+
# use the pypi json api https://wiki.python.org/moin/PyPIJSON
|
|
73
|
+
res = safe_json_from_response(
|
|
74
|
+
requests.get("https://pypi.org/pypi/cumulusci/json", timeout=5)
|
|
75
|
+
)
|
|
76
|
+
with timestamp_file() as f:
|
|
77
|
+
f.write(str(time.time()))
|
|
78
|
+
versions = []
|
|
79
|
+
for versionstring in res["releases"].keys():
|
|
80
|
+
if not is_final_release(versionstring):
|
|
81
|
+
continue
|
|
82
|
+
versions.append(packaging_version.parse(versionstring))
|
|
83
|
+
versions.sort(reverse=True)
|
|
84
|
+
return versions[0]
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def check_latest_version():
|
|
88
|
+
"""checks for the latest version of cumulusci from pypi, max once per hour"""
|
|
89
|
+
check = True
|
|
90
|
+
|
|
91
|
+
with timestamp_file() as f:
|
|
92
|
+
timestamp = float(f.read() or 0)
|
|
93
|
+
delta = time.time() - timestamp
|
|
94
|
+
check = delta > 3600
|
|
95
|
+
|
|
96
|
+
if check:
|
|
97
|
+
try:
|
|
98
|
+
latest_version = get_latest_final_version()
|
|
99
|
+
except requests.exceptions.RequestException as e:
|
|
100
|
+
click.echo("Error checking cci version:", err=True)
|
|
101
|
+
click.echo(str(e), err=True)
|
|
102
|
+
return
|
|
103
|
+
|
|
104
|
+
result = latest_version > get_installed_version()
|
|
105
|
+
if result:
|
|
106
|
+
click.echo(
|
|
107
|
+
f"""An update to CumulusCI is available. To install the update, run this command: {get_cci_upgrade_command()}""",
|
|
108
|
+
err=True,
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
if sys.version_info < LOWEST_SUPPORTED_VERSION:
|
|
112
|
+
click.echo(
|
|
113
|
+
"Sorry! Your Python version is not supported. Please upgrade to Python 3.9.",
|
|
114
|
+
err=True,
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def parse_version(versionstring: str) -> packaging_version.Version:
|
|
119
|
+
"""Parse a version string into a Version object."""
|
|
120
|
+
return packaging_version.parse(versionstring)
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def get_installed_version() -> packaging_version.Version:
|
|
124
|
+
"""Get the installed version of CumulusCI."""
|
|
125
|
+
return parse_version(__version__)
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def win32_long_paths_enabled() -> bool:
|
|
129
|
+
"""Boolean indicating whether long paths are available on Windows systems.
|
|
130
|
+
|
|
131
|
+
Reads the Windows Registry the running platform. Throws ModuleNotFoundError
|
|
132
|
+
if run on non-Windows platforms.
|
|
133
|
+
"""
|
|
134
|
+
# Only present on windows, so import it here instead
|
|
135
|
+
import winreg
|
|
136
|
+
|
|
137
|
+
access_registry = winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE)
|
|
138
|
+
access_key = winreg.OpenKey(
|
|
139
|
+
access_registry, r"SYSTEM\CurrentControlSet\Control\FileSystem"
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
is_enabled, _ = winreg.QueryValueEx(access_key, "LongPathsEnabled")
|
|
143
|
+
|
|
144
|
+
return is_enabled == 1
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
def warn_if_no_long_paths(console: Console = Console()) -> None:
|
|
148
|
+
"""Print a warning to the user if long paths are not enabled."""
|
|
149
|
+
if sys.platform.startswith("win") and not win32_long_paths_enabled():
|
|
150
|
+
console.print(WIN_LONG_PATH_WARNING)
|
cumulusci/conftest.py
ADDED
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import io
|
|
2
|
+
import os
|
|
3
|
+
from contextlib import contextmanager, nullcontext
|
|
4
|
+
from http.client import HTTPMessage
|
|
5
|
+
from logging import getLogger
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from tempfile import TemporaryDirectory
|
|
8
|
+
from unittest import mock
|
|
9
|
+
|
|
10
|
+
import pytest
|
|
11
|
+
import yaml
|
|
12
|
+
from pytest import fixture
|
|
13
|
+
from sqlalchemy import create_engine
|
|
14
|
+
from sqlalchemy.orm import sessionmaker
|
|
15
|
+
|
|
16
|
+
from cumulusci.core.dependencies.utils import TaskContext
|
|
17
|
+
from cumulusci.core.github import get_github_api
|
|
18
|
+
from cumulusci.salesforce_api.org_schema_models import Base
|
|
19
|
+
from cumulusci.tasks.bulkdata.tests.integration_test_utils import (
|
|
20
|
+
ensure_accounts,
|
|
21
|
+
ensure_records,
|
|
22
|
+
)
|
|
23
|
+
from cumulusci.tasks.salesforce.tests.util import create_task_fixture
|
|
24
|
+
from cumulusci.tests.pytest_plugins.pytest_sf_vcr import salesforce_vcr, vcr_config
|
|
25
|
+
from cumulusci.tests.util import DummyKeychain, DummyOrgConfig, mock_env
|
|
26
|
+
|
|
27
|
+
ensure_accounts = ensure_accounts
|
|
28
|
+
ensure_records = ensure_records
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@fixture(scope="session", autouse=True)
|
|
32
|
+
def mock_sleep():
|
|
33
|
+
"""Patch time.sleep to avoid delays in unit tests"""
|
|
34
|
+
with mock.patch("time.sleep"):
|
|
35
|
+
yield
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class MockHttpResponse(mock.Mock):
|
|
39
|
+
def __init__(self, status):
|
|
40
|
+
super(MockHttpResponse, self).__init__()
|
|
41
|
+
self.status = status
|
|
42
|
+
self.strict = 0
|
|
43
|
+
self.version = 0
|
|
44
|
+
self.reason = None
|
|
45
|
+
self.msg = HTTPMessage(io.BytesIO())
|
|
46
|
+
self.closed = True
|
|
47
|
+
|
|
48
|
+
def read(self): # pragma: no cover
|
|
49
|
+
return b""
|
|
50
|
+
|
|
51
|
+
def isclosed(self):
|
|
52
|
+
return self.closed
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
@fixture
|
|
56
|
+
def gh_api():
|
|
57
|
+
return get_github_api("TestOwner", "TestRepo")
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
@fixture(scope="class", autouse=True)
|
|
61
|
+
def restore_cwd():
|
|
62
|
+
d = os.getcwd()
|
|
63
|
+
try:
|
|
64
|
+
yield
|
|
65
|
+
finally:
|
|
66
|
+
os.chdir(d)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
@fixture
|
|
70
|
+
def mock_http_response():
|
|
71
|
+
def _make_response(status):
|
|
72
|
+
return MockHttpResponse(status)
|
|
73
|
+
|
|
74
|
+
return _make_response
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
@fixture(scope="function")
|
|
78
|
+
def fallback_org_config():
|
|
79
|
+
def fallback_org_config():
|
|
80
|
+
return DummyOrgConfig(
|
|
81
|
+
name="pytest_sf_orgconnect_dummy_org_config", keychain=DummyKeychain()
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
return fallback_org_config
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
vcr_config = fixture(vcr_config, scope="module")
|
|
88
|
+
vcr = fixture(salesforce_vcr, scope="module")
|
|
89
|
+
|
|
90
|
+
create_task_fixture = fixture(create_task_fixture, scope="function")
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
# TODO: This should also chdir to a temp directory which
|
|
94
|
+
# can represent the repo-root, but that will require
|
|
95
|
+
# test case changes.
|
|
96
|
+
@pytest.fixture(autouse=True)
|
|
97
|
+
def patch_home_and_env(request):
|
|
98
|
+
"Patch the default home directory and $HOME environment for all tests at once."
|
|
99
|
+
|
|
100
|
+
use_real_env = request.node.get_closest_marker("use_real_env")
|
|
101
|
+
|
|
102
|
+
with TemporaryDirectory(prefix="fake_home_") as home:
|
|
103
|
+
if use_real_env:
|
|
104
|
+
mock_env_cm = nullcontext()
|
|
105
|
+
else:
|
|
106
|
+
mock_env_cm = mock_env(home)
|
|
107
|
+
|
|
108
|
+
with mock_env_cm:
|
|
109
|
+
Path(home, ".cumulusci").mkdir()
|
|
110
|
+
Path(home, ".cumulusci/cumulusci.yml").touch()
|
|
111
|
+
yield
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
@pytest.fixture()
|
|
115
|
+
def temp_db():
|
|
116
|
+
with TemporaryDirectory() as t:
|
|
117
|
+
|
|
118
|
+
@contextmanager
|
|
119
|
+
def open_db():
|
|
120
|
+
engine = create_engine(f"sqlite:///{t}/tempfile.db")
|
|
121
|
+
with engine.connect() as connection:
|
|
122
|
+
Session = sessionmaker(bind=connection)
|
|
123
|
+
Base.metadata.bind = engine
|
|
124
|
+
Base.metadata.create_all()
|
|
125
|
+
session = Session()
|
|
126
|
+
yield connection, Base.metadata, session
|
|
127
|
+
|
|
128
|
+
yield open_db
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
@pytest.fixture()
|
|
132
|
+
def delete_data_from_org(create_task):
|
|
133
|
+
def delete_data_from_org(object_names):
|
|
134
|
+
from cumulusci.tasks.bulkdata.delete import DeleteData
|
|
135
|
+
|
|
136
|
+
t = create_task(DeleteData, {"objects": object_names})
|
|
137
|
+
assert t.org_config.scratch
|
|
138
|
+
t()
|
|
139
|
+
|
|
140
|
+
return delete_data_from_org
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
@pytest.fixture(scope="session")
|
|
144
|
+
def cumulusci_test_repo_root():
|
|
145
|
+
return Path(__file__).parent.parent
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
@pytest.fixture(scope="session")
|
|
149
|
+
def global_describe(cumulusci_test_repo_root):
|
|
150
|
+
global_describe_file = (
|
|
151
|
+
cumulusci_test_repo_root
|
|
152
|
+
/ "cumulusci/tests/shared_cassettes/GET_sobjects_Global_describe.yaml"
|
|
153
|
+
)
|
|
154
|
+
with global_describe_file.open() as f:
|
|
155
|
+
data = yaml.safe_load(yaml.safe_load(f)["response"]["body"]["string"])
|
|
156
|
+
|
|
157
|
+
def global_describe_specific_sobjects(sobjects: int = None):
|
|
158
|
+
if sobjects is None: # pragma: no cover
|
|
159
|
+
subset = data.copy()
|
|
160
|
+
elif isinstance(sobjects, int):
|
|
161
|
+
subset = data.copy()
|
|
162
|
+
subset["sobjects"] = subset["sobjects"][0:sobjects]
|
|
163
|
+
elif isinstance(sobjects, (list, tuple)): # pragma: no cover
|
|
164
|
+
raise NotImplementedError(
|
|
165
|
+
"We could implement a by-name subsetting here when we need it."
|
|
166
|
+
)
|
|
167
|
+
return subset
|
|
168
|
+
|
|
169
|
+
return global_describe_specific_sobjects
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
@pytest.fixture(scope="session")
|
|
173
|
+
def shared_vcr_cassettes(cumulusci_test_repo_root):
|
|
174
|
+
return Path(cumulusci_test_repo_root / "cumulusci/tests/shared_cassettes")
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
@pytest.fixture
|
|
178
|
+
def task_context(org_config, project_config):
|
|
179
|
+
return TaskContext(
|
|
180
|
+
org_config=org_config, project_config=project_config, logger=getLogger()
|
|
181
|
+
)
|
|
File without changes
|