diff --git a/.github/workflows/python.yml b/.github/workflows/python.yml new file mode 100644 index 0000000..bfbbbd6 --- /dev/null +++ b/.github/workflows/python.yml @@ -0,0 +1,58 @@ +name: Build and upload Python native module + +on: + create: + tags: + - 'v*' + +jobs: + nodejs: + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-latest, windows-latest, macos-latest] + include: + - os: ubuntu-latest + ARCH: linux-x86_64 + LIBFILE: 'libhyperbuild_python_lib.so' + PYEXT: 'so' + - os: windows-latest + ARCH: windows-x86_64 + LIBFILE: 'hyperbuild_python_lib.dll' + PYEXT: 'pyd' + - os: macos-latest + ARCH: macos-x86_64 + LIBFILE: 'libhyperbuild_python_lib.dylib' + PYEXT: 'so' + steps: + - uses: actions/checkout@v1 + - name: Get version + id: version + shell: bash + run: echo ::set-output name=VERSION::${GITHUB_REF#refs/tags/v} + - name: Get file name + id: file + shell: bash + run: echo ::set-output name=FILE::${{ steps.version.outputs.VERSION }}-${{ matrix.ARCH }}-python.${{ matrix.PYEXT }} + - name: Set up Python + uses: actions/setup-python@v1 + with: + python-version: '3.5' + architecture: 'x64' + - name: Set up Rust + uses: actions-rs/toolchain@v1 + with: + toolchain: nightly-2019-07-19 + profile: minimal + default: true + - name: Build native module + working-directory: ./python + run: | + cargo build --release + - uses: chrislennon/action-aws-cli@v1.1 + - name: Upload to S3 + env: + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + AWS_REGION: us-west-2 + run: aws s3 cp ./python/target/release/${{ matrix.LIBFILE }} s3://${{ secrets.AWS_S3_BUCKET }}/hyperbuild/bin/${{ steps.file.outputs.FILE }} diff --git a/README.md b/README.md index 02837b5..f7d8739 100644 --- a/README.md +++ b/README.md @@ -53,10 +53,10 @@ hyperbuild = "0.0.19" use hyperbuild::hyperbuild; fn main() { - let mut code = b"

Hello, world!

"; + let mut code = b"

Hello, world!

".to_vec(); match hyperbuild(&mut code) { Ok(minified_len) => {} - Err(error_type, error_at_char_no) => {} + Err((error_type, error_at_char_no)) => {} }; } ``` @@ -66,7 +66,7 @@ fn main() {
Node.js -hyperbuild is available as a [Node.js native module](https://www.npmjs.com/package/hyperbuild), and supports Node.js versions 8 and higher. +hyperbuild is [on npm](https://www.npmjs.com/package/hyperbuild), available as a [Node.js native module](https://neon-bindings.com/), and supports Node.js versions 8 and higher. ##### Get @@ -95,7 +95,7 @@ const minified = hyperbuild.minify("

Hello, world!

");
Java -hyperbuild is available via JNI, and supports Java versions 7 and higher. +hyperbuild is available via [JNI](https://github.com/jni-rs/jni-rs), and supports Java versions 7 and higher. ##### Get @@ -117,6 +117,29 @@ class Main {
+
+Java + +hyperbuild is available as a [native module](https://github.com/PyO3/pyo3), and supports CPython (default Python interpreter) versions 3.5 and higher. + +##### Get + +Download the native module for [Windows](https://wilsonl.in/hyperbuild/bin/0.0.19-windows-x86_64-python.pyd), [macOS](https://wilsonl.in/hyperbuild/bin/0.0.19-macos-x86_64-python.so), or [Linux](https://wilsonl.in/hyperbuild/bin/0.0.19-linux-x86_64-python.so). + +Rename the file to `hyperbuild.pyd` on Windows or `hyperbuild.so` on macOS/Linux. + +##### Use + +Make sure the native module can be [found by Python](https://docs.python.org/3/tutorial/modules.html#the-module-search-path). This is usually done by placing it into a folder declared in the `PYTHONPATH` environment variable or `sys.path` value, or the same folder as the script that will import it. + +```java +import hyperbuild; + +minified = hyperbuild.minify("

Hello, world!

") +``` + +
+ ## Minification ### Whitespace diff --git a/java/Cargo.toml b/java/Cargo.toml index d74afa8..f718ef9 100644 --- a/java/Cargo.toml +++ b/java/Cargo.toml @@ -1,5 +1,6 @@ [package] name = "hyperbuild-java" +publish = false version = "0.0.19" authors = ["Wilson Lin "] edition = "2018" diff --git a/java/src/main/rust/lib.rs b/java/src/main/rust/lib.rs index a097231..f063f00 100644 --- a/java/src/main/rust/lib.rs +++ b/java/src/main/rust/lib.rs @@ -39,7 +39,7 @@ pub extern "system" fn Java_in_wilsonl_hyperbuild_Hyperbuild_minify( ) -> jstring { let source: String = env.get_string(input).unwrap().into(); - let mut code = source.as_bytes().to_vec(); + let mut code = source.into_bytes(); match hyperbuild(&mut code) { Ok(out_len) => env.new_string(unsafe { from_utf8_unchecked(&code[0..out_len]) }).unwrap().into_inner(), diff --git a/python/.gitignore b/python/.gitignore new file mode 100644 index 0000000..1b72444 --- /dev/null +++ b/python/.gitignore @@ -0,0 +1,2 @@ +/Cargo.lock +/target diff --git a/python/Cargo.toml b/python/Cargo.toml new file mode 100644 index 0000000..ead63fe --- /dev/null +++ b/python/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "hyperbuild-python" +publish = false +version = "0.0.19" +authors = ["Wilson Lin "] +edition = "2018" + +[lib] +name = "hyperbuild_python_lib" +crate-type = ["cdylib"] + +[dependencies] +hyperbuild = "0.0.19" + +[dependencies.pyo3] +version = "0.9.0-alpha.1" +features = ["extension-module"] + +[target.x86_64-apple-darwin] +rustflags = [ + "-C", "link-arg=-undefined", + "-C", "link-arg=dynamic_lookup", +] diff --git a/python/src/lib.rs b/python/src/lib.rs new file mode 100644 index 0000000..2081ae1 --- /dev/null +++ b/python/src/lib.rs @@ -0,0 +1,21 @@ +use hyperbuild::hyperbuild as hyperbuild_native; +use pyo3::prelude::*; +use pyo3::exceptions::SyntaxError; +use pyo3::wrap_pyfunction; +use std::str::from_utf8_unchecked; + +#[pyfunction] +fn minify(code: String) -> PyResult { + let mut code = code.into_bytes(); + match hyperbuild_native(&mut code) { + Ok(out_len) => Ok(unsafe { from_utf8_unchecked(&code[0..out_len]).to_string() }), + Err((err, pos)) => Err(SyntaxError::py_err(format!("{} [Character {}]", err.message(), pos))), + } +} + +#[pymodule] +fn hyperbuild(py: Python, m: &PyModule) -> PyResult<()> { + m.add_wrapped(wrap_pyfunction!(minify))?; + + Ok(()) +} diff --git a/version b/version index 83669b3..a7ec279 100755 --- a/version +++ b/version @@ -48,11 +48,11 @@ if (cmd('git', 'status', '--porcelain', {throwOnStderr: true, captureStdio: true throw new Error(`Working directory not clean`); } -for (const f of ["Cargo.toml", "nodejs/native/Cargo.toml", "java/Cargo.toml"]) { +for (const f of ["Cargo.toml", "nodejs/native/Cargo.toml", "java/Cargo.toml", "python/Cargo.toml"]) { replaceInFile(f, /^version = "\d+\.\d+\.\d+"\s*$/m, `version = "${NEW_VERSION}"`); } -for (const f of ["README.md", "nodejs/native/Cargo.toml", "java/Cargo.toml"]) { +for (const f of ["README.md", "nodejs/native/Cargo.toml", "java/Cargo.toml", "python/Cargo.toml"]) { replaceInFile(f, /^hyperbuild = "\d+\.\d+\.\d+"\s*$/m, `hyperbuild = "${NEW_VERSION}"`); }