pydantic model generator for atproto lexicons
at main 3.6 kB view raw
1"""integration tests for git provider support.""" 2 3import subprocess 4import tempfile 5from pathlib import Path 6 7import pytest 8 9pytestmark = pytest.mark.integration 10 11# repos known to exist on each provider with lexicons 12GIT_PROVIDER_REPOS = [ 13 pytest.param( 14 "https://github.com/bluesky-social/atproto.git", 15 id="github-full-url", 16 ), 17 pytest.param( 18 "bluesky-social/atproto", 19 id="github-shorthand", 20 ), 21 pytest.param( 22 "https://tangled.org/zzstoatzz.io/plyr.fm.git", 23 id="tangled-full-url", 24 ), 25 pytest.param( 26 "zzstoatzz.io/plyr.fm", 27 id="tangled-shorthand", 28 ), 29] 30 31 32@pytest.mark.parametrize("source", GIT_PROVIDER_REPOS) 33def test_clone_and_generate(source: str) -> None: 34 """test cloning and generating from various git sources.""" 35 with tempfile.TemporaryDirectory() as tmp: 36 output_dir = Path(tmp) / "output" 37 result = subprocess.run( 38 ["uv", "run", "pmgfal", source, "-o", str(output_dir), "--no-cache"], 39 capture_output=True, 40 text=True, 41 timeout=120, 42 ) 43 assert result.returncode == 0, f"failed: {result.stderr}" 44 assert output_dir.exists() 45 py_files = list(output_dir.glob("*.py")) 46 assert len(py_files) > 0, "no python files generated" 47 48 49def test_shorthand_fallback_on_nonexistent() -> None: 50 """test that shorthand tries providers in order and fails gracefully.""" 51 result = subprocess.run( 52 [ 53 "uv", 54 "run", 55 "pmgfal", 56 "nonexistent-owner-12345/nonexistent-repo-67890", 57 "-o", 58 "/tmp/test", 59 ], 60 capture_output=True, 61 text=True, 62 timeout=120, 63 ) 64 assert result.returncode == 1 65 output = result.stdout + result.stderr 66 assert "trying github" in output 67 assert "trying tangled" in output 68 assert "could not find" in output 69 70 71def test_invalid_source_not_directory() -> None: 72 """test error on invalid local path.""" 73 result = subprocess.run( 74 ["uv", "run", "pmgfal", "/nonexistent/path/to/lexicons", "-o", "/tmp/test"], 75 capture_output=True, 76 text=True, 77 ) 78 assert result.returncode == 1 79 output = result.stdout + result.stderr 80 assert "not a directory" in output 81 82 83def test_plyr_fm_generates_valid_models() -> None: 84 """test that plyr.fm lexicons generate importable pydantic models.""" 85 with tempfile.TemporaryDirectory() as tmp: 86 output_dir = Path(tmp) / "output" 87 88 # generate models from plyr.fm 89 result = subprocess.run( 90 [ 91 "uv", 92 "run", 93 "pmgfal", 94 "zzstoatzz.io/plyr.fm", 95 "-o", 96 str(output_dir), 97 "-p", 98 "fm.plyr", 99 "--no-cache", 100 ], 101 capture_output=True, 102 text=True, 103 timeout=120, 104 ) 105 assert result.returncode == 0, ( 106 f"generation failed: {result.stdout}{result.stderr}" 107 ) 108 109 # find the generated file 110 py_files = list(output_dir.glob("*.py")) 111 assert len(py_files) == 1, f"expected 1 file, got {py_files}" 112 113 # read and validate the generated code 114 content = py_files[0].read_text() 115 116 # should have pydantic imports 117 assert "from pydantic import BaseModel" in content 118 119 # should have fm.plyr models (check for common ones) 120 assert "class FmPlyr" in content 121 122 # compile the generated code to check for syntax errors 123 compile(content, py_files[0].name, "exec")