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
51 changes: 46 additions & 5 deletions pythonforandroid/bootstrap.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import shlex
import shutil

from pythonforandroid.logger import (shprint, info, logger, debug)
from pythonforandroid.logger import (shprint, info, info_main, logger, debug)
from pythonforandroid.util import (
current_directory, ensure_dir, temp_directory, BuildInterruptingException,
rmdir, move)
Expand Down Expand Up @@ -184,11 +184,52 @@ def prepare_build_dir(self):
def prepare_dist_dir(self):
ensure_dir(self.dist_dir)

def _assemble_distribution_for_arch(self, arch):
"""Per-architecture distribution assembly.

Override this method to customize per-arch behavior.
Called once for each architecture in self.ctx.archs.
"""
self.distribute_libs(arch, [self.ctx.get_libs_dir(arch.arch)])
self.distribute_aars(arch)

python_bundle_dir = join(f'_python_bundle__{arch.arch}', '_python_bundle')
ensure_dir(python_bundle_dir)
site_packages_dir = self.ctx.python_recipe.create_python_bundle(
join(self.dist_dir, python_bundle_dir), arch)
if not self.ctx.with_debug_symbols:
self.strip_libraries(arch)
self.fry_eggs(site_packages_dir)

def assemble_distribution(self):
''' Copies all the files into the distribution (this function is
overridden by the specific bootstrap classes to do this)
and add in the distribution info.
'''
"""Assemble the distribution by copying files and creating Python bundle.

This default implementation works for most bootstraps. Override
_assemble_distribution_for_arch() for per-arch customization, or
override this entire method for fundamentally different behavior.
"""
info_main(f'# Creating Android project ({self.name})')

rmdir(self.dist_dir)
shprint(sh.cp, '-r', self.build_dir, self.dist_dir)

with current_directory(self.dist_dir):
with open('local.properties', 'w') as fileh:
fileh.write('sdk.dir={}'.format(self.ctx.sdk_dir))

with current_directory(self.dist_dir):
info('Copying Python distribution')

self.distribute_javaclasses(self.ctx.javaclass_dir,
dest_dir=join("src", "main", "java"))

for arch in self.ctx.archs:
self._assemble_distribution_for_arch(arch)

if 'sqlite3' not in self.ctx.recipe_build_order:
with open('blacklist.txt', 'a') as fileh:
fileh.write('\nsqlite3/*\nlib-dynload/_sqlite3.so\n')

self._copy_in_final_files()
self.distribution.save_info(self.dist_dir)

Expand Down
54 changes: 14 additions & 40 deletions pythonforandroid/bootstraps/_sdl_common/__init__.py
Original file line number Diff line number Diff line change
@@ -1,49 +1,23 @@
from os.path import join

import sh

from pythonforandroid.toolchain import (
Bootstrap, shprint, current_directory, info, info_main)
from pythonforandroid.util import ensure_dir, rmdir
from pythonforandroid.toolchain import Bootstrap
from pythonforandroid.util import ensure_dir


class SDLGradleBootstrap(Bootstrap):
name = "_sdl_common"

recipe_depends = []

def assemble_distribution(self):
info_main("# Creating Android project ({})".format(self.name))

rmdir(self.dist_dir)
info("Copying SDL/gradle build")
shprint(sh.cp, "-r", self.build_dir, self.dist_dir)

# either the build use environment variable (ANDROID_HOME)
# or the local.properties if exists
with current_directory(self.dist_dir):
with open('local.properties', 'w') as fileh:
fileh.write('sdk.dir={}'.format(self.ctx.sdk_dir))

with current_directory(self.dist_dir):
info("Copying Python distribution")

self.distribute_javaclasses(self.ctx.javaclass_dir,
dest_dir=join("src", "main", "java"))

for arch in self.ctx.archs:
python_bundle_dir = join(f'_python_bundle__{arch.arch}', '_python_bundle')
ensure_dir(python_bundle_dir)

self.distribute_libs(arch, [self.ctx.get_libs_dir(arch.arch)])
site_packages_dir = self.ctx.python_recipe.create_python_bundle(
join(self.dist_dir, python_bundle_dir), arch)
if not self.ctx.with_debug_symbols:
self.strip_libraries(arch)
self.fry_eggs(site_packages_dir)

if 'sqlite3' not in self.ctx.recipe_build_order:
with open('blacklist.txt', 'a') as fileh:
fileh.write('\nsqlite3/*\nlib-dynload/_sqlite3.so\n')

super().assemble_distribution()
def _assemble_distribution_for_arch(self, arch):
"""SDL bootstrap skips distribute_aars() - handled differently."""
self.distribute_libs(arch, [self.ctx.get_libs_dir(arch.arch)])
# Note: SDL bootstrap does not call distribute_aars()

python_bundle_dir = join(f'_python_bundle__{arch.arch}', '_python_bundle')
ensure_dir(python_bundle_dir)
site_packages_dir = self.ctx.python_recipe.create_python_bundle(
join(self.dist_dir, python_bundle_dir), arch)
if not self.ctx.with_debug_symbols:
self.strip_libraries(arch)
self.fry_eggs(site_packages_dir)
41 changes: 1 addition & 40 deletions pythonforandroid/bootstraps/service_only/__init__.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
import sh
from os.path import join
from pythonforandroid.toolchain import (
Bootstrap, current_directory, info, info_main, shprint)
from pythonforandroid.util import ensure_dir, rmdir
from pythonforandroid.toolchain import Bootstrap


class ServiceOnlyBootstrap(Bootstrap):
Expand All @@ -13,40 +9,5 @@ class ServiceOnlyBootstrap(Bootstrap):
set(Bootstrap.recipe_depends).union({'genericndkbuild'})
)

def assemble_distribution(self):
info_main('# Creating Android project from build and {} bootstrap'.format(
self.name))

info('This currently just copies the build stuff straight from the build dir.')
rmdir(self.dist_dir)
shprint(sh.cp, '-r', self.build_dir, self.dist_dir)
with current_directory(self.dist_dir):
with open('local.properties', 'w') as fileh:
fileh.write('sdk.dir={}'.format(self.ctx.sdk_dir))

with current_directory(self.dist_dir):
info('Copying python distribution')

self.distribute_javaclasses(self.ctx.javaclass_dir,
dest_dir=join("src", "main", "java"))

for arch in self.ctx.archs:
self.distribute_libs(arch, [self.ctx.get_libs_dir(arch.arch)])
self.distribute_aars(arch)

python_bundle_dir = join(f'_python_bundle__{arch.arch}', '_python_bundle')
ensure_dir(python_bundle_dir)
site_packages_dir = self.ctx.python_recipe.create_python_bundle(
join(self.dist_dir, python_bundle_dir), arch)
if not self.ctx.with_debug_symbols:
self.strip_libraries(arch)
self.fry_eggs(site_packages_dir)

if 'sqlite3' not in self.ctx.recipe_build_order:
with open('blacklist.txt', 'a') as fileh:
fileh.write('\nsqlite3/*\nlib-dynload/_sqlite3.so\n')

super().assemble_distribution()


bootstrap = ServiceOnlyBootstrap()
41 changes: 1 addition & 40 deletions pythonforandroid/bootstraps/webview/__init__.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@
from os.path import join

import sh

from pythonforandroid.toolchain import Bootstrap, current_directory, info, info_main, shprint
from pythonforandroid.util import ensure_dir, rmdir
from pythonforandroid.toolchain import Bootstrap


class WebViewBootstrap(Bootstrap):
Expand All @@ -13,39 +8,5 @@ class WebViewBootstrap(Bootstrap):
set(Bootstrap.recipe_depends).union({'genericndkbuild'})
)

def assemble_distribution(self):
info_main('# Creating Android project from build and {} bootstrap'.format(
self.name))

rmdir(self.dist_dir)
shprint(sh.cp, '-r', self.build_dir, self.dist_dir)
with current_directory(self.dist_dir):
with open('local.properties', 'w') as fileh:
fileh.write('sdk.dir={}'.format(self.ctx.sdk_dir))

with current_directory(self.dist_dir):
info('Copying python distribution')

self.distribute_javaclasses(self.ctx.javaclass_dir,
dest_dir=join("src", "main", "java"))

for arch in self.ctx.archs:
self.distribute_libs(arch, [self.ctx.get_libs_dir(arch.arch)])
self.distribute_aars(arch)

python_bundle_dir = join(f'_python_bundle__{arch.arch}', '_python_bundle')
ensure_dir(python_bundle_dir)
site_packages_dir = self.ctx.python_recipe.create_python_bundle(
join(self.dist_dir, python_bundle_dir), arch)
if not self.ctx.with_debug_symbols:
self.strip_libraries(arch)
self.fry_eggs(site_packages_dir)

if 'sqlite3' not in self.ctx.recipe_build_order:
with open('blacklist.txt', 'a') as fileh:
fileh.write('\nsqlite3/*\nlib-dynload/_sqlite3.so\n')

super().assemble_distribution()


bootstrap = WebViewBootstrap()
53 changes: 26 additions & 27 deletions tests/test_bootstrap.py
Original file line number Diff line number Diff line change
Expand Up @@ -353,34 +353,30 @@ def bootstrap_name(self):
name of the bootstrap to test"""
raise NotImplementedError("Not implemented in GenericBootstrapTest")

@mock.patch("pythonforandroid.bootstraps.qt.shprint")
@mock.patch("pythonforandroid.bootstraps.qt.rmdir")
@mock.patch("pythonforandroid.bootstraps.qt.open", create=True)
@mock.patch("pythonforandroid.bootstraps.service_only.open", create=True)
@mock.patch("pythonforandroid.bootstraps.webview.open", create=True)
@mock.patch("pythonforandroid.bootstraps._sdl_common.open", create=True)
@mock.patch("pythonforandroid.bootstrap.open", create=True)
@mock.patch("pythonforandroid.distribution.open", create=True)
@mock.patch("pythonforandroid.bootstrap.Bootstrap.strip_libraries")
@mock.patch("pythonforandroid.util.exists")
@mock.patch("pythonforandroid.util.chdir")
@mock.patch("pythonforandroid.bootstrap.listdir")
@mock.patch("pythonforandroid.bootstraps._sdl_common.rmdir")
@mock.patch("pythonforandroid.bootstraps.service_only.rmdir")
@mock.patch("pythonforandroid.bootstraps.webview.rmdir")
@mock.patch("pythonforandroid.bootstrap.sh.cp")
@mock.patch("pythonforandroid.bootstrap.rmdir")
@mock.patch("pythonforandroid.bootstrap.shprint")
def test_assemble_distribution(
self,
mock_sh_cp,
mock_rmdir1,
mock_rmdir2,
mock_rmdir3,
mock_shprint,
mock_rmdir,
mock_listdir,
mock_chdir,
mock_ensure_dir,
mock_strip_libraries,
mock_open_dist_files,
mock_open_sdl_files,
mock_open_webview_files,
mock_open_service_only_files,
mock_open_qt_files
mock_open_bootstrap_files,
mock_open_qt_files,
mock_qt_rmdir,
mock_qt_shprint
):
"""
A test for any overwritten method of
Expand Down Expand Up @@ -417,13 +413,11 @@ def test_assemble_distribution(
bs.assemble_distribution()

mock_open_dist_files.assert_called_once_with("dist_info.json", "w")
mock_open_bootstraps = {
"sdl2": mock_open_sdl_files,
"sdl3": mock_open_sdl_files,
"webview": mock_open_webview_files,
"service_only": mock_open_service_only_files,
"qt": mock_open_qt_files
}
# Qt bootstrap has its own assemble_distribution, others use base class
if self.bootstrap_name == "qt":
mock_open_bs = mock_open_qt_files
else:
mock_open_bs = mock_open_bootstrap_files
expected_open_calls = {
"sdl2": [
mock.call("local.properties", "w"),
Expand All @@ -433,11 +427,16 @@ def test_assemble_distribution(
mock.call("local.properties", "w"),
mock.call("blacklist.txt", "a"),
],
"webview": [mock.call("local.properties", "w")],
"service_only": [mock.call("local.properties", "w")],
"webview": [
mock.call("local.properties", "w"),
mock.call("blacklist.txt", "a"),
],
"service_only": [
mock.call("local.properties", "w"),
mock.call("blacklist.txt", "a"),
],
"qt": [mock.call("local.properties", "w")]
}
mock_open_bs = mock_open_bootstraps[self.bootstrap_name]
# test that the expected calls has been called
for expected_call in expected_open_calls[self.bootstrap_name]:
self.assertIn(expected_call, mock_open_bs.call_args_list)
Expand All @@ -446,7 +445,7 @@ def test_assemble_distribution(
mock.call().__enter__().write("sdk.dir=/opt/android/android-sdk"),
mock_open_bs.mock_calls,
)
if self.bootstrap_name in ["sdl2", "sdl3"]:
if self.bootstrap_name in ["sdl2", "sdl3", "webview", "service_only"]:
self.assertIn(
mock.call()
.__enter__()
Expand All @@ -455,7 +454,7 @@ def test_assemble_distribution(
)

# check that the other mocks we made are actually called
mock_sh_cp.assert_called()
mock_shprint.assert_called()
mock_chdir.assert_called()
mock_listdir.assert_called()
mock_strip_libraries.assert_called()
Expand Down
Loading