Added __file__ and __name__ to xonsh scripts

This commit is contained in:
Anthony Scopatz 2017-02-11 18:51:10 -05:00
parent ede2340999
commit 6f448c0cfb
7 changed files with 53 additions and 5 deletions

15
news/file.rst Normal file
View file

@ -0,0 +1,15 @@
**Added:** None
**Changed:**
* Xonsh scripts now report ``__file__`` and ``__name__`` when run as scripts
or sourced. These variables have the same meaning as they do in Python
scripts.
**Deprecated:** None
**Removed:** None
**Fixed:** None
**Security:** None

View file

@ -181,6 +181,9 @@ def test_script_stder(case):
('pwd', None, lambda: os.getcwd() + '\n'),
('echo WORKING', None, 'WORKING\n'),
('ls -f', lambda out: out.splitlines().sort(), os.listdir().sort()),
('printfile.xsh', None, 'printfile.xsh\n'),
('printname.xsh', None, '__main__\n'),
('sourcefile.xsh', None, 'printfile.xsh\n'),
])
def test_single_command(cmd, fmt, exp):
"""The ``fmt`` parameter is a function

View file

@ -23,7 +23,8 @@ from xonsh.tools import (
to_dynamic_cwd_tuple, to_logfile_opt, pathsep_to_set, set_to_pathsep,
is_string_seq, pathsep_to_seq, seq_to_pathsep, is_nonstring_seq_of_strings,
pathsep_to_upper_seq, seq_to_upper_pathsep, expandvars, is_int_as_str, is_slice_as_str,
ensure_timestamp, get_portions, is_balanced, subexpr_before_unbalanced
ensure_timestamp, get_portions, is_balanced, subexpr_before_unbalanced,
swap_values
)
from xonsh.environ import Env
@ -1128,3 +1129,13 @@ def test_expand_path(expand_user, inp, expand_env_vars, exp_end, xonsh_builtins)
assert path == home_path + exp_end
else:
assert path == '~' + exp_end
def test_swap_values():
orig = {'x': 1}
updates = {'x': 42, 'y': 43}
with swap_values(orig, updates):
assert orig['x'] == 42
assert orig['y'] == 43
assert orig['x'] == 1
assert 'y' not in orig

View file

@ -18,7 +18,7 @@ from xonsh.platform import (ON_ANACONDA, ON_DARWIN, ON_WINDOWS, ON_FREEBSD,
from xonsh.proc import foreground
from xonsh.replay import replay_main
from xonsh.timings import timeit_alias
from xonsh.tools import argvquote, escape_windows_cmd_string, to_bool
from xonsh.tools import argvquote, escape_windows_cmd_string, to_bool, swap_values
from xonsh.xontribs import xontribs_main
import xonsh.completers._aliases as xca
@ -270,8 +270,10 @@ def source_alias(args, stdin=None):
src = fp.read()
if not src.endswith('\n'):
src += '\n'
with env.swap(ARGS=args[i+1:]):
builtins.execx(src, 'exec', builtins.__xonsh_ctx__, filename=fpath)
ctx = builtins.__xonsh_ctx__
updates = {'__file__': fpath, '__name__': os.path.abspath(fpath)}
with env.swap(ARGS=args[i+1:]), swap_values(ctx, updates):
builtins.execx(src, 'exec', ctx, filename=fpath)
def source_cmd(args, stdin=None):

View file

@ -101,7 +101,8 @@ def compile_code(filename, code, execer, glb, loc, mode):
code += '\n'
old_filename = execer.filename
execer.filename = filename
ccode = execer.compile(code, glbs=glb, locs=loc, mode=mode)
ccode = execer.compile(code, glbs=glb, locs=loc, mode=mode,
filename=filename)
except Exception:
raise
finally:

View file

@ -336,6 +336,7 @@ def main_xonsh(args):
sys.argv = [args.file] + args.args
env['ARGS'] = sys.argv[:] # $ARGS is not sys.argv
env['XONSH_SOURCE'] = path
shell.ctx.update({'__file__': args.file, '__name__': '__main__'})
run_script_with_cache(args.file, shell.execer, glb=shell.ctx,
loc=None, mode='exec')
else:

View file

@ -805,6 +805,21 @@ def swap(namespace, name, value, default=NotImplemented):
else:
setattr(namespace, name, old)
@contextlib.contextmanager
def swap_values(d, updates, default=NotImplemented):
"""Updates a dictionary (or other mapping) with values from another mapping,
and then restores the original mapping when the context is exited.
"""
old = {k: d.get(k, NotImplemented) for k in updates}
d.update(updates)
yield
for k, v in old.items():
if v is default and k in d:
del d[k]
else:
d[k] = v
#
# Validators and converters
#