test: add pyleak for task and event loop block detections (#8802)

* test: add pyleak for task and event loop block detections

* test: add pyleak for task and event loop block detections

* ci: add env variables for verbose logging

* chore: dummy sleep to shwocase error

* chore: dummy sleep to showcase error

* chore: remove dummy sleep
This commit is contained in:
Deepankar Mahapatro 2025-07-01 18:37:25 +05:30 committed by GitHub
commit 5734735e2d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 46 additions and 6 deletions

View file

@ -84,6 +84,9 @@ jobs:
run: uv sync
- name: Run integration tests
run: make integration_tests_no_api_keys
env:
PYLEAK_LOG_LEVEL: debug # enable pyleak logging
DO_NOT_TRACK: true # disable telemetry reporting
test-cli:
name: Test CLI - Python ${{ matrix.python-version }}

View file

@ -175,6 +175,7 @@ dev = [
"faker>=37.0.0",
"pytest-timeout>=2.3.1",
"pyyaml>=6.0.2",
"pyleak>=0.1.12",
]
[tool.uv.sources]

View file

@ -3,7 +3,9 @@ from langflow.components.processing.parse_json_data import ParseJSONDataComponen
from langflow.schema import Data
from tests.integration.components.mock_components import TextToData
from tests.integration.utils import ComponentInputHandle, run_single_component
from tests.integration.utils import ComponentInputHandle, pyleak_marker, run_single_component
pytestmark = pyleak_marker()
async def test_from_data():

View file

@ -2,7 +2,9 @@ from langflow.components.input_output import ChatInput
from langflow.memory import aget_messages
from langflow.schema.message import Message
from tests.integration.utils import run_single_component
from tests.integration.utils import pyleak_marker, run_single_component
pytestmark = pyleak_marker()
async def test_default():

View file

@ -1,7 +1,9 @@
from langflow.components.input_output import TextInputComponent
from langflow.schema.message import Message
from tests.integration.utils import run_single_component
from tests.integration.utils import pyleak_marker, run_single_component
pytestmark = pyleak_marker()
async def test_text_input():

View file

@ -1,7 +1,9 @@
from langflow.components.processing import PromptComponent
from langflow.schema.message import Message
from tests.integration.utils import run_single_component
from tests.integration.utils import pyleak_marker, run_single_component
pytestmark = pyleak_marker()
async def test():

View file

@ -4,3 +4,7 @@ import pytest
@pytest.fixture(autouse=True)
def _start_app(client):
pass
def pytest_configure(config):
config.addinivalue_line("markers", "no_leaks: detect asyncio task leaks, thread leaks, and event loop blocking")

View file

@ -3,9 +3,10 @@ from langflow.components.processing import PromptComponent
from langflow.graph import Graph
from langflow.schema.message import Message
from tests.integration.utils import run_flow
from tests.integration.utils import pyleak_marker, run_flow
@pyleak_marker()
async def test_simple_no_llm():
graph = Graph()
flow_input = graph.add_component(ChatInput())

View file

@ -3,6 +3,7 @@ import os
import uuid
from typing import Any
import pytest
import requests
from astrapy.admin import parse_api_endpoint
from langflow.api.v1.schemas import InputValueRequest
@ -187,3 +188,11 @@ def build_component_instance_for_tests(version: str, module: str, file_name: str
component = download_component_from_github(module, file_name, version)
cc_class = eval_custom_component_code(component._code)
return cc_class(**kwargs), component._code
def pyleak_marker(**extra_args):
default_args = {
"enable_task_creation_tracking": True, # log task creation stacks
"thread_name_filter": r"^(?!asyncio_\d+$).*", # exclude `asyncio_{num}` threads
}
return pytest.mark.no_leaks(**default_args, **extra_args)

16
uv.lock generated
View file

@ -2309,7 +2309,7 @@ name = "exceptiongroup"
version = "1.3.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "typing-extensions", marker = "python_full_version < '3.11'" },
{ name = "typing-extensions", marker = "python_full_version < '3.13'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/0b/9f/a65090624ecf468cdca03533906e7c69ed7588582240cfe7cc9e770b50eb/exceptiongroup-1.3.0.tar.gz", hash = "sha256:b241f5885f560bc56a59ee63ca4c6a8bfa46ae4ad651af316d4e81817bb9fd88", size = 29749, upload-time = "2025-05-10T17:42:51.123Z" }
wheels = [
@ -4980,6 +4980,7 @@ dev = [
{ name = "pandas-stubs" },
{ name = "pre-commit" },
{ name = "pydantic-ai" },
{ name = "pyleak" },
{ name = "pytest" },
{ name = "pytest-asyncio" },
{ name = "pytest-cov" },
@ -5155,6 +5156,7 @@ dev = [
{ name = "pandas-stubs", specifier = ">=2.1.4.231227" },
{ name = "pre-commit", specifier = ">=3.7.0" },
{ name = "pydantic-ai", specifier = ">=0.0.19" },
{ name = "pyleak", specifier = ">=0.1.12" },
{ name = "pytest", specifier = ">=8.2.0" },
{ name = "pytest-asyncio", specifier = ">=0.23.0" },
{ name = "pytest-cov", specifier = ">=5.0.0" },
@ -8474,6 +8476,18 @@ version = "2.10"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/5d/ab/34ec41718af73c00119d0351b7a2531d2ebddb51833a36448fc7b862be60/pylatexenc-2.10.tar.gz", hash = "sha256:3dd8fd84eb46dc30bee1e23eaab8d8fb5a7f507347b23e5f38ad9675c84f40d3", size = 162597, upload-time = "2021-04-06T07:56:07.854Z" }
[[package]]
name = "pyleak"
version = "0.1.12"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "exceptiongroup" },
]
sdist = { url = "https://files.pythonhosted.org/packages/14/55/bdc246baf6870185555d6ebcb35a7361f9bb95ba3fd0ff295d8fc4ff9e6e/pyleak-0.1.12.tar.gz", hash = "sha256:6af479b2dd5d4c71ff2b33ba5eeccda04b2d248f884801cf414fc84777a636de", size = 104742, upload-time = "2025-07-01T12:04:44.708Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/4d/08/e8bc7e2f63deca307575bcf98d112fe75f80ecd716d3dcc69330ad096fff/pyleak-0.1.12-py3-none-any.whl", hash = "sha256:17a1c8b11d89fdcee79f0a479378bd6de23de323754a81efe8d8d9550ac12863", size = 23762, upload-time = "2025-07-01T12:04:43.494Z" },
]
[[package]]
name = "pylint"
version = "3.3.7"