summaryrefslogtreecommitdiff
path: root/numpy/lib/utils.py
diff options
context:
space:
mode:
authorTravis Oliphant <oliphant@enthought.com>2007-12-30 09:32:31 +0000
committerTravis Oliphant <oliphant@enthought.com>2007-12-30 09:32:31 +0000
commitfdeac7465818652d5fb31e7e0e27f9debd0f54b8 (patch)
tree4d3146fdb9fb8f78eb6bf68891550e9b77b3ad44 /numpy/lib/utils.py
parent083ca64099268bc5967d25a15f9a4d26d750eb69 (diff)
parent50b26d2464f607566bf66986832636816eaa6d05 (diff)
downloadnumpy-fdeac7465818652d5fb31e7e0e27f9debd0f54b8.tar.gz
Merge the lib_for_io branch back into the trunk.
Diffstat (limited to 'numpy/lib/utils.py')
-rw-r--r--numpy/lib/utils.py159
1 files changed, 153 insertions, 6 deletions
diff --git a/numpy/lib/utils.py b/numpy/lib/utils.py
index 95dd4f581..048ffafc0 100644
--- a/numpy/lib/utils.py
+++ b/numpy/lib/utils.py
@@ -1,3 +1,4 @@
+import compiler
import os
import sys
import inspect
@@ -7,9 +8,10 @@ from numpy.core.multiarray import dtype as _dtype
from numpy.core import product, ndarray
__all__ = ['issubclass_', 'get_numpy_include', 'issubsctype',
- 'issubdtype', 'deprecate', 'get_numarray_include',
+ 'issubdtype', 'deprecate', 'deprecate_with_doc',
+ 'get_numarray_include',
'get_include', 'info', 'source', 'who',
- 'byte_bounds', 'may_share_memory']
+ 'byte_bounds', 'may_share_memory', 'safe_eval']
def issubclass_(arg1, arg2):
try:
@@ -82,15 +84,32 @@ else:
func.__name__ = name
return func
-def deprecate(func, oldname, newname):
+def deprecate(func, oldname=None, newname=None):
+ """Deprecate old functions.
+ Issues a DeprecationWarning, adds warning to oldname's docstring,
+ rebinds oldname.__name__ and returns new function object.
+
+ Example:
+ oldfunc = deprecate(newfunc, 'oldfunc', 'newfunc')
+
+ """
+
import warnings
+ if oldname is None:
+ oldname = func.func_name
+ if newname is None:
+ str1 = "%s is deprecated" % (oldname,)
+ depdoc = "%s is DEPRECATED!" % (oldname,)
+ else:
+ str1 = "%s is deprecated, use %s" % (oldname, newname),
+ depdoc = '%s is DEPRECATED! -- use %s instead' % (oldname, newname,)
+
def newfunc(*args,**kwds):
- warnings.warn("%s is deprecated, use %s" % (oldname, newname),
- DeprecationWarning)
+ warnings.warn(str1, DeprecationWarning)
return func(*args, **kwds)
+
newfunc = _set_function_name(newfunc, oldname)
doc = func.__doc__
- depdoc = '%s is DEPRECATED in numpy: use %s instead' % (oldname, newname,)
if doc is None:
doc = depdoc
else:
@@ -104,6 +123,24 @@ def deprecate(func, oldname, newname):
newfunc.__dict__.update(d)
return newfunc
+def deprecate_with_doc(somestr):
+ """Decorator to deprecate functions and provide detailed documentation
+ with 'somestr' that is added to the functions docstring.
+
+ Example:
+ depmsg = 'function numpy.lib.foo has been merged into numpy.lib.io.foobar'
+ @deprecate_with_doc(depmsg)
+ def foo():
+ pass
+
+ """
+
+ def _decorator(func):
+ newfunc = deprecate(func)
+ newfunc.__doc__ += "\n" + somestr
+ return newfunc
+ return _decorator
+
get_numpy_include = deprecate(get_include, 'get_numpy_include', 'get_include')
@@ -430,3 +467,113 @@ def source(object, output=sys.stdout):
print >> output, inspect.getsource(object)
except:
print >> output, "Not available for this object."
+
+#-----------------------------------------------------------------------------
+
+# The following SafeEval class and company are adapted from Michael Spencer's
+# ASPN Python Cookbook recipe:
+# http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/364469
+# Accordingly it is mostly Copyright 2006 by Michael Spencer.
+# The recipe, like most of the other ASPN Python Cookbook recipes was made
+# available under the Python license.
+# http://www.python.org/license
+
+# It has been modified to:
+# * handle unary -/+
+# * support True/False/None
+# * raise SyntaxError instead of a custom exception.
+
+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):
+ raise SyntaxError("Unsupported source construct: %s" % node.__class__)
+
+ def visitExpression(self, node, **kw):
+ for child in node.getChildNodes():
+ return self.visit(child, **kw)
+
+ 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 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]
+
+ def visitUnaryAdd(self, node, **kw):
+ return +self.visit(node.getChildNodes()[0])
+
+ def visitUnarySub(self, node, **kw):
+ return -self.visit(node.getChildNodes()[0])
+
+ def visitName(self, node, **kw):
+ if node.name == 'False':
+ return False
+ elif node.name == 'True':
+ return True
+ elif node.name == 'None':
+ return None
+ else:
+ raise SyntaxError("Unknown name: %s" % node.name)
+
+def safe_eval(source):
+ """ Evaluate a string containing a Python literal expression without
+ allowing the execution of arbitrary non-literal code.
+
+ Parameters
+ ----------
+ source : str
+
+ Returns
+ -------
+ obj : object
+
+ Raises
+ ------
+ SyntaxError if the code is invalid Python expression syntax or if it
+ contains non-literal code.
+
+ Examples
+ --------
+ >>> from numpy.lib.utils import safe_eval
+ >>> safe_eval('1')
+ 1
+ >>> safe_eval('[1, 2, 3]')
+ [1, 2, 3]
+ >>> safe_eval('{"foo": ("bar", 10.0)}')
+ {'foo': ('bar', 10.0)}
+ >>> safe_eval('import os')
+ Traceback (most recent call last):
+ ...
+ SyntaxError: invalid syntax
+ >>> safe_eval('open("/home/user/.ssh/id_dsa").read()')
+ Traceback (most recent call last):
+ ...
+ SyntaxError: Unsupported source construct: compiler.ast.CallFunc
+ >>> safe_eval('dict')
+ Traceback (most recent call last):
+ ...
+ SyntaxError: Unknown name: dict
+ """
+ walker = SafeEval()
+ try:
+ ast = compiler.parse(source, "eval")
+ except SyntaxError, err:
+ raise
+ try:
+ return walker.visit(ast)
+ except SyntaxError, err:
+ raise
+
+#-----------------------------------------------------------------------------
+
+