Repository: python/cpython
Pull request: gh-112405: Optimise `pathlib.Path.relative_to`
On `main` (Windows machine, PGO-optimised build):

```
>python -m timeit -s "from pathlib import Path; p = Path('a/b/c/d/e/f/g')" "p.relative_to('a/b/c/d')"
Running PGUpdate|x64 interpreter...
10000 loops, best of 5: 28.7 usec per loop
```

With this PR:

```
>python -m timeit -s "from pathlib import Path; p = Path('a/b/c/d/e/f/g')" "p.relative_to('a/b/c/d')"
Running PGUpdate|x64 interpreter...
20000 loops, best of 5: 19.5 usec per loop
```

Fixes #112405

<!-- gh-issue-number: gh-112405 -->
* Issue: gh-112405
<!-- /gh-issue-number -->


Problem statement:
Optimise `pathlib.Path.relative_to()`
# Feature or enhancement

### Proposal:

`pathlib.Path.relative_to()` can be significantly optimised by making use of `itertools.chain`

### Has this already been discussed elsewhere?

This is a minor feature, which does not need previous discussion elsewhere

### Links to previous discussion of this feature:

_No response_

<!-- gh-linked-prs -->
### Linked PRs
* gh-112406
<!-- /gh-linked-prs -->

Hints from issue discussion:

Commit message: Concede to the Yanks

Co-authored-by: Itamar Oren <itamarost@gmail.com>

Patch to review:
diff --git a/Lib/pathlib.py b/Lib/pathlib.py
index 0e01099d490a7e..81f75cd47ed087 100644
--- a/Lib/pathlib.py
+++ b/Lib/pathlib.py
@@ -14,6 +14,7 @@
 import warnings
 from _collections_abc import Sequence
 from errno import ENOENT, ENOTDIR, EBADF, ELOOP, EINVAL
+from itertools import chain
 from stat import S_ISDIR, S_ISLNK, S_ISREG, S_ISSOCK, S_ISBLK, S_ISCHR, S_ISFIFO
 
 try:
@@ -445,7 +446,7 @@ def relative_to(self, other, /, *_deprecated, walk_up=False):
             other = self.with_segments(other, *_deprecated)
         elif not isinstance(other, PurePath):
             other = self.with_segments(other)
-        for step, path in enumerate([other] + list(other.parents)):
+        for step, path in enumerate(chain([other], other.parents)):
             if path == self or path in self.parents:
                 break
             elif not walk_up:
diff --git a/Misc/NEWS.d/next/Library/2023-11-25-20-29-28.gh-issue-112405.cOtzxC.rst b/Misc/NEWS.d/next/Library/2023-11-25-20-29-28.gh-issue-112405.cOtzxC.rst
new file mode 100644
index 00000000000000..9a6bd6ff5911c0
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-11-25-20-29-28.gh-issue-112405.cOtzxC.rst
@@ -0,0 +1 @@
+Optimize :meth:`pathlib.Path.relative_to`. Patch by Alex Waygood.


Code review comments:
diff_hunk: @@ -0,0 +1 @@
+Optimize :meth:`pathlib.Path.relative_to`. Patch by Alex Waygood.
path: Misc/NEWS.d/next/Library/2023-11-25-20-29-28.gh-issue-112405.cOtzxC.rst
text: @user1:
```suggestion
Optimize :meth:`pathlib.PurePath.relative_to`. Patch by Alex Waygood.
```