praisonaiagents 0.0.22__py3-none-any.whl → 0.0.24__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,278 @@
1
+ """Tools for performing calculations.
2
+
3
+ Usage:
4
+ from praisonaiagents.tools import calculator_tools
5
+ result = calculator_tools.evaluate("2 + 2 * 3")
6
+
7
+ or
8
+ from praisonaiagents.tools import evaluate, solve_equation, convert_units
9
+ result = evaluate("2 + 2 * 3")
10
+ """
11
+
12
+ import logging
13
+ from typing import List, Dict, Optional, Any
14
+ from importlib import util
15
+ import math
16
+
17
+ class CalculatorTools:
18
+ """Tools for performing calculations."""
19
+
20
+ def __init__(self):
21
+ """Initialize CalculatorTools."""
22
+ self._check_dependencies()
23
+
24
+ def _check_dependencies(self):
25
+ """Check if required packages are installed."""
26
+ missing = []
27
+ for package in ['sympy', 'pint']:
28
+ if util.find_spec(package) is None:
29
+ missing.append(package)
30
+
31
+ if missing:
32
+ raise ImportError(
33
+ f"Required packages not available. Please install: {', '.join(missing)}\n"
34
+ f"Run: pip install {' '.join(missing)}"
35
+ )
36
+
37
+ def evaluate(
38
+ self,
39
+ expression: str,
40
+ variables: Optional[Dict[str, float]] = None,
41
+ precision: int = 10
42
+ ) -> Dict[str, Any]:
43
+ """Evaluate a mathematical expression."""
44
+ try:
45
+ if util.find_spec('sympy') is None:
46
+ error_msg = "sympy package is not available. Please install it using: pip install sympy"
47
+ logging.error(error_msg)
48
+ return {"error": error_msg}
49
+
50
+ # Import sympy only when needed
51
+ import sympy
52
+
53
+ # Replace common mathematical functions
54
+ expression = expression.lower()
55
+ replacements = {
56
+ 'sin(': 'math.sin(',
57
+ 'cos(': 'math.cos(',
58
+ 'tan(': 'math.tan(',
59
+ 'sqrt(': 'math.sqrt(',
60
+ 'log(': 'math.log(',
61
+ 'exp(': 'math.exp(',
62
+ 'pi': str(math.pi),
63
+ 'e': str(math.e)
64
+ }
65
+ for old, new in replacements.items():
66
+ expression = expression.replace(old, new)
67
+
68
+ # Create safe namespace
69
+ safe_dict = {
70
+ 'math': math,
71
+ '__builtins__': None
72
+ }
73
+ if variables:
74
+ safe_dict.update(variables)
75
+
76
+ # Evaluate expression
77
+ result = eval(expression, safe_dict)
78
+
79
+ # Round to specified precision
80
+ if isinstance(result, (int, float)):
81
+ return {"result": round(float(result), precision)}
82
+ return {"error": "Invalid expression"}
83
+ except Exception as e:
84
+ error_msg = f"Error evaluating expression: {str(e)}"
85
+ logging.error(error_msg)
86
+ return {"error": error_msg}
87
+
88
+ def solve_equation(
89
+ self,
90
+ equation: str,
91
+ variable: str = 'x'
92
+ ) -> Dict[str, Any]:
93
+ """Solve a mathematical equation."""
94
+ try:
95
+ if util.find_spec('sympy') is None:
96
+ error_msg = "sympy package is not available. Please install it using: pip install sympy"
97
+ logging.error(error_msg)
98
+ return {"error": error_msg}
99
+
100
+ # Import sympy only when needed
101
+ import sympy
102
+
103
+ # Parse equation
104
+ if '=' in equation:
105
+ left, right = equation.split('=')
106
+ equation = f"({left}) - ({right})"
107
+
108
+ # Convert to SymPy expression
109
+ x = sympy.Symbol(variable)
110
+ expr = sympy.sympify(equation)
111
+
112
+ # Solve equation
113
+ solutions = sympy.solve(expr, x)
114
+
115
+ # Convert complex solutions to real if possible
116
+ real_solutions = []
117
+ for sol in solutions:
118
+ if sol.is_real:
119
+ real_solutions.append(float(sol))
120
+
121
+ return {"solutions": real_solutions} if real_solutions else {"error": "No real solutions found"}
122
+ except Exception as e:
123
+ error_msg = f"Error solving equation: {str(e)}"
124
+ logging.error(error_msg)
125
+ return {"error": error_msg}
126
+
127
+ def convert_units(
128
+ self,
129
+ value: float,
130
+ from_unit: str,
131
+ to_unit: str
132
+ ) -> Dict[str, Any]:
133
+ """Convert between different units."""
134
+ try:
135
+ if util.find_spec('pint') is None:
136
+ error_msg = "pint package is not available. Please install it using: pip install pint"
137
+ logging.error(error_msg)
138
+ return {"error": error_msg}
139
+
140
+ # Import pint only when needed
141
+ import pint
142
+
143
+ # Create quantity with source unit
144
+ ureg = pint.UnitRegistry()
145
+ quantity = value * ureg(from_unit)
146
+
147
+ # Convert to target unit
148
+ result = quantity.to(to_unit)
149
+
150
+ return {"result": float(result.magnitude)}
151
+ except Exception as e:
152
+ error_msg = f"Error converting units: {str(e)}"
153
+ logging.error(error_msg)
154
+ return {"error": error_msg}
155
+
156
+ def calculate_statistics(
157
+ self,
158
+ numbers: List[float]
159
+ ) -> Dict[str, Any]:
160
+ """Calculate basic statistics for a list of numbers."""
161
+ try:
162
+ if not numbers:
163
+ return {"error": "No numbers provided"}
164
+
165
+ n = len(numbers)
166
+ mean = sum(numbers) / n
167
+
168
+ # Calculate variance and std dev
169
+ squared_diff_sum = sum((x - mean) ** 2 for x in numbers)
170
+ variance = squared_diff_sum / (n - 1) if n > 1 else 0
171
+ std_dev = math.sqrt(variance)
172
+
173
+ # Calculate median
174
+ sorted_nums = sorted(numbers)
175
+ if n % 2 == 0:
176
+ median = (sorted_nums[n//2 - 1] + sorted_nums[n//2]) / 2
177
+ else:
178
+ median = sorted_nums[n//2]
179
+
180
+ return {
181
+ "mean": mean,
182
+ "median": median,
183
+ "std_dev": std_dev,
184
+ "variance": variance,
185
+ "min": min(numbers),
186
+ "max": max(numbers),
187
+ "range": max(numbers) - min(numbers),
188
+ "count": n
189
+ }
190
+ except Exception as e:
191
+ error_msg = f"Error calculating statistics: {str(e)}"
192
+ logging.error(error_msg)
193
+ return {"error": error_msg}
194
+
195
+ def calculate_financial(
196
+ self,
197
+ principal: float,
198
+ rate: float,
199
+ time: float,
200
+ frequency: str = 'yearly'
201
+ ) -> Dict[str, Any]:
202
+ """Calculate financial metrics like compound interest."""
203
+ try:
204
+ # Convert rate to decimal
205
+ rate = rate / 100
206
+
207
+ # Get compounding frequency
208
+ freq_map = {
209
+ 'yearly': 1,
210
+ 'semi-annual': 2,
211
+ 'quarterly': 4,
212
+ 'monthly': 12,
213
+ 'daily': 365
214
+ }
215
+ n = freq_map.get(frequency.lower(), 1)
216
+
217
+ # Calculate compound interest
218
+ amount = principal * (1 + rate/n)**(n*time)
219
+ interest = amount - principal
220
+
221
+ # Calculate simple interest
222
+ simple_interest = principal * rate * time
223
+
224
+ return {
225
+ "final_amount": amount,
226
+ "compound_interest": interest,
227
+ "simple_interest": simple_interest,
228
+ "difference": interest - simple_interest
229
+ }
230
+ except Exception as e:
231
+ error_msg = f"Error calculating financial metrics: {str(e)}"
232
+ logging.error(error_msg)
233
+ return {"error": error_msg}
234
+
235
+ # Create instance for direct function access
236
+ _calculator_tools = CalculatorTools()
237
+ evaluate = _calculator_tools.evaluate
238
+ solve_equation = _calculator_tools.solve_equation
239
+ convert_units = _calculator_tools.convert_units
240
+ calculate_statistics = _calculator_tools.calculate_statistics
241
+ calculate_financial = _calculator_tools.calculate_financial
242
+
243
+ if __name__ == "__main__":
244
+ print("\n==================================================")
245
+ print("CalculatorTools Demonstration")
246
+ print("==================================================\n")
247
+
248
+ print("1. Basic Arithmetic")
249
+ print("------------------------------")
250
+ print("2 + 2 =", evaluate("2 + 2")["result"])
251
+ print("5 * 6 =", evaluate("5 * 6")["result"])
252
+ print("10 / 3 =", evaluate("10 / 3")["result"])
253
+ print()
254
+
255
+ print("2. Complex Expressions")
256
+ print("------------------------------")
257
+ print("(2 + 3) * 4 =", evaluate("(2 + 3) * 4")["result"])
258
+ print("2^3 + 4 =", evaluate("2^3 + 4")["result"])
259
+ print("sqrt(16) + 2 =", evaluate("sqrt(16) + 2")["result"])
260
+ print()
261
+
262
+ print("3. Solving Equations")
263
+ print("------------------------------")
264
+ result = solve_equation("x^2 - 5*x + 6 = 0")
265
+ print("x^2 - 5*x + 6 = 0")
266
+ print("Solutions:", result["solutions"])
267
+ print()
268
+
269
+ print("4. Unit Conversions")
270
+ print("------------------------------")
271
+ print("100 meters to kilometers:", convert_units(100, "meters", "kilometers")["result"])
272
+ print("1 hour to minutes:", convert_units(1, "hours", "minutes")["result"])
273
+ print("32 fahrenheit to celsius:", convert_units(32, "fahrenheit", "celsius")["result"])
274
+ print()
275
+
276
+ print("==================================================")
277
+ print("Demonstration Complete")
278
+ print("==================================================")
@@ -0,0 +1,266 @@
1
+ """Tools for working with CSV files.
2
+
3
+ Usage:
4
+ from praisonaiagents.tools import csv_tools
5
+ df = csv_tools.read_csv("data.csv")
6
+
7
+ or
8
+ from praisonaiagents.tools import read_csv, write_csv, merge_csv
9
+ df = read_csv("data.csv")
10
+ """
11
+
12
+ import logging
13
+ from typing import List, Dict, Union, Optional, Any, TYPE_CHECKING
14
+ from importlib import util
15
+ import json
16
+ import csv
17
+ from pathlib import Path
18
+
19
+ if TYPE_CHECKING:
20
+ import pandas as pd
21
+
22
+ class CSVTools:
23
+ """Tools for working with CSV files."""
24
+
25
+ def __init__(self):
26
+ """Initialize CSVTools."""
27
+ pass
28
+
29
+ def _get_pandas(self) -> Optional['pd']:
30
+ """Get pandas module, installing if needed"""
31
+ if util.find_spec('pandas') is None:
32
+ error_msg = "pandas package is not available. Please install it using: pip install pandas"
33
+ logging.error(error_msg)
34
+ return None
35
+ import pandas as pd
36
+ return pd
37
+
38
+ def read_csv(
39
+ self,
40
+ filepath: str,
41
+ encoding: str = 'utf-8',
42
+ delimiter: str = ',',
43
+ header: Union[int, List[int], None] = 0,
44
+ usecols: Optional[List[str]] = None,
45
+ dtype: Optional[Dict[str, str]] = None,
46
+ parse_dates: Optional[List[str]] = None,
47
+ na_values: Optional[List[str]] = None,
48
+ nrows: Optional[int] = None
49
+ ) -> List[Dict[str, Any]]:
50
+ """Read a CSV file with advanced options.
51
+
52
+ Args:
53
+ filepath: Path to CSV file
54
+ encoding: File encoding
55
+ delimiter: Column delimiter
56
+ header: Row number(s) to use as column names
57
+ usecols: Columns to read
58
+ dtype: Dict of column dtypes
59
+ parse_dates: List of columns to parse as dates
60
+ na_values: Additional strings to recognize as NA/NaN
61
+ nrows: Number of rows to read
62
+
63
+ Returns:
64
+ List of row dicts
65
+ """
66
+ try:
67
+ pd = self._get_pandas()
68
+ if pd is None:
69
+ return {"error": "pandas package not available"}
70
+
71
+ df = pd.read_csv(
72
+ filepath,
73
+ encoding=encoding,
74
+ delimiter=delimiter,
75
+ header=header,
76
+ usecols=usecols,
77
+ dtype=dtype,
78
+ parse_dates=parse_dates,
79
+ na_values=na_values,
80
+ nrows=nrows
81
+ )
82
+ return df.to_dict('records')
83
+
84
+ except Exception as e:
85
+ error_msg = f"Error reading CSV file {filepath}: {str(e)}"
86
+ logging.error(error_msg)
87
+ return {"error": error_msg}
88
+
89
+ def write_csv(
90
+ self,
91
+ filepath: str,
92
+ data: List[Dict[str, Any]],
93
+ encoding: str = 'utf-8',
94
+ delimiter: str = ',',
95
+ index: bool = False,
96
+ header: bool = True,
97
+ float_format: Optional[str] = None,
98
+ date_format: Optional[str] = None,
99
+ mode: str = 'w'
100
+ ) -> bool:
101
+ """Write data to a CSV file.
102
+
103
+ Args:
104
+ filepath: Path to CSV file
105
+ data: List of row dicts to write
106
+ encoding: File encoding
107
+ delimiter: Column delimiter
108
+ index: Whether to write row indices
109
+ header: Whether to write column headers
110
+ float_format: Format string for float values
111
+ date_format: Format string for date values
112
+ mode: Write mode ('w' for write, 'a' for append)
113
+
114
+ Returns:
115
+ bool: Success status
116
+ """
117
+ try:
118
+ pd = self._get_pandas()
119
+ if pd is None:
120
+ return False
121
+
122
+ df = pd.DataFrame(data)
123
+ df.to_csv(
124
+ filepath,
125
+ encoding=encoding,
126
+ sep=delimiter,
127
+ index=index,
128
+ header=header,
129
+ float_format=float_format,
130
+ date_format=date_format,
131
+ mode=mode
132
+ )
133
+ return True
134
+
135
+ except Exception as e:
136
+ error_msg = f"Error writing CSV file {filepath}: {str(e)}"
137
+ logging.error(error_msg)
138
+ return False
139
+
140
+ def merge_csv(
141
+ self,
142
+ files: List[str],
143
+ output_file: str,
144
+ how: str = 'inner',
145
+ on: Optional[Union[str, List[str]]] = None,
146
+ suffixes: Optional[tuple] = None
147
+ ) -> bool:
148
+ """Merge multiple CSV files.
149
+
150
+ Args:
151
+ files: List of CSV files to merge
152
+ output_file: Output file path
153
+ how: Merge method ('inner', 'outer', 'left', 'right')
154
+ on: Column(s) to merge on
155
+ suffixes: Suffixes for overlapping columns
156
+
157
+ Returns:
158
+ bool: Success status
159
+ """
160
+ try:
161
+ if len(files) < 2:
162
+ error_msg = "At least two files are required for merging"
163
+ logging.error(error_msg)
164
+ return False
165
+
166
+ pd = self._get_pandas()
167
+ if pd is None:
168
+ return False
169
+
170
+ # Read first file
171
+ result = pd.read_csv(files[0])
172
+
173
+ # Merge with remaining files
174
+ for file in files[1:]:
175
+ df = pd.read_csv(file)
176
+ result = pd.merge(
177
+ result,
178
+ df,
179
+ how=how,
180
+ on=on,
181
+ suffixes=suffixes or ('_1', '_2')
182
+ )
183
+
184
+ # Write merged result
185
+ result.to_csv(output_file, index=False)
186
+ return True
187
+
188
+ except Exception as e:
189
+ error_msg = f"Error merging CSV files: {str(e)}"
190
+ logging.error(error_msg)
191
+ return False
192
+
193
+ # Create instance for direct function access
194
+ _csv_tools = CSVTools()
195
+ read_csv = _csv_tools.read_csv
196
+ write_csv = _csv_tools.write_csv
197
+ merge_csv = _csv_tools.merge_csv
198
+
199
+ if __name__ == "__main__":
200
+ print("\n==================================================")
201
+ print("CSVTools Demonstration")
202
+ print("==================================================\n")
203
+
204
+ # Create a temporary file for testing
205
+ import tempfile
206
+ import os
207
+
208
+ with tempfile.NamedTemporaryFile(suffix='.csv', delete=False) as temp:
209
+ temp_file = temp.name
210
+
211
+ print("1. Writing CSV File")
212
+ print("------------------------------")
213
+ data = [
214
+ {"name": "Alice", "age": 25, "city": "New York"},
215
+ {"name": "Bob", "age": 30, "city": "San Francisco"},
216
+ {"name": "Charlie", "age": 35, "city": "Chicago"}
217
+ ]
218
+ result = write_csv(temp_file, data)
219
+ print(f"Data written successfully: {result}")
220
+ print()
221
+
222
+ print("2. Reading CSV File")
223
+ print("------------------------------")
224
+ read_data = read_csv(temp_file)
225
+ print("Contents of CSV file:")
226
+ for row in read_data:
227
+ print(row)
228
+ print()
229
+
230
+ print("3. Merging CSV Files")
231
+ print("------------------------------")
232
+ # Create a second file for merging
233
+ with tempfile.NamedTemporaryFile(suffix='.csv', delete=False) as temp2:
234
+ temp_file2 = temp2.name
235
+ data2 = [
236
+ {"name": "Alice", "salary": 75000},
237
+ {"name": "Bob", "salary": 85000},
238
+ {"name": "Charlie", "salary": 95000}
239
+ ]
240
+ write_csv(temp_file2, data2)
241
+
242
+ # Merge files
243
+ with tempfile.NamedTemporaryFile(suffix='.csv', delete=False) as temp3:
244
+ temp_file3 = temp3.name
245
+ result = merge_csv(
246
+ [temp_file, temp_file2],
247
+ temp_file3,
248
+ how='inner',
249
+ on='name'
250
+ )
251
+ print(f"Files merged successfully: {result}")
252
+ if result:
253
+ merged_data = read_csv(temp_file3)
254
+ print("\nMerged contents:")
255
+ for row in merged_data:
256
+ print(row)
257
+ print()
258
+
259
+ # Clean up temporary files
260
+ os.unlink(temp_file)
261
+ os.unlink(temp_file2)
262
+ os.unlink(temp_file3)
263
+
264
+ print("==================================================")
265
+ print("Demonstration Complete")
266
+ print("==================================================\n")