package org.python.pydev.debug.profile; import java.io.File; import java.io.FileInputStream; import java.util.List; import java.util.Properties; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.preference.PreferenceStore; import org.python.pydev.core.log.Log; import org.python.pydev.plugin.preferences.PydevPrefs; import org.python.pydev.shared_core.io.FileUtils; import org.python.pydev.shared_core.process.ProcessUtils; import org.python.pydev.shared_core.utils.PlatformUtils; import org.python.pydev.shared_ui.utils.RunInUiThread; import org.python.pydev.ui.dialogs.PyDialogHelpers; public class PyProfilePreferences { public static final String ENABLE_PROFILING_FOR_NEW_LAUNCHES = "ENABLE_PROFILING_FOR_NEW_LAUNCHES"; public static final String PYVMMONITOR_UI_LOCATION = "PYVMMONITOR_UI_LOCATION"; public static final String PROFILE_MODE = "PROFILE_MODE"; public static final int PROFILE_MODE_YAPPI = 0; public static final int PROFILE_MODE_LSPROF = 1; public static final int PROFILE_MODE_NONE = 2; // Volatile stuff (not persisted across restarts). public static boolean getAllRunsDoProfile() { return tempPreferenceStore.getBoolean(ENABLE_PROFILING_FOR_NEW_LAUNCHES); } private static PreferenceStore tempPreferenceStore = new PreferenceStore(); static { tempPreferenceStore.setDefault(ENABLE_PROFILING_FOR_NEW_LAUNCHES, false); } public static IPreferenceStore getTemporaryPreferenceStore() { return tempPreferenceStore; } // Non-volatile stuff public static String getPyVmMonitorUILocation() { String location = getPermanentPreferenceStore().getString(PYVMMONITOR_UI_LOCATION); if (!new File(location).exists() || !new File(location).isFile()) { if (PlatformUtils.isMacOsPlatform()) { File f = new File(location, "Contents"); f = new File(f, "MacOS"); f = new File(f, "pyvmmonitor-ui"); if (f.exists()) { return FileUtils.getFileAbsolutePath(f); } } //If it still didn't find it, let's see if we have a default location to use... location = getDefaultLocation(); } return location; } private static boolean firstCall = true; private static final Object lock = new Object(); public static IPreferenceStore getPermanentPreferenceStore() { IPreferenceStore preferenceStore = PydevPrefs.getPreferenceStore(); if (firstCall) { synchronized (lock) { if (firstCall) { firstCall = false; String defaultLocation = getDefaultLocation(); if (defaultLocation != null) { preferenceStore.setDefault(PYVMMONITOR_UI_LOCATION, defaultLocation); } preferenceStore.setDefault(PROFILE_MODE, PROFILE_MODE_LSPROF); } } } return preferenceStore; } public static String getDefaultLocation() { File settings = null; try { if (PlatformUtils.isMacOsPlatform()) { settings = new File(System.getProperty("user.home"), "Library"); settings = new File(settings, "Application Support"); settings = new File(settings, "Brainwy"); settings = new File(settings, "PyVmMonitor.ini"); } else if (PlatformUtils.isLinuxPlatform()) { settings = new File(System.getProperty("user.home"), ".config/Brainwy/pyvmmonitor.ini"); } else if (PlatformUtils.isWindowsPlatform()) { //It may not be available in all versions of windows, but if it is, let's use it... String env = System.getenv("LOCALAPPDATA"); if (env != null && env.length() > 0 && new File(env).exists()) { settings = new File(new File(env, "Brainwy"), "PyVmMonitor.ini"); } } } catch (Exception e) { Log.log(e); } String defaultLocation = null; try { if (settings != null && settings.exists()) { Properties props = new Properties(); props.load(new FileInputStream(settings)); String property = props.getProperty("pyvmmonitor_ui_executable"); if (property != null) { defaultLocation = property; } } } catch (Exception e) { Log.log(e); } return defaultLocation; } public static int getProfileMode() { return getPermanentPreferenceStore().getInt(PROFILE_MODE); } public static void addProfileArgs(List<String> cmdArgs, boolean profileRun, boolean actualRun) { if (profileRun) { // profile can use yappi or lsprof final String pyVmMonitorUILocation = PyProfilePreferences.getPyVmMonitorUILocation(); if (pyVmMonitorUILocation == null || pyVmMonitorUILocation.length() == 0) { if (actualRun) { RunInUiThread.async(new Runnable() { @Override public void run() { PyDialogHelpers .openWarning( "Unable to run in profile mode.", "Unable to run in profile mode: pyvmmonitor-ui location not specified."); } }); } return; } if (!new File(pyVmMonitorUILocation).exists()) { if (actualRun) { RunInUiThread.async(new Runnable() { @Override public void run() { PyDialogHelpers .openWarning( "Unable to run in profile mode.", "Unable to run in profile mode: Invalid location for pyvmmonitor-ui: " + pyVmMonitorUILocation); } }); } return; } // Ok, we have the pyvmmonitor-ui executable location, let's discover the pyvmmonitor.__init__ location // for doing the launch. File file = new File(pyVmMonitorUILocation); File publicApi = new File(file.getParentFile(), "public_api"); File pyvmmonitorFolder = new File(publicApi, "pyvmmonitor"); final File pyvmmonitorInit = new File(pyvmmonitorFolder, "__init__.py"); if (!pyvmmonitorInit.exists()) { if (actualRun) { RunInUiThread.async(new Runnable() { @Override public void run() { PyDialogHelpers .openWarning( "Unable to run in profile mode.", "Unable to run in profile mode: Invalid location for pyvmmonitor/__init__.py: " + FileUtils.getFileAbsolutePath(pyvmmonitorInit)); } }); } return; } // Now, for the profile to work we have to change the initial script to be pyvmmonitor.__init__. cmdArgs.add(FileUtils.getFileAbsolutePath(pyvmmonitorInit)); int profileMode = PyProfilePreferences.getProfileMode(); if (profileMode == PyProfilePreferences.PROFILE_MODE_YAPPI) { cmdArgs.add("--profile=yappi"); } else if (profileMode == PyProfilePreferences.PROFILE_MODE_LSPROF) { cmdArgs.add("--profile=lsprof"); } else { //Don't pass profile mode } // We'll spawn the UI ourselves (so, ask the backend to skip that step). // We have to do that because otherwise the process we launch will 'appear' to be live unless we // also close the profiler. cmdArgs.add("--spawn-ui=false"); if (actualRun) { ProcessUtils.run(new String[] { pyVmMonitorUILocation, "--default-port-single-instance" }, null, new File(pyVmMonitorUILocation).getParentFile(), null); } } } }