GitXplorerGitXplorer
j

ppx_python

public
34 stars
5 forks
3 issues

Commits

List of commits on branch master.
Unverified
18413ba05503d7c49b55c6487a2a0a61907352f3

v0.18~preview.130.05+548

ppublic-release committed 2 months ago
Unverified
c7eca71b80f923d33380e956eed5cc24ba6a3874

v0.18~preview.129.42+498

ppublic-release committed 4 months ago
Unverified
5f18aa3b91e5839a5adf6bdc9f2358da940f67c7

v0.17~preview.129.36+325

ppublic-release committed 5 months ago
Unverified
e325978857849e42fddb069fa7241187a8e27e6d

v0.17~preview.129.17+77

ppublic-release committed 9 months ago
Unverified
f5265aac219d6aad7bcc6b8a5b46d64d97985ae3

v0.17~preview.129.17+77

ppublic-release committed 9 months ago
Unverified
3e3aa5216f96482815c1f3668e2035f40d2eea7e

v0.17~preview.129.15+205

ppublic-release committed 10 months ago

README

The README file for this repository.

ppx_python

Generate functions to convert OCaml values to/from Python values.

ppx_python is a PPX syntax extension that generates code for converting OCaml types to and from Python. This uses the pyml OCaml bindings for Python to start a Python runtime, create the Python objects or analyze them.

Usage

Annotate the type with [@@deriving python] as in the following example.

let () =
  if not (Pyml.Py.is_initialized ())
  then Pyml.Py.initialize ~version:3 ()
;;

type int_pair = (int * int) [@@deriving python];;

This results in two functions being created automatically, python_of_int_pair and int_pair_of_python with the following types.

val python_of_int_pair: int_pair -> pyobject
val int_pair_of_python: pyobject -> int_pair

If only one direction is needed it is possible to write one of the following.

type int_pair = (int * int) [@@deriving python_of]
type int_pair = (int * int) [@@deriving of_python]

Python converters for primitive types such as int, float, bool, or string can be brought into scope by opening Python_lib.

It is also possible to construct converters based on type expressions as in the following example.

let pyobject = [%python_of: (int * string) list] [ 1, "one"; 2, "two" ];;

Stdio.printf "pyobject: %s\n" (Pyml.Py.Object.to_string pyobject);;

let list = [%of_python: (int * string) list] pyobject;;

Conversions

The conversion is straightforward for basic types such as int, float, bool, or string. unit is converted to None.

OCaml tuples are converted into Python tuples. OCaml lists and arrays are converted in Python lists.

For options, None is used on the Python side to represent the None case. Otherwise the value is directly available. Note that this makes ocaml values Some None and None indistinguishable on the Python side.

Records are represented using Python dictionaries which keys are strings. The [@python.default] attribute can be used on some of the fields: these fields are then optional on the Python side and if not present the default value gets used.

type t =
  { foo : int [@python.default 42]
  ; bar : float
  } [@@deriving python]

Variants don't have an idiomatic Python representation. They get converted to a pair where the first element is the constructor as a string and the second element is the content of the variant or None if this variant case does not embed any data.

Below are some more involved usage examples taken from the test suite.

type t =
  { field_a : int
  ; field_b : string
  }
[@@deriving python]

type u =
  { foo : int * int
  ; bar : t
  }
[@@deriving python]

type v =
  | A
  | B of string
  | C of int
  | D of t * string
  | E of
      { x : int
      ; y : string
      }
[@@deriving python]

type 'a w =
  | One of 'a
  | Multi of 'a list
[@@deriving python]

type 'a tree =
  | Leaf of 'a
  | Node of 'a tree * 'a tree
[@@deriving python]