Skip to content
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

Importing a Brython module that is implemented in pure JavaScript #1568

Closed
moepnse opened this issue Dec 28, 2020 · 13 comments
Closed

Importing a Brython module that is implemented in pure JavaScript #1568

moepnse opened this issue Dec 28, 2020 · 13 comments

Comments

@moepnse
Copy link
Contributor

moepnse commented Dec 28, 2020

I hope you had a wonderful Christmas 🎄 🎅 🤶 🎁

I have the special case that I have a Brython module in pure JavaScript and want to import it using the import statement without making it accessible via a script tag beforehand.

Thanks in advance.

@lovasb
Copy link

lovasb commented Dec 29, 2020

Brython module in pure JavaScript

What does it mean? The Brython module is compiled to Javascript? Or it's developed originaly in Javascript?

@moepnse
Copy link
Contributor Author

moepnse commented Dec 29, 2020

The module is developed in JavaScript and not compiled to JavaScript. To be precise, I forked an existing one.

I have adapted the _webcomponent module and want to use it so that I don't have to build the whole stdlib. I suspect that I can achieve this with the importlib.

@PierreQuentel
Copy link
Contributor

@moepnse
The standard way of adding a new importing process is to add a new loader to sys.meta_path. The loader loads the module at a specified location (here, with a blocking Ajax call), executes it (here, with Javascript's window.eval()) and import the module name in the importer namespace.

Do you think you can develop this loader ? Otherwise I will try, it's something that would be worth including in Brython, with a documentation.

@moepnse
Copy link
Contributor Author

moepnse commented Dec 29, 2020

@PierreQuentel
I'm already working on it.

@PierreQuentel
Copy link
Contributor

@moepnse Cool !

@moepnse
Copy link
Contributor Author

moepnse commented Dec 29, 2020

My first attempt using the importlib failed.

I then looked at py_import.js. Apparently only line 747 needs to be adjusted.

The exec_module method in line 811 can already distinguish between Python and JavaScript modules.

Seems to work:
brython_js_modules

I'll look over it again tomorrow to be sure that it really works and write a test for it. Is there somewhere documented how to write tests for Brython?

@PierreQuentel
Copy link
Contributor

I don't think it's a good idea to change the standard Brython import mechanism in py_import.js, because it would add the search for JS modules (hence an Ajax call) for all imports. At the moment, only the JS modules in the Brython stdlib, in folder libs, can be imported.

My idea was more to develop a specific loader, that would only be added to sys.meta_path for the (rare) case when a user-specific JS module, at a specific location, needs to be imported.

In issue #1182 I had provided an example of a loader written in Python, maybe you can start from this example for a Javascript module loader.

@moepnse
Copy link
Contributor Author

moepnse commented Dec 30, 2020

I understand your concerns.

But maybe I can change your mind.

The importlib uses a list of possible source code file suffixes: https://docs.python.org/3/library/importlib.html#importlib.machinery.SOURCE_SUFFIXES

What do you think of adopting this concept and making it configurable as an option, like in the attached patch? If you do not agree with the patch, then I will implement it as a separate loader, based on the importlib, or your example loader, as suggested by you.

    <body onload="brython({debug: 1, 
        pythonpath: ['/py/', '/bry/'],
        source_suffixes: ['.py', '.js']});">

Apart from that, your sample loader should be part of the documentation or gallery.

@moepnse
Copy link
Contributor Author

moepnse commented Dec 30, 2020

Writing a WebSocket or WAMP capable loader would be interesting.

@kikocorreoso
Copy link
Member

kikocorreoso commented Apr 25, 2021

@NovaAndrom3da
Copy link
Contributor

Perhaps do something like:
JS file:

function my_function(argument) {
  return "some value "+argument
}

Python File:

from browser import window
window.my_function("test")

@PierreQuentel
Copy link
Contributor

In commit 8e8d0a5 I have added a function import_js(url, name) in module javascript that makes it possible to import a module written in Javascript. This module must define a name $module, used to build the module namespace, with the usual Javascript -> Python conversions.

If Javascript script at js_test.js is

var $module = { x: 1 }

then a Python script can use it this way:

import javascript

javascript.import_js("js_test.js", "js_module") 
import js_module 
assert js_module.x == 1

PierreQuentel added a commit that referenced this issue Jun 30, 2022
- if alias is missing, set it from the url ('js_test.js' gives alias 'js_test')
- set alias in local namespace, so there is no need to add "import <alias>"
Related to issue #1568
@PierreQuentel
Copy link
Contributor

Reviewing this old issue: I recently added a function import_modules in the javascript module to import Javascript modules that use the export keyword. It is described in the documentation.

Because such JS modules are loaded asynchronously, the use of Python import, which is blocking, is unfortunately not possible.

I close the issue but if you have other suggestions, just comment and I will reopen it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants