summaryrefslogtreecommitdiffstats
path: root/Lib/pathlib.py
Commit message (Collapse)AuthorAgeFilesLines
* GH-105793: Add follow_symlinks argument to `pathlib.Path.is_dir()` and ↵Barney Gale2023-06-261-4/+4
| | | | | | | `is_file()` (GH-105794) Brings `pathlib.Path.is_dir()` and `in line with `os.DirEntry.is_dir()`, which will be important for implementing generic path walking and globbing. Likewise `is_file()`.
* GH-89812: Add `pathlib.UnsupportedOperation` (GH-105926)Barney Gale2023-06-221-7/+15
| | | | | | | This new exception type is raised instead of `NotImplementedError` when a path operation is not supported. It can be raised from `Path.readlink()`, `symlink_to()`, `hardlink_to()`, `owner()` and `group()`. In a future version of pathlib, it will be raised by `AbstractPath` for these methods and others, such as `AbstractPath.mkdir()` and `unlink()`.
* GH-104996: Defer joining of `pathlib.PurePath()` arguments. (GH-104999)Barney Gale2023-06-071-17/+27
| | | | Joining of arguments is moved to `_load_parts`, which is called when a normalized path is needed.
* GH-102613: Fast recursive globbing in `pathlib.Path.glob()` (GH-104512)Barney Gale2023-06-061-136/+133
| | | | | | | | | | | | | | This commit introduces a 'walk-and-match' strategy for handling glob patterns that include a non-terminal `**` wildcard, such as `**/*.py`. For this example, the previous implementation recursively walked directories using `os.scandir()` when it expanded the `**` component, and then **scanned those same directories again** when expanded the `*.py` component. This is wasteful. In the new implementation, any components following a `**` wildcard are used to build a `re.Pattern` object, which is used to filter the results of the recursive walk. A pattern like `**/*.py` uses half the number of `os.scandir()` calls; a pattern like `**/*/*.py` a third, etc. This new algorithm does not apply if either: 1. The *follow_symlinks* argument is set to `None` (its default), or 2. The pattern contains `..` components. In these cases we fall back to the old implementation. This commit also replaces selector classes with selector functions. These generators directly yield results rather calling through to their successors. A new internal `Path._glob()` method takes care to chain these generators together, which simplifies the lazy algorithm and slightly improves performance. It should also be easier to understand and maintain.
* GH-73435: Implement recursive wildcards in `pathlib.PurePath.match()` (#101398)Barney Gale2023-05-301-14/+85
| | | | | | | | `PurePath.match()` now handles the `**` wildcard as in `Path.glob()`, i.e. it matches any number of path segments. We now compile a `re.Pattern` object for the entire pattern. This is made more difficult by `fnmatch` not treating directory separators as special when evaluating wildcards (`*`, `?`, etc), and so we arrange the path parts onto separate *lines* in a string, and ensure we don't set `re.DOTALL`. Co-authored-by: Hugo van Kemenade <hugovk@users.noreply.github.com> Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
* GH-104898: Revert pathlib os.PathLike registration change. (GH-105073)Barney Gale2023-05-291-1/+5
| | | | | | | | Subclassing `os.PathLike` rather than using `register()` makes initialisation slower, due to the additional `__isinstance__` work. This partially reverts commit bd1b6228d132b8e9836fe352cd8dca2b6c1bd98c. Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
* GH-77609: Add follow_symlinks argument to `pathlib.Path.glob()` (GH-102616)Barney Gale2023-05-291-19/+21
| | | | | Add a keyword-only *follow_symlinks* parameter to `pathlib.Path.glob()` and`rglob()`. When *follow_symlinks* is `None` (the default), these methods follow symlinks except when evaluating "`**`" wildcards. When set to true or false, symlinks are always or never followed, respectively.
* GH-103631: Fix `PurePosixPath(PureWindowsPath(...))` separator handling ↵Barney Gale2023-05-261-0/+3
| | | | | | | | | (GH-104949) For backwards compatibility, accept backslashes as path separators in `PurePosixPath` if an instance of `PureWindowsPath` is supplied. This restores behaviour from Python 3.11. Co-authored-by: Gregory P. Smith <greg@krypto.org>
* GH-104947: Make pathlib.PureWindowsPath comparisons consistent across ↵Barney Gale2023-05-261-1/+4
| | | | | | | | platforms (GH-104948) Use `str.lower()` rather than `ntpath.normcase()` to normalize case of Windows paths. This restores behaviour from Python 3.11. Co-authored-by: Gregory P. Smith <greg@krypto.org>
* GH-104898: Add __slots__ to os.PathLike (GH-104899)Barney Gale2023-05-251-5/+1
|
* GH-83863: Drop support for using `pathlib.Path` objects as context managers ↵Barney Gale2023-05-231-19/+0
| | | | | | | | | | (GH-104807) In Python 3.8 and prior, `pathlib.Path.__exit__()` marked a path as closed; some subsequent attempts to perform I/O would raise an IOError. This functionality was never documented, and had the effect of making `Path` objects mutable, contrary to PEP 428. In Python 3.9 we made `__exit__()` a no-op, and in 3.11 `__enter__()` began raising deprecation warnings. Here we remove both methods.
* GH-104484: Add case_sensitive argument to `pathlib.PurePath.match()` (GH-104565)thirumurugan2023-05-181-6/+14
| | | Co-authored-by: Barney Gale <barney.gale@gmail.com>
* GH-102613: Fix recursion error from `pathlib.Path.glob()` (GH-104373)Barney Gale2023-05-151-20/+5
| | | | Use `Path.walk()` to implement the recursive wildcard `**`. This method uses an iterative (rather than recursive) walk - see GH-100282.
* GH-90208: Suppress OSError exceptions from `pathlib.Path.glob()` (GH-104141)Barney Gale2023-05-111-20/+13
| | | | | | | | | | | `pathlib.Path.glob()` now suppresses all OSError exceptions, except those raised from calling `is_dir()` on the top-level path. Previously, `glob()` suppressed ENOENT, ENOTDIR, EBADF and ELOOP errors and their Windows equivalents. PermissionError was also suppressed unless it occurred when calling `is_dir()` on the top-level path. However, the selector would abort prematurely if a PermissionError was raised, and so `glob()` could return incomplete results.
* GH-87695: Fix OSError from `pathlib.Path.glob()` (GH-104292)Barney Gale2023-05-101-2/+2
| | | | Fix issue where `pathlib.Path.glob()` raised `OSError` when it encountered a symlink to an overly long path.
* GH-102613: Improve performance of `pathlib.Path.rglob()` (GH-104244)Barney Gale2023-05-071-17/+37
| | | | | | | | | | Stop de-duplicating results in `_RecursiveWildcardSelector`. A new `_DoubleRecursiveWildcardSelector` class is introduced which performs de-duplication, but this is used _only_ for patterns with multiple non-adjacent `**` segments, such as `path.glob('**/foo/**')`. By avoiding the use of a set, `PurePath.__hash__()` is not called, and so paths do not need to be stringified and case-normalised. Also merge adjacent '**' segments in patterns.
* GH-89812: Churn `pathlib.Path` methods (GH-104243)Barney Gale2023-05-071-303/+303
| | | | | | | | | | | | | | | Re-arrange `pathlib.Path` methods in source code. No other changes. The methods are arranged as follows: 1. `stat()` and dependants (`exists()`, `is_dir()`, etc) 2. `open()` and dependants (`read_text()`, `write_bytes()`, etc) 3. `iterdir()` and dependants (`glob()`, `walk()`, etc) 4. All other `Path` methods This patch prepares the ground for a new `_AbstractPath` class, which will support the methods in groups 1, 2 and 3 above. By churning the methods here, subsequent patches will be easier to review and less likely to break things.
* GH-103548: Improve performance of `pathlib.Path.[is_]absolute()` (GH-103549)Barney Gale2023-05-061-1/+10
| | | | Improve performance of `pathlib.Path.absolute()` and `cwd()` by joining paths only when necessary. Also improve performance of `PurePath.is_absolute()` on Posix by skipping path parsing and normalization.
* GH-100479: Add `pathlib.PurePath.with_segments()` (GH-103975)Barney Gale2023-05-051-30/+36
| | | | | Add `pathlib.PurePath.with_segments()`, which creates a path object from arguments. This method is called whenever a derivative path is created, such as from `pathlib.PurePath.parent`. Subclasses may override this method to share information between path objects. Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
* GH-81079: Add case_sensitive argument to `pathlib.Path.glob()` (GH-102710)Barney Gale2023-05-041-15/+19
| | | | | | This argument allows case-sensitive matching to be enabled on Windows, and case-insensitive matching to be enabled on Posix. Co-authored-by: Steve Dower <steve.dower@microsoft.com>
* GH-104114: Fix `pathlib.WindowsPath.glob()` use of literal pattern segment ↵Barney Gale2023-05-031-39/+13
| | | | | | | | | case (GH-104116) We now use `_WildcardSelector` to evaluate literal pattern segments, which allows us to retrieve the real filesystem case. This change is necessary in order to implement a *case_sensitive* argument (see GH-81079) and a *follow_symlinks* argument (see GH-77609).
* GH-89769: `pathlib.Path.glob()`: do not follow symlinks when checking for ↵andrei kulakov2023-05-031-3/+7
| | | | | precise match (GH-29655) Co-authored-by: Barney Gale <barney.gale@gmail.com>
* GH-104102: Optimize `pathlib.Path.glob()` handling of `../` pattern segments ↵Barney Gale2023-05-021-0/+12
| | | | | | | | (GH-104103) These segments do not require a `stat()` call, as the selector's `_select_from()` method is called after we've established that the parent is a directory.
* GH-104104: Optimize `pathlib.Path.glob()` by avoiding repeated calls to ↵Barney Gale2023-05-021-11/+14
| | | | | | `os.path.normcase()` (GH-104105) Use `re.IGNORECASE` to implement case-insensitive matching. This restores behaviour from before GH-31691.
* GH-103525: Improve exception message from `pathlib.PurePath()` (GH-103526)Barney Gale2023-05-021-14/+23
| | | | | | | | Check that arguments are strings before calling `os.path.join()`. Also improve performance of `PurePath(PurePath(...))` while we're in the area: we now use the *unnormalized* string path of such arguments. Co-authored-by: Terry Jan Reedy <tjreedy@udel.edu>
* GH-78079: Fix UNC device path root normalization in pathlib (GH-102003)Barney Gale2023-04-141-3/+8
| | | | | | | We no longer add a root to device paths such as `//./PhysicalDrive0`, `//?/BootPartition` and `//./c:` while normalizing. We also avoid adding a root to incomplete UNC share paths, like `//`, `//a` and `//a/`. Co-authored-by: Eryk Sun <eryksun@gmail.com>
* GH-101362: Omit path anchor from `pathlib.PurePath()._parts` (GH-102476)Barney Gale2023-04-091-65/+106
| | | Improve performance of path construction by skipping the addition of the path anchor (`drive + root`) to the internal `_parts` list. Rename this attribute to `_tail` for clarity.
* GH-76846, GH-85281: Call `__new__()` and `__init__()` on pathlib subclasses ↵Barney Gale2023-04-031-67/+78
| | | | | | | | | (GH-102789) Fix an issue where `__new__()` and `__init__()` were not called on subclasses of `pathlib.PurePath` and `Path` in some circumstances. Paths are now normalized on-demand. This speeds up path construction, `p.joinpath(q)`, and `p / q`. Co-authored-by: Steve Dower <steve.dower@microsoft.com>
* GH-89727: Fix pathlib.Path.walk RecursionError on deep trees (GH-100282)Stanislav Zmiev2023-03-221-38/+40
| | | | | | Use a stack to implement `pathlib.Path.walk()` iteratively instead of recursively to avoid hitting recursion limits on deeply nested trees. Co-authored-by: Barney Gale <barney.gale@gmail.com> Co-authored-by: Brett Cannon <brett@python.org>
* GH-80486: Fix handling of NTFS alternate data streams in pathlib (GH-102454)Barney Gale2023-03-101-3/+5
| | | Co-authored-by: Maor Kleinberger <kmaork@gmail.com>
* GH-101362: Optimise PurePath(PurePath(...)) (GH-101667)Barney Gale2023-03-051-25/+11
| | | | | | | The previous `_parse_args()` method pulled the `_parts` out of any supplied `PurePath` objects; these were subsequently joined in `_from_parts()` using `os.path.join()`. This is actually a slower form of joining than calling `fspath()` on the path object, because it doesn't take advantage of the fact that the contents of `_parts` is normalized! This reduces the time taken to run `PurePath("foo", "bar")` by ~20%, and the time taken to run `PurePath(p, "cheese")`, where `p = PurePath("/foo", "bar", "baz")`, by ~40%. Automerge-Triggered-By: GH:AlexWaygood
* GH-101362: Check pathlib.Path flavour compatibility at import time (GH-101664)Barney Gale2023-03-051-5/+11
| | | | | This saves a comparison in `pathlib.Path.__new__()` and reduces the time taken to run `Path()` by ~5%. Automerge-Triggered-By: GH:AlexWaygood
* GH-101362: Call join() only when >1 argument supplied to pathlib.PurePath() ↵Barney Gale2023-03-051-1/+4
| | | | | | | (#101665) GH-101362: Call join() only when >1 argument supplied to pathlib.PurePath This reduces the time taken to run `PurePath("foo")` by ~15%
* gh-100809: Fix handling of drive-relative paths in pathlib.Path.absolute() ↵Barney Gale2023-02-171-1/+6
| | | | | (GH-100812) Resolving the drive independently uses the OS API, which ensures it starts from the current directory on that drive.
* gh-101360: Fix anchor matching in pathlib.PureWindowsPath.match() (GH-101363)Barney Gale2023-02-171-5/+0
| | | | Use `fnmatch` to match path and pattern anchors, just as we do for other path parts. This allows patterns such as `'*:/Users/*'` to be matched.
* gh-101000: Add os.path.splitroot() (#101002)Barney Gale2023-01-271-17/+7
| | | | Co-authored-by: Eryk Sun <eryksun@gmail.com> Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
* gh-74033: Fix bug when Path takes and ignores **kwargs (GH-19632)Yurii Karabas2023-01-141-0/+4
| | | | | Fix a bug where `Path` takes and ignores `**kwargs` by adding to `PurePath` class `__init__` method which can take only positional arguments. Automerge-Triggered-By: GH:brettcannon
* gh-100562: improve performance of `pathlib.Path.absolute()` (GH-100563)Barney Gale2023-01-051-5/+7
| | | | | | | | | | | | | | | | Increase performance of the `absolute()` method by calling `os.getcwd()` directly, rather than using the `Path.cwd()` class method. This avoids constructing an extra `Path` object (and the parsing/normalization that comes with it). Decrease performance of the `cwd()` class method by calling the `Path.absolute()` method, rather than using `os.getcwd()` directly. This involves constructing an extra `Path` object. We do this to maintain a longstanding pattern where `os` functions are called from only one place, which allows them to be more readily replaced by users. As `cwd()` is generally called at most once within user programs, it's a good bargain. ```shell # before $ ./python -m timeit -s 'from pathlib import Path; p = Path("foo", "bar")' 'p.absolute()' 50000 loops, best of 5: 9.04 usec per loop # after $ ./python -m timeit -s 'from pathlib import Path; p = Path("foo", "bar")' 'p.absolute()' 50000 loops, best of 5: 5.02 usec per loop ``` Automerge-Triggered-By: GH:AlexWaygood
* gh-68320, gh-88302 - Allow for private `pathlib.Path` subclassing (GH-31691)Barney Gale2022-12-231-202/+129
| | | | | | | | | | | | | | | | | | | | | | | | | | | Users may wish to define subclasses of `pathlib.Path` to add or modify existing methods. Before this change, attempting to instantiate a subclass raised an exception like: AttributeError: type object 'PPath' has no attribute '_flavour' Previously the `_flavour` attribute was assigned as follows: PurePath._flavour = xxx not set!! xxx PurePosixPath._flavour = _PosixFlavour() PureWindowsPath._flavour = _WindowsFlavour() This change replaces it with a `_pathmod` attribute, set as follows: PurePath._pathmod = os.path PurePosixPath._pathmod = posixpath PureWindowsPath._pathmod = ntpath Functionality from `_PosixFlavour` and `_WindowsFlavour` is moved into `PurePath` as underscored-prefixed classmethods. Flavours are removed. Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com> Co-authored-by: Brett Cannon <brett@python.org> Co-authored-by: Adam Turner <9087854+AA-Turner@users.noreply.github.com> Co-authored-by: Eryk Sun <eryksun@gmail.com>
* gh-78707: deprecate passing >1 argument to `PurePath.[is_]relative_to()` ↵Barney Gale2022-12-171-8/+16
| | | | | | | (GH-94469) This brings `relative_to()` and `is_relative_to()` more in line with other pathlib methods like `rename()` and `symlink_to()`. Resolves #78707.
* gh-99029: Fix handling of `PureWindowsPath('C:\<blah>').relative_to('C:')` ↵Barney Gale2022-11-251-43/+13
| | | | | | | (GH-99031) `relative_to()` now treats naked drive paths as relative. This brings its behaviour in line with other parts of pathlib, and with `ntpath.relpath()`, and so allows us to factor out the pathlib-specific implementation.
* gh-99547: Add isjunction methods for checking if a path is a junction (GH-99548)Charles Machalow2022-11-221-0/+6
|
* gh-98832: Change wording in docstring of `pathlib.Path.iterdir` (GH-98833)Nikita Sobolev2022-11-091-2/+4
| | | | | Found while working on https://github.com/python/cpython/issues/98829 Automerge-Triggered-By: GH:AlexWaygood
* gh-98884: [pathlib] remove `hasattr` check for `lru_cache` (#98885)Nikita Sobolev2022-11-031-3/+1
|
* gh-84538: add strict argument to pathlib.PurePath.relative_to (GH-19813)domragusa2022-10-281-15/+33
| | | | | | | | | | | | | | | | | | | | | | | By default, :meth:`pathlib.PurePath.relative_to` doesn't deal with paths that are not a direct prefix of the other, raising an exception in that instance. This change adds a *walk_up* parameter that can be set to allow for using ``..`` to calculate the relative path. example: ``` >>> p = PurePosixPath('/etc/passwd') >>> p.relative_to('/etc') PurePosixPath('passwd') >>> p.relative_to('/usr') Traceback (most recent call last): File "<stdin>", line 1, in <module> File "pathlib.py", line 940, in relative_to raise ValueError(error_message.format(str(self), str(formatted))) ValueError: '/etc/passwd' does not start with '/usr' >>> p.relative_to('/usr', strict=False) PurePosixPath('../etc/passwd') ``` https://bugs.python.org/issue40358 Automerge-Triggered-By: GH:brettcannon
* gh-94909: fix joining of absolute and relative Windows paths in pathlib ↵Barney Gale2022-08-121-33/+8
| | | | | | | | | | | | | | | | | | | | | | (GH-95450) Have pathlib use `os.path.join()` to join arguments to the `PurePath` initialiser, which fixes a minor bug when handling relative paths with drives. Previously: ```python >>> from pathlib import PureWindowsPath >>> a = 'C:/a/b' >>> b = 'C:x/y' >>> PureWindowsPath(a, b) PureWindowsPath('C:x/y') ``` Now: ```python >>> PureWindowsPath(a, b) PureWindowsPath('C:/a/b/x/y') ```
* gh-86943: implement `pathlib.WindowsPath.is_mount()` (GH-31458)Barney Gale2022-08-051-19/+2
| | | | | | Have `pathlib.WindowsPath.is_mount()` call `ntpath.ismount()`. Previously it raised `NotImplementedError` unconditionally. https://bugs.python.org/issue42777
* gh-90385: Add `pathlib.Path.walk()` method (GH-92517)Stanislav Zmiev2022-07-221-0/+43
| | | Automerge-Triggered-By: GH:brettcannon
* gh-82116: add comment explaining use of `list(scandir_it)` in pathlib. ↵Barney Gale2022-07-201-0/+4
| | | | | (GH-94939) Automerge-Triggered-By: GH:brettcannon
* gh-93654: Add module docstring to pathlib (GH-94611)Samuel Sloniker2022-07-071-0/+7
| | | Issue: gh-93654