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 2020import io
2121import os
2222import logging
23+ import pkgutil
2324import sys
2425
2526# Pgen imports
@@ -143,6 +144,26 @@ def _newer(a, b):
143144 return os .path .getmtime (a ) >= os .path .getmtime (b )
144145
145146
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+
146167def main (* args ):
147168 """Main program, when run as a script: produce grammar pickle files.
148169
Original file line number Diff line number Diff line change @@ -108,6 +108,10 @@ def load(self, filename):
108108 d = pickle .load (f )
109109 self .__dict__ .update (d )
110110
111+ def loads (self , pkl ):
112+ """Load the grammar tables from a pickle bytes object."""
113+ self .__dict__ .update (pickle .loads (pkl ))
114+
111115 def copy (self ):
112116 """
113117 Copy the grammar.
Original file line number Diff line number Diff line change @@ -29,12 +29,12 @@ def __init__(self, grammar):
2929 setattr (self , name , symbol )
3030
3131
32- python_grammar = driver .load_grammar ( _GRAMMAR_FILE )
32+ python_grammar = driver .load_packaged_grammar ( "lib2to3" , _GRAMMAR_FILE )
3333
3434python_symbols = Symbols (python_grammar )
3535
3636python_grammar_no_print_statement = python_grammar .copy ()
3737del python_grammar_no_print_statement .keywords ["print" ]
3838
39- pattern_grammar = driver .load_grammar ( _PATTERN_GRAMMAR_FILE )
39+ pattern_grammar = driver .load_packaged_grammar ( "lib2to3" , _PATTERN_GRAMMAR_FILE )
4040pattern_symbols = Symbols (pattern_grammar )
Original file line number Diff line number Diff line change 1212from test .support import verbose
1313
1414# Python imports
15+ import importlib
16+ import operator
1517import os
18+ import pickle
1619import shutil
1720import subprocess
1821import sys
@@ -99,6 +102,18 @@ def test_load_grammar_from_subprocess(self):
99102 finally :
100103 shutil .rmtree (tmpdir )
101104
105+ def test_load_packaged_grammar (self ):
106+ modname = __name__ + '.load_test'
107+ class MyLoader :
108+ def get_data (self , where ):
109+ return pickle .dumps ({'elephant' : 19 })
110+ class MyModule :
111+ __file__ = 'parsertestmodule'
112+ __spec__ = importlib .util .spec_from_loader (modname , MyLoader ())
113+ sys .modules [modname ] = MyModule ()
114+ self .addCleanup (operator .delitem , sys .modules , modname )
115+ g = pgen2_driver .load_packaged_grammar (modname , 'Grammar.txt' )
116+ self .assertEqual (g .elephant , 19 )
102117
103118
104119class 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