Skip to content

Commit

Permalink
add pyinclude macro (#948)
Browse files Browse the repository at this point in the history
  • Loading branch information
stevengj committed Dec 21, 2021
1 parent 429f251 commit e3e3008
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 2 deletions.
2 changes: 1 addition & 1 deletion Project.toml
@@ -1,7 +1,7 @@
name = "PyCall"
uuid = "438e738f-606a-5dbb-bf0a-cddfbfd45ab0"
authors = ["Steven G. Johnson <stevenj@mit.edu>", "Yichao Yu <yyc1992@gmail.com>", "Takafumi Arakaki <aka.tkf@gmail.com>", "Simon Kornblith <simon@simonster.com>", "Páll Haraldsson <Pall.Haraldsson@gmail.com>", "Jon Malmaud <malmaud@gmail.com>", "Jake Bolewski <jakebolewski@gmail.com>", "Keno Fischer <keno@alumni.harvard.edu>", "Joel Mason <jobba1@hotmail.com>", "Jameson Nash <vtjnash@gmail.com>", "The JuliaPy development team"]
version = "1.92.5"
version = "1.93.0"

[deps]
Conda = "8f4d0f93-b110-5947-807f-2305c1781a2d"
Expand Down
7 changes: 7 additions & 0 deletions README.md
Expand Up @@ -165,6 +165,8 @@ def sinpi(x):
py"sinpi"(1)
```

You can also execute a whole script `"foo.py"` via `@pyinclude("foo.py")` as if you had pasted it into a `py"""..."""` string.

When creating a Julia module, it is a useful pattern to define Python
functions or classes in Julia's `__init__` and then use it in Julia
function with `py"..."`.
Expand Down Expand Up @@ -390,6 +392,11 @@ and also by providing more type information to the Julia compiler.
`__init__`. Side-effect in Python occurred at top-level Julia scope
cannot be used at run-time for precompiled modules.

You can also execute a Python script file `"foo.py"` by running `@pyinclude("foo.py")`, and it will be as if you had pasted the
script into a `py"..."` string. (`@pyinclude` does not support
interpolating Julia variables with `$var`, however — the script
must be pure Python.)

* `pybuiltin(s)`: Look up `s` (a string or symbol) among the global Python
builtins. If `s` is a string it returns a `PyObject`, while if `s` is a
symbol it returns the builtin converted to `PyAny`. (You can also use `py"s"`
Expand Down
2 changes: 1 addition & 1 deletion src/PyCall.jl
Expand Up @@ -14,7 +14,7 @@ export pycall, pycall!, pyimport, pyimport_e, pybuiltin, PyObject, PyReverseDims
pyraise, pytype_mapping, pygui, pygui_start, pygui_stop,
pygui_stop_all, @pylab, set!, PyTextIO, @pysym, PyNULL, ispynull, @pydef,
pyimport_conda, @py_str, @pywith, @pycall, pybytes, pyfunction, pyfunctionret,
pywrapfn, pysetarg!, pysetargs!
pywrapfn, pysetarg!, pysetargs!, @pyinclude

import Base: size, ndims, similar, copy, getindex, setindex!, stride,
convert, pointer, summary, convert, show, haskey, keys, values,
Expand Down
21 changes: 21 additions & 0 deletions src/pyeval.jl
Expand Up @@ -232,3 +232,24 @@ macro py_str(code, options...)
ret
end
end

"""
@pyinclude(filename)
Execute the Python script in the file `filename` as if
it were in a `py\"\"\" ... \"\"\"` block, e.g. so that
any globals defined in `filename` are available to
subsequent `py"..."` evaluations.
(Unlike `py"..."`, however, `@pyinclude` does not
interpolate Julia variables into `\$var` expressions —
the `filename` script must be pure Python.)
"""
macro pyinclude(fname)
quote
m = pynamespace($__module__)
fname = $(esc(fname))
pyeval_(read(fname, String), m, m, Py_file_input, fname)
nothing
end
end
10 changes: 10 additions & 0 deletions test/runtests.jl
Expand Up @@ -819,3 +819,13 @@ if lowercase(get(ENV, "JULIA_PKGEVAL", "false")) != "true"
include("test_venv.jl")
include("test_build.jl")
end

@testset "@pyinclude" begin
mktemp() do path, io
print(io, "foo1 = 1\nbar2 = 2\n")
close(io)
@pyinclude(path)
@test py"foo1" == 1
@test py"bar2" == 2
end
end

2 comments on commit e3e3008

@stevengj
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Registration pull request created: JuliaRegistries/General/50957

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a v1.93.0 -m "<description of version>" e3e3008ee1b3e449c6382293f58a1f85384beea6
git push origin v1.93.0

Please sign in to comment.