Coverage for hledger_lots/options.py: 26%

80 statements  

« prev     ^ index     » next       coverage.py v7.2.3, created at 2023-05-05 10:12 -0300

1from dataclasses import dataclass 

2from typing import Dict, Optional, Tuple 

3 

4NAMESPACE = "hledger-lots" 

5KEYS = {"avg_cost", "check", "no_desc"} 

6 

7 

8@dataclass 

9class Options: 

10 avg_cost: bool 

11 check: bool 

12 no_desc: str 

13 

14 

15class OptionError(BaseException): 

16 TEMPLATE = """Copy/Paste the text below to the journal, changing values according to the need 

17 

18#+hledger-lots avg_cost:false, check:true 

19#+hledger-lots no_desc: 

20 """ 

21 

22 def __init__(self, message: str) -> None: 

23 self.message = f"\n\n{message}\n\n{self.TEMPLATE}" 

24 super().__init__(self.message) 

25 

26 

27class HledgerVars: 

28 NAMESPACE_START = "#+" 

29 

30 def __init__(self, files: Tuple[str, ...]): 

31 self.files = files 

32 self.vars: Dict[str, str] = {} 

33 

34 def get_var_tuple(self, var_str: str): 

35 var_key_value = var_str.split(":", 1) 

36 if len(var_key_value) == 0: 

37 return None 

38 

39 key = var_key_value[0].strip(" \n") 

40 value = var_key_value[1].strip() 

41 result = (key, value) 

42 return result 

43 

44 def get_row_vars(self, row: str, namespace: str): 

45 start = self.NAMESPACE_START + namespace 

46 if not row.startswith(start): 

47 return 

48 

49 vars_str = row[len(start) :] 

50 if len(vars_str) == 0: 

51 return 

52 

53 vars_list = vars_str.split(",") 

54 vars_tuple = (self.get_var_tuple(var) for var in vars_list) 

55 vars_dict = {var[0]: var[1] for var in vars_tuple if var} 

56 return vars_dict 

57 

58 def get_file_vars(self, file: str, namespace: str): 

59 result: Dict[str, str] = {} 

60 with open(file, "r") as f: 

61 for row in f: 

62 row_vars = self.get_row_vars(row, namespace) 

63 if row_vars: 

64 result = {**result, **row_vars} 

65 

66 return result 

67 

68 def get_namespace_vars(self, namespace: str): 

69 result: Dict[str, str] = {} 

70 for file in self.files: 

71 file_vars = self.get_file_vars(file, namespace) 

72 if file_vars: 

73 result = {**result, **file_vars} 

74 

75 self.var = result 

76 return result 

77 

78 def get(self, key: str, default: Optional[str] = None): 

79 if not self.vars: 

80 return default 

81 

82 try: 

83 value = self.vars[key] 

84 except KeyError: 

85 value = default 

86 

87 return value 

88 

89 

90def get_options(files: Tuple[str, ...]): 

91 hledger_vars = HledgerVars(files) 

92 vars = hledger_vars.get_namespace_vars(NAMESPACE) 

93 existing_keys = set(vars.keys()) 

94 missing = KEYS.difference(existing_keys) 

95 

96 if len(missing) > 0: 

97 raise OptionError(f"Missing keys {missing}") 

98 

99 errors = "" 

100 if vars["avg_cost"] not in ["true", "false"]: 

101 errors += 'avg_cost should be "true" or "false"\n' 

102 

103 if vars["check"] not in ["true", "false"]: 

104 errors += 'check should be "true" or "false"\n' 

105 

106 if errors != "": 

107 raise OptionError(errors) 

108 

109 avg_cost = True if vars["avg_cost"] == "true" else False 

110 check = True if vars["check"] == "true" else False 

111 no_desc = vars["no_desc"] 

112 return Options(avg_cost, check, no_desc)