Skip to content
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
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,6 @@ private boolean checkCApiResidue(Heap heap) {
addResidue(residues, inst, "referencesToBeFreed", this::collectionSize);
addResidue(residues, inst, "nativeLookup", this::collectionSize);
addResidue(residues, inst, "nativeWeakRef", this::collectionSize);
addResidue(residues, inst, "managedNativeLookup", this::collectionSize);
addResidue(residues, inst, "nativeTypeLookup", this::objectArraySize);
addResidue(residues, inst, "nativeStubLookup", this::objectArraySize);
addResidue(residues, inst, "nativeStorageReferences", this::collectionSize);
Expand Down
59 changes: 59 additions & 0 deletions graalpython/com.oracle.graal.python.test/src/tests/test_bz2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Copyright (c) 2026, 2026, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# The Universal Permissive License (UPL), Version 1.0
#
# Subject to the condition set forth below, permission is hereby granted to any
# person obtaining a copy of this software, associated documentation and/or
# data (collectively the "Software"), free of charge and under any and all
# copyright rights in the Software, and any and all patent rights owned or
# freely licensable by each licensor hereunder covering either (i) the
# unmodified Software as contributed to or provided by such licensor, or (ii)
# the Larger Works (as defined below), to deal in both
#
# (a) the Software, and
#
# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
# one is included with the Software each a "Larger Work" to which the Software
# is contributed by such licensors),
#
# without restriction, including without limitation the rights to copy, create
# derivative works of, display, perform, and distribute the Software and make,
# use, sell, offer for sale, import, export, have made, and have sold the
# Software and the Larger Work(s), and to sublicense the foregoing rights on
# either these or other terms.
#
# This license is subject to the following condition:
#
# The above copyright notice and either this complete permission notice or at a
# minimum a reference to the UPL must be included in all copies or substantial
# portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
import bz2
import unittest

from tests.util import is_native_compression_backend

DATA = (b"native bz2 support migration test data\n" * 128) + bytes(range(256))


@unittest.skipUnless(is_native_compression_backend(), "requires native compression backend")
def test_bz2_stream_roundtrip_and_unused_data():
compressor = bz2.BZ2Compressor(5)
compressed = compressor.compress(DATA[:97])
compressed += compressor.compress(DATA[97:])
compressed += compressor.flush()

assert bz2.decompress(compressed) == DATA

decompressor = bz2.BZ2Decompressor()
assert decompressor.decompress(compressed + b"tail") == DATA
assert decompressor.eof
assert decompressor.unused_data == b"tail"
71 changes: 71 additions & 0 deletions graalpython/com.oracle.graal.python.test/src/tests/test_lzma.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# Copyright (c) 2026, 2026, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# The Universal Permissive License (UPL), Version 1.0
#
# Subject to the condition set forth below, permission is hereby granted to any
# person obtaining a copy of this software, associated documentation and/or
# data (collectively the "Software"), free of charge and under any and all
# copyright rights in the Software, and any and all patent rights owned or
# freely licensable by each licensor hereunder covering either (i) the
# unmodified Software as contributed to or provided by such licensor, or (ii)
# the Larger Works (as defined below), to deal in both
#
# (a) the Software, and
#
# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
# one is included with the Software each a "Larger Work" to which the Software
# is contributed by such licensors),
#
# without restriction, including without limitation the rights to copy, create
# derivative works of, display, perform, and distribute the Software and make,
# use, sell, offer for sale, import, export, have made, and have sold the
# Software and the Larger Work(s), and to sublicense the foregoing rights on
# either these or other terms.
#
# This license is subject to the following condition:
#
# The above copyright notice and either this complete permission notice or at a
# minimum a reference to the UPL must be included in all copies or substantial
# portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
import lzma
import unittest

from tests.util import is_native_compression_backend

DATA = (b"native lzma support migration test data\n" * 128) + bytes(range(256))


@unittest.skipUnless(is_native_compression_backend(), "requires native compression backend")
def test_lzma_stream_roundtrip_and_unused_data():
compressor = lzma.LZMACompressor(format=lzma.FORMAT_XZ, check=lzma.CHECK_CRC64)
compressed = compressor.compress(DATA[:113])
compressed += compressor.compress(DATA[113:])
compressed += compressor.flush()

assert lzma.decompress(compressed) == DATA

decompressor = lzma.LZMADecompressor()
assert decompressor.decompress(compressed + b"tail") == DATA
assert decompressor.eof
assert decompressor.unused_data == b"tail"


@unittest.skipUnless(is_native_compression_backend(), "requires native compression backend")
def test_lzma_raw_filter_roundtrip():
filters = [{"id": lzma.FILTER_LZMA2, "preset": 1}]
compressor = lzma.LZMACompressor(format=lzma.FORMAT_RAW, filters=filters)
compressed = compressor.compress(DATA)
compressed += compressor.flush()

decompressor = lzma.LZMADecompressor(format=lzma.FORMAT_RAW, filters=filters)
assert decompressor.decompress(compressed) == DATA
assert decompressor.eof
4 changes: 4 additions & 0 deletions graalpython/com.oracle.graal.python.test/src/tests/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ def wrapper(test):
return wrapper


def is_native_compression_backend():
return sys.implementation.name != 'graalpy' or __graalpython__.zlib_module_backend() == 'native'


def _jdk_major_version():
version = __graalpython__.get_jdk_version()
return int(version.split(".", 1)[0].split("-", 1)[0])
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@
version = PythonLanguage.VERSION, //
characterMimeTypes = {PythonLanguage.MIME_TYPE}, //
defaultMimeType = PythonLanguage.MIME_TYPE, //
dependentLanguages = {"nfi", "llvm"}, //
dependentLanguages = "nfi", //
interactive = true, internal = false, //
contextPolicy = TruffleLanguage.ContextPolicy.SHARED, //
fileTypeDetectors = PythonFileDetector.class, //
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1068,9 +1068,9 @@ public final void postInitialize(Env env) {

/*
* Special case for _bz2: If native access is not allowed, we cannot use the built-in
* implementation that would call libbz2 via NFI. Therefore, we remove it from the
* implementation that would call libbz2 via NativeAccess. Therefore, we remove it from the
* built-in modules map (and also from sys.modules if already loaded). This will cause a
* fallback to another _bz2 implementation (e.g. LLVM or maybe some Java lib). This
* fallback to another _bz2 implementation (e.g. some Java lib). This
* needs to be done here and cannot be done in 'initializeBuiltins' because then we
* would never include the intrinsified _bz2 module in the native image since native
* access is never allowed during context pre-initialization.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -954,7 +954,7 @@ TruffleString posixModuleBackend(
public abstract static class ZlibModuleBackendNode extends PythonBuiltinNode {
@Specialization
TruffleString zlibModuleBackend() {
return getContext().getNFIZlibSupport().isAvailable() ? T_NATIVE : T_JAVA;
return getContext().getNativeZlibSupport().isAvailable() ? T_NATIVE : T_JAVA;
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* The Universal Permissive License (UPL), Version 1.0
Expand Down Expand Up @@ -73,8 +73,7 @@
import com.oracle.graal.python.nodes.function.builtins.PythonUnaryBuiltinNode;
import com.oracle.graal.python.nodes.function.builtins.clinic.ArgumentClinicProvider;
import com.oracle.graal.python.runtime.GilNode;
import com.oracle.graal.python.runtime.NFIBz2Support;
import com.oracle.graal.python.runtime.NativeLibrary;
import com.oracle.graal.python.runtime.NativeBz2Support;
import com.oracle.graal.python.runtime.PythonContext;
import com.oracle.graal.python.runtime.object.PFactory;
import com.oracle.truffle.api.dsl.Bind;
Expand Down Expand Up @@ -123,15 +122,13 @@ protected ArgumentClinicProvider getArgumentClinic() {
@Specialization(guards = {"compresslevel >= 1", "compresslevel <= 9"})
PNone init(BZ2Object.BZ2Compressor self, int compresslevel,
@Bind Node inliningTarget,
@Cached NativeLibrary.InvokeNativeFunction createStream,
@Cached NativeLibrary.InvokeNativeFunction compressInit,
@Cached GilNode gil,
@Cached PRaiseNode raiseNode) {
gil.release(true);
try {
NFIBz2Support bz2Support = PythonContext.get(this).getNFIBz2Support();
Object bzst = bz2Support.createStream(createStream);
int err = bz2Support.compressInit(bzst, compresslevel, compressInit);
NativeBz2Support bz2Support = PythonContext.get(this).getNativeBz2Support();
long bzst = bz2Support.createStream();
int err = bz2Support.compressInit(bzst, compresslevel);
if (err != BZ_OK) {
errorHandling(inliningTarget, err, raiseNode);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* The Universal Permissive License (UPL), Version 1.0
Expand Down Expand Up @@ -68,8 +68,7 @@
import com.oracle.graal.python.nodes.function.builtins.PythonTernaryClinicBuiltinNode;
import com.oracle.graal.python.nodes.function.builtins.PythonUnaryBuiltinNode;
import com.oracle.graal.python.nodes.function.builtins.clinic.ArgumentClinicProvider;
import com.oracle.graal.python.runtime.NFIBz2Support;
import com.oracle.graal.python.runtime.NativeLibrary;
import com.oracle.graal.python.runtime.NativeBz2Support;
import com.oracle.graal.python.runtime.PythonContext;
import com.oracle.graal.python.runtime.object.PFactory;
import com.oracle.truffle.api.dsl.Bind;
Expand Down Expand Up @@ -111,12 +110,10 @@ public abstract static class InitNode extends PythonUnaryBuiltinNode {
@Specialization
static PNone init(BZ2Object.BZ2Decompressor self,
@Bind Node inliningTarget,
@Cached NativeLibrary.InvokeNativeFunction createStream,
@Cached NativeLibrary.InvokeNativeFunction compressInit,
@Cached PRaiseNode raiseNode) {
NFIBz2Support bz2Support = PythonContext.get(inliningTarget).getNFIBz2Support();
Object bzst = bz2Support.createStream(createStream);
int err = bz2Support.decompressInit(bzst, compressInit);
NativeBz2Support bz2Support = PythonContext.get(inliningTarget).getNativeBz2Support();
long bzst = bz2Support.createStream();
int err = bz2Support.decompressInit(bzst);
if (err != BZ_OK) {
errorHandling(inliningTarget, err, raiseNode);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* The Universal Permissive License (UPL), Version 1.0
Expand Down Expand Up @@ -44,40 +44,45 @@

import com.oracle.graal.python.builtins.objects.ints.PInt;
import com.oracle.graal.python.builtins.objects.object.PythonBuiltinObject;
import com.oracle.graal.python.runtime.NFIBz2Support;
import com.oracle.graal.python.runtime.NativeBz2Support;
import com.oracle.graal.python.util.OverflowException;
import com.oracle.graal.python.util.PythonUtils;
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.object.Shape;

public abstract class BZ2Object extends PythonBuiltinObject {

private NFIBz2Support.Pointer pointer;
private NativeBz2Support.Pointer pointer;

public BZ2Object(Object cls, Shape instanceShape) {
BZ2Object(Object cls, Shape instanceShape) {
super(cls, instanceShape);
}

public final void init(Object bzst, NFIBz2Support lib) {
this.pointer = new NFIBz2Support.Pointer(this, bzst, lib);
public final void init(long bzst, NativeBz2Support lib) {
this.pointer = new NativeBz2Support.Pointer(this, bzst, lib);
assert !pointer.isReleased();
}

public final Object getBzs() {
assert pointer != null;
return pointer.getReference();
public final long getBzs() {
NativeBz2Support.Pointer p = pointer;
assert p != null && !p.isReleased();
return p.getPointer();
}

@CompilerDirectives.TruffleBoundary
@TruffleBoundary
public final void markReleased() {
if (pointer != null) {
synchronized (this) {
pointer.markReleased();
pointer = null;
}
NativeBz2Support.Pointer p;
synchronized (this) {
p = pointer;
pointer = null;
}
if (p != null) {
boolean markedReleased = p.markReleased();
assert markedReleased || p.isReleased();
}
}

public static class BZ2Compressor extends BZ2Object {
public static final class BZ2Compressor extends BZ2Object {

private boolean flushed;

Expand All @@ -95,7 +100,7 @@ public void setFlushed() {
}
}

public static class BZ2Decompressor extends BZ2Object {
public static final class BZ2Decompressor extends BZ2Object {

private boolean eof;
private byte[] unusedData;
Expand Down Expand Up @@ -221,12 +226,4 @@ public void setBzsAvailInReal(long bzsAvailInReal) throws OverflowException {
this.bzsAvailInReal = PInt.intValueExact(bzsAvailInReal);
}
}

public static BZ2Compressor createCompressor(Object cls, Shape instanceShape) {
return new BZ2Compressor(cls, instanceShape);
}

public static BZ2Decompressor createDecompressor(Object cls, Shape instanceShape) {
return new BZ2Decompressor(cls, instanceShape);
}
}
Loading
Loading