From e402b3c8f490b62e8d62f70f47392a1541376fd6 Mon Sep 17 00:00:00 2001 From: Dan Redding <125183946+dangotbanned@users.noreply.github.com> Date: Sat, 10 Aug 2024 18:17:16 +0100 Subject: [PATCH] ci(ruff): Enforce the default `C901` complexity (#3531) --- altair/jupyter/jupyter_chart.py | 2 +- altair/utils/core.py | 4 ++-- altair/utils/save.py | 3 +-- altair/utils/schemapi.py | 14 ++++++++------ altair/vegalite/v5/api.py | 9 +++++---- pyproject.toml | 6 +++++- tools/schemapi/schemapi.py | 14 ++++++++------ tools/schemapi/utils.py | 4 ++-- 8 files changed, 32 insertions(+), 24 deletions(-) diff --git a/altair/jupyter/jupyter_chart.py b/altair/jupyter/jupyter_chart.py index 64decfe2a..675cce15f 100644 --- a/altair/jupyter/jupyter_chart.py +++ b/altair/jupyter/jupyter_chart.py @@ -218,7 +218,7 @@ def __init__( ) @traitlets.observe("chart") - def _on_change_chart(self, change): + def _on_change_chart(self, change): # noqa: C901 """Updates the JupyterChart's internal state when the wrapped Chart instance changes.""" new_chart = change.new selection_watches = [] diff --git a/altair/utils/core.py b/altair/utils/core.py index abbf6222f..8ab466a87 100644 --- a/altair/utils/core.py +++ b/altair/utils/core.py @@ -319,7 +319,7 @@ def numpy_is_subtype(dtype: Any, subtype: Any) -> bool: return False -def sanitize_pandas_dataframe(df: pd.DataFrame) -> pd.DataFrame: +def sanitize_pandas_dataframe(df: pd.DataFrame) -> pd.DataFrame: # noqa: C901 """ Sanitize a DataFrame to prepare it for serialization. @@ -502,7 +502,7 @@ def to_eager_narwhals_dataframe(data: IntoDataFrame) -> nw.DataFrame[Any]: return data_nw -def parse_shorthand( +def parse_shorthand( # noqa: C901 shorthand: dict[str, Any] | str, data: pd.DataFrame | DataFrameLike | None = None, parse_aggregates: bool = True, diff --git a/altair/utils/save.py b/altair/utils/save.py index 47c0d3dce..042d457dc 100644 --- a/altair/utils/save.py +++ b/altair/utils/save.py @@ -140,8 +140,7 @@ def save( version="5.0.0", ) - if json_kwds is None: - json_kwds = {} + json_kwds = json_kwds or {} encoding = kwargs.get("encoding", "utf-8") format = set_inspect_format_argument(format, fp, inline) # type: ignore[assignment] diff --git a/altair/utils/schemapi.py b/altair/utils/schemapi.py index 567fd8a8a..fdf0d6594 100644 --- a/altair/utils/schemapi.py +++ b/altair/utils/schemapi.py @@ -497,7 +497,7 @@ def _from_array_like(obj: Iterable[Any], /) -> list[Any]: return list(obj) -def _todict(obj: Any, context: dict[str, Any] | None, np_opt: Any, pd_opt: Any) -> Any: +def _todict(obj: Any, context: dict[str, Any] | None, np_opt: Any, pd_opt: Any) -> Any: # noqa: C901 """Convert an object to a dict representation.""" if np_opt is not None: np = np_opt @@ -761,10 +761,12 @@ def _get_default_error_message( # Add unformatted messages of any remaining errors which were not # considered so far. This is not expected to be used but more exists # as a fallback for cases which were not known during development. - for validator, errors in errors_by_validator.items(): - if validator not in {"enum", "type"}: - message += "\n".join([e.message for e in errors]) - + it = ( + "\n".join(e.message for e in errors) + for validator, errors in errors_by_validator.items() + if validator not in {"enum", "type"} + ) + message += "".join(it) return message @@ -868,7 +870,7 @@ def __init__(self, *args: Any, **kwds: Any) -> None: if DEBUG_MODE and self._class_is_valid_at_instantiation: self.to_dict(validate=True) - def copy( + def copy( # noqa: C901 self, deep: bool | Iterable[Any] = True, ignore: list[str] | None = None ) -> Self: """ diff --git a/altair/vegalite/v5/api.py b/altair/vegalite/v5/api.py index 0b3776541..3d81abd9f 100644 --- a/altair/vegalite/v5/api.py +++ b/altair/vegalite/v5/api.py @@ -1725,7 +1725,7 @@ class TopLevelMixin(mixins.ConfigMethodMixin): _class_is_valid_at_instantiation: bool = False data: Any - def to_dict( + def to_dict( # noqa: C901 self, validate: bool = True, *, @@ -3876,7 +3876,8 @@ def _check_if_valid_subspec( raise ValueError(err.format(attr, classname)) -def _check_if_can_be_layered(spec: LayerType | dict[str, Any]) -> None: +# C901 fixed in https://github.com/vega/altair/pull/3520 +def _check_if_can_be_layered(spec: LayerType | dict[str, Any]) -> None: # noqa: C901 """Check if the spec can be layered.""" def _get(spec: LayerType | dict[str, Any], attr: str) -> Any: @@ -4715,7 +4716,7 @@ def _remove_duplicate_params(layer: list[ChartType]) -> list[ChartType]: return subcharts -def _combine_subchart_params( +def _combine_subchart_params( # noqa: C901 params: Optional[Sequence[_Parameter]], subcharts: list[ChartType] ) -> tuple[Optional[Sequence[_Parameter]], list[ChartType]]: if utils.is_undefined(params): @@ -4852,7 +4853,7 @@ def _repeat_names( return params_named -def _remove_layer_props( +def _remove_layer_props( # noqa: C901 chart: LayerChart, subcharts: list[ChartType], layer_props: Iterable[str] ) -> tuple[dict[str, Any], list[ChartType]]: def remove_prop(subchart: ChartType, prop: str) -> ChartType: diff --git a/pyproject.toml b/pyproject.toml index d7defe6ec..0eba4cefe 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -313,6 +313,8 @@ select = [ "ANN", # unsorted-imports "I001", + # complex-structure + "C901", ] ignore = [ # Whitespace before ':' @@ -360,7 +362,7 @@ ignore = [ ] # https://docs.astral.sh/ruff/settings/#lintpydocstyle pydocstyle={ convention="numpy" } -mccabe={ max-complexity=18 } +mccabe={ max-complexity=10 } [tool.ruff.lint.isort] classes = ["expr", "datum"] @@ -386,6 +388,8 @@ See https://github.com/vega/altair/pull/3449 [tool.ruff.lint.per-file-ignores] # Only enforce type annotation rules on public api "!altair/vegalite/v5/api.py" = ["ANN"] +# Allow complex if/elif branching during tests +"tests/**/*.py"= ["C901"] [tool.ruff.format] diff --git a/tools/schemapi/schemapi.py b/tools/schemapi/schemapi.py index be6725a03..1c756c2a2 100644 --- a/tools/schemapi/schemapi.py +++ b/tools/schemapi/schemapi.py @@ -495,7 +495,7 @@ def _from_array_like(obj: Iterable[Any], /) -> list[Any]: return list(obj) -def _todict(obj: Any, context: dict[str, Any] | None, np_opt: Any, pd_opt: Any) -> Any: +def _todict(obj: Any, context: dict[str, Any] | None, np_opt: Any, pd_opt: Any) -> Any: # noqa: C901 """Convert an object to a dict representation.""" if np_opt is not None: np = np_opt @@ -759,10 +759,12 @@ def _get_default_error_message( # Add unformatted messages of any remaining errors which were not # considered so far. This is not expected to be used but more exists # as a fallback for cases which were not known during development. - for validator, errors in errors_by_validator.items(): - if validator not in {"enum", "type"}: - message += "\n".join([e.message for e in errors]) - + it = ( + "\n".join(e.message for e in errors) + for validator, errors in errors_by_validator.items() + if validator not in {"enum", "type"} + ) + message += "".join(it) return message @@ -866,7 +868,7 @@ def __init__(self, *args: Any, **kwds: Any) -> None: if DEBUG_MODE and self._class_is_valid_at_instantiation: self.to_dict(validate=True) - def copy( + def copy( # noqa: C901 self, deep: bool | Iterable[Any] = True, ignore: list[str] | None = None ) -> Self: """ diff --git a/tools/schemapi/utils.py b/tools/schemapi/utils.py index 17326a8a1..21617538d 100644 --- a/tools/schemapi/utils.py +++ b/tools/schemapi/utils.py @@ -386,7 +386,7 @@ def get_python_type_representation( return_as_str: Literal[False] = ..., additional_type_hints: list[str] | None = ..., ) -> list[str]: ... - def get_python_type_representation( + def get_python_type_representation( # noqa: C901 self, for_type_hints: bool = False, return_as_str: bool = True, @@ -682,7 +682,7 @@ def __call__(self, s: str) -> str: rst_parse: RSTParse = RSTParse(RSTRenderer()) -def indent_docstring( +def indent_docstring( # noqa: C901 lines: list[str], indent_level: int, width: int = 100, lstrip=True ) -> str: """Indent a docstring for use in generated code."""