File tree Expand file tree Collapse file tree 5 files changed +45
-2
lines changed
Misc/NEWS.d/next/Tools-Demos Expand file tree Collapse file tree 5 files changed +45
-2
lines changed Original file line number Diff line number Diff line change 19
19
import codecs
20
20
import os
21
21
import logging
22
+ import pkgutil
22
23
import StringIO
23
24
import sys
24
25
@@ -143,6 +144,26 @@ def _newer(a, b):
143
144
return os .path .getmtime (a ) >= os .path .getmtime (b )
144
145
145
146
147
+ def load_packaged_grammar (package , grammar_source ):
148
+ """Normally, loads a pickled grammar by doing
149
+ pkgutil.get_data(package, pickled_grammar)
150
+ where *pickled_grammar* is computed from *grammar_source* by adding the
151
+ Python version and using a ``.pickle`` extension.
152
+
153
+ However, if *grammar_source* is an extant file, load_grammar(grammar_source)
154
+ is called instead. This facilities using a packaged grammar file when needed
155
+ but preserves load_grammar's automatic regeneration behavior when possible.
156
+
157
+ """
158
+ if os .path .isfile (grammar_source ):
159
+ return load_grammar (grammar_source )
160
+ pickled_name = _generate_pickle_name (os .path .basename (grammar_source ))
161
+ data = pkgutil .get_data (package , pickled_name )
162
+ g = grammar .Grammar ()
163
+ g .loads (data )
164
+ return g
165
+
166
+
146
167
def main (* args ):
147
168
"""Main program, when run as a script: produce grammar pickle files.
148
169
Original file line number Diff line number Diff line change @@ -109,6 +109,10 @@ def load(self, filename):
109
109
f .close ()
110
110
self .__dict__ .update (d )
111
111
112
+ def loads (self , pkl ):
113
+ """Load the grammar tables from a pickle bytes object."""
114
+ self .__dict__ .update (pickle .loads (pkl ))
115
+
112
116
def copy (self ):
113
117
"""
114
118
Copy the grammar.
Original file line number Diff line number Diff line change @@ -29,12 +29,12 @@ def __init__(self, grammar):
29
29
setattr (self , name , symbol )
30
30
31
31
32
- python_grammar = driver .load_grammar ( _GRAMMAR_FILE )
32
+ python_grammar = driver .load_packaged_grammar ( "lib2to3" , _GRAMMAR_FILE )
33
33
34
34
python_symbols = Symbols (python_grammar )
35
35
36
36
python_grammar_no_print_statement = python_grammar .copy ()
37
37
del python_grammar_no_print_statement .keywords ["print" ]
38
38
39
- pattern_grammar = driver .load_grammar ( _PATTERN_GRAMMAR_FILE )
39
+ pattern_grammar = driver .load_packaged_grammar ( "lib2to3" , _PATTERN_GRAMMAR_FILE )
40
40
pattern_symbols = Symbols (pattern_grammar )
Original file line number Diff line number Diff line change 11
11
from .support import driver , test_dir
12
12
13
13
# Python imports
14
+ import operator
14
15
import os
16
+ import pickle
15
17
import shutil
16
18
import subprocess
17
19
import sys
18
20
import tempfile
21
+ import types
19
22
import unittest
20
23
21
24
# Local imports
@@ -97,6 +100,18 @@ def test_load_grammar_from_subprocess(self):
97
100
finally :
98
101
shutil .rmtree (tmpdir )
99
102
103
+ def test_load_packaged_grammar (self ):
104
+ modname = __name__ + '.load_test'
105
+ class MyLoader :
106
+ def get_data (self , where ):
107
+ return pickle .dumps ({'elephant' : 19 })
108
+ class MyModule (types .ModuleType ):
109
+ __file__ = 'parsertestmodule'
110
+ __loader__ = MyLoader ()
111
+ sys .modules [modname ] = MyModule (modname )
112
+ self .addCleanup (operator .delitem , sys .modules , modname )
113
+ g = pgen2_driver .load_packaged_grammar (modname , 'Grammar.txt' )
114
+ self .assertEqual (g .elephant , 19 )
100
115
101
116
102
117
class GrammarTest (support .TestCase ):
Original file line number Diff line number Diff line change
1
+ 2to3 and lib2to3 can now read pickled grammar files using pkgutil.get_data()
2
+ rather than probing the filesystem. This lets 2to3 and lib2to3 work when run
3
+ from a zipfile.
You can’t perform that action at this time.
0 commit comments