diff --git a/.gitignore b/.gitignore index e2f217b..f314157 100644 --- a/.gitignore +++ b/.gitignore @@ -24,3 +24,6 @@ __pycache__ .cache .coverage *.swp +.vscode +.pytest_cache +.python-version diff --git a/.travis.yml b/.travis.yml index 99c867f..57bfce2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,7 +14,8 @@ group: edge before_install: - 'if [[ $GROUP != js* ]]; then COVERAGE=""; fi' install: - - pip install setuptools pip --upgrade + - pip install pip --upgrade + - pip install setuptools --upgrade - pip install -e file://$PWD#egg=ipython[test] --upgrade - pip install codecov check-manifest --upgrade - sudo apt-get install graphviz diff --git a/IPython/__init__.py b/IPython/__init__.py index 5e81082..0b78eca 100644 --- a/IPython/__init__.py +++ b/IPython/__init__.py @@ -2,7 +2,7 @@ """ IPython: tools for interactive and parallel computing in Python. -http://ipython.org +https://ipython.org """ #----------------------------------------------------------------------------- # Copyright (c) 2008-2011, IPython Development Team. diff --git a/IPython/core/compilerop.py b/IPython/core/compilerop.py index 19b5596..c5abd06 100644 --- a/IPython/core/compilerop.py +++ b/IPython/core/compilerop.py @@ -40,7 +40,7 @@ import time # Constants #----------------------------------------------------------------------------- -# Roughtly equal to PyCF_MASK | PyCF_MASK_OBSOLETE as defined in pythonrun.h, +# Roughly equal to PyCF_MASK | PyCF_MASK_OBSOLETE as defined in pythonrun.h, # this is used as a bitmask to extract future-related code flags. PyCF_MASK = functools.reduce(operator.or_, (getattr(__future__, fname).compiler_flag @@ -52,7 +52,7 @@ PyCF_MASK = functools.reduce(operator.or_, def code_name(code, number=0): """ Compute a (probably) unique name for code for caching. - + This now expects code to be unicode. """ hash_digest = hashlib.sha1(code.encode("utf-8")).hexdigest() @@ -71,7 +71,7 @@ class CachingCompiler(codeop.Compile): def __init__(self): codeop.Compile.__init__(self) - + # This is ugly, but it must be done this way to allow multiple # simultaneous ipython instances to coexist. Since Python itself # directly accesses the data structures in the linecache module, and @@ -95,7 +95,7 @@ class CachingCompiler(codeop.Compile): def _fix_module_ds(self, module): """ Starting in python 3.7 the AST for mule have changed, and if - the first expressions encountered is a string it is attached to the + the first expressions encountered is a string it is attached to the `docstring` attribute of the `Module` ast node. This breaks IPython, as if this string is the only expression, IPython @@ -108,14 +108,14 @@ class CachingCompiler(codeop.Compile): new_body=[Expr(Str(docstring, lineno=1, col_offset=0), lineno=1, col_offset=0)] new_body.extend(module.body) return fix_missing_locations(Module(new_body)) - + def ast_parse(self, source, filename='', symbol='exec'): """Parse code to an AST with the current compiler flags active. - + Arguments are exactly the same as ast.parse (in the standard library), and are passed to the built-in compile function.""" return self._fix_module_ds(compile(source, filename, symbol, self.flags | PyCF_ONLY_AST, 1)) - + def reset_compiler_flags(self): """Reset compiler flags to default state.""" # This value is copied from codeop.Compile.__init__, so if that ever @@ -127,10 +127,10 @@ class CachingCompiler(codeop.Compile): """Flags currently active in the compilation process. """ return self.flags - + def cache(self, code, number=0): """Make a name for a block of code, and cache the code. - + Parameters ---------- code : str @@ -138,7 +138,7 @@ class CachingCompiler(codeop.Compile): number : int A number which forms part of the code's name. Used for the execution counter. - + Returns ------- The name of the cached code (as a string). Pass this as the filename diff --git a/IPython/core/completer.py b/IPython/core/completer.py index 68d76f2..04d7a9f 100644 --- a/IPython/core/completer.py +++ b/IPython/core/completer.py @@ -1592,7 +1592,7 @@ class IPCompleter(Completer): $ ''' regexps = self.__dict_key_regexps = { - False: re.compile(dict_key_re_fmt % ''' + False: re.compile(dict_key_re_fmt % r''' # identifiers separated by . (?!\d)\w+ (?:\.(?!\d)\w+)* diff --git a/IPython/core/completerlib.py b/IPython/core/completerlib.py index 3c66d73..eeb39a4 100644 --- a/IPython/core/completerlib.py +++ b/IPython/core/completerlib.py @@ -165,7 +165,7 @@ def try_import(mod: str, only_modules=False) -> List[str]: except: return [] - m_is_init = hasattr(m, '__file__') and '__init__' in m.__file__ + m_is_init = '__init__' in (getattr(m, '__file__', '') or '') completions = [] if (not hasattr(m, '__file__')) or (not only_modules) or m_is_init: diff --git a/IPython/core/debugger.py b/IPython/core/debugger.py index 0e0d401..4ece380 100644 --- a/IPython/core/debugger.py +++ b/IPython/core/debugger.py @@ -176,7 +176,7 @@ class Tracer(object): self.debugger.set_trace(sys._getframe().f_back) -RGX_EXTRA_INDENT = re.compile('(?<=\n)\s+') +RGX_EXTRA_INDENT = re.compile(r'(?<=\n)\s+') def strip_indentation(multiline_string): diff --git a/IPython/core/display.py b/IPython/core/display.py index fa64d9c..ca5c3aa 100644 --- a/IPython/core/display.py +++ b/IPython/core/display.py @@ -800,7 +800,7 @@ class JSON(DisplayObject): """ # wrap data in a property, which warns about passing already-serialized JSON _data = None - def __init__(self, data=None, url=None, filename=None, expanded=False, metadata=None, **kwargs): + def __init__(self, data=None, url=None, filename=None, expanded=False, metadata=None, root='root', **kwargs): """Create a JSON display object given raw data. Parameters @@ -817,8 +817,13 @@ class JSON(DisplayObject): Metadata to control whether a JSON display component is expanded. metadata: dict Specify extra metadata to attach to the json display object. + root : str + The name of the root element of the JSON tree """ - self.metadata = {'expanded': expanded} + self.metadata = { + 'expanded': expanded, + 'root': root, + } if metadata: self.metadata.update(metadata) if kwargs: @@ -847,18 +852,25 @@ class JSON(DisplayObject): def _repr_json_(self): return self._data_and_metadata() -_css_t = """$("head").append($("").attr({ - rel: "stylesheet", - type: "text/css", - href: "%s" -})); +_css_t = """var link = document.createElement("link"); + link.ref = "stylesheet"; + link.type = "text/css"; + link.href = "%s"; + document.head.appendChild(link); """ -_lib_t1 = """$.getScript("%s", function () { -""" -_lib_t2 = """}); +_lib_t1 = """new Promise(function(resolve, reject) { + var script = document.createElement("script"); + script.onload = resolve; + script.onerror = reject; + script.src = "%s"; + document.head.appendChild(script); +}).then(() => { """ +_lib_t2 = """ +});""" + class GeoJSON(JSON): """GeoJSON expects JSON-able dict diff --git a/IPython/core/hooks.py b/IPython/core/hooks.py index 7cf250a..66a544d 100644 --- a/IPython/core/hooks.py +++ b/IPython/core/hooks.py @@ -174,7 +174,7 @@ class CommandChainDispatcher: def shutdown_hook(self): """ default shutdown hook - Typically, shotdown hooks should raise TryNext so all shutdown ops are done + Typically, shutdown hooks should raise TryNext so all shutdown ops are done """ #print "default shutdown hook ok" # dbg diff --git a/IPython/core/inputsplitter.py b/IPython/core/inputsplitter.py index 4e60cae..84aa0a7 100644 --- a/IPython/core/inputsplitter.py +++ b/IPython/core/inputsplitter.py @@ -72,7 +72,7 @@ ini_spaces_re = re.compile(r'^([ \t\r\f\v]+)') # regexp to match pure comment lines so we don't accidentally insert 'if 1:' # before pure comments -comment_line_re = re.compile('^\s*\#') +comment_line_re = re.compile(r'^\s*\#') def num_ini_spaces(s): diff --git a/IPython/core/inputtransformer.py b/IPython/core/inputtransformer.py index b1c0dd2..1c35eb6 100644 --- a/IPython/core/inputtransformer.py +++ b/IPython/core/inputtransformer.py @@ -173,7 +173,7 @@ class assemble_python_lines(TokenInputTransformer): @CoroutineInputTransformer.wrap def assemble_logical_lines(): - """Join lines following explicit line continuations (\)""" + r"""Join lines following explicit line continuations (\)""" line = '' while True: line = (yield line) @@ -363,7 +363,7 @@ def cellmagic(end_on_blank_line=False): reset (sent None). """ tpl = 'get_ipython().run_cell_magic(%r, %r, %r)' - cellmagic_help_re = re.compile('%%\w+\?') + cellmagic_help_re = re.compile(r'%%\w+\?') line = '' while True: line = (yield line) diff --git a/IPython/core/magics/config.py b/IPython/core/magics/config.py index 044614b..97b13df 100644 --- a/IPython/core/magics/config.py +++ b/IPython/core/magics/config.py @@ -24,7 +24,7 @@ from logging import error # Magic implementation classes #----------------------------------------------------------------------------- -reg = re.compile('^\w+\.\w+$') +reg = re.compile(r'^\w+\.\w+$') @magics_class class ConfigMagics(Magics): diff --git a/IPython/core/magics/execution.py b/IPython/core/magics/execution.py index 3968969..9fabc43 100644 --- a/IPython/core/magics/execution.py +++ b/IPython/core/magics/execution.py @@ -962,11 +962,12 @@ python-profiler package from non-free.""") body has access to any variables created in the setup code. Options: - -n: execute the given statement times in a loop. If this value - is not given, a fitting value is chosen. + -n: execute the given statement times in a loop. If is not + provided, is determined so as to get sufficient accuracy. - -r: repeat the loop iteration times and take the best result. - Default: 3 + -r: number of repeats , each consisting of loops, and take the + best result. + Default: 7 -t: use time.time to measure the time, which is the default on Unix. This function measures wall time. diff --git a/IPython/core/magics/script.py b/IPython/core/magics/script.py index a041d58..d84b271 100644 --- a/IPython/core/magics/script.py +++ b/IPython/core/magics/script.py @@ -8,7 +8,7 @@ import os import sys import signal import time -from subprocess import Popen, PIPE +from subprocess import Popen, PIPE, CalledProcessError import atexit from IPython.core import magic_arguments @@ -54,6 +54,12 @@ def script_args(f): This is used only when --bg option is given. """ ), + magic_arguments.argument( + '--raise-error', action="store_true", + help="""Whether you should raise an error message in addition to + a stream on stderr if you get a nonzero exit code. + """ + ) ] for arg in args: f = arg(f) @@ -235,6 +241,8 @@ class ScriptMagics(Magics): else: sys.stderr.write(err) sys.stderr.flush() + if args.raise_error and p.returncode!=0: + raise CalledProcessError(p.returncode, cell, output=out, stderr=err) def _run_script(self, p, cell, to_close): """callback for running the script in the background""" diff --git a/IPython/core/prefilter.py b/IPython/core/prefilter.py index 99632ba..0262a29 100644 --- a/IPython/core/prefilter.py +++ b/IPython/core/prefilter.py @@ -82,7 +82,7 @@ class PrefilterManager(Configurable): prefilter consumes lines of input and produces transformed lines of input. - The iplementation consists of two phases: + The implementation consists of two phases: 1. Transformers 2. Checkers and handlers diff --git a/IPython/core/release.py b/IPython/core/release.py index 0e37939..525639e 100644 --- a/IPython/core/release.py +++ b/IPython/core/release.py @@ -48,7 +48,7 @@ IPython provides a rich toolkit to help you make the most out of using Python interactively. Its main components are: * A powerful interactive Python shell -* A `Jupyter `_ kernel to work with Python code in Jupyter +* A `Jupyter `_ kernel to work with Python code in Jupyter notebooks and other interactive frontends. The enhanced interactive Python shells have the following main features: diff --git a/IPython/core/splitinput.py b/IPython/core/splitinput.py index f8bf623..63cdce7 100644 --- a/IPython/core/splitinput.py +++ b/IPython/core/splitinput.py @@ -41,7 +41,7 @@ from IPython.utils.encoding import get_stream_enc # ! and !! trigger if they are first char(s) *or* follow an indent # ? triggers as first or last char. -line_split = re.compile(""" +line_split = re.compile(r""" ^(\s*) # any leading space ([,;/%]|!!?|\?\??)? # escape character or characters \s*(%{0,2}[\w\.\*]*) # function/method, possibly with leading % @@ -68,7 +68,7 @@ def split_user_input(line, pattern=None): except ValueError: # print "split failed for line '%s'" % line ifun, the_rest = line, u'' - pre = re.match('^(\s*)(.*)',line).groups()[0] + pre = re.match(r'^(\s*)(.*)',line).groups()[0] esc = "" else: pre, esc, ifun, the_rest = match.groups() diff --git a/IPython/core/tests/test_completerlib.py b/IPython/core/tests/test_completerlib.py index 6e2a540..fe54668 100644 --- a/IPython/core/tests/test_completerlib.py +++ b/IPython/core/tests/test_completerlib.py @@ -16,7 +16,7 @@ from os.path import join import nose.tools as nt -from IPython.core.completerlib import magic_run_completer, module_completion +from IPython.core.completerlib import magic_run_completer, module_completion, try_import from IPython.utils.tempdir import TemporaryDirectory from IPython.testing.decorators import onlyif_unicode_paths @@ -159,3 +159,20 @@ def test_bad_module_all(): nt.assert_is_instance(r, str) finally: sys.path.remove(testsdir) + + +def test_module_without_init(): + """ + Test module without __init__.py. + + https://github.com/ipython/ipython/issues/11226 + """ + fake_module_name = "foo" + with TemporaryDirectory() as tmpdir: + sys.path.insert(0, tmpdir) + try: + os.makedirs(os.path.join(tmpdir, fake_module_name)) + s = try_import(mod=fake_module_name) + assert s == [] + finally: + sys.path.remove(tmpdir) diff --git a/IPython/core/tests/test_display.py b/IPython/core/tests/test_display.py index 5a1b5be..3851d67 100644 --- a/IPython/core/tests/test_display.py +++ b/IPython/core/tests/test_display.py @@ -213,31 +213,41 @@ def test_progress_iter(): def test_json(): d = {'a': 5} lis = [d] - md = {'expanded': False} - md2 = {'expanded': True} - j = display.JSON(d) - j2 = display.JSON(d, expanded=True) - nt.assert_equal(j._repr_json_(), (d, md)) - nt.assert_equal(j2._repr_json_(), (d, md2)) + metadata = [ + {'expanded': False, 'root': 'root'}, + {'expanded': True, 'root': 'root'}, + {'expanded': False, 'root': 'custom'}, + {'expanded': True, 'root': 'custom'}, + ] + json_objs = [ + display.JSON(d), + display.JSON(d, expanded=True), + display.JSON(d, root='custom'), + display.JSON(d, expanded=True, root='custom'), + ] + for j, md in zip(json_objs, metadata): + nt.assert_equal(j._repr_json_(), (d, md)) with warnings.catch_warnings(record=True) as w: warnings.simplefilter("always") j = display.JSON(json.dumps(d)) nt.assert_equal(len(w), 1) - nt.assert_equal(j._repr_json_(), (d, md)) - nt.assert_equal(j2._repr_json_(), (d, md2)) - - j = display.JSON(lis) - j2 = display.JSON(lis, expanded=True) - nt.assert_equal(j._repr_json_(), (lis, md)) - nt.assert_equal(j2._repr_json_(), (lis, md2)) + nt.assert_equal(j._repr_json_(), (d, metadata[0])) + + json_objs = [ + display.JSON(lis), + display.JSON(lis, expanded=True), + display.JSON(lis, root='custom'), + display.JSON(lis, expanded=True, root='custom'), + ] + for j, md in zip(json_objs, metadata): + nt.assert_equal(j._repr_json_(), (lis, md)) with warnings.catch_warnings(record=True) as w: warnings.simplefilter("always") j = display.JSON(json.dumps(lis)) nt.assert_equal(len(w), 1) - nt.assert_equal(j._repr_json_(), (lis, md)) - nt.assert_equal(j2._repr_json_(), (lis, md2)) + nt.assert_equal(j._repr_json_(), (lis, metadata[0])) def test_video_embedding(): """use a tempfile, with dummy-data, to ensure that video embedding doesn't crash""" diff --git a/IPython/core/tests/test_interactiveshell.py b/IPython/core/tests/test_interactiveshell.py index 492fe1f..b9eae25 100644 --- a/IPython/core/tests/test_interactiveshell.py +++ b/IPython/core/tests/test_interactiveshell.py @@ -546,7 +546,8 @@ class ExitCodeChecks(tt.TempFileMixin): else: del os.environ['SHELL'] -class TestSystemRaw(unittest.TestCase, ExitCodeChecks): + +class TestSystemRaw(ExitCodeChecks, unittest.TestCase): system = ip.system_raw @onlyif_unicode_paths @@ -567,7 +568,7 @@ class TestSystemRaw(unittest.TestCase, ExitCodeChecks): self.assertEqual(ip.user_ns['_exit_code'], -signal.SIGINT) # TODO: Exit codes are currently ignored on Windows. -class TestSystemPipedExitCode(unittest.TestCase, ExitCodeChecks): +class TestSystemPipedExitCode(ExitCodeChecks, unittest.TestCase): system = ip.system_piped @skip_win32 @@ -582,7 +583,7 @@ class TestSystemPipedExitCode(unittest.TestCase, ExitCodeChecks): def test_exit_code_signal(self): ExitCodeChecks.test_exit_code_signal(self) -class TestModules(unittest.TestCase, tt.TempFileMixin): +class TestModules(tt.TempFileMixin, unittest.TestCase): def test_extraneous_loads(self): """Test we're not loading modules on startup that we shouldn't. """ diff --git a/IPython/core/tests/test_shellapp.py b/IPython/core/tests/test_shellapp.py index dd18086..6808114 100644 --- a/IPython/core/tests/test_shellapp.py +++ b/IPython/core/tests/test_shellapp.py @@ -24,7 +24,7 @@ sqlite_err_maybe = dec.module_not_available('sqlite3') SQLITE_NOT_AVAILABLE_ERROR = ('WARNING: IPython History requires SQLite,' ' your history will not be saved\n') -class TestFileToRun(unittest.TestCase, tt.TempFileMixin): +class TestFileToRun(tt.TempFileMixin, unittest.TestCase): """Test the behavior of the file_to_run parameter.""" def test_py_script_file_attribute(self): diff --git a/IPython/core/usage.py b/IPython/core/usage.py index e96579b..37024c4 100644 --- a/IPython/core/usage.py +++ b/IPython/core/usage.py @@ -60,7 +60,7 @@ Usage environment variable with this name and setting it to the desired path. For more information, see the manual available in HTML and PDF in your - installation, or online at http://ipython.org/documentation.html. + installation, or online at https://ipython.org/documentation.html. """ interactive_usage = """ diff --git a/IPython/lib/pretty.py b/IPython/lib/pretty.py index aeaed92..39d23dd 100644 --- a/IPython/lib/pretty.py +++ b/IPython/lib/pretty.py @@ -85,12 +85,12 @@ import re import sys import types from collections import deque +from inspect import signature from io import StringIO from warnings import warn from IPython.utils.decorators import undoc from IPython.utils.py3compat import PYPY -from IPython.utils.signatures import signature __all__ = ['pretty', 'pprint', 'PrettyPrinter', 'RepresentationPrinter', 'for_type', 'for_type_by_name'] @@ -104,7 +104,7 @@ _re_pattern_type = type(re.compile('')) def _safe_getattr(obj, attr, default=None): """Safe version of getattr. - + Same as getattr, but will return ``default`` on any Exception, rather than raising. """ @@ -246,7 +246,7 @@ class PrettyPrinter(_PrettyPrinterBase): self.buffer.append(Breakable(sep, width, self)) self.buffer_width += width self._break_outer_groups() - + def break_(self): """ Explicitly insert a newline into the output, maintaining correct indentation. @@ -256,7 +256,7 @@ class PrettyPrinter(_PrettyPrinterBase): self.output.write(' ' * self.indentation) self.output_width = self.indentation self.buffer_width = 0 - + def begin_group(self, indent=0, open=''): """ @@ -282,7 +282,7 @@ class PrettyPrinter(_PrettyPrinterBase): self.group_stack.append(group) self.group_queue.enq(group) self.indentation += indent - + def _enumerate(self, seq): """like enumerate, but with an upper limit on the number of items""" for idx, x in enumerate(seq): @@ -292,7 +292,7 @@ class PrettyPrinter(_PrettyPrinterBase): self.text('...') return yield idx, x - + def end_group(self, dedent=0, close=''): """End a group. See `begin_group` for more details.""" self.indentation -= dedent @@ -765,7 +765,7 @@ if _env_type is not dict: try: # In PyPy, types.DictProxyType is dict, setting the dictproxy printer - # using dict.setdefault avoids overwritting the dict printer + # using dict.setdefault avoids overwriting the dict printer _type_pprinters.setdefault(types.DictProxyType, _dict_pprinter_factory('dict_proxy({', '})')) _type_pprinters[types.ClassType] = _type_pprint diff --git a/IPython/testing/plugin/test_refs.py b/IPython/testing/plugin/test_refs.py index 50d0857..bd33942 100644 --- a/IPython/testing/plugin/test_refs.py +++ b/IPython/testing/plugin/test_refs.py @@ -19,9 +19,9 @@ def doctest_run(): In [13]: run simplevars.py x is: 1 """ - + def doctest_runvars(): - """Test that variables defined in scripts get loaded correcly via %run. + """Test that variables defined in scripts get loaded correclty via %run. In [13]: run simplevars.py x is: 1 diff --git a/IPython/utils/frame.py b/IPython/utils/frame.py index 1e5e536..11dab31 100644 --- a/IPython/utils/frame.py +++ b/IPython/utils/frame.py @@ -49,7 +49,7 @@ def extract_vars(*names,**kw): """ depth = kw.get('depth',0) - + callerNS = sys._getframe(depth+1).f_locals return dict((k,callerNS[k]) for k in names) @@ -58,7 +58,7 @@ def extract_vars_above(*names): """Extract a set of variables by name from another frame. Similar to extractVars(), but with a specified depth of 1, so that names - are exctracted exactly from above the caller. + are extracted exactly from above the caller. This is simply a convenience function so that the very common case (for us) of skipping exactly 1 frame doesn't have to construct a special dict for @@ -93,4 +93,3 @@ def extract_module_locals(depth=0): global_ns = f.f_globals module = sys.modules[global_ns['__name__']] return (module, f.f_locals) - diff --git a/IPython/utils/module_paths.py b/IPython/utils/module_paths.py index f984580..d50df80 100644 --- a/IPython/utils/module_paths.py +++ b/IPython/utils/module_paths.py @@ -2,14 +2,7 @@ Utility functions for finding modules on sys.path. -`find_mod` finds named module on sys.path. - -`get_init` helper function that finds __init__ file in a directory. - -`find_module` variant of imp.find_module in std_lib that only returns -path to module and not an open file object as well. - - +`find_module` returns a path to module or None, given certain conditions. """ #----------------------------------------------------------------------------- @@ -25,7 +18,7 @@ path to module and not an open file object as well. #----------------------------------------------------------------------------- # Stdlib imports -import imp +import importlib import os # Third-party imports @@ -44,81 +37,34 @@ import os #----------------------------------------------------------------------------- # Classes and functions #----------------------------------------------------------------------------- -def find_module(name, path=None): - """imp.find_module variant that only return path of module. - - The `imp.find_module` returns a filehandle that we are not interested in. - Also we ignore any bytecode files that `imp.find_module` finds. - - Parameters - ---------- - name : str - name of module to locate - path : list of str - list of paths to search for `name`. If path=None then search sys.path - Returns - ------- - filename : str - Return full path of module or None if module is missing or does not have - .py or .pyw extension - """ - if name is None: - return None - try: - file, filename, _ = imp.find_module(name, path) - except ImportError: - return None - if file is None: - return filename - else: - file.close() - if os.path.splitext(filename)[1] in [".py", ".pyc"]: - return filename - else: - return None - -def get_init(dirname): - """Get __init__ file path for module directory - - Parameters - ---------- - dirname : str - Find the __init__ file in directory `dirname` - - Returns - ------- - init_path : str - Path to __init__ file +def find_mod(module_name): """ - fbase = os.path.join(dirname, "__init__") - for ext in [".py", ".pyw"]: - fname = fbase + ext - if os.path.isfile(fname): - return fname + Find module `module_name` on sys.path, and return the path to module `module_name`. + - If `module_name` refers to a module directory, then return path to __init__ file. + - If `module_name` is a directory without an __init__file, return None. + - If module is missing or does not have a `.py` or `.pyw` extension, return None. + - Note that we are not interested in running bytecode. + - Otherwise, return the fill path of the module. -def find_mod(module_name): - """Find module `module_name` on sys.path - - Return the path to module `module_name`. If `module_name` refers to - a module directory then return path to __init__ file. Return full - path of module or None if module is missing or does not have .py or .pyw - extension. We are not interested in running bytecode. - Parameters ---------- module_name : str Returns ------- - modulepath : str - Path to module `module_name`. + module_path : str + Path to module `module_name`, its __init__.py, or None, + depending on above conditions. """ - parts = module_name.split(".") - basepath = find_module(parts[0]) - for submodname in parts[1:]: - basepath = find_module(submodname, [basepath]) - if basepath and os.path.isdir(basepath): - basepath = get_init(basepath) - return basepath + loader = importlib.util.find_spec(module_name) + module_path = loader.origin + if module_path is None: + return None + else: + split_path = module_path.split(".") + if split_path[1] in ["py", "pyw"]: + return module_path + else: + return None diff --git a/IPython/utils/path.py b/IPython/utils/path.py index 08806c2..f866597 100644 --- a/IPython/utils/path.py +++ b/IPython/utils/path.py @@ -202,7 +202,7 @@ def get_home_dir(require_writable=False): import _winreg as wreg # Py 2 key = wreg.OpenKey( wreg.HKEY_CURRENT_USER, - "Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders" + r"Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders" ) homedir = wreg.QueryValueEx(key,'Personal')[0] key.Close() diff --git a/IPython/utils/signatures.py b/IPython/utils/signatures.py index c4d9d1b..88d72b1 100644 --- a/IPython/utils/signatures.py +++ b/IPython/utils/signatures.py @@ -5,7 +5,8 @@ Fallback on backport otherwise. """ import warnings -warnings.warn("{} backport for Python 2 is deprecated in IPython 6, which only supports Python 3".format(__name__), +warnings.warn("{} backport for Python 2 is deprecated in IPython 6, which only supports " + "Python 3. Import directly from standard library `inspect`".format(__name__), DeprecationWarning, stacklevel=2) from inspect import BoundArguments, Parameter, Signature, signature diff --git a/IPython/utils/tests/test_module_paths.py b/IPython/utils/tests/test_module_paths.py index 5b24647..b315c69 100644 --- a/IPython/utils/tests/test_module_paths.py +++ b/IPython/utils/tests/test_module_paths.py @@ -66,62 +66,42 @@ def teardown(): shutil.rmtree(TMP_TEST_DIR) sys.path = old_syspath - -def test_get_init_1(): - """See if get_init can find __init__.py in this testdir""" - with make_tempfile(join(TMP_TEST_DIR, "__init__.py")): - assert mp.get_init(TMP_TEST_DIR) - -def test_get_init_2(): - """See if get_init can find __init__.pyw in this testdir""" - with make_tempfile(join(TMP_TEST_DIR, "__init__.pyw")): - assert mp.get_init(TMP_TEST_DIR) - -def test_get_init_3(): - """get_init can't find __init__.pyc in this testdir""" - with make_tempfile(join(TMP_TEST_DIR, "__init__.pyc")): - nt.assert_is_none(mp.get_init(TMP_TEST_DIR)) - -def test_get_init_4(): - """get_init can't find __init__ in empty testdir""" - nt.assert_is_none(mp.get_init(TMP_TEST_DIR)) - - def test_find_mod_1(): + """ + Search for a directory's file path. + Expected output: a path to that directory's __init__.py file. + """ modpath = join(TMP_TEST_DIR, "xmod", "__init__.py") nt.assert_equal(mp.find_mod("xmod"), modpath) def test_find_mod_2(): + """ + Search for a directory's file path. + Expected output: a path to that directory's __init__.py file. + TODO: Confirm why this is a duplicate test. + """ modpath = join(TMP_TEST_DIR, "xmod", "__init__.py") nt.assert_equal(mp.find_mod("xmod"), modpath) def test_find_mod_3(): + """ + Search for a directory + a filename without its .py extension + Expected output: full path with .py extension. + """ modpath = join(TMP_TEST_DIR, "xmod", "sub.py") nt.assert_equal(mp.find_mod("xmod.sub"), modpath) def test_find_mod_4(): + """ + Search for a filename without its .py extension + Expected output: full path with .py extension + """ modpath = join(TMP_TEST_DIR, "pack.py") nt.assert_equal(mp.find_mod("pack"), modpath) def test_find_mod_5(): - modpath = join(TMP_TEST_DIR, "packpyc.pyc") - nt.assert_equal(mp.find_mod("packpyc"), modpath) - -def test_find_module_1(): - modpath = join(TMP_TEST_DIR, "xmod") - nt.assert_equal(mp.find_module("xmod"), modpath) - -def test_find_module_2(): - """Testing sys.path that is empty""" - nt.assert_is_none(mp.find_module("xmod", [])) - -def test_find_module_3(): - """Testing sys.path that is empty""" - nt.assert_is_none(mp.find_module(None, None)) - -def test_find_module_4(): - """Testing sys.path that is empty""" - nt.assert_is_none(mp.find_module(None)) - -def test_find_module_5(): - nt.assert_is_none(mp.find_module("xmod.nopack")) + """ + Search for a filename with a .pyc extension + Expected output: TODO: do we exclude or include .pyc files? + """ + nt.assert_equal(mp.find_mod("packpyc"), None) diff --git a/IPython/utils/text.py b/IPython/utils/text.py index 98d72f4..0c0d82f 100644 --- a/IPython/utils/text.py +++ b/IPython/utils/text.py @@ -588,7 +588,7 @@ class DollarFormatter(FullEvalFormatter): In [4]: f.format('$a or {b}', a=1, b=2) Out[4]: '1 or 2' """ - _dollar_pattern_ignore_single_quote = re.compile("(.*?)\$(\$?[\w\.]+)(?=([^']*'[^']*')*[^']*$)") + _dollar_pattern_ignore_single_quote = re.compile(r"(.*?)\$(\$?[\w\.]+)(?=([^']*'[^']*')*[^']*$)") def parse(self, fmt_string): for literal_txt, field_name, format_spec, conversion \ in Formatter.parse(self, fmt_string): diff --git a/README.rst b/README.rst index eeb3f88..eb21641 100644 --- a/README.rst +++ b/README.rst @@ -55,7 +55,7 @@ Or see the `development installation docs for the latest revision on read the docs. Documentation and installation instructions for older version of IPython can be -found on the `IPython website `_ +found on the `IPython website `_ @@ -87,7 +87,7 @@ manager. For more information see one of our blog posts: - http://blog.jupyter.org/2016/07/08/ipython-5-0-released/ + https://blog.jupyter.org/2016/07/08/ipython-5-0-released/ As well as the following Pull-Request for discussion: diff --git a/docs/source/coredev/index.rst b/docs/source/coredev/index.rst index 106d2dd..5cb5b17 100644 --- a/docs/source/coredev/index.rst +++ b/docs/source/coredev/index.rst @@ -34,7 +34,7 @@ backport to. .. note:: - The ``@`` and ``[dev]`` when mentioning the bot should be optional and can + The ``@`` and ``[bot]`` when mentioning the bot should be optional and can be omitted. If the pull request cannot be automatically backported, the bot should tell you @@ -44,7 +44,7 @@ so on the PR and apply a "Need manual backport" tag to the origin PR. Backport with ghpro ------------------- -We can also use `ghpro ` +We can also use `ghpro `_ to automatically list and apply the PR on other branches. For example: .. code-block:: bash diff --git a/docs/source/index.rst b/docs/source/index.rst index 0fcb2fd..090fb88 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -22,7 +22,7 @@ interactively. Its main components are: :align: center -* A `Jupyter `_ kernel to work with Python code in Jupyter +* A `Jupyter `_ kernel to work with Python code in Jupyter notebooks and other interactive frontends. The enhanced interactive Python shells and kernel have the following main diff --git a/docs/source/install/install.rst b/docs/source/install/install.rst index d3acc9f..9888a8d 100644 --- a/docs/source/install/install.rst +++ b/docs/source/install/install.rst @@ -28,7 +28,7 @@ Overview This document describes in detail the steps required to install IPython. For a few quick ways to get started with package managers or full Python -distributions, see `the install page `_ of the +distributions, see `the install page `_ of the IPython website. Please let us know if you have problems installing IPython or any of its diff --git a/docs/source/interactive/index.rst b/docs/source/interactive/index.rst index 160a190..97332e1 100644 --- a/docs/source/interactive/index.rst +++ b/docs/source/interactive/index.rst @@ -27,5 +27,5 @@ done some work in the classic Python REPL. .. seealso:: - `A Qt Console for Jupyter `__ + `A Qt Console for Jupyter `__ `The Jupyter Notebook `__ diff --git a/docs/source/links.txt b/docs/source/links.txt index d77d61e..9379d1f 100644 --- a/docs/source/links.txt +++ b/docs/source/links.txt @@ -17,11 +17,11 @@ NOTE: Some of these were taken from the nipy links compendium. .. Main IPython links -.. _ipython: http://ipython.org -.. _`ipython manual`: http://ipython.org/documentation.html +.. _ipython: https://ipython.org +.. _`ipython manual`: https://ipython.org/documentation.html .. _ipython_github: http://github.com/ipython/ipython/ .. _ipython_github_repo: http://github.com/ipython/ipython/ -.. _ipython_downloads: http://ipython.org/download.html +.. _ipython_downloads: https://ipython.org/download.html .. _ipython_pypi: http://pypi.python.org/pypi/ipython .. _nbviewer: http://nbviewer.ipython.org diff --git a/docs/source/overview.rst b/docs/source/overview.rst index de36e6a..bf8654e 100644 --- a/docs/source/overview.rst +++ b/docs/source/overview.rst @@ -218,7 +218,7 @@ which will be something like ``--existing kernel-19732.json`` but with different numbers which correspond to the Process ID of the kernel. You can read more about using `jupyter qtconsole -`_, and +`_, and `jupyter notebook `_. There is also a :ref:`message spec ` which documents the protocol for communication between kernels diff --git a/docs/source/whatsnew/github-stats-2.0.rst b/docs/source/whatsnew/github-stats-2.0.rst index 826b471..5033994 100644 --- a/docs/source/whatsnew/github-stats-2.0.rst +++ b/docs/source/whatsnew/github-stats-2.0.rst @@ -1416,7 +1416,7 @@ Issues (434): * :ghissue:`4759`: Application._load_config_files log parameter default fails * :ghissue:`3153`: docs / file menu: explain how to exit the notebook * :ghissue:`4791`: Did updates to ipython_directive bork support for cython magic snippets? -* :ghissue:`4385`: "Part 4 - Markdown Cells.ipynb" nbviewer example seems not well referenced in current online documentation page http://ipython.org/ipython-doc/stable/interactive/notebook.htm +* :ghissue:`4385`: "Part 4 - Markdown Cells.ipynb" nbviewer example seems not well referenced in current online documentation page https://ipython.org/ipython-doc/stable/interactive/notebook.htm * :ghissue:`4655`: prefer marked to pandoc for markdown2html * :ghissue:`3441`: Fix focus related problems in the notebook * :ghissue:`3402`: Feature Request: Save As (latex, html,..etc) as a menu option in Notebook rather than explicit need to invoke nbconvert diff --git a/docs/source/whatsnew/version0.11.rst b/docs/source/whatsnew/version0.11.rst index abfdade..b032937 100644 --- a/docs/source/whatsnew/version0.11.rst +++ b/docs/source/whatsnew/version0.11.rst @@ -232,7 +232,7 @@ may also offer a slightly more featureful application (with menus and other GUI elements), but we remain committed to always shipping this easy to embed widget. -See the `Jupyter Qt Console site `_ for a detailed +See the `Jupyter Qt Console site `_ for a detailed description of the console's features and use. diff --git a/docs/source/whatsnew/version6.rst b/docs/source/whatsnew/version6.rst index 49bc0e6..461132e 100644 --- a/docs/source/whatsnew/version6.rst +++ b/docs/source/whatsnew/version6.rst @@ -2,6 +2,18 @@ 6.x Series ============ +.. _whatsnew650: + +IPython 6.5.0 +============= + +Miscellaneous bug fixes and compatibility with Python 3.7. + +* Autocompletion fix for modules with out ``__init__.py`` :ghpull:`11227` +* update the ``%pastebin`` magic to use ``dpaste.com`` instead og GitHub Gist + which now requires authentication :ghpull:`11182` +* Fix crash with multiprocessing :ghpull:`11185` + .. _whatsnew640: IPython 6.4.0 diff --git a/examples/IPython Kernel/Rich Output.ipynb b/examples/IPython Kernel/Rich Output.ipynb index 9793963..7b0caed 100644 --- a/examples/IPython Kernel/Rich Output.ipynb +++ b/examples/IPython Kernel/Rich Output.ipynb @@ -3058,7 +3058,7 @@ " \n", @@ -3075,7 +3075,7 @@ ], "source": [ "from IPython.display import IFrame\n", - "IFrame('http://jupyter.org', width='100%', height=350)" + "IFrame('https://jupyter.org', width='100%', height=350)" ] }, { @@ -3263,7 +3263,7 @@ "* When you open a notebook, rich output is only displayed if it doesn't contain security vulberabilities, ...\n", "* ... or if you have trusted a notebook, all rich output will run upon opening it.\n", "\n", - "A full description of the IPython security model can be found on [this page](http://ipython.org/ipython-doc/dev/notebook/security.html)." + "A full description of the IPython security model can be found on [this page](https://ipython.org/ipython-doc/dev/notebook/security.html)." ] }, { diff --git a/examples/Index.ipynb b/examples/Index.ipynb index 0e463d4..30e201a 100644 --- a/examples/Index.ipynb +++ b/examples/Index.ipynb @@ -18,7 +18,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "This directory contains IPython's notebook-based documentation. This augments our [Sphinx-based documentation](http://ipython.org/ipython-doc/stable/index.html) with notebooks that contain interactive tutorials and examples. Over time, more of our documentation will be pulled into this format." + "This directory contains IPython's notebook-based documentation. This augments our [Sphinx-based documentation](https://ipython.org/ipython-doc/stable/index.html) with notebooks that contain interactive tutorials and examples. Over time, more of our documentation will be pulled into this format." ] }, { diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..0c9e0fc --- /dev/null +++ b/setup.cfg @@ -0,0 +1,2 @@ +[metadata] +license_file = LICENSE diff --git a/tools/tests/Confined Output.ipynb b/tools/tests/Confined Output.ipynb index 8ba354d..f767c19 100644 --- a/tools/tests/Confined Output.ipynb +++ b/tools/tests/Confined Output.ipynb @@ -183,7 +183,7 @@ " \n", @@ -199,7 +199,7 @@ } ], "source": [ - "IFrame(src=\"http://ipython.org\", width=900, height=400)" + "IFrame(src=\"https://ipython.org\", width=900, height=400)" ] }, { diff --git a/tools/tests/Markdown Pandoc Limitations.ipynb b/tools/tests/Markdown Pandoc Limitations.ipynb index ff232bb..671aefb 100644 --- a/tools/tests/Markdown Pandoc Limitations.ipynb +++ b/tools/tests/Markdown Pandoc Limitations.ipynb @@ -1993,7 +1993,7 @@ "\n", "var mdcell = new IPython.MarkdownCell();\n", "mdcell.create_element();\n", - "mdcell.set_text('\\n![Alternate Text](http://ipython.org/_static/IPy_header.png)\\n');\n", + "mdcell.set_text('\\n![Alternate Text](https://ipython.org/_static/IPy_header.png)\\n');\n", "mdcell.render();\n", "$(element).append(mdcell.element)\n", ".removeClass()\n", @@ -2022,10 +2022,10 @@ "text/html": [ "
NBConvert Latex Output
\\begin{figure}[htbp]\n",
        "\\centering\n",
-       "\\includegraphics{http://ipython.org/_static/IPy_header.png}\n",
+       "\\includegraphics{https://ipython.org/_static/IPy_header.png}\n",
        "\\caption{Alternate Text}\n",
        "\\end{figure}
NBViewer Output
\n", - "\"Alternate

Alternate Text

\n", + "\"Alternate

Alternate Text

\n", "
" ], "text/plain": [ @@ -2051,7 +2051,7 @@ ], "source": [ "compare_render(r\"\"\"\n", - "![Alternate Text](http://ipython.org/_static/IPy_header.png)\n", + "![Alternate Text](https://ipython.org/_static/IPy_header.png)\n", "\"\"\")" ] }, @@ -2075,7 +2075,7 @@ "\n", "var mdcell = new IPython.MarkdownCell();\n", "mdcell.create_element();\n", - "mdcell.set_text('\\n\\n');\n", + "mdcell.set_text('\\n\\n');\n", "mdcell.render();\n", "$(element).append(mdcell.element)\n", ".removeClass()\n", @@ -2102,7 +2102,7 @@ { "data": { "text/html": [ - "
NBConvert Latex Output
NBViewer Output

" + "
NBConvert Latex Output
NBViewer Output

" ], "text/plain": [ "" @@ -2127,7 +2127,7 @@ ], "source": [ "compare_render(r\"\"\"\n", - "\n", + "\n", "\"\"\")" ] },