diff mbox

[v5,12/17] qapi: rename QAPIExprError/QAPILineError

Message ID 20161117155504.21843-13-marcandre.lureau@redhat.com
State New
Headers show

Commit Message

Marc-André Lureau Nov. 17, 2016, 3:54 p.m. UTC
There is nothing specific about expressions in this exception,
the following patch will use it without expressions.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 scripts/qapi.py | 146 ++++++++++++++++++++++++++++----------------------------
 1 file changed, 73 insertions(+), 73 deletions(-)

Comments

Markus Armbruster Nov. 18, 2016, 10:17 a.m. UTC | #1
Make the summary line "qapi: Rename QAPIExprError to QAPILineError".

Marc-André Lureau <marcandre.lureau@redhat.com> writes:

> There is nothing specific about expressions in this exception,
> the following patch will use it without expressions.
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
>  scripts/qapi.py | 146 ++++++++++++++++++++++++++++----------------------------
>  1 file changed, 73 insertions(+), 73 deletions(-)
>
> diff --git a/scripts/qapi.py b/scripts/qapi.py
> index 21bc32f..4d1b0e4 100644
> --- a/scripts/qapi.py
> +++ b/scripts/qapi.py
> @@ -110,11 +110,11 @@ class QAPISchemaError(Exception):
>              "%s:%d:%d: %s" % (self.fname, self.line, self.col, self.msg)
>  
>  
> -class QAPIExprError(Exception):
> -    def __init__(self, expr_info, msg):
> +class QAPILineError(Exception):
> +    def __init__(self, info, msg):
>          Exception.__init__(self)
> -        assert expr_info
> -        self.info = expr_info
> +        assert info
> +        self.info = info
>          self.msg = msg
>  
>      def __str__(self):

Since we're talking about misnamed / awkward error stuff:

* QAPISchemaError is really a parse error.  __init__()'s schema argument
  isn't a QAPISchema, it's a QAPISchemaParser.

* Method __str__() is mostly duplicated.

How do you like the following untested sketch?

    class QAPISchemaError(Exception):
        def __init__(self, fname, line, col, incl_info, msg):
            Exception.__init__(self)
            self.fname = fname
            self.line = line
            self.col = col
            self.info = incl_info
            self.msg = msg

        def __str__(self):
            loc = "%s:%d" % (self.fname, self.line)
            if self.col is not None:
                loc += ":%s" % self.col
            return error_path(self.info) + \
                "%s: %s" % (loc, self.msg)


    class QAPISchemaParseError(QAPISchemaError):
        def __init__(self, parser, msg):
            col = 1
            for ch in parser.src[parser.line_pos:parser.pos]:
                if ch == '\t':
                    col = (col + 7) % 8 + 1
                else:
                    col += 1
            QAPISchemaError.__init__(self, parser.fname, parser.line, parser.col,
                                     parser.incl_info, msg)


    class QAPISchemaSemanticError(Exception):
        def __init__(self, info, msg):
            QAPISchemaError(self, info['file'], info['line'], None,
                            info['parent'], msg)

The class names are a bit long.  If they result in awkward line breaks,
let's shorten them some.

The "except (QAPISchemaError, QAPIExprError)" become just "except
QAPISchemaError".

Could QAPISchemaParser.__init__() raise QAPISchemaParseError instead?

[...]
Marc-Andre Lureau Nov. 18, 2016, 10:31 a.m. UTC | #2
----- Original Message -----
> Make the summary line "qapi: Rename QAPIExprError to QAPILineError".
> 

ok

> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
> 
> > There is nothing specific about expressions in this exception,
> > the following patch will use it without expressions.
> >
> > Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> > ---
> >  scripts/qapi.py | 146
> >  ++++++++++++++++++++++++++++----------------------------
> >  1 file changed, 73 insertions(+), 73 deletions(-)
> >
> > diff --git a/scripts/qapi.py b/scripts/qapi.py
> > index 21bc32f..4d1b0e4 100644
> > --- a/scripts/qapi.py
> > +++ b/scripts/qapi.py
> > @@ -110,11 +110,11 @@ class QAPISchemaError(Exception):
> >              "%s:%d:%d: %s" % (self.fname, self.line, self.col, self.msg)
> >  
> >  
> > -class QAPIExprError(Exception):
> > -    def __init__(self, expr_info, msg):
> > +class QAPILineError(Exception):
> > +    def __init__(self, info, msg):
> >          Exception.__init__(self)
> > -        assert expr_info
> > -        self.info = expr_info
> > +        assert info
> > +        self.info = info
> >          self.msg = msg
> >  
> >      def __str__(self):
> 
> Since we're talking about misnamed / awkward error stuff:
> 
> * QAPISchemaError is really a parse error.  __init__()'s schema argument
>   isn't a QAPISchema, it's a QAPISchemaParser.
> 
> * Method __str__() is mostly duplicated.
> 
> How do you like the following untested sketch?

I like it, though I would consider it separately from this series. Here I systematically renamed the existing class ("line" since it's about location in file), your proposed change has more implications I don't really want to get into here.

> 
>     class QAPISchemaError(Exception):
>         def __init__(self, fname, line, col, incl_info, msg):
>             Exception.__init__(self)
>             self.fname = fname
>             self.line = line
>             self.col = col
>             self.info = incl_info
>             self.msg = msg
> 
>         def __str__(self):
>             loc = "%s:%d" % (self.fname, self.line)
>             if self.col is not None:
>                 loc += ":%s" % self.col
>             return error_path(self.info) + \
>                 "%s: %s" % (loc, self.msg)
> 
> 
>     class QAPISchemaParseError(QAPISchemaError):
>         def __init__(self, parser, msg):
>             col = 1
>             for ch in parser.src[parser.line_pos:parser.pos]:
>                 if ch == '\t':
>                     col = (col + 7) % 8 + 1
>                 else:
>                     col += 1
>             QAPISchemaError.__init__(self, parser.fname, parser.line,
>             parser.col,
>                                      parser.incl_info, msg)
> 
> 
>     class QAPISchemaSemanticError(Exception):
>         def __init__(self, info, msg):
>             QAPISchemaError(self, info['file'], info['line'], None,
>                             info['parent'], msg)
> 
> The class names are a bit long.  If they result in awkward line breaks,
> let's shorten them some.
> 
> The "except (QAPISchemaError, QAPIExprError)" become just "except
> QAPISchemaError".
> 
> Could QAPISchemaParser.__init__() raise QAPISchemaParseError instead?
> 
> [...]
>
Markus Armbruster Nov. 18, 2016, 2:13 p.m. UTC | #3
Marc-André Lureau <mlureau@redhat.com> writes:

> ----- Original Message -----
>> Make the summary line "qapi: Rename QAPIExprError to QAPILineError".
>> 
>
> ok
>
>> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
>> 
>> > There is nothing specific about expressions in this exception,
>> > the following patch will use it without expressions.
>> >
>> > Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
>> > ---
>> >  scripts/qapi.py | 146
>> >  ++++++++++++++++++++++++++++----------------------------
>> >  1 file changed, 73 insertions(+), 73 deletions(-)
>> >
>> > diff --git a/scripts/qapi.py b/scripts/qapi.py
>> > index 21bc32f..4d1b0e4 100644
>> > --- a/scripts/qapi.py
>> > +++ b/scripts/qapi.py
>> > @@ -110,11 +110,11 @@ class QAPISchemaError(Exception):
>> >              "%s:%d:%d: %s" % (self.fname, self.line, self.col, self.msg)
>> >  
>> >  
>> > -class QAPIExprError(Exception):
>> > -    def __init__(self, expr_info, msg):
>> > +class QAPILineError(Exception):
>> > +    def __init__(self, info, msg):
>> >          Exception.__init__(self)
>> > -        assert expr_info
>> > -        self.info = expr_info
>> > +        assert info
>> > +        self.info = info
>> >          self.msg = msg
>> >  
>> >      def __str__(self):
>> 
>> Since we're talking about misnamed / awkward error stuff:
>> 
>> * QAPISchemaError is really a parse error.  __init__()'s schema argument
>>   isn't a QAPISchema, it's a QAPISchemaParser.
>> 
>> * Method __str__() is mostly duplicated.
>> 
>> How do you like the following untested sketch?
>
> I like it, though I would consider it separately from this series.

Punting ideas we both like to later series is fair.  But when we intend
to rework the error classes later, renaming one of them now is perhaps
not worth the churn.

> Here I systematically renamed the existing class ("line" since it's
> about location in file), your proposed change has more implications I
> don't really want to get into here.

Well, QAPISchemaError is just as much about "location in file" as
QAPIExprError.  They just specify the location differently: one by
reference to the parser's current location, and the other by an "info"
dictionary.

[...]
diff mbox

Patch

diff --git a/scripts/qapi.py b/scripts/qapi.py
index 21bc32f..4d1b0e4 100644
--- a/scripts/qapi.py
+++ b/scripts/qapi.py
@@ -110,11 +110,11 @@  class QAPISchemaError(Exception):
             "%s:%d:%d: %s" % (self.fname, self.line, self.col, self.msg)
 
 
-class QAPIExprError(Exception):
-    def __init__(self, expr_info, msg):
+class QAPILineError(Exception):
+    def __init__(self, info, msg):
         Exception.__init__(self)
-        assert expr_info
-        self.info = expr_info
+        assert info
+        self.info = info
         self.msg = msg
 
     def __str__(self):
@@ -140,24 +140,24 @@  class QAPISchemaParser(object):
         self.accept()
 
         while self.tok is not None:
-            expr_info = {'file': fname, 'line': self.line,
-                         'parent': self.incl_info}
+            info = {'file': fname, 'line': self.line,
+                    'parent': self.incl_info}
             expr = self.get_expr(False)
             if isinstance(expr, dict) and "include" in expr:
                 if len(expr) != 1:
-                    raise QAPIExprError(expr_info,
+                    raise QAPILineError(info,
                                         "Invalid 'include' directive")
                 include = expr["include"]
                 if not isinstance(include, str):
-                    raise QAPIExprError(expr_info,
+                    raise QAPILineError(info,
                                         "Value of 'include' must be a string")
                 incl_abs_fname = os.path.join(os.path.dirname(abs_fname),
                                               include)
                 # catch inclusion cycle
-                inf = expr_info
+                inf = info
                 while inf:
                     if incl_abs_fname == os.path.abspath(inf['file']):
-                        raise QAPIExprError(expr_info, "Inclusion loop for %s"
+                        raise QAPILineError(info, "Inclusion loop for %s"
                                             % include)
                     inf = inf['parent']
                 # skip multiple include of the same file
@@ -166,14 +166,14 @@  class QAPISchemaParser(object):
                 try:
                     fobj = open(incl_abs_fname, 'r')
                 except IOError as e:
-                    raise QAPIExprError(expr_info,
+                    raise QAPILineError(info,
                                         '%s: %s' % (e.strerror, include))
                 exprs_include = QAPISchemaParser(fobj, previously_included,
-                                                 expr_info)
+                                                 info)
                 self.exprs.extend(exprs_include.exprs)
             else:
                 expr_elem = {'expr': expr,
-                             'info': expr_info}
+                             'info': info}
                 self.exprs.append(expr_elem)
 
     def accept(self):
@@ -375,18 +375,18 @@  valid_name = re.compile('^(__[a-zA-Z0-9.-]+_)?'
                         '[a-zA-Z][a-zA-Z0-9_-]*$')
 
 
-def check_name(expr_info, source, name, allow_optional=False,
+def check_name(info, source, name, allow_optional=False,
                enum_member=False):
     global valid_name
     membername = name
 
     if not isinstance(name, str):
-        raise QAPIExprError(expr_info,
+        raise QAPILineError(info,
                             "%s requires a string name" % source)
     if name.startswith('*'):
         membername = name[1:]
         if not allow_optional:
-            raise QAPIExprError(expr_info,
+            raise QAPILineError(info,
                                 "%s does not allow optional name '%s'"
                                 % (source, name))
     # Enum members can start with a digit, because the generated C
@@ -397,7 +397,7 @@  def check_name(expr_info, source, name, allow_optional=False,
     # and 'q_obj_*' implicit type names.
     if not valid_name.match(membername) or \
        c_name(membername, False).startswith('q_'):
-        raise QAPIExprError(expr_info,
+        raise QAPILineError(info,
                             "%s uses invalid name '%s'" % (source, name))
 
 
@@ -407,11 +407,11 @@  def add_name(name, info, meta, implicit=False):
     # FIXME should reject names that differ only in '_' vs. '.'
     # vs. '-', because they're liable to clash in generated C.
     if name in all_names:
-        raise QAPIExprError(info,
+        raise QAPILineError(info,
                             "%s '%s' is already defined"
                             % (all_names[name], name))
     if not implicit and (name.endswith('Kind') or name.endswith('List')):
-        raise QAPIExprError(info,
+        raise QAPILineError(info,
                             "%s '%s' should not end in '%s'"
                             % (meta, name, name[-4:]))
     all_names[name] = meta
@@ -465,7 +465,7 @@  def is_enum(name):
     return find_enum(name) is not None
 
 
-def check_type(expr_info, source, value, allow_array=False,
+def check_type(info, source, value, allow_array=False,
                allow_dict=False, allow_optional=False,
                allow_metas=[]):
     global all_names
@@ -476,10 +476,10 @@  def check_type(expr_info, source, value, allow_array=False,
     # Check if array type for value is okay
     if isinstance(value, list):
         if not allow_array:
-            raise QAPIExprError(expr_info,
+            raise QAPILineError(info,
                                 "%s cannot be an array" % source)
         if len(value) != 1 or not isinstance(value[0], str):
-            raise QAPIExprError(expr_info,
+            raise QAPILineError(info,
                                 "%s: array type must contain single type name"
                                 % source)
         value = value[0]
@@ -487,58 +487,58 @@  def check_type(expr_info, source, value, allow_array=False,
     # Check if type name for value is okay
     if isinstance(value, str):
         if value not in all_names:
-            raise QAPIExprError(expr_info,
+            raise QAPILineError(info,
                                 "%s uses unknown type '%s'"
                                 % (source, value))
         if not all_names[value] in allow_metas:
-            raise QAPIExprError(expr_info,
+            raise QAPILineError(info,
                                 "%s cannot use %s type '%s'"
                                 % (source, all_names[value], value))
         return
 
     if not allow_dict:
-        raise QAPIExprError(expr_info,
+        raise QAPILineError(info,
                             "%s should be a type name" % source)
 
     if not isinstance(value, OrderedDict):
-        raise QAPIExprError(expr_info,
+        raise QAPILineError(info,
                             "%s should be a dictionary or type name" % source)
 
     # value is a dictionary, check that each member is okay
     for (key, arg) in value.items():
-        check_name(expr_info, "Member of %s" % source, key,
+        check_name(info, "Member of %s" % source, key,
                    allow_optional=allow_optional)
         if c_name(key, False) == 'u' or c_name(key, False).startswith('has_'):
-            raise QAPIExprError(expr_info,
+            raise QAPILineError(info,
                                 "Member of %s uses reserved name '%s'"
                                 % (source, key))
         # Todo: allow dictionaries to represent default values of
         # an optional argument.
-        check_type(expr_info, "Member '%s' of %s" % (key, source), arg,
+        check_type(info, "Member '%s' of %s" % (key, source), arg,
                    allow_array=True,
                    allow_metas=['built-in', 'union', 'alternate', 'struct',
                                 'enum'])
 
 
-def check_command(expr, expr_info):
+def check_command(expr, info):
     name = expr['command']
     boxed = expr.get('boxed', False)
 
     args_meta = ['struct']
     if boxed:
         args_meta += ['union', 'alternate']
-    check_type(expr_info, "'data' for command '%s'" % name,
+    check_type(info, "'data' for command '%s'" % name,
                expr.get('data'), allow_dict=not boxed, allow_optional=True,
                allow_metas=args_meta)
     returns_meta = ['union', 'struct']
     if name in returns_whitelist:
         returns_meta += ['built-in', 'alternate', 'enum']
-    check_type(expr_info, "'returns' for command '%s'" % name,
+    check_type(info, "'returns' for command '%s'" % name,
                expr.get('returns'), allow_array=True,
                allow_optional=True, allow_metas=returns_meta)
 
 
-def check_event(expr, expr_info):
+def check_event(expr, info):
     global events
     name = expr['event']
     boxed = expr.get('boxed', False)
@@ -547,12 +547,12 @@  def check_event(expr, expr_info):
     if boxed:
         meta += ['union', 'alternate']
     events.append(name)
-    check_type(expr_info, "'data' for event '%s'" % name,
+    check_type(info, "'data' for event '%s'" % name,
                expr.get('data'), allow_dict=not boxed, allow_optional=True,
                allow_metas=meta)
 
 
-def check_union(expr, expr_info):
+def check_union(expr, info):
     name = expr['union']
     base = expr.get('base')
     discriminator = expr.get('discriminator')
@@ -565,18 +565,18 @@  def check_union(expr, expr_info):
         enum_define = None
         allow_metas = ['built-in', 'union', 'alternate', 'struct', 'enum']
         if base is not None:
-            raise QAPIExprError(expr_info,
+            raise QAPILineError(info,
                                 "Simple union '%s' must not have a base"
                                 % name)
 
     # Else, it's a flat union.
     else:
         # The object must have a string or dictionary 'base'.
-        check_type(expr_info, "'base' for union '%s'" % name,
+        check_type(info, "'base' for union '%s'" % name,
                    base, allow_dict=True, allow_optional=True,
                    allow_metas=['struct'])
         if not base:
-            raise QAPIExprError(expr_info,
+            raise QAPILineError(info,
                                 "Flat union '%s' must have a base"
                                 % name)
         base_members = find_base_members(base)
@@ -584,11 +584,11 @@  def check_union(expr, expr_info):
 
         # The value of member 'discriminator' must name a non-optional
         # member of the base struct.
-        check_name(expr_info, "Discriminator of flat union '%s'" % name,
+        check_name(info, "Discriminator of flat union '%s'" % name,
                    discriminator)
         discriminator_type = base_members.get(discriminator)
         if not discriminator_type:
-            raise QAPIExprError(expr_info,
+            raise QAPILineError(info,
                                 "Discriminator '%s' is not a member of base "
                                 "struct '%s'"
                                 % (discriminator, base))
@@ -596,26 +596,26 @@  def check_union(expr, expr_info):
         allow_metas = ['struct']
         # Do not allow string discriminator
         if not enum_define:
-            raise QAPIExprError(expr_info,
+            raise QAPILineError(info,
                                 "Discriminator '%s' must be of enumeration "
                                 "type" % discriminator)
 
     # Check every branch; don't allow an empty union
     if len(members) == 0:
-        raise QAPIExprError(expr_info,
+        raise QAPILineError(info,
                             "Union '%s' cannot have empty 'data'" % name)
     for (key, value) in members.items():
-        check_name(expr_info, "Member of union '%s'" % name, key)
+        check_name(info, "Member of union '%s'" % name, key)
 
         # Each value must name a known type
-        check_type(expr_info, "Member '%s' of union '%s'" % (key, name),
+        check_type(info, "Member '%s' of union '%s'" % (key, name),
                    value, allow_array=not base, allow_metas=allow_metas)
 
         # If the discriminator names an enum type, then all members
         # of 'data' must also be members of the enum type.
         if enum_define:
             if key not in enum_define['enum_values']:
-                raise QAPIExprError(expr_info,
+                raise QAPILineError(info,
                                     "Discriminator value '%s' is not found in "
                                     "enum '%s'" %
                                     (key, enum_define["enum_name"]))
@@ -624,64 +624,64 @@  def check_union(expr, expr_info):
     if enum_define:
         for value in enum_define['enum_values']:
             if value not in members.keys():
-                raise QAPIExprError(expr_info,
+                raise QAPILineError(info,
                                     "Union '%s' data missing '%s' branch"
                                     % (name, value))
 
 
-def check_alternate(expr, expr_info):
+def check_alternate(expr, info):
     name = expr['alternate']
     members = expr['data']
     types_seen = {}
 
     # Check every branch; require at least two branches
     if len(members) < 2:
-        raise QAPIExprError(expr_info,
+        raise QAPILineError(info,
                             "Alternate '%s' should have at least two branches "
                             "in 'data'" % name)
     for (key, value) in members.items():
-        check_name(expr_info, "Member of alternate '%s'" % name, key)
+        check_name(info, "Member of alternate '%s'" % name, key)
 
         # Ensure alternates have no type conflicts.
-        check_type(expr_info, "Member '%s' of alternate '%s'" % (key, name),
+        check_type(info, "Member '%s' of alternate '%s'" % (key, name),
                    value,
                    allow_metas=['built-in', 'union', 'struct', 'enum'])
         qtype = find_alternate_member_qtype(value)
         if not qtype:
-            raise QAPIExprError(expr_info,
+            raise QAPILineError(info,
                                 "Alternate '%s' member '%s' cannot use "
                                 "type '%s'" % (name, key, value))
         if qtype in types_seen:
-            raise QAPIExprError(expr_info,
+            raise QAPILineError(info,
                                 "Alternate '%s' member '%s' can't "
                                 "be distinguished from member '%s'"
                                 % (name, key, types_seen[qtype]))
         types_seen[qtype] = key
 
 
-def check_enum(expr, expr_info):
+def check_enum(expr, info):
     name = expr['enum']
     members = expr.get('data')
     prefix = expr.get('prefix')
 
     if not isinstance(members, list):
-        raise QAPIExprError(expr_info,
+        raise QAPILineError(info,
                             "Enum '%s' requires an array for 'data'" % name)
     if prefix is not None and not isinstance(prefix, str):
-        raise QAPIExprError(expr_info,
+        raise QAPILineError(info,
                             "Enum '%s' requires a string for 'prefix'" % name)
     for member in members:
-        check_name(expr_info, "Member of enum '%s'" % name, member,
+        check_name(info, "Member of enum '%s'" % name, member,
                    enum_member=True)
 
 
-def check_struct(expr, expr_info):
+def check_struct(expr, info):
     name = expr['struct']
     members = expr['data']
 
-    check_type(expr_info, "'data' for struct '%s'" % name, members,
+    check_type(info, "'data' for struct '%s'" % name, members,
                allow_dict=True, allow_optional=True)
-    check_type(expr_info, "'base' for struct '%s'" % name, expr.get('base'),
+    check_type(info, "'base' for struct '%s'" % name, expr.get('base'),
                allow_metas=['struct'])
 
 
@@ -690,25 +690,25 @@  def check_keys(expr_elem, meta, required, optional=[]):
     info = expr_elem['info']
     name = expr[meta]
     if not isinstance(name, str):
-        raise QAPIExprError(info,
+        raise QAPILineError(info,
                             "'%s' key must have a string value" % meta)
     required = required + [meta]
     for (key, value) in expr.items():
         if key not in required and key not in optional:
-            raise QAPIExprError(info,
+            raise QAPILineError(info,
                                 "Unknown key '%s' in %s '%s'"
                                 % (key, meta, name))
         if (key == 'gen' or key == 'success-response') and value is not False:
-            raise QAPIExprError(info,
+            raise QAPILineError(info,
                                 "'%s' of %s '%s' should only use false value"
                                 % (key, meta, name))
         if key == 'boxed' and value is not True:
-            raise QAPIExprError(info,
+            raise QAPILineError(info,
                                 "'%s' of %s '%s' should only use true value"
                                 % (key, meta, name))
     for key in required:
         if key not in expr:
-            raise QAPIExprError(info,
+            raise QAPILineError(info,
                                 "Key '%s' is missing from %s '%s'"
                                 % (key, meta, name))
 
@@ -743,7 +743,7 @@  def check_exprs(exprs):
             check_keys(expr_elem, 'event', [], ['data', 'boxed'])
             add_name(expr['event'], info, 'event')
         else:
-            raise QAPIExprError(expr_elem['info'],
+            raise QAPILineError(expr_elem['info'],
                                 "Expression is missing metatype")
 
     # Try again for hidden UnionKind enum
@@ -978,7 +978,7 @@  class QAPISchemaObjectType(QAPISchemaType):
 
     def check(self, schema):
         if self.members is False:               # check for cycles
-            raise QAPIExprError(self.info,
+            raise QAPILineError(self.info,
                                 "Object %s contains itself" % self.name)
         if self.members:
             return
@@ -1051,10 +1051,10 @@  class QAPISchemaMember(object):
     def check_clash(self, info, seen):
         cname = c_name(self.name)
         if cname.lower() != cname and self.owner not in case_whitelist:
-            raise QAPIExprError(info,
+            raise QAPILineError(info,
                                 "%s should not use uppercase" % self.describe())
         if cname in seen:
-            raise QAPIExprError(info,
+            raise QAPILineError(info,
                                 "%s collides with %s"
                                 % (self.describe(), seen[cname].describe()))
         seen[cname] = self
@@ -1201,13 +1201,13 @@  class QAPISchemaCommand(QAPISchemaEntity):
             self.arg_type.check(schema)
             if self.boxed:
                 if self.arg_type.is_empty():
-                    raise QAPIExprError(self.info,
+                    raise QAPILineError(self.info,
                                         "Cannot use 'boxed' with empty type")
             else:
                 assert not isinstance(self.arg_type, QAPISchemaAlternateType)
                 assert not self.arg_type.variants
         elif self.boxed:
-            raise QAPIExprError(self.info,
+            raise QAPILineError(self.info,
                                 "Use of 'boxed' requires 'data'")
         if self._ret_type_name:
             self.ret_type = schema.lookup_type(self._ret_type_name)
@@ -1235,13 +1235,13 @@  class QAPISchemaEvent(QAPISchemaEntity):
             self.arg_type.check(schema)
             if self.boxed:
                 if self.arg_type.is_empty():
-                    raise QAPIExprError(self.info,
+                    raise QAPILineError(self.info,
                                         "Cannot use 'boxed' with empty type")
             else:
                 assert not isinstance(self.arg_type, QAPISchemaAlternateType)
                 assert not self.arg_type.variants
         elif self.boxed:
-            raise QAPIExprError(self.info,
+            raise QAPILineError(self.info,
                                 "Use of 'boxed' requires 'data'")
 
     def visit(self, visitor):
@@ -1258,7 +1258,7 @@  class QAPISchema(object):
             self._predefining = False
             self._def_exprs()
             self.check()
-        except (QAPISchemaError, QAPIExprError) as err:
+        except (QAPISchemaError, QAPILineError) as err:
             print >>sys.stderr, err
             exit(1)