[Mesa-dev] [PATCH] mapi/glapi: Use ElementTree instead of libxml2.

Ian Romanick idr at freedesktop.org
Tue Mar 25 16:34:34 PDT 2014


On 03/25/2014 09:34 AM, jfonseca at vmware.com wrote:
> From: José Fonseca <jfonseca at vmware.com>
> 
> It is quite hard to meet the dependency of the libxml2 python bindings
> out side Linux, and in particularly on MacOSX; whereas ElementTree is
> part of Python's standard library.  ElementTree is more limited than
> libxml2: no DTD verification, defaults from DTD, or XInclude support,
> but none of this limitations is serious enough to justify libxml2.
> 
> In fact, it was easier to refactor the code to use ElementTree than to
> try to get libxml2 python bindings...
> 
> In the process, gl_item_factory class was refactored so that there is
> one method for each kind of object to be created, as it simplified
> things substantially.

glx_doc_item_factory (glX_doc.py) derives from glx_item_factory, and
glX_proto_recv.py uses glx_item_factory.  It doesn't look like
glX_proto_recv.py should make any difference, but glX_doc.py is probably
broken now.  I had to look up WTF glX_doc.py is by 'git log --follow'...
and apparently I wrote it. :)  I doubt it has been used by anyone in
many years, so the right fix is probably 'git rm'.

However you decided to deal with glX_doc.py, the series that includes
that fix is

Reviewed-by: Ian Romanick <ian.d.romanick at intel.com>

> I confirmed that precisely the same output is generated for GL/GLX/GLES.
> ---
>  SConstruct                             |   7 --
>  configure.ac                           |   1 -
>  docs/README.WIN32                      |  16 ++-
>  docs/install.html                      |   4 -
>  src/mapi/glapi/gen/glX_XML.py          |  55 ++++-----
>  src/mapi/glapi/gen/glX_proto_common.py |  13 +-
>  src/mapi/glapi/gen/gl_XML.py           | 217 ++++++++++++++++-----------------
>  7 files changed, 141 insertions(+), 172 deletions(-)
> 
> diff --git a/SConstruct b/SConstruct
> index de735e9..0e10818 100644
> --- a/SConstruct
> +++ b/SConstruct
> @@ -59,13 +59,6 @@ else:
>  
>  Help(opts.GenerateHelpText(env))
>  
> -# fail early for a common error on windows
> -if env['gles']:
> -    try:
> -        import libxml2
> -    except ImportError:
> -        raise SCons.Errors.UserError, "GLES requires libxml2-python to build"
> -
>  #######################################################################
>  # Environment setup
>  
> diff --git a/configure.ac b/configure.ac
> index c5042f9..04bf711 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -54,7 +54,6 @@ AM_PROG_CC_C_O
>  AM_PROG_AS
>  AC_CHECK_PROGS([MAKE], [gmake make])
>  AC_CHECK_PROGS([PYTHON2], [python2 python])
> -AX_PYTHON_MODULE([libxml2], [needed])
>  AC_PROG_SED
>  AC_PROG_MKDIR_P
>  
> diff --git a/docs/README.WIN32 b/docs/README.WIN32
> index 0cd007c..c8759f6 100644
> --- a/docs/README.WIN32
> +++ b/docs/README.WIN32
> @@ -36,17 +36,15 @@ Recipe
>  Building on windows requires several open-source packages. These are
>  steps that work as of this writing.
>  
> -1) install python 2.7
> -2) install scons (latest)
> -3) install mingw, flex, and bison
> -4) install libxml2 from here: http://www.lfd.uci.edu/~gohlke/pythonlibs
> -  get libxml2-python-2.9.1.win-amd64-py2.7.exe
> -5) install pywin32 from here: http://www.lfd.uci.edu/~gohlke/pythonlibs
> +- install python 2.7
> +- install scons (latest)
> +- install mingw, flex, and bison
> +- install pywin32 from here: http://www.lfd.uci.edu/~gohlke/pythonlibs
>    get pywin32-218.4.win-amd64-py2.7.exe
> -6) install git
> -7) download mesa from git
> +- install git
> +- download mesa from git
>    see http://www.mesa3d.org/repository.html
> -8) run scons
> +- run scons
>  
>  General
>  -------
> diff --git a/docs/install.html b/docs/install.html
> index 24492a7..5061ede 100644
> --- a/docs/install.html
> +++ b/docs/install.html
> @@ -44,10 +44,6 @@ On Windows with MinGW, install flex and bison with:
>  </li>
>  <li>python - Python is needed for building the Gallium components.
>  Version 2.6.4 or later should work.
> -<br>
> -<br>
> -To build OpenGL ES 1.1 and 2.0 you'll also need
> -<a href="http://xmlsoft.org/sources/win32/python/libxml2-python-2.7.7.win32-py2.7.exe">libxml2-python</a>.
>  </li>
>  </ul>
>  
> diff --git a/src/mapi/glapi/gen/glX_XML.py b/src/mapi/glapi/gen/glX_XML.py
> index 03a35b7..12ff291 100644
> --- a/src/mapi/glapi/gen/glX_XML.py
> +++ b/src/mapi/glapi/gen/glX_XML.py
> @@ -33,29 +33,27 @@ import sys, getopt, string
>  class glx_item_factory(gl_XML.gl_item_factory):
>      """Factory to create GLX protocol oriented objects derived from gl_item."""
>  
> -    def create_item(self, name, element, context):
> -        if name == "function":
> -            return glx_function(element, context)
> -        elif name == "enum":
> -            return glx_enum(element, context)
> -        elif name == "api":
> -            return glx_api(self)
> -        else:
> -            return gl_XML.gl_item_factory.create_item(self, name, element, context)
> +    def create_function(self, element, context):
> +        return glx_function(element, context)
> +
> +    def create_enum(self, element, context, category):
> +        return glx_enum(element, context, category)
> +
> +    def create_api(self):
> +        return glx_api(self)
>  
>  
>  class glx_enum(gl_XML.gl_enum):
> -    def __init__(self, element, context):
> -        gl_XML.gl_enum.__init__(self, element, context)
> +    def __init__(self, element, context, category):
> +        gl_XML.gl_enum.__init__(self, element, context, category)
>  
>          self.functions = {}
>  
> -        child = element.children
> -        while child:
> -            if child.type == "element" and child.name == "size":
> -                n = child.nsProp( "name", None )
> -                c = child.nsProp( "count", None )
> -                m = child.nsProp( "mode", None )
> +        for child in element.getchildren():
> +            if child.tag == "size":
> +                n = child.get( "name" )
> +                c = child.get( "count" )
> +                m = child.get( "mode", "set" )
>  
>                  if not c:
>                      c = self.default_count
> @@ -70,8 +68,6 @@ class glx_enum(gl_XML.gl_enum):
>                  if not self.functions.has_key(n):
>                      self.functions[ n ] = [c, mode]
>  
> -            child = child.next
> -
>          return
>  
>  
> @@ -120,10 +116,10 @@ class glx_function(gl_XML.gl_function):
>          # appears after the function that it aliases.
>  
>          if not self.vectorequiv:
> -            self.vectorequiv = element.nsProp("vectorequiv", None)
> +            self.vectorequiv = element.get("vectorequiv")
>  
>  
> -        name = element.nsProp("name", None)
> +        name = element.get("name")
>          if name == self.name:
>              for param in self.parameters:
>                  self.parameters_by_name[ param.name ] = param
> @@ -135,12 +131,11 @@ class glx_function(gl_XML.gl_function):
>                      self.counter_list.append(param.counter)
>  
>  
> -        child = element.children
> -        while child:
> -            if child.type == "element" and child.name == "glx":
> -                rop = child.nsProp( 'rop', None )
> -                sop = child.nsProp( 'sop', None )
> -                vop = child.nsProp( 'vendorpriv', None )
> +        for child in element.getchildren():
> +            if child.tag == "glx":
> +                rop = child.get( 'rop' )
> +                sop = child.get( 'sop' )
> +                vop = child.get( 'vendorpriv' )
>  
>                  if rop:
>                      self.glx_rop = int(rop)
> @@ -152,12 +147,12 @@ class glx_function(gl_XML.gl_function):
>                      self.glx_vendorpriv = int(vop)
>                      self.glx_vendorpriv_names.append(name)
>  
> -                self.img_reset = child.nsProp( 'img_reset', None )
> +                self.img_reset = child.get( 'img_reset' )
>  
>                  # The 'handcode' attribute can be one of 'true',
>                  # 'false', 'client', or 'server'.
>  
> -                handcode = child.nsProp( 'handcode', None )
> +                handcode = child.get( 'handcode', 'false' )
>                  if handcode == "false":
>                      self.server_handcode = 0
>                      self.client_handcode = 0
> @@ -179,8 +174,6 @@ class glx_function(gl_XML.gl_function):
>                  self.reply_always_array   = gl_XML.is_attr_true( child, 'always_array' )
>                  self.dimensions_in_reply  = gl_XML.is_attr_true( child, 'dimensions_in_reply' )
>  
> -            child = child.next
> -
>  
>          # Do some validation of the GLX protocol information.  As
>          # new tests are discovered, they should be added here.
> diff --git a/src/mapi/glapi/gen/glX_proto_common.py b/src/mapi/glapi/gen/glX_proto_common.py
> index 86d9189..ae2c2d5 100644
> --- a/src/mapi/glapi/gen/glX_proto_common.py
> +++ b/src/mapi/glapi/gen/glX_proto_common.py
> @@ -32,18 +32,15 @@ import string
>  class glx_proto_item_factory(glX_XML.glx_item_factory):
>      """Factory to create GLX protocol oriented objects derived from gl_item."""
>  
> -    def create_item(self, name, element, context):
> -        if name == "type":
> -            return glx_proto_type(element, context)
> -        else:
> -            return glX_XML.glx_item_factory.create_item(self, name, element, context)
> +    def create_type(self, element, context, category):
> +        return glx_proto_type(element, context, category)
>  
>  
>  class glx_proto_type(gl_XML.gl_type):
> -    def __init__(self, element, context):
> -        gl_XML.gl_type.__init__(self, element, context)
> +    def __init__(self, element, context, category):
> +        gl_XML.gl_type.__init__(self, element, context, category)
>  
> -        self.glx_name = element.nsProp( "glx_name", None )
> +        self.glx_name = element.get( "glx_name" )
>          return
>  
>  
> diff --git a/src/mapi/glapi/gen/gl_XML.py b/src/mapi/glapi/gen/gl_XML.py
> index 3bbc794..1a2bc2b 100644
> --- a/src/mapi/glapi/gen/gl_XML.py
> +++ b/src/mapi/glapi/gen/gl_XML.py
> @@ -26,20 +26,19 @@
>  #    Ian Romanick <idr at us.ibm.com>
>  
>  from decimal import Decimal
> -import libxml2
> +import xml.etree.ElementTree as ET
>  import re, sys, string
> +import os.path
>  import typeexpr
>  
>  
>  def parse_GL_API( file_name, factory = None ):
> -    doc = libxml2.readFile( file_name, None, libxml2.XML_PARSE_XINCLUDE + libxml2.XML_PARSE_NOBLANKS + libxml2.XML_PARSE_DTDVALID + libxml2.XML_PARSE_DTDATTR + libxml2.XML_PARSE_DTDLOAD + libxml2.XML_PARSE_NOENT )
> -    ret = doc.xincludeProcess()
>  
>      if not factory:
>          factory = gl_item_factory()
>  
> -    api = factory.create_item( "api", None, None )
> -    api.process_element( doc )
> +    api = factory.create_api()
> +    api.parse_file( file_name )
>  
>      # After the XML has been processed, we need to go back and assign
>      # dispatch offsets to the functions that request that their offsets
> @@ -51,12 +50,10 @@ def parse_GL_API( file_name, factory = None ):
>              func.offset = api.next_offset;
>              api.next_offset += 1
>  
> -    doc.freeDoc()
> -
>      return api
>  
>  
> -def is_attr_true( element, name ):
> +def is_attr_true( element, name, default = "false" ):
>      """Read a name value from an element's attributes.
>  
>      The value read from the attribute list must be either 'true' or
> @@ -64,7 +61,7 @@ def is_attr_true( element, name ):
>      value is 'true', non-zero will be returned.  An exception will be
>      raised for any other value."""
>  
> -    value = element.nsProp( name, None )
> +    value = element.get( name, default )
>      if value == "true":
>          return 1
>      elif value == "false":
> @@ -254,8 +251,8 @@ class gl_print_base(object):
>  
>  
>  def real_function_name(element):
> -    name = element.nsProp( "name", None )
> -    alias = element.nsProp( "alias", None )
> +    name = element.get( "name" )
> +    alias = element.get( "alias" )
>  
>      if alias:
>          return alias
> @@ -324,21 +321,22 @@ def create_parameter_string(parameters, include_names):
>  
>  
>  class gl_item(object):
> -    def __init__(self, element, context):
> +    def __init__(self, element, context, category):
>          self.context = context
> -        self.name = element.nsProp( "name", None )
> -        self.category = real_category_name( element.parent.nsProp( "name", None ) )
> +        self.name = element.get( "name" )
> +        self.category = real_category_name( category )
> +
>          return
>  
>  
>  class gl_type( gl_item ):
> -    def __init__(self, element, context):
> -        gl_item.__init__(self, element, context)
> -        self.size = int( element.nsProp( "size", None ), 0 )
> +    def __init__(self, element, context, category):
> +        gl_item.__init__(self, element, context, category)
> +        self.size = int( element.get( "size" ), 0 )
>  
>          te = typeexpr.type_expression( None )
>          tn = typeexpr.type_node()
> -        tn.size = int( element.nsProp( "size", None ), 0 )
> +        tn.size = int( element.get( "size" ), 0 )
>          tn.integer = not is_attr_true( element, "float" )
>          tn.unsigned = is_attr_true( element, "unsigned" )
>          tn.pointer = is_attr_true( element, "pointer" )
> @@ -354,11 +352,11 @@ class gl_type( gl_item ):
>  
>  
>  class gl_enum( gl_item ):
> -    def __init__(self, element, context):
> -        gl_item.__init__(self, element, context)
> -        self.value = int( element.nsProp( "value", None ), 0 )
> +    def __init__(self, element, context, category):
> +        gl_item.__init__(self, element, context, category)
> +        self.value = int( element.get( "value" ), 0 )
>  
> -        temp = element.nsProp( "count", None )
> +        temp = element.get( "count" )
>          if not temp or temp == "?":
>              self.default_count = -1
>          else:
> @@ -404,12 +402,12 @@ class gl_enum( gl_item ):
>  
>  class gl_parameter(object):
>      def __init__(self, element, context):
> -        self.name = element.nsProp( "name", None )
> +        self.name = element.get( "name" )
>  
> -        ts = element.nsProp( "type", None )
> +        ts = element.get( "type" )
>          self.type_expr = typeexpr.type_expression( ts, context )
>  
> -        temp = element.nsProp( "variable_param", None )
> +        temp = element.get( "variable_param" )
>          if temp:
>              self.count_parameter_list = temp.split( ' ' )
>          else:
> @@ -420,7 +418,7 @@ class gl_parameter(object):
>          # statement will throw an exception, and the except block will
>          # take over.
>  
> -        c = element.nsProp( "count", None )
> +        c = element.get( "count" )
>          try: 
>              count = int(c)
>              self.count = count
> @@ -430,7 +428,7 @@ class gl_parameter(object):
>              self.count = 0
>              self.counter = c
>  
> -        self.count_scale = int(element.nsProp( "count_scale", None ))
> +        self.count_scale = int(element.get( "count_scale", "1" ))
>  
>          elements = (count * self.count_scale)
>          if elements == 1:
> @@ -450,19 +448,19 @@ class gl_parameter(object):
>  
>          # Pixel data has special parameters.
>  
> -        self.width      = element.nsProp('img_width',  None)
> -        self.height     = element.nsProp('img_height', None)
> -        self.depth      = element.nsProp('img_depth',  None)
> -        self.extent     = element.nsProp('img_extent', None)
> +        self.width      = element.get('img_width')
> +        self.height     = element.get('img_height')
> +        self.depth      = element.get('img_depth')
> +        self.extent     = element.get('img_extent')
>  
> -        self.img_xoff   = element.nsProp('img_xoff',   None)
> -        self.img_yoff   = element.nsProp('img_yoff',   None)
> -        self.img_zoff   = element.nsProp('img_zoff',   None)
> -        self.img_woff   = element.nsProp('img_woff',   None)
> +        self.img_xoff   = element.get('img_xoff')
> +        self.img_yoff   = element.get('img_yoff')
> +        self.img_zoff   = element.get('img_zoff')
> +        self.img_woff   = element.get('img_woff')
>  
> -        self.img_format = element.nsProp('img_format', None)
> -        self.img_type   = element.nsProp('img_type',   None)
> -        self.img_target = element.nsProp('img_target', None)
> +        self.img_format = element.get('img_format')
> +        self.img_type   = element.get('img_type')
> +        self.img_target = element.get('img_target')
>  
>          self.img_pad_dimensions = is_attr_true( element, 'img_pad_dimensions' )
>          self.img_null_flag      = is_attr_true( element, 'img_null_flag' )
> @@ -648,17 +646,17 @@ class gl_function( gl_item ):
>  
>  
>      def process_element(self, element):
> -        name = element.nsProp( "name", None )
> -        alias = element.nsProp( "alias", None )
> +        name = element.get( "name" )
> +        alias = element.get( "alias" )
>  
> -        if is_attr_true(element, "static_dispatch"):
> +        if is_attr_true(element, "static_dispatch", "true"):
>              self.static_entry_points.append(name)
>  
>          self.entry_points.append( name )
>  
>          self.entry_point_api_map[name] = {}
>          for api in ('es1', 'es2'):
> -            version_str = element.nsProp(api, None)
> +            version_str = element.get(api, 'none')
>              assert version_str is not None
>              if version_str != 'none':
>                  version_decimal = Decimal(version_str)
> @@ -667,15 +665,15 @@ class gl_function( gl_item ):
>                          version_decimal < self.api_map[api]:
>                      self.api_map[api] = version_decimal
>  
> -        exec_flavor = element.nsProp('exec', None)
> +        exec_flavor = element.get('exec')
>          if exec_flavor:
>              self.exec_flavor = exec_flavor
>  
> -        deprecated = element.nsProp('deprecated', None)
> +        deprecated = element.get('deprecated', 'none')
>          if deprecated != 'none':
>              self.deprecated = Decimal(deprecated)
>  
> -        if not is_attr_true(element, 'desktop'):
> +        if not is_attr_true(element, 'desktop', 'true'):
>              self.desktop = False
>  
>          if alias:
> @@ -686,7 +684,7 @@ class gl_function( gl_item ):
>              # Only try to set the offset when a non-alias entry-point
>              # is being processed.
>  
> -            offset = element.nsProp( "offset", None )
> +            offset = element.get( "offset" )
>              if offset:
>                  try:
>                      o = int( offset )
> @@ -712,16 +710,12 @@ class gl_function( gl_item ):
>  
>          parameters = []
>          return_type = "void"
> -        child = element.children
> -        while child:
> -            if child.type == "element":
> -                if child.name == "return":
> -                    return_type = child.nsProp( "type", None )
> -                elif child.name == "param":
> -                    param = self.context.factory.create_item( "parameter", child, self.context)
> -                    parameters.append( param )
> -
> -            child = child.next
> +        for child in element.getchildren():
> +            if child.tag == "return":
> +                return_type = child.get( "type", "void" )
> +            elif child.tag == "param":
> +                param = self.context.factory.create_parameter(child, self.context)
> +                parameters.append( param )
>  
>  
>          if self.initialized:
> @@ -746,7 +740,7 @@ class gl_function( gl_item ):
>                  if param.is_image():
>                      self.images.append( param )
>  
> -        if element.children:
> +        if element.getchildren():
>              self.initialized = 1
>              self.entry_point_parameters[name] = parameters
>          else:
> @@ -848,19 +842,20 @@ class gl_function( gl_item ):
>  class gl_item_factory(object):
>      """Factory to create objects derived from gl_item."""
>  
> -    def create_item(self, item_name, element, context):
> -        if item_name == "function":
> -            return gl_function(element, context)
> -        if item_name == "type":
> -            return gl_type(element, context)
> -        elif item_name == "enum":
> -            return gl_enum(element, context)
> -        elif item_name == "parameter":
> -            return gl_parameter(element, context)
> -        elif item_name == "api":
> -            return gl_api(self)
> -        else:
> -            return None
> +    def create_function(self, element, context):
> +        return gl_function(element, context)
> +
> +    def create_type(self, element, context, category):
> +        return gl_type(element, context, category)
> +
> +    def create_enum(self, element, context, category):
> +        return gl_enum(element, context, category)
> +
> +    def create_parameter(self, element, context):
> +        return gl_parameter(element, context)
> +
> +    def create_api(self):
> +        return gl_api(self)
>  
>  
>  class gl_api(object):
> @@ -903,66 +898,64 @@ class gl_api(object):
>  
>          self.functions_by_name = functions_by_name
>  
> -    def process_element(self, doc):
> -        element = doc.children
> -        while element.type != "element" or element.name != "OpenGLAPI":
> -            element = element.next
>  
> -        if element:
> -            self.process_OpenGLAPI(element)
> -        return
> +    def parse_file(self, file_name):
> +        doc = ET.parse( file_name )
> +        self.process_element(file_name, doc)
>  
>  
> -    def process_OpenGLAPI(self, element):
> -        child = element.children
> -        while child:
> -            if child.type == "element":
> -                if child.name == "category":
> -                    self.process_category( child )
> -                elif child.name == "OpenGLAPI":
> -                    self.process_OpenGLAPI( child )
> +    def process_element(self, file_name, doc):
> +        element = doc.getroot()
> +        if element.tag == "OpenGLAPI":
> +            self.process_OpenGLAPI(file_name, element)
> +        return
> +
>  
> -            child = child.next
> +    def process_OpenGLAPI(self, file_name, element):
> +        for child in element.getchildren():
> +            if child.tag == "category":
> +                self.process_category( child )
> +            elif child.tag == "OpenGLAPI":
> +                self.process_OpenGLAPI( file_name, child )
> +            elif child.tag == '{http://www.w3.org/2001/XInclude}include':
> +                href = child.get('href')
> +                href = os.path.join(os.path.dirname(file_name), href)
> +                self.parse_file(href)
>  
>          return
>  
>  
>      def process_category(self, cat):
> -        cat_name = cat.nsProp( "name", None )
> -        cat_number = cat.nsProp( "number", None )
> +        cat_name = cat.get( "name" )
> +        cat_number = cat.get( "number" )
>  
>          [cat_type, key] = classify_category(cat_name, cat_number)
>          self.categories[cat_type][key] = [cat_name, cat_number]
>  
> -        child = cat.children
> -        while child:
> -            if child.type == "element":
> -                if child.name == "function":
> -                    func_name = real_function_name( child )
> -
> -                    temp_name = child.nsProp( "name", None )
> -                    self.category_dict[ temp_name ] = [cat_name, cat_number]
> -
> -                    if self.functions_by_name.has_key( func_name ):
> -                        func = self.functions_by_name[ func_name ]
> -                        func.process_element( child )
> -                    else:
> -                        func = self.factory.create_item( "function", child, self )
> -                        self.functions_by_name[ func_name ] = func
> +        for child in cat.getchildren():
> +            if child.tag == "function":
> +                func_name = real_function_name( child )
>  
> -                    if func.offset >= self.next_offset:
> -                        self.next_offset = func.offset + 1
> +                temp_name = child.get( "name" )
> +                self.category_dict[ temp_name ] = [cat_name, cat_number]
>  
> +                if self.functions_by_name.has_key( func_name ):
> +                    func = self.functions_by_name[ func_name ]
> +                    func.process_element( child )
> +                else:
> +                    func = self.factory.create_function( child, self )
> +                    self.functions_by_name[ func_name ] = func
>  
> -                elif child.name == "enum":
> -                    enum = self.factory.create_item( "enum", child, self )
> -                    self.enums_by_name[ enum.name ] = enum
> -                elif child.name == "type":
> -                    t = self.factory.create_item( "type", child, self )
> -                    self.types_by_name[ "GL" + t.name ] = t
> +                if func.offset >= self.next_offset:
> +                    self.next_offset = func.offset + 1
>  
>  
> -            child = child.next
> +            elif child.tag == "enum":
> +                enum = self.factory.create_enum( child, self, cat_name )
> +                self.enums_by_name[ enum.name ] = enum
> +            elif child.tag == "type":
> +                t = self.factory.create_type( child, self, cat_name )
> +                self.types_by_name[ "GL" + t.name ] = t
>  
>          return
>  
> 



More information about the mesa-dev mailing list