Skip to content

Commit

Permalink
Factor out logging code from Buildozer class (#1632)
Browse files Browse the repository at this point in the history
* Remove No-Op code

* Factor out logging code from Buildozer class

* Fixed missed calls

Result of self review

* Update logging references in remotre.py

* Update references to logger in main() defs.
  • Loading branch information
Julian-O authored Jul 20, 2023
1 parent 1532478 commit 9b50902
Show file tree
Hide file tree
Showing 12 changed files with 366 additions and 309 deletions.
186 changes: 59 additions & 127 deletions buildozer/__init__.py

Large diffs are not rendered by default.

87 changes: 87 additions & 0 deletions buildozer/logger.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
"""
Logger
======
Logger implementation used by Buildozer.
Supports colored output, where available.
"""

from os import environ
from pprint import pformat
import sys

try:
# if installed, it can give color to Windows as well
import colorama

colorama.init()
except ImportError:
colorama = None

# set color codes
if colorama:
RESET_SEQ = colorama.Fore.RESET + colorama.Style.RESET_ALL
COLOR_SEQ = lambda x: x # noqa: E731
BOLD_SEQ = ""
if sys.platform == "win32":
BLACK = colorama.Fore.BLACK + colorama.Style.DIM
else:
BLACK = colorama.Fore.BLACK + colorama.Style.BRIGHT
RED = colorama.Fore.RED
BLUE = colorama.Fore.CYAN
USE_COLOR = "NO_COLOR" not in environ
elif sys.platform != "win32":
RESET_SEQ = "\033[0m"
COLOR_SEQ = lambda x: "\033[1;{}m".format(30 + x) # noqa: E731
BOLD_SEQ = "\033[1m"
BLACK = 0
RED = 1
BLUE = 4
USE_COLOR = "NO_COLOR" not in environ
else:
RESET_SEQ = ""
COLOR_SEQ = ""
BOLD_SEQ = ""
RED = BLUE = BLACK = 0
USE_COLOR = False


class Logger:
ERROR = 0
INFO = 1
DEBUG = 2

LOG_LEVELS_C = (RED, BLUE, BLACK) # Map levels to colors
LOG_LEVELS_T = "EID" # error, info, debug

log_level = ERROR

def log(self, level, msg):
if level > self.log_level:
return
if USE_COLOR:
color = COLOR_SEQ(Logger.LOG_LEVELS_C[level])
print("".join((RESET_SEQ, color, "# ", msg, RESET_SEQ)))
else:
print("{} {}".format(Logger.LOG_LEVELS_T[level], msg))

def debug(self, msg):
self.log(self.DEBUG, msg)

def info(self, msg):
self.log(self.INFO, msg)

def error(self, msg):
self.log(self.ERROR, msg)

def log_env(self, level, env):
"""dump env into logger in readable format"""
self.log(level, "ENVIRONMENT:")
for k, v in env.items():
self.log(level, " {} = {}".format(k, pformat(v)))

@classmethod
def set_level(cls, level):
"""set minimum threshold for log messages"""
cls.log_level = level
3 changes: 2 additions & 1 deletion buildozer/scripts/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

import sys
from buildozer import Buildozer, BuildozerCommandException, BuildozerException
from buildozer.logger import Logger


def main():
Expand All @@ -16,7 +17,7 @@ def main():
# the command failed.
sys.exit(1)
except BuildozerException as error:
Buildozer().error('%s' % error)
Logger().error('%s' % error)
sys.exit(1)


Expand Down
39 changes: 20 additions & 19 deletions buildozer/scripts/remote.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import sys
from buildozer import (
Buildozer, BuildozerCommandException, BuildozerException, __version__)
from buildozer.logger import Logger
from sys import stdout, stdin, exit
from select import select
from os.path import join, expanduser, realpath, exists, splitext
Expand All @@ -41,7 +42,7 @@ def run_command(self, args):
arg = args.pop(0)

if arg in ('-v', '--verbose'):
self.log_level = 2
self.logger.log_level = 2

elif arg in ('-p', '--profile'):
self.config_profile = args.pop(0)
Expand All @@ -63,7 +64,7 @@ def run_command(self, args):
remote_name = args[0]
remote_section = 'remote:{}'.format(remote_name)
if not self.config.has_section(remote_section):
self.error('Unknown remote "{}", must be configured first.'.format(
self.logger.error('Unknown remote "{}", must be configured first.'.format(
remote_name))
return

Expand All @@ -78,21 +79,21 @@ def run_command(self, args):
self.remote_identity = self.config.get(
remote_section, 'identity', '')
if not remote_host:
self.error('Missing "host = " for {}'.format(remote_section))
self.logger.error('Missing "host = " for {}'.format(remote_section))
return
if not remote_user:
self.error('Missing "user = " for {}'.format(remote_section))
self.logger.error('Missing "user = " for {}'.format(remote_section))
return
if not remote_build_dir:
self.error('Missing "build_directory = " for {}'.format(remote_section))
self.logger.error('Missing "build_directory = " for {}'.format(remote_section))
return

# fake the target
self.targetname = 'remote'
self.check_build_layout()

# prepare our source code
self.info('Prepare source code to sync')
self.logger.info('Prepare source code to sync')
self._copy_application_sources()
self._ssh_connect()
try:
Expand All @@ -104,7 +105,7 @@ def run_command(self, args):
self._ssh_close()

def _ssh_connect(self):
self.info('Connecting to {}'.format(self.remote_host))
self.logger.info('Connecting to {}'.format(self.remote_host))
self._ssh_client = client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.load_system_host_keys()
Expand All @@ -116,7 +117,7 @@ def _ssh_connect(self):
self._sftp_client = client.open_sftp()

def _ssh_close(self):
self.debug('Closing remote connection')
self.logger.debug('Closing remote connection')
self._sftp_client.close()
self._ssh_client.close()

Expand All @@ -125,16 +126,16 @@ def _ensure_buildozer(self):
root_dir = s.normalize('.')
self.remote_build_dir = join(root_dir, self.remote_build_dir,
self.package_full_name)
self.debug('Remote build directory: {}'.format(self.remote_build_dir))
self.logger.debug('Remote build directory: {}'.format(self.remote_build_dir))
self._ssh_mkdir(self.remote_build_dir)
self._ssh_sync(__path__[0]) # noqa: F821 undefined name

def _sync_application_sources(self):
self.info('Synchronize application sources')
self.logger.info('Synchronize application sources')
self._ssh_sync(self.app_dir)

# create custom buildozer.spec
self.info('Create custom buildozer.spec')
self.logger.info('Create custom buildozer.spec')
config = ConfigParser()
config.read('buildozer.spec')
config.set('app', 'source.dir', 'app')
Expand All @@ -145,34 +146,34 @@ def _sync_application_sources(self):
fd.close()

def _do_remote_commands(self, args):
self.info('Execute remote buildozer')
self.logger.info('Execute remote buildozer')
cmd = (
'source ~/.profile;'
'cd {0};'
'env PYTHONPATH={0}:$PYTHONPATH '
'python -c "import buildozer, sys;'
'buildozer.Buildozer().run_command(sys.argv[1:])" {1} {2} 2>&1').format(
self.remote_build_dir,
'--verbose' if self.log_level == 2 else '',
'--verbose' if self.logger.log_level == 2 else '',
' '.join(args),
)
self._ssh_command(cmd)

def _ssh_mkdir(self, *args):
directory = join(*args)
self.debug('Create remote directory {}'.format(directory))
self.logger.debug('Create remote directory {}'.format(directory))
try:
self._sftp_client.mkdir(directory)
except IOError:
# already created?
try:
self._sftp_client.stat(directory)
except IOError:
self.error('Unable to create remote directory {}'.format(directory))
self.logger.error('Unable to create remote directory {}'.format(directory))
raise

def _ssh_sync(self, directory, mode='put'):
self.debug('Syncing {} directory'.format(directory))
self.logger.debug('Syncing {} directory'.format(directory))
directory = realpath(expanduser(directory))
base_strip = directory.rfind('/')
if mode == 'get':
Expand All @@ -191,11 +192,11 @@ def _ssh_sync(self, directory, mode='put'):
continue
local_file = join(root, fn)
remote_file = join(self.remote_build_dir, root[base_strip + 1:], fn)
self.debug('Sync {} -> {}'.format(local_file, remote_file))
self.logger.debug('Sync {} -> {}'.format(local_file, remote_file))
self._sftp_client.put(local_file, remote_file)

def _ssh_command(self, command):
self.debug('Execute remote command {}'.format(command))
self.logger.debug('Execute remote command {}'.format(command))
transport = self._ssh_client.get_transport()
channel = transport.open_session()
try:
Expand Down Expand Up @@ -271,7 +272,7 @@ def main():
except BuildozerCommandException:
pass
except BuildozerException as error:
Buildozer().error('%s' % error)
Logger().error('%s' % error)


if __name__ == '__main__':
Expand Down
17 changes: 10 additions & 7 deletions buildozer/target.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
import os
from os.path import join

from buildozer.logger import Logger


def no_config(f):
f.__no_config = True
Expand All @@ -14,16 +16,17 @@ def __init__(self, buildozer):
self.build_mode = 'debug'
self.artifact_format = 'apk'
self.platform_update = False
self.logger = Logger()

def check_requirements(self):
pass

def check_configuration_tokens(self, errors=None):
if errors:
self.buildozer.info('Check target configuration tokens')
self.buildozer.error(
self.logger.info('Check target configuration tokens')
self.logger.error(
'{0} error(s) found in the buildozer.spec'.format(
len(errors)))
len(errors)))
for error in errors:
print(error)
exit(1)
Expand All @@ -49,7 +52,7 @@ def get_available_packages(self):

def run_commands(self, args):
if not args:
self.buildozer.error('Missing target command')
self.logger.error('Missing target command')
self.buildozer.usage()
exit(1)

Expand All @@ -68,7 +71,7 @@ def run_commands(self, args):
last_command.append(arg)
else:
if not last_command:
self.buildozer.error('Argument passed without a command')
self.logger.error('Argument passed without a command')
self.buildozer.usage()
exit(1)
last_command.append(arg)
Expand All @@ -80,7 +83,7 @@ def run_commands(self, args):
for item in result:
command, args = item[0], item[1:]
if not hasattr(self, 'cmd_{0}'.format(command)):
self.buildozer.error('Unknown command {0}'.format(command))
self.logger.error('Unknown command {0}'.format(command))
exit(1)

func = getattr(self, 'cmd_{0}'.format(command))
Expand All @@ -106,7 +109,7 @@ def cmd_debug(self, *args):
self.buildozer.build()

def cmd_release(self, *args):
error = self.buildozer.error
error = self.logger.error
self.buildozer.prepare_for_build()
if self.buildozer.config.get("app", "package.domain") == "org.test":
error("")
Expand Down
Loading

0 comments on commit 9b50902

Please sign in to comment.