rgwfuncs 0.0.107__py3-none-any.whl → 0.0.109__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
rgwfuncs/str_lib.py CHANGED
@@ -17,66 +17,47 @@ _PRINT_HEADING_CURRENT_CALL = 0
17
17
  _PRINT_SUBHEADING_COUNTS = defaultdict(int) # Tracks sub-headings per heading
18
18
  _CURRENT_HEADING_NUMBER = 0
19
19
 
20
- def send_telegram_message(preset_name: str, message: str, config: Optional[Union[str, dict]] = None) -> None:
20
+
21
+ def send_telegram_message(message: str, preset_name: Optional[str] = None, bot_token: Optional[str] = None,
22
+ chat_id: Optional[str] = None) -> None:
21
23
  """
22
- Send a Telegram message using the specified preset.
24
+ Send a Telegram message using either a preset or provided bot token and chat ID.
23
25
 
24
26
  Args:
25
- preset_name (str): The name of the preset to use for sending the message.
26
27
  message (str): The message to send.
27
- config (Optional[Union[str, dict]], optional): Configuration source. Can be:
28
- - None: Searches for '.rgwfuncsrc' in current directory and upwards
29
- - str: Path to a JSON configuration file
30
- - dict: Direct configuration dictionary
28
+ preset_name (Optional[str]): The name of the preset to use for sending the message.
29
+ bot_token (Optional[str]): The Telegram bot token.
30
+ chat_id (Optional[str]): The Telegram chat ID.
31
31
 
32
32
  Raises:
33
- FileNotFoundError: If no '.rgwfuncsrc' file is found in current or parent directories.
34
- ValueError: If the config parameter is neither a path string nor a dictionary, or if the config file is empty/invalid.
35
- RuntimeError: If the preset is not found or necessary details are missing.
33
+ FileNotFoundError: If no '.rgwfuncsrc' file is found when preset_name is used.
34
+ ValueError: If preset_name is used with bot_token/chat_id, neither preset_name nor both bot_token/chat_id are provided,
35
+ or the config file is empty/invalid.
36
+ RuntimeError: If the preset is not found or necessary preset details are missing.
36
37
  """
37
- def get_config(config: Optional[Union[str, dict]] = None) -> dict:
38
- """Get configuration either from a path, direct dictionary, or by searching upwards."""
39
- def get_config_from_file(config_path: str) -> dict:
40
- """Load configuration from a JSON file."""
41
- # print(f"Reading config from: {config_path}") # Debug line
42
- with open(config_path, 'r', encoding='utf-8') as file:
43
- content = file.read()
44
- # print(f"Config content (first 100 chars): {content[:100]}...") # Debug line
45
- if not content.strip():
46
- raise ValueError(f"Config file {config_path} is empty")
47
- try:
48
- return json.loads(content)
49
- except json.JSONDecodeError as e:
50
- raise ValueError(f"Invalid JSON in config file {config_path}: {e}")
51
-
38
+ def get_config() -> dict:
39
+ """Get configuration by searching for '.rgwfuncsrc' in current directory and upwards."""
52
40
  def find_config_file() -> str:
53
41
  """Search for '.rgwfuncsrc' in current directory and upwards."""
54
42
  current_dir = os.getcwd()
55
- # print(f"Starting config search from: {current_dir}") # Debug line
56
43
  while True:
57
44
  config_path = os.path.join(current_dir, '.rgwfuncsrc')
58
- # print(f"Checking for config at: {config_path}") # Debug line
59
45
  if os.path.isfile(config_path):
60
- # print(f"Found config at: {config_path}") # Debug line
61
46
  return config_path
62
47
  parent_dir = os.path.dirname(current_dir)
63
48
  if parent_dir == current_dir: # Reached root directory
64
49
  raise FileNotFoundError(f"No '.rgwfuncsrc' file found in {os.getcwd()} or parent directories")
65
50
  current_dir = parent_dir
66
51
 
67
- # Determine the config to use
68
- if config is None:
69
- # Search for .rgwfuncsrc upwards from current directory
70
- config_path = find_config_file()
71
- return get_config_from_file(config_path)
72
- elif isinstance(config, str):
73
- # If config is a string, treat it as a path and load it
74
- return get_config_from_file(config)
75
- elif isinstance(config, dict):
76
- # If config is already a dict, use it directly
77
- return config
78
- else:
79
- raise ValueError("Config must be either a path string or a dictionary")
52
+ config_path = find_config_file()
53
+ with open(config_path, 'r', encoding='utf-8') as file:
54
+ content = file.read()
55
+ if not content.strip():
56
+ raise ValueError(f"Config file {config_path} is empty")
57
+ try:
58
+ return json.loads(content)
59
+ except json.JSONDecodeError as e:
60
+ raise ValueError(f"Invalid JSON in config file {config_path}: {e}")
80
61
 
81
62
  def get_telegram_preset(config: dict, preset_name: str) -> dict:
82
63
  """Get the Telegram preset configuration."""
@@ -90,30 +71,36 @@ def send_telegram_message(preset_name: str, message: str, config: Optional[Union
90
71
  """Retrieve the Telegram bot token and chat ID from the preset."""
91
72
  preset = get_telegram_preset(config, preset_name)
92
73
  if not preset:
93
- raise RuntimeError(
94
- f"Telegram bot preset '{preset_name}' not found in the configuration file")
74
+ raise RuntimeError(f"Telegram bot preset '{preset_name}' not found in the configuration file")
95
75
 
96
76
  bot_token = preset.get("bot_token")
97
77
  chat_id = preset.get("chat_id")
98
78
 
99
79
  if not bot_token or not chat_id:
100
- raise RuntimeError(
101
- f"Telegram bot token or chat ID for '{preset_name}' not found in the configuration file")
80
+ raise RuntimeError(f"Telegram bot token or chat ID for '{preset_name}' not found in the configuration file")
102
81
 
103
82
  return bot_token, chat_id
104
83
 
105
- config = get_config(config)
106
- # Get bot details from the configuration
107
- bot_token, chat_id = get_telegram_bot_details(config, preset_name)
84
+ # Validate input parameters
85
+ if preset_name and (bot_token or chat_id):
86
+ raise ValueError("Cannot specify both preset_name and bot_token/chat_id")
87
+ if not preset_name and (bool(bot_token) != bool(chat_id)):
88
+ raise ValueError("Both bot_token and chat_id must be provided if preset_name is not used")
89
+ if not preset_name and not bot_token and not chat_id:
90
+ raise ValueError("Either preset_name or both bot_token and chat_id must be provided")
91
+
92
+ # Get bot token and chat ID
93
+ if preset_name:
94
+ config = get_config()
95
+ bot_token, chat_id = get_telegram_bot_details(config, preset_name)
108
96
 
109
- # Prepare the request
97
+ # Prepare and send the request
110
98
  url = f"https://api.telegram.org/bot{bot_token}/sendMessage"
111
99
  payload = {"chat_id": chat_id, "text": message}
112
-
113
- # Send the message
114
100
  response = requests.post(url, json=payload)
115
101
  response.raise_for_status()
116
102
 
103
+
117
104
  def title(text: str, font: str = "slant", typing_speed: float = 0.005) -> None:
118
105
  """
119
106
  Print text as ASCII art with a typewriter effect using the specified font (default: slant),
@@ -254,7 +241,7 @@ def sub_heading(text: str, typing_speed: float = 0.002) -> None:
254
241
  # Format sub-heading
255
242
  prefix = f"[{_CURRENT_HEADING_NUMBER}.{current_sub}] "
256
243
  max_text_length = 50 - len(prefix)
257
- formatted_text = text.lower()[:max_text_length]
244
+ formatted_text = text[:max_text_length] # Removed .lower()
258
245
  sub_heading = f"{prefix}{formatted_text}"
259
246
 
260
247
  # Get timestamp
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rgwfuncs
3
- Version: 0.0.107
3
+ Version: 0.0.109
4
4
  Summary: A functional programming paradigm for mathematical modelling and data science
5
5
  Home-page: https://github.com/ryangerardwilson/rgwfuncs
6
6
  Author: Ryan Gerard Wilson
@@ -0,0 +1,11 @@
1
+ rgwfuncs/__init__.py,sha256=XIbMHeEimBLNcX2PK7uQGquG-eAYXsetVEJrlBZIH5U,1295
2
+ rgwfuncs/df_lib.py,sha256=3foomRHlunCpf_accTcqfdgwDmSPIVkVCnlWJ4ag4XQ,76947
3
+ rgwfuncs/docs_lib.py,sha256=i63NzX-V8cGhikYdtkRGAEe2VcuwpXxDUyTRa9xI7l8,1972
4
+ rgwfuncs/interactive_shell_lib.py,sha256=YeJBW9YgH5Nv77ONdOyIKFgtf0ItXStdlKGN9GGf8bU,4228
5
+ rgwfuncs/str_lib.py,sha256=rfzRd7bOc0KQ7UxUN-J6yxY23pHEUHqerVR1u-TyIAY,10690
6
+ rgwfuncs-0.0.109.dist-info/licenses/LICENSE,sha256=jLvt20gcUZYB8UOvyBvyKQ1qhYYhD__qP7ZDx2lPFkU,1062
7
+ rgwfuncs-0.0.109.dist-info/METADATA,sha256=8x4cokNH7a30Xk_Bym-UHPLPNXopZ9NmbBEtm9_sWKE,42972
8
+ rgwfuncs-0.0.109.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
9
+ rgwfuncs-0.0.109.dist-info/entry_points.txt,sha256=j-c5IOPIQ0252EaOV6j6STio56sbXl2C4ym_fQ0lXx0,43
10
+ rgwfuncs-0.0.109.dist-info/top_level.txt,sha256=aGuVIzWsKiV1f2gCb6mynx0zx5ma0B1EwPGFKVEMTi4,9
11
+ rgwfuncs-0.0.109.dist-info/RECORD,,
@@ -1,11 +0,0 @@
1
- rgwfuncs/__init__.py,sha256=XIbMHeEimBLNcX2PK7uQGquG-eAYXsetVEJrlBZIH5U,1295
2
- rgwfuncs/df_lib.py,sha256=3foomRHlunCpf_accTcqfdgwDmSPIVkVCnlWJ4ag4XQ,76947
3
- rgwfuncs/docs_lib.py,sha256=i63NzX-V8cGhikYdtkRGAEe2VcuwpXxDUyTRa9xI7l8,1972
4
- rgwfuncs/interactive_shell_lib.py,sha256=YeJBW9YgH5Nv77ONdOyIKFgtf0ItXStdlKGN9GGf8bU,4228
5
- rgwfuncs/str_lib.py,sha256=xjdD-NJcb5YPKIDnJFItXIUXlTmjX1Kg3lci8eqvfQs,11391
6
- rgwfuncs-0.0.107.dist-info/licenses/LICENSE,sha256=jLvt20gcUZYB8UOvyBvyKQ1qhYYhD__qP7ZDx2lPFkU,1062
7
- rgwfuncs-0.0.107.dist-info/METADATA,sha256=1yKapK7_SsGrpRCAqxnDap4zpoUQ9cz8DbUTLMcCx7g,42972
8
- rgwfuncs-0.0.107.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
9
- rgwfuncs-0.0.107.dist-info/entry_points.txt,sha256=j-c5IOPIQ0252EaOV6j6STio56sbXl2C4ym_fQ0lXx0,43
10
- rgwfuncs-0.0.107.dist-info/top_level.txt,sha256=aGuVIzWsKiV1f2gCb6mynx0zx5ma0B1EwPGFKVEMTi4,9
11
- rgwfuncs-0.0.107.dist-info/RECORD,,