Merge lp:~milo/linaro-image-tools/bug1059579 into lp:linaro-image-tools/11.11
- bug1059579
- Merge into trunk
Status: | Merged | ||||
---|---|---|---|---|---|
Merged at revision: | 581 | ||||
Proposed branch: | lp:~milo/linaro-image-tools/bug1059579 | ||||
Merge into: | lp:linaro-image-tools/11.11 | ||||
Diff against target: |
506 lines (+81/-104) 10 files modified
linaro-hwpack-convert (+4/-22) linaro-hwpack-create (+8/-18) linaro-hwpack-replace (+3/-17) linaro-media-create (+17/-22) linaro_image_tools/hwpack/__init__.py (+2/-1) linaro_image_tools/hwpack/hwpack_convert.py (+1/-1) linaro_image_tools/media_create/__init__.py (+1/-0) linaro_image_tools/media_create/boards.py (+2/-12) linaro_image_tools/media_create/partitions.py (+2/-2) linaro_image_tools/utils.py (+41/-9) |
||||
To merge this branch: | bzr merge lp:~milo/linaro-image-tools/bug1059579 | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Paul Sokolovsky | Approve | ||
James Tunnicliffe | Pending | ||
linaro-image-tools maintainers | Pending | ||
Review via email:
|
Commit message
Description of the change
The proposed branch cleans up a little bit the logger functionalities in linaro-image-tools.
We now have a single method in utils.py used by all the cli tools when setting up parameters. All the other methods/classes will just call default Python logging with their module name as parameter for logging.
This has a small "drawback": when running the tests output from the logger is not shown anymore, so we do not see the "WARNING" for hwpack format 1.0.
- 572. By Fathi Boudra
-
Add Build-Info support.
- 573. By Ricardo Salveti
-
Added support for Foundation fastmodel.
- 574. By Fathi Boudra
-
Build-Info support:
* manifest file isn't license protected (open).
* create an open BUILD-INFO.txt when no protected files are available. - 575. By Fathi Boudra
-
Skip symlink-ed or invalid debian package file. (LP: #1065826)
- 576. By Fathi Boudra
-
Export the updated manifest when manipulating with linaro-
hwpack- replace. - 577. By Paul Sokolovsky
-
[merge] Allow to override initrd_high and fdt_high uboot params, do so for Snowball.
- 578. By Milo Casagrande
-
Added dtb_files support to hwpack config converter.
- 579. By Milo Casagrande
-
Code refactoring for build() method.
- 580. By Fathi Boudra
-
Workaroun IOError in test case.
- 581. By Milo Casagrande
-
Use common logging infrastructure, add --debug option to linaro-
media-create.
Preview Diff
1 | === modified file 'linaro-hwpack-convert' |
2 | --- linaro-hwpack-convert 2012-07-23 07:07:55 +0000 |
3 | +++ linaro-hwpack-convert 2012-10-04 14:31:36 +0000 |
4 | @@ -22,35 +22,17 @@ |
5 | |
6 | |
7 | import argparse |
8 | -import logging |
9 | import sys |
10 | -import os |
11 | |
12 | from linaro_image_tools.hwpack.hwpack_convert import ( |
13 | HwpackConverter, |
14 | HwpackConverterException, |
15 | check_and_validate_args, |
16 | ) |
17 | +from linaro_image_tools.utils import get_logger |
18 | from linaro_image_tools.__version__ import __version__ |
19 | |
20 | |
21 | -def get_logger(debug=False): |
22 | - ch = logging.StreamHandler() |
23 | - logger = logging.getLogger("linaro_hwpack_converter") |
24 | - |
25 | - if debug: |
26 | - ch.setLevel(logging.DEBUG) |
27 | - formatter = logging.Formatter( |
28 | - "%(asctime)s - %(name)s - %(levelname)s - %(message)s") |
29 | - ch.setFormatter(formatter) |
30 | - logger.setLevel(logging.DEBUG) |
31 | - else: |
32 | - ch.setLevel(logging.INFO) |
33 | - formatter = logging.Formatter("%(message)s") |
34 | - ch.setFormatter(formatter) |
35 | - logger.setLevel(logging.INFO) |
36 | - logger.addHandler(ch) |
37 | - |
38 | if __name__ == '__main__': |
39 | parser = argparse.ArgumentParser(version='%(prog)s ' + __version__) |
40 | parser.add_argument("CONFIG_FILE", |
41 | @@ -64,10 +46,10 @@ |
42 | logger = get_logger(debug=args.debug) |
43 | try: |
44 | input_file, output_file = check_and_validate_args(args) |
45 | - print "Converting '%s' into new YAML format..." % (input_file) |
46 | + logger.info("Converting '%s' into new YAML format..." % input_file) |
47 | converter = HwpackConverter(input_file, output_file) |
48 | except HwpackConverterException, e: |
49 | - sys.stderr.write(str(e) + "\n") |
50 | + logger.error(str(e)) |
51 | sys.exit(1) |
52 | converter.convert() |
53 | - print "File '%s' converted in '%s'." % (input_file, output_file) |
54 | + logger.info("File '%s' converted in '%s'." % (input_file, output_file)) |
55 | |
56 | === modified file 'linaro-hwpack-create' |
57 | --- linaro-hwpack-create 2011-10-03 08:18:45 +0000 |
58 | +++ linaro-hwpack-create 2012-10-04 14:31:36 +0000 |
59 | @@ -21,14 +21,14 @@ |
60 | # USA. |
61 | |
62 | import argparse |
63 | -import logging |
64 | import sys |
65 | |
66 | from linaro_image_tools.hwpack.builder import ( |
67 | ConfigFileMissing, HardwarePackBuilder) |
68 | - |
69 | +from linaro_image_tools.utils import get_logger |
70 | from linaro_image_tools.__version__ import __version__ |
71 | |
72 | + |
73 | if __name__ == '__main__': |
74 | parser = argparse.ArgumentParser(version='%(prog)s ' + __version__) |
75 | parser.add_argument( |
76 | @@ -44,24 +44,14 @@ |
77 | "version than a package that would be otherwise installed. " |
78 | "Can be used more than once.")) |
79 | parser.add_argument("--debug", action="store_true") |
80 | + |
81 | args = parser.parse_args() |
82 | - ch = logging.StreamHandler() |
83 | - ch.setLevel(logging.INFO) |
84 | - formatter = logging.Formatter("%(message)s") |
85 | - ch.setFormatter(formatter) |
86 | - logger = logging.getLogger("linaro_image_tools") |
87 | - logger.setLevel(logging.INFO) |
88 | - logger.addHandler(ch) |
89 | - if args.debug: |
90 | - ch.setLevel(logging.DEBUG) |
91 | - formatter = logging.Formatter( |
92 | - "%(asctime)s - %(name)s - %(levelname)s - %(message)s") |
93 | - ch.setFormatter(formatter) |
94 | - logger.setLevel(logging.DEBUG) |
95 | + logger = get_logger(debug=args.debug) |
96 | + |
97 | try: |
98 | - builder = HardwarePackBuilder( |
99 | - args.CONFIG_FILE, args.VERSION, args.local_debs) |
100 | + builder = HardwarePackBuilder(args.CONFIG_FILE, |
101 | + args.VERSION, args.local_debs) |
102 | except ConfigFileMissing, e: |
103 | - sys.stderr.write(str(e) + "\n") |
104 | + logger.error(str(e)) |
105 | sys.exit(1) |
106 | builder.build() |
107 | |
108 | === modified file 'linaro-hwpack-replace' |
109 | --- linaro-hwpack-replace 2011-10-13 12:11:28 +0000 |
110 | +++ linaro-hwpack-replace 2012-10-04 14:31:36 +0000 |
111 | @@ -26,7 +26,6 @@ |
112 | import sys |
113 | import shutil |
114 | import glob |
115 | -import logging |
116 | import tarfile |
117 | import tempfile |
118 | import argparse |
119 | @@ -35,6 +34,7 @@ |
120 | from debian.deb822 import Packages |
121 | from linaro_image_tools.hwpack.packages import get_packages_file |
122 | from linaro_image_tools.hwpack.packages import FetchedPackage |
123 | +from linaro_image_tools.utils import get_logger |
124 | |
125 | |
126 | parser = argparse.ArgumentParser() |
127 | @@ -53,7 +53,7 @@ |
128 | parser.add_argument("-d", "--debug-output", action="store_true", dest="debug", |
129 | help="Verbose messages are displayed when specified") |
130 | |
131 | -logger = logging.getLogger("linaro-hwpack-replace") |
132 | +logger = None |
133 | |
134 | |
135 | class DummyStanza(object): |
136 | @@ -65,20 +65,6 @@ |
137 | fd.write(get_packages_file([self.info])) |
138 | |
139 | |
140 | -def set_logging_param(args): |
141 | - ch = logging.StreamHandler() |
142 | - ch.setLevel(logging.INFO) |
143 | - formatter = logging.Formatter("%(message)s") |
144 | - ch.setFormatter(formatter) |
145 | - logger.setLevel(logging.INFO) |
146 | - logger.addHandler(ch) |
147 | - if args.debug: |
148 | - ch.setLevel(logging.DEBUG) |
149 | - formatter = logging.Formatter( |
150 | - "%(asctime)s - %(name)s - %(levelname)s - %(message)s") |
151 | - ch.setFormatter(formatter) |
152 | - logger.setLevel(logging.DEBUG) |
153 | - |
154 | |
155 | def get_hwpack_name(old_hwpack, build_number): |
156 | # The build_number would be the job build number. |
157 | @@ -178,7 +164,7 @@ |
158 | "and the debian package information\n") |
159 | return 1 |
160 | |
161 | - set_logging_param(args) |
162 | + logger = get_logger(debug=args.debug) |
163 | |
164 | old_hwpack = args.hwpack_name |
165 | new_deb_file_to_copy = args.deb_pack |
166 | |
167 | === modified file 'linaro-media-create' |
168 | --- linaro-media-create 2012-10-01 12:50:55 +0000 |
169 | +++ linaro-media-create 2012-10-04 14:31:36 +0000 |
170 | @@ -22,7 +22,6 @@ |
171 | import os |
172 | import sys |
173 | import tempfile |
174 | -import logging |
175 | |
176 | from linaro_image_tools import cmd_runner |
177 | |
178 | @@ -57,6 +56,7 @@ |
179 | MissingRequiredOption, |
180 | path_in_tarfile_exists, |
181 | prep_media_path, |
182 | + get_logger, |
183 | ) |
184 | |
185 | # Just define the global variables |
186 | @@ -106,35 +106,29 @@ |
187 | parser = get_args_parser() |
188 | args = parser.parse_args() |
189 | |
190 | - ch = logging.StreamHandler() |
191 | - ch.setLevel(logging.INFO) |
192 | - formatter = logging.Formatter("%(message)s") |
193 | - ch.setFormatter(formatter) |
194 | - logger = logging.getLogger("linaro_image_tools") |
195 | - logger.setLevel(logging.INFO) |
196 | - logger.addHandler(ch) |
197 | + logger = get_logger(debug=args.debug) |
198 | |
199 | try: |
200 | additional_option_checks(args) |
201 | except IncompatibleOptions as e: |
202 | parser.print_help() |
203 | - print >> sys.stderr, "\nError:", e.value |
204 | + logger.error(e.value) |
205 | sys.exit(1) |
206 | |
207 | if args.readhwpack: |
208 | try: |
209 | reader = HwpackReader(args.hwpacks) |
210 | - print reader.get_supported_boards() |
211 | + logger.info(reader.get_supported_boards()) |
212 | sys.exit(0) |
213 | except HwpackReaderError as e: |
214 | - print >> sys.stderr, "\nError:", e.value |
215 | + logger.error(e.value) |
216 | sys.exit(1) |
217 | |
218 | try: |
219 | check_required_args(args) |
220 | except MissingRequiredOption as e: |
221 | parser.print_help() |
222 | - print >> sys.stderr, "\nError:", e.value |
223 | + logger.error(e.value) |
224 | sys.exit(1) |
225 | |
226 | board_config = board_configs[args.dev] |
227 | @@ -147,16 +141,16 @@ |
228 | |
229 | if media.is_block_device: |
230 | if not board_config.supports_writing_to_mmc: |
231 | - print ("The board '%s' does not support the --mmc option. " |
232 | - "Please use --image_file to create an image file for this " |
233 | - "board." % args.dev) |
234 | + logger.error("The board '%s' does not support the --mmc option. " |
235 | + "Please use --image_file to create an image file for " |
236 | + "this board." % args.dev) |
237 | sys.exit(1) |
238 | if not confirm_device_selection_and_ensure_it_is_ready( |
239 | args.device, args.nocheck_mmc): |
240 | sys.exit(1) |
241 | elif not args.should_format_rootfs or not args.should_format_bootfs: |
242 | - print ("Do not use --no-boot or --no-part in conjunction with " |
243 | - "--image_file.") |
244 | + logger.error("Do not use --no-boot or --no-part in conjunction with " |
245 | + "--image_file.") |
246 | sys.exit(1) |
247 | else: |
248 | # All good, move on. |
249 | @@ -170,6 +164,7 @@ |
250 | BIN_DIR = os.path.join(TMP_DIR, 'rootfs') |
251 | os.mkdir(BIN_DIR) |
252 | |
253 | + logger.info('Searching correct rootfs path') |
254 | # Identify the correct path for the rootfs |
255 | filesystem_dir = '' |
256 | if path_in_tarfile_exists('binary/etc', args.binary): |
257 | @@ -212,12 +207,12 @@ |
258 | |
259 | if args.rootfs == 'btrfs': |
260 | if not extract_kpkgs: |
261 | - print ("Desired rootfs type is 'btrfs', trying to auto-install " |
262 | - "the 'btrfs-tools' package") |
263 | + logger.info("Desired rootfs type is 'btrfs', trying to " |
264 | + "auto-install the 'btrfs-tools' package") |
265 | install_packages(ROOTFS_DIR, TMP_DIR, "btrfs-tools") |
266 | else: |
267 | - print ("Desired rootfs type is 'btrfs', please make sure the " |
268 | - "rootfs also includes 'btrfs-tools'") |
269 | + logger.info("Desired rootfs type is 'btrfs', please make sure the " |
270 | + "rootfs also includes 'btrfs-tools'") |
271 | |
272 | boot_partition, root_partition = setup_partitions( |
273 | board_config, media, args.image_size, args.boot_label, args.rfs_label, |
274 | @@ -248,4 +243,4 @@ |
275 | board_config.mmc_device_id, board_config.mmc_part_offset, |
276 | board_config) |
277 | |
278 | - print "Done creating Linaro image on %s" % media.path |
279 | + logger.info("Done creating Linaro image on %s" % media.path) |
280 | |
281 | === modified file 'linaro_image_tools/hwpack/__init__.py' |
282 | --- linaro_image_tools/hwpack/__init__.py 2012-06-13 14:26:02 +0000 |
283 | +++ linaro_image_tools/hwpack/__init__.py 2012-10-04 14:31:36 +0000 |
284 | @@ -20,6 +20,7 @@ |
285 | # USA. |
286 | |
287 | import logging |
288 | +from linaro_image_tools.utils import DEFAULT_LOGGER_NAME |
289 | |
290 | |
291 | class NullHandler(logging.Handler): |
292 | @@ -28,4 +29,4 @@ |
293 | |
294 | |
295 | h = NullHandler() |
296 | -logging.getLogger(__name__).addHandler(h) |
297 | +logging.getLogger(DEFAULT_LOGGER_NAME).addHandler(h) |
298 | |
299 | === modified file 'linaro_image_tools/hwpack/hwpack_convert.py' |
300 | --- linaro_image_tools/hwpack/hwpack_convert.py 2012-07-20 08:19:11 +0000 |
301 | +++ linaro_image_tools/hwpack/hwpack_convert.py 2012-10-04 14:31:36 +0000 |
302 | @@ -80,7 +80,7 @@ |
303 | SPL_KEYS = [SPL_IN_BOOT_PART_FIELD, SPL_DD_FIELD, SPL_PACKAGE_FIELD, |
304 | SPL_FILE_FIELD, ENV_DD_FIELD] |
305 | |
306 | -logger = logging.getLogger("linaro_hwpack_converter") |
307 | +logger = logging.getLogger(__name__) |
308 | |
309 | |
310 | class HwpackConverterException(Exception): |
311 | |
312 | === modified file 'linaro_image_tools/media_create/__init__.py' |
313 | --- linaro_image_tools/media_create/__init__.py 2012-10-01 13:44:05 +0000 |
314 | +++ linaro_image_tools/media_create/__init__.py 2012-10-04 14:31:36 +0000 |
315 | @@ -173,6 +173,7 @@ |
316 | help="Select a bootloader from a hardware pack that contains more " |
317 | "than one. If not specified, it will default to '%s'." % |
318 | DEFAULT_BOOTLOADER) |
319 | + parser.add_argument("--debug", action="store_true") |
320 | |
321 | add_common_options(parser) |
322 | return parser |
323 | |
324 | === modified file 'linaro_image_tools/media_create/boards.py' |
325 | --- linaro_image_tools/media_create/boards.py 2012-10-02 15:25:27 +0000 |
326 | +++ linaro_image_tools/media_create/boards.py 2012-10-04 14:31:36 +0000 |
327 | @@ -47,6 +47,8 @@ |
328 | partition_mounted, SECTOR_SIZE, register_loopback) |
329 | from StringIO import StringIO |
330 | |
331 | +logger = logging.getLogger(__name__) |
332 | + |
333 | KERNEL_GLOB = 'vmlinuz-*-%(kernel_flavor)s' |
334 | INITRD_GLOB = 'initrd.img-*-%(kernel_flavor)s' |
335 | DTB_GLOB = 'dt-*-%(kernel_flavor)s/%(dtb_name)s' |
336 | @@ -455,14 +457,6 @@ |
337 | |
338 | hardwarepack_handler = None |
339 | |
340 | - @staticmethod |
341 | - def _get_logger(): |
342 | - """ |
343 | - Gets the logger instance. |
344 | - :return: The logger instance |
345 | - """ |
346 | - return logging.getLogger('linaro_image_tools') |
347 | - |
348 | @classmethod |
349 | def get_metadata_field(cls, field_name): |
350 | """ Return the metadata value for field_name if it can be found. |
351 | @@ -873,7 +867,6 @@ |
352 | :param dest_dir: The directory where to copy each dtb file. |
353 | :param search_dir: The directory where to search for the real file. |
354 | """ |
355 | - logger = logging.getLogger("linaro_image_tools") |
356 | logger.info("Copying dtb files") |
357 | for dtb_file in dtb_files: |
358 | if dtb_file: |
359 | @@ -918,7 +911,6 @@ |
360 | if max_size is not None: |
361 | assert os.path.getsize(from_file) <= max_size, ( |
362 | "'%s' is larger than %s" % (from_file, max_size)) |
363 | - logger = logging.getLogger("linaro_image_tools") |
364 | logger.info("Writing '%s' to '%s' at %s." % (from_file, to_file, seek)) |
365 | _dd(from_file, to_file, seek=seek) |
366 | |
367 | @@ -941,7 +933,6 @@ |
368 | if cls.spl_in_boot_part: |
369 | assert spl_file is not None, ( |
370 | "SPL binary could not be found") |
371 | - logger = logging.getLogger("linaro_image_tools") |
372 | logger.info( |
373 | "Copying spl '%s' to boot partition." % spl_file) |
374 | cmd_runner.run(["cp", "-v", spl_file, boot_dir], |
375 | @@ -1101,7 +1092,6 @@ |
376 | @classmethod |
377 | def _get_kflavor_files_v2(cls, path): |
378 | kernel = initrd = dtb = None |
379 | - logger = logging.getLogger("linaro_image_tools") |
380 | |
381 | if cls.vmlinuz: |
382 | kernel = _get_file_matching(os.path.join(path, cls.vmlinuz)) |
383 | |
384 | === modified file 'linaro_image_tools/media_create/partitions.py' |
385 | --- linaro_image_tools/media_create/partitions.py 2012-06-13 13:42:08 +0000 |
386 | +++ linaro_image_tools/media_create/partitions.py 2012-10-04 14:31:36 +0000 |
387 | @@ -36,6 +36,8 @@ |
388 | |
389 | from linaro_image_tools import cmd_runner |
390 | |
391 | +logger = logging.getLogger(__name__) |
392 | + |
393 | HEADS = 128 |
394 | SECTORS = 32 |
395 | SECTOR_SIZE = 512 # bytes |
396 | @@ -205,7 +207,6 @@ |
397 | try: |
398 | umount(path) |
399 | except cmd_runner.SubcommandNonZeroReturnValue, e: |
400 | - logger = logging.getLogger("linaro_image_tools") |
401 | logger.warn("Failed to umount %s, but ignoring it because of a " |
402 | "previous error" % path) |
403 | logger.warn(e) |
404 | @@ -586,7 +587,6 @@ |
405 | |
406 | :param media: A setup_partitions.Media object to partition. |
407 | """ |
408 | - logger = logging.getLogger("linaro_image_tools") |
409 | tts = 1 |
410 | while (tts > 0) and (tts <= MAX_TTS): |
411 | try: |
412 | |
413 | === modified file 'linaro_image_tools/utils.py' |
414 | --- linaro_image_tools/utils.py 2012-07-26 19:49:43 +0000 |
415 | +++ linaro_image_tools/utils.py 2012-10-04 14:31:36 +0000 |
416 | @@ -28,6 +28,8 @@ |
417 | |
418 | from linaro_image_tools import cmd_runner |
419 | |
420 | +DEFAULT_LOGGER_NAME = 'linaro_image_tools' |
421 | + |
422 | |
423 | # try_import was copied from python-testtools 0.9.12 and was originally |
424 | # licensed under a MIT-style license but relicensed under the GPL in Linaro |
425 | @@ -76,13 +78,15 @@ |
426 | |
427 | |
428 | def path_in_tarfile_exists(path, tar_file): |
429 | - tarinfo = tarfile.open(tar_file, 'r:gz') |
430 | + exists = True |
431 | try: |
432 | + tarinfo = tarfile.open(tar_file, 'r:gz') |
433 | tarinfo.getmember(path) |
434 | - return True |
435 | + tarinfo.close() |
436 | except KeyError: |
437 | - return False |
438 | - tarinfo.close() |
439 | + exists = False |
440 | + finally: |
441 | + return exists |
442 | |
443 | |
444 | def verify_file_integrity(sig_file_list): |
445 | @@ -145,24 +149,24 @@ |
446 | |
447 | # Check the outputs from verify_file_integrity |
448 | # Abort if anything fails. |
449 | + logger = logging.getLogger(__name__) |
450 | if len(sig_file_list): |
451 | if not gpg_sig_pass: |
452 | - logging.error("GPG signature verification failed.") |
453 | + logger.error("GPG signature verification failed.") |
454 | return False, [] |
455 | |
456 | if not os.path.basename(binary) in verified_files: |
457 | - logging.error("OS Binary verification failed") |
458 | + logger.error("OS Binary verification failed") |
459 | return False, [] |
460 | |
461 | for hwpack in hwpacks: |
462 | if not os.path.basename(hwpack) in verified_files: |
463 | - logging.error("Hwpack {0} verification failed".format(hwpack)) |
464 | + logger.error("Hwpack {0} verification failed".format(hwpack)) |
465 | return False, [] |
466 | |
467 | for verified_file in verified_files: |
468 | - logging.info('Hash verification of file {0} OK.'.format( |
469 | + logger.info('Hash verification of file {0} OK.'.format( |
470 | verified_file)) |
471 | - |
472 | return True, verified_files |
473 | |
474 | |
475 | @@ -348,3 +352,31 @@ |
476 | raise MissingRequiredOption("--dev option is required") |
477 | if args.binary is None: |
478 | raise MissingRequiredOption("--binary option is required") |
479 | + |
480 | + |
481 | +def get_logger(name=DEFAULT_LOGGER_NAME, debug=False): |
482 | + """ |
483 | + Retrieves a named logger. Default name is set in the variable |
484 | + DEFAULT_LOG_NAME. Debug is set to False by default. |
485 | + |
486 | + :param name: The name of the logger. |
487 | + :param debug: If debug level should be turned on |
488 | + :return: A logger instance. |
489 | + """ |
490 | + logger = logging.getLogger(name) |
491 | + ch = logging.StreamHandler() |
492 | + |
493 | + if debug: |
494 | + ch.setLevel(logging.DEBUG) |
495 | + formatter = logging.Formatter( |
496 | + "%(asctime)s - %(name)s - %(levelname)s - %(message)s") |
497 | + ch.setFormatter(formatter) |
498 | + logger.setLevel(logging.DEBUG) |
499 | + else: |
500 | + ch.setLevel(logging.INFO) |
501 | + formatter = logging.Formatter("%(message)s") |
502 | + ch.setFormatter(formatter) |
503 | + logger.setLevel(logging.INFO) |
504 | + |
505 | + logger.addHandler(ch) |
506 | + return logger |
I'm old for refactoring [old mess], and I assume you weighed pros and cons of that "drawback" - I don't immediately see any issues with it. Code changes look good to me.