// Path: src/main/java/org/jpy/PyLibConfig.java
// public static final String JPY_LIB_KEY = "jpy.jpyLib";
// 
// Path: src/main/java/org/jpy/PyLibConfig.java
// public enum OS {
//     WINDOWS,
//     UNIX,
//     MAC_OS,
//     SUNOS,
// }
// 
// Path: src/main/java/org/jpy/PyLibConfig.java
// public static final String PYTHON_LIB_KEY = "jpy.pythonLib";
// 
// Path: src/main/java/org/jpy/PyLibConfig.java
// public static OS getOS() {
//     String os = System.getProperty("os.name").toLowerCase();
//     if (os.contains("win")) {
//         return OS.WINDOWS;
//     } else if (os.contains("nix") || os.contains("nux") || os.contains("aix")) {
//         return OS.UNIX;
//     } else if (os.contains("mac")) {
//         return OS.MAC_OS;
//     } else if (os.contains("sunos")) {
//         return OS.SUNOS;
//     }
//     return null;
// }
// 
// Path: src/main/java/org/jpy/PyLibConfig.java
// public static String getProperty(String key, boolean mustHave) {
//     // System properties overwrite .jpy properties
//     String property = System.getProperty(key);
//     if (property != null) {
//         return property;
//     }
//     property = properties.getProperty(key);
//     if (property == null && mustHave) {
//         throw new RuntimeException("missing configuration property '" + key + "'");
//     }
//     return property;
// }


import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Map;
import static org.jpy.PyLibConfig.JPY_LIB_KEY;
import static org.jpy.PyLibConfig.OS;
import static org.jpy.PyLibConfig.PYTHON_LIB_KEY;
import static org.jpy.PyLibConfig.getOS;
import static org.jpy.PyLibConfig.getProperty;
/*
 * Copyright 2015 Brockmann Consult GmbH
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * This file was modified by Illumon.
 *
 */

package org.jpy;



/**
 * Represents the library that provides the Python interpreter (CPython).
 * <p>
 * When the {@code PyLib} class is loaded, it reads its configuration from a Java properties file called {@code .jpy}
 * which must exist in the current user's home directory. The configuration file has been written to this location
 * by installing the Python jpy module using {@code python3 setup.py install --user} on Unix
 * and {@code python setup.py install}) on Windows.
 * <p>
 * Currently, the following properties are recognised in the {@code .jpy} file:
 * <ul>
 * <li>{@code python.lib} - the Python shared library (usually required on Unix only)</li>
 * <li>{@code jpy.lib} - the jpy shared library path for Python (Unix: {@code jpy*.so}, Windows: {@code jpy*.pyd})</li>
 * </ul>
 * <p>
 * jpy API clients should first call {@link #isPythonRunning()} in order to check if a Python interpreter is already available.
 * If not, {@link #startPython(String...)} must be called before any other jpy API is used.
 * <p>
 * <i>Important note for developers: If you change the signature of any of the native {@code PyLib} methods,
 * you must first run {@code javah} on the compiled class, and then adapt {@code src/main/c/jni/org_jpy_PyLib.c}.</i>
 *
 * @author Norman Fomferra
 * @since 0.7
 */
@SuppressWarnings("WeakerAccess")
public class PyLib {

    private static final boolean DEBUG = Boolean.getBoolean("jpy.debug");
    private static final boolean ON_WINDOWS = System.getProperty("os.name").toLowerCase().contains("windows");
    private static final boolean STOP_IS_NO_OP = Boolean.getBoolean("jpy.stopIsNoOp") || ON_WINDOWS;
    private static String dllFilePath;
    private static Throwable dllProblem;
    private static boolean dllLoaded;

    /**
     * The kind of callable Python objects.
     */
    public enum CallableKind {
        /**
         * Function call without the Python {@code self} as first argument.
         */
        FUNCTION,
        /**
         * An instance method call with the Python {@code self} (= the instance) as first argument.
         */
        METHOD,
    }

    /**
     * Controls output of diagnostic information for debugging.
     */
    @SuppressWarnings("UnusedDeclaration")
    public static class Diag {

        static {
            PyLib.loadLib();
        }

        /**
         * Print no diagnostic information at all.
         */
        public static final int F_OFF = 0x00;
        /**
         * Print diagnostic information while Java types are resolved.
         */
        public static final int F_TYPE = 0x01;
        /**
         * Print diagnostic information while Java methods overloads are selected.
         */
        public static final int F_METH = 0x02;
        /**
         * Print diagnostic information when code execution flow is passed from Java to Python or the other way round.
         */
// Path: src/main/java/org/jpy/PyLibConfig.java
// public static final String JPY_LIB_KEY = "jpy.jpyLib";
// 
// Path: src/main/java/org/jpy/PyLibConfig.java
// public enum OS {
//     WINDOWS,
//     UNIX,
//     MAC_OS,
//     SUNOS,
// }
// 
// Path: src/main/java/org/jpy/PyLibConfig.java
// public static final String PYTHON_LIB_KEY = "jpy.pythonLib";
// 
// Path: src/main/java/org/jpy/PyLibConfig.java
// public static OS getOS() {
//     String os = System.getProperty("os.name").toLowerCase();
//     if (os.contains("win")) {
//         return OS.WINDOWS;
//     } else if (os.contains("nix") || os.contains("nux") || os.contains("aix")) {
//         return OS.UNIX;
//     } else if (os.contains("mac")) {
//         return OS.MAC_OS;
//     } else if (os.contains("sunos")) {
//         return OS.SUNOS;
//     }
//     return null;
// }
// 
// Path: src/main/java/org/jpy/PyLibConfig.java
// public static String getProperty(String key, boolean mustHave) {
//     // System properties overwrite .jpy properties
//     String property = System.getProperty(key);
//     if (property != null) {
//         return property;
//     }
//     property = properties.getProperty(key);
//     if (property == null && mustHave) {
//         throw new RuntimeException("missing configuration property '" + key + "'");
//     }
//     return property;
// }


// Path: src/main/java/org/jpy/PyLib.java
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Map;
import static org.jpy.PyLibConfig.JPY_LIB_KEY;
import static org.jpy.PyLibConfig.OS;
import static org.jpy.PyLibConfig.PYTHON_LIB_KEY;
import static org.jpy.PyLibConfig.getOS;
import static org.jpy.PyLibConfig.getProperty;

/*
 * Copyright 2015 Brockmann Consult GmbH
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * This file was modified by Illumon.
 *
 */

package org.jpy;



/**
 * Represents the library that provides the Python interpreter (CPython).
 * <p>
 * When the {@code PyLib} class is loaded, it reads its configuration from a Java properties file called {@code .jpy}
 * which must exist in the current user's home directory. The configuration file has been written to this location
 * by installing the Python jpy module using {@code python3 setup.py install --user} on Unix
 * and {@code python setup.py install}) on Windows.
 * <p>
 * Currently, the following properties are recognised in the {@code .jpy} file:
 * <ul>
 * <li>{@code python.lib} - the Python shared library (usually required on Unix only)</li>
 * <li>{@code jpy.lib} - the jpy shared library path for Python (Unix: {@code jpy*.so}, Windows: {@code jpy*.pyd})</li>
 * </ul>
 * <p>
 * jpy API clients should first call {@link #isPythonRunning()} in order to check if a Python interpreter is already available.
 * If not, {@link #startPython(String...)} must be called before any other jpy API is used.
 * <p>
 * <i>Important note for developers: If you change the signature of any of the native {@code PyLib} methods,
 * you must first run {@code javah} on the compiled class, and then adapt {@code src/main/c/jni/org_jpy_PyLib.c}.</i>
 *
 * @author Norman Fomferra
 * @since 0.7
 */
@SuppressWarnings("WeakerAccess")
public class PyLib {

    private static final boolean DEBUG = Boolean.getBoolean("jpy.debug");
    private static final boolean ON_WINDOWS = System.getProperty("os.name").toLowerCase().contains("windows");
    private static final boolean STOP_IS_NO_OP = Boolean.getBoolean("jpy.stopIsNoOp") || ON_WINDOWS;
    private static String dllFilePath;
    private static Throwable dllProblem;
    private static boolean dllLoaded;

    /**
     * The kind of callable Python objects.
     */
    public enum CallableKind {
        /**
         * Function call without the Python {@code self} as first argument.
         */
        FUNCTION,
        /**
         * An instance method call with the Python {@code self} (= the instance) as first argument.
         */
        METHOD,
    }

    /**
     * Controls output of diagnostic information for debugging.
     */
    @SuppressWarnings("UnusedDeclaration")
    public static class Diag {

        static {
            PyLib.loadLib();
        }

        /**
         * Print no diagnostic information at all.
         */
        public static final int F_OFF = 0x00;
        /**
         * Print diagnostic information while Java types are resolved.
         */
        public static final int F_TYPE = 0x01;
        /**
         * Print diagnostic information while Java methods overloads are selected.
         */
        public static final int F_METH = 0x02;
        /**
         * Print diagnostic information when code execution flow is passed from Java to Python or the other way round.
         */
        public static final int F_EXEC = 0x04;