Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ os:
# - osx
julia:
- 0.6
- 0.7
- 1.0
# - nightly
env:
- CONDA_JL_VERSION="2"
Expand All @@ -31,7 +33,7 @@ before_script:
# - if [ $TRAVIS_OS_NAME = osx ]; then brew install gcc; fi

script:
- julia --color=yes -e 'Pkg.test("IPython"; coverage=true)'
- julia --color=yes -e 'VERSION >= v"0.7-" && using Pkg; Pkg.test("IPython"; coverage=true)'
after_success:
# push coverage results to Coveralls
- julia --color=yes -e 'cd(Pkg.dir("IPython")); Pkg.add("Coverage"); using Coverage; Coveralls.submit(Coveralls.process_folder())'
Expand Down
10 changes: 4 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,9 @@

Run `using IPython` and then type `.` in empty `julia>` prompt or run
`IPython.start_ipython()`. Exiting IPython as usual (e.g., `Ctrl-D`)
brings you back to Julia REPL. Re-entering IPython keeps the previous
state. In IPython, two variables are pre-defined: `Main` for
accessing top-level namespace of the Julia REPL and `julia` for
accessing an instance of `julia.Julia` object.
brings you back to the Julia REPL. Re-entering IPython keeps the
previous state. Use pre-defined `Main` object to access Julia
namespace from IPython.

**Note:**
First launch of IPython may be slow.
Expand All @@ -29,8 +28,7 @@ First launch of IPython may be slow.

### Python

* pyjulia
* IPython
* IPython (7.0 or above is recommended)


[travis-img]: https://travis-ci.org/tkf/IPython.jl.svg?branch=master
Expand Down
2 changes: 2 additions & 0 deletions REQUIRE
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
julia 0.6
Compat
Conda
PyCall 1.16
15 changes: 11 additions & 4 deletions ci/before_script.jl
Original file line number Diff line number Diff line change
@@ -1,17 +1,24 @@
@static if VERSION >= v"0.7.0-"
using Pkg
else
macro info(x)
:(info($(esc(x))))
end
end

# Let PyCall.jl use Python interpreter from Conda.jl
# See: https://github.com/JuliaPy/PyCall.jl
ENV["PYTHON"] = ""

info("Pkg.clone(pwd())")
@info "Pkg.clone(pwd())"
Pkg.clone(pwd())

info("Pkg.build(IPython)")
@info "Pkg.build(IPython)"
Pkg.build("IPython")

using IPython
IPython.install_dependency("ipython"; force=true)
IPython.install_dependency("julia"; force=true)
IPython.install_dependency("pytest"; force=true)

info("show_versions.jl")
@info "show_versions.jl"
include("show_versions.jl")
12 changes: 9 additions & 3 deletions ci/show_versions.jl
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
for line in split(strip(readstring("REQUIRE")), '\n')[2:end]
name = split(line)[1]
println(name, "\t", Pkg.installed(name))
if VERSION >= v"0.7.0-"
using Pkg
show(stdout, "text/plain", Pkg.installed())
println()
else
for line in split(strip(readstring("REQUIRE")), '\n')[2:end]
name = split(line)[1]
println(name, "\t", Pkg.installed(name))
end
end
2 changes: 2 additions & 0 deletions src/IPython.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
module IPython

using Compat
using Compat: @warn, @info
include("core.jl")
include("convenience.jl")
include("julia_repl.jl")
Expand Down
28 changes: 18 additions & 10 deletions src/convenience.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
function envinfo(io::IO = STDOUT; verbosity::Int = 1)
@static if VERSION >= v"0.7.0-"
using InteractiveUtils: versioninfo
else
versioninfo(io; verbose=false) = Base.versioninfo(io, verbose)
end

function envinfo(io::IO = stdout; verbosity::Int = 1)
if verbosity > 0
versioninfo(io, verbosity > 1)
versioninfo(io; verbose = verbosity > 1)
println(io)
end
for ex in [:(PyCall.pyprogramname),
Expand All @@ -11,7 +17,9 @@ function envinfo(io::IO = STDOUT; verbosity::Int = 1)
:(pyversion("julia")),
]
Base.show_unquoted(io, ex)
println(io, " = ", eval(ex))
print(io, " = ")
show(io, eval(ex))
println(io)
end
nothing
end
Expand Down Expand Up @@ -56,22 +64,22 @@ end

function yes_or_no(prompt = string("Type \"yes\" and press enter if ",
"you want to run this command.");
input = STDIN,
output = STDOUT)
input = stdin,
output = stdout)
print(output, prompt, " [yes/no]: ")
answer = readline(input)
if answer == "yes"
return true
elseif answer == "no"
return false
end
warn("Please enter \"yes\" or \"no\". Got: $answer")
@warn "Please enter \"yes\" or \"no\". Got: $answer"
return false
end


conda_packages = ("ipython", "pytest")
NOT_INSTALLABLE = (false, "", Void)
NOT_INSTALLABLE = (false, "", Nothing)

function condajl_installation(package)
if PyCall.conda && package in conda_packages
Expand Down Expand Up @@ -122,20 +130,20 @@ function install_dependency(package; force=false, dry_run=false)
pip_installation]
found, message, install = check_installer(package)
if found
info(message)
@info message
if !dry_run && (force || yes_or_no())
install()
end
return
end
end
warn("Installing $package not supported.")
@warn "Installing $package not supported."
end


function test_replhelper()
command = `$(PyCall.pyprogramname) -m pytest`
info(command)
@info command
cd(@__DIR__) do
run(command)
end
Expand Down
25 changes: 21 additions & 4 deletions src/core.jl
Original file line number Diff line number Diff line change
@@ -1,16 +1,33 @@
using PyCall
import Conda

julia_exepath() =
joinpath(VERSION < v"0.7.0-DEV.3073" ? JULIA_HOME : Base.Sys.BINDIR,
Base.julia_exename())

function eval_str(code::String)
Base.eval(Main, Meta.parse(strip(code)))
end

set_var(name::String, value) = set_var(Symbol(name), value)

function set_var(name::Symbol, value)
Base.eval(Main, :($name = $value))
nothing
end

function _start_ipython(name; kwargs...)
pyimport("replhelper")[name](;
init_julia = false,
jl_runtime_path = joinpath(JULIA_HOME, Base.julia_exename()),
eval_str = eval_str,
set_var = set_var,
kwargs...)
end

start_ipython(; kwargs...) = _start_ipython(:customized_ipython; kwargs...)
function start_ipython(; kwargs...)
_start_ipython(:customized_ipython; kwargs...)
end

function __init__()
unshift!(PyVector(pyimport("sys")["path"]), @__DIR__)
pushfirst!(PyVector(pyimport("sys")["path"]), @__DIR__)
init_repl_if_not()
end
11 changes: 8 additions & 3 deletions src/julia_repl.jl
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
using Base: LineEdit
@static if VERSION >= v"0.7.0-"
using REPL
using REPL: LineEdit
else
using Base: REPL, LineEdit
end

# Register keybind '.' in Julia REPL:

Expand All @@ -10,7 +15,7 @@ function init_repl_if_not(; _init_repl=init_repl)
return
end

if isinteractive() && typeof(active_repl) != Base.REPL.BasicREPL
if isinteractive() && typeof(active_repl) != REPL.BasicREPL
_init_repl(active_repl)
end
end
Expand All @@ -20,7 +25,7 @@ function init_repl(repl)
start = function(s, _...)
if isempty(s) || position(LineEdit.buffer(s)) == 0
# Force current_module() inside IPython to be Main:
eval(Main, :($start_ipython()))
Base.eval(Main, :($start_ipython()))
println()
LineEdit.edit_clear(s)
else
Expand Down
22 changes: 8 additions & 14 deletions src/replhelper.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,26 +11,23 @@ def jl_name(name):

class JuliaNameSpace(object):

def __init__(self, julia):
self.__julia = julia
def __init__(self, eval_str, set_var):
self.__eval = eval_str
self.__set = set_var

eval = property(lambda self: self.__eval)

def __setattr__(self, name, value):
if name.startswith('_'):
super(JuliaNameSpace, self).__setattr__(name, value)
else:
setter = '''
Main.PyCall.pyfunctionret(
(x) -> eval(:({} = $x)),
Any,
PyCall.PyAny)
'''.format(jl_name(name))
self.__julia.eval(setter)(value)
self.__set(name, value)

def __getattr__(self, name):
if name.startswith('_'):
return super(JuliaNameSpace, self).__getattr__(name)
else:
return self.__julia.eval(jl_name(name))
return self.__eval(jl_name(name))


instruction_template = """
Expand Down Expand Up @@ -109,12 +106,9 @@ def wrapped(*args, **kwargs):

def ipython_options(**kwargs):
from traitlets.config import Config
from julia import Julia

julia = Julia(**kwargs)
Main = JuliaNameSpace(julia)
Main = JuliaNameSpace(**kwargs)
user_ns = dict(
julia=julia,
Main=Main,
)

Expand Down
1 change: 1 addition & 0 deletions test/preamble.jl
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ macro test_nothrow(ex)
end

using IPython
using Compat
12 changes: 5 additions & 7 deletions test/test_convenience.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,19 @@ module TestConvenience
include("preamble.jl")

@testset "Convenience" begin
@test_nothrow IPython.envinfo(DevNull)
@test IPython.pyversion("julia") isa String
@test_nothrow IPython.envinfo(devnull)
@test IPython.pyversion("IPython") isa String
@test IPython.pyversion("IPython") == IPython._pyversion("IPython")
@test IPython.pyversion("__NON_EXISTING__") isa Void
@test IPython.pyversion("__NON_EXISTING__") isa Nothing

println("vvv DRY RUN vvv")
@test_nothrow IPython.install_dependency("ipython"; dry_run=true)
@test_nothrow IPython.install_dependency("julia"; dry_run=true)
@test_nothrow IPython.install_dependency("spam"; dry_run=true)
println("^^^ DRY RUN ^^^")

@test IPython.yes_or_no(input=IOBuffer("yes\n"), output=DevNull)
@test IPython.yes_or_no(input=IOBuffer("no\n"), output=DevNull) == false
@test IPython.yes_or_no(input=IOBuffer("spam\n"), output=DevNull) == false
@test IPython.yes_or_no(input=IOBuffer("yes\n"), output=devnull)
@test IPython.yes_or_no(input=IOBuffer("no\n"), output=devnull) == false
@test IPython.yes_or_no(input=IOBuffer("spam\n"), output=devnull) == false

@test IPython.condajl_installation("IPython") isa Tuple
@test IPython.conda_installation("IPython") isa Tuple
Expand Down
18 changes: 14 additions & 4 deletions test/test_julia_repl.jl
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
module TestJuliaREPL

include("preamble.jl")
using IPython: init_repl, init_repl_if_not
using Base.Terminals: TextTerminal
using IPython: init_repl, init_repl_if_not, REPL

@static if VERSION >= v"0.7.0-"
using REPL: TextTerminal
else
using Base.Terminals: TextTerminal
end


@testset "init_repl_if_not" begin
Expand All @@ -19,8 +24,13 @@ struct DummyTerminal <: TextTerminal
end

function dummy_repl()
repl = Base.REPL.LineEditREPL(DummyTerminal())
repl.interface = Base.REPL.setup_interface(repl)
if VERSION >= v"0.7.0-"
hascolor = false
repl = REPL.LineEditREPL(DummyTerminal(), hascolor)
else
repl = REPL.LineEditREPL(DummyTerminal())
end
repl.interface = REPL.setup_interface(repl)
return repl
end

Expand Down