##// END OF EJS Templates
imp module deprecated in 3.4...
Matthias Bussonnier -
Show More
@@ -1,176 +1,180 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """A class for managing IPython extensions."""
2 """A class for managing IPython extensions."""
3
3
4 # Copyright (c) IPython Development Team.
4 # Copyright (c) IPython Development Team.
5 # Distributed under the terms of the Modified BSD License.
5 # Distributed under the terms of the Modified BSD License.
6
6
7 import os
7 import os
8 from shutil import copyfile
8 from shutil import copyfile
9 import sys
9 import sys
10
10
11 from traitlets.config.configurable import Configurable
11 from traitlets.config.configurable import Configurable
12 from IPython.utils.path import ensure_dir_exists
12 from IPython.utils.path import ensure_dir_exists
13 from traitlets import Instance
13 from traitlets import Instance
14 from IPython.utils.py3compat import PY3
14 from IPython.utils.py3compat import PY3
15 if PY3:
15 if PY3:
16 from imp import reload
16 try:
17 from importlib import reload
18 except ImportError :
19 ## deprecated since 3.4
20 from imp import reload
17
21
18 #-----------------------------------------------------------------------------
22 #-----------------------------------------------------------------------------
19 # Main class
23 # Main class
20 #-----------------------------------------------------------------------------
24 #-----------------------------------------------------------------------------
21
25
22 class ExtensionManager(Configurable):
26 class ExtensionManager(Configurable):
23 """A class to manage IPython extensions.
27 """A class to manage IPython extensions.
24
28
25 An IPython extension is an importable Python module that has
29 An IPython extension is an importable Python module that has
26 a function with the signature::
30 a function with the signature::
27
31
28 def load_ipython_extension(ipython):
32 def load_ipython_extension(ipython):
29 # Do things with ipython
33 # Do things with ipython
30
34
31 This function is called after your extension is imported and the
35 This function is called after your extension is imported and the
32 currently active :class:`InteractiveShell` instance is passed as
36 currently active :class:`InteractiveShell` instance is passed as
33 the only argument. You can do anything you want with IPython at
37 the only argument. You can do anything you want with IPython at
34 that point, including defining new magic and aliases, adding new
38 that point, including defining new magic and aliases, adding new
35 components, etc.
39 components, etc.
36
40
37 You can also optionally define an :func:`unload_ipython_extension(ipython)`
41 You can also optionally define an :func:`unload_ipython_extension(ipython)`
38 function, which will be called if the user unloads or reloads the extension.
42 function, which will be called if the user unloads or reloads the extension.
39 The extension manager will only call :func:`load_ipython_extension` again
43 The extension manager will only call :func:`load_ipython_extension` again
40 if the extension is reloaded.
44 if the extension is reloaded.
41
45
42 You can put your extension modules anywhere you want, as long as
46 You can put your extension modules anywhere you want, as long as
43 they can be imported by Python's standard import mechanism. However,
47 they can be imported by Python's standard import mechanism. However,
44 to make it easy to write extensions, you can also put your extensions
48 to make it easy to write extensions, you can also put your extensions
45 in ``os.path.join(self.ipython_dir, 'extensions')``. This directory
49 in ``os.path.join(self.ipython_dir, 'extensions')``. This directory
46 is added to ``sys.path`` automatically.
50 is added to ``sys.path`` automatically.
47 """
51 """
48
52
49 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC',
53 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC',
50 allow_none=True)
54 allow_none=True)
51
55
52 def __init__(self, shell=None, **kwargs):
56 def __init__(self, shell=None, **kwargs):
53 super(ExtensionManager, self).__init__(shell=shell, **kwargs)
57 super(ExtensionManager, self).__init__(shell=shell, **kwargs)
54 self.shell.on_trait_change(
58 self.shell.on_trait_change(
55 self._on_ipython_dir_changed, 'ipython_dir'
59 self._on_ipython_dir_changed, 'ipython_dir'
56 )
60 )
57 self.loaded = set()
61 self.loaded = set()
58
62
59 def __del__(self):
63 def __del__(self):
60 self.shell.on_trait_change(
64 self.shell.on_trait_change(
61 self._on_ipython_dir_changed, 'ipython_dir', remove=True
65 self._on_ipython_dir_changed, 'ipython_dir', remove=True
62 )
66 )
63
67
64 @property
68 @property
65 def ipython_extension_dir(self):
69 def ipython_extension_dir(self):
66 return os.path.join(self.shell.ipython_dir, u'extensions')
70 return os.path.join(self.shell.ipython_dir, u'extensions')
67
71
68 def _on_ipython_dir_changed(self):
72 def _on_ipython_dir_changed(self):
69 ensure_dir_exists(self.ipython_extension_dir)
73 ensure_dir_exists(self.ipython_extension_dir)
70
74
71 def load_extension(self, module_str):
75 def load_extension(self, module_str):
72 """Load an IPython extension by its module name.
76 """Load an IPython extension by its module name.
73
77
74 Returns the string "already loaded" if the extension is already loaded,
78 Returns the string "already loaded" if the extension is already loaded,
75 "no load function" if the module doesn't have a load_ipython_extension
79 "no load function" if the module doesn't have a load_ipython_extension
76 function, or None if it succeeded.
80 function, or None if it succeeded.
77 """
81 """
78 if module_str in self.loaded:
82 if module_str in self.loaded:
79 return "already loaded"
83 return "already loaded"
80
84
81 from IPython.utils.syspathcontext import prepended_to_syspath
85 from IPython.utils.syspathcontext import prepended_to_syspath
82
86
83 with self.shell.builtin_trap:
87 with self.shell.builtin_trap:
84 if module_str not in sys.modules:
88 if module_str not in sys.modules:
85 with prepended_to_syspath(self.ipython_extension_dir):
89 with prepended_to_syspath(self.ipython_extension_dir):
86 __import__(module_str)
90 __import__(module_str)
87 mod = sys.modules[module_str]
91 mod = sys.modules[module_str]
88 if self._call_load_ipython_extension(mod):
92 if self._call_load_ipython_extension(mod):
89 self.loaded.add(module_str)
93 self.loaded.add(module_str)
90 else:
94 else:
91 return "no load function"
95 return "no load function"
92
96
93 def unload_extension(self, module_str):
97 def unload_extension(self, module_str):
94 """Unload an IPython extension by its module name.
98 """Unload an IPython extension by its module name.
95
99
96 This function looks up the extension's name in ``sys.modules`` and
100 This function looks up the extension's name in ``sys.modules`` and
97 simply calls ``mod.unload_ipython_extension(self)``.
101 simply calls ``mod.unload_ipython_extension(self)``.
98
102
99 Returns the string "no unload function" if the extension doesn't define
103 Returns the string "no unload function" if the extension doesn't define
100 a function to unload itself, "not loaded" if the extension isn't loaded,
104 a function to unload itself, "not loaded" if the extension isn't loaded,
101 otherwise None.
105 otherwise None.
102 """
106 """
103 if module_str not in self.loaded:
107 if module_str not in self.loaded:
104 return "not loaded"
108 return "not loaded"
105
109
106 if module_str in sys.modules:
110 if module_str in sys.modules:
107 mod = sys.modules[module_str]
111 mod = sys.modules[module_str]
108 if self._call_unload_ipython_extension(mod):
112 if self._call_unload_ipython_extension(mod):
109 self.loaded.discard(module_str)
113 self.loaded.discard(module_str)
110 else:
114 else:
111 return "no unload function"
115 return "no unload function"
112
116
113 def reload_extension(self, module_str):
117 def reload_extension(self, module_str):
114 """Reload an IPython extension by calling reload.
118 """Reload an IPython extension by calling reload.
115
119
116 If the module has not been loaded before,
120 If the module has not been loaded before,
117 :meth:`InteractiveShell.load_extension` is called. Otherwise
121 :meth:`InteractiveShell.load_extension` is called. Otherwise
118 :func:`reload` is called and then the :func:`load_ipython_extension`
122 :func:`reload` is called and then the :func:`load_ipython_extension`
119 function of the module, if it exists is called.
123 function of the module, if it exists is called.
120 """
124 """
121 from IPython.utils.syspathcontext import prepended_to_syspath
125 from IPython.utils.syspathcontext import prepended_to_syspath
122
126
123 if (module_str in self.loaded) and (module_str in sys.modules):
127 if (module_str in self.loaded) and (module_str in sys.modules):
124 self.unload_extension(module_str)
128 self.unload_extension(module_str)
125 mod = sys.modules[module_str]
129 mod = sys.modules[module_str]
126 with prepended_to_syspath(self.ipython_extension_dir):
130 with prepended_to_syspath(self.ipython_extension_dir):
127 reload(mod)
131 reload(mod)
128 if self._call_load_ipython_extension(mod):
132 if self._call_load_ipython_extension(mod):
129 self.loaded.add(module_str)
133 self.loaded.add(module_str)
130 else:
134 else:
131 self.load_extension(module_str)
135 self.load_extension(module_str)
132
136
133 def _call_load_ipython_extension(self, mod):
137 def _call_load_ipython_extension(self, mod):
134 if hasattr(mod, 'load_ipython_extension'):
138 if hasattr(mod, 'load_ipython_extension'):
135 mod.load_ipython_extension(self.shell)
139 mod.load_ipython_extension(self.shell)
136 return True
140 return True
137
141
138 def _call_unload_ipython_extension(self, mod):
142 def _call_unload_ipython_extension(self, mod):
139 if hasattr(mod, 'unload_ipython_extension'):
143 if hasattr(mod, 'unload_ipython_extension'):
140 mod.unload_ipython_extension(self.shell)
144 mod.unload_ipython_extension(self.shell)
141 return True
145 return True
142
146
143 def install_extension(self, url, filename=None):
147 def install_extension(self, url, filename=None):
144 """Download and install an IPython extension.
148 """Download and install an IPython extension.
145
149
146 If filename is given, the file will be so named (inside the extension
150 If filename is given, the file will be so named (inside the extension
147 directory). Otherwise, the name from the URL will be used. The file must
151 directory). Otherwise, the name from the URL will be used. The file must
148 have a .py or .zip extension; otherwise, a ValueError will be raised.
152 have a .py or .zip extension; otherwise, a ValueError will be raised.
149
153
150 Returns the full path to the installed file.
154 Returns the full path to the installed file.
151 """
155 """
152 # Ensure the extension directory exists
156 # Ensure the extension directory exists
153 ensure_dir_exists(self.ipython_extension_dir)
157 ensure_dir_exists(self.ipython_extension_dir)
154
158
155 if os.path.isfile(url):
159 if os.path.isfile(url):
156 src_filename = os.path.basename(url)
160 src_filename = os.path.basename(url)
157 copy = copyfile
161 copy = copyfile
158 else:
162 else:
159 # Deferred imports
163 # Deferred imports
160 try:
164 try:
161 from urllib.parse import urlparse # Py3
165 from urllib.parse import urlparse # Py3
162 from urllib.request import urlretrieve
166 from urllib.request import urlretrieve
163 except ImportError:
167 except ImportError:
164 from urlparse import urlparse
168 from urlparse import urlparse
165 from urllib import urlretrieve
169 from urllib import urlretrieve
166 src_filename = urlparse(url).path.split('/')[-1]
170 src_filename = urlparse(url).path.split('/')[-1]
167 copy = urlretrieve
171 copy = urlretrieve
168
172
169 if filename is None:
173 if filename is None:
170 filename = src_filename
174 filename = src_filename
171 if os.path.splitext(filename)[1] not in ('.py', '.zip'):
175 if os.path.splitext(filename)[1] not in ('.py', '.zip'):
172 raise ValueError("The file must have a .py or .zip extension", filename)
176 raise ValueError("The file must have a .py or .zip extension", filename)
173
177
174 filename = os.path.join(self.ipython_extension_dir, filename)
178 filename = os.path.join(self.ipython_extension_dir, filename)
175 copy(url, filename)
179 copy(url, filename)
176 return filename
180 return filename
@@ -1,245 +1,249 b''
1 """
1 """
2 Tools to open .py files as Unicode, using the encoding specified within the file,
2 Tools to open .py files as Unicode, using the encoding specified within the file,
3 as per PEP 263.
3 as per PEP 263.
4
4
5 Much of the code is taken from the tokenize module in Python 3.2.
5 Much of the code is taken from the tokenize module in Python 3.2.
6 """
6 """
7 from __future__ import absolute_import
7 from __future__ import absolute_import
8
8
9 import io
9 import io
10 from io import TextIOWrapper, BytesIO
10 from io import TextIOWrapper, BytesIO
11 import os.path
11 import os.path
12 import re
12 import re
13
13
14 from .py3compat import unicode_type
14 from .py3compat import unicode_type
15
15
16 cookie_re = re.compile(r"coding[:=]\s*([-\w.]+)", re.UNICODE)
16 cookie_re = re.compile(r"coding[:=]\s*([-\w.]+)", re.UNICODE)
17 cookie_comment_re = re.compile(r"^\s*#.*coding[:=]\s*([-\w.]+)", re.UNICODE)
17 cookie_comment_re = re.compile(r"^\s*#.*coding[:=]\s*([-\w.]+)", re.UNICODE)
18
18
19 try:
19 try:
20 # Available in Python 3
20 # Available in Python 3
21 from tokenize import detect_encoding
21 from tokenize import detect_encoding
22 except ImportError:
22 except ImportError:
23 from codecs import lookup, BOM_UTF8
23 from codecs import lookup, BOM_UTF8
24
24
25 # Copied from Python 3.2 tokenize
25 # Copied from Python 3.2 tokenize
26 def _get_normal_name(orig_enc):
26 def _get_normal_name(orig_enc):
27 """Imitates get_normal_name in tokenizer.c."""
27 """Imitates get_normal_name in tokenizer.c."""
28 # Only care about the first 12 characters.
28 # Only care about the first 12 characters.
29 enc = orig_enc[:12].lower().replace("_", "-")
29 enc = orig_enc[:12].lower().replace("_", "-")
30 if enc == "utf-8" or enc.startswith("utf-8-"):
30 if enc == "utf-8" or enc.startswith("utf-8-"):
31 return "utf-8"
31 return "utf-8"
32 if enc in ("latin-1", "iso-8859-1", "iso-latin-1") or \
32 if enc in ("latin-1", "iso-8859-1", "iso-latin-1") or \
33 enc.startswith(("latin-1-", "iso-8859-1-", "iso-latin-1-")):
33 enc.startswith(("latin-1-", "iso-8859-1-", "iso-latin-1-")):
34 return "iso-8859-1"
34 return "iso-8859-1"
35 return orig_enc
35 return orig_enc
36
36
37 # Copied from Python 3.2 tokenize
37 # Copied from Python 3.2 tokenize
38 def detect_encoding(readline):
38 def detect_encoding(readline):
39 """
39 """
40 The detect_encoding() function is used to detect the encoding that should
40 The detect_encoding() function is used to detect the encoding that should
41 be used to decode a Python source file. It requires one argment, readline,
41 be used to decode a Python source file. It requires one argment, readline,
42 in the same way as the tokenize() generator.
42 in the same way as the tokenize() generator.
43
43
44 It will call readline a maximum of twice, and return the encoding used
44 It will call readline a maximum of twice, and return the encoding used
45 (as a string) and a list of any lines (left as bytes) it has read in.
45 (as a string) and a list of any lines (left as bytes) it has read in.
46
46
47 It detects the encoding from the presence of a utf-8 bom or an encoding
47 It detects the encoding from the presence of a utf-8 bom or an encoding
48 cookie as specified in pep-0263. If both a bom and a cookie are present,
48 cookie as specified in pep-0263. If both a bom and a cookie are present,
49 but disagree, a SyntaxError will be raised. If the encoding cookie is an
49 but disagree, a SyntaxError will be raised. If the encoding cookie is an
50 invalid charset, raise a SyntaxError. Note that if a utf-8 bom is found,
50 invalid charset, raise a SyntaxError. Note that if a utf-8 bom is found,
51 'utf-8-sig' is returned.
51 'utf-8-sig' is returned.
52
52
53 If no encoding is specified, then the default of 'utf-8' will be returned.
53 If no encoding is specified, then the default of 'utf-8' will be returned.
54 """
54 """
55 bom_found = False
55 bom_found = False
56 encoding = None
56 encoding = None
57 default = 'utf-8'
57 default = 'utf-8'
58 def read_or_stop():
58 def read_or_stop():
59 try:
59 try:
60 return readline()
60 return readline()
61 except StopIteration:
61 except StopIteration:
62 return b''
62 return b''
63
63
64 def find_cookie(line):
64 def find_cookie(line):
65 try:
65 try:
66 line_string = line.decode('ascii')
66 line_string = line.decode('ascii')
67 except UnicodeDecodeError:
67 except UnicodeDecodeError:
68 return None
68 return None
69
69
70 matches = cookie_re.findall(line_string)
70 matches = cookie_re.findall(line_string)
71 if not matches:
71 if not matches:
72 return None
72 return None
73 encoding = _get_normal_name(matches[0])
73 encoding = _get_normal_name(matches[0])
74 try:
74 try:
75 codec = lookup(encoding)
75 codec = lookup(encoding)
76 except LookupError:
76 except LookupError:
77 # This behaviour mimics the Python interpreter
77 # This behaviour mimics the Python interpreter
78 raise SyntaxError("unknown encoding: " + encoding)
78 raise SyntaxError("unknown encoding: " + encoding)
79
79
80 if bom_found:
80 if bom_found:
81 if codec.name != 'utf-8':
81 if codec.name != 'utf-8':
82 # This behaviour mimics the Python interpreter
82 # This behaviour mimics the Python interpreter
83 raise SyntaxError('encoding problem: utf-8')
83 raise SyntaxError('encoding problem: utf-8')
84 encoding += '-sig'
84 encoding += '-sig'
85 return encoding
85 return encoding
86
86
87 first = read_or_stop()
87 first = read_or_stop()
88 if first.startswith(BOM_UTF8):
88 if first.startswith(BOM_UTF8):
89 bom_found = True
89 bom_found = True
90 first = first[3:]
90 first = first[3:]
91 default = 'utf-8-sig'
91 default = 'utf-8-sig'
92 if not first:
92 if not first:
93 return default, []
93 return default, []
94
94
95 encoding = find_cookie(first)
95 encoding = find_cookie(first)
96 if encoding:
96 if encoding:
97 return encoding, [first]
97 return encoding, [first]
98
98
99 second = read_or_stop()
99 second = read_or_stop()
100 if not second:
100 if not second:
101 return default, [first]
101 return default, [first]
102
102
103 encoding = find_cookie(second)
103 encoding = find_cookie(second)
104 if encoding:
104 if encoding:
105 return encoding, [first, second]
105 return encoding, [first, second]
106
106
107 return default, [first, second]
107 return default, [first, second]
108
108
109 try:
109 try:
110 # Available in Python 3.2 and above.
110 # Available in Python 3.2 and above.
111 from tokenize import open
111 from tokenize import open
112 except ImportError:
112 except ImportError:
113 # Copied from Python 3.2 tokenize
113 # Copied from Python 3.2 tokenize
114 def open(filename):
114 def open(filename):
115 """Open a file in read only mode using the encoding detected by
115 """Open a file in read only mode using the encoding detected by
116 detect_encoding().
116 detect_encoding().
117 """
117 """
118 buffer = io.open(filename, 'rb') # Tweaked to use io.open for Python 2
118 buffer = io.open(filename, 'rb') # Tweaked to use io.open for Python 2
119 encoding, lines = detect_encoding(buffer.readline)
119 encoding, lines = detect_encoding(buffer.readline)
120 buffer.seek(0)
120 buffer.seek(0)
121 text = TextIOWrapper(buffer, encoding, line_buffering=True)
121 text = TextIOWrapper(buffer, encoding, line_buffering=True)
122 text.mode = 'r'
122 text.mode = 'r'
123 return text
123 return text
124
124
125 def source_to_unicode(txt, errors='replace', skip_encoding_cookie=True):
125 def source_to_unicode(txt, errors='replace', skip_encoding_cookie=True):
126 """Converts a bytes string with python source code to unicode.
126 """Converts a bytes string with python source code to unicode.
127
127
128 Unicode strings are passed through unchanged. Byte strings are checked
128 Unicode strings are passed through unchanged. Byte strings are checked
129 for the python source file encoding cookie to determine encoding.
129 for the python source file encoding cookie to determine encoding.
130 txt can be either a bytes buffer or a string containing the source
130 txt can be either a bytes buffer or a string containing the source
131 code.
131 code.
132 """
132 """
133 if isinstance(txt, unicode_type):
133 if isinstance(txt, unicode_type):
134 return txt
134 return txt
135 if isinstance(txt, bytes):
135 if isinstance(txt, bytes):
136 buffer = BytesIO(txt)
136 buffer = BytesIO(txt)
137 else:
137 else:
138 buffer = txt
138 buffer = txt
139 try:
139 try:
140 encoding, _ = detect_encoding(buffer.readline)
140 encoding, _ = detect_encoding(buffer.readline)
141 except SyntaxError:
141 except SyntaxError:
142 encoding = "ascii"
142 encoding = "ascii"
143 buffer.seek(0)
143 buffer.seek(0)
144 text = TextIOWrapper(buffer, encoding, errors=errors, line_buffering=True)
144 text = TextIOWrapper(buffer, encoding, errors=errors, line_buffering=True)
145 text.mode = 'r'
145 text.mode = 'r'
146 if skip_encoding_cookie:
146 if skip_encoding_cookie:
147 return u"".join(strip_encoding_cookie(text))
147 return u"".join(strip_encoding_cookie(text))
148 else:
148 else:
149 return text.read()
149 return text.read()
150
150
151 def strip_encoding_cookie(filelike):
151 def strip_encoding_cookie(filelike):
152 """Generator to pull lines from a text-mode file, skipping the encoding
152 """Generator to pull lines from a text-mode file, skipping the encoding
153 cookie if it is found in the first two lines.
153 cookie if it is found in the first two lines.
154 """
154 """
155 it = iter(filelike)
155 it = iter(filelike)
156 try:
156 try:
157 first = next(it)
157 first = next(it)
158 if not cookie_comment_re.match(first):
158 if not cookie_comment_re.match(first):
159 yield first
159 yield first
160 second = next(it)
160 second = next(it)
161 if not cookie_comment_re.match(second):
161 if not cookie_comment_re.match(second):
162 yield second
162 yield second
163 except StopIteration:
163 except StopIteration:
164 return
164 return
165
165
166 for line in it:
166 for line in it:
167 yield line
167 yield line
168
168
169 def read_py_file(filename, skip_encoding_cookie=True):
169 def read_py_file(filename, skip_encoding_cookie=True):
170 """Read a Python file, using the encoding declared inside the file.
170 """Read a Python file, using the encoding declared inside the file.
171
171
172 Parameters
172 Parameters
173 ----------
173 ----------
174 filename : str
174 filename : str
175 The path to the file to read.
175 The path to the file to read.
176 skip_encoding_cookie : bool
176 skip_encoding_cookie : bool
177 If True (the default), and the encoding declaration is found in the first
177 If True (the default), and the encoding declaration is found in the first
178 two lines, that line will be excluded from the output - compiling a
178 two lines, that line will be excluded from the output - compiling a
179 unicode string with an encoding declaration is a SyntaxError in Python 2.
179 unicode string with an encoding declaration is a SyntaxError in Python 2.
180
180
181 Returns
181 Returns
182 -------
182 -------
183 A unicode string containing the contents of the file.
183 A unicode string containing the contents of the file.
184 """
184 """
185 with open(filename) as f: # the open function defined in this module.
185 with open(filename) as f: # the open function defined in this module.
186 if skip_encoding_cookie:
186 if skip_encoding_cookie:
187 return "".join(strip_encoding_cookie(f))
187 return "".join(strip_encoding_cookie(f))
188 else:
188 else:
189 return f.read()
189 return f.read()
190
190
191 def read_py_url(url, errors='replace', skip_encoding_cookie=True):
191 def read_py_url(url, errors='replace', skip_encoding_cookie=True):
192 """Read a Python file from a URL, using the encoding declared inside the file.
192 """Read a Python file from a URL, using the encoding declared inside the file.
193
193
194 Parameters
194 Parameters
195 ----------
195 ----------
196 url : str
196 url : str
197 The URL from which to fetch the file.
197 The URL from which to fetch the file.
198 errors : str
198 errors : str
199 How to handle decoding errors in the file. Options are the same as for
199 How to handle decoding errors in the file. Options are the same as for
200 bytes.decode(), but here 'replace' is the default.
200 bytes.decode(), but here 'replace' is the default.
201 skip_encoding_cookie : bool
201 skip_encoding_cookie : bool
202 If True (the default), and the encoding declaration is found in the first
202 If True (the default), and the encoding declaration is found in the first
203 two lines, that line will be excluded from the output - compiling a
203 two lines, that line will be excluded from the output - compiling a
204 unicode string with an encoding declaration is a SyntaxError in Python 2.
204 unicode string with an encoding declaration is a SyntaxError in Python 2.
205
205
206 Returns
206 Returns
207 -------
207 -------
208 A unicode string containing the contents of the file.
208 A unicode string containing the contents of the file.
209 """
209 """
210 # Deferred import for faster start
210 # Deferred import for faster start
211 try:
211 try:
212 from urllib.request import urlopen # Py 3
212 from urllib.request import urlopen # Py 3
213 except ImportError:
213 except ImportError:
214 from urllib import urlopen
214 from urllib import urlopen
215 response = urlopen(url)
215 response = urlopen(url)
216 buffer = io.BytesIO(response.read())
216 buffer = io.BytesIO(response.read())
217 return source_to_unicode(buffer, errors, skip_encoding_cookie)
217 return source_to_unicode(buffer, errors, skip_encoding_cookie)
218
218
219 def _list_readline(x):
219 def _list_readline(x):
220 """Given a list, returns a readline() function that returns the next element
220 """Given a list, returns a readline() function that returns the next element
221 with each call.
221 with each call.
222 """
222 """
223 x = iter(x)
223 x = iter(x)
224 def readline():
224 def readline():
225 return next(x)
225 return next(x)
226 return readline
226 return readline
227
227
228 # Code for going between .py files and cached .pyc files ----------------------
228 # Code for going between .py files and cached .pyc files ----------------------
229
229
230 try: # Python 3.2, see PEP 3147
230 try: # Python 3.2, see PEP 3147
231 from imp import source_from_cache, cache_from_source
231 try:
232 from importlib.util import source_from_cache, cache_from_source
233 except ImportError :
234 ## deprecated since 3.4
235 from imp import source_from_cache, cache_from_source
232 except ImportError:
236 except ImportError:
233 # Python <= 3.1: .pyc files go next to .py
237 # Python <= 3.1: .pyc files go next to .py
234 def source_from_cache(path):
238 def source_from_cache(path):
235 basename, ext = os.path.splitext(path)
239 basename, ext = os.path.splitext(path)
236 if ext not in ('.pyc', '.pyo'):
240 if ext not in ('.pyc', '.pyo'):
237 raise ValueError('Not a cached Python file extension', ext)
241 raise ValueError('Not a cached Python file extension', ext)
238 # Should we look for .pyw files?
242 # Should we look for .pyw files?
239 return basename + '.py'
243 return basename + '.py'
240
244
241 def cache_from_source(path, debug_override=None):
245 def cache_from_source(path, debug_override=None):
242 if debug_override is None:
246 if debug_override is None:
243 debug_override = __debug__
247 debug_override = __debug__
244 basename, ext = os.path.splitext(path)
248 basename, ext = os.path.splitext(path)
245 return basename + '.pyc' if debug_override else '.pyo'
249 return basename + '.pyc' if debug_override else '.pyo'
General Comments 0
You need to be logged in to leave comments. Login now