[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PULL 27/27] qapi: Improve source file read error handling
From: |
Markus Armbruster |
Subject: |
[PULL 27/27] qapi: Improve source file read error handling |
Date: |
Sat, 28 Sep 2019 20:39:34 +0200 |
qapi-gen.py crashes when it can't open the main schema file, and when
it can't read from any schema file. Lazy.
Change QAPISchema.__init__() to take a file name instead of a file
object. Move the open code from _include() to __init__(), so it's
used for the main schema file, too.
Move the read into the try for good measure, and rephrase the error
message.
Reporting open or read failure for the main schema file needs a
QAPISourceInfo representing "no source". Make QAPISourceInfo cope
with fname=None.
Signed-off-by: Markus Armbruster <address@hidden>
Reviewed-by: Eric Blake <address@hidden>
Message-Id: <address@hidden>
---
scripts/qapi/common.py | 46 +++++++++++++++------------
tests/qapi-schema/include-no-file.err | 2 +-
2 files changed, 27 insertions(+), 21 deletions(-)
diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index a74cd957d4..d6e00c80ea 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -53,7 +53,12 @@ class QAPISourceInfo(object):
return info
def loc(self):
- return '%s:%d' % (self.fname, self.line)
+ if self.fname is None:
+ return sys.argv[0]
+ ret = self.fname
+ if self.line is not None:
+ ret += ':%d' % self.line
+ return ret
def in_defn(self):
if self.defn_name:
@@ -383,14 +388,26 @@ class QAPIDoc(object):
class QAPISchemaParser(object):
- def __init__(self, fp, previously_included=[], incl_info=None):
- self.fname = fp.name
- previously_included.append(os.path.abspath(fp.name))
- self.src = fp.read()
+ def __init__(self, fname, previously_included=[], incl_info=None):
+ previously_included.append(os.path.abspath(fname))
+
+ try:
+ if sys.version_info[0] >= 3:
+ fp = open(fname, 'r', encoding='utf-8')
+ else:
+ fp = open(fname, 'r')
+ self.src = fp.read()
+ except IOError as e:
+ raise QAPISemError(incl_info or QAPISourceInfo(None, None, None),
+ "can't read %s file '%s': %s"
+ % ("include" if incl_info else "schema",
+ fname,
+ e.strerror))
+
if self.src == '' or self.src[-1] != '\n':
self.src += '\n'
self.cursor = 0
- self.info = QAPISourceInfo(self.fname, 1, incl_info)
+ self.info = QAPISourceInfo(fname, 1, incl_info)
self.line_pos = 0
self.exprs = []
self.docs = []
@@ -414,7 +431,7 @@ class QAPISchemaParser(object):
if not isinstance(include, str):
raise QAPISemError(info,
"value of 'include' must be a string")
- incl_fname = os.path.join(os.path.dirname(self.fname),
+ incl_fname = os.path.join(os.path.dirname(fname),
include)
self.exprs.append({'expr': {'include': incl_fname},
'info': info})
@@ -466,14 +483,7 @@ class QAPISchemaParser(object):
if incl_abs_fname in previously_included:
return None
- try:
- if sys.version_info[0] >= 3:
- fobj = open(incl_fname, 'r', encoding='utf-8')
- else:
- fobj = open(incl_fname, 'r')
- except IOError as e:
- raise QAPISemError(info, "%s: %s" % (e.strerror, incl_fname))
- return QAPISchemaParser(fobj, previously_included, info)
+ return QAPISchemaParser(incl_fname, previously_included, info)
def _pragma(self, name, value, info):
global doc_required, returns_whitelist, name_case_whitelist
@@ -1734,11 +1744,7 @@ class QAPISchemaEvent(QAPISchemaEntity):
class QAPISchema(object):
def __init__(self, fname):
self.fname = fname
- if sys.version_info[0] >= 3:
- f = open(fname, 'r', encoding='utf-8')
- else:
- f = open(fname, 'r')
- parser = QAPISchemaParser(f)
+ parser = QAPISchemaParser(fname)
exprs = check_exprs(parser.exprs)
self.docs = parser.docs
self._entity_list = []
diff --git a/tests/qapi-schema/include-no-file.err
b/tests/qapi-schema/include-no-file.err
index e42bcf4bc1..0a6c6bb4a9 100644
--- a/tests/qapi-schema/include-no-file.err
+++ b/tests/qapi-schema/include-no-file.err
@@ -1 +1 @@
-tests/qapi-schema/include-no-file.json:1: No such file or directory:
tests/qapi-schema/include-no-file-sub.json
+tests/qapi-schema/include-no-file.json:1: can't read include file
'tests/qapi-schema/include-no-file-sub.json': No such file or directory
--
2.21.0
- [PULL 00/27] QAPI patches for 2019-09-28, Markus Armbruster, 2019/09/28
- [PULL 01/27] qmp-dispatch: Use CommandNotFound error for disabled commands, Markus Armbruster, 2019/09/28
- [PULL 02/27] qapi: Tighten QAPISchemaFOO.check() assertions, Markus Armbruster, 2019/09/28
- [PULL 14/27] qapi: Make check_type()'s array case a bit more obvious, Markus Armbruster, 2019/09/28
- [PULL 11/27] qapi: Use check_name_str() where it suffices, Markus Armbruster, 2019/09/28
- [PULL 13/27] qapi: Move check for reserved names out of add_name(), Markus Armbruster, 2019/09/28
- [PULL 10/27] qapi: Improve reporting of invalid name errors, Markus Armbruster, 2019/09/28
- [PULL 27/27] qapi: Improve source file read error handling,
Markus Armbruster <=
- [PULL 19/27] qapi: Improve reporting of invalid 'if' errors, Markus Armbruster, 2019/09/28
- [PULL 20/27] qapi: Improve reporting of invalid flags, Markus Armbruster, 2019/09/28
- [PULL 18/27] qapi: Move context-free checking to the proper place, Markus Armbruster, 2019/09/28
- [PULL 24/27] qapi: Eliminate check_keys(), rename check_known_keys(), Markus Armbruster, 2019/09/28
- [PULL 21/27] qapi: Improve reporting of missing / unknown definition keys, Markus Armbruster, 2019/09/28
- [PULL 23/27] qapi: Improve reporting of invalid 'if' further, Markus Armbruster, 2019/09/28
- [PULL 17/27] qapi: Move context-sensitive checking to the proper place, Markus Armbruster, 2019/09/28
- [PULL 03/27] qapi: Rename .owner to .defined_in, Markus Armbruster, 2019/09/28
- [PULL 04/27] qapi: New QAPISourceInfo, replacing dict, Markus Armbruster, 2019/09/28
- [PULL 16/27] qapi: Inline check_name() into check_union(), Markus Armbruster, 2019/09/28