diff --git a/.github/workflows/website.yml b/.github/workflows/website.yml index 6120173c..5727f962 100644 --- a/.github/workflows/website.yml +++ b/.github/workflows/website.yml @@ -18,6 +18,7 @@ jobs: - uses: actions/setup-node@v3.1.1 - name: Retype build run: | + python scripts/gen_docs.py cd docs npm install retypeapp --global retype build diff --git a/.gitignore b/.gitignore index 3d69b671..5e644ff6 100644 --- a/.gitignore +++ b/.gitignore @@ -36,3 +36,4 @@ docs/references.md .vs tests/00_tmp.py +docs/C-API/functions.md diff --git a/docs/modules/base64.md b/docs/modules/base64.md deleted file mode 100644 index 7f0429df..00000000 --- a/docs/modules/base64.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -icon: package -label: base64 ---- - -### `base64.b64encode(b: bytes) -> bytes` - -Encode bytes-like object `b` using the standard Base64 alphabet. - -### `base64.b64decode(b: bytes) -> bytes` - -Decode Base64 encoded bytes-like object `b`. - diff --git a/docs/modules/bisect.md b/docs/modules/bisect.md index 843583ad..6faa1850 100644 --- a/docs/modules/bisect.md +++ b/docs/modules/bisect.md @@ -21,4 +21,8 @@ If x is already in a, insert it to the left of the leftmost x. Insert item `x` in list `a`, and keep it sorted assuming `a` is sorted. -If x is already in a, insert it to the right of the rightmost x. \ No newline at end of file +If x is already in a, insert it to the right of the rightmost x. + +#### Source code + +:::code source="../../python/bisect.py" ::: \ No newline at end of file diff --git a/docs/modules/cmath.md b/docs/modules/cmath.md index ef241d7f..5309f637 100644 --- a/docs/modules/cmath.md +++ b/docs/modules/cmath.md @@ -3,10 +3,10 @@ icon: package label: cmath --- -!!! -This module is experimental and may have bugs or other issues. -!!! - Mathematical functions for complex numbers. https://docs.python.org/3/library/cmath.html + +#### Source code + +:::code source="../../python/cmath.py" ::: \ No newline at end of file diff --git a/docs/modules/collections.md b/docs/modules/collections.md index 8273804a..b44ab53b 100644 --- a/docs/modules/collections.md +++ b/docs/modules/collections.md @@ -3,7 +3,6 @@ icon: package label: collections --- - ### `collections.Counter(iterable)` Return a `dict` containing the counts of each element in `iterable`. @@ -14,4 +13,8 @@ A double-ended queue. ### `collections.defaultdict` -A dictionary that returns a default value when a key is not found. \ No newline at end of file +A dictionary that returns a default value when a key is not found. + +#### Source code + +:::code source="../../python/collections.py" ::: \ No newline at end of file diff --git a/docs/modules/dataclasses.md b/docs/modules/dataclasses.md index c6372233..31705ca3 100644 --- a/docs/modules/dataclasses.md +++ b/docs/modules/dataclasses.md @@ -5,7 +5,7 @@ label: dataclasses ### `dataclasses.dataclass` -A decorator that is used to add generated special method to classes, including `__init__`, `__repr__` and `__eq__`. +A decorator that is used to add special method to classes, including `__init__`, `__repr__` and `__eq__`. ### `dataclasses.asdict(obj) -> dict` diff --git a/docs/modules/datetime.md b/docs/modules/datetime.md index fbe13cf4..23fe00ac 100644 --- a/docs/modules/datetime.md +++ b/docs/modules/datetime.md @@ -9,4 +9,8 @@ Returns the current date and time as a `datetime` object. ### `date.today()` -Returns the current local date as a `date` object. \ No newline at end of file +Returns the current local date as a `date` object. + +#### Source code + +:::code source="../../python/datetime.py" ::: \ No newline at end of file diff --git a/docs/modules/functools.md b/docs/modules/functools.md index b0d89da7..3a88fe85 100644 --- a/docs/modules/functools.md +++ b/docs/modules/functools.md @@ -14,3 +14,8 @@ Apply a function of two arguments cumulatively to the items of a sequence, from ### `functools.partial(f, *args, **kwargs)` Return a new partial object which when called will behave like `f` called with the positional arguments `args` and keyword arguments `kwargs`. If more arguments are supplied to the call, they are appended to `args`. If additional keyword arguments are supplied, they extend and override `kwargs`. + + +#### Source code + +:::code source="../../python/functools.py" ::: \ No newline at end of file diff --git a/docs/modules/heapq.md b/docs/modules/heapq.md index 756ff00a..2ec75141 100644 --- a/docs/modules/heapq.md +++ b/docs/modules/heapq.md @@ -21,4 +21,8 @@ Push `item` on the heap, then pop and return the smallest item from the heap. Th ### `heapq.heapreplace(heap, item)` -Pop and return the smallest item from the heap, and also push the new item. The heap size doesn’t change. If the heap is empty, IndexError is raised. \ No newline at end of file +Pop and return the smallest item from the heap, and also push the new item. The heap size doesn’t change. If the heap is empty, IndexError is raised. + +#### Source code + +:::code source="../../python/heapq.py" ::: \ No newline at end of file diff --git a/docs/modules/json.md b/docs/modules/json.md index 4705d64c..535f420f 100644 --- a/docs/modules/json.md +++ b/docs/modules/json.md @@ -3,13 +3,7 @@ icon: package label: json --- -pkpy has two JSON modules. -1. The built-in JSON module is always available and can be imported via `import json`. -2. After `v1.2.7`, you can set `PK_USE_CJSON` to `ON` in CMakeLists.txt to enable an alternative JSON module `cjson`. - -**Their interfaces are the same.** `cjson` is faster while the built-in `json` is more stable since it was developed earlier. - -### `json.loads(data: str | bytes)` +### `json.loads(data: str)` Decode a JSON string into a python object. diff --git a/docs/modules/linalg.md b/docs/modules/linalg.md index e3f28a07..cb46a3cc 100644 --- a/docs/modules/linalg.md +++ b/docs/modules/linalg.md @@ -9,166 +9,4 @@ This classes adopt `torch`'s naming convention. Methods with `_` suffix will mod https://github.com/pocketpy/pocketpy/blob/main/include/typings/linalg.pyi -```python -from typing import overload -from c import _StructLike, float_p - -class vec2: - x: float - y: float - - def __init__(self, x: float, y: float) -> None: ... - def __add__(self, other: vec2) -> vec2: ... - def __sub__(self, other: vec2) -> vec2: ... - def __getitem__(self, index: int) -> float: ... - - @overload - def __mul__(self, other: float) -> vec2: ... - @overload - def __mul__(self, other: vec2) -> vec2: ... - - def __rmul__(self, other: float) -> vec2: ... - def __truediv__(self, other: float) -> vec2: ... - def dot(self, other: vec2) -> float: ... - def cross(self, other: vec2) -> float: ... - def length(self) -> float: ... - def length_squared(self) -> float: ... - def normalize(self) -> vec2: ... - def rotate(self, radians: float) -> vec2: ... - - @staticmethod - def angle(__from: vec2, __to: vec2) -> float: - """Returns the angle in radians between vectors `from` and `to`. - - The result range is `[-pi, pi]`. - - + if y axis is top to bottom, positive value means clockwise - + if y axis is bottom to top, positive value means counter-clockwise - """ - - @staticmethod - def smooth_damp(current: vec2, target: vec2, current_velocity: vec2, smooth_time: float, max_speed: float, delta_time: float) -> tuple[vec2, vec2]: - ... - -class vec3: - x: float - y: float - z: float - - def __init__(self, x: float, y: float, z: float) -> None: ... - def __add__(self, other: vec3) -> vec3: ... - def __sub__(self, other: vec3) -> vec3: ... - def __getitem__(self, index: int) -> float: ... - - @overload - def __mul__(self, other: float) -> vec3: ... - @overload - def __mul__(self, other: vec3) -> vec3: ... - - def __rmul__(self, other: float) -> vec3: ... - def __truediv__(self, other: float) -> vec3: ... - def dot(self, other: vec3) -> float: ... - def cross(self, other: vec3) -> float: ... - def length(self) -> float: ... - def length_squared(self) -> float: ... - def normalize(self) -> vec3: ... - -class vec4(_StructLike['vec4']): - x: float - y: float - z: float - w: float - - def __init__(self, x: float, y: float, z: float, w: float) -> None: ... - def __add__(self, other: vec4) -> vec4: ... - def __sub__(self, other: vec4) -> vec4: ... - def __getitem__(self, index: int) -> float: ... - - @overload - def __mul__(self, other: float) -> vec4: ... - @overload - def __mul__(self, other: vec4) -> vec4: ... - - def __rmul__(self, other: float) -> vec4: ... - def __truediv__(self, other: float) -> vec4: ... - def dot(self, other: vec4) -> float: ... - def length(self) -> float: ... - def length_squared(self) -> float: ... - def normalize(self) -> vec4: ... - - def copy_(self, other: vec4) -> None: ... - def normalize_(self) -> None: ... - -class mat3x3(_StructLike['mat3x3']): - _11: float - _12: float - _13: float - _21: float - _22: float - _23: float - _31: float - _32: float - _33: float - - @overload - def __init__(self) -> None: ... - @overload - def __init__(self, _11, _12, _13, _21, _22, _23, _31, _32, _33) -> None: ... - @overload - def __init__(self, a: list[float]): ... - - def determinant(self) -> float: ... - def inverse(self) -> mat3x3: ... - def transpose(self) -> mat3x3: ... - - def __getitem__(self, index: tuple[int, int]) -> float: ... - def __setitem__(self, index: tuple[int, int], value: float) -> None: ... - def __add__(self, other: mat3x3) -> mat3x3: ... - def __sub__(self, other: mat3x3) -> mat3x3: ... - def __mul__(self, other: float) -> mat3x3: ... - def __rmul__(self, other: float) -> mat3x3: ... - def __truediv__(self, other: float) -> mat3x3: ... - - def __invert__(self) -> mat3x3: ... - @overload - def __matmul__(self, other: mat3x3) -> mat3x3: ... - @overload - def __matmul__(self, other: vec3) -> vec3: ... - - def matmul(self, other: mat3x3, out: mat3x3 = None) -> mat3x3 | None: ... - - def copy_(self, other: mat3x3) -> None: ... - def inverse_(self) -> None: ... - def transpose_(self) -> None: ... - - @staticmethod - def zeros() -> mat3x3: ... - @staticmethod - def ones() -> mat3x3: ... - @staticmethod - def identity() -> mat3x3: ... - - # affine transformations - @staticmethod - def trs(t: vec2, r: float, s: vec2) -> mat3x3: ... - - def copy_trs_(self, t: vec2, r: float, s: vec2) -> None: ... - def copy_t_(self, t: vec2) -> None: ... - def copy_r_(self, r: float) -> None: ... - def copy_s_(self, s: vec2) -> None: ... - - def _t(self) -> vec2: ... - def _r(self) -> float: ... - def _s(self) -> vec2: ... - - def is_affine(self) -> bool: ... - - def transform_point(self, p: vec2) -> vec2: ... - def transform_vector(self, v: vec2) -> vec2: ... - def inverse_transform_point(self, p: vec2) -> vec2: ... - def inverse_transform_vector(self, v: vec2) -> vec2: ... - -vec4_p = float_p -mat3x3_p = float_p - -``` +:::code source="../../include/typings/linalg.pyi" ::: \ No newline at end of file diff --git a/docs/modules/typing.md b/docs/modules/typing.md index 1cb7a058..3eaca5c9 100644 --- a/docs/modules/typing.md +++ b/docs/modules/typing.md @@ -4,3 +4,5 @@ label: typing --- Placeholder module for type hints. + +:::code source="../../python/typing.py" ::: \ No newline at end of file diff --git a/scripts/gen_docs.py b/scripts/gen_docs.py new file mode 100644 index 00000000..aba10635 --- /dev/null +++ b/scripts/gen_docs.py @@ -0,0 +1,68 @@ +import re +from dataclasses import dataclass + +NEWLINE = '\n' + +@dataclass +class Function: + name: str + args: str + ret: str + comment: str + is_py_raise: bool + is_py_return: bool + + def signature(self): + tmp = f"PK_EXPORT {self.ret} {self.name}{self.args}" + return tmp + ';' + + def badges(self): + res = [] + if self.is_py_raise: + res.append('[!badge text="raise" variant="danger"]') + if self.is_py_return: + res.append('[!badge text="return"]') + return ' '.join(res) + + def markdown(self): + lines = [ + f"### {self.name}" + f" {self.badges()}", + f"```c", + self.comment, + f"{self.signature()}", + f"```", + ] + return '\n'.join(lines) + +with open('include/pocketpy/pocketpy.h') as f: + header = f.read() + +matches = re.finditer(r"((?:/// [^\n]+[\n])*?)PK_EXPORT\s+(\w+)\s+(\w+)(\(.*?\))\s*(PY_RAISE)?\s*(PY_RETURN)?\s*;", header, re.DOTALL) +# ^1 comment ^2 ret ^3 ^4 args ^5 py_raise? ^6 py_return? + +functions: list[Function] = [] +for match in matches: + functions.append(Function( + name=match[3], + args=match[4], + ret=match[2], + comment=match[1].strip(), + is_py_raise=bool(match[5]), + is_py_return=bool(match[6]) + )) + # print(functions[-1]) + + +# generate markdown +with open('docs/C-API/functions.md', 'w', newline='\n') as f: + f.write('\n'.join([ + '---', + 'title: Functions', + 'icon: dot', + 'order: 0', + '---', + '\n\n', + ])) + for function in functions: + f.write(function.markdown()) + f.write('\n\n') \ No newline at end of file