Class PythonCoercion

java.lang.Object
io.micronaut.context.python.PythonCoercion

@Internal public final class PythonCoercion extends Object
Coercion of Java values into a Python context: standard types, generated wrappers, pooled values and the members they expose, including the adaptation of async Java members for Python callers.
Since:
5.2.0
  • Nested Class Summary

    Nested Classes
    Modifier and Type
    Class
    Description
    static final class 
    Adapter invoked from Python async member facades.
  • Method Summary

    Modifier and Type
    Method
    Description
    static @Nullable Object
    asyncMemberValue(org.graalvm.polyglot.Value target, @Nullable Object value)
    Convert an injected Java member into a Python-context-local value suitable for async code.
    static Object[]
    coerceArgumentsToContext(org.graalvm.polyglot.Context context, Object[] args)
    Coerce arguments passed into a target Python context.
    static Object[]
    coerceDependenciesToContext(org.graalvm.polyglot.Context context, Object[] args)
    Coerce the dependencies a pooled bean is constructed with into a context.
    static <E> @Nullable List<Object>
    coerceList(@Nullable List<E> list)
    Coerce a list of types that may extend from ValueCoercible back to a native value list.
    static <E> @Nullable List<Object>
    coerceList(@Nullable List<E> list, @Nullable org.graalvm.polyglot.Context context)
    Coerce a list of types that may extend from ValueCoercible back to a native value list for the given context: generated enum constants become the Python enum members of that context.
    static <K,V> @Nullable Map<Object,Object>
    coerceMap(@Nullable Map<K,V> map)
    Coerce a map whose keys or values may extend from ValueCoercible back to a native value map.
    static <K,V> @Nullable Map<Object,Object>
    coerceMap(@Nullable Map<K,V> map, @Nullable org.graalvm.polyglot.Context context)
    Coerce a map whose keys or values may extend from ValueCoercible back to a native value map for the given context: generated enum constants among the keys and values become the Python enum members of that context, as a bare enum argument does.
    static org.graalvm.polyglot.Value
    coercePooledValue(PooledValueCoercible value, org.graalvm.polyglot.Context context)
    Converts a generated wrapper while preserving wrapper identity for the current conversion.
    static @Nullable Object
    coerceToContext(@Nullable Object value, org.graalvm.polyglot.Context context)
    Coerce values passed into a target Python context.
    static @Nullable Object
    coerceToContext(@Nullable Object value, org.graalvm.polyglot.Context context, Class<?> declaredType)
    Coerce a value using the generated Java bridge's declared parameter type.
    static @Nullable Object
    coerceValue(@Nullable Object value)
    Coerce a generated Python-backed Java wrapper back to its native Python value.
    static void
    copyTransferableMembers(@Nullable org.graalvm.polyglot.Value source, @Nullable org.graalvm.polyglot.Value target)
    Copy simple and host-backed Python instance members into another context.
    static org.graalvm.polyglot.Value
    The Python object standing in for an AOP proxy of a Python class.
    static boolean
    isValueInContext(@Nullable org.graalvm.polyglot.Value value, org.graalvm.polyglot.Context context)
    Determines whether a polyglot value belongs to the supplied context.
    static <E> @Nullable List<E>
    listView(org.graalvm.polyglot.Value member, Class<E> elementType)
    The Java view of a list attribute of a Python object, for the generated field of the property: the Python list stays the attribute and the source of truth, reads and writes through the returned list reach it.
    static <K,V> @Nullable Map<K,V>
    mapView(org.graalvm.polyglot.Value member, Class<K> keyType, Class<V> valueType)
    The Java view of a dict attribute of a Python object, for the generated field of the property, as listView(Value, Class) for a list.
    static @Nullable List<?>
    putListMember(org.graalvm.polyglot.Value target, String name, @Nullable List<?> value, Class<?> elementType)
    Writes the list held by the generated field of a property to the attribute of the Python object and returns the field value to hold from then on.
    static @Nullable Map<?,?>
    putMapMember(org.graalvm.polyglot.Value target, String name, @Nullable Map<?,?> value, Class<?> keyType, Class<?> valueType)
    Writes the map held by the generated field of a property to the attribute of the Python object and returns the field value to hold from then on, as putListMember(Value, String, List, Class) for a list.
    static void
    putMember(org.graalvm.polyglot.Value target, String name, @Nullable Object value)
    Assign a member on a Python value after coercing the value into the same context.
    static void
    putMemberByReference(org.graalvm.polyglot.Value target, String name, @Nullable Object value)
    Assign a member on a Python value, handing a Java collection or a generated wrapper to Python as the host object it is instead of a converted copy.
    static void
    putMembers(org.graalvm.polyglot.Value target, String[] names, @Nullable Object[] values)
    Assign several members on a Python value in a single guest call.
    static @Nullable Object
    pythonDateTime(@Nullable Object value)
    Tags the Java value of an element whose Python type is datetime, declared with Annotated[datetime, Instant] (see PythonDateTime), so that it reaches Python as an aware datetime.
    static void
    rememberPooledValue(PooledValueCoercible source, org.graalvm.polyglot.Context context, org.graalvm.polyglot.Value value)
    Registers a newly allocated Python object before generated code populates its properties.

    Methods inherited from class Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Method Details

    • coerceMap

      public static <K,V> @Nullable Map<Object,Object> coerceMap(@Nullable Map<K,V> map)
      Coerce a map whose keys or values may extend from ValueCoercible back to a native value map. Keys are coerced like values, so a map keyed by generated Python wrappers reaches Python with its keys as Python objects.
      Type Parameters:
      K - The key type of the map
      V - The value type of the map
      Parameters:
      map - The map
      Returns:
      The resulting map
    • coerceMap

      public static <K,V> @Nullable Map<Object,Object> coerceMap(@Nullable Map<K,V> map, @Nullable org.graalvm.polyglot.Context context)
      Coerce a map whose keys or values may extend from ValueCoercible back to a native value map for the given context: generated enum constants among the keys and values become the Python enum members of that context, as a bare enum argument does.
      Type Parameters:
      K - The key type of the map
      V - The value type of the map
      Parameters:
      map - The map
      context - The target context, or null when the map is converted later with its context
      Returns:
      The resulting map
    • coerceList

      public static <E> @Nullable List<Object> coerceList(@Nullable List<E> list)
      Coerce a list of types that may extend from ValueCoercible back to a native value list.
      Type Parameters:
      E - The element type of the list
      Parameters:
      list - The list
      Returns:
      The resulting list
    • coerceList

      public static <E> @Nullable List<Object> coerceList(@Nullable List<E> list, @Nullable org.graalvm.polyglot.Context context)
      Coerce a list of types that may extend from ValueCoercible back to a native value list for the given context: generated enum constants become the Python enum members of that context.
      Type Parameters:
      E - The element type of the list
      Parameters:
      list - The list
      context - The target context, or null when the list is converted later with its context
      Returns:
      The resulting list
    • coerceValue

      public static @Nullable Object coerceValue(@Nullable Object value)
      Coerce a generated Python-backed Java wrapper back to its native Python value.
      Parameters:
      value - The value
      Returns:
      The native Python value when available
    • coerceToContext

      public static @Nullable Object coerceToContext(@Nullable Object value, org.graalvm.polyglot.Context context)
      Coerce values passed into a target Python context.
      Parameters:
      value - The value to coerce
      context - The target context
      Returns:
      The coerced value
    • listView

      public static <E> @Nullable List<E> listView(org.graalvm.polyglot.Value member, Class<E> elementType)
      The Java view of a list attribute of a Python object, for the generated field of the property: the Python list stays the attribute and the source of truth, reads and writes through the returned list reach it. A Java list assigned to the attribute is returned as it is, and an iterable that is not a list is converted the way PythonConversion.convertList(Value, Class) does.
      Type Parameters:
      E - The element type
      Parameters:
      member - The attribute value
      elementType - The declared element type
      Returns:
      The list, or null for None
    • mapView

      public static <K,V> @Nullable Map<K,V> mapView(org.graalvm.polyglot.Value member, Class<K> keyType, Class<V> valueType)
      The Java view of a dict attribute of a Python object, for the generated field of the property, as listView(Value, Class) for a list.
      Type Parameters:
      K - The key type
      V - The value type
      Parameters:
      member - The attribute value
      keyType - The declared key type
      valueType - The declared value type
      Returns:
      The map, or null for None
    • putListMember

      public static @Nullable List<?> putListMember(org.graalvm.polyglot.Value target, String name, @Nullable List<?> value, Class<?> elementType)
      Writes the list held by the generated field of a property to the attribute of the Python object and returns the field value to hold from then on. A view of the attribute of this context is already current. Any other Java list is copied into a new Python list, so the attribute keeps its native type, and the view of that list becomes the field value: the collection assigned from Java is detached from that point. A collection class of its own (not a JDK one) is passed by reference, as an argument would be.
      Parameters:
      target - The Python object
      name - The attribute name
      value - The field value
      elementType - The declared element type
      Returns:
      The list to keep in the field
    • putMapMember

      public static @Nullable Map<?,?> putMapMember(org.graalvm.polyglot.Value target, String name, @Nullable Map<?,?> value, Class<?> keyType, Class<?> valueType)
      Writes the map held by the generated field of a property to the attribute of the Python object and returns the field value to hold from then on, as putListMember(Value, String, List, Class) for a list.
      Parameters:
      target - The Python object
      name - The attribute name
      value - The field value
      keyType - The declared key type
      valueType - The declared value type
      Returns:
      The map to keep in the field
    • coerceToContext

      public static @Nullable Object coerceToContext(@Nullable Object value, org.graalvm.polyglot.Context context, Class<?> declaredType)
      Coerce a value using the generated Java bridge's declared parameter type. A collection argument is only rebuilt with coerced elements when the Python method declares the plain collection contract; a parameter declared with a more specific type (a cache, a view) always stays the host object it is.
      Parameters:
      value - The value to coerce
      context - The target context
      declaredType - The declared Java bridge parameter type
      Returns:
      The coerced value
    • isValueInContext

      public static boolean isValueInContext(@Nullable org.graalvm.polyglot.Value value, org.graalvm.polyglot.Context context)
      Determines whether a polyglot value belongs to the supplied context.
      Parameters:
      value - The value to inspect
      context - The expected context
      Returns:
      Whether the value belongs to the context
    • coercePooledValue

      public static org.graalvm.polyglot.Value coercePooledValue(PooledValueCoercible value, org.graalvm.polyglot.Context context)
      Converts a generated wrapper while preserving wrapper identity for the current conversion.
      Parameters:
      value - The generated wrapper
      context - The target context
      Returns:
      The context-local Python value
    • rememberPooledValue

      public static void rememberPooledValue(PooledValueCoercible source, org.graalvm.polyglot.Context context, org.graalvm.polyglot.Value value)
      Registers a newly allocated Python object before generated code populates its properties.
      Parameters:
      source - The source wrapper
      context - The target context
      value - The newly allocated value
    • pythonDateTime

      public static @Nullable Object pythonDateTime(@Nullable Object value)
      Tags the Java value of an element whose Python type is datetime, declared with Annotated[datetime, Instant] (see PythonDateTime), so that it reaches Python as an aware datetime. An Instant, OffsetDateTime or ZonedDateTime without the tag stays the Java object: Python code that declares the Java type calls Java APIs with it.
      Parameters:
      value - The Java value
      Returns:
      The tagged value, or the value itself when it is not one of those types
    • coerceArgumentsToContext

      public static Object[] coerceArgumentsToContext(org.graalvm.polyglot.Context context, Object[] args)
      Coerce arguments passed into a target Python context.
      Parameters:
      context - The target context
      args - The arguments
      Returns:
      The coerced arguments
    • coerceDependenciesToContext

      public static Object[] coerceDependenciesToContext(org.graalvm.polyglot.Context context, Object[] args)
      Coerce the dependencies a pooled bean is constructed with into a context.

      As coerceArgumentsToContext(Context, Object[]) except for a dependency that is a Python bean of a single context: a singleton, or anything else that is not pooled. Such a bean cannot be reconstructed elsewhere -- there is one Python object and it belongs to its own context -- so the Java wrapper is passed instead, and calls through it return to the context that owns it. Rebuilding it is not merely unsupported, it is wrong: two contexts would hold two objects where the application asked for one.

      This is the same choice module injection makes for the same reason, and it is what the compile-time warning about a pooled type depending on a singleton Python bean is naming: the dependency works, and the work behind it runs in one context however many the pool has.

      Parameters:
      context - The target context
      args - The dependencies, already resolved by injection
      Returns:
      The arguments to construct with
    • interceptedTargetValue

      public static org.graalvm.polyglot.Value interceptedTargetValue(InterceptedProxy<?> proxy)
      The Python object standing in for an AOP proxy of a Python class.

      A generated proxy of a Python class (the scoped proxy of a @Refreshable factory bean, for example) is a subclass of the generated stub, or an implementation of the generated interface, that stands in for the bean its scope currently holds; it has no Python object of its own. Python code receiving the proxy gets a Python scoped proxy of the same class instead: every attribute read, write and method call is forwarded to the Python object of the bean the proxy resolves through its scope at that moment, so a refreshed or replaced bean is seen by Python callers the way Java callers see it. The Python proxy is created once per proxy instance and context. The target is not resolved here: a lazy proxy resolves it on the first use from Python, and a target that turns out to be a Java object (a Java implementation of a Python abstract base class) is forwarded to as the host object it is. The Python proxy carries the AOP proxy as its host object reference, so when Python hands it back to Java (a method returning the injected bean) Java receives the AOP proxy again, with its scope and interceptors, rather than the bean the scope holds at that moment.

      Parameters:
      proxy - The proxy, a generated stub instance or an implementation of a generated interface
      Returns:
      The Python scoped proxy of the intercepted target
      Since:
      5.2.0
    • putMember

      public static void putMember(org.graalvm.polyglot.Value target, String name, @Nullable Object value)
      Assign a member on a Python value after coercing the value into the same context.
      Parameters:
      target - The Python object to update
      name - The member name
      value - The member value
    • putMemberByReference

      public static void putMemberByReference(org.graalvm.polyglot.Value target, String name, @Nullable Object value)
      Assign a member on a Python value, handing a Java collection or a generated wrapper to Python as the host object it is instead of a converted copy.

      Used by the generated wrapper of an introspected class whose state is owned by its Java fields (the object was created from Java or loaded from storage): the Python attribute then is the Java collection, so an item added or removed in Python is added or removed from the Java field, and a nested object is the Java wrapper, so a write to its attribute reaches the Java field of that wrapper. A frozen dataclass, a polyglot value or a value of a standard type is coerced as by putMember(Value, String, Object).

      Parameters:
      target - The Python object to update
      name - The member name
      value - The member value
    • putMembers

      public static void putMembers(org.graalvm.polyglot.Value target, String[] names, @Nullable Object[] values)
      Assign several members on a Python value in a single guest call.

      Rebuilding a dataclass in a pooled context writes every field; doing that with one helper invocation instead of one per field removes most of the per-field interop cost.

      Parameters:
      target - The Python object to update
      names - The member names
      values - The member values, positionally matching names
    • asyncMemberValue

      public static @Nullable Object asyncMemberValue(org.graalvm.polyglot.Value target, @Nullable Object value)
      Convert an injected Java member into a Python-context-local value suitable for async code.
      Parameters:
      target - The target Python object receiving the member.
      value - The Java value to expose.
      Returns:
      A value that adapts Java async method results to Python awaitables.
    • copyTransferableMembers

      public static void copyTransferableMembers(@Nullable org.graalvm.polyglot.Value source, @Nullable org.graalvm.polyglot.Value target)
      Copy simple and host-backed Python instance members into another context.
      Parameters:
      source - The source Python object.
      target - The target Python object.