Skip to content
This repository was archived by the owner on Dec 27, 2023. It is now read-only.

PoC - plugins for different output types #28

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
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
23 changes: 14 additions & 9 deletions src/Handlers/ShellMessagesHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
use JupyterPHP\Shell;

use JupyterPHP\KernelOutput;
use JupyterPHP\zPHP;
use Monolog\Logger;
use React\ZMQ\SocketWrapper;

Expand All @@ -33,7 +34,7 @@ final class ShellMessagesHandler
/** @var KernelInfoAction */
private $kernelInfoAction;

/** @var \JupyterPHP\Actions\ShutdownAction */
/** @var ShutdownAction */
private $shutdownAction;

/** @var Shell */
Expand All @@ -42,6 +43,9 @@ final class ShellMessagesHandler
/** @var Logger */
private $logger;

/** @var zPHP */
private $zPHP;


public function __construct(
JupyterBroker $broker,
Expand All @@ -50,8 +54,9 @@ public function __construct(
Logger $logger
) {
$this->shellSoul = new Shell();
$this->zPHP = new zPHP($broker,$iopubSocket);

$this->executeAction = new ExecuteAction($broker, $iopubSocket, $shellSocket, $this->shellSoul);
$this->executeAction = new ExecuteAction($broker, $iopubSocket, $shellSocket, $this->shellSoul, $this->zPHP);
$this->historyAction = new HistoryAction($broker, $shellSocket);
$this->kernelInfoAction = new KernelInfoAction($broker, $shellSocket, $iopubSocket);
$this->shutdownAction = new ShutdownAction($broker, $iopubSocket, $shellSocket);
Expand All @@ -70,20 +75,20 @@ public function __invoke(array $msg)
// Read ZMQ IDs until we reach the delimiter
$zmqIds = array();
while (!empty($msg)) {
$item = \array_shift($msg);
$item = array_shift($msg);
if ($item === '<IDS|MSG>') break;
else \array_push($zmqIds, $item);
else array_push($zmqIds, $item);
}

// Read the remaining items
list($hmac, $header, $parentHeader, $metadata, $content) = $msg;

$header = \json_decode($header, true);
$content = \json_decode($content, true);
$header = json_decode($header, true);
$content = json_decode($content, true);

$this->logger->debug('Received message', [
'processId' => \getmypid(),
'zmqIds' => \htmlentities(\implode(", ", $zmqIds), ENT_COMPAT, "UTF-8"),
'processId' => getmypid(),
'zmqIds' => htmlentities(implode(", ", $zmqIds), ENT_COMPAT, "UTF-8"),
'hmac' => $hmac,
'header' => $header,
'parentHeader' => $parentHeader,
Expand All @@ -102,7 +107,7 @@ public function __invoke(array $msg)
} elseif ('comm_open' === $header['msg_type']) {
// TODO: Research about what should be done.
} else {
$this->logger->error('Unknown message type', ['processId' => \getmypid(), 'header' => $header]);
$this->logger->error('Unknown message type', ['processId' => getmypid(), 'header' => $header]);
}
}
}
141 changes: 141 additions & 0 deletions src/zPHP.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
<?php

/**
* Author: Zbigniew 'zibi' Jarosik <zibi@nora.pl>
*
* based on https://jupyter-client.readthedocs.io/en/latest/messaging.html
*/

namespace JupyterPHP;

use React\ZMQ\SocketWrapper;

class zPHP
{
/** @var JupyterBroker */
private $broker;

/** @var SocketWrapper */
private $iopubSocket;

private $header;

private $pluginVersion;

public function __construct($broker,$iopubSocket)
{
$this->broker = $broker;
$this->iopubSocket = $iopubSocket;

$this->reloadPlugins();
}
public function send($msgType, $data)
{
$this->broker->send($this->iopubSocket, $msgType, $data, $this->header);
}

public function setHeader($header)
{
$this->header = $header;
}

public function reloadPlugins()
{
$this->pluginVersion = str_replace('.','',microtime(true));
}

private function getObject($name)
{
$namespace = str_replace('.','','SpecialDimension_'.$this->pluginVersion);
$className = "{$namespace}\\{$name}";

if(!class_exists($className))
{
$fileName = __DIR__."/zPHP/{$name}.php";
$classBody = "namespace {$namespace}; ?>".file_get_contents($fileName);

eval($classBody);
}

$className = "{$namespace}\\{$name}";
$object = new $className($this);
return $object;
}

public function __call($className,$params)
{
$object = $this->getObject($className);

call_user_func_array($object,$params);
}

public function imageWorks($imageData)
{
$image = imagecreatefromstring($imageData);

$width = imagesx($image);
$height = imagesy($image);

ob_start();
imagepng($image);
$imageData = ob_get_clean();

$this->send(
'display_data',
[
'data'=>[
'image/png'=>base64_encode($imageData)
],
'metadata'=>[
'image/png'=>[
'width'=>$width,
'height'=>$height
]
]
]
);
}

public function htmlWorks($htmlData)
{
$this->send(
'display_data',
[
'data'=>[
'text/html'=>$htmlData
],
'metadata'=>[]
]
);
}

public function imageDummy()
{
$this->send(
'display_data',
[
'data'=>[
'image/gif'=>'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'
],
'metadata'=>[
'image/gif'=>[
'width'=>64,
'height'=>48
]
]
]
);
}
public function vegaDummy($mime)
{
$this->send(
'display_data',
[
'data'=>[
$mime=>file_get_contents('a1.vega')
],
'metadata'=>[]
]
);
}
}
32 changes: 32 additions & 0 deletions src/zPHP/HTML.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

/**
* Author: Zbigniew 'zibi' Jarosik <zibi@nora.pl>
*/

use JupyterPHP\zPHP;

class HTML
{
/** @var JupyterPHP\zPHP */
private $zPHP;

public function __construct(zPHP $zPHP)
{
$this->zPHP = $zPHP;
}
public function __invoke($htmlData)
{
$this->zPHP->send(
'display_data',
[
'data'=>[
'text/html'=>$htmlData
],
'metadata'=>[]
]
);
}


}
45 changes: 45 additions & 0 deletions src/zPHP/Image.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php

/**
* Author: Zbigniew 'zibi' Jarosik <zibi@nora.pl>
*/

use JupyterPHP\zPHP;

class Image
{
/** @var JupyterPHP\zPHP */
private $zPHP;

public function __construct(zPHP $zPHP)
{
$this->zPHP = $zPHP;
}

public function __invoke($imageData)
{
$image = imagecreatefromstring($imageData);

$width = imagesx($image);
$height = imagesy($image);

ob_start();
imagepng($image);
$imageData = ob_get_clean();

$this->zPHP->send(
'display_data',
[
'data'=>[
'image/png'=>base64_encode($imageData)
],
'metadata'=>[
'image/png'=>[
'width'=>$width,
'height'=>$height
]
]
]
);
}
}
46 changes: 46 additions & 0 deletions src/zPHP/Vega.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?php

/**
* Author: Zbigniew 'zibi' Jarosik <zibi@nora.pl>
*/

use JupyterPHP\zPHP;

class Vega
{
/** @var \Litipk\JupyterPHP\zPHP */
private $zPHP;

public function __construct(zPHP $zPHP)
{
$this->zPHP = $zPHP;
}
public function __invoke()
{
$this->zPHP->send(
'display_data',
[
'data'=>[
"application/vnd.vegalite.v2+json"=>json_decode('{
"$schema": "https://vega.github.io/schema/vega-lite/v2.json",
"description": "A simple bar chart with embedded data.",
"data": {
"values": [
{"a": "A", "b": 28}, {"a": "B", "b": 55}, {"a": "C", "b": 43},
{"a": "D", "b": 91}, {"a": "E", "b": 81}, {"a": "F", "b": 53},
{"a": "G", "b": 91}, {"a": "H", "b": 87}, {"a": "I", "b": 52}
]
},
"mark": "bar",
"encoding": {
"x": {"field": "a", "type": "ordinal"},
"y": {"field": "b", "type": "quantitative"}
}
}'),
"text/plain"=> "<VegaLite 2 object> If you see this message, it means the renderer has not been properly enabled for the frontend that you are using. For more information, see https://altair-viz.github.io/user_guide/troubleshooting.html "
],
'metadata'=>[]
]
);
}
}