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]))
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())