Skip to content

feat(stdlib): expose Python type references and dict/list constructors in Builtins#291

Merged
dbrattli merged 1 commit intomainfrom
feat/builtins-type-refs
May 3, 2026
Merged

feat(stdlib): expose Python type references and dict/list constructors in Builtins#291
dbrattli merged 1 commit intomainfrom
feat/builtins-type-refs

Conversation

@dbrattli
Copy link
Copy Markdown
Collaborator

@dbrattli dbrattli commented May 1, 2026

Closes #290.

Summary

Fable.Python.Builtins exposes int, float, str, bytes, len, isinstance, etc. as methods on IExports, but the type values themselves (the int / dict / list Python objects) and the dict() / list() constructors weren't exposed. Downstream libraries like Thoth.Json.Python and Fable.TypedJson currently redeclare them privately as [<Emit>] boilerplate.

Changes

Type references (top-level let bindings in Builtins)

For use with Fable.Core.PyInterop.pyInstanceof:

  • pyInt, pyFloat, pyBool, pyStr, pyBytes
  • pyList, pyDict, pyTuple, pySet
  • pyNone — Python's None singleton, typed as obj

The py prefix is necessary because int, float, bool, str, list, dict, etc. would shadow F#/.NET built-in types.

New constructors on Builtins.IExports

  • bool: obj -> bool — completing the set alongside int/float/str
  • dict: unit -> Dictionary<string, obj>
  • dict: IEnumerable<string * 'V> -> Dictionary<string, 'V> — generic in 'V
  • list: IEnumerable<'T> -> ResizeArray<'T>

Dictionary<string,'V> and ResizeArray<'T> are used (rather than obj) to stay idiomatic per BINDINGS_GUIDE.md — these are the F# types that Fable maps to Python's native dict and list.

Result

Downstream consumers can now drop the private [<Emit>] boilerplate and write:

open Fable.Core.PyInterop
open Fable.Python.Builtins

pyInstanceof v pyInt        // was: [<Emit("isinstance($0, int)")>]
pyInstanceof v pyDict       // was: [<Emit("isinstance($0, dict)")>]
builtins.dict ()            // was: [<Emit("dict()")>]
builtins.list items         // was: [<Emit("list($0)")>]
pyNone                      // was: [<Emit("None")>]

Test plan

  • Added 6 new test cases in test/TestBuiltins.fs covering bool, dict() empty, dict from pairs, list, pyInstanceof against every type reference, and pyNone
  • All 539 tests pass (just test-python)
  • Verified generated Python is isinstance(v, int), builtins.dict(), None, etc. — exactly what the issue requested
  • No breaking changes — purely additive

🤖 Generated with Claude Code

…s in Builtins

Closes #290.

Adds the missing pieces in `Fable.Python.Builtins` that downstream interop
libraries (Thoth.Json.Python, Fable.TypedJson) currently work around with
private `[<Emit>]` declarations:

- Type value references (`pyInt`, `pyFloat`, `pyBool`, `pyStr`, `pyBytes`,
  `pyList`, `pyDict`, `pyTuple`, `pySet`) for use as the second argument to
  `Fable.Core.PyInterop.pyInstanceof`. The `py` prefix avoids colliding
  with F#/.NET built-in types.
- `pyNone` value for Python's `None` singleton, useful as a JSON-null
  sentinel and at interop sites that need an explicit None.
- `bool`, `dict`, and `list` constructors on `Builtins.IExports`, completing
  the set alongside the existing `int`/`float`/`str`/`bytes` constructors.
  `dict` and `list` are typed to return `Dictionary<string,'V>` and
  `ResizeArray<'T>` respectively to stay idiomatic per BINDINGS_GUIDE.md.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@dbrattli dbrattli merged commit 05f2bea into main May 3, 2026
9 checks passed
@dbrattli dbrattli deleted the feat/builtins-type-refs branch May 3, 2026 08:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Expose Python type references and dict/list constructors in Builtins

1 participant