Skip to content

Commit 7009a7a

Browse files
authored
Merge branch 'main' into renovate/samples-langchain_on_vertexai
2 parents 3b6c227 + 8ad4f48 commit 7009a7a

18 files changed

+1330
-830
lines changed

.github/renovate.json5

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -48,38 +48,18 @@
4848
"matchCurrentVersion": "<=2.2.6",
4949
"enabled": false
5050
},
51-
{
52-
"description": "Disable numpy updates for python <=3.9 in requirements.txt",
53-
"matchPackageNames": ["numpy"],
54-
"matchCurrentVersion": "<=2.0.2",
55-
"enabled": false
56-
},
5751
{
5852
"description": "Disable numpy updates for python 3.10 in pyproject.toml",
5953
"matchFileNames": ["pyproject.toml"],
6054
"matchPackageNames": ["numpy"],
6155
"matchCurrentValue": ">=1.24.4, <=2.2.6",
6256
"enabled": false
6357
},
64-
{
65-
"description": "Disable numpy updates for python <=3.9 in pyproject.toml",
66-
"matchFileNames": ["pyproject.toml"],
67-
"matchPackageNames": ["numpy"],
68-
"matchCurrentValue": ">=1.24.4, <=2.0.2",
69-
"enabled": false
70-
},
7158
{
7259
"description": "Use feat commit type for LangChain Postgres dependency updates",
7360
"matchPackageNames": ["langchain-postgres"],
7461
"semanticCommitType": "feat",
7562
"groupName": "langchain-postgres"
7663
},
77-
{
78-
"description": "Disable isort updates for python <=3.9 in pyproject.toml",
79-
"matchFileNames": ["pyproject.toml"],
80-
"matchPackageNames": ["isort"],
81-
"matchCurrentValue": "==6.1.0",
82-
"enabled": false
83-
}
8464
],
8565
}

.github/workflows/docs.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ jobs:
1010
runs-on: ubuntu-latest
1111
steps:
1212
- name: Checkout
13-
uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5
13+
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6
1414
- name: Setup Python
1515
uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6
1616
with:
@@ -26,7 +26,7 @@ jobs:
2626
runs-on: ubuntu-latest
2727
steps:
2828
- name: Checkout
29-
uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5
29+
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6
3030
- name: Setup Python
3131
uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6
3232
with:

.github/workflows/lint.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ jobs:
3131

3232
steps:
3333
- name: Checkout Repository
34-
uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5
34+
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6
3535

3636
- name: Setup Python
3737
uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6.1.0

.github/workflows/schedule_reporter.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,6 @@ jobs:
2424
issues: 'write'
2525
checks: 'read'
2626
contents: 'read'
27-
uses: googleapis/langchain-google-alloydb-pg-python/.github/workflows/cloud_build_failure_reporter.yml@9eca5220f8f17a443f08b21e66dcdace0c5ac00f
27+
uses: googleapis/langchain-google-alloydb-pg-python/.github/workflows/cloud_build_failure_reporter.yml@593ae87530a872417f3edf063ef055d5a72034c8
2828
with:
2929
trigger_names: "pg-integration-test-nightly,pg-continuous-test-on-merge"

DEVELOPER.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,11 @@ These tests are registered as required tests in `.github/sync-repo-settings.yaml
4242

4343
#### Trigger Setup
4444

45-
Cloud Build triggers (for Python versions 3.9 to 3.11) were created with the following specs:
45+
Cloud Build triggers (for Python versions 3.10 to 3.13) were created with the following specs:
4646

4747
```YAML
4848
name: pg-integration-test-pr-py39
49-
description: Run integration tests on PR for Python 3.9
49+
description: Run integration tests on PR for Python 3.10
5050
filename: integration.cloudbuild.yaml
5151
github:
5252
name: langchain-google-cloud-sql-pg-python
@@ -64,7 +64,7 @@ substitutions:
6464
_DATABASE_ID: <ADD_VALUE>
6565
_INSTANCE_ID: <ADD_VALUE>
6666
_REGION: us-central1
67-
_VERSION: "3.9"
67+
_VERSION: "3.10"
6868
```
6969

7070
Use `gcloud builds triggers import --source=trigger.yaml` to create triggers via the command line

README.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ dependencies.
5656
Supported Python Versions
5757
^^^^^^^^^^^^^^^^^^^^^^^^^
5858

59-
Python >= 3.9
59+
Python >= 3.10
6060

6161
Mac/Linux
6262
^^^^^^^^^

integration.cloudbuild.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ substitutions:
6262
_DATABASE_PORT: "5432"
6363
_DATABASE_ID: test-database
6464
_REGION: us-central1
65-
_VERSION: "3.9"
65+
_VERSION: "3.10"
6666
_IP_ADDRESS: "127.0.0.1"
6767

6868
options:

pyproject.toml

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ dynamic = ["version"]
44
description = "LangChain integrations for Google Cloud SQL for PostgreSQL"
55
readme = "README.rst"
66
license = {file = "LICENSE"}
7-
requires-python = ">=3.9"
7+
requires-python = ">=3.10"
88
authors = [
99
{name = "Google LLC", email = "googleapis-packages@google.com"}
1010
]
@@ -13,7 +13,6 @@ dependencies = [
1313
"cloud-sql-python-connector[asyncpg] >= 1.10.0, <2.0.0",
1414
"numpy>=1.24.4, <3.0.0; python_version >= '3.11'",
1515
"numpy>=1.24.4, <=2.2.6; python_version == '3.10'",
16-
"numpy>=1.24.4, <=2.0.2; python_version <= '3.9'",
1716
"langchain-postgres>=0.0.16",
1817
]
1918

@@ -22,10 +21,10 @@ classifiers = [
2221
"License :: OSI Approved :: Apache Software License",
2322
"Programming Language :: Python",
2423
"Programming Language :: Python :: 3",
25-
"Programming Language :: Python :: 3.9",
2624
"Programming Language :: Python :: 3.10",
2725
"Programming Language :: Python :: 3.11",
2826
"Programming Language :: Python :: 3.12",
27+
"Programming Language :: Python :: 3.13",
2928
]
3029

3130
[tool.setuptools.dynamic]
@@ -43,8 +42,7 @@ langgraph = [
4342
]
4443
test = [
4544
"black[jupyter]==25.9.0",
46-
"isort==6.1.0; python_version == '3.9'",
47-
"isort==7.0.0; python_version >= '3.10'",
45+
"isort==7.0.0",
4846
"mypy==1.18.2",
4947
"pytest-asyncio==0.26.0",
5048
"pytest==8.4.2",
@@ -64,7 +62,7 @@ target-version = ['py39']
6462
profile = "black"
6563

6664
[tool.mypy]
67-
python_version = 3.9
65+
python_version = "3.10"
6866
warn_unused_configs = true
6967
disallow_incomplete_defs = true
7068

requirements.txt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
cloud-sql-python-connector[asyncpg]==1.18.4
1+
cloud-sql-python-connector[asyncpg]==1.18.5
22
numpy==2.3.3; python_version >= "3.11"
33
numpy==2.2.6; python_version == "3.10"
4-
numpy==2.0.2; python_version <= "3.9"
54
langgraph==0.6.10
65
langchain-postgres==0.0.16

tests/test_async_chatmessagehistory.py

Lines changed: 72 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,10 @@
1111
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
14+
import asyncio
1415
import os
1516
import uuid
17+
from typing import Any, Coroutine
1618

1719
import pytest
1820
import pytest_asyncio
@@ -33,10 +35,23 @@
3335
table_name_async = "message_store" + str(uuid.uuid4())
3436

3537

38+
# Helper to bridge the Main Test Loop and the Engine Background Loop
39+
async def run_on_background(engine: PostgresEngine, coro: Coroutine) -> Any:
40+
"""Runs a coroutine on the engine's background loop."""
41+
if engine._loop:
42+
return await asyncio.wrap_future(
43+
asyncio.run_coroutine_threadsafe(coro, engine._loop)
44+
)
45+
return await coro
46+
47+
3648
async def aexecute(engine: PostgresEngine, query: str) -> None:
37-
async with engine._pool.connect() as conn:
38-
await conn.execute(text(query))
39-
await conn.commit()
49+
async def _impl():
50+
async with engine._pool.connect() as conn:
51+
await conn.execute(text(query))
52+
await conn.commit()
53+
54+
await run_on_background(engine, _impl())
4055

4156

4257
@pytest_asyncio.fixture
@@ -47,7 +62,10 @@ async def async_engine():
4762
instance=instance_id,
4863
database=db_name,
4964
)
50-
await async_engine._ainit_chat_history_table(table_name=table_name_async)
65+
await run_on_background(
66+
async_engine,
67+
async_engine._ainit_chat_history_table(table_name=table_name_async),
68+
)
5169
yield async_engine
5270
# use default table for AsyncPostgresChatMessageHistory
5371
query = f'DROP TABLE IF EXISTS "{table_name_async}"'
@@ -59,14 +77,19 @@ async def async_engine():
5977
async def test_chat_message_history_async(
6078
async_engine: PostgresEngine,
6179
) -> None:
62-
history = await AsyncPostgresChatMessageHistory.create(
63-
engine=async_engine, session_id="test", table_name=table_name_async
80+
history = await run_on_background(
81+
async_engine,
82+
AsyncPostgresChatMessageHistory.create(
83+
engine=async_engine, session_id="test", table_name=table_name_async
84+
),
6485
)
6586
msg1 = HumanMessage(content="hi!")
6687
msg2 = AIMessage(content="whats up?")
67-
await history.aadd_message(msg1)
68-
await history.aadd_message(msg2)
69-
messages = await history._aget_messages()
88+
89+
await run_on_background(async_engine, history.aadd_message(msg1))
90+
await run_on_background(async_engine, history.aadd_message(msg2))
91+
92+
messages = await run_on_background(async_engine, history._aget_messages())
7093

7194
# verify messages are correct
7295
assert messages[0].content == "hi!"
@@ -75,48 +98,71 @@ async def test_chat_message_history_async(
7598
assert type(messages[1]) is AIMessage
7699

77100
# verify clear() clears message history
78-
await history.aclear()
79-
assert len(await history._aget_messages()) == 0
101+
await run_on_background(async_engine, history.aclear())
102+
messages_after_clear = await run_on_background(
103+
async_engine, history._aget_messages()
104+
)
105+
assert len(messages_after_clear) == 0
80106

81107

82108
@pytest.mark.asyncio
83109
async def test_chat_message_history_sync_messages(
84110
async_engine: PostgresEngine,
85111
) -> None:
86-
history1 = await AsyncPostgresChatMessageHistory.create(
87-
engine=async_engine, session_id="test", table_name=table_name_async
112+
history1 = await run_on_background(
113+
async_engine,
114+
AsyncPostgresChatMessageHistory.create(
115+
engine=async_engine, session_id="test", table_name=table_name_async
116+
),
88117
)
89-
history2 = await AsyncPostgresChatMessageHistory.create(
90-
engine=async_engine, session_id="test", table_name=table_name_async
118+
history2 = await run_on_background(
119+
async_engine,
120+
AsyncPostgresChatMessageHistory.create(
121+
engine=async_engine, session_id="test", table_name=table_name_async
122+
),
91123
)
92124
msg1 = HumanMessage(content="hi!")
93125
msg2 = AIMessage(content="whats up?")
94-
await history1.aadd_message(msg1)
95-
await history2.aadd_message(msg2)
126+
await run_on_background(async_engine, history1.aadd_message(msg1))
127+
await run_on_background(async_engine, history2.aadd_message(msg2))
128+
129+
len_history1 = len(await run_on_background(async_engine, history1._aget_messages()))
130+
len_history2 = len(await run_on_background(async_engine, history2._aget_messages()))
96131

97-
assert len(await history1._aget_messages()) == 2
98-
assert len(await history2._aget_messages()) == 2
132+
assert len_history1 == 2
133+
assert len_history2 == 2
99134

100135
# verify clear() clears message history
101-
await history2.aclear()
102-
assert len(await history2._aget_messages()) == 0
136+
await run_on_background(async_engine, history2.aclear())
137+
len_history2_after_clear = len(
138+
await run_on_background(async_engine, history2._aget_messages())
139+
)
140+
assert len_history2_after_clear == 0
103141

104142

105143
@pytest.mark.asyncio
106144
async def test_chat_table_async(async_engine):
107145
with pytest.raises(ValueError):
108-
await AsyncPostgresChatMessageHistory.create(
109-
engine=async_engine, session_id="test", table_name="doesnotexist"
146+
await run_on_background(
147+
async_engine,
148+
AsyncPostgresChatMessageHistory.create(
149+
engine=async_engine, session_id="test", table_name="doesnotexist"
150+
),
110151
)
111152

112153

113154
@pytest.mark.asyncio
114155
async def test_chat_schema_async(async_engine):
115156
table_name = "test_table" + str(uuid.uuid4())
116-
await async_engine._ainit_document_table(table_name=table_name)
157+
await run_on_background(
158+
async_engine, async_engine._ainit_document_table(table_name=table_name)
159+
)
117160
with pytest.raises(IndexError):
118-
await AsyncPostgresChatMessageHistory.create(
119-
engine=async_engine, session_id="test", table_name=table_name
161+
await run_on_background(
162+
async_engine,
163+
AsyncPostgresChatMessageHistory.create(
164+
engine=async_engine, session_id="test", table_name=table_name
165+
),
120166
)
121167

122168
query = f'DROP TABLE IF EXISTS "{table_name}"'

0 commit comments

Comments
 (0)