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()