Skip to content

Commit 50a2761

Browse files
authored
Add Python 3.12 to the test suite (#764)
* Mark Python 3.12 as experimental * Add is_junction method to DirEntry class on Python 3.12 * Implement stub functions for os.path.isjunction() (always return False) * Skip extra deps tests for Python 3.12
1 parent 600de95 commit 50a2761

File tree

6 files changed

+53
-2
lines changed

6 files changed

+53
-2
lines changed

.github/workflows/testsuite.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ jobs:
1010
fail-fast: false
1111
matrix:
1212
os: [ubuntu-latest, macOS-latest, windows-latest]
13-
python-version: [3.7, 3.8, 3.9, "3.10", "3.11"]
13+
python-version: [3.7, 3.8, 3.9, "3.10", "3.11", "3.12-dev"]
1414
include:
1515
- python-version: "pypy-3.7"
1616
os: ubuntu-latest
@@ -58,10 +58,12 @@ jobs:
5858
fi
5959
shell: bash
6060
- name: Install extra dependencies
61+
if: ${{ matrix.python-version != '3.12-dev' }}
6162
run: |
6263
pip install -r extra_requirements.txt
6364
shell: bash
6465
- name: Run unit tests with extra packages as non-root user
66+
if: ${{ matrix.python-version != '3.12-dev' }}
6567
run: |
6668
python -m pyfakefs.tests.all_tests
6769
shell: bash

CHANGES.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,15 @@ The released versions correspond to PyPI releases.
66
### Features
77
* added class level setup method `setUpClassPyfakefs` for unittest and class-scoped
88
fixture `fs_class` for pytest (see [#752](../../issues/752))
9+
* added experimental support for Python 3.12: added fake APIs for Windows junction
10+
support. These are not implemented and always return `False`.
911

1012
### Infrastructure
1113
* replaced end-of-life CentOS with RedHat UBI9 docker image
1214
* added tests for pytest 7.2.0
1315
* added black to pre-commit checks, which caused some changes to the
1416
coding style (max line length is now 88, always use double quotes)
17+
* added Python 3.12 to the test suite.
1518

1619
## [Version 5.0.0](https://pypi.python.org/pypi/pyfakefs/5.0.0) (2022-10-09)
1720
New version after the transfer to `pytest-dev`.

pyfakefs/fake_filesystem.py

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -576,6 +576,12 @@ def path(self) -> AnyStr:
576576
dir_path = sep.join(names)
577577
return self.filesystem.absnormpath(dir_path)
578578

579+
if sys.version_info >= (3, 12):
580+
581+
@property
582+
def is_junction(self) -> bool:
583+
return self.filesystem.isjunction(self.path)
584+
579585
def __getattr__(self, item: str) -> Any:
580586
"""Forward some properties to stat_result."""
581587
if item in self.stat_types:
@@ -3440,6 +3446,12 @@ def islink(self, path: AnyPath) -> bool:
34403446
"""
34413447
return self._is_of_type(path, S_IFLNK, follow_symlinks=False)
34423448

3449+
if sys.version_info >= (3, 12):
3450+
3451+
def isjunction(self, path: AnyPath) -> bool:
3452+
"""Returns False. Junctions are never faked."""
3453+
return False
3454+
34433455
def confirmdir(
34443456
self, target_directory: AnyStr, check_owner: bool = False
34453457
) -> FakeDirectory:
@@ -3589,7 +3601,7 @@ def dir() -> List[str]:
35893601
"""Return the list of patched function names. Used for patching
35903602
functions imported from the module.
35913603
"""
3592-
return [
3604+
dir_list = [
35933605
"abspath",
35943606
"dirname",
35953607
"exists",
@@ -3613,6 +3625,9 @@ def dir() -> List[str]:
36133625
"splitdrive",
36143626
"samefile",
36153627
]
3628+
if sys.version_info >= (3, 12):
3629+
dir_list.append("isjunction")
3630+
return dir_list
36163631

36173632
def __init__(self, filesystem: FakeFilesystem, os_module: "FakeOsModule"):
36183633
"""Init.
@@ -3702,6 +3717,12 @@ def islink(self, path: AnyStr) -> bool:
37023717
"""
37033718
return self.filesystem.islink(path)
37043719

3720+
if sys.version_info >= (3, 12):
3721+
3722+
def isjunction(self, path: AnyStr) -> bool:
3723+
"""Returns False. Junctions are never faked."""
3724+
return self.filesystem.isjunction(path)
3725+
37053726
def getmtime(self, path: AnyStr) -> float:
37063727
"""Returns the modification time of the fake file.
37073728

pyfakefs/fake_pathlib.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,10 @@
3232
import fnmatch
3333
import functools
3434
import inspect
35+
import ntpath
3536
import os
3637
import pathlib
38+
import posixpath
3739
import re
3840
import sys
3941
from pathlib import PurePath
@@ -383,6 +385,7 @@ class _FakeWindowsFlavour(_FakeFlavour):
383385
| {"COM%d" % i for i in range(1, 10)}
384386
| {"LPT%d" % i for i in range(1, 10)}
385387
)
388+
pathmod = ntpath
386389

387390
def is_reserved(self, parts):
388391
"""Return True if the path is considered reserved under Windows."""
@@ -459,6 +462,8 @@ class _FakePosixFlavour(_FakeFlavour):
459462
independent of FakeFilesystem properties.
460463
"""
461464

465+
pathmod = posixpath
466+
462467
def is_reserved(self, parts):
463468
return False
464469

pyfakefs/fake_scandir.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,16 @@ def stat(self, follow_symlinks=True):
114114
def __fspath__(self):
115115
return self.path
116116

117+
if sys.version_info >= (3, 12):
118+
119+
def is_junction(self) -> bool:
120+
"""Return True if this entry is a junction.
121+
Junctions are not a part of posix semantic."""
122+
if not self._filesystem.is_windows_fs:
123+
return False
124+
file_object = self._filesystem.resolve(self._abspath)
125+
return file_object.is_junction
126+
117127

118128
class ScanDirIter:
119129
"""Iterator for DirEntry objects returned from `scandir()`

pyfakefs/tests/fake_pathlib_test.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,15 @@ def test_read_text(self):
513513
file_path = self.path(self.make_path("text_file"))
514514
self.assertEqual(file_path.read_text(), "foo")
515515

516+
@unittest.skipIf(
517+
sys.version_info < (3, 12),
518+
"is_junction method new in Python 3.12",
519+
)
520+
def test_is_junction(self):
521+
self.create_file(self.make_path("text_file"), contents="foo")
522+
file_path = self.path(self.make_path("text_file"))
523+
self.assertFalse(file_path.is_junction())
524+
516525
def test_read_text_with_encoding(self):
517526
self.create_file(
518527
self.make_path("text_file"), contents="ерунда", encoding="cyrillic"
@@ -632,6 +641,7 @@ def test_symlink_to(self):
632641
self.assertTrue(path.is_symlink())
633642

634643
@unittest.skipIf(sys.version_info < (3, 8), "link_to new in Python 3.8")
644+
@unittest.skipIf(sys.version_info >= (3, 12), "link_to removed in Python 3.12")
635645
def test_link_to(self):
636646
self.skip_if_symlink_not_supported()
637647
file_name = self.make_path("foo", "bar.txt")

0 commit comments

Comments
 (0)