Skip to content

Commit 0270a4b

Browse files
committed
Speed up importing of past.translation (issue #117)
Also: give more descriptive error messages if top-level packages are imported somehow on Py3.
1 parent 67971ec commit 0270a4b

File tree

23 files changed

+124
-93
lines changed

23 files changed

+124
-93
lines changed

src/_dummy_thread/__init__.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,6 @@
55
if sys.version_info[0] < 3:
66
from dummy_thread import *
77
else:
8-
raise ImportError('Cannot import module from python-future source folder')
8+
raise ImportError('This package should not be accessible on Python 3. '
9+
'Either you are trying to run from the python-future src folder '
10+
'or your installation of python-future is corrupted.')

src/_markupbase/__init__.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,6 @@
55
if sys.version_info[0] < 3:
66
from markupbase import *
77
else:
8-
raise ImportError('Cannot import module from python-future source folder')
8+
raise ImportError('This package should not be accessible on Python 3. '
9+
'Either you are trying to run from the python-future src folder '
10+
'or your installation of python-future is corrupted.')

src/_thread/__init__.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,6 @@
55
if sys.version_info[0] < 3:
66
from dummy_thread import *
77
else:
8-
raise ImportError('Cannot import module from python-future source folder')
8+
raise ImportError('This package should not be accessible on Python 3. '
9+
'Either you are trying to run from the python-future src folder '
10+
'or your installation of python-future is corrupted.')

src/builtins/__init__.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,6 @@
77
# Overwrite any old definitions with the equivalent future.builtins ones:
88
from future.builtins import *
99
else:
10-
raise ImportError('Cannot import module from python-future source folder')
10+
raise ImportError('This package should not be accessible on Python 3. '
11+
'Either you are trying to run from the python-future src folder '
12+
'or your installation of python-future is corrupted.')

src/configparser/__init__.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,11 @@
33

44
if sys.version_info[0] < 3:
55
from ConfigParser import *
6+
try:
7+
from ConfigParser import (_Chainmap, Error, InterpolationMissingOptionError)
8+
except ImportError:
9+
pass
610
else:
7-
raise ImportError('Cannot import module from python-future source folder')
11+
raise ImportError('This package should not be accessible on Python 3. '
12+
'Either you are trying to run from the python-future src folder '
13+
'or your installation of python-future is corrupted.')

src/copyreg/__init__.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
from __future__ import absolute_import
2-
from future.utils import PY3
2+
import sys
33

4-
if PY3:
5-
raise ImportError('Cannot import module from python-future source folder')
6-
from copyreg import *
7-
else:
8-
__future_module__ = True
4+
if sys.version_info[0] < 3:
95
from copy_reg import *
6+
else:
7+
raise ImportError('This package should not be accessible on Python 3. '
8+
'Either you are trying to run from the python-future src folder '
9+
'or your installation of python-future is corrupted.')

src/future/standard_library/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ def load_module(self, name):
267267
# New name. Look up the corresponding old (Py2) name:
268268
oldname = self.new_to_old[name]
269269
module = self._find_and_load_module(oldname)
270-
module.__future_module__ = True
270+
# module.__future_module__ = True
271271
else:
272272
module = self._find_and_load_module(name)
273273
# In any case, make it available under the requested (Py3) name
@@ -451,7 +451,7 @@ def install_aliases():
451451
# We look up the module in sys.modules because __import__ just returns the
452452
# top-level package:
453453
newmod = sys.modules[newmodname]
454-
newmod.__future_module__ = True
454+
# newmod.__future_module__ = True
455455

456456
__import__(oldmodname)
457457
oldmod = sys.modules[oldmodname]

src/html/__init__.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
from __future__ import absolute_import
22
import sys
3-
__future_module__ = True
43

5-
if sys.version_info[0] == 3:
6-
raise ImportError('Cannot import module from python-future source folder')
7-
else:
4+
if sys.version_info[0] < 3:
85
from future.moves.html import *
6+
else:
7+
raise ImportError('This package should not be accessible on Python 3. '
8+
'Either you are trying to run from the python-future src folder '
9+
'or your installation of python-future is corrupted.')

src/http/__init__.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
from __future__ import absolute_import
22
import sys
3-
__future_module__ = True
43

54
if sys.version_info[0] < 3:
65
pass
76
else:
8-
raise ImportError('Cannot import module from python-future source folder')
7+
raise ImportError('This package should not be accessible on Python 3. '
8+
'Either you are trying to run from the python-future src folder '
9+
'or your installation of python-future is corrupted.')

src/http/client.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
from __future__ import absolute_import
22
import sys
3-
__future_module__ = True
43

5-
if sys.version_info[0] < 3:
6-
from httplib import *
7-
else:
8-
raise ImportError('Cannot import module from python-future source folder')
4+
assert sys.version_info[0] < 3
5+
6+
from httplib import *

src/http/cookiejar.py

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
from __future__ import absolute_import
2-
from future.utils import PY3
2+
import sys
33

4-
if PY3:
5-
from http.cookiejar import *
6-
else:
7-
__future_module__ = True
8-
from cookielib import *
4+
assert sys.version_info[0] < 3
5+
6+
from cookielib import *

src/http/cookies.py

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
from __future__ import absolute_import
2-
from future.utils import PY3
2+
import sys
33

4-
if PY3:
5-
from http.cookies import *
6-
else:
7-
__future_module__ = True
8-
from Cookie import *
9-
from Cookie import Morsel # left out of __all__ on Py2.7!
4+
assert sys.version_info[0] < 3
5+
6+
from Cookie import *
7+
from Cookie import Morsel # left out of __all__ on Py2.7!

src/http/server.py

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,18 @@
11
from __future__ import absolute_import
22
import sys
3-
__future_module__ = True
43

5-
if sys.version_info[0] == 3:
6-
raise ImportError('Cannot import module from python-future source folder')
7-
else:
8-
__future_module__ = True
9-
from BaseHTTPServer import *
10-
from CGIHTTPServer import *
11-
from SimpleHTTPServer import *
4+
assert sys.version_info[0] < 3
5+
6+
from BaseHTTPServer import *
7+
from CGIHTTPServer import *
8+
from SimpleHTTPServer import *
9+
try:
10+
from CGIHTTPServer import _url_collapse_path # needed for a test
11+
except ImportError:
1212
try:
13-
from CGIHTTPServer import _url_collapse_path # needed for a test
13+
# Python 2.7.0 to 2.7.3
14+
from CGIHTTPServer import (
15+
_url_collapse_path_split as _url_collapse_path)
1416
except ImportError:
15-
try:
16-
# Python 2.7.0 to 2.7.3
17-
from CGIHTTPServer import (
18-
_url_collapse_path_split as _url_collapse_path)
19-
except ImportError:
20-
# Doesn't exist on Python 2.6.x. Ignore it.
21-
pass
17+
# Doesn't exist on Python 2.6.x. Ignore it.
18+
pass

src/past/__init__.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,10 +82,8 @@
8282
---------
8383
Copyright 2013-2014 Python Charmers Pty Ltd, Australia.
8484
The software is distributed under an MIT licence. See LICENSE.txt.
85-
8685
"""
8786

88-
# from past.builtins import *
8987

9088
from past.translation import install_hooks as autotranslate
9189
from future import __version__, __copyright__, __license__

src/past/translation/__init__.py

Lines changed: 40 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@
4343

4444
from libfuturize import fixes
4545

46-
__version__ = '0.1.0'
4746

4847
logger = logging.getLogger(__name__)
4948
logger.setLevel(logging.DEBUG)
@@ -54,12 +53,6 @@
5453
list(fixes.lib2to3_fix_names_stage2))
5554

5655

57-
# There are two possible grammars: with or without the print statement.
58-
# Hence we have two possible refactoring tool implementations.
59-
_rt = RefactoringTool(myfixes)
60-
_rtp = RefactoringTool(myfixes, {'print_function': True})
61-
62-
#
6356
# We detect whether the code is Py2 or Py3 by applying certain lib2to3 fixers
6457
# to it. If the diff is empty, it's Python 3 code.
6558

@@ -122,12 +115,42 @@
122115
]
123116

124117

125-
_rt_py2_detect = RefactoringTool(py2_detect_fixers)
126-
_rtp_py2_detect = RefactoringTool(py2_detect_fixers,
127-
{'print_function': True})
118+
class RTs:
119+
"""
120+
A namespace for the refactoring tools. This avoids creating these at
121+
the module level, which slows down the module import. (See issue #117).
122+
123+
There are two possible grammars: with or without the print statement.
124+
Hence we have two possible refactoring tool implementations.
125+
"""
126+
_rt = None
127+
_rtp = None
128+
_rt_py2_detect = None
129+
_rtp_py2_detect = None
130+
131+
@staticmethod
132+
def setup():
133+
"""
134+
Call this before using the refactoring tools to create them on demand
135+
if needed.
136+
"""
137+
if None in [RTs._rt, RTs._rtp]:
138+
RTs._rt = RefactoringTool(myfixes)
139+
RTs._rtp = RefactoringTool(myfixes, {'print_function': True})
140+
141+
142+
@staticmethod
143+
def setup_detect_python2():
144+
"""
145+
Call this before using the refactoring tools to create them on demand
146+
if needed.
147+
"""
148+
if None in [RTs._rt_py2_detect, RTs._rtp_py2_detect]:
149+
RTs._rt_py2_detect = RefactoringTool(py2_detect_fixers)
150+
RTs._rtp_py2_detect = RefactoringTool(py2_detect_fixers,
151+
{'print_function': True})
128152

129153

130-
#
131154
# We need to find a prefix for the standard library, as we don't want to
132155
# process any files there (they will already be Python 3).
133156
#
@@ -145,7 +168,6 @@
145168
# Instead, we use the portion of the path common to both the stdlib modules
146169
# ``math`` and ``urllib``.
147170

148-
import os, sys
149171
def splitall(path):
150172
"""
151173
Split a path into all components. From Python Cookbook.
@@ -179,21 +201,20 @@ def common_substring(s1, s2):
179201
chunks.append(dir1)
180202
return os.path.join(*chunks)
181203

182-
# import math
183-
# import urllib
184204
# _stdlibprefix = common_substring(math.__file__, urllib.__file__)
185205

186206

187207
def detect_python2(source, pathname):
188208
"""
189209
Returns a bool indicating whether we think the code is Py2
190210
"""
211+
RTs.setup_detect_python2()
191212
try:
192-
tree = _rt_py2_detect.refactor_string(source, pathname)
213+
tree = RTs._rt_py2_detect.refactor_string(source, pathname)
193214
except ParseError as e:
194215
if e.msg != 'bad input' or e.value != '=':
195216
raise
196-
tree = _rtp.refactor_string(source, pathname)
217+
tree = RTs._rtp.refactor_string(source, pathname)
197218

198219
if source != str(tree)[:-1]: # remove added newline
199220
# The above fixers made changes, so we conclude it's Python 2 code
@@ -282,13 +303,14 @@ def transform(self, source):
282303
# if that's better for you
283304

284305
# lib2to3 likes a newline at the end
306+
RTs.setup()
285307
source += '\n'
286308
try:
287-
tree = _rt.refactor_string(source, self.pathname)
309+
tree = RTs._rt.refactor_string(source, self.pathname)
288310
except ParseError as e:
289311
if e.msg != 'bad input' or e.value != '=':
290312
raise
291-
tree = _rtp.refactor_string(source, self.pathname)
313+
tree = RTs._rtp.refactor_string(source, self.pathname)
292314
# could optimise a bit for only doing str(tree) if
293315
# getattr(tree, 'was_changed', False) returns True
294316
return str(tree)[:-1] # remove added newline

src/queue/__init__.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,6 @@
55
if sys.version_info[0] < 3:
66
from Queue import *
77
else:
8-
raise ImportError('Cannot import module from python-future source folder')
8+
raise ImportError('This package should not be accessible on Python 3. '
9+
'Either you are trying to run from the python-future src folder '
10+
'or your installation of python-future is corrupted.')

src/reprlib/__init__.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
from __future__ import absolute_import
22
import sys
3-
__future_module__ = True
43

54
if sys.version_info[0] < 3:
65
from repr import *
76
else:
8-
raise ImportError('Cannot import module from python-future source folder')
7+
raise ImportError('This package should not be accessible on Python 3. '
8+
'Either you are trying to run from the python-future src folder '
9+
'or your installation of python-future is corrupted.')

src/socketserver/__init__.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
from __future__ import absolute_import
22
import sys
3-
__future_module__ = True
43

54
if sys.version_info[0] < 3:
65
from SocketServer import *
76
else:
8-
raise ImportError('Cannot import module from python-future source folder')
7+
raise ImportError('This package should not be accessible on Python 3. '
8+
'Either you are trying to run from the python-future src folder '
9+
'or your installation of python-future is corrupted.')

src/tkinter/__init__.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
from __future__ import absolute_import
22
import sys
3-
__future_module__ = True
43

54
if sys.version_info[0] < 3:
65
from Tkinter import *
76
else:
8-
raise ImportError('Cannot import module from python-future source folder')
7+
raise ImportError('This package should not be accessible on Python 3. '
8+
'Either you are trying to run from the python-future src folder '
9+
'or your installation of python-future is corrupted.')

src/winreg/__init__.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,6 @@
55
if sys.version_info[0] < 3:
66
from _winreg import *
77
else:
8-
raise ImportError('Cannot import module from python-future source folder')
8+
raise ImportError('This package should not be accessible on Python 3. '
9+
'Either you are trying to run from the python-future src folder '
10+
'or your installation of python-future is corrupted.')

src/xmlrpc/__init__.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
from __future__ import absolute_import
22
import sys
3-
__future_module__ = True
43

54
if sys.version_info[0] < 3:
65
pass
76
else:
8-
raise ImportError('Cannot import module from python-future source folder')
7+
raise ImportError('This package should not be accessible on Python 3. '
8+
'Either you are trying to run from the python-future src folder '
9+
'or your installation of python-future is corrupted.')

src/xmlrpc/client.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
from __future__ import absolute_import
2-
from future.utils import PY3
2+
import sys
33

4-
if PY3:
5-
from xmlrpc.client import *
6-
else:
7-
from xmlrpclib import *
4+
assert sys.version_info[0] < 3
5+
from xmlrpclib import *

src/xmlrpc/server.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
from __future__ import absolute_import
2-
from future.utils import PY3
2+
import sys
33

4-
if PY3:
5-
from xmlrpc.server import *
6-
else:
7-
from xmlrpclib import *
4+
assert sys.version_info[0] < 3
5+
from xmlrpclib import *

0 commit comments

Comments
 (0)