mirror of
https://github.com/xonsh/xonsh.git
synced 2025-03-04 08:24:40 +01:00
Added __file__ and __name__ to xonsh scripts
This commit is contained in:
parent
ede2340999
commit
6f448c0cfb
7 changed files with 53 additions and 5 deletions
15
news/file.rst
Normal file
15
news/file.rst
Normal 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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
#
|
||||
|
|
Loading…
Add table
Reference in a new issue