def test_get_test_requirements(): config = Configuration(name="ewokscore", version="0.1.0rc5") recipe = GrayskullFactory.create_recipe("pypi", config) assert "pytest" not in recipe["test"]["requires"] assert "pytest --pyargs ewokscore" not in recipe["test"]["commands"] config = Configuration(name="ewokscore", version="0.1.0rc5", extras_require_test="wrongoption") recipe = GrayskullFactory.create_recipe("pypi", config) assert "pytest" not in recipe["test"]["requires"] assert "pytest --pyargs ewokscore" not in recipe["test"]["commands"] # pytest dependency has no version constraints config = Configuration(name="ewokscore", version="0.1.0rc5", extras_require_test="test") recipe = GrayskullFactory.create_recipe("pypi", config) assert "pytest" in recipe["test"]["requires"] assert "pytest --pyargs ewokscore" in recipe["test"]["commands"] # pytest dependency has version constraints config = Configuration(name="ewokscore", version="0.1.0rc8 ", extras_require_test="test") recipe = GrayskullFactory.create_recipe("pypi", config) assert "pytest" in recipe["test"]["requires"] assert "pytest --pyargs ewokscore" in recipe["test"]["commands"]
def create(self, output_dir: Optional[Path]) -> Sequence[str]: """ Creates the recipe file. Arguments: output_dir: Probably called "recipes" """ context = self.context wt = output_dir / context.project yaml_path = wt / "meta.yaml" # ex: yaml_path = "tyrannosaurus/meta.yaml" if yaml_path.exists(): context.delete_exact_path(yaml_path, False) wt.mkdir(parents=True, exist_ok=True) skull = GrayskullFactory.create_recipe("pypi", context.poetry("name"), "") skull.generate_recipe( str(output_dir), mantainers=context.source("maintainers").split(",")) logger.debug(f"Generated a new recipe at {output_dir}/meta.yaml") helper = Sync(context) lines = helper.fix_recipe_internal(yaml_path) logger.debug(f"Fixed recipe at {yaml_path}/meta.yaml") return lines
def grayskull_audit_feedstock(fctx: FeedstockContext, ctx: MigratorSessionContext): """Uses grayskull to audit the requirements for a python package""" # TODO: come back to this, since CF <-> PyPI is not one-to-one and onto pkg_name = fctx.package_name pkg_version = fctx.attrs["version"] recipe = GrayskullFactory.create_recipe( "pypi", pkg_name, pkg_version, download=False, ) with tempfile.TemporaryDirectory() as td: recipe.generate_recipe( td, mantainers=list( { m: None for m in fctx.attrs["meta_yaml"]["extra"]["recipe-maintainers"] }, ), ) with open(os.path.join(td, pkg_name, "meta.yaml")) as f: out = f.read() return out
def create_python_recipe(pkg_name, sections_populate=None, **kwargs): config = Configuration(name=pkg_name, **kwargs) return ( GrayskullFactory.create_recipe("pypi", config, sections_populate=sections_populate), config, )
def test_cythongsl_recipe_build(): recipe = GrayskullFactory.create_recipe( "pypi", Configuration(name="cythongsl", version="0.2.2")) assert recipe["requirements"]["build"] == ["<{ compiler('c') }}"] assert recipe["requirements"]["host"] == ["cython >=0.16", "pip", "python"] assert recipe["build"]["noarch"] is None assert recipe["build"]["number"] == 0
def test_panel_entry_points(tmpdir): config = Configuration(name="panel", version="0.9.1") recipe = GrayskullFactory.create_recipe("pypi", config) generate_recipe(recipe, config, folder_path=str(tmpdir)) recipe_path = str(tmpdir / "panel" / "meta.yaml") with open(recipe_path, "r") as f: content = f.read() assert "- panel = panel.cli:main" in content
def test_zipp_recipe_tags_on_deps(): config = Configuration(name="zipp", version="3.0.0") recipe = GrayskullFactory.create_recipe("pypi", config) assert recipe["build"]["noarch"] assert recipe["requirements"]["host"] == [ "pip", "python >=3.6", "setuptools-scm >=3.4.1", ]
def test_requests_recipe_extra_deps(capsys, name): CLIConfig().stdout = True name = parse_pkg_name_version(name)[1] config = Configuration(name=name, version="2.22.0") recipe = GrayskullFactory.create_recipe("pypi", config) captured_stdout = capsys.readouterr() assert "win-inet-pton" not in recipe["requirements"]["run"] assert recipe["build"]["noarch"] assert not recipe["build"]["skip"] assert f"{Fore.GREEN}{Style.BRIGHT}python" in captured_stdout.out
def test_pymc_recipe_fortran(): recipe = GrayskullFactory.create_recipe( "pypi", Configuration(name="pymc", version="2.3.6")) assert sorted(recipe["requirements"]["build"]) == sorted( ["<{ compiler('c') }}", "<{ compiler('fortran') }}"]) assert sorted(recipe["requirements"]["host"]) == sorted( ["numpy", "python", "pip"]) assert sorted(recipe["requirements"]["run"]) == sorted( ["<{ pin_compatible('numpy') }}", "python"]) assert not recipe["build"]["noarch"]
def test_run_requirements_sdist(): config = Configuration(name="botocore", version="1.14.17") recipe = GrayskullFactory.create_recipe("pypi", config) assert sorted(recipe["requirements"]["run"]) == sorted([ "docutils >=0.10,<0.16", "jmespath >=0.7.1,<1.0.0", "python", "python-dateutil >=2.1,<3.0.0", "urllib3 >=1.20,<1.26", ])
def test_ciso_recipe(): recipe = GrayskullFactory.create_recipe( "pypi", Configuration(name="ciso", version="0.1.0")) assert sorted(recipe["requirements"]["host"]) == sorted( ["cython", "numpy", "pip", "python"]) assert sorted(recipe["requirements"]["run"]) == sorted( ["cython", "python", "<{ pin_compatible('numpy') }}"]) assert recipe["test"]["commands"] == ["pip check"] assert recipe["test"]["requires"] == ["pip"] assert recipe["test"]["imports"] == ["ciso"]
def test_deps_comments(): config = Configuration(name="kubernetes_asyncio", version="11.2.0") recipe = GrayskullFactory.create_recipe("pypi", config) assert recipe["requirements"]["run"] == [ "aiohttp >=2.3.10,<4.0.0", "certifi >=14.05.14", "python", "python-dateutil >=2.5.3", "pyyaml >=3.12", "setuptools >=21.0.0", "six >=1.9.0", "urllib3 >=1.24.2", ]
def main(): parser = argparse.ArgumentParser( description="Grayskull - Conda recipe generator") parser.add_argument( "repo_type", nargs=1, help="Specify the repository (pypi, cran).", ) parser.add_argument( "packages", nargs="+", help="Specify the packages name.", ) parser.add_argument("--heman", "--shera", default=False, action="store_true", dest="grayskull_power") parser.add_argument( "--output", "-o", dest="output", default=".", help="Path to where the recipe will be created", ) parser.add_argument("--version", "-v", default="", dest="version", help="Package version ") args = parser.parse_args() logging.debug(f"All arguments received: args: {args}") print(Style.RESET_ALL) print(clear_screen()) if args.grayskull_power: print(f"{Fore.BLUE}By the power of Grayskull...\n" f"{Style.BRIGHT}I have the power!") for pkg_name in args.packages: logging.debug(f"Starting grayskull for pkg: {pkg_name}") print( f"{Fore.GREEN}\n\n" f"#### Initializing recipe for " f"{Fore.BLUE}{pkg_name} ({args.repo_type[0]}) {Fore.GREEN}####\n") recipe = GrayskullFactory.create_recipe(args.repo_type[0], pkg_name, args.version) recipe.generate_recipe(args.output) print(f"\n{Fore.GREEN}#### Recipe generated on " f"{os.path.realpath(args.output)} for {pkg_name} ####\n")
def test_mypy_deps_normalization_and_entry_points(): config = Configuration(name="mypy", version="0.770") recipe = GrayskullFactory.create_recipe("pypi", config) assert "mypy_extensions >=0.4.3,<0.5.0" in recipe["requirements"]["run"] assert "mypy-extensions >=0.4.3,<0.5.0" not in recipe["requirements"][ "run"] assert "typed-ast >=1.4.0,<1.5.0" in recipe["requirements"]["run"] assert "typed_ast <1.5.0,>=1.4.0" not in recipe["requirements"]["run"] assert "typing-extensions >=3.7.4" in recipe["requirements"]["run"] assert "typing_extensions >=3.7.4" not in recipe["requirements"]["run"] assert recipe["build"]["entry_points"] == [ "mypy=mypy.__main__:console_entry", "stubgen=mypy.stubgen:main", "stubtest=mypy.stubtest:main", "dmypy=mypy.dmypy.client:console_entry", ]
def test_part_reload_recipe(tmpdir): recipe = GrayskullFactory.create_recipe( "pypi", Configuration(name="pytest", version="5.3.2") ) host = deepcopy([str(i) for i in recipe["requirements"]["host"]]) run = deepcopy([str(i) for i in recipe["requirements"]["run"]]) recipe["requirements"] = {} recipe["foo"] = "bar" assert not recipe["requirements"].value assert host assert run assert recipe["foo"] == "bar" folder = tmpdir.mkdir("reload_recipe") recipe_path = folder / "recipe.yaml" recipe.save(str(recipe_path)) cli.main(["pypi", str(recipe_path), "--sections", "requirements"]) recipe = Recipe(load_file=str(recipe_path)) assert host == [str(v) for v in recipe["requirements"]["host"] if v] assert run == [str(v) for v in recipe["requirements"]["run"] if v] assert recipe["foo"] == "bar"
def main(args=None): if args is None: args = sys.argv[1:] parser = argparse.ArgumentParser( description="Grayskull - Conda recipe generator") pypi_parser = parser.add_subparsers( help="Options to generate PyPI recipes") pypi_cmds = pypi_parser.add_parser("pypi", help="Generate recipes based on PyPI") pypi_cmds.add_argument("pypi_packages", nargs="+", help="Specify the PyPI packages name.", default=[]) pypi_cmds.add_argument( "--download", "-d", dest="download", action="store_true", default=False, help="Download the sdist package and PyPI information in the same folder" " the recipe is located.", ) pypi_cmds.add_argument( "--maintainers", "-m", dest="maintainers", nargs="+", help="List of maintainers which will be added to the recipe.", ) parser.add_argument( "--version", "-v", default=False, action="store_true", dest="version", help="Print Grayskull version and exit", ) parser.add_argument( "--heman", "--shera", default=False, action="store_true", dest="grayskull_power", help=argparse.SUPPRESS, ) pypi_cmds.add_argument( "--output", "-o", dest="output", default=".", help="Path to where the recipe will be created", ) pypi_cmds.add_argument( "--stdout", dest="stdout", default=True, help="Disable or enable stdout, if it is False, Grayskull" " will disable the prints. Default is True", ) args = parser.parse_args(args) if args.version: print(grayskull.__version__) return logging.debug(f"All arguments received: args: {args}") if args.grayskull_power: print(f"{Fore.BLUE}By the power of Grayskull...\n" f"{Style.BRIGHT}I have the power!") return CLIConfig().stdout = args.stdout print_msg(Style.RESET_ALL) print_msg(clear_screen()) for pkg_name in args.pypi_packages: logging.debug(f"Starting grayskull for pkg: {pkg_name}") print_msg(f"{Fore.GREEN}\n\n" f"#### Initializing recipe for " f"{Fore.BLUE}{pkg_name} (pypi) {Fore.GREEN}####\n") pkg_name, pkg_version = parse_pkg_name_version(pkg_name) recipe = GrayskullFactory.create_recipe("pypi", pkg_name, pkg_version, download=args.download) recipe.generate_recipe(args.output, mantainers=args.maintainers) print_msg(f"\n{Fore.GREEN}#### Recipe generated on " f"{os.path.realpath(args.output)} for {pkg_name} ####\n")
def test_botocore_recipe_license_name(): config = Configuration(name="botocore", version="1.15.8") recipe = GrayskullFactory.create_recipe("pypi", config) assert recipe["about"]["license"] == "Apache-2.0"
def test_factory(repo_type, pkg_name, version, obj_type, monkeypatch): monkeypatch.setattr(PyPi, "__init__", lambda x, y, z: None) assert isinstance( GrayskullFactory.create_recipe(repo_type, pkg_name, version), (AbstractRecipeModel, obj_type), )
def test_ipytest_recipe_license(): config = Configuration(name="ipytest", version="0.8.0") recipe = GrayskullFactory.create_recipe("pypi", config) assert recipe["about"]["license"] == "MIT"
def main(args=None): if not args: args = sys.argv[1:] if sys.argv[1:] else ["--help"] parser = argparse.ArgumentParser( description="Grayskull - Conda recipe generator") pypi_parser = parser.add_subparsers( help="Options to generate PyPI recipes") pypi_cmds = pypi_parser.add_parser("pypi", help="Generate recipes based on PyPI") pypi_cmds.add_argument("pypi_packages", nargs="+", help="Specify the PyPI packages name.", default=[]) pypi_cmds.add_argument( "--download", "-d", dest="download", action="store_true", default=False, help="Download the sdist package and PyPI information in the same folder" " the recipe is located.", ) pypi_cmds.add_argument( "--maintainers", "-m", dest="maintainers", nargs="+", help="List of maintainers which will be added to the recipe.", ) parser.add_argument( "--version", "-v", default=False, action="store_true", dest="version", help="Print Grayskull version and exit", ) parser.add_argument( "--heman", "--shera", default=False, action="store_true", dest="grayskull_power", help=argparse.SUPPRESS, ) pypi_cmds.add_argument( "--output", "-o", dest="output", default=".", help="Path to where the recipe will be created", ) pypi_cmds.add_argument( "--stdout", dest="stdout", default=True, help="Disable or enable stdout, if it is False, Grayskull" " will disable the prints. Default is True", ) pypi_cmds.add_argument( "--list-missing-deps", default=False, action="store_true", dest="list_missing_deps", help= "After the execution Grayskull will print all the missing dependencies.", ) pypi_cmds.add_argument( "--strict-conda-forge", default=False, action="store_true", dest="is_strict_conda_forge", help="It will generate the recipes strict for the conda-forge channel.", ) args = parser.parse_args(args) if args.version: print(grayskull.__version__) return logging.debug(f"All arguments received: args: {args}") if args.grayskull_power: print(f"{Fore.BLUE}By the power of Grayskull...\n" f"{Style.BRIGHT}I have the power!") return CLIConfig().stdout = args.stdout CLIConfig().list_missing_deps = args.list_missing_deps print_msg(Style.RESET_ALL) print_msg(clear_screen()) for pkg_name in args.pypi_packages: logging.debug(f"Starting grayskull for pkg: {pkg_name}") pypi_label = "" if origin_is_github(pkg_name) else " (pypi)" print_msg(f"{Fore.GREEN}\n\n" f"#### Initializing recipe for " f"{Fore.BLUE}{pkg_name}{pypi_label} {Fore.GREEN}####\n") pkg_name, pkg_version = parse_pkg_name_version(pkg_name) try: recipe = GrayskullFactory.create_recipe( "pypi", pkg_name, pkg_version, download=args.download, is_strict_cf=args.is_strict_conda_forge, ) except requests.exceptions.HTTPError as err: print_msg( f"{Fore.RED}Package seems to be missing on pypi.\nException: {err}\n\n" ) continue recipe.generate_recipe(args.output, mantainers=args.maintainers) print_msg(f"\n{Fore.GREEN}#### Recipe generated on " f"{os.path.realpath(args.output)} for {pkg_name} ####\n")
def test_importlib_metadata_two_setuptools_scm(): config = Configuration(name="importlib-metadata", version="1.5.0") recipe = GrayskullFactory.create_recipe("pypi", config) assert "setuptools-scm" in recipe["requirements"]["host"] assert "setuptools_scm" not in recipe["requirements"]["host"] assert recipe["about"]["license"] == "Apache-2.0"
def test_keyring_host_appearing_twice(): config = Configuration(name="keyring", version="21.1.1") recipe = GrayskullFactory.create_recipe("pypi", config) assert "importlib-metadata" in recipe["requirements"]["run"] assert "importlib_metadata" not in recipe["requirements"]["run"]
def test_nbdime_license_type(): config = Configuration(name="nbdime", version="2.0.0") recipe = GrayskullFactory.create_recipe("pypi", config) assert recipe["about"]["license"] == "BSD-3-Clause" assert "setupbase" not in recipe["requirements"]["host"]
def test_django_rest_framework_xml_license(): config = Configuration(name="djangorestframework-xml", version="1.4.0") recipe = GrayskullFactory.create_recipe("pypi", config) assert recipe["about"]["license"] == "BSD-3-Clause" assert recipe["about"]["license_file"] == "LICENSE" assert recipe["test"]["imports"][0] == "rest_framework_xml"
def test_python_requires_setup_py(): config = Configuration(name="pygments", version="2.6.1") recipe = GrayskullFactory.create_recipe("pypi", config) assert recipe["build"]["noarch"] assert "python >=3.5" in recipe["requirements"]["host"] assert "python >=3.5" in recipe["requirements"]["run"]