Skip to content

Factor out dependency checking. Use modern version handling #2866

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 30, 2023
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
70 changes: 70 additions & 0 deletions pythonforandroid/checkdependencies.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
from importlib import import_module
from os import environ
import sys

from packaging.version import Version

from pythonforandroid.prerequisites import (
check_and_install_default_prerequisites,
)


def check_python_dependencies():
"""
Check if the Python requirements are installed. This must appears
before other imports because otherwise they're imported elsewhere.

Using the ok check instead of failing immediately so that all
errors are printed at once.
"""

ok = True

modules = [("colorama", "0.3.3"), "appdirs", ("sh", "1.10"), "jinja2"]

for module in modules:
if isinstance(module, tuple):
module, version = module
else:
version = None

try:
import_module(module)
except ImportError:
if version is None:
print(
"ERROR: The {} Python module could not be found, please "
"install it.".format(module)
)
ok = False
else:
print(
"ERROR: The {} Python module could not be found, "
"please install version {} or higher".format(
module, version
)
)
ok = False
else:
if version is None:
continue
try:
cur_ver = sys.modules[module].__version__
except AttributeError: # this is sometimes not available
continue
if Version(cur_ver) < Version(version):
print(
"ERROR: {} version is {}, but python-for-android needs "
"at least {}.".format(module, cur_ver, version)
)
ok = False

if not ok:
print("python-for-android is exiting due to the errors logged above")
exit(1)


def check():
if not environ.get("SKIP_PREREQUISITES_CHECK", "0") == "1":
check_and_install_default_prerequisites()
check_python_dependencies()
122 changes: 39 additions & 83 deletions pythonforandroid/toolchain.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,96 +6,43 @@
This module defines the entry point for command line and programmatic use.
"""

from appdirs import user_data_dir
import argparse
from functools import wraps
import glob
import logging
import os
from os import environ
from pythonforandroid import __version__
from pythonforandroid.pythonpackage import get_dep_names_of_package
from pythonforandroid.recommendations import (
RECOMMENDED_NDK_API, RECOMMENDED_TARGET_API, print_recommendations)
from pythonforandroid.util import BuildInterruptingException, load_source
from pythonforandroid.entrypoints import main
from pythonforandroid.prerequisites import check_and_install_default_prerequisites


def check_python_dependencies():
# Check if the Python requirements are installed. This appears
# before the imports because otherwise they're imported elsewhere.

# Using the ok check instead of failing immediately so that all
# errors are printed at once

from distutils.version import LooseVersion
from importlib import import_module
import sys

ok = True

modules = [('colorama', '0.3.3'), 'appdirs', ('sh', '1.10'), 'jinja2']

for module in modules:
if isinstance(module, tuple):
module, version = module
else:
version = None

try:
import_module(module)
except ImportError:
if version is None:
print('ERROR: The {} Python module could not be found, please '
'install it.'.format(module))
ok = False
else:
print('ERROR: The {} Python module could not be found, '
'please install version {} or higher'.format(
module, version))
ok = False
else:
if version is None:
continue
try:
cur_ver = sys.modules[module].__version__
except AttributeError: # this is sometimes not available
continue
if LooseVersion(cur_ver) < LooseVersion(version):
print('ERROR: {} version is {}, but python-for-android needs '
'at least {}.'.format(module, cur_ver, version))
ok = False

if not ok:
print('python-for-android is exiting due to the errors logged above')
exit(1)


if not environ.get('SKIP_PREREQUISITES_CHECK', '0') == '1':
check_and_install_default_prerequisites()
check_python_dependencies()


import sys
from sys import platform
from os.path import (join, dirname, realpath, exists, expanduser, basename)
import os
import glob
import shutil
import re
import shlex
from functools import wraps
import shutil
import sys
from sys import platform

import argparse
# This must be imported and run before other third-party or p4a
# packages.
from pythonforandroid.checkdependencies import check
check()

from packaging.version import Version, InvalidVersion
import sh
from appdirs import user_data_dir
import logging
from distutils.version import LooseVersion

from pythonforandroid.recipe import Recipe
from pythonforandroid.logger import (logger, info, warning, setup_color,
Out_Style, Out_Fore,
info_notify, info_main, shprint)
from pythonforandroid.util import current_directory
from pythonforandroid import __version__
from pythonforandroid.bootstrap import Bootstrap
from pythonforandroid.build import Context, build_recipes
from pythonforandroid.distribution import Distribution, pretty_log_dists
from pythonforandroid.entrypoints import main
from pythonforandroid.graph import get_recipe_order_and_bootstrap
from pythonforandroid.build import Context, build_recipes
from pythonforandroid.logger import (logger, info, warning, setup_color,
Out_Style, Out_Fore,
info_notify, info_main, shprint)
from pythonforandroid.pythonpackage import get_dep_names_of_package
from pythonforandroid.recipe import Recipe
from pythonforandroid.recommendations import (
RECOMMENDED_NDK_API, RECOMMENDED_TARGET_API, print_recommendations)
from pythonforandroid.util import (
current_directory, BuildInterruptingException, load_source)

user_dir = dirname(realpath(os.path.curdir))
toolchain_dir = dirname(__file__)
Expand Down Expand Up @@ -1068,13 +1015,22 @@ def _build_package(self, args, package_type):
self.hook("before_apk_assemble")
build_tools_versions = os.listdir(join(ctx.sdk_dir,
'build-tools'))
build_tools_versions = sorted(build_tools_versions,
key=LooseVersion)

def sort_key(version_text):
try:
# Historically, Android build release candidates have had
# spaces in the version number.
return Version(version_text.replace(" ", ""))
except InvalidVersion:
# Put badly named versions at worst position.
return Version("0")

build_tools_versions.sort(key=sort_key)
build_tools_version = build_tools_versions[-1]
info(('Detected highest available build tools '
'version to be {}').format(build_tools_version))

if build_tools_version < '25.0':
if Version(build_tools_version.replace(" ", "")) < Version('25.0'):
raise BuildInterruptingException(
'build_tools >= 25 is required, but %s is installed' % build_tools_version)
if not exists("gradlew"):
Expand Down