[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
Re: [pygame] Networking library
Patrick Mullen wrote:
On Sat, Apr 11, 2009 at 2:55 AM, Chris McCormick <chris@xxxxxxxxxxxx> wrote:
Hi,
On Fri, Apr 10, 2009 at 04:44:30PM -0700, Patrick Mullen wrote:
Python2.6 comes with json. Other than that, it is a small thing to include.
The library seems to be built around json, so removing it as a
dependency doesn't make much sense.
Actually I don't think it would be a huge job to change the serialisation
method to something else, optionally. I'll have a look it and see. My only
concern is about security - I chose JSON serialisation over something like
pickling because there's no way a client can inject malicious code using JSON.
I wonder if there's some other safe, built-in, pythonic way of serialising data
structures that I don't know about?
True. You could probably make the serialization abstract and allow
other methods, by plugging in a different Serializer class of some
sort. Other than json, yaml, xml, etc I don't know any other good
serialization for python, and everything I can think of is a
dependency. Maybe for easy testing it could work with repr/eval, but
prefers json if it is there. (Repr/eval can serialize the same
dictionaries that json can, and I think it's a bit faster too, its
just a bit more dangerous)
I'm not exactly sure how `safe` they really are but I found a recipe for
`safe eval` (I think on activestate) using the built in compiler module
that I iirc works on >= 2.4 python. Only about 70 lines of code or so.
The eval only work on literals ala JSON
I wrote some tests somewhere but I can't seem to place them. Anway, in
todays broadband world what's a few K for simpleson included.
import compiler
class Unsafe_Source_Error(Exception):
def __init__(self,error,descr = None,node = None):
self.error = error
self.descr = descr
self.node = node
self.lineno = getattr(node,"lineno",None)
def __repr__(self):
return "Line %d. %s: %s" % (self.lineno, self.error, self.descr)
__str__ = __repr__
class SafeEval(object):
def visit(self, node,**kw):
cls = node.__class__
meth = getattr(self,'visit'+cls.__name__,self.default)
return meth(node, **kw)
def default(self, node, **kw):
for child in node.getChildNodes():
return self.visit(child, **kw)
visitExpression = default
def visitConst(self, node, **kw):
return node.value
def visitDict(self,node,**kw):
return dict([(self.visit(k),self.visit(v)) for k,v in node.items])
def visitUnarySub(self, node, **kw):
return -self.visit(node.getChildNodes()[0])
def visitTuple(self,node, **kw):
return tuple(self.visit(i) for i in node.nodes)
def visitList(self,node, **kw):
return [self.visit(i) for i in node.nodes]
class SafeEvalWithErrors(SafeEval):
def default(self, node, **kw):
raise Unsafe_Source_Error("Unsupported source construct",
node.__class__,node)
def visitName(self,node, **kw):
if node.name == 'None':
return None
if node.name == 'True':
return True
if node.name == 'False':
return False
raise Unsafe_Source_Error("Strings must be quoted",
node.name, node)
# Add more specific errors if desired
def safe_eval(source, fail_on_error = True):
walker = fail_on_error and SafeEvalWithErrors() or SafeEval()
try:
ast = compiler.parse(source,"eval")
except SyntaxError, err:
raise
try:
return walker.visit(ast)
except Unsafe_Source_Error, err:
raise