Repository: ipython/ipython

Issue:
Duplicated definition of built-in magic aliases after %reset
When running `%reset -f` in Jupyter notebook or Spyder, the following message will be printed.
```
ERROR:root:Invalid alias: The name clear can't be aliased because it is another magic command.
ERROR:root:Invalid alias: The name more can't be aliased because it is another magic command.
ERROR:root:Invalid alias: The name less can't be aliased because it is another magic command.
ERROR:root:Invalid alias: The name man can't be aliased because it is another magic command.
```
However, running `%reset -f` in IPython itself is just fine.

I started experiencing this after upgrading to IPython 7.3.0, and I believe that this behavior was from the change #11528. Maybe those aliases should only be redefined when running in the IPython shell, not in Jupyter or Spyder as a kernel.


Discussion:
@Carreau, any hope to fix this problem? It's very annoying for Spyder users.
Likely. Worst case I revert  #11528. Though I'm stretched thin trying to maintain IPython on my free time. It's not my fulltime job anymore, so i can't commit as much time as before. 

Ok, I understand. Thanks for the quick response.
Successful work-around in Anaconda environment:
`conda install ipython=7.2.0`
Still an issue in ipython-7.4.0 
7.5 the issue remains

I'm running into this too
Try this:    %reset -s -f
In Spyder, using ipython 7.5, every execution still shows this at the beginning:
ERROR:root:Invalid alias: The name clear can't be aliased because it is another magic command.
ERROR:root:Invalid alias: The name more can't be aliased because it is another magic command.
ERROR:root:Invalid alias: The name less can't be aliased because it is another magic command.
ERROR:root:Invalid alias: The name man can't be aliased because it is another magic command.

My new conda update procedure:
conda update --all
conda install ipython=7.2.0

I'd like to stay up-to-date in ipython.  However, continued use of version 7.2.0 seems like the "lesser of evils".

Resolving patch:
diff --git a/IPython/core/interactiveshell.py b/IPython/core/interactiveshell.py
--- a/IPython/core/interactiveshell.py
+++ b/IPython/core/interactiveshell.py
@@ -1435,9 +1435,9 @@ def reset(self, new_session=True):
         drop_keys.discard('__name__')
         for k in drop_keys:
             del ns[k]
-        
+
         self.user_ns_hidden.clear()
-        
+
         # Restore the user namespaces to minimal usability
         self.init_user_ns()
 
@@ -1450,7 +1450,8 @@ def reset(self, new_session=True):
         # GUI or web frontend
         if os.name == 'posix':
             for cmd in ('clear', 'more', 'less', 'man'):
-                self.alias_manager.soft_define_alias(cmd, cmd)
+                if cmd not in self.magics_manager.magics['line']:
+                    self.alias_manager.soft_define_alias(cmd, cmd)
 
         # Flush the private list of module references kept for script
         # execution protection


Test patch:
diff --git a/IPython/core/tests/test_magic.py b/IPython/core/tests/test_magic.py
--- a/IPython/core/tests/test_magic.py
+++ b/IPython/core/tests/test_magic.py
@@ -371,6 +371,31 @@ def test_reset_in_length():
     _ip.run_cell("reset -f in")
     nt.assert_equal(len(_ip.user_ns['In']), _ip.displayhook.prompt_count+1)
 
+class TestResetErrors(TestCase):
+
+    def test_reset_redefine(self):
+
+        @magics_class
+        class KernelMagics(Magics):
+              @line_magic
+              def less(self, shell): pass
+
+        _ip.register_magics(KernelMagics)
+
+        with self.assertLogs() as cm:
+            # hack, we want to just capture logs, but assertLogs fails if not
+            # logs get produce.
+            # so log one things we ignore.
+            import logging as log_mod
+            log = log_mod.getLogger()
+            log.info('Nothing')
+            # end hack.
+            _ip.run_cell("reset -f")
+
+        assert len(cm.output) == 1
+        for out in cm.output:
+            assert "Invalid alias" not in out
+
 def test_tb_syntaxerror():
     """test %tb after a SyntaxError"""
     ip = get_ipython()