8000 fix: Linting, documentation, JSR, CI, etc. by eliassjogreen · Pull Request #81 · denosaurs/deno_python · GitHub
[go: up one dir, main page]

Skip to content

fix: Linting, documentation, JSR, CI, etc. #81

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

Merged
merged 4 commits into from
Feb 10, 2025
Merged
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
21 changes: 7 additions & 14 deletions .github/workflows/checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,10 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout sources
uses: actions/checkout@v2
uses: actions/checkout@v4

- name: Setup latest deno version
uses: denoland/setup-deno@v1
with:
deno-version: v1.x
uses: denoland/setup-deno@v2

- name: Run deno fmt
run: deno fmt --check
Expand All @@ -28,31 +26,26 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout sources
uses: actions/checkout@v2
uses: actions/checkout@v4

- name: Setup latest deno version
uses: denoland/setup-deno@v1
with:
deno-version: v1.x
uses: denoland/setup-deno@v2

- name: Run deno task check
run: deno task check


test:
name: test ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [windows-latest, ubuntu-latest, macos-latest,]
os: [windows-latest, ubuntu-latest, macos-latest]
steps:
- name: Checkout sources
uses: actions/checkout@v2

- name: Setup latest deno version
uses: denoland/setup-deno@v1
with:
deno-version: v1.x
uses: denoland/setup-deno@v2
8000
- name: Setup Bun
if: ${{ matrix.os != 'windows-latest' }}
Expand All @@ -62,7 +55,7 @@ jobs:
uses: actions/setup-python@v2
if: ${{ matrix.os == 'windows-latest' }}
with:
python-version: '3.13'
python-version: "3.13"

- name: Install NumPy
if: ${{ matrix.os != 'macos-latest' }}
Expand Down
22 changes: 22 additions & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
name: Publish

on:
push:
branches:
- main

jobs:
publish:
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
steps:
- name: Checkout sources
uses: actions/checkout@v4

- name: Setup latest deno version
uses: denoland/setup-deno@v2

- name: Publish to JSR
run: deno publish
23 changes: 23 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,29 @@ the Python dynamic library, which is like `python310.dll` (Windows),
`libpython310.dylib` (macOS) and `libpython310.so` (Linux) depending on
platform.

## Usage with docker

Usage with docker is easiest done using the
[`denoland/deno:bin` image](https://github.com/denoland/deno_docker?tab=readme-ov-file#using-your-own-base-image)
along with the [official `python` image](https://hub.docker.com/_/python/).

```Dockerfile
ARG DENO_VERSION=1.38.2
ARG PYTHON_VERSION=3.12

FROM denoland/deno:bin-$DENO_VERSION AS deno
FROM python:$PYTHON_VERSION

# Copy and configure deno
COPY --from=deno /deno /usr/local/bin/deno
ENTRYPOINT ["/usr/local/bin/deno"]

# Copy your project source
COPY . .

RUN ["run", "-A", "--unstable", "https://deno.land/x/python@0.4.2/examples/hello_python.ts"]
```

## Maintainers

- DjDeveloper ([@DjDeveloperr](https://github.com/DjDeveloperr))
Expand Down
6 changes: 6 additions & 0 deletions deno.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
{
"name": "@denosaurs/python",
"version": "0.4.4",
"exports": {
".": "./mod.ts",
"./ext/pip": "./ext/pip.ts"
},
"tasks": {
"check": "deno task check:mod && deno task check:ext && deno task check:examples",
"check:mod": "deno check --unstable-ffi mod.ts",
Expand Down
5 changes: 3 additions & 2 deletions ext/pip.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,8 @@ export class Pip {
*
* ```
*/
async import(module: string, entrypoint?: string) {
// deno-lint-ignore no-explicit-any
async import(module: string, entrypoint?: string): Promise<any> {
const { name } = getModuleNameAndVersion(module);

await this.install(module);
Expand Down Expand Up @@ -166,5 +167,5 @@ export class Pip {
}
}

export const pip = new Pip();
export const pip: Pip = new Pip();
export default pip;
4 changes: 2 additions & 2 deletions ipy.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import py, { Python } from "./mod.ts";
import { Pip, pip } from "./ext/pip.ts";
import py, { type Python } from "./mod.ts";
import { type Pip, pip } from "./ext/pip.ts";

declare global {
const py: Python;
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "bunpy",
"version": "0.3.3",
"version": "0.4.4",
"description": "JavaScript -> Python Bridge for Deno and Bun",
"main": "mod.bun.ts",
"directories": {
Expand Down
65 changes: 38 additions & 27 deletions src/python.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,10 @@ export function kw(
* ```
*/
export class Callback {
unsafe;
unsafe: Deno.UnsafeCallback<{
parameters: ["pointer", "pointer", "pointer"];
result: "pointer";
}>;

constructor(public callback: PythonJSCallback) {
this.unsafe = new Deno.UnsafeCallback(
Expand Down Expand Up @@ -200,7 +203,7 @@ export class PyObject {
/**
* Check if the object is NULL (pointer) or None type in Python.
*/
get isNone() {
get isNone(): boolean {
// deno-lint-ignore ban-ts-comment
// @ts-expect-error
return this.handle === null || this.handle === 0 ||
Expand Down Expand Up @@ -403,9 +406,17 @@ export class PyObject {
/**
* Performs an equals operation on the Python object.
*/
equals(rhs: PythonConvertible) {
equals(rhs: PythonConvertible): boolean {
const rhsObject = PyObject.from(rhs);
return py.PyObject_RichCompareBool(this.handle, rhsObject.handle, 3);
const comparison = py.PyObject_RichCompareBool(
this.handle,
rhsObject.handle,
3,
);
if (comparison === -1) {
maybeThrowError();
}
return comparison === 1;
}

/**
Expand Down Expand Up @@ -590,7 +601,7 @@ export class PyObject {
/**
* Tries to set the attribute, throws an error otherwise.
*/
setAttr(name: string, v: PythonConvertible) {
setAttr(name: string, v: PythonConvertible): void {
if (
py.PyObject_SetAttrString(
this.handle,
Expand All @@ -603,43 +614,43 @@ export class PyObject {
}

/** Checks if Python object has an attribute of given name. */
hasAttr(attr: string) {
hasAttr(attr: string): boolean {
return py.PyObject_HasAttrString(this.handle, cstr(attr)) !== 0;
}

/**
* Casts a Bool Python object as JS Boolean value.
*/
asBoolean() {
asBoolean(): boolean {
return py.PyLong_AsLong(this.handle) === 1;
}

/**
* Casts a Int Python object as JS Number value.
*/
asLong() {
asLong(): number {
return py.PyLong_AsLong(this.handle) as number;
}

/**
* Casts a Float (Double) Python object as JS Number value.
*/
asDouble() {
asDouble(): number {
return py.PyFloat_AsDouble(this.handle) as number;
}

/**
* Casts a String Python object as JS String value.
*/
asString() {
asString(): string | null {
const str = py.PyUnicode_AsUTF8(this.handle);
return str !== null ? Deno.UnsafePointerView.getCString(str) : null;
}

/**
* Casts a List Python object as JS Array value.
*/
asArray() {
asArray(): PythonConvertible[] {
const array: PythonConvertible[] = [];
for (const i of this) {
array.push(i.valueOf());
Expand All @@ -653,7 +664,7 @@ export class PyObject {
* Note: `from` supports converting both Map and Object to Python Dict.
* But this only supports returning a Map.
*/
asDict() {
asDict(): Map<PythonConvertible, PythonConvertible> {
const dict = new Map<PythonConvertible, PythonConvertible>();
const keys = py.PyDict_Keys(this.handle);
const length = py.PyList_Size(keys) as number;
Expand All @@ -669,7 +680,7 @@ export class PyObject {
return dict;
}

*[Symbol.iterator]() {
*[Symbol.iterator](): Generator<PyObject> {
const iter = py.PyObject_GetIter(this.handle);
let item = py.PyIter_Next(iter);
while (item !== null) {
Expand All @@ -682,8 +693,8 @@ export class PyObject {
/**
* Casts a Set Python object as JS Set object.
*/
asSet() {
const set = new Set();
asSet(): Set<PythonConvertible> {
const set = new Set<PythonConvertible>();
for (const i of this) {
set.add(i.valueOf());
}
Expand All @@ -693,7 +704,7 @@ export class PyObject {
/**
* Casts a Tuple Python object as JS Array value.
*/
asTuple() {
asTuple(): PythonConvertible[] {
const tuple = new Array<PythonConvertible>();
const length = py.PyTuple_Size(this.handle) as number;
for (let i = 0; i < length; i++) {
Expand All @@ -711,7 +722,7 @@ export class PyObject {
* Only primitives are casted as JS value type, otherwise returns
* a proxy to Python object.
*/
valueOf() {
valueOf(): any {
const type = py.PyObject_Type(this.handle);

if (Deno.UnsafePointer.equals(type, python.None[ProxiedPyObject].handle)) {
Expand Down Expand Up @@ -759,7 +770,7 @@ export class PyObject {
call(
positional: (PythonConvertible | NamedArgument)[] = [],
named: Record<string, PythonConvertible> = {},
) {
): PyObject {
// count named arguments
const namedCount = positional.filter(
(arg) => arg instanceof NamedArgument,
Expand Down Expand Up @@ -808,16 +819,16 @@ export class PyObject {
/**
* Returns `str` representation of the Python object.
*/
toString() {
toString(): string {
return new PyObject(py.PyObject_Str(this.handle))
.asString();
.asString()!;
}

[Symbol.for("Deno.customInspect")]() {
[Symbol.for("Deno.customInspect")](): string {
return this.toString();
}

[Symbol.for("nodejs.util.inspect.custom")]() {
[Symbol.for("nodejs.util.inspect.custom")](): string {
return this.toString();
}
}
Expand Down Expand Up @@ -928,7 +939,7 @@ export class Python {
/**
* Runs Python script from the given string.
*/
run(code: string) {
run(code: string): void {
if (py.PyRun_SimpleString(cstr(code)) !== 0) {
throw new EvalError("Failed to run python code");
}
Expand All @@ -938,7 +949,7 @@ export class Python {
* Runs Python script as a module and returns its module object,
* for using its attributes, functions, classes, etc. from JavaScript.
*/
runModule(code: string, name?: string) {
runModule(code: string, name?: string): any {
const module = py.PyImport_ExecCodeModule(
cstr(name ?? "__main__"),
PyObject.from(
Expand All @@ -956,7 +967,7 @@ export class Python {
/**
* Import a module as PyObject.
*/
importObject(name: string) {
importObject(name: string): PyObject {
const mod = py.PyImport_ImportModule(cstr(name));
if (mod === null) {
maybeThrowError();
Expand All @@ -968,7 +979,7 @@ export class Python {
/**
* Import a Python module as a proxy object.
*/
import(name: string) {
import(name: string): any {
return this.importObject(name).proxy;
}

Expand Down Expand Up @@ -1013,7 +1024,7 @@ export class Python {
* and also make use of some common built-ins attached to
* this object, such as `str`, `int`, `tuple`, etc.
*/
export const python = new Python();
export const python: Python = new Python();

/**
* Returns true if the value can be converted into a Python slice or
Expand Down
2 changes: 1 addition & 1 deletion test/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
ProxiedPyObject,
PyObject,
python,
PythonProxy,
type PythonProxy,
} from "../mod.ts";

const { version, executable } = python.import("sys");
Expand Down
0