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

Add types #120

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions _quickjs.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
from typing import Any, Callable, Literal


def test() -> Literal[1]: ...

JSValue = None | bool | int | float | str | Object

class Object():
def json(self) -> str: ...
def __call__(self, *args: Any) -> Any: ...

class Context:
def eval(self, code: str) -> JSValue: ...
def module(self, code: str) -> JSValue: ...
def execute_pending_job(self) -> bool: ...
def parse_json(self, data: str) -> JSValue: ...
def get(self, name: str) -> JSValue: ...
def set(self, name: str, item: JSValue) -> None: ...
def set_memory_limit(self, limit: int) -> None: ...
def set_time_limit(self, limit: int) -> None: ...
def set_max_stack_size(self, limit: int) -> None: ...
def memory(self) -> dict[str, int]: ...
def gc(self) -> None: ...
def add_callable(self, name: str, callable: Callable[..., Any]) -> None: ...
@property
def globalThis(self) -> Object: ...

class JSException(Exception):
pass

class StackOverflow(Exception):
pass
2 changes: 1 addition & 1 deletion module.c
Original file line number Diff line number Diff line change
Expand Up @@ -642,7 +642,7 @@ static PyObject *runtime_set_max_stack_size(RuntimeData *self, PyObject *args) {

// _quickjs.Context.memory
//
// Sets the CPU time limit of the context. This will be used in an interrupt handler.
// Returns the memory usage as a dict.
static PyObject *runtime_memory(RuntimeData *self) {
PyObject *dict = PyDict_New();
if (dict == NULL) {
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ description = "Python wrapper around https://bellard.org/quickjs/"
authors = ["Petter Strandmark"]

[tool.poetry.dependencies]
python = ">=3.6"
python = ">=3.7"

[tool.poetry.dev-dependencies]
yapf = "*"
Expand Down
23 changes: 12 additions & 11 deletions quickjs/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import concurrent.futures
import json
import threading
from typing import Tuple, Callable
from typing import Any, Tuple, Callable

import _quickjs

Expand All @@ -21,8 +21,8 @@ class Function:
# same runtime, even if it is not at the same time. So we run everything on the same thread in
# order to prevent this.
_threadpool = concurrent.futures.ThreadPoolExecutor(max_workers=1)
def __init__(self, name: str, code: str, *, own_executor=False) -> None:

def __init__(self, name: str, code: str, *, own_executor: bool = False) -> None:
"""
Arguments:
name: The name of the function in the provided code that will be executed.
Expand All @@ -39,29 +39,29 @@ def __init__(self, name: str, code: str, *, own_executor=False) -> None:
concurrent.futures.wait([future])
self._context, self._f = future.result()

def __call__(self, *args, run_gc=True):
def __call__(self, *args: Any, run_gc: bool = True) -> Any:
with self._lock:
future = self._threadpool.submit(self._call, *args, run_gc=run_gc)
concurrent.futures.wait([future])
return future.result()

def set_memory_limit(self, limit):
def set_memory_limit(self, limit: int):
with self._lock:
return self._context.set_memory_limit(limit)

def set_time_limit(self, limit):
def set_time_limit(self, limit: int):
with self._lock:
return self._context.set_time_limit(limit)

def set_max_stack_size(self, limit):
def set_max_stack_size(self, limit: int):
with self._lock:
return self._context.set_max_stack_size(limit)

def memory(self):
with self._lock:
return self._context.memory()

def add_callable(self, global_name: str, callable: Callable) -> None:
def add_callable(self, global_name: str, callable: Callable[..., Any]) -> None:
with self._lock:
self._context.add_callable(global_name, callable)

Expand All @@ -86,10 +86,11 @@ def _compile(self, name: str, code: str) -> Tuple[Context, Object]:
context = Context()
context.eval(code)
f = context.get(name)
assert isinstance(f, Object)
return context, f

def _call(self, *args, run_gc=True):
def convert_arg(arg):
def _call(self, *args: Any, run_gc: bool = True):
def convert_arg(arg: Any):
if isinstance(arg, (type(None), str, bool, float, int)):
return arg
else:
Expand All @@ -99,7 +100,7 @@ def convert_arg(arg):
try:
result = self._f(*[convert_arg(a) for a in args])
if isinstance(result, Object):
result = json.loads(result.json())
result = json.loads(result.json())
return result
finally:
if run_gc:
Expand Down
Empty file added quickjs/py.typed
Empty file.
12 changes: 8 additions & 4 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import glob
import sys
from typing import List

Expand All @@ -16,13 +15,13 @@
# system PATH when compiling.
# 3. The code below will moneky-patch distutils to work.
import distutils.cygwinccompiler
distutils.cygwinccompiler.get_msvcr = lambda: []
distutils.cygwinccompiler.get_msvcr = lambda: [] # type: ignore
# Make sure that pthreads is linked statically, otherwise we run into problems
# on computers where it is not installed.
extra_link_args = ["-static"]


def get_c_sources(include_headers=False):
def get_c_sources(include_headers: bool = False):
sources = [
"module.c",
"upstream-quickjs/cutils.c",
Expand Down Expand Up @@ -77,4 +76,9 @@ def get_c_sources(include_headers=False):
description='Wrapping the quickjs C library.',
long_description=long_description,
packages=["quickjs"],
ext_modules=[_quickjs])
ext_modules=[_quickjs],
package_data={
"": ["_quickjs.pyi"],
"quickjs": ["py.typed"]
},
include_package_data=True,)