Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1""" 

2Define data types used within processor module. 

3 

4""" 

5import json 

6from dataclasses import asdict, dataclass, field, fields 

7from os import getcwd 

8from pathlib import Path, PurePosixPath 

9from typing import Tuple, Union 

10 

11from config import config 

12from errors import DppArgparseConfigCorruptedError, DppArgparseFileNotFoundError, DppArgparseInvalidConfigError 

13from taxonomy import MetaData, Taxonomy 

14 

15NAMESPACE_ATTR_INDEX = "index" 

16NAMESPACE_ATTR_BUGGY = "buggy" 

17NAMESPACE_ATTR_WORKSPACE = "workspace" 

18NAMESPACE_ATTR_PATH = "path" 

19NAMESPACE_ATTR_PATH_CONFIG_NAME = ".defects4cpp.json" 

20NAMESPACE_ATTR_METADATA = "metadata" 

21NAMESPACE_ATTR_METADATA_BASE = "metadata_base" 

22 

23 

24@dataclass 

25class Worktree: 

26 """ 

27 Dataclass to manage host and container directory structure. 

28 

29 """ 

30 

31 project_name: str 

32 """The name of the defect taxonomy.""" 

33 index: int 

34 """The index number of taxonomy.""" 

35 buggy: bool = field(default=False) 

36 """True if the project is configured as buggy, otherwise False.""" 

37 workspace: str = field(default=getcwd()) 

38 """The workspace path string.""" 

39 

40 @property 

41 def base(self) -> Path: 

42 """Return base path which will be used to test and build defect taxonomies""" 

43 return Path(f"{self.workspace}/{self.project_name}") 

44 

45 @property 

46 def suffix(self) -> Path: 

47 """Return suffix path which is appended to base path""" 

48 return Path(f"{'buggy' if self.buggy else 'fixed'}-{self.index}") 

49 

50 @property 

51 def host(self) -> Path: 

52 """Return path from which is mounted""" 

53 return self.base / self.suffix 

54 

55 @property 

56 def container(self) -> PurePosixPath: 

57 """Return path to which is mounted inside docker""" 

58 return PurePosixPath(config.DPP_DOCKER_HOME) 

59 

60 def __post_init__(self): 

61 for f in fields(self): 

62 value = getattr(self, f.name) 

63 if not value: 

64 setattr(self, f.name, f.default) 

65 

66 

67class Project: 

68 """ 

69 Load and save project from path. 

70 

71 """ 

72 

73 @staticmethod 

74 def read_config(project_dir: Union[str, Path]) -> Tuple[MetaData, Worktree]: 

75 """ 

76 Read config file and return parsed options. 

77 

78 Parameters 

79 ---------- 

80 project_dir : Union[str, Path] 

81 Path to where defect taxonomy is located. 

82 

83 Returns 

84 ------- 

85 Tuple[taxonomy.MetaData, docker.Worktree] 

86 Return a tuple of metadata and worktree information. 

87 """ 

88 try: 

89 with open(Path(project_dir) / NAMESPACE_ATTR_PATH_CONFIG_NAME, "r") as fp: 

90 data = json.load(fp) 

91 except FileNotFoundError as e: 

92 raise DppArgparseFileNotFoundError(e.filename) 

93 except json.JSONDecodeError: 

94 raise DppArgparseInvalidConfigError() 

95 

96 try: 

97 worktree = Worktree(**data) 

98 except TypeError: 

99 raise DppArgparseConfigCorruptedError(data) 

100 

101 t = Taxonomy() 

102 return t[worktree.project_name], worktree 

103 

104 @staticmethod 

105 def write_config(worktree: Worktree) -> None: 

106 """ 

107 Write config file to the directory. 

108 

109 Parameters 

110 ---------- 

111 worktree : taxonomy.Worktree 

112 Worktree 

113 

114 Returns 

115 ------- 

116 None 

117 """ 

118 config_file = Path(worktree.host) / NAMESPACE_ATTR_PATH_CONFIG_NAME 

119 if config_file.exists(): 

120 return 

121 

122 try: 

123 with open(config_file, "w+") as fp: 

124 json.dump(asdict(worktree), fp) 

125 except FileNotFoundError as e: 

126 raise DppArgparseFileNotFoundError(e.filename)