diff --git a/src/commands/default/building.py b/src/commands/default/building.py index a0b65de51..4c8f5ad34 100644 --- a/src/commands/default/building.py +++ b/src/commands/default/building.py @@ -1260,7 +1260,7 @@ class CmdTypeclass(MuxCommand): # we did not supply a new typeclass, view the # current one instead. if hasattr(obj, "typeclass"): - string = "%s's current typeclass is '%s'." % (obj.name, obj.typeclass) + string = "%s's current typeclass is '%s'." % (obj.name, obj.typeclass.typename) else: string = "%s is not a typed object." % obj.name caller.msg(string) @@ -1276,23 +1276,28 @@ class CmdTypeclass(MuxCommand): if not hasattr(obj, 'swap_typeclass') or not hasattr(obj, 'typeclass'): caller.msg("This object cannot have a type at all!") return - - reset = "reset" in self.switches - old_typeclass = obj.typeclass_path - if old_typeclass == typeclass and not 'force' in self.switches: + old_path = obj.typeclass_path + if obj.is_typeclass(typeclass) and not 'force' in self.switches: string = "%s already has the typeclass '%s'." % (obj.name, typeclass) else: - obj.swap_typeclass(typeclass, clean_attributes=reset) - new_typeclass = obj.typeclass - string = "%s's type is now %s (instead of %s).\n" % (obj.name, - new_typeclass, - old_typeclass) - if reset: - string += "All attributes where reset." - else: - string += "Note that the new class type could have overwritten " - string += "same-named attributes on the existing object." + reset = "reset" in self.switches + old_typeclass_name = obj.typeclass.typename + ok = obj.swap_typeclass(typeclass, clean_attributes=reset) + if ok: + string = "%s's type is now %s (instead of %s).\n" % (obj.name, + obj.typeclass.typename, + old_typeclass_name) + if reset: + string += "All attributes where reset." + else: + string += "Note that the new class type could have overwritten " + string += "same-named attributes on the existing object." + else: + string = "Could not swap '%s' (%s) to typeclass '%s'." % (obj.name, + old_typeclass_name, + typeclass) + caller.msg(string) @@ -1555,7 +1560,7 @@ class CmdExamine(ObjManipCommand): elif not perms: perms = [""] string += headers["playerperms"] % (", ".join(perms)) - string += headers["typeclass"] % (obj.typeclass, obj.typeclass_path) + string += headers["typeclass"] % (obj.typeclass.typename, obj.typeclass_path) if hasattr(obj, "location"): string += headers["location"] % obj.location diff --git a/src/commands/default/system.py b/src/commands/default/system.py index ec3f21230..396950c6c 100644 --- a/src/commands/default/system.py +++ b/src/commands/default/system.py @@ -374,7 +374,7 @@ class CmdObjects(MuxCommand): table[0].append(utils.datetime_format(obj.date_created)) table[1].append(obj.dbref) table[2].append(obj.key) - table[3].append(str(obj.typeclass)) + table[3].append(str(obj.typeclass.path)) ftable = utils.format_table(table, 5) for irow, row in enumerate(ftable): srow = "\n" + "".join(row) diff --git a/src/typeclasses/models.py b/src/typeclasses/models.py index c7fdffff6..840d2dd86 100644 --- a/src/typeclasses/models.py +++ b/src/typeclasses/models.py @@ -627,7 +627,7 @@ class TypedObject(SharedMemoryModel): "Setter. Allows for self.typeclass_path = value" self.db_typeclass_path = value self.save() - object.__setattr__(self, "cached_typeclass_path", value) + object.__setattr__(self, 'cached_typeclass_path', value) #@typeclass_path.deleter def typeclass_path_del(self): "Deleter. Allows for del self.typeclass_path" @@ -935,7 +935,7 @@ class TypedObject(SharedMemoryModel): return typeclass and any([current_path == typec for typec in typeclasses]) else: # check parent chain - return any([cls for cls in self.typeclass.mro() + return any([cls for cls in self.typeclass.__class__.mro() if any(["%s.%s" % (cls.__module__, cls.__name__) == typec for typec in typeclasses])]) # @@ -943,7 +943,7 @@ class TypedObject(SharedMemoryModel): # # - def swap_typeclass(self, new_typeclass, clean_attributes=False): + def swap_typeclass(self, new_typeclass, clean_attributes=False, no_default=True): """ This performs an in-situ swap of the typeclass. This means that in-game, this object will suddenly be something else. @@ -967,6 +967,10 @@ class TypedObject(SharedMemoryModel): sure nothing in the new typeclass clashes with the old one. If you supply a list, only those named attributes will be cleared. + no_default - if this is active, the swapper will not allow for + swapping to a default typeclass in case the given + one fails for some reason. Instead the old one + will be preserved. """ if callable(new_typeclass): # this is an actual class object - build the path @@ -974,12 +978,24 @@ class TypedObject(SharedMemoryModel): new_typeclass = "%s.%s" % (cls.__module__, cls.__name__) # Try to set the new path - self.db_typeclass_path = new_typeclass.strip() - self.save() + # this will automatically save to database + + old_typeclass_path = self.typeclass_path + self.typeclass_path = new_typeclass.strip() # this will automatically use a default class if # there is an error with the given typeclass. new_typeclass = self.typeclass - + if self.typeclass_path == new_typeclass.path: + # the typeclass loading worked as expected + self.cached_typeclass_path = None + self.cached_typeclass = None + elif no_default: + # something went wrong; the default was loaded instead, + # and we don't allow that; instead we return to previous. + self.typeclass_path = old_typeclass_path + self.cached_typeclass = None + return False + if clean_attributes: # Clean out old attributes if is_iter(clean_attributes): @@ -999,6 +1015,7 @@ class TypedObject(SharedMemoryModel): # run hooks for this new typeclass new_typeclass.basetype_setup() new_typeclass.at_object_creation() + return True # # Attribute handler methods diff --git a/src/typeclasses/typeclass.py b/src/typeclasses/typeclass.py index 4a7352ad8..2c06b13b1 100644 --- a/src/typeclasses/typeclass.py +++ b/src/typeclasses/typeclass.py @@ -36,6 +36,7 @@ class MetaTypeClass(type): Adds some features to typeclassed objects """ super(MetaTypeClass, mcs).__init__(*args, **kwargs) + mcs.typename = mcs.__name__ mcs.path = "%s.%s" % (mcs.__module__, mcs.__name__) def __str__(cls):