distinguish IOError when loading file from that raised by program itself

Previously, Hy scripts that raised a subclass of IOError would be caught
by code intended to deal with IOErrors raised when Hy couldn't import
the script itself, resulting in either a misleading "Can't open file"
error message, or a misleading TypeError traceback from not being able
to format the "Can't open file" message (for IOErrors for which the
errno attribute was None). This commit (a straightforward implementation
of the idea proposed by @slimetree in #714) introduces a new HyIOError
class, raises that when `import_file_to_hst` can't open the file path,
and catches it in the `cmdline_handler`.

This is believed to fix #513, #714, and #727.
This commit is contained in:
Zack M. Davis 2015-02-16 14:27:18 -08:00
parent 31edaf6dee
commit 4bea6dc59e
3 changed files with 19 additions and 5 deletions

View File

@ -43,6 +43,8 @@ from hy.importer import (ast_compile, import_buffer_to_module,
from hy.completer import completion
from hy.completer import Completer
from hy.errors import HyIOError
from hy.macros import macro, require
from hy.models.expression import HyExpression
from hy.models.string import HyString
@ -324,10 +326,10 @@ def cmdline_handler(scriptname, argv):
# User did "hy <filename>"
try:
return run_file(options.args[0])
except IOError as x:
except HyIOError as e:
sys.stderr.write("hy: Can't open file '%s': [Errno %d] %s\n" %
(x.filename, x.errno, x.strerror))
sys.exit(x.errno)
(e.filename, e.errno, e.strerror))
sys.exit(e.errno)
# User did NOTHING!
return run_repl(spy=options.spy)

View File

@ -111,3 +111,11 @@ class HyTypeError(TypeError):
class HyMacroExpansionError(HyTypeError):
pass
class HyIOError(HyError, IOError):
"""
Trivial subclass of IOError and HyError, to distinguish between
IOErrors thrown by Hy itself as opposed to Hy programs.
"""
pass

View File

@ -22,6 +22,7 @@
from hy.compiler import hy_compile, HyTypeError
from hy.models import HyObject
from hy.lex import tokenize, LexException
from hy.errors import HyIOError
from io import open
import marshal
@ -49,8 +50,11 @@ def import_buffer_to_hst(buf):
def import_file_to_hst(fpath):
"""Import content from fpath and return an Hy AST."""
with open(fpath, 'r', encoding='utf-8') as f:
return import_buffer_to_hst(f.read())
try:
with open(fpath, 'r', encoding='utf-8') as f:
return import_buffer_to_hst(f.read())
except IOError as e:
raise HyIOError(e.errno, e.strerror, e.filename)
def import_buffer_to_ast(buf, module_name):