1- """
2- This module contains classes and methods
3- for assembling and sending telegram messages to the bot.
4- """
1+ """This module contains classes and methods for assembling and sending telegram messages to the bot."""
52import os
63import json
74import math
85import re
9- from typing import Union
106import emoji
7+ from .exceptions import ConfigurationIsNotValid , TemplateNotFound , TemplatesIsNotValid
118
129
1310class Messages :
1411 """
15- This class contains methods
16- for assembling and sending telegram messages to the bot.
12+ This class contains methods for assembling and sending telegram messages to the bot.
13+
14+ Attributes:
15+ configuration (dict): the contents of the configuration file.
16+
17+ Exceptions:
18+ ConfigurationIsNotValid: raised when the configuration file is not valid JSON.
19+ TemplateNotFound: raised when the template is not found in the configuration file.
20+ TemplatesIsNotValid: raised when the templates is not valid.
21+
22+ Examples:
23+ >>> from messages import Messages
24+ >>> messages = Messages('configs/messages.json')
25+ >>> messages.render_template('test_message', username='pytest')
1726 """
1827
19- def __init__ (
20- self ,
21- config_path : str = None
22- ) -> None :
28+ def __init__ (self , config_path : str = 'configs/messages.json' ) -> None :
2329 """
2430 Method for create a new messages instance.
2531
2632 Args:
2733 config (str): the path as a file containing a dictionary with message templates.
34+ """
35+ env_variable = os .environ .get ("MESSAGES_CONFIG" , None )
2836
29- Returns:
30- None
37+ if env_variable :
38+ config_file = env_variable
39+ else :
40+ config_file = config_path
3141
32- Examples:
33- >>> from messages import Messages
34- >>> messages = Messages('configs/messages.json')
42+ self .configuration = self ._read_configuration (config_file = config_file )
43+
44+ if not self ._templates_is_valid ():
45+ raise TemplatesIsNotValid (
46+ "Templates have invalid elements. Please check your configuration file. "
47+ "Otherwise, check examples: https://github.com/obervinov/messages-package?tab=readme-ov-file#-usage-examples"
48+ )
49+
50+ def _read_configuration (self , config_file : str = None ) -> dict :
3551 """
36- if os .environ .get ("MESSAGES_CONFIG" , None ) is not None :
37- self .config_path = os .environ .get ("MESSAGES_CONFIG" , None )
38- elif config_path :
39- self .config_path = config_path
40- else :
41- self .config_path = 'configs/messages.json'
52+ Method for checking the validity of the configuration file and reading its contents.
53+
54+ Args:
55+ config_file (str): the path as a file containing a dictionary with message templates.
4256
43- if os .path .exists (self .config_path ):
44- with open (self .config_path , 'r' , encoding = 'UTF-8' ) as config_json :
57+ Returns:
58+ dict: the contents of the configuration file.
59+ """
60+ if os .path .exists (config_file ):
61+ with open (config_file , 'r' , encoding = 'UTF-8' ) as config_json :
4562 try :
46- self .data = json .load (config_json )
47- config_json .close ()
63+ return json .load (config_json )
4864 except json .JSONDecodeError as json_error :
49- # pylint: disable=no-value-for-parameter
50- raise json .JSONDecodeError (
51- f"Configuration file { self .config_path } is not valid JSON: { json_error } \n "
65+ raise ConfigurationIsNotValid (
66+ "Configuration file structure is not valid JSON. Please check examples: "
5267 "https://github.com/obervinov/messages-package?tab=readme-ov-file#-usage-examples"
53- )
68+ ) from json_error
5469 else :
55- raise FileNotFoundError (f"Configuration file not found: { self .config_path } " )
70+ raise FileNotFoundError (f"Configuration file not found: { config_file } " )
71+
72+ def _templates_is_valid (self ) -> bool :
73+ """
74+ Method for checking the validity of the templates in the configuration file.
75+
76+ Returns:
77+ bool: True if the templates are valid, False otherwise.
78+ """
79+ if 'templates' in self .configuration :
80+ for template in self .configuration ['templates' ].values ():
81+ if 'text' not in template or 'args' not in template :
82+ print (f"[Messages]: there are no text or args in template { template } " )
83+ return False
84+ if not isinstance (template ['text' ], str ) or not isinstance (template ['args' ], list ):
85+ print (f"[Messages]: text or args in template { template } has an invalid data type" )
86+ return False
87+ args_provided = len (template ['args' ])
88+ args_expected = len (re .findall (r"{.*?}" , template ['text' ]))
89+ if args_provided != args_expected :
90+ print (f"[Messages]: the number of arguments in the template { template } does nots match" )
91+ return False
92+ return True
5693
5794 def render_template (
5895 self ,
5996 template_alias : str = None ,
6097 ** kwargs
61- ) -> Union [ str , None ] :
98+ ) -> str | None :
6299 """
63100 Method for reading the text from the configuration file.
64101
65102 Args:
66- template_alias (str): the name of the template key for extracting text from conifg .
103+ template_alias (str): the name of the template key for extracting text from config .
67104
68105 Keyword Args:
69106 **kwargs: passing additional parameters for message assembly.
@@ -78,7 +115,7 @@ def render_template(
78115 >>> messages.render_template('test_message', username='pytest')
79116 """
80117 try :
81- template = self .data ['templates' ][template_alias ]
118+ template = self .configuration ['templates' ][template_alias ]
82119 arguments = []
83120 for arg in template ['args' ]:
84121 if re .match (r":.*:" , arg ):
@@ -89,15 +126,17 @@ def render_template(
89126 arguments .append (kwargs .get (arg ))
90127 # Building full message
91128 return template ['text' ].format (* arguments )
92- except KeyError :
129+ except KeyError as error :
93130 print (f"[Messages]: template not found: { template_alias } " )
94- return None
131+ raise TemplateNotFound (
132+ "Template not found in the configuration file. Please check your configuration file."
133+ ) from error
95134
96135 def render_progressbar (
97136 self ,
98137 total_count : int = 0 ,
99138 current_count : int = 0
100- ) -> Union [ str , None ] :
139+ ) -> str | None :
101140 """
102141 A Method for generating string with a progress bar based
103142 on the transmitted statistics data.
0 commit comments