Skip to content

Commit 8a7dc1c

Browse files
committed
[GR-48526][GR-52892][GR-53509][GR-55096][GR-48550][GR-46819] Cleanup some old minor issues.
PullRequest: graalpython/4639
2 parents 092db7b + 64e43e0 commit 8a7dc1c

18 files changed

Lines changed: 172 additions & 95 deletions

File tree

docs/user/Embedding-Build-Tools.md

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ This approach involves the following steps:
8989
- Smaller JAR/executable size since Python resources aren't embedded
9090

9191
To use an external directory, create your GraalPy context with:
92-
- `GraalPyResources.createContextBuilder(Path)` - Creates a context builder pointing to your external directory path
92+
- `GraalPyResources.contextBuilder(Path)` - Creates a context builder pointing to your external directory path
9393

9494
## Directory Structure
9595

@@ -229,10 +229,9 @@ To customize the lock file path, configure _graalPyLockFile_ :
229229
</configuration>
230230
```
231231

232-
> **Note:** This only changes the path (defaults to _${basedir}/graalpy.lock_).To generate the lock file, run the `lock-packages` goal.
232+
> **Note:** This only changes the path (defaults to _${basedir}/graalpy.lock_). To generate the lock file, run the `lock-packages` goal.
233233
234-
For more information of this feature, please see the
235-
[Python Dependency Management for Reproducible Builds](#python-dependency-management-for-reproducible-builds) section.
234+
For more information about dependency locking, see the [Dependency Management](#dependency-management) section.
236235

237236
## GraalPy Gradle Plugin
238237

@@ -295,8 +294,7 @@ To customize the lock file path, configure _graalPyLockFile_:
295294

296295
> **Note:** This only changes the path (defaults to _$rootDir/graalpy.lock_). To generate the lock file, run the `graalPyLockPackages` task.
297296
298-
For more information of this feature, please see the
299-
[Python Dependency Management for Reproducible Builds](#python-dependency-management-for-reproducible-builds) section.
297+
For more information about dependency locking, see the [Dependency Management](#dependency-management) section.
300298

301299
### Related Documentation
302300

docs/user/Embedding-Getting-Started.md

Lines changed: 81 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -118,45 +118,90 @@ If you prefer Gradle, here is how to set up a new project with GraalPy embedding
118118
119119
> **Note**: GraalPy's performance depends on the JDK you are using. For optimal performance, see the [Runtime Optimization Support](https://www.graalvm.org/latest/reference-manual/embed-languages/#runtime-optimization-support) guide.
120120
121-
### Adding Python Dependencies
121+
## Adding Python Dependencies
122122
123123
To use third-party Python packages like NumPy or Requests in your embedded application:
124124
125-
1. Add the GraalPy Gradle plugin and configure dependencies in _app/build.gradle_:
126-
127-
```gradle
128-
plugins {
129-
id "java"
130-
id "application"
131-
id "org.graalvm.python" version "25.0.3"
132-
}
133-
134-
graalPy {
135-
packages = ["termcolor==2.2"]
136-
}
137-
```
138-
139-
2. Update your Java code to use the Python package:
140-
141-
```java
142-
package interop;
143-
144-
import org.graalvm.polyglot.*;
145-
import org.graalvm.python.embedding.GraalPyResources;
146-
147-
class App {
148-
public static void main(String[] args) {
149-
try (Context context = GraalPyResources.contextBuilder().build()) {
150-
String src = """
151-
from termcolor import colored
152-
colored_text = colored("hello java", "red", attrs=["reverse", "blink"])
153-
print(colored_text)
154-
""";
155-
context.eval("python", src);
156-
}
157-
}
158-
}
159-
```
125+
Configure the GraalPy Maven or Gradle plugin with the packages your application needs.
126+
The plugin installs packages into a managed virtual environment, and `GraalPyResources` configures the Python context to import from it.
127+
128+
### Maven
129+
130+
Add the Python embedding dependency and GraalPy Maven plugin configuration to your _pom.xml_ file:
131+
132+
```xml
133+
<dependencies>
134+
<dependency>
135+
<groupId>org.graalvm.python</groupId>
136+
<artifactId>python-embedding</artifactId>
137+
<version>25.0.3</version>
138+
</dependency>
139+
</dependencies>
140+
141+
<build>
142+
<plugins>
143+
<plugin>
144+
<groupId>org.graalvm.python</groupId>
145+
<artifactId>graalpy-maven-plugin</artifactId>
146+
<version>25.0.3</version>
147+
<executions>
148+
<execution>
149+
<configuration>
150+
<packages>
151+
<package>termcolor==2.2</package>
152+
</packages>
153+
</configuration>
154+
<goals>
155+
<goal>process-graalpy-resources</goal>
156+
</goals>
157+
</execution>
158+
</executions>
159+
</plugin>
160+
</plugins>
161+
</build>
162+
```
163+
164+
### Gradle
165+
166+
Add the GraalPy Gradle plugin and configure dependencies in _app/build.gradle_:
167+
168+
```gradle
169+
plugins {
170+
id "java"
171+
id "application"
172+
id "org.graalvm.python" version "25.0.3"
173+
}
174+
175+
dependencies {
176+
implementation("org.graalvm.python:python-embedding:25.0.3")
177+
}
178+
179+
graalPy {
180+
packages = ["termcolor==2.2"]
181+
}
182+
```
183+
184+
Then use the Python package from Java:
185+
186+
```java
187+
package interop;
188+
189+
import org.graalvm.polyglot.*;
190+
import org.graalvm.python.embedding.GraalPyResources;
191+
192+
class App {
193+
public static void main(String[] args) {
194+
try (Context context = GraalPyResources.contextBuilder().build()) {
195+
String src = """
196+
from termcolor import colored
197+
colored_text = colored("hello java", "red", attrs=["reverse", "blink"])
198+
print(colored_text)
199+
""";
200+
context.eval("python", src);
201+
}
202+
}
203+
}
204+
```
160205
161206
For complete plugin configuration options, deployment strategies, and dependency management, see [Embedding Build Tools](Embedding-Build-Tools.md).
162207

docs/user/Native-Images-with-Python.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ GraalPy supports GraalVM Native Image to generate native binaries of Java applic
44

55
## Building Executables with Python
66

7-
If you started with the [Maven archetype](Embedding-Getting-Started.md#maven), the generated _pom.xml_ file already includes the necessary configuration for creating a native executable using the [Maven plugin for Native Image building](https://graalvm.github.io/native-build-tools/latest/maven-plugin.html).
7+
If you started with the [Maven archetype](Embedding-Getting-Started.md#maven-quick-start), the generated _pom.xml_ file already includes the necessary configuration for creating a native executable using the [Maven plugin for Native Image building](https://graalvm.github.io/native-build-tools/latest/maven-plugin.html).
88

99
To build the application, run:
1010

docs/user/Standalone-Getting-Started.md

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -119,13 +119,6 @@ pyenv shell graalpy-25.0.3
119119

120120
#### Known Windows Limitations
121121

122-
- JLine treats Windows as a dumb terminal (no autocomplete, limited REPL editing)
123-
- Interactive `help()` in REPL doesn't work
124-
- Virtual environment issues:
125-
- `graalpy.cmd` and `graalpy.exe` are broken inside `venv`
126-
- `pip.exe` cannot be used directly
127-
- Use `myvenv/Scripts/python.exe -m pip --no-cache-dir install <pkg>`
128-
- Only pure Python binary wheels supported
129122
- PowerShell works better than CMD
130123

131124
## Using Virtual Environments

graalpython/com.oracle.graal.python.test.integration/src/com/oracle/graal/python/test/integration/interop/JavaInteropTest.java

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2017, 2026, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* The Universal Permissive License (UPL), Version 1.0
@@ -70,7 +70,6 @@
7070
import org.junit.After;
7171
import org.junit.Assert;
7272
import org.junit.Before;
73-
import org.junit.Ignore;
7473
import org.junit.Test;
7574
import org.junit.experimental.runners.Enclosed;
7675
import org.junit.runner.RunWith;
@@ -485,15 +484,14 @@ public Object execute(Value... arguments) {
485484
}
486485
}
487486

488-
@Ignore // blocked by GR-46281
489487
@Test
490488
public void runAForeignExecutable() throws IOException {
491489
Source suitePy = Source.newBuilder("python",
492490
"""
493491
def foo(obj):
494492
try:
495493
obj()
496-
except TypeError as e:
494+
except:
497495
pass
498496
else:
499497
assert False
@@ -504,15 +502,14 @@ def foo(obj):
504502
foo.execute(new AForeignExecutable());
505503
}
506504

507-
@Ignore // blocked by GR-46281
508505
@Test
509506
public void invokeAForeignMember() throws IOException {
510507
Source suitePy = Source.newBuilder("python",
511508
"""
512509
def foo(obj):
513510
try:
514511
obj.fun()
515-
except TypeError as e:
512+
except:
516513
pass
517514
else:
518515
assert False

graalpython/com.oracle.graal.python.test/src/com/oracle/graal/python/test/interop/ArgsKwArgsTest.java

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2024, 2026, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* The Universal Permissive License (UPL), Version 1.0
@@ -41,6 +41,7 @@
4141
package com.oracle.graal.python.test.interop;
4242

4343
import static org.junit.Assert.assertEquals;
44+
import static org.junit.Assert.assertFalse;
4445
import static org.junit.Assert.assertThrows;
4546
import static org.junit.Assert.assertTrue;
4647

@@ -77,6 +78,35 @@ private Value run(String evalString) {
7778
return context.eval("python", evalString);
7879
}
7980

81+
@Test
82+
public void testLazyModuleMemberInvoke() {
83+
Value module = run("""
84+
import types
85+
86+
class LazyModule(types.ModuleType):
87+
def __getattr__(self, name):
88+
if name == "set_seed":
89+
def set_seed(seed):
90+
self.seed = seed
91+
return seed + 1
92+
self.__dict__[name] = set_seed
93+
return set_seed
94+
raise AttributeError(name)
95+
96+
direct = LazyModule("direct")
97+
probe = LazyModule("probe")
98+
""");
99+
100+
Value direct = module.getMember("direct");
101+
assertEquals(44, direct.invokeMember("set_seed", 43).asInt());
102+
assertEquals(43, direct.getMember("seed").asInt());
103+
104+
Value probe = module.getMember("probe");
105+
assertTrue(probe.hasMember("set_seed"));
106+
assertFalse(probe.hasMember("missing"));
107+
assertEquals(12, probe.invokeMember("set_seed", 11).asInt());
108+
}
109+
80110
@Test
81111
public void testPositionalArgs01() {
82112
// @formatter:off

graalpython/com.oracle.graal.python.test/src/tests/test_subprocess.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,14 @@ def test_waitpid(self):
120120
p.kill()
121121
p.wait()
122122

123+
@unittest.skipIf(sys.platform == 'win32' or POSIX_BACKEND_IS_JAVA or not hasattr(os, 'getpgid'), "Posix-specific")
124+
def test_process_group_0(self):
125+
p = subprocess.Popen([sys.executable, "-c", "import os; print(os.getpgid(0))"],
126+
stdout=subprocess.PIPE, process_group=0)
127+
stdout, _ = p.communicate(timeout=60)
128+
self.assertEqual(p.returncode, 0)
129+
self.assertEqual(int(stdout), p.pid)
130+
123131
def _run_in_new_group(self, code):
124132
def safe_decode(x):
125133
return '' if not x else x.decode().strip()

graalpython/com.oracle.graal.python.test/src/tests/unittest_tags/test_subprocess.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ test.test_subprocess.POSIXProcessTestCase.test_group_error @ darwin-arm64,linux-
3838
test.test_subprocess.POSIXProcessTestCase.test_invalid_args @ darwin-arm64,linux-aarch64,linux-aarch64-github,linux-x86_64,linux-x86_64-github
3939
test.test_subprocess.POSIXProcessTestCase.test_kill @ darwin-arm64,linux-aarch64,linux-aarch64-github,linux-x86_64,linux-x86_64-github
4040
test.test_subprocess.POSIXProcessTestCase.test_kill_dead @ darwin-arm64,linux-aarch64,linux-aarch64-github,linux-x86_64,linux-x86_64-github
41+
test.test_subprocess.POSIXProcessTestCase.test_process_group_0 @ darwin-arm64,linux-aarch64,linux-aarch64-github,linux-x86_64,linux-x86_64-github
4142
test.test_subprocess.POSIXProcessTestCase.test_remapping_std_fds @ darwin-arm64,linux-aarch64,linux-aarch64-github,linux-x86_64,linux-x86_64-github
4243
test.test_subprocess.POSIXProcessTestCase.test_select_unbuffered @ darwin-arm64,linux-aarch64,linux-aarch64-github,linux-x86_64,linux-x86_64-github
4344
test.test_subprocess.POSIXProcessTestCase.test_send_signal @ darwin-arm64,linux-aarch64,linux-aarch64-github,linux-x86_64,linux-x86_64-github

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PosixSubprocessModuleBuiltins.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,7 @@ static int forkExec(VirtualFrame frame, Object[] args, Object executableList, bo
303303
gil.release(true);
304304
try {
305305
return posixLib.forkExec(context.getPosixSupport(), executables, processArgs, cwd, env == null ? null : (Object[]) env, stdinRead, stdinWrite, stdoutRead, stdoutWrite, stderrRead,
306-
stderrWrite, errPipeRead, errPipeWrite, closeFds, restoreSignals, callSetsid, fdsToKeep, allowVFork);
306+
stderrWrite, errPipeRead, errPipeWrite, closeFds, restoreSignals, callSetsid, pgidToSet, fdsToKeep, allowVFork);
307307
} catch (PosixException e) {
308308
gil.acquire();
309309
throw constructAndRaiseNode.get(inliningTarget).raiseOSErrorFromPosixException(frame, e);

0 commit comments

Comments
 (0)