Skip to content

Commit

Permalink
Update (#7)
Browse files Browse the repository at this point in the history
  • Loading branch information
davidbrochart authored Oct 17, 2023
1 parent 9385a64 commit be66d2f
Show file tree
Hide file tree
Showing 6 changed files with 196 additions and 161 deletions.
69 changes: 25 additions & 44 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -1,97 +1,81 @@
name: CI

on:
workflow_dispatch:
push:
branches:
- main
- master
pull_request:
branches:
- main
- master

jobs:
unix:

runs-on: ${{ matrix.os }}

strategy:
fail-fast: false
matrix:
os: [ubuntu-20.04, ubuntu-22.04, macos-11, macos-12]


defaults:
run:
shell: bash -l {0}

steps:
- uses: actions/checkout@v2
- name: Get number of CPU cores
uses: SimenB/github-actions-cpu-cores@v1
- name: Checkout repository
uses: actions/checkout@v4

- name: install mamba
uses: mamba-org/provision-with-micromamba@main
- name: Setup conda environment
uses: mamba-org/setup-micromamba@v1
with:
environment-file: env.yml
environment-name: xeusqt

- name: install cxx compiler
shell: bash -l {0}
run: |
$HOME/micromamba-bin/micromamba install cxx-compiler libuuid -c conda-forge -y
- name: cmake configure
shell: bash -l {0}
- name: Configure using CMake
run: |
mkdir -p build
cd build
cmake .. \
-DXEUS_BUILD_TESTS=ON \
-DCMAKE_PREFIX_PATH=$CONDA_PREFIX \
-DCMAKE_INSTALL_PREFIX=$CONDA_PREFIX
-DCMAKE_INSTALL_PREFIX=$CONDA_PREFIX
- name: build
shell: bash -l {0}
- name: Build
run: |
cd build
make -j 2
# make -j ${{ steps.cpu-cores.outputs.count }}
make
- name: install xeus-qt
shell: bash -l {0}
- name: Install
run: |
cd build
make install
win:

runs-on: ${{ matrix.os }}

strategy:
fail-fast: false
matrix:
os: [ windows-2019, windows-2022 ]

defaults:
run:
shell: cmd /C call {0}

steps:
- uses: actions/checkout@v2
- name: Checkout repository
uses: actions/checkout@v4

- name: install mamba
uses: mamba-org/provision-with-micromamba@main
- name: Setup conda environment
uses: mamba-org/setup-micromamba@v1
with:
environment-file: env.yml
environment-name: xeus

- name: micromamba shell hook
shell: powershell
run: |
micromamba shell hook -s cmd.exe -p C:\Users\runneradmin\micromamba-root
init-shell: cmd.exe

- name: Make build directory
run: mkdir build

- name: cmake configure
shell: cmd
- name: Configure using CMake
run: |
call C:\Users\runneradmin\micromamba-root\condabin\micromamba.bat activate xeus
cmake .. ^
-G Ninja ^
-DCMAKE_BUILD_TYPE=Release ^
Expand All @@ -101,10 +85,7 @@ jobs:
-DCMAKE_INSTALL_PREFIX="%CONDA_PREFIX%"
working-directory: build

- name: build
shell: cmd
- name: Build and install
run: |
call C:\Users\runneradmin\micromamba-root\condabin\micromamba.bat activate xeus
set CL=/MP
ninja install
working-directory: build
29 changes: 29 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,32 @@

[![CI](https://github.com/DerThorsten/xeus-qt-python/actions/workflows/main.yml/badge.svg)](https://github.com/DerThorsten/xeus-qt-python/actions/workflows/main.yml)

You will need to compile [xeus-qt](https://github.com/jupyter-xeus/xeus-qt) and [xeus-qt-python](https://github.com/jupyter-xeus/xeus-qt-python) (this repository) from source.
First clone these two repositories under `path/to/xeus-qt` and `path/to/xeus-qt-python`, respectively (or whatever place you'd like).
Then enter in a terminal:

```console
micromamba create -f env.yml
micromamba activate xeus-qt-python
cd path/to/xeus-qt
mkdir build
cd build
cmake .. -DCMAKE_INSTALL_PREFIX=$CONDA_PREFIX
make install
cd path/to/xeus-qt-python
mkdir build
cd build
cmake .. -DCMAKE_PREFIX_PATH=$CONDA_PREFIX -DCMAKE_INSTALL_PREFIX=$CONDA_PREFIX
make
make install
cd ..
python kernel_widget.py
```

This launches JupyterLab in a Qt application. If you look at running kernels in the left tab, you will see a kernel named `qt-python`.
Right-click on it and choose "New Console for Kernel". Now go to the file browser and double-click on the `my_notebook.ipynb` notebook.
In the "Select Kernel" menu, under "Use Kernel from Other Session" at the bottom, select "Console 1".
Now execute all the cells. The last one should display a button with the name "black magic" at the bottom of the Qt application.
If you click on it, it should display "hello from here" inside the last cell.
That's it, you've just connected your custom Qt application to Jupyter!
You added a button to your Qt application from a Jupyter notebook, which when clicked on, prints a message to a notebook cell output.
54 changes: 20 additions & 34 deletions env.yml
Original file line number Diff line number Diff line change
@@ -1,45 +1,31 @@
name: base
name: xeus-qt-python
channels:
- conda-forge

dependencies:
- compilers
- cmake
- pkg-config
- zeromq
- cppzmq
- make # [not win]
- ninja # [win]
- python
- pip
- qt
- xeus
- xeus-qt >=0.1.3
- xeus-zmq
- xeus-python
- xtl
- OpenSSL
- nlohmann_json
- xeus >=3.0.0,<4
- xeus-qt >=0.1.2,<0.2
- xeus-python
- cppzmq
- pybind11
- pybind11_json
- xeus >= 3.0.3
- xeus-zmq >= 1.0.2
- python=3.10
- fps-jupyterlab
- fps-auth
- python >=3.7
- fastapi >=0.87.0,<1
- fps >=0.0.21,<1
- fps-uvicorn >=0.0.19,<1
- fps-auth-base <1
- fps-contents >=0.0.37,<1
- fps-nbconvert >=0.0.37,<1
- fps-yjs >=0.0.37,<1
- pyqt
- PyQtWebEngine
- qtpy
- hatch
- git
- make
- cxx-compiler
- mesa-libgl-cos7-aarch64
- mesa-libgl-cos6-x86_64
- mesa-dri-drivers-cos6-x86_64
- libselinux-cos6-x86_64
- libxdamage-cos6-x86_64
- libxxf86vm-cos6-x86_64
- libxext-cos6-x86_64
- xorg-libxfixes
- pyqtwebengine
- pyside2
- fps-lab
- fps-auth
- fps-jupyterlab
- fps-contents
- fps-kernels
- fps-frontend
63 changes: 22 additions & 41 deletions kernel_widget.py
Original file line number Diff line number Diff line change
@@ -1,41 +1,36 @@
""" README:
- this is a proxy application for an actual qt application which wants to intergrate
jupyter
- this is a proxy application for an actual qt application which wants to intergrate
jupyter
- code to execute:
- code to execute:
from kernel_widget import get_kernel_widget
from PyQt5.QtWidgets import QPushButton
button = QPushButton()
button.setText("black magic")
from kernel_widget import get_kernel_widget
from PyQt5.QtWidgets import QPushButton
button = QPushButton()
button.setText("black magic")
def say_hello():
print("hello from here")
def say_hello():
print("hello from here")
button.clicked.connect(say_hello)
button.clicked.connect(say_hello)
get_kernel_widget().layout.addWidget(button)
get_kernel_widget().layout.addWidget(button)
"""

import json
import os
from pathlib import Path
import sys
import tempfile
import time
import subprocess
import xqtpython
import socket
from contextlib import closing
from types import ModuleType

import PyQt5
from PyQt5.QtCore import QUrl, QTimer
from PyQt5.QtWidgets import (
QApplication,
QHBoxLayout,
QVBoxLayout,
QPushButton,
QWidget,
)
from PyQt5.QtWebEngineWidgets import QWebEngineView
Expand All @@ -53,14 +48,13 @@ class KernelWidget(QWidget):
A webview widget showing a jupyterlab instance
"""

def __init__(self, kernel_name, jupyverse_dir, *args, **kwargs):
def __init__(self, kernel_name, *args, **kwargs):
super(KernelWidget, self).__init__(*args, **kwargs)

self.layout = QVBoxLayout()
self.setLayout(self.layout)

self.kernel_name = kernel_name
self.jupyverse_dir = jupyverse_dir

# browser
self.browser = QWebEngineView()
Expand Down Expand Up @@ -112,25 +106,24 @@ def _start_kernel(self):
def _start_jupyverse(self):
# self.start_server_button.setDisabled(True)
self.server_port = find_free_port()
token = "my_token"

# atm we still run a dev version of jupyverse
args = [
"hatch",
"run",
"dev.jupyterlab-noauth:jupyverse",
f"--kernels.connection_path={str(self.kernel_file_dir.name)}",
"--port",
f"{self.server_port}",
"jupyverse",
"--set", "kernels.allow_external_kernels=true",
"--set" ,f"kernels.external_connection_dir={str(self.kernel_file_dir.name)}",
"--set" ,f"auth.token={token}",
"--port", f"{self.server_port}",
]
self.server_process = subprocess.Popen(
args, cwd=self.jupyverse_dir, shell=False
args, shell=False
)

# we need to wait a tiny bit st the page is ready
def setUrl():
self.browser.setUrl(QUrl(f"http://127.0.0.1:{self.server_port}"))
self.browser.setUrl(QUrl(f"http://127.0.0.1:{self.server_port}/?token={token}"))

QTimer.singleShot(1000, setUrl)
QTimer.singleShot(2000, setUrl)

def closeEvent(self, event):
# do stuff
Expand All @@ -141,20 +134,8 @@ def closeEvent(self, event):


if __name__ == "__main__":
import argparse

parser = argparse.ArgumentParser(
prog="kernel-demo", description="show a kernel in qt application"
)

parser.add_argument("jupyverse_dir")

args = parser.parse_args()

app = QApplication(sys.argv)
kernel_widget = KernelWidget(
kernel_name="qt-python", jupyverse_dir=args.jupyverse_dir
)
kernel_widget = KernelWidget(kernel_name="qt-python")

kernel_widget.show()

Expand Down
Loading

0 comments on commit be66d2f

Please sign in to comment.