def get_path_to_verification(
            self) -> Dict[pathlib.Path, VerificationStatus]:
        result = {}  # type: Dict[pathlib.Path, VerificationStatus]
        # .test.cpp の verify 状況確認
        for cpp_file, cpp_class in self.verify_files.items():
            result[cpp_file] = cpp_class.verification_status

        # .cpp は、それを必要としている .test.cpp が少なくとも 1 つ存在し
        # 全ての .test.cpp が verify 済みなら OK
        for cpp_file, cpp_class in self.library_files.items():
            # cpp_fileを必要としている .test.cpp のstatusのlist
            required_verification_statuses = []
            for verify in cpp_class.required:
                if is_verification_file(verify):
                    required_verification_statuses.append(result[verify])
            # verification statusを解決する
            if len(required_verification_statuses) == 0:
                # 一つも .test.cpp が見つからなかったらverifyされていない
                result[cpp_file] = VerificationStatus.DEFAULT
            elif all(status == VerificationStatus.FAILED
                     for status in required_verification_statuses):
                # cpp_fileを必要としている全てのtestでfailedならfailedとする
                result[cpp_file] = VerificationStatus.FAILED
            elif all(status == VerificationStatus.VERIFIED
                     for status in required_verification_statuses):
                # 上記以外でcpp_fileを必要としている .test.cpp が全てverifiedかfailedならverifiedとする
                result[cpp_file] = VerificationStatus.VERIFIED
            else:
                # 一つでもfailedならfailed、とすると自身のコードに問題ない場合も誤ってfailedとなる可能性が高まるので避けた
                result[cpp_file] = VerificationStatus.QUESTION
            self.library_files[cpp_file].verification_status = result[cpp_file]
        return result
def _build_verification_status(
        paths: List[pathlib.Path], *, verified_with: Dict[pathlib.Path,
                                                          List[pathlib.Path]],
        basedir: pathlib.Path,
        marker: VerificationMarker) -> Dict[pathlib.Path, VerificationStatus]:
    """
    :returns: mapping from absolute paths to verification status
    """
    verification_status: Dict[pathlib.Path, VerificationStatus] = {}

    # list status for verification files
    for path in paths:
        absolute_path = (basedir / path).resolve()
        if utils.is_verification_file(path, basedir=basedir):
            if marker.is_verified(path):
                status = VerificationStatus.TEST_ACCEPTED
            elif marker.is_failed(path):
                status = VerificationStatus.TEST_WRONG_ANSWER
            else:
                status = VerificationStatus.TEST_WAITING_JUDGE
            verification_status[absolute_path] = status

    # list status for library files
    for path in paths:
        absolute_path = (basedir / path).resolve()
        if not utils.is_verification_file(path, basedir=basedir):
            status_list = []
            for verification_path in verified_with[absolute_path]:
                status_list.append(
                    verification_status[(basedir /
                                         verification_path).resolve()])
            if not status_list:
                status = VerificationStatus.LIBRARY_NO_TESTS
            elif status_list.count(
                    VerificationStatus.TEST_ACCEPTED) == len(status_list):
                status = VerificationStatus.LIBRARY_ALL_AC
            elif status_list.count(
                    VerificationStatus.TEST_WRONG_ANSWER) == len(status_list):
                status = VerificationStatus.LIBRARY_ALL_WA
            elif VerificationStatus.TEST_WRONG_ANSWER in status_list:
                status = VerificationStatus.LIBRARY_SOME_WA
            else:
                status = VerificationStatus.LIBRARY_PARTIAL_AC
            verification_status[absolute_path] = status

    return verification_status
def _build_dependency_graph(
    paths: List[pathlib.Path], *, basedir: pathlib.Path
) -> Tuple[Dict[pathlib.Path, List[pathlib.Path]], Dict[
        pathlib.Path, List[pathlib.Path]], Dict[pathlib.Path,
                                                List[pathlib.Path]]]:
    """
    :returns: graphs from absolute paths to relative paths
    """
    depends_on: Dict[pathlib.Path, List[pathlib.Path]] = {}
    required_by: Dict[pathlib.Path, List[pathlib.Path]] = {}
    verified_with: Dict[pathlib.Path, List[pathlib.Path]] = {}

    # initialize
    for path in paths:
        absolute_path = (basedir / path).resolve()
        depends_on[absolute_path] = []
        required_by[absolute_path] = []
        verified_with[absolute_path] = []

    # build the graph
    for src in paths:
        absolute_src = (basedir / src).resolve()
        relative_src = absolute_src.relative_to(
            basedir)  # all paths must be in the git repository
        language = onlinejudge_verify.languages.list.get(src)
        assert language is not None

        try:
            dependencies = language.list_dependencies(src, basedir=basedir)
        except Exception as e:
            logger.exception('failed to list dependencies of %s: %s',
                             str(relative_src), e)
            continue

        for dst in dependencies:
            absolute_dst = (basedir / dst).resolve()
            relative_dst = absolute_dst.relative_to(basedir)
            if absolute_src == absolute_dst:
                continue
            if absolute_dst not in depends_on:
                logger.debug(
                    "The file `%s` which is depended from `%s` is ignored because it's not listed as a source code file.",
                    relative_dst, relative_src)
                continue

            depends_on[absolute_src].append(relative_dst)
            if utils.is_verification_file(src, basedir=basedir):
                verified_with[absolute_dst].append(relative_src)
            else:
                required_by[absolute_dst].append(relative_src)

    return depends_on, required_by, verified_with
 def get_files(
     self,
     source_path: pathlib.Path,
     *,
     is_verify: bool = False,
     ignored_files: 'OrderedDict[pathlib.Path, CppFile]' = OrderedDict()
 ) -> 'OrderedDict[pathlib.Path, CppFile]':
     files = {}
     for path in source_path.glob(r'**/*'):
         if onlinejudge_verify.languages.get(path):
             if is_verify and not is_verification_file(path):
                 continue
             if any([
                     path.samefile(ignored_file)
                     for ignored_file in ignored_files
             ]):
                 continue
             if not self.is_ignored(path):
                 path = path.resolve()
                 files[path] = CppFile(path, source_path)
     return OrderedDict(sorted(files.items(), key=lambda x: x[0]))
示例#5
0
def _render_source_code_stats_for_top_page(
    *,
    source_code_stats: List[SourceCodeStat],
    page_title_dict: Dict[pathlib.Path, str],
    basedir: pathlib.Path,
) -> Dict[str, Any]:
    libraryCategories: Dict[str, List[Dict[str, str]]] = {}
    verificationCategories: Dict[str, List[Dict[str, str]]] = {}
    for stat in source_code_stats:
        if utils.is_verification_file(stat.path, basedir=basedir):
            categories = verificationCategories
        else:
            categories = libraryCategories
        category = str(stat.path.parent)
        if category not in categories:
            categories[category] = []
        categories[category].append({
            'path':
            str(stat.path),
            'title':
            page_title_dict[stat.path],
            'icon':
            _get_verification_status_icon(stat.verification_status),
        })

    data: Dict[str, Any] = {}
    data['libraryCategories'] = []
    for category, pages in libraryCategories.items():
        data['libraryCategories'].append({
            'name': category,
            'pages': pages,
        })
    data['verificationCategories'] = []
    for category, pages in verificationCategories.items():
        data['verificationCategories'].append({
            'name': category,
            'pages': pages,
        })
    return data
    def write_contents(
            self, file_object: IO,
            path_to_title: 'OrderedDict[pathlib.Path, str]',
            path_to_verification: Dict[pathlib.Path,
                                       VerificationStatus]) -> None:
        back_to_top_link = self.get_link(self.md_destination_path /
                                         'index.html')

        # see, docs (絶対パス)
        for see in self.file_class.see:
            file_object.write('* see: {}\n'.format(self.get_linktag(
                see, see)).encode())
        for docs in self.file_class.docs:
            file_object.write(b'\n\n')
            with open(docs, 'rb') as f:
                file_object.write(f.read())
        file_object.write(b'\n\n')

        # cpp (絶対パス) => (cpp|test.cpp) (絶対パス): リンクは相対パスに
        self.file_class.depends = sorted(list(set(self.file_class.depends)))
        if self.file_class.depends != []:
            file_object.write(b'## Depends on\n\n')
            for depends in self.file_class.depends:
                if depends not in path_to_verification:
                    raise FileNotFoundError(
                        '{} seems not to exist in path_to_verification'.format(
                            depends))
                mark = path_to_verification[depends]

                if depends not in path_to_title:
                    raise FileNotFoundError(
                        '{} seems not to exist in path_to_title'.format(
                            depends))
                title = path_to_title[depends]

                file_type = 'verify' if is_verification_file(
                    depends) else 'library'
                link = self.get_link(self.get_destination(depends,
                                                          file_type)) + '.html'
                file_object.write('* {} {}\n'.format(
                    mark.value, self.get_linktag(title, link)).encode())
            file_object.write(b'\n\n')

        required_file_list = [
            f for f in self.file_class.required if not is_verification_file(f)
        ]
        verified_file_list = [
            f for f in self.file_class.required if is_verification_file(f)
        ]

        # ビルド対象ファイルが test.cpp の場合、それに依存している test.cpp ファイルは Verified ではなく Required に入れる
        if is_verification_file(self.file_class.file_path):
            required_file_list.extend(verified_file_list)
            verified_file_list = []

        required_file_list = sorted(set(required_file_list))
        verified_file_list = sorted(set(verified_file_list))

        # cpp <= cpp または test.cpp <= test.cpp
        if required_file_list != []:
            file_object.write(b'## Required by\n\n')
            for required in required_file_list:
                if required not in path_to_verification:
                    raise FileNotFoundError(
                        '{} seems not to exist in path_to_verification'.format(
                            required))
                mark = path_to_verification[required]

                if required not in path_to_title:
                    raise FileNotFoundError(
                        '{} seems not to exist in path_to_title'.format(
                            required))
                title = path_to_title[required]

                file_type = 'verify' if is_verification_file(
                    required) else 'library'
                link = self.get_link(self.get_destination(required,
                                                          file_type)) + '.html'
                file_object.write('* {} {}\n'.format(
                    mark.value, self.get_linktag(title, link)).encode())
            file_object.write(b'\n\n')

        # cpp => test.cpp
        if verified_file_list != []:
            file_object.write(b'## Verified with\n\n')
            for verified in verified_file_list:
                if verified not in path_to_verification:
                    raise FileNotFoundError(
                        '{} seems not to exist in path_to_verification'.format(
                            verified))
                mark = path_to_verification[verified]

                if verified not in path_to_title:
                    raise FileNotFoundError(
                        '{} seems not to exist in path_to_title'.format(
                            verified))
                title = path_to_title[verified]

                link = self.get_link(self.get_destination(verified,
                                                          'verify')) + '.html'
                file_object.write('* {} {}\n'.format(
                    mark.value, self.get_linktag(title, link)).encode())
            file_object.write(b'\n\n')

        # source code
        file_object.write(b'## Code\n\n')
        file_object.write(b'<a id="unbundled"></a>\n')
        file_object.write(b'{% raw %}\n```cpp\n')
        with open(self.file_class.file_path, 'rb') as f:
            file_object.write(f.read())
        file_object.write(b'\n```\n{% endraw %}\n\n')

        language = onlinejudge_verify.languages.get(self.file_class.file_path)
        assert language is not None
        try:
            bundled_code = language.bundle(self.file_class.file_path,
                                           basedir=pathlib.Path.cwd())
        except Exception:
            logger.warning("failed to bundle: %s",
                           str(self.file_class.file_path))
            bundled_code = traceback.format_exc().encode()
        file_object.write(b'<a id="bundled"></a>\n')
        file_object.write(b'{% raw %}\n```cpp\n')
        file_object.write(bundled_code)
        file_object.write(b'\n```\n{% endraw %}\n\n')

        # back to top
        file_object.write('{}\n\n'.format(
            self.get_linktag('Back to top page', back_to_top_link)).encode())