pyloxi: include all members in OFClass.members

This preserves ordering, which is important because we can't rely on the offset
field for sorting (it may be -1).

The newly passing show() tests are due to the side effect of removing type
fields from pretty printing.
diff --git a/py_gen/codegen.py b/py_gen/codegen.py
index 9765815..45adc5d 100644
--- a/py_gen/codegen.py
+++ b/py_gen/codegen.py
@@ -32,8 +32,7 @@
 import util
 import oftype
 
-OFClass = namedtuple('OFClass', ['name', 'pyname',
-                                 'members', 'length_member', 'type_members',
+OFClass = namedtuple('OFClass', ['name', 'pyname', 'members', 'type_members',
                                  'min_length', 'is_fixed_length'])
 Member = namedtuple('Member', ['name', 'oftype', 'offset', 'skip'])
 LengthMember = namedtuple('LengthMember', ['name', 'oftype', 'offset'])
@@ -102,23 +101,22 @@
 
         type_values = get_type_values(cls, version)
         members = []
-
-        length_member = None
         type_members = []
+
         pad_count = 0
 
         for member in unified_class['members']:
             if member['name'] in ['length', 'len']:
-                length_member = LengthMember(name=member['name'],
-                                             offset=member['offset'],
-                                             oftype=oftype.OFType(member['m_type'], version))
+                members.append(LengthMember(name=member['name'],
+                                            offset=member['offset'],
+                                            oftype=oftype.OFType(member['m_type'], version)))
             elif member['name'] in type_values:
-                type_members.append(TypeMember(name=member['name'],
-                                               offset=member['offset'],
-                                               oftype=oftype.OFType(member['m_type'], version),
-                                               value=type_values[member['name']]))
-            else:
-                # HACK ensure member names are unique
+                members.append(TypeMember(name=member['name'],
+                                          offset=member['offset'],
+                                          oftype=oftype.OFType(member['m_type'], version),
+                                          value=type_values[member['name']]))
+                type_members.append(members[-1])
+            else: # HACK ensure member names are unique
                 if member['name'].startswith("pad"):
                     if pad_count == 0:
                         m_name = 'pad'
@@ -136,7 +134,6 @@
             OFClass(name=cls,
                     pyname=pyname,
                     members=members,
-                    length_member=length_member,
                     type_members=type_members,
                     min_length=of_g.base_length[(cls, version)],
                     is_fixed_length=(cls, version) in of_g.is_fixed_length))
diff --git a/py_gen/templates/_ofclass.py b/py_gen/templates/_ofclass.py
index ff8b21b..03fe837 100644
--- a/py_gen/templates/_ofclass.py
+++ b/py_gen/templates/_ofclass.py
@@ -1,11 +1,12 @@
-:: nonskip_members = [m for m in ofclass.members if not m.skip]
+:: from py_gen.codegen import Member, LengthMember, TypeMember
+:: normal_members = [m for m in ofclass.members if type(m) == Member and not m.skip]
 class ${ofclass.pyname}(${superclass}):
 :: for m in ofclass.type_members:
     ${m.name} = ${m.value}
 :: #endfor
 
-    def __init__(${', '.join(['self'] + ["%s=None" % m.name for m in nonskip_members])}):
-:: for m in nonskip_members:
+    def __init__(${', '.join(['self'] + ["%s=None" % m.name for m in normal_members])}):
+:: for m in normal_members:
         if ${m.name} != None:
             self.${m.name} = ${m.name}
         else:
@@ -26,7 +27,7 @@
 
     def __eq__(self, other):
         if type(self) != type(other): return False
-:: for m in nonskip_members:
+:: for m in normal_members:
         if self.${m.name} != other.${m.name}: return False
 :: #endfor
         return True
diff --git a/py_gen/templates/_pack.py b/py_gen/templates/_pack.py
index 0d50a38..15645ee 100644
--- a/py_gen/templates/_pack.py
+++ b/py_gen/templates/_pack.py
@@ -26,14 +26,13 @@
 :: # under the EPL.
 ::
 :: # TODO coalesce format strings
-:: all_members = ofclass.members[:]
-:: if ofclass.length_member: all_members.append(ofclass.length_member)
-:: all_members.extend(ofclass.type_members)
-:: all_members.sort(key=lambda x: x.offset)
+:: from py_gen.codegen import Member, LengthMember, TypeMember
+:: length_member = None
 :: length_member_index = None
 :: index = 0
-:: for m in all_members:
-::     if m == ofclass.length_member:
+:: for m in ofclass.members:
+::     if type(m) == LengthMember:
+::         length_member = m
 ::         length_member_index = index
         packed.append(${m.oftype.gen_pack_expr('0')}) # placeholder for ${m.name} at index ${length_member_index}
 ::     else:
@@ -43,5 +42,5 @@
 :: #endfor
 :: if length_member_index != None:
         length = sum([len(x) for x in packed])
-        packed[${length_member_index}] = ${ofclass.length_member.oftype.gen_pack_expr('length')}
+        packed[${length_member_index}] = ${length_member.oftype.gen_pack_expr('length')}
 :: #endif
diff --git a/py_gen/templates/_pretty_print.py b/py_gen/templates/_pretty_print.py
index 604cd94..5d5edee 100644
--- a/py_gen/templates/_pretty_print.py
+++ b/py_gen/templates/_pretty_print.py
@@ -29,9 +29,10 @@
         with q.group():
             with q.indent(2):
                 q.breakable()
+:: from py_gen.codegen import Member, LengthMember, TypeMember
+:: normal_members = [m for m in ofclass.members if type(m) == Member and not m.skip]
 :: first = True
-:: for m in ofclass.members:
-:: if m.name == 'actions_len': continue
+:: for m in normal_members:
 :: if not first:
                 q.text(","); q.breakable()
 :: else:
diff --git a/py_gen/templates/_unpack.py b/py_gen/templates/_unpack.py
index 173ebb5..6003725 100644
--- a/py_gen/templates/_unpack.py
+++ b/py_gen/templates/_unpack.py
@@ -26,13 +26,10 @@
 :: # under the EPL.
 ::
 :: # TODO coalesce format strings
-:: all_members = ofclass.members[:]
-:: if ofclass.length_member: all_members.append(ofclass.length_member)
-:: all_members.extend(ofclass.type_members)
-:: all_members.sort(key=lambda x: x.offset)
-:: for m in all_members:
+:: from py_gen.codegen import Member, LengthMember, TypeMember
+:: for m in ofclass.members:
 ::     unpack_expr = m.oftype.gen_unpack_expr('buf', m.offset)
-::     if m == ofclass.length_member:
+::     if type(m) == LengthMember:
         _length = ${unpack_expr}
         assert(_length == len(buf))
 :: if ofclass.is_fixed_length:
@@ -40,7 +37,7 @@
 :: else:
         if _length < ${ofclass.min_length}: raise loxi.ProtocolError("${ofclass.pyname} length is %d, should be at least ${ofclass.min_length}" % _length)
 :: #endif
-::     elif m in ofclass.type_members:
+::     elif type(m) == TypeMember:
         ${m.name} = ${unpack_expr}
         assert(${m.name} == ${m.value})
 ::     else:
diff --git a/py_gen/templates/message.py b/py_gen/templates/message.py
index de8fb86..8eb051d 100644
--- a/py_gen/templates/message.py
+++ b/py_gen/templates/message.py
@@ -44,15 +44,17 @@
     xid = None
 
 :: for ofclass in ofclasses:
-:: nonskip_members = [m for m in ofclass.members if not m.skip]
+:: from py_gen.codegen import Member, LengthMember, TypeMember
+:: normal_members = [m for m in ofclass.members if type(m) == Member and not m.skip]
+:: type_members = [m for m in ofclass.members if type(m) == TypeMember]
 class ${ofclass.pyname}(Message):
-:: for m in ofclass.type_members:
+:: for m in type_members:
     ${m.name} = ${m.value}
 :: #endfor
 
-    def __init__(self, ${', '.join(["%s=None" % m.name for m in nonskip_members])}):
+    def __init__(self, ${', '.join(["%s=None" % m.name for m in normal_members])}):
         self.xid = xid
-:: for m in [x for x in nonskip_members if x.name != 'xid']:
+:: for m in [x for x in normal_members if x.name != 'xid']:
         if ${m.name} != None:
             self.${m.name} = ${m.name}
         else:
@@ -83,7 +85,7 @@
         if type(self) != type(other): return False
         if self.version != other.version: return False
         if self.type != other.type: return False
-:: for m in nonskip_members:
+:: for m in normal_members:
         if self.${m.name} != other.${m.name}: return False
 :: #endfor
         return True
diff --git a/py_gen/templates/oxm.py b/py_gen/templates/oxm.py
index c210874..14ea259 100644
--- a/py_gen/templates/oxm.py
+++ b/py_gen/templates/oxm.py
@@ -41,14 +41,16 @@
     pass
 
 :: for ofclass in ofclasses:
-:: nonskip_members = [m for m in ofclass.members if not m.skip]
+:: from py_gen.codegen import Member, LengthMember, TypeMember
+:: normal_members = [m for m in ofclass.members if type(m) == Member and not m.skip]
+:: type_members = [m for m in ofclass.members if type(m) == TypeMember]
 class ${ofclass.pyname}(OXM):
-:: for m in ofclass.type_members:
+:: for m in type_members:
     ${m.name} = ${m.value}
 :: #endfor
 
-    def __init__(self, ${', '.join(["%s=None" % m.name for m in nonskip_members])}):
-:: for m in nonskip_members:
+    def __init__(self, ${', '.join(["%s=None" % m.name for m in normal_members])}):
+:: for m in normal_members:
         if ${m.name} != None:
             self.${m.name} = ${m.name}
         else:
@@ -68,7 +70,7 @@
 
     def __eq__(self, other):
         if type(self) != type(other): return False
-:: for m in nonskip_members:
+:: for m in normal_members:
         if self.${m.name} != other.${m.name}: return False
 :: #endfor
         return True
diff --git a/py_gen/tests/of11.py b/py_gen/tests/of11.py
index 017043f..c36e0f5 100644
--- a/py_gen/tests/of11.py
+++ b/py_gen/tests/of11.py
@@ -109,16 +109,6 @@
     def test_show(self):
         expected_failures = [
             ofp.common.flow_stats_entry,
-            ofp.common.group_desc_stats_entry,
-            ofp.common.instruction,
-            ofp.common.instruction_apply_actions,
-            ofp.common.instruction_clear_actions,
-            ofp.common.instruction_experimenter,
-            ofp.common.instruction_goto_table,
-            ofp.common.instruction_header,
-            ofp.common.instruction_write_actions,
-            ofp.common.instruction_write_metadata,
-            ofp.common.match_v2,
             ofp.message.aggregate_stats_request,
             ofp.message.flow_add,
             ofp.message.flow_delete,
diff --git a/py_gen/tests/of12.py b/py_gen/tests/of12.py
index 9c55db2..2f144b5 100644
--- a/py_gen/tests/of12.py
+++ b/py_gen/tests/of12.py
@@ -147,16 +147,6 @@
     def test_show(self):
         expected_failures = [
             ofp.common.flow_stats_entry,
-            ofp.common.group_desc_stats_entry,
-            ofp.common.instruction,
-            ofp.common.instruction_apply_actions,
-            ofp.common.instruction_clear_actions,
-            ofp.common.instruction_experimenter,
-            ofp.common.instruction_goto_table,
-            ofp.common.instruction_header,
-            ofp.common.instruction_write_actions,
-            ofp.common.instruction_write_metadata,
-            ofp.common.match_v3,
             ofp.common.table_stats_entry,
             ofp.message.aggregate_stats_request,
             ofp.message.flow_add,
diff --git a/py_gen/tests/of13.py b/py_gen/tests/of13.py
index 638e61d..ab1b4d6 100644
--- a/py_gen/tests/of13.py
+++ b/py_gen/tests/of13.py
@@ -222,73 +222,7 @@
                 fn()
 
     def test_show(self):
-        expected_failures = [
-            ofp.common.action_id,
-            ofp.common.action_id_bsn_mirror,
-            ofp.common.action_id_bsn_set_tunnel_dst,
-            ofp.common.action_id_copy_ttl_in,
-            ofp.common.action_id_copy_ttl_out,
-            ofp.common.action_id_dec_mpls_ttl,
-            ofp.common.action_id_dec_nw_ttl,
-            ofp.common.action_id_experimenter,
-            ofp.common.action_id_group,
-            ofp.common.action_id_header,
-            ofp.common.action_id_nicira_dec_ttl,
-            ofp.common.action_id_output,
-            ofp.common.action_id_pop_mpls,
-            ofp.common.action_id_pop_pbb,
-            ofp.common.action_id_pop_vlan,
-            ofp.common.action_id_push_mpls,
-            ofp.common.action_id_push_pbb,
-            ofp.common.action_id_push_vlan,
-            ofp.common.action_id_set_field,
-            ofp.common.action_id_set_mpls_ttl,
-            ofp.common.action_id_set_nw_ttl,
-            ofp.common.action_id_set_queue,
-            ofp.common.flow_stats_entry,
-            ofp.common.group_desc_stats_entry,
-            ofp.common.instruction,
-            ofp.common.instruction_apply_actions,
-            ofp.common.instruction_clear_actions,
-            ofp.common.instruction_experimenter,
-            ofp.common.instruction_goto_table,
-            ofp.common.instruction_header,
-            ofp.common.instruction_meter,
-            ofp.common.instruction_write_actions,
-            ofp.common.instruction_write_metadata,
-            ofp.common.match_v3,
-            ofp.common.meter_band,
-            ofp.common.meter_band_drop,
-            ofp.common.meter_band_dscp_remark,
-            ofp.common.meter_band_experimenter,
-            ofp.common.meter_band_header,
-            ofp.common.table_feature_prop,
-            ofp.common.table_feature_prop_apply_actions,
-            ofp.common.table_feature_prop_apply_actions_miss,
-            ofp.common.table_feature_prop_apply_setfield,
-            ofp.common.table_feature_prop_apply_setfield_miss,
-            ofp.common.table_feature_prop_experimenter,
-            ofp.common.table_feature_prop_header,
-            ofp.common.table_feature_prop_instructions,
-            ofp.common.table_feature_prop_instructions_miss,
-            ofp.common.table_feature_prop_match,
-            ofp.common.table_feature_prop_next_tables,
-            ofp.common.table_feature_prop_next_tables_miss,
-            ofp.common.table_feature_prop_wildcards,
-            ofp.common.table_feature_prop_write_actions,
-            ofp.common.table_feature_prop_write_actions_miss,
-            ofp.common.table_feature_prop_write_setfield,
-            ofp.common.table_feature_prop_write_setfield_miss,
-            ofp.message.aggregate_stats_request,
-            ofp.message.flow_add,
-            ofp.message.flow_delete,
-            ofp.message.flow_delete_strict,
-            ofp.message.flow_modify,
-            ofp.message.flow_modify_strict,
-            ofp.message.flow_removed,
-            ofp.message.flow_stats_request,
-            ofp.message.packet_in,
-        ]
+        expected_failures = []
         for klass in self.klasses:
             def fn():
                 obj = klass()