Added comprehensive encoding handling to support both player-level encoding choices as well as global multiple encodings through the settings file.

This commit is contained in:
Griatch 2010-10-03 19:11:43 +00:00
parent 7904916dba
commit 745df8356f
5 changed files with 69 additions and 34 deletions

View file

@ -505,15 +505,9 @@ class ObjectDB(TypedObject):
"""
# This is an important function that must always work.
# we use a different __getattribute__ to avoid recursive loops.
if from_obj:
try:
from_obj.at_msg_send(message, self)
except Exception:
pass
if self.at_msg_receive(message, from_obj):
for session in object.__getattribute__(self, 'sessions'):
session.msg(message, markup)
if object.__getattribute__(self, 'player'):
object.__getattribute__(self, 'player').msg(message, markup)
def emit_to(self, message, from_obj=None):
"Deprecated. Alias for msg"

View file

@ -253,19 +253,15 @@ class PlayerDB(TypedObject):
def msg(self, message, from_obj=None, markup=True):
"""
This duplicates the same-named method on the Character.
It forwards messages to the character or uses
the session messaging directly.
This is the main route for sending data to the user.
"""
if from_obj:
try:
from_obj.at_msg_send(message, self)
except Exception:
pass
if self.character:
self.character.msg(message, from_obj)
else:
if from_obj:
try:
from_obj.at_msg_send(message, self)
except Exception:
pass
if self.at_msg_receive(message, from_obj):
if self.character.at_msg_receive(message, from_obj):
for session in object.__getattribute__(self, 'sessions'):
session.msg(message, markup)

View file

@ -16,6 +16,8 @@ from src.utils import reloads
from src.utils import logger
from src.utils import utils
ENCODINGS = settings.ENCODINGS
class SessionProtocol(StatefulTelnetProtocol):
"""
This class represents a player's session. Each player
@ -71,6 +73,7 @@ class SessionProtocol(StatefulTelnetProtocol):
self.name = None
self.uid = None
self.logged_in = False
self.encoding = "utf-8"
# The time the user last issued a command.
self.cmd_last = time.time()
@ -103,13 +106,31 @@ class SessionProtocol(StatefulTelnetProtocol):
So we take the user input and pass it to the Player and their currently
connected character.
"""
try:
raw_string = utils.to_unicode(raw_string)
except Exception, e:
self.sendLine(str(e))
return
self.execute_cmd(raw_string)
if self.encoding:
try:
raw_string = utils.to_unicode(raw_string, encoding=self.encoding)
self.execute_cmd(raw_string)
return
except Exception, e:
err = str(e)
print err
pass
# malformed/wrong encoding defined on player-try some defaults
for encoding in ENCODINGS:
try:
raw_string = utils.to_unicode(raw_string, encoding=encoding)
err = None
break
except Exception, e:
err = str(e)
continue
if err:
self.sendLine(err)
else:
self.execute_cmd(raw_string)
def msg(self, message, markup=True):
"""
Communication Evennia -> Player
@ -120,12 +141,27 @@ class SessionProtocol(StatefulTelnetProtocol):
colors, but could also be html tags for
web connections etc.
"""
try:
message = utils.to_str(message)
except Exception, e:
self.sendLine(str(e))
return
self.sendLine(ansi.parse_ansi(message, strip_ansi=not markup))
if self.encoding:
try:
message = utils.to_str(message, encoding=self.encoding)
self.sendLine(ansi.parse_ansi(message, strip_ansi=not markup))
return
except Exception:
pass
# malformed/wrong encoding defined on player - try some defaults
for encoding in ENCODINGS:
try:
message = utils.to_str(message, encoding=encoding)
err = None
break
except Exception, e:
err = str(e)
continue
if err:
self.sendLine(err)
else:
self.sendLine(ansi.parse_ansi(message, strip_ansi=not markup))
def get_character(self):
"""
@ -228,6 +264,8 @@ class SessionProtocol(StatefulTelnetProtocol):
self.name = user.username
self.logged_in = True
self.conn_time = time.time()
if player.db.encoding:
self.encoding = player.db.encoding
if not settings.ALLOW_MULTISESSION:
# disconnect previous sessions.

View file

@ -70,6 +70,12 @@ IMPORT_MUX_HELP = False
# thrown off by sending the empty system command 'idle' to the server
# at regular intervals.
IDLE_TIMEOUT = 3600
# The set of encodings tried. A Player object may set an attribute "encoding" on
# itself to match the client used. If not set, or wrong encoding is
# given, this list is tried, in order, aborting on the first match.
# Add sets for languages/regions your players are likely to use.
# (see http://en.wikipedia.org/wiki/Character_encoding)
ENCODINGS = ["utf-8", "latin-1", "ISO-8859-1"]
###################################################
# Evennia Database config

View file

@ -273,7 +273,7 @@ class Attribute(SharedMemoryModel):
such as dhango model instances, cannot be directly stored/pickled
in an attribute, so we have to be clever about it.
Types of objects and how they are handled:
* str - stored directly in field
* str - s5Atored directly in field
* django model object - store its dbref in field
* any other python structure - pickle in field
@ -813,7 +813,8 @@ class TypedObject(SharedMemoryModel):
"""
Returns all attributes defined on the object.
"""
return [attr for attr in self.objattribute_set.all()]
attr_set_all = eval("self.%s_set.all()" % (self.attribute_model_name.lower()))
return [attr for attr in attr_set_all]
def attr(self, attribute_name=None, value=None, delete=False):
"""