Compare commits

...
Author SHA1 Message Date
MervinPraisonandClaude 6521beb7b2 fix: stub HOME/USERPROFILE in test_default_sqlite_url for Windows (fixes #255)
🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
2026-07-29 09:21:35 +00:00
MervinPraison 9e3384c40a Release v0.3.137 2026-07-29 02:06:56 +00:00
praisonai-triage-agent[bot] e12416e15b Merge pull request #254 from MervinPraison/claude/issue-252-20260728-000000
fix: make five unit tests pass on Windows
2026-07-28 11:38:05 +00:00
MervinPraisonandClaude 652d612d35 fix: make five unit tests pass on Windows (fixes #252)
Resolve cross-platform failures caused by Windows' coarse time.time()
resolution, backslash path separators, and reliance on the grep binary.

- lifecycle: measure hook durations with time.perf_counter() so
  startup_time/shutdown_time are non-zero on Windows' low-res wall clock
- datastore: build the default sqlite URL with Path.as_posix() for a
  consistent forward-slash URL across platforms
- test_audio_hooks: allow last_chunk_at == started_at (clock granularity)
- test_sqlalchemy_datastore: compare against as_posix() paths
- test_unified_naming: replace grep subprocess with a portable Python scan

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
2026-07-28 10:17:52 +00:00
8 changed files with 41 additions and 24 deletions

No files matched your search

+1 -1
View File
@@ -1,6 +1,6 @@
[project]
name = "aiui"
version = "0.3.136"
version = "0.3.137"
description = "YAML-driven website generator - CLI and compiler"
readme = "README.md"
license = {text = "MIT"}
+1 -1
View File
@@ -1,3 +1,3 @@
"""Version information."""
__version__ = "0.3.136"
__version__ = "0.3.137"
+1 -1
View File
@@ -591,7 +591,7 @@ class SQLAlchemyDataStore(BaseDataStore):
base = Path(os.environ.get("AIUI_DATA_DIR", str(Path.home() / ".praisonaiui")))
base.mkdir(parents=True, exist_ok=True)
db_path = base / "aiui.db"
return f"sqlite+aiosqlite:///{db_path}"
return f"sqlite+aiosqlite:///{db_path.as_posix()}"
async def _ensure_initialized(self) -> None:
"""Lazy initialization of SQLAlchemy engine and tables."""
+4 -4
View File
@@ -175,7 +175,7 @@ async def run_startup_hooks() -> None:
return
_log.info(f"Running {len(_startup_hooks)} startup hooks")
start_time = time.time()
start_time = time.perf_counter()
for hook in _startup_hooks:
try:
@@ -187,7 +187,7 @@ async def run_startup_hooks() -> None:
_log.error(f"Startup hook failed: {getattr(hook, '__name__', str(hook))}: {e}")
# Continue with other hooks - individual failures shouldn't break startup
execution_time = time.time() - start_time
execution_time = time.perf_counter() - start_time
_lifecycle_state.update(
{
"startup_completed": True,
@@ -209,7 +209,7 @@ async def run_shutdown_hooks() -> None:
_lifecycle_state["shutdown_initiated"] = True
_log.info(f"Running {len(_shutdown_hooks)} shutdown hooks")
start_time = time.time()
start_time = time.perf_counter()
# Get shutdown timeout from environment
timeout = float(os.environ.get("AIUI_SHUTDOWN_TIMEOUT", "30.0"))
@@ -227,7 +227,7 @@ async def run_shutdown_hooks() -> None:
try:
await asyncio.wait_for(_execute_hooks(), timeout=timeout)
execution_time = time.time() - start_time
execution_time = time.perf_counter() - start_time
_lifecycle_state["shutdown_time"] = execution_time
_log.info(f"Shutdown hooks completed in {execution_time:.3f}s")
except asyncio.TimeoutError:
+1 -1
View File
@@ -305,7 +305,7 @@ class TestAudioSessionManagement:
session = _audio_sessions[session_id]
assert session["chunks_received"] == 1
assert session["bytes_received"] == len(test_data)
assert session["last_chunk_at"] > session["started_at"]
assert session["last_chunk_at"] >= session["started_at"]
# Check global stats were updated
assert _audio_stats["total_chunks"] == 1
+6 -4
View File
@@ -89,13 +89,15 @@ async def test_missing_dependencies_error(monkeypatch):
@pytest.mark.asyncio
async def test_default_sqlite_url():
async def test_default_sqlite_url(tmp_path):
"""Default should create ~/.praisonaiui/aiui.db"""
from praisonaiui.datastore import SQLAlchemyDataStore
with patch.dict(os.environ, {}, clear=True):
home = str(tmp_path)
env = {"HOME": home, "USERPROFILE": home}
with patch.dict(os.environ, env, clear=True):
store = SQLAlchemyDataStore()
expected = str(Path.home() / ".praisonaiui" / "aiui.db")
expected = (Path(home) / ".praisonaiui" / "aiui.db").as_posix()
assert expected in store._database_url
assert store._database_url.startswith("sqlite+aiosqlite:///")
@@ -108,7 +110,7 @@ async def test_respects_aiui_data_dir_env():
with tempfile.TemporaryDirectory() as tmpdir:
with patch.dict(os.environ, {"AIUI_DATA_DIR": tmpdir}):
store = SQLAlchemyDataStore()
expected = str(Path(tmpdir) / "aiui.db")
expected = (Path(tmpdir) / "aiui.db").as_posix()
assert expected in store._database_url
+26 -11
View File
@@ -151,17 +151,32 @@ class TestCompetitorScrub:
"""The peer framework's name must never reappear in the source tree."""
def test_zero_matches_in_source(self):
import subprocess
r = subprocess.run(
["grep", "-rn", "-i", "chainlit",
"src/praisonaiui", "docs", "examples", "tests",
"--include=*.py", "--include=*.md", "--include=*.yaml",
"--include=*.yml", "--include=*.ts", "--include=*.tsx"],
capture_output=True, text=True, cwd=_repo_root(),
)
hits = [line for line in r.stdout.splitlines()
if ".pyc" not in line
and "tests/unit/test_unified_naming" not in line]
import pathlib
root = pathlib.Path(_repo_root())
needle = "chainlit"
suffixes = {".py", ".md", ".yaml", ".yml", ".ts", ".tsx"}
search_dirs = ["src/praisonaiui", "docs", "examples", "tests"]
hits = []
for rel in search_dirs:
base = root / rel
if not base.exists():
continue
for path in base.rglob("*"):
if not path.is_file() or path.suffix not in suffixes:
continue
rel_path = path.relative_to(root).as_posix()
if "test_unified_naming" in rel_path:
continue
try:
text = path.read_text(encoding="utf-8", errors="ignore")
except OSError:
continue
for lineno, line in enumerate(text.splitlines(), 1):
if needle in line.lower():
hits.append(f"{rel_path}:{lineno}:{line}")
assert not hits, f"Competitor name reappeared: {hits}"
Generated
+1 -1
View File
@@ -207,7 +207,7 @@ wheels = [
[[package]]
name = "aiui"
version = "0.3.136"
version = "0.3.137"
source = { editable = "." }
dependencies = [
{ name = "pydantic" },