Example #1
0
    def check_package_version(self):
        """Check the package version in meta.yaml for proper formatting."""
        package_version = self.meta.get("package", {}).get("version", "")

        if package_version == "":
            return Error(self.recipe_dir, "C2104",
                         "Missing package version in meta.yaml")

        if isinstance(package_version, str):
            if (not self.version_pat.match(package_version)
                    or package_version.startswith(
                        ("_", ".")) or package_version.endswith(("_", "."))):
                return Error(
                    self.recipe_dir,
                    "C2105",
                    u'Found invalid package version "{}" in meta.yaml'.format(
                        package_version),
                )

            seq = get_bad_seq(package_version)
            if seq:
                return Error(
                    self.recipe_dir,
                    "C2106",
                    u'Found invalid sequence "{}" in package version'.format(
                        seq),
                )
Example #2
0
    def check_source(self):
        """Check the source field in meta.yaml for proper formatting."""
        sources = ensure_list(self.meta.get("source", {}))
        for source in sources:
            url = source.get("url")
            if url is not None:
                if self.url_pat.match(url):

                    for hash_algorithm in ["md5", "sha1", "sha256"]:
                        hexdigest = source.get(hash_algorithm)
                        if hexdigest is not None and not self.hash_pat[
                                hash_algorithm].match(hexdigest):
                            return Error(
                                self.recipe_dir,
                                "C2119",
                                u'Found invalid hash "{}" in meta.yaml'.format(
                                    hexdigest),
                            )

                else:
                    return Error(
                        self.recipe_dir,
                        "C2120",
                        u'Found invalid URL "{}" in meta.yaml'.format(url),
                    )

            git_url = source.get("git_url")
            if git_url and (source.get("git_tag")
                            and source.get("git_branch")):
                return Error(
                    self.recipe_dir,
                    "C2121",
                    "Found both git_branch and git_tag in meta.yaml source field",
                )
Example #3
0
    def check_windows_arch(self):
        """Check that Windows package .exes and .dlls contain the correct headers."""
        if self.win_pkg:
            arch = self.info["arch"]
            if arch not in ("x86", "x86_64"):
                return Error(
                    self.path,
                    "C1144",
                    u'Found unrecognized Windows architecture "{}"'.format(
                        arch),
                )

            for member in self.archive_members:
                if member.endswith((".exe", ".dll")):
                    with open(os.path.join(self.tmpdir, member),
                              "rb") as file_object:
                        file_header = file_object.read(4096)
                        file_object_type = get_object_type(file_header)
                        if (arch == "x86" and file_object_type != "DLL I386"
                            ) or (arch == "x86_64"
                                  and file_object_type != "DLL AMD64"):

                            return Error(
                                self.path,
                                "C1145",
                                u'Found file "{}" with object type "{}" but with arch "{}"'
                                .format(member, file_object_type, arch),
                            )
Example #4
0
    def check_prefix_file_binary_mode(self):
        """Check that the has_prefix file binary mode is correct."""
        if self.prefix_file_contents is not None:
            placeholder, mode, _ = self.prefix_file_contents

            if mode == "binary":
                if self.name == "python":
                    return Error(
                        self.path,
                        "C1131",
                        "Binary placeholder found in info/has_prefix not allowed when building Python",
                    )
                elif self.win_pkg:
                    return Error(
                        self.path,
                        "C1132",
                        "Binary placeholder found in info/has_prefix not allowed in Windows package",
                    )
                elif len(placeholder) != 255:
                    return Error(
                        self.path,
                        "C1133",
                        u'Binary placeholder "{}" found in info/has_prefix does not have a length of 255 bytes'
                        .format(placeholder),
                    )
Example #5
0
    def check_files_file_for_validity(self):
        """Check that the files listed in info/files exist in the tar archive and vice versa."""
        members = set([
            member for member in self.archive_members
            if not os.path.isdir(os.path.join(self.tmpdir, member))
            and not member.startswith("info")
        ])
        filenames = set([
            os.path.normpath(path.strip())
            for path in self.files_file.decode("utf-8").splitlines()
            if not path.strip().startswith("info")
        ])

        sorted_union_filenames = sorted(members.union(filenames))
        for filename in sorted_union_filenames:
            if filename not in members:
                return Error(
                    self.path,
                    "C1122",
                    (u"Found filename in info/files missing from tar "
                     "archive: {}").format(filename),
                )
            elif filename not in filenames:
                return Error(
                    self.path,
                    "C1123",
                    u"Found filename in tar archive missing from info/files: {}"
                    .format(filename),
                )
Example #6
0
    def check_for_valid_files(self):
        """Check that the files listed in meta.yaml exist."""
        test_files = self.meta.get("test", {}).get("files", [])
        test_source_files = self.meta.get("test", {}).get("source_files", [])
        sources = ensure_list(self.meta.get("source", {}))
        source_patches = []
        for source in sources:
            source_patches.extend(source.get("patches", []))

        for filename in test_files + test_source_files + source_patches:
            filepath = os.path.join(self.recipe_dir, filename)
            if filename.startswith(".."):
                return Error(
                    self.recipe_dir,
                    "C2123",
                    u'Found file "{}" listed outside recipe directory'.format(
                        filename),
                )

            if not os.path.exists(filepath):
                return Error(
                    self.recipe_dir,
                    "C2124",
                    u'Found file "{}" in meta.yaml that doesn\'t exist'.format(
                        filename),
                )
Example #7
0
 def check_build_string(self):
     """Check the build string in info/index.json."""
     build_string = self.info.get('build')
     if not self.version_pat.match(build_string):
         return Error(self.path, 'C1110', 'Found invalid build string "{}" in info/index.json' .format(build_string))
     if build_string != self.build:
         return Error(self.path, 'C1111', 'Found build number in info/index.json "{}" does not match build number "{}" in filename' .format(build_string, self.build))
Example #8
0
 def check_package_version(self):
     """Check the package version located in info/index.json."""
     package_version = str(self.info.get("version"))
     if package_version == "None":
         return Error(
             self.path, "C1104", "Missing package version in info/index.json"
         )
     if package_version.startswith(("_", ".")) or package_version.endswith(
         ("_", ".")
     ):
         return Error(
             self.path,
             "C1107",
             "Package version in info/index.json cannot start or end with '_' or '.'",
         )
     if not self.version_pat.match(package_version) or get_bad_seq(package_version):
         return Error(
             self.path, "C1105", "Found invalid version number in info/index.json"
         )
     if package_version != self.version:
         return Error(
             self.path,
             "C1106",
             u'Found package version in info/index.json "{}" does not match filename version "{}"'.format(
                 package_version, self.version
             ),
         )
Example #9
0
    def check_source(self):
        """Check the source field in meta.yaml for proper formatting."""
        sources = ensure_list(self.meta.get('source', {}))
        for source in sources:
            url = source.get('url')
            if url is not None:
                if self.url_pat.match(url):

                    for hash_algorithm in ['md5', 'sha1', 'sha256']:
                        hexdigest = source.get(hash_algorithm)
                        if hexdigest is not None and not self.hash_pat[
                                hash_algorithm].match(hexdigest):
                            return Error(
                                self.recipe_dir, 'C2119',
                                u'Found invalid hash "{}" in meta.yaml'.format(
                                    hexdigest))

                else:
                    return Error(
                        self.recipe_dir, 'C2120',
                        u'Found invalid URL "{}" in meta.yaml'.format(url))

            git_url = source.get('git_url')
            if git_url and (source.get('git_tag')
                            and source.get('git_branch')):
                return Error(
                    self.recipe_dir, 'C2121',
                    'Found both git_branch and git_tag in meta.yaml source field'
                )
Example #10
0
    def check_fields(self):
        """Check that the fields listed in meta.yaml are valid."""

        for section in self.meta:
            if section not in FIELDS and section != 'extra':
                return Error(self.recipe_dir, 'C2109',
                             u'Found invalid section "{}"'.format(section))

            if section != 'extra':
                subfield = self.meta.get(section)
                if hasattr(subfield, 'keys'):
                    for key in subfield:
                        if key not in FIELDS[section]:
                            return Error(
                                self.recipe_dir, 'C2110',
                                u'Found invalid field "{}" in section "{}"'.
                                format(key, section))
                else:
                    # list of dicts.  Used in source and outputs.
                    for entry in subfield:
                        for key in entry:
                            if key not in FIELDS[section]:
                                return Error(
                                    self.recipe_dir, 'C2110',
                                    u'Found invalid field "{}" in section "{}"'
                                    .format(key, section))
Example #11
0
 def check_package_hashes_and_size(self):
     """Check the sha256 checksum and filesize of each file in the package."""
     for member in self.archive_members:
         file_path = os.path.join(self.tmpdir, member)
         if member in self.paths_json_path:
             if os.path.isfile(file_path):
                 path = self.paths_json_path[member]
                 size = os.stat(file_path).st_size
                 if size != path["size_in_bytes"]:
                     return Error(
                         self.path,
                         "C1147",
                         'Found file "{}" with filesize different than listed in paths.json'.format(
                             member
                         ),
                     )
                 with open(file_path, "rb") as file_object:
                     sha256_digest = sha256_checksum(file_object)
                 if sha256_digest != path["sha256"]:
                     return Error(
                         self.path,
                         "C1146",
                         'Found file "{}" with sha256 hash different than listed in paths.json'.format(
                             member
                         ),
                     )
Example #12
0
 def check_index_dependencies_specs(self):
     """Check that the dependencies in info/index.json are properly formatted."""
     dependencies = ensure_list(self.info.get('depends'))
     if dependencies != [None]:
         for dependency in dependencies:
             dependency_parts = dependency.split()
             if len(dependency_parts) == 0:
                 return Error(self.path, 'C1113', 'Found empty dependencies in info/index.json')
             elif len(dependency_parts) == 2 and not self.ver_spec_pat.match(dependency_parts[1]) or len(dependency_parts) > 3:
                 return Error(self.path, 'C1114', 'Found invalid dependency "{}" in info/index.json' .format(dependency))
Example #13
0
    def check_menu_json_name(self):
        """Check that the Menu/package.json filename is identical to the package name."""
        menu_json_files = [filepath for filepath in self.paths
                           if filepath.startswith('Menu/') and filepath.endswith('.json')]

        if len(menu_json_files) == 1:
            filename = menu_json_files[0]
            if filename != '{}.json' .format(self.name):
                return Error(self.path, 'C1142', u'Found invalid Menu json file "{}"' .format(filename))
        elif len(menu_json_files) > 1:
            return Error(self.path, 'C1143', 'Found more than one Menu json file')
Example #14
0
 def check_package_version(self):
     """Check the package version located in info/index.json."""
     package_version = str(self.info.get('version'))
     if not package_version:
         return Error(self.path, 'C1104', 'Missing package version in info/index.json')
     if not self.version_pat.match(package_version) or get_bad_seq(package_version):
         return Error(self.path, 'C1105', 'Found invalid version number in info/index.json')
     if package_version != self.version:
         return Error(self.path, 'C1106', u'Found package version in info/index.json "{}" does not match filename version "{}"' .format(package_version, self.version))
     if package_version.startswith(('_', '.')) or package_version.endswith(('_', '.')):
         return Error(self.path, 'C1107', "Package version in info/index.json cannot start or end with '_' or '.'")
Example #15
0
    def check_build_number(self):
        """Check the build number located in info/index.json."""
        build_number = self.info.get('build_number')
        if build_number is not None:
            try:
                build_number = int(build_number)
                if build_number < 0:
                    return Error(self.path, 'C1109', 'Build number in info/index.json cannot be a negative integer')

            except ValueError:
                return Error(self.path, 'C1108', 'Build number in info/index.json must be an integer')
Example #16
0
    def check_package_name(self):
        """Check the package name located in info/index.json."""
        package_name = self.info.get('name')
        if package_name is None:
            return Error(self.path, 'C1101', 'Missing package name in info/index.json')

        if package_name != self.name:
            return Error(self.path, 'C1102', u'Found package name in info/index.json "{}" does not match filename "{}"' .format(package_name, self.name))

        if not self.name_pat.match(package_name) or package_name.endswith(('.', '-', '_')):
            return Error(self.path, 'C1103', 'Found invalid package name in info/index.json')
Example #17
0
    def check_build_number(self):
        """Check the build number in meta.yaml for proper formatting."""
        build_number = self.meta.get('build', {}).get('number')

        if build_number is not None:
            try:
                build_number = int(build_number)
                if build_number < 0:
                    return Error(self.recipe_dir, 'C2108', 'Build number in info/index.json cannot be a negative integer')

            except ValueError:
                return Error(self.recipe_dir, 'C2107', 'Build number in info/index.json must be an integer')
Example #18
0
    def check_package_name(self):
        """Check the package name in meta.yaml for proper formatting."""
        package_name = self.meta.get('package', {}).get('name', '')

        if package_name == '':
            return Error(self.recipe_dir, 'C2101', 'Missing package name in meta.yaml')

        if not self.name_pat.match(package_name) or package_name.endswith(('.', '-', '_')):
            return Error(self.recipe_dir, 'C2102', u'Found invalid package name "{}" in meta.yaml' .format(package_name))

        seq = get_bad_seq(package_name)
        if seq:
            return Error(self.recipe_dir, 'C2103', u'Found invalid sequence "{}" in package name' .format(seq))
Example #19
0
    def check_files_file_for_validity(self):
        """Check that the files listed in info/files exist in the tar archive and vice versa."""
        members = [member.path for member in self.archive.getmembers()
                   if not member.isdir() and not member.path.startswith('info')]
        filenames = [path.strip() for path in self.files_file.decode('utf-8').splitlines()
                     if not path.strip().startswith('info')]

        for filename in sorted(set(members).union(set(filenames))):
            if filename not in members:
                return Error(self.path, 'C1122', (u'Found filename in info/files missing from tar '
                                                  'archive: {}').format(filename))
            elif filename not in filenames:
                return Error(self.path, 'C1123', u'Found filename in tar archive missing from info/files: {}' .format(filename))
Example #20
0
    def check_package_version(self):
        """Check the package version in meta.yaml for proper formatting."""
        package_version = self.meta.get('package', {}).get('version', '')

        if package_version == '':
            return Error(self.recipe_dir, 'C2104', 'Missing package version in meta.yaml')

        if isinstance(package_version, str):
            if not self.version_pat.match(package_version) or package_version.startswith(('_', '.')) or package_version.endswith(('_', '.')):
                return Error(self.recipe_dir, 'C2105', u'Found invalid package version "{}" in meta.yaml' .format(package_version))

            seq = get_bad_seq(package_version)
            if seq:
                return Error(self.recipe_dir, 'C2106', u'Found invalid sequence "{}" in package version' .format(seq))
Example #21
0
    def check_package_hashes_and_size(self):
        """Check the sha256 checksum and filesize of each file in the package."""
        paths_json = json.loads(self.paths_file.decode('utf-8'))

        for member in self.archive.getmembers():
            if member.isfile():
                file_object = self.archive.extractfile(member.name).read()
                sha256_digest = hashlib.sha256(file_object).hexdigest()
                for path in paths_json['paths']:
                    if member.name == path['_path']:
                        if sha256_digest != path['sha256']:
                            return Error(self.path, 'C1146', 'Found file "{}" with sha256 hash different than listed in paths.json' .format(member.name))
                        elif member.size != path['size_in_bytes']:
                            return Error(self.path, 'C1147', 'Found file "{}" with filesize different than listed in paths.json' .format(member.name))
Example #22
0
    def check_windows_arch(self):
        """Check that Windows package .exes and .dlls contain the correct headers."""
        if self.win_pkg:
            arch = self.info['arch']
            if arch not in ('x86', 'x86_64'):
                return Error(self.path, 'C1144', u'Found unrecognized Windows architecture "{}"' .format(arch))

            for member in self.archive.getmembers():
                if member.path.endswith(('.exe', '.dll')):
                    file_header = self.archive.extractfile(member.path).read(4096)
                    file_object_type = get_object_type(file_header)
                    if ((arch == 'x86' and file_object_type != 'DLL I386') or
                        (arch == 'x86_64' and file_object_type != 'DLL AMD64')):

                        return Error(self.path, 'C1145', u'Found file "{}" with object type "{}" but with arch "{}"' .format(member.name, file_object_type, arch))
Example #23
0
    def check_about(self):
        """Check the about field in meta.yaml for proper formatting."""
        summary = self.meta.get('about', {}).get('summary')

        if summary is not None and len(summary) > 80:
            return Error(self.recipe_dir, 'C2117', 'Found summary with length greater than 80 characters')

        home = self.meta.get('about', {}).get('home')
        dev_url = self.meta.get('about', {}).get('dev_url')
        doc_url = self.meta.get('about', {}).get('doc_url')
        license_url = self.meta.get('about', {}).get('license_url')

        for url in [home, dev_url, doc_url, license_url]:
            if url is not None and not self.url_pat.match(url):
                return Error(self.recipe_dir, 'C2118', u'Found invalid URL "{}" in meta.yaml' .format(url))
Example #24
0
    def check_license_family(self):
        """Check that the license family listed in meta.yaml is valid."""
        license_family = (self.meta.get('about', {}).get('license_family',
                          self.meta.get('about', {}).get('license')))

        if license_family is not None and license_family not in LICENSE_FAMILIES:
            return Error(self.recipe_dir, 'C2122', u'Found invalid license family "{}"' .format(license_family))
Example #25
0
 def check_for_pyo_file(self):
     """Check the tar archive for .pyo files"""
     for filepath in self.paths:
         if filepath.endswith('.pyo') and self.name != 'python':
             return Error(
                 self.path, 'C1138',
                 u'Found pyo file "{}" in archive'.format(filepath))
Example #26
0
 def check_pyc_files(self):
     """Check that a .pyc file exists for every .py file in a Python 2 package."""
     if 'py3' not in self.build:
         for filepath in self.paths:
             if '/site-packages/' in filepath:
                 if filepath.endswith('.py') and (filepath + 'c') not in self.paths:
                     return Error(self.path, 'C1141', u'Found python file "{}" without a corresponding pyc file' .format(filepath))
Example #27
0
    def check_for_bat_and_exe(self):
        """Check that both .bat and .exe files don't exist in the same package."""
        bat_files = [filepath for filepath in self.paths if filepath.endswith('.bat')]
        exe_files = [filepath for filepath in self.paths if filepath.endswith('.exe')]

        if len(bat_files) > 0 and len(exe_files) > 0:
            return Error(self.path, 'C1127', 'Found both .bat and .exe files in executable directory')
Example #28
0
 def check_for_2to3_pickle(self):
     """Check the tar archive for .pickle files."""
     for filepath in self.paths:
         if 'lib2to3' in filepath and filepath.endswith('.pickle'):
             return Error(
                 self.path, 'C1140',
                 u'Found lib2to3 .pickle file "{}"'.format(filepath))
Example #29
0
    def check_for_unallowed_files(self):
        """Check the tar archive for unallowed directories."""
        unallowed_directories = {'conda-meta', 'conda-bld', 'pkgs', 'pkgs32', 'envs'}

        for filepath in self.paths:
            if filepath in unallowed_directories or filepath.endswith(('.DS_Store', '~')):
                return Error(self.path, 'C1125', u'Found unallowed file in tar archive: {}' .format(filepath))
Example #30
0
 def check_for_pth_file(self):
     """Check the tar archive for .pth files."""
     for filepath in self.paths:
         if filepath.endswith('.pth'):
             return Error(
                 self.path, 'C1137',
                 u'Found namespace file "{}" in archive'.format(filepath))