Skip to content

Commit 545966b

Browse files
committed
feat(bindgen): generate dispatch package test scaffold
1 parent e1a7cec commit 545966b

File tree

6 files changed

+209
-36
lines changed

6 files changed

+209
-36
lines changed

packages/core/typescript/itk-wasm/src/bindgen/python/dispatch-package.js

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,19 @@
11
import path from 'path'
22

3-
import mkdirP from "../mkdir-p.js"
3+
import mkdirP from '../mkdir-p.js'
44

5-
import snakeCase from "../snake-case.js"
5+
import snakeCase from '../snake-case.js'
66

7-
import dispatchPackageReadme from "./dispatch-package-readme.js"
8-
import dispatchFunctionModule from "./dispatch-function-module.js"
7+
import dispatchPackageReadme from './dispatch-package-readme.js'
8+
import dispatchFunctionModule from './dispatch-function-module.js'
99
import packagePyProjectToml from './package-py-project-toml.js'
10-
import packageDocs from "./package-docs.js"
11-
import packageDunderInit from "./package-dunder-init.js"
12-
import packageVersion from "./package-version.js"
10+
import packageDocs from './package-docs.js'
11+
import packageDunderInit from './package-dunder-init.js'
12+
import dispatchTestModule from './dispatch-test-module.js'
13+
import dispatchPipelineTest from './dispatch-pipeline-test.js'
14+
import packageVersion from './package-version.js'
1315

14-
import wasmBinaryInterfaceJson from "../wasm-binary-interface-json.js"
16+
import wasmBinaryInterfaceJson from '../wasm-binary-interface-json.js'
1517

1618
function dispatchPackage(outputDir, buildDir, wasmBinaries, options) {
1719
const packageName = options.packageName
@@ -27,13 +29,33 @@ function dispatchPackage(outputDir, buildDir, wasmBinaries, options) {
2729
packageVersion(packageDir, pypackage, options)
2830
const async = true
2931
const sync = true
30-
packageDunderInit(outputDir, buildDir, wasmBinaries, packageName, options.packageDescription, packageDir, pypackage, async, sync)
32+
packageDunderInit(
33+
outputDir,
34+
buildDir,
35+
wasmBinaries,
36+
packageName,
37+
options.packageDescription,
38+
packageDir,
39+
pypackage,
40+
async,
41+
sync
42+
)
3143
packageDocs(packageName, packageDir, pypackage, options)
44+
dispatchTestModule(packageDir, pypackage)
3245

3346
wasmBinaries.forEach((wasmBinaryName) => {
34-
const { interfaceJson } = wasmBinaryInterfaceJson(outputDir, buildDir, wasmBinaryName)
47+
const { interfaceJson } = wasmBinaryInterfaceJson(
48+
outputDir,
49+
buildDir,
50+
wasmBinaryName
51+
)
3552
const functionName = snakeCase(interfaceJson.name)
36-
dispatchFunctionModule(interfaceJson, pypackage, path.join(packageDir, pypackage, `${functionName}.py`))
53+
dispatchFunctionModule(
54+
interfaceJson,
55+
pypackage,
56+
path.join(packageDir, pypackage, `${functionName}.py`)
57+
)
58+
dispatchPipelineTest(packageDir, pypackage, functionName)
3759
})
3860
}
3961

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import fs from 'fs-extra'
2+
import path from 'path'
3+
4+
function dispatchPipelineTest(packageDir, pypackage, functionName) {
5+
const testDir = path.join(packageDir, 'tests')
6+
const testModulePath = path.join(testDir, `test_${functionName}.py`)
7+
8+
let moduleContent = `import pytest
9+
import sys
10+
11+
if sys.version_info < (3,10):
12+
pytest.skip("Skipping pyodide tests on older Python", allow_module_level=True)
13+
14+
from pytest_pyodide import run_in_pyodide
15+
16+
from .fixtures import emscripten_package_wheel, package_wheel, input_data
17+
18+
@run_in_pyodide(packages=['micropip'])
19+
async def test_${functionName}(selenium, package_wheel, emscripten_package_wheel):
20+
import micropip
21+
await micropip.install(emscripten_package_wheel)
22+
await micropip.install(package_wheel)
23+
24+
from ${pypackage} import ${functionName}
25+
26+
# Write your test code here
27+
`
28+
29+
if (!fs.existsSync(testModulePath)) {
30+
fs.writeFileSync(testModulePath, moduleContent)
31+
}
32+
}
33+
34+
export default dispatchPipelineTest
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import fs from 'fs-extra'
2+
import path from 'path'
3+
4+
import mkdirP from '../mkdir-p.js'
5+
6+
function dispatchTestModule(packageDir, pypackage) {
7+
const testDir = path.join(packageDir, 'tests')
8+
mkdirP(testDir)
9+
10+
const initPath = path.join(testDir, '__init__.py')
11+
if (!fs.existsSync(initPath)) {
12+
fs.writeFileSync(initPath, '')
13+
}
14+
15+
const fixturesContent = `import pytest
16+
import sys
17+
import glob
18+
19+
if sys.version_info < (3,10):
20+
pytest.skip("Skipping pyodide tests on older Python", allow_module_level=True)
21+
22+
from pytest_pyodide import run_in_pyodide
23+
24+
from ${pypackage} import __version__ as test_package_version
25+
26+
@pytest.fixture
27+
def package_wheel():
28+
return f"${pypackage}-{test_package_version}-py3-none-any.whl"
29+
30+
@pytest.fixture
31+
def emscripten_package_wheel():
32+
return f"${pypackage}-emscripten-{test_package_version}-py3-none-any.whl"
33+
34+
@pytest.fixture
35+
def input_data():
36+
from pathlib import Path
37+
input_base_path = Path(__file__).parent.parent / 'test' / 'data'
38+
test_files = list(input_base_path.glob('*'))
39+
data = {}
40+
for test_file in test_files:
41+
with open(test_file, 'rb') as f:
42+
data[test_file.name] = f.read()
43+
return data
44+
`
45+
const fixturesPath = path.join(testDir, 'fixtures.py')
46+
if (!fs.existsSync(fixturesPath)) {
47+
fs.writeFileSync(fixturesPath, fixturesContent)
48+
}
49+
}
50+
51+
export default dispatchTestModule

packages/core/typescript/itk-wasm/src/bindgen/python/emscripten/emscripten-package.js

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,24 +10,36 @@ import packageVersion from '../package-version.js'
1010
import packageDunderInit from '../package-dunder-init.js'
1111
import emscriptenPyodideModule from './emscripten-pyodide-module.js'
1212
import emscriptenTestModule from './emscripten-test-module.js'
13+
import emscriptenPipelineTest from './emscripten-pipeline-test.js'
1314
import emscriptenFunctionModule from './emscripten-function-module.js'
1415
import wasmBinaryInterfaceJson from '../../wasm-binary-interface-json.js'
1516

1617
function emscriptenPackage(outputDir, buildDir, wasmBinaries, options) {
17-
const defaultJsModulePath = path.join(outputDir, '..', 'typescript', 'dist', 'bundle', 'index-worker-embedded.min.js')
18+
const defaultJsModulePath = path.join(
19+
outputDir,
20+
'..',
21+
'typescript',
22+
'dist',
23+
'bundle',
24+
'index-worker-embedded.min.js'
25+
)
1826
const moduleUrl = options.jsModulePath ?? defaultJsModulePath
1927
if (!fs.existsSync(moduleUrl)) {
20-
console.warn(`Could not find ${moduleUrl}: skipping python emscripten package`)
28+
console.warn(
29+
`Could not find ${moduleUrl}: skipping python emscripten package`
30+
)
2131
return
2232
}
23-
const jsModuleContent = btoa(fs.readFileSync(moduleUrl, { encoding: 'utf8', flag: 'r' }))
33+
const jsModuleContent = btoa(
34+
fs.readFileSync(moduleUrl, { encoding: 'utf8', flag: 'r' })
35+
)
2436

2537
const packageName = `${options.packageName}-emscripten`
2638
const packageDir = path.join(outputDir, packageName)
2739
const packageDescription = `${options.packageDescription} Emscripten implementation.`
2840
mkdirP(packageDir)
2941

30-
const pypackage = snakeCase(packageName)
42+
const pypackage = snakeCase(packageName)
3143
const bindgenPyPackage = pypackage
3244
mkdirP(path.join(packageDir, pypackage))
3345

@@ -36,16 +48,35 @@ function emscriptenPackage(outputDir, buildDir, wasmBinaries, options) {
3648
packageVersion(packageDir, pypackage, options)
3749
const async = true
3850
const sync = false
39-
packageDunderInit(outputDir, buildDir, wasmBinaries, packageName, packageDescription, packageDir, pypackage, async, sync)
51+
packageDunderInit(
52+
outputDir,
53+
buildDir,
54+
wasmBinaries,
55+
packageName,
56+
packageDescription,
57+
packageDir,
58+
pypackage,
59+
async,
60+
sync
61+
)
4062
emscriptenPyodideModule(jsModuleContent, packageDir, pypackage)
4163
emscriptenTestModule(packageDir, pypackage)
4264

4365
const wasmModulesDir = path.join(packageDir, pypackage, 'wasm_modules')
4466
mkdirP(wasmModulesDir)
4567
wasmBinaries.forEach((wasmBinaryName) => {
46-
const { interfaceJson, parsedPath } = wasmBinaryInterfaceJson(outputDir, buildDir, wasmBinaryName)
68+
const { interfaceJson, parsedPath } = wasmBinaryInterfaceJson(
69+
outputDir,
70+
buildDir,
71+
wasmBinaryName
72+
)
4773
const functionName = snakeCase(interfaceJson.name) + '_async'
48-
emscriptenFunctionModule(interfaceJson, pypackage, path.join(packageDir, pypackage, `${functionName}.py`))
74+
emscriptenFunctionModule(
75+
interfaceJson,
76+
pypackage,
77+
path.join(packageDir, pypackage, `${functionName}.py`)
78+
)
79+
emscriptenPipelineTest(packageDir, pypackage, functionName)
4980
})
5081
}
5182

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import fs from 'fs-extra'
2+
import path from 'path'
3+
4+
function emscriptenPipelineTest(packageDir, pypackage, functionName) {
5+
const testDir = path.join(packageDir, 'tests')
6+
const testModulePath = path.join(testDir, `test_${functionName}.py`)
7+
8+
let moduleContent = `import pytest
9+
import sys
10+
11+
if sys.version_info < (3,10):
12+
pytest.skip("Skipping pyodide tests on older Python", allow_module_level=True)
13+
14+
from pytest_pyodide import run_in_pyodide
15+
16+
from .fixtures import package_wheel, input_data
17+
18+
@run_in_pyodide(packages=['micropip'])
19+
async def test_${functionName}(selenium, package_wheel):
20+
import micropip
21+
await micropip.install(package_wheel)
22+
23+
from ${pypackage} import ${functionName}
24+
25+
# Write your test code here
26+
`
27+
28+
if (!fs.existsSync(testModulePath)) {
29+
fs.writeFileSync(testModulePath, moduleContent)
30+
}
31+
}
32+
33+
export default emscriptenPipelineTest

packages/core/typescript/itk-wasm/src/bindgen/python/emscripten/emscripten-test-module.js

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,14 @@ function emscriptenTestModule(packageDir, pypackage) {
77
const testDir = path.join(packageDir, 'tests')
88
mkdirP(testDir)
99

10-
let moduleContent = `import pytest
10+
const initPath = path.join(testDir, '__init__.py')
11+
if (!fs.existsSync(initPath)) {
12+
fs.writeFileSync(initPath, '')
13+
}
14+
15+
const fixturesContent = `import pytest
1116
import sys
17+
import glob
1218
1319
if sys.version_info < (3,10):
1420
pytest.skip("Skipping pyodide tests on older Python", allow_module_level=True)
@@ -21,24 +27,20 @@ from ${pypackage} import __version__ as test_package_version
2127
def package_wheel():
2228
return f"${pypackage}-{test_package_version}-py3-none-any.whl"
2329
24-
@run_in_pyodide(packages=['micropip'])
25-
async def test_example(selenium, package_wheel):
26-
import micropip
27-
await micropip.install(package_wheel)
28-
29-
# Write your test code here
30+
@pytest.fixture
31+
def input_data():
32+
from pathlib import Path
33+
input_base_path = Path(__file__).parent.parent / 'test' / 'data'
34+
test_files = list(input_base_path.glob('*'))
35+
data = {}
36+
for test_file in test_files:
37+
with open(test_file, 'rb') as f:
38+
data[test_file.name] = f.read()
39+
return data
3040
`
31-
32-
const modulePath = path.join(
33-
testDir,
34-
`test_${pypackage.replace('_emscripten', '')}.py`
35-
)
36-
if (!fs.existsSync(modulePath)) {
37-
fs.writeFileSync(modulePath, moduleContent)
38-
}
39-
const initPath = path.join(testDir, '__init__.py')
40-
if (!fs.existsSync(initPath)) {
41-
fs.writeFileSync(initPath, '')
41+
const fixturesPath = path.join(testDir, 'fixtures.py')
42+
if (!fs.existsSync(fixturesPath)) {
43+
fs.writeFileSync(fixturesPath, fixturesContent)
4244
}
4345
}
4446

0 commit comments

Comments
 (0)