All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.oracle.graal.python.runtime.PythonOptions Maven / Gradle / Ivy

There is a newer version: 24.1.1
Show newest version
/*
 * Copyright (c) 2017, 2023, Oracle and/or its affiliates.
 * Copyright (c) 2013, Regents of the University of California
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are
 * permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this list of
 * conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice, this list of
 * conditions and the following disclaimer in the documentation and/or other materials provided
 * with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package com.oracle.graal.python.runtime;

import static com.oracle.graal.python.builtins.modules.SysModuleBuiltins.INT_MAX_STR_DIGITS_THRESHOLD;
import static com.oracle.graal.python.nodes.StringLiterals.T_DEFAULT;
import static com.oracle.graal.python.nodes.StringLiterals.T_EMPTY_STRING;
import static com.oracle.graal.python.nodes.StringLiterals.T_JAVA;
import static com.oracle.graal.python.nodes.StringLiterals.T_SPACE;
import static com.oracle.graal.python.util.PythonUtils.tsLiteral;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import org.graalvm.options.OptionCategory;
import org.graalvm.options.OptionDescriptor;
import org.graalvm.options.OptionDescriptors;
import org.graalvm.options.OptionKey;
import org.graalvm.options.OptionStability;
import org.graalvm.options.OptionType;
import org.graalvm.options.OptionValues;

import com.oracle.graal.python.PythonLanguage;
import com.oracle.graal.python.builtins.modules.SysModuleBuiltins;
import com.oracle.graal.python.builtins.objects.str.StringUtils;
import com.oracle.graal.python.util.PythonUtils;
import com.oracle.truffle.api.CompilerAsserts;
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.Option;
import com.oracle.truffle.api.TruffleLanguage.Env;
import com.oracle.truffle.api.dsl.Idempotent;
import com.oracle.truffle.api.nodes.ExplodeLoop;
import com.oracle.truffle.api.strings.TruffleString;

/**
 * The options for Python. Note that some options have an effect on the AST structure, and thus must
 * be the same for all contexts in an engine. We annotate these with {@link EngineOption} and the
 * PythonLanguage will ensure that these are matched across contexts.
 */
@Option.Group(PythonLanguage.ID)
public final class PythonOptions {
    private static final String J_STRING_LIST_SEPARATOR = "🏆";
    private static final TruffleString T_STRING_LIST_SEPARATOR = tsLiteral(J_STRING_LIST_SEPARATOR);

    /**
     * Whether Java classes are included that implement the SSL module. These come from packages
     * including (but not limited to): javax.net.ssl, org.bouncycastle, java.security, javax.crypto,
     * sun.security
     */
    public static final boolean WITHOUT_SSL = Boolean.getBoolean("python.WithoutSSL");

    /**
     * Whether cryptographic hashing functions are implemented via java.security.MessageDigest,
     * javax.crypto.Mac and related functions.
     */
    public static final boolean WITHOUT_DIGEST = Boolean.getBoolean("python.WithoutDigest");

    /**
     * Whether Java classes are included that relate to Unix-specific access, modify process
     * properties such as the default timezone, access the platform's Runtime MXBean, or spawn
     * subprocesses are available.
     */
    public static final boolean WITHOUT_PLATFORM_ACCESS = Boolean.getBoolean("python.WithoutPlatformAccess");

    /**
     * This property can be used to exclude zip, zlib, lzma, and bzip2 support from the Python core.
     */
    public static final boolean WITHOUT_COMPRESSION_LIBRARIES = Boolean.getBoolean("python.WithoutCompressionLibraries");

    /**
     * This property can be used to exclude native posix support from the build. Only Java emulation
     * will be available.
     */
    public static final boolean WITHOUT_NATIVE_POSIX = Boolean.getBoolean("python.WithoutNativePosix");

    /**
     * This property can be used to exclude socket and inet support from the Java posix backend.
     */
    public static final boolean WITHOUT_JAVA_INET = Boolean.getBoolean("python.WithoutJavaInet");

    /**
     * This property can be used to control if async actions are automatically scheduled using
     * daemon threads or via embedder calling a polling API on the main thread.
     */
    public static final boolean AUTOMATIC_ASYNC_ACTIONS = !"false".equalsIgnoreCase(System.getProperty("python.AutomaticAsyncActions"));

    public enum HPyBackendMode {
        NFI,
        JNI,
        LLVM
    }

    static final OptionType HPY_BACKEND_TYPE = new OptionType<>("HPyBackend", s -> {
        try {
            return HPyBackendMode.valueOf(s.toUpperCase());
        } catch (IllegalArgumentException e) {
            throw new IllegalArgumentException("Backend can be one of: " + Arrays.toString(HPyBackendMode.values()));
        }
    });

    private static final OptionType TS_OPTION_TYPE = new OptionType<>("graal.python.TruffleString", PythonUtils::toTruffleStringUncached);

    private PythonOptions() {
        // no instances
    }

    @Option(category = OptionCategory.EXPERT, help = "Set the home of Python. Equivalent of GRAAL_PYTHONHOME env variable. " +
                    "Determines default values for the CoreHome, StdLibHome, SysBasePrefix, SysPrefix.", usageSyntax = "", stability = OptionStability.STABLE) //
    public static final OptionKey PythonHome = new OptionKey<>("");

    @Option(category = OptionCategory.USER, help = "Set the location of sys.prefix. Overrides any environment variables or Java options.", usageSyntax = "", stability = OptionStability.STABLE) //
    public static final OptionKey SysPrefix = new OptionKey<>(T_EMPTY_STRING, TS_OPTION_TYPE);

    @Option(category = OptionCategory.EXPERT, help = "Set the location of sys.base_prefix. Overrides any environment variables or Java options.", usageSyntax = "", stability = OptionStability.STABLE) //
    public static final OptionKey SysBasePrefix = new OptionKey<>(T_EMPTY_STRING, TS_OPTION_TYPE);

    @Option(category = OptionCategory.USER, help = "Set the location of lib/graalpy" + PythonLanguage.GRAALVM_MAJOR + "." + //
                    PythonLanguage.GRAALVM_MINOR + ". Overrides any environment variables or Java options.", //
                    usageSyntax = "", stability = OptionStability.STABLE) //
    public static final OptionKey CoreHome = new OptionKey<>(T_EMPTY_STRING, TS_OPTION_TYPE);

    @Option(category = OptionCategory.USER, help = "Set the location of lib/python" + PythonLanguage.MAJOR + "." + PythonLanguage.MINOR +
                    ". Overrides any environment variables or Java options.", usageSyntax = "", stability = OptionStability.STABLE) //
    public static final OptionKey StdLibHome = new OptionKey<>(T_EMPTY_STRING, TS_OPTION_TYPE);

    @Option(category = OptionCategory.USER, help = "Equivalent to the Python -i flag. Inspect interactively after running a script.", usageSyntax = "true|false", stability = OptionStability.STABLE) //
    public static final OptionKey InspectFlag = new OptionKey<>(false);

    @Option(category = OptionCategory.USER, help = "Equivalent to the Python -q flag. Don't  print version and copyright messages on interactive startup.", usageSyntax = "true|false", stability = OptionStability.STABLE) //
    public static final OptionKey QuietFlag = new OptionKey<>(false);

    @Option(category = OptionCategory.USER, help = "Equivalent to the Python -S flag. Don't imply 'import site' on initialization.", usageSyntax = "true|false", stability = OptionStability.STABLE) //
    public static final OptionKey NoSiteFlag = new OptionKey<>(false);

    @Option(category = OptionCategory.USER, help = "Equivalent to the Python -s flag. Don't add user site directory to sys.path.", usageSyntax = "true|false", stability = OptionStability.STABLE) //
    public static final OptionKey NoUserSiteFlag = new OptionKey<>(false);

    @Option(category = OptionCategory.USER, help = "Equivalent to the Python -E flag. Ignore PYTHON* environment variables.", usageSyntax = "true|false", stability = OptionStability.STABLE) //
    public static final OptionKey IgnoreEnvironmentFlag = new OptionKey<>(false);

    @Option(category = OptionCategory.USER, help = "Equivalent to setting the PYTHONPATH environment variable for the standard launcher. ':'-separated list of directories prefixed to the default module search path.", usageSyntax = "[:]", stability = OptionStability.STABLE) //
    public static final OptionKey PythonPath = new OptionKey<>(T_EMPTY_STRING, TS_OPTION_TYPE);

    @EngineOption @Option(category = OptionCategory.USER, help = "Equivalent to setting the PYTHONIOENCODING environment variable for the standard launcher.", usageSyntax = "[:]", stability = OptionStability.STABLE) //
    public static final OptionKey StandardStreamEncoding = new OptionKey<>(T_EMPTY_STRING, TS_OPTION_TYPE);

    @Option(category = OptionCategory.USER, help = "Remove assert statements and any code conditional on the value of __debug__.", usageSyntax = "true|false", stability = OptionStability.STABLE) //
    public static final OptionKey PythonOptimizeFlag = new OptionKey<>(false);

    @Option(category = OptionCategory.USER, help = "Equivalent to the Python -v flag. Turn on verbose mode.", usageSyntax = "true|false", stability = OptionStability.STABLE) //
    public static final OptionKey VerboseFlag = new OptionKey<>(false);

    @Option(category = OptionCategory.USER, help = "Equivalent to the Python -u flag. Force stdout and stderr to be unbuffered.", usageSyntax = "true|false", stability = OptionStability.STABLE) //
    public static final OptionKey UnbufferedIO = new OptionKey<>(false);

    @Option(category = OptionCategory.USER, help = "Equivalent to the Python -I flag. Isolate from the users environment by not adding the cwd to the path", usageSyntax = "true|false", stability = OptionStability.STABLE) //
    public static final OptionKey IsolateFlag = new OptionKey<>(false);

    @Option(category = OptionCategory.USER, help = "Equivalent to the Python -X warn_default_encoding flag. Enable opt-in EncodingWarning for 'encoding=None'", usageSyntax = "true|false", stability = OptionStability.STABLE) //
    public static final OptionKey WarnDefaultEncodingFlag = new OptionKey<>(false);

    @Option(category = OptionCategory.USER, help = "Equivalent to the Python -X int_max_str_digits option.", stability = OptionStability.STABLE) //
    public static final OptionKey IntMaxStrDigits = new OptionKey<>(SysModuleBuiltins.INT_DEFAULT_MAX_STR_DIGITS,
                    new OptionType<>("IntMaxStrDigits", (input) -> {
                        try {
                            int value = Integer.parseInt(input);
                            if (value == 0 || value >= INT_MAX_STR_DIGITS_THRESHOLD) {
                                return value;
                            }
                        } catch (NumberFormatException e) {
                            // fallthrough
                        }
                        throw new IllegalArgumentException(String.format("IntMaxStrDigits: invalid limit; must be >= %d or 0 for unlimited.", INT_MAX_STR_DIGITS_THRESHOLD));
                    }));

    @Option(category = OptionCategory.USER, help = "Equivalent to the Python -B flag. Don't write bytecode files.", usageSyntax = "true|false", stability = OptionStability.STABLE) //
    public static final OptionKey DontWriteBytecodeFlag = new OptionKey<>(true);

    @Option(category = OptionCategory.USER, help = "If this is set, GraalPython will write .pyc files in a mirror directory tree at this path, " +
                    "instead of in __pycache__ directories within the source tree. " +
                    "Equivalent to setting the PYTHONPYCACHEPREFIX environment variable for the standard launcher.", usageSyntax = "", stability = OptionStability.STABLE) //
    public static final OptionKey PyCachePrefix = new OptionKey<>(T_EMPTY_STRING, TS_OPTION_TYPE);

    @Option(category = OptionCategory.USER, help = "Equivalent to setting the PYTHONWARNINGS environment variable for the standard launcher.", //
                    usageSyntax = "[:[:[:[:]]]][,[:[:[:[:]]]]]", stability = OptionStability.STABLE) //
    public static final OptionKey WarnOptions = new OptionKey<>(T_EMPTY_STRING, TS_OPTION_TYPE);

    @Option(category = OptionCategory.USER, help = "Equivalent to setting PYTHONHASHSEED environment variable", usageSyntax = "random|[0,4294967295]", stability = OptionStability.STABLE) //
    public static final OptionKey> HashSeed = new OptionKey<>(Optional.empty(),
                    new OptionType<>("HashSeed", input -> {
                        if ("random".equals(input)) {
                            return Optional.empty();
                        }
                        try {
                            return Optional.of(Integer.parseUnsignedInt(input));
                        } catch (NumberFormatException e) {
                            throw new IllegalArgumentException("PYTHONHASHSEED must be \"random\" or an integer in range [0; 4294967295]");
                        }
                    }));

    @EngineOption @Option(category = OptionCategory.USER, help = "Choose the backend for the POSIX module.", usageSyntax = "java|native|llvm", stability = OptionStability.STABLE) //
    public static final OptionKey PosixModuleBackend = new OptionKey<>(T_JAVA, TS_OPTION_TYPE);

    @Option(category = OptionCategory.USER, help = "Value of the --check-hash-based-pycs command line option" +
                    "- 'default' means the 'check_source' flag in hash-based pycs" +
                    "  determines invalidation" +
                    "- 'always' causes the interpreter to hash the source file for" +
                    "  invalidation regardless of value of 'check_source' bit" +
                    "- 'never' causes the interpreter to always assume hash-based pycs are" +
                    "  valid" +
                    "The default value is 'default'." +
                    "See PEP 552 'Deterministic pycs' for more details.", usageSyntax = "default|always|never", stability = OptionStability.STABLE) //
    public static final OptionKey CheckHashPycsMode = new OptionKey<>(T_DEFAULT, TS_OPTION_TYPE);

    @Option(category = OptionCategory.INTERNAL, help = "Set the location of C API home. Overrides any environment variables or Java options.", usageSyntax = "", stability = OptionStability.STABLE) //
    public static final OptionKey CAPI = new OptionKey<>(T_EMPTY_STRING, TS_OPTION_TYPE);

    @EngineOption @Option(category = OptionCategory.INTERNAL, help = "Expose internal sources as normal sources, so they will show up in the debugger and stacks", usageSyntax = "true|false") //
    public static final OptionKey ExposeInternalSources = new OptionKey<>(false);

    @EngineOption @Option(category = OptionCategory.INTERNAL, help = "Eagerly initialize source sections.", usageSyntax = "true|false") //
    public static final OptionKey ForceInitializeSourceSections = new OptionKey<>(false);

    @EngineOption @Option(category = OptionCategory.INTERNAL, help = "Print the java stacktrace. Possible modes:" +
                    "    1   Print Java stacktrace for Java exceptions only." +
                    "    2   Print Java stacktrace for Python exceptions only (ATTENTION: this will have a notable performance impact)." +
                    "    3   Combines 1 and 2.", usageSyntax = "1|2|3") //
    public static final OptionKey WithJavaStacktrace = new OptionKey<>(0);

    @Option(category = OptionCategory.INTERNAL, usageSyntax = "true|false", help = "") //
    public static final OptionKey CatchGraalPythonExceptionForUnitTesting = new OptionKey<>(false);

    @EngineOption @Option(category = OptionCategory.INTERNAL, usageSyntax = "true|false", help = "Enable catching all Exceptions in generic try-catch statements.") //
    public static final OptionKey CatchAllExceptions = new OptionKey<>(false);

    @EngineOption @Option(category = OptionCategory.INTERNAL, help = "Choose the backend for HPy binary mode.", usageSyntax = "jni|nfi|llvm", stability = OptionStability.EXPERIMENTAL) //
    public static final OptionKey HPyBackend = new OptionKey<>(HPyBackendMode.JNI, HPY_BACKEND_TYPE);

    @EngineOption @Option(category = OptionCategory.INTERNAL, usageSyntax = "true|false", help = "If {@code true}, code is enabled that tries to reduce expensive upcalls into the runtime" +
                    "when HPy API functions are used. This is achieved by mirroring data in native memory.", stability = OptionStability.EXPERIMENTAL) //
    public static final OptionKey HPyEnableJNIFastPaths = new OptionKey<>(true);

    @EngineOption @Option(category = OptionCategory.INTERNAL, usageSyntax = "




© 2015 - 2024 Weber Informatics LLC | Privacy Policy