Merge branch 'master' into target-android-tests

This commit is contained in:
pavelsof 2020-05-28 18:39:51 +02:00
commit 9527f2ab96
14 changed files with 44 additions and 67 deletions

View file

@ -77,7 +77,7 @@ jobs:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- name: Try Python 2 install - name: Try Python 2 install
run: | run: |
# we don't want to build to fail with the exit 1 so we catch with "||" # we don't want the build to fail with the exit 1 so we catch with "||"
python2 -m pip install -e . 2> error.log || echo Failing as expected python2 -m pip install -e . 2> error.log || echo Failing as expected
cat error.log cat error.log
grep "Unsupported Python version" error.log grep "Unsupported Python version" error.log

View file

@ -18,10 +18,8 @@ project, and for iOS via the kivy-ios project. iOS and OSX are still under work.
For Android, buildozer will automatically download and prepare the For Android, buildozer will automatically download and prepare the
build dependencies. For more information, see build dependencies. For more information, see
[Android-SDK-NDK-Information](https://github.com/kivy/kivy/wiki/Android-SDK-NDK-Information). We [Android-SDK-NDK-Information](https://github.com/kivy/kivy/wiki/Android-SDK-NDK-Information).
recommend targeting Python 3 on Android, but you can target both Note that only Python 3 is supported.
Python 3 and Python 2 regardless of which version you use with
buildozer on the desktop.
Note that this tool has nothing to do with the eponymous online build service Note that this tool has nothing to do with the eponymous online build service
[buildozer.io](http://buildozer.io). [buildozer.io](http://buildozer.io).

View file

@ -617,10 +617,6 @@ class Buildozer:
def file_extract(self, archive, cwd=None): def file_extract(self, archive, cwd=None):
if archive.endswith('.tgz') or archive.endswith('.tar.gz'): if archive.endswith('.tgz') or archive.endswith('.tar.gz'):
# XXX tarfile doesn't work for NDK-r8c :(
#tf = tarfile.open(archive, 'r:*')
#tf.extractall(path=cwd)
#tf.close()
self.cmd('tar xzf {0}'.format(archive), cwd=cwd) self.cmd('tar xzf {0}'.format(archive), cwd=cwd)
return return
@ -631,8 +627,8 @@ class Buildozer:
if archive.endswith('.bin'): if archive.endswith('.bin'):
# To process the bin files for linux and darwin systems # To process the bin files for linux and darwin systems
self.cmd('chmod a+x {0}'.format(archive),cwd=cwd) self.cmd('chmod a+x {0}'.format(archive), cwd=cwd)
self.cmd('./{0}'.format(archive),cwd=cwd) self.cmd('./{0}'.format(archive), cwd=cwd)
return return
if archive.endswith('.zip'): if archive.endswith('.zip'):
@ -830,7 +826,6 @@ class Buildozer:
main_py = join(self.app_dir, 'service', 'main.py') main_py = join(self.app_dir, 'service', 'main.py')
if not self.file_exists(main_py): if not self.file_exists(main_py):
#self.error('Unable to patch main_py to add applibs directory.')
return return
header = (b'import sys, os; ' header = (b'import sys, os; '
@ -847,7 +842,7 @@ class Buildozer:
'''Return a "valid" name from a name with lot of invalid chars '''Return a "valid" name from a name with lot of invalid chars
(allowed characters: a-z, A-Z, 0-9, -, _) (allowed characters: a-z, A-Z, 0-9, -, _)
''' '''
return re.sub('[^a-zA-Z0-9_\-]', '_', name) return re.sub(r'[^a-zA-Z0-9_\-]', '_', name)
@property @property
def root_dir(self): def root_dir(self):
@ -1249,6 +1244,7 @@ def set_config_from_envs(config):
for token in config.options(section): for token in config.options(section):
set_config_token_from_env(section, token, config) set_config_token_from_env(section, token, config)
def set_config_token_from_env(section, token, config): def set_config_token_from_env(section, token, config):
'''Given a config section and token, checks for an appropriate '''Given a config section and token, checks for an appropriate
environment variable. If the variable exists, sets the config entry to environment variable. If the variable exists, sets the config entry to

View file

@ -221,6 +221,10 @@ fullscreen = 0
# (str) The Android arch to build for, choices: armeabi-v7a, arm64-v8a, x86, x86_64 # (str) The Android arch to build for, choices: armeabi-v7a, arm64-v8a, x86, x86_64
android.arch = armeabi-v7a android.arch = armeabi-v7a
# (int) overrides automatic versionCode computation (used in build.gradle)
# this is not the same as app version and should only be edited if you know what you're doing
# android.numeric_version = 1
# #
# Python for android (p4a) specific # Python for android (p4a) specific
# #

View file

@ -6,14 +6,13 @@ This was needed to correctly support db between Python 2 and 3.
__all__ = ["JsonStore"] __all__ = ["JsonStore"]
import io import io
import sys from json import load, dump
from json import load, dump, dumps
from os.path import exists from os.path import exists
class JsonStore: class JsonStore:
def __init__(self, filename): def __init__(self, filename):
super().__init__()
self.filename = filename self.filename = filename
self.data = {} self.data = {}
if exists(filename): if exists(filename):

View file

@ -41,6 +41,7 @@ class Infinity:
def __neg__(self): def __neg__(self):
return NegativeInfinity return NegativeInfinity
Infinity = Infinity() Infinity = Infinity()
@ -73,4 +74,5 @@ class NegativeInfinity:
def __neg__(self): def __neg__(self):
return Infinity return Infinity
NegativeInfinity = NegativeInfinity() NegativeInfinity = NegativeInfinity()

View file

@ -162,6 +162,7 @@ def _legacy_cmpkey(version):
return epoch, parts return epoch, parts
# Deliberately not anchored to the start and end of the string, to make it # Deliberately not anchored to the start and end of the string, to make it
# easier for 3rd party code to reuse # easier for 3rd party code to reuse
VERSION_PATTERN = r""" VERSION_PATTERN = r"""

View file

@ -19,5 +19,6 @@ def main():
Buildozer().error('%s' % error) Buildozer().error('%s' % error)
sys.exit(1) sys.exit(1)
if __name__ == '__main__': if __name__ == '__main__':
main() main()

View file

@ -27,7 +27,6 @@ except ImportError:
from ConfigParser import SafeConfigParser from ConfigParser import SafeConfigParser
try: try:
import termios import termios
import tty
has_termios = True has_termios = True
except ImportError: except ImportError:
has_termios = False has_termios = False
@ -131,7 +130,7 @@ class BuildozerRemote(Buildozer):
self.package_full_name) self.package_full_name)
self.debug('Remote build directory: {}'.format(self.remote_build_dir)) self.debug('Remote build directory: {}'.format(self.remote_build_dir))
self._ssh_mkdir(self.remote_build_dir) self._ssh_mkdir(self.remote_build_dir)
self._ssh_sync(__path__[0]) self._ssh_sync(__path__[0]) # noqa: F821 undefined name
def _sync_application_sources(self): def _sync_application_sources(self):
self.info('Synchronize application sources') self.info('Synchronize application sources')
@ -159,7 +158,7 @@ class BuildozerRemote(Buildozer):
self.remote_build_dir, self.remote_build_dir,
'--verbose' if self.log_level == 2 else '', '--verbose' if self.log_level == 2 else '',
' '.join(args), ' '.join(args),
) )
self._ssh_command(cmd) self._ssh_command(cmd)
def _ssh_mkdir(self, *args): def _ssh_mkdir(self, *args):
@ -180,7 +179,7 @@ class BuildozerRemote(Buildozer):
directory = realpath(directory) directory = realpath(directory)
base_strip = directory.rfind('/') base_strip = directory.rfind('/')
if mode == 'get': if mode == 'get':
local_dir = join(directory,'bin') local_dir = join(directory, 'bin')
remote_dir = join(self.remote_build_dir, 'bin') remote_dir = join(self.remote_build_dir, 'bin')
if not exists(local_dir): if not exists(local_dir):
makedirs(local_dir) makedirs(local_dir)
@ -200,9 +199,6 @@ class BuildozerRemote(Buildozer):
def _ssh_command(self, command): def _ssh_command(self, command):
self.debug('Execute remote command {}'.format(command)) self.debug('Execute remote command {}'.format(command))
#shell = self._ssh_client.invoke_shell()
#shell.sendall(command)
#shell.sendall('\nexit\n')
transport = self._ssh_client.get_transport() transport = self._ssh_client.get_transport()
channel = transport.open_session() channel = transport.open_session()
try: try:
@ -220,8 +216,6 @@ class BuildozerRemote(Buildozer):
def _posix_shell(self, chan): def _posix_shell(self, chan):
oldtty = termios.tcgetattr(stdin) oldtty = termios.tcgetattr(stdin)
try: try:
#tty.setraw(stdin.fileno())
#tty.setcbreak(stdin.fileno())
chan.settimeout(0.0) chan.settimeout(0.0)
while True: while True:
@ -234,7 +228,6 @@ class BuildozerRemote(Buildozer):
break break
stdout.write(x) stdout.write(x)
stdout.flush() stdout.flush()
#print len(x), repr(x)
except socket.timeout: except socket.timeout:
pass pass
if stdin in r: if stdin in r:
@ -246,7 +239,7 @@ class BuildozerRemote(Buildozer):
termios.tcsetattr(stdin, termios.TCSADRAIN, oldtty) termios.tcsetattr(stdin, termios.TCSADRAIN, oldtty)
# thanks to Mike Looijmans for this code # thanks to Mike Looijmans for this code
def _windows_shell(self,chan): def _windows_shell(self, chan):
import threading import threading
stdout.write("Line-buffered terminal emulation. Press F6 or ^Z to send EOF.\r\n\r\n") stdout.write("Line-buffered terminal emulation. Press F6 or ^Z to send EOF.\r\n\r\n")
@ -274,6 +267,7 @@ class BuildozerRemote(Buildozer):
# user hit ^Z or F6 # user hit ^Z or F6
pass pass
def main(): def main():
try: try:
BuildozerRemote().run_command(sys.argv[1:]) BuildozerRemote().run_command(sys.argv[1:])
@ -282,5 +276,6 @@ def main():
except BuildozerException as error: except BuildozerException as error:
Buildozer().error('%s' % error) Buildozer().error('%s' % error)
if __name__ == '__main__': if __name__ == '__main__':
main() main()

View file

@ -2,6 +2,7 @@ from sys import exit
import os import os
from os.path import join from os.path import join
def no_config(f): def no_config(f):
f.__no_config = True f.__no_config = True
return f return f
@ -9,7 +10,6 @@ def no_config(f):
class Target: class Target:
def __init__(self, buildozer): def __init__(self, buildozer):
super().__init__()
self.buildozer = buildozer self.buildozer = buildozer
self.build_mode = 'debug' self.build_mode = 'debug'
self.platform_update = False self.platform_update = False

View file

@ -24,7 +24,6 @@ import os
import io import io
import re import re
import ast import ast
import sh
from pipes import quote from pipes import quote
from sys import platform, executable from sys import platform, executable
from buildozer import BuildozerException, USE_COLOR from buildozer import BuildozerException, USE_COLOR
@ -249,7 +248,7 @@ class TargetAndroid(Target):
break_on_error=False) break_on_error=False)
is_debian_like = (returncode_dpkg == 0) is_debian_like = (returncode_dpkg == 0)
if is_debian_like and \ if is_debian_like and \
not self.buildozer.file_exists('/usr/include/zlib.h'): not self.buildozer.file_exists('/usr/include/zlib.h'):
raise BuildozerException( raise BuildozerException(
'zlib headers must be installed, ' 'zlib headers must be installed, '
'run: sudo apt-get install zlib1g-dev') 'run: sudo apt-get install zlib1g-dev')
@ -740,7 +739,7 @@ class TargetAndroid(Target):
try: try:
with open(join(self.p4a_dir, "setup.py")) as fd: with open(join(self.p4a_dir, "setup.py")) as fd:
setup = fd.read() setup = fd.read()
deps = re.findall("^\s*install_reqs = (\[[^\]]*\])", setup, re.DOTALL | re.MULTILINE)[0] deps = re.findall(r"^\s*install_reqs = (\[[^\]]*\])", setup, re.DOTALL | re.MULTILINE)[0]
deps = ast.literal_eval(deps) deps = ast.literal_eval(deps)
except IOError: except IOError:
self.buildozer.error('Failed to read python-for-android setup.py at {}'.format( self.buildozer.error('Failed to read python-for-android setup.py at {}'.format(
@ -768,7 +767,7 @@ class TargetAndroid(Target):
'P4A_{}_DIR'.format(name[20:]): realpath(expanduser(value)) 'P4A_{}_DIR'.format(name[20:]): realpath(expanduser(value))
for name, value in self.buildozer.config.items('app') for name, value in self.buildozer.config.items('app')
if name.startswith('requirements.source.') if name.startswith('requirements.source.')
} }
if source_dirs: if source_dirs:
self.buildozer.environ.update(source_dirs) self.buildozer.environ.update(source_dirs)
self.buildozer.info('Using custom source dirs:\n {}'.format( self.buildozer.info('Using custom source dirs:\n {}'.format(
@ -1055,12 +1054,12 @@ class TargetAndroid(Target):
build_cmd += [('--add-compile-option', option)] build_cmd += [('--add-compile-option', option)]
# android.add_gradle_repositories # android.add_gradle_repositories
repos = config.getlist('app','android.add_gradle_repositories', []) repos = config.getlist('app', 'android.add_gradle_repositories', [])
for repo in repos: for repo in repos:
build_cmd += [('--add-gradle-repository', repo)] build_cmd += [('--add-gradle-repository', repo)]
# android packaging options # android packaging options
pkgoptions = config.getlist('app','android.add_packaging_options', []) pkgoptions = config.getlist('app', 'android.add_packaging_options', [])
for pkgoption in pkgoptions: for pkgoption in pkgoptions:
build_cmd += [('--add-packaging-option', pkgoption)] build_cmd += [('--add-packaging-option', pkgoption)]
@ -1114,7 +1113,7 @@ class TargetAndroid(Target):
build_cmd += [("--ouya-icon", join(self.buildozer.root_dir, build_cmd += [("--ouya-icon", join(self.buildozer.root_dir,
ouya_icon))] ouya_icon))]
if config.getdefault('app','p4a.bootstrap','sdl2') != 'service_only': if config.getdefault('app', 'p4a.bootstrap', 'sdl2') != 'service_only':
# add orientation # add orientation
orientation = config.getdefault('app', 'orientation', 'landscape') orientation = config.getdefault('app', 'orientation', 'landscape')
if orientation == 'all': if orientation == 'all':
@ -1144,6 +1143,11 @@ class TargetAndroid(Target):
if launch_mode: if launch_mode:
build_cmd += [("--activity-launch-mode", launch_mode)] build_cmd += [("--activity-launch-mode", launch_mode)]
# numeric version
numeric_version = config.getdefault('app', 'android.numeric_version')
if numeric_version:
build_cmd += [("--numeric-version", numeric_version)]
# build only in debug right now. # build only in debug right now.
if self.build_mode == 'debug': if self.build_mode == 'debug':
build_cmd += [("debug", )] build_cmd += [("debug", )]
@ -1360,6 +1364,7 @@ def get_target(buildozer):
buildozer.targetname = "android" buildozer.targetname = "android"
return TargetAndroid(buildozer) return TargetAndroid(buildozer)
def generate_dist_folder_name(base_dist_name, arch_names=None): def generate_dist_folder_name(base_dist_name, arch_names=None):
"""Generate the distribution folder name to use, based on a """Generate the distribution folder name to use, based on a
combination of the input arguments. combination of the input arguments.

View file

@ -59,6 +59,7 @@ li { padding: 1em; }
</html> </html>
''' '''
class TargetIos(Target): class TargetIos(Target):
targetname = "ios" targetname = "ios"
@ -113,7 +114,7 @@ class TargetIos(Target):
# we need to extract the requirements that kivy-ios knows about # we need to extract the requirements that kivy-ios knows about
available_modules = self.get_available_packages() available_modules = self.get_available_packages()
onlyname = lambda x: x.split('==')[0] onlyname = lambda x: x.split('==')[0] # noqa: E731 do not assign a lambda expression, use a def
ios_requirements = [x for x in app_requirements if onlyname(x) in ios_requirements = [x for x in app_requirements if onlyname(x) in
available_modules] available_modules]
@ -401,5 +402,6 @@ class TargetIos(Target):
with open(password_file, 'wb') as fd: with open(password_file, 'wb') as fd:
fd.write(password.encode()) fd.write(password.encode())
def get_target(buildozer): def get_target(buildozer):
return TargetIos(buildozer) return TargetIos(buildozer)

View file

@ -6,25 +6,10 @@ import sys
if sys.platform != 'darwin': if sys.platform != 'darwin':
raise NotImplementedError('This will only work on osx') raise NotImplementedError('This will only work on osx')
#Global variables
#Global imports
import traceback
import os
import io
from pipes import quote
from sys import platform, executable
from buildozer import BuildozerException
from buildozer.target import Target from buildozer.target import Target
from os import environ from os.path import exists, join, abspath, dirname
from os.path import (exists, join, realpath, expanduser,
basename, relpath, abspath, dirname)
from shutil import copyfile
from glob import glob
from subprocess import check_call, check_output from subprocess import check_call, check_output
from buildozer.libs.version import parse
class TargetOSX(Target): class TargetOSX(Target):
targetname = "osx" targetname = "osx"
@ -32,7 +17,7 @@ class TargetOSX(Target):
def ensure_sdk(self): def ensure_sdk(self):
self.buildozer.info('Check if kivy-sdk-packager exists') self.buildozer.info('Check if kivy-sdk-packager exists')
if exists( if exists(
join(self.buildozer.platform_dir, 'kivy-sdk-packager-master')): join(self.buildozer.platform_dir, 'kivy-sdk-packager-master')):
self.buildozer.info( self.buildozer.info(
'kivy-sdk-packager found at ' 'kivy-sdk-packager found at '
'{}'.format(self.buildozer.platform_dir)) '{}'.format(self.buildozer.platform_dir))
@ -122,7 +107,7 @@ class TargetOSX(Target):
author = bc.getdefault('app', 'author', '') author = bc.getdefault('app', 'author', '')
self.buildozer.info('Create {}.app'.format(package_name)) self.buildozer.info('Create {}.app'.format(package_name))
cwd = join(self.buildozer.platform_dir,'kivy-sdk-packager-master', 'osx') cwd = join(self.buildozer.platform_dir, 'kivy-sdk-packager-master', 'osx')
# remove kivy from app_deps # remove kivy from app_deps
app_deps = [a for a in app_deps.split('\n') if not a.startswith('#') and a not in ['kivy', '']] app_deps = [a for a in app_deps.split('\n') if not a.startswith('#') and a not in ['kivy', '']]
@ -139,7 +124,6 @@ class TargetOSX(Target):
'--bundlename={}'.format(title), '--bundlename={}'.format(title),
'--bundleid={}'.format(domain), '--bundleid={}'.format(domain),
'--bundleversion={}'.format(version), '--bundleversion={}'.format(version),
#'--deps={}'.format(','.join(app_deps)),
'--displayname={}'.format(title) '--displayname={}'.format(title)
] ]
if icon: if icon:
@ -174,7 +158,7 @@ class TargetOSX(Target):
# #
self.buildozer.environ.update({ self.buildozer.environ.update({
'PACKAGES_PATH': self.buildozer.global_packages_dir, 'PACKAGES_PATH': self.buildozer.global_packages_dir,
}) })
def get_custom_commands(self): def get_custom_commands(self):
result = [] result = []

12
tox.ini
View file

@ -21,22 +21,12 @@ commands = flake8 buildozer/ tests/
ignore = ignore =
E121, # continuation line under-indented for hanging indent E121, # continuation line under-indented for hanging indent
E122, # continuation line missing indentation or outdented E122, # continuation line missing indentation or outdented
E123, # closing bracket does not match indentation of opening bracket's line
E125, # continuation line with same indent as next logical line
E126, # continuation line over-indented for hanging indent E126, # continuation line over-indented for hanging indent
E127, # continuation line over-indented for visual indent E127, # continuation line over-indented for visual indent
E128, # continuation line under-indented for visual indent E128, # continuation line under-indented for visual indent
E131, # continuation line unaligned for hanging indent E131, # continuation line unaligned for hanging indent
E231, # missing whitespace after ','
E265, # block comment should start with '# '
E302, # expected 2 blank lines, found 1
E305, # expected 2 blank lines after class or function definition, found 1
E402, # module level import not at top of file E402, # module level import not at top of file
E501, # line too long E501, # line too long
E722, # do not use bare 'except' E722, # do not use bare 'except'
E731, # do not assign a lambda expression, use a def
F401, # imported but unused
F821, # undefined name
W503, # line break before binary operator W503, # line break before binary operator
W504, # line break after binary operator W504 # line break after binary operator
W605 # invalid escape sequence