Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix: make baml_py work with playwright/inspect (#1214)
When using `baml_py.Image` in a Pydantic model with playwright-python (the headless browser stack), the playwright library freezes up (see [user report](https://discord.com/channels/1119368998161752075/1309277325703250000)). Specifically this code suffices to repro the issue: ``` from playwright.sync_api import sync_playwright import baml_py from pydantic import BaseModel class Foo(BaseModel): screenshot: baml_py.Image print('This happens') sync_playwright().start() print('This never happens') ``` The reason turns out to be that when the playwright context manager is entered, deep in the callstack, the playwright connection grabs the stack context using `inspect.stack()`. Because of how `__get_pydantic_core_schema__` was implemented for `baml_py.Image` and `baml_py.Audio`, declaring a pydantic model that relied on either of these types would cause `inspect.stack()` to crash: ``` ============================================================================= FAILURES ============================================================================== ___________________________________________________________________________ test_inspect ____________________________________________________________________________ def test_inspect(): class LoremIpsum(pydantic.BaseModel): my_image: baml_py.Image > inspect.stack() tests/test_pydantic.py:88: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../../../.local/share/mise/installs/python/3.10.14/lib/python3.10/inspect.py:1673: in stack return getouterframes(sys._getframe(1), context) ../../../.local/share/mise/installs/python/3.10.14/lib/python3.10/inspect.py:1650: in getouterframes frameinfo = (frame,) + getframeinfo(frame, context) ../../../.local/share/mise/installs/python/3.10.14/lib/python3.10/inspect.py:1624: in getframeinfo lines, lnum = findsource(frame) ../../../.local/share/mise/installs/python/3.10.14/lib/python3.10/inspect.py:952: in findsource module = getmodule(object, file) ../../../.local/share/mise/installs/python/3.10.14/lib/python3.10/inspect.py:875: in getmodule f = getabsfile(module) ../../../.local/share/mise/installs/python/3.10.14/lib/python3.10/inspect.py:844: in getabsfile _filename = getsourcefile(object) or getfile(object) ../../../.local/share/mise/installs/python/3.10.14/lib/python3.10/inspect.py:817: in getsourcefile filename = getfile(object) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ object = <module 'rust:media_repr' from '/Users/sam/baml/integ-tests/python'> def getfile(object): """Work out which source or compiled file an object was defined in.""" if ismodule(object): if getattr(object, '__file__', None): return object.__file__ > raise TypeError('{!r} is a built-in module'.format(object)) E TypeError: <module 'rust:media_repr' from '/Users/sam/baml/integ-tests/python'> is a built-in module ../../../.local/share/mise/installs/python/3.10.14/lib/python3.10/inspect.py:778: TypeError ====================================================================== short test summary info ====================================================================== FAILED tests/test_pydantic.py::test_inspect - TypeError: <module 'rust:media_repr' from '/Users/sam/baml/integ-tests/python'> is a built-in module ``` The fix turns out to be very simple: when we evaluate Python code in `__get_pydantic_core_schema__`, we just need to actually synthesize a file and module name for the evaluated code, instead of passing in an empty string (which is what we do today). (Also, since we added pickle support for image/audio during the investigation, keep it.) <!-- ELLIPSIS_HIDDEN --> ---- > [!IMPORTANT] > Fixes `inspect.stack()` crash and adds pickle support for `baml_py.Image` and `baml_py.Audio`, with updated tests and CI workflow. > > - **Behavior**: > - Fixes `inspect.stack()` crash by providing file and module name in `__get_pydantic_core_schema__` for `baml_py.Image` and `baml_py.Audio`. > - Adds pickle support for `baml_py.Image` and `baml_py.Audio` with `py_new` and `__getnewargs__` methods. > - **Testing**: > - Adds `test_inspect` and `test_pickle` in `test_python.py` to verify compatibility and pickle functionality. > - Introduces `run_tests.sh` for running Python integration tests. > - **CI/CD**: > - Updates `primary.yml` to include a scheduled job and integration tests job. > - Adds `poetry` version to `.mise.toml`. > > <sup>This description was created by </sup>[<img alt="Ellipsis" src="https://img.shields.io/badge/Ellipsis-blue?color=175173">](https://www.ellipsis.dev?ref=BoundaryML%2Fbaml&utm_source=github&utm_medium=referral)<sup> for bb55aa2. It will automatically update as commits are pushed.</sup> <!-- ELLIPSIS_HIDDEN -->
- Loading branch information