Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package python-langchain-core for
openSUSE:Factory checked in at 2026-07-26 11:29:59
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-langchain-core (Old)
and /work/SRC/openSUSE:Factory/.python-langchain-core.new.2004 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-langchain-core"
Sun Jul 26 11:29:59 2026 rev:4 rq:1367769 version:1.5.1
Changes:
--------
---
/work/SRC/openSUSE:Factory/python-langchain-core/python-langchain-core.changes
2026-07-21 23:10:22.078230920 +0200
+++
/work/SRC/openSUSE:Factory/.python-langchain-core.new.2004/python-langchain-core.changes
2026-07-26 11:32:37.115279587 +0200
@@ -1,0 +2,9 @@
+Sat Jul 25 19:01:38 UTC 2026 - Martin Pluskal <[email protected]>
+
+- Update to version 1.5.1:
+ * Support the langsmith gateway through an environment
+ variable
+ * Use the tool_call_schema cache for BaseTool token counting
+ in count_tokens_approximately
+
+-------------------------------------------------------------------
Old:
----
langchain_core-1.5.0.tar.gz
New:
----
langchain_core-1.5.1.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-langchain-core.spec ++++++
--- /var/tmp/diff_new_pack.QdzpoD/_old 2026-07-26 11:32:37.615296811 +0200
+++ /var/tmp/diff_new_pack.QdzpoD/_new 2026-07-26 11:32:37.615296811 +0200
@@ -17,7 +17,7 @@
Name: python-langchain-core
-Version: 1.5.0
+Version: 1.5.1
Release: 0
Summary: Building applications with LLMs through composability
License: MIT
++++++ langchain_core-1.5.0.tar.gz -> langchain_core-1.5.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/langchain_core-1.5.0/PKG-INFO
new/langchain_core-1.5.1/PKG-INFO
--- old/langchain_core-1.5.0/PKG-INFO 2020-02-02 01:00:00.000000000 +0100
+++ new/langchain_core-1.5.1/PKG-INFO 2020-02-02 01:00:00.000000000 +0100
@@ -1,6 +1,6 @@
Metadata-Version: 2.4
Name: langchain-core
-Version: 1.5.0
+Version: 1.5.1
Summary: Building applications with LLMs through composability
Project-URL: Homepage, https://docs.langchain.com/
Project-URL: Documentation,
https://reference.langchain.com/python/langchain_core/
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/langchain_core-1.5.0/langchain_core/messages/utils.py
new/langchain_core-1.5.1/langchain_core/messages/utils.py
--- old/langchain_core-1.5.0/langchain_core/messages/utils.py 2020-02-02
01:00:00.000000000 +0100
+++ new/langchain_core-1.5.1/langchain_core/messages/utils.py 2020-02-02
01:00:00.000000000 +0100
@@ -47,7 +47,7 @@
from langchain_core.messages.modifier import RemoveMessage
from langchain_core.messages.system import SystemMessage, SystemMessageChunk
from langchain_core.messages.tool import ToolCall, ToolMessage,
ToolMessageChunk
-from langchain_core.utils.function_calling import convert_to_openai_tool
+from langchain_core.utils.pydantic import model_json_schema as
get_model_json_schema
if TYPE_CHECKING:
from langchain_core.language_models import BaseLanguageModel
@@ -2274,9 +2274,10 @@
using the **most recent** AI message that has
`usage_metadata['total_tokens']`. The scaling factor is:
`AI_total_tokens / approx_tokens_up_to_that_AI_message`
- tools: List of tools to include in the token count. Each tool can be
either
- a `BaseTool` instance or a dict representing a tool schema.
`BaseTool`
- instances are converted to OpenAI tool format before counting.
+ tools: List of tools to include in the token count. Each tool can be a
+ `BaseTool` instance, a dict representing a tool schema, or a plain
+ callable. `BaseTool` instances and callables are converted to
+ OpenAI tool format before counting.
Returns:
Approximate number of tokens in the messages (and tools, if provided).
@@ -2304,7 +2305,24 @@
if tools:
tools_chars = 0
for tool in tools:
- tool_dict = tool if isinstance(tool, dict) else
convert_to_openai_tool(tool)
+ if isinstance(tool, dict):
+ tool_dict = tool
+ else:
+ # tool_call_schema is memoized per instance
+ schema = tool.tool_call_schema
+ if isinstance(schema, dict):
+ parameters = dict(schema)
+ else:
+ parameters = dict(get_model_json_schema(schema))
+ # Drop the schema's own `title`/`description` to avoid
double-counting:
+ # they're duplicated at the top level.
+ parameters.pop("title", None)
+ parameters.pop("description", None)
+ tool_dict = {
+ "name": tool.name,
+ "description": tool.description,
+ "parameters": parameters,
+ }
tools_chars += len(json.dumps(tool_dict))
token_count += math.ceil(tools_chars / chars_per_token)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/langchain_core-1.5.0/langchain_core/utils/_gateway.py
new/langchain_core-1.5.1/langchain_core/utils/_gateway.py
--- old/langchain_core-1.5.0/langchain_core/utils/_gateway.py 1970-01-01
01:00:00.000000000 +0100
+++ new/langchain_core-1.5.1/langchain_core/utils/_gateway.py 2020-02-02
01:00:00.000000000 +0100
@@ -0,0 +1,229 @@
+"""Private helpers for resolving LangSmith gateway configuration.
+
+The [LangSmith LLM gateway](https://docs.langchain.com/langsmith/llm-gateway)
+lets a chat model reach a provider through a proxy configured via environment
+variables. These helpers centralize the (non-trivial) precedence rules so that
+each provider integration resolves its base URL and API key identically.
+
+This module is private: the API is not stable and may change without notice.
+"""
+
+from __future__ import annotations
+
+import os
+from typing import TYPE_CHECKING, Any, NamedTuple
+
+from pydantic import SecretStr
+
+if TYPE_CHECKING:
+ from collections.abc import Sequence
+
+ from pydantic import BaseModel
+
+_LANGSMITH_GATEWAY_ENV = "LANGSMITH_GATEWAY"
+_LANGSMITH_GATEWAY_API_KEY_ENV = "LANGSMITH_GATEWAY_API_KEY"
+_LANGSMITH_GATEWAY_DEFAULT_BASE = "https://gateway.smith.langchain.com"
+
+_TRUE_VALUES = ("true", "1", "yes")
+_FALSE_VALUES = ("false", "0", "no")
+
+
+class GatewayConfig(NamedTuple):
+ """Resolved gateway configuration.
+
+ Attributes:
+ base_url: The base URL the client should use, or None to defer to the
+ provider SDK's own default.
+ api_key: The API key to use. A ``SecretStr`` when derived from the
+ environment; the caller's value returned unchanged when one was
+ passed explicitly; None when no key could be resolved.
+ base_url_from_gateway: Whether ``base_url`` was populated from the
+ LangSmith gateway (as opposed to an explicit value, a provider env
+ var, or a default).
+ """
+
+ base_url: str | None
+ api_key: Any
+ base_url_from_gateway: bool
+
+
+def _first_env(names: str | Sequence[str]) -> str | None:
+ """Return the first non-empty value among ``names``, or None."""
+ if isinstance(names, str):
+ names = (names,)
+ for name in names:
+ value = os.getenv(name)
+ if value:
+ return value
+ return None
+
+
+def _resolve_gateway_base_url(provider_path: str) -> str | None:
+ """Resolve the LangSmith gateway base URL for a provider.
+
+ ``LANGSMITH_GATEWAY`` accepts either a boolean-ish string or an explicit
+ base URL:
+
+ - ``true`` / ``1`` / ``yes`` -> the default gateway host.
+ - ``false`` / ``0`` / ``no`` / unset -> the gateway is disabled (None).
+ - anything else -> treated as a custom gateway base URL.
+
+ The provider-specific path is appended in all enabled cases.
+
+ Args:
+ provider_path: Path segment for the provider, e.g. ``"openai/v1"`` or
+ ``"anthropic"``.
+
+ Returns:
+ The provider base URL on the gateway, or None if the gateway is
+ disabled.
+ """
+ raw = os.getenv(_LANGSMITH_GATEWAY_ENV)
+ if raw is None or raw.lower() in _FALSE_VALUES:
+ return None
+ base = (
+ _LANGSMITH_GATEWAY_DEFAULT_BASE
+ if raw.lower() in _TRUE_VALUES
+ else raw.rstrip("/")
+ )
+ return f"{base}/{provider_path}"
+
+
+def _resolve_gateway_config(
+ *,
+ base_url: str | None,
+ api_key: Any,
+ provider_path: str,
+ base_url_env: str | Sequence[str] = (),
+ api_key_env: str | Sequence[str] = (),
+ default_base_url: str | None = None,
+) -> GatewayConfig:
+ """Resolve a provider's base URL and API key, applying gateway settings.
+
+ Precedence:
+
+ - **base_url:** explicit ``base_url`` > ``base_url_env`` > LangSmith
gateway
+ > ``default_base_url``.
+ - **api_key:** explicit ``api_key`` (returned unchanged) > the gateway key
if
+ the base URL came from the gateway, otherwise the provider key > the
other.
+ The gateway key is only a candidate when the gateway is enabled.
+
+ The provenance flip on the key means an ``OPENAI_API_KEY``-style provider
key
+ is preferred whenever the caller pointed the base URL at a non-gateway
+ endpoint (so a stray gateway key is not sent to the provider), while the
+ gateway key wins for the common "just enable the gateway" setup even if a
+ provider key happens to be present in the environment.
+
+ Args:
+ base_url: Explicitly-provided base URL (e.g. a ``base_url`` kwarg), or
+ None if not set by the caller.
+ api_key: Explicitly-provided API key, or None if not set by the caller.
+ Returned unchanged when not None, so a caller-supplied value
(secret
+ or callable) always wins.
+ provider_path: Path segment appended to the gateway host.
+ base_url_env: Env var name(s) for the provider base URL, in priority
+ order.
+ api_key_env: Env var name(s) for the provider API key, in priority
order.
+ default_base_url: Base URL used when nothing else is set.
+
+ Returns:
+ The resolved `GatewayConfig`.
+ """
+ gateway_base_url = _resolve_gateway_base_url(provider_path)
+
+ resolved_base_url = base_url
+ base_url_from_gateway = False
+ if resolved_base_url is None:
+ resolved_base_url = _first_env(base_url_env)
+ if resolved_base_url is None:
+ if gateway_base_url is not None:
+ resolved_base_url = gateway_base_url
+ base_url_from_gateway = True
+ else:
+ resolved_base_url = default_base_url
+
+ if api_key is not None:
+ resolved_api_key: Any = api_key
+ else:
+ gateway_api_key = (
+ os.getenv(_LANGSMITH_GATEWAY_API_KEY_ENV)
+ if gateway_base_url is not None
+ else None
+ )
+ provider_api_key = _first_env(api_key_env)
+ chosen = (
+ (gateway_api_key or provider_api_key)
+ if base_url_from_gateway
+ else (provider_api_key or gateway_api_key)
+ )
+ resolved_api_key = SecretStr(chosen) if chosen else None
+
+ return GatewayConfig(resolved_base_url, resolved_api_key,
base_url_from_gateway)
+
+
+def _pop_provided(values: dict[str, Any], cls: type[BaseModel], field: str) ->
Any:
+ """Pop a caller-provided field value by name or alias; None if absent.
+
+ Handles models with ``populate_by_name=True``, where a field may be
supplied
+ under either its name or its alias. Both keys are removed so the resolved
+ value can be written back canonically under the field name. The alias is
read
+ from the model rather than hard-coded, so callers pass only field names.
+ """
+ value = values.pop(field, None)
+ alias = cls.model_fields[field].alias
+ if alias is not None:
+ alias_value = values.pop(alias, None)
+ if value is None:
+ value = alias_value
+ return value
+
+
+def _apply_gateway_config(
+ values: dict[str, Any],
+ cls: type[BaseModel],
+ *,
+ base_url_field: str,
+ api_key_field: str,
+ provider_path: str,
+ base_url_env: str | Sequence[str] = (),
+ api_key_env: str | Sequence[str] = (),
+ default_base_url: str | None = None,
+) -> GatewayConfig:
+ """Resolve gateway settings from a model's raw input in a "before"
validator.
+
+ Reads the caller-provided base URL and API key (by field name or alias),
+ resolves them against the gateway and provider env vars via
+ `_resolve_gateway_config`, then writes the results back into ``values``
under
+ the canonical field names. This lets a provider integration keep a
+ non-optional key field: the resolved value is injected before field
+ validation runs, so the field always receives a concrete value.
+
+ The resolved API key is written only when non-None, so the field's own
+ default applies when no key is found. Returns the `GatewayConfig` so the
+ caller can, for example, raise when a required key is missing.
+
+ Args:
+ values: The raw input mapping passed to the model, mutated in place.
+ cls: The model class, used to look up field aliases.
+ base_url_field: Name of the base URL field (e.g.
``"anthropic_api_url"``).
+ api_key_field: Name of the API key field (e.g.
``"anthropic_api_key"``).
+ provider_path: Path segment appended to the gateway host.
+ base_url_env: Env var name(s) for the provider base URL.
+ api_key_env: Env var name(s) for the provider API key.
+ default_base_url: Base URL used when nothing else is set.
+
+ Returns:
+ The resolved `GatewayConfig`.
+ """
+ config = _resolve_gateway_config(
+ base_url=_pop_provided(values, cls, base_url_field),
+ api_key=_pop_provided(values, cls, api_key_field),
+ provider_path=provider_path,
+ base_url_env=base_url_env,
+ api_key_env=api_key_env,
+ default_base_url=default_base_url,
+ )
+ values[base_url_field] = config.base_url
+ if config.api_key is not None:
+ values[api_key_field] = config.api_key
+ return config
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/langchain_core-1.5.0/langchain_core/version.py
new/langchain_core-1.5.1/langchain_core/version.py
--- old/langchain_core-1.5.0/langchain_core/version.py 2020-02-02
01:00:00.000000000 +0100
+++ new/langchain_core-1.5.1/langchain_core/version.py 2020-02-02
01:00:00.000000000 +0100
@@ -1,3 +1,3 @@
"""Version information for `langchain-core`."""
-VERSION = "1.5.0"
+VERSION = "1.5.1"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/langchain_core-1.5.0/pyproject.toml
new/langchain_core-1.5.1/pyproject.toml
--- old/langchain_core-1.5.0/pyproject.toml 2020-02-02 01:00:00.000000000
+0100
+++ new/langchain_core-1.5.1/pyproject.toml 2020-02-02 01:00:00.000000000
+0100
@@ -21,7 +21,7 @@
"Topic :: Software Development :: Libraries :: Python Modules",
]
-version = "1.5.0"
+version = "1.5.1"
requires-python = ">=3.10.0,<4.0.0"
dependencies = [
"langsmith>=0.3.45,<1.0.0",
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/langchain_core-1.5.0/tests/unit_tests/messages/test_utils.py
new/langchain_core-1.5.1/tests/unit_tests/messages/test_utils.py
--- old/langchain_core-1.5.0/tests/unit_tests/messages/test_utils.py
2020-02-02 01:00:00.000000000 +0100
+++ new/langchain_core-1.5.1/tests/unit_tests/messages/test_utils.py
2020-02-02 01:00:00.000000000 +0100
@@ -29,7 +29,7 @@
merge_message_runs,
trim_messages,
)
-from langchain_core.tools import BaseTool, tool
+from langchain_core.tools import BaseTool, StructuredTool, tool
@pytest.mark.parametrize("msg_cls", [HumanMessage, AIMessage, SystemMessage])
@@ -2961,6 +2961,33 @@
assert count_empty_tools == base_count
+def test_count_tokens_approximately_basetool_dict_args_schema() -> None:
+ """`BaseTool.tool_call_schema` can itself already be a plain dict.
+
+ This happens when `args_schema` is given as a raw JSON schema instead of
+ a Pydantic model class -- there's no model class to call
+ `model_json_schema()` on in that case.
+ """
+ schema_dict = {
+ "title": "GetWeatherInput",
+ "type": "object",
+ "properties": {"location": {"type": "string"}},
+ "required": ["location"],
+ }
+ weather_tool = StructuredTool.from_function(
+ func=lambda location: f"Weather in {location}",
+ name="get_weather",
+ description="Get the weather for a location.",
+ args_schema=schema_dict,
+ )
+ assert isinstance(weather_tool.tool_call_schema, dict)
+
+ messages = [HumanMessage(content="Hello")]
+ base_count = count_tokens_approximately(messages)
+ count_with_tool = count_tokens_approximately(messages,
tools=[weather_tool])
+ assert count_with_tool > base_count
+
+
# ---------------------------------------------------------------------------
# `Serializable` constructor-envelope wire-shape acceptance in
`_convert_to_message`
# ---------------------------------------------------------------------------
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/langchain_core-1.5.0/tests/unit_tests/runnables/__snapshots__/test_fallbacks.ambr
new/langchain_core-1.5.1/tests/unit_tests/runnables/__snapshots__/test_fallbacks.ambr
---
old/langchain_core-1.5.0/tests/unit_tests/runnables/__snapshots__/test_fallbacks.ambr
2020-02-02 01:00:00.000000000 +0100
+++
new/langchain_core-1.5.1/tests/unit_tests/runnables/__snapshots__/test_fallbacks.ambr
2020-02-02 01:00:00.000000000 +0100
@@ -84,7 +84,7 @@
"fake",
"FakeListLLM"
],
- "repr": "FakeListLLM(metadata={'lc_versions':
{'langchain-core': '1.5.0'}}, responses=['foo'], i=1)",
+ "repr": "FakeListLLM(metadata={'lc_versions':
{'langchain-core': '1.5.1'}}, responses=['foo'], i=1)",
"name": "FakeListLLM"
}
},
@@ -128,7 +128,7 @@
"fake",
"FakeListLLM"
],
- "repr": "FakeListLLM(metadata={'lc_versions':
{'langchain-core': '1.5.0'}}, responses=['bar'])",
+ "repr": "FakeListLLM(metadata={'lc_versions':
{'langchain-core': '1.5.1'}}, responses=['bar'])",
"name": "FakeListLLM"
}
},
@@ -268,7 +268,7 @@
"fake",
"FakeListLLM"
],
- "repr": "FakeListLLM(metadata={'lc_versions': {'langchain-core':
'1.5.0'}}, responses=['foo'], i=1)",
+ "repr": "FakeListLLM(metadata={'lc_versions': {'langchain-core':
'1.5.1'}}, responses=['foo'], i=1)",
"name": "FakeListLLM"
},
"fallbacks": [
@@ -281,7 +281,7 @@
"fake",
"FakeListLLM"
],
- "repr": "FakeListLLM(metadata={'lc_versions': {'langchain-core':
'1.5.0'}}, responses=['bar'])",
+ "repr": "FakeListLLM(metadata={'lc_versions': {'langchain-core':
'1.5.1'}}, responses=['bar'])",
"name": "FakeListLLM"
}
],
@@ -322,7 +322,7 @@
"fake",
"FakeListLLM"
],
- "repr": "FakeListLLM(metadata={'lc_versions': {'langchain-core':
'1.5.0'}}, responses=['foo'], i=1)",
+ "repr": "FakeListLLM(metadata={'lc_versions': {'langchain-core':
'1.5.1'}}, responses=['foo'], i=1)",
"name": "FakeListLLM"
},
"fallbacks": [
@@ -335,7 +335,7 @@
"fake",
"FakeListLLM"
],
- "repr": "FakeListLLM(metadata={'lc_versions': {'langchain-core':
'1.5.0'}}, responses=['baz'], i=1)",
+ "repr": "FakeListLLM(metadata={'lc_versions': {'langchain-core':
'1.5.1'}}, responses=['baz'], i=1)",
"name": "FakeListLLM"
},
{
@@ -347,7 +347,7 @@
"fake",
"FakeListLLM"
],
- "repr": "FakeListLLM(metadata={'lc_versions': {'langchain-core':
'1.5.0'}}, responses=['bar'])",
+ "repr": "FakeListLLM(metadata={'lc_versions': {'langchain-core':
'1.5.1'}}, responses=['bar'])",
"name": "FakeListLLM"
}
],
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/langchain_core-1.5.0/tests/unit_tests/runnables/__snapshots__/test_runnable.ambr
new/langchain_core-1.5.1/tests/unit_tests/runnables/__snapshots__/test_runnable.ambr
---
old/langchain_core-1.5.0/tests/unit_tests/runnables/__snapshots__/test_runnable.ambr
2020-02-02 01:00:00.000000000 +0100
+++
new/langchain_core-1.5.1/tests/unit_tests/runnables/__snapshots__/test_runnable.ambr
2020-02-02 01:00:00.000000000 +0100
@@ -97,7 +97,7 @@
"fake_chat_models",
"FakeListChatModel"
],
- "repr": "FakeListChatModel(metadata={'lc_versions':
{'langchain-core': '1.5.0'}}, responses=['foo, bar'])",
+ "repr": "FakeListChatModel(metadata={'lc_versions':
{'langchain-core': '1.5.1'}}, responses=['foo, bar'])",
"name": "FakeListChatModel"
}
],
@@ -227,7 +227,7 @@
"fake_chat_models",
"FakeListChatModel"
],
- "repr": "FakeListChatModel(metadata={'lc_versions':
{'langchain-core': '1.5.0'}}, responses=['baz, qux'])",
+ "repr": "FakeListChatModel(metadata={'lc_versions':
{'langchain-core': '1.5.1'}}, responses=['baz, qux'])",
"name": "FakeListChatModel"
}
],
@@ -346,7 +346,7 @@
"fake_chat_models",
"FakeListChatModel"
],
- "repr": "FakeListChatModel(metadata={'lc_versions':
{'langchain-core': '1.5.0'}}, responses=['foo, bar'])",
+ "repr": "FakeListChatModel(metadata={'lc_versions':
{'langchain-core': '1.5.1'}}, responses=['foo, bar'])",
"name": "FakeListChatModel"
},
{
@@ -457,7 +457,7 @@
"fake_chat_models",
"FakeListChatModel"
],
- "repr": "FakeListChatModel(metadata={'lc_versions':
{'langchain-core': '1.5.0'}}, responses=['baz, qux'])",
+ "repr": "FakeListChatModel(metadata={'lc_versions':
{'langchain-core': '1.5.1'}}, responses=['baz, qux'])",
"name": "FakeListChatModel"
}
],
@@ -848,7 +848,7 @@
"fake",
"FakeStreamingListLLM"
],
- "repr": "FakeStreamingListLLM(metadata={'lc_versions':
{'langchain-core': '1.5.0'}}, responses=['first item, second item, third
item'])",
+ "repr": "FakeStreamingListLLM(metadata={'lc_versions':
{'langchain-core': '1.5.1'}}, responses=['first item, second item, third
item'])",
"name": "FakeStreamingListLLM"
},
{
@@ -884,7 +884,7 @@
"fake",
"FakeStreamingListLLM"
],
- "repr": "FakeStreamingListLLM(metadata={'lc_versions':
{'langchain-core': '1.5.0'}}, responses=['this', 'is', 'a', 'test'])",
+ "repr": "FakeStreamingListLLM(metadata={'lc_versions':
{'langchain-core': '1.5.1'}}, responses=['this', 'is', 'a', 'test'])",
"name": "FakeStreamingListLLM"
}
},
@@ -1009,7 +1009,7 @@
# name: test_prompt_with_chat_model
'''
ChatPromptTemplate(input_variables=['question'], input_types={},
partial_variables={},
messages=[SystemMessagePromptTemplate(prompt=PromptTemplate(input_variables=[],
input_types={}, partial_variables={}, template='You are a nice assistant.'),
additional_kwargs={}),
HumanMessagePromptTemplate(prompt=PromptTemplate(input_variables=['question'],
input_types={}, partial_variables={}, template='{question}'),
additional_kwargs={})])
- | FakeListChatModel(metadata={'lc_versions': {'langchain-core': '1.5.0'}},
responses=['foo'])
+ | FakeListChatModel(metadata={'lc_versions': {'langchain-core': '1.5.1'}},
responses=['foo'])
'''
# ---
# name: test_prompt_with_chat_model.1
@@ -1109,7 +1109,7 @@
"fake_chat_models",
"FakeListChatModel"
],
- "repr": "FakeListChatModel(metadata={'lc_versions': {'langchain-core':
'1.5.0'}}, responses=['foo'])",
+ "repr": "FakeListChatModel(metadata={'lc_versions': {'langchain-core':
'1.5.1'}}, responses=['foo'])",
"name": "FakeListChatModel"
}
},
@@ -1220,7 +1220,7 @@
"fake_chat_models",
"FakeListChatModel"
],
- "repr": "FakeListChatModel(metadata={'lc_versions':
{'langchain-core': '1.5.0'}}, responses=['foo, bar'])",
+ "repr": "FakeListChatModel(metadata={'lc_versions':
{'langchain-core': '1.5.1'}}, responses=['foo, bar'])",
"name": "FakeListChatModel"
}
],
@@ -1249,7 +1249,7 @@
# name: test_prompt_with_chat_model_async
'''
ChatPromptTemplate(input_variables=['question'], input_types={},
partial_variables={},
messages=[SystemMessagePromptTemplate(prompt=PromptTemplate(input_variables=[],
input_types={}, partial_variables={}, template='You are a nice assistant.'),
additional_kwargs={}),
HumanMessagePromptTemplate(prompt=PromptTemplate(input_variables=['question'],
input_types={}, partial_variables={}, template='{question}'),
additional_kwargs={})])
- | FakeListChatModel(metadata={'lc_versions': {'langchain-core': '1.5.0'}},
responses=['foo'])
+ | FakeListChatModel(metadata={'lc_versions': {'langchain-core': '1.5.1'}},
responses=['foo'])
'''
# ---
# name: test_prompt_with_chat_model_async.1
@@ -1349,7 +1349,7 @@
"fake_chat_models",
"FakeListChatModel"
],
- "repr": "FakeListChatModel(metadata={'lc_versions': {'langchain-core':
'1.5.0'}}, responses=['foo'])",
+ "repr": "FakeListChatModel(metadata={'lc_versions': {'langchain-core':
'1.5.1'}}, responses=['foo'])",
"name": "FakeListChatModel"
}
},
@@ -1459,7 +1459,7 @@
"fake",
"FakeListLLM"
],
- "repr": "FakeListLLM(metadata={'lc_versions': {'langchain-core':
'1.5.0'}}, responses=['foo', 'bar'])",
+ "repr": "FakeListLLM(metadata={'lc_versions': {'langchain-core':
'1.5.1'}}, responses=['foo', 'bar'])",
"name": "FakeListLLM"
}
},
@@ -1576,7 +1576,7 @@
"fake",
"FakeListLLM"
],
- "repr": "FakeListLLM(metadata={'lc_versions': {'langchain-core':
'1.5.0'}}, responses=['foo', 'bar'])",
+ "repr": "FakeListLLM(metadata={'lc_versions': {'langchain-core':
'1.5.1'}}, responses=['foo', 'bar'])",
"name": "FakeListLLM"
}
],
@@ -1699,7 +1699,7 @@
"fake",
"FakeStreamingListLLM"
],
- "repr": "FakeStreamingListLLM(metadata={'lc_versions':
{'langchain-core': '1.5.0'}}, responses=['bear, dog, cat', 'tomato, lettuce,
onion'])",
+ "repr": "FakeStreamingListLLM(metadata={'lc_versions':
{'langchain-core': '1.5.1'}}, responses=['bear, dog, cat', 'tomato, lettuce,
onion'])",
"name": "FakeStreamingListLLM"
}
],
@@ -1867,7 +1867,7 @@
"fake",
"FakeListLLM"
],
- "repr": "FakeListLLM(metadata={'lc_versions':
{'langchain-core': '1.5.0'}}, responses=['4'])",
+ "repr": "FakeListLLM(metadata={'lc_versions':
{'langchain-core': '1.5.1'}}, responses=['4'])",
"name": "FakeListLLM"
}
},
@@ -1940,7 +1940,7 @@
"fake",
"FakeListLLM"
],
- "repr": "FakeListLLM(metadata={'lc_versions':
{'langchain-core': '1.5.0'}}, responses=['2'])",
+ "repr": "FakeListLLM(metadata={'lc_versions':
{'langchain-core': '1.5.1'}}, responses=['2'])",
"name": "FakeListLLM"
}
},
@@ -13407,7 +13407,7 @@
just_to_test_lambda: RunnableLambda(...)
}
| ChatPromptTemplate(input_variables=['documents', 'question'],
input_types={}, partial_variables={},
messages=[SystemMessagePromptTemplate(prompt=PromptTemplate(input_variables=[],
input_types={}, partial_variables={}, template='You are a nice assistant.'),
additional_kwargs={}),
HumanMessagePromptTemplate(prompt=PromptTemplate(input_variables=['documents',
'question'], input_types={}, partial_variables={},
template='Context:\n{documents}\n\nQuestion:\n{question}'),
additional_kwargs={})])
- | FakeListChatModel(metadata={'lc_versions': {'langchain-core': '1.5.0'}},
responses=['foo, bar'])
+ | FakeListChatModel(metadata={'lc_versions': {'langchain-core': '1.5.1'}},
responses=['foo, bar'])
| CommaSeparatedListOutputParser()
'''
# ---
@@ -13610,7 +13610,7 @@
"fake_chat_models",
"FakeListChatModel"
],
- "repr": "FakeListChatModel(metadata={'lc_versions':
{'langchain-core': '1.5.0'}}, responses=['foo, bar'])",
+ "repr": "FakeListChatModel(metadata={'lc_versions':
{'langchain-core': '1.5.1'}}, responses=['foo, bar'])",
"name": "FakeListChatModel"
}
],
@@ -13636,8 +13636,8 @@
ChatPromptTemplate(input_variables=['question'], input_types={},
partial_variables={},
messages=[SystemMessagePromptTemplate(prompt=PromptTemplate(input_variables=[],
input_types={}, partial_variables={}, template='You are a nice assistant.'),
additional_kwargs={}),
HumanMessagePromptTemplate(prompt=PromptTemplate(input_variables=['question'],
input_types={}, partial_variables={}, template='{question}'),
additional_kwargs={})])
| RunnableLambda(...)
| {
- chat: FakeListChatModel(metadata={'lc_versions': {'langchain-core':
'1.5.0'}}, responses=["i'm a chatbot"]),
- llm: FakeListLLM(metadata={'lc_versions': {'langchain-core': '1.5.0'}},
responses=["i'm a textbot"])
+ chat: FakeListChatModel(metadata={'lc_versions': {'langchain-core':
'1.5.1'}}, responses=["i'm a chatbot"]),
+ llm: FakeListLLM(metadata={'lc_versions': {'langchain-core': '1.5.1'}},
responses=["i'm a textbot"])
}
'''
# ---
@@ -13762,7 +13762,7 @@
"fake_chat_models",
"FakeListChatModel"
],
- "repr": "FakeListChatModel(metadata={'lc_versions':
{'langchain-core': '1.5.0'}}, responses=[\"i'm a chatbot\"])",
+ "repr": "FakeListChatModel(metadata={'lc_versions':
{'langchain-core': '1.5.1'}}, responses=[\"i'm a chatbot\"])",
"name": "FakeListChatModel"
},
"llm": {
@@ -13774,7 +13774,7 @@
"fake",
"FakeListLLM"
],
- "repr": "FakeListLLM(metadata={'lc_versions': {'langchain-core':
'1.5.0'}}, responses=[\"i'm a textbot\"])",
+ "repr": "FakeListLLM(metadata={'lc_versions': {'langchain-core':
'1.5.1'}}, responses=[\"i'm a textbot\"])",
"name": "FakeListLLM"
}
}
@@ -13917,7 +13917,7 @@
"fake_chat_models",
"FakeListChatModel"
],
- "repr": "FakeListChatModel(metadata={'lc_versions':
{'langchain-core': '1.5.0'}}, responses=[\"i'm a chatbot\"])",
+ "repr": "FakeListChatModel(metadata={'lc_versions':
{'langchain-core': '1.5.1'}}, responses=[\"i'm a chatbot\"])",
"name": "FakeListChatModel"
},
"kwargs": {
@@ -13938,7 +13938,7 @@
"fake",
"FakeListLLM"
],
- "repr": "FakeListLLM(metadata={'lc_versions': {'langchain-core':
'1.5.0'}}, responses=[\"i'm a textbot\"])",
+ "repr": "FakeListLLM(metadata={'lc_versions': {'langchain-core':
'1.5.1'}}, responses=[\"i'm a textbot\"])",
"name": "FakeListLLM"
},
"passthrough": {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/langchain_core-1.5.0/tests/unit_tests/utils/test_gateway.py
new/langchain_core-1.5.1/tests/unit_tests/utils/test_gateway.py
--- old/langchain_core-1.5.0/tests/unit_tests/utils/test_gateway.py
1970-01-01 01:00:00.000000000 +0100
+++ new/langchain_core-1.5.1/tests/unit_tests/utils/test_gateway.py
2020-02-02 01:00:00.000000000 +0100
@@ -0,0 +1,279 @@
+"""Tests for LangSmith gateway configuration resolution."""
+
+from typing import Any
+
+import pytest
+from pydantic import BaseModel, ConfigDict, Field, SecretStr
+
+from langchain_core.utils._gateway import (
+ GatewayConfig,
+ _apply_gateway_config,
+ _resolve_gateway_base_url,
+ _resolve_gateway_config,
+)
+
+# A representative provider path; the helper is provider-agnostic.
+_PATH = "openai/v1"
+_BASE_ENV = "OPENAI_API_BASE"
+_KEY_ENV = "OPENAI_API_KEY"
+_DEFAULT_GATEWAY = "https://gateway.smith.langchain.com/openai/v1"
+
+
[email protected](autouse=True)
+def _clear_env(monkeypatch: pytest.MonkeyPatch) -> None:
+ """Ensure a hermetic environment for every test."""
+ for var in (
+ "LANGSMITH_GATEWAY",
+ "LANGSMITH_GATEWAY_API_KEY",
+ _BASE_ENV,
+ _KEY_ENV,
+ ):
+ monkeypatch.delenv(var, raising=False)
+
+
+def _config(**overrides: object) -> GatewayConfig:
+ kwargs: dict[str, Any] = {
+ "base_url": None,
+ "api_key": None,
+ "provider_path": _PATH,
+ "base_url_env": _BASE_ENV,
+ "api_key_env": _KEY_ENV,
+ }
+ kwargs.update(overrides)
+ return _resolve_gateway_config(**kwargs)
+
+
+# --- _resolve_gateway_base_url --------------------------------------------
+
+
[email protected]("value", ["true", "1", "yes", "TRUE", "Yes"])
+def test_base_url_truthy(monkeypatch: pytest.MonkeyPatch, value: str) -> None:
+ monkeypatch.setenv("LANGSMITH_GATEWAY", value)
+ assert _resolve_gateway_base_url(_PATH) == _DEFAULT_GATEWAY
+
+
[email protected]("value", ["false", "0", "no", "FALSE"])
+def test_base_url_falsy(monkeypatch: pytest.MonkeyPatch, value: str) -> None:
+ monkeypatch.setenv("LANGSMITH_GATEWAY", value)
+ assert _resolve_gateway_base_url(_PATH) is None
+
+
+def test_base_url_unset(monkeypatch: pytest.MonkeyPatch) -> None:
+ monkeypatch.delenv("LANGSMITH_GATEWAY", raising=False)
+ assert _resolve_gateway_base_url(_PATH) is None
+
+
+def test_base_url_custom(monkeypatch: pytest.MonkeyPatch) -> None:
+ monkeypatch.setenv("LANGSMITH_GATEWAY", "https://eu.gateway.example.com/")
+ assert (
+ _resolve_gateway_base_url(_PATH) ==
"https://eu.gateway.example.com/openai/v1"
+ )
+
+
+# --- api key + base url resolution matrix ---------------------------------
+# Each case mirrors a documented requirement scenario.
+
+
+def test_gateway_on_with_gateway_key(monkeypatch: pytest.MonkeyPatch) -> None:
+ monkeypatch.setenv("LANGSMITH_GATEWAY", "true")
+ monkeypatch.setenv("LANGSMITH_GATEWAY_API_KEY", "gateway-key")
+ config = _config()
+ assert config.base_url == _DEFAULT_GATEWAY
+ assert config.base_url_from_gateway is True
+ assert isinstance(config.api_key, SecretStr)
+ assert config.api_key.get_secret_value() == "gateway-key"
+
+
+def test_gateway_key_ignored_when_gateway_off(
+ monkeypatch: pytest.MonkeyPatch,
+) -> None:
+ # Gateway key set but LANGSMITH_GATEWAY unset -> never used.
+ monkeypatch.setenv("LANGSMITH_GATEWAY_API_KEY", "gateway-key")
+ monkeypatch.setenv(_KEY_ENV, "provider-key")
+ config = _config()
+ assert config.base_url is None
+ assert config.base_url_from_gateway is False
+ assert isinstance(config.api_key, SecretStr)
+ assert config.api_key.get_secret_value() == "provider-key"
+
+
+def test_gateway_off_explicitly(monkeypatch: pytest.MonkeyPatch) -> None:
+ monkeypatch.setenv("LANGSMITH_GATEWAY", "false")
+ monkeypatch.setenv("LANGSMITH_GATEWAY_API_KEY", "gateway-key")
+ config = _config()
+ assert config.base_url is None
+ assert config.api_key is None
+
+
+def test_gateway_key_beats_provider_key_on_gateway(
+ monkeypatch: pytest.MonkeyPatch,
+) -> None:
+ monkeypatch.setenv("LANGSMITH_GATEWAY", "true")
+ monkeypatch.setenv("LANGSMITH_GATEWAY_API_KEY", "gateway-key")
+ monkeypatch.setenv(_KEY_ENV, "provider-key")
+ config = _config()
+ assert config.base_url == _DEFAULT_GATEWAY
+ assert config.api_key.get_secret_value() == "gateway-key"
+
+
+def test_gateway_on_falls_back_to_provider_key(
+ monkeypatch: pytest.MonkeyPatch,
+) -> None:
+ monkeypatch.setenv("LANGSMITH_GATEWAY", "true")
+ monkeypatch.setenv(_KEY_ENV, "provider-key")
+ config = _config()
+ assert config.base_url == _DEFAULT_GATEWAY
+ assert config.api_key.get_secret_value() == "provider-key"
+
+
+def test_provider_base_url_uses_provider_key(
+ monkeypatch: pytest.MonkeyPatch,
+) -> None:
+ # Base URL overridden away from the gateway -> provider key wins.
+ monkeypatch.setenv("LANGSMITH_GATEWAY", "true")
+ monkeypatch.setenv("LANGSMITH_GATEWAY_API_KEY", "gateway-key")
+ monkeypatch.setenv(_BASE_ENV, "https://api.openai.com/v1")
+ monkeypatch.setenv(_KEY_ENV, "provider-key")
+ config = _config()
+ assert config.base_url == "https://api.openai.com/v1"
+ assert config.base_url_from_gateway is False
+ assert config.api_key.get_secret_value() == "provider-key"
+
+
+def test_provider_base_url_falls_back_to_gateway_key(
+ monkeypatch: pytest.MonkeyPatch,
+) -> None:
+ # Base URL overridden, no provider key -> gateway key used as fallback.
+ monkeypatch.setenv("LANGSMITH_GATEWAY", "true")
+ monkeypatch.setenv("LANGSMITH_GATEWAY_API_KEY", "gateway-key")
+ monkeypatch.setenv(_BASE_ENV, "https://api.openai.com/v1")
+ config = _config()
+ assert config.base_url == "https://api.openai.com/v1"
+ assert config.api_key.get_secret_value() == "gateway-key"
+
+
+def test_custom_gateway_url(monkeypatch: pytest.MonkeyPatch) -> None:
+ monkeypatch.setenv("LANGSMITH_GATEWAY", "https://eu.gateway.example.com")
+ monkeypatch.setenv("LANGSMITH_GATEWAY_API_KEY", "gateway-key")
+ config = _config()
+ assert config.base_url == "https://eu.gateway.example.com/openai/v1"
+ assert config.base_url_from_gateway is True
+ assert config.api_key.get_secret_value() == "gateway-key"
+
+
+def test_explicit_kwargs_override_everything(
+ monkeypatch: pytest.MonkeyPatch,
+) -> None:
+ monkeypatch.setenv("LANGSMITH_GATEWAY", "https://eu.gateway.example.com")
+ monkeypatch.setenv("LANGSMITH_GATEWAY_API_KEY", "gateway-key")
+ monkeypatch.setenv(_KEY_ENV, "provider-key")
+ explicit_key = SecretStr("explicit-key")
+ config = _config(
+ base_url="https://apac.gateway.example.com",
+ api_key=explicit_key,
+ )
+ assert config.base_url == "https://apac.gateway.example.com"
+ assert config.base_url_from_gateway is False
+ assert config.api_key is explicit_key
+
+
+def test_explicit_base_url_pairs_with_gateway_key(
+ monkeypatch: pytest.MonkeyPatch,
+) -> None:
+ # Explicit base URL, no explicit key: gateway key still resolved from env.
+ monkeypatch.setenv("LANGSMITH_GATEWAY", "https://eu.gateway.example.com")
+ monkeypatch.setenv("LANGSMITH_GATEWAY_API_KEY", "gateway-key")
+ config = _config(base_url="https://apac.gateway.example.com")
+ assert config.base_url == "https://apac.gateway.example.com"
+ assert config.api_key.get_secret_value() == "gateway-key"
+
+
+def test_no_gateway_uses_provider_defaults(
+ monkeypatch: pytest.MonkeyPatch,
+) -> None:
+ monkeypatch.setenv(_BASE_ENV, "https://provider.example.com")
+ monkeypatch.setenv(_KEY_ENV, "provider-key")
+ config = _config(default_base_url="https://default.example.com")
+ assert config.base_url == "https://provider.example.com"
+ assert config.api_key.get_secret_value() == "provider-key"
+
+
+def test_default_base_url_when_nothing_set() -> None:
+ config = _config(default_base_url="https://default.example.com")
+ assert config.base_url == "https://default.example.com"
+ assert config.base_url_from_gateway is False
+ assert config.api_key is None
+
+
+def test_multiple_base_url_env_vars_priority(
+ monkeypatch: pytest.MonkeyPatch,
+) -> None:
+ monkeypatch.setenv("SECOND_BASE", "https://second.example.com")
+ config = _config(base_url_env=["FIRST_BASE", "SECOND_BASE"])
+ assert config.base_url == "https://second.example.com"
+
+
+# --- _apply_gateway_config (before-validator path) ------------------------
+
+
+class _Model(BaseModel):
+ """Stand-in for a provider chat model with aliased fields."""
+
+ model_config = ConfigDict(populate_by_name=True)
+
+ api_base: str | None = Field(default=None, alias="base_url")
+ api_key: SecretStr = Field(default=SecretStr(""), alias="api_key_alias")
+
+
+def _apply(values: dict[str, Any]) -> tuple[dict[str, Any], GatewayConfig]:
+ config = _apply_gateway_config(
+ values,
+ _Model,
+ base_url_field="api_base",
+ api_key_field="api_key",
+ provider_path="openai/v1",
+ base_url_env=_BASE_ENV,
+ api_key_env=_KEY_ENV,
+ )
+ return values, config
+
+
+def test_apply_writes_resolved_values_by_field_name(
+ monkeypatch: pytest.MonkeyPatch,
+) -> None:
+ monkeypatch.setenv("LANGSMITH_GATEWAY", "true")
+ monkeypatch.setenv("LANGSMITH_GATEWAY_API_KEY", "gateway-key")
+ values, config = _apply({})
+ assert values["api_base"] == _DEFAULT_GATEWAY
+ assert isinstance(values["api_key"], SecretStr)
+ assert values["api_key"].get_secret_value() == "gateway-key"
+ assert config.base_url_from_gateway is True
+
+
+def test_apply_reads_explicit_via_alias(monkeypatch: pytest.MonkeyPatch) ->
None:
+ # Values provided under aliases are consumed and rewritten under field
names.
+ monkeypatch.setenv("LANGSMITH_GATEWAY", "true")
+ monkeypatch.setenv("LANGSMITH_GATEWAY_API_KEY", "gateway-key")
+ values, _ = _apply(
+ {"base_url": "https://explicit.example.com", "api_key_alias":
"explicit-key"}
+ )
+ assert "base_url" not in values
+ assert "api_key_alias" not in values
+ assert values["api_base"] == "https://explicit.example.com"
+ assert values["api_key"] == "explicit-key"
+
+
+def test_apply_reads_explicit_via_field_name(
+ monkeypatch: pytest.MonkeyPatch,
+) -> None:
+ monkeypatch.setenv("LANGSMITH_GATEWAY", "true")
+ monkeypatch.setenv("LANGSMITH_GATEWAY_API_KEY", "gateway-key")
+ values, _ = _apply({"api_base": "https://explicit.example.com"})
+ assert values["api_base"] == "https://explicit.example.com"
+
+
+def test_apply_omits_key_when_unresolved() -> None:
+ # No key anywhere: the field is left unset so its own default applies.
+ values, config = _apply({})
+ assert "api_key" not in values
+ assert config.api_key is None
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/langchain_core-1.5.0/uv.lock
new/langchain_core-1.5.1/uv.lock
--- old/langchain_core-1.5.0/uv.lock 2020-02-02 01:00:00.000000000 +0100
+++ new/langchain_core-1.5.1/uv.lock 2020-02-02 01:00:00.000000000 +0100
@@ -490,7 +490,7 @@
version = "1.3.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
- { name = "typing-extensions" },
+ { name = "typing-extensions", marker = "python_full_version < '3.11'" },
]
sdist = { url =
"https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz",
hash =
"sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size
= 30371, upload-time = "2025-11-21T23:01:54.787Z" }
wheels = [
@@ -652,17 +652,17 @@
"python_full_version < '3.11' and platform_python_implementation !=
'PyPy'",
]
dependencies = [
- { name = "colorama", marker = "sys_platform == 'win32'" },
- { name = "decorator" },
- { name = "exceptiongroup" },
- { name = "jedi" },
- { name = "matplotlib-inline" },
- { name = "pexpect", marker = "sys_platform != 'emscripten' and
sys_platform != 'win32'" },
- { name = "prompt-toolkit" },
- { name = "pygments" },
- { name = "stack-data" },
- { name = "traitlets" },
- { name = "typing-extensions" },
+ { name = "colorama", marker = "python_full_version < '3.11' and
sys_platform == 'win32'" },
+ { name = "decorator", marker = "python_full_version < '3.11'" },
+ { name = "exceptiongroup", marker = "python_full_version < '3.11'" },
+ { name = "jedi", marker = "python_full_version < '3.11'" },
+ { name = "matplotlib-inline", marker = "python_full_version < '3.11'" },
+ { name = "pexpect", marker = "python_full_version < '3.11' and
sys_platform != 'emscripten' and sys_platform != 'win32'" },
+ { name = "prompt-toolkit", marker = "python_full_version < '3.11'" },
+ { name = "pygments", marker = "python_full_version < '3.11'" },
+ { name = "stack-data", marker = "python_full_version < '3.11'" },
+ { name = "traitlets", marker = "python_full_version < '3.11'" },
+ { name = "typing-extensions", marker = "python_full_version < '3.11'" },
]
sdist = { url =
"https://files.pythonhosted.org/packages/85/31/10ac88f3357fc276dc8a64e8880c82e80e7459326ae1d0a211b40abf6665/ipython-8.37.0.tar.gz",
hash =
"sha256:ca815841e1a41a1e6b73a0b08f3038af9b2252564d01fc405356d34033012216", size
= 5606088, upload-time = "2025-05-31T16:39:09.613Z" }
wheels = [
@@ -684,17 +684,17 @@
"python_full_version >= '3.11' and python_full_version < '3.13' and
platform_python_implementation != 'PyPy'",
]
dependencies = [
- { name = "colorama", marker = "sys_platform == 'win32'" },
- { name = "decorator" },
- { name = "ipython-pygments-lexers" },
- { name = "jedi" },
- { name = "matplotlib-inline" },
- { name = "pexpect", marker = "sys_platform != 'emscripten' and
sys_platform != 'win32'" },
- { name = "prompt-toolkit" },
- { name = "pygments" },
- { name = "stack-data" },
- { name = "traitlets" },
- { name = "typing-extensions", marker = "python_full_version < '3.12'" },
+ { name = "colorama", marker = "python_full_version >= '3.11' and
sys_platform == 'win32'" },
+ { name = "decorator", marker = "python_full_version >= '3.11'" },
+ { name = "ipython-pygments-lexers", marker = "python_full_version >=
'3.11'" },
+ { name = "jedi", marker = "python_full_version >= '3.11'" },
+ { name = "matplotlib-inline", marker = "python_full_version >= '3.11'" },
+ { name = "pexpect", marker = "python_full_version >= '3.11' and
sys_platform != 'emscripten' and sys_platform != 'win32'" },
+ { name = "prompt-toolkit", marker = "python_full_version >= '3.11'" },
+ { name = "pygments", marker = "python_full_version >= '3.11'" },
+ { name = "stack-data", marker = "python_full_version >= '3.11'" },
+ { name = "traitlets", marker = "python_full_version >= '3.11'" },
+ { name = "typing-extensions", marker = "python_full_version == '3.11.*'" },
]
sdist = { url =
"https://files.pythonhosted.org/packages/12/51/a703c030f4928646d390b4971af4938a1b10c9dfce694f0d99a0bb073cb2/ipython-9.8.0.tar.gz",
hash =
"sha256:8e4ce129a627eb9dd221c41b1d2cdaed4ef7c9da8c17c63f6f578fe231141f83", size
= 4424940, upload-time = "2025-12-03T10:18:24.353Z" }
wheels = [
@@ -706,7 +706,7 @@
version = "1.1.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
- { name = "pygments" },
+ { name = "pygments", marker = "python_full_version >= '3.11'" },
]
sdist = { url =
"https://files.pythonhosted.org/packages/ef/4c/5dd1d8af08107f88c7f741ead7a40854b8ac24ddf9ae850afbcf698aa552/ipython_pygments_lexers-1.1.1.tar.gz",
hash =
"sha256:09c0138009e56b6854f9535736f4171d855c8c08a563a0dcd8022f78355c7e81", size
= 8393, upload-time = "2025-01-17T11:24:34.505Z" }
wheels = [
@@ -1039,7 +1039,7 @@
[[package]]
name = "langchain-core"
-version = "1.5.0"
+version = "1.5.1"
source = { editable = "." }
dependencies = [
{ name = "jsonpatch" },