aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/Lib/test/test_pathlib
Commit message (Collapse)AuthorAge
* pathlib tests: create test hierarchy without using class under test (#128200)Barney Gale2024-12-23
| | | | | In the pathlib tests, avoid using the path class under test (`self.cls`) in test setup. Instead we use `os` functions in `test_pathlib`, and direct manipulation of `DummyPath` internal data in `test_pathlib_abc`.
* GH-127807: pathlib ABCs: remove `PurePathBase._raw_paths` (#127883)Barney Gale2024-12-22
| | | | | Remove the `PurePathBase` initializer, and make `with_segments()` and `__str__()` abstract. This allows us to drop the `_raw_paths` attribute, and also the `Parser.join()` protocol method.
* gh-127146: Emscripten clean up test suite (#127984)Hood Chatham2024-12-17
| | | Removed test skips that are no longer required as a result of Emscripten updates.
* GH-127807: pathlib ABCs: remove `PathBase._unsupported_msg()` (#127855)Barney Gale2024-12-12
| | | | | This method helped us customise the `UnsupportedOperation` message depending on the type. But we're aiming to make `PathBase` a proper ABC soon, so `NotImplementedError` is the right exception to raise there.
* GH-127381: pathlib ABCs: remove remaining uncommon `PathBase` methods (#127714)Barney Gale2024-12-12
| | | | | | | | | | | | | | | | | | Remove the following methods from `pathlib._abc.PathBase`: - `expanduser()` - `hardlink_to()` - `touch()` - `chmod()` - `lchmod()` - `owner()` - `group()` - `from_uri()` - `as_uri()` These operations aren't regularly supported in virtual filesystems, so they don't win a place in the `PathBase` interface. (Some of them probably don't deserve a place in `Path` :P.) They're quasi-abstract (except `lchmod()`), and they're not called by other `PathBase` methods.
* GH-127381: pathlib ABCs: remove `PathBase.samefile()` and rarer `is_*()` ↵Barney Gale2024-12-11
| | | | | | | | | | (#127709) Remove `PathBase.samefile()`, which is fairly specific to the local FS, and relies on `stat()`, which we're aiming to remove from `PathBase`. Also remove `PathBase.is_mount()`, `is_junction()`, `is_block_device()`, `is_char_device()`, `is_fifo()` and `is_socket()`. These rely on POSIX file type numbers that we're aiming to remove from the `PathBase` API.
* GH-127456: pathlib ABCs: add protocol for path parser (#127494)Barney Gale2024-12-09
| | | | | | | | | | Change the default value of `PurePathBase.parser` from `ParserBase()` to `posixpath`. As a result, user subclasses of `PurePathBase` and `PathBase` use POSIX path syntax by default, which is very often desirable. Move `pathlib._abc.ParserBase` to `pathlib._types.Parser`, and convert it to a runtime-checkable protocol. Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com>
* GH-127381: pathlib ABCs: remove `PathBase.unlink()` and `rmdir()` (#127736)Barney Gale2024-12-08
| | | | | | | Virtual filesystems don't always make a distinction between deleting files and empty directories, and sometimes support deleting non-empty directories in a single operation. Here we remove `PathBase.unlink()` and `rmdir()`, leaving `_delete()` as the sole deletion method, now made abstract. I hope to drop the underscore prefix later on.
* GH-127381: pathlib ABCs: remove `PathBase.resolve()` and `absolute()` (#127707)Barney Gale2024-12-06
| | | | | | | | | Remove our implementation of POSIX path resolution in `PathBase.resolve()`. This functionality is rather fragile and isn't necessary in most cases. It depends on `PathBase.stat()`, which we're looking to remove. Also remove `PathBase.absolute()`. Many legitimate virtual filesystems lack the notion of a 'current directory', so it's wrong to include in the basic interface.
* GH-127381: pathlib ABCs: remove `PathBase.rename()` and `replace()` (#127658)Barney Gale2024-12-06
| | | | These methods are obviated by `PathBase.move()`, which can move directories and supports any `PathBase` object as a target.
* GH-125413: Revert addition of `pathlib.Path.scandir()` method (#127377)Barney Gale2024-12-05
| | | | | | | | | | Remove documentation for `pathlib.Path.scandir()`, and rename the method to `_scandir()`. In the private pathlib ABCs, make `iterdir()` abstract and call it from `_scandir()`. It's not worthwhile to add this method at the moment - see discussion: https://discuss.python.org/t/ergonomics-of-new-pathlib-path-scandir/71721 Co-authored-by: Steve Dower <steve.dower@microsoft.com>
* gh-127146: Emscripten: Skip segfaults in test suite (#127151)Hood Chatham2024-12-05
| | | | Added skips for tests known to cause problems when running on Emscripten. These mostly relate to the limited stack depth on Emscripten.
* GH-127381: pathlib ABCs: remove `PathBase.cwd()` and `home()` (#127427)Barney Gale2024-11-30
| | | | | These classmethods presume that the user has retained the original `__init__()` signature, which may not be the case. Also, many virtual filesystems don't provide current or home directories.
* GH-127381: pathlib ABCs: remove `PathBase.lstat()` (#127382)Barney Gale2024-11-29
| | | | | | Remove the `PathBase.lstat()` method, which is a trivial variation of `stat()`. No user-facing changes because the pathlib ABCs are still private.
* pathlib tests: move `walk()` tests into their own classes (GH-126651)Barney Gale2024-11-23
| | | Move tests for Path.walk() into a new PathWalkTest class, and apply a similar change in tests for the ABCs. This allows us to properly tear down the walk test hierarchy in tearDown(), rather than leaving it to os_helper.rmtree().
* pathlib ABCs: tighten up `resolve()` and `absolute()` (#126611)Barney Gale2024-11-09
| | | | | | | | | | | | In `PathBase.resolve()`, raise `UnsupportedOperation` if a non-POSIX path parser is used (our implementation uses `posixpath._realpath()`, which produces incorrect results for non-POSIX path flavours.) Also tweak code to call `self.absolute()` upfront rather than supplying an emulated `getcwd()` function. Adjust `PathBase.absolute()` to work somewhat like `resolve()`. If a POSIX path parser is used, we treat the root directory as the current directory. This is the simplest useful behaviour for concrete path types without a current directory cursor.
* pathlib ABCs: support initializing paths with no arguments (#126608)Barney Gale2024-11-09
| | | | | | | | In the past I've equivocated about whether to require at least one argument in the `PurePathBase` (and `PathBase`) initializer, and what the default should be if we make it optional. I now have a local use case that has persuaded me to make it optional and default to the empty string (a `zipp.Path`-like class that treats relative and absolute paths similarly.) Happily this brings the base class more in line with `PurePath` and `Path`.
* pathlib ABCs: defer path joining (#126409)Barney Gale2024-11-05
| | | | | | | | Defer joining of path segments in the private `PurePathBase` ABC. The new behaviour matches how the public `PurePath` class handles path segments. This removes a hard-to-grok difference between the ABCs and the main classes. It also slightly reduces the size of `PurePath` objects by eliminating a `_raw_path` slot.
* GH-125413: pathlib ABCs: use `scandir()` to speed up `walk()` (#126262)Barney Gale2024-11-01
| | | | | | | Use the new `PathBase.scandir()` method in `PathBase.walk()`, which greatly reduces the number of `PathBase.stat()` calls needed when walking. There are no user-facing changes, because the pathlib ABCs are still private and `Path.walk()` doesn't use the implementation in its superclass.
* GH-125413: pathlib ABCs: use `scandir()` to speed up `glob()` (#126261)Barney Gale2024-11-01
| | | | | | | Use the new `PathBase.scandir()` method in `PathBase.glob()`, which greatly reduces the number of `PathBase.stat()` calls needed when globbing. There are no user-facing changes, because the pathlib ABCs are still private and `Path.glob()` doesn't use the implementation in its superclass.
* GH-125413: Add `pathlib.Path.scandir()` method (#126060)Barney Gale2024-11-01
| | | | | Add `pathlib.Path.scandir()` as a trivial wrapper of `os.scandir()`. This will be used to implement several `PathBase` methods more efficiently, including methods that provide `Path.copy()`.
* GH-125069: Fix inconsistent joining in `WindowsPath(PosixPath(...))` (#125156)Barney Gale2024-10-13
| | | | | | | | | | `PurePath.__init__()` incorrectly uses the `_raw_paths` of a given `PurePath` object with a different flavour, even though the procedure to join path segments can differ between flavours. This change makes the `_raw_paths`-enabled deferred joining apply _only_ when the path flavours match. Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com>
* GH-119518: Stop interning strings in pathlib GH-123356)Barney Gale2024-09-02
| | | | Remove `sys.intern(str(x))` calls when normalizing a path in pathlib. This speeds up `str(Path('foo/bar'))` by about 10%.
* GH-73991: Prune `pathlib.Path.copy()` and `copy_into()` arguments (#123337)Barney Gale2024-08-26
| | | | | | | | | | | | | | | | Remove *ignore* and *on_error* arguments from `pathlib.Path.copy[_into]()`, because these arguments are under-designed. Specifically: - *ignore* is appropriated from `shutil.copytree()`, but it's not clear how it should apply when the user copies a non-directory. We've changed the callback signature from the `shutil` version, but I'm not confident the new signature is as good as it can be. - *on_error* is a generalisation of `shutil.copytree()`'s error handling, which is to accumulate exceptions and raise a single `shutil.Error` at the end. It's not obvious which solution is better. Additionally, this arguments may be challenging to implement in future user subclasses of `PathBase`, which might utilise a native recursive copying method.
* GH-73991: Make `pathlib.Path.delete()` private. (#123315)Barney Gale2024-08-26
| | | | | | | | Per feedback from Paul Moore on GH-123158, it's better to defer making `Path.delete()` public than ship it with under-designed error handling capabilities. We leave a remnant `_delete()` method, which is used by `move()`. Any functionality not needed by `move()` is deleted.
* GH-73991: Add `pathlib.Path.copy_into()` and `move_into()` (#123314)Barney Gale2024-08-26
| | | | | | | | | | | | These two methods accept an *existing* directory path, onto which we join the source path's base name to form the final target path. A possible alternative implementation is to check for directories in `copy()` and `move()` and adjust the target path, which is done in several `shutil` functions. This behaviour is helpful in a shell context, but less so in a stored program that explicitly specifies destinations. For example, a user that calls `Path('foo.py').copy('bar.py')` might not imagine that `bar.py/foo.py` would be created, but under the alternative implementation this will happen if `bar.py` is an existing directory.
* GH-73991: Add `pathlib.Path.move()` (#122073)Barney Gale2024-08-25
| | | | | Add a `Path.move()` method that moves a file or directory tree, and returns a new `Path` instance pointing to the target. This method is similar to `shutil.move()`, except that it doesn't accept a *copy_function* argument, and it doesn't check whether the destination is an existing directory.
* GH-122890: Fix low-level error handling in `pathlib.Path.copy()` (#122897)Barney Gale2024-08-24
| | | | | | | | | Give unique names to our low-level FD copying functions, and try each one in turn. Handle errors appropriately for each implementation: - `fcntl.FICLONE`: suppress `EBADF`, `EOPNOTSUPP`, `ETXTBSY`, `EXDEV` - `posix._fcopyfile`: suppress `EBADF`, `ENOTSUP` - `os.copy_file_range`: suppress `ETXTBSY`, `EXDEV` - `os.sendfile`: suppress `ENOTSOCK`
* GH-73991: Disallow copying directory into itself via `pathlib.Path.copy()` ↵Barney Gale2024-08-23
| | | | (#122924)
* GH-120754: Disable buffering in Path.read_bytes (#122111)Cody Maloney2024-08-16
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | `Path.read_bytes()` is used to read a whole file. buffering / BufferedIO is focused around making small, possibly interleaved, read/write efficient which doesn't add value in this case. On my Mac, running the benchmark: ```python import pyperf from pathlib import Path def read_all(all_paths): for p in all_paths: p.read_bytes() def read_file(path_obj): path_obj.read_bytes() all_rst = list(Path("Doc").glob("**/*.rst")) all_py = list(Path(".").glob("**/*.py")) assert all_rst, "Should have found rst files" assert all_py, "Should have found python source files" runner = pyperf.Runner() runner.bench_func("read_file_small", read_file, Path("Doc/howto/clinic.rst")) runner.bench_func("read_file_large", read_file, Path("Doc/c-api/typeobj.rst")) ``` before: ```python ..................... read_file_small: Mean +- std dev: 6.80 us +- 0.07 us ..................... read_file_large: Mean +- std dev: 10.8 us +- 0.2 us ```` after: ```python ..................... read_file_small: Mean +- std dev: 5.67 us +- 0.05 us ..................... read_file_large: Mean +- std dev: 9.77 us +- 0.52 us ```
* GH-85633: Fix pathlib test failures on filesystems without world-write. ↵Barney Gale2024-08-13
| | | | | | | (#122883) Replace `umask(0)` with `umask(0o002)` so the created files are not world-writable, and replace `umask(0o022)` with `umask(0o026)` to check that permissions for 'others' can still be set.
* GH-73991: Rework `pathlib.Path.copytree()` into `copy()` (#122369)Barney Gale2024-08-11
| | | | | | | | | | Rename `pathlib.Path.copy()` to `_copy_file()` (i.e. make it private.) Rename `pathlib.Path.copytree()` to `copy()`, and add support for copying non-directories. This simplifies the interface for users, and nicely complements the upcoming `move()` and `delete()` methods (which will also accept any type of file.) Co-authored-by: Adam Turner <9087854+AA-Turner@users.noreply.github.com>
* GH-73991: Rework `pathlib.Path.rmtree()` into `delete()` (#122368)Barney Gale2024-08-07
| | | | | | Rename `pathlib.Path.rmtree()` to `delete()`, and add support for deleting non-directories. This simplifies the interface for users, and nicely complements the upcoming `move()` and `copy()` methods (which will also accept any type of file.)
* gh-122096: Remove accidentally left debugging prints (#122097)Kirill Podoprigora2024-07-21
|
* GH-73991: Support preserving metadata in `pathlib.Path.copytree()` (#121438)Barney Gale2024-07-20
| | | | | Add *preserve_metadata* keyword-only argument to `pathlib.Path.copytree()`, defaulting to false. When set to true, we copy timestamps, permissions, extended attributes and flags where available, like `shutil.copystat()`.
* GH-73991: Add `pathlib.Path.rmtree()` (#119060)Barney Gale2024-07-20
| | | | | | | | | | | Add a `Path.rmtree()` method that removes an entire directory tree, like `shutil.rmtree()`. The signature of the optional *on_error* argument matches the `Path.walk()` argument of the same name, but differs from the *onexc* and *onerror* arguments to `shutil.rmtree()`. Consistency within pathlib is probably more important. In the private pathlib ABCs, we add an implementation based on `walk()`. Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com>
* GH-73991: Fix "Operation not supported" on Fedora buildbot. (#121444)Barney Gale2024-07-07
| | | | Follow-up to #120806. Use `os_helper.skip_unless_xattr` to skip testing xattr preservation when unsupported.
* GH-73991: Support preserving metadata in `pathlib.Path.copy()` (#120806)Barney Gale2024-07-06
| | | | | Add *preserve_metadata* keyword-only argument to `pathlib.Path.copy()`, defaulting to false. When set to true, we copy timestamps, permissions, extended attributes and flags where available, like `shutil.copystat()`. The argument has no effect on Windows, where metadata is always copied. Internally (in the pathlib ABCs), path types gain `_readable_metadata` and `_writable_metadata` attributes. These sets of strings describe what kinds of metadata can be retrieved and stored. We take an intersection of `source._readable_metadata` and `target._writable_metadata` to minimise reads/writes. A new `_read_metadata()` method accepts a set of metadata keys and returns a dict with those keys, and a new `_write_metadata()` method accepts a dict of metadata. We *might* make these public in future, but it's hard to justify while the ABCs are still private.
* GH-73991: Support copying directory symlinks on older Windows (#120807)Barney Gale2024-07-03
| | | | | Check for `ERROR_INVALID_PARAMETER` when calling `_winapi.CopyFile2()` and raise `UnsupportedOperation`. In `Path.copy()`, handle this exception and fall back to the `PathBase.copy()` implementation.
* gh-73991: Skip permission test if running as *nix superuser (GH-120994)Petr Viktorin2024-06-26
|
* GH-73991: Add `pathlib.Path.copytree()` (#120718)Barney Gale2024-06-23
| | | | | | | | | | | | | | | | | | | | Add `pathlib.Path.copytree()` method, which recursively copies one directory to another. This differs from `shutil.copytree()` in the following respects: 1. Our method has a *follow_symlinks* argument, whereas shutil's has a *symlinks* argument with an inverted meaning. 2. Our method lacks something like a *copy_function* argument. It always uses `Path.copy()` to copy files. 3. Our method lacks something like a *ignore_dangling_symlinks* argument. Instead, users can filter out danging symlinks with *ignore*, or ignore exceptions with *on_error* 4. Our *ignore* argument is a callable that accepts a single path object, whereas shutil's accepts a path and a list of child filenames. 5. We add an *on_error* argument, which is a callable that accepts an `OSError` instance. (`Path.walk()` also accepts such a callable). Co-authored-by: Nice Zombies <nineteendo19d0@gmail.com>
* GH-73991: Add follow_symlinks argument to `pathlib.Path.copy()` (#120519)Barney Gale2024-06-19
| | | | | | | Add support for not following symlinks in `pathlib.Path.copy()`. On Windows we add the `COPY_FILE_COPY_SYMLINK` flag is following symlinks is disabled. If the source is symlink to a directory, this call will fail with `ERROR_ACCESS_DENIED`. In this case we add `COPY_FILE_DIRECTORY` to the flags and retry. This can fail on old Windowses, which we note in the docs. No news as `copy()` was only just added.
* GH-73991: pathlib ABC tests: add `DummyPath.unlink()` and `rmdir()` (#120715)Barney Gale2024-06-18
| | | | | In preparation for the addition of `PathBase.rmtree()`, implement `DummyPath.unlink()` and `rmdir()`, and move corresponding tests into `test_pathlib_abc` so they're run against `DummyPath`.
* GH-73991: Add `pathlib.Path.copy()` (#119058)Barney Gale2024-06-14
| | | | | | | | | | | | | | | Add a `Path.copy()` method that copies the content of one file to another. This method is similar to `shutil.copyfile()` but differs in the following ways: - Uses `fcntl.FICLONE` where available (see GH-81338) - Uses `os.copy_file_range` where available (see GH-81340) - Uses `_winapi.CopyFile2` where available, even though this copies more metadata than the other implementations. This makes `WindowsPath.copy()` more similar to `shutil.copy2()`. The method is presently _less_ specified than the `shutil` functions to allow OS-specific optimizations that might copy more or less metadata. Incorporates code from GH-81338 and GH-93152. Co-authored-by: Eryk Sun <eryksun@gmail.com>
* GH-82805: Fix handling of single-dot file extensions in pathlib (#118952)Barney Gale2024-05-25
| | | | | | | | | | | | | | | pathlib now treats "`.`" as a valid file extension (suffix). This brings it in line with `os.path.splitext()`. In the (private) pathlib ABCs, we add a new `ParserBase.splitext()` method that splits a path into a `(root, ext)` pair, like `os.path.splitext()`. This method is called by `PurePathBase.stem`, `suffix`, etc. In a future version of pathlib, we might make these base classes public, and so users will be able to define their own `splitext()` method to control file extension splitting. In `pathlib.PurePath` we add optimised `stem`, `suffix` and `suffixes` properties that don't use `splitext()`, which avoids computing the path base name twice.
* GH-119113: Raise `TypeError` from `pathlib.PurePath.with_suffix(None)` (#119124)Barney Gale2024-05-19
| | | Restore behaviour from 3.12 when `path.with_suffix(None)` is called.
* GH-74033: Drop deprecated `pathlib.Path` keyword arguments (#118793)Barney Gale2024-05-14
| | | | Remove support for supplying keyword arguments to `pathlib.Path()`. This has been deprecated since Python 3.12.
* GH-78707: Drop deprecated `pathlib.PurePath.[is_]relative_to()` arguments ↵Barney Gale2024-05-10
| | | | | | | (#118780) Remove support for supplying additional positional arguments to `PurePath.relative_to()` and `is_relative_to()`. This has been deprecated since Python 3.12.
* GH-115060: Speed up `pathlib.Path.glob()` by omitting initial `stat()` (#117831)Barney Gale2024-04-14
| | | | | | | | Since 6258844c, paths that might not exist can be fed into pathlib's globbing implementation, which will call `os.scandir()` / `os.lstat()` only when strictly necessary. This allows us to drop an initial `self.is_dir()` call, which saves a `stat()`. Co-authored-by: Shantanu <12621235+hauntsaninja@users.noreply.github.com>
* GH-115060: Speed up `pathlib.Path.glob()` by not scanning literal parts ↵Barney Gale2024-04-12
| | | | | | | | | (#117732) Don't bother calling `os.scandir()` to scan for literal pattern segments, like `foo` in `foo/*.py`. Instead, append the segment(s) as-is and call through to the next selector with `exists=False`, which signals that the path might not exist. Subsequent selectors will call `os.scandir()` or `os.lstat()` to filter out missing paths as needed.