Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 0 additions & 8 deletions .flake8

This file was deleted.

16 changes: 6 additions & 10 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,27 +1,23 @@
default_language_version:
python: python3
repos:
- repo: https://github.com/ambv/black
rev: 22.3.0
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.15.8
hooks:
- id: black
- id: ruff
args: [--fix]
- id: ruff-format
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v2.0.0
rev: v5.0.0
hooks:
- id: check-merge-conflict
- id: flake8
- id: debug-statements
exclude: "cumulusci/(utils/logging|cli/cci|tasks/robotframework/debugger/ui|cli/task|robotframework/utils).py"
- repo: https://github.com/Lucas-C/pre-commit-hooks-markup
rev: v1.0.1
hooks:
- id: rst-linter
exclude: "docs"
- repo: https://github.com/pycqa/isort
rev: 5.12.0
hooks:
- id: isort
args: ["--profile", "black", "--filter-files"]
- repo: https://github.com/pre-commit/mirrors-prettier
rev: v3.1.0
hooks:
Expand Down
16 changes: 12 additions & 4 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
Test*.yaml
# Jinja-templated HTML: Prettier lowercases <!DOCTYPE>, which breaks
# xml.etree.ElementTree.parse() in RobotLibDoc tests.
cumulusci/tasks/robotframework/template.html

# VCR cassettes are YAML-shaped but not reliably parseable by Prettier's YAML
# formatter (multi-line quoted bodies, anchors, etc.).
**/cassettes/**

# Bundled third-party diagram assets (minified JS/CSS).
docs/diagram/
**/*.min.js
**/*.min.css
cumulusci/files/templates/

# Jinja-templated JSON/YAML shipped as project templates.
cumulusci/files/templates/
2 changes: 1 addition & 1 deletion .readthedocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ sphinx:
formats:
- pdf
- epub
# Optionally declare the Python requirements required to build your docs
# Optionally declare the Python requirements required to build your docs
# python:
# install:
# - requirements: requirements_dev.txt
30 changes: 15 additions & 15 deletions CODE_OF_CONDUCT.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,23 +35,23 @@ socioeconomic status, or other similar personal characteristics.
Examples of behavior that contributes to creating a positive environment
include:

* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy toward other community members
- Using welcoming and inclusive language
- Being respectful of differing viewpoints and experiences
- Gracefully accepting constructive criticism
- Focusing on what is best for the community
- Showing empathy toward other community members

Examples of unacceptable behavior by participants include:

* The use of sexualized language or imagery and unwelcome sexual attention or
advances
* Personal attacks, insulting/derogatory comments, or trolling
* Public or private harassment
* Publishing, or threatening to publish, others' private information—such as
a physical or electronic address—without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
* Advocating for or encouraging any of the above behaviors
- The use of sexualized language or imagery and unwelcome sexual attention or
advances
- Personal attacks, insulting/derogatory comments, or trolling
- Public or private harassment
- Publishing, or threatening to publish, others' private information—such as
a physical or electronic address—without explicit permission
- Other conduct which could reasonably be considered inappropriate in a
professional setting
- Advocating for or encouraging any of the above behaviors

## Our Responsibilities

Expand Down Expand Up @@ -98,7 +98,7 @@ It includes adaptions and additions from [Go Community Code of Conduct][golang-c

This Code of Conduct is licensed under the [Creative Commons Attribution 3.0 License][cc-by-3-us].

[contributor-covenant-home]: https://www.contributor-covenant.org (https://www.contributor-covenant.org/)
[contributor-covenant-home]: https://www.contributor-covenant.org "https://www.contributor-covenant.org/"
[golang-coc]: https://golang.org/conduct
[cncf-coc]: https://github.com/cncf/foundation/blob/master/code-of-conduct.md
[microsoft-coc]: https://opensource.microsoft.com/codeofconduct/
Expand Down
23 changes: 9 additions & 14 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -40,20 +40,20 @@ clean-pyc: ## remove Python file artifacts
find . -name '__pycache__' -exec rm -fr {} +

clean-test: ## remove test and coverage artifacts
rm -fr .tox/
rm -f .coverage
rm -fr htmlcov/
rm -f output.xml
rm -f report.html

lint: ## check style with flake8
flake8 cumulusci tests
lint: ## check style with ruff and pyright
ruff check cumulusci tests
ruff format --check cumulusci tests

test: ## run tests quickly with the default Python
pytest

test-all: ## run tests on every Python version with tox
tox
test-all: ## run tests on every Python version via CI matrix
@echo "Multi-version testing runs in CI. Use 'pytest' for local testing."

# Use CLASS_PATH to run coverage for a subset of tests.
# $ make coverage CLASS_PATH="cumulusci/core/tests"
Expand Down Expand Up @@ -82,7 +82,6 @@ servedocs: docs ## compile the docs watching for changes
watchmedo shell-command -p '*.rst' -c '$(MAKE) -C docs html' -R -D .

release: clean ## package and upload a release
python utility/pin_dependencies.py
hatch build
hatch publish

Expand All @@ -97,15 +96,11 @@ tag: clean
git tag -a -m 'version $$(hatch version)' v$$(hatch version)
git push --follow-tags

update-deps:
echo Use the _Update Python Dependencies_ Github action for real releases
pip-compile --upgrade --resolver=backtracking --output-file=requirements/prod.txt pyproject.toml
pip-compile --upgrade --resolver=backtracking --output-file=requirements/dev.txt --all-extras pyproject.toml
update-deps: ## update all dependencies via uv
uv lock --upgrade

dev-install:
python -m pip install --upgrade pip pip-tools setuptools
pip-sync requirements/*.txt
python -m pip install -e .
dev-install: ## install development dependencies via uv
uv sync --group dev

schema:
python -c 'from cumulusci.utils.yaml import cumulusci_yml; open("cumulusci/schema/cumulusci.jsonschema.json", "w").write(cumulusci_yml.CumulusCIRoot.schema_json(indent=4))'
Expand Down
2 changes: 1 addition & 1 deletion SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ Please report any security issue to [security@salesforce.com](mailto:security@sa
as soon as it is discovered. This library limits its runtime dependencies in
order to reduce the total cost of ownership as much as can be, but all consumers
should remain vigilant and have their security stakeholders review all third-party
products (3PP) like this one and their dependencies.
products (3PP) like this one and their dependencies.
4 changes: 2 additions & 2 deletions cumulusci/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,5 @@
if sys.version_info < (3, 8): # pragma: no cover
raise Exception("CumulusCI requires Python 3.8+.")

api.OrderedDict = dict
bulk.OrderedDict = dict
api.OrderedDict = dict # pyright: ignore[reportPrivateImportUsage]
bulk.OrderedDict = dict # pyright: ignore[reportPrivateImportUsage]
6 changes: 3 additions & 3 deletions cumulusci/cli/flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@ def flow_doc(runtime, project=False):
flows_by_group = group_items(flows)
flow_groups = sorted(
flows_by_group.keys(),
key=lambda group: flow_info_groups.index(group)
if group in flow_info_groups
else 100,
key=lambda group: (
flow_info_groups.index(group) if group in flow_info_groups else 100
),
)

for group in flow_groups:
Expand Down
3 changes: 2 additions & 1 deletion cumulusci/cli/logger.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
""" CLI logger """
"""CLI logger"""

import logging
import os
import sys
Expand Down
2 changes: 1 addition & 1 deletion cumulusci/cli/org.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ def set_org_name(required):

`required` is a boolean for whether org_name is required
"""

# could be generalized to work for any mutex pair (or list) but no obvious need
def callback(ctx, param, value):
"""Callback which enforces mutex and 'required' behaviour (if required)."""
Expand Down Expand Up @@ -474,7 +475,6 @@ def org_prune(runtime, include_active=False):
org_shapes_skipped = []
active_orgs_skipped = []
for org_name in runtime.keychain.list_orgs():

org_config = runtime.keychain.get_org(org_name)

if org_name in predefined_scratch_configs:
Expand Down
1 change: 0 additions & 1 deletion cumulusci/cli/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,6 @@ def init_from_context(context: Dict[str, object], echo: bool = False):

# Create sfdx-project.json
if not os.path.isfile("sfdx-project.json"):

sfdx_project = {
"packageDirectories": [{"path": "force-app", "default": True}],
"namespace": context["package_namespace"],
Expand Down
2 changes: 1 addition & 1 deletion cumulusci/cli/runtime.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ def __init__(self, *args, **kwargs):
super(CliRuntime, self).__init__(*args, **kwargs)
except ConfigError as e:
raise click.UsageError(f"Config Error: {str(e)}")
except (KeychainKeyNotFound) as e:
except KeychainKeyNotFound as e:
raise click.UsageError(f"Keychain Error: {str(e)}")

def get_keychain_class(self):
Expand Down
2 changes: 1 addition & 1 deletion cumulusci/cli/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ def service_list(runtime, plain, print_json):
console.print(table)


class ConnectServiceCommand(click.MultiCommand):
class ConnectServiceCommand(click.Group):
def _get_services_config(self, runtime):
return (
runtime.project_config.services
Expand Down
2 changes: 1 addition & 1 deletion cumulusci/cli/task.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ def task_info(runtime, task_name):
click.echo(rst2ansi(doc))


class RunTaskCommand(click.MultiCommand):
class RunTaskCommand(click.Group):
# options that are not task specific
global_options = {
"no-prompt": {
Expand Down
4 changes: 3 additions & 1 deletion cumulusci/cli/tests/test_error.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,9 @@ def test_error_gist(
)
webbrowser_open.assert_called_once_with(expected_gist_url)

@pytest.mark.skipif(sys.version_info > (3, 11), reason="requires python3.10 or higher")
@pytest.mark.skipif(
sys.version_info > (3, 11), reason="requires python3.10 or higher"
)
@mock.patch("cumulusci.cli.error.platform")
@mock.patch("cumulusci.cli.error.sys")
@mock.patch("cumulusci.cli.error.datetime")
Expand Down
4 changes: 2 additions & 2 deletions cumulusci/cli/tests/test_org.py
Original file line number Diff line number Diff line change
Expand Up @@ -887,9 +887,9 @@ def get_org(orgname):

run_click_command(org.org_list, runtime=runtime, json_flag=False, plain=False)

assert "Cannot load org config for `test1`" in str(
assert "Cannot load org config for `test1`" in str(echo.mock_calls), (
echo.mock_calls
), echo.mock_calls
)
assert "NOPE!" in str(echo.mock_calls), echo.mock_calls
assert "Cannot cleanup org cache dirs" in str(echo.mock_calls), echo.mock_calls

Expand Down
60 changes: 33 additions & 27 deletions cumulusci/cli/tests/test_plan.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,16 +148,18 @@ def test_plan_info__config(self, cli_table, runtime):
run_click_command(
plan.plan_info, "plan 1", runtime=runtime, messages_only=False
)
cli_table.assert_any_call(
title="Config",
data=[
["Key", "Value"],
["YAML Key", "plan 1"],
["Slug", "plan1_slug"],
["Tier", "primary"],
["Hidden?", False],
],
),
(
cli_table.assert_any_call(
title="Config",
data=[
["Key", "Value"],
["YAML Key", "plan 1"],
["Slug", "plan1_slug"],
["Tier", "primary"],
["Hidden?", False],
],
),
)

@mock.patch("cumulusci.cli.plan.CliTable")
def test_plan_info__messages(self, cli_table, runtime):
Expand All @@ -182,31 +184,35 @@ def test_plan_info__preflight_checks(self, cli_table, runtime):
run_click_command(
plan.plan_info, "plan 1", runtime=runtime, messages_only=False
)
cli_table.assert_any_call(
title="Plan Preflights",
data=[
["Action", "Message", "When"],
[
"error",
"Test Package must be installed in your org.",
"'test package' not in tasks.get_installed_packages()",
(
cli_table.assert_any_call(
title="Plan Preflights",
data=[
["Action", "Message", "When"],
[
"error",
"Test Package must be installed in your org.",
"'test package' not in tasks.get_installed_packages()",
],
],
],
),
),
)

@mock.patch("cumulusci.cli.plan.CliTable")
def test_plan_info__step_preflight_checks(self, cli_table, runtime):
"""Verify we are creating a CliTable for the step preflight checks"""
run_click_command(
plan.plan_info, "plan 1", runtime=runtime, messages_only=False
)
cli_table.assert_any_call(
title="Step Preflights",
data=[
["Step", "Action", "Message", "When"],
[1, "error", "Danger Will Robinson!", "soon"],
],
),
(
cli_table.assert_any_call(
title="Step Preflights",
data=[
["Step", "Action", "Message", "When"],
[1, "error", "Danger Will Robinson!", "soon"],
],
),
)

@mock.patch("cumulusci.cli.plan.CliTable")
def test_plan_info__steps(self, cli_table, runtime):
Expand Down
4 changes: 1 addition & 3 deletions cumulusci/cli/tests/test_project.py
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,4 @@ def test_render_recursive(self):
- list
\x1b[1mdict:\x1b[0m
\x1b[1mkey:\x1b[0m value
\x1b[1mstr:\x1b[0m str""" == "\n".join(
out
)
\x1b[1mstr:\x1b[0m str""" == "\n".join(out)
1 change: 1 addition & 0 deletions cumulusci/cli/ui.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
Classes:
CliTable: Pretty prints tabular data to stdout, via Rich's Console API
"""

import os
from typing import Any, List, Union

Expand Down
6 changes: 3 additions & 3 deletions cumulusci/core/config/base_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ def __init__(self, config: Optional[dict] = None, keychain=None):
if not type_for_value:
warnings.warn(f"{k}: {v} not declared for {type(self)}")
if (v is not None) and (type_for_value is not None):
assert isinstance(
v, type_for_value
), f"{k}: {v} should be of type {type_for_value}, not {type(v)} for {type(self)}"
assert isinstance(v, type_for_value), (
f"{k}: {v} should be of type {type_for_value}, not {type(v)} for {type(self)}"
)
self.config = config.copy()

self._init_logger()
Expand Down
1 change: 0 additions & 1 deletion cumulusci/core/config/marketing_cloud_service_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@


class MarketingCloudServiceConfig(OAuth2ServiceConfig):

refresh_token: str
oauth2_client: str
soap_instance_url: str
Expand Down
Loading
Loading