Skip to content

Commit 65d8bae

Browse files
committed
Merge branch 'main' into Xmader/feat/pm.require
2 parents b7a935a + e8147b1 commit 65d8bae

33 files changed

+1464
-1288
lines changed

.github/workflows/test-and-publish.yaml

Lines changed: 56 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,9 @@ jobs:
2424
build-spidermonkey-unix:
2525
strategy:
2626
matrix:
27-
# Use Ubuntu 20.04 / macOS 12 + Python 3.8 to build SpiderMonkey
28-
os: [ 'ubuntu-20.04', 'macos-12' ]
29-
python_version: [ '3.8' ]
27+
# Use Ubuntu 20.04 / macOS 12 + Python 3.10 to build SpiderMonkey
28+
os: [ 'ubuntu-20.04', 'macos-12', 'm2ci' ]
29+
python_version: [ '3.10' ]
3030
runs-on: ${{ matrix.os }}
3131
steps:
3232
- uses: actions/checkout@v3
@@ -39,7 +39,7 @@ jobs:
3939
with:
4040
path: |
4141
./_spidermonkey_install/*
42-
key: ${{ runner.os }}-spidermonkey
42+
key: spidermonkey-${{ runner.os }}-${{ runner.arch }}
4343
lookup-only: true # skip download
4444
- name: Build spidermonkey
4545
if: ${{ steps.cache-spidermonkey.outputs.cache-hit != 'true' }}
@@ -54,7 +54,7 @@ jobs:
5454
with:
5555
path: |
5656
./_spidermonkey_install/*
57-
key: ${{ runner.os }}-spidermonkey
57+
key: spidermonkey-${{ runner.os }}-${{ runner.arch }}
5858
lookup-only: true # skip download
5959
- name: Install dependencies
6060
if: ${{ steps.cache-spidermonkey.outputs.cache-hit != 'true' }}
@@ -78,41 +78,61 @@ jobs:
7878
fail-fast: false
7979
matrix:
8080
# The lowest supported version is Ubuntu 20.04 + Python 3.8 or macOS 12 + Python 3.9
81-
os: [ 'ubuntu-20.04', 'macos-12', 'windows-2019' ]
81+
os: [ 'ubuntu-20.04', 'macos-12', 'windows-2019', 'm2ci' ]
8282
python_version: [ '3.8', '3.9', '3.10', '3.11', '3.12-dev' ]
8383
exclude:
8484
# macOS 12 comes with Python 3.9 by default, so we drop ci support for Python 3.8 on macOS
8585
# FIXME: We can't build on macOS 11 for now because our prebuilt `uncrustify` binary requires macOS 12
8686
- os: 'macos-12'
8787
python_version: '3.8'
88+
# actions/setup-python: The version '3.8'/'3.9' with architecture 'arm64' was not found for macOS.
89+
# see https://raw.githubusercontent.com/actions/python-versions/main/versions-manifest.json
90+
- os: 'm2ci'
91+
python_version: '3.8'
92+
- os: 'm2ci'
93+
python_version: '3.9'
8894
runs-on: ${{ matrix.os }}
8995
steps:
9096
- uses: actions/checkout@v3
97+
with:
98+
fetch-depth: 0 # fetch all history for all branches and tags
99+
# poetry-dynamic-versioning needs git tags to produce the correct version number
91100
- uses: actions/setup-python@v4
92101
with:
93102
python-version: ${{ matrix.python_version }}
94103
- name: Setup Poetry
95104
uses: snok/install-poetry@v1
105+
with:
106+
version: 1.5.1
96107
- name: Install Dependencies
97108
run: |
98109
echo "Installing Dependencies"
99110
if [[ "$OSTYPE" == "linux-gnu"* ]]; then # Linux
100111
sudo apt-get update -y
101112
sudo apt-get install -y cmake doxygen graphviz llvm
102113
elif [[ "$OSTYPE" == "darwin"* ]]; then # macOS
103-
brew update
114+
brew update || true # allow failure
104115
brew install cmake doxygen graphviz pkg-config wget coreutils # `coreutils` installs the `realpath` command
105116
fi
106117
echo "Installing python deps"
107-
poetry install --no-root
118+
poetry self add "poetry-dynamic-versioning[plugin]"
119+
poetry env use python3 # use the correct Python version we've set up
120+
poetry install --no-root --only=dev
108121
echo "Installed Dependencies"
109122
- name: Use cached spidermonkey build
110123
uses: actions/cache@v3
111124
with:
112125
path: |
113126
./_spidermonkey_install/*
114-
key: ${{ runner.os }}-spidermonkey
127+
key: spidermonkey-${{ runner.os }}-${{ runner.arch }}
115128
fail-on-cache-miss: true # SpiderMonkey is expected to be cached in its dedicated job
129+
- name: Build pminit
130+
run: |
131+
cd python/pminit
132+
poetry build --format=sdist
133+
cd -
134+
mkdir -p ./dist/
135+
mv -v python/pminit/dist/* ./dist/
116136
- name: Build wheel
117137
run: |
118138
echo $(poetry run python --version)
@@ -125,19 +145,24 @@ jobs:
125145
path: ./dist/
126146
- name: Run Python tests (pytest)
127147
run: |
128-
poetry run python -m pip install ./dist/*.whl
148+
poetry run python -m pip install --force-reinstall ./dist/*
129149
poetry run python -m pytest tests/python
130150
sdist:
131151
runs-on: ubuntu-20.04
132152
steps:
133153
- uses: actions/checkout@v3
154+
with:
155+
fetch-depth: 0
134156
- uses: actions/setup-python@v4
135157
with:
136158
python-version: '3.9'
137159
- name: Setup Poetry
138160
uses: snok/install-poetry@v1
161+
with:
162+
version: 1.5.1
139163
- name: Build source distribution (sdist) file
140164
run: |
165+
poetry self add "poetry-dynamic-versioning[plugin]"
141166
poetry build --format=sdist
142167
ls -lah ./dist/
143168
- name: Upload sdist as CI artifacts
@@ -156,6 +181,8 @@ jobs:
156181
python-version: '3.9'
157182
- name: Setup Poetry
158183
uses: snok/install-poetry@v1
184+
with:
185+
version: 1.5.1
159186
- name: Download wheels built
160187
uses: actions/download-artifact@v3
161188
with:
@@ -185,16 +212,26 @@ jobs:
185212
uses: actions/download-artifact@v3
186213
with:
187214
name: wheel-${{ github.run_id }}-${{ github.sha }}
188-
path: ./pythonmonkey/ # write to the repository project path
215+
path: ./dist/
216+
- name: Move wheels to the correct repository project paths
217+
run: |
218+
mkdir -p ./pythonmonkey/ ./pminit/
219+
mv ./dist/pythonmonkey-* ./pythonmonkey/
220+
mv ./dist/pminit-* ./pminit/
189221
- name: Generate index page for the project
190222
run: |
191-
cd ./pythonmonkey/
192-
html="<html><head><title>PythonMonkey Nightly Builds</title></head><body>"
193-
for file in ./*; do # generate <a> tags for each file
194-
html+="<a href=\"$file\">$file</a><br/>"
195-
done
196-
html+="</body></html>"
197-
echo "$html" > ./index.html
223+
generate_index () {
224+
cd $1
225+
html="<html><head><title>PythonMonkey Nightly Builds</title></head><body>"
226+
for file in ./*; do # generate <a> tags for each file
227+
html+="<a href=\"$file\">$file</a><br/>"
228+
done
229+
html+="</body></html>"
230+
echo "$html" > ./index.html
231+
cd -
232+
}
233+
generate_index ./pythonmonkey/
234+
generate_index ./pminit/
198235
- name: Generate repository root page
199236
run: |
200237
html="<html><head><title>PythonMonkey Nightly Builds</title></head><body>"
@@ -203,6 +240,7 @@ jobs:
203240
html+="<pre>pip install -i https://nightly.pythonmonkey.io/ --pre pythonmonkey</pre>"
204241
html+="<h3>Browse files:</h3>"
205242
html+="<a href="pythonmonkey/">pythonmonkey</a>"
243+
html+="<a href="pminit/">pminit</a>"
206244
html+="</body></html>"
207245
echo "$html" > ./index.html
208246
- uses: actions/upload-pages-artifact@v1

.gitignore

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
build/
22
.vscode/
33
pyvenv.cfg
4-
python/pythonmonkey/version.py
54
python/pythonmonkey/node_modules
65
bin/
76
lib/*
@@ -15,12 +14,6 @@ _spidermonkey_install
1514
__pycache__/*
1615
dist
1716
*.so
18-
_spidermonkey_install/*
19-
*~
20-
Makefile
21-
CMakeDoxyfile.in
22-
CMakeDoxygenDefaults.cmake
23-
CMakeCache.txt
2417
*.dylib
2518
*.dll
2619
*.pyd

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Copyright (c) 2022 Distributive Inc. All Rights Reserved.
22

3-
cmake_minimum_required(VERSION 3.4...3.18) # Set minimum cmake version
3+
cmake_minimum_required(VERSION 3.25) # Set minimum cmake version
44

55
project("PythonMonkey"
66
DESCRIPTION "A tool for Javascript-Python interoperability."

README.md

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
PythonMonkey is a Mozilla [SpiderMonkey](https://firefox-source-docs.mozilla.org/js/index.html) JavaScript engine embedded into the Python VM,
77
using the Python engine to provide the JS host environment.
88

9-
This product is in an early stage, approximately 75% to MVP as of May 2023. It is under active development by Distributive Corp.,
9+
This product is in an early stage, approximately 80% to MVP as of May 2023. It is under active development by Distributive Corp.,
1010
https://distributive.network/. External contributions and feedback are welcome and encouraged.
1111

1212
The goal is to make writing code in either JS or Python a developer preference, with libraries commonly used in either language
@@ -33,12 +33,12 @@ this package to execute our complex `dcp-client` library, which is written in JS
3333
- [done] NodeJS+NPM-compatible CommonJS module system
3434
- [done] Python strings coerce to JS strings
3535
- [done] Python intrinsics coerce to JS intrinsics
36-
- Python dicts coerce to JS objects
36+
- [done] Python dicts coerce to JS objects
3737
- [done] Python `require` function, returns a coerced dict of module exports
3838
- [done] Python functions coerce to JS function wrappers
3939
- [done] CommonJS module system .py loader, loads Python modules for use by JS
4040
- JS object->Python dict coercion supports inherited-property lookup (via __getattribute__?)
41-
- Python host environment supplies event loop, including EventEmitter, setTimeout, etc.
41+
- [done] Python host environment supplies event loop, including EventEmitter, setTimeout, etc.
4242
- Python host environment supplies XMLHttpRequest (other project?)
4343
- Python host environment supplies basic subsets of NodeJS's fs, path, process, etc, modules; as-needed by dcp-client (other project?)
4444
- Python TypedArrays coerce to JS TypeArrays
@@ -55,20 +55,17 @@ this package to execute our complex `dcp-client` library, which is written in JS
5555
- spidermonkey 102.2.0 or later
5656
- npm (nodejs)
5757
- [Poetry](https://python-poetry.org/docs/#installation)
58+
- [poetry-dynamic-versioning](https://github.com/mtkennerly/poetry-dynamic-versioning)
5859

59-
2. Run `poetry install`. This command automatically compiles the project and installs the project as well as all Python dependencies to the poetry virtualenv.
60+
2. Run `poetry run pip install --verbose python/pminit ./`. This command automatically compiles the project and installs the project as well as dependencies into the poetry virtualenv.
6061

6162
## Running tests
6263
1. Compile the project
63-
2. From the root directory, run `poetry run pytest ./tests/python`
64+
2. Install development dependencies: `poetry install --no-root --only=dev`
65+
3. From the root directory, run `poetry run pytest ./tests/python`
6466

6567
## Using the library
6668

67-
See also: examples/
68-
69-
### Method 1
70-
After compiling the project in the `build/src` folder you will find a `.so` file named `pythonmonkey.so`. This is the shared object file that contains the pythonmonkey module.
71-
7269
### Install from [PyPI](https://pypi.org/project/pythonmonkey/)
7370

7471
> PythonMonkey is not release-ready yet. Our first public release is scheduled for mid-June 2023.
@@ -101,10 +98,19 @@ Type "help", "copyright", "credits" or "license" for more information.
10198

10299
Alternatively, you can build a `wheel` package by running `poetry build --format=wheel`, and install it by `pip install dist/*.whl`.
103100

101+
## Examples
102+
103+
* [examples/](examples/)
104+
* https://github.com/Distributive-Network/PythonMonkey-examples
105+
* https://github.com/Distributive-Network/PythonMonkey-Crypto-JS-Fullstack-Example
106+
104107
# Troubleshooting Tips
105108

109+
## REPL - pmjs
110+
A basic JavaScript shell, `pmjs`, ships with PythonMonkey.
111+
106112
## CommonJS (require)
107-
If you are having trouble with the CommonJS require function, set DEBUG='ctx-module*' and you can see the filenames it tries to laod
113+
If you are having trouble with the CommonJS require function, set environment variable DEBUG='ctx-module*' and you can see the filenames it tries to laod.
108114

109115
### Extra Symbols
110116
Loading the CommonJS subsystem declares some extra symbols which may be helpful in debugging -

build_script.sh

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,3 @@ else
2323
cmake ..
2424
fi
2525
cmake --build . -j$CPUS --config Release
26-
27-
# npm is used to load JS components, see package.json
28-
cd "${topDir}/python/pythonmonkey/"
29-
npm i

include/JSObjectProxy.hh

Lines changed: 1 addition & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -57,15 +57,6 @@ public:
5757
*/
5858
static int JSObjectProxy_init(JSObjectProxy *self, PyObject *args, PyObject *kwds);
5959

60-
/**
61-
* @brief Helper function for JSObjectProxy_init
62-
*
63-
* @param jsObject - The underlying backing store JSObject for the JSObjectProxy
64-
* @param dict - The python dict to be converted into a JSObjectProxy
65-
* @param subValsMap - A map of PyObject to JS::Value pairs, representing values that have been visited so far
66-
*/
67-
static void JSObjectProxy_init_helper(JS::HandleObject jsObject, PyObject *dict, std::unordered_map<PyObject *, JS::RootedValue *> &subValsMap);
68-
6960
/**
7061
* @brief Length method (.mp_length), returns the number of key-value pairs in the JSObject, used by the python len() method
7162
*
@@ -121,16 +112,6 @@ public:
121112
* @return bool - Whether the compared objects are equal or not
122113
*/
123114
static bool JSObjectProxy_richcompare_helper(JSObjectProxy *self, PyObject *other, std::unordered_map<PyObject *, PyObject *> &visited);
124-
125-
/**
126-
* @brief Function to satisfy the python GC. See comment in function implementation for more details
127-
*
128-
* @param self - unused
129-
* @param visit - unused
130-
* @param arg - unused
131-
* @return int - always 0
132-
*/
133-
static int JSObjectProxy_traverse(JSObjectProxy *self, visitproc visit, void *arg);
134115
};
135116

136117

@@ -146,22 +127,5 @@ static PyMappingMethods JSObjectProxy_mapping_methods = {
146127

147128
/**
148129
* @brief Struct for the JSObjectProxyType, used by all JSObjectProxy objects
149-
*
150130
*/
151-
static PyTypeObject JSObjectProxyType = {
152-
.ob_base = PyVarObject_HEAD_INIT(&PyType_Type, 0)
153-
.tp_name = "pythonmonkey.JSObjectProxy",
154-
.tp_basicsize = sizeof(JSObjectProxy),
155-
.tp_dealloc = (destructor)JSObjectProxyMethodDefinitions::JSObjectProxy_dealloc,
156-
.tp_as_mapping = &JSObjectProxy_mapping_methods,
157-
.tp_getattro = (getattrofunc)JSObjectProxyMethodDefinitions::JSObjectProxy_get,
158-
.tp_setattro = (setattrofunc)JSObjectProxyMethodDefinitions::JSObjectProxy_assign,
159-
.tp_flags = Py_TPFLAGS_DEFAULT
160-
| Py_TPFLAGS_DICT_SUBCLASS, // https://docs.python.org/3/c-api/typeobj.html#Py_TPFLAGS_DICT_SUBCLASS
161-
.tp_doc = PyDoc_STR("Javascript Object proxy dict"),
162-
.tp_traverse = (traverseproc)JSObjectProxyMethodDefinitions::JSObjectProxy_traverse,
163-
.tp_richcompare = (richcmpfunc)JSObjectProxyMethodDefinitions::JSObjectProxy_richcompare,
164-
.tp_base = &PyDict_Type,
165-
.tp_init = (initproc)JSObjectProxyMethodDefinitions::JSObjectProxy_init,
166-
.tp_new = JSObjectProxyMethodDefinitions::JSObjectProxy_new,
167-
};
131+
extern PyTypeObject JSObjectProxyType;

0 commit comments

Comments
 (0)