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-10-09 21:45:23
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-langchain-core (Old)
 and      /work/SRC/openSUSE:Factory/.python-langchain-core.new.3698736 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-langchain-core"

Fri Oct  9 21:45:23 2026 rev:19 rq:1383683 version:1.6.9

Changes:
--------
--- 
/work/SRC/openSUSE:Factory/python-langchain-core/python-langchain-core.changes  
    2026-10-08 12:00:19.634322775 +0200
+++ 
/work/SRC/openSUSE:Factory/.python-langchain-core.new.3698736/python-langchain-core.changes
 2026-10-09 21:45:29.015570991 +0200
@@ -1,0 +2,7 @@
+Fri Oct  9 06:55:05 UTC 2026 - Martin Pluskal <[email protected]>
+
+- Update to version 1.6.9:
+  * Harden scoped and compatible IPv6 SSRF checks
+  * with_retry now accepts a callable for retry_if_exception_type
+
+-------------------------------------------------------------------

Old:
----
  langchain_core-1.6.7.tar.gz

New:
----
  langchain_core-1.6.9.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-langchain-core.spec ++++++
--- /var/tmp/diff_new_pack.vmOHV7/_old  2026-10-09 21:45:29.818604782 +0200
+++ /var/tmp/diff_new_pack.vmOHV7/_new  2026-10-09 21:45:29.820604866 +0200
@@ -17,7 +17,7 @@
 
 
 Name:           python-langchain-core
-Version:        1.6.7
+Version:        1.6.9
 Release:        0
 Summary:        Building applications with LLMs through composability
 License:        MIT

++++++ langchain_core-1.6.7.tar.gz -> langchain_core-1.6.9.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/langchain_core-1.6.7/PKG-INFO 
new/langchain_core-1.6.9/PKG-INFO
--- old/langchain_core-1.6.7/PKG-INFO   2020-02-02 01:00:00.000000000 +0100
+++ new/langchain_core-1.6.9/PKG-INFO   2020-02-02 01:00:00.000000000 +0100
@@ -1,6 +1,6 @@
 Metadata-Version: 2.5
 Name: langchain-core
-Version: 1.6.7
+Version: 1.6.9
 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.6.7/langchain_core/_security/_policy.py 
new/langchain_core-1.6.9/langchain_core/_security/_policy.py
--- old/langchain_core-1.6.7/langchain_core/_security/_policy.py        
2020-02-02 01:00:00.000000000 +0100
+++ new/langchain_core-1.6.9/langchain_core/_security/_policy.py        
2020-02-02 01:00:00.000000000 +0100
@@ -88,6 +88,7 @@
 
 _LOOPBACK_IPV4 = ipaddress.IPv4Network("127.0.0.0/8")
 _LOOPBACK_IPV6 = ipaddress.IPv6Address("::1")
+_IPV4_COMPATIBLE_PREFIX = ipaddress.IPv6Network("::/96")
 
 # NAT64 well-known prefixes
 _NAT64_PREFIX = ipaddress.IPv6Network("64:ff9b::/96")
@@ -125,7 +126,7 @@
 def _extract_embedded_ipv4(
     addr: ipaddress.IPv6Address,
 ) -> ipaddress.IPv4Address | None:
-    """Extract an embedded IPv4 from IPv4-mapped or NAT64 IPv6 addresses."""
+    """Extract IPv4 from mapped, compatible, or NAT64 IPv6 addresses."""
     # Check ipv4_mapped first (covers ::ffff:x.x.x.x)
     if addr.ipv4_mapped is not None:
         return addr.ipv4_mapped
@@ -135,6 +136,9 @@
         raw = addr.packed
         return ipaddress.IPv4Address(raw[-4:])
 
+    if addr in _IPV4_COMPATIBLE_PREFIX and int(addr) > 1:
+        return ipaddress.IPv4Address(int(addr))
+
     return None
 
 
@@ -203,6 +207,7 @@
         raise SSRFBlockedError(msg) from exc
 
     if isinstance(addr, ipaddress.IPv6Address):
+        addr = ipaddress.IPv6Address(int(addr))
         inner = _extract_embedded_ipv4(addr)
         if inner is not None:
             addr = inner
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/langchain_core-1.6.7/langchain_core/runnables/base.py 
new/langchain_core-1.6.9/langchain_core/runnables/base.py
--- old/langchain_core-1.6.7/langchain_core/runnables/base.py   2020-02-02 
01:00:00.000000000 +0100
+++ new/langchain_core-1.6.9/langchain_core/runnables/base.py   2020-02-02 
01:00:00.000000000 +0100
@@ -2102,7 +2102,8 @@
     def with_retry(
         self,
         *,
-        retry_if_exception_type: tuple[type[BaseException], ...] = 
(Exception,),
+        retry_if_exception_type: tuple[type[BaseException], ...]
+        | Callable[[BaseException], bool] = (Exception,),
         wait_exponential_jitter: bool = True,
         exponential_jitter_params: ExponentialJitterParams | None = None,
         stop_after_attempt: int = 3,
@@ -2110,7 +2111,9 @@
         """Create a new `Runnable` that retries the original `Runnable` on 
exceptions.
 
         Args:
-            retry_if_exception_type: A tuple of exception types to retry on.
+            retry_if_exception_type: A tuple of exception types to retry on, 
or a
+                callable that receives the raised exception and returns 
whether to
+                retry it.
             wait_exponential_jitter: Whether to add jitter to the wait
                 time between retries.
             stop_after_attempt: The maximum number of attempts to make before
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/langchain_core-1.6.7/langchain_core/runnables/retry.py 
new/langchain_core-1.6.9/langchain_core/runnables/retry.py
--- old/langchain_core-1.6.7/langchain_core/runnables/retry.py  2020-02-02 
01:00:00.000000000 +0100
+++ new/langchain_core-1.6.9/langchain_core/runnables/retry.py  2020-02-02 
01:00:00.000000000 +0100
@@ -1,5 +1,6 @@
 """`Runnable` that retries a `Runnable` if it fails."""
 
+from collections.abc import Callable
 from typing import (
     TYPE_CHECKING,
     Any,
@@ -12,6 +13,7 @@
     RetryCallState,
     RetryError,
     Retrying,
+    retry_if_exception,
     retry_if_exception_type,
     stop_after_attempt,
     wait_exponential_jitter,
@@ -111,8 +113,11 @@
         ```
     """
 
-    retry_exception_types: tuple[type[BaseException], ...] = (Exception,)
-    """The exception types to retry on. By default all exceptions are retried.
+    retry_exception_types: (
+        tuple[type[BaseException], ...] | Callable[[BaseException], bool]
+    ) = (Exception,)
+    """The exception types to retry on, or a callable that receives the raised
+    exception and returns whether to retry it. By default all exceptions are 
retried.
 
     In general you should only retry on exceptions that are likely to be
     transient, such as network errors.
@@ -144,7 +149,9 @@
                 **(self.exponential_jitter_params or {})
             )
 
-        if self.retry_exception_types:
+        if callable(self.retry_exception_types):
+            kwargs["retry"] = retry_if_exception(self.retry_exception_types)
+        elif self.retry_exception_types:
             kwargs["retry"] = 
retry_if_exception_type(self.retry_exception_types)
 
         return kwargs
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/langchain_core-1.6.7/langchain_core/version.py 
new/langchain_core-1.6.9/langchain_core/version.py
--- old/langchain_core-1.6.7/langchain_core/version.py  2020-02-02 
01:00:00.000000000 +0100
+++ new/langchain_core-1.6.9/langchain_core/version.py  2020-02-02 
01:00:00.000000000 +0100
@@ -1,3 +1,3 @@
 """Version information for `langchain-core`."""
 
-VERSION = "1.6.7"
+VERSION = "1.6.9"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/langchain_core-1.6.7/pyproject.toml 
new/langchain_core-1.6.9/pyproject.toml
--- old/langchain_core-1.6.7/pyproject.toml     2020-02-02 01:00:00.000000000 
+0100
+++ new/langchain_core-1.6.9/pyproject.toml     2020-02-02 01:00:00.000000000 
+0100
@@ -21,7 +21,7 @@
     "Topic :: Software Development :: Libraries :: Python Modules",
 ]
 
-version = "1.6.7"
+version = "1.6.9"
 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.6.7/tests/unit_tests/runnables/test_runnable.py 
new/langchain_core-1.6.9/tests/unit_tests/runnables/test_runnable.py
--- old/langchain_core-1.6.7/tests/unit_tests/runnables/test_runnable.py        
2020-02-02 01:00:00.000000000 +0100
+++ new/langchain_core-1.6.9/tests/unit_tests/runnables/test_runnable.py        
2020-02-02 01:00:00.000000000 +0100
@@ -4126,6 +4126,60 @@
     lambda_mock.reset_mock()
 
 
+def _retry_value_errors(exc: BaseException) -> bool:
+    return isinstance(exc, ValueError)
+
+
+def test_retrying_with_predicate(mocker: MockerFixture) -> None:
+    def _lambda(x: int) -> int:
+        if x == 1:
+            msg = "x is 1"
+            raise ValueError(msg)
+        msg = "x is 2"
+        raise RuntimeError(msg)
+
+    lambda_mock = mocker.Mock(side_effect=_lambda)
+    runnable = RunnableLambda(lambda_mock).with_retry(
+        stop_after_attempt=2,
+        wait_exponential_jitter=False,
+        retry_if_exception_type=_retry_value_errors,
+    )
+
+    with pytest.raises(ValueError, match="x is 1"):
+        runnable.invoke(1)
+    assert lambda_mock.call_count == 2  # retried
+    lambda_mock.reset_mock()
+
+    with pytest.raises(RuntimeError, match="x is 2"):
+        runnable.invoke(2)
+    assert lambda_mock.call_count == 1  # did not retry
+
+
+async def test_async_retrying_with_predicate(mocker: MockerFixture) -> None:
+    def _lambda(x: int) -> int:
+        if x == 1:
+            msg = "x is 1"
+            raise ValueError(msg)
+        msg = "x is 2"
+        raise RuntimeError(msg)
+
+    lambda_mock = mocker.Mock(side_effect=_lambda)
+    runnable = RunnableLambda(lambda_mock).with_retry(
+        stop_after_attempt=2,
+        wait_exponential_jitter=False,
+        retry_if_exception_type=_retry_value_errors,
+    )
+
+    with pytest.raises(ValueError, match="x is 1"):
+        await runnable.ainvoke(1)
+    assert lambda_mock.call_count == 2  # retried
+    lambda_mock.reset_mock()
+
+    with pytest.raises(RuntimeError, match="x is 2"):
+        await runnable.ainvoke(2)
+    assert lambda_mock.call_count == 1  # did not retry
+
+
 def test_runnable_lambda_stream() -> None:
     """Test that stream works for both normal functions & those returning 
Runnable."""
     # Normal output should work
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/langchain_core-1.6.7/tests/unit_tests/test_ssrf_policy_transport.py 
new/langchain_core-1.6.9/tests/unit_tests/test_ssrf_policy_transport.py
--- old/langchain_core-1.6.7/tests/unit_tests/test_ssrf_policy_transport.py     
2020-02-02 01:00:00.000000000 +0100
+++ new/langchain_core-1.6.9/tests/unit_tests/test_ssrf_policy_transport.py     
2020-02-02 01:00:00.000000000 +0100
@@ -37,6 +37,40 @@
         validate_resolved_ip("64:ff9b::c0a8:101", policy)
 
 
[email protected]("block_private_ips", [True, False])
[email protected](
+    "ip",
+    [
+        "fd00:ec2::254%eth0",
+        "fd00:ec2::23%eth0",
+        "fe80::a9fe:a9fe%eth0",
+        "::1%eth0",
+        "::169.254.169.254",
+        "::169.254.170.2",
+        "::100.100.100.200",
+        "::127.0.0.1",
+    ],
+)
+def test_scoped_and_compatible_ipv6_blocked(
+    ip: str, *, block_private_ips: bool
+) -> None:
+    policy = SSRFPolicy(block_private_ips=block_private_ips)
+    with pytest.raises(SSRFBlockedError):
+        validate_resolved_ip(ip, policy)
+    with pytest.raises(SSRFBlockedError):
+        validate_url_sync(f"http://[{ip}]/";, policy)
+
+
[email protected]("ip", ["::8.8.8.8", "::192.168.1.1", 
"fd00::123%eth0", "::"])
+def test_relaxed_policy_allows_non_metadata_ipv6(ip: str) -> None:
+    validate_resolved_ip(ip, SSRFPolicy(block_private_ips=False))
+
+
[email protected]("ip", ["::1", "::1%eth0", "::127.0.0.1"])
+def test_relaxed_policy_can_allow_ipv6_localhost(ip: str) -> None:
+    validate_resolved_ip(ip, SSRFPolicy(block_private_ips=False, 
block_localhost=False))
+
+
 def test_validate_resolved_ip_blocks_cgnat() -> None:
     policy = SSRFPolicy()
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/langchain_core-1.6.7/uv.lock 
new/langchain_core-1.6.9/uv.lock
--- old/langchain_core-1.6.7/uv.lock    2020-02-02 01:00:00.000000000 +0100
+++ new/langchain_core-1.6.9/uv.lock    2020-02-02 01:00:00.000000000 +0100
@@ -1087,7 +1087,7 @@
 
 [[package]]
 name = "langchain-core"
-version = "1.6.7"
+version = "1.6.9"
 source = { editable = "." }
 dependencies = [
     { name = "httpx" },

Reply via email to