Skip to content

Commit 53d3c43

Browse files
author
Cruz Monrreal
authored
Merge pull request #6781 from theotherjimmy/refactor-notify
tools: Refactor notification API
2 parents 5038135 + 81f969e commit 53d3c43

File tree

19 files changed

+499
-448
lines changed

19 files changed

+499
-448
lines changed

tools/build.py

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,10 @@
3939
from tools.build_api import mcu_toolchain_matrix
4040
from tools.build_api import print_build_results
4141
from tools.settings import CPPCHECK_CMD, CPPCHECK_MSG_FORMAT
42-
from utils import argparse_filestring_type, args_error
4342
from tools.settings import CPPCHECK_CMD, CPPCHECK_MSG_FORMAT, CLI_COLOR_MAP
44-
from utils import argparse_filestring_type, argparse_dir_not_parent
43+
from tools.notifier.term import TerminalNotifier
44+
from tools.utils import argparse_filestring_type, args_error
45+
from tools.utils import argparse_filestring_type, argparse_dir_not_parent
4546

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

148-
if options.color:
149-
# This import happens late to prevent initializing colorization when we don't need it
150-
import colorize
151-
if options.verbose:
152-
notify = mbedToolchain.print_notify_verbose
153-
else:
154-
notify = mbedToolchain.print_notify
155-
notify = colorize.print_in_color_notifier(CLI_COLOR_MAP, notify)
156-
else:
157-
notify = None
158149

159150
# Get libraries list
160151
libraries = []
@@ -190,6 +181,7 @@
190181
skipped.append(tt_id)
191182
else:
192183
try:
184+
notify = TerminalNotifer(options.verbose, options.silent)
193185
mcu = TARGET_MAP[target]
194186
profile = extract_profile(parser, options, toolchain)
195187
if options.source_dir:

tools/build_api.py

Lines changed: 32 additions & 79 deletions
Large diffs are not rendered by default.

tools/colorize.py

Lines changed: 0 additions & 80 deletions
This file was deleted.

tools/export/__init__.py

Lines changed: 34 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,24 @@ def generate_project_files(resources, export_path, target, name, toolchain, ide,
163163
return files, exporter
164164

165165

166-
def zip_export(file_name, prefix, resources, project_files, inc_repos):
166+
def _inner_zip_export(resources, inc_repos):
167+
for loc, res in resources.items():
168+
to_zip = (
169+
res.headers + res.s_sources + res.c_sources +\
170+
res.cpp_sources + res.libraries + res.hex_files + \
171+
[res.linker_script] + res.bin_files + res.objects + \
172+
res.json_files + res.lib_refs + res.lib_builds)
173+
if inc_repos:
174+
for directory in res.repo_dirs:
175+
for root, _, files in walk(directory):
176+
for repo_file in files:
177+
source = join(root, repo_file)
178+
to_zip.append(source)
179+
res.file_basepath[source] = res.base_path
180+
to_zip += res.repo_files
181+
yield loc, to_zip
182+
183+
def zip_export(file_name, prefix, resources, project_files, inc_repos, notify):
167184
"""Create a zip file from an exported project.
168185
169186
Positional Parameters:
@@ -173,29 +190,25 @@ def zip_export(file_name, prefix, resources, project_files, inc_repos):
173190
project_files - a list of extra files to be added to the root of the prefix
174191
directory
175192
"""
193+
to_zip_list = list(_inner_zip_export(resources, inc_repos))
194+
total_files = sum(len(to_zip) for _, to_zip in to_zip_list)
195+
total_files += len(project_files)
196+
zipped = 0
176197
with zipfile.ZipFile(file_name, "w") as zip_file:
177198
for prj_file in project_files:
178199
zip_file.write(prj_file, join(prefix, basename(prj_file)))
179-
for loc, res in resources.items():
180-
to_zip = (
181-
res.headers + res.s_sources + res.c_sources +\
182-
res.cpp_sources + res.libraries + res.hex_files + \
183-
[res.linker_script] + res.bin_files + res.objects + \
184-
res.json_files + res.lib_refs + res.lib_builds)
185-
if inc_repos:
186-
for directory in res.repo_dirs:
187-
for root, _, files in walk(directory):
188-
for repo_file in files:
189-
source = join(root, repo_file)
190-
to_zip.append(source)
191-
res.file_basepath[source] = res.base_path
192-
to_zip += res.repo_files
200+
for loc, to_zip in to_zip_list:
201+
res = resources[loc]
193202
for source in to_zip:
194203
if source:
195204
zip_file.write(
196205
source,
197206
join(prefix, loc,
198207
relpath(source, res.file_basepath[source])))
208+
notify.progress("Zipping", source,
209+
100 * (zipped / total_files))
210+
zipped += 1
211+
for lib, res in resources.items():
199212
for source in res.lib_builds:
200213
target_dir, _ = splitext(source)
201214
dest = join(prefix, loc,
@@ -206,10 +219,9 @@ def zip_export(file_name, prefix, resources, project_files, inc_repos):
206219

207220

208221
def export_project(src_paths, export_path, target, ide, libraries_paths=None,
209-
linker_script=None, notify=None, verbose=False, name=None,
210-
inc_dirs=None, jobs=1, silent=False, extra_verbose=False,
211-
config=None, macros=None, zip_proj=None, inc_repos=False,
212-
build_profile=None, app_config=None):
222+
linker_script=None, notify=None, name=None, inc_dirs=None,
223+
jobs=1, config=None, macros=None, zip_proj=None,
224+
inc_repos=False, build_profile=None, app_config=None):
213225
"""Generates a project file and creates a zip archive if specified
214226
215227
Positional Arguments:
@@ -223,13 +235,9 @@ def export_project(src_paths, export_path, target, ide, libraries_paths=None,
223235
linker_script - path to the linker script for the specified target
224236
notify - function is passed all events, and expected to handle notification
225237
of the user, emit the events to a log, etc.
226-
verbose - assigns the notify function to toolchains print_notify_verbose
227238
name - project name
228239
inc_dirs - additional include directories
229240
jobs - number of threads
230-
silent - silent build - no output
231-
extra_verbose - assigns the notify function to toolchains
232-
print_notify_verbose
233241
config - toolchain's config object
234242
macros - User-defined macros
235243
zip_proj - string name of the zip archive you wish to creat (exclude arg
@@ -260,8 +268,7 @@ def export_project(src_paths, export_path, target, ide, libraries_paths=None,
260268
# Pass all params to the unified prepare_resources()
261269
toolchain = prepare_toolchain(
262270
paths, "", target, toolchain_name, macros=macros, jobs=jobs,
263-
notify=notify, silent=silent, verbose=verbose,
264-
extra_verbose=extra_verbose, config=config, build_profile=build_profile,
271+
notify=notify, config=config, build_profile=build_profile,
265272
app_config=app_config)
266273

267274
toolchain.RESPONSE_FILES = False
@@ -300,10 +307,10 @@ def export_project(src_paths, export_path, target, ide, libraries_paths=None,
300307
resource.add(res)
301308
if isinstance(zip_proj, basestring):
302309
zip_export(join(export_path, zip_proj), name, resource_dict,
303-
files + list(exporter.static_files), inc_repos)
310+
files + list(exporter.static_files), inc_repos, notify)
304311
else:
305312
zip_export(zip_proj, name, resource_dict,
306-
files + list(exporter.static_files), inc_repos)
313+
files + list(exporter.static_files), inc_repos, notify)
307314
else:
308315
for static_file in exporter.static_files:
309316
if not exists(join(export_path, basename(static_file))):

tools/make.py

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
from tools.options import get_default_options_parser
4646
from tools.options import extract_profile
4747
from tools.options import extract_mcus
48+
from tools.notifier.term import TerminalNotifier
4849
from tools.build_api import build_project
4950
from tools.build_api import mcu_toolchain_matrix
5051
from tools.build_api import mcu_toolchain_list
@@ -54,7 +55,6 @@
5455
from utils import argparse_many
5556
from utils import argparse_dir_not_parent
5657
from tools.toolchains import mbedToolchain, TOOLCHAIN_CLASSES, TOOLCHAIN_PATHS
57-
from tools.settings import CLI_COLOR_MAP
5858

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

234234

235-
if options.color:
236-
# This import happens late to prevent initializing colorization when we don't need it
237-
import colorize
238-
if options.verbose:
239-
notify = mbedToolchain.print_notify_verbose
240-
else:
241-
notify = mbedToolchain.print_notify
242-
notify = colorize.print_in_color_notifier(CLI_COLOR_MAP, notify)
243-
else:
244-
notify = None
235+
notify = TerminalNotifier(options.verbose, options.silent, options.color)
245236

246237
if not TOOLCHAIN_CLASSES[toolchain].check_executable():
247238
search_path = TOOLCHAIN_PATHS[toolchain] or "No path set"
@@ -283,10 +274,8 @@
283274
set(test.dependencies),
284275
linker_script=options.linker_script,
285276
clean=options.clean,
286-
verbose=options.verbose,
287277
notify=notify,
288278
report=build_data_blob,
289-
silent=options.silent,
290279
macros=options.macros,
291280
jobs=options.jobs,
292281
name=options.artifact_name,

tools/notifier/__init__.py

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
# mbed SDK
2+
# Copyright (c) 2011-2013 ARM Limited
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
16+
from __future__ import print_function, division, absolute_import
17+
18+
from abc import ABCMeta, abstractmethod
19+
20+
21+
class Notifier(object):
22+
"""
23+
Notifiers send build system events to a front end or may implement a front
24+
end themselves, displaying warnings and errors for a user.
25+
26+
This is different from a logger in a few ways:
27+
* The structure of the events are defined by this interface.
28+
* A "progress" level is included allowing signaling completion status to
29+
users.
30+
* It's tailored to providing events from a build system.
31+
32+
The structure of a message is a dict with a 'type' key. The type key
33+
determines the remaining keys as follows:
34+
type | description and remaining keys
35+
---------- | ------------------------------
36+
info | A simple message. The 'message' key contains the message
37+
debug | Another simple message; this one is less useful when compiles
38+
| are working. Again, the 'message' key contains the message
39+
progress | A progress indicator, which may include progress as a
40+
| percentage. The action key includes what action was taken to
41+
| make this progress, the file key what file was used to make
42+
| this progress, and the percent key, when present, indicates
43+
| how far along the build is.
44+
tool_error | When a compile fails, this contains the entire output of the
45+
| compiler.
46+
var | Provides a key, in the 'key' key, and a value, in the 'value'
47+
| key, for use in a UI. At the time of writing it's used to
48+
| communicate the binary location to the online IDE.
49+
"""
50+
51+
__metaclass__ = ABCMeta
52+
53+
@abstractmethod
54+
def notify(self, event):
55+
"""
56+
Send the user a notification specified in the event.
57+
"""
58+
raise NotImplemented
59+
60+
def info(self, message):
61+
"""
62+
Send the user a simple message.
63+
"""
64+
self.notify({'type': 'info', 'message': message})
65+
66+
def debug(self, message):
67+
"""
68+
Send a debug message to the user.
69+
"""
70+
if isinstance(message, list):
71+
message = ' '.join(message)
72+
self.notify({'type': 'debug', 'message': message})
73+
74+
def cc_info(self, info=None):
75+
if info is not None:
76+
info['type'] = 'cc'
77+
self.notify(info)
78+
79+
def cc_verbose(self, message, file=""):
80+
self.notify({
81+
'type': 'cc',
82+
'severity': 'verbose',
83+
'file': file,
84+
'message': message
85+
})
86+
87+
def progress(self, action, file, percent=None):
88+
"""
89+
Indicate compilation progress to a user.
90+
"""
91+
msg = {'type': 'progress', 'action': action, 'file': file}
92+
if percent:
93+
msg['percent'] = percent
94+
self.notify(msg)
95+
96+
def tool_error(self, message):
97+
"""
98+
Communicate a full fatal error to a user.
99+
"""
100+
self.notify({'type': 'tool_error', 'message': message})
101+
102+
def var(self, key, value):
103+
"""
104+
Update a UI with a key, value pair
105+
"""
106+
self.notify({'type': 'var', 'key': key, 'val': value})

0 commit comments

Comments
 (0)