mirror of
https://github.com/pyscript/pyscript.git
synced 2025-12-22 19:53:00 -05:00
Add display impl, rm outputManage, print and console.log default to browser console (#749)
* Add display impl, remove outputManage, print and console.log defaults to terminal * Fixing tests * Lint * Erase unecessary code, add cuter CSS formating for errors, fix problems around REPL output * Add fix to repl2 and lint * lint * Allow for list of display, fix elif to else * Add better global option * test work * xfails * (antocuni, mariana): let's try to start again with TDD methodology: write the minimum test and code for a simple display() * (antocuni, mariana): this test works out of the box * WIP: this test is broken, mariana is going to fix it * add a failing test * Add ability to deal with targets * Add append arg and append tests * Add multiple values to display * Small adjustments to tests. I noticed I wasn;t running all at some point * add display test * Add console tests * Add async tests * Fix repl tests * Fixing merging issues * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Address antocuni's review * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Fixing more tests * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * linting * Improve repl tests * Change my test so codespell is hapy with it * Test: change test_runtime_config to use json instead of toml to see if stops failing on CI * kill this file: it is a merge artifact since it was renamed into test_py_config.py on the main branch * Change test execution order and add async tests to async test file Co-authored-by: Antonio Cuni <anto.cuni@gmail.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit is contained in:
@@ -111,45 +111,19 @@ export class BaseEvalElement extends HTMLElement {
|
||||
this.preEvaluate();
|
||||
|
||||
let source: string;
|
||||
let output: string;
|
||||
try {
|
||||
source = this.source ? await this.getSourceFromFile(this.source)
|
||||
: this.getSourceFromElement();
|
||||
|
||||
this._register_esm(runtime);
|
||||
<string>await runtime.run(
|
||||
`output_manager.change(out="${this.outputElement.id}", err="${this.errorElement.id}", append=${this.appendOutput ? 'True' : 'False'})`,
|
||||
);
|
||||
output = <string>await runtime.run(source);
|
||||
|
||||
if (output !== undefined) {
|
||||
if (Element === undefined) {
|
||||
Element = <Element>runtime.globals.get('Element');
|
||||
}
|
||||
const out = Element(this.outputElement.id);
|
||||
out.write.callKwargs(output, { append: this.appendOutput });
|
||||
|
||||
this.outputElement.hidden = false;
|
||||
this.outputElement.style.display = 'block';
|
||||
try {
|
||||
<string>await runtime.run(`set_current_display_target(target_id="${this.id}")`);
|
||||
<string>await runtime.run(source);
|
||||
} finally {
|
||||
<string>await runtime.run(`set_current_display_target(target_id=None)`);
|
||||
}
|
||||
|
||||
await runtime.run(`output_manager.revert()`);
|
||||
|
||||
// check if this REPL contains errors, delete them and remove error classes
|
||||
const errorElements = document.querySelectorAll(`div[id^='${this.errorElement.id}'][error]`);
|
||||
if (errorElements.length > 0) {
|
||||
errorElements.forEach( errorElement =>
|
||||
{
|
||||
errorElement.classList.add('hidden');
|
||||
if (this.hasAttribute('std-err')) {
|
||||
this.errorElement.hidden = true;
|
||||
this.errorElement.style.removeProperty('display');
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
removeClasses(this.errorElement, ['bg-red-200', 'p-2']);
|
||||
|
||||
removeClasses(this.errorElement, ['py-error']);
|
||||
this.postEvaluate();
|
||||
} catch (err) {
|
||||
logger.error(err);
|
||||
@@ -159,7 +133,7 @@ export class BaseEvalElement extends HTMLElement {
|
||||
}
|
||||
const out = Element(this.errorElement.id);
|
||||
|
||||
addClasses(this.errorElement, ['bg-red-200', 'p-2']);
|
||||
addClasses(this.errorElement, ['py-error']);
|
||||
out.write.callKwargs(err.toString(), { append: this.appendOutput });
|
||||
if (this.errorElement.children.length === 0){
|
||||
this.errorElement.setAttribute('error', '');
|
||||
|
||||
@@ -89,34 +89,6 @@ export function make_PyWidget(runtime: Runtime) {
|
||||
createWidget(runtime, this.name, this.code, this.klass);
|
||||
}
|
||||
|
||||
initOutErr(): void {
|
||||
if (this.hasAttribute('output')) {
|
||||
this.errorElement = this.outputElement = document.getElementById(this.getAttribute('output'));
|
||||
|
||||
// in this case, the default output-mode is append, if hasn't been specified
|
||||
if (!this.hasAttribute('output-mode')) {
|
||||
this.setAttribute('output-mode', 'append');
|
||||
}
|
||||
} else {
|
||||
if (this.hasAttribute('std-out')) {
|
||||
this.outputElement = document.getElementById(this.getAttribute('std-out'));
|
||||
} else {
|
||||
// In this case neither output or std-out have been provided so we need
|
||||
// to create a new output div to output to
|
||||
this.outputElement = document.createElement('div');
|
||||
this.outputElement.classList.add('output');
|
||||
this.outputElement.hidden = true;
|
||||
this.outputElement.id = this.id + '-' + this.getAttribute('exec-id');
|
||||
}
|
||||
|
||||
if (this.hasAttribute('std-err')) {
|
||||
this.errorElement = document.getElementById(this.getAttribute('std-err'));
|
||||
} else {
|
||||
this.errorElement = this.outputElement;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async getSourceFromFile(s: string): Promise<string> {
|
||||
const response = await fetch(s);
|
||||
return await response.text();
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import asyncio
|
||||
import base64
|
||||
import io
|
||||
import sys
|
||||
import time
|
||||
from textwrap import dedent
|
||||
|
||||
@@ -124,6 +123,33 @@ class PyScript:
|
||||
)
|
||||
|
||||
|
||||
def set_current_display_target(target_id):
|
||||
get_current_display_target._id = target_id
|
||||
|
||||
|
||||
def get_current_display_target():
|
||||
return get_current_display_target._id
|
||||
|
||||
|
||||
get_current_display_target._id = None
|
||||
|
||||
|
||||
def display(*values, target=None, append=True):
|
||||
default_target = get_current_display_target()
|
||||
|
||||
if default_target is None and target is None:
|
||||
raise Exception(
|
||||
"Implicit target not allowed here. Please use display(..., target=...)"
|
||||
)
|
||||
|
||||
if target is not None:
|
||||
for v in values:
|
||||
Element(target).write(v, append=append)
|
||||
else:
|
||||
for v in values:
|
||||
Element(default_target).write(v, append=append)
|
||||
|
||||
|
||||
class Element:
|
||||
def __init__(self, element_id, element=None):
|
||||
self._id = element_id
|
||||
@@ -365,59 +391,4 @@ class PyListTemplate:
|
||||
pass
|
||||
|
||||
|
||||
class OutputCtxManager:
|
||||
def __init__(self, out=None, output_to_console=True, append=True):
|
||||
self._out = out
|
||||
self._prev = out
|
||||
self.output_to_console = output_to_console
|
||||
self._append = append
|
||||
|
||||
def change(self, out=None, output_to_console=True, append=True):
|
||||
self._prev = self._out
|
||||
self._out = out
|
||||
self.output_to_console = output_to_console
|
||||
self._append = append
|
||||
|
||||
def revert(self):
|
||||
self._out = self._prev
|
||||
|
||||
def write(self, value):
|
||||
if self._out:
|
||||
Element(self._out).write(value, self._append)
|
||||
|
||||
if self.output_to_console:
|
||||
console.info(value)
|
||||
|
||||
|
||||
class OutputManager:
|
||||
def __init__(self, out=None, err=None, output_to_console=True, append=True):
|
||||
sys.stdout = self._out_manager = OutputCtxManager(
|
||||
out=out, output_to_console=output_to_console, append=append
|
||||
)
|
||||
sys.stderr = self._err_manager = OutputCtxManager(
|
||||
out=err, output_to_console=output_to_console, append=append
|
||||
)
|
||||
self.output_to_console = output_to_console
|
||||
self._append = append
|
||||
|
||||
def change(self, out=None, err=None, output_to_console=True, append=True):
|
||||
self._out_manager.change(
|
||||
out=out, output_to_console=output_to_console, append=append
|
||||
)
|
||||
sys.stdout = self._out_manager
|
||||
self._err_manager.change(
|
||||
out=err, output_to_console=output_to_console, append=append
|
||||
)
|
||||
sys.stderr = self._err_manager
|
||||
self.output_to_console = output_to_console
|
||||
self._append = append
|
||||
|
||||
def revert(self):
|
||||
self._out_manager.revert()
|
||||
self._err_manager.revert()
|
||||
sys.stdout = self._out_manager
|
||||
sys.stderr = self._err_manager
|
||||
|
||||
|
||||
pyscript = PyScript()
|
||||
output_manager = OutputManager()
|
||||
|
||||
@@ -89,6 +89,7 @@ html {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
color: #0f172a;
|
||||
.py-pop-up {
|
||||
text-align: center;
|
||||
width: 600px;
|
||||
@@ -107,7 +108,16 @@ html {
|
||||
right: 5%;
|
||||
}
|
||||
|
||||
.py-box {
|
||||
/* Pop-up second layer end */
|
||||
|
||||
.py-error{
|
||||
background-color: rgb(254 226 226);
|
||||
border: solid;
|
||||
border-color: #fca5a5;
|
||||
color: #ff0000;
|
||||
}
|
||||
|
||||
.py-box{
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: flex-start;
|
||||
|
||||
Reference in New Issue
Block a user