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
2 changes: 1 addition & 1 deletion demo/.idea/gradle.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions demo/app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,12 @@ afterEvaluate {

android {
namespace = "com.chaquo.python.demo"
compileSdk = 36
compileSdk = 37

defaultConfig {
applicationId = "com.chaquo.python.demo3"
minSdk = 24
targetSdk = 36
targetSdk = 37

val plugins = buildscript.configurations.getByName("classpath")
.resolvedConfiguration.resolvedArtifacts.map {
Expand Down
19 changes: 10 additions & 9 deletions demo/app/src/utils/java/com/chaquo/python/utils/BaseActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -51,20 +51,21 @@ public void setContentView(View view) {
view,
(v, insets) -> {
// systemBars includes the status bar, navigation bar (which may be on
// the left or right on API level 28 and older), action bar, and display
// cutouts.
Insets systemBars =
insets.getInsets(WindowInsetsCompat.Type.systemBars());
v.setPadding(
// the left or right on API level 28 and older), and action bar.
Insets systemBars = insets.getInsets(
WindowInsetsCompat.Type.systemBars()
| WindowInsetsCompat.Type.displayCutout()
);
((ViewGroup.MarginLayoutParams) v.getLayoutParams()).setMargins(
systemBars.left, systemBars.top, systemBars.right, systemBars.bottom
);

ViewGroup.MarginLayoutParams lp =
ViewGroup.MarginLayoutParams statusLp =
(ViewGroup.MarginLayoutParams) statusBarBackground.getLayoutParams();
lp.height = systemBars.top;
lp.leftMargin = systemBars.left;
lp.rightMargin = systemBars.right;
statusLp.height = systemBars.top;
statusLp.setMargins(systemBars.left, 0, systemBars.right, 0);
statusBarBackground.requestLayout();

return insets;
}
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public class Common {
// This should match api_level in target/android-env.sh.
public static final int MIN_SDK_VERSION = 24;

public static final int COMPILE_SDK_VERSION = 36;
public static final String COMPILE_SDK_VERSION = "37.0";

public static final Map<String, String> PYTHON_VERSIONS = new LinkedHashMap<>();
static {
Expand Down
14 changes: 14 additions & 0 deletions product/runtime/src/main/python/java/android/importer.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import re
from shutil import copyfileobj, rmtree
import site
from stat import S_IMODE
import sys
from tempfile import NamedTemporaryFile
import time
Expand Down Expand Up @@ -850,7 +851,20 @@ def extract_if_changed(self, member, target_dir):
if need_extract:
extracted_filename = self.extract(member, target_dir)
assert extracted_filename == out_filename, (extracted_filename, out_filename)

# In API level 37, native libraries loaded using System.load must be
# read-only. This doesn't affect lower-level APIs yet, but it's likely
# they'll tighten this in the future.
#
# In theory we could apply this to all files, but while writing to a virtual
# environment at runtime is certainly bad practice, it's usually possible,
# so there's probably someone out there doing it.
if re.search(r"\.so(\.|$)", basename(member.filename)):
os.chmod(out_filename, S_IMODE(os.stat(out_filename).st_mode) & ~0o222)

# Do this last to indicate that the file is in its final state.
os.utime(out_filename, (time.time(), timegm(member.date_time)))

return out_filename

def exists(self, path):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
import pkgutil
import re
from shutil import rmtree
from stat import S_IMODE

import sys
from traceback import format_exc
from unittest import skipIf
Expand Down Expand Up @@ -266,8 +268,8 @@ def test_non_package_data(self):
("non_package_data/subdir", "subdirectory")]:
with self.subTest(dir_name=dir_name):
extracted_dir = asset_path(APP_ZIP, dir_name)
self.assertCountEqual(
[entry.name for entry in os.scandir(extracted_dir) if entry.is_file()],
self.check_non_package_data(
extracted_dir,
[
# Should extract everything except .py and .pyc files.
"libnon_package_data.so.1",
Expand All @@ -286,12 +288,18 @@ def test_non_package_data(self):

# The chaquopy directory is also treated as non-package data.
for dir_name, expected in [
("chaquopy", ["lib"]),
("chaquopy", []),
("chaquopy/lib", ["libc++_shared.so"]),
]:
self.assertCountEqual(
os.listdir(asset_path(REQS_ABI_ZIP, dir_name)), expected
)
self.check_non_package_data(asset_path(REQS_ABI_ZIP, dir_name), expected)

def check_non_package_data(self, extracted_dir, expected):
self.assertCountEqual(
[entry.name for entry in os.scandir(extracted_dir) if entry.is_file()],
expected,
)
for name in expected:
self.check_readonly(f"{extracted_dir}/{name}"),

def test_package_data(self):
# App ZIP
Expand Down Expand Up @@ -339,6 +347,7 @@ def check_extract_if_changed(self, mod, cache_filename):
os.remove(cache_filename)
mod = self.clean_reload(mod)
self.assertPredicate(exists, cache_filename)
self.check_readonly(cache_filename)

# An unchanged file should not be extracted again.
with self.assertNotModifies(cache_filename):
Expand All @@ -351,6 +360,11 @@ def check_extract_if_changed(self, mod, cache_filename):
self.clean_reload(mod)
self.assertEqual(original_mtime, os.stat(cache_filename).st_mtime)

def check_readonly(self, path):
actual = (S_IMODE(os.stat(path).st_mode) & 0o222) == 0
expected = bool(re.search(r"\.so(\.|$)", basename(path)))
self.assertEqual(actual, expected, path)

def test_extract_packages(self):
self.check_extract_packages("ep_alpha", []) # Not extracted
self.check_extract_packages("ep_bravo", [ # Top-level package extracted
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,6 @@ def test_lib2to3(self):

def test_locale(self):
import locale
self.assertEqual("UTF-8", locale.getlocale()[1])
with catch_warnings():
filterwarnings("default", category=DeprecationWarning)
self.assertEqual("UTF-8", locale.getdefaultlocale()[1])
self.assertEqual("utf-8", # Became lower-case in Python 3.11.
locale.getpreferredencoding().lower())
self.assertEqual("utf-8", sys.getdefaultencoding())
Expand Down
4 changes: 2 additions & 2 deletions server/pypi/pkgtest/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,12 @@ ext.TEST_PACKAGES = [

android {
namespace "com.chaquo.python.pkgtest3"
compileSdk = 36
compileSdk = 37

defaultConfig {
applicationId "com.chaquo.python.pkgtest3"
minSdk = 24
targetSdk = 36
targetSdk = 37

String pluginVersion = null
for (art in rootProject.buildscript.configurations.getByName("classpath")
Expand Down
Loading