lionagi 0.0.306__py3-none-any.whl → 0.0.308__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- lionagi/__init__.py +2 -5
- lionagi/core/__init__.py +7 -5
- lionagi/core/agent/__init__.py +3 -0
- lionagi/core/agent/base_agent.py +10 -12
- lionagi/core/branch/__init__.py +4 -0
- lionagi/core/branch/base_branch.py +81 -81
- lionagi/core/branch/branch.py +16 -28
- lionagi/core/branch/branch_flow_mixin.py +3 -7
- lionagi/core/branch/executable_branch.py +86 -56
- lionagi/core/branch/util.py +77 -162
- lionagi/core/{flow/direct → direct}/__init__.py +1 -1
- lionagi/core/{flow/direct/predict.py → direct/parallel_predict.py} +39 -17
- lionagi/core/direct/parallel_react.py +0 -0
- lionagi/core/direct/parallel_score.py +0 -0
- lionagi/core/direct/parallel_select.py +0 -0
- lionagi/core/direct/parallel_sentiment.py +0 -0
- lionagi/core/direct/predict.py +174 -0
- lionagi/core/{flow/direct → direct}/react.py +2 -2
- lionagi/core/{flow/direct → direct}/score.py +28 -23
- lionagi/core/{flow/direct → direct}/select.py +48 -45
- lionagi/core/direct/utils.py +83 -0
- lionagi/core/flow/monoflow/ReAct.py +6 -5
- lionagi/core/flow/monoflow/__init__.py +9 -0
- lionagi/core/flow/monoflow/chat.py +10 -10
- lionagi/core/flow/monoflow/chat_mixin.py +11 -10
- lionagi/core/flow/monoflow/followup.py +6 -5
- lionagi/core/flow/polyflow/__init__.py +1 -0
- lionagi/core/flow/polyflow/chat.py +15 -3
- lionagi/core/mail/mail_manager.py +18 -19
- lionagi/core/mail/schema.py +5 -4
- lionagi/core/messages/schema.py +18 -20
- lionagi/core/prompt/__init__.py +0 -0
- lionagi/core/prompt/prompt_template.py +0 -0
- lionagi/core/schema/__init__.py +2 -2
- lionagi/core/schema/action_node.py +11 -3
- lionagi/core/schema/base_mixin.py +56 -59
- lionagi/core/schema/base_node.py +34 -37
- lionagi/core/schema/condition.py +24 -0
- lionagi/core/schema/data_logger.py +96 -99
- lionagi/core/schema/data_node.py +19 -19
- lionagi/core/schema/prompt_template.py +0 -0
- lionagi/core/schema/structure.py +171 -169
- lionagi/core/session/__init__.py +1 -3
- lionagi/core/session/session.py +196 -214
- lionagi/core/tool/tool_manager.py +95 -103
- lionagi/integrations/__init__.py +1 -3
- lionagi/integrations/bridge/langchain_/documents.py +17 -18
- lionagi/integrations/bridge/langchain_/langchain_bridge.py +14 -14
- lionagi/integrations/bridge/llamaindex_/llama_index_bridge.py +22 -22
- lionagi/integrations/bridge/llamaindex_/node_parser.py +12 -12
- lionagi/integrations/bridge/llamaindex_/reader.py +11 -11
- lionagi/integrations/bridge/llamaindex_/textnode.py +7 -7
- lionagi/integrations/config/openrouter_configs.py +0 -1
- lionagi/integrations/provider/oai.py +26 -26
- lionagi/integrations/provider/services.py +38 -38
- lionagi/libs/__init__.py +34 -1
- lionagi/libs/ln_api.py +211 -221
- lionagi/libs/ln_async.py +53 -60
- lionagi/libs/ln_convert.py +118 -120
- lionagi/libs/ln_dataframe.py +32 -33
- lionagi/libs/ln_func_call.py +334 -342
- lionagi/libs/ln_nested.py +99 -107
- lionagi/libs/ln_parse.py +161 -165
- lionagi/libs/sys_util.py +52 -52
- lionagi/tests/test_core/test_session.py +254 -266
- lionagi/tests/test_core/test_session_base_util.py +299 -300
- lionagi/tests/test_core/test_tool_manager.py +70 -74
- lionagi/tests/test_libs/test_nested.py +2 -7
- lionagi/tests/test_libs/test_parse.py +2 -2
- lionagi/version.py +1 -1
- {lionagi-0.0.306.dist-info → lionagi-0.0.308.dist-info}/METADATA +4 -2
- lionagi-0.0.308.dist-info/RECORD +115 -0
- lionagi/core/flow/direct/utils.py +0 -43
- lionagi-0.0.306.dist-info/RECORD +0 -106
- /lionagi/core/{flow/direct → direct}/sentiment.py +0 -0
- {lionagi-0.0.306.dist-info → lionagi-0.0.308.dist-info}/LICENSE +0 -0
- {lionagi-0.0.306.dist-info → lionagi-0.0.308.dist-info}/WHEEL +0 -0
- {lionagi-0.0.306.dist-info → lionagi-0.0.308.dist-info}/top_level.txt +0 -0
lionagi/libs/ln_async.py
CHANGED
@@ -11,6 +11,7 @@ import aiohttp
|
|
11
11
|
|
12
12
|
class AsyncUtil:
|
13
13
|
|
14
|
+
@staticmethod
|
14
15
|
async def _call_handler(
|
15
16
|
func: Callable, *args, error_map: dict[type, Callable] = None, **kwargs
|
16
17
|
) -> Any:
|
@@ -19,43 +20,42 @@ class AsyncUtil:
|
|
19
20
|
functions.
|
20
21
|
|
21
22
|
Args:
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
23
|
+
func (Callable):
|
24
|
+
The function to call.
|
25
|
+
*args:
|
26
|
+
Positional arguments to pass to the function.
|
27
|
+
error_map (Dict[type, Callable], optional):
|
28
|
+
A dictionary mapping error types to handler functions.
|
29
|
+
**kwargs:
|
30
|
+
Keyword arguments to pass to the function.
|
30
31
|
|
31
32
|
Returns:
|
32
|
-
|
33
|
+
Any: The result of the function call.
|
33
34
|
|
34
35
|
Raises:
|
35
|
-
|
36
|
+
Exception: Propagates any exceptions not handled by the error_map.
|
36
37
|
|
37
38
|
examples:
|
38
|
-
|
39
|
-
|
40
|
-
|
39
|
+
>>> async def async_add(x, y): return x + y
|
40
|
+
>>> asyncio.run(_call_handler(async_add, 1, 2))
|
41
|
+
3
|
41
42
|
"""
|
42
43
|
try:
|
43
|
-
if AsyncUtil.is_coroutine_func(func):
|
44
|
-
|
45
|
-
try:
|
46
|
-
loop = asyncio.get_running_loop()
|
47
|
-
except RuntimeError: # No running event loop
|
48
|
-
loop = asyncio.new_event_loop()
|
49
|
-
result = loop.run_until_complete(func(*args, **kwargs))
|
44
|
+
if not AsyncUtil.is_coroutine_func(func):
|
45
|
+
return func(*args, **kwargs)
|
50
46
|
|
51
|
-
|
52
|
-
|
47
|
+
# Checking for a running event loop
|
48
|
+
try:
|
49
|
+
loop = asyncio.get_running_loop()
|
50
|
+
except RuntimeError: # No running event loop
|
51
|
+
loop = asyncio.new_event_loop()
|
52
|
+
result = loop.run_until_complete(func(*args, **kwargs))
|
53
53
|
|
54
|
-
|
55
|
-
|
54
|
+
loop.close()
|
55
|
+
return result
|
56
56
|
|
57
|
-
|
58
|
-
return func(*args, **kwargs)
|
57
|
+
if loop.is_running():
|
58
|
+
return await func(*args, **kwargs)
|
59
59
|
|
60
60
|
except Exception as e:
|
61
61
|
if error_map:
|
@@ -71,10 +71,10 @@ class AsyncUtil:
|
|
71
71
|
Checks whether a function is an asyncio coroutine function.
|
72
72
|
|
73
73
|
Args:
|
74
|
-
|
74
|
+
func: The function to check.
|
75
75
|
|
76
76
|
Returns:
|
77
|
-
|
77
|
+
True if the function is a coroutine function, False otherwise.
|
78
78
|
"""
|
79
79
|
return asyncio.iscoroutinefunction(func)
|
80
80
|
|
@@ -87,18 +87,17 @@ class AsyncUtil:
|
|
87
87
|
handle errors based on a given error mapping.
|
88
88
|
|
89
89
|
Args:
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
90
|
+
error (Exception):
|
91
|
+
The error to handle.
|
92
|
+
error_map (Mapping[type, Callable]):
|
93
|
+
A dictionary mapping error types to handler functions.
|
94
94
|
|
95
95
|
examples:
|
96
|
-
|
97
|
-
|
98
|
-
|
96
|
+
>>> def handle_value_error(e): print("ValueError occurred")
|
97
|
+
>>> custom_error_handler(ValueError(), {ValueError: handle_value_error})
|
98
|
+
ValueError occurred
|
99
99
|
"""
|
100
|
-
handler
|
101
|
-
if handler:
|
100
|
+
if handler := error_map.get(type(error)):
|
102
101
|
handler(error)
|
103
102
|
else:
|
104
103
|
logging.error(f"Unhandled error: {error}")
|
@@ -111,30 +110,28 @@ class AsyncUtil:
|
|
111
110
|
Executes a function, automatically handling synchronous and asynchronous functions.
|
112
111
|
|
113
112
|
Args:
|
114
|
-
|
115
|
-
|
116
|
-
|
113
|
+
func: The function to execute.
|
114
|
+
*args: Positional arguments for the function.
|
115
|
+
**kwargs: Keyword arguments for the function.
|
117
116
|
|
118
117
|
Returns:
|
119
|
-
|
118
|
+
The result of the function execution.
|
120
119
|
"""
|
121
120
|
|
122
121
|
try:
|
123
|
-
if AsyncUtil.is_coroutine_func(func):
|
124
|
-
|
125
|
-
try:
|
126
|
-
loop = asyncio.get_event_loop()
|
127
|
-
|
128
|
-
if loop.is_running():
|
129
|
-
return await func(*args, **kwargs)
|
130
|
-
else:
|
131
|
-
return await asyncio.run(func(*args, **kwargs))
|
122
|
+
if not AsyncUtil.is_coroutine_func(func):
|
123
|
+
return func(*args, **kwargs)
|
132
124
|
|
133
|
-
|
134
|
-
|
125
|
+
try:
|
126
|
+
loop = asyncio.get_event_loop()
|
135
127
|
|
136
|
-
|
137
|
-
|
128
|
+
return (
|
129
|
+
await func(*args, **kwargs)
|
130
|
+
if loop.is_running()
|
131
|
+
else await asyncio.run(func(*args, **kwargs))
|
132
|
+
)
|
133
|
+
except RuntimeError:
|
134
|
+
return asyncio.run(func(*args, **kwargs))
|
138
135
|
|
139
136
|
except Exception as e:
|
140
137
|
if error_map:
|
@@ -205,10 +202,6 @@ class AsyncUtil:
|
|
205
202
|
def create_lock(*args, **kwargs):
|
206
203
|
return asyncio.Lock(*args, **kwargs)
|
207
204
|
|
208
|
-
# @classmethod
|
209
|
-
# def HttpClientSession(cls):
|
210
|
-
# return aiohttp.ClientSession
|
205
|
+
# @classmethod # def HttpClientSession(cls): # return aiohttp.ClientSession
|
211
206
|
|
212
|
-
# @classmethod
|
213
|
-
# def HttpClientError(cls):
|
214
|
-
# return aiohttp.ClientError
|
207
|
+
# @classmethod # def HttpClientError(cls): # return aiohttp.ClientError
|
lionagi/libs/ln_convert.py
CHANGED
@@ -23,29 +23,28 @@ def to_list(input_, /, *, flatten: bool = True, dropna: bool = True) -> list[Any
|
|
23
23
|
Specialized implementations may use additional keyword arguments specific to their conversion logic.
|
24
24
|
|
25
25
|
Args:
|
26
|
-
|
27
|
-
|
28
|
-
|
26
|
+
input_ (Any): The input object to convert to a list.
|
27
|
+
flatten (bool): If True, and the input is a nested list, the function will attempt to flatten it.
|
28
|
+
dropna (bool): If True, None values will be removed from the resulting list.
|
29
29
|
|
30
30
|
Returns:
|
31
|
-
|
31
|
+
list[Any]: A list representation of the input, with modifications based on `flatten` and `dropna`.
|
32
32
|
|
33
33
|
Raises:
|
34
|
-
|
34
|
+
ValueError: If the input type is unsupported or cannot be converted to a list.
|
35
35
|
|
36
36
|
Note:
|
37
|
-
|
38
|
-
|
39
|
-
|
37
|
+
- This function uses `@singledispatch` to handle different input types via overloading.
|
38
|
+
- The default behavior for dictionaries is to wrap them in a list without flattening.
|
39
|
+
- For specific behaviors with lists, tuples, sets, and other types, see the registered implementations.
|
40
40
|
"""
|
41
41
|
try:
|
42
|
-
if isinstance(input_, Iterable)
|
42
|
+
if not isinstance(input_, Iterable) or isinstance(
|
43
43
|
input_, (str, bytes, bytearray, dict)
|
44
44
|
):
|
45
|
-
iterable_list = list(input_)
|
46
|
-
return _flatten_list(iterable_list, dropna) if flatten else iterable_list
|
47
|
-
else:
|
48
45
|
return [input_]
|
46
|
+
iterable_list = list(input_)
|
47
|
+
return _flatten_list(iterable_list, dropna) if flatten else iterable_list
|
49
48
|
except Exception as e:
|
50
49
|
raise ValueError(f"Could not convert {type(input_)} object to list: {e}") from e
|
51
50
|
|
@@ -76,19 +75,19 @@ def to_dict(input_, /, *args, **kwargs) -> dict[Any, Any]:
|
|
76
75
|
and Pydantic's BaseModel, utilizing the single dispatch mechanism for type-specific conversions.
|
77
76
|
|
78
77
|
Args:
|
79
|
-
|
80
|
-
|
81
|
-
|
78
|
+
input_ (Any): The input object to convert to a dictionary.
|
79
|
+
*args: Variable length argument list for additional options in type-specific handlers.
|
80
|
+
**kwargs: Arbitrary keyword arguments for additional options in type-specific handlers.
|
82
81
|
|
83
82
|
Returns:
|
84
|
-
|
83
|
+
dict[Any, Any]: A dictionary representation of the input object.
|
85
84
|
|
86
85
|
Raises:
|
87
|
-
|
86
|
+
ValueError: If the input type is not supported or cannot be converted to a dictionary.
|
88
87
|
|
89
88
|
Note:
|
90
|
-
|
91
|
-
|
89
|
+
- For specific behaviors with dict, str, pandas.Series, pandas.DataFrame, and BaseModel,
|
90
|
+
see the registered implementations.
|
92
91
|
"""
|
93
92
|
try:
|
94
93
|
return dict(input_, *args, **kwargs)
|
@@ -104,10 +103,10 @@ def _(input_) -> dict[Any, Any]:
|
|
104
103
|
Handles dictionary inputs directly, returning the input without modification.
|
105
104
|
|
106
105
|
Args:
|
107
|
-
|
106
|
+
input_ (dict[Any, Any]): The dictionary to be returned.
|
108
107
|
|
109
108
|
Returns:
|
110
|
-
|
109
|
+
dict[Any, Any]: The input dictionary, unchanged.
|
111
110
|
"""
|
112
111
|
return input_
|
113
112
|
|
@@ -118,15 +117,15 @@ def _(input_, /, *args, **kwargs) -> dict[Any, Any]:
|
|
118
117
|
Converts a JSON-formatted string to a dictionary.
|
119
118
|
|
120
119
|
Args:
|
121
|
-
|
122
|
-
|
123
|
-
|
120
|
+
input_ (str): The JSON string to convert.
|
121
|
+
*args: Variable length argument list for json.loads().
|
122
|
+
**kwargs: Arbitrary keyword arguments for json.loads().
|
124
123
|
|
125
124
|
Returns:
|
126
|
-
|
125
|
+
dict[Any, Any]: The dictionary representation of the JSON string.
|
127
126
|
|
128
127
|
Raises:
|
129
|
-
|
128
|
+
ValueError: If the string cannot be decoded into a dictionary.
|
130
129
|
"""
|
131
130
|
try:
|
132
131
|
return json.loads(input_, *args, **kwargs)
|
@@ -140,12 +139,12 @@ def _(input_, /, *args, **kwargs) -> dict[Any, Any]:
|
|
140
139
|
Converts a pandas Series to a dictionary.
|
141
140
|
|
142
141
|
Args:
|
143
|
-
|
144
|
-
|
145
|
-
|
142
|
+
input_ (pd.Series): The pandas Series to convert.
|
143
|
+
*args: Variable length argument list for Series.to_dict().
|
144
|
+
**kwargs: Arbitrary keyword arguments for Series.to_dict().
|
146
145
|
|
147
146
|
Returns:
|
148
|
-
|
147
|
+
dict[Any, Any]: The dictionary representation of the pandas Series.
|
149
148
|
"""
|
150
149
|
return input_.to_dict(*args, **kwargs)
|
151
150
|
|
@@ -158,15 +157,15 @@ def _(
|
|
158
157
|
Converts a pandas DataFrame to a dictionary or a list of dictionaries, based on the `orient` and `as_list` parameters.
|
159
158
|
|
160
159
|
Args:
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
160
|
+
input_ (pd.DataFrame): The pandas DataFrame to convert.
|
161
|
+
*args: Variable length argument list for DataFrame.to_dict() or DataFrame.iterrows().
|
162
|
+
orient (str): The orientation of the data. Default is 'list'.
|
163
|
+
as_list (bool): If True, returns a list of dictionaries, one for each row. Default is False.
|
164
|
+
**kwargs: Arbitrary keyword arguments for DataFrame.to_dict().
|
166
165
|
|
167
166
|
Returns:
|
168
|
-
|
169
|
-
|
167
|
+
dict[Any, Any] | list[dict[Any, Any]]: Depending on `as_list`, either a dictionary representation
|
168
|
+
of the DataFrame or a list of dictionaries, one for each row.
|
170
169
|
"""
|
171
170
|
if as_list:
|
172
171
|
return [row.to_dict(*args, **kwargs) for _, row in input_.iterrows()]
|
@@ -179,12 +178,12 @@ def _(input_, /, *args, **kwargs) -> dict[Any, Any]:
|
|
179
178
|
Converts a Pydantic BaseModel instance to a dictionary.
|
180
179
|
|
181
180
|
Args:
|
182
|
-
|
183
|
-
|
184
|
-
|
181
|
+
input_ (BaseModel): The Pydantic BaseModel instance to convert.
|
182
|
+
*args: Variable length argument list for the model's dict() method.
|
183
|
+
**kwargs: Arbitrary keyword arguments for the model's dict() method.
|
185
184
|
|
186
185
|
Returns:
|
187
|
-
|
186
|
+
dict[Any, Any]: The dictionary representation of the BaseModel instance.
|
188
187
|
"""
|
189
188
|
return input_.model_dump(*args, **kwargs)
|
190
189
|
|
@@ -198,17 +197,17 @@ def to_str(input_) -> str:
|
|
198
197
|
providing type-specific conversions to string format.
|
199
198
|
|
200
199
|
Args:
|
201
|
-
|
202
|
-
|
203
|
-
|
200
|
+
input_ (Any): The input object to convert to a string.
|
201
|
+
*args: Variable length argument list for additional options in type-specific handlers.
|
202
|
+
**kwargs: Arbitrary keyword arguments for additional options in type-specific handlers.
|
204
203
|
|
205
204
|
Returns:
|
206
|
-
|
205
|
+
str: A string representation of the input object.
|
207
206
|
|
208
207
|
Note:
|
209
|
-
|
210
|
-
|
211
|
-
|
208
|
+
- The base implementation simply uses the str() function for conversion.
|
209
|
+
- For detailed behaviors with dict, str, list, pandas.Series, and pandas.DataFrame,
|
210
|
+
refer to the registered implementations.
|
212
211
|
"""
|
213
212
|
return str(input_)
|
214
213
|
|
@@ -219,12 +218,12 @@ def _(input_, /, *args, **kwargs) -> str:
|
|
219
218
|
Converts a dictionary to a JSON-formatted string.
|
220
219
|
|
221
220
|
Args:
|
222
|
-
|
223
|
-
|
224
|
-
|
221
|
+
input_ (dict): The dictionary to convert.
|
222
|
+
*args: Variable length argument list for json.dumps().
|
223
|
+
**kwargs: Arbitrary keyword arguments for json.dumps().
|
225
224
|
|
226
225
|
Returns:
|
227
|
-
|
226
|
+
str: The JSON string representation of the dictionary.
|
228
227
|
"""
|
229
228
|
return json.dumps(input_, *args, **kwargs)
|
230
229
|
|
@@ -235,12 +234,12 @@ def _(input_) -> str:
|
|
235
234
|
Returns the input string unchanged.
|
236
235
|
|
237
236
|
Args:
|
238
|
-
|
239
|
-
|
240
|
-
|
237
|
+
input_ (str): The input string.
|
238
|
+
*args: Ignored.
|
239
|
+
**kwargs: Ignored.
|
241
240
|
|
242
241
|
Returns:
|
243
|
-
|
242
|
+
str: The input string, unchanged.
|
244
243
|
"""
|
245
244
|
return input_
|
246
245
|
|
@@ -252,15 +251,15 @@ def _(input_, /, *args, as_list: bool = False, **kwargs) -> str | list[str]:
|
|
252
251
|
of the list itself or join the string representations of its elements.
|
253
252
|
|
254
253
|
Args:
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
254
|
+
input_ (list): The list to convert.
|
255
|
+
*args: Variable length argument list for additional options in element conversion.
|
256
|
+
as_list (bool): If True, returns the string representation of the list. If False,
|
257
|
+
returns the elements joined by a comma. Default is False.
|
258
|
+
**kwargs: Arbitrary keyword arguments for additional options in element conversion.
|
260
259
|
|
261
260
|
Returns:
|
262
|
-
|
263
|
-
|
261
|
+
str: Depending on `as_list`, either the string representation of the list or a string
|
262
|
+
of the elements joined by a comma.
|
264
263
|
"""
|
265
264
|
lst_ = [to_str(item, *args, **kwargs) for item in input_]
|
266
265
|
return lst_ if as_list else ", ".join(lst_)
|
@@ -272,12 +271,12 @@ def _(input_, /, *args, **kwargs) -> str:
|
|
272
271
|
Converts a pandas Series to a JSON-formatted string.
|
273
272
|
|
274
273
|
Args:
|
275
|
-
|
276
|
-
|
277
|
-
|
274
|
+
input_ (pd.Series): The pandas Series to convert.
|
275
|
+
*args: Variable length argument list for Series.to_json().
|
276
|
+
**kwargs: Arbitrary keyword arguments for Series.to_json().
|
278
277
|
|
279
278
|
Returns:
|
280
|
-
|
279
|
+
str: The JSON string representation of the pandas Series.
|
281
280
|
"""
|
282
281
|
return input_.to_json(*args, **kwargs)
|
283
282
|
|
@@ -289,15 +288,15 @@ def _(input_, /, *args, as_list: bool = False, **kwargs) -> str | list[str]:
|
|
289
288
|
first if `as_list` is True, then to a string representation of that list.
|
290
289
|
|
291
290
|
Args:
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
291
|
+
input_ (pd.DataFrame): The pandas DataFrame to convert.
|
292
|
+
*args: Variable length argument list for additional options in conversion.
|
293
|
+
as_list (bool): If True, converts the DataFrame to a list of dictionaries before converting
|
294
|
+
to a string. Default is False.
|
295
|
+
**kwargs: Arbitrary keyword arguments for DataFrame.to_json() or to_dict().
|
297
296
|
|
298
297
|
Returns:
|
299
|
-
|
300
|
-
|
298
|
+
str: Depending on `as_list`, either a JSON string representation of the DataFrame or a string
|
299
|
+
representation of a list of dictionaries derived from the DataFrame.
|
301
300
|
"""
|
302
301
|
if as_list:
|
303
302
|
return to_dict(input_, as_list=True, *args, **kwargs)
|
@@ -324,20 +323,20 @@ def to_df(
|
|
324
323
|
The base implementation attempts to directly convert the input to a DataFrame, applying dropna and reset_index as specified.
|
325
324
|
|
326
325
|
Args:
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
326
|
+
input_ (Any): The input data to convert into a DataFrame. Accepts a wide range of types thanks to overloads.
|
327
|
+
how (str): Specifies how missing values are dropped. Passed directly to DataFrame.dropna().
|
328
|
+
drop_kwargs (dict[str, Any] | None): Additional keyword arguments for DataFrame.dropna().
|
329
|
+
reset_index (bool): If True, the DataFrame index will be reset, removing the index labels.
|
330
|
+
**kwargs: Additional keyword arguments passed to the pandas DataFrame constructor.
|
332
331
|
|
333
332
|
Returns:
|
334
|
-
|
333
|
+
pd.DataFrame: A pandas DataFrame constructed from the input data.
|
335
334
|
|
336
335
|
Raises:
|
337
|
-
|
336
|
+
ValueError: If there is an error during the conversion process.
|
338
337
|
|
339
338
|
Note:
|
340
|
-
|
339
|
+
- This function is overloaded to provide specialized behavior for different input types, enhancing its flexibility.
|
341
340
|
"""
|
342
341
|
|
343
342
|
if drop_kwargs is None:
|
@@ -345,7 +344,7 @@ def to_df(
|
|
345
344
|
|
346
345
|
try:
|
347
346
|
dfs = pd.DataFrame(input_, **kwargs)
|
348
|
-
dfs.dropna(**(drop_kwargs | {"how": how})
|
347
|
+
dfs = dfs.dropna(**(drop_kwargs | {"how": how}))
|
349
348
|
return dfs.reset_index(drop=True) if reset_index else dfs
|
350
349
|
|
351
350
|
except Exception as e:
|
@@ -367,7 +366,7 @@ def _(
|
|
367
366
|
drop_kwargs = {}
|
368
367
|
try:
|
369
368
|
dfs = pd.DataFrame(input_, **kwargs)
|
370
|
-
dfs.dropna(**(drop_kwargs | {"how": how})
|
369
|
+
dfs = dfs.dropna(**(drop_kwargs | {"how": how}))
|
371
370
|
return dfs.reset_index(drop=True) if reset_index else dfs
|
372
371
|
except Exception as e:
|
373
372
|
raise ValueError(f"Error converting input_ to DataFrame: {e}") from e
|
@@ -387,7 +386,9 @@ def _(
|
|
387
386
|
dfs = pd.concat([dfs, i], **kwargs)
|
388
387
|
|
389
388
|
except Exception as e2:
|
390
|
-
raise ValueError(
|
389
|
+
raise ValueError(
|
390
|
+
f"Error converting input_ to DataFrame: {e1}, {e2}"
|
391
|
+
) from e2
|
391
392
|
|
392
393
|
dfs.dropna(**(drop_kwargs | {"how": how}), inplace=True)
|
393
394
|
return dfs.reset_index(drop=True) if reset_index else dfs
|
@@ -406,17 +407,17 @@ def to_num(
|
|
406
407
|
Converts the input to a numeric value of specified type, with optional bounds and precision.
|
407
408
|
|
408
409
|
Args:
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
410
|
+
input_ (Any): The input value to convert. Can be of any type that `to_str` can handle.
|
411
|
+
upper_bound (float | None): The upper bound for the numeric value. If specified, values above this bound will raise an error.
|
412
|
+
lower_bound (float | None): The lower bound for the numeric value. If specified, values below this bound will raise an error.
|
413
|
+
num_type (Type[int | float]): The numeric type to convert to. Can be `int` or `float`.
|
414
|
+
precision (int | None): The number of decimal places for the result. Applies only to `float` type.
|
414
415
|
|
415
416
|
Returns:
|
416
|
-
|
417
|
+
int | float: The converted numeric value, adhering to specified type and precision.
|
417
418
|
|
418
419
|
Raises:
|
419
|
-
|
420
|
+
ValueError: If the input cannot be converted to a number, or if it violates the specified bounds.
|
420
421
|
"""
|
421
422
|
str_ = to_str(input_)
|
422
423
|
return _str_to_num(str_, upper_bound, lower_bound, num_type, precision)
|
@@ -427,10 +428,10 @@ def to_readable_dict(input_: Any | list[Any]) -> str | list[Any]:
|
|
427
428
|
Converts a given input to a readable dictionary format, either as a string or a list of dictionaries.
|
428
429
|
|
429
430
|
Args:
|
430
|
-
|
431
|
+
input_ (Any | list[Any]): The input to convert to a readable dictionary format.
|
431
432
|
|
432
433
|
Returns:
|
433
|
-
|
434
|
+
str | list[str]: The readable dictionary format of the input.
|
434
435
|
"""
|
435
436
|
|
436
437
|
try:
|
@@ -445,11 +446,11 @@ def is_same_dtype(input_: list | dict, dtype: Type | None = None) -> bool:
|
|
445
446
|
Checks if all elements in a list or dictionary values are of the same data type.
|
446
447
|
|
447
448
|
Args:
|
448
|
-
|
449
|
-
|
449
|
+
input_ (list | dict): The input list or dictionary to check.
|
450
|
+
dtype (Type | None): The data type to check against. If None, uses the type of the first element.
|
450
451
|
|
451
452
|
Returns:
|
452
|
-
|
453
|
+
bool: True if all elements are of the same type (or if the input is empty), False otherwise.
|
453
454
|
"""
|
454
455
|
if not input_:
|
455
456
|
return True
|
@@ -486,13 +487,13 @@ def strip_lower(input_: Any) -> str:
|
|
486
487
|
Converts the input to a lowercase string with leading and trailing whitespace removed.
|
487
488
|
|
488
489
|
Args:
|
489
|
-
|
490
|
+
input_ (Any): The input value to convert and process.
|
490
491
|
|
491
492
|
Returns:
|
492
|
-
|
493
|
+
str: The processed string.
|
493
494
|
|
494
495
|
Raises:
|
495
|
-
|
496
|
+
ValueError: If the input cannot be converted to a string.
|
496
497
|
"""
|
497
498
|
try:
|
498
499
|
return str(input_).strip().lower()
|
@@ -517,11 +518,11 @@ def is_structure_homogeneous(
|
|
517
518
|
either list | dict, or None).
|
518
519
|
|
519
520
|
examples:
|
520
|
-
|
521
|
-
|
521
|
+
>>> _is_structure_homogeneous({'a': {'b': 1}, 'c': {'d': 2}})
|
522
|
+
True
|
522
523
|
|
523
|
-
|
524
|
-
|
524
|
+
>>> _is_structure_homogeneous({'a': {'b': 1}, 'c': [1, 2]})
|
525
|
+
False
|
525
526
|
"""
|
526
527
|
|
527
528
|
# noinspection PyShadowingNames
|
@@ -550,10 +551,7 @@ def is_structure_homogeneous(
|
|
550
551
|
return True, structure_type
|
551
552
|
|
552
553
|
is_, structure_type = _check_structure(structure)
|
553
|
-
if return_structure_type
|
554
|
-
return is_, structure_type
|
555
|
-
else:
|
556
|
-
return is_
|
554
|
+
return (is_, structure_type) if return_structure_type else is_
|
557
555
|
|
558
556
|
|
559
557
|
def is_homogeneous(iterables: list[Any] | dict[Any, Any], type_check: type) -> bool:
|
@@ -614,17 +612,17 @@ def _flatten_list(lst_: list[Any], dropna: bool = True) -> list[Any]:
|
|
614
612
|
flatten a nested list, optionally removing None values.
|
615
613
|
|
616
614
|
Args:
|
617
|
-
|
618
|
-
|
615
|
+
lst_ (list[Any]): A nested list to flatten.
|
616
|
+
dropna (bool): If True, None values are removed. default is True.
|
619
617
|
|
620
618
|
Returns:
|
621
|
-
|
619
|
+
list[Any]: A flattened list.
|
622
620
|
|
623
621
|
examples:
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
|
622
|
+
>>> flatten_list([[1, 2], [3, None]], dropna=True)
|
623
|
+
[1, 2, 3]
|
624
|
+
>>> flatten_list([[1, [2, None]], 3], dropna=False)
|
625
|
+
[1, 2, None, 3]
|
628
626
|
"""
|
629
627
|
flattened_list = list(_flatten_list_generator(lst_, dropna))
|
630
628
|
return list(_dropna_iterator(flattened_list)) if dropna else flattened_list
|
@@ -637,15 +635,15 @@ def _flatten_list_generator(
|
|
637
635
|
Generator for flattening a nested list.
|
638
636
|
|
639
637
|
Args:
|
640
|
-
|
641
|
-
|
638
|
+
lst_ (list[Any]): A nested list to flatten.
|
639
|
+
dropna (bool): If True, None values are omitted. Default is True.
|
642
640
|
|
643
641
|
Yields:
|
644
|
-
|
642
|
+
Generator[Any, None, None]: A generator yielding flattened elements.
|
645
643
|
|
646
644
|
Examples:
|
647
|
-
|
648
|
-
|
645
|
+
>>> list(_flatten_list_generator([[1, [2, None]], 3], dropna=False))
|
646
|
+
[1, 2, None, 3]
|
649
647
|
"""
|
650
648
|
for i in lst_:
|
651
649
|
if isinstance(i, list):
|