fabricatio 0.2.0.dev10__cp312-cp312-manylinux_2_34_x86_64.whl → 0.2.0.dev12__cp312-cp312-manylinux_2_34_x86_64.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.
fabricatio/__init__.py CHANGED
@@ -1,7 +1,6 @@
1
1
  """Fabricatio is a Python library for building llm app using event-based agent structure."""
2
2
 
3
- from fabricatio._rust import TemplateManager
4
- from fabricatio.config import configs
3
+ from fabricatio._rust_instances import template_manager
5
4
  from fabricatio.core import env
6
5
  from fabricatio.fs import magika
7
6
  from fabricatio.journal import logger
@@ -13,8 +12,6 @@ from fabricatio.models.tool import ToolBox
13
12
  from fabricatio.models.utils import Message, Messages
14
13
  from fabricatio.parser import Capture, CodeBlockCapture, JsonCapture, PythonCapture
15
14
 
16
- template_manager = TemplateManager(configs.code2prompt.template_dir)
17
-
18
15
  __all__ = [
19
16
  "Action",
20
17
  "Capture",
@@ -31,5 +28,5 @@ __all__ = [
31
28
  "env",
32
29
  "logger",
33
30
  "magika",
34
- "template_manager"
31
+ "template_manager",
35
32
  ]
@@ -0,0 +1,4 @@
1
+ from fabricatio._rust import TemplateManager
2
+ from fabricatio.config import configs
3
+
4
+ template_manager = TemplateManager(configs.code2prompt.template_dir)
fabricatio/decorators.py CHANGED
@@ -19,30 +19,9 @@ def depend_on_external_cmd[**P, R](bin_name: str, install_tip: str) -> Callable[
19
19
  RuntimeError: If the required binary is not found.
20
20
  """
21
21
 
22
- def decorator(func: Callable[P, R]) -> Callable[P, R]:
23
- """Decorator to wrap the function with binary presence check.
24
-
25
- Args:
26
- func (Callable[P, R]): The function to be decorated.
27
-
28
- Returns:
29
- Callable[P, R]: The wrapped function.
30
- """
31
-
22
+ def _decorator(func: Callable[P, R]) -> Callable[P, R]:
32
23
  @wraps(func)
33
- def wrapper(*args: P.args, **kwargs: P.kwargs) -> R:
34
- """Wrapper function to check for the presence of the required binary.
35
-
36
- Args:
37
- *args: Positional arguments for the function.
38
- **kwargs: Keyword arguments for the function.
39
-
40
- Returns:
41
- R: The result of the function call.
42
-
43
- Raises:
44
- RuntimeError: If the required binary is not found.
45
- """
24
+ def _wrapper(*args: P.args, **kwargs: P.kwargs) -> R:
46
25
  if which(bin_name) is None:
47
26
  err = (
48
27
  f"{bin_name} is required to run function: {func.__name__}, please install it first.\n{install_tip}"
@@ -51,6 +30,6 @@ def depend_on_external_cmd[**P, R](bin_name: str, install_tip: str) -> Callable[
51
30
  raise RuntimeError(err)
52
31
  return func(*args, **kwargs)
53
32
 
54
- return wrapper
33
+ return _wrapper
55
34
 
56
- return decorator
35
+ return _decorator
@@ -123,6 +123,5 @@ class WorkFlow[A: Type[Action] | Action](WithBriefing, LLMUsage):
123
123
 
124
124
  def fallback_to_self(self) -> Self:
125
125
  """Set the fallback for each step to the workflow itself."""
126
- for step in self._instances:
127
- step.fallback_to(self)
126
+ self.hold_to(self._instances)
128
127
  return self
@@ -1,13 +1,15 @@
1
1
  """This module defines generic classes for models in the Fabricatio library."""
2
2
 
3
3
  from pathlib import Path
4
- from typing import Callable, Dict, List, Optional, Self
4
+ from typing import Callable, Dict, Iterable, List, Optional, Self, Union
5
5
 
6
6
  import litellm
7
7
  import orjson
8
+ from fabricatio._rust_instances import template_manager
8
9
  from fabricatio.config import configs
9
10
  from fabricatio.fs.readers import magika
10
11
  from fabricatio.models.utils import Messages
12
+ from fabricatio.parser import JsonCapture
11
13
  from litellm.types.utils import Choices, ModelResponse, StreamingChoices
12
14
  from pydantic import (
13
15
  BaseModel,
@@ -274,21 +276,90 @@ class LLMUsage(Base):
274
276
  for _ in range(max_validations):
275
277
  if (
276
278
  response := await self.aask(
277
- question,
278
- system_message,
279
- model,
280
- temperature,
281
- stop,
282
- top_p,
283
- max_tokens,
284
- stream,
285
- timeout,
286
- max_retries,
279
+ question=question,
280
+ system_message=system_message,
281
+ model=model,
282
+ temperature=temperature,
283
+ stop=stop,
284
+ top_p=top_p,
285
+ max_tokens=max_tokens,
286
+ stream=stream,
287
+ timeout=timeout,
288
+ max_retries=max_retries,
287
289
  )
288
290
  ) and (validated := validator(response)):
289
291
  return validated
290
292
  raise ValueError("Failed to validate the response.")
291
293
 
294
+ async def achoose[T: WithBriefing](
295
+ self,
296
+ instruction: str,
297
+ choices: List[T],
298
+ max_validations: PositiveInt = 2,
299
+ system_message: str = "",
300
+ model: str | None = None,
301
+ temperature: NonNegativeFloat | None = None,
302
+ stop: str | List[str] | None = None,
303
+ top_p: NonNegativeFloat | None = None,
304
+ max_tokens: PositiveInt | None = None,
305
+ stream: bool | None = None,
306
+ timeout: PositiveInt | None = None,
307
+ max_retries: PositiveInt | None = None,
308
+ ) -> List[T]:
309
+ """Asynchronously executes a multi-choice decision-making process, generating a prompt based on the instruction and options, and validates the returned selection results.
310
+
311
+ Args:
312
+ instruction: The user-provided instruction/question description.
313
+ choices: A list of candidate options, requiring elements to have `name` and `briefing` fields.
314
+ max_validations: Maximum number of validation failures, default is 2.
315
+ system_message: Custom system-level prompt, defaults to an empty string.
316
+ model: The name of the LLM model to use.
317
+ temperature: Sampling temperature to control randomness in generation.
318
+ stop: Stop condition string or list for generation.
319
+ top_p: Core sampling probability threshold.
320
+ max_tokens: Maximum token limit for the generated result.
321
+ stream: Whether to enable streaming response mode.
322
+ timeout: Request timeout in seconds.
323
+ max_retries: Maximum number of retries.
324
+
325
+ Returns:
326
+ List[T]: The final validated selection result list, with element types matching the input `choices`.
327
+
328
+ Important:
329
+ - Uses a template engine to generate structured prompts.
330
+ - Ensures response compliance through JSON parsing and format validation.
331
+ - Relies on `aask_validate` to implement retry mechanisms with validation.
332
+ """
333
+ prompt = template_manager.render_template(
334
+ "make_choice",
335
+ {"instruction": instruction, "options": [m.model_dump(include={"name", "briefing"}) for m in choices]},
336
+ )
337
+ names = [c.name for c in choices]
338
+
339
+ def _validate(response: str) -> List[T] | None:
340
+ cap = JsonCapture.capture(response)
341
+ ret = orjson.loads(cap)
342
+ if not isinstance(ret, List):
343
+ return None
344
+ if any(n not in names for n in ret):
345
+ return None
346
+ return ret
347
+
348
+ return await self.aask_validate(
349
+ question=prompt,
350
+ validator=_validate,
351
+ max_validations=max_validations,
352
+ system_message=system_message,
353
+ model=model,
354
+ temperature=temperature,
355
+ stop=stop,
356
+ top_p=top_p,
357
+ max_tokens=max_tokens,
358
+ stream=stream,
359
+ timeout=timeout,
360
+ max_retries=max_retries,
361
+ )
362
+
292
363
  def fallback_to(self, other: "LLMUsage") -> Self:
293
364
  """Fallback to another instance's attribute values if the current instance's attributes are None.
294
365
 
@@ -298,23 +369,9 @@ class LLMUsage(Base):
298
369
  Returns:
299
370
  Self: The current instance, allowing for method chaining.
300
371
  """
301
- # Define the list of attribute names to check and potentially copy
302
- attr_names = [
303
- "llm_api_endpoint",
304
- "llm_api_key",
305
- "llm_model",
306
- "llm_stop_sign",
307
- "llm_temperature",
308
- "llm_top_p",
309
- "llm_generation_count",
310
- "llm_stream",
311
- "llm_max_tokens",
312
- "llm_timeout",
313
- "llm_max_retries",
314
- ]
315
-
316
372
  # Iterate over the attribute names and copy values from 'other' to 'self' where applicable
317
- for attr_name in attr_names:
373
+ # noinspection PydanticTypeChecker,PyTypeChecker
374
+ for attr_name in LLMUsage.model_fields:
318
375
  # Copy the attribute value from 'other' to 'self' only if 'self' has None and 'other' has a non-None value
319
376
  if getattr(self, attr_name) is None and (attr := getattr(other, attr_name)) is not None:
320
377
  setattr(self, attr_name, attr)
@@ -322,6 +379,21 @@ class LLMUsage(Base):
322
379
  # Return the current instance to allow for method chaining
323
380
  return self
324
381
 
382
+ def hold_to(self, others: Union["LLMUsage", Iterable["LLMUsage"]]) -> Self:
383
+ """Hold to another instance's attribute values if the current instance's attributes are None.
384
+
385
+ Args:
386
+ others (LLMUsage | Iterable[LLMUsage]): Another instance or iterable of instances from which to copy attribute values.
387
+
388
+ Returns:
389
+ Self: The current instance, allowing for method chaining.
390
+ """
391
+ for other in others:
392
+ # noinspection PyTypeChecker,PydanticTypeChecker
393
+ for attr_name in LLMUsage.model_fields:
394
+ if (attr := getattr(self, attr_name)) is not None and getattr(other, attr_name) is None:
395
+ setattr(other, attr_name, attr)
396
+
325
397
 
326
398
  class WithJsonExample(Base):
327
399
  """Class that provides a JSON schema for the model."""
fabricatio/models/task.py CHANGED
@@ -7,6 +7,7 @@ from asyncio import Queue
7
7
  from enum import Enum
8
8
  from typing import Any, List, Optional, Self
9
9
 
10
+ from fabricatio._rust_instances import template_manager
10
11
  from fabricatio.core import env
11
12
  from fabricatio.journal import logger
12
13
  from fabricatio.models.events import Event, EventLike
@@ -273,11 +274,9 @@ class ProposeTask(LLMUsage, WithBriefing):
273
274
  logger.error(f"Failed to parse task from JSON: {e}")
274
275
  return None
275
276
 
277
+ template_data = {"prompt": prompt, "json_example": Task.json_example()}
276
278
  return await self.aask_validate(
277
- f"{prompt} \n\nBased on requirement above, "
278
- f"you need to construct a task to satisfy that requirement in JSON format "
279
- f"written like this: \n\n```json\n{Task.json_example()}\n```\n\n"
280
- f"No extra explanation needed. ",
279
+ template_manager.render_template("propose_task", template_data),
281
280
  _validate_json,
282
281
  system_message=f"# your personal briefing: \n{self.briefing}",
283
282
  )
fabricatio/models/tool.py CHANGED
@@ -1,9 +1,9 @@
1
1
  """A module for defining tools and toolboxes."""
2
2
 
3
- from inspect import getfullargspec, signature
4
- from typing import Any, Callable, List, Self
3
+ from inspect import iscoroutinefunction, signature
4
+ from typing import Any, Callable, Iterable, List, Optional, Self, Union
5
5
 
6
- from fabricatio.models.generic import WithBriefing
6
+ from fabricatio.models.generic import Base, WithBriefing
7
7
  from pydantic import Field
8
8
 
9
9
 
@@ -24,6 +24,7 @@ class Tool[**P, R](WithBriefing):
24
24
  self.name = self.name or self.source.__name__
25
25
  assert self.name, "The tool must have a name."
26
26
  self.description = self.description or self.source.__doc__ or ""
27
+ self.description = self.description.strip()
27
28
 
28
29
  def invoke(self, *args: P.args, **kwargs: P.kwargs) -> R:
29
30
  """Invoke the tool's source function with the provided arguments."""
@@ -36,10 +37,15 @@ class Tool[**P, R](WithBriefing):
36
37
  Returns:
37
38
  str: A brief description of the tool.
38
39
  """
39
- source_signature = str(signature(self.source))
40
40
  # 获取源函数的返回类型
41
- return_annotation = getfullargspec(self.source).annotations.get("return", "None")
42
- return f"{self.name}{source_signature} -> {return_annotation}\n{self.description}"
41
+
42
+ return f"{'async ' if iscoroutinefunction(self.source) else ''}def {self.name}{signature(self.source)}\n{_desc_wrapper(self.description)}"
43
+
44
+
45
+ def _desc_wrapper(desc: str) -> str:
46
+ lines = desc.split("\n")
47
+ lines_indent = [f" {line}" for line in ['"""', *lines, '"""']]
48
+ return "\n".join(lines_indent)
43
49
 
44
50
 
45
51
  class ToolBox(WithBriefing):
@@ -79,7 +85,7 @@ class ToolBox(WithBriefing):
79
85
  Returns:
80
86
  str: A brief description of the toolbox.
81
87
  """
82
- list_out = "\n\n".join([f"- {tool.briefing}" for tool in self.tools])
88
+ list_out = "\n\n".join([f"{tool.briefing}" for tool in self.tools])
83
89
  toc = f"## {self.name}: {self.description}\n## {len(self.tools)} tools available:"
84
90
  return f"{toc}\n\n{list_out}"
85
91
 
@@ -98,3 +104,42 @@ class ToolBox(WithBriefing):
98
104
  tool = next((tool for tool in self.tools if tool.name == name), None)
99
105
  assert tool, f"No tool named {name} found."
100
106
  return tool
107
+
108
+
109
+ class ToolUsage(Base):
110
+ """A class representing the usage of tools in a task."""
111
+
112
+ toolboxes: Optional[List[ToolBox]]
113
+ """The tools used by the task, a list of ToolBox instances."""
114
+
115
+ def supply_tools_from(self, others: Union["ToolUsage", Iterable["ToolUsage"]]) -> Self:
116
+ """Supplies tools from other ToolUsage instances to this instance.
117
+
118
+ Args:
119
+ others ("ToolUsage" | Iterable["ToolUsage"]): A single ToolUsage instance or an iterable of ToolUsage instances
120
+ from which to take tools.
121
+
122
+ Returns:
123
+ Self: The current ToolUsage instance with updated tools.
124
+ """
125
+ if isinstance(others, ToolUsage):
126
+ others = [others]
127
+ for other in others:
128
+ self.toolboxes.extend(other.toolboxes)
129
+ return self
130
+
131
+ def provide_tools_to(self, others: Union["ToolUsage", Iterable["ToolUsage"]]) -> Self:
132
+ """Provides tools from this instance to other ToolUsage instances.
133
+
134
+ Args:
135
+ others ("ToolUsage" | Iterable["ToolUsage"]): A single ToolUsage instance or an iterable of ToolUsage instances
136
+ to which to provide tools.
137
+
138
+ Returns:
139
+ Self: The current ToolUsage instance.
140
+ """
141
+ if isinstance(others, ToolUsage):
142
+ others = [others]
143
+ for other in others:
144
+ other.toolboxes.extend(self.toolboxes)
145
+ return self
fabricatio/parser.py CHANGED
@@ -3,13 +3,11 @@
3
3
  from typing import Any, Self, Tuple
4
4
 
5
5
  import regex
6
- from pydantic import Field, PositiveInt, PrivateAttr
6
+ from pydantic import BaseModel, ConfigDict, Field, PositiveInt, PrivateAttr
7
7
  from regex import Pattern, compile
8
8
 
9
- from fabricatio.models.generic import Base
10
9
 
11
-
12
- class Capture(Base):
10
+ class Capture(BaseModel):
13
11
  """A class to capture patterns in text using regular expressions.
14
12
 
15
13
  Attributes:
@@ -17,6 +15,7 @@ class Capture(Base):
17
15
  _compiled (Pattern): The compiled regular expression pattern.
18
16
  """
19
17
 
18
+ model_config = ConfigDict(use_attribute_docstrings=True)
20
19
  target_groups: Tuple[int, ...] = Field(default_factory=tuple)
21
20
  """The target groups to capture from the pattern."""
22
21
  pattern: str = Field(frozen=True)
@@ -0,0 +1,60 @@
1
+ from fabricatio.models.tool import ToolBox
2
+
3
+ arithmetic_tools = ToolBox(name="ArithmeticToolBox", description="A toolbox for arithmetic operations.")
4
+
5
+
6
+ @arithmetic_tools.collect_tool
7
+ def add(a: float, b: float) -> float:
8
+ """Add two numbers.
9
+
10
+ Args:
11
+ a (float): The first number.
12
+ b (float): The second number.
13
+
14
+ Returns:
15
+ float: The sum of the two numbers.
16
+ """
17
+ return a + b
18
+
19
+
20
+ @arithmetic_tools.collect_tool
21
+ def subtract(a: float, b: float) -> float:
22
+ """Subtract two numbers.
23
+
24
+ Args:
25
+ a (float): The first number.
26
+ b (float): The second number.
27
+
28
+ Returns:
29
+ float: The result of subtracting b from a.
30
+ """
31
+ return a - b
32
+
33
+
34
+ @arithmetic_tools.collect_tool
35
+ def multiply(a: float, b: float) -> float:
36
+ """Multiply two numbers.
37
+
38
+ Args:
39
+ a (float): The first number.
40
+ b (float): The second number.
41
+
42
+ Returns:
43
+ float: The product of the two numbers.
44
+ """
45
+ return a * b
46
+
47
+
48
+ @arithmetic_tools.collect_tool
49
+ def divide(a: float, b: float) -> float:
50
+ """Divide two numbers.
51
+
52
+ Args:
53
+ a (float): The numerator.
54
+ b (float): The denominator (must not be zero).
55
+
56
+ Returns:
57
+ float: The result of dividing a by b.
58
+
59
+ """
60
+ return a / b
@@ -1,7 +1,8 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fabricatio
3
- Version: 0.2.0.dev10
3
+ Version: 0.2.0.dev12
4
4
  Classifier: License :: OSI Approved :: MIT License
5
+ Classifier: Programming Language :: Rust
5
6
  Classifier: Programming Language :: Python :: 3.12
6
7
  Classifier: Programming Language :: Python :: Implementation :: CPython
7
8
  Classifier: Framework :: AsyncIO
@@ -23,7 +24,7 @@ Requires-Dist: regex>=2024.11.6
23
24
  Requires-Dist: rich>=13.9.4
24
25
  License-File: LICENSE
25
26
  Summary: A LLM multi-agent framework.
26
- Keywords: ai,agents,multi-agent,llm
27
+ Keywords: ai,agents,multi-agent,llm,pyo3
27
28
  Author-email: Whth <zettainspector@foxmail.com>
28
29
  Requires-Python: >=3.12
29
30
  Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
@@ -1,28 +1,30 @@
1
- fabricatio-0.2.0.dev10.dist-info/METADATA,sha256=oobQLrDqEDfEOGsTLMYfzJ6oH3UrbUbHQpCHZIsOoUg,5778
2
- fabricatio-0.2.0.dev10.dist-info/WHEEL,sha256=RIvmwLDYujv60MYBx2jxyP4vdn1DD7X0kBgz1TQvZuc,108
3
- fabricatio-0.2.0.dev10.dist-info/licenses/LICENSE,sha256=yDZaTLnOi03bi3Dk6f5IjhLUc5old2yOsihHWU0z-i0,1067
1
+ fabricatio-0.2.0.dev12.dist-info/METADATA,sha256=gWEeKNwVXLETbzTMO9Qd2rkbN_TLH4sdpedRVvW8myc,5824
2
+ fabricatio-0.2.0.dev12.dist-info/WHEEL,sha256=RIvmwLDYujv60MYBx2jxyP4vdn1DD7X0kBgz1TQvZuc,108
3
+ fabricatio-0.2.0.dev12.dist-info/licenses/LICENSE,sha256=yDZaTLnOi03bi3Dk6f5IjhLUc5old2yOsihHWU0z-i0,1067
4
4
  fabricatio/fs/__init__.py,sha256=bYE9r8uR0dtknzbg_YaGv_6Wwa27ntkQt0Tl7Kb3HFI,117
5
5
  fabricatio/fs/readers.py,sha256=E219Pef7gknltkHjL9iZXwjI841_EPFpNvDG9KBUG3g,118
6
6
  fabricatio/toolboxes/__init__.py,sha256=8gd8yPhhQBO0A37w1zqVLfbOG-pyCPrveEtO0MX042A,151
7
7
  fabricatio/toolboxes/task.py,sha256=G_nNYT8Sy5ll6YmXES458MUmgJnDSBNwlozyJewdnzY,200
8
- fabricatio/__init__.py,sha256=ExoKVER1_6bVoTzT9d7LET7HlHYQ4xLoGN9foRX1CnU,977
8
+ fabricatio/toolboxes/arithmetic.py,sha256=MbS1-a4uLGqs7ZypH2dtrTa0d2-Rr8ifok-1mrVfVb4,1257
9
+ fabricatio/__init__.py,sha256=UE2qARwRgL3T1NgnzK9b4Cx3eksUvNZmN_rf-dycM4E,881
9
10
  fabricatio/core.py,sha256=apwXgI94DCWpGujGlsmXsTZQvJOQMB9llmuUo7ohd-4,5771
10
11
  fabricatio/config.py,sha256=Or_PzOzXy_4Rqje1r788sID4bxILXhNC3r7eelcZJy0,7852
11
- fabricatio/decorators.py,sha256=Y2F5JuN3K5Pas_JPBLQrB_Np0s1U8k2lPvrdtCHtcRE,1799
12
+ fabricatio/decorators.py,sha256=UgW8_pV_RUm0a69co1POnKvJHh9Qy2R0pyh1BtEKzFI,1169
12
13
  fabricatio/journal.py,sha256=u6YTKrD9EoebbR8guvAe5zSqWV1nS-BGyKxZR_Sw2ik,684
13
- fabricatio/models/generic.py,sha256=1S5guUWnHSpoyNi1D1t4q14e6YNIovI4Goc3kizHd8M,15698
14
- fabricatio/models/action.py,sha256=PNcm4t34fSaI03ECIOZ8ezvB6PlZkNhJtZFEhtU0Gec,4916
15
- fabricatio/models/task.py,sha256=W66bRf6au6ysS_ypZ3i4W1mL-WhotfvbhbjX-3CrBj4,9146
14
+ fabricatio/models/generic.py,sha256=Q92xkAL1S8zWMCGDUNQahT9atFamZKhHzKbI1OXjBmk,19264
15
+ fabricatio/models/action.py,sha256=VL_A8BWOuCYQCjwCAm0vExA88KSwm6VkluXHOtHijUw,4882
16
+ fabricatio/models/task.py,sha256=-YB9SGqOYrPmk7ce5Go3OO5Cc7Q_KB7QdmeG49GeZpY,9090
16
17
  fabricatio/models/role.py,sha256=1vhpHRKJ6f7PDBLl6jYRZbxTJyrVhNN3FEEh_HAwU3o,990
17
- fabricatio/models/tool.py,sha256=jzH34UHIgqEwYdXOQ3Jz_TN0cyj_jLTVBVs0qGl9tQU,3299
18
+ fabricatio/models/tool.py,sha256=PCsX5hdf6YnslkyoPA8FwybGvrO0fJFJpHsheBwg2bo,4886
18
19
  fabricatio/models/events.py,sha256=S0E7l5iQoJYdUn0pSSziHdXqPzIvvLy8ifVPQxXeAho,2570
19
20
  fabricatio/models/utils.py,sha256=u-eR_v-o0BSFSmCprP3mOyAO-WOyg_P68jjzLjyit_w,2457
20
21
  fabricatio/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
22
+ fabricatio/_rust_instances.py,sha256=c3aB95D7qKrA1AxDHD94lYinklAmK5EL6_DDJUEzPB0,153
21
23
  fabricatio/actions/__init__.py,sha256=eLa_5ACZ-FqdrLtOfCHk5nQBxzhIs1kgMIXWmkm2P8Y,110
22
24
  fabricatio/actions/communication.py,sha256=4hNzyv5_j4HU291dDuBmBEb66VihQPI9SLRVZrxWu1Y,412
23
25
  fabricatio/actions/transmission.py,sha256=gLLKoi4keL64uaEkHDxwVrBGciheupQrO2fW3GkjfEw,1156
24
26
  fabricatio/_rust.pyi,sha256=EwMPoCZFOCYZ5h_9PZLvO3YrgBEG0Hwae0ux0hcBabM,1487
25
- fabricatio/parser.py,sha256=2wFvkyAIlFyB_dj8txr6shc-0ik5cz0mUy_Yj_GrqcI,2355
26
- fabricatio/_rust.cpython-312-x86_64-linux-gnu.so,sha256=zSQ7Y-Hp7TDAzKenBEEWirLdaVturuUyGbNn1oXtRYs,1191136
27
- fabricatio-0.2.0.dev10.data/scripts/tdown,sha256=jyItwd3z9dBoOT6EEA3niK0e7AXhhBnL87-T0IBRkYk,4540840
28
- fabricatio-0.2.0.dev10.dist-info/RECORD,,
27
+ fabricatio/parser.py,sha256=CAI7S3u2xI_-s1JWb4v2GkhiNeX1kr_C2olxy98KLR8,2400
28
+ fabricatio/_rust.cpython-312-x86_64-linux-gnu.so,sha256=JUDe4N51fXgkY7c-vEXnFJaTBWzwwh93AwJPk_QWoGE,1190824
29
+ fabricatio-0.2.0.dev12.data/scripts/tdown,sha256=7IEbm2H2hkcCNmm8b4BEfHtnauc5oO9fIiGn_UXYb3M,4549648
30
+ fabricatio-0.2.0.dev12.dist-info/RECORD,,
Binary file