Skip to content

Commit

Permalink
pythonGH-113373: Slightly speed up path parsing in pathlib
Browse files Browse the repository at this point in the history
Small improvements:

- `Path('foo', '')` and `Path('foo') / ''` are improved by omitting an
  `os.path.join()` call.
- The result of `os.path.join()` is stored and re-used for subsequent
  joins.

Smaller improvements:

- Check for the common case (`len(paths) == 0`) first, and speed up the
  subsequent `elif` by avoiding a length check
- Don't bother assigning the `_parse_path()` result to local variables
  • Loading branch information
barneygale committed Dec 21, 2023
1 parent 2f0ec7f commit dc08c5d
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 12 deletions.
3 changes: 2 additions & 1 deletion Lib/pathlib/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,8 @@ def __init__(self, *args):
"argument should be a str or an os.PathLike "
"object where __fspath__ returns a str, "
f"not {type(path).__name__!r}")
paths.append(path)
if path:
paths.append(path)
# Avoid calling super().__init__, as an optimisation
self._raw_paths = paths
self._resolving = False
Expand Down
27 changes: 16 additions & 11 deletions Lib/pathlib/_abc.py
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,11 @@ class PurePathBase:
)
pathmod = os.path

def __init__(self, *paths):
def __init__(self, *args):
paths = []
for arg in args:
if arg:
paths.append(arg)
self._raw_paths = paths
self._resolving = False

Expand All @@ -219,8 +223,6 @@ def with_segments(self, *pathsegments):

@classmethod
def _parse_path(cls, path):
if not path:
return '', '', []
sep = cls.pathmod.sep
altsep = cls.pathmod.altsep
if altsep:
Expand All @@ -239,16 +241,19 @@ def _parse_path(cls, path):

def _load_parts(self):
paths = self._raw_paths
if len(paths) == 0:
path = ''
elif len(paths) == 1:
if len(paths) == 1:
path = paths[0]
else:
elif paths:
path = self.pathmod.join(*paths)
drv, root, tail = self._parse_path(path)
self._drv = drv
self._root = root
self._tail_cached = tail
# Store the joined path. This makes subsequent joins onto this
# path slightly faster.
paths.clear()
paths.append(path)
else:
self._drv = self._root = ''
self._tail_cached = []
return
self._drv, self._root, self._tail_cached = self._parse_path(path)

def _from_parsed_parts(self, drv, root, tail):
path_str = self._format_parsed_parts(drv, root, tail)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Slightly speed up path parsing in :mod:`pathlib`. Patch by Barney Gale.

0 comments on commit dc08c5d

Please sign in to comment.