10000 Hooks not working on REPL Run button · Issue #2320 · pyscript/pyscript · GitHub
[go: up one dir, main page]

Skip to content

Hooks not working on REPL Run button #2320

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
3 tasks done
limitcracker opened this issue Mar 26, 2025 · 21 comments · Fixed by #2329
Closed
3 tasks done

Hooks not working on REPL Run button #2320

limitcracker opened this issue Mar 26, 2025 · 21 comments · Fixed by #2329
Labels
needs-triage Issue needs triage type: bug Something isn't working

Comments

@limitcracker
Copy link
limitcracker commented Mar 26, 2025

Checklist

  • I added a descriptive title
  • I searched for other issues and couldn't find a solution or duplication
  • I already searched in Google and didn't find any good information or help

What happened?

I want to make a student Python IDE using the default REPL of PyScript and when the student writes, runs his code to be able to test his code against premade test cases. I want also the test cases to not be visible to the student. But hooks do not work on <script type="py-editor" env="test"> see full code below:

<!DOCTYPE html>
<html>
<head>
    <title>Python Test Cases</title>
    <link rel="stylesheet" href="https://pyscript.net/releases/2025.3.1/core.css">
    <script type="module" src="https://pyscript.net/releases/2025.3.1/core.js"></script>
    <style>
        body {
            font-family: Arial, sans-serif;
            max-width: 800px;
            margin: 0 auto;
            padding: 20px;
        }
        #test-results {
            margin-top: 20px;
            padding: 15px;
            border: 1px solid #ddd;
            border-radius: 5px;
            background-color: #f9f9f9;
        }
        .test-case {
            margin-bottom: 10px;
            padding: 10px;
            border-left: 4px solid #ddd;
        }
        .test-pass {
            border-left-color: #4CAF50;
            background-color: #e8f5e9;
        }
        .test-fail {
            border-left-color: #f44336;
            background-color: #ffebee;
        }
    </style>
</head>
<body>
    <h1>Python Test Cases</h1>
    
    <!-- Student's visible code editor -->
    <script type="py-editor" id="student-code" env="student">
def add_numbers(a, b):
    # Your code here
    return a + b
    </script>
    
    <!-- Test results display -->
    <div id="test-results">
        <h3>Test Results</h3>
        <div id="test-output">Click Run to test your code</div>
    </div>

    <!-- Test runner -->
    <script type="py" env="student">
from js import document, console
from pyodide.ffi import create_proxy
import asyncio

# Test cases
tests = [
    ((2, 3), 5, "Basic addition"),
    ((0, 0), 0, "Adding zeros"),
    ((-1, 1), 0, "Negative number"),
    ((10, -5), 5, "Larger numbers")
]

async def run_tests():
    test_output = document.getElementById("test-output")
    test_output.innerHTML = "Running tests..."
    await asyncio.sleep(0.1)
    
    try:
        results = []
        passed = 0
        
        for inputs, expected, desc in tests:
            try:
                result = add_numbers(*inputs)
                if result == expected:
                    results.append(f'<div class="test-case test-pass">✅ {desc}: add_numbers{inputs} = {expected}</div>')
                    passed += 1
                else:
                    results.append(f'<div class="test-case test-fail">❌ {desc}: Expected {expected}, got {result}</div>')
            except Exception as e:
                results.append(f'<div class="test-case test-fail">❌ {desc}: Error - {str(e)}</div>')
        
        # Show results
        test_output.innerHTML = ''.join(results)
        summary = f'<div style="margin-top: 10px"><b>Score: {passed}/{len(tests)} tests passed</b></div>'
        if passed == len(tests):
            summary += '<div style="color: #4CAF50">🎉 All tests passed! Great job!</div>'
        else:
            summary += '<div style="color: #f44336">⚠️ Some tests failed. Keep trying!</div>'
        test_output.innerHTML += summary
        
    except Exception as e:
        test_output.innerHTML = f'<div class="test-fail">Error running tests: {str(e)}</div>'

# Run tests after each execution
document.addEventListener("py:editor:afterExecute", create_proxy(lambda _: asyncio.ensure_future(run_tests())))
    </script>

</body>
</html>

Any ideas why ?

What browsers are you seeing the problem on? (if applicable)

No response

Console info

Additional Context

No response

@limitcracker limitcracker added needs-triage Issue needs triage type: bug Something isn't working labels Mar 26, 2025
@WebReflection
Copy link
Contributor

what do you mean by "hooks don't work" ? also, we have a setup attribute to do things before any other same env starts ... have you tried using a setup py-editor variant? it's in our docs

@limitcracker
Copy link
Author
limitcracker commented Mar 27, 2025

what do you mean by "hooks don't work" ? also, we have a setup attribute to do things before any other same env starts ... have you tried using a setup py-editor variant? it's in our docs

Hi, yes tried it but I want to Run some code after the Run button of REPL is pressed. (to test the written code in repl)

<script type="py-editor" ..> notation or older <py-repl> notation do not work with when decorator or other hooks on doc guides.

Any ideas why?

@WebReflection
Copy link
Contributor

could you please provide an extremely minimal example of what you are after? hooks have a different meaning in current PyScript and <py-repl> is a completely different thing ... also remember that a button on the page is still a button, you can use the setup script to reach that button and add a listener after it's clicked to do something else ... you can grab the xworker reference too from the script so basically I am saying you have full control of everything but I think I am not understanding your example.

@limitcracker
Copy link
Author

could you please provide an extremely minimal example of what you are after? hooks have a different meaning in current PyScript and <py-repl> is a completely different thing ... also remember that a button on the page is still a button, you can use the setup script to reach that button and add a listener after it's clicked to do something else ... you can grab the xworker reference too from the script so basically I am saying you have full control of everything but I think I am not understanding your example.

Here's a complete HTML file with a PyScript REPL that includes a test case when the student presses the Run button. This uses the <script type="py-editor"> notation:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>PyScript REPL with Test Case</title>
    <link rel="stylesheet" href="https://pyscript.net/releases/2024.1.1/core.css">
    <script type="module" src="https://pyscript.net/releases/2024.1.1/core.js"></script>
    <style>
        body {
            font-family: Arial, sans-serif;
            line-height: 1.6;
            margin: 0;
            padding: 20px;
            max-width: 800px;
            margin: 0 auto;
        }
        .task {
            background-color: #f5f5f5;
            padding: 15px;
            border-radius: 5px;
            margin-bottom: 20px;
        }
        .test-results {
            margin-top: 20px;
            padding: 15px;
            border-radius: 5px;
        }
        .pass {
            background-color: #d4edda;
            color: #155724;
        }
        .fail {
            background-color: #f8d7da;
            color: #721c24;
        }
    </style>
</head>
<body>
    <h1>Python Code Exercise</h1>
    
    <div class="task">
        <h2>Task</h2>
        <p>Write a function called <code>add_numbers(a, b)</code> that takes two numbers as arguments and returns their sum.</p>
    </div>

    <script type="py-editor">
def add_numbers(a, b):
    # Write your code here
    return a + b

# Test case - this will run when you click "Run"
test_result = add_numbers(3, 5)
expected_result = 8

if test_result == expected_result:
    print(f"✅ Test passed! Got {test_result} as expected.")
else:
    print(f"❌ Test failed. Expected {expected_result}, but got {test_result}.")
    </script>

    <div id="test-results" class="test-results" style="display: none;"></div>

    <script type="py">
        from js import document
        from pyodide.ffi import create_proxy
        
        def display_test_results(event):
            test_results_div = document.getElementById("test-results")
            test_results_div.style.display = "block"
            
            # This would be more sophisticated in a real implementation
            # Here we just check if the output contains "✅" or "❌"
            output = event.detail.output
            if "✅" in output:
                test_results_div.className = "test-results pass"
                test_results_div.innerHTML = "<h3>Test Results</h3><p>Good job! Your code passed the test.</p>"
            else:
                test_results_div.className = "test-results fail"
                test_results_div.innerHTML = "<h3>Test Results</h3><p>Your code didn't pass the test. Check the output above for details.</p>"
        
        document.addEventListener("py-editor-ready", create_proxy(display_test_results))
    </script>
</body>
</html>

@WebReflection
Copy link
Contributor

so ... you use https://pyscript.net/releases/2024.1.1/core.js while we are at https://pyscript.net/releases/2025.3.1/core.js ... that's the first issue, but I meant something that has no CSS, no nothing else around your expectations ... something like "write 1 + 1" that, once pressed, doesn't do what you want it to do ... after updating to latest too, as we don't backport to 1+ years old code fixes, thank you

@limitcracker
Copy link
Author

so ... you use https://pyscript.net/releases/2024.1.1/core.js while we are at https://pyscript.net/releases/2025.3.1/core.js ... that's the first issue, but I meant something that has no CSS, no nothing else around your expectations ... something like "write 1 + 1" that, once pressed, doesn't do what you want it to do ... after updating to latest too, as we don't backport to 1+ years old code fixes, thank you

sorry didn't quite understand you. I might have css in there but the main point is to run code on the event of pressing Run Repl button (more specifically after the code of repl have finished running). Is there such an event to hook onto in PyScript?

@WebReflection
Copy link
Contributor

pyscript has py:done but py-editor, which is a custom type, doesn't have a py-editor:done event, also because with the env variant it'd be hard to reason about which script/worker has done, and which hasn't ... all solvable though ... how would you like the flow to be and what do you expect in such done event?

@limitcracker
Copy link
Author

pyscript has py:done but py-editor, which is a custom type, doesn't have a py-editor:done event, also because with the env variant it'd be hard to reason about which script/worker has done, and which hasn't ... all solvable though ... how would you like the flow to be and what do you expect in such done event?

I would like the following scenario:

  • Student writes his python code in REPL
  • Presses the Run button
  • When the code in REPL has finished running
  • A simple test function to start running to check the result of the code that had finished (i.e. an assert of a variable)
  • Write a message (fail or pass) on output

@WebReflection
Copy link
Contributor
WebReflection commented Apr 3, 2025

@limitcracker the last two points are too specific ... you can attach an event listener and do both or something else completely different, which is what we should offer, imho, we can't change code per each specific use case, I hope we agree there.

Would a bubbling py-editor:done event with the source script that was done be enough? It allows you to do what you are after already, it's up to you to do more or less within such event ... would that work?

@limitcracker
Copy link
Author

@limitcracker the last two points are too specific ... you can attach an event listener and do both or something else completely different, which is what we should offer, imho, we can't change code per each specific use case, I hope we agree there.

Would a bubbling py-editor:done event with the source script that was done be enough? It allows you to do what you are after already, it's up to you to do more or less within such event ... would that work?

I am trying to 8000 get a working example with the solution you provide but really does not work!
Could you provide me a really simple example?

Thanks in advance!

@WebReflection
Copy link
Contributor

@limitcracker it doesn't work because it's not implemented yet ...

@limitcracker
Copy link
Author
limitcracker commented Apr 7, 2025

@limitcracker it doesn't work because it's not implemented yet ...

Nice! Any ETA? Can I use any of the existing ones as alternative in the meanwhile?

@WebReflection
Copy link
Contributor

py-editor is a type a part, it shares nothing with py in terms of events and there is no event for what you need so ... I am afraid the answer is no

@WebReflection
Copy link
Contributor

MR up and running (linked above) ... it triggers a py-editor:done event when an editor finishes working. It provides the original script that created the editor as target so you can get the editor target, its code and whatnot we expose already.

@limitcracker
Copy link
Author

MR up and running (linked above) ... it triggers a py-editor:done event when an editor finishes working. It provides the original script that created the editor as target so you can get the editor target, its code and whatnot we expose already.

I am trying to use py-editor:done but I cannot make it to work. Any hints or a ready made example to tweak/test? Thanks once again for your help!

@WebReflection
Copy link
Contributor

we haven't released yet

@limitcracker
Copy link
Author

we haven't released yet

tried a simple example but py-editor:done does not seem to work. See example below:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <title>PyScript Editor Example</title>
  <link rel="stylesheet" href="https://pyscript.net/2025.3.1/pyscript.css" />
  <script defer src="https://pyscript.net/2025.3.1/pyscript.js"></script>
</head>
<body>

  <h2>Python REPL</h2>

  <!-- PyScript Editor -->
  <script type="py-editor" id="my-editor">
print("Hello from PyScript!")
  </script>

  <!-- Output area -->
  <div id="output" style="margin-top: 1em; font-weight: bold;"></div>

  <!-- JS to listen for 'py-editor:done' -->
  <script>
    addEventListener("py:ready", () => {
      const editor = document.getElementById("my-editor");

      editor.addEventListener("py-editor:done", () => {
        const outputDiv = document.getElementById("output");
        outputDiv.textContent = "✅ Python code execution finished!";
      });
    });
  </script>

</body>
</html>

@WebReflection
Copy link
Contributor

@limitcracker ... we haven't released yet means: until we release, you will never see that event happening.

We will release not this week but the next one, then you'll need to update and see that even happening. You don't even need to use 2 listeners as events bubble up ... you will have a top level (window) py-editor:done event per each script and each run but not until we release.

@limitcracker
Copy link
Author

@limitcracker ... we haven't released yet means: until we release, you will never see that event happening.

We will release not this week but the next one, then you'll need to update and see that even happening. You don't even need to use 2 listeners as events bubble up ... you will have a top level (window) py-editor:done event per each script and each run but not until we release.

Sorry I saw this that's why I thought it was released.

Image

@WebReflection
Copy link
Contributor

merged on main does not mean it's released ... we do have releases when we release, but I'll try to remember to directly notify this thread once that happens, apologies for the confusion.

@WebReflection
Copy link
Contributor

FYI we just released, apologies for the delay, thank you for your patience.

That is: https://pyscript.net/releases/2025.5.1/core.js and https://pyscript.net/releases/2025.5.1/core.css

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
needs-triage Issue needs triage type: bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants
0