pyloxi: slightly generalize alignment

The _pack and _unpack templates should not be matching on particular class
names. Move the decision up a few levels to codegen.
diff --git a/py_gen/codegen.py b/py_gen/codegen.py
index 4e93c4c..6570938 100644
--- a/py_gen/codegen.py
+++ b/py_gen/codegen.py
@@ -35,7 +35,8 @@
 from loxi_ir import *
 
 PyOFClass = namedtuple('PyOFClass', ['name', 'pyname', 'members', 'type_members',
-                                     'min_length', 'is_fixed_length'])
+                                     'min_length', 'is_fixed_length',
+                                     'has_internal_alignment', 'has_external_alignment'])
 
 # Return the name for the generated Python class
 def generate_pyname(cls):
@@ -92,7 +93,9 @@
                       members=members,
                       type_members=type_members,
                       min_length=of_g.base_length[(cls, version)],
-                      is_fixed_length=(cls, version) in of_g.is_fixed_length))
+                      is_fixed_length=(cls, version) in of_g.is_fixed_length,
+                      has_internal_alignment=cls == 'of_action_set_field',
+                      has_external_alignment=cls == 'of_match_v3'))
     return ofclasses
 
 def generate_init(out, name, version):
diff --git a/py_gen/templates/_pack.py b/py_gen/templates/_pack.py
index 534e930..9956cf6 100644
--- a/py_gen/templates/_pack.py
+++ b/py_gen/templates/_pack.py
@@ -56,12 +56,12 @@
 :: #endfor
 :: if length_member_index != None:
         length = sum([len(x) for x in packed])
-:: if ofclass.name == 'of_action_set_field':
+:: if ofclass.has_internal_alignment:
         packed.append(loxi.generic_util.pad_to(8, length))
         length += len(packed[-1])
 :: #endif
         packed[${length_member_index}] = ${gen_pack_expr(length_member.oftype, 'length')}
 :: #endif
-:: if ofclass.name == 'of_match_v3':
+:: if ofclass.has_external_alignment:
         packed.append(loxi.generic_util.pad_to(8, length))
 :: #endif
diff --git a/py_gen/templates/_unpack.py b/py_gen/templates/_unpack.py
index 133e831..09a0e08 100644
--- a/py_gen/templates/_unpack.py
+++ b/py_gen/templates/_unpack.py
@@ -53,6 +53,6 @@
         obj.${m.name} = ${gen_unpack_expr(m.oftype, reader_expr)}
 ::     #endif
 :: #endfor
-:: if ofclass.name == 'of_match_v3':
-        reader.skip((_length + 7)/8*8 - _length)
+:: if ofclass.has_external_alignment or ofclass.has_internal_alignment:
+        reader.skip_align()
 :: #endif
diff --git a/py_gen/templates/generic_util.py b/py_gen/templates/generic_util.py
index eca828c..28d3b5f 100644
--- a/py_gen/templates/generic_util.py
+++ b/py_gen/templates/generic_util.py
@@ -109,6 +109,12 @@
             raise loxi.ProtocolError("Buffer too short")
         self.offset += length
 
+    def skip_align(self):
+        new_offset = (self.offset + 7) / 8 * 8
+        if new_offset > len(self.buf):
+            raise loxi.ProtocolError("Buffer too short")
+        self.offset = new_offset
+
     def is_empty(self):
         return self.offset == len(self.buf)