aboutsummaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
authorMarkus Armbruster <armbru@redhat.com>2019-09-27 15:46:39 +0200
committerMarkus Armbruster <armbru@redhat.com>2019-09-28 17:17:48 +0200
commitc615550df306a7b16e75d21f65ee38898c756bac (patch)
tree1d2de035c046909657471164f51fddf51890457d /scripts
parent56d2df5e65d873ca0e9841f7bb7676cab759f8da (diff)
qapi: Improve source file read error handling
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 <armbru@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com> Message-Id: <20190927134639.4284-27-armbru@redhat.com>
Diffstat (limited to 'scripts')
-rw-r--r--scripts/qapi/common.py46
1 files changed, 26 insertions, 20 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 = []