Skip to content

Commit

Permalink
Merge branch 'kivy:develop' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
kyprosantreou committed Mar 23, 2024
2 parents 0823f81 + b92522f commit c561230
Show file tree
Hide file tree
Showing 18 changed files with 140 additions and 41 deletions.
8 changes: 0 additions & 8 deletions Makefile
Expand Up @@ -3,14 +3,6 @@ PIP=$(VIRTUAL_ENV)/bin/pip
TOX=`which tox`
ACTIVATE=$(VIRTUAL_ENV)/bin/activate
PYTHON=$(VIRTUAL_ENV)/bin/python
FLAKE8=$(VIRTUAL_ENV)/bin/flake8
PYTEST=$(VIRTUAL_ENV)/bin/pytest
SOURCES=src/ tests/
PYTHON_MAJOR_VERSION=3
PYTHON_MINOR_VERSION=6
PYTHON_VERSION=$(PYTHON_MAJOR_VERSION).$(PYTHON_MINOR_VERSION)
PYTHON_MAJOR_MINOR=$(PYTHON_MAJOR_VERSION)$(PYTHON_MINOR_VERSION)
PYTHON_WITH_VERSION=python$(PYTHON_VERSION)
DOCKER_IMAGE=kivy/python-for-android
ANDROID_SDK_HOME ?= $(HOME)/.android/android-sdk
ANDROID_NDK_HOME ?= $(HOME)/.android/android-ndk
Expand Down
14 changes: 9 additions & 5 deletions ci/rebuild_updated_recipes.py
Expand Up @@ -59,14 +59,18 @@ def build(target_python, requirements, archs):
requirements.add(target_python.name)
requirements = ','.join(requirements)
logger.info('requirements: {}'.format(requirements))
build_command = [
'setup.py', 'apk',
'--sdk-dir', android_sdk_home,
'--ndk-dir', android_ndk_home,
'--requirements', requirements
] + [f"--arch={arch}" for arch in archs]
build_command_str = " ".join(build_command)
logger.info(f"Build command: {build_command_str}")

with current_directory('testapps/on_device_unit_tests/'):
# iterates to stream the output
for line in sh.python(
'setup.py', 'apk', '--sdk-dir', android_sdk_home,
'--ndk-dir', android_ndk_home, '--requirements',
requirements, *[f"--arch={arch}" for arch in archs],
_err_to_out=True, _iter=True):
for line in sh.python(*build_command, _err_to_out=True, _iter=True):
print(line)


Expand Down
Expand Up @@ -21,7 +21,6 @@
import android.content.pm.PackageManager;

import org.qtproject.qt.android.bindings.QtActivity;
import org.qtproject.qt.android.QtNative;

public class PythonActivity extends QtActivity {

Expand Down Expand Up @@ -52,6 +51,18 @@ public String getEntryPoint(String search_dir) {
return "main.py";
}

public void setEnvironmentVariable(String key, String value) {
/**
* Sets an environment variable based on key/value.
**/
try {
android.system.Os.setenv(key, value, true);
} catch (Exception e) {
Log.e("Qt bootstrap", "Unable set environment variable:" + key + "=" + value);
e.printStackTrace();
}
}

@Override
public void onCreate(Bundle savedInstanceState) {
this.mActivity = this;
Expand All @@ -69,14 +80,14 @@ public void onCreate(Bundle savedInstanceState) {
String entry_point = getEntryPoint(app_root_dir);

Log.v(TAG, "Setting env vars for start.c and Python to use");
QtNative.setEnvironmentVariable("ANDROID_ENTRYPOINT", entry_point);
QtNative.setEnvironmentVariable("ANDROID_ARGUMENT", app_root_dir);
QtNative.setEnvironmentVariable("ANDROID_APP_PATH", app_root_dir);
QtNative.setEnvironmentVariable("ANDROID_PRIVATE", mFilesDirectory);
QtNative.setEnvironmentVariable("ANDROID_UNPACK", app_root_dir);
QtNative.setEnvironmentVariable("PYTHONHOME", app_root_dir);
QtNative.setEnvironmentVariable("PYTHONPATH", app_root_dir + ":" + app_root_dir + "/lib");
QtNative.setEnvironmentVariable("PYTHONOPTIMIZE", "2");
setEnvironmentVariable("ANDROID_ENTRYPOINT", entry_point);
setEnvironmentVariable("ANDROID_ARGUMENT", app_root_dir);
setEnvironmentVariable("ANDROID_APP_PATH", app_root_dir);
setEnvironmentVariable("ANDROID_PRIVATE", mFilesDirectory);
setEnvironmentVariable("ANDROID_UNPACK", app_root_dir);
setEnvironmentVariable("PYTHONHOME", app_root_dir);
setEnvironmentVariable("PYTHONPATH", app_root_dir + ":" + app_root_dir + "/lib");
setEnvironmentVariable("PYTHONOPTIMIZE", "2");

Log.v(TAG, "About to do super onCreate");
super.onCreate(savedInstanceState);
Expand Down
8 changes: 8 additions & 0 deletions pythonforandroid/bootstraps/qt/build/templates/libs.tmpl.xml
@@ -1,5 +1,13 @@
<?xml version='1.0' encoding='utf-8'?>
<resources>

<!--
The bunlded_libs placeholder is needed for QtLoader.java. Otherwise the application will crash.
Adding extra libraries can be done through buildozer directly with android.add_libs_* option
-->
<array name="bundled_libs">
</array>

<array name="qt_libs">
<item>{{ arch }};c++_shared</item>
{%- for qt_lib in qt_libs %}
Expand Down
2 changes: 1 addition & 1 deletion pythonforandroid/build.py
Expand Up @@ -764,7 +764,7 @@ def run_pymodules_install(ctx, arch, modules, project_dir=None,
if project_dir is not None and (
project_has_setup_py(project_dir) and not ignore_setup_py
):
run_setuppy_install(ctx, project_dir, env, arch.arch)
run_setuppy_install(ctx, project_dir, env, arch)
elif not ignore_setup_py:
info("No setup.py found in project directory: " + str(project_dir))

Expand Down
3 changes: 3 additions & 0 deletions pythonforandroid/recipes/android/src/android/permissions.py
Expand Up @@ -449,6 +449,9 @@ class Permission:
WRITE_VOICEMAIL = (
"com.android.voicemail.permission.WRITE_VOICEMAIL"
)
MANAGE_EXTERNAL_STORAGE = ( # Convenient use of paths to manage files
"android.permission.MANAGE_EXTERNAL_STORAGE"
)


PERMISSION_GRANTED = 0
Expand Down
21 changes: 21 additions & 0 deletions pythonforandroid/recipes/coincurve/__init__.py
@@ -0,0 +1,21 @@
import os
from pythonforandroid.recipe import PythonRecipe


class CoincurveRecipe(PythonRecipe):
version = "19.0.1"
url = "https://github.com/ofek/coincurve/archive/v{version}.tar.gz"
call_hostpython_via_targetpython = False
depends = ["setuptools", "libffi", "cffi", "libsecp256k1", "asn1crypto"]
patches = ["coincurve.patch"]

def get_recipe_env(self, arch=None, with_flags_in_cc=True):
env = super(CoincurveRecipe, self).get_recipe_env(arch, with_flags_in_cc)
libsecp256k1 = self.get_recipe("libsecp256k1", self.ctx)
libsecp256k1_dir = libsecp256k1.get_build_dir(arch.arch)
env["CFLAGS"] += " -I" + os.path.join(libsecp256k1_dir, "include")
env["LDFLAGS"] += " -lsecp256k1"
return env


recipe = CoincurveRecipe()
54 changes: 54 additions & 0 deletions pythonforandroid/recipes/coincurve/coincurve.patch
@@ -0,0 +1,54 @@
diff '--color=auto' -uNr coincurve-19.0.1/setup.py coincurve-19.0.1.patch/setup.py
--- coincurve-19.0.1/setup.py 2024-03-02 10:40:59.000000000 +0530
+++ coincurve-19.0.1.patch/setup.py 2024-03-10 09:51:58.034737104 +0530
@@ -47,6 +47,7 @@


def download_library(command):
+ return
if command.dry_run:
return
libdir = absolute('libsecp256k1')
@@ -189,6 +190,7 @@
absolute('libsecp256k1/configure'),
'--disable-shared',
'--enable-static',
+ '--host=%s' % os.environ['TOOLCHAIN_PREFIX'],
'--disable-dependency-tracking',
'--with-pic',
'--enable-module-extrakeys',
@@ -269,13 +271,7 @@
# ABI?: py_limited_api=True,
)

- extension.extra_compile_args = [
- subprocess.check_output(['pkg-config', '--cflags-only-I', 'libsecp256k1']).strip().decode('utf-8') # noqa S603
- ]
- extension.extra_link_args = [
- subprocess.check_output(['pkg-config', '--libs-only-L', 'libsecp256k1']).strip().decode('utf-8'), # noqa S603
- subprocess.check_output(['pkg-config', '--libs-only-l', 'libsecp256k1']).strip().decode('utf-8'), # noqa S603
- ]
+ extension.extra_link_args = ["-lsecp256k1"]

if os.name == 'nt' or sys.platform == 'win32':
# Apparently, the linker on Windows interprets -lxxx as xxx.lib, not libxxx.lib
@@ -340,7 +336,7 @@
license='MIT OR Apache-2.0',

python_requires='>=3.8',
- install_requires=['asn1crypto', 'cffi>=1.3.0'],
+ install_requires=[],

packages=find_packages(exclude=('_cffi_build', '_cffi_build.*', 'libsecp256k1', 'tests')),
package_data=package_data,
diff '--color=auto' -uNr coincurve-19.0.1/setup_support.py coincurve-19.0.1.patch/setup_support.py
--- coincurve-19.0.1/setup_support.py 2024-03-02 10:40:59.000000000 +0530
+++ coincurve-19.0.1.patch/setup_support.py 2024-03-10 08:53:45.650056659 +0530
@@ -56,6 +56,7 @@


def _find_lib():
+ return True
if 'COINCURVE_IGNORE_SYSTEM_LIB' in os.environ:
return False

4 changes: 2 additions & 2 deletions pythonforandroid/recipes/libsecp256k1/__init__.py
Expand Up @@ -9,8 +9,8 @@
class LibSecp256k1Recipe(Recipe):

built_libraries = {'libsecp256k1.so': '.libs'}

url = 'https://github.com/bitcoin-core/secp256k1/archive/master.zip'
version = '0.4.1'
url = 'https://github.com/bitcoin-core/secp256k1/archive/refs/tags/v{version}.tar.gz'

def build_arch(self, arch):
env = self.get_recipe_env(arch)
Expand Down
3 changes: 2 additions & 1 deletion pythonforandroid/recipes/libzmq/__init__.py
Expand Up @@ -6,7 +6,7 @@


class LibZMQRecipe(Recipe):
version = '4.3.2'
version = '4.3.4'
url = 'https://github.com/zeromq/libzmq/releases/download/v{version}/zeromq-{version}.zip'
depends = []
built_libraries = {'libzmq.so': 'src/.libs'}
Expand Down Expand Up @@ -34,6 +34,7 @@ def build_arch(self, arch):
'--prefix={}'.format(prefix),
'--with-libsodium=no',
'--disable-libunwind',
'--disable-Werror',
_env=env)
shprint(sh.make, _env=env)
shprint(sh.make, 'install', _env=env)
Expand Down
2 changes: 1 addition & 1 deletion pythonforandroid/recipes/pyzbar/__init__.py
Expand Up @@ -4,7 +4,7 @@

class PyZBarRecipe(PythonRecipe):

version = '0.1.7'
version = '0.1.9'

url = 'https://github.com/NaturalHistoryMuseum/pyzbar/archive/v{version}.tar.gz' # noqa

Expand Down
6 changes: 3 additions & 3 deletions tests/recipes/recipe_lib_test.py
Expand Up @@ -88,7 +88,7 @@ def test_build_arch(
with mock.patch(
f"pythonforandroid.recipes.{self.recipe_name}.sh.Command"
) as mock_sh_command, mock.patch(
f"pythonforandroid.recipes.{self.recipe_name}.sh.make"
f"pythonforandroid.recipes.{self.recipe_name}.sh.make", create=True
) as mock_make:
self.recipe.build_arch(self.arch)

Expand Down Expand Up @@ -130,9 +130,9 @@ def test_build_arch(
# Since the following mocks are dynamic,
# we mock it inside a Context Manager
with mock.patch(
f"pythonforandroid.recipes.{self.recipe_name}.sh.make"
f"pythonforandroid.recipes.{self.recipe_name}.sh.make", create=True
) as mock_make, mock.patch(
f"pythonforandroid.recipes.{self.recipe_name}.sh.cmake"
f"pythonforandroid.recipes.{self.recipe_name}.sh.cmake", create=True
) as mock_cmake:
self.recipe.build_arch(self.arch)

Expand Down
4 changes: 2 additions & 2 deletions tests/recipes/test_openal.py
Expand Up @@ -9,8 +9,8 @@ class TestOpenalRecipe(BaseTestForCmakeRecipe, unittest.TestCase):
"""
recipe_name = "openal"

@mock.patch("pythonforandroid.recipes.openal.sh.cmake")
@mock.patch("pythonforandroid.recipes.openal.sh.make")
@mock.patch("pythonforandroid.recipes.openal.sh.cmake", create=True)
@mock.patch("pythonforandroid.recipes.openal.sh.make", create=True)
@mock.patch("pythonforandroid.recipes.openal.sh.cp")
@mock.patch("pythonforandroid.util.chdir")
@mock.patch("pythonforandroid.build.ensure_dir")
Expand Down
8 changes: 7 additions & 1 deletion tests/recipes/test_sdl2_mixer.py
@@ -1,5 +1,5 @@
import unittest
from tests.recipes.recipe_lib_test import RecipeCtx
from tests.recipes.recipe_ctx import RecipeCtx


class TestSDL2MixerRecipe(RecipeCtx, unittest.TestCase):
Expand All @@ -8,6 +8,12 @@ class TestSDL2MixerRecipe(RecipeCtx, unittest.TestCase):
"""
recipe_name = "sdl2_mixer"

def setUp(self):
"""Setups bootstrap build_dir."""
super().setUp()
bootstrap = self.ctx.bootstrap
bootstrap.build_dir = bootstrap.get_build_dir()

def test_get_include_dirs(self):
list_of_includes = self.recipe.get_include_dirs(self.arch)
self.assertIsInstance(list_of_includes, list)
Expand Down
8 changes: 4 additions & 4 deletions tests/test_bootstrap.py
Expand Up @@ -15,12 +15,12 @@
from pythonforandroid.util import BuildInterruptingException
from pythonforandroid.androidndk import AndroidNDK

from test_graph import get_fake_recipe
from tests.test_graph import get_fake_recipe


class BaseClassSetupBootstrap(object):
class BaseClassSetupBootstrap:
"""
An class object which is intended to be used as a base class to configure
An class which is intended to be used as a base class to configure
an inherited class of `unittest.TestCase`. This class will override the
`setUp` and `tearDown` methods.
"""
Expand Down Expand Up @@ -115,7 +115,7 @@ def test__cmp_bootstraps_by_priority(self):
) < 0)

# Test a random bootstrap is always lower priority than sdl2:
class _FakeBootstrap(object):
class _FakeBootstrap:
def __init__(self, name):
self.name = name
bs1 = _FakeBootstrap("alpha")
Expand Down
2 changes: 1 addition & 1 deletion tests/test_pythonpackage_basic.py
Expand Up @@ -85,7 +85,7 @@ def test_get_dep_names_of_package():
# TEST 1 from external ref:
# Check that colorama is returned without the install condition when
# just getting the names (it has a "; ..." conditional originally):
dep_names = get_dep_names_of_package("python-for-android")
dep_names = get_dep_names_of_package("python-for-android==2023.9.16")
assert "colorama" in dep_names
assert "setuptools" not in dep_names
try:
Expand Down
4 changes: 2 additions & 2 deletions tests/test_recipe.py
@@ -1,16 +1,16 @@
import os
import pytest
import tempfile
import types
import unittest
import warnings
from unittest import mock
from backports import tempfile

from pythonforandroid.build import Context
from pythonforandroid.recipe import Recipe, TargetPythonRecipe, import_recipe
from pythonforandroid.archs import ArchAarch_64
from pythonforandroid.bootstrap import Bootstrap
from test_bootstrap import BaseClassSetupBootstrap
from tests.test_bootstrap import BaseClassSetupBootstrap


def patch_logger(level):
Expand Down
1 change: 0 additions & 1 deletion tox.ini
Expand Up @@ -6,7 +6,6 @@ basepython = python3
deps =
pytest
py3: coveralls
backports.tempfile
# posargs will be replaced by the tox args, so you can override pytest
# args e.g. `tox -- tests/test_graph.py`
commands = pytest {posargs:tests/}
Expand Down

0 comments on commit c561230

Please sign in to comment.