From 55e5159f4953181238c18ce45b258f9878c8e0ab Mon Sep 17 00:00:00 2001 From: marius Date: Tue, 12 May 2020 00:16:32 -0700 Subject: [PATCH 1/2] refactor py_str macro to allow passing custom global/locals --- src/pyeval.jl | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/pyeval.jl b/src/pyeval.jl index 4eca19d5..7613195d 100644 --- a/src/pyeval.jl +++ b/src/pyeval.jl @@ -202,14 +202,19 @@ pasted into the Python code. This allows you to evaluate code where the code itself is generated by a Julia expression. """ macro py_str(code, options...) + m = :(pynamespace($__module__)) + esc(macroexpand(__module__, :(PyCall.@_py_str($m, $m, $code, $(options...))))) +end + +macro _py_str(pyglobals, pylocals, code, options...) T = length(options) == 1 && 'o' in options[1] ? PyObject : PyAny code, locals = interpolate_pycode(code) input_type = '\n' in code ? Py_file_input : Py_eval_input fname = make_fname(@__FILE__) assignlocals = Expr(:block, [(isa(v,String) ? - :(m[$v] = PyObject($(esc(ex)))) : + :(pylocals[$v] = PyObject($(esc(ex)))) : nothing) for (v,ex) in locals]...) - code_expr = Expr(:call, esc(:(Base.string))) + code_expr = Expr(:call, Base.string) i0 = firstindex(code) for i in sort!(collect(filter(k -> isa(k,Integer), keys(locals)))) push!(code_expr.args, code[i0:prevind(code,i)], esc(locals[i])) @@ -217,7 +222,7 @@ macro py_str(code, options...) end push!(code_expr.args, code[i0:lastindex(code)]) if input_type == Py_eval_input - removelocals = Expr(:block, [:(delete!(m, $v)) for v in keys(locals)]...) + removelocals = Expr(:block, [:(delete!(pylocals, $v)) for v in keys(locals)]...) else # if we are evaluating multi-line input, then it is not # safe to remove the local variables, because they might be referred @@ -225,9 +230,9 @@ macro py_str(code, options...) removelocals = nothing end quote - m = pynamespace($__module__) + pyglobals, pylocals = $pyglobals, $pylocals $assignlocals - ret = $T(pyeval_($code_expr, m, m, $input_type, $fname)) + ret = $T(pyeval_($code_expr, pyglobals, pylocals, $input_type, $fname)) $removelocals ret end From eb582579416c6d3da9892a25bfc1ed7fbbc4a099 Mon Sep 17 00:00:00 2001 From: marius Date: Fri, 15 May 2020 00:26:24 -0700 Subject: [PATCH 2/2] get rid of unnecessary macroexpand, fix fname argument --- src/pyeval.jl | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/pyeval.jl b/src/pyeval.jl index 7613195d..4264433e 100644 --- a/src/pyeval.jl +++ b/src/pyeval.jl @@ -77,10 +77,6 @@ function pyeval(s::AbstractString, returntype::TypeTuple=PyAny, return convert(returntype, pyeval_(s, pynamespace(Main), locals, input_type)) end -# get filename from @__FILE__ macro, which returns nothing in the REPL -make_fname(fname::AbstractString) = String(fname) -make_fname(fname::Any) = "REPL" - # a little finite-state-machine dictionary to keep track of where # we are in Python code, since $ is ignored in string literals and comments. # 'p' = Python code, '#' = comment, '$' = Julia interpolation @@ -203,14 +199,14 @@ where the code itself is generated by a Julia expression. """ macro py_str(code, options...) m = :(pynamespace($__module__)) - esc(macroexpand(__module__, :(PyCall.@_py_str($m, $m, $code, $(options...))))) + fname = String(__source__.file) + esc(:(PyCall.@_py_str($m, $m, $fname, $code, $(options...)))) end -macro _py_str(pyglobals, pylocals, code, options...) +macro _py_str(pyglobals, pylocals, fname, code, options...) T = length(options) == 1 && 'o' in options[1] ? PyObject : PyAny code, locals = interpolate_pycode(code) input_type = '\n' in code ? Py_file_input : Py_eval_input - fname = make_fname(@__FILE__) assignlocals = Expr(:block, [(isa(v,String) ? :(pylocals[$v] = PyObject($(esc(ex)))) : nothing) for (v,ex) in locals]...)