コード例 #1
0
    def test_maintainers_section(self):
        expected_message = (
            "The recipe could do with some maintainers listed "
            "in the `extra/recipe-maintainers` section."
        )

        lints, hints = linter.lintify({"extra": {"recipe-maintainers": []}})
        self.assertIn(expected_message, lints)

        # No extra section at all.
        lints, hints = linter.lintify({})
        self.assertIn(expected_message, lints)

        lints, hints = linter.lintify({"extra": {"recipe-maintainers": ["a"]}})
        self.assertNotIn(expected_message, lints)

        expected_message = (
            'The "extra" section was expected to be a ' "dictionary, but got a list."
        )
        lints, hints = linter.lintify({"extra": ["recipe-maintainers"]})
        self.assertIn(expected_message, lints)

        lints, hints = linter.lintify({"extra": {"recipe-maintainers": "Luke"}})
        expected_message = "Recipe maintainers should be a json list."
        self.assertIn(expected_message, lints)
コード例 #2
0
    def test_bad_subheader(self):
        expected_message = (
            "The {} section contained an unexpected "
            "subsection name. {} is not a valid subsection"
            " name."
        )
        meta = {
            "build": {"skip": "True", "script": "python setup.py install", "number": 0}
        }
        lints, hints = linter.lintify(meta)
        self.assertNotIn(expected_message.format("build", "ski"), lints)

        meta = {
            "build": {"ski": "True", "script": "python setup.py install", "number": 0}
        }
        lints, hints = linter.lintify(meta)
        self.assertIn(expected_message.format("build", "ski"), lints)

        meta = {"source": {"urll": "http://test"}}
        lints, hints = linter.lintify(meta)
        self.assertIn(expected_message.format("source", "urll"), lints)

        meta = {"source": [{"urll": "http://test"}, {"url": "https://test"}]}
        lints, hints = linter.lintify(meta)
        self.assertIn(expected_message.format("source", "urll"), lints)
コード例 #3
0
    def test_version(self):
        meta = {"package": {"name": "python", "version": "3.6.4"}}
        expected_message = "Package version 3.6.4 doesn't match conda spec"
        lints, hints = linter.lintify(meta)
        self.assertNotIn(expected_message, lints)

        meta = {"package": {"name": "python", "version": "2.0.0~alpha0"}}
        expected_message = "Package version 2.0.0~alpha0 doesn't match conda spec"
        lints, hints = linter.lintify(meta)
        self.assertIn(expected_message, lints)
コード例 #4
0
    def test_missing_build_number(self):
        expected_message = "The recipe must have a `build/number` section."

        meta = {
            "build": {"skip": "True", "script": "python setup.py install", "number": 0}
        }
        lints, hints = linter.lintify(meta)
        self.assertNotIn(expected_message, lints)

        meta = {"build": {"skip": "True", "script": "python setup.py install"}}
        lints, hints = linter.lintify(meta)
        self.assertIn(expected_message, lints)
コード例 #5
0
 def test_examples(self):
     msg = "Please move the recipe out of the example dir and into its " "own dir."
     lints, hints = linter.lintify(
         {"extra": {"recipe-maintainers": ["support"]}},
         recipe_dir="recipes/example/",
         conda_forge=True,
     )
     self.assertIn(msg, lints)
     lints = linter.lintify(
         {"extra": {"recipe-maintainers": ["support"]}},
         recipe_dir="python",
         conda_forge=True,
     )
     self.assertNotIn(msg, lints)
コード例 #6
0
    def test_test_section_with_recipe(self):
        # If we have a run_test.py file, we shouldn't need to provide
        # other tests.

        expected_message = "The recipe must have some tests."

        with tmp_directory() as recipe_dir:
            lints, hints = linter.lintify({}, recipe_dir)
            self.assertIn(expected_message, lints)

            with io.open(os.path.join(recipe_dir, "run_test.py"), "w") as fh:
                fh.write("# foo")
            lints, hints = linter.lintify({}, recipe_dir)
            self.assertNotIn(expected_message, lints)
コード例 #7
0
 def assert_selector(selector, is_good=True):
     with io.open(os.path.join(recipe_dir, "meta.yaml"), "w") as fh:
         fh.write(
             """
                 package:
                    name: foo_py2  # [py2k]
                    {}
                  """.format(
                 selector
             )
         )
     lints, hints = linter.lintify({}, recipe_dir)
     if is_good:
         message = (
             "Found lints when there shouldn't have been a "
             "lint for '{}'.".format(selector)
         )
     else:
         message = "Expecting lints for '{}', but didn't get any." "".format(
             selector
         )
     self.assertEqual(
         not is_good,
         any(lint.startswith(expected_message) for lint in lints),
         message,
     )
コード例 #8
0
 def assert_jinja(jinja_var, is_good=True):
     with io.open(os.path.join(recipe_dir, "meta.yaml"), "w") as fh:
         fh.write(
             """
                  {{% set name = "nwb-extensions-smithy" %}}
                  {}
                  """.format(
                 jinja_var
             )
         )
     lints, hints = linter.lintify({}, recipe_dir)
     if is_good:
         message = (
             "Found lints when there shouldn't have been a "
             "lint for '{}'.".format(jinja_var)
         )
     else:
         message = "Expecting lints for '{}', but didn't get any." "".format(
             jinja_var
         )
     self.assertEqual(
         not is_good,
         any(lint.startswith(expected_message) for lint in lints),
         message,
     )
コード例 #9
0
 def test_single_space_pins(self):
     meta = {
         "requirements": {
             "build": [
                 "{{ compilers('c') }}",
                 "python >=3",
                 "pip   19",
             ],
             "host": [
                 "python >= 2",
                 "libcblas 3.8.* *netlib",
             ],
             "run": [
                 "xonsh>1.0",
                 "conda= 4.*",
                 "conda-smithy<=54.*",
             ],
         }
     }
     lints, hints = linter.lintify(meta)
     filtered_lints = [lint for lint in lints if lint.startswith("``requirements: ")]
     expected_messages = [
         "``requirements: host: python >= 2`` should not contain a space between "
         "relational operator and the version, i.e. ``python >=2``",
         "``requirements: run: xonsh>1.0`` must contain a space between the "
         "name and the pin, i.e. ``xonsh >1.0``",
         "``requirements: run: conda= 4.*`` must contain a space between the "
         "name and the pin, i.e. ``conda =4.*``",
         "``requirements: run: conda-smithy<=54.*`` must contain a space "
         "between the name and the pin, i.e. ``conda-smithy <=54.*``",
     ]
     self.assertEqual(expected_messages, filtered_lints)
コード例 #10
0
    def test_no_sha_with_dl(self):
        expected_message = (
            "When defining a source/url please add a sha256, "
            "sha1 or md5 checksum (sha256 preferably)."
        )
        lints, hints = linter.lintify({"source": {"url": None}})
        self.assertIn(expected_message, lints)

        lints, hints = linter.lintify({"source": {"url": None, "sha1": None}})
        self.assertNotIn(expected_message, lints)

        lints, hints = linter.lintify({"source": {"url": None, "sha256": None}})
        self.assertNotIn(expected_message, lints, hints)

        meta = {"source": {"url": None, "md5": None}}
        self.assertNotIn(expected_message, linter.lintify(meta))
コード例 #11
0
    def test_missing_about_license_and_summary(self):
        meta = {"about": {"home": "a URL"}}
        lints, hints = linter.lintify(meta)
        expected_message = "The license item is expected in the about section."
        self.assertIn(expected_message, lints)

        expected_message = "The summary item is expected in the about section."
        self.assertIn(expected_message, lints)
コード例 #12
0
 def test_string_source(self):
     url = "http://mistake.com/v1.0.tar.gz"
     lints, hints = linter.lintify({"source": url})
     msg = (
         'The "source" section was expected to be a dictionary or a '
         "list, but got a {}.{}."
     ).format(type(url).__module__, type(url).__name__)
     self.assertIn(msg, lints)
コード例 #13
0
 def test_recipe_name(self):
     meta = {"package": {"name": "mp++"}}
     lints, hints = linter.lintify(meta)
     expected_message = (
         "Recipe name has invalid characters. only lowercase alpha, "
         "numeric, underscores, hyphens and dots allowed"
     )
     self.assertIn(expected_message, lints)
コード例 #14
0
 def test_bad_order(self):
     meta = OrderedDict([["package", {}], ["build", {}], ["source", {}]])
     lints, hints = linter.lintify(meta)
     expected_msg = (
         "The top level meta keys are in an unexpected "
         "order. Expecting ['package', 'source', 'build']."
     )
     self.assertIn(expected_msg, lints)
コード例 #15
0
    def test_missing_about_home_empty(self):
        meta = {"about": {"home": "", "summary": "", "license": ""}}
        lints, hints = linter.lintify(meta)
        expected_message = "The home item is expected in the about section."
        self.assertIn(expected_message, lints)

        expected_message = "The license item is expected in the about section."
        self.assertIn(expected_message, lints)

        expected_message = "The summary item is expected in the about section."
        self.assertIn(expected_message, lints)
コード例 #16
0
 def test_bad_about_license(self):
     meta = {
         "about": {
             "home": "a URL",
             "summary": "A test summary",
             "license": "unknown",
         }
     }
     lints, hints = linter.lintify(meta)
     expected_message = "The recipe license cannot be unknown."
     self.assertIn(expected_message, lints)
コード例 #17
0
 def test_bad_about_license_family(self):
     meta = {
         "about": {
             "home": "a URL",
             "summary": "A test summary",
             "license": "BSD 3-clause",
             "license_family": "BSD3",
         }
     }
     lints, hints = linter.lintify(meta)
     expected = "about/license_family 'BSD3' not allowed"
     self.assertTrue(any(lint.startswith(expected) for lint in lints))
コード例 #18
0
 def test_redundant_license(self):
     meta = {
         "about": {
             "home": "a URL",
             "summary": "A test summary",
             "license": "MIT License",
         }
     }
     lints, hints = linter.lintify(meta)
     expected_message = (
         "The recipe `license` should not include " 'the word "License".'
     )
     self.assertIn(expected_message, lints)
コード例 #19
0
 def test_license_file_required(self):
     meta = {
         "about": {
             "home": "a URL",
             "summary": "A test summary",
             "license": "MIT",
         }
     }
     lints, hints = linter.lintify(meta)
     expected_message = (
         "license_file entry is missing, but is required."
     )
     self.assertIn(expected_message, lints)
コード例 #20
0
    def test_bad_requirements_order(self):
        expected_message = (
            "The `requirements/` sections should be defined in "
            "the following order: build, host, run; "
            "instead saw: run, build."
        )

        meta = {"requirements": OrderedDict([["run", "a"], ["build", "a"]])}
        lints, hints = linter.lintify(meta)
        self.assertIn(expected_message, lints)

        meta = {
            "requirements": OrderedDict(
                [["run", "a"], ["invalid", "a"], ["build", "a"]]
            )
        }
        lints, hints = linter.lintify(meta)
        self.assertIn(expected_message, lints)

        meta = {"requirements": OrderedDict([["build", "a"], ["run", "a"]])}
        lints, hints = linter.lintify(meta)
        self.assertNotIn(expected_message, lints)
コード例 #21
0
    def test_end_empty_line(self):
        bad_contents = [
            # No empty lines at the end of the file
            "extra:\n  recipe-maintainers:\n    - goanpeca",
            "extra:\r  recipe-maintainers:\r    - goanpeca",
            "extra:\r\n  recipe-maintainers:\r\n    - goanpeca",
            # Two empty lines at the end of the file
            "extra:\n  recipe-maintainers:\n    - goanpeca\n\n",
            "extra:\r  recipe-maintainers:\r    - goanpeca\r\r",
            "extra:\r\n  recipe-maintainers:\r\n    - goanpeca\r\n\r\n",
            # Three empty lines at the end of the file
            "extra:\n  recipe-maintainers:\n    - goanpeca\n\n\n",
            "extra:\r  recipe-maintainers:\r    - goanpeca\r\r\r",
            "extra:\r\n  recipe-maintainers:\r\n    - goanpeca\r\n\r\n\r\n",
        ]
        # Exactly one empty line at the end of the file
        valid_content = "extra:\n  recipe-maintainers:\n    - goanpeca\n"

        for content, lines in zip(
            bad_contents + [valid_content], [0, 0, 0, 2, 2, 2, 3, 3, 3, 1]
        ):
            with tmp_directory() as recipe_dir:
                with io.open(os.path.join(recipe_dir, "meta.yaml"), "w") as f:
                    f.write(content)
                lints, hints = linter.lintify({}, recipe_dir=recipe_dir)
                if lines > 1:
                    expected_message = (
                        "There are {} too many lines.  "
                        "There should be one empty line "
                        "at the end of the "
                        "file.".format(lines - 1)
                    )
                else:
                    expected_message = (
                        "There are too few lines.  "
                        "There should be one empty line at"
                        " the end of the file."
                    )
                if content == valid_content:
                    self.assertNotIn(expected_message, lints)
                else:
                    self.assertIn(expected_message, lints)
コード例 #22
0
    def test_test_section(self):
        expected_message = "The recipe must have some tests."

        lints, hints = linter.lintify({})
        self.assertIn(expected_message, lints)

        lints, hints = linter.lintify({"test": {"files": "foo"}})
        self.assertIn(expected_message, lints)

        lints, hints = linter.lintify({"test": {"imports": "sys"}})
        self.assertNotIn(expected_message, lints)

        lints, hints = linter.lintify({"outputs": [{"name": "foo"}]})
        self.assertIn(expected_message, lints)

        lints, hints = linter.lintify(
            {"outputs": [{"name": "foo", "test": {"files": "foo"}}]}
        )
        self.assertIn(expected_message, lints)

        lints, hints = linter.lintify(
            {"outputs": [{"name": "foo", "test": {"imports": "sys"}}]}
        )
        self.assertNotIn(expected_message, lints)

        lints, hints = linter.lintify(
            {
                "outputs": [
                    {"name": "foo", "test": {"imports": "sys"}},
                    {"name": "foobar", "test": {"files": "hi"}},
                ]
            }
        )
        self.assertNotIn(expected_message, lints)
        self.assertIn(
            "It looks like the 'foobar' output doesn't have any tests.", hints
        )
コード例 #23
0
    def test_maintainer_exists(self):
        lints, hints = linter.lintify(
            {"extra": {"recipe-maintainers": ["support"]}}, conda_forge=True
        )
        expected_message = 'Recipe maintainer "support" does not exist'
        self.assertIn(expected_message, lints)

        lints = linter.lintify(
            {"extra": {"recipe-maintainers": ["isuruf"]}}, conda_forge=True
        )
        expected_message = 'Recipe maintainer "isuruf" does not exist'
        self.assertNotIn(expected_message, lints)

        expected_message = "Feedstock with the same name exists in conda-forge"
        # Check that feedstock exists if staged_recipes
        lints = linter.lintify(
            {"package": {"name": "python"}}, recipe_dir="python", conda_forge=True
        )
        self.assertIn(expected_message, lints)
        lints = linter.lintify(
            {"package": {"name": "python"}}, recipe_dir="python", conda_forge=False
        )
        self.assertNotIn(expected_message, lints)
        # No lint if in a feedstock
        lints = linter.lintify(
            {"package": {"name": "python"}}, recipe_dir="recipe", conda_forge=True
        )
        self.assertNotIn(expected_message, lints)
        lints = linter.lintify(
            {"package": {"name": "python"}}, recipe_dir="recipe", conda_forge=False
        )
        self.assertNotIn(expected_message, lints)

        # Make sure there's no feedstock named python1 before proceeding
        gh = github.Github(os.environ["GH_TOKEN"])
        cf = gh.get_user("conda-forge")
        try:
            cf.get_repo("python1-feedstock")
            feedstock_exists = True
        except github.UnknownObjectException as e:
            feedstock_exists = False

        if feedstock_exists:
            warnings.warn(
                "There's a feedstock named python1, but tests assume that there isn't"
            )
        else:
            lints = linter.lintify(
                {"package": {"name": "python1"}}, recipe_dir="python", conda_forge=True
            )
            self.assertNotIn(expected_message, lints)

        # Test bioconda recipe checking
        expected_message = (
            "Recipe with the same name exists in bioconda: "
            "please discuss with @conda-forge/bioconda-recipes."
        )
        bio = gh.get_user("bioconda").get_repo("bioconda-recipes")
        r = "samtools"
        try:
            bio.get_dir_contents("recipe/{}".format(r))
        except github.UnknownObjectException as e:
            warnings.warn(
                "There's no bioconda recipe named {}, but tests assume that there is".format(
                    r
                )
            )
        else:
            # Check that feedstock exists if staged_recipes
            lints = linter.lintify(
                {"package": {"name": r}}, recipe_dir=r, conda_forge=True
            )
            self.assertIn(expected_message, lints)
            lints = linter.lintify(
                {"package": {"name": r}}, recipe_dir=r, conda_forge=False
            )
            self.assertNotIn(expected_message, lints)
            # No lint if in a feedstock
            lints = linter.lintify(
                {"package": {"name": r}}, recipe_dir="recipe", conda_forge=True
            )
            self.assertNotIn(expected_message, lints)
            lints = linter.lintify(
                {"package": {"name": r}}, recipe_dir="recipe", conda_forge=False
            )
            self.assertNotIn(expected_message, lints)
            # No lint if the name isn't specified
            lints = linter.lintify({}, recipe_dir=r, conda_forge=True)
            self.assertNotIn(expected_message, lints)

        r = "this-will-never-exist"
        try:
            bio.get_dir_contents("recipes/{}".format(r))
        except github.UnknownObjectException as e:
            lints = linter.lintify(
                {"package": {"name": r}}, recipe_dir=r, conda_forge=True
            )
            self.assertNotIn(expected_message, lints)
        else:
            warnings.warn(
                "There's a bioconda recipe named {}, but tests assume that there isn't".format(
                    r
                )
            )
コード例 #24
0
 def test_bad_top_level(self):
     meta = OrderedDict([["package", {}], ["build", {}], ["sources", {}]])
     lints, hints = linter.lintify(meta)
     expected_msg = "The top level meta key sources is unexpected"
     self.assertIn(expected_msg, lints)
コード例 #25
0
 def test_outputs(self):
     meta = OrderedDict([["outputs", [{"name": "asd"}]]])
     lints, hints = linter.lintify(meta)