Closed thautwarm closed 2 years ago
There are several use-cases:
Fable.PyInterop
namespace for making bindings similar to Fable.Python
(similar to this repo).We could add an option to the compiler to not bundle fable-library but reference PyPI installed library instead. For referenced Fable NuGet's this will be more difficult since it may not be trivial to convert them into a package. This was btw my first plan, but gave up and reverted to "static-linking" instead. One idea is to bundle a pyproject.toml with the Fable package so it knows how to install itself (dependencies etc). We could also have a compiler switch to generate Python packages instead i.e similar structure to:
poetry-demo
├── pyproject.toml
├── README.rst
├── poetry_demo
│ └── __init__.py
└── tests
├── __init__.py
└── test_poetry_demo.py
Is it something like this you have in mind?
FYI: There is also Femto that handles NPM references for Fable (JS) NuGet's. We should extend it to support PyPI.
For referenced Fable NuGet's this will be more difficult since it may not be trivial to convert them into a package.
I think for NuGet packages we'd better keep them "static linking", before we get to know convert to them.
Is it something like this you have in mind?
Yes, but I'm not sure if bundling a pyproject.toml is sufficient. I was actually considering another format to control, (1) pyproject.toml, (2) .fsproj, (3) fable_modules (locally installed python packages and Fable packages).. but if we can avoid reinveting wheels that'd be great.
There is also Femto that handles NPM references for Fable (JS) NuGet's. We should extend it to support PyPI.
I don't have an idea about Femto, will check out this today. Initially I was considering to have a pyproject.toml for fable python projects to manage both fable python dependecies and pure python dependencies.
Hi there! Not sure if I understand the problem well as I don't have much experience with Python packages (I just know they're very messy 😉) but I'll try to leave a couple of notes in case it helps. First, when you talk about a Fable library is this?
So far, in Fable JS when talking about Fable libraries it's about 1. Nuget packages. When Fable compiles a project it gathers all the sources from the referenced packages and treats them as if they belonged to the same .fsproj. We don't usually distribute precompiled code because there are not guarantees that generated code will be compatible with later versions of Fable.
However, it's possible that Fable packages also include some native (JS) code or make references to native npm packages. In the first case, library authors just put the .js files together with the .fs files in the fable
folder included in the Nuget package, and Fable will just copy all contents of this folder to the output directory (within fable_modules
) when compiling. In the second cases, library authors just use "bare modules" (ie. non-relative paths) that will be later resolved by JS tooling like Webpack.
The problem with "bare modules" is users often forget to install the npm dependencies and authors cannot specify version ranges either. This is what Femto tries to solve by reading metadata from the Nuget package so it can verify users have the proper npm dependencies installed.
Not sure if something similar can be done with Python. The ideal thing would be to avoid global package installations and have versions managed locally. Would it be possible to enforce this for Fable Python projects using tools like Poetry?
FYI: this issue will be fixed by https://github.com/fable-compiler/Fable/pull/2974 and #59 (if we decide to merge). With the suggested changes, fable-modules will contain proper Python packages, and you would have to use Poetry (or e.g change PYTHONPATH) to find the local modules. Fable compiled NuGet's should include a pyproject.toml file to list their Python dependencies. Projects also needs to have a pyproject.toml that refers to fable-modules (static) or PyPI (dynamic). Fable-modules will also be distributed to PyPI for dynamic usage.
I think you have thoroughly considered this issue according to https://github.com/fable-compiler/Fable.Python/issues/30#issuecomment-1003394317 , but let me repeat something here for being clarified.
Suppose we want to reference an external Fable Python library (namely, another Fable library not owned by us), there are at least 2 approaches and people might choose 2 different ways accordingly.
The first of which is "static link", we just take an external Fable library and generate code inside our package. Users do not need to install the Fable package. We keep the namespace of the external Fable inside our generated code, so that users can install that external package independently without polluting the environment.
The second of which is "dynamic link", we just take the type information of the external Fable library, and the generated code uses python import to access the library. The whole environment keeps only one version of the external Fable library.
I think both of them are useful. "static link" is easy to achieve, even without support from the Fable Python compiler. We can upload Fable project to any software registry and implement a tool to upload, download and verify libraries. For "dynamic link", I'm not sure if it is supported.
About the implementations.
For "static link", I think you have made progress and supported it in some degree, but I wonder if PyPI Fable packages are supported, if not I can help.
For "dynamic link", I wonder if Fable can extract type information that is usable for transpilation from the compiled dlls, I think "dynamic link" is do-able.