Skip to content

Releases: Distributive-Network/PythonMonkey

v1.1.0

03 Dec 04:03
Compare
Choose a tag to compare

PythonMonkey v1.1.0

This release adds Python 3.13 support to PythonMonkey.

What's Changed

Full Changelog: v1.0.0...v1.1.0

v1.0.0

12 Sep 15:42
e72bfd2
Compare
Choose a tag to compare

PythonMonkey v1.0.0

PythonMonkey is now stable for production, including Distributive's use-case of DCP! 🥳

Bug Fixes:

  • calling a python method that has 0 parameters in JavaScript would cause a segfault rather than a TypeError: Class.method() takes 0 positional arguments but 1 was given exception
  • Using a python iterable as the yield of a JavaScript function* generator would cause a segfault rather than a TypeError: 'iterable' object is not an iterator exception

v0.9.0

10 Sep 19:38
ce0394d
Compare
Choose a tag to compare

PythonMonkey v0.9.0

This release fixes the long annoying string corruption bug.

PythonMonkey is now super powerful and a lot more stable! 🦾 🦾 🦾


Generated release notes:

What's Changed

  • Upgrade SpiderMonkey to mozilla-central commit a283127a5d0aa005c54d339e8ca27414b55f079b by @github-actions in #424
  • Fix the string corruption bug by @Xmader in #428
  • Philippe/final edits for first release by @philippedistributive in #427
  • Make the wheel packages we build also support lower versions of macOS by @Xmader in #415
  • Make easier debugging HTTP errors (such as DCPError: no transports defined) by @Xmader in #371
  • Docs: add uninstallation instructions in the README by @Xmader in #431
  • Add CI for publishing to ⊇istributive's archive server by @Xmader in #432

Full Changelog: v0.8.1...v0.9.0

v0.8.1

03 Sep 16:05
5a91430
Compare
Choose a tag to compare
  • bug fixes:

    • segfault could occur if exit() or quit() were called asynchronously
    • atob did not include padding
    • pythonmonkey could not be installed on Windows if cargo was not installed beforehand
  • performance improvements:

    • improved memory-use, particularly regarding python strings passed to JavaScript
    • increased the maximum JavaScript garbage-collected heap size to the maximum allowed (4 GB)
  • other:

    • pythonmonkey now ships pre-built arm64 wheels
    • removed Doxygen and Graphviz as mandatory prerequisites to install PythonMonkey (you still need them to build the docs, but you'll have to install them yourself if you wish to do so)

v0.8.0

31 Jul 18:52
7a2ffd0
Compare
Choose a tag to compare
  • python bytes objects are now passed to JavaScript as immutable Uint8Array
  • python dict and user-defined class objects now use the prototype chain for following methods in JavaScript:
    • Object.prototype.toString
    • Object.prototype.toLocaleString
    • Object.prototype.valueOf
  • python iterator objects passed to JS now have the [Symbol.toPrimitive] and .valueOf properties in JavaScript to support use with console.log

v0.7.1

18 Jul 14:41
fb900e8
Compare
Choose a tag to compare
  • fixed a bug where users without Rust and cargo installed could not install pythonmonkey from a source distribution

v0.7.0

16 Jul 19:02
e77643f
Compare
Choose a tag to compare
  • added a new build type:
  • added a new tool inspired by wtfnode called WTFPythonMonkey to track down any hanging setTimeout/setInterval timers that are still ref'd when you hit ctrl-C.
    • When using pmjs, to enable it you can simply pass the --wtf flag, like so:
    pmjs --wtf <filename>.js
    import asyncio
    import pythonmonkey as pm
    from pythonmonkey.lib.wtfpm import WTF
    
    async def pythonmonkey_main():
      pm.eval("setInterval(() => console.log(new Date), 500)")
      await pm.wait()
    
    with WTF():
      asyncio.run(pythonmonkey_main())
  • implemented JS-like function calling for python functions in JS. Similar to JS functions, you can now call python functions with too few or too many arguments without throwing an error.
    • When too many arguments are supplied, those beyond the function's parameter count are ignored, e.g.:
    def f(a, b):
      return [a, b]
    assert [1, 2] == pm.eval("(f) => f(1, 2, 3)")(f)
    • When too few arguments are supplied, those beyond the number of supplied arguments are passed as None to match JS's behaviour of passing undefined, e.g.:
    def f(a, b):
      return [a, b]
    assert [1, None] == pm.eval("(f) => f(1)")(f)
    • This also works for functions with default arguments, or varargs, e.g.:
    def f(a, b, c=42, d=43, *args):
      return [a, b, c, d, *args]
    assert [1,    2,    3,  4, 5] == pm.eval("(f) => f(1, 2, 3, 4, 5)")(f)
    assert [1,    2,    3,  4   ] == pm.eval("(f) => f(1, 2, 3, 4)"   )(f)
    assert [1,    2,    3,  43  ] == pm.eval("(f) => f(1, 2, 3)"      )(f)
    assert [1,    2,    42, 43  ] == pm.eval("(f) => f(1, 2)"         )(f)
    assert [1,    None, 42, 43  ] == pm.eval("(f) => f(1)"            )(f)
    assert [None, None, 42, 43  ] == pm.eval("(f) => f()"             )(f)
  • implemented the copy protocol (both copy.copy and copy.deepcopy) for JSStringProxies
  • using the aforementioned WTFPythonMonkey, we've fixed several bugs related to timers, including:
    • the Future object is not initialized error and following segfault
    • heap-use-after-free in timerJobWrapper
    • hitting ctrl-C in pmjs printing out the entire Python KeyboardInterrupt traceback
    • intervals from setInterval were not being unref'd correctly
  • fixed a bug where uncaught JS Promise rejections would result in a Future exception was never retrieved Python error, rather than the actual JS error
  • added support for HTTP-Keep-Alive in our implementation of XMLHttpRequest
  • fixed a memory leak related to cross-language strings
  • fixed a bug where attempting to install Pythonmonkey from source failed on Ubuntu 24.04
  • PythonMonkey now uses the bleeding edge version of SpiderMonkey on this and all future releases
  • we now build and distribute binaries for python 3.8 on amd64 Mac OS

v0.6.0

02 May 19:24
ee72ee4
Compare
Choose a tag to compare

PythonMonkey v0.6.0

  • significant performance improvements, particularly in memory usage
  • improved build system and build time, including making building the docs optional, and the following build types:
    • Release: stripped symbols, maximum optimizations (default, what gets published on pip)
    • DRelease: same as Release, except symbols are not stripped
    • Debug: minimal optimizations
    • Profile: same as Debug, except profiling is enabled
  • fixed a bug where users with particularly old versions of PythonMonkey were unable to update to the latest release using pip unless they completely uninstalled PythonMonkey first

v0.5.0

15 Apr 19:24
c9bec0f
Compare
Choose a tag to compare

PythonMonkey v0.5.0

  • fixed a bug where pmjs -e / pmjs -p was not able to call functions that require the event loop
  • implemented setInterval and clearInterval
  • implemented further cross-language support for iterators (more widespread use of iterators, such as the for-of loop for arrays, was already working in previous versions)

using a JS iterator in python:

import pythonmonkey as pm

myit = pm.eval('(function* () { yield 1; yield 2; })')()
print(next(myit)) # 1.0
print(next(myit)) # 2.0
print(next(myit)) # StopIteration exception

using a python iterator in JS:

import pythonmonkey as pm

myit = iter((1,2))
pm.eval("""
(myit) => {
  console.log([...myit]); // [1, 2]
}
""")(myit)

v0.4.0

04 Apr 20:45
9f52f58
Compare
Choose a tag to compare

PythonMonkey v0.4.0

  • fixed a bug where methods called on proxied JS objects would use globalThis for the value of this
  • implemented proxying of arbitrary python objects in JavaScript, like so:
import pythonmonkey as pm

class Counter:
  def __init__(self):
    self.count = 0
  def increment(self):
    self.count = self.count + 1

counter = Counter()

pm.eval("""
(pyObject) => {
  console.log(pyObject.count); // 0
  pyObject.increment();
  console.log(pyObject.count); // 1
}
""")(counter)
  • implemented a new type called JSMethodProxy, which can be used to implement methods on python objects in JavaScript, like so:
import pythonmonkey as pm

jsFunc = pm.eval("(function() { this.count++; })")

class Counter:
  def __init__(self):
    self.count = 0
    self.increment = pm.JSMethodProxy(jsFunc, self)

counter = Counter()
print(counter.count) # 0
counter.increment()
print(counter.count) # 1
  • various garbage collection optimizations
  • various memory leak fixes
  • implemented complete cross-language stack traces
  • pm.eval can now accept a file object as its first argument (such as an object returned by the open() python built-in), which is expected to be a javascript file
  • when calling pm.require (or other requires created by pm.createRequire), .py CommonJS modules now have precedence over .js modules when there is a namespace collision
  • setTimeout now returns a Node.js-style Timeout class for the timeout id, with .ref() and .unref() methods
  • implemented XMLHttpRequest.withCredentials
  • implemented "json" support for XMLHttpRequest.responseType
  • implemented remaining standard console methods