Skip to content

Commit

Permalink
[translation] Create e_usage() wrapper for args.UsageError.
Browse files Browse the repository at this point in the history
11 compile errors left in bin/osh_eval.

- ui.Stderr
- use of incomplete types
- readline module Any/void* type
- split::DEFAULT_IFS needs an 'extern'
- MultipleExceptions
- format string printing RuntimeError

Also update some comments.
  • Loading branch information
Andy Chu committed Feb 29, 2020
1 parent fff2884 commit 7a6a029
Show file tree
Hide file tree
Showing 6 changed files with 47 additions and 23 deletions.
11 changes: 3 additions & 8 deletions bin/oil.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,9 @@
Based on argv[0], it acts like a few different programs.
Builtins that can be exposed:
- test / [ -- call BoolParser at runtime
- 'time' -- because it has format strings, etc.
- find/xargs equivalents (even if they are not compatible)
- list/each/every
- echo: most likely don't care about this
Note: could also expose some other binaries for a smaller POSIX system?
- 'test' / '['
- 'time' -- has some differnt flags
"""
from __future__ import print_function

Expand Down
26 changes: 21 additions & 5 deletions core/pyutil.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,22 @@

import posix_ as posix

from typing import IO
from typing import IO, NoReturn, Any


# TODO: Move log, p_die, and e_die here too. They have different
# implementations in C++.

def e_usage(msg, *pos_args, **kwargs):
# type: (str, *Any, **Any) -> NoReturn
"""Convenience wrapper for arg parsing / validation errors.
Usually causes a builtin to fail with status 2, but the script can continue
if 'set +o errexit'. Main programs like bin/oil also use this.
"""
from frontend import args
# TODO: Should be error.Usage
raise args.UsageError(msg, *pos_args, **kwargs)


class _ResourceLoader(object):
Expand Down Expand Up @@ -69,10 +84,11 @@ def GetResourceLoader():
_loader = _FileResourceLoader(root_dir)

else:
# NOTE: This assumes all unit tests are one directory deep, e.g.
# core/util_test.py.
bin_dir = os_path.dirname(os_path.abspath(sys.argv[0])) # ~/git/oil/bin
root_dir = os_path.join(bin_dir, '..') # ~/git/oil/osh
# Find resources relative to the binary, e.g.
# ~/git/oilshell/oil/bin/oil.py. But it also assumes that all unit tests
# that use resources are are one directory deep, e.g. core/util_test.py.
bin_dir = os_path.dirname(os_path.abspath(sys.argv[0]))
root_dir = os_path.join(bin_dir, '..') # ~/git/oilshell/oil
_loader = _FileResourceLoader(root_dir)

return _loader
Expand Down
12 changes: 6 additions & 6 deletions core/state.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@
)
from _devbuild.gen import runtime_asdl # for cell
from asdl import runtime
from core.pyutil import e_usage
from core import ui
from core.util import log, e_die
from core import optview
from frontend import args
from frontend import consts
from frontend import match
from mycpp import mylib
Expand Down Expand Up @@ -280,7 +280,7 @@ def _SetArrayByName(self, opt_name, b):
index = match.MatchOption(opt_name)
if index == 0:
# Could be an assert sometimes, but check anyway
raise args.UsageError('got invalid option %r' % opt_name)
e_usage('got invalid option %r' % opt_name)
self.opt_array[index] = b

def _SetOption(self, opt_name, b):
Expand All @@ -305,7 +305,7 @@ def SetOption(self, opt_name, b):
# type: (str, bool) -> None
""" For set -o, set +o, or shopt -s/-u -o. """
if opt_name not in consts.SET_OPTION_NAMES:
raise args.UsageError('got invalid option %r' % opt_name)
e_usage('got invalid option %r' % opt_name)
self._SetOption(opt_name, b)

UP_val = self.mem.GetVar('SHELLOPTS')
Expand Down Expand Up @@ -359,7 +359,7 @@ def SetShoptOption(self, opt_name, b):
return

if opt_name not in consts.SHOPT_OPTION_NAMES:
raise args.UsageError('got invalid option %r' % opt_name)
e_usage('got invalid option %r' % opt_name)

self._SetArrayByName(opt_name, b)

Expand All @@ -373,7 +373,7 @@ def ShowOptions(self, opt_names):

for opt_name in opt_names:
if opt_name not in consts.SET_OPTION_NAMES:
raise args.UsageError('got invalid option %r' % opt_name)
e_usage('got invalid option %r' % opt_name)

if opt_name == 'errexit':
b = self.errexit.value()
Expand All @@ -391,7 +391,7 @@ def ShowShoptOptions(self, opt_names):
for opt_name in opt_names:
index = match.MatchOption(opt_name)
if index == 0:
raise args.UsageError('got invalid option %r' % opt_name)
e_usage('got invalid option %r' % opt_name)
b = self.opt_array[index]
print('shopt -%s %s' % ('s' if b else 'u', opt_name))

Expand Down
12 changes: 10 additions & 2 deletions core/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,20 +42,28 @@ def UserErrorString(self):

def p_die(msg, *args, **kwargs):
# type: (str, *Any, **Any) -> NoReturn
"""Convenience wrapper for parse errors."""
"""Convenience wrapper for parse errors.
Exits with status 2. See core/main_loop.py.
"""
raise error.Parse(msg, *args, **kwargs)


def e_die(msg, *args, **kwargs):
# type: (str, *Any, **Any) -> NoReturn
"""Convenience wrapper for runtime errors."""
"""Convenience wrapper for fatal runtime errors.
Usually exits with status 1. See osh/cmd_exec.py.
"""
raise error.FatalRuntime(msg, *args, **kwargs)


def e_strict(msg, *args, **kwargs):
# type: (str, *Any, **Any) -> NoReturn
"""Convenience wrapper for strictness errors.
Like e_die(), except the script MAY continue executing after these errors.
TODO: This could have a level too?
"""
raise error.Strict(msg, *args, **kwargs)
Expand Down
5 changes: 5 additions & 0 deletions cpp/preamble.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,3 +115,8 @@ Str* repr(void* obj) {
[[noreturn]] void e_strict(Str* s) {
assert(0);
}

// e.g. used in core/state.py
[[noreturn]] void e_usage(Str* s) {
assert(0);
}
4 changes: 2 additions & 2 deletions mycpp/cppgen_pass.py
Original file line number Diff line number Diff line change
Expand Up @@ -519,7 +519,7 @@ def visit_call_expr(self, o: 'mypy.nodes.CallExpr') -> T:
return

# TODO: Consolidate X_die() and log()? It has an extra arg though.
if o.callee.name in ('p_die', 'e_die', 'e_strict'):
if o.callee.name in ('p_die', 'e_die', 'e_strict', 'e_usage'):
args = o.args
if len(args) == 1: # log(CONST)
self.write('%s(' % o.callee.name)
Expand Down Expand Up @@ -1947,7 +1947,7 @@ def visit_import_from(self, o: 'mypy.nodes.ImportFrom') -> T:

# TODO: Should these be moved to core/pylib.py or something?
# They are varargs functions that have to be rewritten.
if name in ('log', 'p_die', 'e_die', 'e_strict'):
if name in ('log', 'p_die', 'e_die', 'e_strict', 'e_usage'):
continue # do nothing
if name in ('switch', 'tagswitch', 'iteritems'): # mylib
continue # do nothing
Expand Down

0 comments on commit 7a6a029

Please sign in to comment.