<commit_before>﻿/* ****************************************************************************
 *
 * Copyright (c) Microsoft Corporation. 
 *
 * This source code is subject to terms and conditions of the Apache License, Version 2.0. A 
 * copy of the license can be found in the License.html file at the root of this distribution. If 
 * you cannot locate the Apache License, Version 2.0, please send an email to 
 * <EMAIL>. By using this source code in any fashion, you are agreeing to be bound 
 * by the terms of the Apache License, Version 2.0.
 *
 * You must not remove this notice, or any other, from this software.
 *
 * ***************************************************************************/

using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net.NetworkInformation;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using System.Windows.Forms;
using Microsoft.PythonTools.Debugger.DebugEngine;
using Microsoft.PythonTools.Intellisense;
using Microsoft.PythonTools.Interpreter;
using Microsoft.VisualStudio;
using Microsoft.VisualStudio.Debugger;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
using Microsoft.VisualStudioTools;
using Microsoft.VisualStudioTools.Project;

namespace Microsoft.PythonTools.Project.Web {
    /// <summary>
    /// Web launcher.  This wraps the default launcher and provides it with a
    /// different IPythonProject which launches manage.py with the appropriate
    /// options.  Upon a successful launch we will then automatically load the
    /// appropriate page into the users web browswer.
    /// </summary>
    [Export(typeof(IProjectLauncher))]
    class PythonWebLauncher : IProjectLauncher {
        private int? _testServerPort;

        private readonly IPythonProject _project;
        private readonly IAsyncCommand _runServerCommand;
        private readonly IAsyncCommand _debugServerCommand;

        public PythonWebLauncher(IPythonProject project) {
            _project = project;

            var project2 = project as IPythonProject2;
            if (project2 != null) {
                // The provider may return its own object, but the web launcher only
                // supports instances of CustomCommand.
                _runServerCommand = project2.FindCommand("PythonRunWebServerCommand");
                _debugServerCommand = project2.FindCommand("PythonDebugWebServerCommand");
            }

            var portNumber = _project.GetProperty(PythonConstants.WebBrowserPortSetting);
            int portNum;
            if (Int32.TryParse(portNumber, out portNum)) {
                _testServerPort = portNum;
            }
        }

        #region IPythonLauncher Members

        public int LaunchProject(bool debug) {
            return LaunchFile(_project.GetStartupFile(), debug);
        }

        public int LaunchFile(string file, bool debug) {
            bool isWindows;
            if (!Boolean.TryParse(_project.GetProperty(CommonConstants.IsWindowsApplication) ?? Boolean.FalseString, out isWindows)) {
                isWindows = false;
            }

            var cmd = debug ? _debugServerCommand : _runServerCommand;
            var customCmd = cmd as CustomCommand;
            if (customCmd == null && cmd != null) {
                // We have a command we don't understand, so we'll execute it
                // but won't start debugging. The (presumably) flavored project
                // that provided the command is responsible for handling the
                // attach.
                cmd.Execute(null);
                return VSConstants.S_OK;
            }

            CommandStartInfo startInfo;
            var project2 = _project as IPythonProject2;
            if (customCmd != null && project2 != null) {
                // We have one of our own commands, so let's use the actual
                // start info.
                startInfo = customCmd.GetStartInfo(project2);
            } else {
                // No command, so set up a startInfo that looks like the default
                // launcher.
                startInfo = new CommandStartInfo {
                    Filename = file,
                    Arguments = _project.GetProperty(CommonConstants.CommandLineArguments) ?? string.Empty,
                    WorkingDirectory = _project.GetWorkingDirectory(),
                    EnvironmentVariables = null,
                    TargetType = "script",
                    ExecuteIn = "console"
                };
            }

            if (isWindows) {
                // Must run hidden if running with pythonw
                startInfo.ExecuteIn = "hidden";
            }

            var env = startInfo.EnvironmentVariables;
            if (env == null) {
                env = startInfo.EnvironmentVariables = new Dictionary<string, string>();
            }

            string value;
            if (!env.TryGetValue("SERVER_HOST", out value) || string.IsNullOrEmpty(value)) {
                env["SERVER_HOST"] = "localhost";
            }
            int dummyInt;
            if (!env.TryGetValue("SERVER_PORT", out value) ||
                string.IsNullOrEmpty(value) ||
                !int.TryParse(value, out dummyInt)) {
                env["SERVER_PORT"] = TestServerPortString;
            }

            if (debug) {
                PythonToolsPackage.Instance.Logger.LogEvent(Logging.PythonLogEvent.Launch, 1);

                using (var dsi = CreateDebugTargetInfo(startInfo, GetInterpreterPath(_project, isWindows))) {
                    dsi.Launch(PythonToolsPackage.Instance);
                }
            } else {
                PythonToolsPackage.Instance.Logger.LogEvent(Logging.PythonLogEvent.Launch, 0);

                var psi = CreateProcessStartInfo(startInfo, GetInterpreterPath(_project, isWindows));

                var process = Process.Start(psi);
                if (process != null) {
                    StartBrowser(GetFullUrl(), () => process.HasExited);
                }
            }

            return VSConstants.S_OK;<commit_msg>#2103 Start with/without debugging doesn't work in web projects Fixes PythonWebLauncher's implementation of LaunchProject vs. LaunchFile.<commit_after>﻿/* ****************************************************************************
 *
 * Copyright (c) Microsoft Corporation. 
 *
 * This source code is subject to terms and conditions of the Apache License, Version 2.0. A 
 * copy of the license can be found in the License.html file at the root of this distribution. If 
 * you cannot locate the Apache License, Version 2.0, please send an email to 
 * <EMAIL>. By using this source code in any fashion, you are agreeing to be bound 
 * by the terms of the Apache License, Version 2.0.
 *
 * You must not remove this notice, or any other, from this software.
 *
 * ***************************************************************************/

using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net.NetworkInformation;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using System.Windows.Forms;
using Microsoft.PythonTools.Debugger.DebugEngine;
using Microsoft.PythonTools.Intellisense;
using Microsoft.PythonTools.Interpreter;
using Microsoft.VisualStudio;
using Microsoft.VisualStudio.Debugger;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
using Microsoft.VisualStudioTools;
using Microsoft.VisualStudioTools.Project;

namespace Microsoft.PythonTools.Project.Web {
    /// <summary>
    /// Web launcher.  This wraps the default launcher and provides it with a
    /// different IPythonProject which launches manage.py with the appropriate
    /// options.  Upon a successful launch we will then automatically load the
    /// appropriate page into the users web browswer.
    /// </summary>
    [Export(typeof(IProjectLauncher))]
    class PythonWebLauncher : IProjectLauncher {
        private int? _testServerPort;

        private readonly IPythonProject _project;
        private readonly IAsyncCommand _runServerCommand;
        private readonly IAsyncCommand _debugServerCommand;

        public PythonWebLauncher(IPythonProject project) {
            _project = project;

            var project2 = project as IPythonProject2;
            if (project2 != null) {
                // The provider may return its own object, but the web launcher only
                // supports instances of CustomCommand.
                _runServerCommand = project2.FindCommand("PythonRunWebServerCommand");
                _debugServerCommand = project2.FindCommand("PythonDebugWebServerCommand");
            }

            var portNumber = _project.GetProperty(PythonConstants.WebBrowserPortSetting);
            int portNum;
            if (Int32.TryParse(portNumber, out portNum)) {
                _testServerPort = portNum;
            }
        }

        #region IPythonLauncher Members

        public int LaunchProject(bool debug) {
            bool isWindows;
            if (!Boolean.TryParse(_project.GetProperty(CommonConstants.IsWindowsApplication) ?? Boolean.FalseString, out isWindows)) {
                isWindows = false;
            }

            var cmd = debug ? _debugServerCommand : _runServerCommand;
            var customCmd = cmd as CustomCommand;
            if (customCmd == null && cmd != null) {
                // We have a command we don't understand, so we'll execute it
                // but won't start debugging. The (presumably) flavored project
                // that provided the command is responsible for handling the
                // attach.
                cmd.Execute(null);
                return VSConstants.S_OK;
            }

            CommandStartInfo startInfo;
            var project2 = _project as IPythonProject2;
            if (customCmd != null && project2 != null) {
                // We have one of our own commands, so let's use the actual
                // start info.
                startInfo = customCmd.GetStartInfo(project2);
            } else {
                // No command, so set up a startInfo that looks like the default
                // launcher.
                startInfo = new CommandStartInfo {
                    Filename = _project.GetStartupFile(),
                    Arguments = _project.GetProperty(CommonConstants.CommandLineArguments) ?? string.Empty,
                    WorkingDirectory = _project.GetWorkingDirectory(),
                    EnvironmentVariables = null,
                    TargetType = "script",
                    ExecuteIn = "console"
                };
            }

            if (isWindows) {
                // Must run hidden if running with pythonw
                startInfo.ExecuteIn = "hidden";
            }

            var env = startInfo.EnvironmentVariables;
            if (env == null) {
                env = startInfo.EnvironmentVariables = new Dictionary<string, string>();
            }

            string value;
            if (!env.TryGetValue("SERVER_HOST", out value) || string.IsNullOrEmpty(value)) {
                env["SERVER_HOST"] = "localhost";
            }
            int dummyInt;
            if (!env.TryGetValue("SERVER_PORT", out value) ||
                string.IsNullOrEmpty(value) ||
                !int.TryParse(value, out dummyInt)) {
                env["SERVER_PORT"] = TestServerPortString;
            }

            if (debug) {
                PythonToolsPackage.Instance.Logger.LogEvent(Logging.PythonLogEvent.Launch, 1);

                using (var dsi = CreateDebugTargetInfo(startInfo, GetInterpreterPath(_project, isWindows))) {
                    dsi.Launch(PythonToolsPackage.Instance);
                }
            } else {
                PythonToolsPackage.Instance.Logger.LogEvent(Logging.PythonLogEvent.Launch, 0);

                var psi = CreateProcessStartInfo(startInfo, GetInterpreterPath(_project, isWindows));

                var process = Process.Start(psi);
                if (process != null) {
                    StartBrowser(GetFullUrl(), () => process.HasExited);
                }
            }

            return VSConstants.S_OK;
        }

        public int LaunchFile(string file, bool debug) {
            return new DefaultPythonLauncher(_project).LaunchFile(file, debug);
{'fraction_non_alphanumeric': 0.10085160069389686, 'fraction_numerical': 0.0033117804762655733, 'mean_word_length': 2.187484292535813, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1374122', 'n_tokens_mistral': 3137, 'n_tokens_neox': 2922, 'n_words': 895}