<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.Diagnostics;
using System.IO;
using System.Reflection;
using System.Threading;
using IronPython.Compiler;
using IronPython.Runtime;
using IronPython.Runtime.Exceptions;
using IronPython.Runtime.Operations;
using Microsoft.Scripting;
using Microsoft.Scripting.Hosting.Shell;
using Microsoft.Scripting.Runtime;
using Microsoft.Scripting.Utils;

namespace IronPython.Hosting {
#if !SILVERLIGHT
    /// <summary>
    /// A simple Python command-line should mimic the standard python.exe
    /// </summary>
    public sealed class PythonCommandLine : CommandLine {
        private PythonContext PythonContext {
            get { return (PythonContext)Language; }
        }
        
        private new PythonConsoleOptions Options { get { return (PythonConsoleOptions)base.Options; } }
        
        public PythonCommandLine() {
        }

        protected override string/*!*/ Logo {
            get {
                return GetLogoDisplay();
            }
        }

        /// <summary>
        /// Returns the display look for IronPython.  
        /// 
        /// The returned string uses This \n instead of Environment.NewLine for it's line seperator 
        /// because it is intended to be outputted through the Python I/O system.
        /// </summary>
        public static string GetLogoDisplay() {
            return GetVersionString() +
                   "\nType \"help\", \"copyright\", \"credits\" or \"license\" for more information.\n";
        }

        private static string/*!*/ VersionString {
            get {
                return GetVersionString();                    
            }
        }

        private static string GetVersionString() {

            return String.Format("{0}{3} ({1}) on .NET {2}",
                                PythonContext.IronPythonDisplayName,
                                PythonContext.GetPythonVersion().ToString(),
                                Environment.Version,
#if DEBUG
                                " DEBUG"
#else
                                ""
#endif
                                );
        }

        private int GetEffectiveExitCode(SystemExitException/*!*/ e) {
            object nonIntegerCode;
            int exitCode = e.GetExitCode(out nonIntegerCode);
            if (nonIntegerCode != null) {
                Console.WriteLine(nonIntegerCode.ToString(), Style.Error);
            }
            return exitCode;
        }

        protected override void Shutdown() {
            try {
                Language.Shutdown();
            } catch (Exception e) {
                Console.WriteLine("", Style.Error);
                Console.WriteLine("Error in sys.exitfunc:", Style.Error);
                Console.Write(Language.FormatException(e), Style.Error);
            }
        }

        protected override int Run() {
            if (Options.ModuleToRun != null) {
                // PEP 338 support - http://www.python.org/dev/peps/pep-0338
                // This requires the presence of the Python standard library or
                // an equivalent runpy.py which defines a run_module method.

                // import the runpy module
                object runpy, runMod;
                try {
                    runpy = Importer.Import(
                        PythonContext.SharedContext,
                        "runpy",
                        PythonTuple.EMPTY,
                        0
                    );
                } catch (Exception) {
                    Console.WriteLine("Could not import runpy module", Style.Error);
                    return -1;
                }

                // get the run_module method
                try {
                    runMod = PythonOps.GetBoundAttr(PythonContext.SharedContext, runpy, "run_module");
                } catch (Exception) {
                    Console.WriteLine("Could not access runpy.run_module", Style.Error);
                    return -1;
                }

                // call it with the name of the module to run
                try {
                    PythonOps.CallWithKeywordArgs(
                        PythonContext.SharedContext,
                        runMod,
                        new object[] { Options.ModuleToRun, "__main__", ScriptingRuntimeHelpers.True },
                        new string[] { "run_name", "alter_sys" }
                    );
                } catch (SystemExitException e) {
                    object dummy;
                    return e.GetExitCode(out dummy);
                }

                return 0;
            }

            return base.Run();
        }

        #region Initialization

        protected override void Initialize() {
            Debug.Assert(Language != null);

            base.Initialize();

            Console.Output = new OutputWriter(PythonContext, false);
            Console.ErrorOutput = new OutputWriter(PythonContext, true);
            
            // TODO: must precede path initialization! (??? - test test_importpkg.py)
            int pathIndex = PythonContext.PythonOptions.SearchPaths.Count;
                        
            Language.DomainManager.LoadAssembly(typeof(string).Assembly);
            Language.DomainManager.LoadAssembly(typeof(System.Diagnostics.Debug).Assembly);

            InitializePath(ref pathIndex);
            InitializeModules();
            InitializeExtensionDLLs();

            ImportSite();

            PythonContext.InsertIntoPath(0, ".");
            PythonContext.InsertIntoPath(++pathIndex, PythonContext.DomainManager.Platform.CurrentDirectory);

            if (Options.Command == null && Options.FileName != null) {
                if (Options.FileName == "-") {
                    Options.FileName = "<stdin>";
                } else {
#if !SILVERLIGHT
                    if (!File.Exists(Options.FileName)) {
                        Console.WriteLine(
                            String.Format(
                                System.Globalization.CultureInfo.InvariantCulture,
                                "File {0} does not exist.",
                                Options.FileName),
                            Style.Error);
                        Environment.Exit(1);
                    }
#endif
                    string fullPath = Language.DomainManager.Platform.GetFullPath(Options.FileName);
                    PythonContext.InsertIntoPath(0, Path.GetDirectoryName(fullPath));
                }
            }
        }

        protected override Scope/*!*/ CreateScope() {
            ModuleOptions trueDiv = (PythonContext.PythonOptions.DivisionOptions == PythonDivisionOptions.New) ? ModuleOptions.TrueDivision : ModuleOptions.None;
            var modCtx = new ModuleContext(new PythonDictionary(), PythonContext);
            modCtx.Features = trueDiv;
            modCtx.InitializeBuiltins(true);

            PythonContext.PublishModule("__main__", modCtx.Module);
            modCtx.Globals["__doc__"] = null;
            modCtx.Globals["__name__"] = "__main__";

            return modCtx.GlobalScope;
        }
        
        private void InitializePath(ref int pathIndex) {
#if !SILVERLIGHT // paths, environment vars<commit_msg>Only add the current working directory if running the console or with -c. If running a script, add the script's containing folder.<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.Diagnostics;
using System.IO;
using System.Reflection;
using System.Threading;
using IronPython.Compiler;
using IronPython.Runtime;
using IronPython.Runtime.Exceptions;
using IronPython.Runtime.Operations;
using Microsoft.Scripting;
using Microsoft.Scripting.Hosting.Shell;
using Microsoft.Scripting.Runtime;
using Microsoft.Scripting.Utils;

namespace IronPython.Hosting {
#if !SILVERLIGHT
    /// <summary>
    /// A simple Python command-line should mimic the standard python.exe
    /// </summary>
    public sealed class PythonCommandLine : CommandLine {
        private PythonContext PythonContext {
            get { return (PythonContext)Language; }
        }
        
        private new PythonConsoleOptions Options { get { return (PythonConsoleOptions)base.Options; } }
        
        public PythonCommandLine() {
        }

        protected override string/*!*/ Logo {
            get {
                return GetLogoDisplay();
            }
        }

        /// <summary>
        /// Returns the display look for IronPython.  
        /// 
        /// The returned string uses This \n instead of Environment.NewLine for it's line seperator 
        /// because it is intended to be outputted through the Python I/O system.
        /// </summary>
        public static string GetLogoDisplay() {
            return GetVersionString() +
                   "\nType \"help\", \"copyright\", \"credits\" or \"license\" for more information.\n";
        }

        private static string/*!*/ VersionString {
            get {
                return GetVersionString();                    
            }
        }

        private static string GetVersionString() {

            return String.Format("{0}{3} ({1}) on .NET {2}",
                                PythonContext.IronPythonDisplayName,
                                PythonContext.GetPythonVersion().ToString(),
                                Environment.Version,
#if DEBUG
                                " DEBUG"
#else
                                ""
#endif
                                );
        }

        private int GetEffectiveExitCode(SystemExitException/*!*/ e) {
            object nonIntegerCode;
            int exitCode = e.GetExitCode(out nonIntegerCode);
            if (nonIntegerCode != null) {
                Console.WriteLine(nonIntegerCode.ToString(), Style.Error);
            }
            return exitCode;
        }

        protected override void Shutdown() {
            try {
                Language.Shutdown();
            } catch (Exception e) {
                Console.WriteLine("", Style.Error);
                Console.WriteLine("Error in sys.exitfunc:", Style.Error);
                Console.Write(Language.FormatException(e), Style.Error);
            }
        }

        protected override int Run() {
            if (Options.ModuleToRun != null) {
                // PEP 338 support - http://www.python.org/dev/peps/pep-0338
                // This requires the presence of the Python standard library or
                // an equivalent runpy.py which defines a run_module method.

                // import the runpy module
                object runpy, runMod;
                try {
                    runpy = Importer.Import(
                        PythonContext.SharedContext,
                        "runpy",
                        PythonTuple.EMPTY,
                        0
                    );
                } catch (Exception) {
                    Console.WriteLine("Could not import runpy module", Style.Error);
                    return -1;
                }

                // get the run_module method
                try {
                    runMod = PythonOps.GetBoundAttr(PythonContext.SharedContext, runpy, "run_module");
                } catch (Exception) {
                    Console.WriteLine("Could not access runpy.run_module", Style.Error);
                    return -1;
                }

                // call it with the name of the module to run
                try {
                    PythonOps.CallWithKeywordArgs(
                        PythonContext.SharedContext,
                        runMod,
                        new object[] { Options.ModuleToRun, "__main__", ScriptingRuntimeHelpers.True },
                        new string[] { "run_name", "alter_sys" }
                    );
                } catch (SystemExitException e) {
                    object dummy;
                    return e.GetExitCode(out dummy);
                }

                return 0;
            }

            return base.Run();
        }

        #region Initialization

        protected override void Initialize() {
            Debug.Assert(Language != null);

            base.Initialize();

            Console.Output = new OutputWriter(PythonContext, false);
            Console.ErrorOutput = new OutputWriter(PythonContext, true);
            
            // TODO: must precede path initialization! (??? - test test_importpkg.py)
            int pathIndex = PythonContext.PythonOptions.SearchPaths.Count;
                        
            Language.DomainManager.LoadAssembly(typeof(string).Assembly);
            Language.DomainManager.LoadAssembly(typeof(System.Diagnostics.Debug).Assembly);

            InitializePath(ref pathIndex);
            InitializeModules();
            InitializeExtensionDLLs();

            ImportSite();

            // If running in console mode (including with -c), the current working directory should be
            // the first entry in sys.path. If running a script file, however, the CWD should not be added;
            // instead, the script's containg folder should be added.

            string fullPath = "."; // this is a valid path resolving to current working dir. Pinky-swear.

            if (Options.Command == null && Options.FileName != null) {
                if (Options.FileName == "-") {
                    Options.FileName = "<stdin>";
                } else {
#if !SILVERLIGHT
                    if (!File.Exists(Options.FileName)) {
                        Console.WriteLine(
                            String.Format(
                                System.Globalization.CultureInfo.InvariantCulture,
                                "File {0} does not exist.",
                                Options.FileName),
                            Style.Error);
                        Environment.Exit(1);
                    }
#endif
                    fullPath = Path.GetDirectoryName(
                        Language.DomainManager.Platform.GetFullPath(Options.FileName)
                    );
                }
            }

            PythonContext.InsertIntoPath(0, fullPath);
        }

        protected override Scope/*!*/ CreateScope() {
            ModuleOptions trueDiv = (PythonContext.PythonOptions.DivisionOptions == PythonDivisionOptions.New) ? ModuleOptions.TrueDivision : ModuleOptions.None;
            var modCtx = new ModuleContext(new PythonDictionary(), PythonContext);
            modCtx.Features = trueDiv;
            modCtx.InitializeBuiltins(true);

            PythonContext.PublishModule("__main__", modCtx.Module);
            modCtx.Globals["__doc__"] = null;
            modCtx.Globals["__name__"] = "__main__";

            return modCtx.GlobalScope;
        }
        
        private void InitializePath(ref int pathIndex) {
#if !SILVERLIGHT // paths, environment vars
{'fraction_non_alphanumeric': 0.10419352858107693, 'fraction_numerical': 0.0030085344139497757, 'mean_word_length': 1.5829368855058674, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3400391', 'n_tokens_mistral': 3850, 'n_tokens_neox': 3617, 'n_words': 1023}