Skip to content

Commit

Permalink
Merge pull request #6781 from theotherjimmy/refactor-notify
Browse files Browse the repository at this point in the history
tools: Refactor notification API
  • Loading branch information
Cruz Monrreal committed May 7, 2018
2 parents 5038135 + 81f969e commit 53d3c43
Show file tree
Hide file tree
Showing 19 changed files with 499 additions and 448 deletions.
16 changes: 4 additions & 12 deletions tools/build.py
Expand Up @@ -39,9 +39,10 @@
from tools.build_api import mcu_toolchain_matrix
from tools.build_api import print_build_results
from tools.settings import CPPCHECK_CMD, CPPCHECK_MSG_FORMAT
from utils import argparse_filestring_type, args_error
from tools.settings import CPPCHECK_CMD, CPPCHECK_MSG_FORMAT, CLI_COLOR_MAP
from utils import argparse_filestring_type, argparse_dir_not_parent
from tools.notifier.term import TerminalNotifier
from tools.utils import argparse_filestring_type, args_error
from tools.utils import argparse_filestring_type, argparse_dir_not_parent

if __name__ == '__main__':
start = time()
Expand Down Expand Up @@ -145,16 +146,6 @@
if options.source_dir and not options.build_dir:
args_error(parser, "argument --build is required by argument --source")

if options.color:
# This import happens late to prevent initializing colorization when we don't need it
import colorize
if options.verbose:
notify = mbedToolchain.print_notify_verbose
else:
notify = mbedToolchain.print_notify
notify = colorize.print_in_color_notifier(CLI_COLOR_MAP, notify)
else:
notify = None

# Get libraries list
libraries = []
Expand Down Expand Up @@ -190,6 +181,7 @@
skipped.append(tt_id)
else:
try:
notify = TerminalNotifer(options.verbose, options.silent)
mcu = TARGET_MAP[target]
profile = extract_profile(parser, options, toolchain)
if options.source_dir:
Expand Down
111 changes: 32 additions & 79 deletions tools/build_api.py

Large diffs are not rendered by default.

80 changes: 0 additions & 80 deletions tools/colorize.py

This file was deleted.

61 changes: 34 additions & 27 deletions tools/export/__init__.py
Expand Up @@ -163,7 +163,24 @@ def generate_project_files(resources, export_path, target, name, toolchain, ide,
return files, exporter


def zip_export(file_name, prefix, resources, project_files, inc_repos):
def _inner_zip_export(resources, inc_repos):
for loc, res in resources.items():
to_zip = (
res.headers + res.s_sources + res.c_sources +\
res.cpp_sources + res.libraries + res.hex_files + \
[res.linker_script] + res.bin_files + res.objects + \
res.json_files + res.lib_refs + res.lib_builds)
if inc_repos:
for directory in res.repo_dirs:
for root, _, files in walk(directory):
for repo_file in files:
source = join(root, repo_file)
to_zip.append(source)
res.file_basepath[source] = res.base_path
to_zip += res.repo_files
yield loc, to_zip

def zip_export(file_name, prefix, resources, project_files, inc_repos, notify):
"""Create a zip file from an exported project.
Positional Parameters:
Expand All @@ -173,29 +190,25 @@ def zip_export(file_name, prefix, resources, project_files, inc_repos):
project_files - a list of extra files to be added to the root of the prefix
directory
"""
to_zip_list = list(_inner_zip_export(resources, inc_repos))
total_files = sum(len(to_zip) for _, to_zip in to_zip_list)
total_files += len(project_files)
zipped = 0
with zipfile.ZipFile(file_name, "w") as zip_file:
for prj_file in project_files:
zip_file.write(prj_file, join(prefix, basename(prj_file)))
for loc, res in resources.items():
to_zip = (
res.headers + res.s_sources + res.c_sources +\
res.cpp_sources + res.libraries + res.hex_files + \
[res.linker_script] + res.bin_files + res.objects + \
res.json_files + res.lib_refs + res.lib_builds)
if inc_repos:
for directory in res.repo_dirs:
for root, _, files in walk(directory):
for repo_file in files:
source = join(root, repo_file)
to_zip.append(source)
res.file_basepath[source] = res.base_path
to_zip += res.repo_files
for loc, to_zip in to_zip_list:
res = resources[loc]
for source in to_zip:
if source:
zip_file.write(
source,
join(prefix, loc,
relpath(source, res.file_basepath[source])))
notify.progress("Zipping", source,
100 * (zipped / total_files))
zipped += 1
for lib, res in resources.items():
for source in res.lib_builds:
target_dir, _ = splitext(source)
dest = join(prefix, loc,
Expand All @@ -206,10 +219,9 @@ def zip_export(file_name, prefix, resources, project_files, inc_repos):


def export_project(src_paths, export_path, target, ide, libraries_paths=None,
linker_script=None, notify=None, verbose=False, name=None,
inc_dirs=None, jobs=1, silent=False, extra_verbose=False,
config=None, macros=None, zip_proj=None, inc_repos=False,
build_profile=None, app_config=None):
linker_script=None, notify=None, name=None, inc_dirs=None,
jobs=1, config=None, macros=None, zip_proj=None,
inc_repos=False, build_profile=None, app_config=None):
"""Generates a project file and creates a zip archive if specified
Positional Arguments:
Expand All @@ -223,13 +235,9 @@ def export_project(src_paths, export_path, target, ide, libraries_paths=None,
linker_script - path to the linker script for the specified target
notify - function is passed all events, and expected to handle notification
of the user, emit the events to a log, etc.
verbose - assigns the notify function to toolchains print_notify_verbose
name - project name
inc_dirs - additional include directories
jobs - number of threads
silent - silent build - no output
extra_verbose - assigns the notify function to toolchains
print_notify_verbose
config - toolchain's config object
macros - User-defined macros
zip_proj - string name of the zip archive you wish to creat (exclude arg
Expand Down Expand Up @@ -260,8 +268,7 @@ def export_project(src_paths, export_path, target, ide, libraries_paths=None,
# Pass all params to the unified prepare_resources()
toolchain = prepare_toolchain(
paths, "", target, toolchain_name, macros=macros, jobs=jobs,
notify=notify, silent=silent, verbose=verbose,
extra_verbose=extra_verbose, config=config, build_profile=build_profile,
notify=notify, config=config, build_profile=build_profile,
app_config=app_config)

toolchain.RESPONSE_FILES = False
Expand Down Expand Up @@ -300,10 +307,10 @@ def export_project(src_paths, export_path, target, ide, libraries_paths=None,
resource.add(res)
if isinstance(zip_proj, basestring):
zip_export(join(export_path, zip_proj), name, resource_dict,
files + list(exporter.static_files), inc_repos)
files + list(exporter.static_files), inc_repos, notify)
else:
zip_export(zip_proj, name, resource_dict,
files + list(exporter.static_files), inc_repos)
files + list(exporter.static_files), inc_repos, notify)
else:
for static_file in exporter.static_files:
if not exists(join(export_path, basename(static_file))):
Expand Down
15 changes: 2 additions & 13 deletions tools/make.py
Expand Up @@ -45,6 +45,7 @@
from tools.options import get_default_options_parser
from tools.options import extract_profile
from tools.options import extract_mcus
from tools.notifier.term import TerminalNotifier
from tools.build_api import build_project
from tools.build_api import mcu_toolchain_matrix
from tools.build_api import mcu_toolchain_list
Expand All @@ -54,7 +55,6 @@
from utils import argparse_many
from utils import argparse_dir_not_parent
from tools.toolchains import mbedToolchain, TOOLCHAIN_CLASSES, TOOLCHAIN_PATHS
from tools.settings import CLI_COLOR_MAP

if __name__ == '__main__':
# Parse Options
Expand Down Expand Up @@ -232,16 +232,7 @@
args_error(parser, "argument --build is required when argument --source is provided")


if options.color:
# This import happens late to prevent initializing colorization when we don't need it
import colorize
if options.verbose:
notify = mbedToolchain.print_notify_verbose
else:
notify = mbedToolchain.print_notify
notify = colorize.print_in_color_notifier(CLI_COLOR_MAP, notify)
else:
notify = None
notify = TerminalNotifier(options.verbose, options.silent, options.color)

if not TOOLCHAIN_CLASSES[toolchain].check_executable():
search_path = TOOLCHAIN_PATHS[toolchain] or "No path set"
Expand Down Expand Up @@ -283,10 +274,8 @@
set(test.dependencies),
linker_script=options.linker_script,
clean=options.clean,
verbose=options.verbose,
notify=notify,
report=build_data_blob,
silent=options.silent,
macros=options.macros,
jobs=options.jobs,
name=options.artifact_name,
Expand Down
106 changes: 106 additions & 0 deletions tools/notifier/__init__.py
@@ -0,0 +1,106 @@
# mbed SDK
# Copyright (c) 2011-2013 ARM Limited
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from __future__ import print_function, division, absolute_import

from abc import ABCMeta, abstractmethod


class Notifier(object):
"""
Notifiers send build system events to a front end or may implement a front
end themselves, displaying warnings and errors for a user.
This is different from a logger in a few ways:
* The structure of the events are defined by this interface.
* A "progress" level is included allowing signaling completion status to
users.
* It's tailored to providing events from a build system.
The structure of a message is a dict with a 'type' key. The type key
determines the remaining keys as follows:
type | description and remaining keys
---------- | ------------------------------
info | A simple message. The 'message' key contains the message
debug | Another simple message; this one is less useful when compiles
| are working. Again, the 'message' key contains the message
progress | A progress indicator, which may include progress as a
| percentage. The action key includes what action was taken to
| make this progress, the file key what file was used to make
| this progress, and the percent key, when present, indicates
| how far along the build is.
tool_error | When a compile fails, this contains the entire output of the
| compiler.
var | Provides a key, in the 'key' key, and a value, in the 'value'
| key, for use in a UI. At the time of writing it's used to
| communicate the binary location to the online IDE.
"""

__metaclass__ = ABCMeta

@abstractmethod
def notify(self, event):
"""
Send the user a notification specified in the event.
"""
raise NotImplemented

def info(self, message):
"""
Send the user a simple message.
"""
self.notify({'type': 'info', 'message': message})

def debug(self, message):
"""
Send a debug message to the user.
"""
if isinstance(message, list):
message = ' '.join(message)
self.notify({'type': 'debug', 'message': message})

def cc_info(self, info=None):
if info is not None:
info['type'] = 'cc'
self.notify(info)

def cc_verbose(self, message, file=""):
self.notify({
'type': 'cc',
'severity': 'verbose',
'file': file,
'message': message
})

def progress(self, action, file, percent=None):
"""
Indicate compilation progress to a user.
"""
msg = {'type': 'progress', 'action': action, 'file': file}
if percent:
msg['percent'] = percent
self.notify(msg)

def tool_error(self, message):
"""
Communicate a full fatal error to a user.
"""
self.notify({'type': 'tool_error', 'message': message})

def var(self, key, value):
"""
Update a UI with a key, value pair
"""
self.notify({'type': 'var', 'key': key, 'val': value})

0 comments on commit 53d3c43

Please sign in to comment.