Made some commands sensible to the new form of obj.typeclass (it's not a typeclass instance, not a class). Changed the way TypedObject.swap_typeclass works, so as to properly manage failures.

This commit is contained in:
Griatch 2011-10-03 23:53:23 +02:00
parent c8b4f7518d
commit 2c4af9076d
4 changed files with 46 additions and 23 deletions

View file

@ -1260,7 +1260,7 @@ class CmdTypeclass(MuxCommand):
# we did not supply a new typeclass, view the # we did not supply a new typeclass, view the
# current one instead. # current one instead.
if hasattr(obj, "typeclass"): 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: else:
string = "%s is not a typed object." % obj.name string = "%s is not a typed object." % obj.name
caller.msg(string) caller.msg(string)
@ -1277,22 +1277,27 @@ class CmdTypeclass(MuxCommand):
caller.msg("This object cannot have a type at all!") caller.msg("This object cannot have a type at all!")
return return
reset = "reset" in self.switches old_path = obj.typeclass_path
if obj.is_typeclass(typeclass) and not 'force' in self.switches:
old_typeclass = obj.typeclass_path
if old_typeclass == typeclass and not 'force' in self.switches:
string = "%s already has the typeclass '%s'." % (obj.name, typeclass) string = "%s already has the typeclass '%s'." % (obj.name, typeclass)
else: else:
obj.swap_typeclass(typeclass, clean_attributes=reset) reset = "reset" in self.switches
new_typeclass = obj.typeclass 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, string = "%s's type is now %s (instead of %s).\n" % (obj.name,
new_typeclass, obj.typeclass.typename,
old_typeclass) old_typeclass_name)
if reset: if reset:
string += "All attributes where reset." string += "All attributes where reset."
else: else:
string += "Note that the new class type could have overwritten " string += "Note that the new class type could have overwritten "
string += "same-named attributes on the existing object." 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) caller.msg(string)
@ -1555,7 +1560,7 @@ class CmdExamine(ObjManipCommand):
elif not perms: elif not perms:
perms = ["<None>"] perms = ["<None>"]
string += headers["playerperms"] % (", ".join(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"): if hasattr(obj, "location"):
string += headers["location"] % obj.location string += headers["location"] % obj.location

View file

@ -374,7 +374,7 @@ class CmdObjects(MuxCommand):
table[0].append(utils.datetime_format(obj.date_created)) table[0].append(utils.datetime_format(obj.date_created))
table[1].append(obj.dbref) table[1].append(obj.dbref)
table[2].append(obj.key) table[2].append(obj.key)
table[3].append(str(obj.typeclass)) table[3].append(str(obj.typeclass.path))
ftable = utils.format_table(table, 5) ftable = utils.format_table(table, 5)
for irow, row in enumerate(ftable): for irow, row in enumerate(ftable):
srow = "\n" + "".join(row) srow = "\n" + "".join(row)

View file

@ -627,7 +627,7 @@ class TypedObject(SharedMemoryModel):
"Setter. Allows for self.typeclass_path = value" "Setter. Allows for self.typeclass_path = value"
self.db_typeclass_path = value self.db_typeclass_path = value
self.save() self.save()
object.__setattr__(self, "cached_typeclass_path", value) object.__setattr__(self, 'cached_typeclass_path', value)
#@typeclass_path.deleter #@typeclass_path.deleter
def typeclass_path_del(self): def typeclass_path_del(self):
"Deleter. Allows for del self.typeclass_path" "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]) return typeclass and any([current_path == typec for typec in typeclasses])
else: else:
# check parent chain # 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])]) 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 This performs an in-situ swap of the typeclass. This means
that in-game, this object will suddenly be something else. that in-game, this object will suddenly be something else.
@ -967,6 +967,10 @@ class TypedObject(SharedMemoryModel):
sure nothing in the new typeclass clashes sure nothing in the new typeclass clashes
with the old one. If you supply a list, with the old one. If you supply a list,
only those named attributes will be cleared. 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): if callable(new_typeclass):
# this is an actual class object - build the path # this is an actual class object - build the path
@ -974,11 +978,23 @@ class TypedObject(SharedMemoryModel):
new_typeclass = "%s.%s" % (cls.__module__, cls.__name__) new_typeclass = "%s.%s" % (cls.__module__, cls.__name__)
# Try to set the new path # Try to set the new path
self.db_typeclass_path = new_typeclass.strip() # this will automatically save to database
self.save()
old_typeclass_path = self.typeclass_path
self.typeclass_path = new_typeclass.strip()
# this will automatically use a default class if # this will automatically use a default class if
# there is an error with the given typeclass. # there is an error with the given typeclass.
new_typeclass = self.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: if clean_attributes:
# Clean out old attributes # Clean out old attributes
@ -999,6 +1015,7 @@ class TypedObject(SharedMemoryModel):
# run hooks for this new typeclass # run hooks for this new typeclass
new_typeclass.basetype_setup() new_typeclass.basetype_setup()
new_typeclass.at_object_creation() new_typeclass.at_object_creation()
return True
# #
# Attribute handler methods # Attribute handler methods

View file

@ -36,6 +36,7 @@ class MetaTypeClass(type):
Adds some features to typeclassed objects Adds some features to typeclassed objects
""" """
super(MetaTypeClass, mcs).__init__(*args, **kwargs) super(MetaTypeClass, mcs).__init__(*args, **kwargs)
mcs.typename = mcs.__name__
mcs.path = "%s.%s" % (mcs.__module__, mcs.__name__) mcs.path = "%s.%s" % (mcs.__module__, mcs.__name__)
def __str__(cls): def __str__(cls):