File tree Expand file tree Collapse file tree
Misc/NEWS.d/next/Tools-Demos Expand file tree Collapse file tree 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
@@ -140,6 +141,26 @@ def _newer(a, b):
140141 return os .path .getmtime (a ) >= os .path .getmtime (b )
141142
142143
144+ def load_packaged_grammar (package , grammar_source ):
145+ """Normally, loads a pickled grammar by doing
146+ pkgutil.get_data(package, pickled_grammar)
147+ where *pickled_grammar* is computed from *grammar_source* by adding the
148+ Python version and using a ``.pickle`` extension.
149+
150+ However, if *grammar_source* is an extant file, load_grammar(grammar_source)
151+ is called instead. This facilities using a packaged grammar file when needed
152+ but preserves load_grammar's automatic regeneration behavior when possible.
153+
154+ """
155+ if os .path .isfile (grammar_source ):
156+ return load_grammar (grammar_source )
157+ pickled_name = _generate_pickle_name (os .path .basename (grammar_source ))
158+ data = pkgutil .get_data (package , pickled_name )
159+ g = grammar .Grammar ()
160+ g .loads (data )
161+ return g
162+
163+
143164def main (* args ):
144165 """Main program, when run as a script: produce grammar pickle files.
145166
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