langchain-core 0.3.75__py3-none-any.whl → 0.3.77__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.

Potentially problematic release.


This version of langchain-core might be problematic. Click here for more details.

Files changed (119) hide show
  1. langchain_core/_api/beta_decorator.py +22 -44
  2. langchain_core/_api/deprecation.py +30 -17
  3. langchain_core/_api/path.py +19 -2
  4. langchain_core/_import_utils.py +7 -0
  5. langchain_core/agents.py +10 -6
  6. langchain_core/beta/runnables/context.py +1 -2
  7. langchain_core/callbacks/base.py +28 -15
  8. langchain_core/callbacks/manager.py +83 -71
  9. langchain_core/callbacks/usage.py +6 -4
  10. langchain_core/chat_history.py +29 -21
  11. langchain_core/document_loaders/base.py +34 -9
  12. langchain_core/document_loaders/langsmith.py +4 -1
  13. langchain_core/documents/base.py +35 -10
  14. langchain_core/documents/transformers.py +4 -2
  15. langchain_core/embeddings/fake.py +8 -5
  16. langchain_core/env.py +2 -3
  17. langchain_core/example_selectors/base.py +12 -0
  18. langchain_core/exceptions.py +7 -0
  19. langchain_core/globals.py +17 -28
  20. langchain_core/indexing/api.py +88 -76
  21. langchain_core/indexing/base.py +5 -8
  22. langchain_core/indexing/in_memory.py +23 -3
  23. langchain_core/language_models/__init__.py +3 -2
  24. langchain_core/language_models/base.py +31 -20
  25. langchain_core/language_models/chat_models.py +98 -27
  26. langchain_core/language_models/fake_chat_models.py +10 -9
  27. langchain_core/language_models/llms.py +52 -18
  28. langchain_core/load/dump.py +2 -3
  29. langchain_core/load/load.py +15 -1
  30. langchain_core/load/serializable.py +39 -44
  31. langchain_core/memory.py +7 -3
  32. langchain_core/messages/ai.py +53 -24
  33. langchain_core/messages/base.py +43 -22
  34. langchain_core/messages/chat.py +4 -1
  35. langchain_core/messages/content_blocks.py +23 -2
  36. langchain_core/messages/function.py +9 -5
  37. langchain_core/messages/human.py +13 -10
  38. langchain_core/messages/modifier.py +1 -0
  39. langchain_core/messages/system.py +11 -8
  40. langchain_core/messages/tool.py +60 -29
  41. langchain_core/messages/utils.py +250 -131
  42. langchain_core/output_parsers/base.py +5 -2
  43. langchain_core/output_parsers/json.py +4 -4
  44. langchain_core/output_parsers/list.py +7 -22
  45. langchain_core/output_parsers/openai_functions.py +3 -0
  46. langchain_core/output_parsers/openai_tools.py +6 -1
  47. langchain_core/output_parsers/pydantic.py +4 -0
  48. langchain_core/output_parsers/string.py +5 -1
  49. langchain_core/output_parsers/xml.py +19 -19
  50. langchain_core/outputs/chat_generation.py +25 -10
  51. langchain_core/outputs/generation.py +14 -3
  52. langchain_core/outputs/llm_result.py +8 -1
  53. langchain_core/prompt_values.py +16 -6
  54. langchain_core/prompts/base.py +4 -9
  55. langchain_core/prompts/chat.py +89 -57
  56. langchain_core/prompts/dict.py +16 -8
  57. langchain_core/prompts/few_shot.py +12 -11
  58. langchain_core/prompts/few_shot_with_templates.py +5 -1
  59. langchain_core/prompts/image.py +12 -5
  60. langchain_core/prompts/message.py +5 -6
  61. langchain_core/prompts/pipeline.py +13 -8
  62. langchain_core/prompts/prompt.py +22 -8
  63. langchain_core/prompts/string.py +18 -10
  64. langchain_core/prompts/structured.py +7 -2
  65. langchain_core/rate_limiters.py +2 -2
  66. langchain_core/retrievers.py +7 -6
  67. langchain_core/runnables/base.py +406 -186
  68. langchain_core/runnables/branch.py +14 -19
  69. langchain_core/runnables/config.py +9 -15
  70. langchain_core/runnables/configurable.py +34 -19
  71. langchain_core/runnables/fallbacks.py +20 -13
  72. langchain_core/runnables/graph.py +48 -38
  73. langchain_core/runnables/graph_ascii.py +41 -18
  74. langchain_core/runnables/graph_mermaid.py +54 -25
  75. langchain_core/runnables/graph_png.py +27 -31
  76. langchain_core/runnables/history.py +55 -58
  77. langchain_core/runnables/passthrough.py +44 -21
  78. langchain_core/runnables/retry.py +44 -23
  79. langchain_core/runnables/router.py +9 -8
  80. langchain_core/runnables/schema.py +2 -0
  81. langchain_core/runnables/utils.py +51 -89
  82. langchain_core/stores.py +19 -31
  83. langchain_core/sys_info.py +9 -8
  84. langchain_core/tools/base.py +37 -28
  85. langchain_core/tools/convert.py +26 -15
  86. langchain_core/tools/simple.py +36 -8
  87. langchain_core/tools/structured.py +25 -12
  88. langchain_core/tracers/base.py +2 -2
  89. langchain_core/tracers/context.py +5 -1
  90. langchain_core/tracers/core.py +109 -39
  91. langchain_core/tracers/evaluation.py +22 -26
  92. langchain_core/tracers/event_stream.py +45 -34
  93. langchain_core/tracers/langchain.py +12 -3
  94. langchain_core/tracers/langchain_v1.py +10 -2
  95. langchain_core/tracers/log_stream.py +56 -17
  96. langchain_core/tracers/root_listeners.py +4 -20
  97. langchain_core/tracers/run_collector.py +6 -16
  98. langchain_core/tracers/schemas.py +5 -1
  99. langchain_core/utils/aiter.py +15 -7
  100. langchain_core/utils/env.py +3 -0
  101. langchain_core/utils/function_calling.py +50 -28
  102. langchain_core/utils/interactive_env.py +6 -2
  103. langchain_core/utils/iter.py +12 -4
  104. langchain_core/utils/json.py +12 -3
  105. langchain_core/utils/json_schema.py +156 -40
  106. langchain_core/utils/loading.py +5 -1
  107. langchain_core/utils/mustache.py +24 -15
  108. langchain_core/utils/pydantic.py +38 -9
  109. langchain_core/utils/utils.py +25 -9
  110. langchain_core/vectorstores/base.py +7 -20
  111. langchain_core/vectorstores/in_memory.py +23 -17
  112. langchain_core/vectorstores/utils.py +18 -12
  113. langchain_core/version.py +1 -1
  114. langchain_core-0.3.77.dist-info/METADATA +67 -0
  115. langchain_core-0.3.77.dist-info/RECORD +174 -0
  116. langchain_core-0.3.75.dist-info/METADATA +0 -106
  117. langchain_core-0.3.75.dist-info/RECORD +0 -174
  118. {langchain_core-0.3.75.dist-info → langchain_core-0.3.77.dist-info}/WHEEL +0 -0
  119. {langchain_core-0.3.75.dist-info → langchain_core-0.3.77.dist-info}/entry_points.txt +0 -0
@@ -96,22 +96,22 @@ class RunnablePassthrough(RunnableSerializable[Other, Other]):
96
96
  )
97
97
 
98
98
  runnable = RunnableParallel(
99
- origin=RunnablePassthrough(),
100
- modified=lambda x: x+1
99
+ origin=RunnablePassthrough(), modified=lambda x: x + 1
101
100
  )
102
101
 
103
- runnable.invoke(1) # {'origin': 1, 'modified': 2}
102
+ runnable.invoke(1) # {'origin': 1, 'modified': 2}
104
103
 
105
104
 
106
- def fake_llm(prompt: str) -> str: # Fake LLM for the example
105
+ def fake_llm(prompt: str) -> str: # Fake LLM for the example
107
106
  return "completion"
108
107
 
108
+
109
109
  chain = RunnableLambda(fake_llm) | {
110
- 'original': RunnablePassthrough(), # Original LLM output
111
- 'parsed': lambda text: text[::-1] # Parsing logic
110
+ "original": RunnablePassthrough(), # Original LLM output
111
+ "parsed": lambda text: text[::-1], # Parsing logic
112
112
  }
113
113
 
114
- chain.invoke('hello') # {'original': 'completion', 'parsed': 'noitelpmoc'}
114
+ chain.invoke("hello") # {'original': 'completion', 'parsed': 'noitelpmoc'}
115
115
 
116
116
  In some cases, it may be useful to pass the input through while adding some
117
117
  keys to the output. In this case, you can use the `assign` method:
@@ -120,17 +120,19 @@ class RunnablePassthrough(RunnableSerializable[Other, Other]):
120
120
 
121
121
  from langchain_core.runnables import RunnablePassthrough
122
122
 
123
- def fake_llm(prompt: str) -> str: # Fake LLM for the example
123
+
124
+ def fake_llm(prompt: str) -> str: # Fake LLM for the example
124
125
  return "completion"
125
126
 
127
+
126
128
  runnable = {
127
- 'llm1': fake_llm,
128
- 'llm2': fake_llm,
129
+ "llm1": fake_llm,
130
+ "llm2": fake_llm,
129
131
  } | RunnablePassthrough.assign(
130
- total_chars=lambda inputs: len(inputs['llm1'] + inputs['llm2'])
132
+ total_chars=lambda inputs: len(inputs["llm1"] + inputs["llm2"])
131
133
  )
132
134
 
133
- runnable.invoke('hello')
135
+ runnable.invoke("hello")
134
136
  # {'llm1': 'completion', 'llm2': 'completion', 'total_chars': 20}
135
137
 
136
138
  """
@@ -191,11 +193,16 @@ class RunnablePassthrough(RunnableSerializable[Other, Other]):
191
193
  @classmethod
192
194
  @override
193
195
  def is_lc_serializable(cls) -> bool:
196
+ """Return True as this class is serializable."""
194
197
  return True
195
198
 
196
199
  @classmethod
197
- @override
198
200
  def get_lc_namespace(cls) -> list[str]:
201
+ """Get the namespace of the langchain object.
202
+
203
+ Returns:
204
+ ``["langchain", "schema", "runnable"]``
205
+ """
199
206
  return ["langchain", "schema", "runnable"]
200
207
 
201
208
  @property
@@ -378,11 +385,15 @@ class RunnableAssign(RunnableSerializable[dict[str, Any], dict[str, Any]]):
378
385
  )
379
386
  from langchain_core.runnables.base import RunnableLambda
380
387
 
388
+
381
389
  def add_ten(x: dict[str, int]) -> dict[str, int]:
382
390
  return {"added": x["input"] + 10}
383
391
 
392
+
384
393
  mapper = RunnableParallel(
385
- {"add_step": RunnableLambda(add_ten),}
394
+ {
395
+ "add_step": RunnableLambda(add_ten),
396
+ }
386
397
  )
387
398
 
388
399
  runnable_assign = RunnableAssign(mapper)
@@ -411,11 +422,17 @@ class RunnableAssign(RunnableSerializable[dict[str, Any], dict[str, Any]]):
411
422
  @classmethod
412
423
  @override
413
424
  def is_lc_serializable(cls) -> bool:
425
+ """Return True as this class is serializable."""
414
426
  return True
415
427
 
416
428
  @classmethod
417
429
  @override
418
430
  def get_lc_namespace(cls) -> list[str]:
431
+ """Get the namespace of the langchain object.
432
+
433
+ Returns:
434
+ ``["langchain", "schema", "runnable"]``
435
+ """
419
436
  return ["langchain", "schema", "runnable"]
420
437
 
421
438
  @override
@@ -688,13 +705,13 @@ class RunnablePick(RunnableSerializable[dict[str, Any], dict[str, Any]]):
688
705
  from langchain_core.runnables.passthrough import RunnablePick
689
706
 
690
707
  input_data = {
691
- 'name': 'John',
692
- 'age': 30,
693
- 'city': 'New York',
694
- 'country': 'USA'
708
+ "name": "John",
709
+ "age": 30,
710
+ "city": "New York",
711
+ "country": "USA",
695
712
  }
696
713
 
697
- runnable = RunnablePick(keys=['name', 'age'])
714
+ runnable = RunnablePick(keys=["name", "age"])
698
715
 
699
716
  output_data = runnable.invoke(input_data)
700
717
 
@@ -715,12 +732,17 @@ class RunnablePick(RunnableSerializable[dict[str, Any], dict[str, Any]]):
715
732
  @classmethod
716
733
  @override
717
734
  def is_lc_serializable(cls) -> bool:
735
+ """Return True as this class is serializable."""
718
736
  return True
719
737
 
720
738
  @classmethod
721
739
  @override
722
740
  def get_lc_namespace(cls) -> list[str]:
723
- """Get the namespace of the langchain object."""
741
+ """Get the namespace of the langchain object.
742
+
743
+ Returns:
744
+ ``["langchain", "schema", "runnable"]``
745
+ """
724
746
  return ["langchain", "schema", "runnable"]
725
747
 
726
748
  @override
@@ -730,7 +752,8 @@ class RunnablePick(RunnableSerializable[dict[str, Any], dict[str, Any]]):
730
752
  name = (
731
753
  name
732
754
  or self.name
733
- or f"RunnablePick<{','.join([self.keys] if isinstance(self.keys, str) else self.keys)}>" # noqa: E501
755
+ or "RunnablePick"
756
+ f"<{','.join([self.keys] if isinstance(self.keys, str) else self.keys)}>"
734
757
  )
735
758
  return super().get_name(suffix, name=name)
736
759
 
@@ -66,17 +66,21 @@ class RunnableRetry(RunnableBindingBase[Input, Output]): # type: ignore[no-rede
66
66
 
67
67
  import time
68
68
 
69
+
69
70
  def foo(input) -> None:
70
71
  '''Fake function that raises an exception.'''
71
72
  raise ValueError(f"Invoking foo failed. At time {time.time()}")
72
73
 
74
+
73
75
  runnable = RunnableLambda(foo)
74
76
 
75
77
  runnable_with_retries = runnable.with_retry(
76
- retry_if_exception_type=(ValueError,), # Retry only on ValueError
77
- wait_exponential_jitter=True, # Add jitter to the exponential backoff
78
- stop_after_attempt=2, # Try twice
79
- exponential_jitter_params={"initial": 2}, # if desired, customize backoff
78
+ retry_if_exception_type=(ValueError,), # Retry only on ValueError
79
+ wait_exponential_jitter=True, # Add jitter to the exponential backoff
80
+ stop_after_attempt=2, # Try twice
81
+ exponential_jitter_params={
82
+ "initial": 2
83
+ }, # if desired, customize backoff
80
84
  )
81
85
 
82
86
  # The method invocation above is equivalent to the longer form below:
@@ -111,7 +115,7 @@ class RunnableRetry(RunnableBindingBase[Input, Output]): # type: ignore[no-rede
111
115
  chain = template | model
112
116
  retryable_chain = chain.with_retry()
113
117
 
114
- """ # noqa: E501
118
+ """
115
119
 
116
120
  retry_exception_types: tuple[type[BaseException], ...] = (Exception,)
117
121
  """The exception types to retry on. By default all exceptions are retried.
@@ -234,31 +238,40 @@ class RunnableRetry(RunnableBindingBase[Input, Output]): # type: ignore[no-rede
234
238
  ) -> list[Union[Output, Exception]]:
235
239
  results_map: dict[int, Output] = {}
236
240
 
237
- def pending(iterable: list[U]) -> list[U]:
238
- return [item for idx, item in enumerate(iterable) if idx not in results_map]
239
-
240
241
  not_set: list[Output] = []
241
242
  result = not_set
242
243
  try:
243
244
  for attempt in self._sync_retrying():
244
245
  with attempt:
245
- # Get the results of the inputs that have not succeeded yet.
246
+ # Retry for inputs that have not yet succeeded
247
+ # Determine which original indices remain.
248
+ remaining_indices = [
249
+ i for i in range(len(inputs)) if i not in results_map
250
+ ]
251
+ if not remaining_indices:
252
+ break
253
+ pending_inputs = [inputs[i] for i in remaining_indices]
254
+ pending_configs = [config[i] for i in remaining_indices]
255
+ pending_run_managers = [run_manager[i] for i in remaining_indices]
256
+ # Invoke underlying batch only on remaining elements.
246
257
  result = super().batch(
247
- pending(inputs),
258
+ pending_inputs,
248
259
  self._patch_config_list(
249
- pending(config), pending(run_manager), attempt.retry_state
260
+ pending_configs, pending_run_managers, attempt.retry_state
250
261
  ),
251
262
  return_exceptions=True,
252
263
  **kwargs,
253
264
  )
254
- # Register the results of the inputs that have succeeded.
265
+ # Register the results of the inputs that have succeeded, mapping
266
+ # back to their original indices.
255
267
  first_exception = None
256
- for i, r in enumerate(result):
268
+ for offset, r in enumerate(result):
257
269
  if isinstance(r, Exception):
258
270
  if not first_exception:
259
271
  first_exception = r
260
272
  continue
261
- results_map[i] = r
273
+ orig_idx = remaining_indices[offset]
274
+ results_map[orig_idx] = r
262
275
  # If any exception occurred, raise it, to retry the failed ones
263
276
  if first_exception:
264
277
  raise first_exception
@@ -301,31 +314,39 @@ class RunnableRetry(RunnableBindingBase[Input, Output]): # type: ignore[no-rede
301
314
  ) -> list[Union[Output, Exception]]:
302
315
  results_map: dict[int, Output] = {}
303
316
 
304
- def pending(iterable: list[U]) -> list[U]:
305
- return [item for idx, item in enumerate(iterable) if idx not in results_map]
306
-
307
317
  not_set: list[Output] = []
308
318
  result = not_set
309
319
  try:
310
320
  async for attempt in self._async_retrying():
311
321
  with attempt:
312
- # Get the results of the inputs that have not succeeded yet.
322
+ # Retry for inputs that have not yet succeeded
323
+ # Determine which original indices remain.
324
+ remaining_indices = [
325
+ i for i in range(len(inputs)) if i not in results_map
326
+ ]
327
+ if not remaining_indices:
328
+ break
329
+ pending_inputs = [inputs[i] for i in remaining_indices]
330
+ pending_configs = [config[i] for i in remaining_indices]
331
+ pending_run_managers = [run_manager[i] for i in remaining_indices]
313
332
  result = await super().abatch(
314
- pending(inputs),
333
+ pending_inputs,
315
334
  self._patch_config_list(
316
- pending(config), pending(run_manager), attempt.retry_state
335
+ pending_configs, pending_run_managers, attempt.retry_state
317
336
  ),
318
337
  return_exceptions=True,
319
338
  **kwargs,
320
339
  )
321
- # Register the results of the inputs that have succeeded.
340
+ # Register the results of the inputs that have succeeded, mapping
341
+ # back to their original indices.
322
342
  first_exception = None
323
- for i, r in enumerate(result):
343
+ for offset, r in enumerate(result):
324
344
  if isinstance(r, Exception):
325
345
  if not first_exception:
326
346
  first_exception = r
327
347
  continue
328
- results_map[i] = r
348
+ orig_idx = remaining_indices[offset]
349
+ results_map[orig_idx] = r
329
350
  # If any exception occurred, raise it, to retry the failed ones
330
351
  if first_exception:
331
352
  raise first_exception
@@ -38,15 +38,12 @@ if TYPE_CHECKING:
38
38
 
39
39
 
40
40
  class RouterInput(TypedDict):
41
- """Router input.
42
-
43
- Attributes:
44
- key: The key to route on.
45
- input: The input to pass to the selected Runnable.
46
- """
41
+ """Router input."""
47
42
 
48
43
  key: str
44
+ """The key to route on."""
49
45
  input: Any
46
+ """The input to pass to the selected Runnable."""
50
47
 
51
48
 
52
49
  class RouterRunnable(RunnableSerializable[RouterInput, Output]):
@@ -98,13 +95,17 @@ class RouterRunnable(RunnableSerializable[RouterInput, Output]):
98
95
  @classmethod
99
96
  @override
100
97
  def is_lc_serializable(cls) -> bool:
101
- """Return whether this class is serializable."""
98
+ """Return True as this class is serializable."""
102
99
  return True
103
100
 
104
101
  @classmethod
105
102
  @override
106
103
  def get_lc_namespace(cls) -> list[str]:
107
- """Get the namespace of the langchain object."""
104
+ """Get the namespace of the langchain object.
105
+
106
+ Returns:
107
+ ``["langchain", "schema", "runnable"]``
108
+ """
108
109
  return ["langchain", "schema", "runnable"]
109
110
 
110
111
  @override
@@ -51,9 +51,11 @@ class BaseStreamEvent(TypedDict):
51
51
 
52
52
  from langchain_core.runnables import RunnableLambda
53
53
 
54
+
54
55
  async def reverse(s: str) -> str:
55
56
  return s[::-1]
56
57
 
58
+
57
59
  chain = RunnableLambda(func=reverse)
58
60
 
59
61
  events = [event async for event in chain.astream_events("hello")]
@@ -122,7 +122,12 @@ def accepts_context(callable: Callable[..., Any]) -> bool: # noqa: A002
122
122
 
123
123
  @lru_cache(maxsize=1)
124
124
  def asyncio_accepts_context() -> bool:
125
- """Cache the result of checking if asyncio.create_task accepts a ``context`` arg."""
125
+ """Cache the result of checking if asyncio.create_task accepts a ``context`` arg.
126
+
127
+ Returns:
128
+ bool: True if ``asyncio.create_task`` accepts a context argument, False
129
+ otherwise.
130
+ """
126
131
  return accepts_context(asyncio.create_task)
127
132
 
128
133
 
@@ -160,14 +165,11 @@ class IsLocalDict(ast.NodeVisitor):
160
165
  self.keys = keys
161
166
 
162
167
  @override
163
- def visit_Subscript(self, node: ast.Subscript) -> Any:
168
+ def visit_Subscript(self, node: ast.Subscript) -> None:
164
169
  """Visit a subscript node.
165
170
 
166
171
  Args:
167
172
  node: The node to visit.
168
-
169
- Returns:
170
- Any: The result of the visit.
171
173
  """
172
174
  if (
173
175
  isinstance(node.ctx, ast.Load)
@@ -180,14 +182,11 @@ class IsLocalDict(ast.NodeVisitor):
180
182
  self.keys.add(node.slice.value)
181
183
 
182
184
  @override
183
- def visit_Call(self, node: ast.Call) -> Any:
185
+ def visit_Call(self, node: ast.Call) -> None:
184
186
  """Visit a call node.
185
187
 
186
188
  Args:
187
189
  node: The node to visit.
188
-
189
- Returns:
190
- Any: The result of the visit.
191
190
  """
192
191
  if (
193
192
  isinstance(node.func, ast.Attribute)
@@ -210,14 +209,11 @@ class IsFunctionArgDict(ast.NodeVisitor):
210
209
  self.keys: set[str] = set()
211
210
 
212
211
  @override
213
- def visit_Lambda(self, node: ast.Lambda) -> Any:
212
+ def visit_Lambda(self, node: ast.Lambda) -> None:
214
213
  """Visit a lambda function.
215
214
 
216
215
  Args:
217
216
  node: The node to visit.
218
-
219
- Returns:
220
- Any: The result of the visit.
221
217
  """
222
218
  if not node.args.args:
223
219
  return
@@ -225,14 +221,11 @@ class IsFunctionArgDict(ast.NodeVisitor):
225
221
  IsLocalDict(input_arg_name, self.keys).visit(node.body)
226
222
 
227
223
  @override
228
- def visit_FunctionDef(self, node: ast.FunctionDef) -> Any:
224
+ def visit_FunctionDef(self, node: ast.FunctionDef) -> None:
229
225
  """Visit a function definition.
230
226
 
231
227
  Args:
232
228
  node: The node to visit.
233
-
234
- Returns:
235
- Any: The result of the visit.
236
229
  """
237
230
  if not node.args.args:
238
231
  return
@@ -240,14 +233,11 @@ class IsFunctionArgDict(ast.NodeVisitor):
240
233
  IsLocalDict(input_arg_name, self.keys).visit(node)
241
234
 
242
235
  @override
243
- def visit_AsyncFunctionDef(self, node: ast.AsyncFunctionDef) -> Any:
236
+ def visit_AsyncFunctionDef(self, node: ast.AsyncFunctionDef) -> None:
244
237
  """Visit an async function definition.
245
238
 
246
239
  Args:
247
240
  node: The node to visit.
248
-
249
- Returns:
250
- Any: The result of the visit.
251
241
  """
252
242
  if not node.args.args:
253
243
  return
@@ -264,14 +254,11 @@ class NonLocals(ast.NodeVisitor):
264
254
  self.stores: set[str] = set()
265
255
 
266
256
  @override
267
- def visit_Name(self, node: ast.Name) -> Any:
257
+ def visit_Name(self, node: ast.Name) -> None:
268
258
  """Visit a name node.
269
259
 
270
260
  Args:
271
261
  node: The node to visit.
272
-
273
- Returns:
274
- Any: The result of the visit.
275
262
  """
276
263
  if isinstance(node.ctx, ast.Load):
277
264
  self.loads.add(node.id)
@@ -279,14 +266,11 @@ class NonLocals(ast.NodeVisitor):
279
266
  self.stores.add(node.id)
280
267
 
281
268
  @override
282
- def visit_Attribute(self, node: ast.Attribute) -> Any:
269
+ def visit_Attribute(self, node: ast.Attribute) -> None:
283
270
  """Visit an attribute node.
284
271
 
285
272
  Args:
286
273
  node: The node to visit.
287
-
288
- Returns:
289
- Any: The result of the visit.
290
274
  """
291
275
  if isinstance(node.ctx, ast.Load):
292
276
  parent = node.value
@@ -321,42 +305,33 @@ class FunctionNonLocals(ast.NodeVisitor):
321
305
  self.nonlocals: set[str] = set()
322
306
 
323
307
  @override
324
- def visit_FunctionDef(self, node: ast.FunctionDef) -> Any:
308
+ def visit_FunctionDef(self, node: ast.FunctionDef) -> None:
325
309
  """Visit a function definition.
326
310
 
327
311
  Args:
328
312
  node: The node to visit.
329
-
330
- Returns:
331
- Any: The result of the visit.
332
313
  """
333
314
  visitor = NonLocals()
334
315
  visitor.visit(node)
335
316
  self.nonlocals.update(visitor.loads - visitor.stores)
336
317
 
337
318
  @override
338
- def visit_AsyncFunctionDef(self, node: ast.AsyncFunctionDef) -> Any:
319
+ def visit_AsyncFunctionDef(self, node: ast.AsyncFunctionDef) -> None:
339
320
  """Visit an async function definition.
340
321
 
341
322
  Args:
342
323
  node: The node to visit.
343
-
344
- Returns:
345
- Any: The result of the visit.
346
324
  """
347
325
  visitor = NonLocals()
348
326
  visitor.visit(node)
349
327
  self.nonlocals.update(visitor.loads - visitor.stores)
350
328
 
351
329
  @override
352
- def visit_Lambda(self, node: ast.Lambda) -> Any:
330
+ def visit_Lambda(self, node: ast.Lambda) -> None:
353
331
  """Visit a lambda function.
354
332
 
355
333
  Args:
356
334
  node: The node to visit.
357
-
358
- Returns:
359
- Any: The result of the visit.
360
335
  """
361
336
  visitor = NonLocals()
362
337
  visitor.visit(node)
@@ -372,14 +347,11 @@ class GetLambdaSource(ast.NodeVisitor):
372
347
  self.count = 0
373
348
 
374
349
  @override
375
- def visit_Lambda(self, node: ast.Lambda) -> Any:
350
+ def visit_Lambda(self, node: ast.Lambda) -> None:
376
351
  """Visit a lambda function.
377
352
 
378
353
  Args:
379
354
  node: The node to visit.
380
-
381
- Returns:
382
- Any: The result of the visit.
383
355
  """
384
356
  self.count += 1
385
357
  if hasattr(ast, "unparse"):
@@ -496,6 +468,9 @@ class AddableDict(dict[str, Any]):
496
468
 
497
469
  Args:
498
470
  other: The other dictionary to add.
471
+
472
+ Returns:
473
+ A dictionary that is the result of adding the two dictionaries.
499
474
  """
500
475
  chunk = AddableDict(self)
501
476
  for key in other:
@@ -514,6 +489,9 @@ class AddableDict(dict[str, Any]):
514
489
 
515
490
  Args:
516
491
  other: The other dictionary to be added to.
492
+
493
+ Returns:
494
+ A dictionary that is the result of adding the two dictionaries.
517
495
  """
518
496
  chunk = AddableDict(other)
519
497
  for key in self:
@@ -573,22 +551,18 @@ async def aadd(addables: AsyncIterable[Addable]) -> Optional[Addable]:
573
551
 
574
552
 
575
553
  class ConfigurableField(NamedTuple):
576
- """Field that can be configured by the user.
577
-
578
- Parameters:
579
- id: The unique identifier of the field.
580
- name: The name of the field. Defaults to None.
581
- description: The description of the field. Defaults to None.
582
- annotation: The annotation of the field. Defaults to None.
583
- is_shared: Whether the field is shared. Defaults to False.
584
- """
554
+ """Field that can be configured by the user."""
585
555
 
586
556
  id: str
587
-
557
+ """The unique identifier of the field."""
588
558
  name: Optional[str] = None
559
+ """The name of the field. Defaults to None."""
589
560
  description: Optional[str] = None
561
+ """The description of the field. Defaults to None."""
590
562
  annotation: Optional[Any] = None
563
+ """The annotation of the field. Defaults to None."""
591
564
  is_shared: bool = False
565
+ """Whether the field is shared. Defaults to False."""
592
566
 
593
567
  @override
594
568
  def __hash__(self) -> int:
@@ -596,24 +570,20 @@ class ConfigurableField(NamedTuple):
596
570
 
597
571
 
598
572
  class ConfigurableFieldSingleOption(NamedTuple):
599
- """Field that can be configured by the user with a default value.
600
-
601
- Parameters:
602
- id: The unique identifier of the field.
603
- options: The options for the field.
604
- default: The default value for the field.
605
- name: The name of the field. Defaults to None.
606
- description: The description of the field. Defaults to None.
607
- is_shared: Whether the field is shared. Defaults to False.
608
- """
573
+ """Field that can be configured by the user with a default value."""
609
574
 
610
575
  id: str
576
+ """The unique identifier of the field."""
611
577
  options: Mapping[str, Any]
578
+ """The options for the field."""
612
579
  default: str
613
-
580
+ """The default value for the field."""
614
581
  name: Optional[str] = None
582
+ """The name of the field. Defaults to None."""
615
583
  description: Optional[str] = None
584
+ """The description of the field. Defaults to None."""
616
585
  is_shared: bool = False
586
+ """Whether the field is shared. Defaults to False."""
617
587
 
618
588
  @override
619
589
  def __hash__(self) -> int:
@@ -621,24 +591,20 @@ class ConfigurableFieldSingleOption(NamedTuple):
621
591
 
622
592
 
623
593
  class ConfigurableFieldMultiOption(NamedTuple):
624
- """Field that can be configured by the user with multiple default values.
625
-
626
- Parameters:
627
- id: The unique identifier of the field.
628
- options: The options for the field.
629
- default: The default values for the field.
630
- name: The name of the field. Defaults to None.
631
- description: The description of the field. Defaults to None.
632
- is_shared: Whether the field is shared. Defaults to False.
633
- """
594
+ """Field that can be configured by the user with multiple default values."""
634
595
 
635
596
  id: str
597
+ """The unique identifier of the field."""
636
598
  options: Mapping[str, Any]
599
+ """The options for the field."""
637
600
  default: Sequence[str]
638
-
601
+ """The default values for the field."""
639
602
  name: Optional[str] = None
603
+ """The name of the field. Defaults to None."""
640
604
  description: Optional[str] = None
605
+ """The description of the field. Defaults to None."""
641
606
  is_shared: bool = False
607
+ """Whether the field is shared. Defaults to False."""
642
608
 
643
609
  @override
644
610
  def __hash__(self) -> int:
@@ -651,26 +617,22 @@ AnyConfigurableField = Union[
651
617
 
652
618
 
653
619
  class ConfigurableFieldSpec(NamedTuple):
654
- """Field that can be configured by the user. It is a specification of a field.
655
-
656
- Parameters:
657
- id: The unique identifier of the field.
658
- annotation: The annotation of the field.
659
- name: The name of the field. Defaults to None.
660
- description: The description of the field. Defaults to None.
661
- default: The default value for the field. Defaults to None.
662
- is_shared: Whether the field is shared. Defaults to False.
663
- dependencies: The dependencies of the field. Defaults to None.
664
- """
620
+ """Field that can be configured by the user. It is a specification of a field."""
665
621
 
666
622
  id: str
623
+ """The unique identifier of the field."""
667
624
  annotation: Any
668
-
625
+ """The annotation of the field."""
669
626
  name: Optional[str] = None
627
+ """The name of the field. Defaults to None."""
670
628
  description: Optional[str] = None
629
+ """The description of the field. Defaults to None."""
671
630
  default: Any = None
631
+ """The default value for the field. Defaults to None."""
672
632
  is_shared: bool = False
633
+ """Whether the field is shared. Defaults to False."""
673
634
  dependencies: Optional[list[str]] = None
635
+ """The dependencies of the field. Defaults to None."""
674
636
 
675
637
 
676
638
  def get_unique_config_specs(