Skip to main content

Minimal, modern embedded V8 for Python.

Project description

PyPI status indicator Github workflow status indicator ISC License

Minimal, modern embedded V8 for Python.

MiniRacer logo: a V8 with a very snakey 8

Full documentation.

Features

  • Latest ECMAScript support
  • Web Assembly support
  • Unicode support
  • Thread safe
  • Re-usable contexts

MiniRacer can be easily used by Django or Flask projects to minify assets, run babel or WASM modules.

New home! (As of March 2024)

PyMiniRacer was created by Sqreen, and originally lived at https://github.com/sqreen/PyMiniRacer with the PyPI package py-mini-racer.

As of March 2024, after a few years without updates, I have reached out to the original Sqreen team. We agreed that I should fork PyMiniRacer, giving it a new home at https://github.com/bpcreech/PyMiniRacer with a new PyPI package mini-racer (note: no py-). It now has a new version for the first time since 2021!

Examples

MiniRacer is straightforward to use:

    $ pip install mini-racer

and then:

    $ python3
    >>> from py_mini_racer import MiniRacer
    >>> ctx = MiniRacer()
    >>> ctx.eval("1+1")
    2
    >>> ctx.eval("var x = {company: 'Sqreen'}; x.company")
    'Sqreen'
    >>> print(ctx.eval("'❤'"))
    
    >>> ctx.eval("var fun = () => ({ foo: 1 });")

Variables are kept inside of a context:

    >>> ctx.eval("x.company")
    'Sqreen'

While eval only supports returning primitive data types such as strings, call supports returning composite types such as objects:

    >>> ctx.call("fun")
    {'foo': 1}

Composite values are serialized using JSON. Use a custom JSON encoder when sending non-JSON encodable parameters:

    import json

    from datetime import datetime

    class CustomEncoder(json.JSONEncoder):

            def default(self, obj):
                if isinstance(obj, datetime):
                    return obj.isoformat()

                return json.JSONEncoder.default(self, obj)
    >>> ctx.eval("var f = function(args) { return args; }")
    >>> ctx.call("f", datetime.now(), encoder=CustomEncoder)
    '2017-03-31T16:51:02.474118'

MiniRacer is ES6 capable:

    >>> ctx.execute("[1,2,3].includes(5)")
    False

MiniRacer supports asynchronous execution using JS Promise instances (new in v0.10.0):

    >>> promise = ctx.eval(
    ...     "new Promise((res, rej) => setTimeout(() => res(42), 10000))")
    >>> promise.get()  # blocks for 10 seconds, and then:
    42

You can use JS Promise instances with Python async (new in v0.10.0):

    >>> import asyncio
    >>> async def demo():
    ...     promise = ctx.eval(
    ...         "new Promise((res, rej) => setTimeout(() => res(42), 10000))")
    ...     return await promise
    ... 
    >>> asyncio.run(demo())  # blocks for 10 seconds, and then:
    42

MiniRacer supports the ECMA Intl API:

    # Indonesian dates!
    >>> ctx.eval('Intl.DateTimeFormat(["ban", "id"]).format(new Date())')
    '16/3/2024'

V8 heap information can be retrieved:

    >>> ctx.heap_stats()
    {'total_physical_size': 1613896,
     'used_heap_size': 1512520,
     'total_heap_size': 3997696,
     'total_heap_size_executable': 3145728,
     'heap_size_limit': 1501560832}

A WASM example is available in the tests.

Compatibility

PyMiniRacer is compatible with Python 3.8-3.12 and is based on ctypes.

PyMiniRacer is distributed using wheels on PyPI. The wheels are intended to provide compatibility with:

OS x86_64 aarch64
macOS ≥ 10.9
Windows ≥ 10
Ubuntu ≥ 20.04
Debian ≥ 11
RHEL ≥ 8
other Linuxes with glibc ≥ 2.31
Alpine ≥ 3.19
other Linux with musl ≥ 1.2

If you have a up-to-date pip and it doesn't use a wheel, you might have an environment for which no wheel is built. Please open an issue.

Developing and releasing PyMiniRacer

See the contribution guide.

Credits

Built with love by Sqreen.

PyMiniRacer launch was described in this blog post.

PyMiniRacer is inspired by mini_racer, built for the Ruby world by Sam Saffron.

In 2024, PyMiniRacer was revived, and adopted by Ben Creech. Upon discussion with the original Sqreen authors, we decided to re-launch PyMiniRacer as a fork under https://github.com/bpcreech/PyMiniRacer and https://pypi.org/project/mini-racer/.

Release history

0.10.0 (2024-03-31)

  • Updated to V8 12.3 from V8 12.2 now that Chromium stable is on 12.3.

  • Added Python-side support for JS Promises. You can now return a JS Promise from code executed by MiniRacer.eval, and PyMiniRacer will convert it to a Python object which has a blocking promise.get() method, and also supports await promise in async Python functions.

  • Added a setTimeout and clearTimeout. These common functions live in the Web API standard, not the ECMAScript standard, and thus don't come with V8, but they're so ubiquitious we now ship an implemention with PyMiniRacer.

0.9.0 (2024-03-30)

  • Revamped JS execution model to be out-of-thread. Python/C++ interaction now happens via callbacks.

  • Consequently, Control+C (KeyboardInterrupt) now interrupts JS execution.

  • Hardened C++-side thread safety model, resolving potential race conditions introduced in v0.8.1 (but not actually reported as happening anywhere).

  • Further improved JS exception reporting; exception reports now show the offending code where possible.

  • Introduced timeout_sec parameter to eval, call, and execute to replace the timeout, which unfortunately uses milliseconds (unlike the Python standard library). In the future we may emit deprecation warnings for use of timeout.

0.8.1 (2024-03-23)

  • A series of C++ changes which should not impact the behavior of PyMiniRacer:
  • Refactoring how we use V8 by inverting the control flow. Before we had function evaluations which ran and drained the message loop. Now we have an always-running message loop into which we inject function evaluations. This seems to be the preferred way to use V8. This is not expected to cause any behavior changes (but, in tests, makes microtask competion more consistent).
  • Refactoring the C++ implementation into multiple components to make startup and teardown logic more robust.
  • Added tests for the existing fast-function-call path.
  • Also, simplified Python conversion of C++ evaluation results.

0.8.0 (2024-03-18)

  • General overhaul of C++ implementation to better adhere to modern best practice. This should have no visible impact except for the following notes...
  • Exposed the hard memory limit as a context-specific (as opposed to eval-specific) limit, since that's how it worked all along anyway. The max_memory eval argument still works for backwards compatibility purposes.
  • Correct message type of some exceptions to str instead of bytes (they should all be str now).
  • Added better messages for JS parse errors.
  • Added backtraces for more JS errors.
  • Added some really basic Python typing.

0.7.0 (2024-03-06)

  • Update V8 to 12.2
  • Drop Python 2 support
  • Fix small Python 3.12 issue and add testing for Python 3.9-3.12
  • Add aarch64 support for Mac and Linux
  • Revamp DLL loading to be compliant with Python 3.9-style resource loading. This may present a small breaking change for advanced usage; the EXTENSION_PATH and EXTENSION_NAME module variables, and MiniRacer.v8_flags and MiniRacer.ext class variable have all been removed.
  • Add support for the ECMAScript internalization API and thus the ECMA Intl API
  • Use fast startup snapshots
  • Switch from setuptools to Hatch
  • Switch from tox to Hatch
  • Switch from flake8 and isort to Hatch's wrapper of Ruff
  • Switch from Sphinx to mkdocs (and hatch-mkdocs)
  • Switch from unittest to pytest
  • Add ARCHITECTURE.md and lots of code comments

0.6.0 (2020-04-20)

  • Update V8 to 8.9
  • Optimize function calls without arguments
  • Switch V8 to single threaded mode to avoid crashes after fork
  • Switch to strict mode by default
  • Revamp documentation

0.5.0 (2020-02-25)

  • Update V8 to 8.8

0.4.0 (2020-09-22)

  • Universal wheels for Linux, Mac and Windows
  • Fallback to source package for Alpine Linux

0.3.0 (2020-06-29)

  • Introduce a strict mode
  • Fix array conversion when size changes dynamically (CVE-2020-25489)

0.2.0 (2020-03-11)

  • Support for Alpine Linux
  • Avoid pip private modules in setup.py

0.2.0b1 (2020-01-09)

  • Support for Windows 64 bits
  • Support for Python 3.8
  • Upgrade V8 to 7.8
  • Support soft memory limits

0.1.18 (2019-01-04)

  • Support memory and time limits

0.1.17 (2018-19-12)

  • Upgrade libv8
  • Fix a memory leak

0.1.16 (2018-07-11)

  • Add wheel for Python without PyMalloc

0.1.15 (2018-06-18)

  • Add wheel for Python 3.7

0.1.14 (2018-05-25)

  • Add support for pip 10
  • Update package metadata

0.1.13 (2018-03-15)

  • Add heap_stats function
  • Fix issue with returned strings containing null bytes

0.1.12 (2018-17-04)

  • Remove dependency to enum

0.1.11 (2017-07-11)

  • Add compatibility for centos6

0.1.10 (2017-03-31)

  • Add the possibility to pass a custom JSON encoder in call.

0.1.9 (2017-03-24)

  • Fix the compilation for Ubuntu 12.04 and glibc < 2.17.

0.1.8 (2017-03-02)

  • Update targets build for better compatibility with old Mac OS X and linux platforms.

0.1.7 (2016-10-04)

  • Improve general performances of the JS execution.
  • Add the possibility to build a different version of V8 (for example with debug symbols).
  • Fix a conflict that could happens between statically linked libraries and dynamic ones.

0.1.6 (2016-08-12)

  • Add error message when py_mini_racer sdist fails to build asking to update pip in order to download the pre-compiled wheel instead of the source distribution.

0.1.5 (2016-08-04)

  • Build py_mini_racer against a static Python. When built against a shared library python, it doesn't work with a static Python.

0.1.4 (2016-08-04)

  • Ensure JSEvalException message is converted to unicode

0.1.3 (2016-08-04)

  • Fix extension loading for python3
  • Add a make target for building distributions (sdist + wheels)
  • Fix eval conversion for python 3

0.1.2 (2016-08-03)

  • Fix date support
  • Fix Dockerfile for generating python3 wheels

0.1.1 (2016-08-02)

  • Fix sdist distribution.

0.1.0 (2016-08-01)

  • First release on PyPI.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

mini_racer-0.10.0.tar.gz (417.1 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

mini_racer-0.10.0-py3-none-win_amd64.whl (12.9 MB view details)

Uploaded Python 3Windows x86-64

mini_racer-0.10.0-py3-none-musllinux_1_2_x86_64.whl (14.5 MB view details)

Uploaded Python 3musllinux: musl 1.2+ x86-64

mini_racer-0.10.0-py3-none-musllinux_1_2_aarch64.whl (14.7 MB view details)

Uploaded Python 3musllinux: musl 1.2+ ARM64

mini_racer-0.10.0-py3-none-manylinux_2_31_x86_64.whl (14.5 MB view details)

Uploaded Python 3manylinux: glibc 2.31+ x86-64

mini_racer-0.10.0-py3-none-manylinux_2_31_aarch64.whl (14.5 MB view details)

Uploaded Python 3manylinux: glibc 2.31+ ARM64

mini_racer-0.10.0-py3-none-macosx_11_0_arm64.whl (14.3 MB view details)

Uploaded Python 3macOS 11.0+ ARM64

mini_racer-0.10.0-py3-none-macosx_10_9_x86_64.whl (15.2 MB view details)

Uploaded Python 3macOS 10.9+ x86-64

File details

Details for the file mini_racer-0.10.0.tar.gz.

File metadata

  • Download URL: mini_racer-0.10.0.tar.gz
  • Upload date:
  • Size: 417.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.0.0 CPython/3.12.2

File hashes

Hashes for mini_racer-0.10.0.tar.gz
Algorithm Hash digest
SHA256 a970a53bf17809254a770e563ed749e3e33958c6471954bd34d5912d7d1cbfd7
MD5 2a7237ff15b81122e16c2d996bece0a5
BLAKE2b-256 ba95a4aeec0321f265ae0bdf3fa541eec0bed1dbafe1cfe93352f71a77e1719a

See more details on using hashes here.

File details

Details for the file mini_racer-0.10.0-py3-none-win_amd64.whl.

File metadata

  • Download URL: mini_racer-0.10.0-py3-none-win_amd64.whl
  • Upload date:
  • Size: 12.9 MB
  • Tags: Python 3, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.0.0 CPython/3.12.2

File hashes

Hashes for mini_racer-0.10.0-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 b404c676f3535d70bc3548722b108917bc79719ef92f4756dbc0dce17ab1b54e
MD5 07c6edb3bbd53861f5acb663ba7dd939
BLAKE2b-256 af3300c7dc9b250ce548370ec9a59244836d82a6ead2725214fd2c86c660c0ed

See more details on using hashes here.

File details

Details for the file mini_racer-0.10.0-py3-none-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for mini_racer-0.10.0-py3-none-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 bba97b890134531e4471a1086fd5206815adf4d349a237d4179d1ad9f130fc27
MD5 f1de6fb2af5568cdb08cdfc8e1993769
BLAKE2b-256 e2e85ead0f3920c54b37aa333676f74234f8021c3dbd2c4ac2d344ecf695a843

See more details on using hashes here.

File details

Details for the file mini_racer-0.10.0-py3-none-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for mini_racer-0.10.0-py3-none-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 b11ea0d43949df3e3df90510b0dd2b9299c54b4cd6931112e3ebdbbab8deba96
MD5 0fb57f8396b83f9735ccc241cf7ef979
BLAKE2b-256 6a241a0ee7de915d9631547cf003d55ac63ff449dc3a1b1675e6683e032779f1

See more details on using hashes here.

File details

Details for the file mini_racer-0.10.0-py3-none-manylinux_2_31_x86_64.whl.

File metadata

File hashes

Hashes for mini_racer-0.10.0-py3-none-manylinux_2_31_x86_64.whl
Algorithm Hash digest
SHA256 a1992a525cfe062c3d78b1783641d11276f396a003c97db5789cd69c93248ffd
MD5 e3e1ac149b1b75fab20ca9f2c761a088
BLAKE2b-256 ac612357d794994934a3990a035b91b427fda0d06ad3ce46dc94fce11a1e998e

See more details on using hashes here.

File details

Details for the file mini_racer-0.10.0-py3-none-manylinux_2_31_aarch64.whl.

File metadata

File hashes

Hashes for mini_racer-0.10.0-py3-none-manylinux_2_31_aarch64.whl
Algorithm Hash digest
SHA256 e3f5e1e9e4901a640bf9860a2aa9eaea5e58d0dddb2fe1cd14b2bc5cf36bf202
MD5 004e32a12095687d44e9869a112d46d8
BLAKE2b-256 d59dd0face656d565c69c3bb4901b063f714860e8d3535cb2e65f641e8f12504

See more details on using hashes here.

File details

Details for the file mini_racer-0.10.0-py3-none-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for mini_racer-0.10.0-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 94995b269533f39c81634ad07012428b9e7bed6c939d322ffff3a38f06445f3c
MD5 d2f18a6c82bc16552a3d4fc4eec00ba7
BLAKE2b-256 7144ea9ec69a24f8819b523d4c4a019abc73322c66dd4f3308bb9f7b36bfd11b

See more details on using hashes here.

File details

Details for the file mini_racer-0.10.0-py3-none-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for mini_racer-0.10.0-py3-none-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 99c86bef3e10e44e9c152c450c617a435c6d5de33bc15296b0fecfb2af5cccdb
MD5 0075f44c876ef42c135f9a311e5ab287
BLAKE2b-256 cda69b7ccdab76a27798fbca28c71b0932602ee6e89d176e2e33cfe9b3bae842

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page