diff --git a/.gitignore b/.gitignore
index b6b693b..a0942c0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,5 @@
/src/jupynium/jupynium_pid.txt
+/src/jupynium/jupynium_persist_queue
# Created by https://www.toptal.com/developers/gitignore/api/python
# Edit at https://www.toptal.com/developers/gitignore?templates=python
diff --git a/README.md b/README.md
index 792a7cd..5603420 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,7 @@
[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
-
+
Jupynium uses Selenium to automate Jupyter Notebook, synchronising everything you type on Neovim.
@@ -10,7 +10,7 @@ Never leave Neovim. Switch tabs on the browser as you switch files on Neovim.
-Note that it doesn't sync from Notebook to Neovim so be careful.
+Note that it doesn't sync from Notebook to Neovim so only modify from Neovim.
### How does it work?
@@ -27,7 +27,7 @@ Only supports Jupyter Notebook (Jupyter Lab disables front-end interaction)
### Requirements
-- 💻 Linux, macOS and Windows WSL2
+- 💻 Linux, macOS and Windows (CMD, PowerShell, WSL2)
- 🦊 Firefox (Other browsers are not supported due to their limitation with Selenium)
- ✌️ Neovim >= v0.8
- 🐍 Python >= 3.10
@@ -40,6 +40,7 @@ conda activate jupynium && conda install -c conda-forge python=3.11
```
Install with vim-plug:
+
```vim
Plug 'kiyoon/jupynium.nvim', { 'do': 'pip3 install --user .' }
" Plug 'kiyoon/jupynium.nvim', { 'do': '~/miniconda3/bin/envs/jupynium/bin/pip install .' }
@@ -55,6 +56,7 @@ use { "rcarriga/nvim-notify" } -- optional
```
Install with 💤lazy.nvim
+
```lua
{
"kiyoon/jupynium.nvim",
@@ -66,6 +68,7 @@ Install with 💤lazy.nvim
```
Setup is optional for system python users and here are the defaults. Conda users need to change the `python_host`.
+
See setup defaults
@@ -162,7 +165,7 @@ For example:
### Open and attach to a Jupynium server
-**This is for local neovim only. For remote neovim, see [Command-Line Usage](#%EF%B8%8F-command-line-usage-attach-to-remote-neovim).**
+**This is for local neovim only. For remote neovim, see [Command-Line Usage](#%EF%B8%8F-command-line-usage-attach-to-remote-neovim).**
Running `:JupyniumStartAndAttachToServer` will open the notebook.
Type password and once **you need to be on the main page (file browser) for the next steps**.
diff --git a/lua/jupynium/server.lua b/lua/jupynium/server.lua
index 4c4bf0b..22fe71b 100644
--- a/lua/jupynium/server.lua
+++ b/lua/jupynium/server.lua
@@ -104,24 +104,41 @@ function M.add_commands()
vim.api.nvim_create_user_command("JupyniumAttachToServer", M.attach_to_server_cmd, { nargs = "?" })
end
+local function call_jupynium_cli_bg(args)
+ local call_str
+ if vim.fn.has "win32" == 1 then
+ call_str = [[call system('PowerShell "Start-Process -FilePath \"]]
+ .. vim.fn.expand(options.opts.python_host):gsub("\\", "\\\\")
+ .. [[\" -ArgumentList \"-m jupynium --nvim_listen_addr ]]
+ .. vim.v.servername
+
+ for _, v in ipairs(args) do
+ call_str = call_str .. [[ `\"]] .. v:gsub("\\", "\\\\") .. [[`\"]]
+ end
+
+ call_str = call_str .. [[\""')]]
+ else
+ call_str = [[call system('"]]
+ .. vim.fn.expand(options.opts.python_host)
+ .. [[" -m jupynium --nvim_listen_addr ]]
+ .. vim.v.servername
+
+ for _, v in ipairs(args) do
+ call_str = call_str .. [[ "]] .. v:gsub("\\", "\\\\") .. [["]]
+ end
+
+ call_str = call_str .. [[ &')]]
+ end
+ vim.cmd(call_str)
+end
+
function M.start_and_attach_to_server_cmd(args)
local notebook_URL = vim.fn.trim(args.args)
+
if notebook_URL == "" then
- vim.cmd(
- [[call system(']]
- .. options.opts.python_host
- .. [[ -m jupynium --notebook_URL ]]
- .. options.opts.default_notebook_URL
- .. [[ --nvim_listen_addr ' . v:servername . ' &')]]
- )
+ call_jupynium_cli_bg { "--notebook_URL", options.opts.default_notebook_URL }
else
- vim.cmd(
- [[call system(']]
- .. options.opts.python_host
- .. [[ -m jupynium --notebook_URL ]]
- .. notebook_URL
- .. [[ --nvim_listen_addr ' . v:servername . ' &')]]
- )
+ call_jupynium_cli_bg { "--notebook_URL", notebook_URL }
end
end
@@ -129,21 +146,9 @@ function M.attach_to_server_cmd(args)
local notebook_URL = vim.fn.trim(args.args)
if notebook_URL == "" then
- vim.cmd(
- [[call system(']]
- .. options.opts.python_host
- .. [[ -m jupynium --attach_only --notebook_URL ]]
- .. options.opts.default_notebook_URL
- .. [[ --nvim_listen_addr ' . v:servername . ' &')]]
- )
+ call_jupynium_cli_bg { "--attach_only", "--notebook_URL", options.opts.default_notebook_URL }
else
- vim.cmd(
- [[call system(']]
- .. options.opts.python_host
- .. [[ -m jupynium --attach_only --notebook_URL ]]
- .. notebook_URL
- .. [[ --nvim_listen_addr ' . v:servername . ' &')]]
- )
+ call_jupynium_cli_bg { "--attach_only", "--notebook_URL", notebook_URL }
end
end
diff --git a/requirements.txt b/requirements.txt
index d15527c..a1d91c4 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -3,5 +3,5 @@ packaging==22.0
coloredlogs==15.0.1
verboselogs==1.7
pynvim==0.4.3
-sysv-ipc==1.1.0
psutil==5.9.4
+persist-queue==0.8.0
diff --git a/setup.cfg b/setup.cfg
index 15472be..6dd46bf 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -20,8 +20,8 @@ install_requires =
verboselogs >= 1.7
selenium >= 4.7.2
packaging >= 22.0
- sysv-ipc >= 1.1.0
psutil >= 5.9.4
+ persist-queue >= 0.8.0
python_requires = >=3.10
package_dir =
=src
diff --git a/src/jupynium/cmds/jupynium.py b/src/jupynium/cmds/jupynium.py
index ef15082..11dfcbf 100644
--- a/src/jupynium/cmds/jupynium.py
+++ b/src/jupynium/cmds/jupynium.py
@@ -4,25 +4,26 @@
import json
import logging
import os
-from pathlib import Path
import sys
import traceback
+from pathlib import Path
import coloredlogs
+import persistqueue
+import verboselogs
+from persistqueue.exceptions import Empty
from selenium import webdriver
+from selenium.common.exceptions import WebDriverException
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
-from selenium.common.exceptions import WebDriverException
-import sysv_ipc
-import verboselogs
+from .. import __version__
from .. import selenium_helpers as sele
-from ..definitions import IPC_KEY, IPC_TYPE_ATTACH_NEOVIM
+from ..definitions import persist_queue_path
from ..events_control import process_events
+from ..nvim import NvimInfo
from ..process import already_running_pid
from ..pynvim_helpers import attach_and_init
-from ..nvim import NvimInfo
-from .. import __version__
logger = verboselogs.VerboseLogger(__name__)
@@ -92,10 +93,10 @@ def get_parser():
return parser
-def start_if_running_else_clear(args, ipc_queue):
+def start_if_running_else_clear(args, q: persistqueue.UniqueQ):
# If Jupynium is already running, send args and quit.
if already_running_pid():
- ipc_queue.send(json.dumps(args.__dict__), True, type=IPC_TYPE_ATTACH_NEOVIM)
+ q.put(args)
logger.info("Jupynium is already running. Attaching to the running process.")
return 0
else:
@@ -108,8 +109,8 @@ def start_if_running_else_clear(args, ipc_queue):
# If Jupynium is not running, clear the message queue before starting.
while True:
try:
- _, _ = ipc_queue.receive(block=False, type=IPC_TYPE_ATTACH_NEOVIM)
- except sysv_ipc.BusyError:
+ _ = q.get(block=False)
+ except Empty:
break
return None
@@ -122,17 +123,17 @@ def attach_new_neovim(
URL_to_home_windows: dict[str, str],
):
logger.info(f"New nvim wants to attach: {new_args}")
- if new_args["nvim_listen_addr"] in nvims:
+ if new_args.nvim_listen_addr in nvims:
logger.info("Already attached.")
else:
try:
- nvim = attach_and_init(new_args["nvim_listen_addr"])
- if new_args["notebook_URL"] in URL_to_home_windows.keys():
- home_window = URL_to_home_windows[new_args["notebook_URL"]]
+ nvim = attach_and_init(new_args.nvim_listen_addr)
+ if new_args.notebook_URL in URL_to_home_windows.keys():
+ home_window = URL_to_home_windows[new_args.notebook_URL]
else:
prev_num_windows = len(driver.window_handles)
driver.switch_to.new_window("tab")
- driver.get(new_args["notebook_URL"])
+ driver.get(new_args.notebook_URL)
# Wait for the notebook to load
driver_wait = WebDriverWait(driver, 10)
@@ -140,10 +141,10 @@ def attach_new_neovim(
sele.wait_until_loaded(driver)
home_window = driver.current_window_handle
- URL_to_home_windows[new_args["notebook_URL"]] = home_window
+ URL_to_home_windows[new_args.notebook_URL] = home_window
nvim_info = NvimInfo(nvim, home_window)
- nvims[new_args["nvim_listen_addr"]] = nvim_info
+ nvims[new_args.nvim_listen_addr] = nvim_info
except Exception:
logger.exception("Exception occurred while attaching a new nvim. Ignoring.")
@@ -178,8 +179,8 @@ def main():
print(pid)
sys.exit(0)
- ipc_queue = sysv_ipc.MessageQueue(IPC_KEY, sysv_ipc.IPC_CREAT)
- return_code = start_if_running_else_clear(args, ipc_queue)
+ q = persistqueue.UniqueQ(persist_queue_path)
+ return_code = start_if_running_else_clear(args, q)
if return_code is not None:
sys.exit(return_code)
@@ -239,13 +240,10 @@ def main():
# Check if a new newvim instance wants to attach to this server.
try:
- message, _ = ipc_queue.receive(
- block=False, type=IPC_TYPE_ATTACH_NEOVIM
- )
- except sysv_ipc.BusyError:
+ new_args = q.get(block=False)
+ except Empty:
pass
else:
- new_args = json.loads(message.decode())
attach_new_neovim(driver, new_args, nvims, URL_to_home_windows)
except WebDriverException:
break
diff --git a/src/jupynium/definitions.py b/src/jupynium/definitions.py
index 8a6c74b..aa97bc1 100644
--- a/src/jupynium/definitions.py
+++ b/src/jupynium/definitions.py
@@ -1,9 +1,6 @@
import os
from pathlib import Path
-import sysv_ipc
-
PACKAGE_DIR = Path(os.path.dirname(os.path.abspath(__file__)))
-IPC_KEY = 32985427282198 % sysv_ipc.KEY_MAX
-IPC_TYPE_ATTACH_NEOVIM = 1
+persist_queue_path = PACKAGE_DIR / "jupynium_persist_queue"