def test_caching(self): # SETUP data = StringIO(ZOGGERY_PROTO_SPEC) ppp = StringProtoSpecParser(data) # data should be file-like self.str_obj_model = ppp.parse() # object model from string serialization self.proto_name = self.str_obj_model.name # the dotted name of the protocol # END SETUp self.assertTrue(isinstance(self.str_obj_model, M.ProtoSpec)) msg_spec = self.str_obj_model.msgs[0] name = msg_spec.name cls0 = make_msg_class(self.str_obj_model, name) cls1 = make_msg_class(self.str_obj_model, name) # we cache classe, so the two should be the same self.assertEqual(id(cls0), id(cls1)) # chan = Channel(BUFSIZE) values = self.le_msg_values() le_msg0 = cls0(values) le_msg1 = cls0(values) # we don't cache instances, so these will differ self.assertNotEqual(id(le_msg0), id(le_msg1)) field_spec = msg_spec[0] dotted_name = "%s.%s" % (self.proto_name, msg_spec.name) f0cls = make_field_class(dotted_name, field_spec) f1cls = make_field_class(dotted_name, field_spec) self.assertEqual(id(f0cls), id(f1cls))
def check_field_impl_against_spec(self, proto_name, msg_name, # not actually tested field_spec, value): # significant for tests self.assertIsNotNone(field_spec) dotted_name = "%s.%s" % (proto_name, msg_name) cls = make_field_class(dotted_name, field_spec) # a class if '__dict__' in dir(cls): print('\nGENERATED FieldImpl CLASS DICTIONARY') for exc in list(cls.__dict__.keys()): print(" %-20s %s" % (exc, cls.__dict__[exc])) self.assertIsNotNone(cls) file = cls(value) # an instance self.assertIsNotNone(file) self.assertTrue(isinstance(file, cls)) # instance attributes ----------------------------- # we verify that the properties work correctly self.assertEqual(field_spec.name, file._name) self.assertEqual(field_spec.field_type_ndx, file.field_type) self.assertEqual(field_spec.quantifier, file.quantifier) self.assertEqual(field_spec.field_nbr, file.field_nbr) self.assertIsNone(file.default) # not an elegant test # instance attribute ------------------------------ # we can read back the value assigned to the instance self.assertEqual(value, file.value) # with slots enabled, this is never seen ---------- # because __dict__ is not in the list of valid # attributes for f if '__dict__' in dir(file): print('\nGENERATED FieldImpl INSTANCE DICTIONARY') for item in list(file.__dict__.keys()): print("%-20s %s" % (item, file.__dict__[item]))
def _make_msg_class(parent, msg_spec): """ construct a MsgClass given a MsgSpec """ if parent is None: raise ValueError('parent must be specified') proto_name = parent.name if msg_spec is None: raise ValueError('msgSpec be specified') # XXX single-dot name and so NO NESTED MSG_CLASSes qual_name = '%s.%s' % (proto_name, msg_spec.name) # DEBUG print('MAKE_MSG_CLASS for %s' % qual_name) # END if qual_name in MSG_CLS_BY_Q_NAME: return MSG_CLS_BY_Q_NAME[qual_name] # build list of field classes ----------------------------------- field_classes = [] field_classes_by_name = {} field_classes_by_nbr = {} # by field nbr, not index # XXX implicit assumption is that fields are ordered by ascending # XXX field number for field_spec in msg_spec: # XXX NO ALLOWANCE FOR NESTED MSG_SPEC cls = make_field_class(qual_name, field_spec) field_classes.append(cls) field_classes_by_name['%s.%s' % (qual_name, field_spec.name)] = cls field_classes_by_nbr[field_spec.field_nbr] = cls # class is not in cache, so construct --------------------------- _enums = [] _msgs = [] class Msg(MsgImpl, metaclass=MetaMsg, # __init__ = msgInitter, # 'name' already in use? _name=msg_spec.name, enums=property(my_enums), msgs=property(my_msgs), field_classes=property(my_field_classes), # EXPERIMENT 2012-12-15 parent_spec=parent, msg_spec=msg_spec # END EXPERIMENT ): pass # DEBUG ===================================== print("MSG_IMPL DICTIONARY:") for key in Msg.__dict__: print(" %-16s => %s" % (key, Msg.__dict__[key])) # END ======================================= # DEBUG print("\n_make_msg_class returning something of type ", type(Msg)) # END #---------------------------- # possibly some more fiddling ... #---------------------------- MSG_CLS_BY_Q_NAME[qual_name] = Msg return Msg