Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 809ebdf

Browse files
committed
Replace %averbose with args to %autoreload
1 parent d8bb14b commit 809ebdf

3 files changed

Lines changed: 83 additions & 72 deletions

File tree

IPython/extensions/autoreload.py

Lines changed: 60 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@
5353
Same as 2/all, but also adds any new objects in the module. See
5454
unit test at IPython/extensions/tests/test_autoreload.py::test_autoload_newly_added_objects
5555
56+
Adding ``--print`` or ``-p`` to the ``%autoreload`` line will print autoreload activity to
57+
standard out. ``--log`` or ``-l`` will do it to the log at INFO level; both can be used
58+
simultaneously.
59+
5660
``%aimport``
5761
5862
List modules which are to be automatically imported or not to be imported.
@@ -69,18 +73,6 @@
6973
7074
Mark module 'foo' to not be autoreloaded.
7175
72-
``%averbose off``
73-
74-
Perform autoreload tasks quietly
75-
76-
``%averbose on``
77-
78-
Report activity with `print` statements.
79-
80-
``%averbose log``
81-
82-
Report activity with the logger.
83-
8476
Caveats
8577
=======
8678
@@ -113,6 +105,7 @@
113105
- Reloading a module, or importing the same module by a different name, creates new Enums. These may look the same, but are not.
114106
"""
115107

108+
from IPython.core import magic_arguments
116109
from IPython.core.magic import Magics, magics_class, line_magic
117110

118111
__skip_doctest__ = True
@@ -525,7 +518,28 @@ def __init__(self, *a, **kw):
525518
self.loaded_modules = set(sys.modules)
526519

527520
@line_magic
528-
def autoreload(self, parameter_s=""):
521+
@magic_arguments.magic_arguments()
522+
@magic_arguments.argument('mode', type=str, default='now', nargs='?',
523+
help="""
524+
blank or 'now' - Reload all modules (except those excluded by
525+
%%aimport) automaticallynow.
526+
527+
'0' or 'off' - Disable automatic reloading.
528+
529+
'1' or 'explicit' - Reload only modules imported with %%aimport every
530+
time before executing the Python code typed.
531+
532+
'2' or 'all' - Reload all modules (except those excluded by %%aimport)
533+
every time before executing the Python code typed.
534+
535+
'3' or 'complete' - Same as 2/all, but also but also adds any new
536+
objects in the module.
537+
""")
538+
@magic_arguments.argument('-p', '--print', action='store_true', default=False,
539+
help='Show autoreload activity using `print` statements')
540+
@magic_arguments.argument('-l', '--log', action='store_true', default=False,
541+
help='Show autoreload activity using the logger')
542+
def autoreload(self, line=""):
529543
r"""%autoreload => Reload modules automatically
530544
531545
%autoreload or %autoreload now
@@ -547,6 +561,10 @@ def autoreload(self, parameter_s=""):
547561
Same as 2/all, but also but also adds any new objects in the module. See
548562
unit test at IPython/extensions/tests/test_autoreload.py::test_autoload_newly_added_objects
549563
564+
The optional arguments --print and --log control display of autoreload activity. The default
565+
is to act silently; --print (or -p) will print out the names of modules that are being
566+
reloaded, and --log (or -l) outputs them to the log at INFO level.
567+
550568
Reloading Python modules in a reliable way is in general
551569
difficult, and unexpected things may occur. %autoreload tries to
552570
work around common pitfalls by replacing function code objects and
@@ -573,23 +591,45 @@ def autoreload(self, parameter_s=""):
573591
autoreloaded.
574592
575593
"""
576-
parameter_s_lower = parameter_s.lower()
577-
if parameter_s == "" or parameter_s_lower == "now":
594+
args = magic_arguments.parse_argstring(self.autoreload, line)
595+
mode = args.mode.lower()
596+
597+
def p(msg):
598+
print(msg)
599+
600+
def l(msg):
601+
logging.getLogger("autoreload").info(msg)
602+
603+
def pl(msg):
604+
p(msg)
605+
l(msg)
606+
607+
if args.print is False and args.log is False:
608+
self._reloader._report = lambda msg: None
609+
elif args.print is True:
610+
if args.log is True:
611+
self._reloader._report = lambda msg: pl(msg)
612+
else:
613+
self._reloader._report = lambda msg: p(msg)
614+
elif args.log is True:
615+
self._reloader._report = lambda msg: l(msg)
616+
617+
if mode == "" or mode == "now":
578618
self._reloader.check(True)
579-
elif parameter_s == "0" or parameter_s_lower == "off":
619+
elif mode == "0" or mode == "off":
580620
self._reloader.enabled = False
581-
elif parameter_s == "1" or parameter_s_lower == "explicit":
621+
elif mode == "1" or mode == "explicit":
582622
self._reloader.check_all = False
583623
self._reloader.enabled = True
584-
elif parameter_s == "2" or parameter_s_lower == "all":
624+
elif mode == "2" or mode == "all":
585625
self._reloader.check_all = True
586626
self._reloader.enabled = True
587-
elif parameter_s == "3" or parameter_s_lower == "complete":
627+
elif mode == "3" or mode == "complete":
588628
self._reloader.check_all = True
589629
self._reloader.enabled = True
590630
self._reloader.autoload_obj = True
591631
else:
592-
raise ValueError(f'Unrecognized parameter "{parameter_s}".')
632+
raise ValueError(f'Unrecognized autoreload mode "{mode}".')
593633

594634
@line_magic
595635
def aimport(self, parameter_s="", stream=None):
@@ -630,31 +670,6 @@ def aimport(self, parameter_s="", stream=None):
630670
# Inject module to user namespace
631671
self.shell.push({top_name: top_module})
632672

633-
@line_magic
634-
def averbose(self, parameter_s=""):
635-
r"""%averbose => Turn verbosity on/off for autoreloading.
636-
637-
%averbose 0 or %averbose off
638-
Turn off any reporting during autoreload.
639-
640-
%averbose 1 or %averbose on
641-
Report autoreload activity via print statements.
642-
643-
%averbose 2 or %averbose log
644-
Report autoreload activity via logging.
645-
"""
646-
647-
if parameter_s == "0" or parameter_s.lower() == "off":
648-
self._reloader._report = lambda msg: None
649-
elif parameter_s == "1" or parameter_s.lower() == "on":
650-
self._reloader._report = lambda msg: print(msg)
651-
elif parameter_s == "2" or parameter_s.lower() == "log":
652-
self._reloader._report = lambda msg: logging.getLogger("autoreload").info(
653-
msg
654-
)
655-
else:
656-
raise ValueError(f'Unrecognized parameter "{parameter_s}".')
657-
658673
def pre_run_cell(self):
659674
if self._reloader.enabled:
660675
try:

IPython/extensions/tests/test_autoreload.py

Lines changed: 19 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,6 @@ def magic_aimport(self, parameter, stream=None):
7171
self.auto_magics.aimport(parameter, stream=stream)
7272
self.auto_magics.post_execute_hook()
7373

74-
def magic_averbose(self, parameter):
75-
self.auto_magics.averbose(parameter)
76-
7774
class Fixture(TestCase):
7875
"""Fixture for creating test module files"""
7976

@@ -442,41 +439,40 @@ def test_aimport_parsing(self):
442439
assert module_reloader.skip_modules["os"] is True
443440
assert "os" not in module_reloader.modules.keys()
444441

445-
def test_averbose(self):
446-
self.shell.magic_averbose("off")
442+
def test_autoreload_output(self):
447443
self.shell.magic_autoreload("complete")
448444
mod_code = """
449445
def func1(): pass
450446
"""
451447
mod_name, mod_fn = self.new_module(mod_code)
452448
self.shell.run_code(f"import {mod_name}")
453-
with tt.AssertPrints("", channel="stdout"): # no output.
449+
with tt.AssertPrints("", channel="stdout"): # no output; this is default
454450
self.shell.run_code("pass")
455451

452+
self.shell.magic_autoreload("complete --print")
456453
self.write_file(mod_fn, mod_code) # "modify" the module
457-
self.shell.magic_averbose("on") # Should now see a print statement.
458-
with tt.AssertPrints(f"Reloading '{mod_name}'.", channel="stdout"):
454+
with tt.AssertPrints(f"Reloading '{mod_name}'.", channel="stdout"): # see something printed out
459455
self.shell.run_code("pass")
460456

457+
self.shell.magic_autoreload("complete -p")
461458
self.write_file(mod_fn, mod_code) # "modify" the module
462-
self.shell.magic_averbose("off") # Should not see anything on next call
463-
with tt.AssertPrints("", channel="stdout"):
459+
with tt.AssertPrints(f"Reloading '{mod_name}'.", channel="stdout"): # see something printed out
464460
self.shell.run_code("pass")
465461

466-
# TODO: test logging. Why won't this work?
467-
# with tt.AssertPrints('LOGGER: '):
468-
# self.shell.run_code("import logging; logging.basicConfig(format='LOGGER: %(message)s');"
469-
# "logger = logging.getLogger(); logger.setLevel(logging.DEBUG);"
470-
# "logger.info('test')")
471-
472-
# self.shell.magic_averbose("log") # Should see it formatted as per our logging config
473-
# self.write_file(mod_fn, mod_code) # "modify" the module
474-
# with tt.AssertPrints(f"LOGGER: Reloading '{mod_name}'.", channel="stdout"):
475-
# self.shell.run_code("pass")
462+
self.shell.magic_autoreload("complete --print --log")
463+
self.write_file(mod_fn, mod_code) # "modify" the module
464+
with tt.AssertPrints(f"Reloading '{mod_name}'.", channel="stdout"): # see something printed out
465+
self.shell.run_code("pass")
476466

477-
# And an invalid mode name raises an exception.
478-
with self.assertRaises(ValueError):
479-
self.shell.magic_averbose("fax")
467+
# TODO: test logging, i.e. --log. Why won't this work?
468+
# with tt.AssertPrints("LOGGER: test", channel="stdout"):
469+
# # logger.info('test')
470+
# self.shell.run_code("import logging; import sys;"
471+
# "logging.basicConfig(format='LOGGER: %(message)s',"
472+
# " stream=sys.stdout,"
473+
# " level=logging.DEBUG);"
474+
# "logging.getLogger().info('test');"
475+
# )
480476

481477
def _check_smoketest(self, use_aimport=True):
482478
"""

docs/source/whatsnew/pr/autoreload-verbosity.rst

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,12 @@ We introduce more descriptive names for the `%autoreload` parameter:
1010

1111
The original designations (e.g. "2") still work, and these new ones are case-insensitive.
1212

13+
Additionally, the option `--print` or `-p` can be added to the line to print the names of modules
14+
being reloaded. Similarly, `--log` or `-l` will output the names to the logger at INFO level. Both
15+
can be used simultaneously.
16+
1317
The parsing logic for `%aimport` is now improved such that modules can be whitelisted and
1418
blacklisted in the same line, e.g. it's now possible to call `%aimport os, -math` to include `os`
1519
for `%autoreload explicit` and exclude `math` for modes 2 and 3.
1620

17-
A new magic command `%averbose` controls printing of the names of modules about to be autoreloaded.
18-
- `%averbose off` / `%averbose 0` - turns off all output (default behavior)
19-
- `%averbose on` / `%averbose 1` - uses `print` to display module name
20-
- `%averbose log` / `%averbose 2` - logs an `INFO` message with the module name
2121

0 commit comments

Comments
 (0)