def eval_expr(expr):
import ast
import operator as op
op = {
ast.Add: op.add,
ast.Sub: op.sub,
ast.Mult: op.mul,
ast.Div: op.truediv,
ast.Pow: op.pow,
ast.BitXor: op.xor,
ast.USub: op.neg,
}
def eval_(node):
if isinstance(node, ast.Num):
return fractions.Fraction(node.n)
elif isinstance(node, ast.BinOp):
return op[type(node.op)](eval_(node.left), eval_(node.right))
elif isinstance(node, ast.UnaryOp):
return op[type(node.op)](eval_(node.operand))
raise TypeError(node)
return eval_(ast.parse(str(expr), mode='eval').body)
python类Num()的实例源码
def get_info(filename):
info = {}
with open(filename) as _file:
data = ast.parse(_file.read())
for node in data.body:
if type(node) != ast.Assign:
continue
if type(node.value) not in [ast.Str, ast.Num]:
continue
name = None
for target in node.targets:
name = target.id
if type(node.value) == ast.Str:
info[name] = node.value.s
elif type(node.value) == ast.Num:
info[name] = node.value.n
return info
def convert_to_value(item):
if isinstance(item, ast.Str):
return item.s
elif hasattr(ast, 'Bytes') and isinstance(item, ast.Bytes):
return item.s
elif isinstance(item, ast.Tuple):
return tuple(convert_to_value(i) for i in item.elts)
elif isinstance(item, ast.Num):
return item.n
elif isinstance(item, ast.Name):
result = VariableKey(item=item)
constants_lookup = {
'True': True,
'False': False,
'None': None,
}
return constants_lookup.get(
result.name,
result,
)
elif (not PY33) and isinstance(item, ast.NameConstant):
# None, True, False are nameconstants in python3, but names in 2
return item.value
else:
return UnhandledKeyType()
def test_subscript(self):
sub = ast.Subscript(ast.Name("x", ast.Store()), ast.Index(ast.Num(3)),
ast.Load())
self.expr(sub, "must have Load context")
x = ast.Name("x", ast.Load())
sub = ast.Subscript(x, ast.Index(ast.Name("y", ast.Store())),
ast.Load())
self.expr(sub, "must have Load context")
s = ast.Name("x", ast.Store())
for args in (s, None, None), (None, s, None), (None, None, s):
sl = ast.Slice(*args)
self.expr(ast.Subscript(x, sl, ast.Load()),
"must have Load context")
sl = ast.ExtSlice([])
self.expr(ast.Subscript(x, sl, ast.Load()), "empty dims on ExtSlice")
sl = ast.ExtSlice([ast.Index(s)])
self.expr(ast.Subscript(x, sl, ast.Load()), "must have Load context")
def buildexec(self):
if isinstance(self.schema, Null):
if sys.version_info[0] <= 2:
return ast.Name("None", ast.Load())
else:
return ast.NameConstant(None)
elif isinstance(self.schema, Boolean):
if sys.version_info[0] <= 2:
if self.value:
return ast.Name("True", ast.Load())
else:
return ast.Name("False", ast.Load())
else:
if self.value:
return ast.NameConstant(True)
else:
return ast.NameConstant(False)
elif isinstance(self.schema, Number):
return ast.Num(self.value)
else:
raise NotImplementedError # have to think about this when the case comes up
def version():
path = 'pypika/__init__.py'
with open(path, 'rU') as file:
t = compile(file.read(), path, 'exec', ast.PyCF_ONLY_AST)
for node in (n for n in t.body if isinstance(n, ast.Assign)):
if len(node.targets) == 1:
name = node.targets[0]
if isinstance(name, ast.Name) and \
name.id in ('__version__', '__version_info__', 'VERSION'):
v = node.value
if isinstance(v, ast.Str):
return v.s
if isinstance(v, ast.Tuple):
r = []
for e in v.elts:
if isinstance(e, ast.Str):
r.append(e.s)
elif isinstance(e, ast.Num):
r.append(str(e.n))
return '.'.join(r)
def reify(kvalue, gen_sym):
value = kvalue.value
if value is True or value is False or value is None:
return ast.NameConstant(value=value), gen_sym, {}
elif type(value) == str:
return ast.Str(s=value), gen_sym, {}
elif type(value) == bytes:
return ast.Bytes(s=value), gen_sym, {}
elif type(value) in (int, float, complex):
return ast.Num(n=value), gen_sym, {}
else:
if kvalue.preferred_name is None:
name, gen_sym = gen_sym('temp')
else:
name = kvalue.preferred_name
return ast.Name(id=name, ctx=ast.Load()), gen_sym, {name: value}
def test_simple_reify():
check_reify(True, ast.NameConstant(value=True))
check_reify(False, ast.NameConstant(value=False))
check_reify(None, ast.NameConstant(value=None))
class Dummy(): pass
x = Dummy()
check_reify(
x, ast.Name(id='__peval_temp_1', ctx=ast.Load()),
expected_binding=dict(__peval_temp_1=x))
check_reify(
x, ast.Name(id='y', ctx=ast.Load()),
preferred_name='y', expected_binding=dict(y=x))
check_reify(1, ast.Num(n=1))
check_reify(2.3, ast.Num(n=2.3))
check_reify(3+4j, ast.Num(n=3+4j))
check_reify('abc', ast.Str(s='abc'))
s = bytes('abc', encoding='ascii')
check_reify(s, ast.Bytes(s=s))
def test_walker():
@ast_walker
def process_numbers(state, node, **kwds):
if isinstance(node, ast.Num):
return state.update(numbers=state.numbers.add(node.n)), ast.Num(n=node.n + 1)
else:
return state, node
node = get_ast(dummy)
state, new_node = process_numbers(dict(numbers=immutableset()), node)
assert state.numbers == set([1, 4])
assert_ast_equal(new_node, get_ast("""
def dummy(x, y):
c = 5
a = 2
"""))
# Transformations
def test_walk_field_transform():
@ast_transformer
def increment(node, walk_field, **kwds):
if isinstance(node, ast.Assign):
return replace_fields(node, targets=node.targets, value=walk_field(node.value))
elif isinstance(node, ast.Num):
return ast.Num(n=node.n + 1)
else:
return node
node = get_ast(dummy)
new_node = increment(node)
assert_ast_equal(new_node, get_ast(
"""
def dummy(x, y):
c = 5
a = 2
"""))
def test_walk_field_transform_inspect():
@ast_walker
def names_and_incremented_nums(state, node, walk_field, **kwds):
if isinstance(node, ast.Assign):
state, value_node = walk_field(state, node.value)
new_node = replace_fields(node, targets=node.targets, value=value_node)
new_state = state.update(objs=state.objs.add(node.targets[0].id))
return new_state, new_node
elif isinstance(node, ast.Num):
return state.update(objs=state.objs.add(node.n)), ast.Num(n=node.n + 1)
else:
return state, node
node = get_ast(dummy)
state, new_node = names_and_incremented_nums(dict(objs=immutableset()), node)
assert state.objs == set(['a', 'c', 1, 4])
assert_ast_equal(new_node, get_ast(
"""
def dummy(x, y):
c = 5
a = 2
"""))
def test_skip_fields():
@ast_transformer
def increment(node, skip_fields, **kwds):
if isinstance(node, ast.Assign) and node.targets[0].id == 'c':
skip_fields()
if isinstance(node, ast.Num):
return ast.Num(n=node.n + 1)
else:
return node
node = get_ast(dummy)
new_node = increment(node)
assert_ast_equal(new_node, get_ast(
"""
def dummy(x, y):
c = 4
a = 2
"""))
def _read_label(key):
if isinstance(key, ast.Name):
return key.id
elif isinstance(key, ast.Num):
n = key.n
if isinstance(n, (int, long)) and n >= 0:
return n
else:
raise _errors.TyError("Invalid numeric label.", key)
elif isinstance(key, ast.Str):
s = key.s
if s != "":
return s
else:
raise _errors.TyError("Invalid string label.", key)
else:
raise _errors.TyError("Invalid label", key)
def translate_pat_Call_constructor(self, ctx, pat, scrutinee_trans):
lbl = pat.func.id
tag_loc = ast.Subscript(
value=scrutinee_trans,
slice=ast.Index(value=ast.Num(n=0)))
lbl_condition = ast.Compare(
left=tag_loc,
ops=[ast.Eq()],
comparators=[ast.Str(s=lbl)])
arg = pat.args[0]
arg_scrutinee = ast.Subscript(
value=scrutinee_trans,
slice=ast.Index(value=ast.Num(n=1)))
arg_condition, binding_translations = ctx.translate_pat(arg, arg_scrutinee)
condition = ast.BoolOp(
op=ast.And(),
values=[lbl_condition, arg_condition])
return condition, binding_translations
def parse_unit(item):
if isinstance(item, ast.Name):
if item.id not in valid_units:
raise InvalidTypeException("Invalid base unit", item)
return {item.id: 1}
elif isinstance(item, ast.Num) and item.n == 1:
return {}
elif not isinstance(item, ast.BinOp):
raise InvalidTypeException("Invalid unit expression", item)
elif isinstance(item.op, ast.Mult):
left, right = parse_unit(item.left), parse_unit(item.right)
return combine_units(left, right)
elif isinstance(item.op, ast.Div):
left, right = parse_unit(item.left), parse_unit(item.right)
return combine_units(left, right, div=True)
elif isinstance(item.op, ast.Pow):
if not isinstance(item.left, ast.Name):
raise InvalidTypeException("Can only raise a base type to an exponent", item)
if not isinstance(item.right, ast.Num) or not isinstance(item.right.n, int) or item.right.n <= 0:
raise InvalidTypeException("Exponent must be positive integer", item)
return {item.left.id: item.right.n}
else:
raise InvalidTypeException("Invalid unit expression", item)
# Parses an expression representing a type. Annotation refers to whether
# the type is to be located in memory or storage
def resolve_negative_literals(_ast):
class RewriteUnaryOp(ast.NodeTransformer):
def visit_UnaryOp(self, node):
if isinstance(node.op, ast.USub) and isinstance(node.operand, ast.Num):
node.operand.n = 0 - node.operand.n
return node.operand
else:
return node
return RewriteUnaryOp().visit(_ast)
# Make a getter for a variable. This function gives an output that
# contains lists of 4-tuples:
# (i) the tail of the function name for the getter
# (ii) the code for the arguments that the function takes
# (iii) the code for the return
# (iv) the output type
#
# Here is an example:
#
# Input: my_variable: {foo: num, bar: decimal[5]}
#
# Output:
#
# [('__foo', '', '.foo', 'num'),
# ('__bar', 'arg0: num, ', '.bar[arg0]', 'decimal')]
#
# The getters will have code:
# def get_my_variable__foo() -> num: return self.foo
# def get_my_variable__bar(arg0: nun) -> decimal: return self.bar[arg0]
def visit_BoolOp(self, boolop):
res_var = self.variable()
expl_list = self.assign(ast.List([], ast.Load()))
app = ast.Attribute(expl_list, "append", ast.Load())
is_or = int(isinstance(boolop.op, ast.Or))
body = save = self.statements
fail_save = self.on_failure
levels = len(boolop.values) - 1
self.push_format_context()
# Process each operand, short-circuting if needed.
for i, v in enumerate(boolop.values):
if i:
fail_inner = []
# cond is set in a prior loop iteration below
self.on_failure.append(ast.If(cond, fail_inner, [])) # noqa
self.on_failure = fail_inner
self.push_format_context()
res, expl = self.visit(v)
body.append(ast.Assign([ast.Name(res_var, ast.Store())], res))
expl_format = self.pop_format_context(ast.Str(expl))
call = ast_Call(app, [expl_format], [])
self.on_failure.append(ast.Expr(call))
if i < levels:
cond = res
if is_or:
cond = ast.UnaryOp(ast.Not(), cond)
inner = []
self.statements.append(ast.If(cond, inner, []))
self.statements = body = inner
self.statements = save
self.on_failure = fail_save
expl_template = self.helper("format_boolop", expl_list, ast.Num(is_or))
expl = self.pop_format_context(expl_template)
return ast.Name(res_var, ast.Load()), self.explanation_param(expl)
def _add_value(self, module, name, alias):
module = __import__(module)
value = getattr(module, name)
if isinstance(value, (int, float)):
self._values[alias] = ast.Num(n = value)
def _is_numeric_mult(self, node: ast.BinOp) -> bool:
if isinstance(node.op, ast.Mult):
if isinstance(node.left , (ast.Name, ast.Num)) \
and isinstance(node.right, ast.Num):
return True
if isinstance(node.right, (ast.Name, ast.Num)) \
and isinstance(node.left , ast.Num):
return True
return False
def visit_BinOp(self, node: ast.BinOp):
node = self.generic_visit(node)
if self._is_numeric_pow(node):
left, right = node.left, node.right
degree = ( right.n if isinstance(right, ast.Num)
else -right.operand.n if isinstance(right.op, ast.USub)
else right.operand.n )
degree = int(degree)
if abs(degree) == 0:
node = ast.copy_location(ast.Num(n = 1), node)
elif abs(degree) == 1:
node = node.left
elif 2 <= abs(degree) <= self.MAX_DEGREE:
for _ in range(1, abs(degree)):
new_node = ast.BinOp\
( left = left
, op = ast.Mult()
, right = copy(node.left)
)
left = new_node = ast.copy_location(new_node, node)
node = new_node
else:
return node
if degree < 0:
new_node = ast.BinOp\
( left = ast.Num(n = 1)
, op = ast.Div()
, right = node
)
node = ast.copy_location(new_node, node)
return node