Code Monkey home page Code Monkey logo

Comments (16)

WebReflection avatar WebReflection commented on June 4, 2024 1

@AlteriusOmega this was wrong:

"../geometry_generator.py": ".geometry_generator.py"

you forgot the slash ... this would be fine:

"../geometry_generator.py": "./geometry_generator.py"

but your solution, which does the same, is fine too.

The Element doesn't exist in current PyScript, it's been moved into the PyWeb module so you should from pyweb import Element but there's a lot of ongoing refactoring there so if you need an element, for the time being, import document from pyscript and then document.getElementById("interface") to read, change, or operate with that node.

I am closing as nothing seems to be a bug here but feel free to ask more if needed.

from pyscript.

WebReflection avatar WebReflection commented on June 4, 2024

I believe you are running a very outdated version of PyScript. You shold try with latest release, which is a JS module, not something that lands globally, and it has some different concept API behind.

Until then, or better, until you manage to tell us what doesn't work with current PyScript, not the legacy (classic) one, it's hard to help as we're not working on 2023.03.1 and we won't work on legacy PyScript these days (or ever).

from pyscript.

AlteriusOmega avatar AlteriusOmega commented on June 4, 2024

I believe you are running a very outdated version of PyScript. You shold try with latest release, which is a JS module, not something that lands globally, and it has some different concept API behind.

Until then, or better, until you manage to tell us what doesn't work with current PyScript, not the legacy (classic) one, it's hard to help as we're not working on 2023.03.1 and we won't work on legacy PyScript these days (or ever).

No I tried it with the current version of PyScript and still the same issue persisted:

<script type="module" src="https://pyscript.net/releases/2024.1.1/core.js"></script>

Also as I mentioned I also tried with pyscript-react which uses a recent version.
I updated the original post to reflect using the current version.

from pyscript.

JeffersGlass avatar JeffersGlass commented on June 4, 2024

The issue is that the [[fetch]] key tries to preserve existing folder hierarchy wherever possible, so that fetching ../some_file puts that file in the parent directory of the path where Python executes. Hence that module can't be found nor imported.

You can peek at the virtual filesystem to confirm this:

from pyscript import display
from pathlib import Path
from os import getcwd

def print_tree(path, prefix=''):
    for item in path.iterdir():
        display(f'{prefix}├── {item.name}')
        if item.is_dir():
            print_tree(item, prefix + '│   ')

display(f"{getcwd() =}")
print_tree(Path(".."))
getcwd() ='/home/pyodide'
├── web_user
├── pyodide <<< cwd when PyScript executes
│ ├── pyscript
│ │ ├── __init__.py
│ │ ├── display.py
│ │ ├── event_handling.py
│ │ ├── fetch.py
│ │ ├── ffi.py
│ │ ├── magic_js.py
│ │ ├── util.py
│ ├── pyweb
│ │ ├── __init__.py
│ │ ├── media.py
│ │ ├── pydom.py
├── geometry_generator.py <<< inside parent folder, can't be imported

While there are ways around this using the [[fetch]] key, I recommend changing to the more recent [files] key, which takes a list of URL = path_in_virtual_filesystem pairs:

<py-config>
    [files]
    "../geometry_generator.py" = "./geometry_generator.py"
</py-config>

from pyscript.

AlteriusOmega avatar AlteriusOmega commented on June 4, 2024

While there are ways around this using the [[fetch]] key, I recommend changing to the more recent [files] key, which takes a list of URL = path_in_virtual_filesystem pairs:

Thank you very much. I tried using [files] instead of [[fetch]] but I'm still getting the same error. This is what my current pyscript_config.toml looks like:

packages = ["svgwrite"]

[files]
"../geometry_generator.py" = ".geometry_generator.py"

I'm currently trying to get this working with pyscript-react. However, I notice that it lists an old version when the page loads. Here is the pyscript config-loaded message:

[pyscript/main] config loaded:
{
  "type": "app",
  "execution_thread": "main",
  "schema_version": 1,
  "runtimes": [],
  "interpreters": [
    {
      "src": "https://cdn.jsdelivr.net/pyodide/v0.23.2/full/pyodide.js",
      "name": "pyodide-0.23.2",
      "lang": "python"
    }
  ],
  "packages": [
    "svgwrite"
  ],
  "fetch": [],
  "plugins": [],
  "files": {
    "../geometry_generator.py": ".geometry_generator.py"
  },
  "pyscript": {
    "version": "2022.12.1.dev",
    "time": "2024-05-01T00:52:26.926Z"
  }
}

I will try it out with the current vanilla pyscript shortly

from pyscript.

AlteriusOmega avatar AlteriusOmega commented on June 4, 2024

OK @JeffersGlass I tried using [files] instead of [[fetch]] using the most recent version of vanilla pyscript and I'm still getting the ModuleNotFound error. I am also not seeing anything showing that it loaded or even tried to load the file:


GET
http://127.0.0.1:5500/images/favicon.ico
[HTTP/1.1 404 Not Found 1ms]

Loading micropip, packaging pyodide.asm.js:9:111847
Loaded packaging, micropip pyodide.asm.js:9:112111
Loading svgwrite pyodide.asm.js:9:111847
Loaded svgwrite pyodide.asm.js:9:112111
[pyscript/main] PyScript Ready 2 core.js:194:32
in getPolygonSize and about to return Infinity,Infinity,-Infinity,-Infinity geometry_generator.html:78:29
PythonError: Traceback (most recent call last):
  File "/lib/python311.zip/_pyodide/_base.py", line 499, in eval_code
    .run(globals, locals)
     ^^^^^^^^^^^^^^^^^^^^
  File "/lib/python311.zip/_pyodide/_base.py", line 340, in run
    coroutine = eval(self.code, globals, locals)
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<exec>", line 45, in <module>
ImportError: cannot import name 'Element' from 'pyscript' (/home/pyodide/pyscript/__init__.py)
    k pyodide.asm.js:9
    new_error pyodide.asm.js:9
    _pythonexc2js pyodide.asm.js:9
    callPyObjectKwargs pyodide.asm.js:9
    callKwargs pyodide.asm.js:9
    runPython pyodide.asm.js:9
    Nt _python.js:12
    t utils.js:61
    nn/e[i]< hooks.js:65
    run utils.js:53
    connectedCallback core.js:304
    async* core.js:271
    promise callback* core.js:133
error.js:15:15
    stderr error.js:15
    Nt _python.js:15
    t utils.js:61
    nn/e[i]< hooks.js:65
    run utils.js:53
    connectedCallback core.js:304
    <anonymous> core.js:271
    (Async: promise callback)
    <anonymous> core.js:133

Actually it doesn't matter if I use [files] as you showed or [[fetch]] as I had before, I get the exact same console output. Even if I remove that section entirely from the config file and leave only the packages section, the console output is the same. It's like its completely ignoring that part.
I know its not ignoring it though because if I put in a bogus file name I get a 404 error. So it's reading the files section correctly and finding the file. It just isn't loading it as a module that's accessible for some reason.

from pyscript.

AlteriusOmega avatar AlteriusOmega commented on June 4, 2024

Update I finally got it to recognize the module, just had do adjust the paths from what @JeffersGlass suggested. Below is what worked for my project:

[files]
"../geometry_generator.py" = "geometry_generator.py"

Now however I'm getting an error from using Element like below:
interface_element = Element("interface")

Has the Element method been removed from PyScript? I can't find anything to that effect online. It works fine with the older version of PyScript.Error is below:

PythonError: Traceback (most recent call last):
  File "/lib/python311.zip/_pyodide/_base.py", line 499, in eval_code
    .run(globals, locals)
     ^^^^^^^^^^^^^^^^^^^^
  File "/lib/python311.zip/_pyodide/_base.py", line 340, in run
    coroutine = eval(self.code, globals, locals)
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<exec>", line 46, in <module>
NameError: name 'Element' is not defined

from pyscript.

AlteriusOmega avatar AlteriusOmega commented on June 4, 2024

@AlteriusOmega this was wrong:

"../geometry_generator.py": ".geometry_generator.py"

you forgot the slash ... this would be fine:

"../geometry_generator.py": "./geometry_generator.py"

but your solution, which does the same, is fine too.

The Element doesn't exist in current PyScript, it's been moved into the PyWeb module so you should from pyweb import Element but there's a lot of ongoing refactoring there so if you need an element, for the time being, import document from pyscript and then document.getElementById("interface") to read, change, or operate with that node.

I am closing as nothing seems to be a bug here but feel free to ask more if needed.

Thanks, yep that was it! Sorry, very silly typo mistake, you just sometimes become blind to things like this when working on the same problem for so long with so many variables.

And thank you, I tried importing pydom from pyweb and using pydom.Element() like in this example and that is working, however now I have 2 new issues.

The first is mysterious. When I click a button to run one of the functions in geometry_interface.py, I get:

TypeError: a is undefined
    Pt _python.js:35
    gn listeners.js:42
    value main.js:67
    wn listeners.js:61
    define custom.js:237
    <anonymous> core.js:260
    promise callback* core.js:133
app-index.tsx:25:19
    error app-index.tsx:25
    error hydration-error-info.ts:72
    stderr error.js:15
    Pt _python.js:39
    gn listeners.js:42
    value main.js:67
    wn listeners.js:61
    define custom.js:237
    <anonymous> core.js:260
    (Async: promise callback)
    <anonymous> core.js:133

I don't have any variable named "a" anywhere in my code.

The second issue is that React doesn't recognize <py-repl> tags of course and gives:
Property 'py-repl' does not exist on type 'JSX.IntrinsicElements'.ts(2339)

I get the same type warnings for other pyscript tags like <py-config> and <py-script> but those ones still seem to work. The py-repl is not working. It just loads as text and never renders as a repl box like it should even though I get "[pyscript/main] PyScript Ready".

I found this Reddit post with the same issue with py-repl but they didn't find any solution.

from pyscript.

JeffersGlass avatar JeffersGlass commented on June 4, 2024

I can's speak to the React issue, but the issue with a is undefined is typically when your event listener attribute is mis-named or the syntax is incorrect.

from pyscript.

AlteriusOmega avatar AlteriusOmega commented on June 4, 2024

I can's speak to the React issue, but the issue with a is undefined is typically when your event listener attribute is mis-named or the syntax is incorrect.

I'm not using any event listeners, at least not normal js or React ones, I'm using py-click from pyscript. I'm sure its not the actual function itself because I created a simple test function and button as below:

In page.tsx:
<button id="test_button" py-click="test_function()">Test button</button>

In geometry_interface.py:

def test_function():
    print("test_function ran!")

I still get the same error "TypeError: can't access property "call", a is undefined". Maybe py-click also just doesn't work with React. I am guessing this "a" is from some minified code, either in pyscript/pyodide or js somewhere.

from pyscript.

AlteriusOmega avatar AlteriusOmega commented on June 4, 2024

I dug a little bit into the "a is udnefined" error and it is coming from pyscript.net/releases/node_modules/polyscript/esm/_python.js in in the runEvent function:

export const runEvent = async (interpreter, code, event) => {
    // allows method(event) as well as namespace.method(event)
    // it does not allow fancy brackets names for now
    const [name, ...keys] = code.split('.');
    let target = interpreter.globals.get(name);
    let context;
    for (const key of keys) [context, target] = [target, target[key]];
    try {
        await target.call(context, event);
    }
    catch (error) {
        io.get(interpreter).stderr(error);
    }
};

The line causing the error is line 35:

    try {
        await target.call(context, event);
    }

Also I just tried updating my old HTML version to use the newest version of PyScript and now I'm getting the same exact error there, and my py-repl elements also no longer work there so it doesn't have to do with React or Next

from pyscript.

JeffersGlass avatar JeffersGlass commented on June 4, 2024

In PyScript 203.11.1 and later, py-event attribute don’t need parentheses after them, just the same of the callable in the global namespace.

from pyscript.

AlteriusOmega avatar AlteriusOmega commented on June 4, 2024

In PyScript 203.11.1, py-event attribute don’t need parentheses after them, just the same of the callable in the global namespace.

OK thank you. If you mean like this:
<button id="test_button" py-click="test_function">Test button</button>

Then I get a new error PythonError: TypeError: test_function() takes 0 positional arguments but 1 was given which is odd since I'm not giving it any arguments.

from pyscript.

JeffersGlass avatar JeffersGlass commented on June 4, 2024

When using the py-*event syntax, the function is passed an Event object corresponding to the triggering event. You can either receive this event and use it def test_function(evt): or swallow and ignore it def test_function(*args).

from pyscript.

AlteriusOmega avatar AlteriusOmega commented on June 4, 2024

When using the py-*event syntax, the function is passed an Event object corresponding to the triggering event. You can either receive this event and use it def test_function(evt): or swallow and ignore it def test_function(*args).

Ah that makes sense, I changed my functions to ignore the event for now just using *args as you suggested to allow the 1 positional argument.

I finally got the test function working, so thank you!

However when I tried to run my actual functions that do something I got:

Uncaught (in promise) Error: Unable to use SharedArrayBuffer due insecure environment.
Please read requirements in MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer#security_requirements

So, I set the CORS headers by adding a middleware directory and a securityHeaders.ts file:

import { NextApiResponse } from "next";

export default function securityHeaders(res: NextApiResponse): void {
  res.setHeader("Cross-Origin-Opener-Policy", "same-origin");
  res.setHeader("Cross-Origin-Embedder-Policy", "require-corp");
}

And added this to my next.config.mjs file:

/** @type {import('next').NextConfig} */
const nextConfig = {
  async headers() {
    return [
      {
        // Set for all API routes
        source: "/(.*)",
        headers: [
          { key: "Cross-Origin-Opener-Policy", value: "same-origin" },
          { key: "Cross-Origin-Embedder-Policy", value: "require-corp" },
        ]
      }
    ]
  }
};

export default nextConfig;

Which seems to have fixed that but now I'm getting a source map error:

Source map error: unsupported protocol for sourcemap request pyodide.mjs.map
Resource URL: null
Source Map URL: pyodide.mjs.map

💀🔒 - Possible deadlock if proxy.runAsync(...args) is awaited 

from pyscript.

AlteriusOmega avatar AlteriusOmega commented on June 4, 2024

Just for reference this is the whole geometry_interface.py file currently:

from geometry_generator import *
import svgwrite
from pyweb import pydom
# from pyscript import document

print(f"geometry_interface.py ran!")

interface_element = pydom.Element("interface")

svg_output_width = 500
diameter = svg_output_width / 2

center = [svg_output_width*0.5, svg_output_width*0.5]
print(f"center is {center}")

svg_output = pydom.Element("svg-output")

# Note, drawing_global is global variable from geometry_generator.py itself 

repl = pydom.Element("py-repl")

def test_function(*args):
    print("test_function ran!")

def render_drawing_html(*args):
    print(f"render_drawing_html ran!")
    svg_string = drawing_global.tostring()
    print(f"svg_string is {svg_string}")
    svg_output.innerHTML = svg_string

def clear_drawing(*args):
    print("clear_drawing ran!")
    global drawing_global
    print(f"clear_drawing ran! and drawing is {drawing_global} and drawing xml is {drawing_global.get_xml()}")
    drawing_global = svgwrite.Drawing(output_path)
    render_drawing_html() # Render the drawing to update the page with empty drawing
    
print("Geometry Interafce loaded!")

from pyscript.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.