lionagi 0.0.312__py3-none-any.whl → 0.2.1__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 +61 -3
- lionagi/core/__init__.py +0 -14
- lionagi/core/_setting/_setting.py +59 -0
- lionagi/core/action/__init__.py +14 -0
- lionagi/core/action/function_calling.py +136 -0
- lionagi/core/action/manual.py +1 -0
- lionagi/core/action/node.py +109 -0
- lionagi/core/action/tool.py +114 -0
- lionagi/core/action/tool_manager.py +356 -0
- lionagi/core/agent/__init__.py +0 -3
- lionagi/core/agent/base_agent.py +45 -36
- lionagi/core/agent/eval/evaluator.py +1 -0
- lionagi/core/agent/eval/vote.py +40 -0
- lionagi/core/agent/learn/learner.py +59 -0
- lionagi/core/agent/plan/unit_template.py +1 -0
- lionagi/core/collections/__init__.py +17 -0
- lionagi/core/collections/_logger.py +319 -0
- lionagi/core/collections/abc/__init__.py +53 -0
- lionagi/core/collections/abc/component.py +615 -0
- lionagi/core/collections/abc/concepts.py +297 -0
- lionagi/core/collections/abc/exceptions.py +150 -0
- lionagi/core/collections/abc/util.py +45 -0
- lionagi/core/collections/exchange.py +161 -0
- lionagi/core/collections/flow.py +426 -0
- lionagi/core/collections/model.py +419 -0
- lionagi/core/collections/pile.py +913 -0
- lionagi/core/collections/progression.py +236 -0
- lionagi/core/collections/util.py +64 -0
- lionagi/core/director/direct.py +314 -0
- lionagi/core/director/director.py +2 -0
- lionagi/core/engine/branch_engine.py +333 -0
- lionagi/core/engine/instruction_map_engine.py +204 -0
- lionagi/core/engine/sandbox_.py +14 -0
- lionagi/core/engine/script_engine.py +99 -0
- lionagi/core/executor/base_executor.py +90 -0
- lionagi/core/executor/graph_executor.py +330 -0
- lionagi/core/executor/neo4j_executor.py +384 -0
- lionagi/core/generic/__init__.py +7 -0
- lionagi/core/generic/edge.py +112 -0
- lionagi/core/generic/edge_condition.py +16 -0
- lionagi/core/generic/graph.py +236 -0
- lionagi/core/generic/hyperedge.py +1 -0
- lionagi/core/generic/node.py +220 -0
- lionagi/core/generic/tree.py +48 -0
- lionagi/core/generic/tree_node.py +79 -0
- lionagi/core/mail/__init__.py +7 -3
- lionagi/core/mail/mail.py +25 -0
- lionagi/core/mail/mail_manager.py +142 -58
- lionagi/core/mail/package.py +45 -0
- lionagi/core/mail/start_mail.py +36 -0
- lionagi/core/message/__init__.py +19 -0
- lionagi/core/message/action_request.py +133 -0
- lionagi/core/message/action_response.py +135 -0
- lionagi/core/message/assistant_response.py +95 -0
- lionagi/core/message/instruction.py +234 -0
- lionagi/core/message/message.py +101 -0
- lionagi/core/message/system.py +86 -0
- lionagi/core/message/util.py +283 -0
- lionagi/core/report/__init__.py +4 -0
- lionagi/core/report/base.py +217 -0
- lionagi/core/report/form.py +231 -0
- lionagi/core/report/report.py +166 -0
- lionagi/core/report/util.py +28 -0
- lionagi/core/rule/__init__.py +0 -0
- lionagi/core/rule/_default.py +16 -0
- lionagi/core/rule/action.py +99 -0
- lionagi/core/rule/base.py +238 -0
- lionagi/core/rule/boolean.py +56 -0
- lionagi/core/rule/choice.py +47 -0
- lionagi/core/rule/mapping.py +96 -0
- lionagi/core/rule/number.py +71 -0
- lionagi/core/rule/rulebook.py +109 -0
- lionagi/core/rule/string.py +52 -0
- lionagi/core/rule/util.py +35 -0
- lionagi/core/session/__init__.py +0 -3
- lionagi/core/session/branch.py +431 -0
- lionagi/core/session/directive_mixin.py +287 -0
- lionagi/core/session/session.py +230 -902
- lionagi/core/structure/__init__.py +1 -0
- lionagi/core/structure/chain.py +1 -0
- lionagi/core/structure/forest.py +1 -0
- lionagi/core/structure/graph.py +1 -0
- lionagi/core/structure/tree.py +1 -0
- lionagi/core/unit/__init__.py +5 -0
- lionagi/core/unit/parallel_unit.py +245 -0
- lionagi/core/unit/template/__init__.py +0 -0
- lionagi/core/unit/template/action.py +81 -0
- lionagi/core/unit/template/base.py +51 -0
- lionagi/core/unit/template/plan.py +84 -0
- lionagi/core/unit/template/predict.py +109 -0
- lionagi/core/unit/template/score.py +124 -0
- lionagi/core/unit/template/select.py +104 -0
- lionagi/core/unit/unit.py +362 -0
- lionagi/core/unit/unit_form.py +305 -0
- lionagi/core/unit/unit_mixin.py +1168 -0
- lionagi/core/unit/util.py +71 -0
- lionagi/core/validator/__init__.py +0 -0
- lionagi/core/validator/validator.py +364 -0
- lionagi/core/work/__init__.py +0 -0
- lionagi/core/work/work.py +76 -0
- lionagi/core/work/work_function.py +101 -0
- lionagi/core/work/work_queue.py +103 -0
- lionagi/core/work/worker.py +258 -0
- lionagi/core/work/worklog.py +120 -0
- lionagi/experimental/__init__.py +0 -0
- lionagi/experimental/compressor/__init__.py +0 -0
- lionagi/experimental/compressor/base.py +46 -0
- lionagi/experimental/compressor/llm_compressor.py +247 -0
- lionagi/experimental/compressor/llm_summarizer.py +61 -0
- lionagi/experimental/compressor/util.py +70 -0
- lionagi/experimental/directive/__init__.py +19 -0
- lionagi/experimental/directive/parser/__init__.py +0 -0
- lionagi/experimental/directive/parser/base_parser.py +282 -0
- lionagi/experimental/directive/template/__init__.py +0 -0
- lionagi/experimental/directive/template/base_template.py +79 -0
- lionagi/experimental/directive/template/schema.py +36 -0
- lionagi/experimental/directive/tokenizer.py +73 -0
- lionagi/experimental/evaluator/__init__.py +0 -0
- lionagi/experimental/evaluator/ast_evaluator.py +131 -0
- lionagi/experimental/evaluator/base_evaluator.py +218 -0
- lionagi/experimental/knowledge/__init__.py +0 -0
- lionagi/experimental/knowledge/base.py +10 -0
- lionagi/experimental/knowledge/graph.py +0 -0
- lionagi/experimental/memory/__init__.py +0 -0
- lionagi/experimental/strategies/__init__.py +0 -0
- lionagi/experimental/strategies/base.py +1 -0
- lionagi/integrations/bridge/autogen_/__init__.py +0 -0
- lionagi/integrations/bridge/autogen_/autogen_.py +124 -0
- lionagi/integrations/bridge/langchain_/documents.py +4 -0
- lionagi/integrations/bridge/llamaindex_/index.py +30 -0
- lionagi/integrations/bridge/llamaindex_/llama_index_bridge.py +6 -0
- lionagi/integrations/bridge/llamaindex_/llama_pack.py +227 -0
- lionagi/integrations/bridge/llamaindex_/node_parser.py +6 -9
- lionagi/integrations/bridge/pydantic_/pydantic_bridge.py +1 -0
- lionagi/integrations/bridge/transformers_/__init__.py +0 -0
- lionagi/integrations/bridge/transformers_/install_.py +36 -0
- lionagi/integrations/chunker/__init__.py +0 -0
- lionagi/integrations/chunker/chunk.py +312 -0
- lionagi/integrations/config/oai_configs.py +38 -7
- lionagi/integrations/config/ollama_configs.py +1 -1
- lionagi/integrations/config/openrouter_configs.py +14 -2
- lionagi/integrations/loader/__init__.py +0 -0
- lionagi/integrations/loader/load.py +253 -0
- lionagi/integrations/loader/load_util.py +195 -0
- lionagi/integrations/provider/_mapping.py +46 -0
- lionagi/integrations/provider/litellm.py +2 -1
- lionagi/integrations/provider/mlx_service.py +16 -9
- lionagi/integrations/provider/oai.py +91 -4
- lionagi/integrations/provider/ollama.py +7 -6
- lionagi/integrations/provider/openrouter.py +115 -8
- lionagi/integrations/provider/services.py +2 -2
- lionagi/integrations/provider/transformers.py +18 -22
- lionagi/integrations/storage/__init__.py +3 -0
- lionagi/integrations/storage/neo4j.py +665 -0
- lionagi/integrations/storage/storage_util.py +287 -0
- lionagi/integrations/storage/structure_excel.py +285 -0
- lionagi/integrations/storage/to_csv.py +63 -0
- lionagi/integrations/storage/to_excel.py +83 -0
- lionagi/libs/__init__.py +26 -1
- lionagi/libs/ln_api.py +78 -23
- lionagi/libs/ln_context.py +37 -0
- lionagi/libs/ln_convert.py +21 -9
- lionagi/libs/ln_func_call.py +69 -28
- lionagi/libs/ln_image.py +107 -0
- lionagi/libs/ln_knowledge_graph.py +405 -0
- lionagi/libs/ln_nested.py +26 -11
- lionagi/libs/ln_parse.py +110 -14
- lionagi/libs/ln_queue.py +117 -0
- lionagi/libs/ln_tokenize.py +164 -0
- lionagi/{core/prompt/field_validator.py → libs/ln_validate.py} +79 -14
- lionagi/libs/special_tokens.py +172 -0
- lionagi/libs/sys_util.py +107 -2
- lionagi/lions/__init__.py +0 -0
- lionagi/lions/coder/__init__.py +0 -0
- lionagi/lions/coder/add_feature.py +20 -0
- lionagi/lions/coder/base_prompts.py +22 -0
- lionagi/lions/coder/code_form.py +13 -0
- lionagi/lions/coder/coder.py +168 -0
- lionagi/lions/coder/util.py +96 -0
- lionagi/lions/researcher/__init__.py +0 -0
- lionagi/lions/researcher/data_source/__init__.py +0 -0
- lionagi/lions/researcher/data_source/finhub_.py +191 -0
- lionagi/lions/researcher/data_source/google_.py +199 -0
- lionagi/lions/researcher/data_source/wiki_.py +96 -0
- lionagi/lions/researcher/data_source/yfinance_.py +21 -0
- lionagi/tests/integrations/__init__.py +0 -0
- lionagi/tests/libs/__init__.py +0 -0
- lionagi/tests/libs/test_field_validators.py +353 -0
- lionagi/tests/{test_libs → libs}/test_func_call.py +23 -21
- lionagi/tests/{test_libs → libs}/test_nested.py +36 -21
- lionagi/tests/{test_libs → libs}/test_parse.py +1 -1
- lionagi/tests/libs/test_queue.py +67 -0
- lionagi/tests/test_core/collections/__init__.py +0 -0
- lionagi/tests/test_core/collections/test_component.py +206 -0
- lionagi/tests/test_core/collections/test_exchange.py +138 -0
- lionagi/tests/test_core/collections/test_flow.py +145 -0
- lionagi/tests/test_core/collections/test_pile.py +171 -0
- lionagi/tests/test_core/collections/test_progression.py +129 -0
- lionagi/tests/test_core/generic/__init__.py +0 -0
- lionagi/tests/test_core/generic/test_edge.py +67 -0
- lionagi/tests/test_core/generic/test_graph.py +96 -0
- lionagi/tests/test_core/generic/test_node.py +106 -0
- lionagi/tests/test_core/generic/test_tree_node.py +73 -0
- lionagi/tests/test_core/test_branch.py +115 -292
- lionagi/tests/test_core/test_form.py +46 -0
- lionagi/tests/test_core/test_report.py +105 -0
- lionagi/tests/test_core/test_validator.py +111 -0
- lionagi/version.py +1 -1
- {lionagi-0.0.312.dist-info → lionagi-0.2.1.dist-info}/LICENSE +12 -11
- {lionagi-0.0.312.dist-info → lionagi-0.2.1.dist-info}/METADATA +19 -118
- lionagi-0.2.1.dist-info/RECORD +240 -0
- lionagi/core/branch/__init__.py +0 -4
- lionagi/core/branch/base_branch.py +0 -654
- lionagi/core/branch/branch.py +0 -471
- lionagi/core/branch/branch_flow_mixin.py +0 -96
- lionagi/core/branch/executable_branch.py +0 -347
- lionagi/core/branch/util.py +0 -323
- lionagi/core/direct/__init__.py +0 -6
- lionagi/core/direct/predict.py +0 -161
- lionagi/core/direct/score.py +0 -278
- lionagi/core/direct/select.py +0 -169
- lionagi/core/direct/utils.py +0 -87
- lionagi/core/direct/vote.py +0 -64
- lionagi/core/flow/base/baseflow.py +0 -23
- lionagi/core/flow/monoflow/ReAct.py +0 -238
- lionagi/core/flow/monoflow/__init__.py +0 -9
- lionagi/core/flow/monoflow/chat.py +0 -95
- lionagi/core/flow/monoflow/chat_mixin.py +0 -263
- lionagi/core/flow/monoflow/followup.py +0 -214
- lionagi/core/flow/polyflow/__init__.py +0 -1
- lionagi/core/flow/polyflow/chat.py +0 -248
- lionagi/core/mail/schema.py +0 -56
- lionagi/core/messages/__init__.py +0 -3
- lionagi/core/messages/schema.py +0 -533
- lionagi/core/prompt/prompt_template.py +0 -316
- lionagi/core/schema/__init__.py +0 -22
- lionagi/core/schema/action_node.py +0 -29
- lionagi/core/schema/base_mixin.py +0 -296
- lionagi/core/schema/base_node.py +0 -199
- lionagi/core/schema/condition.py +0 -24
- lionagi/core/schema/data_logger.py +0 -354
- lionagi/core/schema/data_node.py +0 -93
- lionagi/core/schema/prompt_template.py +0 -67
- lionagi/core/schema/structure.py +0 -910
- lionagi/core/tool/__init__.py +0 -3
- lionagi/core/tool/tool_manager.py +0 -280
- lionagi/integrations/bridge/pydantic_/base_model.py +0 -7
- lionagi/tests/test_core/test_base_branch.py +0 -427
- lionagi/tests/test_core/test_chat_flow.py +0 -63
- lionagi/tests/test_core/test_mail_manager.py +0 -75
- lionagi/tests/test_core/test_prompts.py +0 -51
- lionagi/tests/test_core/test_session.py +0 -254
- lionagi/tests/test_core/test_session_base_util.py +0 -312
- lionagi/tests/test_core/test_tool_manager.py +0 -95
- lionagi-0.0.312.dist-info/RECORD +0 -111
- /lionagi/core/{branch/base → _setting}/__init__.py +0 -0
- /lionagi/core/{flow → agent/eval}/__init__.py +0 -0
- /lionagi/core/{flow/base → agent/learn}/__init__.py +0 -0
- /lionagi/core/{prompt → agent/plan}/__init__.py +0 -0
- /lionagi/core/{tool/manual.py → agent/plan/plan.py} +0 -0
- /lionagi/{tests/test_integrations → core/director}/__init__.py +0 -0
- /lionagi/{tests/test_libs → core/engine}/__init__.py +0 -0
- /lionagi/{tests/test_libs/test_async.py → core/executor/__init__.py} +0 -0
- /lionagi/tests/{test_libs → libs}/test_api.py +0 -0
- /lionagi/tests/{test_libs → libs}/test_convert.py +0 -0
- /lionagi/tests/{test_libs → libs}/test_sys_util.py +0 -0
- {lionagi-0.0.312.dist-info → lionagi-0.2.1.dist-info}/WHEEL +0 -0
- {lionagi-0.0.312.dist-info → lionagi-0.2.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,426 @@
|
|
1
|
+
"""
|
2
|
+
Copyright 2024 HaiyangLi
|
3
|
+
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
you may not use this file except in compliance with the License.
|
6
|
+
You may obtain a copy of the License at
|
7
|
+
|
8
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
|
10
|
+
Unless required by applicable law or agreed to in writing, software
|
11
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
See the License for the specific language governing permissions and
|
14
|
+
limitations under the License.
|
15
|
+
"""
|
16
|
+
|
17
|
+
from collections.abc import Mapping
|
18
|
+
from collections import deque
|
19
|
+
from typing import Tuple
|
20
|
+
from pydantic import Field
|
21
|
+
import contextlib
|
22
|
+
from .abc import (
|
23
|
+
Record,
|
24
|
+
LionTypeError,
|
25
|
+
ItemNotFoundError,
|
26
|
+
LionIDable,
|
27
|
+
Element,
|
28
|
+
)
|
29
|
+
from .pile import Pile, pile
|
30
|
+
from .progression import Progression, progression
|
31
|
+
|
32
|
+
|
33
|
+
class Flow(Element):
|
34
|
+
"""
|
35
|
+
Represents a flow of categorical sequences.
|
36
|
+
|
37
|
+
Attributes:
|
38
|
+
sequences (Pile[Progression]): A collection of progression sequences.
|
39
|
+
registry (dict[str, str]): A registry mapping sequence names to IDs.
|
40
|
+
default_name (str): The default name for the flow.
|
41
|
+
"""
|
42
|
+
|
43
|
+
sequences: Pile[Progression] = Field(
|
44
|
+
default_factory=lambda: pile({}, Progression, use_obj=True)
|
45
|
+
)
|
46
|
+
|
47
|
+
registry: dict[str, str] = {}
|
48
|
+
default_name: str = "main"
|
49
|
+
|
50
|
+
def __init__(self, sequences=None, default_name=None):
|
51
|
+
"""
|
52
|
+
Initializes a Flow instance.
|
53
|
+
|
54
|
+
Args:
|
55
|
+
sequences (optional): Initial sequences to include in the flow.
|
56
|
+
default_name (optional): Default name for the flow.
|
57
|
+
"""
|
58
|
+
super().__init__()
|
59
|
+
self.sequences = self._validate_sequences(sequences)
|
60
|
+
self.default_name = default_name or "main"
|
61
|
+
|
62
|
+
def _validate_sequences(self, value):
|
63
|
+
"""
|
64
|
+
Validates and initializes the sequences.
|
65
|
+
|
66
|
+
Args:
|
67
|
+
value: Sequences to validate and initialize.
|
68
|
+
|
69
|
+
Returns:
|
70
|
+
Pile[Progression]: A pile of progression sequences.
|
71
|
+
"""
|
72
|
+
if not value:
|
73
|
+
return pile({}, Progression, use_obj=True)
|
74
|
+
if isinstance(value, dict):
|
75
|
+
return pile(value, Progression, use_obj=True)
|
76
|
+
if (
|
77
|
+
isinstance(value, list)
|
78
|
+
and len(value) > 0
|
79
|
+
and isinstance(value[0], Progression)
|
80
|
+
):
|
81
|
+
return pile({i.ln_id: i for i in value}, Progression, use_obj=True)
|
82
|
+
return pile({}, Progression, use_obj=True)
|
83
|
+
|
84
|
+
def all_orders(self) -> list[list[str]]:
|
85
|
+
"""
|
86
|
+
Retrieves all orders in the flow.
|
87
|
+
|
88
|
+
Returns:
|
89
|
+
list[list[str]]: A list of lists containing sequence orders.
|
90
|
+
"""
|
91
|
+
return [list(seq) for seq in self.sequences]
|
92
|
+
|
93
|
+
def all_unique_items(self) -> Tuple[str]:
|
94
|
+
"""
|
95
|
+
Retrieves all unique items across sequences.
|
96
|
+
|
97
|
+
Returns:
|
98
|
+
Tuple[str]: A tuple of unique items.
|
99
|
+
"""
|
100
|
+
return tuple({item for seq in self.sequences for item in seq})
|
101
|
+
|
102
|
+
def keys(self):
|
103
|
+
yield from self.sequences.keys()
|
104
|
+
|
105
|
+
def values(self):
|
106
|
+
yield from self.sequences.values()
|
107
|
+
|
108
|
+
def items(self):
|
109
|
+
yield from self.sequences.items()
|
110
|
+
|
111
|
+
def get(self, seq=None, default=...):
|
112
|
+
"""
|
113
|
+
Retrieves a sequence by name or returns the default sequence.
|
114
|
+
|
115
|
+
Args:
|
116
|
+
seq (optional): The name of the sequence.
|
117
|
+
default (optional): Default value if sequence is not found.
|
118
|
+
|
119
|
+
Returns:
|
120
|
+
Progression: The requested sequence.
|
121
|
+
"""
|
122
|
+
|
123
|
+
if seq is None:
|
124
|
+
if self.default_name in self.registry:
|
125
|
+
seq = self.registry[self.default_name]
|
126
|
+
seq = self.sequences[seq]
|
127
|
+
else:
|
128
|
+
raise ItemNotFoundError("No sequence found.")
|
129
|
+
|
130
|
+
elif seq is not None and seq in self:
|
131
|
+
if not isinstance(seq, (str, Progression)):
|
132
|
+
raise LionTypeError("Sequence must be of type Progression.")
|
133
|
+
|
134
|
+
if isinstance(seq, str):
|
135
|
+
seq = self.registry[seq]
|
136
|
+
|
137
|
+
return (
|
138
|
+
self.sequences[seq] if default == ... else self.sequences.get(seq, default)
|
139
|
+
)
|
140
|
+
|
141
|
+
def __getitem__(self, seq=None, /):
|
142
|
+
return self.get(seq)
|
143
|
+
|
144
|
+
def __setitem__(self, seq: LionIDable | str, index=None, value=None, /):
|
145
|
+
if seq not in self:
|
146
|
+
raise ItemNotFoundError(f"Sequence {seq}")
|
147
|
+
|
148
|
+
if index:
|
149
|
+
self.sequences[seq][index] = value
|
150
|
+
return
|
151
|
+
|
152
|
+
self.sequences[seq] = value
|
153
|
+
|
154
|
+
def __contains__(self, item):
|
155
|
+
return (
|
156
|
+
item in self.registry
|
157
|
+
or item in self.sequences
|
158
|
+
or item in self.all_unique_items()
|
159
|
+
)
|
160
|
+
|
161
|
+
def shape(self):
|
162
|
+
return (len(self.all_orders()), [len(i) for i in self.all_orders()])
|
163
|
+
|
164
|
+
def size(self):
|
165
|
+
return sum(len(seq) for seq in self.all_orders())
|
166
|
+
|
167
|
+
def clear(self):
|
168
|
+
self.sequences.clear()
|
169
|
+
self.registry.clear()
|
170
|
+
|
171
|
+
def include(self, seq=None, item=None, name=None):
|
172
|
+
_sequence = self._find_sequence(seq, None) or self._find_sequence(name, None)
|
173
|
+
if not _sequence:
|
174
|
+
if not item and not name:
|
175
|
+
"""None is not in the registry or sequencees."""
|
176
|
+
return False
|
177
|
+
if item:
|
178
|
+
self.append(item, name)
|
179
|
+
return item in self
|
180
|
+
|
181
|
+
else:
|
182
|
+
if _sequence in self:
|
183
|
+
if not item and not name:
|
184
|
+
return True
|
185
|
+
if item:
|
186
|
+
self.append(item, _sequence)
|
187
|
+
return item in self
|
188
|
+
return True # will ignore name if sequence is already found
|
189
|
+
|
190
|
+
else:
|
191
|
+
if isinstance(seq, Progression):
|
192
|
+
if item and seq.include(item):
|
193
|
+
self.register(seq, name)
|
194
|
+
return seq in self
|
195
|
+
|
196
|
+
return False
|
197
|
+
|
198
|
+
def exclude(self, seq: LionIDable = None, item=None, name=None):
|
199
|
+
"""
|
200
|
+
Excludes an item or sequence from the flow.
|
201
|
+
|
202
|
+
Args:
|
203
|
+
seq (LionIDable, optional): The sequence to exclude from.
|
204
|
+
item (optional): The item to exclude.
|
205
|
+
name (optional): The name of the sequence.
|
206
|
+
|
207
|
+
Returns:
|
208
|
+
bool: True if exclusion was successful, False otherwise.
|
209
|
+
"""
|
210
|
+
# if sequence is not None, we will not check the name
|
211
|
+
if seq is not None:
|
212
|
+
|
213
|
+
with contextlib.suppress(ItemNotFoundError, AttributeError):
|
214
|
+
if item:
|
215
|
+
# if there is item, we exclude it from the sequence
|
216
|
+
self.sequences[self.registry[seq]].exclude(item)
|
217
|
+
return item not in self.sequences[self.registry[seq]]
|
218
|
+
else:
|
219
|
+
# if there is no item, we exclude the sequence
|
220
|
+
a = self.registry.pop(seq.name or seq.ln_id, None)
|
221
|
+
return a is not None and self.sequences.exclude(seq)
|
222
|
+
return False
|
223
|
+
|
224
|
+
elif name is not None:
|
225
|
+
|
226
|
+
with contextlib.suppress(ItemNotFoundError):
|
227
|
+
if item:
|
228
|
+
# if there is item, we exclude it from the sequence
|
229
|
+
return self.sequences[self.registry[name]].exclude(item)
|
230
|
+
else:
|
231
|
+
# if there is no item, we exclude the sequence
|
232
|
+
a = self.registry.pop(name, None)
|
233
|
+
return a is not None and self.sequences.exclude(a)
|
234
|
+
return False
|
235
|
+
|
236
|
+
def register(self, sequence: Progression, name: str = None):
|
237
|
+
"""
|
238
|
+
Registers a sequence with a name.
|
239
|
+
|
240
|
+
Args:
|
241
|
+
sequence (Progression): The sequence to register.
|
242
|
+
name (str, optional): The name for the sequence.
|
243
|
+
|
244
|
+
Raises:
|
245
|
+
LionTypeError: If the sequence is not of type Progression.
|
246
|
+
ValueError: If the sequence name already exists.
|
247
|
+
"""
|
248
|
+
|
249
|
+
if not isinstance(sequence, Progression):
|
250
|
+
raise LionTypeError(f"Sequence must be of type Progression.")
|
251
|
+
|
252
|
+
name = name or sequence.name
|
253
|
+
if not name:
|
254
|
+
if self.default_name in self.registry:
|
255
|
+
name = sequence.ln_id
|
256
|
+
else:
|
257
|
+
name = self.default_name
|
258
|
+
|
259
|
+
if name in self.registry:
|
260
|
+
raise ValueError(f"Sequence '{name}' already exists.")
|
261
|
+
|
262
|
+
self.sequences.include(sequence)
|
263
|
+
self.registry[name] = sequence.ln_id
|
264
|
+
|
265
|
+
def append(self, item, sequence=None, /):
|
266
|
+
"""
|
267
|
+
Appends an item to a sequence.
|
268
|
+
|
269
|
+
Args:
|
270
|
+
item: The item to append.
|
271
|
+
sequence (optional): The sequence to append to.
|
272
|
+
"""
|
273
|
+
if not sequence:
|
274
|
+
if self.default_name in self.registry:
|
275
|
+
sequence = self.registry[self.default_name]
|
276
|
+
self.sequences[sequence].include(item)
|
277
|
+
return
|
278
|
+
|
279
|
+
p = progression(item, self.default_name)
|
280
|
+
self.register(p)
|
281
|
+
return
|
282
|
+
|
283
|
+
if sequence in self.sequences:
|
284
|
+
self.sequences[sequence].include(item)
|
285
|
+
return
|
286
|
+
|
287
|
+
if sequence in self.registry:
|
288
|
+
self.sequences[self.registry[sequence]].include(item)
|
289
|
+
return
|
290
|
+
|
291
|
+
p = progression(item, sequence if isinstance(sequence, str) else None)
|
292
|
+
self.register(p)
|
293
|
+
|
294
|
+
def popleft(self, sequence=None, /):
|
295
|
+
"""
|
296
|
+
Removes and returns an item from the left end of a sequence.
|
297
|
+
|
298
|
+
Args:
|
299
|
+
sequence (optional): The sequence to remove the item from.
|
300
|
+
|
301
|
+
Returns:
|
302
|
+
The removed item.
|
303
|
+
"""
|
304
|
+
sequence = self._find_sequence(sequence)
|
305
|
+
return self.sequences[sequence].popleft()
|
306
|
+
|
307
|
+
def shape(self):
|
308
|
+
return {key: len(self.sequences[value]) for key, value in self.registry.items()}
|
309
|
+
|
310
|
+
def get(self, sequence: str, /, default=...) -> deque[str] | None:
|
311
|
+
sequence = getattr(sequence, "ln_id", None) or sequence
|
312
|
+
|
313
|
+
if sequence in self.registry:
|
314
|
+
return self.sequences[self.registry[sequence]]
|
315
|
+
|
316
|
+
try:
|
317
|
+
return self.sequences[sequence]
|
318
|
+
except KeyError as e:
|
319
|
+
if default == ...:
|
320
|
+
raise e
|
321
|
+
return default
|
322
|
+
|
323
|
+
def remove(self, item, sequence="all"):
|
324
|
+
"""
|
325
|
+
Removes an item from a sequence or all sequences.
|
326
|
+
|
327
|
+
Args:
|
328
|
+
item: The item to remove.
|
329
|
+
sequence (str, optional): The sequence to remove the item from. Defaults to "all".
|
330
|
+
"""
|
331
|
+
if sequence == "all":
|
332
|
+
for seq in self.sequences:
|
333
|
+
seq.remove(item)
|
334
|
+
return
|
335
|
+
|
336
|
+
sequence = self._find_sequence(sequence)
|
337
|
+
self.sequences[sequence].remove(item)
|
338
|
+
|
339
|
+
def __len__(self):
|
340
|
+
return len(self.sequences)
|
341
|
+
|
342
|
+
def __iter__(self):
|
343
|
+
return iter(self.sequences)
|
344
|
+
|
345
|
+
def __next__(self):
|
346
|
+
return next(self.__iter__())
|
347
|
+
|
348
|
+
def _find_sequence(self, sequence=None, default=...):
|
349
|
+
"""
|
350
|
+
Finds the sequence ID in the registry or sequences.
|
351
|
+
|
352
|
+
Args:
|
353
|
+
sequence (optional): The sequence to find.
|
354
|
+
default (optional): The default value if sequence is not found.
|
355
|
+
|
356
|
+
Returns:
|
357
|
+
The found sequence ID.
|
358
|
+
|
359
|
+
Raises:
|
360
|
+
ItemNotFoundError: If no sequence is found.
|
361
|
+
"""
|
362
|
+
|
363
|
+
if not sequence:
|
364
|
+
if self.default_name in self.registry:
|
365
|
+
return self.registry[self.default_name]
|
366
|
+
if default != ...:
|
367
|
+
return default
|
368
|
+
raise ItemNotFoundError("No sequence found.")
|
369
|
+
|
370
|
+
if sequence in self.sequences:
|
371
|
+
return sequence.ln_id if isinstance(sequence, Progression) else sequence
|
372
|
+
|
373
|
+
if sequence in self.registry:
|
374
|
+
return self.registry[sequence]
|
375
|
+
|
376
|
+
def to_dict(self):
|
377
|
+
return {
|
378
|
+
"sequences": self.sequences.to_dict(),
|
379
|
+
"registry": self.registry,
|
380
|
+
"default_name": self.default_name,
|
381
|
+
}
|
382
|
+
|
383
|
+
def to_df(self):
|
384
|
+
return self.sequences.to_df()
|
385
|
+
|
386
|
+
|
387
|
+
def flow(sequences=None, default_name=None, /):
|
388
|
+
"""
|
389
|
+
Creates a new Flow instance.
|
390
|
+
|
391
|
+
Args:
|
392
|
+
sequences (optional): Initial sequences to include in the flow.
|
393
|
+
default_name (optional): Default name for the flow.
|
394
|
+
|
395
|
+
Returns:
|
396
|
+
Flow: A new Flow instance.
|
397
|
+
"""
|
398
|
+
if sequences is None:
|
399
|
+
return Flow()
|
400
|
+
|
401
|
+
flow = Flow()
|
402
|
+
if default_name:
|
403
|
+
flow.default_name = default_name
|
404
|
+
|
405
|
+
# if mapping we assume a dictionary of in {name: data} format
|
406
|
+
if isinstance(sequences, (Mapping, Record)):
|
407
|
+
for name, seq in sequences.items():
|
408
|
+
if not isinstance(seq, Progression):
|
409
|
+
try:
|
410
|
+
seq = progression(seq, name)
|
411
|
+
except Exception as e:
|
412
|
+
raise e
|
413
|
+
if (a := name or seq.name) is not None:
|
414
|
+
flow.register(seq, a)
|
415
|
+
else:
|
416
|
+
flow.register(seq, seq.ln_id)
|
417
|
+
return flow
|
418
|
+
|
419
|
+
for seq in sequences:
|
420
|
+
if not isinstance(seq, Progression):
|
421
|
+
try:
|
422
|
+
seq = progression(seq)
|
423
|
+
except Exception as e:
|
424
|
+
raise e
|
425
|
+
flow.register(seq)
|
426
|
+
return flow
|