feat: add --memory flag to codeflash compare for peak memory profiling

Adds a second profiling phase using pytest-memray that runs after timing
benchmarks. Memory tables are suppressed when the delta is <1%.
This commit is contained in:
Kevin Turcios 2026-04-02 10:29:31 -05:00
parent 74c29b20b1
commit 279a8fcb29
8 changed files with 495 additions and 4 deletions

View file

@ -25,7 +25,7 @@ from codeflash.cli_cmds.console import console, logger
if TYPE_CHECKING:
from collections.abc import Callable
from codeflash.benchmarking.plugin.plugin import BenchmarkStats
from codeflash.benchmarking.plugin.plugin import BenchmarkStats, MemoryStats
from codeflash.models.function_types import FunctionToOptimize
from codeflash.models.models import BenchmarkKey
@ -42,6 +42,8 @@ class CompareResult:
head_stats: dict[BenchmarkKey, BenchmarkStats] = field(default_factory=dict)
base_function_ns: dict[str, dict[BenchmarkKey, float]] = field(default_factory=dict)
head_function_ns: dict[str, dict[BenchmarkKey, float]] = field(default_factory=dict)
base_memory: dict[BenchmarkKey, MemoryStats] = field(default_factory=dict)
head_memory: dict[BenchmarkKey, MemoryStats] = field(default_factory=dict)
def format_markdown(self) -> str:
if not self.base_stats and not self.head_stats:
@ -106,6 +108,29 @@ class CompareResult:
f"| `{short_name}` | {fmt_us(b)} | {fmt_us(h)} | {md_bar(b, h)} | {md_speedup(b, h)} |"
)
# Memory section (skip when delta is negligible)
base_mem = self.base_memory.get(bm_key)
head_mem = self.head_memory.get(bm_key)
if has_meaningful_memory_change(base_mem, head_mem):
lines.append("")
lines.append("#### Memory")
lines.append("")
lines.append("| Ref | Peak Memory | Allocations | Delta |")
lines.append("|:---|---:|---:|:---|")
if base_mem:
lines.append(
f"| `{base_short}` (base) | {md_bytes(base_mem.peak_memory_bytes)}"
f" | {base_mem.total_allocations:,} | |"
)
if head_mem:
delta = md_memory_delta(
base_mem.peak_memory_bytes if base_mem else None, head_mem.peak_memory_bytes
)
lines.append(
f"| `{head_short}` (head) | {md_bytes(head_mem.peak_memory_bytes)}"
f" | {head_mem.total_allocations:,} | {delta} |"
)
sections.append("\n".join(lines))
sections.append("---\n*Generated by codeflash optimization agent*")
@ -120,16 +145,23 @@ def compare_branches(
tests_root: Path,
functions: Optional[dict[Path, list[FunctionToOptimize]]] = None,
timeout: int = 600,
memory: bool = False,
) -> CompareResult:
"""Compare benchmark performance between two git refs.
If functions is None, auto-detects changed functions from git diff.
Returns a CompareResult with timing data from both refs.
"""
import sys
from codeflash.benchmarking.instrument_codeflash_trace import instrument_codeflash_trace_decorator
from codeflash.benchmarking.plugin.plugin import CodeFlashBenchmarkPlugin
from codeflash.benchmarking.trace_benchmarks import trace_benchmarks_pytest
if memory and sys.platform == "win32":
logger.error("--memory requires memray which is not available on Windows")
return CompareResult(base_ref=base_ref, head_ref=head_ref)
repo = git.Repo(project_root, search_parent_directories=True)
repo_root = Path(repo.working_dir)
@ -182,12 +214,17 @@ def compare_branches(
head_worktree = worktree_dirs / f"compare-head-{timestamp}"
base_trace_db = worktree_dirs / f"trace-base-{timestamp}.db"
head_trace_db = worktree_dirs / f"trace-head-{timestamp}.db"
base_memray_dir = worktree_dirs / f"memray-base-{timestamp}"
head_memray_dir = worktree_dirs / f"memray-head-{timestamp}"
memray_prefix = "cf-mem"
result = CompareResult(base_ref=base_ref, head_ref=head_ref)
from rich.console import Group
step_labels = ["Creating worktrees", f"Benchmarking base ({base_short})", f"Benchmarking head ({head_short})"]
if memory:
step_labels.extend([f"Memory profiling base ({base_short})", f"Memory profiling head ({head_short})"])
def build_steps(current_step: int) -> Group:
lines: list[Text] = []
@ -260,6 +297,18 @@ def compare_branches(
trace_fn=trace_benchmarks_pytest,
)
# Steps 4-5: Memory profiling (reuses existing worktrees)
if memory:
from codeflash.benchmarking.trace_benchmarks import memory_benchmarks_pytest
live.update(build_panel(3))
wt_base_benchmarks = base_worktree / benchmarks_root.relative_to(repo_root)
memory_benchmarks_pytest(wt_base_benchmarks, base_worktree, base_memray_dir, memray_prefix, timeout)
live.update(build_panel(4))
wt_head_benchmarks = head_worktree / benchmarks_root.relative_to(repo_root)
memory_benchmarks_pytest(wt_head_benchmarks, head_worktree, head_memray_dir, memray_prefix, timeout)
# Load results
if base_trace_db.exists():
result.base_stats = CodeFlashBenchmarkPlugin.get_benchmark_timings(base_trace_db)
@ -269,6 +318,14 @@ def compare_branches(
result.head_stats = CodeFlashBenchmarkPlugin.get_benchmark_timings(head_trace_db)
result.head_function_ns = CodeFlashBenchmarkPlugin.get_function_benchmark_timings(head_trace_db)
if memory:
from codeflash.benchmarking.plugin.plugin import MemoryStats
if base_memray_dir.exists():
result.base_memory = MemoryStats.parse_memray_results(base_memray_dir, memray_prefix)
if head_memray_dir.exists():
result.head_memory = MemoryStats.parse_memray_results(head_memray_dir, memray_prefix)
# Render comparison
render_comparison(result)
@ -282,10 +339,16 @@ def compare_branches(
remove_worktree(base_worktree)
remove_worktree(head_worktree)
repo.git.worktree("prune")
# Cleanup trace DBs
# Cleanup trace DBs and memray dirs
for db in [base_trace_db, head_trace_db]:
if db.exists():
db.unlink()
if memory:
import shutil
for memray_dir in [base_memray_dir, head_memray_dir]:
if memray_dir.exists():
shutil.rmtree(memray_dir)
return result
@ -543,6 +606,31 @@ def render_comparison(result: CompareResult) -> None:
console.print(t2, justify="center")
# Table 3: Memory (skip when delta is negligible)
base_mem = result.base_memory.get(bm_key)
head_mem = result.head_memory.get(bm_key)
if has_meaningful_memory_change(base_mem, head_mem):
console.print()
t3 = Table(title="Memory (peak per test)", border_style="magenta", show_lines=True, expand=False)
t3.add_column("Ref", style="bold cyan")
t3.add_column("Peak Memory", justify="right")
t3.add_column("Allocations", justify="right")
t3.add_column("Delta", justify="right")
if base_mem:
t3.add_row(
f"{base_short} (base)", fmt_bytes(base_mem.peak_memory_bytes), f"{base_mem.total_allocations:,}", ""
)
if head_mem:
delta = fmt_memory_delta(base_mem.peak_memory_bytes if base_mem else None, head_mem.peak_memory_bytes)
t3.add_row(
f"{head_short} (head)",
fmt_bytes(head_mem.peak_memory_bytes),
f"{head_mem.total_allocations:,}",
delta,
)
console.print(t3, justify="center")
console.print()
@ -641,3 +729,63 @@ def md_bar(before: Optional[float], after: Optional[float], width: int = 10) ->
filled = min(filled, width)
bar = "\u2588" * filled + "\u2591" * (width - filled)
return f"`{bar}` {pct:+.0f}%"
def fmt_bytes(b: Optional[int]) -> str:
if b is None:
return "-"
if b >= 1 << 30:
return f"{b / (1 << 30):,.1f} GiB"
if b >= 1 << 20:
return f"{b / (1 << 20):,.1f} MiB"
if b >= 1 << 10:
return f"{b / (1 << 10):,.1f} KiB"
return f"{b:,} B"
def fmt_memory_delta(before: Optional[int], after: Optional[int]) -> str:
if before is None or after is None or before == 0:
return "-"
pct = ((after - before) / before) * 100
if pct < 0:
return _GREEN_TPL % pct
return _RED_TPL % pct
def md_bytes(b: Optional[int]) -> str:
if b is None:
return "-"
if b >= 1 << 30:
return f"{b / (1 << 30):,.1f} GiB"
if b >= 1 << 20:
return f"{b / (1 << 20):,.1f} MiB"
if b >= 1 << 10:
return f"{b / (1 << 10):,.1f} KiB"
return f"{b:,} B"
def md_memory_delta(before: Optional[int], after: Optional[int]) -> str:
if before is None or after is None or before == 0:
return "-"
pct = ((after - before) / before) * 100
emoji = "\U0001f7e2" if pct <= 0 else "\U0001f534"
return f"{emoji} {pct:+.0f}%"
def has_meaningful_memory_change(
base_mem: Optional[MemoryStats], head_mem: Optional[MemoryStats], threshold_pct: float = 1.0
) -> bool:
"""Return True if peak memory or allocation count changed by more than threshold_pct."""
if base_mem is None or head_mem is None:
return base_mem is not None or head_mem is not None
if base_mem.peak_memory_bytes == 0 and head_mem.peak_memory_bytes == 0:
return False
if base_mem.peak_memory_bytes > 0:
mem_pct = abs((head_mem.peak_memory_bytes - base_mem.peak_memory_bytes) / base_mem.peak_memory_bytes) * 100
if mem_pct > threshold_pct:
return True
if base_mem.total_allocations > 0:
alloc_pct = abs((head_mem.total_allocations - base_mem.total_allocations) / base_mem.total_allocations) * 100
if alloc_pct > threshold_pct:
return True
return False

View file

@ -68,6 +68,51 @@ class BenchmarkStats:
)
@dataclass
class MemoryStats:
peak_memory_bytes: int
total_allocations: int
@staticmethod
def parse_memray_results(bin_dir: Path, bin_prefix: str) -> dict:
from codeflash.models.models import BenchmarkKey
try:
from memray import FileReader
except ImportError as e:
msg = "memray is required for --memory profiling. Install with: uv add memray pytest-memray"
raise ImportError(msg) from e
results: dict[BenchmarkKey, MemoryStats] = {}
for bin_file in sorted(bin_dir.glob(f"{bin_prefix}-*.bin")):
stem = bin_file.stem
# pytest-memray names: {prefix}-{nodeid with :: and os.sep replaced by -}.bin
nodeid_part = stem[len(bin_prefix) + 1 :] # strip "{prefix}-"
# Extract the test function name (last segment after the final -)
# Node IDs look like: tests-benchmarks-test_file.py-test_func_name
# We need the module_path and function_name for BenchmarkKey
# Split on ".py-" to separate module path from function name
parts = nodeid_part.split(".py-", 1)
if len(parts) == 2:
module_part = parts[0].replace("-", ".")
function_name = parts[1]
else:
module_part = nodeid_part.rsplit("-", 1)[0].replace("-", ".")
function_name = nodeid_part.rsplit("-", 1)[-1] if "-" in nodeid_part else nodeid_part
try:
reader = FileReader(str(bin_file))
meta = reader.metadata
bm_key = BenchmarkKey(module_path=module_part, function_name=function_name)
results[bm_key] = MemoryStats(
peak_memory_bytes=meta.peak_memory, total_allocations=meta.total_allocations
)
reader.close()
except OSError:
continue
return results
class CodeFlashBenchmarkPlugin:
def __init__(self) -> None:
self._trace_path = None

View file

@ -0,0 +1,42 @@
"""Subprocess entry point for memory profiling benchmarks via pytest-memray.
Runs pytest with --memray --native to profile peak memory per test function.
The codeflash-benchmark plugin is left active (without --codeflash-trace) so it
provides a no-op ``benchmark`` fixture for tests that depend on it.
"""
import sys
from pathlib import Path
benchmarks_root = sys.argv[1]
memray_bin_dir = sys.argv[2]
memray_bin_prefix = sys.argv[3]
if __name__ == "__main__":
import pytest
Path(memray_bin_dir).mkdir(parents=True, exist_ok=True)
exitcode = pytest.main(
[
benchmarks_root,
"--memray",
"--native",
f"--memray-bin-path={memray_bin_dir}",
f"--memray-bin-prefix={memray_bin_prefix}",
"--hide-memray-summary",
"-p",
"no:benchmark",
"-p",
"no:codspeed",
"-p",
"no:cov",
"-p",
"no:profiling",
"-s",
"-o",
"addopts=",
]
)
sys.exit(exitcode)

View file

@ -46,3 +46,39 @@ def trace_benchmarks_pytest(
error_section = combined_output
logger.warning(f"Error collecting benchmarks - Pytest Exit code: {result.returncode}, {error_section}")
logger.debug(f"Full pytest output:\n{combined_output}")
def memory_benchmarks_pytest(
benchmarks_root: Path, project_root: Path, memray_bin_dir: Path, memray_bin_prefix: str, timeout: int = 300
) -> None:
benchmark_env = make_env_with_project_root(project_root)
run_args = get_cross_platform_subprocess_run_args(
cwd=project_root, env=benchmark_env, timeout=timeout, check=False, text=True, capture_output=True
)
result = subprocess.run( # noqa: PLW1510
[
SAFE_SYS_EXECUTABLE,
Path(__file__).parent / "pytest_new_process_memory_benchmarks.py",
benchmarks_root,
memray_bin_dir,
memray_bin_prefix,
],
**run_args,
)
if result.returncode != 0:
combined_output = result.stdout
if result.stderr:
combined_output = combined_output + "\n" + result.stderr if combined_output else result.stderr
if "ERROR collecting" in combined_output:
error_pattern = r"={3,}\s*ERRORS\s*={3,}\n([\s\S]*?)(?:={3,}|$)"
match = re.search(error_pattern, combined_output)
error_section = match.group(1) if match else combined_output
elif "FAILURES" in combined_output:
error_pattern = r"={3,}\s*FAILURES\s*={3,}\n([\s\S]*?)(?:={3,}|$)"
match = re.search(error_pattern, combined_output)
error_section = match.group(1) if match else combined_output
else:
error_section = combined_output
logger.warning(f"Error collecting memory benchmarks - Pytest Exit code: {result.returncode}, {error_section}")
logger.debug(f"Full pytest output:\n{combined_output}")

View file

@ -392,6 +392,9 @@ def _build_parser() -> ArgumentParser:
)
compare_parser.add_argument("--timeout", type=int, default=600, help="Benchmark timeout in seconds (default: 600)")
compare_parser.add_argument("--output", "-o", type=str, help="Write markdown report to file")
compare_parser.add_argument(
"--memory", action="store_true", help="Profile peak memory usage per benchmark (requires memray, Linux/macOS)"
)
compare_parser.add_argument("--config-file", type=str, dest="config_file", help="Path to pyproject.toml")
trace_optimize = subparsers.add_parser("optimize", help="Trace and optimize your project.")

View file

@ -73,6 +73,7 @@ def run_compare(args: Namespace) -> None:
tests_root=tests_root,
functions=functions,
timeout=args.timeout,
memory=getattr(args, "memory", False),
)
if not result.base_stats and not result.head_stats:

View file

@ -53,6 +53,8 @@ dependencies = [
"filelock>=3.20.3; python_version >= '3.10'",
"filelock<3.20.3; python_version < '3.10'",
"pytest-asyncio>=0.18.0",
"memray>=1.12; sys_platform != 'win32'",
"pytest-memray>=1.7; sys_platform != 'win32'",
]
[project.urls]
@ -339,8 +341,8 @@ vcs = "git"
[tool.hatch.build.hooks.version]
path = "codeflash/version.py"
template = """# These version placeholders will be replaced by uv-dynamic-versioning during build.
__version__ = "{version}"
template = """# These version placeholders will be replaced by uv-dynamic-versioning during build.
__version__ = "{version}"
"""

214
uv.lock
View file

@ -466,6 +466,7 @@ dependencies = [
{ name = "libcst" },
{ name = "line-profiler" },
{ name = "lxml" },
{ name = "memray", marker = "sys_platform != 'win32'" },
{ name = "parameterized" },
{ name = "platformdirs", version = "4.4.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" },
{ name = "platformdirs", version = "4.9.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" },
@ -477,6 +478,7 @@ dependencies = [
{ name = "pytest", version = "9.0.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" },
{ name = "pytest-asyncio", version = "1.2.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" },
{ name = "pytest-asyncio", version = "1.3.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" },
{ name = "pytest-memray", marker = "sys_platform != 'win32'" },
{ name = "pytest-timeout" },
{ name = "requests", version = "2.32.5", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" },
{ name = "requests", version = "2.33.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" },
@ -576,6 +578,7 @@ requires-dist = [
{ name = "libcst", specifier = ">=1.0.1" },
{ name = "line-profiler", specifier = ">=4.2.0" },
{ name = "lxml", specifier = ">=5.3.0" },
{ name = "memray", marker = "sys_platform != 'win32'", specifier = ">=1.12" },
{ name = "parameterized", specifier = ">=0.9.0" },
{ name = "platformdirs", specifier = ">=4.3.7" },
{ name = "posthog", specifier = ">=3.0.0" },
@ -583,6 +586,7 @@ requires-dist = [
{ name = "pygls", specifier = ">=2.0.0,<3.0.0" },
{ name = "pytest", specifier = ">=7.0.0" },
{ name = "pytest-asyncio", specifier = ">=0.18.0" },
{ name = "pytest-memray", marker = "sys_platform != 'win32'", specifier = ">=1.7" },
{ name = "pytest-timeout", specifier = ">=2.1.0" },
{ name = "requests", specifier = ">=2.28.0" },
{ name = "rich", specifier = ">=13.8.1" },
@ -2261,6 +2265,45 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/32/9f/228020e1bce6308723b5455e7de054428b9908b340b4c702dd2b3409f016/line_profiler-5.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:2b70a38fe852d7c95eca105ec603a28ca6f0bd3c909f2cca9e7cca2bf19cb77e", size = 480441, upload-time = "2026-02-23T23:31:19.162Z" },
]
[[package]]
name = "linkify-it-py"
version = "2.0.3"
source = { registry = "https://pypi.org/simple" }
resolution-markers = [
"python_full_version >= '3.9.2' and python_full_version < '3.10'",
"python_full_version < '3.9.2'",
]
dependencies = [
{ name = "uc-micro-py", version = "1.0.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/2a/ae/bb56c6828e4797ba5a4821eec7c43b8bf40f69cda4d4f5f8c8a2810ec96a/linkify-it-py-2.0.3.tar.gz", hash = "sha256:68cda27e162e9215c17d786649d1da0021a451bdc436ef9e0fa0ba5234b9b048", size = 27946, upload-time = "2024-02-04T14:48:04.179Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/04/1e/b832de447dee8b582cac175871d2f6c3d5077cc56d5575cadba1fd1cccfa/linkify_it_py-2.0.3-py3-none-any.whl", hash = "sha256:6bcbc417b0ac14323382aef5c5192c0075bf8a9d6b41820a2b66371eac6b6d79", size = 19820, upload-time = "2024-02-04T14:48:02.496Z" },
]
[[package]]
name = "linkify-it-py"
version = "2.1.0"
source = { registry = "https://pypi.org/simple" }
resolution-markers = [
"python_full_version >= '3.14' and sys_platform == 'emscripten'",
"python_full_version >= '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'",
"python_full_version == '3.13.*' and sys_platform == 'emscripten'",
"python_full_version == '3.13.*' and sys_platform != 'emscripten' and sys_platform != 'win32'",
"python_full_version == '3.12.*' and sys_platform == 'emscripten'",
"python_full_version == '3.12.*' and sys_platform != 'emscripten' and sys_platform != 'win32'",
"python_full_version == '3.11.*' and sys_platform == 'emscripten'",
"python_full_version == '3.11.*' and sys_platform != 'emscripten' and sys_platform != 'win32'",
"python_full_version == '3.10.*'",
]
dependencies = [
{ name = "uc-micro-py", version = "2.0.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.10' and sys_platform != 'win32') or (python_full_version == '3.10.*' and sys_platform == 'win32')" },
]
sdist = { url = "https://files.pythonhosted.org/packages/2e/c9/06ea13676ef354f0af6169587ae292d3e2406e212876a413bf9eece4eb23/linkify_it_py-2.1.0.tar.gz", hash = "sha256:43360231720999c10e9328dc3691160e27a718e280673d444c38d7d3aaa3b98b", size = 29158, upload-time = "2026-03-01T07:48:47.683Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/b4/de/88b3be5c31b22333b3ca2f6ff1de4e863d8fe45aaea7485f591970ec1d3e/linkify_it_py-2.1.0-py3-none-any.whl", hash = "sha256:0d252c1594ecba2ecedc444053db5d3a9b7ec1b0dd929c8f1d74dce89f86c05e", size = 19878, upload-time = "2026-03-01T07:48:46.098Z" },
]
[[package]]
name = "llvmlite"
version = "0.43.0"
@ -2515,6 +2558,11 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/42/d7/1ec15b46af6af88f19b8e5ffea08fa375d433c998b8a7639e76935c14f1f/markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1", size = 87528, upload-time = "2023-06-03T06:41:11.019Z" },
]
[package.optional-dependencies]
linkify = [
{ name = "linkify-it-py", version = "2.0.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" },
]
[[package]]
name = "markdown-it-py"
version = "4.0.0"
@ -2542,6 +2590,11 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/94/54/e7d793b573f298e1c9013b8c4dade17d481164aa517d1d7148619c2cedbf/markdown_it_py-4.0.0-py3-none-any.whl", hash = "sha256:87327c59b172c5011896038353a81343b6754500a08cd7a4973bb48c6d578147", size = 87321, upload-time = "2025-08-11T12:57:51.923Z" },
]
[package.optional-dependencies]
linkify = [
{ name = "linkify-it-py", version = "2.1.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.10' and sys_platform != 'win32') or (python_full_version == '3.10.*' and sys_platform == 'win32')" },
]
[[package]]
name = "markupsafe"
version = "3.0.3"
@ -2650,6 +2703,45 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/af/33/ee4519fa02ed11a94aef9559552f3b17bb863f2ecfe1a35dc7f548cde231/matplotlib_inline-0.2.1-py3-none-any.whl", hash = "sha256:d56ce5156ba6085e00a9d54fead6ed29a9c47e215cd1bba2e976ef39f5710a76", size = 9516, upload-time = "2025-10-23T09:00:20.675Z" },
]
[[package]]
name = "mdit-py-plugins"
version = "0.4.2"
source = { registry = "https://pypi.org/simple" }
resolution-markers = [
"python_full_version >= '3.9.2' and python_full_version < '3.10'",
"python_full_version < '3.9.2'",
]
dependencies = [
{ name = "markdown-it-py", version = "3.0.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/19/03/a2ecab526543b152300717cf232bb4bb8605b6edb946c845016fa9c9c9fd/mdit_py_plugins-0.4.2.tar.gz", hash = "sha256:5f2cd1fdb606ddf152d37ec30e46101a60512bc0e5fa1a7002c36647b09e26b5", size = 43542, upload-time = "2024-09-09T20:27:49.564Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/a7/f7/7782a043553ee469c1ff49cfa1cdace2d6bf99a1f333cf38676b3ddf30da/mdit_py_plugins-0.4.2-py3-none-any.whl", hash = "sha256:0c673c3f889399a33b95e88d2f0d111b4447bdfea7f237dab2d488f459835636", size = 55316, upload-time = "2024-09-09T20:27:48.397Z" },
]
[[package]]
name = "mdit-py-plugins"
version = "0.5.0"
source = { registry = "https://pypi.org/simple" }
resolution-markers = [
"python_full_version >= '3.14' and sys_platform == 'emscripten'",
"python_full_version >= '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'",
"python_full_version == '3.13.*' and sys_platform == 'emscripten'",
"python_full_version == '3.13.*' and sys_platform != 'emscripten' and sys_platform != 'win32'",
"python_full_version == '3.12.*' and sys_platform == 'emscripten'",
"python_full_version == '3.12.*' and sys_platform != 'emscripten' and sys_platform != 'win32'",
"python_full_version == '3.11.*' and sys_platform == 'emscripten'",
"python_full_version == '3.11.*' and sys_platform != 'emscripten' and sys_platform != 'win32'",
"python_full_version == '3.10.*'",
]
dependencies = [
{ name = "markdown-it-py", version = "4.0.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.10' and sys_platform != 'win32') or (python_full_version == '3.10.*' and sys_platform == 'win32')" },
]
sdist = { url = "https://files.pythonhosted.org/packages/b2/fd/a756d36c0bfba5f6e39a1cdbdbfdd448dc02692467d83816dff4592a1ebc/mdit_py_plugins-0.5.0.tar.gz", hash = "sha256:f4918cb50119f50446560513a8e311d574ff6aaed72606ddae6d35716fe809c6", size = 44655, upload-time = "2025-08-11T07:25:49.083Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/fb/86/dd6e5db36df29e76c7a7699123569a4a18c1623ce68d826ed96c62643cae/mdit_py_plugins-0.5.0-py3-none-any.whl", hash = "sha256:07a08422fc1936a5d26d146759e9155ea466e842f5ab2f7d2266dd084c8dab1f", size = 57205, upload-time = "2025-08-11T07:25:47.597Z" },
]
[[package]]
name = "mdurl"
version = "0.1.2"
@ -2659,6 +2751,61 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" },
]
[[package]]
name = "memray"
version = "1.19.2"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "jinja2", marker = "python_full_version < '3.11' or sys_platform != 'win32'" },
{ name = "rich", marker = "python_full_version < '3.11' or sys_platform != 'win32'" },
{ name = "textual", marker = "python_full_version < '3.11' or sys_platform != 'win32'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/e9/db/56ff21f47be261ab781105b233d1851d3f2fcdd4f08ebf689f6d6fd84f0d/memray-1.19.2.tar.gz", hash = "sha256:680cb90ac4564d140673ac9d8b7a7e07a8405bd1fb8f933da22616f93124ca84", size = 2410256, upload-time = "2026-03-13T15:22:31.825Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/3e/5f/48c6d7c6e4d02883d0c3de98c46c71d20c53038dfdde79614d0e55f9f163/memray-1.19.2-cp310-cp310-macosx_10_14_x86_64.whl", hash = "sha256:50d7130bb0c8609176b3b691c8b67fc92805180166e087549a59e7881ae8cf36", size = 2181142, upload-time = "2026-03-13T15:20:26.87Z" },
{ url = "https://files.pythonhosted.org/packages/1d/85/34d5dc497741bf684cfb5f59d58428b6fd4a034e55cb950339ee8f137f9d/memray-1.19.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3643d601c4c1c413a62fb296598ed05dce1e1c3a58ea5c8659ae98ad36ce3a7a", size = 2162529, upload-time = "2026-03-13T15:20:29.187Z" },
{ url = "https://files.pythonhosted.org/packages/95/5f/ca6ab3cd76de6134cbe29f5a6daa77234f216ae9bd8c963beda226a22653/memray-1.19.2-cp310-cp310-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:661aca0dbf4c448eef93f2f0bd0852eeefe3de2460e8105c2160c86e308beea5", size = 9707355, upload-time = "2026-03-13T15:20:30.941Z" },
{ url = "https://files.pythonhosted.org/packages/bd/c9/4b79508b2cf646ca3fe3c87bdef80cd26362679274b26dab1f4b725ebba0/memray-1.19.2-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d13f33f1fa76165c5596e73bc45a366d58066be567fb131498cd770fa87f5a02", size = 9938651, upload-time = "2026-03-13T15:20:33.755Z" },
{ url = "https://files.pythonhosted.org/packages/d5/d6/ca9cef1c0aba2245c41aed699a45a748db7b0dd8a9a63484e809b0f8e448/memray-1.19.2-cp310-cp310-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:74291aa9bbf54ff2ac5df2665c792d490c576720dd2cbad89af53528bda5443f", size = 9327619, upload-time = "2026-03-13T15:20:36.179Z" },
{ url = "https://files.pythonhosted.org/packages/ce/66/572f819ff58d0f0fefeeeeaa7206f192107f39027a92fd90af1c1cbff61b/memray-1.19.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:716a1b2569e049d0cb769015e5be9138bd97bd157e67920cc9e215e011fbb9cd", size = 12158374, upload-time = "2026-03-13T15:20:39.213Z" },
{ url = "https://files.pythonhosted.org/packages/63/bf/b8f28adbd3e1eeeb88e188053a26164b195ebcf66f8af6b30003a83f5660/memray-1.19.2-cp311-cp311-macosx_10_14_x86_64.whl", hash = "sha256:c8d35a9f5b222165c5aedbfc18b79dc5161a724963a4fca8d1053faa0b571195", size = 2181644, upload-time = "2026-03-13T15:20:41.756Z" },
{ url = "https://files.pythonhosted.org/packages/21/66/0791e5514b475d6300d13ebe87839db1606b2dc2fbe00fecce4da2fb405d/memray-1.19.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3735567011cc22339aee2c59b5fc94d1bdd4a23f9990e02a2c3cccc9c3cf6de4", size = 2164670, upload-time = "2026-03-13T15:20:44.14Z" },
{ url = "https://files.pythonhosted.org/packages/0f/aa/086878e99693b174b0d04d0b267231862fb6a3cfc35cab2920284c2a2e38/memray-1.19.2-cp311-cp311-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:ab78af759eebcb8d8ecef173042515711d2dcc9600d5dd446d1592b24a89b7d9", size = 9777844, upload-time = "2026-03-13T15:20:46.266Z" },
{ url = "https://files.pythonhosted.org/packages/40/a6/40247667e72b5d8322c5dc2ef30513238b3480be1e482faaaf9cc573ff38/memray-1.19.2-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f3ae7983297d168cdcc2d05cd93a4934b9b6fe0d341a91ac5b71bf45f9cec06c", size = 10021548, upload-time = "2026-03-13T15:20:49.079Z" },
{ url = "https://files.pythonhosted.org/packages/b3/bb/50603e8f7fe950b3f6a6e09a80413a8f25c4a9d360d8b3b027a8841e1fe8/memray-1.19.2-cp311-cp311-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:08a4316d7a92eb415024b46988844ed0fd44b2d02ca00fa4a21f2481c1f803e6", size = 9400168, upload-time = "2026-03-13T15:20:51.801Z" },
{ url = "https://files.pythonhosted.org/packages/e2/89/a21e0b639496ed59d2a733e60869ff2e685c5a78891474a494e09a17dc7c/memray-1.19.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:dbdb14fd31e2a031312755dc76146aeff9d0889e82ccffe231f1f20f50526f57", size = 12234413, upload-time = "2026-03-13T15:20:54.454Z" },
{ url = "https://files.pythonhosted.org/packages/13/4e/8685c202ddd76860cd8fc5f7f552115ea6f317e9f5f16219a56f336e351e/memray-1.19.2-cp312-cp312-macosx_10_14_x86_64.whl", hash = "sha256:22d4482f559ffa91a9727693e7e338856bee5e316f922839bf8b96e0f9b8a4de", size = 2183484, upload-time = "2026-03-13T15:20:56.696Z" },
{ url = "https://files.pythonhosted.org/packages/89/79/602f55d5466f1f587cdddf0324f82752bd0319ea814bc7cca2efb8593bc8/memray-1.19.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4fd1476868177ee8d9f7f85e5a085a20cc3c3a8228a23ced72749265885d55ca", size = 2162900, upload-time = "2026-03-13T15:20:58.174Z" },
{ url = "https://files.pythonhosted.org/packages/02/1b/402207971653b9861bbbe449cbed7d82e7bb9b953dd6ac93dd4d78e76fa2/memray-1.19.2-cp312-cp312-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:23375d50faa199e1c1bc2e89f08691f6812478fddb49a1b82bebe6ef5a56df2c", size = 9731991, upload-time = "2026-03-13T15:21:00.299Z" },
{ url = "https://files.pythonhosted.org/packages/3f/7d/895ce73fcf9ab0a2b675ed49bbc91cbca14bda187e2b4df86ccefeb1c9bc/memray-1.19.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8ef3d8e4fba0b26280b550278a0660554283135cbccc34e2d49ba82a1945eb61", size = 9997104, upload-time = "2026-03-13T15:21:02.959Z" },
{ url = "https://files.pythonhosted.org/packages/a0/b9/586bf51a1321cde736d886ca8ac3d4b1f910e4f3f813d7c8eb22498ee16f/memray-1.19.2-cp312-cp312-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a4d6cf9597ae5d60f7893a0b7b6b9af9c349121446b3c1e7b9ac1d8b5d45a505", size = 9373508, upload-time = "2026-03-13T15:21:05.945Z" },
{ url = "https://files.pythonhosted.org/packages/5d/f1/7cb51edeeceaaee770d4222e833369fbc927227d27e0a917b5ad6f4b2f85/memray-1.19.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:716a0a0e9048d21da98f9107fa030a76138eb694a16a81ad15eace54fddef4cd", size = 12222756, upload-time = "2026-03-13T15:21:08.9Z" },
{ url = "https://files.pythonhosted.org/packages/34/10/cbf57c122988d6e3bd148aa374e91e0e2f156cc7db1ac6397eb6db3946d1/memray-1.19.2-cp313-cp313-macosx_10_14_x86_64.whl", hash = "sha256:13aa87ad34cc88b3f31f7205e0a4543c391032e8600dc0c0cbf22555ff816d97", size = 2182910, upload-time = "2026-03-13T15:21:11.357Z" },
{ url = "https://files.pythonhosted.org/packages/5c/0e/7979dfe7e2b034431e44e3bab86356d9bc2c4f3ed0eb1594cb0ceb38c859/memray-1.19.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d6b249618a3e4fa8e10291445a2b2dfaf6f188e7cc1765966aac8fb52cb22066", size = 2161575, upload-time = "2026-03-13T15:21:13.051Z" },
{ url = "https://files.pythonhosted.org/packages/f9/92/2f0ca3936cdf4c59bc8c59fc8738ce8854ba24fd8519988f2ece0eba10fa/memray-1.19.2-cp313-cp313-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:34985e5e638ef8d4d54de8173c5e4481c478930f545bd0eb4738a631beb63d04", size = 9732172, upload-time = "2026-03-13T15:21:15.115Z" },
{ url = "https://files.pythonhosted.org/packages/52/23/de78510b4e3a0668b793d8b5dff03f2af20eef97943ca5b3263effff799c/memray-1.19.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ee0fcfafd1e8535bdc0d0ed75bcdd48d436a6f62d467df91871366cbb3bbaebc", size = 9999447, upload-time = "2026-03-13T15:21:18.099Z" },
{ url = "https://files.pythonhosted.org/packages/00/0d/b0e50537470f93bddfa2c134177fe9332c20be44a571588866776ff92b82/memray-1.19.2-cp313-cp313-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:846185c393ff0dc6bca55819b1c83b510b77d8d561b7c0c50f4873f69579e35d", size = 9379158, upload-time = "2026-03-13T15:21:21.003Z" },
{ url = "https://files.pythonhosted.org/packages/5c/53/78f6de5c7208821b15cfbbb9da44ab4a5a881a7cc5075f9435a1700320e8/memray-1.19.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8cc31327ed71e9f6ef7e9ed558e764f0e9c3f01da13ad8547734eb65fbeade1d", size = 12226753, upload-time = "2026-03-13T15:21:24.041Z" },
{ url = "https://files.pythonhosted.org/packages/e1/f4/3d8205b9f46657d26d54d1e644f27d09955b737189354a01907d8a08c7e2/memray-1.19.2-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:410377c0eae8d544421f74b919a18e119279fe1a2fa5ff381404b55aeb4c6514", size = 2184823, upload-time = "2026-03-13T15:21:27.176Z" },
{ url = "https://files.pythonhosted.org/packages/fb/07/7a342801317eff410a8267b55cb7514e156ee1f574e690852eb240bbe9fd/memray-1.19.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:a53dc4032581ed075fcb62a4acc0ced14fb90a8269159d4e53dfac7af269c255", size = 2163669, upload-time = "2026-03-13T15:21:29.123Z" },
{ url = "https://files.pythonhosted.org/packages/d4/00/2c342b1472f9f03018bb88c80760cdfa6979404d63c4300c607fd0562607/memray-1.19.2-cp314-cp314-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:a7630865fbf3823aa2d1a6f7536f7aec88cf8ccf5b2498aad44adbc733f6bd2e", size = 9732615, upload-time = "2026-03-13T15:21:31.038Z" },
{ url = "https://files.pythonhosted.org/packages/fe/ae/2cf960526c9b1f6d46977fc70e11de29ca6b9eafeeb42d1cec7d3bcb056a/memray-1.19.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c23e2b4be22a23cf5cae08854549e3460869a36c5f4bedc739b646ac97da4a60", size = 9979299, upload-time = "2026-03-13T15:21:34.072Z" },
{ url = "https://files.pythonhosted.org/packages/e1/78/73ee3d0ebee3c38fbb2d51766854d2932beec6481063532a6019bf340a2d/memray-1.19.2-cp314-cp314-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:95b6c02ca7f8555b5bee1c54c50cbbcf2033e07ebca95dade2ac3a27bb36b320", size = 9375722, upload-time = "2026-03-13T15:21:36.884Z" },
{ url = "https://files.pythonhosted.org/packages/3b/c6/2f02475e85ccd32fa306736986f1f77f99365066ecdc859f5078148ebc40/memray-1.19.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:907470e2684568eb91a993ae69a08b1430494c8f2f6ef489b4b78519d9dae3d0", size = 12220041, upload-time = "2026-03-13T15:21:40.16Z" },
{ url = "https://files.pythonhosted.org/packages/76/12/01bb32188c011e6d802469e04c1d7c8054eb8300164e2269c830f5b26a8e/memray-1.19.2-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:124138f35fea36c434256c417f1b8cb32f78769f208530c1e56bf2c2b7654120", size = 2201353, upload-time = "2026-03-13T15:21:42.607Z" },
{ url = "https://files.pythonhosted.org/packages/e5/e0/d9b59f8be00f27440f60b95da5db6515a1c44c481651b8d2fa8f3468fc35/memray-1.19.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:240192dc98ff0b3501055521bfd73566d339808b11bd5af10865afe6ae18abef", size = 2180420, upload-time = "2026-03-13T15:21:44.623Z" },
{ url = "https://files.pythonhosted.org/packages/a5/5c/30aca63f4b88dca79ba679675200938652c816edee34c12565d2f17ea936/memray-1.19.2-cp314-cp314t-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:edb7a3c2a9e97fb409b352f6c316598c7c0c3c22732e73704d25b9eb75ae2f2d", size = 9697953, upload-time = "2026-03-13T15:21:47.088Z" },
{ url = "https://files.pythonhosted.org/packages/9f/02/9e4a68bdd5ebc9079f97bdf287cc0ccc51c18e9edc205de7d41648315809/memray-1.19.2-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b6a43db4c1466446a905a77944813253231ac0269f758c6c6bc03ceb1821c1b6", size = 9944517, upload-time = "2026-03-13T15:21:50.125Z" },
{ url = "https://files.pythonhosted.org/packages/4a/f0/3adad59ebed6841c2f88b43c9b90cc9c03ff086129a8aef3cff23c92d6ac/memray-1.19.2-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cf951dae8d27d502fbc549f6784460a70cce05b1e71bf5446d8692a74051f14f", size = 9365528, upload-time = "2026-03-13T15:21:53.141Z" },
{ url = "https://files.pythonhosted.org/packages/45/0e/083e00fe74e576b463e7b00e4214b8962f27bd70c5c77e494c0211a77342/memray-1.19.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:8033b78232555bb1856b3298bef2898ec8b334d3d465c1822c665206d1fa910a", size = 12143894, upload-time = "2026-03-13T15:21:56.486Z" },
{ url = "https://files.pythonhosted.org/packages/4d/1b/b2e54cbe9a67a63a2f8b0c0d3cbfef0db8592e00ced4d6afb324245910e5/memray-1.19.2-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:f82ee0a0b50a04894dacfbe49db1c259fa8a19efb094514b0100e9916d3b1c55", size = 2183022, upload-time = "2026-03-13T15:22:14.81Z" },
{ url = "https://files.pythonhosted.org/packages/fd/1e/17a3e62bccf2c34cfa2208c28bdab127afd279c8a6d7fbb7c2b835a606db/memray-1.19.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5b1c58a54372707b3977c079ef93e751109f0bfe566adc7bd640971d123d8d11", size = 2163707, upload-time = "2026-03-13T15:22:16.507Z" },
{ url = "https://files.pythonhosted.org/packages/9c/bd/a9bb3d747b138c8bc382389857879941f6c7a83fb3beeebce1c3251ad401/memray-1.19.2-cp39-cp39-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:fa236140320ef1b8801cd289962fd81a2d7e59484cc3ecdbc851d1b5c321795e", size = 9703623, upload-time = "2026-03-13T15:22:19.551Z" },
{ url = "https://files.pythonhosted.org/packages/a3/70/24006fcab90eb6a21b5b2c45f046746578a817c82cb7ed2987d08dffad9d/memray-1.19.2-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:816baeda8e62fddf99c900bdc9e748339dba65df091a7c7ceb0f4f9544c2e7ec", size = 9925887, upload-time = "2026-03-13T15:22:23.297Z" },
{ url = "https://files.pythonhosted.org/packages/41/5e/6ac00a20da0b84c9e41d1e0ebaf27d49907ff7be1cd66b1e2b410d1c9c25/memray-1.19.2-cp39-cp39-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a1532d5dcf8036ec55e43ab6d6b1ff4e70b11a3902dd1c8396b6d2a24ec69d98", size = 9323522, upload-time = "2026-03-13T15:22:26.144Z" },
{ url = "https://files.pythonhosted.org/packages/2d/e0/74c17f7095e7c476fef3f47a13637fe0d717b58c8e0e5e06a388b7ca3cac/memray-1.19.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:86060df2e8e18cc867335c50bf92deb973d4dff856bdb565e17fc86ca7a6619b", size = 12154107, upload-time = "2026-03-13T15:22:29.341Z" },
]
[[package]]
name = "ml-dtypes"
version = "0.5.4"
@ -4368,6 +4515,20 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/e5/35/f8b19922b6a25bc0880171a2f1a003eaeb93657475193ab516fd87cac9da/pytest_asyncio-1.3.0-py3-none-any.whl", hash = "sha256:611e26147c7f77640e6d0a92a38ed17c3e9848063698d5c93d5aa7aa11cebff5", size = 15075, upload-time = "2025-11-10T16:07:45.537Z" },
]
[[package]]
name = "pytest-memray"
version = "1.8.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "memray", marker = "python_full_version < '3.11' or sys_platform != 'win32'" },
{ name = "pytest", version = "8.4.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" },
{ name = "pytest", version = "9.0.2", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.10' and sys_platform != 'win32') or (python_full_version == '3.10.*' and sys_platform == 'win32')" },
]
sdist = { url = "https://files.pythonhosted.org/packages/3d/28/f67963efed56d847d028d0bb939f26cdeb32c4de474b3befc9da43bf18f9/pytest_memray-1.8.0.tar.gz", hash = "sha256:c0c706ef81941a7aa7064f2b3b8b5cdc0cea72b5277c6a6a09b113ca9ab30bdb", size = 240608, upload-time = "2025-08-18T17:32:47.329Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/cc/52/b8b8e126c176c5f405b307354e1722025063ea104dbd7d286e8b18a76e9f/pytest_memray-1.8.0-py3-none-any.whl", hash = "sha256:44da9fe0d98541abf4cc76acea6e4a9c525b3c8e604655e5537705f336c9b875", size = 17688, upload-time = "2025-08-18T17:32:45.476Z" },
]
[[package]]
name = "pytest-timeout"
version = "2.4.0"
@ -5338,6 +5499,26 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/33/d1/8bb87d21e9aeb323cc03034f5eaf2c8f69841e40e4853c2627edf8111ed3/termcolor-3.3.0-py3-none-any.whl", hash = "sha256:cf642efadaf0a8ebbbf4bc7a31cec2f9b5f21a9f726f4ccbb08192c9c26f43a5", size = 7734, upload-time = "2025-12-29T12:55:20.718Z" },
]
[[package]]
name = "textual"
version = "8.2.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "markdown-it-py", version = "3.0.0", source = { registry = "https://pypi.org/simple" }, extra = ["linkify"], marker = "python_full_version < '3.10'" },
{ name = "markdown-it-py", version = "4.0.0", source = { registry = "https://pypi.org/simple" }, extra = ["linkify"], marker = "(python_full_version >= '3.10' and sys_platform != 'win32') or (python_full_version == '3.10.*' and sys_platform == 'win32')" },
{ name = "mdit-py-plugins", version = "0.4.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" },
{ name = "mdit-py-plugins", version = "0.5.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.10' and sys_platform != 'win32') or (python_full_version == '3.10.*' and sys_platform == 'win32')" },
{ name = "platformdirs", version = "4.4.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" },
{ name = "platformdirs", version = "4.9.4", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.10' and sys_platform != 'win32') or (python_full_version == '3.10.*' and sys_platform == 'win32')" },
{ name = "pygments", marker = "python_full_version < '3.11' or sys_platform != 'win32'" },
{ name = "rich", marker = "python_full_version < '3.11' or sys_platform != 'win32'" },
{ name = "typing-extensions", marker = "python_full_version < '3.11' or sys_platform != 'win32'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/4f/07/766ad19cf2b15cae2d79e0db46a1b783b62316e9ff3e058e7424b2a4398b/textual-8.2.1.tar.gz", hash = "sha256:4176890e9cd5c95dcdd206541b2956b0808e74c8c36381c88db53dcb45237451", size = 1848386, upload-time = "2026-03-29T03:57:32.242Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/25/09/c6f000c2e3702036e593803319af02feee58a662528d0d5728a37e1cf81b/textual-8.2.1-py3-none-any.whl", hash = "sha256:746cbf947a8ca875afc09779ef38cadbc7b9f15ac886a5090f7099fef5ade990", size = 723871, upload-time = "2026-03-29T03:57:34.334Z" },
]
[[package]]
name = "tomli"
version = "2.4.1"
@ -6324,6 +6505,39 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl", hash = "sha256:06a47e5700f3081aab02b2e513160914ff0694bce9947d6b76ebd6bf57cfc5d1", size = 348521, upload-time = "2025-12-13T17:45:33.889Z" },
]
[[package]]
name = "uc-micro-py"
version = "1.0.3"
source = { registry = "https://pypi.org/simple" }
resolution-markers = [
"python_full_version >= '3.9.2' and python_full_version < '3.10'",
"python_full_version < '3.9.2'",
]
sdist = { url = "https://files.pythonhosted.org/packages/91/7a/146a99696aee0609e3712f2b44c6274566bc368dfe8375191278045186b8/uc-micro-py-1.0.3.tar.gz", hash = "sha256:d321b92cff673ec58027c04015fcaa8bb1e005478643ff4a500882eaab88c48a", size = 6043, upload-time = "2024-02-09T16:52:01.654Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/37/87/1f677586e8ac487e29672e4b17455758fce261de06a0d086167bb760361a/uc_micro_py-1.0.3-py3-none-any.whl", hash = "sha256:db1dffff340817673d7b466ec86114a9dc0e9d4d9b5ba229d9d60e5c12600cd5", size = 6229, upload-time = "2024-02-09T16:52:00.371Z" },
]
[[package]]
name = "uc-micro-py"
version = "2.0.0"
source = { registry = "https://pypi.org/simple" }
resolution-markers = [
"python_full_version >= '3.14' and sys_platform == 'emscripten'",
"python_full_version >= '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'",
"python_full_version == '3.13.*' and sys_platform == 'emscripten'",
"python_full_version == '3.13.*' and sys_platform != 'emscripten' and sys_platform != 'win32'",
"python_full_version == '3.12.*' and sys_platform == 'emscripten'",
"python_full_version == '3.12.*' and sys_platform != 'emscripten' and sys_platform != 'win32'",
"python_full_version == '3.11.*' and sys_platform == 'emscripten'",
"python_full_version == '3.11.*' and sys_platform != 'emscripten' and sys_platform != 'win32'",
"python_full_version == '3.10.*'",
]
sdist = { url = "https://files.pythonhosted.org/packages/78/67/9a363818028526e2d4579334460df777115bdec1bb77c08f9db88f6389f2/uc_micro_py-2.0.0.tar.gz", hash = "sha256:c53691e495c8db60e16ffc4861a35469b0ba0821fe409a8a7a0a71864d33a811", size = 6611, upload-time = "2026-03-01T06:31:27.526Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/61/73/d21edf5b204d1467e06500080a50f79d49ef2b997c79123a536d4a17d97c/uc_micro_py-2.0.0-py3-none-any.whl", hash = "sha256:3603a3859af53e5a39bc7677713c78ea6589ff188d70f4fee165db88e22b242c", size = 6383, upload-time = "2026-03-01T06:31:26.257Z" },
]
[[package]]
name = "unidiff"
version = "0.7.5"