lionagi 0.0.306__py3-none-any.whl → 0.0.308__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.
- 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):
|