Skip to content

Commit 50eeaa1

Browse files
authored
Merge branch 'main' into fix/namespaced-config-value-type-in-schema
2 parents 3364c76 + f179b0c commit 50eeaa1

14 files changed

Lines changed: 143 additions & 119 deletions

File tree

AUTHORS.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,4 @@ For example:
3939
* Chandler Anderson (zenibako)
4040
* Ben French (BenjaminFrench)
4141
* Rupert Barrow (rupertbarrow)
42+
* Rupesh J (rupeshjSFDC)

cumulusci/__about__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = "4.4.0"
1+
__version__ = "4.5.0"

cumulusci/__init__.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
import os
22
import sys
3+
from importlib.metadata import PackageNotFoundError, version
34

45
from simple_salesforce import api, bulk
56

6-
from cumulusci.__about__ import __version__
7-
8-
__import__("pkg_resources").declare_namespace("cumulusci")
9-
107
__location__ = os.path.dirname(os.path.realpath(__file__))
118

12-
__version__ = __version__
9+
try:
10+
__version__ = version("cumulusci")
11+
except PackageNotFoundError:
12+
__version__ = "unknown"
1313

1414
if sys.version_info < (3, 8): # pragma: no cover
1515
raise Exception("CumulusCI requires Python 3.8+.")

cumulusci/cli/robot.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1+
import importlib.metadata
12
import sys
23

34
import click
4-
import pkg_resources
55
import sarge
66

77
from .runtime import pass_runtime
@@ -109,5 +109,8 @@ def _require_npm():
109109

110110
def _is_package_installed(package_name):
111111
"""Return True if the given package is installed"""
112-
# technique shamelessly stolen from https://stackoverflow.com/a/44210735/7432
113-
return package_name in {pkg.key for pkg in pkg_resources.working_set}
112+
try:
113+
importlib.metadata.distribution(package_name)
114+
return True
115+
except importlib.metadata.PackageNotFoundError:
116+
return False

cumulusci/cli/runtime.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
import click
88
import keyring
9-
import pkg_resources
9+
from packaging import version
1010

1111
from cumulusci.cli.utils import get_installed_version
1212
from cumulusci.core.exceptions import ConfigError, KeychainKeyNotFound, OrgNotFound
@@ -143,7 +143,7 @@ def check_cumulusci_version(self):
143143
if self.project_config:
144144
min_cci_version = self.project_config.minimum_cumulusci_version
145145
if min_cci_version:
146-
parsed_version = pkg_resources.parse_version(min_cci_version)
146+
parsed_version = version.parse(min_cci_version)
147147
if get_installed_version() < parsed_version:
148148
raise click.UsageError(
149149
f"This project requires CumulusCI version {min_cci_version} or later. "

cumulusci/cli/tests/test_cci.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88
from unittest import mock
99

1010
import click
11-
import pkg_resources
1211
import pytest
12+
from packaging import version
1313
from requests.exceptions import ConnectionError
1414
from rich.console import Console
1515

@@ -402,7 +402,7 @@ def test_cli():
402402

403403
@mock.patch(
404404
"cumulusci.cli.cci.get_latest_final_version",
405-
mock.Mock(return_value=pkg_resources.parse_version("100")),
405+
mock.Mock(return_value=version.parse("100")),
406406
)
407407
def test_version(capsys):
408408
run_click_command(cci.version)
@@ -413,7 +413,7 @@ def test_version(capsys):
413413

414414
@mock.patch(
415415
"cumulusci.cli.cci.get_latest_final_version",
416-
mock.Mock(return_value=pkg_resources.parse_version("1")),
416+
mock.Mock(return_value=version.parse("1")),
417417
)
418418
def test_version__latest(capsys):
419419
run_click_command(cci.version)

cumulusci/cli/tests/test_robot.py

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,11 @@
99
from .utils import run_cli_command
1010

1111

12-
class MockWorkingSet(list):
13-
"""Mocks a pkg_resources.workingset object
12+
class MockDistribution:
13+
"""Mocks an importlib.metadata.Distribution object"""
1414

15-
Basically, a list of mock packages representing all of the packages
16-
installed in the current environment
17-
"""
18-
19-
def __init__(self, *package_names):
20-
super().__init__()
21-
for package_name in package_names:
22-
pkg = mock.Mock()
23-
pkg.key = package_name
24-
self.append(pkg)
15+
def __init__(self, name):
16+
self.name = name
2517

2618

2719
def mock_Command(returncodes={}):
@@ -49,16 +41,18 @@ def run():
4941
return the_real_mock
5042

5143

52-
@mock.patch("cumulusci.cli.robot.pkg_resources")
53-
def test_is_package_installed(pkg_resources):
44+
@mock.patch("cumulusci.cli.robot.importlib.metadata.distribution")
45+
def test_is_package_installed(mock_distribution):
5446
"""Verify that the helper _is_package_installed returns the correct result"""
55-
pkg_resources.working_set = MockWorkingSet(
56-
"robotframework", "robotframework-browser", "snowfakery"
57-
)
47+
# Test when package is installed
48+
mock_distribution.return_value = MockDistribution("robotframework-browser")
5849
result = _is_package_installed("robotframework-browser")
5950
assert result is True
6051

61-
pkg_resources.working_set = MockWorkingSet("robotframework", "snowfakery")
52+
# Test when package is not installed
53+
from importlib.metadata import PackageNotFoundError
54+
55+
mock_distribution.side_effect = PackageNotFoundError("Package not found")
6256
result = _is_package_installed("robotframework-browser")
6357
assert result is False
6458

cumulusci/cli/tests/test_utils.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@
33
import time
44
from unittest import mock
55

6-
import pkg_resources
76
import pytest
87
import requests
98
import responses
9+
from packaging import version
1010

1111
import cumulusci
1212

@@ -46,8 +46,8 @@ def test_get_latest_final_version():
4646
def test_check_latest_version(click, get_latest_final_version, get_installed_version):
4747
with utils.timestamp_file() as f:
4848
f.write(str(time.time() - 4000))
49-
get_latest_final_version.return_value = pkg_resources.parse_version("2")
50-
get_installed_version.return_value = pkg_resources.parse_version("1")
49+
get_latest_final_version.return_value = version.parse("2")
50+
get_installed_version.return_value = version.parse("1")
5151

5252
utils.check_latest_version()
5353
if sys.version_info > utils.LOWEST_SUPPORTED_VERSION:

cumulusci/cli/utils.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
from collections import defaultdict
77

88
import click
9-
import pkg_resources
109
import requests
10+
from packaging import version as packaging_version
1111
from rich.console import Console
1212

1313
from cumulusci import __version__
@@ -74,7 +74,7 @@ def get_latest_final_version():
7474
for versionstring in res["releases"].keys():
7575
if not is_final_release(versionstring):
7676
continue
77-
versions.append(pkg_resources.parse_version(versionstring))
77+
versions.append(packaging_version.parse(versionstring))
7878
versions.sort(reverse=True)
7979
return versions[0]
8080

@@ -110,9 +110,14 @@ def check_latest_version():
110110
)
111111

112112

113-
def get_installed_version():
114-
"""returns the version name (e.g. 2.0.0b58) that is installed"""
115-
return pkg_resources.parse_version(__version__)
113+
def parse_version(versionstring: str) -> packaging_version.Version:
114+
"""Parse a version string into a Version object."""
115+
return packaging_version.parse(versionstring)
116+
117+
118+
def get_installed_version() -> packaging_version.Version:
119+
"""Get the installed version of CumulusCI."""
120+
return parse_version(__version__)
116121

117122

118123
def win32_long_paths_enabled() -> bool:

cumulusci/tasks/salesforce/sourcetracking.py

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,8 @@ def _reset_sfdx_snapshot(self):
182182
retrieve_changes_task_options["output_dir"] = {
183183
"description": (
184184
"The output directory for the retrieved metadata. "
185-
+ "If not specified, defaults to force-app or the target directory passed to retrieve changes."
185+
+ "If set, this will be passed as the --output-dir option to 'sfdx project retrieve start'. "
186+
+ "If not set, the default output directory will be used by Salesforce CLI (usually 'force-app')."
186187
),
187188
"required": False,
188189
}
@@ -247,10 +248,8 @@ def retrieve_components(
247248
to a namespace prefix to replace it with a `%%%NAMESPACE%%%` token.
248249
"""
249250

250-
# Always use output_dir if specified, else use target
251-
retrieve_target = (
252-
os.path.realpath(output_dir) if output_dir else os.path.realpath(target)
253-
)
251+
# Resolve output_dir if provided; otherwise let sfdx choose defaults
252+
retrieve_target = os.path.realpath(output_dir) if output_dir else None
254253
profiles = []
255254
# If retrieve_complete_profile and project_config is None, raise error
256255
# This is because project_config is only required if retrieve_complete_profile is True
@@ -302,21 +301,23 @@ def retrieve_components(
302301
_write_manifest(components, package_xml_path, api_version)
303302

304303
# Retrieve specified components in DX format
304+
args = [
305+
"-a",
306+
str(api_version),
307+
"-x",
308+
os.path.join(package_xml_path, "package.xml"),
309+
"-w",
310+
"5",
311+
"--ignore-conflicts",
312+
]
313+
if retrieve_target is not None:
314+
args.extend(["--output-dir", retrieve_target])
315+
305316
p = sfdx(
306317
"project retrieve start",
307318
access_token=org_config.access_token,
308319
log_note="Retrieving components",
309-
args=[
310-
"-a",
311-
str(api_version),
312-
"-x",
313-
os.path.join(package_xml_path, "package.xml"),
314-
"-w",
315-
"5",
316-
"--ignore-conflicts",
317-
"--output-dir",
318-
retrieve_target,
319-
],
320+
args=args,
320321
capture_output=capture_output,
321322
check_return=True,
322323
env={"SF_ORG_INSTANCE_URL": org_config.instance_url},

0 commit comments

Comments
 (0)