Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 06a26fd

Browse filesBrowse files
authored
gh-118761: Optimise import time for shlex (#132036)
1 parent 984a314 commit 06a26fd
Copy full SHA for 06a26fd

File tree

3 files changed

+17
-7
lines changed
Filter options

3 files changed

+17
-7
lines changed

‎Lib/shlex.py

Copy file name to clipboardExpand all lines: Lib/shlex.py
+10-7Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,7 @@
77
# iterator interface by Gustavo Niemeyer, April 2003.
88
# changes to tokenize more like Posix shells by Vinay Sajip, July 2016.
99

10-
import os
11-
import re
1210
import sys
13-
from collections import deque
14-
1511
from io import StringIO
1612

1713
__all__ = ["shlex", "split", "quote", "join"]
@@ -20,6 +16,8 @@ class shlex:
2016
"A lexical analyzer class for simple shell-like syntaxes."
2117
def __init__(self, instream=None, infile=None, posix=False,
2218
punctuation_chars=False):
19+
from collections import deque # deferred import for performance
20+
2321
if isinstance(instream, str):
2422
instream = StringIO(instream)
2523
if instream is not None:
@@ -278,6 +276,7 @@ def read_token(self):
278276

279277
def sourcehook(self, newfile):
280278
"Hook called on a filename to be sourced."
279+
import os.path
281280
if newfile[0] == '"':
282281
newfile = newfile[1:-1]
283282
# This implements cpp-like semantics for relative-path inclusion.
@@ -318,13 +317,17 @@ def join(split_command):
318317
return ' '.join(quote(arg) for arg in split_command)
319318

320319

321-
_find_unsafe = re.compile(r'[^\w@%+=:,./-]', re.ASCII).search
322-
323320
def quote(s):
324321
"""Return a shell-escaped version of the string *s*."""
325322
if not s:
326323
return "''"
327-
if _find_unsafe(s) is None:
324+
325+
# Use bytes.translate() for performance
326+
safe_chars = (b'%+,-./0123456789:=@'
327+
b'ABCDEFGHIJKLMNOPQRSTUVWXYZ_'
328+
b'abcdefghijklmnopqrstuvwxyz')
329+
# No quoting is needed if `s` is an ASCII string consisting only of `safe_chars`
330+
if s.isascii() and not s.encode().translate(None, delete=safe_chars):
328331
return s
329332

330333
# use single quotes, and put single quotes into double quotes

‎Lib/test/test_shlex.py

Copy file name to clipboardExpand all lines: Lib/test/test_shlex.py
+4Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import shlex
44
import string
55
import unittest
6+
from test.support import import_helper
67

78

89
# The original test data set was from shellwords, by Hartmut Goebel.
@@ -363,6 +364,9 @@ def testPunctuationCharsReadOnly(self):
363364
with self.assertRaises(AttributeError):
364365
shlex_instance.punctuation_chars = False
365366

367+
def test_lazy_imports(self):
368+
import_helper.ensure_lazy_imports('shlex', {'collections', 're', 'os'})
369+
366370

367371
# Allow this test to be used with old shlex.py
368372
if not getattr(shlex, "split", None):
+3Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Improve import times by up to 33x for the :mod:`shlex` module,
2+
and improve the performance of :func:`shlex.quote` by up to 12x.
3+
Patch by Adam Turner.

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.