diff --git a/grayskull/strategy/pypi.py b/grayskull/strategy/pypi.py index 20892a07b..94b47bc67 100644 --- a/grayskull/strategy/pypi.py +++ b/grayskull/strategy/pypi.py @@ -2,6 +2,7 @@ import logging import os import re +from collections.abc import Mapping from pathlib import Path from tempfile import mkdtemp from typing import Dict, Iterable, List, Optional @@ -480,12 +481,25 @@ def get_metadata(recipe, config) -> dict: } +def remove_all_inner_nones(metadata: Dict) -> Dict: + """Remove all inner None values from a dictionary.""" + if not isinstance(metadata, Mapping): + return metadata + for k, v in metadata.items(): + if not isinstance(v, list): + continue + metadata[k] = [i for i in v if i is not None] + return metadata + + def update_recipe(recipe: Recipe, config: Configuration, all_sections: List[str]): """Update one specific section.""" from souschef.section import Section metadata = get_metadata(recipe, config) + for section in all_sections: + metadata[section] = remove_all_inner_nones(metadata.get(section, {})) if metadata.get(section): if section == "package": package_metadata = dict(metadata[section]) diff --git a/tests/test_pypi.py b/tests/test_pypi.py index e05ad7e58..b1e9bae93 100644 --- a/tests/test_pypi.py +++ b/tests/test_pypi.py @@ -41,8 +41,10 @@ get_url_filename, merge_pypi_sdist_metadata, normalize_requirements_list, + remove_all_inner_nones, remove_selectors_pkgs_if_needed, sort_reqs, + update_recipe, ) from grayskull.utils import PyVer, format_dependencies, generate_recipe @@ -1326,3 +1328,31 @@ def test_sort_reqs(): assert sort_reqs(original_deps) in [sorted_deps_orig, sorted_deps_alpha] assert sort_reqs(original_deps_38) in [sorted_deps_orig_38, sorted_deps_alpha_38] + + +@patch("grayskull.strategy.pypi.get_metadata") +def test_metadata_pypi_none_value(mock_get_data): + mock_get_data.return_value = { + "package": {"name": "pypylon", "version": "1.2.3"}, + "build": {"test": [None]}, + } + recipe = Recipe(name="pypylon") + update_recipe( + recipe, + Configuration(name="pypylon", repo_github="https://github.com/basler/pypylon"), + ("package", "build"), + ) + assert recipe["build"]["test"] == [] + + +@pytest.mark.parametrize( + "param, result", + [ + ({"test": [None, None, None]}, {"test": []}), + ({"test": [None, "foo", None]}, {"test": ["foo"]}), + ({"test": [None, "foo", None, "bar", None]}, {"test": ["foo", "bar"]}), + ({"test": [None, "foo", None, "bar", None, None]}, {"test": ["foo", "bar"]}), + ], +) +def test_remove_all_inner_none(param, result): + assert remove_all_inner_nones(param) == result