Repository: xonsh/xonsh

Issue:
Add `--no-env` argument
xonsh [has `--no-rc`](https://github.com/xonsh/xonsh/blob/6fa83f830579d2bad39b1842911951f55a9da22c/xonsh/main.py#L180-L186) to avoid loading RC files. But if we want to run completely clean xonsh we need to avoid inheritance environment.

For example sometimes I faced with issues when I want to run xonsh from xonsh and `$XONSH_HISTORY_FILE` goes to the new xonsh instance and lock the file system. I believe that the similar logic could produce the issues with any other use cases. For example we had issues around multiple running `xonsh -c ...` because the history backend uses the same file (fixed in #4178).

I suggest to add `--no-env` as well as [`--no-rc`](https://github.com/xonsh/xonsh/blob/6fa83f830579d2bad39b1842911951f55a9da22c/xonsh/main.py#L180-L186) argument that will run xonsh with `default_env` only:

https://github.com/xonsh/xonsh/blob/6fa83f830579d2bad39b1842911951f55a9da22c/xonsh/environ.py#L2499-L2500

So to get clean xonsh instance we can run `xonsh --no-rc --no-env`.

## For community
⬇️  **Please click the 👍 reaction instead of leaving a `+1` or 👍  comment**



Discussion:
Hi, hello
Can I and my friend (@Juncheng-wq) take over this issue plz? We will try to work on it by the end of October. 
Thankyou
Hello @121247 ! PR is welcome!
Hi maintainers,

Could I just ask if we want to write tests to see if the` default_env` is returned correctly by` --no-env` command, are we expected to include it in `test_environ.py` file or` test_main.py` file? I'm not so sure with if.

Thankyou
@121247 I'm in favor for test_main. @yaxollum @jnoortheen feel free to point another way.

Resolving patch:
diff --git a/xonsh/built_ins.py b/xonsh/built_ins.py
--- a/xonsh/built_ins.py
+++ b/xonsh/built_ins.py
@@ -593,7 +593,7 @@ def _restore_python_exit(self):
         if self._py_quit is not None:
             builtins.quit = self._py_quit
 
-    def load(self, execer=None, ctx=None, **kwargs):
+    def load(self, execer=None, ctx=None, inherit_env=True, **kwargs):
         """Loads the session with default values.
 
         Parameters
@@ -602,6 +602,10 @@ def load(self, execer=None, ctx=None, **kwargs):
             Xonsh execution object, may be None to start
         ctx : Mapping, optional
             Context to start xonsh session with.
+        inherit_env : bool
+            If ``True``: inherit environment variables from ``os.environ``.
+            If ``False``: use default values for environment variables and
+            set ``$XONSH_ENV_INHERITED = False``.
         """
         from xonsh.commands_cache import CommandsCache
         from xonsh.environ import Env, default_env
@@ -611,7 +615,12 @@ def load(self, execer=None, ctx=None, **kwargs):
         if ctx is not None:
             self.ctx = ctx
 
-        self.env = kwargs.pop("env") if "env" in kwargs else Env(default_env())
+        if "env" in kwargs:
+            self.env = kwargs.pop("env")
+        elif inherit_env:
+            self.env = Env(default_env())
+        else:
+            self.env = Env({"XONSH_ENV_INHERITED": False})
 
         self.exit = False
         self.stdout_uncaptured = None
diff --git a/xonsh/environ.py b/xonsh/environ.py
--- a/xonsh/environ.py
+++ b/xonsh/environ.py
@@ -897,6 +897,12 @@ class GeneralSetting(Xettings):
     if hasattr(locale, "LC_MESSAGES"):
         LC_MESSAGES = Var.for_locale("LC_MESSAGES")
 
+    PWD = Var.with_default(
+        _get_cwd() or ".",
+        "Current working directory.",
+        "os.getcwd()",
+        is_configurable=False,
+    )
     OLDPWD = Var.with_default(
         ".",
         "Used to represent a previous present working directory.",
diff --git a/xonsh/main.py b/xonsh/main.py
--- a/xonsh/main.py
+++ b/xonsh/main.py
@@ -191,6 +191,13 @@ def parser():
         action="store_true",
         default=False,
     )
+    p.add_argument(
+        "--no-env",
+        help="Do not inherit parent environment variables.",
+        dest="inherit_env",
+        action="store_false",
+        default=True,
+    )
     p.add_argument(
         "--no-script-cache",
         help="Do not cache scripts as they are run.",
@@ -343,7 +350,7 @@ def start_services(shell_kwargs, args, pre_env=None):
         scriptcache=shell_kwargs.get("scriptcache", True),
         cacheall=shell_kwargs.get("cacheall", False),
     )
-    XSH.load(ctx=ctx, execer=execer)
+    XSH.load(ctx=ctx, execer=execer, inherit_env=shell_kwargs.get("inherit_env", True))
     events.on_timingprobe.fire(name="post_execer_init")
 
     install_import_hooks(execer)
@@ -387,6 +394,7 @@ def premain(argv=None):
         shell_kwargs["norc"] = True
     elif args.rc:
         shell_kwargs["rc"] = args.rc
+    shell_kwargs["inherit_env"] = args.inherit_env
     sys.displayhook = _pprint_displayhook
     if args.command is not None:
         args.mode = XonshMode.single_command
@@ -484,6 +492,7 @@ def func_sig_ttin_ttou(n, f):
         signal.signal(signal.SIGTTOU, func_sig_ttin_ttou)
 
     events.on_post_init.fire()
+
     env = XSH.env
     shell = XSH.shell
     history = XSH.history


Test patch: