Skip to content

Commit

Permalink
Add GraalPy JBang QRCode Demo.
Browse files Browse the repository at this point in the history
  • Loading branch information
fniephaus committed Oct 1, 2024
1 parent 69a34dc commit d1f197b
Show file tree
Hide file tree
Showing 4 changed files with 120 additions and 0 deletions.
29 changes: 29 additions & 0 deletions .github/workflows/graalpy-jbang-qrcode.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: Test GraalPy JBang QRCode Demo
on:
push:
paths:
- 'graalpy/graalpy-jbang-qrcode/**'
- '.github/workflows/graalpy-jbang-qrcode.yml'
pull_request:
paths:
- 'graalpy/graalpy-jbang-qrcode/**'
- '.github/workflows/graalpy-jbang-qrcode.yml'
workflow_dispatch:
permissions:
contents: read
jobs:
run:
name: 'graalpy-jbang-qrcode'
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@v4
- uses: graalvm/setup-graalvm@v1
with:
java-version: '23.0.0'
distribution: 'graalvm'
github-token: ${{ secrets.GITHUB_TOKEN }}
- name: Run 'graalpy-jbang-qrcode' demo
run: |
cd graalpy/graalpy-jbang-qrcode
curl -Ls https://sh.jbang.dev | bash -s - run qrcode.java "Hello from GraalPy!"
1 change: 1 addition & 0 deletions graalpy/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ This directory contains demo applications and guides for [GraalPy](https://www.g

- [Minimal Java application that embeds GraalPy](graalpy-starter/README.md)
- [Minimal Java application that embeds `openai` Python package with GraalPy](graalpy-openai-starter/README.md)
- [Embed `qrcode` Python package with GraalPy in JBang](graalpy-jbang-qrcode/README.md)

## Guides

Expand Down
35 changes: 35 additions & 0 deletions graalpy/graalpy-jbang-qrcode/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# GraalPy JBang QRCode Demo

This demo illustrates how GraalPy can be used to embed the [`qrcode` Python package](https://pypi.org/project/qrcode/) in a script that runs on [JBang](https://www.jbang.dev/).

## Preparation

Install GraalVM for JDK 23 and set the value of `JAVA_HOME` accordingly.
We recommend using [SDKMAN!](https://sdkman.io/). (For other download options, see [GraalVM Downloads](https://www.graalvm.org/downloads/).)

```bash
sdk install java 23-graal
```

Afterward, [install `jbang`](https://www.jbang.dev/download/), for with:

```bash
sdk install jbang
```

## Run the Application

To start the demo, run:

```bash
jbang run QRCodeMaker.java "Hello from GraalPy!"
```

## Implementation Details

[qrcode.java](qrcode.java) defines required dependencies on GraalPy, which also allows to depend on Python packages.
`//PIP qrcode==7.4.2` defines the dependency on the `qrcode` Python package.
The `main()` method checks the arguments and then creates a new `Context`.
It then fetches the `qrcode` Python module and maps it to a `QRCode` Java interface.
Afterward, it uses the `qrcode` module as illustrated in [this example](https://github.com/lincolnloop/python-qrcode/tree/v7.4.2?tab=readme-ov-file#examples) through Java interfaces.
Finally, it prints the result to `System.out`.
55 changes: 55 additions & 0 deletions graalpy/graalpy-jbang-qrcode/qrcode.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* Copyright (c) 2024, Oracle and/or its affiliates.
*
* Licensed under the Universal Permissive License v 1.0 as shown at https://opensource.org/license/UPL.
*/

//DEPS org.graalvm.python:python-language:24.1.0
//DEPS org.graalvm.python:python-launcher:24.1.0
//DEPS org.graalvm.python:python-resources:24.1.0
//DEPS org.graalvm.python:python-embedding:24.1.0
//DEPS org.graalvm.python:python-embedding-tools:24.1.0
//PIP qrcode==7.4.2

import org.graalvm.python.embedding.utils.GraalPyResources;

public class qrcode {

public static void main(String[] args) {
if (args.length != 1 || args[0].equals("-h") || args[0].equals("--help")) {
System.out.println("This tool takes only a single argument, the QR code data.");
return;
}
try (var context = GraalPyResources.contextBuilder().option("python.PythonHome", "").build()) {
QRCodeModule qrcodeModule = context.eval("python", "import qrcode; qrcode").as(QRCodeModule.class);
IO io = context.eval("python", "import io; io").as(IO.class);

QRCode qr = qrcodeModule.QRCode();
qr.add_data(args[0]);

StringIO f = io.StringIO();
qr.print_ascii(f);
String qrCodeString = f.getvalue();

System.out.println(qrCodeString);
}
}

public interface QRCodeModule {
QRCode QRCode();
}

public interface QRCode {
void add_data(String text);

void print_ascii(StringIO out);
}

public interface IO {
StringIO StringIO();
}

public interface StringIO {
String getvalue();
}
}

0 comments on commit d1f197b

Please sign in to comment.