def test_empty_recipe(tmpdir): r = Recipe('recipes/sina', 'recipes/') with pytest.raises(EmptyRecipe): r.load_from_string("") with open(op.join(tmpdir, 'meta.yaml'), "w"): pass with pytest.raises(EmptyRecipe): Recipe.from_file(str(tmpdir), str(tmpdir)) res = Recipe.from_file(str(tmpdir), str(tmpdir), return_exceptions=True) assert isinstance(res, EmptyRecipe)
def _run(contents, expect_pass=True): """ Build the recipe and run the lint function on the rendered recipe """ r = Recipes(contents, from_string=True) r.write_recipes() assert len(r.recipe_dirs) == 1 name = list(r.recipe_dirs.keys())[0] recipe = Recipe.from_file(r.basedir, r.recipe_dirs[name]) metas = [] for platform in ["linux", "osx"]: config = utils.load_conda_build_config(platform=platform, trim_skip=False) metas.extend(utils.load_all_meta(r.recipe_dirs[name], config=config, finalize=False)) if expect_pass: assert func(recipe, metas) is None, "lint did not pass" else: assert func(recipe, metas) is not None, "lint did not fail"
def _run(contents, expect_pass=True): """ Build the recipe and run the lint function on the rendered recipe """ r = Recipes(contents, from_string=True) r.write_recipes() assert len(r.recipe_dirs) == 1 name = list(r.recipe_dirs.keys())[0] recipe = Recipe.from_file(r.basedir, r.recipe_dirs[name]) metas = [] for platform in ["linux", "osx"]: config = utils.load_conda_build_config(platform=platform, trim_skip=False) metas.extend( utils.load_all_meta(r.recipe_dirs[name], config=config, finalize=False)) if expect_pass: assert func(recipe, metas) is None, "lint did not pass" else: assert func(recipe, metas) is not None, "lint did not fail"
def generate_readme(recipe_basedir, output_dir, folder, repodata, renderer): """Generates README.rst for the recipe in folder Args: folder: Toplevel folder name in recipes directory repodata: RepoData object renderer: Renderer object Returns: List of template_options for each concurrent version for which meta.yaml files exist in the recipe folder and its subfolders """ output_file = op.join(output_dir, folder, 'README.rst') # Select meta yaml meta_fname = op.join(recipe_basedir, folder, 'meta.yaml') if not op.exists(meta_fname): for item in os.listdir(op.join(recipe_basedir, folder)): dname = op.join(recipe_basedir, folder, item) if op.isdir(dname): fname = op.join(dname, 'meta.yaml') if op.exists(fname): meta_fname = fname break else: logger.error("No 'meta.yaml' found in %s", folder) return [] meta_relpath = meta_fname[len(recipe_basedir) + 1:] # Read the meta.yaml file(s) try: recipe = Recipe.from_file(recipe_basedir, meta_fname) except RecipeError as e: logger.error("Unable to process %s: %s", meta_fname, e) return [] # Format the README packages = [] for package in sorted(list(set(recipe.package_names))): versions_in_channel = set( repodata.get_package_data(['version', 'build_number'], channels='bioconda', name=package)) sorted_versions = sorted(versions_in_channel, key=lambda x: (VersionOrder(x[0]), x[1]), reverse=True) if sorted_versions: depends = [ depstring.split(' ', 1) if ' ' in depstring else (depstring, '') for depstring in repodata.get_package_data( 'depends', name=package, version=sorted_versions[0][0], build_number=sorted_versions[0][1], )[0] ] else: depends = [] packages.append({ 'name': package, 'versions': ['-'.join(str(w) for w in v) for v in sorted_versions], 'depends': depends, }) template_options = { 'name': recipe.name, 'about': recipe.get('about', None), 'extra': recipe.get('extra', None), 'recipe': recipe, 'packages': packages, } renderer.render_to_file(output_file, 'readme.rst_t', template_options) return [output_file]
def generate_readme(recipe_basedir, output_dir, folder, repodata, renderer): """Generates README.rst for the recipe in folder Args: folder: Toplevel folder name in recipes directory repodata: RepoData object renderer: Renderer object Returns: List of template_options for each concurrent version for which meta.yaml files exist in the recipe folder and its subfolders """ output_file = op.join(output_dir, folder, 'README.rst') # Select meta yaml meta_fname = op.join(recipe_basedir, folder, 'meta.yaml') if not op.exists(meta_fname): for item in os.listdir(op.join(recipe_basedir, folder)): dname = op.join(recipe_basedir, folder, item) if op.isdir(dname): fname = op.join(dname, 'meta.yaml') if op.exists(fname): meta_fname = fname break else: logger.error("No 'meta.yaml' found in %s", folder) return [] meta_relpath = meta_fname[len(recipe_basedir)+1:] # Read the meta.yaml file(s) try: recipe = Recipe.from_file(recipe_basedir, meta_fname) except RecipeError as e: logger.error("Unable to process %s: %s", meta_fname, e) return [] # Format the README packages = [] for package in sorted(list(set(recipe.package_names))): versions_in_channel = set(repodata.get_package_data(['version', 'build_number'], channels='bioconda', name=package)) sorted_versions = sorted(versions_in_channel, key=lambda x: (VersionOrder(x[0]), x[1]), reverse=True) if sorted_versions: depends = [ depstring.split(' ', 1) if ' ' in depstring else (depstring, '') for depstring in repodata.get_package_data('depends', name=package, version=sorted_versions[0][0], build_number=sorted_versions[0][1], )[0] ] else: depends = [] packages.append({ 'name': package, 'versions': ['-'.join(str(w) for w in v) for v in sorted_versions], 'depends' : depends, }) template_options = { 'name': recipe.name, 'about': recipe.get('about'), 'extra': recipe.get('extra'), 'recipe': recipe, 'packages': packages, } renderer.render_to_file(output_file, 'readme.rst_t', template_options) return [output_file]
def create_recipe(bioconda_recipe_path, recipe_path, strategy): # Load meta.yaml file and instantiate Recipe object temp_folder_name = hashlib.md5(recipe_path.encode("utf-8")).hexdigest() recipes_pkg_path = os.path.join(bioconda_recipe_path, "recipes", temp_folder_name) try: os.mkdir(recipes_pkg_path) copytree(recipe_path, recipes_pkg_path) bioconda_recipe = bioconda_utils_Recipe.from_file( bioconda_recipe_path, recipes_pkg_path) finally: rmtree(recipes_pkg_path) name = bioconda_recipe.get("package/name") version = bioconda_recipe.get("package/version") recipe = Recipe(name, version, recipe_path, strategy) # Parse values from file to Recipe object try: recipe.add_source_url(bioconda_recipe.get("source/url")) except KeyError: sys.exit( "No source url was found in the given meta.yaml file, please add a source url" ) recipe.add_build_number(bioconda_recipe.get("build/number", "0")) try: recipe.add_checksum_sha256(bioconda_recipe.get("source/sha256")) except KeyError: recipe.add_checksum_md5( bioconda_recipe.get( "source/md5", calculate_md5_checksum(bioconda_recipe.get("source/url")))) build_requirements = bioconda_recipe.get("requirements/build", []) for requirement in build_requirements: recipe.add_requirement(requirement, "build") host_requirements = bioconda_recipe.get("requirements/host", []) for requirement in host_requirements: recipe.add_requirement(requirement, "host", host_only=True) run_requirements = bioconda_recipe.get("requirements/run", []) for requirement in run_requirements: recipe.add_requirement(requirement, "run") try: recipe.add_test_commands(bioconda_recipe.get("test/commands")) except KeyError: pass try: recipe.add_test_files_with_list(bioconda_recipe.get("test/files")) except KeyError: pass try: recipe.add_patches_with_list(bioconda_recipe.get("source/patches"), recipe_path) except KeyError: pass # Conda will not accept the compiler dependency given by bioconda try: build_requirements = recipe.recipe_dict["requirements"]["build"] if "compiler_c" in build_requirements: recipe.recipe_dict["requirements"]["build"].remove("compiler_c") recipe.recipe_dict["requirements"]["build"].append( "{{compiler('c')}}") if "compiler_cxx" in build_requirements: recipe.recipe_dict["requirements"]["build"].remove("compiler_cxx") recipe.recipe_dict["requirements"]["build"].append( "{{compiler('cxx')}}") except KeyError: if strategy == "cmake": recipe.add_requirement("{{ compiler('c') }}", "build") recipe.add_requirement("cmake", "build") recipe.add_requirement("make", "build") elif strategy == "autoconf": recipe.add_requirement("make", "build") recipe.add_requirement("autoconf", "build") recipe.add_requirement("automake", "build") recipe.add_requirement("{{ compiler('c') }}", "build") if strategy.startswith("python"): try: host_environment = recipe.recipe_dict["requirements"]["host"] if not any( map(lambda req: req.startswith("python"), host_environment)): if strategy == "python2": recipe.add_requirement("python =2.7", "host") else: recipe.add_requirement("python >=3", "host") except KeyError: if strategy == "python2": recipe.add_requirement("python =2.7", "host") else: recipe.add_requirement("python >=3", "host") try: recipe.script = bioconda_recipe.get("build/script") except KeyError: pass try: recipe.add_command_imports(bioconda_recipe.get("test/imports")) except KeyError: pass try: recipe.add_entry_point(bioconda_recipe.get("build/entry_points")) except KeyError: pass try: recipe.add_noarch(bioconda_recipe.get("build/noarch")) except KeyError: pass try: recipe.add_test_requires(bioconda_recipe.get("test/requires")) except KeyError: pass recipe.increment_build_number() return recipe
def test_file_not_found(): with pytest.raises(MissingMetaYaml): Recipe.from_file('/', '/doesnotexist') res = Recipe.from_file('/', '/doesnotexist', return_exceptions=True) assert isinstance(res, MissingMetaYaml)
def test_stub(): r = Recipe('recipes/sina', 'recipes/') assert r.path == 'recipes/sina/meta.yaml' assert r.relpath == 'sina/meta.yaml' assert r.reldir == 'sina' assert str(r) == 'sina'
def recipe(recipe_dir, recipes_folder): yield Recipe.from_file(recipes_folder, recipe_dir)
def generate_readme(folder, repodata, renderer): """Generates README.rst for the recipe in folder Args: folder: Toplevel folder name in recipes directory repodata: RepoData object renderer: Renderer object Returns: List of template_options for each concurrent version for which meta.yaml files exist in the recipe folder and its subfolders """ # Subfolders correspond to different versions versions = [] for sf in os.listdir(op.join(RECIPE_DIR, folder)): if not op.isdir(op.join(RECIPE_DIR, folder, sf)): # Not a folder continue try: LooseVersion(sf) except ValueError: logger.error("'{}' does not look like a proper version!" "".format(sf)) continue versions.append(sf) # Read the meta.yaml file(s) try: recipe = op.join(RECIPE_DIR, folder, "meta.yaml") if op.exists(recipe): metadata = MetaData(recipe) if metadata.version() not in versions: versions.insert(0, metadata.version()) else: if versions: recipe = op.join(RECIPE_DIR, folder, versions[0], "meta.yaml") metadata = MetaData(recipe) else: # ignore non-recipe folders return [] except UnableToParse as e: logger.error("Failed to parse recipe {}".format(recipe)) raise e ## Get all versions and build numbers for data package # Select meta yaml meta_fname = op.join(RECIPE_DIR, folder, 'meta.yaml') if not op.exists(meta_fname): for item in os.listdir(op.join(RECIPE_DIR, folder)): dname = op.join(RECIPE_DIR, folder, item) if op.isdir(dname): fname = op.join(dname, 'meta.yaml') if op.exists(fname): meta_fname = fname break else: logger.error("No 'meta.yaml' found in %s", folder) return [] meta_relpath = meta_fname[len(RECIPE_DIR)+1:] # Read the meta.yaml file(s) try: recipe_object = Recipe.from_file(RECIPE_DIR, meta_fname) except RecipeError as e: logger.error("Unable to process %s: %s", meta_fname, e) return [] # Format the README for package in sorted(list(set(recipe_object.package_names))): versions_in_channel = set(repodata.get_package_data(['version', 'build_number'], channels='ggd-genomics', name=package)) sorted_versions = sorted(versions_in_channel, key=lambda x: (VersionOrder(x[0]), x[1]), reverse=False) if sorted_versions: depends = [ depstring.split(' ', 1) if ' ' in depstring else (depstring, '') for depstring in repodata.get_package_data('depends', name=package, version=sorted_versions[0][0], build_number=sorted_versions[0][1], )[0] ] else: depends = [] # Format the README name = metadata.name() versions_in_channel = repodata.get_versions(name) template_options = { 'name': name, 'about': (metadata.get_section('about') or {}), 'species': (metadata.get_section('about')["identifiers"]["species"] if "species" in metadata.get_section('about')["identifiers"] else {}), 'genome_build': (metadata.get_section('about')["identifiers"]["genome-build"] if "genome-build" in metadata.get_section('about')["identifiers"] else {}), 'ggd_channel': (metadata.get_section('about')["tags"]["ggd-channel"] if "ggd-channel" in metadata.get_section('about')["tags"] else "genomics"), 'extra': (metadata.get_section('extra') or {}), 'versions': ["-".join(str(w) for w in v) for v in sorted_versions], 'gh_recipes': 'https://github.com/gogetdata/ggd-recipes/tree/master/recipes/', 'recipe_path': op.dirname(op.relpath(metadata.meta_path, RECIPE_DIR)), 'Package': '<a href="recipes/{0}/README.html">{0}</a>'.format(name) } renderer.render_to_file( op.join(OUTPUT_DIR, name, 'README.rst'), 'readme.rst_t', template_options) recipes = [] latest_version = "-".join(str(w) for w in sorted_versions[-1]) for version, version_info in sorted(versions_in_channel.items()): t = template_options.copy() if 'noarch' in version_info: t.update({ 'Linux': '<i class="fa fa-linux"></i>' if 'linux' in version_info else '<i class="fa fa-dot-circle-o"></i>', 'OSX': '<i class="fa fa-apple"></i>' if 'osx' in version_info else '<i class="fa fa-dot-circle-o"></i>', 'NOARCH': '<i class="fa fa-desktop"></i>' if 'noarch' in version_info else '', 'Version': latest_version ## The latest version #'Version': version }) else: t.update({ 'Linux': '<i class="fa fa-linux"></i>' if 'linux' in version_info else '', 'OSX': '<i class="fa fa-apple"></i>' if 'osx' in version_info else '', 'NOARCH': '<i class="fa fa-desktop"></i>' if 'noarch' in version_info else '', 'Version': latest_version ## The latest version #'Version': version }) recipes.append(t) return recipes