From ea016ac5c51be590f06aaee93044387aa53fe225 Mon Sep 17 00:00:00 2001 From: Paul Prescod Date: Mon, 16 Jan 2023 14:07:09 -0800 Subject: [PATCH 1/5] Cleanup some warnings --- .prettierignore | 1 + cumulusci/core/config/org_config.py | 9 +++++---- cumulusci/core/config/tests/test_config.py | 2 +- ....test_datasets_read_explicit_extract_declaration.yaml | 3 +++ 4 files changed, 10 insertions(+), 5 deletions(-) create mode 100644 cumulusci/core/tests/cassettes/TestDatasetsE2E.test_datasets_read_explicit_extract_declaration.yaml diff --git a/.prettierignore b/.prettierignore index e69de29bb2..329331137b 100644 --- a/.prettierignore +++ b/.prettierignore @@ -0,0 +1 @@ +Test*.yaml \ No newline at end of file diff --git a/cumulusci/core/config/org_config.py b/cumulusci/core/config/org_config.py index b3f191d172..19d5ccbe6a 100644 --- a/cumulusci/core/config/org_config.py +++ b/cumulusci/core/config/org_config.py @@ -3,6 +3,8 @@ from collections import defaultdict, namedtuple from contextlib import contextmanager from datetime import date, datetime +from distutils.version import StrictVersion +from typing import Optional from urllib.parse import urlparse import requests @@ -47,14 +49,12 @@ class OrgConfig(BaseConfig): is_sandbox: bool namespace: str namespaced: bool - org_id: str org_type: str password: str scratch: bool scratch_org_type: str set_password: bool sfdx_alias: str - username: str userinfo: str id: str active: bool @@ -63,8 +63,9 @@ class OrgConfig(BaseConfig): refresh_token: str client_secret: str connected_app: str + serialization_format: str - createable: bool = None + createable: Optional[bool] = None # make sure it can be mocked for tests OAuth2Client = OAuth2Client @@ -254,7 +255,7 @@ def populate_expiration_date(self): @property def organization_sobject(self): """Cached copy of Organization sObject. Does not perform API call.""" - return self._org_sobject + return getattr(self, "_org_sobject", None) def _fetch_community_info(self): """Use the API to re-fetch information about communities""" diff --git a/cumulusci/core/config/tests/test_config.py b/cumulusci/core/config/tests/test_config.py index 74b2104bb8..c5394a9be2 100644 --- a/cumulusci/core/config/tests/test_config.py +++ b/cumulusci/core/config/tests/test_config.py @@ -66,7 +66,7 @@ def test_getattr_toplevel_key_missing(self): assert config.foo is None with mock.patch( "cumulusci.core.config.base_config.STRICT_GETATTR", True - ), pytest.raises(AssertionError): + ), pytest.deprecated_call(), pytest.raises(AssertionError): assert config.foo is None def test_getattr_child_key(self): diff --git a/cumulusci/core/tests/cassettes/TestDatasetsE2E.test_datasets_read_explicit_extract_declaration.yaml b/cumulusci/core/tests/cassettes/TestDatasetsE2E.test_datasets_read_explicit_extract_declaration.yaml new file mode 100644 index 0000000000..86d77843f9 --- /dev/null +++ b/cumulusci/core/tests/cassettes/TestDatasetsE2E.test_datasets_read_explicit_extract_declaration.yaml @@ -0,0 +1,3 @@ +version: 1 +interactions: + - include_file: GET_sobjects_Organization.yaml From 49c5d26228091d00b3a6e0005831c2641bf6b3c4 Mon Sep 17 00:00:00 2001 From: Paul Prescod Date: Tue, 17 Jan 2023 05:20:32 -0800 Subject: [PATCH 2/5] Cleanup various warnings --- .../tasks/bulkdata/tests/test_snowfakery.py | 2 -- cumulusci/tasks/release_notes/parser.py | 2 +- .../tasks/salesforce/BaseRetrieveMetadata.py | 3 ++- cumulusci/tasks/salesforce/RetrievePackaged.py | 4 +++- .../salesforce/tests/test_RetrievePackaged.py | 1 + .../salesforce/users/tests/test_permsets.py | 17 +++++++++-------- .../tasks/tests/test_create_package_version.py | 2 +- cumulusci/utils/ziputils.py | 2 +- 8 files changed, 18 insertions(+), 15 deletions(-) diff --git a/cumulusci/tasks/bulkdata/tests/test_snowfakery.py b/cumulusci/tasks/bulkdata/tests/test_snowfakery.py index de87c5503f..99858b2e00 100644 --- a/cumulusci/tasks/bulkdata/tests/test_snowfakery.py +++ b/cumulusci/tasks/bulkdata/tests/test_snowfakery.py @@ -783,7 +783,6 @@ def test_explicit_channel_declarations(self, mock_load_data, create_task): "recipe": Path(__file__).parent / "snowfakery/simple_snowfakery.recipe.yml", "run_until_recipe_repeated": 15, - "recipe_options": {"xyzzy": "Nothing happens", "some_number": 42}, "loading_rules": Path(__file__).parent / "snowfakery/simple_snowfakery_channels.load.yml", }, @@ -833,7 +832,6 @@ def test_serial_mode(self, mock_load_data, create_task): "recipe": Path(__file__).parent / "snowfakery/simple_snowfakery.recipe.yml", "run_until_recipe_repeated": 15, - "recipe_options": {"xyzzy": "Nothing happens", "some_number": 42}, "bulk_mode": "Serial", }, ) diff --git a/cumulusci/tasks/release_notes/parser.py b/cumulusci/tasks/release_notes/parser.py index 3e307cfaa7..1fef5d4e16 100644 --- a/cumulusci/tasks/release_notes/parser.py +++ b/cumulusci/tasks/release_notes/parser.py @@ -186,7 +186,7 @@ class GithubIssuesParser(IssuesParser): def __new__(cls, release_notes_generator, title, issue_regex=None): if not release_notes_generator.has_issues: - logging.getLogger(__file__).warn( + logging.getLogger(__file__).warning( "Issues are disabled for this repository. Falling back to change notes parser." ) return GithubLinesParser(release_notes_generator, title) diff --git a/cumulusci/tasks/salesforce/BaseRetrieveMetadata.py b/cumulusci/tasks/salesforce/BaseRetrieveMetadata.py index b8bb7da5f5..65e5a8be42 100644 --- a/cumulusci/tasks/salesforce/BaseRetrieveMetadata.py +++ b/cumulusci/tasks/salesforce/BaseRetrieveMetadata.py @@ -1,4 +1,5 @@ import functools +from zipfile import ZipFile from cumulusci.tasks.salesforce.BaseSalesforceMetadataApiTask import ( BaseSalesforceMetadataApiTask, @@ -52,6 +53,6 @@ def _process_namespace(self, src_zip): ) return src_zip - def _extract_zip(self, src_zip): + def _extract_zip(self, src_zip: ZipFile): src_zip = self._process_namespace(src_zip) src_zip.extractall(self.options["path"]) diff --git a/cumulusci/tasks/salesforce/RetrievePackaged.py b/cumulusci/tasks/salesforce/RetrievePackaged.py index 25ddddf57e..6a24d1f5e4 100644 --- a/cumulusci/tasks/salesforce/RetrievePackaged.py +++ b/cumulusci/tasks/salesforce/RetrievePackaged.py @@ -1,3 +1,5 @@ +from zipfile import ZipFile + from cumulusci.salesforce_api.metadata import ApiRetrievePackaged from cumulusci.tasks.salesforce import BaseRetrieveMetadata from cumulusci.utils import zip_subfolder @@ -34,6 +36,6 @@ def _get_api(self): self, self.options["package"], self.options.get("api_version") ) - def _extract_zip(self, src_zip): + def _extract_zip(self, src_zip: ZipFile): src_zip = zip_subfolder(src_zip, self.options.get("package")) super(RetrievePackaged, self)._extract_zip(src_zip) diff --git a/cumulusci/tasks/salesforce/tests/test_RetrievePackaged.py b/cumulusci/tasks/salesforce/tests/test_RetrievePackaged.py index 352b40cc19..c61a7b82c8 100644 --- a/cumulusci/tasks/salesforce/tests/test_RetrievePackaged.py +++ b/cumulusci/tasks/salesforce/tests/test_RetrievePackaged.py @@ -21,3 +21,4 @@ def test_run_task(self): task.api_class = mock.Mock(return_value=mock.Mock(return_value=zf)) task() assert os.path.exists(os.path.join(path, "testfile")) + zf.close() diff --git a/cumulusci/tasks/salesforce/users/tests/test_permsets.py b/cumulusci/tasks/salesforce/users/tests/test_permsets.py index 901a49952c..5ce0bbca5c 100644 --- a/cumulusci/tasks/salesforce/users/tests/test_permsets.py +++ b/cumulusci/tasks/salesforce/users/tests/test_permsets.py @@ -3,6 +3,7 @@ import pytest import responses +from responses.matchers import json_params_matcher from cumulusci.core.exceptions import CumulusCIException from cumulusci.tasks.salesforce.tests.util import create_task @@ -68,7 +69,7 @@ def test_create_permset(self): status=200, json=[{"id": "0Pa000000000001", "success": True, "errors": []}], match=[ - responses.json_params_matcher( + json_params_matcher( { "allOrNone": False, "records": [ @@ -152,7 +153,7 @@ def test_create_permset__alias(self): {"id": "0Pa000000000001", "success": True, "errors": []}, ], match=[ - responses.json_params_matcher( + json_params_matcher( { "allOrNone": False, "records": [ @@ -383,7 +384,7 @@ def test_create_permset_partial_success_raises(self, table): }, ], match=[ - responses.json_params_matcher( + json_params_matcher( { "allOrNone": False, "records": [ @@ -470,7 +471,7 @@ def test_create_permsetlicense(self): status=200, json=[{"id": "0Pa000000000001", "success": True, "errors": []}], match=[ - responses.json_params_matcher( + json_params_matcher( { "allOrNone": False, "records": [ @@ -543,7 +544,7 @@ def test_create_permsetlicense__no_assignments(self): {"id": "0Pa000000000001", "success": True, "errors": []}, ], match=[ - responses.json_params_matcher( + json_params_matcher( { "allOrNone": False, "records": [ @@ -627,7 +628,7 @@ def test_create_permsetlicense__alias(self): status=200, json=[{"id": "0Pa000000000001", "success": True, "errors": []}], match=[ - responses.json_params_matcher( + json_params_matcher( { "allOrNone": False, "records": [ @@ -774,7 +775,7 @@ def test_create_permsetgroup(self): status=200, json=[{"id": "0Pa000000000001", "success": True, "errors": []}], match=[ - responses.json_params_matcher( + json_params_matcher( { "allOrNone": False, "records": [ @@ -847,7 +848,7 @@ def test_create_permsetgroup__alias(self): status=200, json=[{"id": "0Pa000000000001", "success": True, "errors": []}], match=[ - responses.json_params_matcher( + json_params_matcher( { "allOrNone": False, "records": [ diff --git a/cumulusci/tasks/tests/test_create_package_version.py b/cumulusci/tasks/tests/test_create_package_version.py index 7bd4bdf9e9..7f78c5be5f 100644 --- a/cumulusci/tasks/tests/test_create_package_version.py +++ b/cumulusci/tasks/tests/test_create_package_version.py @@ -455,7 +455,7 @@ def test_run_task( return_value=devhub_config, ): task() - + zf.close() assert task.return_values["dependencies"] == [ {"version_id": "04t000000000009AAA"} ] diff --git a/cumulusci/utils/ziputils.py b/cumulusci/utils/ziputils.py index dabb365eb0..f1ae0ead3e 100644 --- a/cumulusci/utils/ziputils.py +++ b/cumulusci/utils/ziputils.py @@ -3,7 +3,7 @@ import zipfile -def zip_subfolder(zip_src, path): +def zip_subfolder(zip_src: zipfile.ZipFile, path): if not path.endswith("/"): path = path + "/" From ad53e8011e997299f013cd560873e0c4893492ae Mon Sep 17 00:00:00 2001 From: Paul Prescod Date: Tue, 17 Jan 2023 10:37:29 -0800 Subject: [PATCH 3/5] Clean up more warnings --- cumulusci/core/config/org_config.py | 10 ++- .../dependencies/tests/test_dependencies.py | 5 ++ cumulusci/tasks/apex/tests/test_apex_tasks.py | 75 +++++++++++-------- .../tasks/bulkdata/tests/test_snowfakery.py | 2 +- cumulusci/tasks/github/tests/test_release.py | 3 +- .../tests/test_enable_prediction.py | 13 ++-- 6 files changed, 69 insertions(+), 39 deletions(-) diff --git a/cumulusci/core/config/org_config.py b/cumulusci/core/config/org_config.py index 19d5ccbe6a..4867106c8e 100644 --- a/cumulusci/core/config/org_config.py +++ b/cumulusci/core/config/org_config.py @@ -205,7 +205,15 @@ def user_id(self): @property def org_id(self): - return self.id.split("/")[-2] + try: + if org_id := self.config.get("org_id"): + return org_id + elif hasattr(self, "id") and self.id: + return self.id.split("/")[-2] + else: + return None + except Exception as e: # pragma: no cover + assert e is None, e @property def username(self): diff --git a/cumulusci/core/dependencies/tests/test_dependencies.py b/cumulusci/core/dependencies/tests/test_dependencies.py index c3eb329d8f..d50cb25f73 100644 --- a/cumulusci/core/dependencies/tests/test_dependencies.py +++ b/cumulusci/core/dependencies/tests/test_dependencies.py @@ -645,6 +645,7 @@ def test_install(self, api_deploy_mock, zip_builder_mock, download_mock): assert mock_task.project_config == context api_deploy_mock.return_value.assert_called_once() + zf.close() def test_get_unmanaged(self): org = mock.Mock() @@ -733,6 +734,7 @@ def test_install(self, api_deploy_mock, zip_builder_mock, download_mock): assert mock_task.project_config == context api_deploy_mock.return_value.assert_called_once() + zf.close() def test_get_unmanaged(self): org = mock.Mock() @@ -793,6 +795,7 @@ def test_get_metadata_package_zip_builder__mdapi_root( }, context=mock.ANY, ) + zf.close() @mock.patch("cumulusci.core.dependencies.dependencies.MetadataPackageZipBuilder") @mock.patch("cumulusci.core.dependencies.dependencies.download_extract_zip") @@ -827,6 +830,7 @@ def test_get_metadata_package_zip_builder__mdapi_subfolder( }, context=mock.ANY, ) + zf.close() @mock.patch("cumulusci.core.dependencies.dependencies.MetadataPackageZipBuilder") @mock.patch("cumulusci.core.dependencies.dependencies.download_extract_zip") @@ -866,6 +870,7 @@ def test_get_metadata_package_zip_builder__sfdx( capture_output=True, check_return=True, ) + zf.close() class TestParseDependency: diff --git a/cumulusci/tasks/apex/tests/test_apex_tasks.py b/cumulusci/tasks/apex/tests/test_apex_tasks.py index 8f7f654844..83469db56b 100644 --- a/cumulusci/tasks/apex/tests/test_apex_tasks.py +++ b/cumulusci/tasks/apex/tests/test_apex_tasks.py @@ -8,6 +8,7 @@ import pytest import responses +from responses.matchers import query_string_matcher from simple_salesforce import SalesforceGeneralError from cumulusci.core import exceptions as exc @@ -73,9 +74,9 @@ def setup_method(self): def _mock_apex_class_query(self, name="TestClass_TEST", namespace=None): namespace_param = "null" if namespace is None else f"%27{namespace}%27" - url = ( - self.base_tooling_url - + "query/?q=SELECT+Id%2C+Name+" + url = self.base_tooling_url + "query/" + query_string = ( + "q=SELECT+Id%2C+Name+" + f"FROM+ApexClass+WHERE+NamespacePrefix+%3D+{namespace_param}" + "+AND+%28Name+LIKE+%27%25_TEST%27%29" ) @@ -85,7 +86,10 @@ def _mock_apex_class_query(self, name="TestClass_TEST", namespace=None): "totalSize": 1, } responses.add( - responses.GET, url, match_querystring=True, json=expected_response + responses.GET, + url, + match=[query_string_matcher(query_string)], + json=expected_response, ) def _get_mock_test_query_results(self, methodnames, outcomes, messages): @@ -163,59 +167,63 @@ def _get_mock_test_query_results(self, methodnames, outcomes, messages): def _get_mock_test_query_url(self, job_id): return ( - self.base_tooling_url - + "query/?q=%0ASELECT+Id%2CApexClassId%2CTestTimestamp%2C%0A+++++++Message%2CMethodName%2COutcome%2C%0A+++++++RunTime%2CStackTrace%2C%0A+++++++%28SELECT%0A++++++++++Id%2CCallouts%2CAsyncCalls%2CDmlRows%2CEmail%2C%0A++++++++++LimitContext%2CLimitExceptions%2CMobilePush%2C%0A++++++++++QueryRows%2CSosl%2CCpu%2CDml%2CSoql%0A++++++++FROM+ApexTestResults%29%0AFROM+ApexTestResult%0AWHERE+AsyncApexJobId%3D%27{}%27%0A".format( - job_id - ) + self.base_tooling_url + "query/", + f"q=%0ASELECT+Id%2CApexClassId%2CTestTimestamp%2C%0A+++++++Message%2CMethodName%2COutcome%2C%0A+++++++RunTime%2CStackTrace%2C%0A+++++++%28SELECT%0A++++++++++Id%2CCallouts%2CAsyncCalls%2CDmlRows%2CEmail%2C%0A++++++++++LimitContext%2CLimitExceptions%2CMobilePush%2C%0A++++++++++QueryRows%2CSosl%2CCpu%2CDml%2CSoql%0A++++++++FROM+ApexTestResults%29%0AFROM+ApexTestResult%0AWHERE+AsyncApexJobId%3D%27{job_id}%27%0A", ) def _get_mock_testqueueitem_status_query_url(self, job_id): return ( - self.base_tooling_url - + f"query/?q=SELECT+Id%2C+Status%2C+ExtendedStatus%2C+ApexClassId+FROM+ApexTestQueueItem+WHERE+ParentJobId+%3D+%27{job_id}%27+AND+Status+%3D+%27Failed%27" + (self.base_tooling_url + "query/"), + f"q=SELECT+Id%2C+Status%2C+ExtendedStatus%2C+ApexClassId+FROM+ApexTestQueueItem+WHERE+ParentJobId+%3D+%27{job_id}%27+AND+Status+%3D+%27Failed%27", ) def _mock_get_test_results( self, outcome="Pass", message="Test Passed", job_id="JOB_ID1234567" ): - url = self._get_mock_test_query_url(job_id) + url, query_string = self._get_mock_test_query_url(job_id) expected_response = self._get_mock_test_query_results( ["TestMethod"], [outcome], [message] ) responses.add( - responses.GET, url, match_querystring=True, json=expected_response + responses.GET, + url, + match=[query_string_matcher(query_string)], + json=expected_response, ) def _mock_get_test_results_multiple( self, method_names, outcomes, messages, job_id="JOB_ID1234567" ): - url = self._get_mock_test_query_url(job_id) + url, query_string = self._get_mock_test_query_url(job_id) expected_response = self._get_mock_test_query_results( method_names, outcomes, messages ) responses.add( - responses.GET, url, match_querystring=True, json=expected_response + responses.GET, + url, + match=[query_string_matcher(query_string)], + json=expected_response, ) def _mock_get_failed_test_classes(self, job_id="JOB_ID1234567"): - url = self._get_mock_testqueueitem_status_query_url(job_id) + url, query_string = self._get_mock_testqueueitem_status_query_url(job_id) responses.add( responses.GET, url, - match_querystring=True, + match=[query_string_matcher(query_string)], json={"totalSize": 0, "records": [], "done": True}, ) def _mock_get_failed_test_classes_failure(self, job_id="JOB_ID1234567"): - url = self._get_mock_testqueueitem_status_query_url(job_id) + url, query_string = self._get_mock_testqueueitem_status_query_url(job_id) responses.add( responses.GET, url, - match_querystring=True, + match=[query_string_matcher(query_string)], json={ "totalSize": 1, "records": [ @@ -231,14 +239,15 @@ def _mock_get_failed_test_classes_failure(self, job_id="JOB_ID1234567"): ) def _mock_get_symboltable(self): - url = ( - self.base_tooling_url - + "query/?q=SELECT+SymbolTable+FROM+ApexClass+WHERE+Name%3D%27TestClass_TEST%27" + url = self.base_tooling_url + "query/" + query_string = ( + "q=SELECT+SymbolTable+FROM+ApexClass+WHERE+Name%3D%27TestClass_TEST%27" ) responses.add( responses.GET, url, + match=[query_string_matcher(query_string)], json={ "records": [ { @@ -261,9 +270,9 @@ def _mock_get_symboltable_failure(self): responses.add(responses.GET, url, json={"records": []}) def _mock_tests_complete(self, job_id="JOB_ID1234567"): - url = ( - self.base_tooling_url - + "query/?q=SELECT+Id%2C+Status%2C+" + url = self.base_tooling_url + "query/" + query_string = ( + "q=SELECT+Id%2C+Status%2C+" + "ApexClassId+FROM+ApexTestQueueItem+WHERE+ParentJobId+%3D+%27" + "{}%27".format(job_id) ) @@ -273,15 +282,18 @@ def _mock_tests_complete(self, job_id="JOB_ID1234567"): "records": [{"Status": "Completed"}], } responses.add( - responses.GET, url, match_querystring=True, json=expected_response + responses.GET, + url, + match=[query_string_matcher(query_string)], + json=expected_response, ) def _mock_tests_processing(self, job_id="JOB_ID1234567"): - url = ( - self.base_tooling_url - + "query/?q=SELECT+Id%2C+Status%2C+" + url = self.base_tooling_url + "query/" + query_string = ( + "q=SELECT+Id%2C+Status%2C+" + "ApexClassId+FROM+ApexTestQueueItem+WHERE+ParentJobId+%3D+%27" - + "{}%27".format(job_id) + + f"{job_id}%27" ) expected_response = { "done": True, @@ -289,7 +301,10 @@ def _mock_tests_processing(self, job_id="JOB_ID1234567"): "records": [{"Status": "Processing", "ApexClassId": 1}], } responses.add( - responses.GET, url, match_querystring=True, json=expected_response + responses.GET, + url, + match=[query_string_matcher(query_string)], + json=expected_response, ) def _mock_run_tests(self, success=True, body="JOB_ID1234567"): diff --git a/cumulusci/tasks/bulkdata/tests/test_snowfakery.py b/cumulusci/tasks/bulkdata/tests/test_snowfakery.py index 99858b2e00..daa0fa2ef4 100644 --- a/cumulusci/tasks/bulkdata/tests/test_snowfakery.py +++ b/cumulusci/tasks/bulkdata/tests/test_snowfakery.py @@ -787,7 +787,7 @@ def test_explicit_channel_declarations(self, mock_load_data, create_task): / "snowfakery/simple_snowfakery_channels.load.yml", }, ) - with mock.patch.object( + with pytest.warns(UserWarning), mock.patch.object( task.project_config, "keychain", DummyKeychain() ) as keychain: diff --git a/cumulusci/tasks/github/tests/test_release.py b/cumulusci/tasks/github/tests/test_release.py index 9fabe24eb3..14563ba6b3 100644 --- a/cumulusci/tasks/github/tests/test_release.py +++ b/cumulusci/tasks/github/tests/test_release.py @@ -3,6 +3,7 @@ import pytest import responses +from responses.matchers import json_params_matcher from cumulusci.core.config import ServiceConfig, TaskConfig from cumulusci.core.exceptions import GithubException, TaskOptionsError @@ -352,7 +353,7 @@ def test_run_task__with_beta_2gp(self): url=self.repo_api_url + "/releases", json=self._get_expected_release("release"), match=[ - responses.json_params_matcher( + json_params_matcher( { "tag_name": "beta/1.1", "name": "1.1", diff --git a/cumulusci/tasks/salesforce/tests/test_enable_prediction.py b/cumulusci/tasks/salesforce/tests/test_enable_prediction.py index 194c0e4a19..101860177c 100644 --- a/cumulusci/tasks/salesforce/tests/test_enable_prediction.py +++ b/cumulusci/tasks/salesforce/tests/test_enable_prediction.py @@ -1,5 +1,6 @@ import pytest import responses +from responses.matchers import json_params_matcher from cumulusci.core.config.org_config import OrgConfig from cumulusci.core.exceptions import CumulusCIException @@ -89,12 +90,12 @@ def test_run_task(mock_oauth, task): mock_oauth.add( method="PATCH", url=f"https://test-dev-ed.my.salesforce.com/services/data/v{CURRENT_SF_API_VERSION}/tooling/sobjects/MLPredictionDefinition/001", - match=[responses.json_params_matcher({"Metadata": {"status": "Enabled"}})], + match=[json_params_matcher({"Metadata": {"status": "Enabled"}})], ) mock_oauth.add( method="PATCH", url=f"https://test-dev-ed.my.salesforce.com/services/data/v{CURRENT_SF_API_VERSION}/tooling/sobjects/MLPredictionDefinition/002", - match=[responses.json_params_matcher({"Metadata": {"status": "Enabled"}})], + match=[json_params_matcher({"Metadata": {"status": "Enabled"}})], ) task() @@ -164,12 +165,12 @@ def test_run_task__namespaced_org(mock_oauth, task): mock_oauth.add( method="PATCH", url=f"https://test-dev-ed.my.salesforce.com/services/data/v{CURRENT_SF_API_VERSION}/tooling/sobjects/MLPredictionDefinition/001", - match=[responses.json_params_matcher({"Metadata": {"status": "Enabled"}})], + match=[json_params_matcher({"Metadata": {"status": "Enabled"}})], ) mock_oauth.add( method="PATCH", url=f"https://test-dev-ed.my.salesforce.com/services/data/v{CURRENT_SF_API_VERSION}/tooling/sobjects/MLPredictionDefinition/002", - match=[responses.json_params_matcher({"Metadata": {"status": "Enabled"}})], + match=[json_params_matcher({"Metadata": {"status": "Enabled"}})], ) mock_oauth.add( @@ -222,12 +223,12 @@ def test_run_task__managed_org(mock_oauth, task): mock_oauth.add( method="PATCH", url=f"https://test-dev-ed.my.salesforce.com/services/data/v{CURRENT_SF_API_VERSION}/tooling/sobjects/MLPredictionDefinition/001", - match=[responses.json_params_matcher({"Metadata": {"status": "Enabled"}})], + match=[json_params_matcher({"Metadata": {"status": "Enabled"}})], ) mock_oauth.add( method="PATCH", url=f"https://test-dev-ed.my.salesforce.com/services/data/v{CURRENT_SF_API_VERSION}/tooling/sobjects/MLPredictionDefinition/002", - match=[responses.json_params_matcher({"Metadata": {"status": "Enabled"}})], + match=[json_params_matcher({"Metadata": {"status": "Enabled"}})], ) task() From b4867541b21cc1548b8695f7a1d81a9fa1178a86 Mon Sep 17 00:00:00 2001 From: Paul Prescod Date: Tue, 17 Jan 2023 11:35:38 -0800 Subject: [PATCH 4/5] Cleanup OAuth Warnings --- cumulusci/oauth/tests/test_client.py | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/cumulusci/oauth/tests/test_client.py b/cumulusci/oauth/tests/test_client.py index 1737792e9a..357140c5ed 100644 --- a/cumulusci/oauth/tests/test_client.py +++ b/cumulusci/oauth/tests/test_client.py @@ -13,7 +13,10 @@ import responses from requests.models import Response -from cumulusci.core.exceptions import SalesforceCredentialsException +from cumulusci.core.exceptions import ( + CumulusCIUsageError, + SalesforceCredentialsException, +) from cumulusci.core.keychain.base_project_keychain import DEFAULT_CONNECTED_APP_PORT from cumulusci.oauth.client import ( PORT_IN_USE_ERR, @@ -72,9 +75,17 @@ def http_client(client_config): @contextmanager @mock.patch("time.sleep", time.sleep) # undo mock from conftest -def httpd_thread(oauth_client): +def httpd_thread(oauth_client, expected_error=None): # call OAuth object on another thread - this spawns local httpd - thread = threading.Thread(target=oauth_client.auth_code_flow) + + def run_code_and_check_exception(): + if expected_error: + with pytest.raises(expected_error): + oauth_client.auth_code_flow() + else: + oauth_client.auth_code_flow() + + thread = threading.Thread(target=run_code_and_check_exception) thread.start() while thread.is_alive(): if oauth_client.httpd: @@ -191,7 +202,7 @@ def test_oauth_flow_error_from_auth(self, client): ) # call OAuth object on another thread - this spawns local httpd - with httpd_thread(client): + with httpd_thread(client, OAuth2Error): # simulate callback from browser with pytest.raises(urllib.error.HTTPError): urllib.request.urlopen( @@ -203,7 +214,7 @@ def test_oauth_flow_error_from_auth(self, client): sys.platform.startswith("win"), reason="setup differs from windows" ) def test_create_httpd__port_already_in_use(self, client): - with httpd_thread(client): + with httpd_thread(client, CumulusCIUsageError): with pytest.raises( OAuth2Error, match=PORT_IN_USE_ERR.format(DEFAULT_CONNECTED_APP_PORT) ): @@ -226,7 +237,7 @@ def test_oauth_flow_error_from_token(self, client): ) # call OAuth object on another thread - this spawns local httpd - with httpd_thread(client): + with httpd_thread(client, OAuth2Error): # simulate callback from browser with pytest.raises(urllib.error.HTTPError): urllib.request.urlopen(client.client_config.redirect_uri + "?code=123") From 00d2bb0d5cde8000de548fa84e93de45f82c7861 Mon Sep 17 00:00:00 2001 From: Paul Prescod Date: Tue, 9 May 2023 15:33:45 -0700 Subject: [PATCH 5/5] Remove extra import --- cumulusci/core/config/org_config.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cumulusci/core/config/org_config.py b/cumulusci/core/config/org_config.py index 4867106c8e..e179fbbe3b 100644 --- a/cumulusci/core/config/org_config.py +++ b/cumulusci/core/config/org_config.py @@ -3,7 +3,6 @@ from collections import defaultdict, namedtuple from contextlib import contextmanager from datetime import date, datetime -from distutils.version import StrictVersion from typing import Optional from urllib.parse import urlparse @@ -326,7 +325,8 @@ def installed_packages(self): To check if a required package is present, call `has_minimum_package_version()` with either the namespace or 033 Id of the desired package and its version, in 1.2.3 format. - Beta version of a package are represented as "1.2.3b5", where 5 is the build number.""" + Beta version of a package are represented as "1.2.3b5", where 5 is the build number. + """ if self._installed_packages is None: isp_result = self.salesforce_client.restful( "tooling/query/?q=SELECT SubscriberPackage.Id, SubscriberPackage.NamespacePrefix, "