I'm trying to write a python parser, and in my opiniion it could parse an "if statement" but it doesn't.
It shows me a "syntax error" message.
Can someone tell me what I'm doing wrong?
Thanks in advance.
The code is here: https://github.com/narke/py2neko
I modified the input string like this:
s = '''if 5:
print 10
else:
print 20 \n'''
check_syntax(s)
and the output is:
Syntax error at '5'
atom: 10
factor None
None
cmp: None None
atom: 20
factor None
None
cmp: None None
simple_stmt: None
From your code:
s = "if 5:\n"
check_syntax(s)
if 5:\n is not valid syntax because it is not a complete if statement. You need to provide a suite (code to execute) if the expression is True. For example:
>>> if 5:
...
File "<stdin>", line 2
^
IndentationError: expected an indented block
>>> compile('if 5:\n', '<string>', 'exec')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 1
if 5:
^
SyntaxError: unexpected EOF while parsing
>>> compile('if 5:\n print 5', '<string>', 'exec')
<code object <module> at 0xb7f60530, file "<string>", line 2>
Related
I really don't understand what causes the problem, could someone point it out for me please?
with shelve.open(obj_path) as obj:
for as_num in obj['as_number_list']: # ignore warning, obj['as_number_list'] is a list
temp = charge_as(obj['as_' + str(as_num)]) # temp is an object
as_test = temp # doing like this is ok
print(type(as_test))
exec("as_{}_obj = {}".format(as_num, temp)) # **error here**
And it gives syntax error like this:
<class 'instruments.AS'>
Traceback (most recent call last):
File "...", line 45, in <module>
exec("as_{}_obj = {}".format(as_num, temp))
File "<string>", line 1
as_1_obj = <instruments.AS object at 0x000002A86732E290>
^
SyntaxError: invalid syntax
I tried
exec("as_{}_obj = {}".format(as_num, temp.__dict__))
no error is shown but now as_{}_obj is of class 'dict' instead of class 'instruments.AS'
line 45:
exec("as_{}_obj = temp".format(as_num))
This question already has answers here:
Why must "exec" (and not "eval") be used for Python import statements?
(3 answers)
Closed 3 years ago.
Basically I am doing a POC against python eval security issue, but I am getting below error:
Traceback (most recent call last):
File "exploit.py", line 11, in <module>
a = paste()
File "exploit.py", line 6, in paste
if eval('%s > 1' % a):
File "<string>", line 1
import os;os.system('pwd') > 1
^
SyntaxError: invalid syntax
Code:
import datetime
def paste():
a = "import os;os.system('pwd')"
if eval('%s > 1' % a):
print a
else:
#create_brew(request.json)
return None, 201
a = paste()
print a
can anyone help me how to import libraries in-line?
eval works in expressions.
Use exec to execute a statement [import is a statement]
Also note, you cannot assign exec to a variable.
>> exec('import os;data = os.getcwd()')
>> print(data)
>> # /path/of/you/cwd
You may use the variable data to continue with your tests.
Taking the liberty to edit your code as follow:
def paste():
data = None
exec('import os;data = os.getcwd()')
if data:
return data
else:
return None, 201
a = paste()
print(a)
I have write code in Python 3 in the following format :
def function1()
def function2()
def function3()
def main()
Then I call the main :
main()
The function eval() it's into my main() also.
The purpose of my code is to getting two expressions and returns whether they are equals or not.
For example :
answer = """ A ← A * 3"""
my_input = """ A ← 3 * A"""
Comparing these expressions the result must be "Equals" ( or True ).
I'm getting the error below :
Traceback (most recent call last):
File "my_path", line 218, in <module>
main()
File "my_path", line 200, in main
if eval(a) == eval(b) and eval(c) == eval(d) :
File "<string>", line 2
^
SyntaxError: unexpected EOF while parsing
Do I need to import something ?
Or to re-arrange the functions ?
I'm here to understand, not to solve the issue.
Thanks.
I want to check a string - is it an import command? I have tried
# Helper - analyses a string - is it an import string?
"""
fromlike - from foo import bar
classic - import foo
classic_as - import foo as baz
"""
def check_is_import(string):
importname = ''
fromlike = False
classic = False
classic_as = False
if string[0:4] is 'from':
fromlike = True
importname = ''
if not fromlike and (string[0:6] is 'import'):
classic = True
importname = string.split(' ')[1]
if classic:
commandlist = string.split(' ')
if commandlist[2] is 'as':
classic_as = True
importname = commandlist[3]
del commandlist
if fromlike:
return ('fromlike', importname)
elif classic and (not classic_as):
return ('classic', importname)
elif classic_as:
return ('classic_as', importname)
else:
return ('no_import', importname)
but it worked for "fromlike" imports. (Note: I'm not asking "why does this code don't work?", I'm just searching a solution) What code will sure detect all imports? Basically my code takes a slice of the string. If the [0:4] slice equals 'from', the string is a "fromlike import". Else: if the [0:6] slice equals 'import', the string is a "classic import". If it detects 'as', it will find the pseudo-name. This function must return a tuple which contains the import type under index 0 and imported module-name under index 1.
If you want to be sure to handle all Python import forms, have Python do the parsing. Use the ast.parse() function and use the resulting parse tree; you'll either get Import or ImportFrom objects:
| Import(alias* names)
| ImportFrom(identifier? module, alias* names, int? level)
Each alias consists of a name and optional identifier used to import the name as:
-- import name with optional 'as' alias.
alias = (identifier name, identifier? asname)
Note that there can be multiple imports! You either have classic or fromlike imports, and both can import multiple names. Your function needs to return a list of (type, name) tuples. For invalid inputs, raise an exception (ValueError is a good fit here):
import ast
def check_is_import(string):
try:
body = ast.parse(string).body
except SyntaxError:
# not valid Python
raise ValueError('No import found')
if len(body) > 1:
# not a single statement
raise ValueError('Multiple statements found')
if not isinstance(body[0], (ast.Import, ast.ImportFrom)):
raise ValueError('No import found')
type_ = 'classic' if isinstance(body[0], ast.Import) else 'fromlike'
results = []
for alias in body[0].names:
alias_type = type_
if alias.asname:
alias_type += '_as'
results.append((alias_type, alias.asname or alias.name))
return results
The method should probably be renamed to extract_import_names(), as that reflects what it does much better.
Demo:
>>> check_is_import('from foo import bar')
[('fromlike', 'bar')]
>>> check_is_import('import foo')
[('classic', 'foo')]
>>> check_is_import('import foo as baz')
[('classic_as', 'baz')]
>>> check_is_import('from foo import bar, baz as spam, monty as python')
[('fromlike', 'bar'), ('fromlike_as', 'spam'), ('fromlike_as', 'python')]
>>> check_is_import('import foo as baz, baz, spam as ham')
[('classic_as', 'baz'), ('classic', 'baz'), ('classic_as', 'ham')]
>>> check_is_import('invalid python')
Traceback (most recent call last):
File "<stdin>", line 3, in check_is_import
File "/Users/mjpieters/Development/Library/buildout.python/parts/opt/lib/python3.6/ast.py", line 35, in parse
return compile(source, filename, mode, PyCF_ONLY_AST)
File "<unknown>", line 1
invalid python
^
SyntaxError: invalid syntax
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 6, in check_is_import
ValueError: No import found
>>> check_is_import('import foo; import bar')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 9, in check_is_import
ValueError: Multiple statements found
>>> check_is_import('1 + 1 == 2')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 11, in check_is_import
ValueError: No import found
I'm trying to implement an assert function. How can I get the text of the failing condition into the error message? If I have to parse it from the backtrace, can I portably rely on anything about the format of frames?
AssertionError is just like any other exception in python, and assert is a simple statement that is equivalent to
if __debug__:
if not expression: raise AssertionError
or
if __debug__:
if not expression1: raise AssertionError(expression2)
so you can add a second parameter to your assertion to have additional output
from sys import exc_info
from traceback import print_exception
# assertions are simply exceptions in Python
try:
assert False, "assert was false"
except AssertionError:
print_exception(*exc_info())
outputs
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
AssertionError: assert was false
If you're sure the expression to test is secure you could do something like this:
File my_assert.py:
import sys
def my_assert(condition):
caller = sys._getframe(1)
if not eval(condition, caller.f_globals, caller.f_locals):
raise AssertionError(repr(condition) + " on line " +
str(caller.f_lineno) + ' in ' +
caller.f_code.co_name)
File test_my_assert.py:
from my_assert import my_assert
global_var = 42
def test():
local_var = 17
my_assert('local_var*2 < global_var') # OK
my_assert('local_var > global_var')
test()
Output:
Traceback (most recent call last):
File "test_my_assert.py", line 10, in <module>
test()
File "test_my_assert.py", line 8, in test
my_assert('local_var > global_var')
File "my_assert.py", line 8, in my_assert
caller.f_code.co_name)
AssertionError: 'local_var > global_var' on line 8 in test
My very hackish solution:
def my_assert(condition):
if not eval(condition):
# error stuff
Then use it by placing the condition in quotation marks. It is then a string that can be printed in the error message.
Or, if you want it to actually raise an AssertionError:
def my_assert(condition):
if not eval(condition):
raise AssertionError(condition)