Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package python-pyfakefs for openSUSE:Factory
checked in at 2026-05-28 23:07:36
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-pyfakefs (Old)
and /work/SRC/openSUSE:Factory/.python-pyfakefs.new.1937 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-pyfakefs"
Thu May 28 23:07:36 2026 rev:30 rq:1355087 version:6.2.0
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-pyfakefs/python-pyfakefs.changes
2026-03-23 17:11:42.745540897 +0100
+++
/work/SRC/openSUSE:Factory/.python-pyfakefs.new.1937/python-pyfakefs.changes
2026-05-28 23:07:46.213112061 +0200
@@ -1,0 +2,16 @@
+Mon May 25 15:56:57 UTC 2026 - Dirk Müller <[email protected]>
+
+- update to 6.2.0:
+ * fake file wrappers now derive from `io.TextIOBase` or
+ `io.BufferedIOBase`, so that `isinstance`-checks for these
+ classes succeed
+ * route some pseudo-devices to the system instead of patching
+ them; this ensures that `os.urandom` and related functions
+ work correctly with PyPy
+ * fake file `seek` method did not return the location in the
+ file
+ * make sure case sensitivity is correctly set for fake posix
+ paths in `hash()`, `Path.match` and `Path.full_match`
+ * use newest `pytest` for testing in CI
+
+-------------------------------------------------------------------
Old:
----
python-pyfakefs-6.1.6.tar.gz
New:
----
python-pyfakefs-6.2.0.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-pyfakefs.spec ++++++
--- /var/tmp/diff_new_pack.cRRYOi/_old 2026-05-28 23:07:47.517165752 +0200
+++ /var/tmp/diff_new_pack.cRRYOi/_new 2026-05-28 23:07:47.521165916 +0200
@@ -26,18 +26,18 @@
%endif
%{?sle15_python_module_pythons}
Name: python-pyfakefs%{psuffix}
-Version: 6.1.6
+Version: 6.2.0
Release: 0
Summary: Fake file system that mocks the Python file system modules
License: Apache-2.0
URL: https://github.com/jmcgeheeiv/pyfakefs
Source:
https://github.com/jmcgeheeiv/pyfakefs/archive/v%{version}.tar.gz#/python-pyfakefs-%{version}.tar.gz
BuildRequires: %{python_module pip}
-BuildRequires: %{python_module setuptools}
+BuildRequires: %{python_module setuptools >= 77.0.3}
BuildRequires: %{python_module wheel}
BuildRequires: fdupes
BuildRequires: python-rpm-macros
-Requires: python
+Requires: python >= 3.10
BuildArch: noarch
%if %{with test}
BuildRequires: %{python_module pytest >= 3}
++++++ python-pyfakefs-6.1.6.tar.gz -> python-pyfakefs-6.2.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pyfakefs-6.1.6/.github/workflows/testsuite.yml
new/pyfakefs-6.2.0/.github/workflows/testsuite.yml
--- old/pyfakefs-6.1.6/.github/workflows/testsuite.yml 2026-03-18
20:47:51.000000000 +0100
+++ new/pyfakefs-6.2.0/.github/workflows/testsuite.yml 2026-04-12
15:30:15.000000000 +0200
@@ -103,16 +103,16 @@
matrix:
os: [ubuntu-latest, macOS-latest, windows-latest]
python-version: ["3.10", "3.11", "3.12", "3.13"]
- pytest-version: [6.2.5, 7.0.1, 7.4.4, 8.0.2, 8.4.2, 9.0.2]
+ pytest-version: [6.2.5, 7.0.1, 7.4.4, 8.0.2, 8.4.2, 9.0.3]
include:
- python-version: "3.14"
- pytest-version: 8.4.2
+ pytest-version: 9.0.3
os: ubuntu-latest
- python-version: "3.14"
- pytest-version: 8.4.2
+ pytest-version: 9.0.3
os: macOS-latest
- python-version: "3.14"
- pytest-version: 8.4.2
+ pytest-version: 9.0.3
os: windows-latest
steps:
- uses: actions/checkout@v6
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pyfakefs-6.1.6/.pre-commit-config.yaml
new/pyfakefs-6.2.0/.pre-commit-config.yaml
--- old/pyfakefs-6.1.6/.pre-commit-config.yaml 2026-03-18 20:47:51.000000000
+0100
+++ new/pyfakefs-6.2.0/.pre-commit-config.yaml 2026-04-12 15:30:15.000000000
+0200
@@ -11,7 +11,7 @@
- "--py310-plus"
- repo: https://github.com/astral-sh/ruff-pre-commit
- rev: "v0.15.6"
+ rev: "v0.15.9"
hooks:
- id: ruff
args: ["--fix"]
@@ -44,7 +44,7 @@
language: python
files: \.py$
- repo: https://github.com/pre-commit/mirrors-mypy
- rev: v1.19.1
+ rev: v1.20.0
hooks:
- id: mypy
exclude: (docs|pyfakefs/tests)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pyfakefs-6.1.6/CHANGES.md
new/pyfakefs-6.2.0/CHANGES.md
--- old/pyfakefs-6.1.6/CHANGES.md 2026-03-18 20:47:51.000000000 +0100
+++ new/pyfakefs-6.2.0/CHANGES.md 2026-04-12 15:30:15.000000000 +0200
@@ -2,6 +2,28 @@
The released versions correspond to PyPI releases.
`pyfakefs` versions follow [Semantic Versioning](https://semver.org/).
+## [Version 6.2.0](https://pypi.python.org/pypi/pyfakefs/6.2.0) (2026-04-12)
+Changes the MRO for file wrappers.
+
+### Changes
+* fake file wrappers now derive from `io.TextIOBase` or `io.BufferedIOBase`,
+ so that `isinstance`-checks for these classes succeed
+ (see [#1307](https://github.com/pytest-dev/pyfakefs/issues/1307)
+ and [#484](https://github.com/pytest-dev/pyfakefs/issues/484))
+
+### Fixes
+* route some pseudo-devices to the system instead of patching them; this
ensures
+ that `os.urandom` and related functions work correctly with PyPy
+ (see [#1300](https://github.com/pytest-dev/pyfakefs/issues/1300))
+* fake file `seek` method did not return the location in the file
+ (see [#1304](https://github.com/pytest-dev/pyfakefs/issues/1304))
+* make sure case sensitivity is correctly set for fake posix paths
+ in `hash()`, `Path.match` and `Path.full_match`
+ (see [#1308](https://github.com/pytest-dev/pyfakefs/issues/1308))
+
+### Infrastructure
+* use newest `pytest` for testing in CI
+
## [Version 6.1.6](https://pypi.python.org/pypi/pyfakefs/6.1.6) (2026-03-18)
Follow-up bugfix release for 6.1.5.
@@ -20,7 +42,7 @@
Fixes incompatibility with VCCode unittest runner.
### Fixes
-* expanduser now correctly handles paths besides home and different separators
+* `expanduser` now correctly handles paths besides home and different
separators
(see [#1289](https://github.com/pytest-dev/pyfakefs/issues/1289))
* avoid faking filesystem in VSCode unittest runner
(see [#1285](https://github.com/pytest-dev/pyfakefs/issues/1285))
@@ -29,7 +51,7 @@
Minor bugfix release.
### Fixes
-* handle expanduser() and home() correctly in cross OS usage
+* handle `expanduser()` and `home()` correctly in cross OS usage
(see [#1289](https://github.com/pytest-dev/pyfakefs/issues/1289))
## [Version 6.1.2](https://pypi.python.org/pypi/pyfakefs/6.1.2) (2026-02-22)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pyfakefs-6.1.6/docs/conf.py
new/pyfakefs-6.2.0/docs/conf.py
--- old/pyfakefs-6.1.6/docs/conf.py 2026-03-18 20:47:51.000000000 +0100
+++ new/pyfakefs-6.2.0/docs/conf.py 2026-04-12 15:30:15.000000000 +0200
@@ -48,7 +48,7 @@
project = "pyfakefs"
copyright = """2009 Google Inc. All Rights Reserved.
© Copyright 2014 Altera Corporation. All Rights Reserved.
-© Copyright 2014-2025 John McGehee and pyfakefs contributors."""
+© Copyright 2014-2026 John McGehee and pyfakefs contributors."""
author = "John McGehee"
# The version info for the project you're documenting, acts as replacement for
@@ -56,9 +56,9 @@
# built documents.
#
# The short X.Y version.
-version = "6.1"
+version = "6.2.0"
# The full version, including alpha/beta/rc tags.
-release = "6.1.6"
+release = "6.2.0"
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pyfakefs-6.1.6/docs/intro.rst
new/pyfakefs-6.2.0/docs/intro.rst
--- old/pyfakefs-6.1.6/docs/intro.rst 2026-03-18 20:47:51.000000000 +0100
+++ new/pyfakefs-6.2.0/docs/intro.rst 2026-04-12 15:30:15.000000000 +0200
@@ -72,9 +72,10 @@
See :ref:`customizing_patcher` for more information and ways to work around
this.
-- ``pyfakefs`` does not retain the MRO for file objects, so you cannot rely on
- checks using `isinstance` for these objects (for example, to differentiate
- between binary and textual file objects).
+- ``pyfakefs`` does not retain the MRO for file objects, so you can mostly not
rely on
+ checks using `isinstance` for these objects (note though that binary and
textual file
+ objects are derived from `io.BufferedIOBase` and `io.TextIOBase`,
respectively,
+ and can thus be differentiated via `isinstance` checks).
- ``pyfakefs`` is only tested with CPython and the newest PyPy versions, other
Python implementations will probably not work
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pyfakefs-6.1.6/docs/troubleshooting.rst
new/pyfakefs-6.2.0/docs/troubleshooting.rst
--- old/pyfakefs-6.1.6/docs/troubleshooting.rst 2026-03-18 20:47:51.000000000
+0100
+++ new/pyfakefs-6.2.0/docs/troubleshooting.rst 2026-04-12 15:30:15.000000000
+0200
@@ -525,6 +525,19 @@
* if you really need the large files, call `gc.collect`_ between tests to
ensure that the
garbage collector cleans up the memory
+Directly accessing device files in tests
+----------------------------------------
+Under Posix, (almost) everything is a file, and not all files are handled by
pyfakefs.
+Specifically, files in the `/dev` directory represent devices. Accessing them
directly
+using Python file system functions is not possible while patching with
``pyfakefs``, except
+for some pseudo-devices. The null device (`/dev/null`, or `NUL` under Windows)
is patched
+to work as expected, and the pseudo-devices `/dev/random`, `/dev/urandom`,
`/dev/zero` and
+`/dev/full` are just directly routed the system without patching them, as they
have no
+side-effect on the real system.
+While this is rarely needed, some Python functions like `os.random` may rely
on these,
+and in the case of the PyPy implementation, directly access them using Python
functions.
+
+
.. _`multiprocessing`: https://docs.python.org/3/library/multiprocessing.html
.. _`subprocess`: https://docs.python.org/3/library/subprocess.html
.. _`sqlite3`: https://docs.python.org/3/library/sqlite3.html
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pyfakefs-6.1.6/pyfakefs/_version.py
new/pyfakefs-6.2.0/pyfakefs/_version.py
--- old/pyfakefs-6.1.6/pyfakefs/_version.py 2026-03-18 20:47:51.000000000
+0100
+++ new/pyfakefs-6.2.0/pyfakefs/_version.py 2026-04-12 15:30:15.000000000
+0200
@@ -1 +1 @@
-__version__ = "6.1.6"
+__version__ = "6.2.0"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pyfakefs-6.1.6/pyfakefs/fake_file.py
new/pyfakefs-6.2.0/pyfakefs/fake_file.py
--- old/pyfakefs-6.1.6/pyfakefs/fake_file.py 2026-03-18 20:47:51.000000000
+0100
+++ new/pyfakefs-6.2.0/pyfakefs/fake_file.py 2026-04-12 15:30:15.000000000
+0200
@@ -995,7 +995,7 @@
):
open_file._sync_io()
- def seek(self, offset: int, whence: int = 0) -> None:
+ def seek(self, offset: int, whence: int = 0) -> int:
"""Move read/write pointer in 'file'."""
self._check_open_file()
if not self.open_modes.append:
@@ -1005,6 +1005,7 @@
self._read_whence = whence
if not self.is_stream:
self.flush()
+ return self.tell()
def tell(self) -> int:
"""Return the file's current position.
@@ -1285,7 +1286,7 @@
def __iter__(self) -> Iterator[str] | Iterator[bytes]:
if not self.readable():
self._raise("File is not open for reading")
- return self._io.__iter__()
+ return self._io.__iter__() # type: ignore[return-value]
def __next__(self):
if not self.readable():
@@ -1293,6 +1294,32 @@
return next(self._io)
+class FakeTextFileWrapper(FakeFileWrapper, io.TextIOBase): # type:
ignore[misc]
+ """Represents a text file wrapper.
+ Derives from io.TextIOBase so it can be used as a file object
+ if the type is checked by a library user, while it delegates all calls
+ to `FakeFileWrapper`.
+ """
+
+ def __getattribute__(self, name): # type: ignore[override]
+ if hasattr(FakeFileWrapper, name) or name in self.__dict__:
+ return FakeFileWrapper.__getattribute__(self, name)
+ return self.__getattr__(name)
+
+
+class FakeBinaryFileWrapper(FakeFileWrapper, io.BufferedIOBase): # type:
ignore[misc]
+ """Represents a buffered binary file wrapper.
+ Derives from io.BufferedIOBase so it can be used as a file object
+ if the type is checked by a library user, while it delegates all calls
+ to `FakeFileWrapper`.
+ """
+
+ def __getattribute__(self, name): # type: ignore[override]
+ if hasattr(FakeFileWrapper, name) or name in self.__dict__:
+ return FakeFileWrapper.__getattribute__(self, name)
+ return self.__getattr__(name)
+
+
class StandardStreamWrapper:
"""Wrapper for a system standard stream to be used in open files list."""
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pyfakefs-6.1.6/pyfakefs/fake_open.py
new/pyfakefs-6.2.0/pyfakefs/fake_open.py
--- old/pyfakefs-6.1.6/pyfakefs/fake_open.py 2026-03-18 20:47:51.000000000
+0100
+++ new/pyfakefs-6.2.0/pyfakefs/fake_open.py 2026-04-12 15:30:15.000000000
+0200
@@ -32,13 +32,15 @@
IO,
)
-from pyfakefs import helpers
from pyfakefs.fake_file import (
+ FakeBinaryFileWrapper,
+ FakeTextFileWrapper,
FakePipeWrapper,
FakeFileWrapper,
FakeFile,
AnyFileWrapper,
)
+from pyfakefs import helpers
from pyfakefs.helpers import (
AnyString,
is_called_from_skipped_module,
@@ -46,6 +48,7 @@
PERM_READ,
PERM_WRITE,
_OpenModes,
+ is_unfaked_path,
)
if TYPE_CHECKING:
@@ -87,10 +90,14 @@
"""
# We don't need to check this if we are in an `open_code` call
# from a faked file (and this might cause recursions in `linecache`)
- if not is_fake_open_code and is_called_from_skipped_module(
- skip_names=skip_names,
- case_sensitive=filesystem.is_case_sensitive,
- check_open_code=sys.version_info >= (3, 12),
+ if (
+ not is_fake_open_code
+ and is_called_from_skipped_module(
+ skip_names=skip_names,
+ case_sensitive=filesystem.is_case_sensitive,
+ check_open_code=sys.version_info >= (3, 12),
+ )
+ or is_unfaked_path(file)
):
return io_open( # pytype: disable=wrong-arg-count
file,
@@ -265,7 +272,8 @@
if not self.filesystem.is_windows_fs:
file_object.st_ctime = current_time
- fakefile = FakeFileWrapper(
+ wrapper_class = FakeBinaryFileWrapper if binary else
FakeTextFileWrapper
+ fakefile = wrapper_class(
file_object,
file_path,
open_modes=open_modes,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pyfakefs-6.1.6/pyfakefs/fake_pathlib.py
new/pyfakefs-6.2.0/pyfakefs/fake_pathlib.py
--- old/pyfakefs-6.1.6/pyfakefs/fake_pathlib.py 2026-03-18 20:47:51.000000000
+0100
+++ new/pyfakefs-6.2.0/pyfakefs/fake_pathlib.py 2026-04-12 15:30:15.000000000
+0200
@@ -798,6 +798,7 @@
)
except AttributeError:
return path
+
else:
@classmethod
@@ -1037,10 +1038,18 @@
return grp.getgrgid(self.stat().st_gid).gr_name
+ if sys.version_info >= (3, 13):
+
+ def __init__(self, *args):
+ super().__init__(*args)
+ # case-sensitivity for filling the _str_normcase_cached
variable
+ # is filled depending on a class check (self.parser is
posixpath),
+ # which we cannot fake, thus we set it at initialization time
+ self._str_normcase_cached = str(self)
+
if sys.version_info >= (3, 14):
- # in Python 3.14, case-sensitivity is checked using an is-check
- # (self.parser is posixpath) if not given, which we cannot fake
- # therefore we already provide the case sensitivity under Posix
+ # a similar check is used in the implementations of glob, match
and full_match, to check for
+ # case sensitivity if not given, so we provide it under Posix as
True
def glob(self, pattern, *, case_sensitive=None,
recurse_symlinks=False):
if case_sensitive is None:
case_sensitive = True
@@ -1050,6 +1059,20 @@
recurse_symlinks=recurse_symlinks,
)
+ def match(self, path_pattern, *, case_sensitive=None):
+ if case_sensitive is None:
+ case_sensitive = True
+ return super().match(
+ path_pattern, case_sensitive=case_sensitive
+ ) # pytype: disable=wrong-keyword-args
+
+ def full_match(self, pattern, *, case_sensitive=None):
+ if case_sensitive is None:
+ case_sensitive = True
+ return super().full_match( # pytype: disable=attribute-error
+ pattern, case_sensitive=case_sensitive
+ ) # pytype: disable=wrong-keyword-args
+
Path = FakePath
def __getattr__(self, name):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pyfakefs-6.1.6/pyfakefs/helpers.py
new/pyfakefs-6.2.0/pyfakefs/helpers.py
--- old/pyfakefs-6.1.6/pyfakefs/helpers.py 2026-03-18 20:47:51.000000000
+0100
+++ new/pyfakefs-6.2.0/pyfakefs/helpers.py 2026-04-12 15:30:15.000000000
+0200
@@ -207,6 +207,24 @@
return string # pytype: disable=bad-return-type
+def is_unfaked_path(val: Any) -> bool:
+ """Return ``True`` if `val` is a path that should not be faked.
+ Currently only ``True`` for some pseudo-devices under Posix,
+ which will have no side effect if reading/writing them.
+ """
+ if IS_WIN:
+ return False
+ try:
+ return matching_string("", val) in (
+ "/dev/random",
+ "/dev/urandom",
+ "/dev/zero",
+ "/dev/full",
+ )
+ except AttributeError:
+ return False
+
+
@dataclass
class FSProperties:
sep: str
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pyfakefs-6.1.6/pyfakefs/tests/fake_open_test.py
new/pyfakefs-6.2.0/pyfakefs/tests/fake_open_test.py
--- old/pyfakefs-6.1.6/pyfakefs/tests/fake_open_test.py 2026-03-18
20:47:51.000000000 +0100
+++ new/pyfakefs-6.2.0/pyfakefs/tests/fake_open_test.py 2026-04-12
15:30:15.000000000 +0200
@@ -903,6 +903,14 @@
f0.seek(3)
self.assertEqual(4, self.os.path.getsize(file_path))
+ def test_seek_returns_location(self):
+ # Regression test for #1304
+ file_path = self.make_path("foo")
+ with self.open(file_path, "w", encoding="utf8") as f0:
+ f0.write("test")
+ result = f0.seek(3)
+ self.assertEqual(3, result)
+
def test_truncate_flushes(self):
# Regression test for #291
file_path = self.make_path("foo")
@@ -995,6 +1003,18 @@
with self.open(self.os.devnull, encoding="utf8") as f:
self.assertEqual("", f.read())
+ @unittest.skipIf(os.name == "nt", "only exist on posix")
+ def test_pseudo_devices(self):
+ self.check_posix_only()
+ with self.open("/dev/random", "rb") as f:
+ self.assertEqual(1, len(f.read(1)))
+ with self.open("/dev/zero", "rb") as f:
+ self.assertEqual(b"\0\0\0\0", f.read(4))
+ if sys.platform == "linux":
+ with self.raises_os_error(errno.ENOSPC):
+ with self.open("/dev/full", "wb") as f:
+ f.write(b"\0")
+
def test_utf16_text(self):
# regression test for #574
file_path = self.make_path("foo")
@@ -1031,6 +1051,18 @@
self.assertTrue(f.readable())
self.assertTrue(f.writable())
+ def test_file_class(self):
+ file_path = self.make_path("foo")
+ with self.open(file_path, "w") as f:
+ assert isinstance(f, io.TextIOBase)
+ f.write("test")
+ with self.open(file_path) as f:
+ assert isinstance(f, io.TextIOBase)
+ assert f.read() == "test"
+ with self.open(file_path, "rb") as f:
+ assert isinstance(f, io.BufferedIOBase)
+ assert f.read() == b"test"
+
class RealFileOpenTest(FakeFileOpenTest):
def use_real_fs(self):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pyfakefs-6.1.6/pyfakefs/tests/fake_pathlib_test.py
new/pyfakefs-6.2.0/pyfakefs/tests/fake_pathlib_test.py
--- old/pyfakefs-6.1.6/pyfakefs/tests/fake_pathlib_test.py 2026-03-18
20:47:51.000000000 +0100
+++ new/pyfakefs-6.2.0/pyfakefs/tests/fake_pathlib_test.py 2026-04-12
15:30:15.000000000 +0200
@@ -265,6 +265,36 @@
self.assertTrue(self.path("/a.py").match("/*.py"))
self.assertFalse(self.path("a/b.py").match("/*.py"))
+ @unittest.skipIf(sys.version_info < (3, 13), "full_match new in Python
3.13")
+ def test_full_match(self):
+ self.assertFalse(self.path("a/b.py").full_match("*.py"))
+ self.assertTrue(self.path("/a/b.py").full_match("/a/*.py"))
+ self.assertTrue(self.path("/a/b/c.py").full_match("/a/**"))
+
+ def test_match_with_differing_case_posix(self):
+ self.check_posix_only()
+ self.assertFalse(self.path("a/b.py").match("*.Py"))
+ self.assertFalse(self.path("/a/b/c.py").match("B/*.py"))
+ self.assertFalse(self.path("/a.py").match("/*.PY"))
+
+ def test_match_with_differing_case_windows(self):
+ self.check_windows_only()
+ self.assertTrue(self.path("a/b.py").match("*.Py"))
+ self.assertTrue(self.path("/a/b/c.py").match("B/*.py"))
+ self.assertTrue(self.path("/a.py").match("/*.PY"))
+
+ @unittest.skipIf(sys.version_info < (3, 13), "full_match new in Python
3.13")
+ def test_full_match_with_differing_case_posix(self):
+ self.check_posix_only()
+ self.assertFalse(self.path("/a/b.py").full_match("/a/*.PY"))
+ self.assertFalse(self.path("/a/b/c.py").full_match("/A/**"))
+
+ @unittest.skipIf(sys.version_info < (3, 13), "full_match new in Python
3.13")
+ def test_full_match_with_differing_case_windows(self):
+ self.check_windows_only()
+ self.assertTrue(self.path("/a/b.py").full_match("/a/*.PY"))
+ self.assertTrue(self.path("/a/b/c.py").full_match("/A/**"))
+
def test_relative_to(self):
self.assertEqual(
self.path("/etc/passwd").relative_to("/"), self.path("etc/passwd")
@@ -298,6 +328,20 @@
self.path("README").with_suffix(".txt"), self.path("README.txt")
)
+ def test_path_comparison_posix(self):
+ self.check_posix_only()
+ path1 = self.path("Test")
+ path2 = self.path("test")
+ assert path1 != path2
+ assert hash(path1) != hash(path2)
+
+ def test_path_comparison_windows(self):
+ self.check_windows_only()
+ path1 = self.path("Test")
+ path2 = self.path("test")
+ assert path1 == path2
+ assert hash(path1) == hash(path2)
+
class RealPathlibPurePathTest(FakePathlibPurePathTest):
def use_real_fs(self):