Skip to content

Commit 856d61b

Browse files
committed
Merge from main
1 parent 56b7770 commit 856d61b

File tree

8 files changed

+101
-95
lines changed

8 files changed

+101
-95
lines changed

.pre-commit-config.yaml

Lines changed: 11 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -46,52 +46,14 @@ repos:
4646
- id: prettier
4747
args: [--tab-width, "4"]
4848

49-
- repo: https://github.com/PyCQA/flake8
50-
rev: 6.0.0
51-
hooks:
52-
- id: flake8 # See 'setup.cfg' for args
53-
additional_dependencies: [flake8-bugbear, flake8-comprehensions]
54-
55-
- repo: https://github.com/pycqa/isort
56-
rev: 5.12.0
57-
hooks:
58-
- id: isort
59-
name: isort (python)
60-
args: [--profile, black]
61-
62-
- repo: https://github.com/macisamuele/language-formatters-pre-commit-hooks
63-
rev: v2.6.0
64-
hooks:
65-
- id: pretty-format-yaml
66-
args: [--autofix, --indent, '4']
67-
exclude: .github/ISSUE_TEMPLATE/.*\.yml$
68-
69-
- repo: https://github.com/asottile/pyupgrade
70-
rev: v3.3.1
71-
hooks:
72-
- id: pyupgrade
73-
args:
74-
- --py310-plus
75-
76-
- repo: https://github.com/pre-commit/mirrors-eslint
77-
rev: v8.33.0
78-
hooks:
79-
- id: eslint
80-
files: pyscriptjs/src/.*\.[jt]sx?$ # *.js, *.jsx, *.ts and *.tsx
81-
types: [file]
82-
additional_dependencies:
83-
- eslint@8.25.0
84-
- typescript@4.8.4
85-
- '@typescript-eslint/eslint-plugin@5.39.0'
86-
- '@typescript-eslint/parser@5.39.0'
87-
88-
# Commented out until mdformat-myst supports custom extensions
89-
# See https://github.com/executablebooks/mdformat-myst/pull/9
90-
# - repo: https://github.com/executablebooks/mdformat
91-
# rev: 0.7.14 # Use the ref you want to point at
92-
# hooks:
93-
# - id: mdformat
94-
# additional_dependencies:
95-
# - mdformat-gfm
96-
# - mdformat-myst
97-
# - mdformat-black
49+
- repo: https://github.com/pre-commit/mirrors-eslint
50+
rev: v8.35.0
51+
hooks:
52+
- id: eslint
53+
files: pyscriptjs/src/.*\.[jt]sx?$ # *.js, *.jsx, *.ts and *.tsx
54+
types: [file]
55+
additional_dependencies:
56+
- eslint@8.25.0
57+
- typescript@4.8.4
58+
- "@typescript-eslint/eslint-plugin@5.39.0"
59+
- "@typescript-eslint/parser@5.39.0"

docs/development/developing.md

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -84,15 +84,7 @@ Documentation
8484

8585
## Quick guide to pytest
8686

87-
## Rebasing changes
88-
89-
Sometimes you might be asked to rebase main into your branch. Please refer to this [section on git rebase from GitHub docs](https://docs.github.com/en/get-started/using-git/about-git-rebase).
90-
91-
If you need help with anything, feel free to reach out and ask for help!
92-
93-
## pytest quick guide
94-
95-
We make a heavy usage of `pytest`. Here is a quick guide and collection of
87+
We make heavy usage of `pytest`. Here is a quick guide and collection of
9688
useful options:
9789

9890
- To run all tests in the current directory and subdirectories: `pytest`

pyscriptjs/src/components/elements.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import type { PyScriptApp } from '../main';
21
import { InterpreterClient } from '../interpreter_client';
2+
import type { PyScriptApp } from '../main';
33
import { make_PyRepl } from './pyrepl';
44
import { make_PyWidget } from './pywidget';
55

pyscriptjs/src/components/pyrepl.ts

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import { Stdio } from '../stdio';
1616
const logger = getLogger('py-repl');
1717
const RUNBUTTON = `<svg style="height:20px;width:20px;vertical-align:-.125em;transform-origin:center;overflow:visible;color:green" viewBox="0 0 384 512" aria-hidden="true" role="img" xmlns="http://www.w3.org/2000/svg"><g transform="translate(192 256)" transform-origin="96 0"><g transform="translate(0,0) scale(1,1)"><path d="M361 215C375.3 223.8 384 239.3 384 256C384 272.7 375.3 288.2 361 296.1L73.03 472.1C58.21 482 39.66 482.4 24.52 473.9C9.377 465.4 0 449.4 0 432V80C0 62.64 9.377 46.63 24.52 38.13C39.66 29.64 58.21 29.99 73.03 39.04L361 215z" fill="currentColor" transform="translate(-192 -256)"></path></g></g></svg>`;
1818

19-
export function make_PyRepl(interpreter: InterpreterClient, app: PyScriptApp) {
19+
export function make_PyRepl(interpreter: InterpreterClient, app: PyScriptApp) {
2020
/* High level structure of py-repl DOM, and the corresponding JS names.
2121
2222
this <py-repl>
@@ -156,12 +156,19 @@ export function make_PyRepl(interpreter: InterpreterClient, app: PyScriptApp) {
156156
*/
157157
async execute(): Promise<void> {
158158
const pySrc = this.getPySrc();
159-
const outEl = this.outDiv
159+
const outEl = this.outDiv;
160160

161161
// execute the python code
162-
app.plugins.beforePyReplExec({interpreter: interpreter, src: pySrc, outEl: outEl, pyReplTag: this});
162+
app.plugins.beforePyReplExec({ interpreter: interpreter, src: pySrc, outEl: outEl, pyReplTag: this });
163+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
163164
const pyResult = (await pyExec(interpreter, pySrc, outEl)).result;
164-
app.plugins.afterPyReplExec({interpreter: interpreter, src: pySrc, outEl: outEl, pyReplTag: this, result: pyResult});
165+
app.plugins.afterPyReplExec({
166+
interpreter: interpreter,
167+
src: pySrc,
168+
outEl: outEl,
169+
pyReplTag: this,
170+
result: pyResult, // eslint-disable-line @typescript-eslint/no-unsafe-assignment
171+
});
165172

166173
this.autogenerateMaybe();
167174
}
@@ -182,7 +189,7 @@ export function make_PyRepl(interpreter: InterpreterClient, app: PyScriptApp) {
182189
const newPyRepl = document.createElement('py-repl');
183190

184191
//Attributes to be copied from old REPL to auto-generated REPL
185-
for (const attribute of ['root', 'output-mode', 'output', 'stderr']){
192+
for (const attribute of ['root', 'output-mode', 'output', 'stderr']) {
186193
const attr = getAttribute(this, attribute);
187194
if (attr) {
188195
newPyRepl.setAttribute(attribute, attr);

pyscriptjs/src/plugin.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,9 @@ export class Plugin {
8888
* @param options.outEl The element that the result of the REPL evaluation will be output to.
8989
* @param options.pyReplTag The <py-repl> HTML tag the originated the evaluation
9090
*/
91-
beforePyReplExec(options: {interpreter: InterpreterClient, src: string, outEl: HTMLElement, pyReplTag: any}){}
91+
beforePyReplExec(options: { interpreter: InterpreterClient; src: string; outEl: HTMLElement; pyReplTag: any }) {
92+
/* empty */
93+
}
9294

9395
/**
9496
*
@@ -98,7 +100,15 @@ export class Plugin {
98100
* @param options.pyReplTag The <py-repl> HTML tag the originated the evaluation
99101
* @param options.result The result of evaluating the Python (if any)
100102
*/
101-
afterPyReplExec(options: {interpreter: InterpreterClient, src: string, outEl: HTMLElement, pyReplTag: HTMLElement, result: any}){}
103+
afterPyReplExec(options: {
104+
interpreter: InterpreterClient;
105+
src: string;
106+
outEl: HTMLElement;
107+
pyReplTag: HTMLElement;
108+
result: any;
109+
}) {
110+
/* empty */
111+
}
102112

103113
/** Startup complete. The interpreter is initialized and ready, user
104114
* scripts have been executed: the main initialization logic ends here and

pyscriptjs/src/plugins/stdiodirector.ts

Lines changed: 35 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import type { InterpreterClient } from "../interpreter_client";
44
import { createSingularWarning } from '../utils'
55
import { make_PyScript } from '../components/pyscript';
66
import { pyDisplay } from '../pyexec'
7+
import { make_PyRepl } from "../components/pyrepl";
78

89
type PyScriptTag = InstanceType<ReturnType<typeof make_PyScript>>;
910

@@ -61,63 +62,70 @@ export class StdioDirector extends Plugin {
6162
}
6263
}
6364

64-
beforePyReplExec(options: {interpreter: InterpreterClient, src: string, outEl: HTMLElement, pyReplTag: any}): void {
65+
beforePyReplExec(options: {
66+
interpreter: InterpreterClient;
67+
src: string;
68+
outEl: HTMLElement;
69+
pyReplTag: InstanceType<ReturnType<typeof make_PyRepl>>;
70+
}): void {
6571
//Handle 'output-mode' attribute (removed in PR #881/f9194cc8, restored here)
6672
//If output-mode == 'append', don't clear target tag before writing
67-
if (options.pyReplTag.getAttribute('output-mode') != 'append'){
68-
options.outEl.innerHTML = ''
73+
if (options.pyReplTag.getAttribute('output-mode') != 'append') {
74+
options.outEl.innerHTML = '';
6975
}
7076

7177
// Handle 'output' attribute; defaults to writing stdout to the existing outEl
7278
// If 'output' attribute is used, the DOM element with the specified ID receives
7379
// -both- sys.stdout and sys.stderr
74-
let output_targeted_io;
75-
if (options.pyReplTag.hasAttribute("output")){
76-
output_targeted_io = new TargetedStdio(options.pyReplTag, "output", true, true);
77-
}
78-
else {
79-
output_targeted_io = new TargetedStdio(options.pyReplTag.outDiv, "id", true, true);
80+
let output_targeted_io: TargetedStdio;
81+
if (options.pyReplTag.hasAttribute('output')) {
82+
output_targeted_io = new TargetedStdio(options.pyReplTag, 'output', true, true);
83+
} else {
84+
output_targeted_io = new TargetedStdio(options.pyReplTag.outDiv, 'id', true, true);
8085
}
8186
options.pyReplTag.stdout_manager = output_targeted_io;
8287
this._stdioMultiplexer.addListener(output_targeted_io);
8388

8489
//Handle 'stderr' attribute;
85-
if (options.pyReplTag.hasAttribute("stderr")){
86-
const stderr_targeted_io = new TargetedStdio(options.pyReplTag, "stderr", false, true);
90+
if (options.pyReplTag.hasAttribute('stderr')) {
91+
const stderr_targeted_io = new TargetedStdio(options.pyReplTag, 'stderr', false, true);
8792
options.pyReplTag.stderr_manager = stderr_targeted_io;
8893
this._stdioMultiplexer.addListener(stderr_targeted_io);
8994
}
90-
9195
}
9296

93-
afterPyReplExec(options: {interpreter: any, src: any, outEl: any, pyReplTag: any, result: any}): void {
97+
afterPyReplExec(options: {
98+
interpreter: InterpreterClient;
99+
src: string;
100+
outEl: HTMLElement;
101+
pyReplTag: InstanceType<ReturnType<typeof make_PyRepl>>;
102+
result: any; // eslint-disable-line @typescript-eslint/no-explicit-any
103+
}): void {
94104
// display the value of the last-evaluated expression in the REPL
95105
if (options.result !== undefined) {
96-
const outputId: string | undefined = options.pyReplTag.getAttribute("output")
106+
const outputId: string | undefined = options.pyReplTag.getAttribute('output');
97107
if (outputId) {
98108
// 'output' attribute also used as location to send
99109
// result of REPL
100-
if (document.getElementById(outputId)){
110+
if (document.getElementById(outputId)) {
101111
pyDisplay(options.interpreter, options.result, { target: outputId });
112+
} else {
113+
//no matching element on page
114+
createSingularWarning(`output = "${outputId}" does not match the id of any element on the page.`);
102115
}
103-
else { //no matching element on page
104-
createSingularWarning(`output = "${outputId}" does not match the id of any element on the page.`)
105-
}
106-
107-
}
108-
else {
116+
} else {
109117
// 'otuput atribuite not provided
110118
pyDisplay(options.interpreter, options.result, { target: options.outEl.id });
111119
}
112120
}
113121

114-
if (options.pyReplTag.stdout_manager != null){
115-
this._stdioMultiplexer.removeListener(options.pyReplTag.stdout_manager)
116-
options.pyReplTag.stdout_manager = null
122+
if (options.pyReplTag.stdout_manager != null) {
123+
this._stdioMultiplexer.removeListener(options.pyReplTag.stdout_manager);
124+
options.pyReplTag.stdout_manager = null;
117125
}
118-
if (options.pyReplTag.stderr_manager != null){
119-
this._stdioMultiplexer.removeListener(options.pyReplTag.stderr_manager)
120-
options.pyReplTag.stderr_manager = null
126+
if (options.pyReplTag.stderr_manager != null) {
127+
this._stdioMultiplexer.removeListener(options.pyReplTag.stderr_manager);
128+
options.pyReplTag.stderr_manager = null;
121129
}
122130
}
123131
}

pyscriptjs/tests/integration/test_py_repl.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -566,3 +566,30 @@ def test_repl_output_element_id_change(self):
566566
)
567567
alert_banner = self.page.locator(".alert-banner")
568568
assert expected_alert_banner_msg in alert_banner.inner_text()
569+
570+
def test_multiple_repls_mixed_display_order(self):
571+
"""
572+
Displaying several outputs that don't obey the order in which the original
573+
repl displays were created using the auto_generate attr
574+
"""
575+
self.pyscript_run(
576+
"""
577+
<py-repl auto-generate="true" data-testid=="first"> display("root first") </py-repl>
578+
<py-repl auto-generate="true" data-testid=="second"> display("root second") </py-repl>
579+
"""
580+
)
581+
582+
second_py_repl = self.page.get_by_text("root second")
583+
second_py_repl.click()
584+
self.page.keyboard.press("Shift+Enter")
585+
self.page.keyboard.type("display('second children')")
586+
self.page.keyboard.press("Shift+Enter")
587+
588+
first_py_repl = self.page.get_by_text("root first")
589+
first_py_repl.click()
590+
self.page.keyboard.press("Shift+Enter")
591+
self.page.keyboard.type("display('first children')")
592+
self.page.keyboard.press("Shift+Enter")
593+
594+
assert self.page.inner_text("#py-internal-1-1-repl-output") == "second children"
595+
assert self.page.inner_text("#py-internal-0-1-repl-output") == "first children"

pyscriptjs/tests/py-unit/conftest.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88

99
import pytest
1010

11-
# current working directory
12-
base_path = pathlib.Path().absolute()
11+
pyscriptjs = Path(__file__).parents[2]
12+
1313
# add pyscript folder to path
1414
python_source = pyscriptjs / "src" / "python"
1515
sys.path.append(str(python_source))

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy