diff --git a/.gitignore b/.gitignore index 01fb28e..e47c79b 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,5 @@ erl_crash.dump *.iml /ielixir test_db.sqlite3 +.DS_store +resources/ielixir/kernel.json diff --git a/.travis.yml b/.travis.yml index 77640b6..f64fed5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,5 @@ language: elixir +sudo: true elixir: - 1.1.0 - 1.2.3 @@ -6,19 +7,28 @@ otp_release: - 17.5 - 18.1 - 18.2 -sudo: true -before_script: - - yes | mix deps.get - - mix deps.compile - - sudo apt-get install python python-pip +matrix: + include: + - otp_release: 19.2 + elixir: 1.4 + - otp_release: 19.3 + elixir: 1.4 +python: + - "2.7" +install: - sudo pip install virtualenv virtualenvwrapper - mkdir ~/.virtualenvs - export WORKON_HOME=~/.virtualenvs - source /usr/local/bin/virtualenvwrapper.sh - mkvirtualenv test_ielixir - workon test_ielixir + - pip install pip --upgrade + - pip install jupyter nose + - mix local.rebar --force +before_script: + - yes | mix deps.get + - mix deps.compile - git clone -b ielixir https://github.com/pprzetacznik/jupyter_kernel_test.git - - pip install jupyter-console nose - MIX_ENV=dev ./install_script.sh script: - mix test diff --git a/README.md b/README.md index ebf3d72..3e73108 100644 --- a/README.md +++ b/README.md @@ -12,17 +12,24 @@ Hex: https://hex.pm/packages/ielixir. Please see generated documentation for implementation details: http://hexdocs.pm/ielixir/. -##Getting Started +## Getting Started ### Configure Jupyter +I recommend you to use `virtualenv` and `virtualenvwrapper` for this project to isolate dependencies between this and other projects however you may also work without this if you don't like this. +```Bash +$ pip install virtualenv virtualenvwrapper +``` +Now you need to load `virtualenvwrapper.sh` script into your current environment. I recommend you to add this like as well to the `~/.bash_profile.sh` script to have this script loaded every time you open fresh bash. +```Bash +$ source /usr/local/bin/virtualenvwrapper.sh +``` + +Now using our new tools we can easily create isolated virtual environment for jupyter installation. ```Bash -$ git clone https://github.com/jupyter/notebook.git -$ cd notebook $ mkvirtualenv jupyter-env $ workon jupyter-env -(jupyter-env) $ pip install --pre -e . -(jupyter-env) $ pip install jupyter-console +(jupyter-env) $ pip install jupyter ``` ### Configure IElixir @@ -36,24 +43,15 @@ $ mix test $ MIX_ENV=prod mix compile ``` -#### Prepare `kernel.json` file - -Create and edit `kernel.json` file +There may be also need to install rebar before IElixir installation, you can do this with command: ```Bash -$ mkdir ~/.ipython/kernels/ielixir -$ vim ~/.ipython/kernels/ielixir/kernel.json +mix local.rebar --force ``` +After this you may need to add `~/.mix/` to your `$PATH` variable if you don't have `rebar` visible yet outside `~/.mix/` directory. -Put into the file following content: -```Bash -{ - "argv": ["{PATH_TO_YOUR_IELIXIR_PROJECT}/start_script.sh", "{connection_file}"], - "display_name": "ielixir", - "language": "Elixir" -} -``` +#### Install Kernel -or simply run installation script to create this file: +Simply run installation script to create file `kernel.json` file in `./resouces` directory and bind it to the jupyter: ```Bash $ ./install_script.sh ``` @@ -78,6 +76,14 @@ Evaluate some commands in your new notebook: ![IElixir basics](/resources/jupyter_ielixir_basics.png?raw=true) +### Developement mode + +If you want to see requests passing logs please use `dev` environment to see what is happening in the background. + +```Bash +(jupyter-env) $ MIX_ENV=dev jupyter console --kernel ielixir +``` + ### Generate documentation Run following command and see `doc` directory for generated documentation in HTML: @@ -85,6 +91,14 @@ Run following command and see `doc` directory for generated documentation in HTM $ mix docs ``` +### Some issues + +There may be need to run IElixir kernel with specific erlang attribute which can be turned on by setting variable: +```Bash +ELIXIR_ERL_OPTIONS="-smp enable" +``` +This option has been included inside `install_script.sh` and `start_script.sh` scripts. + ### References Some useful articles: diff --git a/install_script.sh b/install_script.sh index 3ced994..ffdf6d4 100755 --- a/install_script.sh +++ b/install_script.sh @@ -5,13 +5,24 @@ then export MIX_ENV=prod fi -mkdir -p ~/.ipython/kernels/ielixir/ +# Provide setup according to kernel-spec +# https://jupyter-client.readthedocs.io/en/latest/kernels.html#kernel-specs + +UNAMESTR=$(UNAME) +KERNEL_SPEC="./resources/ielixir" +NAME="ielixir" + START_SCRIPT_PATH=$(cd `dirname "$0"` && pwd)/start_script.sh + +# help links and language info is provided on connection +# by the client CONTENT='{ "argv": ["'${START_SCRIPT_PATH}'", "{connection_file}"], - "display_name": "ielixir", - "language": "Elixir" + "display_name": "Elixir", + "language": "Elixir" }' -echo $CONTENT > ~/.ipython/kernels/ielixir/kernel.json +echo $CONTENT | python -m json.tool > $KERNEL_SPEC/kernel.json -mix ecto.migrate -r IElixir.Repo +# for global install remove the --user flag +jupyter kernelspec install --user --replace --name=$NAME $KERNEL_SPEC +ELIXIR_ERL_OPTIONS="-smp enable" mix ecto.migrate -r IElixir.Repo diff --git a/lib/ielixir/sandbox.ex b/lib/ielixir/sandbox.ex index 22f8f77..67226db 100644 --- a/lib/ielixir/sandbox.ex +++ b/lib/ielixir/sandbox.ex @@ -99,8 +99,11 @@ defmodule IElixir.Sandbox do iex> IElixir.Sandbox.execute_code(%{"code" => "hd []"}) {:error, "ArgumentError", ["** (ArgumentError) \"argument error\""]} - iex> IElixir.Sandbox.execute_code(%{"code" => "\"a\" + 5"}) - {:error, "ArithmeticError", ["** %ArithmeticError{}"]} + iex> abc = IElixir.Sandbox.execute_code(%{"code" => "\"a\" + 5"}) + iex> elem(abc, 0) + :error + iex> elem(abc, 1) + "ArithmeticError" """ @spec execute_code(map) :: execution_response diff --git a/lib/ielixir/socket/shell.ex b/lib/ielixir/socket/shell.ex index 035cc74..4c90b6f 100644 --- a/lib/ielixir/socket/shell.ex +++ b/lib/ielixir/socket/shell.ex @@ -51,7 +51,7 @@ defmodule IElixir.Socket.Shell do "version" => inspect(version), "mimetype" => "text/x-elixir", "file_extension" => "ex", - "pygments_lexer" => "pygments.lexers.erlang.ElixirLexer", + "pygments_lexer" => "elixir", "codemirror_mode" => "erlang", "nbconvert_exporter" => "" }, diff --git a/lib/ielixir/utils.ex b/lib/ielixir/utils.ex index 2222f11..5b4890a 100644 --- a/lib/ielixir/utils.ex +++ b/lib/ielixir/utils.ex @@ -20,8 +20,9 @@ defmodule IElixir.Utils do """ @spec parse_connection_file(String.t) :: map def parse_connection_file(connection_file) do - File.read!(connection_file) - |> Poison.Parser.parse! + connection_file + |> File.read! + |> Poison.Parser.parse! end @doc false diff --git a/mix.exs b/mix.exs index 39f854d..b51e8b8 100644 --- a/mix.exs +++ b/mix.exs @@ -1,36 +1,36 @@ defmodule IElixir.Mixfile do use Mix.Project - @version "0.9.5" + @version "0.9.6" def project do [app: :ielixir, version: @version, source_url: "https://github.com/pprzetacznik/IElixir", name: "IElixir", - elixir: ">= 1.1.0 and < 1.4.0", + elixir: ">= 1.1.0 and < 1.5.0", build_embedded: Mix.env == :prod, start_permanent: Mix.env == :prod, - deps: deps, + deps: deps(), description: """ Jupyter's kernel for Elixir programming language """, - package: package, + package: package(), test_coverage: [tool: ExCoveralls]] end def application do [mod: {IElixir, []}, - applications: [:logger, :iex, :sqlite_ecto, :ecto]] + applications: [:logger, :iex, :sqlite_ecto, :ecto, :erlzmq, :poison, :uuid]] end defp deps do - [{:erlzmq, github: "zeromq/erlzmq2"}, - {:poison, github: "devinus/poison", override: true}, + [{:erlzmq, github: "zeromq/erlzmq2", compile: "make"}, + # {:poison, github: "devinus/poison", override: true}, + {:poison, "~> 3.1", override: true}, {:uuid, github: "okeuday/uuid"}, - {:sqlite_ecto, "~> 0.5.0"}, - {:ecto, "~> 0.15.0"}, + {:sqlite_ecto, "~> 1.0.0"}, # Docs dependencies {:earmark, "~> 0.1", only: :docs}, diff --git a/mix.lock b/mix.lock index 750f621..af7b53c 100644 --- a/mix.lock +++ b/mix.lock @@ -1,23 +1,24 @@ -%{"certifi": {:hex, :certifi, "0.4.0", "a7966efb868b179023618d29a407548f70c52466bf1849b9e8ebd0e34b7ea11f", [:rebar3], []}, - "decimal": {:hex, :decimal, "1.1.1", "a8ff5b673105e6cdaca96f799aeefc6f07142881b616c65db16e14e556b16e76", [:mix], []}, +%{"certifi": {:hex, :certifi, "1.2.1", "c3904f192bd5284e5b13f20db3ceac9626e14eeacfbb492e19583cf0e37b22be", [:rebar3], []}, + "decimal": {:hex, :decimal, "1.1.2", "79a769d4657b2d537b51ef3c02d29ab7141d2b486b516c109642d453ee08e00c", [:mix], []}, "earmark": {:hex, :earmark, "0.2.1", "ba6d26ceb16106d069b289df66751734802777a3cbb6787026dd800ffeb850f3", [:mix], []}, - "ecto": {:hex, :ecto, "0.15.0", "0f070eca5dc452901379a761004f995f721319a5d431aa9e7b8a8e26b33d3fc1", [:mix], [{:sbroker, "~> 0.7", [hex: :sbroker, optional: true]}, {:postgrex, "~> 0.9.1", [hex: :postgrex, optional: true]}, {:poolboy, "~> 1.4", [hex: :poolboy, optional: false]}, {:poison, "~> 1.0", [hex: :poison, optional: true]}, {:mariaex, "~> 0.4.1", [hex: :mariaex, optional: true]}, {:decimal, "~> 1.0", [hex: :decimal, optional: false]}]}, + "ecto": {:hex, :ecto, "1.1.9", "6f30e4662d540c794048e62a04926c1d3c892a2ba4704fe1e19d4a9b5b2f881e", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, optional: false]}, {:mariaex, "~> 0.5.0 or ~> 0.6.0", [hex: :mariaex, optional: true]}, {:poison, "~> 1.0 or ~> 2.0", [hex: :poison, optional: true]}, {:poolboy, "~> 1.4", [hex: :poolboy, optional: false]}, {:postgrex, "~> 0.11.0", [hex: :postgrex, optional: true]}, {:sbroker, "~> 0.7", [hex: :sbroker, optional: true]}]}, "erlzmq": {:git, "https://github.com/zeromq/erlzmq2.git", "573d583930c4b1134e504bec83926d188112b401", []}, - "esqlite": {:hex, :esqlite, "0.2.2", "e4e8b39062a075e0bd4756b894dd2aa8edbf94c9081c1fb5c72dc705bf2f2d88", [:rebar, :make], []}, - "ex_doc": {:hex, :ex_doc, "0.11.4", "a064bdb720594c3745b94709b17ffb834fd858b4e0c1f48f37c0d92700759e02", [:mix], [{:earmark, "~> 0.1.17 or ~> 0.2", [hex: :earmark, optional: true]}]}, - "excoveralls": {:hex, :excoveralls, "0.3.11", "cd1abaf07db5bed9cf7891d86470247c8b3c8739d7758679071ce1920bb09dbc", [:mix], [{:hackney, ">= 0.12.0", [hex: :hackney, optional: false]}, {:exjsx, "~> 3.0", [hex: :exjsx, optional: false]}]}, - "exjsx": {:hex, :exjsx, "3.2.0", "7136cc739ace295fc74c378f33699e5145bead4fdc1b4799822d0287489136fb", [:mix], [{:jsx, "~> 2.6.2", [hex: :jsx, optional: false]}]}, - "hackney": {:hex, :hackney, "1.6.0", "8d1e9440c9edf23bf5e5e2fe0c71de03eb265103b72901337394c840eec679ac", [:rebar3], [{:ssl_verify_fun, "1.1.0", [hex: :ssl_verify_fun, optional: false]}, {:mimerl, "1.0.2", [hex: :mimerl, optional: false]}, {:metrics, "1.0.1", [hex: :metrics, optional: false]}, {:idna, "1.2.0", [hex: :idna, optional: false]}, {:certifi, "0.4.0", [hex: :certifi, optional: false]}]}, - "idna": {:hex, :idna, "1.2.0", "ac62ee99da068f43c50dc69acf700e03a62a348360126260e87f2b54eced86b2", [:rebar3], []}, + "esqlite": {:hex, :esqlite, "0.2.3", "1a8b60877fdd3d50a8a84b342db04032c0231cc27ecff4ddd0d934485d4c0cd5", [:rebar3], []}, + "ex_doc": {:hex, :ex_doc, "0.12.0", "b774aabfede4af31c0301aece12371cbd25995a21bb3d71d66f5c2fe074c603f", [:mix], [{:earmark, "~> 0.2", [hex: :earmark, optional: false]}]}, + "excoveralls": {:hex, :excoveralls, "0.3.11", "cd1abaf07db5bed9cf7891d86470247c8b3c8739d7758679071ce1920bb09dbc", [:mix], [{:exjsx, "~> 3.0", [hex: :exjsx, optional: false]}, {:hackney, ">= 0.12.0", [hex: :hackney, optional: false]}]}, + "exjsx": {:hex, :exjsx, "3.2.1", "1bc5bf1e4fd249104178f0885030bcd75a4526f4d2a1e976f4b428d347614f0f", [:mix], [{:jsx, "~> 2.8.0", [hex: :jsx, optional: false]}]}, + "hackney": {:hex, :hackney, "1.8.6", "21a725db3569b3fb11a6af17d5c5f654052ce9624219f1317e8639183de4a423", [:rebar3], [{:certifi, "1.2.1", [hex: :certifi, optional: false]}, {:idna, "5.0.2", [hex: :idna, optional: false]}, {:metrics, "1.0.1", [hex: :metrics, optional: false]}, {:mimerl, "1.0.2", [hex: :mimerl, optional: false]}, {:ssl_verify_fun, "1.1.1", [hex: :ssl_verify_fun, optional: false]}]}, + "idna": {:hex, :idna, "5.0.2", "ac203208ada855d95dc591a764b6e87259cb0e2a364218f215ad662daa8cd6b4", [:rebar3], [{:unicode_util_compat, "0.2.0", [hex: :unicode_util_compat, optional: false]}]}, "inch_ex": {:hex, :inch_ex, "0.4.0", "27829de2227edfba8fa5c431088578685c0956128b40522957077963e563e868", [:mix], [{:poison, "~> 1.2", [hex: :poison, optional: false]}]}, - "jsx": {:hex, :jsx, "2.6.2", "213721e058da0587a4bce3cc8a00ff6684ced229c8f9223245c6ff2c88fbaa5a", [:mix, :rebar], []}, + "jsx": {:hex, :jsx, "2.8.2", "7acc7d785b5abe8a6e9adbde926a24e481f29956dd8b4df49e3e4e7bcc92a018", [:mix, :rebar3], []}, "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], []}, "mimerl": {:hex, :mimerl, "1.0.2", "993f9b0e084083405ed8252b99460c4f0563e41729ab42d9074fd5e52439be88", [:rebar3], []}, "pipe": {:hex, :pipe, "0.0.2", "eff98a868b426745acef103081581093ff5c1b88100f8ff5949b4a30e81d0d9f", [:mix], []}, - "poison": {:git, "https://github.com/devinus/poison.git", "7a7882e8b9877c8868eabaa6b005c813f8d6dc6b", []}, + "poison": {:hex, :poison, "3.1.0", "d9eb636610e096f86f25d9a46f35a9facac35609a7591b3be3326e99a0484665", [:mix], []}, "poolboy": {:hex, :poolboy, "1.5.1", "6b46163901cfd0a1b43d692657ed9d7e599853b3b21b95ae5ae0a777cf9b6ca8", [:rebar], []}, - "quickrand": {:hex, :quickrand, "1.5.2-rc1", "1345b1652dadc520692ee55f4d996d74d399a86c0265b53a24c8540803929cb4", [:rebar], []}, - "sqlite_ecto": {:hex, :sqlite_ecto, "0.5.0", "1e2e0c4aa3b8137cef08274c694d289c56887a52bb0fb4c856413c30045df8ef", [:mix], [{:sqlitex, "~> 0.8", [hex: :sqlitex, optional: false]}, {:poison, "~> 1.0", [hex: :poison, optional: false]}, {:ecto, "~> 0.15.0", [hex: :ecto, optional: false]}]}, - "sqlitex": {:hex, :sqlitex, "0.8.3", "226901fe73fb9d74a5bc742594074dc3cac725ee632d595a704dd8bf92661044", [:mix], [{:pipe, "~> 0.0.2", [hex: :pipe, optional: false]}, {:esqlite, "~> 0.2.0", [hex: :esqlite, optional: false]}, {:decimal, "~> 1.1.0", [hex: :decimal, optional: false]}]}, - "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.0", "edee20847c42e379bf91261db474ffbe373f8acb56e9079acb6038d4e0bf414f", [:rebar, :make], []}, - "uuid": {:git, "https://github.com/okeuday/uuid.git", "fdd2861e2f5049c25d44ff342c9756ce64a2a783", []}} + "quickrand": {:hex, :quickrand, "1.7.1", "b0c2a41d08c955f055c44bed357660de443cd9068a33aba530076910b7333659", [:rebar3], []}, + "sqlite_ecto": {:hex, :sqlite_ecto, "1.0.0", "63c1da849c5862c04207928b4a465bdf5e70e84151bed1cdc29d426bd8d8f2ee", [:mix], [{:ecto, "~> 1.0", [hex: :ecto, optional: false]}, {:poison, "~> 1.0", [hex: :poison, optional: false]}, {:sqlitex, "~> 0.8", [hex: :sqlitex, optional: false]}]}, + "sqlitex": {:hex, :sqlitex, "0.8.0", "e0013cc7b70723db22c2ac8d318fa434d062242075296499c4c76469b7c22e78", [:mix], [{:decimal, "~> 1.1.0", [hex: :decimal, optional: false]}, {:esqlite, "~> 0.2.0", [hex: :esqlite, optional: false]}, {:pipe, "~> 0.0.2", [hex: :pipe, optional: false]}]}, + "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.1", "28a4d65b7f59893bc2c7de786dec1e1555bd742d336043fe644ae956c3497fbe", [:make, :rebar], []}, + "unicode_util_compat": {:hex, :unicode_util_compat, "0.2.0", "dbbccf6781821b1c0701845eaf966c9b6d83d7c3bfc65ca2b78b88b8678bfa35", [:rebar3], []}, + "uuid": {:git, "https://github.com/okeuday/uuid.git", "3b4a500963d42195db3ad4b90fda94d2fb75b7e9", []}} diff --git a/resources/ielixir/logo-32x32.png b/resources/ielixir/logo-32x32.png new file mode 100644 index 0000000..9fad970 Binary files /dev/null and b/resources/ielixir/logo-32x32.png differ diff --git a/resources/ielixir/logo-64x64.png b/resources/ielixir/logo-64x64.png new file mode 100644 index 0000000..0dfad03 Binary files /dev/null and b/resources/ielixir/logo-64x64.png differ diff --git a/resources/logo-32x32.png b/resources/logo-32x32.png new file mode 100644 index 0000000..9fad970 Binary files /dev/null and b/resources/logo-32x32.png differ diff --git a/resources/logo-64x64.png b/resources/logo-64x64.png new file mode 100644 index 0000000..0dfad03 Binary files /dev/null and b/resources/logo-64x64.png differ diff --git a/start_script.sh b/start_script.sh index b92abb4..0bea38e 100755 --- a/start_script.sh +++ b/start_script.sh @@ -12,5 +12,4 @@ then fi IELIXIR_PATH=$(cd `dirname "$0"` && pwd)/ cd $IELIXIR_PATH -CONNECTION_FILE=$1 mix run --no-halt - +ELIXIR_ERL_OPTIONS="-smp enable" CONNECTION_FILE=$1 mix run --no-halt