dd84ai

Refactoring

Aug 17th, 2023 (edited)
1,078
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 3.14 KB | None | 0 0
  1. from typing import Generator, Any, Callable
  2. import argparse
  3.  
  4. class ParserException(Exception):
  5.     pass
  6.  
  7.  
  8. class ManagableArgparser(argparse.ArgumentParser):
  9.     def error(self, message):
  10.         """
  11.        Default Argparser exits with sys.exit on error. We override error func to continue program flow
  12.        """
  13.         self.print_usage(argparse._sys.stderr)
  14.         args = {'prog': self.prog, 'message': message}
  15.         raise ParserException('%(prog)s: error: %(message)s\n' % args)
  16.  
  17. class Rule:
  18.     def __init__(self, func: Callable[[Any], bool], err_msg: str):
  19.         self.func = func
  20.         self.err_msg = err_msg
  21.  
  22. class MyParser():
  23.     answer_varname = "answer"
  24.     def __init__(self):
  25.         self.parser = ManagableArgparser()
  26.  
  27.     def add_argument(self, choices = None, type = None):
  28.         arguments = {}
  29.         if choices is not None:
  30.             arguments["choices"] = choices
  31.         if type is not None:
  32.             arguments["type"] = type
  33.         self.parser.add_argument(self.answer_varname, **arguments)
  34.         return self
  35.  
  36.     def ask_question(self, question: str, rules: list[Rule]=[]) -> Generator[Any, None, None]:
  37.         """
  38.        handling retries and all rules :)
  39.        """
  40.         while True:
  41.             userinput = input(question)
  42.             try:
  43.                 result = self.parser.parse_args(args=[userinput])
  44.                 answer = getattr(result,self.answer_varname)
  45.  
  46.                 for rule in rules:
  47.                     if not rule.func(answer):
  48.                         raise ParserException(rule.err_msg)
  49.  
  50.                 return answer
  51.             except ParserException as err:
  52.                 print(f"{str(err)=}")
  53.  
  54.  
  55. class Item:
  56.     def __init__(self):
  57.         self.name: str = MyParser() \
  58.             .add_argument(type=str) \
  59.             .ask_question("Enter item name?> ", rules=[
  60.                 Rule(lambda answer: " " not in answer, "must not contains spaces"),
  61.                 Rule(lambda answer: answer.isalpha(), "Must be out of alphabet characters only"),
  62.             ])
  63.  
  64.         positive_number = Rule(lambda answer: answer > 0, "Must be positive number")
  65.         self.carbs: int = MyParser().add_argument(type=int).ask_question("Enter grams of carbs?> ", rules=[positive_number])
  66.         self.fats: int = MyParser().add_argument(type=int).ask_question("Enter grams of fats?> ", rules=[positive_number])
  67.         self.proteins: int = MyParser().add_argument(type=int).ask_question("Enter grams of proteins?> ", rules=[positive_number])
  68.  
  69.     @property
  70.     def calories(self) -> int:
  71.         return self.carbs * 4 + self.fats * 9 + self.proteins * 4
  72.  
  73. class Session:
  74.     def __init__(self):
  75.         self.items: list[Item] = []
  76.  
  77.     def run(self):
  78.         while True:
  79.             answer = MyParser().add_argument(choices=["y","n"]).ask_question("would you like to add another item?> (y/n) ")
  80.             if answer == "n":
  81.                 break
  82.  
  83.             self.items.append(Item())
  84.  
  85.         print(f"this meal has {len(self.items)} for {sum([item.calories for item in self.items])} calories")
  86.  
  87. if __name__=="__main__":
  88.     session = Session()
  89.     session.run()
  90.  
  91.  
  92.  
Advertisement
Add Comment
Please, Sign In to add comment